From cfb984627d4ea57ff8333b0cbd4c8de583d68434 Mon Sep 17 00:00:00 2001 From: root Date: Thu, 15 Oct 2026 23:55:27 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=9D=E5=A7=8B=E6=8F=90=E4=BA=A4=EF=BC=9A?= =?UTF-8?q?=E5=AE=9E=E4=B9=A0=E5=B7=A5=E4=BD=9C=E6=97=A5=E5=BF=97=E7=B3=BB?= =?UTF-8?q?=E7=BB=9F=EF=BC=88=E8=AE=BE=E8=AE=A1=E6=96=B9=E6=A1=88=20+=20Vu?= =?UTF-8?q?e3=20=E5=BA=94=E7=94=A8=20+=20Electron=20=E6=89=93=E5=8C=85?= =?UTF-8?q?=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- intern-log/.gitignore | 4 + intern-log/README.md | 30 + intern-log/build/icon.ico | Bin 0 -> 17595 bytes intern-log/build/icon.png | Bin 0 -> 3525 bytes intern-log/build/make_ico.py | 6 + intern-log/electron/main.cjs | 43 + intern-log/index.html | 16 + intern-log/package.json | 52 + intern-log/pnpm-lock.yaml | 3685 +++++++++++++++++ intern-log/pnpm-workspace.yaml | 3 + intern-log/public/icons/icon-192.png | Bin 0 -> 1163 bytes intern-log/public/icons/icon-512.png | Bin 0 -> 3525 bytes intern-log/public/icons/icon.svg | 13 + intern-log/public/icons/make_icons.py | 23 + intern-log/public/manifest.webmanifest | 15 + intern-log/public/sw.js | 46 + intern-log/src/App.vue | 425 ++ intern-log/src/components/ConfirmDialog.vue | 69 + .../src/components/CredentialDialog.vue | 155 + intern-log/src/components/Icon.vue | 11 + intern-log/src/components/icons.ts | 25 + intern-log/src/components/log/DayPanel.vue | 542 +++ .../src/components/log/EditLogDialog.vue | 243 ++ intern-log/src/db/auth.ts | 160 + intern-log/src/db/repo.ts | 405 ++ intern-log/src/db/schema.ts | 125 + intern-log/src/db/vault.ts | 142 + intern-log/src/domain/ai.ts | 44 + intern-log/src/domain/attendance.ts | 46 + intern-log/src/domain/report.ts | 178 + intern-log/src/lib/bus.ts | 11 + intern-log/src/lib/clipboard.ts | 14 + intern-log/src/lib/crypto.ts | 62 + intern-log/src/lib/csv.ts | 16 + intern-log/src/lib/date.ts | 65 + intern-log/src/lib/download.ts | 9 + intern-log/src/lib/toast.ts | 22 + intern-log/src/main.ts | 12 + intern-log/src/styles/tokens.css | 117 + intern-log/src/views/CalendarView.vue | 209 + intern-log/src/views/LoginView.vue | 147 + intern-log/src/views/MemoView.vue | 255 ++ intern-log/src/views/ReportView.vue | 241 ++ intern-log/src/views/SettingsView.vue | 377 ++ intern-log/src/views/StatsView.vue | 206 + intern-log/src/views/TodayView.vue | 12 + intern-log/src/views/VaultView.vue | 437 ++ intern-log/tsconfig.json | 14 + intern-log/vite.config.ts | 7 + 实习工作日志系统-设计方案.md | 484 +++ 50 files changed, 9223 insertions(+) create mode 100644 intern-log/.gitignore create mode 100644 intern-log/README.md create mode 100644 intern-log/build/icon.ico create mode 100644 intern-log/build/icon.png create mode 100644 intern-log/build/make_ico.py create mode 100644 intern-log/electron/main.cjs create mode 100644 intern-log/index.html create mode 100644 intern-log/package.json create mode 100644 intern-log/pnpm-lock.yaml create mode 100644 intern-log/pnpm-workspace.yaml create mode 100644 intern-log/public/icons/icon-192.png create mode 100644 intern-log/public/icons/icon-512.png create mode 100644 intern-log/public/icons/icon.svg create mode 100644 intern-log/public/icons/make_icons.py create mode 100644 intern-log/public/manifest.webmanifest create mode 100644 intern-log/public/sw.js create mode 100644 intern-log/src/App.vue create mode 100644 intern-log/src/components/ConfirmDialog.vue create mode 100644 intern-log/src/components/CredentialDialog.vue create mode 100644 intern-log/src/components/Icon.vue create mode 100644 intern-log/src/components/icons.ts create mode 100644 intern-log/src/components/log/DayPanel.vue create mode 100644 intern-log/src/components/log/EditLogDialog.vue create mode 100644 intern-log/src/db/auth.ts create mode 100644 intern-log/src/db/repo.ts create mode 100644 intern-log/src/db/schema.ts create mode 100644 intern-log/src/db/vault.ts create mode 100644 intern-log/src/domain/ai.ts create mode 100644 intern-log/src/domain/attendance.ts create mode 100644 intern-log/src/domain/report.ts create mode 100644 intern-log/src/lib/bus.ts create mode 100644 intern-log/src/lib/clipboard.ts create mode 100644 intern-log/src/lib/crypto.ts create mode 100644 intern-log/src/lib/csv.ts create mode 100644 intern-log/src/lib/date.ts create mode 100644 intern-log/src/lib/download.ts create mode 100644 intern-log/src/lib/toast.ts create mode 100644 intern-log/src/main.ts create mode 100644 intern-log/src/styles/tokens.css create mode 100644 intern-log/src/views/CalendarView.vue create mode 100644 intern-log/src/views/LoginView.vue create mode 100644 intern-log/src/views/MemoView.vue create mode 100644 intern-log/src/views/ReportView.vue create mode 100644 intern-log/src/views/SettingsView.vue create mode 100644 intern-log/src/views/StatsView.vue create mode 100644 intern-log/src/views/TodayView.vue create mode 100644 intern-log/src/views/VaultView.vue create mode 100644 intern-log/tsconfig.json create mode 100644 intern-log/vite.config.ts create mode 100644 实习工作日志系统-设计方案.md diff --git a/intern-log/.gitignore b/intern-log/.gitignore new file mode 100644 index 0000000..b9491f9 --- /dev/null +++ b/intern-log/.gitignore @@ -0,0 +1,4 @@ +node_modules/ +dist/ +release/ +*.local diff --git a/intern-log/README.md b/intern-log/README.md new file mode 100644 index 0000000..6e7a8cc --- /dev/null +++ b/intern-log/README.md @@ -0,0 +1,30 @@ +# 实习工作日志 + +本地优先的实习工作记录工具:考勤打卡、月历、随手记、周记、一键生成总结。 + +对应设计方案文档:实习工作日志系统-设计方案.md + +## 运行 + + pnpm install + pnpm dev # 开发模式,默认 http://localhost:5173 + pnpm build # 构建产物到 dist/ + pnpm preview # 预览构建产物,默认 http://localhost:4173 + +## 说明 + +- 技术栈:Vue 3 + TypeScript + Vite + Dexie(IndexedDB),无后端、无外部图标库 +- 数据保存在浏览器 IndexedDB(数据库名 intern_worklog) +- 「设置」页可导出/导入 JSON 全量备份;「总结」页可导出 Markdown +- 支持上班地点记录(公司、客户现场、出差等),可直接输入自定义地点并自动记住,统计与总结含地点分布 +- 打卡时间支持行内直接修改(含补录下班时间),考勤状态自动重算 +- 表单带标签与必填校验;删除与备份覆盖导入使用统一确认弹窗;操作结果轻提示反馈 +- 工作记录支持弹窗完整信息编辑(全部字段),点击条目或编辑图标打开 +- 备忘录:双栏列表与编辑,未保存修改有守卫 +- 密码库:企业账号密码管理,主密码 PBKDF2 派生 AES-256-GCM 加密,支持解锁、锁定、搜索、复制、随机密码生成、修改主密码;备份文件中密码保持密文 +- 用户系统:每位用户独立 IndexedDB 数据库隔离存储;登录密码仅存 PBKDF2 哈希;30 分钟无操作自动退出;创建用户时可迁移升级前数据 +- PWA:在 Edge/Chrome 中打开后,地址栏右侧点「安装」或菜单选择「将此站点作为应用安装」,即可获得独立窗口与桌面图标,离线可用 +- Electron 桌面版:pnpm dist 产出 release/InternLog-Setup-<版本>.exe(NSIS 安装包)与 release/win-unpacked/InternLog.exe(免安装版);数据存于系统用户目录,与浏览器数据互不影响 +- 全局搜索:Ctrl+K 唤起,覆盖工作记录与备忘录,点击结果跳转定位 +- 考勤支持休假标记;支持导出工作记录与考勤 CSV;总结草稿可复制、可 AI 润色(设置页配置 OpenAI 兼容接口);密码库 5 分钟无操作自动锁定 +- 图标为自绘 SVG(src/components/icons.ts),界面不含表情与特殊符号 diff --git a/intern-log/build/icon.ico b/intern-log/build/icon.ico new file mode 100644 index 0000000000000000000000000000000000000000..477094c0f743b18964cf80e91d0fbaf7388c9dd4 GIT binary patch literal 17595 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 upJFOhkh%1J;q(`` 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 FL;!u(#tHxc literal 0 HcmV?d00001 diff --git a/intern-log/build/icon.png b/intern-log/build/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..407b66d79cbaa95609b114c0ead98c5b4545f1fb GIT binary patch literal 3525 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 { + if (/^https?:/i.test(url)) shell.openExternal(url) + return { action: 'deny' } + }) + if (DEV_URL) { + win.loadURL(DEV_URL) + } else { + win.loadFile(path.join(__dirname, '..', 'dist', 'index.html')) + } +} + +app.whenReady().then(() => { + createWindow() + app.on('activate', () => { + if (BrowserWindow.getAllWindows().length === 0) createWindow() + }) +}) + +app.on('window-all-closed', () => { + if (process.platform !== 'darwin') app.quit() +}) diff --git a/intern-log/index.html b/intern-log/index.html new file mode 100644 index 0000000..3c070b2 --- /dev/null +++ b/intern-log/index.html @@ -0,0 +1,16 @@ + + + + + + + + + + 实习工作日志 + + +
+ + + diff --git a/intern-log/package.json b/intern-log/package.json new file mode 100644 index 0000000..1b9b5fc --- /dev/null +++ b/intern-log/package.json @@ -0,0 +1,52 @@ +{ + "name": "intern-log", + "private": true, + "version": "0.1.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "preview": "vite preview", + "electron": "electron electron/main.cjs", + "dist": "vite build && electron-builder" + }, + "dependencies": { + "dexie": "^4.0.8", + "vue": "^3.5.13" + }, + "devDependencies": { + "@vitejs/plugin-vue": "^5.2.1", + "typescript": "~5.6.3", + "vite": "^5.4.11", + "electron": "^33.2.0", + "electron-builder": "^25.1.8" + }, + "description": "实习工作日志:打卡、记录、备忘录与密码库", + "main": "electron/main.cjs", + "build": { + "appId": "com.internlog.desktop", + "productName": "InternLog", + "directories": { + "output": "release" + }, + "files": [ + "dist/**/*", + "electron/**/*", + "package.json" + ], + "win": { + "target": [ + "nsis", + "dir" + ], + "icon": "build/icon.ico" + }, + "nsis": { + "oneClick": false, + "allowToChangeInstallationDirectory": true, + "createDesktopShortcut": true, + "shortcutName": "实习工作日志" + }, + "artifactName": "InternLog-Setup-${version}.${ext}" + } +} diff --git a/intern-log/pnpm-lock.yaml b/intern-log/pnpm-lock.yaml new file mode 100644 index 0000000..0f96e5e --- /dev/null +++ b/intern-log/pnpm-lock.yaml @@ -0,0 +1,3685 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + dependencies: + dexie: + specifier: ^4.0.8 + version: 4.4.6 + vue: + specifier: ^3.5.13 + version: 3.5.44(typescript@5.6.3) + devDependencies: + '@vitejs/plugin-vue': + specifier: ^5.2.1 + version: 5.2.4(vite@5.4.21(@types/node@26.6.5))(vue@3.5.44(typescript@5.6.3)) + electron: + specifier: ^33.2.0 + version: 33.4.11(supports-color@7.2.0) + electron-builder: + specifier: ^25.1.8 + version: 25.1.8(bluebird@3.7.2)(electron-builder-squirrel-windows@25.1.8)(supports-color@7.2.0) + typescript: + specifier: ~5.6.3 + version: 5.6.3 + vite: + specifier: ^5.4.11 + version: 5.4.21(@types/node@26.6.5) + +packages: + + 7zip-bin@5.2.0: + resolution: {integrity: sha512-ukTPVhqG4jNzMro2qA9HSCSSVJN3aN7tlb+hfqYCt3ER0yWroeA2VR38MNrOHLQ/cVj+DaIMad0kFCtWWowh/A==} + + '@babel/helper-string-parser@7.29.7': + resolution: {integrity: sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-identifier@7.29.7': + resolution: {integrity: sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==} + engines: {node: '>=6.9.0'} + + '@babel/parser@7.29.9': + resolution: {integrity: sha512-CjXrNHTnvqBVqHgdBysY3vk2T8tpJHb5/RMeHJBTyVa9xgugCB0CJTx/3oO8RV2QRQP391RWpB7D6hLjm8V9uA==} + engines: {node: '>=6.0.0'} + hasBin: true + + '@babel/types@7.29.8': + resolution: {integrity: sha512-Vj1jF3cPfxg7OAfoI7QnVKLoILlm2JF9pnVHrX8qx7AHMiYWT+NDAA7jChlNgRS4WTLc/fD1lXLmPixluj+3Gg==} + engines: {node: '>=6.9.0'} + + '@develar/schema-utils@2.6.5': + resolution: {integrity: sha512-0cp4PsWQ/9avqTVMCtZ+GirikIA36ikvjtHweU4/j8yLtgObI0+JUPhYFScgwlteveGB1rt3Cm8UhN04XayDig==} + engines: {node: '>= 8.9.0'} + + '@electron/asar@3.4.1': + resolution: {integrity: sha512-i4/rNPRS84t0vSRa2HorerGRXWyF4vThfHesw0dmcWHp+cspK743UanA0suA5Q5y8kzY2y6YKrvbIUn69BCAiA==} + engines: {node: '>=10.12.0'} + hasBin: true + + '@electron/get@2.0.3': + resolution: {integrity: sha512-Qkzpg2s9GnVV2I2BjRksUi43U5e6+zaQMcjoJy0C+C5oxaKl+fmckGDQFtRpZpZV0NQekuZZ+tGz7EA9TVnQtQ==} + engines: {node: '>=12'} + + '@electron/notarize@2.5.0': + resolution: {integrity: sha512-jNT8nwH1f9X5GEITXaQ8IF/KdskvIkOFfB2CvwumsveVidzpSc+mvhhTMdAGSYF3O+Nq49lJ7y+ssODRXu06+A==} + engines: {node: '>= 10.0.0'} + + '@electron/osx-sign@1.3.1': + resolution: {integrity: sha512-BAfviURMHpmb1Yb50YbCxnOY0wfwaLXH5KJ4+80zS0gUkzDX3ec23naTlEqKsN+PwYn+a1cCzM7BJ4Wcd3sGzw==} + engines: {node: '>=12.0.0'} + hasBin: true + + '@electron/rebuild@3.6.1': + resolution: {integrity: sha512-f6596ZHpEq/YskUd8emYvOUne89ij8mQgjYFA5ru25QwbrRO+t1SImofdDv7kKOuWCmVOuU5tvfkbgGxIl3E/w==} + engines: {node: '>=12.13.0'} + hasBin: true + + '@electron/universal@2.0.1': + resolution: {integrity: sha512-fKpv9kg4SPmt+hY7SVBnIYULE9QJl8L3sCfcBsnqbJwwBwAeTLokJ9TRt9y7bK0JAzIW2y78TVVjvnQEms/yyA==} + engines: {node: '>=16.4'} + + '@esbuild/aix-ppc64@0.21.5': + resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [aix] + + '@esbuild/android-arm64@0.21.5': + resolution: {integrity: sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==} + engines: {node: '>=12'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm@0.21.5': + resolution: {integrity: sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==} + engines: {node: '>=12'} + cpu: [arm] + os: [android] + + '@esbuild/android-x64@0.21.5': + resolution: {integrity: sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==} + engines: {node: '>=12'} + cpu: [x64] + os: [android] + + '@esbuild/darwin-arm64@0.21.5': + resolution: {integrity: sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-x64@0.21.5': + resolution: {integrity: sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + + '@esbuild/freebsd-arm64@0.21.5': + resolution: {integrity: sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==} + engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.21.5': + resolution: {integrity: sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [freebsd] + + '@esbuild/linux-arm64@0.21.5': + resolution: {integrity: sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm@0.21.5': + resolution: {integrity: sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==} + engines: {node: '>=12'} + cpu: [arm] + os: [linux] + + '@esbuild/linux-ia32@0.21.5': + resolution: {integrity: sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==} + engines: {node: '>=12'} + cpu: [ia32] + os: [linux] + + '@esbuild/linux-loong64@0.21.5': + resolution: {integrity: sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==} + engines: {node: '>=12'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-mips64el@0.21.5': + resolution: {integrity: sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==} + engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-ppc64@0.21.5': + resolution: {integrity: sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-riscv64@0.21.5': + resolution: {integrity: sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==} + engines: {node: '>=12'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-s390x@0.21.5': + resolution: {integrity: sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==} + engines: {node: '>=12'} + cpu: [s390x] + os: [linux] + + '@esbuild/linux-x64@0.21.5': + resolution: {integrity: sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [linux] + + '@esbuild/netbsd-x64@0.21.5': + resolution: {integrity: sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==} + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + + '@esbuild/openbsd-x64@0.21.5': + resolution: {integrity: sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==} + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] + + '@esbuild/sunos-x64@0.21.5': + resolution: {integrity: sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==} + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] + + '@esbuild/win32-arm64@0.21.5': + resolution: {integrity: sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==} + engines: {node: '>=12'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-ia32@0.21.5': + resolution: {integrity: sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==} + engines: {node: '>=12'} + cpu: [ia32] + os: [win32] + + '@esbuild/win32-x64@0.21.5': + resolution: {integrity: sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==} + engines: {node: '>=12'} + cpu: [x64] + os: [win32] + + '@gar/promisify@1.1.3': + resolution: {integrity: sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==} + + '@isaacs/cliui@8.0.2': + resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} + engines: {node: '>=12'} + + '@jridgewell/sourcemap-codec@1.6.0': + resolution: {integrity: sha512-T7jf+5zgsZHwNJ4lvQ7/aezbyk0nNX+zJVWpmHA7VYsEx7a7qr5Rg5IbtJFqkgze5Y2sruq1RUY8Q837Od7iFw==} + + '@malept/cross-spawn-promise@2.0.0': + resolution: {integrity: sha512-1DpKU0Z5ThltBwjNySMC14g0CkbyhCaz9FkhxqNsZI6uAPJXFS8cMXlBKo26FJ8ZuW6S9GCMcR9IO5k2X5/9Fg==} + engines: {node: '>= 12.13.0'} + + '@malept/flatpak-bundler@0.4.0': + resolution: {integrity: sha512-9QOtNffcOF/c1seMCDnjckb3R9WHcG34tky+FHpNKKCW0wc/scYLwMtO+ptyGUfMW0/b/n4qRiALlaFHc9Oj7Q==} + engines: {node: '>= 10.0.0'} + + '@napi-rs/lzma-linux-x64-gnu@1.5.1': + resolution: {integrity: sha512-oTXEIha4SsuXdTA4Iyskj0kpdx2yVXdhd75c2v3xGrHFfVMsbhTPZU/nMPL4sWKo4pBHm3aucLaqGlF696dTyQ==} + engines: {node: ^22.20 || ^24.12 || >=25} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@npmcli/fs@2.1.2': + resolution: {integrity: sha512-yOJKRvohFOaLqipNtwYB9WugyZKhC/DZC4VYPmpaCzDBrA8YpK3qHZ8/HGscMnE4GqbkLNuVcCnxkeQEdGt6LQ==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + + '@npmcli/move-file@2.0.1': + resolution: {integrity: sha512-mJd2Z5TjYWq/ttPLLGqArdtnC74J6bOzg4rMDnN+p1xTacZ2yPRCk2y0oSWQtygLR9YVQXgOcONrwtnk3JupxQ==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + deprecated: This functionality has been moved to @npmcli/fs + + '@pkgjs/parseargs@0.11.0': + resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} + engines: {node: '>=14'} + + '@rollup/rollup-android-arm-eabi@4.64.6': + resolution: {integrity: sha512-FkO19Fowv/OQeJZPVfdetJaI3/VpbZmBsnmAlR/rQ+b3QwfiGQiOpVegpSRH331kelvHTVw9hXYG3DwjAaRzyQ==} + cpu: [arm] + os: [android] + + '@rollup/rollup-android-arm64@4.64.6': + resolution: {integrity: sha512-si5/Etm6MphPc2xYHnk455Shls/hoMjTy3mhXge4OPmvCw7TwC4KP4fKokAlKLV4XaQvLvgSHfafPcblLMYYdQ==} + cpu: [arm64] + os: [android] + + '@rollup/rollup-darwin-arm64@4.64.6': + resolution: {integrity: sha512-PQCl3q7b0BgvVt72i2xrWM6I5KliwwVe4GpWW5QDGyUQawDS9aPZss/aGyFqBmxdRxlE8wDc9CaxiQ5DHRSp/Q==} + cpu: [arm64] + os: [darwin] + + '@rollup/rollup-darwin-x64@4.64.6': + resolution: {integrity: sha512-l9DFl1Itb1YYdSrP1K3U8ih44AOHa/p+Q4WMMDfGvH5qVWp+ajfgS1DlYo4yCRh8wJ2ZJv0Fqccf+ULAmMFjmg==} + cpu: [x64] + os: [darwin] + + '@rollup/rollup-freebsd-arm64@4.64.6': + resolution: {integrity: sha512-bR4GR3205N9+od0+l5Dd9/iZTDpJkIe6d6Ydp2qbcQZJLmKBdYQQRp8gbWpbMt92twKJY66o1vK4NkoKQODIrA==} + cpu: [arm64] + os: [freebsd] + + '@rollup/rollup-freebsd-x64@4.64.6': + resolution: {integrity: sha512-XTVNaDzcFl2TeBglvxdGgsCv9JGtAGRAoJENmGBR/XvDH2mA2K0IXc2aMfP0dR8mexSXSKifJ85FixoXX1wfTw==} + cpu: [x64] + os: [freebsd] + + '@rollup/rollup-linux-arm-gnueabihf@4.64.6': + resolution: {integrity: sha512-qWc6qbc+25ugG9vqPR9P422KJBbVfZ05mjcMggoq8tsfWP+eRfC+/tiDdIlRF5VL2pDVZWN9zAhWsmu7R1+7Dw==} + cpu: [arm] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-arm-musleabihf@4.64.6': + resolution: {integrity: sha512-V4Nwkp8844X/Xnww3PI1LYS0YPei8XQEVG70R+5MPZGO7AhYoun4hCN7Svs4U3wbQLZbwiz+9xRFhUZZdRl8Ww==} + cpu: [arm] + os: [linux] + libc: [musl] + + '@rollup/rollup-linux-arm64-gnu@4.64.6': + resolution: {integrity: sha512-xb72A1aPaaIsp+a88VtRae/ovIEXislbUMyp7b9AQQU7ZkP2m/+ik6DW9TQcJyw5R8/RIailF9zExYwkjR++UA==} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-arm64-musl@4.64.6': + resolution: {integrity: sha512-pbcs1BVBwC43hZkjhjlF8Rx8m5G0KnhLZs9Azy/gqccP6UsNSzJr0hKGIAVPqzAH1O/NdPxxC9GVGb4msQg/aw==} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@rollup/rollup-linux-loong64-gnu@4.64.6': + resolution: {integrity: sha512-EKOC8os6Vsg487ZLKUqzLF99Jsmnq6tu7O7mAELakNpcA+8KadktFf/JYdRuHe/DzCUXmN38pUKu4XBcKlqGbQ==} + cpu: [loong64] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-loong64-musl@4.64.6': + resolution: {integrity: sha512-v/SQ68GnSlr/HyjB79sNXesGDwkOPu9JjbHfmWaymCiM+nZsQ9TstG1KfA4MuEvTr2d3PoY8PhFxj9bt0e32JA==} + cpu: [loong64] + os: [linux] + libc: [musl] + + '@rollup/rollup-linux-ppc64-gnu@4.64.6': + resolution: {integrity: sha512-G3pmliMQ7r15zFFNwBlaT/xTdSLi4lfgI7CUrQueyKYheNVhrd8JrWCE6Ll8xf4AA1RZFqq+mNJYntiElsVOyA==} + cpu: [ppc64] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-ppc64-musl@4.64.6': + resolution: {integrity: sha512-XQTB/IPoB/wG6x/wu9uomAt8YH61IAr5iZTubMiad/lu88sotq2ocz9hJd556+Jz2kIkF7ZQZIsUuWE3OWqtcA==} + cpu: [ppc64] + os: [linux] + libc: [musl] + + '@rollup/rollup-linux-riscv64-gnu@4.64.6': + resolution: {integrity: sha512-O5mpokth6+ydMuwiGtY8fIjvOBfH7u6SzmDNmZ3k6GK5C6iEAC2q2ZN/T5L9jYILx0IcCT0KnfMDihQ5yQFSBw==} + cpu: [riscv64] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-riscv64-musl@4.64.6': + resolution: {integrity: sha512-aIFxbAD9v3TvIaEDsKmukjcDg1JS4/tFXw8SHyQQgzOwzWCQ4cyDK7Ju1pQKqUXDFkEu/BZCFDCDATsKhQcB/Q==} + cpu: [riscv64] + os: [linux] + libc: [musl] + + '@rollup/rollup-linux-s390x-gnu@4.64.6': + resolution: {integrity: sha512-fuNo1UwBc6BxnHDOxxguQL/InhheMN3RJcJMb0b4xP8r5Q3CNCrJbVg0eCIFuJ4e/zAfjR2gYbOfbzO/G7CIyw==} + cpu: [s390x] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-x64-gnu@4.64.6': + resolution: {integrity: sha512-05v6wFKDKJPZs9xlytVrrRu6IbRuoSvlH9xNwEOafXsKyjBFZPvAcZz2VIAB/M+lblYeKa9iOYC4RDVdfcAAaw==} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-x64-musl@4.64.6': + resolution: {integrity: sha512-wJXKcdMjvkc/FaavZXNP1yW4i0pfOmhZAIWRSLG2yJ0PB0TWi7dkLErhX0u0vptDcXKKO/m1Y/YTeuyvb2MXwg==} + cpu: [x64] + os: [linux] + libc: [musl] + + '@rollup/rollup-openbsd-x64@4.64.6': + resolution: {integrity: sha512-cwg7/h0ThvJwy8CBkmACdiHAxRWpbsCmIsjOt+Zzx0hTnIcSUmKYEV03bGg+hD827OnwUsbKh1ZZDW754xWyBA==} + cpu: [x64] + os: [openbsd] + + '@rollup/rollup-openharmony-arm64@4.64.6': + resolution: {integrity: sha512-T0RkYIJbdYXJEQFw+tMBO09KDFdgmNxkHsof3wWAABrvnx15Yh8RytmrgYy9+q9cBeBNZF66MMQZC+5nzEz6vg==} + cpu: [arm64] + os: [openharmony] + + '@rollup/rollup-win32-arm64-msvc@4.64.6': + resolution: {integrity: sha512-KlfpmF1AAIdAWxt8QQNClbpLFlAUfYOzqIuJ7IXEStMHpFRuH78RG6FjqPb3Rqhh0K89F5npvG+/i3Fjl6IveQ==} + cpu: [arm64] + os: [win32] + + '@rollup/rollup-win32-ia32-msvc@4.64.6': + resolution: {integrity: sha512-MrTLjd7Jlt9/ZavJZYG61KQv9Iy9bzbY+yXy73Xvwoa2uP66wvDShkyBr5Chz/yrE6lbD/zHMuTmKQVNQqBApg==} + cpu: [ia32] + os: [win32] + + '@rollup/rollup-win32-x64-gnu@4.64.6': + resolution: {integrity: sha512-8fWDH1CkPI8GdBKAxzHDza7UmgficsKo2+MVbvUgOGhB0629w5sHMg3Qu5y7TZsrYKHHWpz8fla4KvoT7WsO3Q==} + cpu: [x64] + os: [win32] + + '@rollup/rollup-win32-x64-msvc@4.64.6': + resolution: {integrity: sha512-9/c9PWdr5GCIHkkxiHM1HjNBQMVdftP4O8QTcoUAaRza2FSqJ4axbf8QAnBuE6BIGQDl71SaRPeDdDYid5ecTw==} + cpu: [x64] + os: [win32] + + '@sindresorhus/is@4.6.0': + resolution: {integrity: sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==} + engines: {node: '>=10'} + + '@szmarczak/http-timer@4.0.6': + resolution: {integrity: sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==} + engines: {node: '>=10'} + + '@tootallnate/once@2.0.1': + resolution: {integrity: sha512-HqmEUIGRJ5fSXchkVgR5F7qn48bDBzv0kWj/Kfu5e6uci4UlEeng4331LnBkWffb++Ei3FOVLxo8JJWMFBDMeQ==} + engines: {node: '>= 10'} + + '@types/cacheable-request@6.0.3': + resolution: {integrity: sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==} + + '@types/debug@4.1.13': + resolution: {integrity: sha512-KSVgmQmzMwPlmtljOomayoR89W4FynCAi3E8PPs7vmDVPe84hT+vGPKkJfThkmXs0x0jAaa9U8uW8bbfyS2fWw==} + + '@types/estree@1.0.9': + resolution: {integrity: sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==} + + '@types/fs-extra@9.0.13': + resolution: {integrity: sha512-nEnwB++1u5lVDM2UI4c1+5R+FYaKfaAzS4OococimjVm3nQw3TuzH5UNsocrcTBbhnerblyHj4A49qXbIiZdpA==} + + '@types/http-cache-semantics@4.2.0': + resolution: {integrity: sha512-L3LgimLHXtGkWikKnsPg0/VFx9OGZaC+eN1u4r+OB1XRqH3meBIAVC2zr1WdMH+RHmnRkqliQAOHNJ/E0j/e0Q==} + + '@types/keyv@3.1.4': + resolution: {integrity: sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==} + + '@types/ms@2.1.0': + resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==} + + '@types/node@20.19.43': + resolution: {integrity: sha512-6oYBAi5ikg4Pl+kGsoYtawUMBT2zZMCvPNF7pVLnHZfd1zf38DRiWn/gT01RYCdUqkv7Fhr+C9ot4/tb+2sVvA==} + + '@types/node@26.6.5': + resolution: {integrity: sha512-uMzsv9stDdofIZBx4UGh4Z9ZgXnGC9seRDscilBcTHAeOFk67MZg/k9bWVfO+bk4qZmG+l52hRnLwUiH2LnJTg==} + + '@types/plist@3.0.5': + resolution: {integrity: sha512-E6OCaRmAe4WDmWNsL/9RMqdkkzDCY1etutkflWk4c+AcjDU07Pcz1fQwTX0TQz+Pxqn9i4L1TU3UFpjnrcDgxA==} + + '@types/responselike@1.0.3': + resolution: {integrity: sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==} + + '@types/verror@1.10.11': + resolution: {integrity: sha512-RlDm9K7+o5stv0Co8i8ZRGxDbrTxhJtgjqjFyVh/tXQyl/rYtTKlnTvZ88oSTeYREWurwx20Js4kTuKCsFkUtg==} + + '@types/yauzl@2.10.3': + resolution: {integrity: sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==} + + '@vitejs/plugin-vue@5.2.4': + resolution: {integrity: sha512-7Yx/SXSOcQq5HiiV3orevHUFn+pmMB4cgbEkDYgnkUWb0WfeQ/wa2yFv6D5ICiCQOVpjA7vYDXrC7AGO8yjDHA==} + engines: {node: ^18.0.0 || >=20.0.0} + peerDependencies: + vite: ^5.0.0 || ^6.0.0 + vue: ^3.2.25 + + '@vue/compiler-core@3.5.44': + resolution: {integrity: sha512-k34nCytbK8PQ1gR2mGROYOw6Pnv/mumqIdrZ3x2tbyXZDWm7ViKGLTfdB+DRrWqEQsLgGJvn0WN9jBif5zCTLQ==} + + '@vue/compiler-dom@3.5.44': + resolution: {integrity: sha512-W5AoBFWdw1lQAKiHowkfgFKFab82oSRT6sGsPfw/q1GRjsy/ZJFLHGhJyBRIFN9APLTUduDH9U2JAiPOIyKuYg==} + + '@vue/compiler-sfc@3.5.44': + resolution: {integrity: sha512-dzHmQ4jXTpdr5FjIQUeykVakN/uzqFbUo9/C5ikBFg3a3PeM6uRxeczx1ZbXBML0/zJstEh3ygYipzR5Z7b2Pw==} + + '@vue/compiler-ssr@3.5.44': + resolution: {integrity: sha512-xr5gb1JVHlfXJwSlRz1FeP6uxoazdzHuMTVLE7up+4Vrqxk219CvxLPxD9NXBt47yvZW7+p4DXfyp4O1fkByIA==} + + '@vue/reactivity@3.5.44': + resolution: {integrity: sha512-u+QJdKeBBEADkPdevsL+6E12QlYVfBD8Zcw5qjDQKtamI6l14KyqazJMobhCKelhWN5zpyKUiEDoTyHE93cqWw==} + + '@vue/runtime-core@3.5.44': + resolution: {integrity: sha512-uEa/ndwjhrrhnOfb2p+sZy6zeoamJOISqaLSJGk/8R6nABT1ZldpzcJoPzKj+zHVomVBPcmQYyC2r4LtvDV6CQ==} + + '@vue/runtime-dom@3.5.44': + resolution: {integrity: sha512-3fc4ARcXVhVBaJ3ujWiNZJARD6pkyRcwG+ZYhMzjKtKUp7MAY0HLwr7r3Smep3Li6ZaWT6ewdmx8XqdaD5oNZg==} + + '@vue/server-renderer@3.5.44': + resolution: {integrity: sha512-R4S1UoH4h5Frrauv8Z5XE5TxV9oBiUSgWIC4TyVK1FK+RocRnOLwFA5Xcmo2011RlgJp+AbZCnw6afrhlgRuUQ==} + + '@vue/shared@3.5.44': + resolution: {integrity: sha512-H82XLH0DjmSOdbEwO15x3QTo1f5PWEtv237eLpYKc0mqLu+B8hnq16lFWmuBmNurkeiG3wr+oM1FhOll/YVFRg==} + + '@xmldom/xmldom@0.9.12': + resolution: {integrity: sha512-5AXjrcMClTryPe9LgZrygpB1lj7s0S9E0+W+AHaVKAVyHanafK86iPSvG5xHVSp/jC+VH1UXu0TAEmY279xH7A==} + engines: {node: '>=14.6'} + + abbrev@1.1.1: + resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==} + + agent-base@6.0.2: + resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} + engines: {node: '>= 6.0.0'} + + agent-base@7.1.4: + resolution: {integrity: sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==} + engines: {node: '>= 14'} + + agentkeepalive@4.6.0: + resolution: {integrity: sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ==} + engines: {node: '>= 8.0.0'} + + aggregate-error@3.1.0: + resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==} + engines: {node: '>=8'} + + ajv-keywords@3.5.2: + resolution: {integrity: sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==} + peerDependencies: + ajv: ^6.9.1 + + ajv@6.15.0: + resolution: {integrity: sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==} + + ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + + ansi-regex@6.4.0: + resolution: {integrity: sha512-KzTVk2tCWAHtYrvvvaP8bJKJq2pVinhLcGEQdtLIYPbmNGNyYe8QwNaTUYQp2J7/vIsUKt5QCqAfUkYyG9DkOw==} + engines: {node: '>=12'} + + ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + + ansi-styles@6.2.3: + resolution: {integrity: sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==} + engines: {node: '>=12'} + + app-builder-bin@5.0.0-alpha.10: + resolution: {integrity: sha512-Ev4jj3D7Bo+O0GPD2NMvJl+PGiBAfS7pUGawntBNpCbxtpncfUixqFj9z9Jme7V7s3LBGqsWZZP54fxBX3JKJw==} + + app-builder-lib@25.1.8: + resolution: {integrity: sha512-pCqe7dfsQFBABC1jeKZXQWhGcCPF3rPCXDdfqVKjIeWBcXzyC1iOWZdfFhGl+S9MyE/k//DFmC6FzuGAUudNDg==} + engines: {node: '>=14.0.0'} + peerDependencies: + dmg-builder: 25.1.8 + electron-builder-squirrel-windows: 25.1.8 + + aproba@2.1.0: + resolution: {integrity: sha512-tLIEcj5GuR2RSTnxNKdkK0dJ/GrC7P38sUkiDmDuHfsHmbagTFAxDVIBltoklXEVIQ/f14IL8IMJ5pn9Hez1Ew==} + + archiver-utils@2.1.0: + resolution: {integrity: sha512-bEL/yUb/fNNiNTuUz979Z0Yg5L+LzLxGJz8x79lYmR54fmTIb6ob/hNQgkQnIUDWIFjZVQwl9Xs356I6BAMHfw==} + engines: {node: '>= 6'} + + archiver-utils@3.0.4: + resolution: {integrity: sha512-KVgf4XQVrTjhyWmx6cte4RxonPLR9onExufI1jhvw/MQ4BB6IsZD5gT8Lq+u/+pRkWna/6JoHpiQioaqFP5Rzw==} + engines: {node: '>= 10'} + + archiver@5.3.2: + resolution: {integrity: sha512-+25nxyyznAXF7Nef3y0EbBeqmGZgeN/BxHX29Rs39djAfaFalmQ89SE6CWyDCHzGL0yt/ycBtNOmGTW0FyGWNw==} + engines: {node: '>= 10'} + + are-we-there-yet@3.0.1: + resolution: {integrity: sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + deprecated: This package is no longer supported. + + argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + + assert-plus@1.0.0: + resolution: {integrity: sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==} + engines: {node: '>=0.8'} + + astral-regex@2.0.0: + resolution: {integrity: sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==} + engines: {node: '>=8'} + + async-exit-hook@2.0.1: + resolution: {integrity: sha512-NW2cX8m1Q7KPA7a5M2ULQeZ2wR5qI5PAbw5L0UOMxdioVk9PMZ0h1TmyZEkPYrCvYjDlFICusOu1dlEKAAeXBw==} + engines: {node: '>=0.12.0'} + + async@3.2.6: + resolution: {integrity: sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==} + + asynckit@0.4.0: + resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + + at-least-node@1.0.0: + resolution: {integrity: sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==} + engines: {node: '>= 4.0.0'} + + balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + + balanced-match@4.0.4: + resolution: {integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==} + engines: {node: 18 || 20 || >=22} + + base64-js@1.5.1: + resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + + bl@4.1.0: + resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} + + bluebird-lst@1.0.9: + resolution: {integrity: sha512-7B1Rtx82hjnSD4PGLAjVWeYH3tHAcVUmChh85a3lltKQm6FresXh9ErQo6oAv6CqxttczC3/kEg8SY5NluPuUw==} + + bluebird@3.7.2: + resolution: {integrity: sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==} + + boolean@3.2.0: + resolution: {integrity: sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==} + deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info. + + brace-expansion@1.1.21: + resolution: {integrity: sha512-9zeA+KLZNNzglF2TPKRQEDyx6Yby7daAkuy8MiPzpXPsYDWi/DRM8jmwUDxokQjYqBpv5DgPiwD4h4ZZSy1Ujw==} + + brace-expansion@2.1.7: + resolution: {integrity: sha512-uZbew1NqdmPDTMJ8ah1y+b+9QEJrfkXFk3RcTQw3X0jW/xRUvFKsg1CfQdSYGdTbXZWExtU3J3ccxtnfw1Fi0g==} + + brace-expansion@5.0.12: + resolution: {integrity: sha512-YovQ3rzhaLMIrDjNDMkNS01tea93qhEhG5xy8f6+R0l+dw3Ki+5sCoIoI942iuLZTHWogWktgwVDhU09iNEimQ==} + engines: {node: 20 || >=22} + + buffer-crc32@0.2.13: + resolution: {integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==} + + buffer-from@1.1.2: + resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} + + buffer@5.7.1: + resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} + + builder-util-runtime@9.2.10: + resolution: {integrity: sha512-6p/gfG1RJSQeIbz8TK5aPNkoztgY1q5TgmGFMAXcY8itsGW6Y2ld1ALsZ5UJn8rog7hKF3zHx5iQbNQ8uLcRlw==} + engines: {node: '>=12.0.0'} + + builder-util@25.1.7: + resolution: {integrity: sha512-7jPjzBwEGRbwNcep0gGNpLXG9P94VA3CPAZQCzxkFXiV2GMQKlziMbY//rXPI7WKfhsvGgFXjTcXdBEwgXw9ww==} + + cacache@16.1.3: + resolution: {integrity: sha512-/+Emcj9DAXxX4cwlLmRI9c166RuL3w30zp4R7Joiv2cQTtTtA+jeuCAjH3ZlGnYS3tKENSrKhAzVVP9GVyzeYQ==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + + cacheable-lookup@5.0.4: + resolution: {integrity: sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==} + engines: {node: '>=10.6.0'} + + cacheable-request@7.0.4: + resolution: {integrity: sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg==} + engines: {node: '>=8'} + + call-bind-apply-helpers@1.0.2: + resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} + engines: {node: '>= 0.4'} + + chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + + chownr@2.0.0: + resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==} + engines: {node: '>=10'} + + chromium-pickle-js@0.2.0: + resolution: {integrity: sha512-1R5Fho+jBq0DDydt+/vHWj5KJNJCKdARKOCwZUen84I5BreWoLqRLANH1U87eJy1tiASPtMnGqJJq0ZsLoRPOw==} + + ci-info@3.9.0: + resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} + engines: {node: '>=8'} + + clean-stack@2.2.0: + resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==} + engines: {node: '>=6'} + + cli-cursor@3.1.0: + resolution: {integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==} + engines: {node: '>=8'} + + cli-spinners@2.9.2: + resolution: {integrity: sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==} + engines: {node: '>=6'} + + cli-truncate@2.1.0: + resolution: {integrity: sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==} + engines: {node: '>=8'} + + cliui@8.0.1: + resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} + engines: {node: '>=12'} + + clone-response@1.0.3: + resolution: {integrity: sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==} + + clone@1.0.4: + resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==} + engines: {node: '>=0.8'} + + color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + + color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + + color-support@1.1.3: + resolution: {integrity: sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==} + hasBin: true + + combined-stream@1.0.8: + resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} + engines: {node: '>= 0.8'} + + commander@5.1.0: + resolution: {integrity: sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==} + engines: {node: '>= 6'} + + compare-version@0.1.2: + resolution: {integrity: sha512-pJDh5/4wrEnXX/VWRZvruAGHkzKdr46z11OlTPN+VrATlWWhSKewNCJ1futCO5C7eJB3nPMFZA1LeYtcFboZ2A==} + engines: {node: '>=0.10.0'} + + compress-commons@4.1.2: + resolution: {integrity: sha512-D3uMHtGc/fcO1Gt1/L7i1e33VOvD4A9hfQLP+6ewd+BvG/gQ84Yh4oftEhAdjSMgBgwGL+jsppT7JYNpo6MHHg==} + engines: {node: '>= 10'} + + concat-map@0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + + config-file-ts@0.2.8-rc1: + resolution: {integrity: sha512-GtNECbVI82bT4RiDIzBSVuTKoSHufnU7Ce7/42bkWZJZFLjmDF2WBpVsvRkhKCfKBnTBb3qZrBwPpFBU/Myvhg==} + + console-control-strings@1.1.0: + resolution: {integrity: sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==} + + core-util-is@1.0.2: + resolution: {integrity: sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==} + + core-util-is@1.0.3: + resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} + + crc-32@1.2.2: + resolution: {integrity: sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==} + engines: {node: '>=0.8'} + hasBin: true + + crc32-stream@4.0.3: + resolution: {integrity: sha512-NT7w2JVU7DFroFdYkeq8cywxrgjPHWkdX1wjpRQXPX5Asews3tA+Ght6lddQO5Mkumffp3X7GEqku3epj2toIw==} + engines: {node: '>= 10'} + + crc@3.8.0: + resolution: {integrity: sha512-iX3mfgcTMIq3ZKLIsVFAbv7+Mc10kxabAGQb8HvjA1o3T1PIYprbakQ65d3I+2HGHt6nSKkM9PYjgoJO2KcFBQ==} + + cross-spawn@7.0.6: + resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} + engines: {node: '>= 8'} + + csstype@3.2.3: + resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==} + + debug@4.4.3: + resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + decompress-response@6.0.0: + resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==} + engines: {node: '>=10'} + + defaults@1.0.4: + resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==} + + defer-to-connect@2.0.1: + resolution: {integrity: sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==} + engines: {node: '>=10'} + + define-data-property@1.1.4: + resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} + engines: {node: '>= 0.4'} + + define-properties@1.2.1: + resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} + engines: {node: '>= 0.4'} + + delayed-stream@1.0.0: + resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} + engines: {node: '>=0.4.0'} + + delegates@1.0.0: + resolution: {integrity: sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==} + + detect-libc@2.1.2: + resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} + engines: {node: '>=8'} + + detect-node@2.1.0: + resolution: {integrity: sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==} + + dexie@4.4.6: + resolution: {integrity: sha512-hJP/BO6mjB+tX6hToIO1kmxYLNmun90wYbfcoAoLpKEyDYal/k33dg0TAfoUe2TDsbbLoVIzljJ3BN2UbR5EOg==} + + dir-compare@4.2.0: + resolution: {integrity: sha512-2xMCmOoMrdQIPHdsTawECdNPwlVFB9zGcz3kuhmBO6U3oU+UQjsue0i8ayLKpgBcm+hcXPMVSGUN9d+pvJ6+VQ==} + + dmg-builder@25.1.8: + resolution: {integrity: sha512-NoXo6Liy2heSklTI5OIZbCgXC1RzrDQsZkeEwXhdOro3FT1VBOvbubvscdPnjVuQ4AMwwv61oaH96AbiYg9EnQ==} + + dmg-license@1.0.11: + resolution: {integrity: sha512-ZdzmqwKmECOWJpqefloC5OJy1+WZBBse5+MR88z9g9Zn4VY+WYUkAyojmhzJckH5YbbZGcYIuGAkY5/Ys5OM2Q==} + engines: {node: '>=8'} + os: [darwin] + hasBin: true + + dotenv-expand@11.0.7: + resolution: {integrity: sha512-zIHwmZPRshsCdpMDyVsqGmgyP0yT8GAgXUnkdAoJisxvf33k7yO6OuoKmcTGuXPWSsm8Oh88nZicRLA9Y0rUeA==} + engines: {node: '>=12'} + + dotenv@16.6.1: + resolution: {integrity: sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==} + engines: {node: '>=12'} + + dunder-proto@1.0.1: + resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} + engines: {node: '>= 0.4'} + + eastasianwidth@0.2.0: + resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} + + ejs@3.1.10: + resolution: {integrity: sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==} + engines: {node: '>=0.10.0'} + hasBin: true + + electron-builder-squirrel-windows@25.1.8: + resolution: {integrity: sha512-2ntkJ+9+0GFP6nAISiMabKt6eqBB0kX1QqHNWFWAXgi0VULKGisM46luRFpIBiU3u/TDmhZMM8tzvo2Abn3ayg==} + + electron-builder@25.1.8: + resolution: {integrity: sha512-poRgAtUHHOnlzZnc9PK4nzG53xh74wj2Jy7jkTrqZ0MWPoHGh1M2+C//hGeYdA+4K8w4yiVCNYoLXF7ySj2Wig==} + engines: {node: '>=14.0.0'} + hasBin: true + + electron-publish@25.1.7: + resolution: {integrity: sha512-+jbTkR9m39eDBMP4gfbqglDd6UvBC7RLh5Y0MhFSsc6UkGHj9Vj9TWobxevHYMMqmoujL11ZLjfPpMX+Pt6YEg==} + + electron@33.4.11: + resolution: {integrity: sha512-xmdAs5QWRkInC7TpXGNvzo/7exojubk+72jn1oJL7keNeIlw7xNglf8TGtJtkR4rWC5FJq0oXiIXPS9BcK2Irg==} + engines: {node: '>= 12.20.55'} + hasBin: true + + emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + + emoji-regex@9.2.2: + resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + + encoding@0.1.13: + resolution: {integrity: sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==} + + end-of-stream@1.4.5: + resolution: {integrity: sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==} + + entities@7.0.1: + resolution: {integrity: sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==} + engines: {node: '>=0.12'} + + env-paths@2.2.1: + resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==} + engines: {node: '>=6'} + + err-code@2.0.3: + resolution: {integrity: sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==} + + es-define-property@1.0.1: + resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} + engines: {node: '>= 0.4'} + + es-errors@1.3.0: + resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} + engines: {node: '>= 0.4'} + + es-object-atoms@1.1.2: + resolution: {integrity: sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==} + engines: {node: '>= 0.4'} + + es-set-tostringtag@2.1.0: + resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} + engines: {node: '>= 0.4'} + + es6-error@4.1.1: + resolution: {integrity: sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==} + + esbuild@0.21.5: + resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==} + engines: {node: '>=12'} + hasBin: true + + escalade@3.2.0: + resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} + engines: {node: '>=6'} + + escape-string-regexp@4.0.0: + resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} + engines: {node: '>=10'} + + estree-walker@2.0.2: + resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} + + exponential-backoff@3.1.3: + resolution: {integrity: sha512-ZgEeZXj30q+I0EN+CbSSpIyPaJ5HVQD18Z1m+u1FXbAeT94mr1zw50q4q6jiiC447Nl/YTcIYSAftiGqetwXCA==} + + extract-zip@2.0.1: + resolution: {integrity: sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==} + engines: {node: '>= 10.17.0'} + hasBin: true + + extsprintf@1.4.1: + resolution: {integrity: sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA==} + engines: {'0': node >=0.6.0} + + fast-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + + fast-json-stable-stringify@2.1.0: + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + + fd-slicer@1.1.0: + resolution: {integrity: sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==} + + filelist@1.0.6: + resolution: {integrity: sha512-5giy2PkLYY1cP39p17Ech+2xlpTRL9HLspOfEgm0L6CwBXBTgsK5ou0JtzYuepxkaQ/tvhCFIJ5uXo0OrM2DxA==} + + foreground-child@3.3.1: + resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} + engines: {node: '>=14'} + + form-data@4.0.6: + resolution: {integrity: sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==} + engines: {node: '>= 6'} + + fs-constants@1.0.0: + resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==} + + fs-extra@10.1.0: + resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==} + engines: {node: '>=12'} + + fs-extra@11.4.1: + resolution: {integrity: sha512-KYAb4c9BJQI6QqGKthV68OHe0badztdXJWKo0WtBA9IuCFPTKvE5ZdUBglP833aMjhaSPNO4A5j/EkzZtGlKjA==} + engines: {node: '>=14.14'} + + fs-extra@8.1.0: + resolution: {integrity: sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==} + engines: {node: '>=6 <7 || >=8'} + + fs-extra@9.1.0: + resolution: {integrity: sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==} + engines: {node: '>=10'} + + fs-minipass@2.1.0: + resolution: {integrity: sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==} + engines: {node: '>= 8'} + + fs.realpath@1.0.0: + resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} + + fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + + function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + + gauge@4.0.4: + resolution: {integrity: sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + deprecated: This package is no longer supported. + + get-caller-file@2.0.5: + resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} + engines: {node: 6.* || 8.* || >= 10.*} + + get-intrinsic@1.3.0: + resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} + engines: {node: '>= 0.4'} + + get-proto@1.0.1: + resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} + engines: {node: '>= 0.4'} + + get-stream@5.2.0: + resolution: {integrity: sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==} + engines: {node: '>=8'} + + glob@10.5.0: + resolution: {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 + hasBin: true + + glob@7.2.3: + resolution: {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 + + glob@8.1.0: + resolution: {integrity: sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==} + engines: {node: '>=12'} + 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 + + global-agent@3.0.0: + resolution: {integrity: sha512-PT6XReJ+D07JvGoxQMkT6qji/jVNfX/h364XHZOWeRzy64sSFr+xJ5OX7LI3b4MPQzdL4H8Y8M0xzPpsVMwA8Q==} + engines: {node: '>=10.0'} + + globalthis@1.0.4: + resolution: {integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==} + engines: {node: '>= 0.4'} + + gopd@1.2.0: + resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} + engines: {node: '>= 0.4'} + + got@11.8.6: + resolution: {integrity: sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==} + engines: {node: '>=10.19.0'} + + graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + + has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + + has-property-descriptors@1.0.2: + resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} + + has-symbols@1.1.0: + resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} + engines: {node: '>= 0.4'} + + has-tostringtag@1.0.2: + resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} + engines: {node: '>= 0.4'} + + has-unicode@2.0.1: + resolution: {integrity: sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==} + + hasown@2.0.4: + resolution: {integrity: sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==} + engines: {node: '>= 0.4'} + + hosted-git-info@4.1.0: + resolution: {integrity: sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==} + engines: {node: '>=10'} + + http-cache-semantics@4.3.0: + resolution: {integrity: sha512-M5t5LlJpS1UHMjvwRQVdFHvPISGeLAxNcrWuJkeGh0KxsqCHZ1O3NXZU/8x7cD0BDcGW8kapxMKTvwlqrNkHkA==} + + http-proxy-agent@5.0.0: + resolution: {integrity: sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==} + engines: {node: '>= 6'} + + http-proxy-agent@7.0.2: + resolution: {integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==} + engines: {node: '>= 14'} + + http2-wrapper@1.0.3: + resolution: {integrity: sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==} + engines: {node: '>=10.19.0'} + + https-proxy-agent@5.0.1: + resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} + engines: {node: '>= 6'} + + https-proxy-agent@7.0.6: + resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==} + engines: {node: '>= 14'} + + humanize-ms@1.2.1: + resolution: {integrity: sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==} + + iconv-corefoundation@1.1.7: + resolution: {integrity: sha512-T10qvkw0zz4wnm560lOEg0PovVqUXuOFhhHAkixw8/sycy7TJt7v/RrkEKEQnAw2viPSJu6iAkErxnzR0g8PpQ==} + engines: {node: ^8.11.2 || >=10} + os: [darwin] + + iconv-lite@0.6.3: + resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} + engines: {node: '>=0.10.0'} + + ieee754@1.2.1: + resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} + + imurmurhash@0.1.4: + resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} + engines: {node: '>=0.8.19'} + + indent-string@4.0.0: + resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} + engines: {node: '>=8'} + + infer-owner@1.0.4: + resolution: {integrity: sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==} + + inflight@1.0.6: + resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. + + inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + + ip-address@10.7.4: + resolution: {integrity: sha512-DWBMKyeM25D70nrIiTkgQth59/G+naKOTep6huF9j+GmeK3DMD60Zvxg5d5qQnz+38AHgou6ean2LECX+lrKDg==} + engines: {node: '>= 12'} + + is-ci@3.0.1: + resolution: {integrity: sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==} + hasBin: true + + is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + + is-interactive@1.0.0: + resolution: {integrity: sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==} + engines: {node: '>=8'} + + is-lambda@1.0.1: + resolution: {integrity: sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==} + + is-unicode-supported@0.1.0: + resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==} + engines: {node: '>=10'} + + isarray@1.0.0: + resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} + + isbinaryfile@4.0.10: + resolution: {integrity: sha512-iHrqe5shvBUcFbmZq9zOQHBoeOhZJu6RQGrDpBgenUm/Am+F3JM2MgQj+rK3Z601fzrL5gLZWtAPH2OBaSVcyw==} + engines: {node: '>= 8.0.0'} + + isbinaryfile@5.0.7: + resolution: {integrity: sha512-gnWD14Jh3FzS3CPhF0AxNOJ8CxqeblPTADzI38r0wt8ZyQl5edpy75myt08EG2oKvpyiqSqsx+Wkz9vtkbTqYQ==} + engines: {node: '>= 18.0.0'} + + isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + + jackspeak@3.4.3: + resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} + + jake@10.9.4: + resolution: {integrity: sha512-wpHYzhxiVQL+IV05BLE2Xn34zW1S223hvjtqk0+gsPrwd/8JNLXJgZZM/iPFsYc1xyphF+6M6EvdE5E9MBGkDA==} + engines: {node: '>=10'} + hasBin: true + + js-yaml@4.3.2: + resolution: {integrity: sha512-SFNOvSJ+Dgf/9An904Yx+CgSlIPCkIpao4qo51lpee25TIRejdH3rhR4EZMGoNx3/TP3O+wzWuiTFl4sqbltzA==} + hasBin: true + + json-buffer@3.0.1: + resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} + + json-schema-traverse@0.4.1: + resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + + json-stringify-safe@5.0.1: + resolution: {integrity: sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==} + + json5@2.2.3: + resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} + engines: {node: '>=6'} + hasBin: true + + jsonfile@4.0.0: + resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==} + + jsonfile@6.2.1: + resolution: {integrity: sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==} + + keyv@4.5.4: + resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} + + lazy-val@1.0.5: + resolution: {integrity: sha512-0/BnGCCfyUMkBpeDgWihanIAF9JmZhHBgUhEqzvf+adhNGLoP6TaiI5oF8oyb3I45P+PcnrqihSf01M0l0G5+Q==} + + lazystream@1.0.1: + resolution: {integrity: sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==} + engines: {node: '>= 0.6.3'} + + lodash.defaults@4.2.0: + resolution: {integrity: sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==} + + lodash.difference@4.5.0: + resolution: {integrity: sha512-dS2j+W26TQ7taQBGN8Lbbq04ssV3emRw4NY58WErlTO29pIqS0HmoT5aJ9+TUQ1N3G+JOZSji4eugsWwGp9yPA==} + + lodash.flatten@4.4.0: + resolution: {integrity: sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==} + + lodash.isplainobject@4.0.6: + resolution: {integrity: sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==} + + lodash.union@4.6.0: + resolution: {integrity: sha512-c4pB2CdGrGdjMKYLA+XiRDO7Y0PRQbm/Gzg8qMj+QH+pFVAoTp5sBpO0odL3FjoPCGjK96p6qsP+yQoiLoOBcw==} + + lodash@4.18.1: + resolution: {integrity: sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==} + + log-symbols@4.1.0: + resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==} + engines: {node: '>=10'} + + lowercase-keys@2.0.0: + resolution: {integrity: sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==} + engines: {node: '>=8'} + + lru-cache@10.4.3: + resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} + + lru-cache@6.0.0: + resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} + engines: {node: '>=10'} + + lru-cache@7.18.3: + resolution: {integrity: sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==} + engines: {node: '>=12'} + + magic-string@0.30.21: + resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} + + make-fetch-happen@10.2.1: + resolution: {integrity: sha512-NgOPbRiaQM10DYXvN3/hhGVI2M5MtITFryzBGxHM5p4wnFxsVCbxkrBrDsk+EZ5OB4jEOT7AjDxtdF+KVEFT7w==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + + matcher@3.0.0: + resolution: {integrity: sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng==} + engines: {node: '>=10'} + + math-intrinsics@1.1.0: + resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} + engines: {node: '>= 0.4'} + + mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + + mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + + mime@2.6.0: + resolution: {integrity: sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==} + engines: {node: '>=4.0.0'} + hasBin: true + + mimic-fn@2.1.0: + resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} + engines: {node: '>=6'} + + mimic-response@1.0.1: + resolution: {integrity: sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==} + engines: {node: '>=4'} + + mimic-response@3.1.0: + resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==} + engines: {node: '>=10'} + + minimatch@10.2.6: + resolution: {integrity: sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A==} + engines: {node: 18 || 20 || >=22} + + minimatch@3.1.5: + resolution: {integrity: sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==} + + minimatch@5.1.9: + resolution: {integrity: sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==} + engines: {node: '>=10'} + + minimatch@9.0.9: + resolution: {integrity: sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==} + engines: {node: '>=16 || 14 >=14.17'} + + minimist@1.2.8: + resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + + minipass-collect@1.0.2: + resolution: {integrity: sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==} + engines: {node: '>= 8'} + + minipass-fetch@2.1.2: + resolution: {integrity: sha512-LT49Zi2/WMROHYoqGgdlQIZh8mLPZmOrN2NdJjMXxYe4nkN6FUyuPuOAOedNJDrx0IRGg9+4guZewtp8hE6TxA==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + + minipass-flush@1.0.7: + resolution: {integrity: sha512-TbqTz9cUwWyHS2Dy89P3ocAGUGxKjjLuR9z8w4WUTGAVgEj17/4nhgo2Du56i0Fm3Pm30g4iA8Lcqctc76jCzA==} + engines: {node: '>= 8'} + + minipass-pipeline@1.2.4: + resolution: {integrity: sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==} + engines: {node: '>=8'} + + minipass-sized@1.0.3: + resolution: {integrity: sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==} + engines: {node: '>=8'} + + minipass@3.3.6: + resolution: {integrity: sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==} + engines: {node: '>=8'} + + minipass@5.0.0: + resolution: {integrity: sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==} + engines: {node: '>=8'} + + minipass@7.1.3: + resolution: {integrity: sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==} + engines: {node: '>=16 || 14 >=14.17'} + + minizlib@2.1.2: + resolution: {integrity: sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==} + engines: {node: '>= 8'} + + mkdirp@1.0.4: + resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==} + engines: {node: '>=10'} + hasBin: true + + ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + + nanoid@3.3.20: + resolution: {integrity: sha512-uKdg2G3GNCKQn9byYOpxbGqrT2fGO5KRt5J/8b3pok8rT6qxGWF6hxMyJiEYtAf+FVyYuD9hRaDqX5uPFYJ4ZQ==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + + negotiator@0.6.4: + resolution: {integrity: sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==} + engines: {node: '>= 0.6'} + + node-abi@3.98.0: + resolution: {integrity: sha512-Llh8noNw7s15m+rmIrZnZQbe4gLyasL9loT74rC92PkmwWKeEedKvc7o6pjp8B3MhrYT/Cl846NOYZbz1wmddw==} + engines: {node: '>=10'} + + node-addon-api@1.7.2: + resolution: {integrity: sha512-ibPK3iA+vaY1eEjESkQkM0BbCqFOaZMiXRTtdB0u7b4djtY6JnsjvPdUHVMg6xQt3B8fpTTWHI9A+ADjM9frzg==} + + node-api-version@0.2.1: + resolution: {integrity: sha512-2xP/IGGMmmSQpI1+O/k72jF/ykvZ89JeuKX3TLJAYPDVLUalrshrLHkeVcCCZqG/eEa635cr8IBYzgnDvM2O8Q==} + + node-gyp@9.4.1: + resolution: {integrity: sha512-OQkWKbjQKbGkMf/xqI1jjy3oCTgMKJac58G2+bjZb3fza6gW2YrCSdMQYaoTb70crvE//Gngr4f0AgVHmqHvBQ==} + engines: {node: ^12.13 || ^14.13 || >=16} + hasBin: true + + nopt@6.0.0: + resolution: {integrity: sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + hasBin: true + + normalize-path@3.0.0: + resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} + engines: {node: '>=0.10.0'} + + normalize-url@6.1.0: + resolution: {integrity: sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==} + engines: {node: '>=10'} + + npmlog@6.0.2: + resolution: {integrity: sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + deprecated: This package is no longer supported. + + object-keys@1.1.1: + resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} + engines: {node: '>= 0.4'} + + once@1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + + onetime@5.1.2: + resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} + engines: {node: '>=6'} + + ora@5.4.1: + resolution: {integrity: sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==} + engines: {node: '>=10'} + + p-cancelable@2.1.1: + resolution: {integrity: sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==} + engines: {node: '>=8'} + + p-limit@3.1.0: + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} + engines: {node: '>=10'} + + p-map@4.0.0: + resolution: {integrity: sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==} + engines: {node: '>=10'} + + package-json-from-dist@1.0.1: + resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} + + path-is-absolute@1.0.1: + resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} + engines: {node: '>=0.10.0'} + + path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + + path-scurry@1.11.1: + resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} + engines: {node: '>=16 || 14 >=14.18'} + + pe-library@0.4.1: + resolution: {integrity: sha512-eRWB5LBz7PpDu4PUlwT0PhnQfTQJlDDdPa35urV4Osrm0t0AqQFGn+UIkU3klZvwJ8KPO3VbBFsXquA6p6kqZw==} + engines: {node: '>=12', npm: '>=6'} + + pend@1.2.0: + resolution: {integrity: sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==} + + picocolors@1.1.1: + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} + + plist@3.1.1: + resolution: {integrity: sha512-ZIfcLJC+7E7FBFnDxm9MPmt7D+DidyQ26lewieO75AdhA2ayMtsJSES0iWzqJQbcVRSrTufQoy0DR94xHue0oA==} + engines: {node: '>=10.4.0'} + + postcss@8.5.30: + resolution: {integrity: sha512-zkd+e9S1AQHhmaBKye9zlFHWjOwVgqXl1q3ECYy8561K7qxR2cREf/STLskulBFd78k6AOFeA+ff1TtEzk9bAA==} + engines: {node: ^10 || ^12 || >=14} + + process-nextick-args@2.0.1: + resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} + + progress@2.0.3: + resolution: {integrity: sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==} + engines: {node: '>=0.4.0'} + + promise-inflight@1.0.1: + resolution: {integrity: sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==} + peerDependencies: + bluebird: '*' + peerDependenciesMeta: + bluebird: + optional: true + + promise-retry@2.0.1: + resolution: {integrity: sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==} + engines: {node: '>=10'} + + pump@3.0.4: + resolution: {integrity: sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==} + + punycode@2.3.1: + resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} + engines: {node: '>=6'} + + quick-lru@5.1.1: + resolution: {integrity: sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==} + engines: {node: '>=10'} + + read-binary-file-arch@1.0.6: + resolution: {integrity: sha512-BNg9EN3DD3GsDXX7Aa8O4p92sryjkmzYYgmgTAc6CA4uGLEDzFfxOxugu21akOxpcXHiEgsYkC6nPsQvLLLmEg==} + hasBin: true + + readable-stream@2.3.8: + resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==} + + readable-stream@3.6.2: + resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} + engines: {node: '>= 6'} + + readdir-glob@1.1.3: + resolution: {integrity: sha512-v05I2k7xN8zXvPD9N+z/uhXPaj0sUFCe2rcWZIpBsqxfP7xXFQ0tipAd/wjj1YxWyWtUS5IDJpOG82JKt2EAVA==} + + require-directory@2.1.1: + resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} + engines: {node: '>=0.10.0'} + + resedit@1.7.2: + resolution: {integrity: sha512-vHjcY2MlAITJhC0eRD/Vv8Vlgmu9Sd3LX9zZvtGzU5ZImdTN3+d6e/4mnTyV8vEbyf1sgNIrWxhWlrys52OkEA==} + engines: {node: '>=12', npm: '>=6'} + + resolve-alpn@1.2.1: + resolution: {integrity: sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==} + + responselike@2.0.1: + resolution: {integrity: sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==} + + restore-cursor@3.1.0: + resolution: {integrity: sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==} + engines: {node: '>=8'} + + retry@0.12.0: + resolution: {integrity: sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==} + engines: {node: '>= 4'} + + rimraf@3.0.2: + resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} + deprecated: Rimraf versions prior to v4 are no longer supported + hasBin: true + + roarr@2.15.4: + resolution: {integrity: sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A==} + engines: {node: '>=8.0'} + + rollup@4.64.6: + resolution: {integrity: sha512-fX1Vy+UNKdXn+xKDnu/HBXbHVr1AY8cSdQj9BU4kLv5aFCMqGpvrVbyUMmjN3DdzWhSAuTbcX8PCNEVaumthYA==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} + hasBin: true + + safe-buffer@5.1.2: + resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} + + safe-buffer@5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + + safer-buffer@2.1.2: + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + + sanitize-filename@1.6.4: + resolution: {integrity: sha512-9ZyI08PsvdQl2r/bBIGubpVdR3RR9sY6RDiWFPreA21C/EFlQhmgo20UZlNjZMMZNubusLhAQozkA0Od5J21Eg==} + + sax@1.6.1: + resolution: {integrity: sha512-42tBVwLWnaQvW5zc4HbZrTuWccECCZfBi92FDuwtqxasH+JbPB3/FOKb1m222K42R4WxuxzzMsTswfzgtSu64Q==} + engines: {node: '>=11.0.0'} + + semver-compare@1.0.0: + resolution: {integrity: sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==} + + semver@6.3.1: + resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} + hasBin: true + + semver@7.8.5: + resolution: {integrity: sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==} + engines: {node: '>=10'} + hasBin: true + + serialize-error@7.0.1: + resolution: {integrity: sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==} + engines: {node: '>=10'} + + set-blocking@2.0.0: + resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==} + + shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + + shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + + signal-exit@3.0.7: + resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} + + signal-exit@4.1.0: + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} + engines: {node: '>=14'} + + simple-update-notifier@2.0.0: + resolution: {integrity: sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==} + engines: {node: '>=10'} + + slice-ansi@3.0.0: + resolution: {integrity: sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==} + engines: {node: '>=8'} + + smart-buffer@4.2.0: + resolution: {integrity: sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==} + engines: {node: '>= 6.0.0', npm: '>= 3.0.0'} + + socks-proxy-agent@7.0.0: + resolution: {integrity: sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww==} + engines: {node: '>= 10'} + + socks@2.8.10: + resolution: {integrity: sha512-e0VyvkVTwVYViNovRkZ9aodhxVlyoMn7eJhVUPxZ+eK9P/7CBkxvvsBOHqFPEH416726W8tLXXXjKwqgTErrCQ==} + engines: {node: '>= 10.0.0', npm: '>= 3.0.0'} + + source-map-js@1.2.2: + resolution: {integrity: sha512-KGj/8Y43x35aZVDtt+J4mK1hoLGHULMYfSkODJNQjNDC3oW1PqPoxMwo0pLUsWM/UEGzON/NxeHywEfNXNP3Vw==} + engines: {node: '>=0.10.0'} + + source-map-support@0.5.21: + resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} + + source-map@0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + + sprintf-js@1.1.3: + resolution: {integrity: sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==} + + ssri@9.0.1: + resolution: {integrity: sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + + stat-mode@1.0.0: + resolution: {integrity: sha512-jH9EhtKIjuXZ2cWxmXS8ZP80XyC3iasQxMDV8jzhNJpfDb7VbQLVW4Wvsxz9QZvzV+G4YoSfBUVKDOyxLzi/sg==} + engines: {node: '>= 6'} + + string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + + string-width@5.1.2: + resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} + engines: {node: '>=12'} + + string_decoder@1.1.1: + resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} + + string_decoder@1.3.0: + resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} + + strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + + strip-ansi@7.2.0: + resolution: {integrity: sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==} + engines: {node: '>=12'} + + sumchecker@3.0.1: + resolution: {integrity: sha512-MvjXzkz/BOfyVDkG0oFOtBxHX2u3gKbMHIF/dXblZsgD3BWOFLmHovIpZY7BykJdAjcqRCBi1WYBNdEC9yI7vg==} + engines: {node: '>= 8.0'} + + supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + + tar-stream@2.2.0: + resolution: {integrity: sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==} + engines: {node: '>=6'} + + tar@6.2.1: + resolution: {integrity: sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==} + engines: {node: '>=10'} + deprecated: Old versions of tar 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 + + temp-file@3.4.0: + resolution: {integrity: sha512-C5tjlC/HCtVUOi3KWVokd4vHVViOmGjtLwIh4MuzPo/nMYTV/p1urt3RnMz2IWXDdKEGJH3k5+KPxtqRsUYGtg==} + + tmp-promise@3.0.3: + resolution: {integrity: sha512-RwM7MoPojPxsOBYnyd2hy0bxtIlVrihNs9pj5SUvY8Zz1sQcQG2tG1hSr8PDxfgEB8RNKDhqbIlroIarSNDNsQ==} + + tmp@0.2.7: + resolution: {integrity: sha512-e0votIpp4Uo2AJYSzVHV6xCcawuiez3DzqDAbrTc3YxBkplN6e+dM13ZeIcZnDg/QpSuU2zfZ3rzwY8ukEnaXw==} + engines: {node: '>=14.14'} + + truncate-utf8-bytes@1.0.2: + resolution: {integrity: sha512-95Pu1QXQvruGEhv62XCMO3Mm90GscOCClvrIUwCM0PYOXK3kaF3l3sIHxx71ThJfcbM2O5Au6SO3AWCSEfW4mQ==} + + type-fest@0.13.1: + resolution: {integrity: sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==} + engines: {node: '>=10'} + + typescript@5.6.3: + resolution: {integrity: sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==} + engines: {node: '>=14.17'} + hasBin: true + + undici-types@6.21.0: + resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} + + undici-types@8.9.0: + resolution: {integrity: sha512-KTDyRTYX8sWmKXAikPHHSyc63CRPETMctyjKFupcC6OBLXT3xsN0e9aF7m+mIXutFWpUXuedtowG7iLOzp0kQg==} + + unique-filename@2.0.1: + resolution: {integrity: sha512-ODWHtkkdx3IAR+veKxFV+VBkUMcN+FaqzUUd7IZzt+0zhDZFPFxhlqwPF3YQvMHx1TD0tdgYl+kuPnJ8E6ql7A==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + + unique-slug@3.0.0: + resolution: {integrity: sha512-8EyMynh679x/0gqE9fT9oilG+qEt+ibFyqjuVTsZn1+CMxH+XLlpvr2UZx4nVcCwTpx81nICr2JQFkM+HPLq4w==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + + universalify@0.1.2: + resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} + engines: {node: '>= 4.0.0'} + + universalify@2.0.1: + resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} + engines: {node: '>= 10.0.0'} + + uri-js@4.4.1: + resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + + utf8-byte-length@1.0.5: + resolution: {integrity: sha512-Xn0w3MtiQ6zoz2vFyUVruaCL53O/DwUvkEeOvj+uulMm0BkUGYWmBYVyElqZaSLhY6ZD0ulfU3aBra2aVT4xfA==} + + util-deprecate@1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + + verror@1.10.1: + resolution: {integrity: sha512-veufcmxri4e3XSrT0xwfUR7kguIkaxBeosDg00yDWhk49wdwkSUrvvsm7nc75e1PUyvIeZj6nS8VQRYz2/S4Xg==} + engines: {node: '>=0.6.0'} + + vite@5.4.21: + resolution: {integrity: sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==} + engines: {node: ^18.0.0 || >=20.0.0} + hasBin: true + peerDependencies: + '@types/node': ^18.0.0 || >=20.0.0 + less: '*' + lightningcss: ^1.21.0 + sass: '*' + sass-embedded: '*' + stylus: '*' + sugarss: '*' + terser: ^5.4.0 + peerDependenciesMeta: + '@types/node': + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + + vue@3.5.44: + resolution: {integrity: sha512-dvvmaOCG7lAMkJTPqPwWeGMsPS6DIsFsfZDUgBp9V6mHf9b3+/wyVwYR4Es+WV6uJC0FKRxp81Obcq0ZwUcGFQ==} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + wcwidth@1.0.1: + resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==} + + which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + + wide-align@1.1.5: + resolution: {integrity: sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==} + + wrap-ansi@7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} + + wrap-ansi@8.1.0: + resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} + engines: {node: '>=12'} + + wrappy@1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + + xmlbuilder@15.1.1: + resolution: {integrity: sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==} + engines: {node: '>=8.0'} + + y18n@5.0.8: + resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} + engines: {node: '>=10'} + + yallist@4.0.0: + resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} + + yargs-parser@21.1.1: + resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} + engines: {node: '>=12'} + + yargs@17.7.3: + resolution: {integrity: sha512-GZtjxm/J/4TSxuL3FNYjCmLktBTnIw/rVmKSIyKeYAZpmJB2ig9VauCC5xsa82GNKVKDAqpOn3KVzNt0zmrU0g==} + engines: {node: '>=12'} + + yauzl@2.10.0: + resolution: {integrity: sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==} + + yocto-queue@0.1.0: + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + engines: {node: '>=10'} + + zip-stream@4.1.1: + resolution: {integrity: sha512-9qv4rlDiopXg4E69k+vMHjNN63YFMe9sZMrdlvKnCjlCRWeCBswPPMPUfx+ipsAWq1LXHe70RcbaHdJJpS6hyQ==} + engines: {node: '>= 10'} + +snapshots: + + 7zip-bin@5.2.0: {} + + '@babel/helper-string-parser@7.29.7': {} + + '@babel/helper-validator-identifier@7.29.7': {} + + '@babel/parser@7.29.9': + dependencies: + '@babel/types': 7.29.8 + + '@babel/types@7.29.8': + dependencies: + '@babel/helper-string-parser': 7.29.7 + '@babel/helper-validator-identifier': 7.29.7 + + '@develar/schema-utils@2.6.5': + dependencies: + ajv: 6.15.0 + ajv-keywords: 3.5.2(ajv@6.15.0) + + '@electron/asar@3.4.1': + dependencies: + commander: 5.1.0 + glob: 7.2.3 + minimatch: 3.1.5 + + '@electron/get@2.0.3(supports-color@7.2.0)': + dependencies: + debug: 4.4.3(supports-color@7.2.0) + env-paths: 2.2.1 + fs-extra: 8.1.0 + got: 11.8.6 + progress: 2.0.3 + semver: 6.3.1 + sumchecker: 3.0.1(supports-color@7.2.0) + optionalDependencies: + global-agent: 3.0.0 + transitivePeerDependencies: + - supports-color + + '@electron/notarize@2.5.0(supports-color@7.2.0)': + dependencies: + debug: 4.4.3(supports-color@7.2.0) + fs-extra: 9.1.0 + promise-retry: 2.0.1 + transitivePeerDependencies: + - supports-color + + '@electron/osx-sign@1.3.1(supports-color@7.2.0)': + dependencies: + compare-version: 0.1.2 + debug: 4.4.3(supports-color@7.2.0) + fs-extra: 10.1.0 + isbinaryfile: 4.0.10 + minimist: 1.2.8 + plist: 3.1.1 + transitivePeerDependencies: + - supports-color + + '@electron/rebuild@3.6.1(bluebird@3.7.2)(supports-color@7.2.0)': + dependencies: + '@malept/cross-spawn-promise': 2.0.0 + chalk: 4.1.2 + debug: 4.4.3(supports-color@7.2.0) + detect-libc: 2.1.2 + fs-extra: 10.1.0 + got: 11.8.6 + node-abi: 3.98.0 + node-api-version: 0.2.1 + node-gyp: 9.4.1(bluebird@3.7.2)(supports-color@7.2.0) + ora: 5.4.1 + read-binary-file-arch: 1.0.6(supports-color@7.2.0) + semver: 7.8.5 + tar: 6.2.1 + yargs: 17.7.3 + transitivePeerDependencies: + - bluebird + - supports-color + + '@electron/universal@2.0.1(supports-color@7.2.0)': + dependencies: + '@electron/asar': 3.4.1 + '@malept/cross-spawn-promise': 2.0.0 + debug: 4.4.3(supports-color@7.2.0) + dir-compare: 4.2.0 + fs-extra: 11.4.1 + minimatch: 9.0.9 + plist: 3.1.1 + transitivePeerDependencies: + - supports-color + + '@esbuild/aix-ppc64@0.21.5': + optional: true + + '@esbuild/android-arm64@0.21.5': + optional: true + + '@esbuild/android-arm@0.21.5': + optional: true + + '@esbuild/android-x64@0.21.5': + optional: true + + '@esbuild/darwin-arm64@0.21.5': + optional: true + + '@esbuild/darwin-x64@0.21.5': + optional: true + + '@esbuild/freebsd-arm64@0.21.5': + optional: true + + '@esbuild/freebsd-x64@0.21.5': + optional: true + + '@esbuild/linux-arm64@0.21.5': + optional: true + + '@esbuild/linux-arm@0.21.5': + optional: true + + '@esbuild/linux-ia32@0.21.5': + optional: true + + '@esbuild/linux-loong64@0.21.5': + optional: true + + '@esbuild/linux-mips64el@0.21.5': + optional: true + + '@esbuild/linux-ppc64@0.21.5': + optional: true + + '@esbuild/linux-riscv64@0.21.5': + optional: true + + '@esbuild/linux-s390x@0.21.5': + optional: true + + '@esbuild/linux-x64@0.21.5': + optional: true + + '@esbuild/netbsd-x64@0.21.5': + optional: true + + '@esbuild/openbsd-x64@0.21.5': + optional: true + + '@esbuild/sunos-x64@0.21.5': + optional: true + + '@esbuild/win32-arm64@0.21.5': + optional: true + + '@esbuild/win32-ia32@0.21.5': + optional: true + + '@esbuild/win32-x64@0.21.5': + optional: true + + '@gar/promisify@1.1.3': {} + + '@isaacs/cliui@8.0.2': + dependencies: + string-width: 5.1.2 + string-width-cjs: string-width@4.2.3 + strip-ansi: 7.2.0 + strip-ansi-cjs: strip-ansi@6.0.1 + wrap-ansi: 8.1.0 + wrap-ansi-cjs: wrap-ansi@7.0.0 + + '@jridgewell/sourcemap-codec@1.6.0': {} + + '@malept/cross-spawn-promise@2.0.0': + dependencies: + cross-spawn: 7.0.6 + + '@malept/flatpak-bundler@0.4.0(supports-color@7.2.0)': + dependencies: + debug: 4.4.3(supports-color@7.2.0) + fs-extra: 9.1.0 + lodash: 4.18.1 + tmp-promise: 3.0.3 + transitivePeerDependencies: + - supports-color + + '@napi-rs/lzma-linux-x64-gnu@1.5.1': + optional: true + + '@npmcli/fs@2.1.2': + dependencies: + '@gar/promisify': 1.1.3 + semver: 7.8.5 + + '@npmcli/move-file@2.0.1': + dependencies: + mkdirp: 1.0.4 + rimraf: 3.0.2 + + '@pkgjs/parseargs@0.11.0': + optional: true + + '@rollup/rollup-android-arm-eabi@4.64.6': + optional: true + + '@rollup/rollup-android-arm64@4.64.6': + optional: true + + '@rollup/rollup-darwin-arm64@4.64.6': + optional: true + + '@rollup/rollup-darwin-x64@4.64.6': + optional: true + + '@rollup/rollup-freebsd-arm64@4.64.6': + optional: true + + '@rollup/rollup-freebsd-x64@4.64.6': + optional: true + + '@rollup/rollup-linux-arm-gnueabihf@4.64.6': + optional: true + + '@rollup/rollup-linux-arm-musleabihf@4.64.6': + optional: true + + '@rollup/rollup-linux-arm64-gnu@4.64.6': + optional: true + + '@rollup/rollup-linux-arm64-musl@4.64.6': + optional: true + + '@rollup/rollup-linux-loong64-gnu@4.64.6': + optional: true + + '@rollup/rollup-linux-loong64-musl@4.64.6': + optional: true + + '@rollup/rollup-linux-ppc64-gnu@4.64.6': + optional: true + + '@rollup/rollup-linux-ppc64-musl@4.64.6': + optional: true + + '@rollup/rollup-linux-riscv64-gnu@4.64.6': + optional: true + + '@rollup/rollup-linux-riscv64-musl@4.64.6': + optional: true + + '@rollup/rollup-linux-s390x-gnu@4.64.6': + optional: true + + '@rollup/rollup-linux-x64-gnu@4.64.6': + optional: true + + '@rollup/rollup-linux-x64-musl@4.64.6': + optional: true + + '@rollup/rollup-openbsd-x64@4.64.6': + optional: true + + '@rollup/rollup-openharmony-arm64@4.64.6': + optional: true + + '@rollup/rollup-win32-arm64-msvc@4.64.6': + optional: true + + '@rollup/rollup-win32-ia32-msvc@4.64.6': + optional: true + + '@rollup/rollup-win32-x64-gnu@4.64.6': + optional: true + + '@rollup/rollup-win32-x64-msvc@4.64.6': + optional: true + + '@sindresorhus/is@4.6.0': {} + + '@szmarczak/http-timer@4.0.6': + dependencies: + defer-to-connect: 2.0.1 + + '@tootallnate/once@2.0.1': {} + + '@types/cacheable-request@6.0.3': + dependencies: + '@types/http-cache-semantics': 4.2.0 + '@types/keyv': 3.1.4 + '@types/node': 20.19.43 + '@types/responselike': 1.0.3 + + '@types/debug@4.1.13': + dependencies: + '@types/ms': 2.1.0 + + '@types/estree@1.0.9': {} + + '@types/fs-extra@9.0.13': + dependencies: + '@types/node': 26.6.5 + + '@types/http-cache-semantics@4.2.0': {} + + '@types/keyv@3.1.4': + dependencies: + '@types/node': 20.19.43 + + '@types/ms@2.1.0': {} + + '@types/node@20.19.43': + dependencies: + undici-types: 6.21.0 + + '@types/node@26.6.5': + dependencies: + undici-types: 8.9.0 + + '@types/plist@3.0.5': + dependencies: + '@types/node': 26.6.5 + xmlbuilder: 15.1.1 + optional: true + + '@types/responselike@1.0.3': + dependencies: + '@types/node': 20.19.43 + + '@types/verror@1.10.11': + optional: true + + '@types/yauzl@2.10.3': + dependencies: + '@types/node': 20.19.43 + optional: true + + '@vitejs/plugin-vue@5.2.4(vite@5.4.21(@types/node@26.6.5))(vue@3.5.44(typescript@5.6.3))': + dependencies: + vite: 5.4.21(@types/node@26.6.5) + vue: 3.5.44(typescript@5.6.3) + + '@vue/compiler-core@3.5.44': + dependencies: + '@babel/parser': 7.29.9 + '@vue/shared': 3.5.44 + entities: 7.0.1 + estree-walker: 2.0.2 + source-map-js: 1.2.2 + + '@vue/compiler-dom@3.5.44': + dependencies: + '@vue/compiler-core': 3.5.44 + '@vue/shared': 3.5.44 + + '@vue/compiler-sfc@3.5.44': + dependencies: + '@babel/parser': 7.29.9 + '@vue/compiler-core': 3.5.44 + '@vue/compiler-dom': 3.5.44 + '@vue/compiler-ssr': 3.5.44 + '@vue/shared': 3.5.44 + estree-walker: 2.0.2 + magic-string: 0.30.21 + postcss: 8.5.30 + source-map-js: 1.2.2 + + '@vue/compiler-ssr@3.5.44': + dependencies: + '@vue/compiler-dom': 3.5.44 + '@vue/shared': 3.5.44 + + '@vue/reactivity@3.5.44': + dependencies: + '@vue/shared': 3.5.44 + + '@vue/runtime-core@3.5.44': + dependencies: + '@vue/reactivity': 3.5.44 + '@vue/shared': 3.5.44 + + '@vue/runtime-dom@3.5.44': + dependencies: + '@vue/reactivity': 3.5.44 + '@vue/runtime-core': 3.5.44 + '@vue/shared': 3.5.44 + csstype: 3.2.3 + + '@vue/server-renderer@3.5.44': + dependencies: + '@vue/compiler-ssr': 3.5.44 + '@vue/runtime-dom': 3.5.44 + '@vue/shared': 3.5.44 + + '@vue/shared@3.5.44': {} + + '@xmldom/xmldom@0.9.12': {} + + abbrev@1.1.1: {} + + agent-base@6.0.2(supports-color@7.2.0): + dependencies: + debug: 4.4.3(supports-color@7.2.0) + transitivePeerDependencies: + - supports-color + + agent-base@7.1.4: {} + + agentkeepalive@4.6.0: + dependencies: + humanize-ms: 1.2.1 + + aggregate-error@3.1.0: + dependencies: + clean-stack: 2.2.0 + indent-string: 4.0.0 + + ajv-keywords@3.5.2(ajv@6.15.0): + dependencies: + ajv: 6.15.0 + + ajv@6.15.0: + dependencies: + fast-deep-equal: 3.1.3 + fast-json-stable-stringify: 2.1.0 + json-schema-traverse: 0.4.1 + uri-js: 4.4.1 + + ansi-regex@5.0.1: {} + + ansi-regex@6.4.0: {} + + ansi-styles@4.3.0: + dependencies: + color-convert: 2.0.1 + + ansi-styles@6.2.3: {} + + app-builder-bin@5.0.0-alpha.10: {} + + app-builder-lib@25.1.8(bluebird@3.7.2)(dmg-builder@25.1.8)(electron-builder-squirrel-windows@25.1.8)(supports-color@7.2.0): + dependencies: + '@develar/schema-utils': 2.6.5 + '@electron/notarize': 2.5.0(supports-color@7.2.0) + '@electron/osx-sign': 1.3.1(supports-color@7.2.0) + '@electron/rebuild': 3.6.1(bluebird@3.7.2)(supports-color@7.2.0) + '@electron/universal': 2.0.1(supports-color@7.2.0) + '@malept/flatpak-bundler': 0.4.0(supports-color@7.2.0) + '@types/fs-extra': 9.0.13 + async-exit-hook: 2.0.1 + bluebird-lst: 1.0.9 + builder-util: 25.1.7(supports-color@7.2.0) + builder-util-runtime: 9.2.10(supports-color@7.2.0) + chromium-pickle-js: 0.2.0 + config-file-ts: 0.2.8-rc1 + debug: 4.4.3(supports-color@7.2.0) + dmg-builder: 25.1.8(bluebird@3.7.2)(electron-builder-squirrel-windows@25.1.8)(supports-color@7.2.0) + dotenv: 16.6.1 + dotenv-expand: 11.0.7 + ejs: 3.1.10 + electron-builder-squirrel-windows: 25.1.8(bluebird@3.7.2)(dmg-builder@25.1.8)(supports-color@7.2.0) + electron-publish: 25.1.7(supports-color@7.2.0) + form-data: 4.0.6 + fs-extra: 10.1.0 + hosted-git-info: 4.1.0 + is-ci: 3.0.1 + isbinaryfile: 5.0.7 + js-yaml: 4.3.2 + json5: 2.2.3 + lazy-val: 1.0.5 + minimatch: 10.2.6 + resedit: 1.7.2 + sanitize-filename: 1.6.4 + semver: 7.8.5 + tar: 6.2.1 + temp-file: 3.4.0 + transitivePeerDependencies: + - bluebird + - supports-color + + aproba@2.1.0: {} + + archiver-utils@2.1.0: + dependencies: + glob: 7.2.3 + graceful-fs: 4.2.11 + lazystream: 1.0.1 + lodash.defaults: 4.2.0 + lodash.difference: 4.5.0 + lodash.flatten: 4.4.0 + lodash.isplainobject: 4.0.6 + lodash.union: 4.6.0 + normalize-path: 3.0.0 + readable-stream: 2.3.8 + + archiver-utils@3.0.4: + dependencies: + glob: 7.2.3 + graceful-fs: 4.2.11 + lazystream: 1.0.1 + lodash.defaults: 4.2.0 + lodash.difference: 4.5.0 + lodash.flatten: 4.4.0 + lodash.isplainobject: 4.0.6 + lodash.union: 4.6.0 + normalize-path: 3.0.0 + readable-stream: 3.6.2 + + archiver@5.3.2: + dependencies: + archiver-utils: 2.1.0 + async: 3.2.6 + buffer-crc32: 0.2.13 + readable-stream: 3.6.2 + readdir-glob: 1.1.3 + tar-stream: 2.2.0 + zip-stream: 4.1.1 + + are-we-there-yet@3.0.1: + dependencies: + delegates: 1.0.0 + readable-stream: 3.6.2 + + argparse@2.0.1: {} + + assert-plus@1.0.0: + optional: true + + astral-regex@2.0.0: + optional: true + + async-exit-hook@2.0.1: {} + + async@3.2.6: {} + + asynckit@0.4.0: {} + + at-least-node@1.0.0: {} + + balanced-match@1.0.2: {} + + balanced-match@4.0.4: {} + + base64-js@1.5.1: {} + + bl@4.1.0: + dependencies: + buffer: 5.7.1 + inherits: 2.0.4 + readable-stream: 3.6.2 + + bluebird-lst@1.0.9: + dependencies: + bluebird: 3.7.2 + + bluebird@3.7.2: {} + + boolean@3.2.0: + optional: true + + brace-expansion@1.1.21: + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + + brace-expansion@2.1.7: + dependencies: + balanced-match: 1.0.2 + + brace-expansion@5.0.12: + dependencies: + balanced-match: 4.0.4 + + buffer-crc32@0.2.13: {} + + buffer-from@1.1.2: {} + + buffer@5.7.1: + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + + builder-util-runtime@9.2.10(supports-color@7.2.0): + dependencies: + debug: 4.4.3(supports-color@7.2.0) + sax: 1.6.1 + transitivePeerDependencies: + - supports-color + + builder-util@25.1.7(supports-color@7.2.0): + dependencies: + 7zip-bin: 5.2.0 + '@types/debug': 4.1.13 + app-builder-bin: 5.0.0-alpha.10 + bluebird-lst: 1.0.9 + builder-util-runtime: 9.2.10(supports-color@7.2.0) + chalk: 4.1.2 + cross-spawn: 7.0.6 + debug: 4.4.3(supports-color@7.2.0) + fs-extra: 10.1.0 + http-proxy-agent: 7.0.2(supports-color@7.2.0) + https-proxy-agent: 7.0.6(supports-color@7.2.0) + is-ci: 3.0.1 + js-yaml: 4.3.2 + source-map-support: 0.5.21 + stat-mode: 1.0.0 + temp-file: 3.4.0 + transitivePeerDependencies: + - supports-color + + cacache@16.1.3(bluebird@3.7.2): + dependencies: + '@npmcli/fs': 2.1.2 + '@npmcli/move-file': 2.0.1 + chownr: 2.0.0 + fs-minipass: 2.1.0 + glob: 8.1.0 + infer-owner: 1.0.4 + lru-cache: 7.18.3 + minipass: 3.3.6 + minipass-collect: 1.0.2 + minipass-flush: 1.0.7 + minipass-pipeline: 1.2.4 + mkdirp: 1.0.4 + p-map: 4.0.0 + promise-inflight: 1.0.1(bluebird@3.7.2) + rimraf: 3.0.2 + ssri: 9.0.1 + tar: 6.2.1 + unique-filename: 2.0.1 + transitivePeerDependencies: + - bluebird + + cacheable-lookup@5.0.4: {} + + cacheable-request@7.0.4: + dependencies: + clone-response: 1.0.3 + get-stream: 5.2.0 + http-cache-semantics: 4.3.0 + keyv: 4.5.4 + lowercase-keys: 2.0.0 + normalize-url: 6.1.0 + responselike: 2.0.1 + + call-bind-apply-helpers@1.0.2: + dependencies: + es-errors: 1.3.0 + function-bind: 1.1.2 + + chalk@4.1.2: + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + + chownr@2.0.0: {} + + chromium-pickle-js@0.2.0: {} + + ci-info@3.9.0: {} + + clean-stack@2.2.0: {} + + cli-cursor@3.1.0: + dependencies: + restore-cursor: 3.1.0 + + cli-spinners@2.9.2: {} + + cli-truncate@2.1.0: + dependencies: + slice-ansi: 3.0.0 + string-width: 4.2.3 + optional: true + + cliui@8.0.1: + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + + clone-response@1.0.3: + dependencies: + mimic-response: 1.0.1 + + clone@1.0.4: {} + + color-convert@2.0.1: + dependencies: + color-name: 1.1.4 + + color-name@1.1.4: {} + + color-support@1.1.3: {} + + combined-stream@1.0.8: + dependencies: + delayed-stream: 1.0.0 + + commander@5.1.0: {} + + compare-version@0.1.2: {} + + compress-commons@4.1.2: + dependencies: + buffer-crc32: 0.2.13 + crc32-stream: 4.0.3 + normalize-path: 3.0.0 + readable-stream: 3.6.2 + + concat-map@0.0.1: {} + + config-file-ts@0.2.8-rc1: + dependencies: + glob: 10.5.0 + typescript: 5.6.3 + + console-control-strings@1.1.0: {} + + core-util-is@1.0.2: + optional: true + + core-util-is@1.0.3: {} + + crc-32@1.2.2: {} + + crc32-stream@4.0.3: + dependencies: + crc-32: 1.2.2 + readable-stream: 3.6.2 + + crc@3.8.0: + dependencies: + buffer: 5.7.1 + optional: true + + cross-spawn@7.0.6: + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + + csstype@3.2.3: {} + + debug@4.4.3(supports-color@7.2.0): + dependencies: + ms: 2.1.3 + optionalDependencies: + supports-color: 7.2.0 + + decompress-response@6.0.0: + dependencies: + mimic-response: 3.1.0 + + defaults@1.0.4: + dependencies: + clone: 1.0.4 + + defer-to-connect@2.0.1: {} + + define-data-property@1.1.4: + dependencies: + es-define-property: 1.0.1 + es-errors: 1.3.0 + gopd: 1.2.0 + optional: true + + define-properties@1.2.1: + dependencies: + define-data-property: 1.1.4 + has-property-descriptors: 1.0.2 + object-keys: 1.1.1 + optional: true + + delayed-stream@1.0.0: {} + + delegates@1.0.0: {} + + detect-libc@2.1.2: {} + + detect-node@2.1.0: + optional: true + + dexie@4.4.6: {} + + dir-compare@4.2.0: + dependencies: + minimatch: 3.1.5 + p-limit: 3.1.0 + + dmg-builder@25.1.8(bluebird@3.7.2)(electron-builder-squirrel-windows@25.1.8)(supports-color@7.2.0): + dependencies: + app-builder-lib: 25.1.8(bluebird@3.7.2)(dmg-builder@25.1.8)(electron-builder-squirrel-windows@25.1.8)(supports-color@7.2.0) + builder-util: 25.1.7(supports-color@7.2.0) + builder-util-runtime: 9.2.10(supports-color@7.2.0) + fs-extra: 10.1.0 + iconv-lite: 0.6.3 + js-yaml: 4.3.2 + optionalDependencies: + dmg-license: 1.0.11 + transitivePeerDependencies: + - bluebird + - electron-builder-squirrel-windows + - supports-color + + dmg-license@1.0.11: + dependencies: + '@types/plist': 3.0.5 + '@types/verror': 1.10.11 + ajv: 6.15.0 + crc: 3.8.0 + iconv-corefoundation: 1.1.7 + plist: 3.1.1 + smart-buffer: 4.2.0 + verror: 1.10.1 + optional: true + + dotenv-expand@11.0.7: + dependencies: + dotenv: 16.6.1 + + dotenv@16.6.1: {} + + dunder-proto@1.0.1: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-errors: 1.3.0 + gopd: 1.2.0 + + eastasianwidth@0.2.0: {} + + ejs@3.1.10: + dependencies: + jake: 10.9.4 + + electron-builder-squirrel-windows@25.1.8(bluebird@3.7.2)(dmg-builder@25.1.8)(supports-color@7.2.0): + dependencies: + app-builder-lib: 25.1.8(bluebird@3.7.2)(dmg-builder@25.1.8)(electron-builder-squirrel-windows@25.1.8)(supports-color@7.2.0) + archiver: 5.3.2 + builder-util: 25.1.7(supports-color@7.2.0) + fs-extra: 10.1.0 + transitivePeerDependencies: + - bluebird + - dmg-builder + - supports-color + + electron-builder@25.1.8(bluebird@3.7.2)(electron-builder-squirrel-windows@25.1.8)(supports-color@7.2.0): + dependencies: + app-builder-lib: 25.1.8(bluebird@3.7.2)(dmg-builder@25.1.8)(electron-builder-squirrel-windows@25.1.8)(supports-color@7.2.0) + builder-util: 25.1.7(supports-color@7.2.0) + builder-util-runtime: 9.2.10(supports-color@7.2.0) + chalk: 4.1.2 + dmg-builder: 25.1.8(bluebird@3.7.2)(electron-builder-squirrel-windows@25.1.8)(supports-color@7.2.0) + fs-extra: 10.1.0 + is-ci: 3.0.1 + lazy-val: 1.0.5 + simple-update-notifier: 2.0.0 + yargs: 17.7.3 + transitivePeerDependencies: + - bluebird + - electron-builder-squirrel-windows + - supports-color + + electron-publish@25.1.7(supports-color@7.2.0): + dependencies: + '@types/fs-extra': 9.0.13 + builder-util: 25.1.7(supports-color@7.2.0) + builder-util-runtime: 9.2.10(supports-color@7.2.0) + chalk: 4.1.2 + fs-extra: 10.1.0 + lazy-val: 1.0.5 + mime: 2.6.0 + transitivePeerDependencies: + - supports-color + + electron@33.4.11(supports-color@7.2.0): + dependencies: + '@electron/get': 2.0.3(supports-color@7.2.0) + '@types/node': 20.19.43 + extract-zip: 2.0.1(supports-color@7.2.0) + transitivePeerDependencies: + - supports-color + + emoji-regex@8.0.0: {} + + emoji-regex@9.2.2: {} + + encoding@0.1.13: + dependencies: + iconv-lite: 0.6.3 + optional: true + + end-of-stream@1.4.5: + dependencies: + once: 1.4.0 + + entities@7.0.1: {} + + env-paths@2.2.1: {} + + err-code@2.0.3: {} + + es-define-property@1.0.1: {} + + es-errors@1.3.0: {} + + es-object-atoms@1.1.2: + dependencies: + es-errors: 1.3.0 + + es-set-tostringtag@2.1.0: + dependencies: + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + has-tostringtag: 1.0.2 + hasown: 2.0.4 + + es6-error@4.1.1: + optional: true + + esbuild@0.21.5: + optionalDependencies: + '@esbuild/aix-ppc64': 0.21.5 + '@esbuild/android-arm': 0.21.5 + '@esbuild/android-arm64': 0.21.5 + '@esbuild/android-x64': 0.21.5 + '@esbuild/darwin-arm64': 0.21.5 + '@esbuild/darwin-x64': 0.21.5 + '@esbuild/freebsd-arm64': 0.21.5 + '@esbuild/freebsd-x64': 0.21.5 + '@esbuild/linux-arm': 0.21.5 + '@esbuild/linux-arm64': 0.21.5 + '@esbuild/linux-ia32': 0.21.5 + '@esbuild/linux-loong64': 0.21.5 + '@esbuild/linux-mips64el': 0.21.5 + '@esbuild/linux-ppc64': 0.21.5 + '@esbuild/linux-riscv64': 0.21.5 + '@esbuild/linux-s390x': 0.21.5 + '@esbuild/linux-x64': 0.21.5 + '@esbuild/netbsd-x64': 0.21.5 + '@esbuild/openbsd-x64': 0.21.5 + '@esbuild/sunos-x64': 0.21.5 + '@esbuild/win32-arm64': 0.21.5 + '@esbuild/win32-ia32': 0.21.5 + '@esbuild/win32-x64': 0.21.5 + + escalade@3.2.0: {} + + escape-string-regexp@4.0.0: + optional: true + + estree-walker@2.0.2: {} + + exponential-backoff@3.1.3: {} + + extract-zip@2.0.1(supports-color@7.2.0): + dependencies: + debug: 4.4.3(supports-color@7.2.0) + get-stream: 5.2.0 + yauzl: 2.10.0 + optionalDependencies: + '@types/yauzl': 2.10.3 + transitivePeerDependencies: + - supports-color + + extsprintf@1.4.1: + optional: true + + fast-deep-equal@3.1.3: {} + + fast-json-stable-stringify@2.1.0: {} + + fd-slicer@1.1.0: + dependencies: + pend: 1.2.0 + + filelist@1.0.6: + dependencies: + minimatch: 5.1.9 + + foreground-child@3.3.1: + dependencies: + cross-spawn: 7.0.6 + signal-exit: 4.1.0 + + form-data@4.0.6: + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + es-set-tostringtag: 2.1.0 + hasown: 2.0.4 + mime-types: 2.1.35 + + fs-constants@1.0.0: {} + + fs-extra@10.1.0: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 6.2.1 + universalify: 2.0.1 + + fs-extra@11.4.1: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 6.2.1 + universalify: 2.0.1 + + fs-extra@8.1.0: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 4.0.0 + universalify: 0.1.2 + + fs-extra@9.1.0: + dependencies: + at-least-node: 1.0.0 + graceful-fs: 4.2.11 + jsonfile: 6.2.1 + universalify: 2.0.1 + + fs-minipass@2.1.0: + dependencies: + minipass: 3.3.6 + + fs.realpath@1.0.0: {} + + fsevents@2.3.3: + optional: true + + function-bind@1.1.2: {} + + gauge@4.0.4: + dependencies: + aproba: 2.1.0 + color-support: 1.1.3 + console-control-strings: 1.1.0 + has-unicode: 2.0.1 + signal-exit: 3.0.7 + string-width: 4.2.3 + strip-ansi: 6.0.1 + wide-align: 1.1.5 + + get-caller-file@2.0.5: {} + + get-intrinsic@1.3.0: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-define-property: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.2 + function-bind: 1.1.2 + get-proto: 1.0.1 + gopd: 1.2.0 + has-symbols: 1.1.0 + hasown: 2.0.4 + math-intrinsics: 1.1.0 + + get-proto@1.0.1: + dependencies: + dunder-proto: 1.0.1 + es-object-atoms: 1.1.2 + + get-stream@5.2.0: + dependencies: + pump: 3.0.4 + + glob@10.5.0: + dependencies: + foreground-child: 3.3.1 + jackspeak: 3.4.3 + minimatch: 9.0.9 + minipass: 7.1.3 + package-json-from-dist: 1.0.1 + path-scurry: 1.11.1 + + glob@7.2.3: + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.1.5 + once: 1.4.0 + path-is-absolute: 1.0.1 + + glob@8.1.0: + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 5.1.9 + once: 1.4.0 + + global-agent@3.0.0: + dependencies: + boolean: 3.2.0 + es6-error: 4.1.1 + matcher: 3.0.0 + roarr: 2.15.4 + semver: 7.8.5 + serialize-error: 7.0.1 + optional: true + + globalthis@1.0.4: + dependencies: + define-properties: 1.2.1 + gopd: 1.2.0 + optional: true + + gopd@1.2.0: {} + + got@11.8.6: + dependencies: + '@sindresorhus/is': 4.6.0 + '@szmarczak/http-timer': 4.0.6 + '@types/cacheable-request': 6.0.3 + '@types/responselike': 1.0.3 + cacheable-lookup: 5.0.4 + cacheable-request: 7.0.4 + decompress-response: 6.0.0 + http2-wrapper: 1.0.3 + lowercase-keys: 2.0.0 + p-cancelable: 2.1.1 + responselike: 2.0.1 + + graceful-fs@4.2.11: {} + + has-flag@4.0.0: {} + + has-property-descriptors@1.0.2: + dependencies: + es-define-property: 1.0.1 + optional: true + + has-symbols@1.1.0: {} + + has-tostringtag@1.0.2: + dependencies: + has-symbols: 1.1.0 + + has-unicode@2.0.1: {} + + hasown@2.0.4: + dependencies: + function-bind: 1.1.2 + + hosted-git-info@4.1.0: + dependencies: + lru-cache: 6.0.0 + + http-cache-semantics@4.3.0: {} + + http-proxy-agent@5.0.0(supports-color@7.2.0): + dependencies: + '@tootallnate/once': 2.0.1 + agent-base: 6.0.2(supports-color@7.2.0) + debug: 4.4.3(supports-color@7.2.0) + transitivePeerDependencies: + - supports-color + + http-proxy-agent@7.0.2(supports-color@7.2.0): + dependencies: + agent-base: 7.1.4 + debug: 4.4.3(supports-color@7.2.0) + transitivePeerDependencies: + - supports-color + + http2-wrapper@1.0.3: + dependencies: + quick-lru: 5.1.1 + resolve-alpn: 1.2.1 + + https-proxy-agent@5.0.1(supports-color@7.2.0): + dependencies: + agent-base: 6.0.2(supports-color@7.2.0) + debug: 4.4.3(supports-color@7.2.0) + transitivePeerDependencies: + - supports-color + + https-proxy-agent@7.0.6(supports-color@7.2.0): + dependencies: + agent-base: 7.1.4 + debug: 4.4.3(supports-color@7.2.0) + transitivePeerDependencies: + - supports-color + + humanize-ms@1.2.1: + dependencies: + ms: 2.1.3 + + iconv-corefoundation@1.1.7: + dependencies: + cli-truncate: 2.1.0 + node-addon-api: 1.7.2 + optional: true + + iconv-lite@0.6.3: + dependencies: + safer-buffer: 2.1.2 + + ieee754@1.2.1: {} + + imurmurhash@0.1.4: {} + + indent-string@4.0.0: {} + + infer-owner@1.0.4: {} + + inflight@1.0.6: + dependencies: + once: 1.4.0 + wrappy: 1.0.2 + + inherits@2.0.4: {} + + ip-address@10.7.4: {} + + is-ci@3.0.1: + dependencies: + ci-info: 3.9.0 + + is-fullwidth-code-point@3.0.0: {} + + is-interactive@1.0.0: {} + + is-lambda@1.0.1: {} + + is-unicode-supported@0.1.0: {} + + isarray@1.0.0: {} + + isbinaryfile@4.0.10: {} + + isbinaryfile@5.0.7: {} + + isexe@2.0.0: {} + + jackspeak@3.4.3: + dependencies: + '@isaacs/cliui': 8.0.2 + optionalDependencies: + '@pkgjs/parseargs': 0.11.0 + + jake@10.9.4: + dependencies: + async: 3.2.6 + filelist: 1.0.6 + picocolors: 1.1.1 + + js-yaml@4.3.2: + dependencies: + argparse: 2.0.1 + + json-buffer@3.0.1: {} + + json-schema-traverse@0.4.1: {} + + json-stringify-safe@5.0.1: + optional: true + + json5@2.2.3: {} + + jsonfile@4.0.0: + optionalDependencies: + graceful-fs: 4.2.11 + + jsonfile@6.2.1: + dependencies: + universalify: 2.0.1 + optionalDependencies: + graceful-fs: 4.2.11 + + keyv@4.5.4: + dependencies: + json-buffer: 3.0.1 + + lazy-val@1.0.5: {} + + lazystream@1.0.1: + dependencies: + readable-stream: 2.3.8 + + lodash.defaults@4.2.0: {} + + lodash.difference@4.5.0: {} + + lodash.flatten@4.4.0: {} + + lodash.isplainobject@4.0.6: {} + + lodash.union@4.6.0: {} + + lodash@4.18.1: {} + + log-symbols@4.1.0: + dependencies: + chalk: 4.1.2 + is-unicode-supported: 0.1.0 + + lowercase-keys@2.0.0: {} + + lru-cache@10.4.3: {} + + lru-cache@6.0.0: + dependencies: + yallist: 4.0.0 + + lru-cache@7.18.3: {} + + magic-string@0.30.21: + dependencies: + '@jridgewell/sourcemap-codec': 1.6.0 + + make-fetch-happen@10.2.1(bluebird@3.7.2)(supports-color@7.2.0): + dependencies: + agentkeepalive: 4.6.0 + cacache: 16.1.3(bluebird@3.7.2) + http-cache-semantics: 4.3.0 + http-proxy-agent: 5.0.0(supports-color@7.2.0) + https-proxy-agent: 5.0.1(supports-color@7.2.0) + is-lambda: 1.0.1 + lru-cache: 7.18.3 + minipass: 3.3.6 + minipass-collect: 1.0.2 + minipass-fetch: 2.1.2 + minipass-flush: 1.0.7 + minipass-pipeline: 1.2.4 + negotiator: 0.6.4 + promise-retry: 2.0.1 + socks-proxy-agent: 7.0.0(supports-color@7.2.0) + ssri: 9.0.1 + transitivePeerDependencies: + - bluebird + - supports-color + + matcher@3.0.0: + dependencies: + escape-string-regexp: 4.0.0 + optional: true + + math-intrinsics@1.1.0: {} + + mime-db@1.52.0: {} + + mime-types@2.1.35: + dependencies: + mime-db: 1.52.0 + + mime@2.6.0: {} + + mimic-fn@2.1.0: {} + + mimic-response@1.0.1: {} + + mimic-response@3.1.0: {} + + minimatch@10.2.6: + dependencies: + brace-expansion: 5.0.12 + + minimatch@3.1.5: + dependencies: + brace-expansion: 1.1.21 + + minimatch@5.1.9: + dependencies: + brace-expansion: 2.1.7 + + minimatch@9.0.9: + dependencies: + brace-expansion: 2.1.7 + + minimist@1.2.8: {} + + minipass-collect@1.0.2: + dependencies: + minipass: 3.3.6 + + minipass-fetch@2.1.2: + dependencies: + minipass: 3.3.6 + minipass-sized: 1.0.3 + minizlib: 2.1.2 + optionalDependencies: + encoding: 0.1.13 + + minipass-flush@1.0.7: + dependencies: + minipass: 3.3.6 + + minipass-pipeline@1.2.4: + dependencies: + minipass: 3.3.6 + + minipass-sized@1.0.3: + dependencies: + minipass: 3.3.6 + + minipass@3.3.6: + dependencies: + yallist: 4.0.0 + + minipass@5.0.0: {} + + minipass@7.1.3: {} + + minizlib@2.1.2: + dependencies: + minipass: 3.3.6 + yallist: 4.0.0 + + mkdirp@1.0.4: {} + + ms@2.1.3: {} + + nanoid@3.3.20: {} + + negotiator@0.6.4: {} + + node-abi@3.98.0: + dependencies: + semver: 7.8.5 + + node-addon-api@1.7.2: + optional: true + + node-api-version@0.2.1: + dependencies: + semver: 7.8.5 + + node-gyp@9.4.1(bluebird@3.7.2)(supports-color@7.2.0): + dependencies: + env-paths: 2.2.1 + exponential-backoff: 3.1.3 + glob: 7.2.3 + graceful-fs: 4.2.11 + make-fetch-happen: 10.2.1(bluebird@3.7.2)(supports-color@7.2.0) + nopt: 6.0.0 + npmlog: 6.0.2 + rimraf: 3.0.2 + semver: 7.8.5 + tar: 6.2.1 + which: 2.0.2 + transitivePeerDependencies: + - bluebird + - supports-color + + nopt@6.0.0: + dependencies: + abbrev: 1.1.1 + + normalize-path@3.0.0: {} + + normalize-url@6.1.0: {} + + npmlog@6.0.2: + dependencies: + are-we-there-yet: 3.0.1 + console-control-strings: 1.1.0 + gauge: 4.0.4 + set-blocking: 2.0.0 + + object-keys@1.1.1: + optional: true + + once@1.4.0: + dependencies: + wrappy: 1.0.2 + + onetime@5.1.2: + dependencies: + mimic-fn: 2.1.0 + + ora@5.4.1: + dependencies: + bl: 4.1.0 + chalk: 4.1.2 + cli-cursor: 3.1.0 + cli-spinners: 2.9.2 + is-interactive: 1.0.0 + is-unicode-supported: 0.1.0 + log-symbols: 4.1.0 + strip-ansi: 6.0.1 + wcwidth: 1.0.1 + + p-cancelable@2.1.1: {} + + p-limit@3.1.0: + dependencies: + yocto-queue: 0.1.0 + + p-map@4.0.0: + dependencies: + aggregate-error: 3.1.0 + + package-json-from-dist@1.0.1: {} + + path-is-absolute@1.0.1: {} + + path-key@3.1.1: {} + + path-scurry@1.11.1: + dependencies: + lru-cache: 10.4.3 + minipass: 7.1.3 + + pe-library@0.4.1: {} + + pend@1.2.0: {} + + picocolors@1.1.1: {} + + plist@3.1.1: + dependencies: + '@xmldom/xmldom': 0.9.12 + base64-js: 1.5.1 + xmlbuilder: 15.1.1 + + postcss@8.5.30: + dependencies: + nanoid: 3.3.20 + picocolors: 1.1.1 + source-map-js: 1.2.2 + + process-nextick-args@2.0.1: {} + + progress@2.0.3: {} + + promise-inflight@1.0.1(bluebird@3.7.2): + optionalDependencies: + bluebird: 3.7.2 + + promise-retry@2.0.1: + dependencies: + err-code: 2.0.3 + retry: 0.12.0 + + pump@3.0.4: + dependencies: + end-of-stream: 1.4.5 + once: 1.4.0 + + punycode@2.3.1: {} + + quick-lru@5.1.1: {} + + read-binary-file-arch@1.0.6(supports-color@7.2.0): + dependencies: + debug: 4.4.3(supports-color@7.2.0) + transitivePeerDependencies: + - supports-color + + readable-stream@2.3.8: + dependencies: + core-util-is: 1.0.3 + inherits: 2.0.4 + isarray: 1.0.0 + process-nextick-args: 2.0.1 + safe-buffer: 5.1.2 + string_decoder: 1.1.1 + util-deprecate: 1.0.2 + + readable-stream@3.6.2: + dependencies: + inherits: 2.0.4 + string_decoder: 1.3.0 + util-deprecate: 1.0.2 + + readdir-glob@1.1.3: + dependencies: + minimatch: 5.1.9 + + require-directory@2.1.1: {} + + resedit@1.7.2: + dependencies: + pe-library: 0.4.1 + + resolve-alpn@1.2.1: {} + + responselike@2.0.1: + dependencies: + lowercase-keys: 2.0.0 + + restore-cursor@3.1.0: + dependencies: + onetime: 5.1.2 + signal-exit: 3.0.7 + + retry@0.12.0: {} + + rimraf@3.0.2: + dependencies: + glob: 7.2.3 + + roarr@2.15.4: + dependencies: + boolean: 3.2.0 + detect-node: 2.1.0 + globalthis: 1.0.4 + json-stringify-safe: 5.0.1 + semver-compare: 1.0.0 + sprintf-js: 1.1.3 + optional: true + + rollup@4.64.6: + dependencies: + '@types/estree': 1.0.9 + optionalDependencies: + '@napi-rs/lzma-linux-x64-gnu': 1.5.1 + '@rollup/rollup-android-arm-eabi': 4.64.6 + '@rollup/rollup-android-arm64': 4.64.6 + '@rollup/rollup-darwin-arm64': 4.64.6 + '@rollup/rollup-darwin-x64': 4.64.6 + '@rollup/rollup-freebsd-arm64': 4.64.6 + '@rollup/rollup-freebsd-x64': 4.64.6 + '@rollup/rollup-linux-arm-gnueabihf': 4.64.6 + '@rollup/rollup-linux-arm-musleabihf': 4.64.6 + '@rollup/rollup-linux-arm64-gnu': 4.64.6 + '@rollup/rollup-linux-arm64-musl': 4.64.6 + '@rollup/rollup-linux-loong64-gnu': 4.64.6 + '@rollup/rollup-linux-loong64-musl': 4.64.6 + '@rollup/rollup-linux-ppc64-gnu': 4.64.6 + '@rollup/rollup-linux-ppc64-musl': 4.64.6 + '@rollup/rollup-linux-riscv64-gnu': 4.64.6 + '@rollup/rollup-linux-riscv64-musl': 4.64.6 + '@rollup/rollup-linux-s390x-gnu': 4.64.6 + '@rollup/rollup-linux-x64-gnu': 4.64.6 + '@rollup/rollup-linux-x64-musl': 4.64.6 + '@rollup/rollup-openbsd-x64': 4.64.6 + '@rollup/rollup-openharmony-arm64': 4.64.6 + '@rollup/rollup-win32-arm64-msvc': 4.64.6 + '@rollup/rollup-win32-ia32-msvc': 4.64.6 + '@rollup/rollup-win32-x64-gnu': 4.64.6 + '@rollup/rollup-win32-x64-msvc': 4.64.6 + fsevents: 2.3.3 + + safe-buffer@5.1.2: {} + + safe-buffer@5.2.1: {} + + safer-buffer@2.1.2: {} + + sanitize-filename@1.6.4: + dependencies: + truncate-utf8-bytes: 1.0.2 + + sax@1.6.1: {} + + semver-compare@1.0.0: + optional: true + + semver@6.3.1: {} + + semver@7.8.5: {} + + serialize-error@7.0.1: + dependencies: + type-fest: 0.13.1 + optional: true + + set-blocking@2.0.0: {} + + shebang-command@2.0.0: + dependencies: + shebang-regex: 3.0.0 + + shebang-regex@3.0.0: {} + + signal-exit@3.0.7: {} + + signal-exit@4.1.0: {} + + simple-update-notifier@2.0.0: + dependencies: + semver: 7.8.5 + + slice-ansi@3.0.0: + dependencies: + ansi-styles: 4.3.0 + astral-regex: 2.0.0 + is-fullwidth-code-point: 3.0.0 + optional: true + + smart-buffer@4.2.0: {} + + socks-proxy-agent@7.0.0(supports-color@7.2.0): + dependencies: + agent-base: 6.0.2(supports-color@7.2.0) + debug: 4.4.3(supports-color@7.2.0) + socks: 2.8.10 + transitivePeerDependencies: + - supports-color + + socks@2.8.10: + dependencies: + ip-address: 10.7.4 + smart-buffer: 4.2.0 + + source-map-js@1.2.2: {} + + source-map-support@0.5.21: + dependencies: + buffer-from: 1.1.2 + source-map: 0.6.1 + + source-map@0.6.1: {} + + sprintf-js@1.1.3: + optional: true + + ssri@9.0.1: + dependencies: + minipass: 3.3.6 + + stat-mode@1.0.0: {} + + string-width@4.2.3: + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + + string-width@5.1.2: + dependencies: + eastasianwidth: 0.2.0 + emoji-regex: 9.2.2 + strip-ansi: 7.2.0 + + string_decoder@1.1.1: + dependencies: + safe-buffer: 5.1.2 + + string_decoder@1.3.0: + dependencies: + safe-buffer: 5.2.1 + + strip-ansi@6.0.1: + dependencies: + ansi-regex: 5.0.1 + + strip-ansi@7.2.0: + dependencies: + ansi-regex: 6.4.0 + + sumchecker@3.0.1(supports-color@7.2.0): + dependencies: + debug: 4.4.3(supports-color@7.2.0) + transitivePeerDependencies: + - supports-color + + supports-color@7.2.0: + dependencies: + has-flag: 4.0.0 + + tar-stream@2.2.0: + dependencies: + bl: 4.1.0 + end-of-stream: 1.4.5 + fs-constants: 1.0.0 + inherits: 2.0.4 + readable-stream: 3.6.2 + + tar@6.2.1: + dependencies: + chownr: 2.0.0 + fs-minipass: 2.1.0 + minipass: 5.0.0 + minizlib: 2.1.2 + mkdirp: 1.0.4 + yallist: 4.0.0 + + temp-file@3.4.0: + dependencies: + async-exit-hook: 2.0.1 + fs-extra: 10.1.0 + + tmp-promise@3.0.3: + dependencies: + tmp: 0.2.7 + + tmp@0.2.7: {} + + truncate-utf8-bytes@1.0.2: + dependencies: + utf8-byte-length: 1.0.5 + + type-fest@0.13.1: + optional: true + + typescript@5.6.3: {} + + undici-types@6.21.0: {} + + undici-types@8.9.0: {} + + unique-filename@2.0.1: + dependencies: + unique-slug: 3.0.0 + + unique-slug@3.0.0: + dependencies: + imurmurhash: 0.1.4 + + universalify@0.1.2: {} + + universalify@2.0.1: {} + + uri-js@4.4.1: + dependencies: + punycode: 2.3.1 + + utf8-byte-length@1.0.5: {} + + util-deprecate@1.0.2: {} + + verror@1.10.1: + dependencies: + assert-plus: 1.0.0 + core-util-is: 1.0.2 + extsprintf: 1.4.1 + optional: true + + vite@5.4.21(@types/node@26.6.5): + dependencies: + esbuild: 0.21.5 + postcss: 8.5.30 + rollup: 4.64.6 + optionalDependencies: + '@types/node': 26.6.5 + fsevents: 2.3.3 + + vue@3.5.44(typescript@5.6.3): + dependencies: + '@vue/compiler-dom': 3.5.44 + '@vue/compiler-sfc': 3.5.44 + '@vue/runtime-dom': 3.5.44 + '@vue/server-renderer': 3.5.44 + '@vue/shared': 3.5.44 + optionalDependencies: + typescript: 5.6.3 + + wcwidth@1.0.1: + dependencies: + defaults: 1.0.4 + + which@2.0.2: + dependencies: + isexe: 2.0.0 + + wide-align@1.1.5: + dependencies: + string-width: 4.2.3 + + wrap-ansi@7.0.0: + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + + wrap-ansi@8.1.0: + dependencies: + ansi-styles: 6.2.3 + string-width: 5.1.2 + strip-ansi: 7.2.0 + + wrappy@1.0.2: {} + + xmlbuilder@15.1.1: {} + + y18n@5.0.8: {} + + yallist@4.0.0: {} + + yargs-parser@21.1.1: {} + + yargs@17.7.3: + dependencies: + cliui: 8.0.1 + escalade: 3.2.0 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 21.1.1 + + yauzl@2.10.0: + dependencies: + buffer-crc32: 0.2.13 + fd-slicer: 1.1.0 + + yocto-queue@0.1.0: {} + + zip-stream@4.1.1: + dependencies: + archiver-utils: 3.0.4 + compress-commons: 4.1.2 + readable-stream: 3.6.2 diff --git a/intern-log/pnpm-workspace.yaml b/intern-log/pnpm-workspace.yaml new file mode 100644 index 0000000..757aaf2 --- /dev/null +++ b/intern-log/pnpm-workspace.yaml @@ -0,0 +1,3 @@ +allowBuilds: + esbuild: true + electron: true diff --git a/intern-log/public/icons/icon-192.png b/intern-log/public/icons/icon-192.png new file mode 100644 index 0000000000000000000000000000000000000000..840d85b4fe4925cae8082b22254a5e11c57ae974 GIT binary patch literal 1163 zcmeAS@N?(olHy`uVBq!ia0vp^2SAvE4M+yv$zf+;Uu% zn!IW|f8+3_@hcMJ4~JQF6zQM2us&B?%z37G@`ukktVt68n0V}N9}sBEz40Jeu}M+d z^iK%q!`m+t+U9$GE{w=!o8PtiprUre!{x8;l<*(;5L{Wei!I^DN;~(vOa_0>82HD6 zD5LQ9dLFK+Cj19(&Yu@`KKwERkG*?_W%^l=-$Ch1+%8d|Nr;k_8J;~B>cFtk?5%j>=DLqgxa{7jK&_Q65(*y z|CU?WlmAZqqkd_lb_08I?OuH$7q$lnBmVFA4-*v!ioCsVuHDJakOvNfs2B#ho~`xw z*Qn?Y4!VWHFn4C z#9zE;6g*`3yHfNt%Z68si`Kuq&wOA4gWS%0O>uH_-L)AmvN&vsW!%BD2$DR3scf4y z!*s`Eb71_v-0Ymoh(XGml@VD$t-+2$26YN#le5=^V6yV zmtPbXy#=X_EQw}xIl%Mz%2y!|mXP_2-@ON_dHU1x&AN42{u38$TkJQd{r)u#7OhxQ znSX{Wyp^=h9={-cdo5d!ogv>}r88LvURY{;&JbShIB)HN#iecg8@9J>*tYh-h5K4x ylkN!}mfDu&T)+Aa_wNpkSGT$NZD0jLLDZ%E0zdO5`3>D4L1Lb+elF{r5}E+{q3_ZF literal 0 HcmV?d00001 diff --git a/intern-log/public/icons/icon-512.png b/intern-log/public/icons/icon-512.png new file mode 100644 index 0000000000000000000000000000000000000000..407b66d79cbaa95609b114c0ead98c5b4545f1fb GIT binary patch literal 3525 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 + + + + + + + + + + + + diff --git a/intern-log/public/icons/make_icons.py b/intern-log/public/icons/make_icons.py new file mode 100644 index 0000000..f45922a --- /dev/null +++ b/intern-log/public/icons/make_icons.py @@ -0,0 +1,23 @@ +from PIL import Image, ImageDraw + +ACCENT = (51, 112, 255, 255) +WHITE = (255, 255, 255, 255) + +def make(size, path): + img = Image.new('RGBA', (size, size), (0, 0, 0, 0)) + d = ImageDraw.Draw(img) + m = size * 0.07 + d.rounded_rectangle([m, m, size - m, size - m], radius=size * 0.19, fill=ACCENT) + x0, y0, x1, y1 = size * 0.24, size * 0.30, size * 0.76, size * 0.78 + d.rounded_rectangle([x0, y0, x1, y1], radius=size * 0.045, fill=WHITE) + d.rectangle([x0, y0 + size * 0.045, x1, y0 + size * 0.09], fill=ACCENT) + for cx in (0.36, 0.64): + d.rounded_rectangle([size * cx - size * 0.02, size * 0.20, size * cx + size * 0.02, size * 0.33], radius=size * 0.02, fill=WHITE) + for dx in (0.34, 0.5, 0.66): + for dy in (0.5, 0.63): + d.ellipse([size * dx - size * 0.025, size * dy - size * 0.025, size * dx + size * 0.025, size * dy + size * 0.025], fill=ACCENT) + img.save(path) + +make(192, 'icon-192.png') +make(512, 'icon-512.png') +print('icons generated') diff --git a/intern-log/public/manifest.webmanifest b/intern-log/public/manifest.webmanifest new file mode 100644 index 0000000..a26b376 --- /dev/null +++ b/intern-log/public/manifest.webmanifest @@ -0,0 +1,15 @@ +{ + "name": "实习工作日志", + "short_name": "工作日志", + "description": "实习打卡、工作记录、备忘录与加密密码库", + "start_url": "./", + "scope": "./", + "display": "standalone", + "background_color": "#FFFFFF", + "theme_color": "#FFFFFF", + "icons": [ + { "src": "./icons/icon-192.png", "sizes": "192x192", "type": "image/png" }, + { "src": "./icons/icon-512.png", "sizes": "512x512", "type": "image/png" }, + { "src": "./icons/icon.svg", "sizes": "any", "type": "image/svg+xml" } + ] +} diff --git a/intern-log/public/sw.js b/intern-log/public/sw.js new file mode 100644 index 0000000..bb2a0a3 --- /dev/null +++ b/intern-log/public/sw.js @@ -0,0 +1,46 @@ +const CACHE = 'intern-log-v1' +const CORE = ['./', './index.html'] + +self.addEventListener('install', event => { + event.waitUntil(caches.open(CACHE).then(c => c.addAll(CORE)).then(() => self.skipWaiting())) +}) + +self.addEventListener('activate', event => { + event.waitUntil( + caches.keys() + .then(keys => Promise.all(keys.filter(k => k !== CACHE).map(k => caches.delete(k)))) + .then(() => self.clients.claim()) + ) +}) + +self.addEventListener('fetch', event => { + const req = event.request + if (req.method !== 'GET') return + const url = new URL(req.url) + if (url.origin !== location.origin) return + + // 页面导航:网络优先,离线回退缓存的应用壳 + if (req.mode === 'navigate') { + event.respondWith( + fetch(req) + .then(resp => { + const clone = resp.clone() + caches.open(CACHE).then(c => c.put('./index.html', clone)) + return resp + }) + .catch(() => caches.match('./index.html')) + ) + return + } + + // 静态资源:缓存优先,未命中时拉取并写入缓存 + event.respondWith( + caches.match(req).then(hit => hit || fetch(req).then(resp => { + if (resp.ok) { + const clone = resp.clone() + caches.open(CACHE).then(c => c.put(req, clone)) + } + return resp + })) + ) +}) diff --git a/intern-log/src/App.vue b/intern-log/src/App.vue new file mode 100644 index 0000000..9d354c3 --- /dev/null +++ b/intern-log/src/App.vue @@ -0,0 +1,425 @@ + + + + + diff --git a/intern-log/src/components/ConfirmDialog.vue b/intern-log/src/components/ConfirmDialog.vue new file mode 100644 index 0000000..987d68a --- /dev/null +++ b/intern-log/src/components/ConfirmDialog.vue @@ -0,0 +1,69 @@ + + + + + diff --git a/intern-log/src/components/CredentialDialog.vue b/intern-log/src/components/CredentialDialog.vue new file mode 100644 index 0000000..e4944d2 --- /dev/null +++ b/intern-log/src/components/CredentialDialog.vue @@ -0,0 +1,155 @@ + + + + + diff --git a/intern-log/src/components/Icon.vue b/intern-log/src/components/Icon.vue new file mode 100644 index 0000000..7a5f012 --- /dev/null +++ b/intern-log/src/components/Icon.vue @@ -0,0 +1,11 @@ + + + diff --git a/intern-log/src/components/icons.ts b/intern-log/src/components/icons.ts new file mode 100644 index 0000000..7e9a67e --- /dev/null +++ b/intern-log/src/components/icons.ts @@ -0,0 +1,25 @@ +// 自绘 SVG 图标:24 画布 / 1.5 描边 / 圆角端点 / currentColor(设计方案 第 8 节) +function svg(body: string): string { + return '' + body + '' +} + +export const ICONS: Record = { + calendar: svg(''), + clock: svg(''), + 'check-circle': svg(''), + edit: svg(''), + tag: svg(''), + star: svg(''), + close: svg(''), + flag: svg(''), + chart: svg(''), + export: svg(''), + 'chevron-left': svg(''), + 'chevron-right': svg(''), + 'chevron-down': svg(''), + plus: svg(''), + search: svg(''), + settings: svg(''), + memo: svg(''), + lock: svg('') +} diff --git a/intern-log/src/components/log/DayPanel.vue b/intern-log/src/components/log/DayPanel.vue new file mode 100644 index 0000000..413305c --- /dev/null +++ b/intern-log/src/components/log/DayPanel.vue @@ -0,0 +1,542 @@ + + + + + diff --git a/intern-log/src/components/log/EditLogDialog.vue b/intern-log/src/components/log/EditLogDialog.vue new file mode 100644 index 0000000..5e9c787 --- /dev/null +++ b/intern-log/src/components/log/EditLogDialog.vue @@ -0,0 +1,243 @@ + + + + + diff --git a/intern-log/src/db/auth.ts b/intern-log/src/db/auth.ts new file mode 100644 index 0000000..38bc195 --- /dev/null +++ b/intern-log/src/db/auth.ts @@ -0,0 +1,160 @@ +import Dexie, { type Table } from 'dexie' +import { bindDatabase, db, unbindDatabase, WorklogDB } from './schema' +import { lockVault } from './vault' +import { pbkdf2Hash, randomSaltB64 } from '../lib/crypto' + +interface UserRecord { + id: string + username: string + pwd_hash: string + pwd_salt: string + legacy_imported_at?: string + created_at: string +} + +// 用户注册表:独立小库,仅存用户名与密码哈希,不存任何业务数据 +class UserRegistry extends Dexie { + user!: Table + constructor() { + super('intern_worklog_users') + this.version(1).stores({ user: 'id, &username' }) + } +} + +const registry = new UserRegistry() + +const LEGACY_DB_NAME = 'intern_worklog' +const SESSION_KEY = 'dsh_session_user' + +export interface Session { + userId: string + username: string +} + +// 会话存 sessionStorage:关闭标签页即退出,刷新页面保持登录 +export function getSession(): Session | null { + try { + const raw = sessionStorage.getItem(SESSION_KEY) + if (!raw) return null + const s = JSON.parse(raw) + if (s && s.userId && s.username) return s as Session + } catch { /* 忽略损坏会话 */ } + return null +} +function setSession(s: Session): void { + sessionStorage.setItem(SESSION_KEY, JSON.stringify(s)) +} +function clearSession(): void { + sessionStorage.removeItem(SESSION_KEY) +} + +export function openUserDatabase(userId: string): void { + bindDatabase(new WorklogDB(LEGACY_DB_NAME + '_' + userId)) +} + +export async function createUser(username: string, password: string, migrateLegacy: boolean): Promise { + const name = username.trim() + if (name.length < 2 || name.length > 20) throw new Error('用户名需 2 到 20 个字符') + if (password.length < 6) throw new Error('登录密码至少 6 位') + const exists = await registry.user.where('username').equals(name).first() + if (exists) throw new Error('用户名已存在') + const salt = randomSaltB64() + const hash = await pbkdf2Hash(password, salt) + const id = 'u_' + Date.now().toString(36) + '_' + Math.random().toString(36).slice(2, 6) + await registry.user.add({ id, username: name, pwd_hash: hash, pwd_salt: salt, created_at: new Date().toISOString() }) + openUserDatabase(id) + let copied = 0 + if (migrateLegacy && await legacyDataExists()) { + copied = await migrateLegacyInto() + await registry.user.update(id, { legacy_imported_at: new Date().toISOString() }) + } + const session: Session = { userId: id, username: name } + setSession(session) + if (copied) showToastCopied(copied) + return session +} + +export async function login(username: string, password: string): Promise { + const name = username.trim() + const rec = await registry.user.where('username').equals(name).first() + if (!rec) throw new Error('用户不存在') + const hash = await pbkdf2Hash(password, rec.pwd_salt) + if (hash !== rec.pwd_hash) throw new Error('密码不正确') + openUserDatabase(rec.id) + const session: Session = { userId: rec.id, username: rec.username } + setSession(session) + return session +} + +export async function logoutUser(): Promise { + lockVault() + unbindDatabase() + clearSession() +} + +export async function changeLoginPassword(oldPwd: string, newPwd: string): Promise { + const s = getSession() + if (!s) throw new Error('未登录') + if (newPwd.length < 6) throw new Error('新密码至少 6 位') + const rec = await registry.user.get(s.userId) + if (!rec) throw new Error('用户不存在') + const oldHash = await pbkdf2Hash(oldPwd, rec.pwd_salt) + if (oldHash !== rec.pwd_hash) throw new Error('旧密码不正确') + const salt = randomSaltB64() + const hash = await pbkdf2Hash(newPwd, salt) + await registry.user.update(rec.id, { pwd_hash: hash, pwd_salt: salt }) +} + +export async function deleteCurrentUser(): Promise { + const s = getSession() + if (!s) throw new Error('未登录') + lockVault() + unbindDatabase() + await Dexie.delete(LEGACY_DB_NAME + '_' + s.userId) + await registry.user.delete(s.userId) + clearSession() +} + +// 旧单机数据检测与迁移(迁移只复制,不删除原库,作为安全兜底) +export async function legacyDataExists(): Promise { + return Dexie.exists(LEGACY_DB_NAME) +} + +async function migrateLegacyInto(): Promise { + if (!db) throw new Error('用户数据库未就绪') + const legacy = new WorklogDB(LEGACY_DB_NAME) + const legacyData = await Promise.all([ + legacy.project.toArray(), + legacy.work_log.toArray(), + legacy.log_item.toArray(), + legacy.attendance.toArray(), + legacy.weekly_note.toArray(), + legacy.setting.toArray(), + legacy.memo.toArray(), + legacy.credential.toArray() + ]) + await db.transaction('rw', [db.project, db.work_log, db.log_item, db.attendance, db.weekly_note, db.setting, db.memo, db.credential], async () => { + await Promise.all([ + db.project.clear(), db.work_log.clear(), db.log_item.clear(), + db.attendance.clear(), db.weekly_note.clear(), db.setting.clear(), + db.memo.clear(), db.credential.clear() + ]) + if (legacyData[0].length) await db.project.bulkAdd(legacyData[0] as never[]) + if (legacyData[1].length) await db.work_log.bulkAdd(legacyData[1] as never[]) + if (legacyData[2].length) await db.log_item.bulkAdd(legacyData[2] as never[]) + if (legacyData[3].length) await db.attendance.bulkAdd(legacyData[3] as never[]) + if (legacyData[4].length) await db.weekly_note.bulkAdd(legacyData[4] as never[]) + if (legacyData[5].length) await db.setting.bulkAdd(legacyData[5] as never[]) + if (legacyData[6].length) await db.memo.bulkAdd(legacyData[6] as never[]) + if (legacyData[7].length) await db.credential.bulkAdd(legacyData[7] as never[]) + }) + const count = legacyData[0].length + legacyData[1].length + legacyData[2].length + + legacyData[3].length + legacyData[4].length + legacyData[6].length + legacyData[7].length + legacy.close() + return count +} + +function showToastCopied(count: number): void { + // 迁移完成的反馈由登录后的轻提示呈现(此处在会话建立前,暂存标记) + try { sessionStorage.setItem('dsh_migrate_toast', String(count)) } catch { /* 忽略 */ } +} diff --git a/intern-log/src/db/repo.ts b/intern-log/src/db/repo.ts new file mode 100644 index 0000000..5a04630 --- /dev/null +++ b/intern-log/src/db/repo.ts @@ -0,0 +1,405 @@ +import { db, DEFAULT_LOCATIONS, SCHEMA_VERSION, type Attendance, type Credential, type LogItem, type Memo, type Project, type WeeklyNote, type WorkLog } from './schema' +import { addDays, nowLocalISO, toDateStr } from '../lib/date' + +// ---------- 设置 ---------- + +export async function getSetting(key: string, fallback: string): Promise { + const row = await db.setting.get(key) + return row ? row.value : fallback +} + +export async function setSetting(key: string, value: string): Promise { + await db.setting.put({ key, value }) +} + +export interface WorkRule { + work_start: string + work_end: string + grace_minutes: number + lunch_minutes: number + remind_weekly: string +} + +export async function getWorkRule(): Promise { + const values = await Promise.all([ + getSetting('work_start', '09:00'), + getSetting('work_end', '18:00'), + getSetting('grace_minutes', '10'), + getSetting('lunch_minutes', '60'), + getSetting('remind_weekly', 'friday') + ]) + return { + work_start: values[0], + work_end: values[1], + grace_minutes: Number(values[2]) || 0, + lunch_minutes: Number(values[3]) || 0, + remind_weekly: values[4] + } +} + +export async function getLastPick(): Promise<{ project_id: number | null; category: string }> { + const lp = await getSetting('last_project', '') + const lc = await getSetting('last_category', 'dev') + return { project_id: lp ? Number(lp) : null, category: lc || 'dev' } +} + +export async function getLastLocation(): Promise { + return getSetting('last_location', '') +} + +// 记录某天的上班地点;当天尚无打卡记录时先建一条仅含地点的记录 +export async function setAttendanceLocation(date: string, location: string): Promise { + const loc = location.trim() + await setSetting('last_location', loc) + if (loc) await rememberLocation(loc) + const row = await getAttendance(date) + if (row && row.id) { + await db.attendance.update(row.id, { location: loc || null }) + } else if (loc) { + await db.attendance.add({ + date, clock_in_at: null, clock_out_at: null, + kind: 'normal', note: null, location: loc, created_at: nowLocalISO() + }) + } +} + +export async function getLocationPresets(): Promise { + const raw = await getSetting('location_presets', '') + if (!raw) return DEFAULT_LOCATIONS.slice() + try { + const arr = JSON.parse(raw) + if (Array.isArray(arr)) { + return arr.filter(x => typeof x === 'string' && x.trim()).map(x => (x as string).trim()) + } + } catch { /* 忽略损坏数据,回退默认 */ } + return DEFAULT_LOCATIONS.slice() +} + +export async function saveLocationPresets(list: string[]): Promise { + const clean = Array.from(new Set(list.map(x => x.trim()).filter(Boolean))) + await setSetting('location_presets', JSON.stringify(clean)) +} + +// 自定义输入的地点自动加入常用列表,下次可直接选 +export async function rememberLocation(loc: string): Promise { + const v = loc.trim() + if (!v) return + const presets = await getLocationPresets() + if (!presets.includes(v)) { + await saveLocationPresets([...presets, v]) + } +} + +// ---------- 项目 ---------- + +export async function listProjects(includeArchived = false): Promise { + const all = await db.project.orderBy('name').toArray() + return includeArchived ? all : all.filter(p => p.archived !== 1) +} + +export async function addProject(name: string): Promise { + await db.project.add({ name: name.trim(), archived: 0, created_at: nowLocalISO() }) +} + +export async function renameProject(id: number, name: string): Promise { + await db.project.update(id, { name: name.trim() }) +} + +export async function setProjectArchived(id: number, archived: boolean): Promise { + await db.project.update(id, { archived: archived ? 1 : 0 }) +} + +// ---------- 打卡 ---------- + +export async function getAttendance(date: string): Promise { + return db.attendance.where('date').equals(date).first() +} + +export async function clockIn(date: string, location?: string): Promise { + const loc = ((location === undefined ? await getSetting('last_location', '') : location) || '').trim() + const row = await getAttendance(date) + if (row && row.id) { + if (!row.clock_in_at) { + const patch: Partial = { clock_in_at: nowLocalISO() } + if (loc) patch.location = loc + await db.attendance.update(row.id, patch) + } + if (loc) { + await setSetting('last_location', loc) + await rememberLocation(loc) + } + return + } + await db.attendance.add({ + date, clock_in_at: nowLocalISO(), clock_out_at: null, + kind: 'normal', note: null, location: loc || null, created_at: nowLocalISO() + }) + if (loc) { + await setSetting('last_location', loc) + await rememberLocation(loc) + } +} + +export async function clockOut(date: string): Promise { + const row = await getAttendance(date) + if (row && row.id && row.clock_in_at && !row.clock_out_at) { + await db.attendance.update(row.id, { clock_out_at: nowLocalISO() }) + } +} + +export async function smartClockOut(): Promise { + const now = new Date() + const today = toDateStr(now) + if (now.getHours() < 4) { + const yRec = await getAttendance(addDays(today, -1)) + if (yRec && yRec.id && yRec.clock_in_at && !yRec.clock_out_at) { + await db.attendance.update(yRec.id, { clock_out_at: nowLocalISO() }) + return yRec.date + } + } + const tRec = await getAttendance(today) + if (tRec && tRec.id && tRec.clock_in_at && !tRec.clock_out_at) { + await db.attendance.update(tRec.id, { clock_out_at: nowLocalISO() }) + return tRec.date + } + throw new Error('没有进行中的打卡') +} + +export async function saveMakeup(date: string, inAt: string, outAt: string, note: string, location?: string): Promise { + if ((location || '').trim()) await rememberLocation(location as string) + const row = await getAttendance(date) + const patch = { + date, + clock_in_at: inAt, + clock_out_at: outAt, + kind: 'makeup', + note: note || null, + location: (location || '').trim() || null, + created_at: nowLocalISO() + } + if (row && row.id) await db.attendance.update(row.id, patch) + else await db.attendance.add(patch) +} + +// 直接修改某天的上/下班时间(行内编辑),状态由 computeDay 运行时自动重算 +export async function setAttendanceTime(date: string, field: 'clock_in_at' | 'clock_out_at', time: string): Promise { + const t = (time || '').trim() + if (!t) return + const row = await getAttendance(date) + if (row && row.id) { + await db.attendance.update(row.id, { [field]: date + 'T' + t + ':00' }) + } +} + +export async function listAttendanceBetween(start: string, end: string): Promise { + return db.attendance.where('date').between(start, end, true, true).toArray() +} + +// 休假标记:标记时清空上下班时间,取消后恢复可打卡状态 +export async function setLeave(date: string, leave: boolean): Promise { + const row = await getAttendance(date) + if (leave) { + const base = { date, kind: 'leave', clock_in_at: null, clock_out_at: null, created_at: nowLocalISO() } + if (row && row.id) await db.attendance.update(row.id, base) + else await db.attendance.add({ ...base, note: null, location: null }) + } else if (row && row.id) { + await db.attendance.update(row.id, { kind: 'normal' }) + } +} + +// ---------- 工作日志 ---------- + +export async function ensureWorkLog(date: string): Promise { + const found = await db.work_log.where('date').equals(date).first() + if (found) return found + const id = await db.work_log.add({ date, created_at: nowLocalISO() }) + return { id, date, created_at: nowLocalISO() } +} + +export async function getWorkLogByDate(date: string): Promise { + return db.work_log.where('date').equals(date).first() +} + +export async function listLogItemsByDate(date: string): Promise { + const wl = await getWorkLogByDate(date) + if (!wl || !wl.id) return [] + const items = await db.log_item.where('work_log_id').equals(wl.id).toArray() + return items.sort((a, b) => (b.id as number) - (a.id as number)) +} + +export interface NewLogItem { + content: string + project_id: number | null + category: string + minutes: number | null + takeaway: string | null + remark: string | null +} + +export async function addLogItem(date: string, data: NewLogItem): Promise { + const wl = await ensureWorkLog(date) + await db.log_item.add({ + work_log_id: wl.id as number, + content: data.content, + project_id: data.project_id, + category: data.category, + minutes: data.minutes, + is_milestone: 0, + needs_followup: 0, + takeaway: data.takeaway, + remark: data.remark, + sort_order: 0, + created_at: nowLocalISO() + }) + await setSetting('last_project', data.project_id ? String(data.project_id) : '') + await setSetting('last_category', data.category) +} + +export async function updateLogItem(id: number, patch: Partial): Promise { + await db.log_item.update(id, patch) +} + +export async function deleteLogItem(id: number): Promise { + await db.log_item.delete(id) +} + +export async function listLogItemsBetween(start: string, end: string): Promise<(LogItem & { date: string })[]> { + const wls = await db.work_log.where('date').between(start, end, true, true).toArray() + if (!wls.length) return [] + const map = new Map(wls.map(w => [w.id as number, w.date])) + const items = await db.log_item.where('work_log_id').anyOf(wls.map(w => w.id as number)).toArray() + return items + .map(it => ({ ...it, date: map.get(it.work_log_id) || '' })) + .sort((a, b) => (a.date === b.date ? (a.id as number) - (b.id as number) : a.date < b.date ? -1 : 1)) +} + +// ---------- 周记 ---------- + +export async function getWeeklyNote(weekStart: string): Promise { + return db.weekly_note.where('week_start').equals(weekStart).first() +} + +export async function saveWeeklyNote( + weekStart: string, + patch: { highlights?: string | null; challenges?: string | null; plan_next?: string | null } +): Promise { + const row = await getWeeklyNote(weekStart) + if (row && row.id) { + await db.weekly_note.update(row.id, patch) + } else { + await db.weekly_note.add({ + week_start: weekStart, + highlights: patch.highlights ?? null, + challenges: patch.challenges ?? null, + plan_next: patch.plan_next ?? null, + created_at: nowLocalISO() + }) + } +} + +export async function listWeeklyNotesBetween(start: string, end: string): Promise { + return db.weekly_note.where('week_start').between(start, end, true, true).toArray() +} + +// ---------- 备忘录 ---------- + +export async function listMemos(): Promise { + const rows = await db.memo.toArray() + return rows.sort((a, b) => (a.updated_at < b.updated_at ? 1 : -1)) +} + +export async function addMemo(title: string, content: string): Promise { + const now = nowLocalISO() + const id = await db.memo.add({ title: title.trim(), content, created_at: now, updated_at: now }) + return { id, title: title.trim(), content, created_at: now, updated_at: now } +} + +export async function updateMemo(id: number, title: string, content: string): Promise { + await db.memo.update(id, { title: title.trim(), content, updated_at: nowLocalISO() }) +} + +export async function deleteMemo(id: number): Promise { + await db.memo.delete(id) +} + +// ---------- 全局搜索 ---------- + +export async function searchLogItems(q: string, limit = 8): Promise<(LogItem & { date: string })[]> { + const needle = q.trim().toLowerCase() + if (!needle) return [] + const wls = await db.work_log.toArray() + const map = new Map(wls.map(w => [w.id as number, w.date])) + const all = await db.log_item.toArray() + return all + .filter(it => ((it.content || '') + ' ' + (it.takeaway || '') + ' ' + (it.remark || '')).toLowerCase().includes(needle)) + .sort((a, b) => (b.id as number) - (a.id as number)) + .slice(0, limit) + .map(it => ({ ...it, date: map.get(it.work_log_id) || '' })) +} + +export async function searchMemos(q: string, limit = 4): Promise { + const needle = q.trim().toLowerCase() + if (!needle) return [] + const all = await db.memo.toArray() + return all + .filter(m => ((m.title || '') + ' ' + (m.content || '')).toLowerCase().includes(needle)) + .sort((a, b) => (a.updated_at < b.updated_at ? 1 : -1)) + .slice(0, limit) +} + +// ---------- 备份 ---------- + +export async function exportAll(): Promise { + const tables = await Promise.all([ + db.project.toArray(), + db.work_log.toArray(), + db.log_item.toArray(), + db.attendance.toArray(), + db.weekly_note.toArray(), + db.setting.toArray(), + db.memo.toArray(), + db.credential.toArray() + ]) + return JSON.stringify({ + schema_version: SCHEMA_VERSION, + exported_at: nowLocalISO(), + data: { + project: tables[0], + work_log: tables[1], + log_item: tables[2], + attendance: tables[3], + weekly_note: tables[4], + setting: tables[5], + memo: tables[6], + credential: tables[7] + } + }, null, 2) +} + +export async function importAll(jsonText: string): Promise { + let parsed: { schema_version?: number; data?: Record } | null = null + try { + parsed = JSON.parse(jsonText) + } catch { + throw new Error('不是有效的 JSON 文件') + } + if (!parsed || (parsed.schema_version !== 1 && parsed.schema_version !== 2) || !parsed.data) { + throw new Error('文件格式或 schema 版本不匹配') + } + const d = parsed.data + await db.transaction('rw', [db.project, db.work_log, db.log_item, db.attendance, db.weekly_note, db.setting, db.memo, db.credential], async () => { + await Promise.all([ + db.project.clear(), db.work_log.clear(), db.log_item.clear(), + db.attendance.clear(), db.weekly_note.clear(), db.setting.clear(), + db.memo.clear(), db.credential.clear() + ]) + if (d.project && d.project.length) await db.project.bulkAdd(d.project as never[]) + if (d.work_log && d.work_log.length) await db.work_log.bulkAdd(d.work_log as never[]) + if (d.log_item && d.log_item.length) await db.log_item.bulkAdd(d.log_item as never[]) + if (d.attendance && d.attendance.length) await db.attendance.bulkAdd(d.attendance as never[]) + if (d.weekly_note && d.weekly_note.length) await db.weekly_note.bulkAdd(d.weekly_note as never[]) + if (d.setting && d.setting.length) await db.setting.bulkAdd(d.setting as never[]) + if (d.memo && d.memo.length) await db.memo.bulkAdd(d.memo as never[]) + if (d.credential && d.credential.length) await db.credential.bulkAdd(d.credential as never[]) + }) +} diff --git a/intern-log/src/db/schema.ts b/intern-log/src/db/schema.ts new file mode 100644 index 0000000..f57c727 --- /dev/null +++ b/intern-log/src/db/schema.ts @@ -0,0 +1,125 @@ +import Dexie, { type Table } from 'dexie' + +export interface Project { + id?: number + name: string + archived: number + created_at: string +} + +export interface WorkLog { + id?: number + date: string + created_at: string +} + +export interface LogItem { + id?: number + work_log_id: number + content: string + project_id: number | null + category: string + minutes: number | null + is_milestone: number + needs_followup: number + takeaway: string | null + remark: string | null + sort_order: number + created_at: string +} + +export interface Attendance { + id?: number + date: string + clock_in_at: string | null + clock_out_at: string | null + kind: string + note: string | null + location?: string | null + created_at: string +} + +export interface WeeklyNote { + id?: number + week_start: string + highlights: string | null + challenges: string | null + plan_next: string | null + created_at: string +} + +export interface Memo { + id?: number + title: string + content: string + created_at: string + updated_at: string +} + +export interface Credential { + id?: number + system: string + account: string + password: string + remark: string + created_at: string + updated_at: string +} + +export class WorklogDB extends Dexie { + project!: Table + work_log!: Table + log_item!: Table + attendance!: Table + weekly_note!: Table + setting!: Table<{ key: string; value: string }, string> + memo!: Table + credential!: Table + + constructor(dbName = 'intern_worklog') { + super(dbName) + this.version(1).stores({ + project: '++id, &name, archived', + work_log: '++id, &date', + log_item: '++id, work_log_id, project_id, category', + attendance: '++id, &date', + weekly_note: '++id, &week_start', + setting: 'key' + }) + this.version(2).stores({ + memo: '++id, updated_at', + credential: '++id, system, updated_at' + }) + } +} + +// 当前登录用户绑定的数据库实例:不同用户物理隔离不同库,登录后由 auth 模块注入 +export let db: WorklogDB | undefined + +export function bindDatabase(instance: WorklogDB): void { + db = instance +} + +export function unbindDatabase(): void { + if (db) db.close() + db = undefined +} + +export const SCHEMA_VERSION = 2 + +export const DEFAULT_LOCATIONS: string[] = ['公司', '客户现场', '出差', '居家办公'] + +export const CATEGORIES: { key: string; label: string }[] = [ + { key: 'dev', label: '开发' }, + { key: 'bugfix', label: 'BUG修复' }, + { key: 'test', label: '测试' }, + { key: 'learning', label: '学习成长' }, + { key: 'meeting', label: '会议沟通' }, + { key: 'doc', label: '文档输出' }, + { key: 'other', label: '其他' } +] + +export function categoryLabel(key: string): string { + const found = CATEGORIES.find(c => c.key === key) + return found ? found.label : '其他' +} diff --git a/intern-log/src/db/vault.ts b/intern-log/src/db/vault.ts new file mode 100644 index 0000000..64e8299 --- /dev/null +++ b/intern-log/src/db/vault.ts @@ -0,0 +1,142 @@ +import { db, type Credential } from './schema' +import { getSetting, setSetting } from './repo' +import { aesGcmDecrypt, aesGcmEncrypt, bufToB64, deriveKeyFromPassword, randomSaltB64 } from '../lib/crypto' +import { nowLocalISO } from '../lib/date' + +const VERIFY_TEXT = 'intern-log-vault-verify' +const ENCRYPT_PREFIX = 'enc:v1:' + +// 主密钥仅存于内存,页面刷新或手动锁定后需重新解锁 +let masterKey: CryptoKey | null = null + +export function isVaultUnlocked(): boolean { + return masterKey !== null +} + +export function lockVault(): void { + masterKey = null +} + +export async function isVaultInitialized(): Promise { + return (await getSetting('pwd_salt', '')) !== '' +} + +export async function setupVault(password: string): Promise { + if (password.length < 6) throw new Error('主密码至少 6 位') + if (await isVaultInitialized()) throw new Error('主密码已设置') + const salt = randomSaltB64() + const key = await deriveKeyFromPassword(password, salt) + const verifier = await aesGcmEncrypt(key, VERIFY_TEXT) + await setSetting('pwd_salt', salt) + await setSetting('pwd_verifier', verifier) + masterKey = key +} + +export async function unlockVault(password: string): Promise { + const salt = await getSetting('pwd_salt', '') + if (!salt) throw new Error('主密码尚未设置') + const key = await deriveKeyFromPassword(password, salt) + const verifier = await getSetting('pwd_verifier', '') + try { + await aesGcmDecrypt(key, verifier) + } catch { + throw new Error('主密码不正确') + } + masterKey = key +} + +async function requireKey(): Promise { + if (!masterKey) throw new Error('密码库未解锁') + return masterKey +} + +export async function encryptSecret(plain: string): Promise { + const key = await requireKey() + return ENCRYPT_PREFIX + await aesGcmEncrypt(key, plain) +} + +export async function decryptSecret(packed: string | null | undefined): Promise { + if (!packed) return '' + if (!packed.startsWith(ENCRYPT_PREFIX)) return packed + const key = await requireKey() + return aesGcmDecrypt(key, packed.slice(ENCRYPT_PREFIX.length)) +} + +// ---------- 账号密码 CRUD ---------- + +export async function listCredentials(): Promise { + return db.credential.orderBy('system').toArray() +} + +export interface CredentialInput { + system: string + account: string + password: string + remark: string +} + +export async function saveCredential(input: CredentialInput, id?: number): Promise { + const enc = await encryptSecret(input.password) + const base = { + system: input.system.trim(), + account: input.account.trim(), + password: enc, + remark: input.remark.trim() + } + if (id) { + await db.credential.update(id, { ...base, updated_at: nowLocalISO() }) + } else { + await db.credential.add({ ...base, created_at: nowLocalISO(), updated_at: nowLocalISO() }) + } +} + +export async function deleteCredential(id: number): Promise { + await db.credential.delete(id) +} + +export async function revealCredentialPassword(id: number): Promise { + const row = await db.credential.get(id) + if (!row) throw new Error('记录不存在') + return decryptSecret(row.password) +} + +// ---------- 修改主密码:旧密钥解密全部记录后用新密钥重新加密 ---------- + +export async function changeMasterPassword(oldPwd: string, newPwd: string): Promise { + if (!oldPwd) throw new Error('请输入旧主密码') + if (newPwd.length < 6) throw new Error('新主密码至少 6 位') + if (newPwd === oldPwd) throw new Error('新主密码不能与旧主密码相同') + const salt = await getSetting('pwd_salt', '') + if (!salt) throw new Error('密码库尚未初始化') + const oldKey = await deriveKeyFromPassword(oldPwd, salt) + const verifier = await getSetting('pwd_verifier', '') + try { + await aesGcmDecrypt(oldKey, verifier) + } catch { + throw new Error('旧主密码不正确') + } + const newKey = await deriveKeyFromPassword(newPwd, salt) + const rows = await db.credential.toArray() + let count = 0 + for (const row of rows) { + if (row.id == null) continue + const plain = await decryptSecretWithKey(row.password, oldKey) + const enc = ENCRYPT_PREFIX + await aesGcmEncrypt(newKey, plain) + await db.credential.update(row.id, { password: enc }) + count++ + } + await setSetting('pwd_verifier', await aesGcmEncrypt(newKey, VERIFY_TEXT)) + masterKey = newKey + return count +} + +async function decryptSecretWithKey(packed: string | null | undefined, key: CryptoKey): Promise { + if (!packed) return '' + if (!packed.startsWith(ENCRYPT_PREFIX)) return packed + return aesGcmDecrypt(key, packed.slice(ENCRYPT_PREFIX.length)) +} + +// 供备份模块使用:生成新的随机盐(占位,保持导出接口一致) +export function newSaltB64(): string { + return bufToB64(crypto.getRandomValues(new Uint8Array(16)).buffer) +} diff --git a/intern-log/src/domain/ai.ts b/intern-log/src/domain/ai.ts new file mode 100644 index 0000000..76f84b1 --- /dev/null +++ b/intern-log/src/domain/ai.ts @@ -0,0 +1,44 @@ +import { getSetting } from '../db/repo' + +// AI 润色:调用 OpenAI 兼容的 Chat Completions 接口 +export async function polishReport(markdown: string): Promise { + const values = await Promise.all([ + getSetting('ai_base_url', ''), + getSetting('ai_api_key', ''), + getSetting('ai_model', '') + ]) + const base = values[0].trim().replace(/\/+$/, '') + const key = values[1].trim() + const model = values[2].trim() + if (!base || !model) throw new Error('请先在设置页配置 AI 接口地址与模型名称') + const url = base + '/chat/completions' + const headers: Record = { 'Content-Type': 'application/json' } + if (key) headers['Authorization'] = 'Bearer ' + key + const system = '你是一名严谨的中文助理。请将用户提供的工作总结 Markdown 草稿润色为通顺、专业、简洁的工作总结。要求:保留原有章节结构与全部事实数据(数字、日期、条目),不得虚构或遗漏内容,只输出 Markdown 正文。' + const body = JSON.stringify({ + model, + messages: [ + { role: 'system', content: system }, + { role: 'user', content: markdown } + ], + temperature: 0.3 + }) + let resp: Response + try { + resp = await fetch(url, { method: 'POST', headers, body }) + } catch { + throw new Error('无法访问 AI 接口:请检查地址是否正确、服务端是否允许浏览器跨域访问') + } + if (!resp.ok) { + let msg = '接口返回 ' + resp.status + try { + const j = await resp.json() + if (j && j.error && j.error.message) msg += ':' + j.error.message + } catch { /* 忽略非 JSON 响应 */ } + throw new Error(msg) + } + const j = await resp.json() + const text = j && j.choices && j.choices[0] && j.choices[0].message && j.choices[0].message.content + if (!text) throw new Error('接口未返回内容') + return String(text) +} diff --git a/intern-log/src/domain/attendance.ts b/intern-log/src/domain/attendance.ts new file mode 100644 index 0000000..bbf76a5 --- /dev/null +++ b/intern-log/src/domain/attendance.ts @@ -0,0 +1,46 @@ +import type { Attendance } from '../db/schema' +import type { WorkRule } from '../db/repo' +import { hhmm, isWeekend, tsMinutes } from '../lib/date' + +export type DayStatus = 'normal' | 'late' | 'early' | 'incomplete' | 'absent' | 'none' | 'rest' + +export interface DayAttendanceInfo { + status: DayStatus + label: string + makeup: boolean + workedMinutes: number | null +} + +function toMin(t: string): number { + const parts = t.split(':') + return Number(parts[0]) * 60 + Number(parts[1]) +} + +// 考勤状态运行时计算,不落库(设计方案 4.3) +export function computeDay(rec: Attendance | undefined, date: string, rule: WorkRule, isToday: boolean): DayAttendanceInfo { + if (rec && rec.kind === 'leave') { + return { status: 'leave', label: '请假', makeup: false, workedMinutes: null } + } + if (isWeekend(date)) { + return { status: 'rest', label: '休息日', makeup: false, workedMinutes: null } + } + if (!rec || !rec.clock_in_at) { + if (isToday) return { status: 'none', label: '未打卡', makeup: false, workedMinutes: null } + return { status: 'absent', label: '缺勤', makeup: !!(rec && rec.kind === 'makeup'), workedMinutes: null } + } + const makeup = rec.kind === 'makeup' + if (!rec.clock_out_at) { + return { status: 'incomplete', label: isToday ? '进行中' : '未完成', makeup, workedMinutes: null } + } + const inMin = toMin(hhmm(rec.clock_in_at)) + const outMin = toMin(hhmm(rec.clock_out_at)) + const startMin = toMin(rule.work_start) + const endMin = toMin(rule.work_end) + let status: DayStatus = 'normal' + if (!makeup && inMin > startMin + rule.grace_minutes) status = 'late' + else if (!makeup && outMin < endMin) status = 'early' + const span = tsMinutes(rec.clock_in_at, rec.clock_out_at) + const worked = Math.max(0, span - rule.lunch_minutes) + const label = makeup ? '补卡' : status === 'late' ? '迟到' : status === 'early' ? '早退' : '正常' + return { status, label, makeup, workedMinutes: worked } +} diff --git a/intern-log/src/domain/report.ts b/intern-log/src/domain/report.ts new file mode 100644 index 0000000..2ca94a0 --- /dev/null +++ b/intern-log/src/domain/report.ts @@ -0,0 +1,178 @@ +import { getWorkRule, listAttendanceBetween, listLogItemsBetween, listProjects, listWeeklyNotesBetween } from '../db/repo' +import { CATEGORIES, type LogItem } from '../db/schema' +import { todayStr } from '../lib/date' +import { computeDay } from './attendance' + +export interface ReportRange { + start: string + end: string + label: string +} + +export interface CategoryStat { + key: string + label: string + count: number + percent: number +} + +export interface ProjectStat { + name: string + count: number +} + +export interface ReportData { + range: ReportRange + attendDays: number + totalHours: string + makeupCount: number + leaveCount: number + itemCount: number + categoryStats: CategoryStat[] + projectStats: ProjectStat[] + locationStats: { name: string; count: number }[] + milestones: { date: string; content: string }[] + followups: { date: string; content: string; remark: string }[] + takeaways: { date: string; text: string }[] + weekNotes: { weekStart: string; highlights: string; challenges: string; plan_next: string }[] +} + +export async function buildReport(start: string, end: string, label: string): Promise { + const t = todayStr() + const results = await Promise.all([ + getWorkRule(), + listAttendanceBetween(start, end), + listLogItemsBetween(start, end), + listProjects(true), + listWeeklyNotesBetween(start, end) + ]) + const rule = results[0] + const atts = results[1] + const items = results[2] + const projects = results[3] + const notes = results[4] + + let attendDays = 0 + let workedMin = 0 + let makeupCount = 0 + for (const a of atts) { + if (a.clock_in_at || a.kind === 'makeup') attendDays++ + if (a.kind === 'makeup') makeupCount++ + const info = computeDay(a, a.date, rule, a.date === t) + workedMin += info.workedMinutes ?? 0 + } + + const lcount = new Map() + for (const a of atts) { + if (!(a.clock_in_at || a.kind === 'makeup')) continue + const name = a.location || '未记录' + lcount.set(name, (lcount.get(name) || 0) + 1) + } + const locationStats = Array.from(lcount.entries()) + .map(pair => ({ name: pair[0], count: pair[1] })) + .sort((a, b) => b.count - a.count) + + const total = items.length || 1 + const categoryStats: CategoryStat[] = CATEGORIES + .map(c => { + const count = items.filter((i: LogItem) => i.category === c.key).length + return { key: c.key, label: c.label, count, percent: Math.round((count / total) * 100) } + }) + .filter(c => c.count > 0) + .sort((a, b) => b.count - a.count) + + const pname = new Map(projects.map(p => [p.id as number, p.name])) + const pcount = new Map() + for (const it of items) { + const name = it.project_id ? (pname.get(it.project_id) || '已删除项目') : '无项目' + pcount.set(name, (pcount.get(name) || 0) + 1) + } + const projectStats: ProjectStat[] = Array.from(pcount.entries()) + .map(pair => ({ name: pair[0], count: pair[1] })) + .sort((a, b) => b.count - a.count) + + const milestones = items.filter(i => i.is_milestone === 1).map(i => ({ date: i.date, content: i.content })) + const followups = items.filter(i => i.needs_followup === 1).map(i => ({ date: i.date, content: i.content, remark: i.remark || '' })) + const takeaways = items.filter(i => !!i.takeaway).map(i => ({ date: i.date, text: i.takeaway as string })) + const weekNotes = notes.map(n => ({ + weekStart: n.week_start, + highlights: n.highlights || '', + challenges: n.challenges || '', + plan_next: n.plan_next || '' + })) + + return { + range: { start, end, label }, + attendDays, + totalHours: (workedMin / 60).toFixed(1), + makeupCount, + leaveCount: atts.filter(a => a.kind === 'leave').length, + itemCount: items.length, + categoryStats, + projectStats, + locationStats, + milestones, + followups, + takeaways, + weekNotes + } +} + +export function reportToMarkdown(d: ReportData): string { + const out: string[] = [] + out.push('# 实习工作总结(' + d.range.start + ' ~ ' + d.range.end + ')') + out.push('') + out.push('## 一、考勤概况') + out.push('') + out.push('出勤 ' + d.attendDays + ' 天,累计工时 ' + d.totalHours + ' 小时,补卡 ' + d.makeupCount + ' 次' + (d.leaveCount ? ',请假 ' + d.leaveCount + ' 天' : '')) + const locParts = d.locationStats.filter(l => l.name !== '未记录') + if (locParts.length) { + out.push('其中:' + locParts.map(l => l.name + ' ' + l.count + ' 天').join(',')) + } + out.push('') + out.push('## 二、工作内容分布') + out.push('') + out.push(d.categoryStats.length + ? d.categoryStats.map(c => c.label + ' ' + c.percent + '%(' + c.count + ' 条)').join(',') + : '(无记录)') + out.push('') + out.push('## 三、项目投入') + out.push('') + out.push(d.projectStats.length + ? d.projectStats.map(p => p.name + ' ' + p.count + ' 条').join(',') + : '(无记录)') + out.push('') + out.push('## 四、主要成果') + out.push('') + if (d.milestones.length) { + d.milestones.forEach((m, i) => out.push((i + 1) + '. 【成果】' + m.content + '(' + m.date + ')')) + } else { + out.push('(无)') + } + out.push('') + out.push('## 五、待跟进事项') + out.push('') + if (d.followups.length) { + d.followups.forEach(f => out.push('- 【待跟进】' + f.content + (f.remark ? '(' + f.date + ' 备注:' + f.remark + ')' : '(' + f.date + ')'))) + } else { + out.push('(无)') + } + out.push('') + out.push('## 六、学习与成长') + out.push('') + if (d.takeaways.length) { + d.takeaways.forEach(tk => out.push('- ' + tk.text + '(' + tk.date + ')')) + } else { + out.push('(无)') + } + for (const w of d.weekNotes) { + out.push('') + out.push('### 周记(' + w.weekStart + ' 起)') + out.push('') + out.push('- 本周亮点:' + (w.highlights || '(无)')) + out.push('- 踩的坑:' + (w.challenges || '(无)')) + out.push('- 下周计划:' + (w.plan_next || '(无)')) + } + out.push('') + return out.join('\n') +} diff --git a/intern-log/src/lib/bus.ts b/intern-log/src/lib/bus.ts new file mode 100644 index 0000000..070f3e0 --- /dev/null +++ b/intern-log/src/lib/bus.ts @@ -0,0 +1,11 @@ +import { ref } from 'vue' + +// 跨视图定位信号:全局搜索命中后跳转到对应视图并聚焦 +export const focusDate = ref(null) +export const focusMemo = ref(null) + +// 考勤数据变更信号:打卡、修改时间、补卡、休假后自增,所有考勤展示视图监听并实时刷新 +export const attendanceChanged = ref(0) +export function notifyAttendanceChanged(): void { + attendanceChanged.value++ +} diff --git a/intern-log/src/lib/clipboard.ts b/intern-log/src/lib/clipboard.ts new file mode 100644 index 0000000..8731b26 --- /dev/null +++ b/intern-log/src/lib/clipboard.ts @@ -0,0 +1,14 @@ +export async function copyText(text: string): Promise { + try { + await navigator.clipboard.writeText(text) + } catch { + const ta = document.createElement('textarea') + ta.value = text + ta.style.position = 'fixed' + ta.style.opacity = '0' + document.body.appendChild(ta) + ta.select() + document.execCommand('copy') + document.body.removeChild(ta) + } +} diff --git a/intern-log/src/lib/crypto.ts b/intern-log/src/lib/crypto.ts new file mode 100644 index 0000000..974a90e --- /dev/null +++ b/intern-log/src/lib/crypto.ts @@ -0,0 +1,62 @@ +// 主密码加密:PBKDF2-SHA256 派生 AES-256-GCM 密钥(设计方案 3.8) +const PBKDF2_ITERATIONS = 150000 + +export function bufToB64(buf: ArrayBuffer): string { + const bytes = new Uint8Array(buf) + let bin = '' + for (let i = 0; i < bytes.length; i++) bin += String.fromCharCode(bytes[i]) + return btoa(bin) +} + +function b64ToBytes(s: string): Uint8Array { + const bin = atob(s) + const bytes = new Uint8Array(bin.length) + for (let i = 0; i < bin.length; i++) bytes[i] = bin.charCodeAt(i) + return bytes +} + +export function randomSaltB64(): string { + return bufToB64(crypto.getRandomValues(new Uint8Array(16)).buffer) +} + +// 登录密码哈希:仅存 PBKDF2 派生值,不存明文 +export async function pbkdf2Hash(password: string, saltB64: string): Promise { + const enc = new TextEncoder() + const base = await crypto.subtle.importKey('raw', enc.encode(password), 'PBKDF2', false, ['deriveBits']) + const bits = await crypto.subtle.deriveBits( + { name: 'PBKDF2', salt: b64ToBytes(saltB64), iterations: PBKDF2_ITERATIONS, hash: 'SHA-256' }, + base, + 256 + ) + return bufToB64(bits) +} + +export async function deriveKeyFromPassword(password: string, saltB64: string): Promise { + const enc = new TextEncoder() + const base = await crypto.subtle.importKey('raw', enc.encode(password), 'PBKDF2', false, ['deriveKey']) + return crypto.subtle.deriveKey( + { name: 'PBKDF2', salt: b64ToBytes(saltB64), iterations: PBKDF2_ITERATIONS, hash: 'SHA-256' }, + base, + { name: 'AES-GCM', length: 256 }, + false, + ['encrypt', 'decrypt'] + ) +} + +// 密文打包格式:iv_base64:cipher_base64 +export async function aesGcmEncrypt(key: CryptoKey, plaintext: string): Promise { + const iv = crypto.getRandomValues(new Uint8Array(12)) + const cipher = await crypto.subtle.encrypt({ name: 'AES-GCM', iv }, key, new TextEncoder().encode(plaintext)) + return bufToB64(iv.buffer as ArrayBuffer) + ':' + bufToB64(cipher) +} + +export async function aesGcmDecrypt(key: CryptoKey, packed: string): Promise { + const parts = packed.split(':') + if (parts.length !== 2) throw new Error('密文格式错误') + const plain = await crypto.subtle.decrypt( + { name: 'AES-GCM', iv: b64ToBytes(parts[0]) }, + key, + b64ToBytes(parts[1]) + ) + return new TextDecoder().decode(plain) +} diff --git a/intern-log/src/lib/csv.ts b/intern-log/src/lib/csv.ts new file mode 100644 index 0000000..41bc919 --- /dev/null +++ b/intern-log/src/lib/csv.ts @@ -0,0 +1,16 @@ +function csvCell(v: string | number | null | undefined): string { + const s = v == null ? '' : String(v) + return '"' + s.replace(/"/g, '""') + '"' +} + +// 导出 UTF-8 BOM 的 CSV,Excel 可直接打开中文不乱码 +export function downloadCsv(filename: string, rows: (string | number | null | undefined)[][]): void { + const content = rows.map(r => r.map(csvCell).join(',')).join('\r\n') + const blob = new Blob(['\ufeff' + content], { type: 'text/csv;charset=utf-8' }) + const url = URL.createObjectURL(blob) + const a = document.createElement('a') + a.href = url + a.download = filename + a.click() + URL.revokeObjectURL(url) +} diff --git a/intern-log/src/lib/date.ts b/intern-log/src/lib/date.ts new file mode 100644 index 0000000..d96531c --- /dev/null +++ b/intern-log/src/lib/date.ts @@ -0,0 +1,65 @@ +export function pad(n: number): string { + return n < 10 ? '0' + n : String(n) +} + +export function toDateStr(d: Date): string { + return d.getFullYear() + '-' + pad(d.getMonth() + 1) + '-' + pad(d.getDate()) +} + +export function todayStr(): string { + return toDateStr(new Date()) +} + +export function nowLocalISO(): string { + const d = new Date() + return toDateStr(d) + 'T' + pad(d.getHours()) + ':' + pad(d.getMinutes()) + ':' + pad(d.getSeconds()) +} + +export function hhmm(iso: string | null | undefined): string { + if (!iso) return '--:--' + const i = iso.indexOf('T') + return i >= 0 ? iso.slice(i + 1, i + 6) : iso.slice(0, 5) +} + +export function parseDateStr(s: string): Date { + const parts = s.split('-').map(Number) + return new Date(parts[0], parts[1] - 1, parts[2]) +} + +export function addDays(s: string, n: number): string { + const d = parseDateStr(s) + d.setDate(d.getDate() + n) + return toDateStr(d) +} + +export function addMonths(s: string, n: number): string { + const d = parseDateStr(s) + const day = d.getDate() + d.setDate(1) + d.setMonth(d.getMonth() + n) + const last = new Date(d.getFullYear(), d.getMonth() + 1, 0).getDate() + d.setDate(Math.min(day, last)) + return toDateStr(d) +} + +export function weekStart(s: string): string { + const d = parseDateStr(s) + const wd = (d.getDay() + 6) % 7 + d.setDate(d.getDate() - wd) + return toDateStr(d) +} + +export function isWeekend(s: string): boolean { + const wd = parseDateStr(s).getDay() + return wd === 0 || wd === 6 +} + +export function tsMinutes(a: string, b: string): number { + return Math.round((new Date(b).getTime() - new Date(a).getTime()) / 60000) +} + +export function formatDateCN(s: string): string { + const d = parseDateStr(s) + const names = ['周日', '周一', '周二', '周三', '周四', '周五', '周六'] + return d.getFullYear() + ' 年 ' + (d.getMonth() + 1) + ' 月 ' + d.getDate() + ' 日 ' + names[d.getDay()] +} diff --git a/intern-log/src/lib/download.ts b/intern-log/src/lib/download.ts new file mode 100644 index 0000000..7cb1208 --- /dev/null +++ b/intern-log/src/lib/download.ts @@ -0,0 +1,9 @@ +export function downloadText(filename: string, text: string): void { + const blob = new Blob([text], { type: 'text/plain;charset=utf-8' }) + const url = URL.createObjectURL(blob) + const a = document.createElement('a') + a.href = url + a.download = filename + a.click() + URL.revokeObjectURL(url) +} diff --git a/intern-log/src/lib/toast.ts b/intern-log/src/lib/toast.ts new file mode 100644 index 0000000..c24a5ca --- /dev/null +++ b/intern-log/src/lib/toast.ts @@ -0,0 +1,22 @@ +import { ref } from 'vue' + +export interface ToastItem { + id: number + text: string +} + +const toasts = ref([]) +let seq = 0 + +// 轻提示:操作结果统一在右上角反馈,2 秒自动消失 +export function showToast(text: string): void { + const id = ++seq + toasts.value.push({ id, text }) + setTimeout(() => { + toasts.value = toasts.value.filter(t => t.id !== id) + }, 2000) +} + +export function useToasts() { + return toasts +} diff --git a/intern-log/src/main.ts b/intern-log/src/main.ts new file mode 100644 index 0000000..5c97cf3 --- /dev/null +++ b/intern-log/src/main.ts @@ -0,0 +1,12 @@ +import { createApp } from 'vue' +import App from './App.vue' +import './styles/tokens.css' + +createApp(App).mount('#app') + +// PWA:注册 Service Worker,安装为应用后可离线使用 +if ('serviceWorker' in navigator && location.protocol.startsWith('http')) { + window.addEventListener('load', () => { + navigator.serviceWorker.register('sw.js').catch(() => { /* 注册失败不影响正常使用 */ }) + }) +} diff --git a/intern-log/src/styles/tokens.css b/intern-log/src/styles/tokens.css new file mode 100644 index 0000000..997dffe --- /dev/null +++ b/intern-log/src/styles/tokens.css @@ -0,0 +1,117 @@ +:root { + --bg-page: #FFFFFF; + --bg-subtle: #F7F8FA; + --bg-hover: #F2F3F5; + --border: #EBEDF0; + --border-strong: #DCDEE3; + --text-1: #1D2129; + --text-2: #4E5969; + --text-3: #86909C; + --accent: #3370FF; + --accent-bg: #F0F5FF; + --ok: #23A757; + --warn: #E8842C; + --danger: #E5484D; + --dot-empty: #C9CDD4; + --radius-sm: 6px; + --radius-md: 8px; + --radius-lg: 12px; + --shadow-float: 0 4px 16px rgba(29, 33, 41, 0.08); +} + +* { box-sizing: border-box; } + +html, body { margin: 0; padding: 0; } + +body { + background: var(--bg-page); + color: var(--text-1); + font-family: -apple-system, "PingFang SC", "Microsoft YaHei", system-ui, sans-serif; + font-size: 13px; + line-height: 1.6; + -webkit-font-smoothing: antialiased; +} + +button, input, select, textarea { font: inherit; color: inherit; } + +.num { font-variant-numeric: tabular-nums; } +.flex1 { flex: 1; } +.muted { color: var(--text-3); } +.muted2 { color: var(--text-2); } + +.btn { + display: inline-flex; + align-items: center; + justify-content: center; + gap: 6px; + padding: 0 12px; + height: 32px; + border-radius: var(--radius-sm); + border: 1px solid var(--border-strong); + background: var(--bg-page); + color: var(--text-1); + cursor: pointer; + white-space: nowrap; +} +.btn:hover { background: var(--bg-hover); } +.btn:disabled { opacity: 0.45; cursor: not-allowed; } +.btn-primary { background: var(--accent); border-color: var(--accent); color: #FFFFFF; } +.btn-primary:hover { background: #2B5FD9; } +.btn-danger { color: var(--danger); border-color: var(--danger); } +.btn-sm { height: 26px; padding: 0 10px; font-size: 12px; } +.btn-xs { height: 22px; padding: 0 8px; font-size: 12px; } + +.input, .select, .textarea { + height: 32px; + padding: 0 10px; + border: 1px solid var(--border-strong); + border-radius: var(--radius-sm); + background: var(--bg-page); + outline: none; + width: 100%; +} +.textarea { height: auto; min-height: 56px; padding: 8px 10px; resize: vertical; } +.input:focus, .select:focus, .textarea:focus { border-color: var(--accent); } +.input::placeholder, .textarea::placeholder { color: var(--text-3); } + +.card { border: 1px solid var(--border); border-radius: var(--radius-md); background: var(--bg-page); } + +.icon-btn { + display: inline-flex; + align-items: center; + justify-content: center; + width: 26px; + height: 26px; + flex: none; + border: none; + background: transparent; + border-radius: var(--radius-sm); + color: var(--text-3); + cursor: pointer; +} +.icon-btn:hover { background: var(--bg-hover); color: var(--text-1); } +.icon-btn.active { color: var(--accent); } +.icon-btn.active-warn { color: var(--warn); } + +.tag { + display: inline-block; + padding: 0 8px; + height: 22px; + line-height: 20px; + border-radius: 4px; + font-size: 12px; + background: var(--bg-subtle); + color: var(--text-2); + border: 1px solid var(--border); + white-space: nowrap; +} + +.dot { width: 6px; height: 6px; border-radius: 50%; display: inline-block; flex: none; } +.dot.normal { background: var(--ok); } +.dot.late, .dot.early, .dot.incomplete { background: var(--warn); } +.dot.absent { background: var(--danger); } +.dot.none { background: var(--dot-empty); } +.dot.rest { background: var(--border); } + +.icon { display: inline-flex; align-items: center; justify-content: center; flex: none; } +.icon svg { width: 100%; height: 100%; display: block; } diff --git a/intern-log/src/views/CalendarView.vue b/intern-log/src/views/CalendarView.vue new file mode 100644 index 0000000..76ac9e7 --- /dev/null +++ b/intern-log/src/views/CalendarView.vue @@ -0,0 +1,209 @@ + + + + + diff --git a/intern-log/src/views/LoginView.vue b/intern-log/src/views/LoginView.vue new file mode 100644 index 0000000..42ea942 --- /dev/null +++ b/intern-log/src/views/LoginView.vue @@ -0,0 +1,147 @@ + + + + + diff --git a/intern-log/src/views/MemoView.vue b/intern-log/src/views/MemoView.vue new file mode 100644 index 0000000..e155300 --- /dev/null +++ b/intern-log/src/views/MemoView.vue @@ -0,0 +1,255 @@ + + + + + diff --git a/intern-log/src/views/ReportView.vue b/intern-log/src/views/ReportView.vue new file mode 100644 index 0000000..1d8ec42 --- /dev/null +++ b/intern-log/src/views/ReportView.vue @@ -0,0 +1,241 @@ + + + + + diff --git a/intern-log/src/views/SettingsView.vue b/intern-log/src/views/SettingsView.vue new file mode 100644 index 0000000..10ee07c --- /dev/null +++ b/intern-log/src/views/SettingsView.vue @@ -0,0 +1,377 @@ + + + + + diff --git a/intern-log/src/views/StatsView.vue b/intern-log/src/views/StatsView.vue new file mode 100644 index 0000000..0ed8b22 --- /dev/null +++ b/intern-log/src/views/StatsView.vue @@ -0,0 +1,206 @@ + + + + + diff --git a/intern-log/src/views/TodayView.vue b/intern-log/src/views/TodayView.vue new file mode 100644 index 0000000..e27a295 --- /dev/null +++ b/intern-log/src/views/TodayView.vue @@ -0,0 +1,12 @@ + + + diff --git a/intern-log/src/views/VaultView.vue b/intern-log/src/views/VaultView.vue new file mode 100644 index 0000000..d59ddbc --- /dev/null +++ b/intern-log/src/views/VaultView.vue @@ -0,0 +1,437 @@ + + + + + diff --git a/intern-log/tsconfig.json b/intern-log/tsconfig.json new file mode 100644 index 0000000..da0aa32 --- /dev/null +++ b/intern-log/tsconfig.json @@ -0,0 +1,14 @@ +{ + "compilerOptions": { + "target": "ES2020", + "module": "ESNext", + "moduleResolution": "Bundler", + "strict": true, + "jsx": "preserve", + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "types": ["vite/client"], + "skipLibCheck": true, + "noEmit": true + }, + "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.vue"] +} diff --git a/intern-log/vite.config.ts b/intern-log/vite.config.ts new file mode 100644 index 0000000..aee54b2 --- /dev/null +++ b/intern-log/vite.config.ts @@ -0,0 +1,7 @@ +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' + +export default defineConfig({ + plugins: [vue()], + base: './' +}) diff --git a/实习工作日志系统-设计方案.md b/实习工作日志系统-设计方案.md new file mode 100644 index 0000000..868715e --- /dev/null +++ b/实习工作日志系统-设计方案.md @@ -0,0 +1,484 @@ +# 实习工作日志系统 设计方案 + +- 版本:v1.10(Electron 桌面应用) +- 范围:个人版全量功能;团队版仅作扩展预留 + +## 1. 产品定位 + +面向实习生的轻量工作记录工具,覆盖四个环节:考勤打卡、每日记录、周记沉淀、一键总结。 + +| 维度 | 说明 | +|---|---| +| 目标用户 | 实习生本人(个人版);扩展支持导师查看(团队版预留) | +| 核心痛点 | 记录难坚持、总结靠回忆、考勤对不清 | +| 核心价值 | 10 秒记一条;写入即结构化,总结零回忆;数据本地可控、随时导出 | +| 产品形态 | 本地优先 Web 应用,桌面与移动浏览器均可使用 | + +## 2. 设计原则 + +1. 写入时结构化,总结时只聚合:记录时多花 2 秒选项目与分类,总结时不再回忆 +2. 一切以「天」为聚合键:打卡、日志、周记按日期自然关联,无复杂外键 +3. 极致低摩擦:打卡一键完成,记录一句话即可 +4. 视觉克制:高级白主题、灰阶文字、唯一强调色、1px 细线分层 +5. 无特殊符号、无表情:全部图标自绘 SVG,导出文档用文字标签 +## 3. 功能设计 + +### 3.1 打卡 + +| 功能 | 说明 | +|---|---| +| 上班打卡 | 一键记录时间戳;当日重复点击时按钮置灰并显示打卡时间 | +| 下班打卡 | 仅当日已有上班打卡后可用 | +| 考勤状态 | 运行时按规则实时计算,不落库(规则见 4.3) | +| 补卡 | 近 30 天内任选日期补录上下班时间,kind 记为 makeup,原因写入 note | +| 规则配置 | 上班时间、下班时间、迟到宽限分钟、午休扣除分钟 | +| 上班地点 | 打卡与补卡时可选可输入(公司、客户现场、出差、居家办公等,支持自由输入城市),存于 attendance.location,记住上次选择 | + +### 3.2 日历(月视图) + +| 元素 | 表达方式 | +|---|---| +| 出勤状态 | 6px 圆点:正常(ok) / 缺卡(warn) / 缺勤(danger) / 无记录(dot-empty) | +| 已写日志 | 12px check-circle 小图标 | +| 成果日 | 小 star 图标,表示当日存在星标条目 | +| 今天 | 日期数字用强调色,其余日期灰阶 | +| 周末 | 文字降为辅助色,不填色块 | +| 交互 | 点击日期打开当日抽屉(桌面右侧 / 移动整页);月份切换;回到今天 | + +### 3.3 工作日志 + +快速记录控件状态: + +| 控件 | 默认状态 | +|---|---| +| 内容输入框 | 常显,placeholder「做了什么」,回车即提交 | +| 项目下拉 | 常显,记住上次选择 | +| 分类下拉 | 常显,记住上次选择 | +| 耗时 / 备注 / 收获 | 默认折叠,点击展开 | +| 星标 / 待跟进 | 条目上的图标按钮,点击切换 | + +三个文本位分工(防重复): + +| 字段 | 回答的问题 | 总结去向 | +|---|---|---| +| content | 做了什么 | 总结正文 | +| takeaway | 学到了什么 | 「学习与成长」章节 | +| remark | 背景、链接、未决事项 | 可检索;带旗标的进「待跟进」章节 | + +### 3.4 周记 + +- 每周五(可配置开关)顶部提示补填:本周亮点 / 踩的坑 / 下周计划,三个文本位 +- 周报草稿 = 周记 + 当周日志自动聚合 +- 周定义:周一为一周开始 + +### 3.5 总结生成 + +范围:本周 / 本月 / 自定义区间 / 全部实习期。 +流程:选范围 → 按模板聚合 → 生成可编辑草稿 → 导出 Markdown。 + +模板结构: + +``` +实习工作总结(起 ~ 止) + +一、考勤概况 + 出勤 N 天,累计工时 H 小时,补卡 M 次 + 地点分布:公司 N 天,客户现场 M 天 +二、工作内容分布 + 开发 45%,BUG修复 20%,学习 15%,会议 10%,文档 10% +三、项目投入 + 项目A 32 条,项目B 11 条 +四、主要成果 + 1. 星标条目逐条列出 +五、待跟进事项 + 带旗标且未勾销的备注 +六、学习与成长 + takeaway 汇总 + 各周 highlights +``` + +Markdown 导出节选示例(成果与待跟进均用文字标签,不用符号): + +``` +## 四、主要成果 +- 【成果】独立完成订单列表分页接口并上线(2025-03-04) +- 【成果】排查并修复订单金额精度丢失问题(2025-03-05) + +## 五、待跟进事项 +- 【待跟进】订单并发场景未覆盖测试(2025-03-06 备注) +``` + +AI 润色为可选进阶:将统计、成果、周记交给大模型按四段式输出,结果仍可编辑;前提是原料已结构化。 + +### 3.6 统计 + +| 卡片 | 指标 | +|---|---| +| 考勤 | 出勤天数 / 累计工时 / 补卡次数 | +| 记录 | 总条数 / 连续记录天数 | +| 分布 | 分类横向条形、项目投入横向条形(灰阶 + 单一强调色) | +| 趋势 | 近 12 周记录热力图(绿色单阶,克制) | + +### 3.7 备忘录 + +双栏结构:左侧列表(标题、内容摘要、更新时间),右侧编辑器(标题 + 内容)。带未保存修改守卫(切换、新建前确认)、删除确认弹窗。 + +### 3.8 密码库 + +企业账号密码管理:字段为系统名称、账号、密码、备注。 + +| 项 | 说明 | +|---|---| +| 加密 | 主密码经 PBKDF2-SHA256(150000 次迭代)派生 AES-256-GCM 密钥;密码字段以密文落库(enc:v1:iv:cipher) | +| 解锁 | 主密钥仅存内存,页面刷新或手动锁定后需重新解锁;首次使用时设置主密码 | +| 表格 | 系统名称 / 账号 / 密码(掩码显示、显示切换、一键复制)/ 备注 / 操作;支持按名称、账号、备注搜索 | +| 其他 | 新增与编辑弹窗(必填校验、一键生成随机密码)、删除确认、修改主密码(全量重新加密)、5 分钟无操作自动锁定 | + +### 3.9 全局搜索 + +顶栏搜索框(Ctrl+K 聚焦),覆盖工作记录(内容、收获、备注)与备忘录(标题、内容)。结果分组展示,点击跳转:工作记录定位到日历当月并打开当日抽屉,备忘录定位并选中。 + +### 3.10 数据导出与 AI 润色 + +- CSV 导出:工作记录(日期、分类、项目、内容、耗时、成果、待跟进、收获、备注)与考勤(日期、星期、状态、上下班、地点、类型、说明),UTF-8 BOM,Excel 直接打开 +- 报表支持复制到剪贴板 +- AI 润色:设置页配置 OpenAI 兼容接口(地址、API Key、模型名,仅存本机),总结页一键润色草稿,保留结构与事实数据,可一键还原润色前版本 +- 考勤支持休假标记:标记后该日状态为请假并清空打卡时间,统计与总结含请假天数 + +### 3.11 用户系统与数据隔离 + +| 项 | 说明 | +|---|---| +| 数据隔离 | 每位用户独立一个 IndexedDB 数据库(intern_worklog_u_用户ID),工作日志、考勤、备忘录、密码库物理隔离;用户注册表为独立小库,仅存用户名与密码哈希 | +| 身份校验 | 登录密码经 PBKDF2-SHA256(150000 次迭代、随机盐)哈希后存储,系统不保存明文;会话存 sessionStorage,关闭标签页即退出 | +| 会话安全 | 30 分钟无操作自动退出;退出即断开数据库连接并清空内存密钥 | +| 账号管理 | 设置页可修改登录密码、删除用户(连同其全部数据,二次确认) | +| 旧数据迁移 | 首次创建用户时可勾选迁移升级前单机数据,迁移仅复制、原库保留兜底 | + +## 4. 数据模型(SQLite) + +### 4.1 建表语句 + +```sql +-- 项目 +CREATE TABLE project ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + name TEXT NOT NULL UNIQUE, + archived INTEGER NOT NULL DEFAULT 0, + created_at TEXT NOT NULL DEFAULT (datetime('now','localtime')) +); + +-- 工作日志(以天为单位) +CREATE TABLE work_log ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + date TEXT NOT NULL UNIQUE, + created_at TEXT NOT NULL DEFAULT (datetime('now','localtime')) +); + +-- 日志条目(随手记) +CREATE TABLE log_item ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + work_log_id INTEGER NOT NULL REFERENCES work_log(id) ON DELETE CASCADE, + content TEXT NOT NULL, + project_id INTEGER REFERENCES project(id) ON DELETE SET NULL, + category TEXT NOT NULL DEFAULT 'other', + minutes INTEGER, + is_milestone INTEGER NOT NULL DEFAULT 0, + needs_followup INTEGER NOT NULL DEFAULT 0, + takeaway TEXT, + remark TEXT, + sort_order INTEGER NOT NULL DEFAULT 0, + created_at TEXT NOT NULL DEFAULT (datetime('now','localtime')) +); + +-- 打卡 +CREATE TABLE attendance ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + date TEXT NOT NULL UNIQUE, + clock_in_at TEXT, + clock_out_at TEXT, + kind TEXT NOT NULL DEFAULT 'normal', + note TEXT, + location TEXT, + created_at TEXT NOT NULL DEFAULT (datetime('now','localtime')) +); + +-- 周记 +CREATE TABLE weekly_note ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + week_start TEXT NOT NULL UNIQUE, + highlights TEXT, + challenges TEXT, + plan_next TEXT, + created_at TEXT NOT NULL DEFAULT (datetime('now','localtime')) +); + +-- 备忘录 +CREATE TABLE memo ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + title TEXT NOT NULL, + content TEXT NOT NULL, + created_at TEXT NOT NULL, + updated_at TEXT NOT NULL +); + +-- 账号密码(password 为 AES-256-GCM 密文,主密码派生密钥加密) +CREATE TABLE credential ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + system TEXT NOT NULL, + account TEXT NOT NULL, + password TEXT NOT NULL, + remark TEXT, + created_at TEXT NOT NULL, + updated_at TEXT NOT NULL +); + +-- 设置 +CREATE TABLE setting ( + key TEXT PRIMARY KEY, + value TEXT NOT NULL +); + +CREATE INDEX idx_log_item_log ON log_item(work_log_id); +CREATE INDEX idx_work_log_date ON work_log(date); +CREATE INDEX idx_attendance_date ON attendance(date); +``` + +setting 预置键:work_start(09:00)、work_end(18:00)、grace_minutes(10)、lunch_minutes(60)、remind_weekly(friday/off)、last_project、last_category。 + +### 4.2 分类枚举(固定,不开放自定义标签) + +dev 开发 / bugfix BUG修复 / test 测试 / learning 学习成长 / meeting 会议沟通 / doc 文档输出 / other 其他 + +### 4.3 考勤状态计算规则(运行时,不落库) + +``` +输入:attendance 记录 + setting 规则 +1. 工作日无任何打卡 缺勤 +2. 有上班、无下班 未完成 +3. 上班时间晚于 上班时刻+宽限 迟到 +4. 下班时间早于 下班时刻 早退 +5. kind 为 makeup 按正常计,附加「补卡」标记 +其余 正常 +``` + +### 4.4 约束要点 + +- work_log.date、attendance.date、weekly_note.week_start 均 UNIQUE,保证一天一条 +- 时间一律存 ISO 本地时间文本,展示层不做时区换算 +- log_item 通过外键级联删除,删天即清条目 +## 5. 页面结构 + +整体布局:左侧 56px 图标导航,顶部 56px 工具栏(视图标题 + 打卡主按钮 + 周记提醒点),主内容区最大宽 1200px 居中。 + +``` ++------+-------------------------------+ +| 导航 | 工具栏:标题 · 打卡按钮 · 提醒 | +| 日历 +-------------------------------+ +| 今日 | | +| 统计 | 主内容区 | +| 总结 | | +| 设置 | | ++------+-------------------------------+ +``` + +| 视图 | 内容 | +|---|---| +| 日历(默认首页) | 月历网格;点击日期开右侧当日抽屉:打卡时间线 + 条目列表 + 快速记录 | +| 今日 | 打卡状态卡 / 快速记录区 / 今日条目列表 / 自动小结(x 条 · y 小时) | +| 统计 | 概览卡片行 / 记录热力图 / 分类与项目条形图 | +| 总结 | 范围选择 + 左侧草稿编辑 + 右侧数据摘要 + 导出 Markdown | +| 设置 | 打卡规则 / 项目管理 / 周记提醒 / JSON 备份导入导出 | + +## 6. 交互细节 + +- 打卡点击后按钮原地变为文字状态「已打卡 09:02」,无弹窗 +- 快速记录回车提交,新条目插入列表顶部,150ms 透明度过渡 +- 删除、备份覆盖导入等不可逆操作:统一确认弹窗,明确说明操作对象与不可恢复性 +- 操作结果(打卡、保存、删除、导入等)以右上角轻提示统一反馈,2 秒自动消失 +- 空状态:居中灰字「暂无记录」 +- 备注中的 URL 自动识别为链接 +- 历史列表按月分页加载 +## 7. 视觉设计规范(高级白) + +色彩: + +``` +--bg-page #FFFFFF 页面底色 +--bg-subtle #F7F8FA 卡片内分区 +--bg-hover #F2F3F5 悬停态 +--border #EBEDF0 1px 分隔线 +--border-strong #DCDEE3 输入框描边 +--text-1 #1D2129 主文本 +--text-2 #4E5969 次要文本 +--text-3 #86909C 辅助与占位 +--accent #3370FF 唯一强调色:主按钮、当前日期、链接 +--accent-bg #F0F5FF 选中态浅底 +--ok #23A757 出勤正常(状态点) +--warn #E8842C 缺卡、待跟进(状态点) +--danger #E5484D 缺勤(状态点) +--dot-empty #C9CDD4 无记录(状态点) +``` + +排版: + +``` +font-family -apple-system, "PingFang SC", "Microsoft YaHei", system-ui, sans-serif +字号 12 辅助 / 13 正文 / 14 小标题 / 20 页面标题 +字重 400 正文 / 500 次强调 / 600 仅页面标题 +数字 font-variant-numeric: tabular-nums,打卡时间与统计数字严格对齐 +``` + +形状与层级: + +``` +圆角 6px 输入框与按钮 / 8px 卡片 / 12px 弹层 +阴影 常态无阴影,靠 1px 边框分层;仅浮层 0 4px 16px rgba(29,33,41,0.08) +间距 4 的倍数(4/8/12/16/24);内容区最大宽 1200px 居中 +强调色面积小于 5%;不使用渐变与大面积色块 +日历:白底 + 1px 细线网格,状态用 6px 圆点,不填色块 +``` + +交互态: + +``` +hover:--bg-hover +选中:--accent-bg 浅底 + 文字 --accent +过渡:仅透明度与背景色,不超过 150ms +``` + +禁用清单: + +1. 界面文案纯文字,不出现表情与装饰符号 +2. 勾、叉、箭头、展开折叠等视觉指示一律 SVG +3. 导出文档用文字标签「成果」「待跟进」,不用符号 +4. 数据层为纯文本,不依赖符号字符做逻辑判断 +## 8. SVG 图标体系 + +绘制规则: + +``` +画布 viewBox 0 0 24 24 +风格 线性描边,fill none +线宽 stroke-width 1.5 +端点 linecap 与 linejoin 均 round +颜色 stroke currentColor,激活态由 CSS 切色 +``` + +图标清单(14 个,覆盖全部界面): + +| 图标 | 用途 | 图标 | 用途 | +|---|---|---|---| +| calendar | 日历 | flag | 待跟进 | +| clock | 打卡 | chart | 统计 | +| check-circle | 完成 | export | 导出 | +| edit | 日志 | chevron-left / chevron-right | 月份切换 | +| tag | 项目分类 | chevron-down | 展开 | +| star | 成果 | plus | 新增 | +| close | 关闭 | search | 搜索(预留) | + +示例(定风格基调): + +```svg + + + + + + + + + + + + + + + + + + + + + + + + + + + + +``` + +工程化:全部图标集中在 components/icons.ts,以常量字符串导出、内联渲染,不引入任何第三方图标库。 +## 9. 技术方案 + +| 层 | 选型 | 理由 | +|---|---|---| +| 框架 | Vue 3 + TypeScript + Vite | 轻量、构建快、单页够用 | +| 存储 M1 | Dexie.js(IndexedDB) | 零部署、本地优先、打开即用 | +| 存储 M2 | Tauri 2 + SQLite | 日用稳定后桌面化,schema 不变仅换持久层 | +| 图标 | 自绘 SVG 内联 | 视觉完全自控 | +| 导出 | 前端生成 Markdown / JSON 下载 | 无后端依赖 | +| 应用化 | PWA(清单 + Service Worker + 自绘图标) | Edge/Chrome 一键安装为独立窗口应用,离线可用,数据仍在浏览器本地 | +| 桌面安装包 | Electron 33 + electron-builder(NSIS 安装包与免安装目录) | 数据存储于用户目录(userData),不受浏览器影响,双击即用 | + +路线:M1 纯前端交付;稳定后 Tauri 桌面化;团队版再加服务端与账号。 + +工程结构: + +``` +src/ + main.ts 入口 + App.vue 布局:导航 + 工具栏 + 路由视图 + router.ts 五个视图路由 + db/schema.ts 建表与迁移 + db/repo.ts 数据访问:attendance / log / weekly / project / setting + domain/attendance.ts 考勤状态计算 + domain/report.ts 总结聚合与模板渲染 + components/calendar/ 月历、格子、当日抽屉 + components/log/ 快速记录、条目列表、行内编辑 + components/icons.ts 自绘 SVG 图标 + styles/tokens.css 设计令牌(第 7 节) +``` + +## 10. 备份与导出 + +- JSON 全量备份:五表整包,含 schema 版本号,导入时校验版本 +- Markdown:总结草稿、单日记录 +- Excel 导出列入后续需求,M1 不做 +## 11. 边界情况 + +| 场景 | 处理 | +|---|---| +| 凌晨下班 | 04:00 前的下班打卡归属前一日;之后仍无下班记「未完成」,次日补卡 | +| 重复打卡 | 已有上班打卡时按钮置灰并显示时间 | +| 补卡超期 | 仅允许近 30 天 | +| 历史修改 | 个人版信任模式,任意条目可编辑;补卡记录保留 makeup 标记 | +| 缺周记 | 总结对应周显示「无周记」占位文字,不影响其余聚合 | + +## 12. 开发路线图 + +| 阶段 | 内容 | 预估 | +|---|---|---| +| M1 MVP | 打卡 + 月历 + 快速记录(项目/分类)+ 今日列表 | 1-2 天 | +| M2 | 星标、旗标、备注、收获 + 周记 + 统计页 | 1-2 天 | +| M3 | 总结生成 + Markdown 导出 + JSON 备份 + 设置页 | 1-2 天 | +| M4 可选 | AI 润色 / 提醒 / Tauri 桌面化 / 团队版 | 按需 | + +## 13. 扩展预留(本期不做) + +团队版(账号、导师只读、周报提交)、截图附件、系统级提醒、多端同步。 + +## 变更记录 + +- v1.1:新增上班地点(attendance.location):打卡、补卡可选填并记住上次选择;设置页支持常用地点预设;统计页与总结报告增加地点分布 +- v1.2:打卡时间支持行内直接修改(点击当日详情中的上班/下班时间即可编辑,可补录下班时间),修改后考勤状态运行时自动重算 +- v1.3:上班地点支持自定义输入并自动记忆:输入新地点保存后自动加入常用地点列表(可在设置中删减) +- v1.4:企业级表单与确认规范——当日详情重构为分区结构(出勤信息、补卡登记、新增工作记录、记录列表),字段全部带标签、必填校验与错误提示;时间编辑采用显式确认/取消;删除与备份覆盖导入使用统一确认弹窗;操作结果统一轻提示反馈 +- v1.5:已有工作记录支持完整信息编辑——点击条目或编辑图标,屏幕中央弹窗编辑全部字段(内容、项目、分类、耗时、收获、备注、成果标记、待跟进),带必填校验与归档项目回显 +- v1.6:新增备忘录(双栏列表与编辑、未保存守卫)与加密密码库(主密码 PBKDF2 派生 AES-256-GCM,密码密文落库,解锁、锁定、搜索、一键复制、随机密码生成、修改主密码全量重加密);备份兼容 v1 与 v2 格式 +- v1.7:全局搜索(Ctrl+K,跨工作记录与备忘录并跳转定位);考勤支持休假标记并纳入统计与总结;工作记录与考勤 CSV 导出;总结草稿一键复制;AI 润色(OpenAI 兼容接口,本机保存配置,可还原);密码库 5 分钟无操作自动锁定;日历格子悬停显示状态与地点 +- v1.7.1:考勤数据全视图实时同步——打卡、修改时间、补卡、休假、地点变更后,顶栏按钮、今日面板、日历抽屉、月历格子与统计页通过全局变更信号即时刷新,无需切换视图 +- v1.8:新增用户系统——每位用户独立 IndexedDB 数据库物理隔离数据;登录密码仅存 PBKDF2 哈希;会话存 sessionStorage 并支持 30 分钟无操作自动退出;设置页支持修改登录密码与删除用户;首次创建用户可一键迁移升级前单机数据(原库保留兜底) +- v1.9:PWA 应用化——新增 Web 应用清单、Service Worker 离线缓存与自绘应用图标;在 Edge/Chrome 中可一键安装为独立窗口应用(桌面图标、开始菜单入口),离线可用,数据随浏览器配置文件存储 +- v1.10:Electron 桌面应用——pnpm dist 一键产出 NSIS 安装包与免安装目录;主进程加载本地构建产物,数据存于系统用户目录;窗口禁用菜单栏、外部链接交由系统浏览器打开