diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c38753c --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +# 依赖(几百 MB,且由 pnpm 从镜像还原) +node_modules/ + +# 构建产物(Windows zip / Linux tar.gz 各上百 MB,随 Release 或交付包分发,不进仓库) +dist/ + +# 日志与系统垃圾 +*.log +.DS_Store +Thumbs.db diff --git a/.npmrc b/.npmrc new file mode 100644 index 0000000..94e2d91 --- /dev/null +++ b/.npmrc @@ -0,0 +1,7 @@ +# 依赖与二进制一律走国内镜像 / 加速站点(这台机器在离线内网环境外,直连官方源很慢甚至失败)。 +# 注意:这几个键对 pnpm 同样生效(pnpm 读 .npmrc),所以本机与构建机都不用再手配环境变量。 +registry=https://registry.npmmirror.com + +# electron 的运行时(postinstall 下载的那几十 MB)与 electron-builder 的打包工具二进制 +electron_mirror=https://npmmirror.com/mirrors/electron/ +electron_builder_binaries_mirror=https://npmmirror.com/mirrors/electron-builder-binaries/ diff --git a/DEVELOP.md b/DEVELOP.md new file mode 100644 index 0000000..3a57511 --- /dev/null +++ b/DEVELOP.md @@ -0,0 +1,205 @@ +# ClockLab · 开发文档 + +面向**要改这个项目**的人。使用者请看 [README.md](./README.md)。 + +--- + +## 一、项目结构 + +``` +main.js 主进程:建两个窗口、持有走时模型、注册全部 IPC、夹窗口尺寸 +preload.js contextBridge 暴露 window.clockApi(contextIsolation:true,无 nodeIntegration) +renderer/ + control.html/.css/.js 控制窗口:三块分区(时钟窗口 / 显示样式 / 时间与流速) + clock.html/.css/.js 时钟窗口:拖动区 + 8 条改大小热区 + 数字/表盘两种视图 + resize.js 拖边缘改大小的纯几何计算(单独拆出来是为了能在 node 里跑用例) + presented-time.js 呈现时间层:跳转动画(纯逻辑,浏览器/node 双向可加载) +src/ + clock-model.js 走时模型:基准时间 + 基准时刻 + 倍率(纯函数,可单测) + selftest.js GUI 自检(electron . --selftest),跑完出截图,只在开发机上用 +test/ 6 个文件、152 条用例(见第五节) +build/icon.ico, icon.png 程序图标 +.npmrc、pnpm-workspace.yaml 镜像与 pnpm 11 的依赖构建放行(见第六节,**别删**) +``` + +**分层原则**:凡是能用纯函数表达的(走时、改大小几何、呈现时间)都**单独成模块**,页面里只做接线。这样 152 条用例里有 103 条不需要浏览器环境就能跑。 + +--- + +## 二、三个关键实现 + +### 2.1 走时模型:锚点式,不累加 + +`src/clock-model.js` 只有三个动作,**每一个都是"重新锚定基准"**,没有一处累加: + +```js +displayMs(clock, now) = clock.baseMs + (now - clock.baseRealMs) * clock.rate + +setRate(clock, now, rate) // 倍率、暂停(0)、倒转(负)、小数都走这里 + clock.baseMs = displayMs(clock, now) // 先把当前显示时间固化 → 切倍率不跳变 + clock.baseRealMs = now + clock.rate = rate + if (rate !== 0) clock.lastRate = rate // 暂停时记住上次倍率,供「继续」用 + +shift(clock, now, deltaMs) // 快进/快退:与倍率完全解耦 +setTimeOfDay(clock, now, h, m, s) // 设定时间 +``` + +为什么这么写:如果用 `setInterval` 每次 `+1 秒`,倍率不是整数时会累积漂移,而且暂停/倒转都要另开分支。锚点式写法下,**倍率、暂停、倒转、快进是同一套机制的四个用法**,互不打架("先倒转、再暂停、再 +5 分钟"不会丢掉倒转的偏移)。 + +两个窗口各自用 `Date.now()`(同一台机器)跑同一个公式,画面 60fps 重算。 + +### 2.2 呈现时间层:跳转动画 + +`renderer/presented-time.js`。**数字和指针都从"呈现时间"推导**,而不是各做一套动画。 + +```js +function jumpBetween(previous, next) { // 同一真实时刻,两个参数算出的目标值之差 + const at = next.baseRealMs; + return targetAt(next, at) - targetAt(previous, at); +} +const animate = layer.snapshot !== null && snapshot.rate !== 0 + && Math.abs(jump) > JUMP_THRESHOLD_MS; // 1500ms +``` + +三个细节,**别在重构时弄丢**: + +1. **改倍率不会被误判成跳变** —— 比较的是"同一真实时刻的两个目标值",而模型在切倍率时先把当前显示时间固化进基准,两个公式在这一刻必然相等; +2. **数字和指针永远同步** —— 它们读同一个呈现时间,不会出现"数字到了、指针还在半路"; +3. **不会跨 12 点倒着转一圈** —— 动画的是**时间**,指针角度照样按正常公式从时间算(359°→1° 自然往前扫)。这是这类动画最经典的坑,用"动画时间而不是动画角度"直接绕开。 + +阈值 1500ms、缓动 0.35s `ease-out`。**动画没结束又来新跳变时,从当前呈现值重新出发**(不是跳回旧值重来)。 + +### 2.3 无边框窗口:拖动与改大小都是自己实现的 + +`frame: false` 之后,Windows 上**靠系统做边缘命中不可靠**,所以: + +- **拖动移动**:CSS `-webkit-app-region: drag`。整块 `.stage` 是拖动区,**按钮和 8 条热区单独声明 `no-drag`** —— 否则按钮会被拖动区盖住、点不动。 +- **拖边缘改大小**:渲染进程热区接 `pointerdown/move`,用「按下瞬间的窗口 bounds + 鼠标位移」算新 bounds,走 IPC 让主进程 `setBounds`。几何计算在 `renderer/resize.js`(纯函数,17 条用例)。 + - `pointerdown` 时用 `sendSync` 取 bounds —— **必须在这一刻拿到精确基准**; + - 顶到最小尺寸后继续拖,**被拖的那条边停住**,而不是把整个窗口推走(`resize.js` 里有专门处理与用例); + - 主进程 `applyBounds` 再夹一次最小值并挡掉 `NaN`。 + +最小尺寸 **260×150**(`main.js` 的 `MIN_SIZE`)。 + +--- + +## 三、环境与命令 + +```bash +pnpm install # 依赖 +npm start # 起应用 +npm test # 152 条用例(纯逻辑 + DOM 桩) +npm run selftest # GUI 自检:electron . --selftest,跑完出截图 +``` + +⚠️ **本机(Linux 无显示环境)跑 `npm start` 要 Xvfb**,而且 GPU 会刷 MESA 报错 —— 那是正常的。 + +--- + +## 四、改代码的几条约定 + +- **纯逻辑尽量往模块里放**(`src/clock-model.js`、`renderer/resize.js`、`renderer/presented-time.js`),页面只接线 —— 这样测试不用浏览器。 +- **改行为就同时改用例**,但**改断言之前先想清楚**:现有 152 条里有不少是钉边界的(例如"拖西边超过最小宽度时右边界不动"),它们是有意为之。 +- **数字输入相关的坑**:HTML 里 `type="number"` 的 `v-model`/取值在不同框架下会给 `number` 而不是字符串,本项目一律显式 `String(x)` 再用;**另一个坑是补零** —— `String(0)` 是 `"0"`,而时钟输入框按 `HH:MM:SS` 解析,所以必须 `pad2`(这个 bug 只在**凌晨 9 点前**才露出来,白天怎么测都是绿的)。 +- 注释写**为什么**,不写"这里做了什么"。 + +--- + +## 五、测试(152 条) + +| 文件 | 条数 | 覆盖 | +| --- | --- | --- | +| `test/clock-model.test.js` | 26 | 走时:零漂移、倍率切换不跳变、暂停/继续、倒转、快进 | +| `test/resize.test.js` | 17 | 改大小几何:四边四角、最小尺寸夹紧 | +| `test/presented-time.test.js` | 30 | 跳变判定、阈值、重定向、暂停不缓动、换倍率不算跳变 | +| `test/renderer-clock.dom-test.js` | 24 | 时钟窗口 DOM 桩:渲染、样式切换、热区接线 | +| `test/renderer-clock-anim.dom-test.js` | 26 | 跳转动画全链路:参数下发 → 呈现时间 → 数字 + 指针 | +| `test/renderer-control.dom-test.js` | 29 | 控制窗口:各按钮发出的调用、输入夹紧、置顶开关 | + +--- + +## 六、构建与打包 + +### 6.1 Windows(在 Windows 构建机上) + +**推荐在真 Windows 上打**,不要在这台 Linux 上跨平台打。踩过的坑见 6.3,能跑的流程是这样: + +```bat +:: 1) 依赖:必须 --ignore-scripts +:: electron 的 postinstall 会去下载运行时,网络不通时会把整个 install 拖垮 +pnpm install --ignore-scripts + +:: 2) 运行时:把 electron-v38.2.2-win32-x64.zip 手工解压到位 +:: ⚠️ node_modules/electron 是 pnpm 的**符号链接**,tar 拒绝"穿过符号链接"解压 +:: → 先解到临时目录,再 robocopy 进去 +mkdir D:\tmp\electron-dist +cd /d D:\tmp\electron-dist && tar -xf D:\tmp\electron-win-x64.zip +robocopy D:\tmp\electron-dist <项目>\node_modules\electron\dist /E + +:: 3) 出包:直接调 electron-builder 的 CLI(`pnpm run` 会先做依赖检查、可能 EPERM) +:: 用 --config.electronDist 明确告诉它运行时在哪,别让它走下载分支 +node node_modules\electron-builder\out\cli\cli.js --win --x64 ^ + --config.electronDist=D:\tmp\electron-dist + +:: 4) 压缩:electron-builder 的 zip target 会去下 7zip 工具(见 6.3),自己压更稳 +cd dist && tar -a -c -f ClockLab-1.0.0-win-x64.zip win-unpacked +``` + +产物:`dist\win-unpacked\`(目录版)+ 自己压的 zip。 + +### 6.2 Linux ARM64(在本机打) + +**手工拼**,不要用 electron-builder: + +```bash +# 1) 复制 Electron 运行时(本机是 arm64,node_modules/electron/dist 就是对的版本) +cp -a node_modules/electron/dist/. dist/ClockLab-1.0.0-linux-arm64/ +mv dist/ClockLab-1.0.0-linux-arm64/electron dist/ClockLab-1.0.0-linux-arm64/clocklab + +# 2) 应用代码进 resources/app/ +mkdir -p dist/ClockLab-1.0.0-linux-arm64/resources/app +cp main.js preload.js package.json dist/ClockLab-1.0.0-linux-arm64/resources/app/ +cp -a src renderer dist/ClockLab-1.0.0-linux-arm64/resources/app/ + +# 3) 打 tar.gz +tar -C dist -czf dist/ClockLab-1.0.0-linux-arm64.tar.gz ClockLab-1.0.0-linux-arm64 +``` + +**验证**:解压后 `./clocklab` 直接能跑(本机就是 arm64,Xvfb 下起得来即说明链接与资源都对)。 + +### 6.3 踩过的坑(**看这一节能省几个小时**) + +**① electron-builder 在"需要下载"这条分支上必崩** + +``` +⨯ Cannot read properties of undefined (reading 'ReadWrite') + at resolveCacheMode (app-builder-lib/src/util/electronGet.ts:131) +``` +根因:`ElectronDownloadCacheMode` 在运行环境里是 `undefined`,代码却直接读它的 `.ReadWrite`。**26.15.3 与 26.16.1 都有**,Windows 与 Linux 都复现。触发点是"它认为需要下载 Electron 运行时/7zip 工具" —— 所以: +- 用 `--config.electronDist=<运行时目录>` 让它**不需要下载**; +- 打 zip 时它仍要 7zip 工具,那条路也会崩 → **压缩自己来**。 + +**② 手工放运行时还不够,还得让它"知道"运行时在哪** +- electron 包装里的 `path.txt` **不是** electron-builder 的判据(它走 `@electron/get` 的缓存机制); +- 直接给它 `electronDist` 才是正解。 + +**③ 网络:这台环境从官方源下 Electron 很难** +- 直连 GitHub:`%TEMP%` 里会堆一排 `electron-download-*` 重试目录直到失败; +- npmmirror 镜像:`ELECTRON_MIRROR` 可用,但它在拼 `SHASUMS256.txt` 时可能 404; +- gh 加速站(`gh-proxy.com`):实测 403; +- **最稳**:**在能上网的机器上把 zip 下好**(`https://npmmirror.com/mirrors/electron/38.2.2/electron-v38.2.2-<平台>.zip`),再传过去手工放。 + +**④ pnpm 11 的 `strictDepBuilds`** +只要有依赖的构建脚本被跳过,`pnpm install` 会**直接以退出码 1 失败**(`ERR_PNPM_IGNORED_BUILDS`),而 electron 的 postinstall 正是下载运行时那一步。放行写在 `pnpm-workspace.yaml` 的 `allowBuilds`(`package.json` 的 `pnpm` 字段与 `.npmrc` 的 `onlyBuiltDependencies` 在 pnpm 11 已不生效),**这个文件别删**。 + +**⑤ `pnpm run` 会先做依赖状态检查** +`pnpm run dist:win` 可能触发一次 `install`,在 `node_modules` 被动过的目录上会 `ERR_PNPM_EPERM`(rename 失败)。**直接调 CLI**(`node node_modules/electron-builder/out/cli/cli.js …`)可绕过。 + +--- + +## 七、已知可以再做的 + +- **Windows 的 portable 单文件 exe** 还没做成(卡在 6.3 ① 的 7zip 工具那条路)—— 绿色版 zip 功能等价,只是多一步解压; +- **飞腾平台(LoongArch 不是 ARM64)不支持** —— 本项目产出的是 ARM64,龙芯需要另找运行时; +- 表盘目前没有"刻度数字"(只有刻度线与指针)。 diff --git a/README.md b/README.md index 04494e8..212f019 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,109 @@ -# ClockLab +# ClockLab · 可调速桌面时钟 -一个简单的本地时钟计时器 \ No newline at end of file +一个用于**演练、演示、排练**的小工具:一个**可以任意调速的时钟**(走快、走慢、暂停、**倒着走**、一键快进),配上随时可开的**满屏时钟窗口**。 + +典型用法:现场排练时把时钟投到第二块屏上,需要"跳过 30 分钟"或"把时间倒回去重来一遍"时,不用真的等 —— 在控制窗口点一下就行。 + +--- + +## 一、两个窗口 + +程序启动后只出来**一个**窗口: + +- **控制窗口** —— 普通窗口,所有操作都在这里; +- **时钟窗口** —— **默认不出现**,由控制窗口的「打开时钟窗口」按钮创建/关闭。 + +**时钟窗口的特点**:无标题栏、无工具栏、无边框 —— 投屏时不会露出窗口装饰。它**可以拖动移动**(按住空白处拖),**可以拖四条边和四个角改变大小**(最小 260×150)。 + +--- + +## 二、怎么操作 + +### 时钟窗口那一块 + +| 功能 | 说明 | +| --- | --- | +| **打开 / 关闭时钟窗口** | 按钮文案会跟着状态变;关掉随时能再开 | +| **时钟窗口始终置顶** | 让它压在所有窗口之上(现场投屏基本都要开) | +| **控制窗口始终置顶** | 单独一个开关,两个窗口互不影响 | + +> 提醒:时钟窗口用的是**比普通置顶更硬**的级别,**可能会盖住任务栏**。如果你希望它"温柔"一点,见《DEVELOP.md》里的说明。 + +### 显示样式 + +- **纯数字** —— 大字号电子钟,`HH:MM:SS` 加日期; +- **圆形表盘** —— 带时针 / 分针 / 秒针的表盘。 + +切换**立即生效**,不用重开窗口。 + +### 时间与流速 + +| 功能 | 说明 | +| --- | --- | +| **设定时间** | 填时 / 分 / 秒,点应用,时钟立刻跳到那个时间 | +| **填入当前显示时间** | 把输入框一键填成时钟**现在显示**的时间(改之前先看一下当前值) | +| **倍率** | 支持 **正数、负数、0、小数**:`1` 正常、`2` 两倍速、`-1` **倒着走**、`0` 暂停、`0.5` 半速 | +| **暂停 / 继续** | 暂停后按钮会变成「**继续(回到 ×N)**」,N 是暂停前的倍率,点一下按原速度接着走 | +| **快进** | `+5 秒` / `+1 分钟` / `+5 分钟` / `+10 分钟` / `+30 分钟`,点了立刻往前跳(与当前倍率不冲突,倒着走时点快进也是往前跳) | + +几个组合起来的效果: + +- 想现场"重新来一遍":倍率填 `-1`,时钟就倒着走;到点了点「暂停」,再点 `+30 分钟` 往前调。 +- 想演示"时间飞逝":倍率填 `10`,秒针会飞快转。 +- 只想让时钟停在那儿:点「暂停」。 + +### 跳转时的动画 + +**快进、设定时间、继续**这些**一次性跳变**会播放动画:数字滚到新值、表盘指针扫过去(约 0.35 秒)。 + +**正常走时、倒转、高倍率不加动画** —— 那时数字本来就在飞快变化,再加动画只会糊成一团。跳变幅度小于 1.5 秒也直接跳(免得正常走时每秒都抖一下)。 + +--- + +## 三、怎么运行 + +### Windows + +解压 `ClockLab-1.0.0-win-x64.zip`,双击里面的 **`ClockLab.exe`**。绿色版,不写注册表、不需要安装。 + +### Linux(ARM64) + +```bash +tar -xzf ClockLab-1.0.0-linux-arm64.tar.gz # 解压(约 290 MB) +cd ClockLab-1.0.0-linux-arm64 +./clocklab +``` + +> ⚠️ **解压前建议先校验**:`sha256sum ClockLab-1.0.0-linux-arm64.tar.gz` 对着交付时给的哈希看一眼。传输中断过的话,`tar` 会报 `异常的 EOF`,那就是没传完(不是包坏了)。 + +--- + +## 四、常见问题 + +**界面黑屏 / 花屏 / 一闪就退(国产平台常见)** + +多半是显卡驱动下的硬件加速不兼容,用这两个参数之一启动: + +```bash +./clocklab --disable-gpu # 关掉硬件加速(最常用) +./clocklab --in-process-gpu # 或者让 GPU 跑在主进程里 +``` + +**窗口拖不动 / 改不了大小** + +先确认拖的是**时钟窗口的空白处**(按钮和边缘热区不在拖动区内);改大小要把鼠标移到**四条边或四个角**上(光标会变成双向箭头)。 + +**文字太小 / 太大** + +直接拖时钟窗口的边缘改变尺寸,数字和表盘会跟着缩放。 + +--- + +## 五、这个项目在哪 + +源码与构建说明见同目录的 **[DEVELOP.md](./DEVELOP.md)**。已经打好的包在 `dist/`: + +``` +dist/ClockLab-1.0.0-win-x64.zip Windows x64 绿色版 +dist/ClockLab-1.0.0-linux-arm64.tar.gz Linux ARM64(飞腾 D2000 等) +``` diff --git a/build/icon.ico b/build/icon.ico new file mode 100644 index 0000000..5946a75 Binary files /dev/null and b/build/icon.ico differ diff --git a/build/icon.png b/build/icon.png new file mode 100644 index 0000000..877e1a8 Binary files /dev/null and b/build/icon.png differ diff --git a/main.js b/main.js new file mode 100644 index 0000000..113df9c --- /dev/null +++ b/main.js @@ -0,0 +1,243 @@ +'use strict'; + +const { app, BrowserWindow, ipcMain } = require('electron'); +const path = require('node:path'); +const clockModel = require('./src/clock-model'); + +const RENDERER_DIR = path.join(__dirname, 'renderer'); +const PRELOAD = path.join(__dirname, 'preload.js'); +const SELF_TEST = process.argv.includes('--selftest'); + +const MIN_SIZE = { width: 260, height: 150 }; +const DEFAULT_CLOCK_SIZE = { width: 520, height: 280 }; + +const state = { + clock: clockModel.create(Date.now()), + style: 'digital', + alwaysOnTop: { clock: true, control: false } +}; + +let controlWindow = null; +let clockWindow = null; + +function isAlive(win) { + return Boolean(win) && !win.isDestroyed(); +} + +function publicState() { + return { + style: state.style, + baseMs: state.clock.baseMs, + baseRealMs: state.clock.baseRealMs, + rate: state.clock.rate, + lastRate: state.clock.lastRate, + paused: state.clock.rate === 0, + clockWindowOpen: isAlive(clockWindow), + alwaysOnTop: { ...state.alwaysOnTop }, + serverNow: Date.now() + }; +} + +function broadcast() { + const snapshot = publicState(); + for (const win of [controlWindow, clockWindow]) { + if (isAlive(win)) win.webContents.send('state', snapshot); + } +} + +const WEB_PREFERENCES = { + preload: PRELOAD, + contextIsolation: true, + nodeIntegration: false +}; + +function createControlWindow() { + controlWindow = new BrowserWindow({ + width: 920, + height: 720, + minWidth: 780, + minHeight: 560, + title: 'ClockLab 控制台', + backgroundColor: '#12151c', + autoHideMenuBar: true, + show: false, + webPreferences: WEB_PREFERENCES + }); + + controlWindow.setAlwaysOnTop(state.alwaysOnTop.control); + controlWindow.loadFile(path.join(RENDERER_DIR, 'control.html')); + controlWindow.once('ready-to-show', () => controlWindow.show()); + controlWindow.on('closed', () => { + controlWindow = null; + // 控制窗口是唯一常驻入口,它被关掉就等于用户要退出整个程序(时钟窗口一起走) + if (!SELF_TEST) app.quit(); + }); +} + +function createClockWindow() { + if (isAlive(clockWindow)) return clockWindow; + + clockWindow = new BrowserWindow({ + width: DEFAULT_CLOCK_SIZE.width, + height: DEFAULT_CLOCK_SIZE.height, + minWidth: MIN_SIZE.width, + minHeight: MIN_SIZE.height, + frame: false, + resizable: true, + movable: true, + maximizable: false, + fullscreenable: false, + backgroundColor: '#05070c', + title: 'ClockLab 时钟', + show: false, + webPreferences: WEB_PREFERENCES + }); + + // screen-saver 级别:现场投影时希望它压在其他全屏窗口之上,普通 alwaysOnTop 在 Windows 上不够硬 + clockWindow.setAlwaysOnTop(state.alwaysOnTop.clock, 'screen-saver'); + clockWindow.loadFile(path.join(RENDERER_DIR, 'clock.html')); + clockWindow.once('ready-to-show', () => { + clockWindow.show(); + broadcast(); + }); + clockWindow.on('closed', () => { + clockWindow = null; + broadcast(); + }); + + return clockWindow; +} + +function closeClockWindow() { + if (isAlive(clockWindow)) clockWindow.close(); +} + +// 自定义拖边缘改大小最终落到这里:夹住最小尺寸,避免渲染进程算出 NaN 时把窗口搞坏 +function applyBounds(next) { + if (!isAlive(clockWindow)) return null; + const current = clockWindow.getBounds(); + const bounds = { + x: Number.isFinite(next.x) ? Math.round(next.x) : current.x, + y: Number.isFinite(next.y) ? Math.round(next.y) : current.y, + width: Math.max(MIN_SIZE.width, Number.isFinite(next.width) ? Math.round(next.width) : current.width), + height: Math.max(MIN_SIZE.height, Number.isFinite(next.height) ? Math.round(next.height) : current.height) + }; + clockWindow.setBounds(bounds); + return clockWindow.getBounds(); +} + +// 所有会改动时钟/窗口的动作都集中在这里:IPC 和自检脚本共用同一条代码路径, +// 自检才不会测到一份「和线上不一样」的逻辑。 +const actions = { + setRate(rate) { + const value = Number(rate); + if (Number.isFinite(value)) { + clockModel.setRate(state.clock, Date.now(), value); + broadcast(); + } + return publicState(); + }, + + togglePause() { + const now = Date.now(); + const target = state.clock.rate === 0 ? state.clock.lastRate || 1 : 0; + clockModel.setRate(state.clock, now, target); + broadcast(); + return publicState(); + }, + + fastForward(deltaMs) { + const delta = Number(deltaMs); + if (Number.isFinite(delta)) { + clockModel.shift(state.clock, Date.now(), delta); + broadcast(); + } + return publicState(); + }, + + setTime(h, m, s) { + const parts = [Number(h), Number(m), Number(s)]; + if (parts.every(Number.isFinite)) { + clockModel.setTimeOfDay(state.clock, Date.now(), parts[0], parts[1], parts[2]); + broadcast(); + } + return publicState(); + }, + + setStyle(style) { + if (style === 'digital' || style === 'analog') { + state.style = style; + broadcast(); + } + return publicState(); + }, + + setAlwaysOnTop(target, value) { + const key = target === 'control' ? 'control' : 'clock'; + state.alwaysOnTop[key] = Boolean(value); + const win = key === 'clock' ? clockWindow : controlWindow; + // 时钟窗口用 screen-saver 级别,普通置顶在 Windows 上会被某些全屏窗口压住 + if (isAlive(win)) win.setAlwaysOnTop(state.alwaysOnTop[key], key === 'clock' ? 'screen-saver' : 'normal'); + broadcast(); + return publicState(); + }, + + toggleClockWindow() { + if (isAlive(clockWindow)) closeClockWindow(); + else createClockWindow(); + broadcast(); + return publicState(); + }, + + closeClockWindow() { + closeClockWindow(); + return publicState(); + } +}; + +function registerIpc() { + ipcMain.handle('state:get', () => publicState()); + ipcMain.handle('rate:set', (_event, rate) => actions.setRate(rate)); + ipcMain.handle('pause:toggle', () => actions.togglePause()); + ipcMain.handle('fast-forward', (_event, deltaMs) => actions.fastForward(deltaMs)); + ipcMain.handle('time:set', (_event, payload) => actions.setTime(payload?.h, payload?.m, payload?.s)); + ipcMain.handle('style:set', (_event, style) => actions.setStyle(style)); + ipcMain.handle('always-on-top:set', (_event, payload) => actions.setAlwaysOnTop(payload?.target, payload?.value)); + ipcMain.handle('clock-window:toggle', () => actions.toggleClockWindow()); + ipcMain.handle('clock-window:close', () => actions.closeClockWindow()); + ipcMain.handle('control-window:close', () => { + if (isAlive(controlWindow)) controlWindow.close(); + return publicState(); + }); + + ipcMain.on('bounds:get-sync', (event) => { + event.returnValue = isAlive(clockWindow) ? clockWindow.getBounds() : null; + }); + + ipcMain.on('bounds:set', (_event, bounds) => { + if (bounds && typeof bounds === 'object') applyBounds(bounds); + }); +} + +app.whenReady().then(() => { + registerIpc(); + createControlWindow(); + + if (SELF_TEST) { + require('./src/selftest')({ + app, + state, + clockModel, + actions, + publicState, + applyBounds, + createClockWindow, + getClockWindow: () => clockWindow, + getControlWindow: () => controlWindow + }); + } +}); + +app.on('window-all-closed', () => { + if (!SELF_TEST) app.quit(); +}); diff --git a/package.json b/package.json new file mode 100644 index 0000000..bcf7166 --- /dev/null +++ b/package.json @@ -0,0 +1,75 @@ +{ + "name": "clocklab", + "version": "1.0.0", + "description": "ClockLab - 可调速桌面时钟(数字/表盘,支持倍率、暂停、倒转、快进)", + "author": "AskaEth", + "license": "MIT", + "private": true, + "main": "main.js", + "scripts": { + "start": "electron .", + "selftest": "electron . --selftest", + "test": "node test/clock-model.test.js && node test/resize.test.js && node test/presented-time.test.js && node test/renderer-clock.dom-test.js && node test/renderer-clock-anim.dom-test.js && node test/renderer-control.dom-test.js", + "dist:win": "electron-builder --win --x64", + "dist:linux": "electron-builder --linux --arm64" + }, + "devDependencies": { + "electron": "38.2.2", + "electron-builder": "26.15.3" + }, + "build": { + "appId": "com.askasoft.clocklab", + "productName": "ClockLab", + "directories": { + "output": "dist", + "buildResources": "build" + }, + "files": [ + "main.js", + "preload.js", + "src/**/*", + "renderer/**/*", + "!**/*.md" + ], + "win": { + "icon": "build/icon.ico", + "artifactName": "ClockLab-${version}-${arch}.${ext}", + "target": [ + { + "target": "portable", + "arch": [ + "x64" + ] + }, + { + "target": "zip", + "arch": [ + "x64" + ] + } + ] + }, + "portable": { + "artifactName": "ClockLab-${version}-portable-x64.exe" + }, + "linux": { + "icon": "build/icon.png", + "category": "Utility", + "artifactName": "ClockLab-${version}-${arch}.${ext}", + "target": [ + { + "target": "tar.gz", + "arch": [ + "arm64" + ] + }, + { + "target": "AppImage", + "arch": [ + "arm64" + ] + } + ] + } + } +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml new file mode 100644 index 0000000..86c5af2 --- /dev/null +++ b/pnpm-lock.yaml @@ -0,0 +1,2413 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + devDependencies: + electron: + specifier: 38.2.2 + version: 38.2.2(supports-color@7.1.0) + electron-builder: + specifier: 26.16.1 + version: 26.16.1(electron-builder-squirrel-windows@26.16.1)(supports-color@7.1.0) + +packages: + + '@electron/asar@3.2.1': + resolution: {integrity: sha512-hE2cQMZ5+4o7+6T2lUaVbxIzrOjZZfX7dB02xuapyYFJZEAiWTelq6J3mMoxzd0iONDvYLPVKecB5tyjIoVDVA==} + engines: {node: '>=10.12.0'} + hasBin: true + + '@electron/asar@3.4.1': + resolution: {integrity: sha512-i4/rNPRS84t0vSRa2HorerGRXWyF4vThfHesw0dmcWHp+cspK743UanA0suA5Q5y8kzY2y6YKrvbIUn69BCAiA==} + engines: {node: '>=10.12.0'} + hasBin: true + + '@electron/fuses@1.8.0': + resolution: {integrity: sha512-zx0EIq78WlY/lBb1uXlziZmDZI4ubcCXIMJ4uGjXzZW0nS19TjSPeXPAjzzTmKQlJUZm0SbmZhPKP7tuQ1SsEw==} + hasBin: true + + '@electron/get@2.0.0': + resolution: {integrity: sha512-d0XfNGayKLrYRqddW4f2Zdjaj71LfvZlCnUN8ojyNMr7WD8v6B+fqdCV8Etnwn/vUfFWFwMk/HtLEFZy01h4tQ==} + engines: {node: '>=12'} + + '@electron/get@3.0.0': + resolution: {integrity: sha512-hLv4BYFiyrNRI+U0Mm2X7RxCCdJLkDUn8GCEp9QJzbLpZRko+UaLlCjOMkj6TEtirNLPyBA7y1SeGfnpOB21aQ==} + engines: {node: '>=14'} + + '@electron/notarize@2.5.0': + resolution: {integrity: sha512-jNT8nwH1f9X5GEITXaQ8IF/KdskvIkOFfB2CvwumsveVidzpSc+mvhhTMdAGSYF3O+Nq49lJ7y+ssODRXu06+A==} + engines: {node: '>= 10.0.0'} + + '@electron/osx-sign@1.3.3': + resolution: {integrity: sha512-KZ8mhXvWv2rIEgMbWZ4y33bDHyUKMXnx4M0sTyPNK/vcB81ImdeY9Ggdqy0SWbMDgmbqyQ+phgejh6V3R2QuSg==} + engines: {node: '>=12.0.0'} + hasBin: true + + '@electron/rebuild@4.2.0': + resolution: {integrity: sha512-RKL/O+jGoXJMxrx/5771y1n0xTKmFuOYGO3gMmwypBM6rsH0kou0mswwdXA2JrhIkE4xyC7v9vGk0n6NPzgOxQ==} + engines: {node: '>=22.12.0'} + hasBin: true + + '@electron/universal@2.0.3': + resolution: {integrity: sha512-Wn9sPYIVFRFl5HmwMJkARCCf7rqK/EurkfQ/rJZ14mHP3iYTjZSIOSVonEAnhWeAXwtw7zOekGRlc6yTtZ0t+g==} + engines: {node: '>=16.4'} + + '@electron/windows-sign@1.2.2': + resolution: {integrity: sha512-dfZeox66AvdPtb2lD8OsIIQh12Tp0GNCRUDfBHIKGpbmopZto2/A8nSpYYLoedPIHpqkeblZ/k8OV0Gy7PYuyQ==} + engines: {node: '>=14.14'} + hasBin: true + + '@isaacs/fs-minipass@4.0.1': + resolution: {integrity: sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==} + engines: {node: '>=18.0.0'} + + '@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'} + + '@noble/hashes@1.4.0': + resolution: {integrity: sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==} + engines: {node: '>= 16'} + + '@noble/hashes@1.8.0': + resolution: {integrity: sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==} + engines: {node: ^14.21.3 || >=16} + + '@peculiar/asn1-schema@2.9.4': + resolution: {integrity: sha512-GjzePcT9Iw8NzeOPf73iNS9xM+TBhd/FilAfP+RQGkTMQJTVWtytN3JHJACCjf/ABNau5S7mS3g+DcuxmRgYEg==} + engines: {node: '>=14'} + + '@peculiar/json-schema@1.1.12': + resolution: {integrity: sha512-coUfuoMeIB7B8/NMekxaDzLhaYmp0HZNPEjYRm9goRou8UZIC3z21s0sL9AWoCw4EG876QyO3kYrc61WNF9B/w==} + engines: {node: '>=8.0.0'} + + '@peculiar/utils@2.0.3': + resolution: {integrity: sha512-+oL3HPFRIZ1St2K50lWCXiioIgSoxzz7R1J3uF6neO2yl1sgmpgY6XXJH4BdpoDkMWznQTeYF6oWNDZLCdQ4eQ==} + + '@peculiar/webcrypto@1.7.1': + resolution: {integrity: sha512-ODOov0sGMJMf3jPonOkgGqPknTsu+DdQ7kD++gz8aI+aFMOMHFbWAA2taqXXVTdP+OTOQR/znGvSpmkeI0WTYQ==} + engines: {node: '>=14.18.0'} + + '@sindresorhus/is@4.0.0': + resolution: {integrity: sha512-FyD2meJpDPjyNQejSjvnhpgI/azsQkA4lGbuu5BQZfjvJ9cbRZXzeWL2HceCekW4lixO9JPesIIQkSoLjeJHNQ==} + engines: {node: '>=10'} + + '@szmarczak/http-timer@4.0.6': + resolution: {integrity: sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==} + 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/fs-extra@9.0.13': + resolution: {integrity: sha512-nEnwB++1u5lVDM2UI4c1+5R+FYaKfaAzS4OococimjVm3nQw3TuzH5UNsocrcTBbhnerblyHj4A49qXbIiZdpA==} + + '@types/glob@7.2.0': + resolution: {integrity: sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==} + + '@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/minimatch@6.0.0': + resolution: {integrity: sha512-zmPitbQ8+6zNutpwgcQuLcsEpn/Cj54Kbn7L5pX0Os5kdWplB7xPgEh/g+SWOB/qmows2gpuCaPyduq8ZZRnxA==} + deprecated: This is a stub types definition. minimatch provides its own type definitions, so you do not need this installed. + + '@types/ms@2.1.0': + resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==} + + '@types/node@22.20.2': + resolution: {integrity: sha512-xlvWf4Vs9n1PEVYwP1n4vvG07M6y8WgvJ2t0vbrWTmijsIHp1cS+uJ2kMIRdY3nHZK0nCYKrPeD171+SzF4/zw==} + + '@types/node@26.5.1': + resolution: {integrity: sha512-CzNm2FezW4VR/LjG6yUdiEgLE/rAQ9Slj5gCu/C2VrdcW7I0ahNZ8DRbHT7zOZ6r3ONgd/bsQIeSaoDGrd1C6g==} + + '@types/responselike@1.0.3': + resolution: {integrity: sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==} + + '@types/yauzl@2.10.3': + resolution: {integrity: sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==} + + '@xmldom/xmldom@0.8.15': + resolution: {integrity: sha512-/5NV/vDALVFDXgLmfsy9TRCBlKwO2LNBFzpzvb9iIj+jR+eSc6DLYYvVOdivT/jm7MtU6TebYuRmzEOI7w40UA==} + engines: {node: '>=10.0.0'} + + '@xmldom/xmldom@0.9.12': + resolution: {integrity: sha512-5AXjrcMClTryPe9LgZrygpB1lj7s0S9E0+W+AHaVKAVyHanafK86iPSvG5xHVSp/jC+VH1UXu0TAEmY279xH7A==} + engines: {node: '>=14.6'} + + abbrev@4.0.0: + resolution: {integrity: sha512-a1wflyaL0tHtJSmLSOVybYhy22vRih4eduhhrkcjgrWGnRfrZtovJ2FRjxuTtkkj47O/baf0R86QU5OuYpz8fA==} + engines: {node: ^20.17.0 || >=22.9.0} + + agent-base@7.0.2: + resolution: {integrity: sha512-k2/tQ1+8Zf50dEUJWklUP80LcE/+Ph+OJ6cf2Ff2fD/c/TtCe6ofnCoNMz9UnyxOQYlaAALZtEWETzn+1JjfHg==} + engines: {node: '>= 14'} + + agent-base@7.1.0: + resolution: {integrity: sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg==} + engines: {node: '>= 14'} + + ajv@8.20.0: + resolution: {integrity: sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==} + + ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + + ansi-styles@4.0.0: + resolution: {integrity: sha512-8zjUtFJ3db/QoPXuuEMloS2AUf79/yeyttJ7Abr3hteopJu9HK8vsgGviGUMq+zyA6cZZO6gAyZoMTF6TgaEjA==} + engines: {node: '>=8'} + + ansi-styles@4.1.0: + resolution: {integrity: sha512-Qts4KCLKG+waHc9C4m07weIY8qyeixoS0h6RnbsNVD6Fw+pEZGW3vTyObL3WXpE09Mq4Oi7/lBEyLmOiLtlYWQ==} + engines: {node: '>=8'} + + app-builder-lib@26.16.1: + resolution: {integrity: sha512-FhaO6YOup01ZfQW0Z6gt3AyukJjv1gW4uFK47jTgwcHZKqyN/fSlK2LqPf9tAeZYLP2bRJLDzeOkRImsw2X4Pg==} + engines: {node: '>=14.0.0'} + peerDependencies: + dmg-builder: 26.16.1 + electron-builder-squirrel-windows: 26.16.1 + + argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + + asn1js@3.0.10: + resolution: {integrity: sha512-S2s3aOytiKdFRdulw2qPE51MzjzVOisppcVv7jVFR+Kw0kxwvFrDcYA0h7Ndqbmj0HkMIXYWaoj7fli8kgx1eg==} + engines: {node: '>=12.0.0'} + + 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'} + + aws4@1.13.2: + resolution: {integrity: sha512-lHe62zvbTB5eEABUVi/AwVh0ZKY9rMMDhmm+eeyuuUQbQ3+J+fONVQOZyj+DdrvD4BY33uYniyRJ4UJIaSKAfw==} + + balanced-match@1.0.0: + resolution: {integrity: sha512-9Y0g0Q8rmSt+H33DfKv7FOc3v+iRI+o1lbzt8jGcIosYW37IIW/2XVYq5NPdmaD5NQ59Nk26Kl/vZbwW9Fr8vg==} + + 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==} + + 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.18: + resolution: {integrity: sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==} + + brace-expansion@2.1.4: + resolution: {integrity: sha512-hGfVzPxthbf3+2yjg/RBs60cB0FhqBS/zvdV/4wn4/BmN0bNMMHPc4V/BbFieqf1TKAGGAHnY4eSjajCl0f2Xg==} + + brace-expansion@5.0.9: + resolution: {integrity: sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==} + 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==} + + builder-util-runtime@9.7.0: + resolution: {integrity: sha512-g/kR520giAFYkSXTzcmF3kqQq7wi8F6N6SzeDgZrqTBN+VHdmgWOyTdD1yD7AATDId/yXLvuP34CxW46/BwCdw==} + engines: {node: '>=12.0.0'} + + builder-util@26.16.0: + resolution: {integrity: sha512-RLyJhB7Si3YkzKR9ubQslWuXW3Vhs3CGe1i+SeixBZ0qTd1mk3XBmssvY22TlB6CS5blyko8Gu1JzpYk8UkYAg==} + engines: {node: '>=14.0.0'} + + bytestreamjs@2.0.1: + resolution: {integrity: sha512-U1Z/ob71V/bXfVABvNr/Kumf5VyeQRBEm6Txb0PQ6S7V5GpBM3w4Cbqz/xPDicR5tN0uvDifng8C+5qECeGwyQ==} + engines: {node: '>=6.0.0'} + + cacheable-lookup@5.0.4: + resolution: {integrity: sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==} + engines: {node: '>=10.6.0'} + + cacheable-request@7.0.2: + resolution: {integrity: sha512-pouW8/FmiPQbuGpkXQ9BAPv/Mo5xDGANgSNXzTzJ8DrKGuXOssM4wIQRjfanNRh3Yu5cfYPvcorqbhg2KIJtew==} + 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.0: + resolution: {integrity: sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==} + engines: {node: '>=10'} + + chalk@4.1.1: + resolution: {integrity: sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==} + engines: {node: '>=10'} + + chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + + chownr@3.0.0: + resolution: {integrity: sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==} + engines: {node: '>=18'} + + chromium-pickle-js@0.2.0: + resolution: {integrity: sha512-1R5Fho+jBq0DDydt+/vHWj5KJNJCKdARKOCwZUen84I5BreWoLqRLANH1U87eJy1tiASPtMnGqJJq0ZsLoRPOw==} + + ci-info@4.3.1: + resolution: {integrity: sha512-Wdy2Igu8OcBpI2pZePZ5oWjPC38tmDVx5WKUXKwlLYkA0ozo85sLsLvkBbBn/sZaSCMFOGZJ14fvW9t5/d7kdA==} + engines: {node: '>=8'} + + ci-info@4.4.0: + resolution: {integrity: sha512-77PSwercCZU2Fc4sX94eF8k8Pxte6JAwL4/ICZLFjJLqegs7kCuAsqqj/70NQF6TvDpgFjkubQB2FW2ZZddvQg==} + 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==} + + color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + + color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + + combined-stream@1.0.8: + resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} + engines: {node: '>= 0.8'} + + commander@5.0.0: + resolution: {integrity: sha512-JrDGPAKjMGSP1G0DUoaceEJ3DZgAfr/q6X7FVk4+U5KxUSKviYGM2k6zWkfyyBHy5rAtzgYJFa1ro2O9PtoxwQ==} + engines: {node: '>= 6'} + + commander@9.5.0: + resolution: {integrity: sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==} + engines: {node: ^12.20.0 || >=14} + + compare-version@0.1.2: + resolution: {integrity: sha512-pJDh5/4wrEnXX/VWRZvruAGHkzKdr46z11OlTPN+VrATlWWhSKewNCJ1futCO5C7eJB3nPMFZA1LeYtcFboZ2A==} + engines: {node: '>=0.10.0'} + + concat-map@0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + + config-chain@1.1.13: + resolution: {integrity: sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==} + + core-util-is@1.0.3: + resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} + + cross-dirname@0.1.0: + resolution: {integrity: sha512-+R08/oI0nl3vfPcqftZRpytksBXDzOUveBq/NBVx0sUp1axwzPQrKinNx5yd5sxPu8j1wIy8AfnVQ+5eFdha6Q==} + + cross-spawn@7.0.6: + resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} + engines: {node: '>= 8'} + + 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'} + + 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'} + + detect-node@2.1.0: + resolution: {integrity: sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==} + + dir-compare@4.2.0: + resolution: {integrity: sha512-2xMCmOoMrdQIPHdsTawECdNPwlVFB9zGcz3kuhmBO6U3oU+UQjsue0i8ayLKpgBcm+hcXPMVSGUN9d+pvJ6+VQ==} + + dmg-builder@26.16.1: + resolution: {integrity: sha512-pnI/3Qb24Uk+rMTgIUrsVUKosVgwmBUdF8Zeb8TexOSbpq8MWc7v6l+n+FrEqVkjNZwzBN+XpDS9ENgZ/rkWAw==} + + dotenv-expand@11.0.6: + resolution: {integrity: sha512-8NHi73otpWsZGBSZwwknTXS5pqMOrk9+Ssrna8xCaxkzEpU9OTf9R5ArQGVw03//Zmk9MOwLPng9WwndvpAJ5g==} + engines: {node: '>=12'} + + dotenv@16.4.5: + resolution: {integrity: sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==} + engines: {node: '>=12'} + + dunder-proto@1.0.1: + resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} + engines: {node: '>= 0.4'} + + duplexer2@0.1.4: + resolution: {integrity: sha512-asLFVfWWtJ90ZyOUHMqk7/S2w2guQKxUI2itj3d92ADHhxUSbCMGi1f1cBcJ7xM1To+pE/Khbwo1yuNbMEPKeA==} + + ejs@3.1.8: + resolution: {integrity: sha512-/sXZeMlhS0ArkfX2Aw780gJzXSMPnKjtspYZv+f3NiKLlubezAHDU5+9xz6gd3/NhG3txQCo6xlglmTS+oTGEQ==} + engines: {node: '>=0.10.0'} + hasBin: true + + electron-builder-squirrel-windows@26.16.1: + resolution: {integrity: sha512-w0y44wSaT1l6R7CAGmeHn4nHPfvzDyCAU1xJyi1w9SbPYJpYn76SmHDzqHf8Y7l91cPWTdPYBpGQtB2T5mJ08A==} + + electron-builder@26.16.1: + resolution: {integrity: sha512-LrLK65QX5PUYYODXqp23FKrV7CILTtVY7mrJckNknO9jLNSMiqFkKbSMiDRw4CjOADMPVDdWLxY4mezOZWswxg==} + engines: {node: '>=14.0.0'} + hasBin: true + + electron-publish@26.16.0: + resolution: {integrity: sha512-Vt3KzQIiw9BImvNOYtndg9Mjki+tl4+1sQiC/+G5j8khWaENOJFWodiB+sUl6yyHwtd37avehskdtPw7f8y/+Q==} + + electron-winstaller@5.4.0: + resolution: {integrity: sha512-bO3y10YikuUwUuDUQRM4KfwNkKhnpVO7IPdbsrejwN9/AABJzzTQ4GeHwyzNSrVO+tEH3/Np255a3sVZpZDjvg==} + engines: {node: '>=8.0.0'} + + electron@38.2.2: + resolution: {integrity: sha512-OXSaVNXDlonXDjMRsFNQo1j5tzTKwKXh5/m46IjAFccBcZJZMISI+EjSI07oexIuhvKM8AZLuFuihVn4YjWWrA==} + engines: {node: '>= 12.20.55'} + hasBin: true + + emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + + encodeurl@1.0.2: + resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==} + engines: {node: '>= 0.8'} + + end-of-stream@1.4.5: + resolution: {integrity: sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==} + + env-paths@2.2.0: + resolution: {integrity: sha512-6u0VYSCo/OW6IoD5WCLLy9JUGARbamfSavcNXry/eu8aHVFei6CD3Sw+VGX5alea1i9pgPHW0mbu6Xj0uBh7gA==} + 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==} + + 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'} + + 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 + + fast-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + + fast-uri@3.1.7: + resolution: {integrity: sha512-dOvZVzjdZdz7phd9v6jCbwxrBW3fK6n8Rc0CtdmM4bumzMnxywBYhuph6J819RRw/ku+rLbelwfMunktuzVVHg==} + + fd-slicer@1.1.0: + resolution: {integrity: sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==} + + fdir@6.5.0: + resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} + engines: {node: '>=12.0.0'} + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + + filelist@1.0.6: + resolution: {integrity: sha512-5giy2PkLYY1cP39p17Ech+2xlpTRL9HLspOfEgm0L6CwBXBTgsK5ou0JtzYuepxkaQ/tvhCFIJ5uXo0OrM2DxA==} + + form-data@4.0.6: + resolution: {integrity: sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==} + engines: {node: '>= 6'} + + fs-extra@10.1.0: + resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==} + engines: {node: '>=12'} + + fs-extra@11.3.1: + resolution: {integrity: sha512-eXvGGwZ5CL17ZSwHWd3bbgk7UUpF6IFHtP57NYYakPvHOs8GDgDe5KJI36jIJzDkJ6eJjuzRA8eBQb6SkKue0g==} + engines: {node: '>=14.14'} + + fs-extra@11.4.0: + resolution: {integrity: sha512-EQsFzMUJkCKGr1ePqlYADkIUmHW1s3ZXr5Yqy6wbGrfUCphpl2maM/kyOIRA2HpP3AaFQTZXD4ldjek+nccddA==} + engines: {node: '>=14.14'} + + fs-extra@7.0.1: + resolution: {integrity: sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==} + engines: {node: '>=6 <7 || >=8'} + + fs-extra@8.1.0: + resolution: {integrity: sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==} + engines: {node: '>=6 <7 || >=8'} + + fs-extra@9.0.0: + resolution: {integrity: sha512-pmEYSk3vYsG/bF651KPUXZ+hvjpgWYw/Gc7W9NFUe3ZVLczKKWIij3IKpOrQcdw4TILtibFslZ0UmR8Vvzig4g==} + engines: {node: '>=10'} + + fs-extra@9.0.1: + resolution: {integrity: sha512-h2iAoN838FqAFJY2/qVpzFXy+EBxfVE220PalAqQLDVsFOHLJrZvut5puAbCdNv6WJk+B8ihI+k0c7JK5erwqQ==} + engines: {node: '>=10'} + + fs.realpath@1.0.0: + resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} + + function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + + 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@7.2.0: + resolution: {integrity: sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==} + 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'} + + global-tunnel-ng@2.7.1: + resolution: {integrity: sha512-4s+DyciWBV0eK148wqXxcmVAbFVPqtc3sEtUE/GTQfuU80rySLcMhUmHKSHI7/LDj8q0gDYI1lIhRRB7ieRAqg==} + engines: {node: '>=0.10'} + + 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.5: + resolution: {integrity: sha512-o0Je4NvQObAuZPHLFoRSkdG2lTgtcynqymzg2Vupdx6PorhaT5MCbIyXG6d4D94kk8ZG57QeosgdiqfJWhEhlQ==} + 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'} + + 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.2.0: + resolution: {integrity: sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==} + + http-proxy-agent@7.0.0: + resolution: {integrity: sha512-+ZT+iBxVUQ1asugqnD6oWoRiS25AkjNfG085dKJGtGxkdwLQrMKU5wJr2bOOFAXzKcTuqq+7fZlTMgG3SRfIYQ==} + engines: {node: '>= 14'} + + http2-wrapper@1.0.3: + resolution: {integrity: sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==} + engines: {node: '>=10.19.0'} + + https-proxy-agent@7.0.0: + resolution: {integrity: sha512-0euwPCRyAPSgGdzD1IVN9nJYHtBhJwb6XPfbpQcYbPCwrBidX6GzxmchnaF4sfF/jPb74Ojx5g4yTg3sixlyPw==} + engines: {node: '>= 14'} + + inflight@1.0.6: + resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. + + inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + + ini@1.3.4: + resolution: {integrity: sha512-VUA7WAWNCWfm6/8f9kAb8Y6iGBWnmCfgFS5dTrv2C38LLm1KUmpY388mCVCJCsMKQomvOQ1oW8/edXdChd9ZXQ==} + deprecated: Please update to ini >=1.3.6 to avoid a prototype pollution issue + + is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + + 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==} + + isexe@3.1.5: + resolution: {integrity: sha512-6B3tLtFqtQS4ekarvLVMZ+X+VlvQekbe4taUkf/rhVO3d/h0M2rfARm/pXLcPEsjjMsFgrFgSrhQIxcSVrBz8w==} + engines: {node: '>=18'} + + isexe@4.0.0: + resolution: {integrity: sha512-FFUtZMpoZ8RqHS3XeXEmHWLA4thH+ZxCv2lOiPIn1Xc7CxrqhWzNSDzD+/chS/zbYezmiwWLdQC09JdQKmthOw==} + engines: {node: '>=20'} + + jake@10.8.5: + resolution: {integrity: sha512-sVpxYeuAhWt0OTWITwT98oyV0GsXyMlXCF+3L1SuafBVUIr/uILGRB+NqwkzhgXKvoJpDIpQvqkUALgdmQsQxw==} + engines: {node: '>=10'} + hasBin: true + + jiti@2.7.0: + resolution: {integrity: sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==} + 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@1.0.0: + resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} + + 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.0.0: + resolution: {integrity: sha512-U7ioE8AimvRVLfw4LffyOIRhL2xVgmE8T22L6i0BucSnBUyv4w+I7VN/zVZwRKHOI6ZRUcdMdWHQ8KSUvGpEog==} + + lazy-val@1.0.5: + resolution: {integrity: sha512-0/BnGCCfyUMkBpeDgWihanIAF9JmZhHBgUhEqzvf+adhNGLoP6TaiI5oF8oyb3I45P+PcnrqihSf01M0l0G5+Q==} + + lodash@4.18.1: + resolution: {integrity: sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==} + + lowercase-keys@2.0.0: + resolution: {integrity: sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==} + engines: {node: '>=8'} + + lru-cache@6.0.0: + resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} + engines: {node: '>=10'} + + 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-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@7.1.3: + resolution: {integrity: sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==} + engines: {node: '>=16 || 14 >=14.17'} + + minizlib@3.1.0: + resolution: {integrity: sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw==} + engines: {node: '>= 18'} + + mkdirp@0.5.6: + resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==} + hasBin: true + + ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + + node-abi@4.35.0: + resolution: {integrity: sha512-ymk4aIzxdPopw2giv8Fs1Ec6vybGkjmyxUwVqhkI4MCy2tVfXdkOGGWieWVjL0THgH+7a8lRdevyupoYj3Js/Q==} + engines: {node: '>=22.12.0'} + + node-api-version@0.2.1: + resolution: {integrity: sha512-2xP/IGGMmmSQpI1+O/k72jF/ykvZ89JeuKX3TLJAYPDVLUalrshrLHkeVcCCZqG/eEa635cr8IBYzgnDvM2O8Q==} + + node-gyp@12.4.0: + resolution: {integrity: sha512-OMcPNvqTCFUnNaBlmdgq+lfNqY7gTiSmNRDjY3uAXRyudeKZEZxu3CLtjMQrx4zZxCX2b/mpNqTtwuCJgXhHkw==} + engines: {node: ^20.17.0 || >=22.9.0} + hasBin: true + + node-int64@0.4.0: + resolution: {integrity: sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==} + + nopt@9.0.0: + resolution: {integrity: sha512-Zhq3a+yFKrYwSBluL4H9XP3m3y5uvQkB/09CwDruCiRmR/UJYnn9W4R48ry0uGC70aeTPKLynBtscP9efFFcPw==} + engines: {node: ^20.17.0 || >=22.9.0} + hasBin: true + + normalize-url@6.0.1: + resolution: {integrity: sha512-VU4pzAuh7Kip71XEmO9aNREYAdMHFGTVj/i+CaTImS8x0i1d3jUZkXhqluy/PRgjPLMgsLQulYY3PJ/aSbSjpQ==} + engines: {node: '>=10'} + + npm-conf@1.1.3: + resolution: {integrity: sha512-Yic4bZHJOt9RCFbRP3GgpqhScOY4HH3V2P8yBj6CeYq118Qr+BLXqT2JvpJ00mryLESpgOxf5XlFv4ZjXxLScw==} + engines: {node: '>=4'} + + 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==} + + 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'} + + 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'} + + 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==} + + picomatch@4.0.7: + resolution: {integrity: sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA==} + engines: {node: '>=12'} + + pify@3.0.0: + resolution: {integrity: sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==} + engines: {node: '>=4'} + + pkijs@3.4.0: + resolution: {integrity: sha512-emEcLuomt2j03vxD54giVB4SxTjnsqkU692xZOZXHDVoYyypEm+b3jpiTcc+Cf+myooc+/Ly0z01jqeNHVgJGw==} + engines: {node: '>=16.0.0'} + + plist@3.1.0: + resolution: {integrity: sha512-uysumyrvkUX0rX/dEVqt8gC3sTBzd4zoWfLeS29nb53imdaXVvLINYXTI2GNqzaMuvacNx4uJQ8+b3zXR0pkgQ==} + engines: {node: '>=10.4.0'} + + plist@3.1.1: + resolution: {integrity: sha512-ZIfcLJC+7E7FBFnDxm9MPmt7D+DidyQ26lewieO75AdhA2ayMtsJSES0iWzqJQbcVRSrTufQoy0DR94xHue0oA==} + engines: {node: '>=10.4.0'} + + postject@1.0.0-alpha.6: + resolution: {integrity: sha512-b9Eb8h2eVqNE8edvKdwqkrY6O7kAwmI8kcnBv1NScolYJbo59XUF0noFq+lxbC1yN20bmC0WBEbDC5H/7ASb0A==} + engines: {node: '>=14.0.0'} + hasBin: true + + proc-log@6.0.0: + resolution: {integrity: sha512-KG/XsTDN901PNfPfAMmj6N/Ywg9tM+bHK8pAz+27fS4N4Pcr+4zoYBOcGSBu6ceXYNPxkLpa4ohtfxV1XcLAfA==} + engines: {node: ^20.17.0 || >=22.9.0} + + 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-retry@2.0.1: + resolution: {integrity: sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==} + engines: {node: '>=10'} + + proper-lockfile@4.1.2: + resolution: {integrity: sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA==} + + proto-list@1.2.4: + resolution: {integrity: sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==} + + pump@3.0.4: + resolution: {integrity: sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==} + + pvtsutils@1.3.6: + resolution: {integrity: sha512-PLgQXQ6H2FWCaeRak8vvk1GW462lMxB5s3Jm673N82zI4vqtVUPuZdffdZbPDFRoU8kAhItWFtPCWiPpp4/EDg==} + + pvutils@1.2.0: + resolution: {integrity: sha512-BbubeCEyTuQjVMakvJQ/Sxbc93F2pwmbsxONT/ZRrwU7Ua38d8unYTwXpTVLAKJ4BDuH9IGztCjQcd/N/39Dvg==} + engines: {node: '>=16.0.0'} + + 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==} + + require-directory@2.1.1: + resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} + engines: {node: '>=0.10.0'} + + require-from-string@2.0.2: + resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} + engines: {node: '>=0.10.0'} + + resedit@1.7.0: + resolution: {integrity: sha512-dbsZ0gk5opWPFlKMqvxCrLCuMZUVmsW3yTPT0tT4mYwo5fjQM8c4HMN9ZJt6dRDqDV/78m9SU4rv24PN4NiYaA==} + 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==} + + retry@0.12.0: + resolution: {integrity: sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==} + engines: {node: '>= 4'} + + rimraf@2.6.2: + resolution: {integrity: sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==} + deprecated: Rimraf versions prior to v4 are no longer supported + hasBin: true + + roarr@2.15.3: + resolution: {integrity: sha512-AEjYvmAhlyxOeB9OqPUzQCo3kuAkNfuDk/HqWbZdFsqDFpapkTjiw+p4svNEoRLvuqNTxqfL+s+gtD4eDgZ+CA==} + engines: {node: '>=8.0'} + + safe-buffer@5.1.2: + resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} + + 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@5.5.0: + resolution: {integrity: sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==} + hasBin: true + + semver@6.2.0: + resolution: {integrity: sha512-jdFC1VdUGT/2Scgbimf7FSx9iJLXoqfglSF+gJeuNWVpiE37OIbc1jywR/GJyFdz3mnkz2/id0L0J/cr0izR5A==} + hasBin: true + + semver@7.7.4: + resolution: {integrity: sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==} + engines: {node: '>=10'} + 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'} + + 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==} + + simple-update-notifier@2.0.0: + resolution: {integrity: sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==} + engines: {node: '>=10'} + + source-map-support@0.5.21: + resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} + + source-map@0.6.0: + resolution: {integrity: sha512-mTozplhTX4tLKIHYji92OTZzVyZvi+Z1qRZDeBvQFI2XUB89wrRoj/xXad3c9NZ1GPJXXRvB+k41PQCPTMC+aA==} + engines: {node: '>=0.10.0'} + + sprintf-js@1.1.3: + resolution: {integrity: sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==} + + 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_decoder@1.1.1: + resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} + + strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + + sumchecker@3.0.1: + resolution: {integrity: sha512-MvjXzkz/BOfyVDkG0oFOtBxHX2u3gKbMHIF/dXblZsgD3BWOFLmHovIpZY7BykJdAjcqRCBi1WYBNdEC9yI7vg==} + engines: {node: '>= 8.0'} + + supports-color@7.1.0: + resolution: {integrity: sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==} + engines: {node: '>=8'} + + tar@7.5.22: + resolution: {integrity: sha512-MFO/QzvtAOmJbkhOaCTvbGcFN9L9b+JunIsDwaKljSOdcLMea3NJ1k9Usz/rjdfSXTq4dfzfeS7W4p4YOAAHeA==} + engines: {node: '>=18'} + + temp-file@3.4.0: + resolution: {integrity: sha512-C5tjlC/HCtVUOi3KWVokd4vHVViOmGjtLwIh4MuzPo/nMYTV/p1urt3RnMz2IWXDdKEGJH3k5+KPxtqRsUYGtg==} + + temp@0.9.4: + resolution: {integrity: sha512-yYrrsWnrXMcdsnu/7YMYAofM1ktpL5By7vZhf15CrXijWWrEYZks5AXBudalfSWJLlnen/QUJUB5aoB0kqZUGA==} + engines: {node: '>=6.0.0'} + + tiny-async-pool@1.3.0: + resolution: {integrity: sha512-01EAw5EDrcVrdgyCLgoSPvqznC0sVxDSVeiOz09FUpjh71G79VCqneOr+xvt7T1r76CF6ZZfPjHorN2+d+3mqA==} + + tinyglobby@0.2.17: + resolution: {integrity: sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==} + engines: {node: '>=12.0.0'} + + 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==} + + tslib@2.8.1: + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + + tunnel@0.0.6: + resolution: {integrity: sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==} + engines: {node: '>=0.6.11 <=0.7.0 || >=0.7.3'} + + type-fest@0.13.1: + resolution: {integrity: sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==} + engines: {node: '>=10'} + + undici-types@6.21.0: + resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} + + undici-types@8.9.0: + resolution: {integrity: sha512-KTDyRTYX8sWmKXAikPHHSyc63CRPETMctyjKFupcC6OBLXT3xsN0e9aF7m+mIXutFWpUXuedtowG7iLOzp0kQg==} + + undici@6.28.1: + resolution: {integrity: sha512-zWpdTVD54H48CIybL0rWQ3ukpb9d23wM7eH5RtfdmeP70cWHNjtfo7P4vZX+5CoDcO53J4Pu5uXp7lNfjc6DRA==} + engines: {node: '>=18.17'} + + universalify@0.1.2: + resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} + engines: {node: '>= 4.0.0'} + + universalify@1.0.0: + resolution: {integrity: sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug==} + engines: {node: '>= 10.0.0'} + + universalify@2.0.1: + resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} + engines: {node: '>= 10.0.0'} + + unzipper@0.12.5: + resolution: {integrity: sha512-tXYOi9R57Uj/2Z25SOs5RRSzq886MBQj2gY8dPL+xl/kv6s6SvByoKfAtvfVeEuhntWDgjd2o9p2lb4TVPAz0A==} + + utf8-byte-length@1.0.5: + resolution: {integrity: sha512-Xn0w3MtiQ6zoz2vFyUVruaCL53O/DwUvkEeOvj+uulMm0BkUGYWmBYVyElqZaSLhY6ZD0ulfU3aBra2aVT4xfA==} + + util-deprecate@1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + + webcrypto-core@1.9.2: + resolution: {integrity: sha512-gsXecm82UQNlTBURJGuqOWy1Ww08S3kZUcr3aOJS02Pk0xLtkfeUAVC0u0xhgdonFme80edSJUIJyuvL/7250Q==} + + which@2.0.1: + resolution: {integrity: sha512-N7GBZOTswtB9lkQBZA4+zAXrjEIWAUOB93AvzUiudRzRxhUdLURQ7D/gAIMY1gatT/LTbmbcv8SiYazy3eYB7w==} + engines: {node: '>= 8'} + hasBin: true + + which@5.0.0: + resolution: {integrity: sha512-JEdGzHwwkrbWoGOlIHqQ5gtprKGOenpDHpxE9zVR1bWbOtYRyPPHMe9FaP6x61CmNaTThSkb0DAJte5jD+DmzQ==} + engines: {node: ^18.17.0 || >=20.5.0} + hasBin: true + + which@6.0.1: + resolution: {integrity: sha512-oGLe46MIrCRqX7ytPUf66EAYvdeMIZYn3WaocqqKZAxrBpkqHfL/qvTyJ/bTk5+AqHCjXmrv3CEWgy368zhRUg==} + engines: {node: ^20.17.0 || >=22.9.0} + hasBin: true + + wrap-ansi@7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} + + 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==} + + yallist@5.0.0: + resolution: {integrity: sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==} + engines: {node: '>=18'} + + 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'} + +snapshots: + + '@electron/asar@3.2.1': + dependencies: + chromium-pickle-js: 0.2.0 + commander: 5.0.0 + glob: 7.2.0 + minimatch: 3.1.5 + optionalDependencies: + '@types/glob': 7.2.0 + + '@electron/asar@3.4.1': + dependencies: + commander: 5.0.0 + glob: 7.2.0 + minimatch: 3.1.5 + + '@electron/fuses@1.8.0': + dependencies: + chalk: 4.1.1 + fs-extra: 9.0.1 + minimist: 1.2.8 + + '@electron/get@2.0.0(supports-color@7.1.0)': + dependencies: + debug: 4.4.3(supports-color@7.1.0) + env-paths: 2.2.0 + fs-extra: 8.1.0 + got: 11.8.5 + progress: 2.0.3 + semver: 6.2.0 + sumchecker: 3.0.1(supports-color@7.1.0) + optionalDependencies: + global-agent: 3.0.0 + global-tunnel-ng: 2.7.1 + transitivePeerDependencies: + - supports-color + + '@electron/get@3.0.0(supports-color@7.1.0)': + dependencies: + debug: 4.4.3(supports-color@7.1.0) + env-paths: 2.2.0 + fs-extra: 8.1.0 + got: 11.8.5 + progress: 2.0.3 + semver: 6.2.0 + sumchecker: 3.0.1(supports-color@7.1.0) + optionalDependencies: + global-agent: 3.0.0 + transitivePeerDependencies: + - supports-color + + '@electron/notarize@2.5.0(supports-color@7.1.0)': + dependencies: + debug: 4.4.3(supports-color@7.1.0) + fs-extra: 9.0.1 + promise-retry: 2.0.1 + transitivePeerDependencies: + - supports-color + + '@electron/osx-sign@1.3.3(supports-color@7.1.0)': + dependencies: + compare-version: 0.1.2 + debug: 4.4.3(supports-color@7.1.0) + fs-extra: 10.1.0 + isbinaryfile: 4.0.10 + minimist: 1.2.8 + plist: 3.1.1 + transitivePeerDependencies: + - supports-color + + '@electron/rebuild@4.2.0(supports-color@7.1.0)': + dependencies: + '@malept/cross-spawn-promise': 2.0.0 + debug: 4.4.3(supports-color@7.1.0) + node-abi: 4.35.0 + node-api-version: 0.2.1 + node-gyp: 12.4.0 + read-binary-file-arch: 1.0.6(supports-color@7.1.0) + transitivePeerDependencies: + - supports-color + + '@electron/universal@2.0.3(supports-color@7.1.0)': + dependencies: + '@electron/asar': 3.4.1 + '@malept/cross-spawn-promise': 2.0.0 + debug: 4.4.3(supports-color@7.1.0) + dir-compare: 4.2.0 + fs-extra: 11.4.0 + minimatch: 9.0.9 + plist: 3.1.1 + transitivePeerDependencies: + - supports-color + + '@electron/windows-sign@1.2.2(supports-color@7.1.0)': + dependencies: + cross-dirname: 0.1.0 + debug: 4.4.3(supports-color@7.1.0) + fs-extra: 11.4.0 + minimist: 1.2.8 + postject: 1.0.0-alpha.6 + transitivePeerDependencies: + - supports-color + optional: true + + '@isaacs/fs-minipass@4.0.1': + dependencies: + minipass: 7.1.3 + + '@malept/cross-spawn-promise@2.0.0': + dependencies: + cross-spawn: 7.0.6 + + '@malept/flatpak-bundler@0.4.0(supports-color@7.1.0)': + dependencies: + debug: 4.4.3(supports-color@7.1.0) + fs-extra: 9.0.0 + lodash: 4.18.1 + tmp-promise: 3.0.3 + transitivePeerDependencies: + - supports-color + + '@noble/hashes@1.4.0': {} + + '@noble/hashes@1.8.0': {} + + '@peculiar/asn1-schema@2.9.4': + dependencies: + '@peculiar/utils': 2.0.3 + asn1js: 3.0.10 + tslib: 2.8.1 + + '@peculiar/json-schema@1.1.12': + dependencies: + tslib: 2.8.1 + + '@peculiar/utils@2.0.3': + dependencies: + tslib: 2.8.1 + + '@peculiar/webcrypto@1.7.1': + dependencies: + '@peculiar/asn1-schema': 2.9.4 + '@peculiar/json-schema': 1.1.12 + '@peculiar/utils': 2.0.3 + tslib: 2.8.1 + webcrypto-core: 1.9.2 + + '@sindresorhus/is@4.0.0': {} + + '@szmarczak/http-timer@4.0.6': + dependencies: + defer-to-connect: 2.0.1 + + '@types/cacheable-request@6.0.3': + dependencies: + '@types/http-cache-semantics': 4.2.0 + '@types/keyv': 3.1.4 + '@types/node': 22.20.2 + '@types/responselike': 1.0.3 + + '@types/debug@4.1.13': + dependencies: + '@types/ms': 2.1.0 + + '@types/fs-extra@9.0.13': + dependencies: + '@types/node': 26.5.1 + + '@types/glob@7.2.0': + dependencies: + '@types/minimatch': 6.0.0 + '@types/node': 26.5.1 + optional: true + + '@types/http-cache-semantics@4.2.0': {} + + '@types/keyv@3.1.4': + dependencies: + '@types/node': 22.20.2 + + '@types/minimatch@6.0.0': + dependencies: + minimatch: 3.1.5 + optional: true + + '@types/ms@2.1.0': {} + + '@types/node@22.20.2': + dependencies: + undici-types: 6.21.0 + + '@types/node@26.5.1': + dependencies: + undici-types: 8.9.0 + + '@types/responselike@1.0.3': + dependencies: + '@types/node': 22.20.2 + + '@types/yauzl@2.10.3': + dependencies: + '@types/node': 22.20.2 + optional: true + + '@xmldom/xmldom@0.8.15': {} + + '@xmldom/xmldom@0.9.12': {} + + abbrev@4.0.0: {} + + agent-base@7.0.2(supports-color@7.1.0): + dependencies: + debug: 4.4.3(supports-color@7.1.0) + transitivePeerDependencies: + - supports-color + + agent-base@7.1.0(supports-color@7.1.0): + dependencies: + debug: 4.4.3(supports-color@7.1.0) + transitivePeerDependencies: + - supports-color + + ajv@8.20.0: + dependencies: + fast-deep-equal: 3.1.3 + fast-uri: 3.1.7 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + + ansi-regex@5.0.1: {} + + ansi-styles@4.0.0: + dependencies: + color-convert: 2.0.1 + + ansi-styles@4.1.0: + dependencies: + color-convert: 2.0.1 + + app-builder-lib@26.16.1(dmg-builder@26.16.1)(electron-builder-squirrel-windows@26.16.1)(supports-color@7.1.0): + dependencies: + '@electron/asar': 3.4.1 + '@electron/fuses': 1.8.0 + '@electron/get': 3.0.0(supports-color@7.1.0) + '@electron/notarize': 2.5.0(supports-color@7.1.0) + '@electron/osx-sign': 1.3.3(supports-color@7.1.0) + '@electron/rebuild': 4.2.0(supports-color@7.1.0) + '@electron/universal': 2.0.3(supports-color@7.1.0) + '@malept/flatpak-bundler': 0.4.0(supports-color@7.1.0) + '@noble/hashes': 1.8.0 + '@peculiar/webcrypto': 1.7.1 + '@types/fs-extra': 9.0.13 + ajv: 8.20.0 + asn1js: 3.0.10 + async-exit-hook: 2.0.1 + builder-util: 26.16.0(supports-color@7.1.0) + builder-util-runtime: 9.7.0(supports-color@7.1.0) + chromium-pickle-js: 0.2.0 + ci-info: 4.3.1 + debug: 4.4.3(supports-color@7.1.0) + dmg-builder: 26.16.1(electron-builder-squirrel-windows@26.16.1)(supports-color@7.1.0) + dotenv: 16.4.5 + dotenv-expand: 11.0.6 + ejs: 3.1.8 + electron-builder-squirrel-windows: 26.16.1(dmg-builder@26.16.1)(supports-color@7.1.0) + electron-publish: 26.16.0(supports-color@7.1.0) + fs-extra: 10.1.0 + hosted-git-info: 4.1.0 + isbinaryfile: 5.0.7 + jiti: 2.7.0 + js-yaml: 4.3.2 + json5: 2.2.3 + lazy-val: 1.0.5 + minimatch: 10.2.6 + pkijs: 3.4.0 + plist: 3.1.0 + proper-lockfile: 4.1.2 + resedit: 1.7.0 + semver: 7.7.4 + tar: 7.5.22 + temp-file: 3.4.0 + tiny-async-pool: 1.3.0 + unzipper: 0.12.5 + which: 5.0.0 + transitivePeerDependencies: + - supports-color + + argparse@2.0.1: {} + + asn1js@3.0.10: + dependencies: + pvtsutils: 1.3.6 + pvutils: 1.2.0 + tslib: 2.8.1 + + async-exit-hook@2.0.1: {} + + async@3.2.6: {} + + asynckit@0.4.0: {} + + at-least-node@1.0.0: {} + + aws4@1.13.2: {} + + balanced-match@1.0.0: {} + + balanced-match@4.0.4: {} + + base64-js@1.5.1: {} + + bluebird@3.7.2: {} + + boolean@3.2.0: + optional: true + + brace-expansion@1.1.18: + dependencies: + balanced-match: 1.0.0 + concat-map: 0.0.1 + + brace-expansion@2.1.4: + dependencies: + balanced-match: 1.0.0 + + brace-expansion@5.0.9: + dependencies: + balanced-match: 4.0.4 + + buffer-crc32@0.2.13: {} + + buffer-from@1.1.2: {} + + builder-util-runtime@9.7.0(supports-color@7.1.0): + dependencies: + debug: 4.4.3(supports-color@7.1.0) + sax: 1.6.1 + transitivePeerDependencies: + - supports-color + + builder-util@26.16.0(supports-color@7.1.0): + dependencies: + '@types/debug': 4.1.13 + builder-util-runtime: 9.7.0(supports-color@7.1.0) + chalk: 4.1.2 + cross-spawn: 7.0.6 + debug: 4.4.3(supports-color@7.1.0) + fs-extra: 10.1.0 + http-proxy-agent: 7.0.0(supports-color@7.1.0) + https-proxy-agent: 7.0.0(supports-color@7.1.0) + js-yaml: 4.3.2 + sanitize-filename: 1.6.4 + source-map-support: 0.5.21 + stat-mode: 1.0.0 + temp-file: 3.4.0 + tiny-async-pool: 1.3.0 + transitivePeerDependencies: + - supports-color + + bytestreamjs@2.0.1: {} + + cacheable-lookup@5.0.4: {} + + cacheable-request@7.0.2: + dependencies: + clone-response: 1.0.3 + get-stream: 5.2.0 + http-cache-semantics: 4.2.0 + keyv: 4.0.0 + lowercase-keys: 2.0.0 + normalize-url: 6.0.1 + 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.0: + dependencies: + ansi-styles: 4.1.0 + supports-color: 7.1.0 + + chalk@4.1.1: + dependencies: + ansi-styles: 4.1.0 + supports-color: 7.1.0 + + chalk@4.1.2: + dependencies: + ansi-styles: 4.1.0 + supports-color: 7.1.0 + + chownr@3.0.0: {} + + chromium-pickle-js@0.2.0: {} + + ci-info@4.3.1: {} + + ci-info@4.4.0: {} + + 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 + + color-convert@2.0.1: + dependencies: + color-name: 1.1.4 + + color-name@1.1.4: {} + + combined-stream@1.0.8: + dependencies: + delayed-stream: 1.0.0 + + commander@5.0.0: {} + + commander@9.5.0: + optional: true + + compare-version@0.1.2: {} + + concat-map@0.0.1: {} + + config-chain@1.1.13: + dependencies: + ini: 1.3.4 + proto-list: 1.2.4 + optional: true + + core-util-is@1.0.3: {} + + cross-dirname@0.1.0: + optional: true + + cross-spawn@7.0.6: + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.1 + + debug@4.4.3(supports-color@7.1.0): + dependencies: + ms: 2.1.3 + optionalDependencies: + supports-color: 7.1.0 + + decompress-response@6.0.0: + dependencies: + mimic-response: 3.1.0 + + 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: {} + + detect-node@2.1.0: + optional: true + + dir-compare@4.2.0: + dependencies: + minimatch: 3.1.5 + p-limit: 3.1.0 + + dmg-builder@26.16.1(electron-builder-squirrel-windows@26.16.1)(supports-color@7.1.0): + dependencies: + app-builder-lib: 26.16.1(dmg-builder@26.16.1)(electron-builder-squirrel-windows@26.16.1)(supports-color@7.1.0) + builder-util: 26.16.0(supports-color@7.1.0) + fs-extra: 10.1.0 + js-yaml: 4.3.2 + transitivePeerDependencies: + - electron-builder-squirrel-windows + - supports-color + + dotenv-expand@11.0.6: + dependencies: + dotenv: 16.4.5 + + dotenv@16.4.5: {} + + dunder-proto@1.0.1: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-errors: 1.3.0 + gopd: 1.2.0 + + duplexer2@0.1.4: + dependencies: + readable-stream: 2.3.8 + + ejs@3.1.8: + dependencies: + jake: 10.8.5 + + electron-builder-squirrel-windows@26.16.1(dmg-builder@26.16.1)(supports-color@7.1.0): + dependencies: + app-builder-lib: 26.16.1(dmg-builder@26.16.1)(electron-builder-squirrel-windows@26.16.1)(supports-color@7.1.0) + builder-util: 26.16.0(supports-color@7.1.0) + electron-winstaller: 5.4.0(supports-color@7.1.0) + transitivePeerDependencies: + - dmg-builder + - supports-color + + electron-builder@26.16.1(electron-builder-squirrel-windows@26.16.1)(supports-color@7.1.0): + dependencies: + app-builder-lib: 26.16.1(dmg-builder@26.16.1)(electron-builder-squirrel-windows@26.16.1)(supports-color@7.1.0) + builder-util: 26.16.0(supports-color@7.1.0) + builder-util-runtime: 9.7.0(supports-color@7.1.0) + chalk: 4.1.2 + ci-info: 4.4.0 + dmg-builder: 26.16.1(electron-builder-squirrel-windows@26.16.1)(supports-color@7.1.0) + fs-extra: 10.1.0 + lazy-val: 1.0.5 + simple-update-notifier: 2.0.0 + yargs: 17.7.3 + transitivePeerDependencies: + - electron-builder-squirrel-windows + - supports-color + + electron-publish@26.16.0(supports-color@7.1.0): + dependencies: + '@types/fs-extra': 9.0.13 + aws4: 1.13.2 + builder-util: 26.16.0(supports-color@7.1.0) + builder-util-runtime: 9.7.0(supports-color@7.1.0) + chalk: 4.1.2 + form-data: 4.0.6 + fs-extra: 10.1.0 + lazy-val: 1.0.5 + mime: 2.6.0 + transitivePeerDependencies: + - supports-color + + electron-winstaller@5.4.0(supports-color@7.1.0): + dependencies: + '@electron/asar': 3.2.1 + debug: 4.4.3(supports-color@7.1.0) + fs-extra: 7.0.1 + lodash: 4.18.1 + temp: 0.9.4 + optionalDependencies: + '@electron/windows-sign': 1.2.2(supports-color@7.1.0) + transitivePeerDependencies: + - supports-color + + electron@38.2.2(supports-color@7.1.0): + dependencies: + '@electron/get': 2.0.0(supports-color@7.1.0) + '@types/node': 22.20.2 + extract-zip: 2.0.1(supports-color@7.1.0) + transitivePeerDependencies: + - supports-color + + emoji-regex@8.0.0: {} + + encodeurl@1.0.2: + optional: true + + end-of-stream@1.4.5: + dependencies: + once: 1.4.0 + + env-paths@2.2.0: {} + + 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 + + escalade@3.2.0: {} + + escape-string-regexp@4.0.0: + optional: true + + exponential-backoff@3.1.3: {} + + extract-zip@2.0.1(supports-color@7.1.0): + dependencies: + debug: 4.4.3(supports-color@7.1.0) + get-stream: 5.2.0 + yauzl: 2.10.0 + optionalDependencies: + '@types/yauzl': 2.10.3 + transitivePeerDependencies: + - supports-color + + fast-deep-equal@3.1.3: {} + + fast-uri@3.1.7: {} + + fd-slicer@1.1.0: + dependencies: + pend: 1.2.0 + + fdir@6.5.0(picomatch@4.0.7): + optionalDependencies: + picomatch: 4.0.7 + + filelist@1.0.6: + dependencies: + minimatch: 5.1.9 + + 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-extra@10.1.0: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 6.2.1 + universalify: 2.0.1 + + fs-extra@11.3.1: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 6.2.1 + universalify: 2.0.1 + + fs-extra@11.4.0: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 6.2.1 + universalify: 2.0.1 + + fs-extra@7.0.1: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 4.0.0 + universalify: 0.1.2 + + fs-extra@8.1.0: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 4.0.0 + universalify: 0.1.2 + + fs-extra@9.0.0: + dependencies: + at-least-node: 1.0.0 + graceful-fs: 4.2.11 + jsonfile: 6.2.1 + universalify: 1.0.0 + + fs-extra@9.0.1: + dependencies: + at-least-node: 1.0.0 + graceful-fs: 4.2.11 + jsonfile: 6.2.1 + universalify: 1.0.0 + + fs.realpath@1.0.0: {} + + function-bind@1.1.2: {} + + 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@7.2.0: + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.1.5 + once: 1.4.0 + path-is-absolute: 1.0.1 + + global-agent@3.0.0: + dependencies: + boolean: 3.2.0 + es6-error: 4.1.1 + matcher: 3.0.0 + roarr: 2.15.3 + semver: 7.8.5 + serialize-error: 7.0.1 + optional: true + + global-tunnel-ng@2.7.1: + dependencies: + encodeurl: 1.0.2 + lodash: 4.18.1 + npm-conf: 1.1.3 + tunnel: 0.0.6 + 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.5: + dependencies: + '@sindresorhus/is': 4.0.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.2 + 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 + + 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.2.0: {} + + http-proxy-agent@7.0.0(supports-color@7.1.0): + dependencies: + agent-base: 7.1.0(supports-color@7.1.0) + debug: 4.4.3(supports-color@7.1.0) + transitivePeerDependencies: + - supports-color + + http2-wrapper@1.0.3: + dependencies: + quick-lru: 5.1.1 + resolve-alpn: 1.2.1 + + https-proxy-agent@7.0.0(supports-color@7.1.0): + dependencies: + agent-base: 7.0.2(supports-color@7.1.0) + debug: 4.4.3(supports-color@7.1.0) + transitivePeerDependencies: + - supports-color + + inflight@1.0.6: + dependencies: + once: 1.4.0 + wrappy: 1.0.2 + + inherits@2.0.4: {} + + ini@1.3.4: + optional: true + + is-fullwidth-code-point@3.0.0: {} + + isarray@1.0.0: {} + + isbinaryfile@4.0.10: {} + + isbinaryfile@5.0.7: {} + + isexe@2.0.0: {} + + isexe@3.1.5: {} + + isexe@4.0.0: {} + + jake@10.8.5: + dependencies: + async: 3.2.6 + chalk: 4.1.0 + filelist: 1.0.6 + minimatch: 3.1.5 + + jiti@2.7.0: {} + + js-yaml@4.3.2: + dependencies: + argparse: 2.0.1 + + json-buffer@3.0.1: {} + + json-schema-traverse@1.0.0: {} + + 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.0.0: + dependencies: + json-buffer: 3.0.1 + + lazy-val@1.0.5: {} + + lodash@4.18.1: {} + + lowercase-keys@2.0.0: {} + + lru-cache@6.0.0: + dependencies: + yallist: 4.0.0 + + 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-response@1.0.1: {} + + mimic-response@3.1.0: {} + + minimatch@10.2.6: + dependencies: + brace-expansion: 5.0.9 + + minimatch@3.1.5: + dependencies: + brace-expansion: 1.1.18 + + minimatch@5.1.9: + dependencies: + brace-expansion: 2.1.4 + + minimatch@9.0.9: + dependencies: + brace-expansion: 2.1.4 + + minimist@1.2.8: {} + + minipass@7.1.3: {} + + minizlib@3.1.0: + dependencies: + minipass: 7.1.3 + + mkdirp@0.5.6: + dependencies: + minimist: 1.2.8 + + ms@2.1.3: {} + + node-abi@4.35.0: + dependencies: + semver: 7.7.4 + + node-api-version@0.2.1: + dependencies: + semver: 7.7.4 + + node-gyp@12.4.0: + dependencies: + env-paths: 2.2.0 + exponential-backoff: 3.1.3 + graceful-fs: 4.2.11 + nopt: 9.0.0 + proc-log: 6.0.0 + semver: 7.7.4 + tar: 7.5.22 + tinyglobby: 0.2.17 + undici: 6.28.1 + which: 6.0.1 + + node-int64@0.4.0: {} + + nopt@9.0.0: + dependencies: + abbrev: 4.0.0 + + normalize-url@6.0.1: {} + + npm-conf@1.1.3: + dependencies: + config-chain: 1.1.13 + pify: 3.0.0 + optional: true + + object-keys@1.1.1: + optional: true + + once@1.4.0: + dependencies: + wrappy: 1.0.2 + + p-cancelable@2.1.1: {} + + p-limit@3.1.0: + dependencies: + yocto-queue: 0.1.0 + + path-is-absolute@1.0.1: {} + + path-key@3.1.1: {} + + pe-library@0.4.1: {} + + pend@1.2.0: {} + + picomatch@4.0.7: {} + + pify@3.0.0: + optional: true + + pkijs@3.4.0: + dependencies: + '@noble/hashes': 1.4.0 + asn1js: 3.0.10 + bytestreamjs: 2.0.1 + pvtsutils: 1.3.6 + pvutils: 1.2.0 + tslib: 2.8.1 + + plist@3.1.0: + dependencies: + '@xmldom/xmldom': 0.8.15 + base64-js: 1.5.1 + xmlbuilder: 15.1.1 + + plist@3.1.1: + dependencies: + '@xmldom/xmldom': 0.9.12 + base64-js: 1.5.1 + xmlbuilder: 15.1.1 + + postject@1.0.0-alpha.6: + dependencies: + commander: 9.5.0 + optional: true + + proc-log@6.0.0: {} + + process-nextick-args@2.0.1: {} + + progress@2.0.3: {} + + promise-retry@2.0.1: + dependencies: + err-code: 2.0.3 + retry: 0.12.0 + + proper-lockfile@4.1.2: + dependencies: + graceful-fs: 4.2.11 + retry: 0.12.0 + signal-exit: 3.0.7 + + proto-list@1.2.4: + optional: true + + pump@3.0.4: + dependencies: + end-of-stream: 1.4.5 + once: 1.4.0 + + pvtsutils@1.3.6: + dependencies: + tslib: 2.8.1 + + pvutils@1.2.0: {} + + quick-lru@5.1.1: {} + + read-binary-file-arch@1.0.6(supports-color@7.1.0): + dependencies: + debug: 4.4.3(supports-color@7.1.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 + + require-directory@2.1.1: {} + + require-from-string@2.0.2: {} + + resedit@1.7.0: + dependencies: + pe-library: 0.4.1 + + resolve-alpn@1.2.1: {} + + responselike@2.0.1: + dependencies: + lowercase-keys: 2.0.0 + + retry@0.12.0: {} + + rimraf@2.6.2: + dependencies: + glob: 7.2.0 + + roarr@2.15.3: + 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 + + safe-buffer@5.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@5.5.0: {} + + semver@6.2.0: {} + + semver@7.7.4: {} + + semver@7.8.5: {} + + serialize-error@7.0.1: + dependencies: + type-fest: 0.13.1 + optional: true + + shebang-command@2.0.0: + dependencies: + shebang-regex: 3.0.0 + + shebang-regex@3.0.0: {} + + signal-exit@3.0.7: {} + + simple-update-notifier@2.0.0: + dependencies: + semver: 7.8.5 + + source-map-support@0.5.21: + dependencies: + buffer-from: 1.1.2 + source-map: 0.6.0 + + source-map@0.6.0: {} + + sprintf-js@1.1.3: + optional: true + + 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_decoder@1.1.1: + dependencies: + safe-buffer: 5.1.2 + + strip-ansi@6.0.1: + dependencies: + ansi-regex: 5.0.1 + + sumchecker@3.0.1(supports-color@7.1.0): + dependencies: + debug: 4.4.3(supports-color@7.1.0) + transitivePeerDependencies: + - supports-color + + supports-color@7.1.0: + dependencies: + has-flag: 4.0.0 + + tar@7.5.22: + dependencies: + '@isaacs/fs-minipass': 4.0.1 + chownr: 3.0.0 + minipass: 7.1.3 + minizlib: 3.1.0 + yallist: 5.0.0 + + temp-file@3.4.0: + dependencies: + async-exit-hook: 2.0.1 + fs-extra: 10.1.0 + + temp@0.9.4: + dependencies: + mkdirp: 0.5.6 + rimraf: 2.6.2 + + tiny-async-pool@1.3.0: + dependencies: + semver: 5.5.0 + + tinyglobby@0.2.17: + dependencies: + fdir: 6.5.0(picomatch@4.0.7) + picomatch: 4.0.7 + + 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 + + tslib@2.8.1: {} + + tunnel@0.0.6: + optional: true + + type-fest@0.13.1: + optional: true + + undici-types@6.21.0: {} + + undici-types@8.9.0: {} + + undici@6.28.1: {} + + universalify@0.1.2: {} + + universalify@1.0.0: {} + + universalify@2.0.1: {} + + unzipper@0.12.5: + dependencies: + bluebird: 3.7.2 + duplexer2: 0.1.4 + fs-extra: 11.3.1 + graceful-fs: 4.2.11 + node-int64: 0.4.0 + + utf8-byte-length@1.0.5: {} + + util-deprecate@1.0.2: {} + + webcrypto-core@1.9.2: + dependencies: + '@peculiar/asn1-schema': 2.9.4 + '@peculiar/json-schema': 1.1.12 + '@peculiar/utils': 2.0.3 + asn1js: 3.0.10 + tslib: 2.8.1 + + which@2.0.1: + dependencies: + isexe: 2.0.0 + + which@5.0.0: + dependencies: + isexe: 3.1.5 + + which@6.0.1: + dependencies: + isexe: 4.0.0 + + wrap-ansi@7.0.0: + dependencies: + ansi-styles: 4.0.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + + wrappy@1.0.2: {} + + xmlbuilder@15.1.1: {} + + y18n@5.0.8: {} + + yallist@4.0.0: {} + + yallist@5.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: {} diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml new file mode 100644 index 0000000..7fb1dab --- /dev/null +++ b/pnpm-workspace.yaml @@ -0,0 +1,6 @@ +# pnpm 11 的 strictDepBuilds 默认为 true:只要有依赖的构建脚本被跳过,pnpm install 就直接以退出码 1 结束。 +# electron 的 postinstall 正是「下载运行时」那一步,必须放行,否则构建机上装依赖会中途失败。 +# (pnpm 11 起设置从 package.json 的 pnpm 字段和 .npmrc 搬到这里,且旧键 onlyBuiltDependencies 已不再生效。) +allowBuilds: + electron: true + electron-winstaller: true diff --git a/preload.js b/preload.js new file mode 100644 index 0000000..6af6f05 --- /dev/null +++ b/preload.js @@ -0,0 +1,21 @@ +'use strict'; + +const { contextBridge, ipcRenderer } = require('electron'); + +// 只把需要的动作暴露出去,渲染进程拿不到 ipcRenderer 本体,也不开 nodeIntegration +contextBridge.exposeInMainWorld('clockApi', { + getState: () => ipcRenderer.invoke('state:get'), + onState: (cb) => ipcRenderer.on('state', (_event, snapshot) => cb(snapshot)), + setRate: (rate) => ipcRenderer.invoke('rate:set', rate), + togglePause: () => ipcRenderer.invoke('pause:toggle'), + fastForward: (deltaMs) => ipcRenderer.invoke('fast-forward', deltaMs), + setTime: (h, m, s) => ipcRenderer.invoke('time:set', { h, m, s }), + setStyle: (style) => ipcRenderer.invoke('style:set', style), + setAlwaysOnTop: (target, value) => ipcRenderer.invoke('always-on-top:set', { target, value }), + toggleClockWindow: () => ipcRenderer.invoke('clock-window:toggle'), + closeClockWindow: () => ipcRenderer.invoke('clock-window:close'), + closeControlWindow: () => ipcRenderer.invoke('control-window:close'), + // 调整大小要在 mousedown 那一刻拿到精确的窗口位置,异步往返会让第一条 mousemove 用错基准 + getBoundsSync: () => ipcRenderer.sendSync('bounds:get-sync'), + setBounds: (bounds) => ipcRenderer.send('bounds:set', bounds) +}); diff --git a/renderer/clock.css b/renderer/clock.css new file mode 100644 index 0000000..88eba14 --- /dev/null +++ b/renderer/clock.css @@ -0,0 +1,214 @@ +:root { + --bg: #05070c; + --fg: #f2f6ff; + --accent: #4fd1c5; + --muted: #7d8aa5; + --handle: 10px; + --corner: 18px; +} + +* { + box-sizing: border-box; +} + +html, +body { + margin: 0; + height: 100%; + overflow: hidden; + background: var(--bg); + color: var(--fg); + user-select: none; + cursor: default; + font-family: 'Segoe UI', 'Microsoft YaHei', sans-serif; +} + +/* 拖动区:无边框窗口靠它实现「按住任意空白处移动窗口」 */ +.stage { + position: absolute; + inset: 0; + display: flex; + align-items: center; + justify-content: center; + background: radial-gradient(120% 140% at 50% 0%, #131a29 0%, var(--bg) 70%); + -webkit-app-region: drag; +} + +.view { + width: 100%; + height: 100%; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; +} + +.view[hidden] { + display: none; +} + +.digital-time { + font-family: Consolas, 'Cascadia Mono', 'DejaVu Sans Mono', monospace; + font-variant-numeric: tabular-nums; + font-weight: 600; + line-height: 1; + letter-spacing: 0.02em; + color: var(--fg); + text-shadow: 0 0 28px rgba(79, 209, 197, 0.35); + white-space: nowrap; +} + +.digital-date { + margin-top: 0.7em; + /* 用 vmin 跟着窗口缩放,投到大屏时日期才不会小得看不见 */ + font-size: clamp(13px, 5.5vmin, 64px); + letter-spacing: 0.18em; + color: var(--muted); + white-space: nowrap; +} + +.analog-view { + padding: 10px; +} + +.dial { + height: 100%; + width: 100%; + max-width: 100%; + max-height: 100%; +} + +.dial-face { + fill: #0b1020; + stroke: #26314a; + stroke-width: 2; +} + +.tick { + stroke: #46577a; + stroke-width: 2; + stroke-linecap: round; +} + +.tick-major { + stroke: #8fa4cc; + stroke-width: 4; +} + +.numeral { + fill: #8fa4cc; + font-family: Consolas, 'DejaVu Sans Mono', monospace; + font-size: 18px; + text-anchor: middle; + dominant-baseline: central; +} + +.hand { + stroke-linecap: round; +} + +.hand-hour { + stroke: #e6ecff; + stroke-width: 7; +} + +.hand-minute { + stroke: #c3cfe8; + stroke-width: 4.5; +} + +.hand-second { + stroke: var(--accent); + stroke-width: 2; +} + +.hand-cap { + fill: var(--accent); +} + +.badge { + position: absolute; + top: 10px; + left: 12px; + padding: 3px 10px; + border-radius: 999px; + font-size: 13px; + letter-spacing: 0.06em; + color: #0b1020; + background: var(--accent); + opacity: 0.92; + -webkit-app-region: no-drag; +} + +.badge[hidden] { + display: none; +} + +.close-btn { + position: absolute; + top: 8px; + right: 8px; + width: 26px; + height: 26px; + line-height: 1; + font-size: 18px; + border: 0; + border-radius: 8px; + color: #9fb0cc; + background: rgba(255, 255, 255, 0.06); + cursor: pointer; + opacity: 0; + transition: opacity 0.15s ease; + /* 关键:按钮必须退出拖动区,否则在无边框窗口里点不动 */ + -webkit-app-region: no-drag; +} + +.stage:hover .close-btn { + opacity: 1; +} + +.close-btn:hover { + color: #fff; + background: #e0555a; +} + +/* 自定义改大小的边缘热区:放在 stage 之外,天然不属于拖动区,鼠标事件能正常到达 */ +.rz { + position: fixed; + z-index: 20; + -webkit-app-region: no-drag; +} + +.rz-n, +.rz-s { + left: var(--corner); + right: var(--corner); + height: var(--handle); + cursor: ns-resize; +} + +.rz-w, +.rz-e { + top: var(--corner); + bottom: var(--corner); + width: var(--handle); + cursor: ew-resize; +} + +.rz-n { top: 0; } +.rz-s { bottom: 0; } +.rz-w { left: 0; } +.rz-e { right: 0; } + +.rz-nw, +.rz-ne, +.rz-sw, +.rz-se { + width: var(--corner); + height: var(--corner); +} + +.rz-nw { top: 0; left: 0; cursor: nwse-resize; } +.rz-se { bottom: 0; right: 0; cursor: nwse-resize; } +.rz-ne { top: 0; right: 0; cursor: nesw-resize; } +.rz-sw { bottom: 0; left: 0; cursor: nesw-resize; } diff --git a/renderer/clock.html b/renderer/clock.html new file mode 100644 index 0000000..1bdd0b0 --- /dev/null +++ b/renderer/clock.html @@ -0,0 +1,47 @@ + + +
+ + +显示时间 = 基准时间 + 真实经过时间 × 倍率
+关掉控制窗口即退出整个程序,时钟窗口一并关闭。
+切换立即生效,不需要重开时钟窗口。
+「暂停 / 继续」按钮等价于倍率 0 / 回到暂停前的那个倍率。倍率为负时时钟会一直往回走,不是卡住。
+