From 9d76926b8a57eba2a8d2207b8270e95c0d846d59 Mon Sep 17 00:00:00 2001 From: sivdead <923396178@qq.com> Date: Thu, 11 Sep 2025 10:05:50 +0800 Subject: [PATCH 01/26] =?UTF-8?q?feat(frontend/vditor):=20=E5=AE=9E?= =?UTF-8?q?=E7=8E=B0=E5=9F=BA=E4=BA=8E=20FFmpeg.wasm=20=E7=9A=84=E8=A7=86?= =?UTF-8?q?=E9=A2=91=E5=8E=8B=E7=BC=A9=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 添加视频压缩相关配置和工具函数 - 实现 FFmpeg.wasm 初始化和视频压缩功能 - 优化文件上传流程,支持视频文件压缩 --- frontend_nuxt/.env.example | 5 + frontend_nuxt/config/uploadConfig.js | 137 ++++++++ frontend_nuxt/nuxt.config.ts | 15 +- frontend_nuxt/package-lock.json | 53 ++- frontend_nuxt/package.json | 3 + frontend_nuxt/plugins/ffmpeg.client.ts | 37 +++ frontend_nuxt/utils/ffmpegVideoCompressor.js | 327 +++++++++++++++++++ frontend_nuxt/utils/vditor.js | 82 ++++- frontend_nuxt/utils/videoCompressor.js | 79 +++++ 9 files changed, 723 insertions(+), 15 deletions(-) create mode 100644 frontend_nuxt/config/uploadConfig.js create mode 100644 frontend_nuxt/plugins/ffmpeg.client.ts create mode 100644 frontend_nuxt/utils/ffmpegVideoCompressor.js create mode 100644 frontend_nuxt/utils/videoCompressor.js diff --git a/frontend_nuxt/.env.example b/frontend_nuxt/.env.example index dadb36387..2990fd052 100644 --- a/frontend_nuxt/.env.example +++ b/frontend_nuxt/.env.example @@ -17,3 +17,8 @@ NUXT_PUBLIC_GITHUB_CLIENT_ID=Ov23liVkO1NPAX5JyWxJ NUXT_PUBLIC_DISCORD_CLIENT_ID=1394985417044000779 NUXT_PUBLIC_TWITTER_CLIENT_ID=ZTRTU05KSk9KTTJrTTdrVC1tc1E6MTpjaQ NUXT_PUBLIC_TELEGRAM_BOT_ID=8450237135 + +# 视频压缩配置 - FFmpeg.wasm 专用 +# 支持 Chrome 60+ 和 Safari 11.1+ +NUXT_PUBLIC_VIDEO_MAX_SIZE=52428800 # 50MB (字节) +NUXT_PUBLIC_VIDEO_TARGET_SIZE=20971520 # 20MB (字节) \ No newline at end of file diff --git a/frontend_nuxt/config/uploadConfig.js b/frontend_nuxt/config/uploadConfig.js new file mode 100644 index 000000000..e98f13d70 --- /dev/null +++ b/frontend_nuxt/config/uploadConfig.js @@ -0,0 +1,137 @@ +/** + * 文件上传配置 - 简化版 + * 专注于 FFmpeg.wasm 视频压缩,支持 Chrome/Safari + */ + +// 声明全局变量以避免 TypeScript 错误 +/* global useRuntimeConfig */ + +// 简化的环境变量读取功能 +function getEnvNumber(key, defaultValue) { + if (typeof window !== 'undefined') { + // 客户端:尝试从 Nuxt 环境获取 + try { + // 使用 globalThis 避免直接引用未定义的变量 + const nuxtApp = globalThis.$nuxt || globalThis.nuxtApp + if (nuxtApp && nuxtApp.$config) { + const value = nuxtApp.$config.public?.[key.replace('NUXT_PUBLIC_', '').toLowerCase()] + return value ? Number(value) : defaultValue + } + return defaultValue + } catch { + return defaultValue + } + } + // 服务端:从 process.env 获取 + return process.env[key] ? Number(process.env[key]) : defaultValue +} + +function getEnvBoolean(key, defaultValue) { + if (typeof window !== 'undefined') { + try { + // 使用 globalThis 避免直接引用未定义的变量 + const nuxtApp = globalThis.$nuxt || globalThis.nuxtApp + if (nuxtApp && nuxtApp.$config) { + const value = nuxtApp.$config.public?.[key.replace('NUXT_PUBLIC_', '').toLowerCase()] + return value === 'true' || value === true + } + return defaultValue + } catch { + return defaultValue + } + } + const envValue = process.env[key] + return envValue ? envValue === 'true' : defaultValue +} + +export const UPLOAD_CONFIG = { + // 视频文件配置 - 专为 FFmpeg.wasm 优化 + VIDEO: { + // 文件大小限制 (字节) + MAX_SIZE: getEnvNumber('NUXT_PUBLIC_VIDEO_MAX_SIZE', 20 * 1024 * 1024), // 5MB + TARGET_SIZE: getEnvNumber('NUXT_PUBLIC_VIDEO_TARGET_SIZE', 5 * 1024 * 1024), // 5MB + + // 支持的输入格式 (FFmpeg.wasm 支持更多格式) + SUPPORTED_FORMATS: ['mp4', 'webm', 'avi', 'mov', 'wmv', 'flv', 'mkv', 'm4v', 'ogv'], + + // 输出格式 - MP4 (兼容性最好) + OUTPUT_FORMAT: 'mp4', + OUTPUT_CODEC: 'h264', + }, + + // 图片文件配置 + IMAGE: { + MAX_SIZE: 5 * 1024 * 1024, // 5MB + TARGET_SIZE: 5 * 1024 * 1024, // 5MB + SUPPORTED_FORMATS: ['jpg', 'jpeg', 'png', 'gif', 'webp', 'svg', 'bmp'], + }, + + // 音频文件配置 + AUDIO: { + MAX_SIZE: 5 * 1024 * 1024, // 5MB + TARGET_SIZE: 5 * 1024 * 1024, // 5MB + SUPPORTED_FORMATS: ['mp3', 'wav', 'ogg', 'aac', 'm4a'], + }, + + // 通用文件配置 + GENERAL: { + MAX_SIZE: 100 * 1024 * 1024, // 100MB + CHUNK_SIZE: 5 * 1024 * 1024, // 5MB 分片大小 + }, + + // 用户体验配置 + UI: { + SUCCESS_DURATION: 2000, + ERROR_DURATION: 3000, + WARNING_DURATION: 3000, + }, +} + +/** + * 获取文件类型配置 + */ +export function getFileTypeConfig(filename) { + const ext = filename.split('.').pop().toLowerCase() + + if (UPLOAD_CONFIG.VIDEO.SUPPORTED_FORMATS.includes(ext)) { + return { type: 'video', config: UPLOAD_CONFIG.VIDEO } + } + + if (UPLOAD_CONFIG.IMAGE.SUPPORTED_FORMATS.includes(ext)) { + return { type: 'image', config: UPLOAD_CONFIG.IMAGE } + } + + if (UPLOAD_CONFIG.AUDIO.SUPPORTED_FORMATS.includes(ext)) { + return { type: 'audio', config: UPLOAD_CONFIG.AUDIO } + } + + return { type: 'general', config: UPLOAD_CONFIG.GENERAL } +} + +/** + * 格式化文件大小 + */ +export function formatFileSize(bytes) { + if (bytes === 0) return '0 B' + const k = 1024 + const sizes = ['B', 'KB', 'MB', 'GB'] + const i = Math.floor(Math.log(bytes) / Math.log(k)) + return parseFloat((bytes / Math.pow(k, i)).toFixed(1)) + ' ' + sizes[i] +} + +/** + * 计算压缩节省的费用 (示例函数) + */ +export function calculateSavings(originalSize, compressedSize, costPerMB = 0.01) { + const originalMB = originalSize / (1024 * 1024) + const compressedMB = compressedSize / (1024 * 1024) + const savedMB = originalMB - compressedMB + const savedCost = savedMB * costPerMB + + return { + savedMB: savedMB.toFixed(2), + savedCost: savedCost.toFixed(4), + originalCost: (originalMB * costPerMB).toFixed(4), + compressedCost: (compressedMB * costPerMB).toFixed(4), + } +} diff --git a/frontend_nuxt/nuxt.config.ts b/frontend_nuxt/nuxt.config.ts index bc33291b0..dad43963c 100644 --- a/frontend_nuxt/nuxt.config.ts +++ b/frontend_nuxt/nuxt.config.ts @@ -1,9 +1,21 @@ import { defineNuxtConfig } from 'nuxt/config' +import { createRequire } from 'node:module' +const require = createRequire(import.meta.url) +const appPkg = require('./package.json') as { + dependencies?: Record + devDependencies?: Record +} +const ffmpegVersion = ( + process.env.NUXT_PUBLIC_FFMPEG_VERSION || + appPkg.dependencies?.['@ffmpeg/ffmpeg'] || + appPkg.devDependencies?.['@ffmpeg/ffmpeg'] || + '0.12.15' +).replace(/^[^\d]*/, '') export default defineNuxtConfig({ devServer: { host: '0.0.0.0', - port: 3000 + port: 3000, }, ssr: true, modules: ['@nuxt/image'], @@ -17,6 +29,7 @@ export default defineNuxtConfig({ discordClientId: process.env.NUXT_PUBLIC_DISCORD_CLIENT_ID || '', twitterClientId: process.env.NUXT_PUBLIC_TWITTER_CLIENT_ID || '', telegramBotId: process.env.NUXT_PUBLIC_TELEGRAM_BOT_ID || '', + ffmpegVersion, }, }, css: [ diff --git a/frontend_nuxt/package-lock.json b/frontend_nuxt/package-lock.json index 4c8d81069..39770a80c 100644 --- a/frontend_nuxt/package-lock.json +++ b/frontend_nuxt/package-lock.json @@ -6,6 +6,8 @@ "": { "name": "frontend_nuxt", "dependencies": { + "@ffmpeg/ffmpeg": "^0.12.15", + "@ffmpeg/util": "^0.12.2", "@icon-park/vue-next": "^1.4.2", "@nuxt/image": "^1.11.0", "@stomp/stompjs": "^7.0.0", @@ -19,6 +21,7 @@ "ldrs": "^1.0.0", "markdown-it": "^14.1.0", "mermaid": "^10.9.4", + "nanoid": "^5.1.5", "nprogress": "^0.2.0", "nuxt": "latest", "sanitize-html": "^2.17.0", @@ -996,9 +999,39 @@ "integrity": "sha512-m9FVDXU3GT2ITSe0UaMA5rU3QkfC/UXtCU8y0gSN/GugTqtVldOBWIB5V6V3sbmenVZUIpU6f+mPEO2+m5iTaA==", "license": "MIT" }, + "node_modules/@ffmpeg/ffmpeg": { + "version": "0.12.15", + "resolved": "https://registry.npmmirror.com/@ffmpeg/ffmpeg/-/ffmpeg-0.12.15.tgz", + "integrity": "sha512-1C8Obr4GsN3xw+/1Ww6PFM84wSQAGsdoTuTWPOj2OizsRDLT4CXTaVjPhkw6ARyDus1B9X/L2LiXHqYYsGnRFw==", + "license": "MIT", + "dependencies": { + "@ffmpeg/types": "^0.12.4" + }, + "engines": { + "node": ">=18.x" + } + }, + "node_modules/@ffmpeg/types": { + "version": "0.12.4", + "resolved": "https://registry.npmmirror.com/@ffmpeg/types/-/types-0.12.4.tgz", + "integrity": "sha512-k9vJQNBGTxE5AhYDtOYR5rO5fKsspbg51gbcwtbkw2lCdoIILzklulcjJfIDwrtn7XhDeF2M+THwJ2FGrLeV6A==", + "license": "MIT", + "engines": { + "node": ">=16.x" + } + }, + "node_modules/@ffmpeg/util": { + "version": "0.12.2", + "resolved": "https://registry.npmmirror.com/@ffmpeg/util/-/util-0.12.2.tgz", + "integrity": "sha512-ouyoW+4JB7WxjeZ2y6KpRvB+dLp7Cp4ro8z0HIVpZVCM7AwFlHa0c4R8Y/a4M3wMqATpYKhC7lSFHQ0T11MEDw==", + "license": "MIT", + "engines": { + "node": ">=18.x" + } + }, "node_modules/@icon-park/vue-next": { "version": "1.4.2", - "resolved": "https://registry.npmjs.org/@icon-park/vue-next/-/vue-next-1.4.2.tgz", + "resolved": "https://registry.npmmirror.com/@icon-park/vue-next/-/vue-next-1.4.2.tgz", "integrity": "sha512-+QklF255wkfBOabY+xw6FAI0Bwln/RhdwCunNy/9sKdKuChtaU67QZqU67KGAvZUTeeBgsL+yaHHxqfQeGZXEQ==", "license": "Apache-2.0", "engines": { @@ -7222,7 +7255,7 @@ }, "node_modules/diff2html": { "version": "3.4.52", - "resolved": "https://registry.npmjs.org/diff2html/-/diff2html-3.4.52.tgz", + "resolved": "https://registry.npmmirror.com/diff2html/-/diff2html-3.4.52.tgz", "integrity": "sha512-qhMg8/I3sZ4zm/6R/Kh0xd6qG6Vm86w6M+C9W+DuH1V8ACz+1cgEC8/k0ucjv6AGqZWzHm/8G1gh7IlrUqCMhg==", "license": "MIT", "dependencies": { @@ -7238,7 +7271,7 @@ }, "node_modules/diff2html/node_modules/diff": { "version": "7.0.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-7.0.0.tgz", + "resolved": "https://registry.npmmirror.com/diff/-/diff-7.0.0.tgz", "integrity": "sha512-PJWHUb1RFevKCwaFA9RlG5tCd+FO5iRh9A8HEtkmBH2Li03iJriB6m6JIN4rGz3K3JLawI7/veA1xzRKP6ISBw==", "license": "BSD-3-Clause", "engines": { @@ -7247,7 +7280,7 @@ }, "node_modules/diff2html/node_modules/highlight.js": { "version": "11.9.0", - "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-11.9.0.tgz", + "resolved": "https://registry.npmmirror.com/highlight.js/-/highlight.js-11.9.0.tgz", "integrity": "sha512-fJ7cW7fQGCYAkgv4CPfwFHrfd/cLS4Hau96JuJ+ZTOWhjnhoeN1ub1tFmALm/+lW5z4WCAuAV9bm05AP0mS6Gw==", "license": "BSD-3-Clause", "optional": true, @@ -8330,7 +8363,7 @@ }, "node_modules/hogan.js": { "version": "3.0.2", - "resolved": "https://registry.npmjs.org/hogan.js/-/hogan.js-3.0.2.tgz", + "resolved": "https://registry.npmmirror.com/hogan.js/-/hogan.js-3.0.2.tgz", "integrity": "sha512-RqGs4wavGYJWE07t35JQccByczmNUXQT0E12ZYV1VKYu5UiAU9lsos/yBAcf840+zrUQQxgVduCR5/B8nNtibg==", "dependencies": { "mkdirp": "0.3.0", @@ -8342,13 +8375,13 @@ }, "node_modules/hogan.js/node_modules/abbrev": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "resolved": "https://registry.npmmirror.com/abbrev/-/abbrev-1.1.1.tgz", "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", "license": "ISC" }, "node_modules/hogan.js/node_modules/mkdirp": { "version": "0.3.0", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.0.tgz", + "resolved": "https://registry.npmmirror.com/mkdirp/-/mkdirp-0.3.0.tgz", "integrity": "sha512-OHsdUcVAQ6pOtg5JYWpCBo9W/GySVuwvP9hueRMW7UqshC0tbfzLv8wjySTPm3tfUZ/21CE9E1pJagOA91Pxew==", "deprecated": "Legacy versions of mkdirp are no longer supported. Please update to mkdirp 1.x. (Note that the API surface has changed to use Promises in 1.x.)", "license": "MIT/X11", @@ -8358,7 +8391,7 @@ }, "node_modules/hogan.js/node_modules/nopt": { "version": "1.0.10", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", + "resolved": "https://registry.npmmirror.com/nopt/-/nopt-1.0.10.tgz", "integrity": "sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==", "license": "MIT", "dependencies": { @@ -8614,7 +8647,7 @@ }, "node_modules/ipx": { "version": "3.1.1", - "resolved": "https://registry.npmjs.org/ipx/-/ipx-3.1.1.tgz", + "resolved": "https://registry.npmmirror.com/ipx/-/ipx-3.1.1.tgz", "integrity": "sha512-7Xnt54Dco7uYkfdAw0r2vCly3z0rSaVhEXMzPvl3FndsTVm5p26j+PO+gyinkYmcsEUvX2Rh7OGK7KzYWRu6BA==", "license": "MIT", "dependencies": { @@ -10171,7 +10204,7 @@ }, "node_modules/nanoid": { "version": "5.1.5", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.1.5.tgz", + "resolved": "https://registry.npmmirror.com/nanoid/-/nanoid-5.1.5.tgz", "integrity": "sha512-Ir/+ZpE9fDsNH0hQ3C68uyThDXzYcim2EqcZ8zn8Chtt1iylPT9xXJB0kPCnqzgcEGikO9RxSrh63MsmVCU7Fw==", "funding": [ { diff --git a/frontend_nuxt/package.json b/frontend_nuxt/package.json index 65385285c..31f873a29 100644 --- a/frontend_nuxt/package.json +++ b/frontend_nuxt/package.json @@ -13,6 +13,8 @@ }, "dependencies": { "@icon-park/vue-next": "^1.4.2", + "@ffmpeg/ffmpeg": "^0.12.15", + "@ffmpeg/util": "^0.12.2", "@nuxt/image": "^1.11.0", "@stomp/stompjs": "^7.0.0", "cropperjs": "^1.6.2", @@ -25,6 +27,7 @@ "ldrs": "^1.0.0", "markdown-it": "^14.1.0", "mermaid": "^10.9.4", + "nanoid": "^5.1.5", "nprogress": "^0.2.0", "nuxt": "latest", "sanitize-html": "^2.17.0", diff --git a/frontend_nuxt/plugins/ffmpeg.client.ts b/frontend_nuxt/plugins/ffmpeg.client.ts new file mode 100644 index 000000000..562a93aa2 --- /dev/null +++ b/frontend_nuxt/plugins/ffmpeg.client.ts @@ -0,0 +1,37 @@ +import { FFmpeg } from '@ffmpeg/ffmpeg' +import { toBlobURL } from '@ffmpeg/util' +import { defineNuxtPlugin, useRuntimeConfig } from 'nuxt/app' + +let ffmpeg: FFmpeg | null = null + +export default defineNuxtPlugin(() => { + const { + public: { ffmpegVersion }, + } = useRuntimeConfig() + + return { + provide: { + ffmpeg: async () => { + if (ffmpeg) return ffmpeg + + ffmpeg = new FFmpeg() + + const mtOk = + typeof crossOriginIsolated !== 'undefined' && + crossOriginIsolated && + typeof SharedArrayBuffer !== 'undefined' + + const pkg = mtOk ? '@ffmpeg/core-mt' : '@ffmpeg/core-st' + const base = `https://unpkg.com/${pkg}@${ffmpegVersion}/dist/umd` + + await ffmpeg.load({ + coreURL: await toBlobURL(`${base}/ffmpeg-core.js`, 'text/javascript'), + wasmURL: await toBlobURL(`${base}/ffmpeg-core.wasm`, 'application/wasm'), + workerURL: await toBlobURL(`${base}/ffmpeg-core.worker.js`, 'text/javascript'), + }) + + return ffmpeg + }, + }, + } +}) diff --git a/frontend_nuxt/utils/ffmpegVideoCompressor.js b/frontend_nuxt/utils/ffmpegVideoCompressor.js new file mode 100644 index 000000000..2aa155049 --- /dev/null +++ b/frontend_nuxt/utils/ffmpegVideoCompressor.js @@ -0,0 +1,327 @@ +/** + * FFmpeg.wasm 视频压缩器 + * + * 用法: + * const { $ffmpeg } = useNuxtApp() + * const ff = await $ffmpeg() // 插件里已完成 ffmpeg.load() + * const out = await compressVideoWithFFmpeg(ff, file, { onProgress, strictSize: false }) + * + * 设计要点: + * - 本文件不再负责加载/初始化,只负责转码逻辑;和 Nuxt 插件解耦。 + * - 针对【同一个 ffmpeg 实例】做串行队列,避免并发 exec 踩内存文件系统。 + * - 使用 nanoid 生成唯一文件名;日志环形缓冲;默认 CRF+VBV,可选 strictSize(two-pass)。 + * - 体积明显小于目标时直通返回,减少无谓重编码。 + */ + +import { fetchFile } from '@ffmpeg/util' +import { nanoid } from 'nanoid' +import { UPLOAD_CONFIG } from '../config/uploadConfig.js' + +/************************* + * 每实例一个串行队列 * + *************************/ +// WeakMapPromise)[], running: boolean, resolvers: {res,rej}[] }> +const queues = new WeakMap() + +function enqueueOn(instance, taskFn) { + return new Promise((res, rej) => { + let st = queues.get(instance) + if (!st) { + st = { q: [], running: false, resolvers: [] } + queues.set(instance, st) + } + st.q.push(taskFn) + st.resolvers.push({ res, rej }) + drain(instance) + }) +} + +async function drain(instance) { + const st = queues.get(instance) + if (!st || st.running) return + st.running = true + try { + while (st.q.length) { + const task = st.q.shift() + const rr = st.resolvers.shift() + try { + rr.res(await task()) + } catch (e) { + rr.rej(e) + } + } + } finally { + st.running = false + } +} + +/***************** + * 工具函数 * + *****************/ +function decideScale(widthHint) { + if (!widthHint) return { filter: null, width: null } + const evenW = widthHint % 2 === 0 ? widthHint : widthHint - 1 + return { filter: `scale=${evenW}:-2:flags=bicubic,setsar=1`, width: evenW } +} + +function calculateParamsByRatio(originalSize, targetSize) { + const ratio = Math.min(targetSize / originalSize, 1) + const crf = ratio < 0.35 ? 29 : ratio < 0.5 ? 27 : ratio < 0.7 ? 25 : 23 + const preset = ratio < 0.35 ? 'slow' : ratio < 0.5 ? 'medium' : 'veryfast' + const s = + ratio < 0.35 + ? decideScale(720) + : ratio < 0.6 + ? decideScale(960) + : ratio < 0.8 + ? decideScale(1280) + : { filter: null, width: null } + const audioBitrateK = ratio < 0.5 ? 96 : ratio < 0.7 ? 128 : 160 + const profile = s.width && s.width <= 1280 ? 'main' : 'high' + return { crf, preset, scaleFilter: s.filter, scaleWidth: s.width, audioBitrateK, profile } +} + +function makeRingLogger(capBytes = 4000) { + const buf = [] + let total = 0 + function push(s) { + if (!s) return + buf.push(s) + total += s.length + while (total > capBytes) total -= buf.shift().length + } + return { push, dump: () => buf.slice() } +} + +function parseDurationFromLogs(logs) { + // 避免正则:查找 Duration: 后的 00:00:00.xx + const text = logs.join(' ') + const idx = text.indexOf('Duration:') + if (idx === -1) return null + let i = idx + 'Duration:'.length + while (i < text.length && text[i] === ' ') i++ + function read2(start) { + const a = text.charCodeAt(start) - 48 + const b = text.charCodeAt(start + 1) - 48 + if (a < 0 || a > 9 || b < 0 || b > 9) return null + return a * 10 + b + } + const hh = read2(i) + if (hh === null) return null + i += 2 + if (text[i++] !== ':') return null + const mm = read2(i) + if (mm === null) return null + i += 2 + if (text[i++] !== ':') return null + const s1 = read2(i) + if (s1 === null) return null + i += 2 + if (text[i++] !== '.') return null + let j = i + while (j < text.length && text.charCodeAt(j) >= 48 && text.charCodeAt(j) <= 57) j++ + const frac = parseFloat('0.' + text.slice(i, j) || '0') + return hh * 3600 + mm * 60 + s1 + frac +} + +export function isFFmpegSupported() { + return typeof WebAssembly !== 'undefined' && typeof Worker !== 'undefined' +} + +/** + * 读取 ffmpeg 核心版本(通过 -version),会进入队列避免并发冲突 + */ +export async function getFFmpegInfo(ffmpegInstance) { + return enqueueOn(ffmpegInstance, async () => { + const logs = [] + const onLog = ({ type, message }) => { + if (type === 'info' || type === 'fferr') logs.push(message) + } + ffmpegInstance.on('log', onLog) + try { + await ffmpegInstance.exec(['-version']) + } finally { + ffmpegInstance.off('log', onLog) + } + const line = logs.find((l) => l.toLowerCase().includes('ffmpeg version')) || '' + const parts = line.trim().split(' ').filter(Boolean) + const version = parts.length > 2 ? parts[2] : parts[1] || null + return { version } + }) +} + +/** + * 压缩:接受一个已经 load() 完成的 ffmpeg 实例 + * @param {*} ffmpegInstance 已初始化的 FFmpeg 实例(来自 Nuxt 插件) + * @param {File|Blob} file 输入文件 + * @param {{ onProgress?:(p:{stage:string,progress:number})=>void, signal?:AbortSignal, strictSize?:boolean, targetSize?:number }} opts + */ +export async function compressVideoWithFFmpeg(ffmpegInstance, file, opts = {}) { + return enqueueOn(ffmpegInstance, () => doCompress(ffmpegInstance, file, opts)) +} + +async function doCompress(ffmpegInstance, file, opts) { + const onProgress = opts.onProgress || (() => {}) + const { signal, strictSize = false } = opts + + onProgress({ stage: 'preparing', progress: 10 }) + + const targetSize = opts.targetSize ?? UPLOAD_CONFIG?.VIDEO?.TARGET_SIZE ?? 12 * 1024 * 1024 + + // 小体积直通 + const sizeKnown = 'size' in file && typeof file.size === 'number' + if (sizeKnown && file.size <= targetSize * 0.9) { + onProgress({ stage: 'skipped', progress: 100 }) + return file + } + + const params = calculateParamsByRatio(sizeKnown ? file.size : targetSize * 2, targetSize) + const { crf, preset, scaleFilter, audioBitrateK, profile } = params + + const name = 'name' in file && typeof file.name === 'string' ? file.name : 'input.mp4' + const dot = name.lastIndexOf('.') + const outName = (dot > -1 ? name.slice(0, dot) : name) + '.mp4' + + const ext = dot > -1 ? name.slice(dot + 1).toLowerCase() : 'mp4' + const id = nanoid() + const inputName = `input-${id}.${ext}` + const outputName = `output-${id}.mp4` + const passlog = `ffpass-${id}` + + // 监听 + const ring = makeRingLogger() + const onFfmpegProgress = ({ progress: p }) => { + const adjusted = 20 + p * 70 + onProgress({ stage: 'compressing', progress: Math.min(90, adjusted) }) + } + const onFfmpegLog = ({ type, message }) => { + if (type === 'fferr' || type === 'info') ring.push(message) + } + ffmpegInstance.on('progress', onFfmpegProgress) + ffmpegInstance.on('log', onFfmpegLog) + + let aborted = false + const abortHandler = () => { + aborted = true + } + if (signal) signal.addEventListener('abort', abortHandler, { once: true }) + + try { + await ffmpegInstance.writeFile(inputName, await fetchFile(file)) + onProgress({ stage: 'analyzing', progress: 20 }) + + let durationSec = null + try { + await ffmpegInstance.exec(['-hide_banner', '-i', inputName, '-f', 'null', '-']) + durationSec = parseDurationFromLogs(ring.dump()) + } catch { + durationSec = durationSec ?? parseDurationFromLogs(ring.dump()) + } + + let videoBitrate = null + if (durationSec && sizeKnown && targetSize < file.size) { + const totalTargetBits = targetSize * 8 + const audioBits = audioBitrateK * 1000 * durationSec + const maxVideoBits = Math.max(totalTargetBits - audioBits, totalTargetBits * 0.7) + const bps = Math.max(180000, Math.floor(maxVideoBits / durationSec)) + videoBitrate = String(Math.min(bps, 5000000)) + } + + const baseArgs = [ + '-hide_banner', + '-i', + inputName, + '-c:v', + 'libx264', + '-pix_fmt', + 'yuv420p', + '-profile:v', + profile, + '-movflags', + '+faststart', + '-preset', + preset, + '-c:a', + 'aac', + '-b:a', + `${audioBitrateK}k`, + '-ac', + '2', + ] + if (scaleFilter) baseArgs.push('-vf', scaleFilter) + + const onePassArgs = [...baseArgs, '-crf', String(crf)] + if (videoBitrate) + onePassArgs.push('-maxrate', videoBitrate, '-bufsize', String(parseInt(videoBitrate, 10) * 2)) + + const twoPassFirst = [ + '-y', + '-hide_banner', + '-i', + inputName, + '-c:v', + 'libx264', + '-b:v', + `${videoBitrate || '1000000'}`, + '-pass', + '1', + '-passlogfile', + passlog, + '-an', + '-f', + 'mp4', + '/dev/null', + ] + const twoPassSecond = [ + ...baseArgs, + '-b:v', + `${videoBitrate || '1000000'}`, + '-pass', + '2', + '-passlogfile', + passlog, + outputName, + ] + + if (aborted) throw new DOMException('Aborted', 'AbortError') + + if (!strictSize) { + await ffmpegInstance.exec([...onePassArgs, outputName]) + } else { + if (!videoBitrate) videoBitrate = '1000000' + await ffmpegInstance.exec(twoPassFirst) + onProgress({ stage: 'second-pass', progress: 85 }) + await ffmpegInstance.exec(twoPassSecond) + } + + if (aborted) throw new DOMException('Aborted', 'AbortError') + + onProgress({ stage: 'finalizing', progress: 95 }) + const out = await ffmpegInstance.readFile(outputName) + + const mime = 'video/mp4' + const blob = new Blob([out], { type: mime }) + const hasFileCtor = typeof File === 'function' + const result = hasFileCtor ? new File([blob], outName, { type: mime }) : blob + + onProgress({ stage: 'completed', progress: 100 }) + return result + } finally { + try { + await ffmpegInstance.deleteFile(inputName) + } catch {} + try { + await ffmpegInstance.deleteFile(outputName) + } catch {} + try { + await ffmpegInstance.deleteFile(`${passlog}-0.log`) + } catch {} + try { + await ffmpegInstance.deleteFile(`${passlog}-0.log.mbtree`) + } catch {} + + ffmpegInstance.off('progress', onFfmpegProgress) + ffmpegInstance.off('log', onFfmpegLog) + if (signal) signal.removeEventListener('abort', abortHandler) + } +} diff --git a/frontend_nuxt/utils/vditor.js b/frontend_nuxt/utils/vditor.js index 3016fbc69..c2c6d7d9a 100644 --- a/frontend_nuxt/utils/vditor.js +++ b/frontend_nuxt/utils/vditor.js @@ -3,6 +3,8 @@ import { getToken, authState } from './auth' import { searchUsers, fetchFollowings, fetchAdmins } from './user' import { tiebaEmoji } from './tiebaEmoji' import vditorPostCitation from './vditorPostCitation.js' +import { checkFileSize, formatFileSize, compressVideo, VIDEO_CONFIG } from './videoCompressor.js' +import { UPLOAD_CONFIG } from '../config/uploadConfig.js' export function getEditorTheme() { return document.documentElement.dataset.theme === 'dark' ? 'dark' : 'classic' @@ -91,10 +93,81 @@ export function createVditor(editorId, options = {}) { multiple: false, handler: async (files) => { const file = files[0] - vditor.tip('图片上传中', 0) + const ext = file.name.split('.').pop().toLowerCase() + const videoExts = ['mp4', 'webm', 'avi', 'mov', 'wmv', 'flv', 'mkv', 'm4v', 'ogv'] + const isVideo = videoExts.includes(ext) + + // 检查文件大小 + const sizeCheck = checkFileSize(file) + if (!sizeCheck.isValid) { + console.log( + '文件大小不能超过', + formatFileSize(sizeCheck.maxSize), + ',当前文件', + formatFileSize(sizeCheck.actualSize), + ) + vditor.tip( + `文件大小不能超过 ${formatFileSize(sizeCheck.maxSize)},当前文件 ${formatFileSize(sizeCheck.actualSize)}`, + 3000, + ) + return '文件过大' + } + + let processedFile = file + + // 如果是视频文件且需要压缩 + if (isVideo && sizeCheck.needsCompression) { + try { + vditor.tip('视频压缩中...', 0) + vditor.disabled() + + // 使用 FFmpeg 压缩视频 + processedFile = await compressVideo(file, (progress) => { + const messages = { + initializing: '初始化 FFmpeg', + preparing: '准备压缩', + analyzing: '分析视频', + compressing: '压缩中', + finalizing: '完成压缩', + completed: '压缩完成', + } + const message = messages[progress.stage] || progress.stage + vditor.tip(`${message} ${progress.progress}%`, 0) + }) + + const originalSize = formatFileSize(file.size) + const compressedSize = formatFileSize(processedFile.size) + const savings = Math.round((1 - processedFile.size / file.size) * 100) + + vditor.tip(`压缩完成!${originalSize} → ${compressedSize} (节省 ${savings}%)`, 2000) + // 压缩成功但仍然超过最大限制,则阻止上传 + if (processedFile.size > VIDEO_CONFIG.MAX_SIZE) { + vditor.tip( + `压缩后仍超过限制 (${formatFileSize(VIDEO_CONFIG.MAX_SIZE)}). 请降低分辨率或码率后再上传。`, + 4000, + ) + vditor.enable() + return '压缩后仍超过大小限制' + } + } catch (error) { + // 压缩失败时,如果原文件超过最大限制,则阻止上传 + if (file.size > VIDEO_CONFIG.MAX_SIZE) { + vditor.tip( + `视频压缩失败,且文件超过限制 (${formatFileSize(VIDEO_CONFIG.MAX_SIZE)}). 请先压缩后再上传。`, + 4000, + ) + vditor.enable() + return '视频压缩失败且文件过大' + } + vditor.tip('视频压缩失败,将尝试上传原文件', 3000) + processedFile = file + } + } + + vditor.tip('文件上传中', 0) vditor.disabled() const res = await fetch( - `${API_BASE_URL}/api/upload/presign?filename=${encodeURIComponent(file.name)}`, + `${API_BASE_URL}/api/upload/presign?filename=${encodeURIComponent(processedFile.name)}`, { headers: { Authorization: `Bearer ${getToken()}` } }, ) if (!res.ok) { @@ -103,14 +176,13 @@ export function createVditor(editorId, options = {}) { return '获取上传地址失败' } const info = await res.json() - const put = await fetch(info.uploadUrl, { method: 'PUT', body: file }) + const put = await fetch(info.uploadUrl, { method: 'PUT', body: processedFile }) if (!put.ok) { vditor.enable() vditor.tip('上传失败') return '上传失败' } - const ext = file.name.split('.').pop().toLowerCase() const imageExts = [ 'apng', 'bmp', @@ -132,6 +204,8 @@ export function createVditor(editorId, options = {}) { md = `![${file.name}](${info.fileUrl})` } else if (audioExts.includes(ext)) { md = `` + } else if (videoExts.includes(ext)) { + md = `` } else { md = `[${file.name}](${info.fileUrl})` } diff --git a/frontend_nuxt/utils/videoCompressor.js b/frontend_nuxt/utils/videoCompressor.js new file mode 100644 index 000000000..584d8a487 --- /dev/null +++ b/frontend_nuxt/utils/videoCompressor.js @@ -0,0 +1,79 @@ +/** + * 基于 FFmpeg.wasm 的视频压缩工具 + * 专为现代浏览器 (Chrome/Safari) 优化 + */ + +import { UPLOAD_CONFIG } from '../config/uploadConfig.js' +import { compressVideoWithFFmpeg, isFFmpegSupported } from './ffmpegVideoCompressor.js' +import { useNuxtApp } from '#app' + +// 导出配置供外部使用 +export const VIDEO_CONFIG = UPLOAD_CONFIG.VIDEO + +/** + * 检查文件大小是否超出限制 + */ +export function checkFileSize(file) { + return { + isValid: file.size <= VIDEO_CONFIG.MAX_SIZE, + actualSize: file.size, + maxSize: VIDEO_CONFIG.MAX_SIZE, + needsCompression: file.size > VIDEO_CONFIG.TARGET_SIZE, + } +} + +/** + * 格式化文件大小显示 + */ +export function formatFileSize(bytes) { + if (bytes === 0) return '0 B' + const k = 1024 + const sizes = ['B', 'KB', 'MB', 'GB'] + const i = Math.floor(Math.log(bytes) / Math.log(k)) + return parseFloat((bytes / Math.pow(k, i)).toFixed(1)) + ' ' + sizes[i] +} + +/** + * 压缩视频文件 - 使用 FFmpeg.wasm + */ +export async function compressVideo(file, onProgress = () => {}) { + // 检查是否需要压缩 + const sizeCheck = checkFileSize(file) + if (!sizeCheck.needsCompression) { + onProgress({ stage: 'completed', progress: 100 }) + return file + } + + // 检查 FFmpeg 支持 + if (!isFFmpegSupported()) { + throw new Error('当前浏览器不支持视频压缩功能,请使用 Chrome 或 Safari 浏览器') + } + + try { + const { $ffmpeg } = useNuxtApp() + const ff = await $ffmpeg() + return await compressVideoWithFFmpeg(ff, file, { onProgress }) + } catch (error) { + console.error('FFmpeg 压缩失败:', error) + throw new Error(`视频压缩失败: ${error.message}`) + } +} + +/** + * 预加载 FFmpeg(可选的性能优化) + */ +export async function preloadVideoCompressor() { + try { + // FFmpeg 初始化现在通过 Nuxt 插件处理 + // 这里只需要检查支持性 + if (!isFFmpegSupported()) { + throw new Error('当前浏览器不支持 FFmpeg') + } + const { $ffmpeg } = useNuxtApp() + await $ffmpeg() + return { success: true, message: 'FFmpeg 预加载成功' } + } catch (error) { + console.warn('FFmpeg 预加载失败:', error) + return { success: false, error: error.message } + } +} From 37c43060108233e06d4886b7bb71293b9260c523 Mon Sep 17 00:00:00 2001 From: wangshun <932054296@qq.com> Date: Thu, 11 Sep 2025 15:29:24 +0800 Subject: [PATCH 02/26] =?UTF-8?q?=E7=BC=93=E5=AD=98=E5=8A=9F=E8=83=BD?= =?UTF-8?q?=E8=BF=BD=E5=8A=A0=201.=E6=9C=80=E6=96=B0=E5=9B=9E=E5=A4=8D?= =?UTF-8?q?=E5=88=97=E8=A1=A8=202.=E6=9C=80=E6=96=B0=E5=88=97=E8=A1=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/openisle/config/CachingConfig.java | 7 +- .../openisle/controller/PostController.java | 62 +++-------- .../main/java/com/openisle/model/Post.java | 8 +- .../com/openisle/service/CategoryService.java | 14 +++ .../com/openisle/service/CommentService.java | 19 ++++ .../com/openisle/service/PostService.java | 100 ++++++++++++++---- .../java/com/openisle/service/TagService.java | 14 +++ 7 files changed, 152 insertions(+), 72 deletions(-) diff --git a/backend/src/main/java/com/openisle/config/CachingConfig.java b/backend/src/main/java/com/openisle/config/CachingConfig.java index 7497d1024..9094efa1a 100644 --- a/backend/src/main/java/com/openisle/config/CachingConfig.java +++ b/backend/src/main/java/com/openisle/config/CachingConfig.java @@ -46,6 +46,8 @@ public class CachingConfig { public static final String LIMIT_CACHE_NAME="openisle_limit"; // 用户访问统计 public static final String VISIT_CACHE_NAME="openisle_visit"; + // 文章缓存 + public static final String POST_CACHE_NAME="openisle_posts"; /** * 自定义Redis的序列化器 @@ -65,7 +67,10 @@ public class CachingConfig { // Hibernate6Module 可以自动处理懒加载代理对象。 // Tag对象的creator是FetchType.LAZY objectMapper.registerModule(new Hibernate6Module() - .disable(Hibernate6Module.Feature.USE_TRANSIENT_ANNOTATION)); + .disable(Hibernate6Module.Feature.USE_TRANSIENT_ANNOTATION) + // 将 Hibernate 特有的集合类型转换为标准 Java 集合类型 + // 避免序列化时出现 org.hibernate.collection.spi.PersistentSet 这样的类型信息 + .configure(Hibernate6Module.Feature.REPLACE_PERSISTENT_COLLECTIONS, true)); // service的时候带上类型信息 // 启用类型信息,避免 LinkedHashMap 问题 objectMapper.activateDefaultTyping( diff --git a/backend/src/main/java/com/openisle/controller/PostController.java b/backend/src/main/java/com/openisle/controller/PostController.java index 002455900..907358c30 100644 --- a/backend/src/main/java/com/openisle/controller/PostController.java +++ b/backend/src/main/java/com/openisle/controller/PostController.java @@ -27,6 +27,8 @@ import java.util.stream.Collectors; @RequiredArgsConstructor public class PostController { private final PostService postService; + private final CategoryService categoryService; + private final TagService tagService; private final LevelService levelService; private final CaptchaService captchaService; private final DraftService draftService; @@ -147,33 +149,16 @@ public class PostController { @RequestParam(value = "page", required = false) Integer page, @RequestParam(value = "pageSize", required = false) Integer pageSize, Authentication auth) { - List ids = categoryIds; - if (categoryId != null) { - ids = java.util.List.of(categoryId); - } - List tids = tagIds; - if (tagId != null) { - tids = java.util.List.of(tagId); - } + + List ids = categoryService.getSearchCategoryIds(categoryIds, categoryId); + List tids = tagService.getSearchTagIds(tagIds, tagId); // 只需要在请求的一开始统计一次 // if (auth != null) { // userVisitService.recordVisit(auth.getName()); // } - boolean hasCategories = ids != null && !ids.isEmpty(); - boolean hasTags = tids != null && !tids.isEmpty(); - - if (hasCategories && hasTags) { - return postService.listPostsByCategoriesAndTags(ids, tids, page, pageSize) - .stream().map(postMapper::toSummaryDto).collect(Collectors.toList()); - } - if (hasTags) { - return postService.listPostsByTags(tids, page, pageSize) - .stream().map(postMapper::toSummaryDto).collect(Collectors.toList()); - } - - return postService.listPostsByCategories(ids, page, pageSize) - .stream().map(postMapper::toSummaryDto).collect(Collectors.toList()); + return postService.defaultListPosts(ids,tids,page, pageSize).stream() + .map(postMapper::toSummaryDto).collect(Collectors.toList()); } @GetMapping("/ranking") @@ -187,14 +172,9 @@ public class PostController { @RequestParam(value = "page", required = false) Integer page, @RequestParam(value = "pageSize", required = false) Integer pageSize, Authentication auth) { - List ids = categoryIds; - if (categoryId != null) { - ids = java.util.List.of(categoryId); - } - List tids = tagIds; - if (tagId != null) { - tids = java.util.List.of(tagId); - } + + List ids = categoryService.getSearchCategoryIds(categoryIds, categoryId); + List tids = tagService.getSearchTagIds(tagIds, tagId); // 只需要在请求的一开始统计一次 // if (auth != null) { // userVisitService.recordVisit(auth.getName()); @@ -215,14 +195,9 @@ public class PostController { @RequestParam(value = "page", required = false) Integer page, @RequestParam(value = "pageSize", required = false) Integer pageSize, Authentication auth) { - List ids = categoryIds; - if (categoryId != null) { - ids = java.util.List.of(categoryId); - } - List tids = tagIds; - if (tagId != null) { - tids = java.util.List.of(tagId); - } + + List ids = categoryService.getSearchCategoryIds(categoryIds, categoryId); + List tids = tagService.getSearchTagIds(tagIds, tagId); // 只需要在请求的一开始统计一次 // if (auth != null) { // userVisitService.recordVisit(auth.getName()); @@ -243,14 +218,9 @@ public class PostController { @RequestParam(value = "page", required = false) Integer page, @RequestParam(value = "pageSize", required = false) Integer pageSize, Authentication auth) { - List ids = categoryIds; - if (categoryId != null) { - ids = java.util.List.of(categoryId); - } - List tids = tagIds; - if (tagId != null) { - tids = java.util.List.of(tagId); - } + + List ids = categoryService.getSearchCategoryIds(categoryIds, categoryId); + List tids = tagService.getSearchTagIds(tagIds, tagId); // 只需要在请求的一开始统计一次 // if (auth != null) { // userVisitService.recordVisit(auth.getName()); diff --git a/backend/src/main/java/com/openisle/model/Post.java b/backend/src/main/java/com/openisle/model/Post.java index 3dcbbab3c..7e5df2a4f 100644 --- a/backend/src/main/java/com/openisle/model/Post.java +++ b/backend/src/main/java/com/openisle/model/Post.java @@ -39,19 +39,19 @@ public class Post { columnDefinition = "DATETIME(6) DEFAULT CURRENT_TIMESTAMP(6)") private LocalDateTime createdAt; - @ManyToOne(optional = false, fetch = FetchType.LAZY) + @ManyToOne(optional = false, fetch = FetchType.EAGER) @JoinColumn(name = "author_id") private User author; - @ManyToOne(optional = false, fetch = FetchType.LAZY) + @ManyToOne(optional = false, fetch = FetchType.EAGER) @JoinColumn(name = "category_id") private Category category; - @ManyToMany(fetch = FetchType.LAZY) + @ManyToMany(fetch = FetchType.EAGER) @JoinTable(name = "post_tags", joinColumns = @JoinColumn(name = "post_id"), inverseJoinColumns = @JoinColumn(name = "tag_id")) - private java.util.Set tags = new java.util.HashSet<>(); + private Set tags = new HashSet<>(); @Column(nullable = false) private long views = 0; diff --git a/backend/src/main/java/com/openisle/service/CategoryService.java b/backend/src/main/java/com/openisle/service/CategoryService.java index 9486bc88c..309ae7f0d 100644 --- a/backend/src/main/java/com/openisle/service/CategoryService.java +++ b/backend/src/main/java/com/openisle/service/CategoryService.java @@ -62,4 +62,18 @@ public class CategoryService { public List listCategories() { return categoryRepository.findAll(); } + + /** + * 获取检索用的分类Id列表 + * @param categoryIds + * @param categoryId + * @return + */ + public List getSearchCategoryIds(List categoryIds, Long categoryId){ + List ids = categoryIds; + if (categoryId != null) { + ids = List.of(categoryId); + } + return ids; + } } diff --git a/backend/src/main/java/com/openisle/service/CommentService.java b/backend/src/main/java/com/openisle/service/CommentService.java index 1076aa5e2..e9456caf7 100644 --- a/backend/src/main/java/com/openisle/service/CommentService.java +++ b/backend/src/main/java/com/openisle/service/CommentService.java @@ -1,5 +1,6 @@ package com.openisle.service; +import com.openisle.config.CachingConfig; import com.openisle.model.Comment; import com.openisle.model.Post; import com.openisle.model.User; @@ -20,6 +21,8 @@ import com.openisle.model.Role; import com.openisle.exception.RateLimitException; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; import java.util.List; @@ -47,6 +50,10 @@ public class CommentService { private final PointService pointService; private final ImageUploader imageUploader; + @CacheEvict( + value = CachingConfig.POST_CACHE_NAME, + key = "'latest_reply'" + ) @Transactional public Comment addComment(String username, Long postId, String content) { log.debug("addComment called by user {} for post {}", username, postId); @@ -95,6 +102,10 @@ public class CommentService { return commentRepository.findLastCommentTimeOfUserByUserId(userId); } + @CacheEvict( + value = CachingConfig.POST_CACHE_NAME, + key = "'latest_reply'" + ) @Transactional public Comment addReply(String username, Long parentId, String content) { log.debug("addReply called by user {} for parent comment {}", username, parentId); @@ -228,6 +239,10 @@ public class CommentService { return count; } + @CacheEvict( + value = CachingConfig.POST_CACHE_NAME, + key = "'latest_reply'" + ) @Transactional public void deleteComment(String username, Long id) { log.debug("deleteComment called by user {} for comment {}", username, id); @@ -243,6 +258,10 @@ public class CommentService { log.debug("deleteComment completed for comment {}", id); } + @CacheEvict( + value = CachingConfig.POST_CACHE_NAME, + key = "'latest_reply'" + ) @Transactional public void deleteCommentCascade(Comment comment) { log.debug("deleteCommentCascade called for comment {}", comment.getId()); diff --git a/backend/src/main/java/com/openisle/service/PostService.java b/backend/src/main/java/com/openisle/service/PostService.java index 16162d32a..65092d0b7 100644 --- a/backend/src/main/java/com/openisle/service/PostService.java +++ b/backend/src/main/java/com/openisle/service/PostService.java @@ -1,17 +1,8 @@ package com.openisle.service; import com.openisle.config.CachingConfig; -import com.openisle.model.Post; -import com.openisle.model.PostStatus; -import com.openisle.model.PostType; -import com.openisle.model.PublishMode; -import com.openisle.model.User; -import com.openisle.model.Category; -import com.openisle.model.Comment; -import com.openisle.model.NotificationType; -import com.openisle.model.LotteryPost; -import com.openisle.model.PollPost; -import com.openisle.model.PollVote; +import com.openisle.mapper.PostMapper; +import com.openisle.model.*; import com.openisle.repository.PostRepository; import com.openisle.repository.LotteryPostRepository; import com.openisle.repository.PollPostRepository; @@ -26,11 +17,12 @@ import com.openisle.repository.ReactionRepository; import com.openisle.repository.PostSubscriptionRepository; import com.openisle.repository.NotificationRepository; import com.openisle.repository.PollVoteRepository; -import com.openisle.model.Role; import com.openisle.exception.RateLimitException; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Value; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; import org.springframework.context.ApplicationContext; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Service; @@ -52,6 +44,8 @@ import java.time.LocalDateTime; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ScheduledFuture; +import java.util.stream.Collectors; + import org.springframework.boot.context.event.ApplicationReadyEvent; import org.springframework.context.event.EventListener; @@ -195,12 +189,14 @@ public class PostService { pointService.awardForFeatured(saved.getAuthor().getUsername(), saved.getId()); return saved; } - + @CacheEvict( + value = CachingConfig.POST_CACHE_NAME, allEntries = true + ) public Post createPost(String username, Long categoryId, String title, String content, - java.util.List tagIds, + List tagIds, PostType type, String prizeDescription, String prizeIcon, @@ -511,6 +507,10 @@ public class PostService { return listPostsByLatestReply(null, null, page, pageSize); } + @Cacheable( + value = CachingConfig.POST_CACHE_NAME, + key = "'latest_reply'" + ) public List listPostsByLatestReply(java.util.List categoryIds, java.util.List tagIds, Integer page, @@ -538,9 +538,9 @@ public class PostService { posts = postRepository.findByCategoryInAndStatusOrderByCreatedAtDesc(categories, PostStatus.PUBLISHED); } } else { - java.util.List tags = tagRepository.findAllById(tagIds); + List tags = tagRepository.findAllById(tagIds); if (tags.isEmpty()) { - return java.util.List.of(); + return new ArrayList<>(); } posts = postRepository.findByAllTagsOrderByCreatedAtDesc(tags, PostStatus.PUBLISHED, tags.size()); } @@ -638,11 +638,43 @@ public class PostService { return paginate(sortByPinnedAndCreated(posts), page, pageSize); } + /** + * 默认的文章列表 + * @param ids + * @param tids + * @param page + * @param pageSize + * @return + */ + @Cacheable( + value = CachingConfig.POST_CACHE_NAME, + key = "'default'" + ) + public List defaultListPosts(List ids, List tids, Integer page, Integer pageSize){ + boolean hasCategories = !CollectionUtils.isEmpty(ids); + boolean hasTags = !CollectionUtils.isEmpty(tids); + + if (hasCategories && hasTags) { + return listPostsByCategoriesAndTags(ids, tids, page, pageSize) + .stream().collect(Collectors.toList()); + } + if (hasTags) { + return listPostsByTags(tids, page, pageSize) + .stream().collect(Collectors.toList()); + } + + return listPostsByCategories(ids, page, pageSize) + .stream().collect(Collectors.toList()); + } public List listPendingPosts() { return postRepository.findByStatus(PostStatus.PENDING); } + @CacheEvict( + value = CachingConfig.POST_CACHE_NAME, + key = "'default'" + ) public Post approvePost(Long id) { Post post = postRepository.findById(id) .orElseThrow(() -> new com.openisle.exception.NotFoundException("Post not found")); @@ -679,6 +711,10 @@ public class PostService { return post; } + @CacheEvict( + value = CachingConfig.POST_CACHE_NAME, + key = "'default'" + ) public Post pinPost(Long id, String username) { Post post = postRepository.findById(id) .orElseThrow(() -> new com.openisle.exception.NotFoundException("Post not found")); @@ -691,6 +727,10 @@ public class PostService { return saved; } + @CacheEvict( + value = CachingConfig.POST_CACHE_NAME, + key = "'default'" + ) public Post unpinPost(Long id, String username) { Post post = postRepository.findById(id) .orElseThrow(() -> new com.openisle.exception.NotFoundException("Post not found")); @@ -703,6 +743,10 @@ public class PostService { return saved; } + @CacheEvict( + value = CachingConfig.POST_CACHE_NAME, + key = "'default'" + ) public Post closePost(Long id, String username) { Post post = postRepository.findById(id) .orElseThrow(() -> new com.openisle.exception.NotFoundException("Post not found")); @@ -718,6 +762,10 @@ public class PostService { return saved; } + @CacheEvict( + value = CachingConfig.POST_CACHE_NAME, + key = "'default'" + ) public Post reopenPost(Long id, String username) { Post post = postRepository.findById(id) .orElseThrow(() -> new com.openisle.exception.NotFoundException("Post not found")); @@ -733,7 +781,11 @@ public class PostService { return saved; } - @org.springframework.transaction.annotation.Transactional + @CacheEvict( + value = CachingConfig.POST_CACHE_NAME, + key = "'default'" + ) + @Transactional public Post updatePost(Long id, String username, Long categoryId, @@ -786,7 +838,11 @@ public class PostService { return updated; } - @org.springframework.transaction.annotation.Transactional + @CacheEvict( + value = CachingConfig.POST_CACHE_NAME, + key = "'default'" + ) + @Transactional public void deletePost(Long id, String username) { Post post = postRepository.findById(id) .orElseThrow(() -> new com.openisle.exception.NotFoundException("Post not found")); @@ -879,15 +935,17 @@ public class PostService { .toList(); } - private java.util.List paginate(java.util.List posts, Integer page, Integer pageSize) { + private List paginate(List posts, Integer page, Integer pageSize) { if (page == null || pageSize == null) { return posts; } int from = page * pageSize; if (from >= posts.size()) { - return java.util.List.of(); + return new ArrayList<>(); } int to = Math.min(from + pageSize, posts.size()); - return posts.subList(from, to); + // 这里必须将list包装为arrayList类型,否则序列化会有问题 + // list.sublist返回的是内部类 + return new ArrayList<>(posts.subList(from, to)); } } diff --git a/backend/src/main/java/com/openisle/service/TagService.java b/backend/src/main/java/com/openisle/service/TagService.java index eee84121e..02191427d 100644 --- a/backend/src/main/java/com/openisle/service/TagService.java +++ b/backend/src/main/java/com/openisle/service/TagService.java @@ -120,4 +120,18 @@ public class TagService { .orElseThrow(() -> new com.openisle.exception.NotFoundException("User not found")); return tagRepository.findByCreator(user); } + + /** + * 获取检索用的标签Id列表 + * @param tagIds + * @param tagId + * @return + */ + public List getSearchTagIds(List tagIds, Long tagId){ + List ids = tagIds; + if (tagId != null) { + ids = List.of(tagId); + } + return ids; + } } From 3f35add587da23d025fa1bded3cf53cd619c07c4 Mon Sep 17 00:00:00 2001 From: Tim <135014430+nagisa77@users.noreply.github.com> Date: Thu, 11 Sep 2025 17:01:54 +0800 Subject: [PATCH 03/26] feat: switch video compression to webcodecs --- frontend_nuxt/nuxt.config.ts | 14 - frontend_nuxt/package-lock.json | 42 +-- frontend_nuxt/package.json | 3 +- frontend_nuxt/plugins/ffmpeg.client.ts | 37 -- frontend_nuxt/utils/ffmpegVideoCompressor.js | 327 ------------------ frontend_nuxt/utils/vditor.js | 7 +- frontend_nuxt/utils/videoCompressor.js | 31 +- .../utils/webcodecVideoCompressor.js | 108 ++++++ 8 files changed, 134 insertions(+), 435 deletions(-) delete mode 100644 frontend_nuxt/plugins/ffmpeg.client.ts delete mode 100644 frontend_nuxt/utils/ffmpegVideoCompressor.js create mode 100644 frontend_nuxt/utils/webcodecVideoCompressor.js diff --git a/frontend_nuxt/nuxt.config.ts b/frontend_nuxt/nuxt.config.ts index dad43963c..f0adf3c98 100644 --- a/frontend_nuxt/nuxt.config.ts +++ b/frontend_nuxt/nuxt.config.ts @@ -1,17 +1,4 @@ import { defineNuxtConfig } from 'nuxt/config' -import { createRequire } from 'node:module' - -const require = createRequire(import.meta.url) -const appPkg = require('./package.json') as { - dependencies?: Record - devDependencies?: Record -} -const ffmpegVersion = ( - process.env.NUXT_PUBLIC_FFMPEG_VERSION || - appPkg.dependencies?.['@ffmpeg/ffmpeg'] || - appPkg.devDependencies?.['@ffmpeg/ffmpeg'] || - '0.12.15' -).replace(/^[^\d]*/, '') export default defineNuxtConfig({ devServer: { host: '0.0.0.0', @@ -29,7 +16,6 @@ export default defineNuxtConfig({ discordClientId: process.env.NUXT_PUBLIC_DISCORD_CLIENT_ID || '', twitterClientId: process.env.NUXT_PUBLIC_TWITTER_CLIENT_ID || '', telegramBotId: process.env.NUXT_PUBLIC_TELEGRAM_BOT_ID || '', - ffmpegVersion, }, }, css: [ diff --git a/frontend_nuxt/package-lock.json b/frontend_nuxt/package-lock.json index 39770a80c..a7a28be3d 100644 --- a/frontend_nuxt/package-lock.json +++ b/frontend_nuxt/package-lock.json @@ -6,8 +6,6 @@ "": { "name": "frontend_nuxt", "dependencies": { - "@ffmpeg/ffmpeg": "^0.12.15", - "@ffmpeg/util": "^0.12.2", "@icon-park/vue-next": "^1.4.2", "@nuxt/image": "^1.11.0", "@stomp/stompjs": "^7.0.0", @@ -21,6 +19,7 @@ "ldrs": "^1.0.0", "markdown-it": "^14.1.0", "mermaid": "^10.9.4", + "mp4box": "^2.1.1", "nanoid": "^5.1.5", "nprogress": "^0.2.0", "nuxt": "latest", @@ -999,36 +998,6 @@ "integrity": "sha512-m9FVDXU3GT2ITSe0UaMA5rU3QkfC/UXtCU8y0gSN/GugTqtVldOBWIB5V6V3sbmenVZUIpU6f+mPEO2+m5iTaA==", "license": "MIT" }, - "node_modules/@ffmpeg/ffmpeg": { - "version": "0.12.15", - "resolved": "https://registry.npmmirror.com/@ffmpeg/ffmpeg/-/ffmpeg-0.12.15.tgz", - "integrity": "sha512-1C8Obr4GsN3xw+/1Ww6PFM84wSQAGsdoTuTWPOj2OizsRDLT4CXTaVjPhkw6ARyDus1B9X/L2LiXHqYYsGnRFw==", - "license": "MIT", - "dependencies": { - "@ffmpeg/types": "^0.12.4" - }, - "engines": { - "node": ">=18.x" - } - }, - "node_modules/@ffmpeg/types": { - "version": "0.12.4", - "resolved": "https://registry.npmmirror.com/@ffmpeg/types/-/types-0.12.4.tgz", - "integrity": "sha512-k9vJQNBGTxE5AhYDtOYR5rO5fKsspbg51gbcwtbkw2lCdoIILzklulcjJfIDwrtn7XhDeF2M+THwJ2FGrLeV6A==", - "license": "MIT", - "engines": { - "node": ">=16.x" - } - }, - "node_modules/@ffmpeg/util": { - "version": "0.12.2", - "resolved": "https://registry.npmmirror.com/@ffmpeg/util/-/util-0.12.2.tgz", - "integrity": "sha512-ouyoW+4JB7WxjeZ2y6KpRvB+dLp7Cp4ro8z0HIVpZVCM7AwFlHa0c4R8Y/a4M3wMqATpYKhC7lSFHQ0T11MEDw==", - "license": "MIT", - "engines": { - "node": ">=18.x" - } - }, "node_modules/@icon-park/vue-next": { "version": "1.4.2", "resolved": "https://registry.npmmirror.com/@icon-park/vue-next/-/vue-next-1.4.2.tgz", @@ -10172,6 +10141,15 @@ "node": ">=18" } }, + "node_modules/mp4box": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/mp4box/-/mp4box-2.1.1.tgz", + "integrity": "sha512-gttYFNmlCjredsdnxqNC6ho0bx6zEwOqAwSKZNQXtsBqvSN1CjtzlTLY9Kfhvt14Co8Iu+qMuOOpnPIRjvvFtw==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=20.8.1" + } + }, "node_modules/mri": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz", diff --git a/frontend_nuxt/package.json b/frontend_nuxt/package.json index 31f873a29..935d6db93 100644 --- a/frontend_nuxt/package.json +++ b/frontend_nuxt/package.json @@ -13,8 +13,6 @@ }, "dependencies": { "@icon-park/vue-next": "^1.4.2", - "@ffmpeg/ffmpeg": "^0.12.15", - "@ffmpeg/util": "^0.12.2", "@nuxt/image": "^1.11.0", "@stomp/stompjs": "^7.0.0", "cropperjs": "^1.6.2", @@ -27,6 +25,7 @@ "ldrs": "^1.0.0", "markdown-it": "^14.1.0", "mermaid": "^10.9.4", + "mp4box": "^2.1.1", "nanoid": "^5.1.5", "nprogress": "^0.2.0", "nuxt": "latest", diff --git a/frontend_nuxt/plugins/ffmpeg.client.ts b/frontend_nuxt/plugins/ffmpeg.client.ts deleted file mode 100644 index 562a93aa2..000000000 --- a/frontend_nuxt/plugins/ffmpeg.client.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { FFmpeg } from '@ffmpeg/ffmpeg' -import { toBlobURL } from '@ffmpeg/util' -import { defineNuxtPlugin, useRuntimeConfig } from 'nuxt/app' - -let ffmpeg: FFmpeg | null = null - -export default defineNuxtPlugin(() => { - const { - public: { ffmpegVersion }, - } = useRuntimeConfig() - - return { - provide: { - ffmpeg: async () => { - if (ffmpeg) return ffmpeg - - ffmpeg = new FFmpeg() - - const mtOk = - typeof crossOriginIsolated !== 'undefined' && - crossOriginIsolated && - typeof SharedArrayBuffer !== 'undefined' - - const pkg = mtOk ? '@ffmpeg/core-mt' : '@ffmpeg/core-st' - const base = `https://unpkg.com/${pkg}@${ffmpegVersion}/dist/umd` - - await ffmpeg.load({ - coreURL: await toBlobURL(`${base}/ffmpeg-core.js`, 'text/javascript'), - wasmURL: await toBlobURL(`${base}/ffmpeg-core.wasm`, 'application/wasm'), - workerURL: await toBlobURL(`${base}/ffmpeg-core.worker.js`, 'text/javascript'), - }) - - return ffmpeg - }, - }, - } -}) diff --git a/frontend_nuxt/utils/ffmpegVideoCompressor.js b/frontend_nuxt/utils/ffmpegVideoCompressor.js deleted file mode 100644 index 2aa155049..000000000 --- a/frontend_nuxt/utils/ffmpegVideoCompressor.js +++ /dev/null @@ -1,327 +0,0 @@ -/** - * FFmpeg.wasm 视频压缩器 - * - * 用法: - * const { $ffmpeg } = useNuxtApp() - * const ff = await $ffmpeg() // 插件里已完成 ffmpeg.load() - * const out = await compressVideoWithFFmpeg(ff, file, { onProgress, strictSize: false }) - * - * 设计要点: - * - 本文件不再负责加载/初始化,只负责转码逻辑;和 Nuxt 插件解耦。 - * - 针对【同一个 ffmpeg 实例】做串行队列,避免并发 exec 踩内存文件系统。 - * - 使用 nanoid 生成唯一文件名;日志环形缓冲;默认 CRF+VBV,可选 strictSize(two-pass)。 - * - 体积明显小于目标时直通返回,减少无谓重编码。 - */ - -import { fetchFile } from '@ffmpeg/util' -import { nanoid } from 'nanoid' -import { UPLOAD_CONFIG } from '../config/uploadConfig.js' - -/************************* - * 每实例一个串行队列 * - *************************/ -// WeakMapPromise)[], running: boolean, resolvers: {res,rej}[] }> -const queues = new WeakMap() - -function enqueueOn(instance, taskFn) { - return new Promise((res, rej) => { - let st = queues.get(instance) - if (!st) { - st = { q: [], running: false, resolvers: [] } - queues.set(instance, st) - } - st.q.push(taskFn) - st.resolvers.push({ res, rej }) - drain(instance) - }) -} - -async function drain(instance) { - const st = queues.get(instance) - if (!st || st.running) return - st.running = true - try { - while (st.q.length) { - const task = st.q.shift() - const rr = st.resolvers.shift() - try { - rr.res(await task()) - } catch (e) { - rr.rej(e) - } - } - } finally { - st.running = false - } -} - -/***************** - * 工具函数 * - *****************/ -function decideScale(widthHint) { - if (!widthHint) return { filter: null, width: null } - const evenW = widthHint % 2 === 0 ? widthHint : widthHint - 1 - return { filter: `scale=${evenW}:-2:flags=bicubic,setsar=1`, width: evenW } -} - -function calculateParamsByRatio(originalSize, targetSize) { - const ratio = Math.min(targetSize / originalSize, 1) - const crf = ratio < 0.35 ? 29 : ratio < 0.5 ? 27 : ratio < 0.7 ? 25 : 23 - const preset = ratio < 0.35 ? 'slow' : ratio < 0.5 ? 'medium' : 'veryfast' - const s = - ratio < 0.35 - ? decideScale(720) - : ratio < 0.6 - ? decideScale(960) - : ratio < 0.8 - ? decideScale(1280) - : { filter: null, width: null } - const audioBitrateK = ratio < 0.5 ? 96 : ratio < 0.7 ? 128 : 160 - const profile = s.width && s.width <= 1280 ? 'main' : 'high' - return { crf, preset, scaleFilter: s.filter, scaleWidth: s.width, audioBitrateK, profile } -} - -function makeRingLogger(capBytes = 4000) { - const buf = [] - let total = 0 - function push(s) { - if (!s) return - buf.push(s) - total += s.length - while (total > capBytes) total -= buf.shift().length - } - return { push, dump: () => buf.slice() } -} - -function parseDurationFromLogs(logs) { - // 避免正则:查找 Duration: 后的 00:00:00.xx - const text = logs.join(' ') - const idx = text.indexOf('Duration:') - if (idx === -1) return null - let i = idx + 'Duration:'.length - while (i < text.length && text[i] === ' ') i++ - function read2(start) { - const a = text.charCodeAt(start) - 48 - const b = text.charCodeAt(start + 1) - 48 - if (a < 0 || a > 9 || b < 0 || b > 9) return null - return a * 10 + b - } - const hh = read2(i) - if (hh === null) return null - i += 2 - if (text[i++] !== ':') return null - const mm = read2(i) - if (mm === null) return null - i += 2 - if (text[i++] !== ':') return null - const s1 = read2(i) - if (s1 === null) return null - i += 2 - if (text[i++] !== '.') return null - let j = i - while (j < text.length && text.charCodeAt(j) >= 48 && text.charCodeAt(j) <= 57) j++ - const frac = parseFloat('0.' + text.slice(i, j) || '0') - return hh * 3600 + mm * 60 + s1 + frac -} - -export function isFFmpegSupported() { - return typeof WebAssembly !== 'undefined' && typeof Worker !== 'undefined' -} - -/** - * 读取 ffmpeg 核心版本(通过 -version),会进入队列避免并发冲突 - */ -export async function getFFmpegInfo(ffmpegInstance) { - return enqueueOn(ffmpegInstance, async () => { - const logs = [] - const onLog = ({ type, message }) => { - if (type === 'info' || type === 'fferr') logs.push(message) - } - ffmpegInstance.on('log', onLog) - try { - await ffmpegInstance.exec(['-version']) - } finally { - ffmpegInstance.off('log', onLog) - } - const line = logs.find((l) => l.toLowerCase().includes('ffmpeg version')) || '' - const parts = line.trim().split(' ').filter(Boolean) - const version = parts.length > 2 ? parts[2] : parts[1] || null - return { version } - }) -} - -/** - * 压缩:接受一个已经 load() 完成的 ffmpeg 实例 - * @param {*} ffmpegInstance 已初始化的 FFmpeg 实例(来自 Nuxt 插件) - * @param {File|Blob} file 输入文件 - * @param {{ onProgress?:(p:{stage:string,progress:number})=>void, signal?:AbortSignal, strictSize?:boolean, targetSize?:number }} opts - */ -export async function compressVideoWithFFmpeg(ffmpegInstance, file, opts = {}) { - return enqueueOn(ffmpegInstance, () => doCompress(ffmpegInstance, file, opts)) -} - -async function doCompress(ffmpegInstance, file, opts) { - const onProgress = opts.onProgress || (() => {}) - const { signal, strictSize = false } = opts - - onProgress({ stage: 'preparing', progress: 10 }) - - const targetSize = opts.targetSize ?? UPLOAD_CONFIG?.VIDEO?.TARGET_SIZE ?? 12 * 1024 * 1024 - - // 小体积直通 - const sizeKnown = 'size' in file && typeof file.size === 'number' - if (sizeKnown && file.size <= targetSize * 0.9) { - onProgress({ stage: 'skipped', progress: 100 }) - return file - } - - const params = calculateParamsByRatio(sizeKnown ? file.size : targetSize * 2, targetSize) - const { crf, preset, scaleFilter, audioBitrateK, profile } = params - - const name = 'name' in file && typeof file.name === 'string' ? file.name : 'input.mp4' - const dot = name.lastIndexOf('.') - const outName = (dot > -1 ? name.slice(0, dot) : name) + '.mp4' - - const ext = dot > -1 ? name.slice(dot + 1).toLowerCase() : 'mp4' - const id = nanoid() - const inputName = `input-${id}.${ext}` - const outputName = `output-${id}.mp4` - const passlog = `ffpass-${id}` - - // 监听 - const ring = makeRingLogger() - const onFfmpegProgress = ({ progress: p }) => { - const adjusted = 20 + p * 70 - onProgress({ stage: 'compressing', progress: Math.min(90, adjusted) }) - } - const onFfmpegLog = ({ type, message }) => { - if (type === 'fferr' || type === 'info') ring.push(message) - } - ffmpegInstance.on('progress', onFfmpegProgress) - ffmpegInstance.on('log', onFfmpegLog) - - let aborted = false - const abortHandler = () => { - aborted = true - } - if (signal) signal.addEventListener('abort', abortHandler, { once: true }) - - try { - await ffmpegInstance.writeFile(inputName, await fetchFile(file)) - onProgress({ stage: 'analyzing', progress: 20 }) - - let durationSec = null - try { - await ffmpegInstance.exec(['-hide_banner', '-i', inputName, '-f', 'null', '-']) - durationSec = parseDurationFromLogs(ring.dump()) - } catch { - durationSec = durationSec ?? parseDurationFromLogs(ring.dump()) - } - - let videoBitrate = null - if (durationSec && sizeKnown && targetSize < file.size) { - const totalTargetBits = targetSize * 8 - const audioBits = audioBitrateK * 1000 * durationSec - const maxVideoBits = Math.max(totalTargetBits - audioBits, totalTargetBits * 0.7) - const bps = Math.max(180000, Math.floor(maxVideoBits / durationSec)) - videoBitrate = String(Math.min(bps, 5000000)) - } - - const baseArgs = [ - '-hide_banner', - '-i', - inputName, - '-c:v', - 'libx264', - '-pix_fmt', - 'yuv420p', - '-profile:v', - profile, - '-movflags', - '+faststart', - '-preset', - preset, - '-c:a', - 'aac', - '-b:a', - `${audioBitrateK}k`, - '-ac', - '2', - ] - if (scaleFilter) baseArgs.push('-vf', scaleFilter) - - const onePassArgs = [...baseArgs, '-crf', String(crf)] - if (videoBitrate) - onePassArgs.push('-maxrate', videoBitrate, '-bufsize', String(parseInt(videoBitrate, 10) * 2)) - - const twoPassFirst = [ - '-y', - '-hide_banner', - '-i', - inputName, - '-c:v', - 'libx264', - '-b:v', - `${videoBitrate || '1000000'}`, - '-pass', - '1', - '-passlogfile', - passlog, - '-an', - '-f', - 'mp4', - '/dev/null', - ] - const twoPassSecond = [ - ...baseArgs, - '-b:v', - `${videoBitrate || '1000000'}`, - '-pass', - '2', - '-passlogfile', - passlog, - outputName, - ] - - if (aborted) throw new DOMException('Aborted', 'AbortError') - - if (!strictSize) { - await ffmpegInstance.exec([...onePassArgs, outputName]) - } else { - if (!videoBitrate) videoBitrate = '1000000' - await ffmpegInstance.exec(twoPassFirst) - onProgress({ stage: 'second-pass', progress: 85 }) - await ffmpegInstance.exec(twoPassSecond) - } - - if (aborted) throw new DOMException('Aborted', 'AbortError') - - onProgress({ stage: 'finalizing', progress: 95 }) - const out = await ffmpegInstance.readFile(outputName) - - const mime = 'video/mp4' - const blob = new Blob([out], { type: mime }) - const hasFileCtor = typeof File === 'function' - const result = hasFileCtor ? new File([blob], outName, { type: mime }) : blob - - onProgress({ stage: 'completed', progress: 100 }) - return result - } finally { - try { - await ffmpegInstance.deleteFile(inputName) - } catch {} - try { - await ffmpegInstance.deleteFile(outputName) - } catch {} - try { - await ffmpegInstance.deleteFile(`${passlog}-0.log`) - } catch {} - try { - await ffmpegInstance.deleteFile(`${passlog}-0.log.mbtree`) - } catch {} - - ffmpegInstance.off('progress', onFfmpegProgress) - ffmpegInstance.off('log', onFfmpegLog) - if (signal) signal.removeEventListener('abort', abortHandler) - } -} diff --git a/frontend_nuxt/utils/vditor.js b/frontend_nuxt/utils/vditor.js index c2c6d7d9a..dbe6ae2bb 100644 --- a/frontend_nuxt/utils/vditor.js +++ b/frontend_nuxt/utils/vditor.js @@ -121,14 +121,13 @@ export function createVditor(editorId, options = {}) { vditor.tip('视频压缩中...', 0) vditor.disabled() - // 使用 FFmpeg 压缩视频 + // 使用 WebCodecs 压缩视频 processedFile = await compressVideo(file, (progress) => { const messages = { - initializing: '初始化 FFmpeg', + initializing: '初始化编解码器', preparing: '准备压缩', - analyzing: '分析视频', compressing: '压缩中', - finalizing: '完成压缩', + packaging: '封装中', completed: '压缩完成', } const message = messages[progress.stage] || progress.stage diff --git a/frontend_nuxt/utils/videoCompressor.js b/frontend_nuxt/utils/videoCompressor.js index 584d8a487..943551283 100644 --- a/frontend_nuxt/utils/videoCompressor.js +++ b/frontend_nuxt/utils/videoCompressor.js @@ -1,11 +1,10 @@ /** - * 基于 FFmpeg.wasm 的视频压缩工具 + * 基于 WebCodecs + MP4Box.js 的视频压缩工具 * 专为现代浏览器 (Chrome/Safari) 优化 */ import { UPLOAD_CONFIG } from '../config/uploadConfig.js' -import { compressVideoWithFFmpeg, isFFmpegSupported } from './ffmpegVideoCompressor.js' -import { useNuxtApp } from '#app' +import { compressVideoWithWebCodecs, isWebCodecSupported } from './webcodecVideoCompressor.js' // 导出配置供外部使用 export const VIDEO_CONFIG = UPLOAD_CONFIG.VIDEO @@ -34,7 +33,7 @@ export function formatFileSize(bytes) { } /** - * 压缩视频文件 - 使用 FFmpeg.wasm + * 压缩视频文件 - 使用 WebCodecs */ export async function compressVideo(file, onProgress = () => {}) { // 检查是否需要压缩 @@ -44,36 +43,30 @@ export async function compressVideo(file, onProgress = () => {}) { return file } - // 检查 FFmpeg 支持 - if (!isFFmpegSupported()) { + // 检查 WebCodecs 支持 + if (!isWebCodecSupported()) { throw new Error('当前浏览器不支持视频压缩功能,请使用 Chrome 或 Safari 浏览器') } try { - const { $ffmpeg } = useNuxtApp() - const ff = await $ffmpeg() - return await compressVideoWithFFmpeg(ff, file, { onProgress }) + return await compressVideoWithWebCodecs(file, { onProgress }) } catch (error) { - console.error('FFmpeg 压缩失败:', error) + console.error('WebCodecs 压缩失败:', error) throw new Error(`视频压缩失败: ${error.message}`) } } /** - * 预加载 FFmpeg(可选的性能优化) + * 预加载 WebCodecs(可选的性能优化) */ export async function preloadVideoCompressor() { try { - // FFmpeg 初始化现在通过 Nuxt 插件处理 - // 这里只需要检查支持性 - if (!isFFmpegSupported()) { - throw new Error('当前浏览器不支持 FFmpeg') + if (!isWebCodecSupported()) { + throw new Error('当前浏览器不支持 WebCodecs') } - const { $ffmpeg } = useNuxtApp() - await $ffmpeg() - return { success: true, message: 'FFmpeg 预加载成功' } + return { success: true, message: 'WebCodecs 可用' } } catch (error) { - console.warn('FFmpeg 预加载失败:', error) + console.warn('WebCodecs 预加载失败:', error) return { success: false, error: error.message } } } diff --git a/frontend_nuxt/utils/webcodecVideoCompressor.js b/frontend_nuxt/utils/webcodecVideoCompressor.js new file mode 100644 index 000000000..eef17e2e6 --- /dev/null +++ b/frontend_nuxt/utils/webcodecVideoCompressor.js @@ -0,0 +1,108 @@ +/** + * WebCodecs + MP4Box.js video compressor + * Simplified transcoding using browser WebCodecs API + */ +import { createFile } from 'mp4box' +import { UPLOAD_CONFIG } from '../config/uploadConfig.js' + +export function isWebCodecSupported() { + return ( + typeof window !== 'undefined' && + 'VideoEncoder' in window && + 'MediaStreamTrackProcessor' in window && + 'VideoFrame' in window + ) +} + +/** + * Compress a video File using WebCodecs and MP4Box.js + * @param {File} file original video file + * @param {Object} options optional callbacks + * @param {Function} options.onProgress progress callback + * @returns {Promise} compressed file + */ +export async function compressVideoWithWebCodecs(file, { onProgress = () => {} } = {}) { + if (!isWebCodecSupported()) { + throw new Error('当前浏览器不支持 WebCodecs') + } + + onProgress({ stage: 'initializing', progress: 0 }) + + const url = URL.createObjectURL(file) + const video = document.createElement('video') + video.src = url + await video.play() + video.pause() + + onProgress({ stage: 'preparing', progress: 10 }) + + const stream = video.captureStream() + const track = stream.getVideoTracks()[0] + const processor = new MediaStreamTrackProcessor({ track }) + const reader = processor.readable.getReader() + + const { width, height, frameRate = 30 } = track.getSettings() + const bitrate = UPLOAD_CONFIG.VIDEO.TARGET_BITRATE || 1_000_000 + + const chunks = [] + const encoder = new VideoEncoder({ + output: (chunk) => { + const copy = new Uint8Array(chunk.byteLength) + chunk.copyTo(copy) + chunks.push({ type: chunk.type, timestamp: chunk.timestamp, data: copy }) + }, + error: (e) => console.error('编码失败', e), + }) + + encoder.configure({ + codec: 'avc1.42001E', + width, + height, + bitrate, + framerate: frameRate, + }) + + let processed = 0 + const totalFrames = Math.ceil(video.duration * frameRate) + + while (true) { + const { done, value } = await reader.read() + if (done) break + encoder.encode(value) + value.close() + processed++ + onProgress({ stage: 'compressing', progress: Math.round((processed / totalFrames) * 80) }) + } + + await encoder.flush() + + onProgress({ stage: 'packaging', progress: 90 }) + + const mp4 = createFile() + const trackId = mp4.addTrack({ + id: 1, + type: 'avc1', + width, + height, + timescale: frameRate, + }) + + chunks.forEach((chunk) => { + mp4.addSample(trackId, chunk.data.buffer, { + duration: 1, + dts: chunk.timestamp, + cts: 0, + is_sync: chunk.type === 'key', + }) + }) + + const streamOut = mp4.getBuffer() + const outBuffer = streamOut.buffer.slice(0, streamOut.position) + const outFile = new File([outBuffer], file.name.replace(/\.[^.]+$/, '.mp4'), { + type: 'video/mp4', + }) + + onProgress({ stage: 'completed', progress: 100 }) + + return outFile +} From 90bd41e74014fc1334408098ea41f4a787f9d047 Mon Sep 17 00:00:00 2001 From: tim Date: Thu, 11 Sep 2025 17:20:08 +0800 Subject: [PATCH 04/26] Revert "feat: switch video compression to webcodecs" This reverts commit 3f35add587da23d025fa1bded3cf53cd619c07c4. --- frontend_nuxt/nuxt.config.ts | 14 + frontend_nuxt/package-lock.json | 42 ++- frontend_nuxt/package.json | 3 +- frontend_nuxt/plugins/ffmpeg.client.ts | 37 ++ frontend_nuxt/utils/ffmpegVideoCompressor.js | 327 ++++++++++++++++++ frontend_nuxt/utils/vditor.js | 7 +- frontend_nuxt/utils/videoCompressor.js | 31 +- .../utils/webcodecVideoCompressor.js | 108 ------ 8 files changed, 435 insertions(+), 134 deletions(-) create mode 100644 frontend_nuxt/plugins/ffmpeg.client.ts create mode 100644 frontend_nuxt/utils/ffmpegVideoCompressor.js delete mode 100644 frontend_nuxt/utils/webcodecVideoCompressor.js diff --git a/frontend_nuxt/nuxt.config.ts b/frontend_nuxt/nuxt.config.ts index f0adf3c98..dad43963c 100644 --- a/frontend_nuxt/nuxt.config.ts +++ b/frontend_nuxt/nuxt.config.ts @@ -1,4 +1,17 @@ import { defineNuxtConfig } from 'nuxt/config' +import { createRequire } from 'node:module' + +const require = createRequire(import.meta.url) +const appPkg = require('./package.json') as { + dependencies?: Record + devDependencies?: Record +} +const ffmpegVersion = ( + process.env.NUXT_PUBLIC_FFMPEG_VERSION || + appPkg.dependencies?.['@ffmpeg/ffmpeg'] || + appPkg.devDependencies?.['@ffmpeg/ffmpeg'] || + '0.12.15' +).replace(/^[^\d]*/, '') export default defineNuxtConfig({ devServer: { host: '0.0.0.0', @@ -16,6 +29,7 @@ export default defineNuxtConfig({ discordClientId: process.env.NUXT_PUBLIC_DISCORD_CLIENT_ID || '', twitterClientId: process.env.NUXT_PUBLIC_TWITTER_CLIENT_ID || '', telegramBotId: process.env.NUXT_PUBLIC_TELEGRAM_BOT_ID || '', + ffmpegVersion, }, }, css: [ diff --git a/frontend_nuxt/package-lock.json b/frontend_nuxt/package-lock.json index a7a28be3d..39770a80c 100644 --- a/frontend_nuxt/package-lock.json +++ b/frontend_nuxt/package-lock.json @@ -6,6 +6,8 @@ "": { "name": "frontend_nuxt", "dependencies": { + "@ffmpeg/ffmpeg": "^0.12.15", + "@ffmpeg/util": "^0.12.2", "@icon-park/vue-next": "^1.4.2", "@nuxt/image": "^1.11.0", "@stomp/stompjs": "^7.0.0", @@ -19,7 +21,6 @@ "ldrs": "^1.0.0", "markdown-it": "^14.1.0", "mermaid": "^10.9.4", - "mp4box": "^2.1.1", "nanoid": "^5.1.5", "nprogress": "^0.2.0", "nuxt": "latest", @@ -998,6 +999,36 @@ "integrity": "sha512-m9FVDXU3GT2ITSe0UaMA5rU3QkfC/UXtCU8y0gSN/GugTqtVldOBWIB5V6V3sbmenVZUIpU6f+mPEO2+m5iTaA==", "license": "MIT" }, + "node_modules/@ffmpeg/ffmpeg": { + "version": "0.12.15", + "resolved": "https://registry.npmmirror.com/@ffmpeg/ffmpeg/-/ffmpeg-0.12.15.tgz", + "integrity": "sha512-1C8Obr4GsN3xw+/1Ww6PFM84wSQAGsdoTuTWPOj2OizsRDLT4CXTaVjPhkw6ARyDus1B9X/L2LiXHqYYsGnRFw==", + "license": "MIT", + "dependencies": { + "@ffmpeg/types": "^0.12.4" + }, + "engines": { + "node": ">=18.x" + } + }, + "node_modules/@ffmpeg/types": { + "version": "0.12.4", + "resolved": "https://registry.npmmirror.com/@ffmpeg/types/-/types-0.12.4.tgz", + "integrity": "sha512-k9vJQNBGTxE5AhYDtOYR5rO5fKsspbg51gbcwtbkw2lCdoIILzklulcjJfIDwrtn7XhDeF2M+THwJ2FGrLeV6A==", + "license": "MIT", + "engines": { + "node": ">=16.x" + } + }, + "node_modules/@ffmpeg/util": { + "version": "0.12.2", + "resolved": "https://registry.npmmirror.com/@ffmpeg/util/-/util-0.12.2.tgz", + "integrity": "sha512-ouyoW+4JB7WxjeZ2y6KpRvB+dLp7Cp4ro8z0HIVpZVCM7AwFlHa0c4R8Y/a4M3wMqATpYKhC7lSFHQ0T11MEDw==", + "license": "MIT", + "engines": { + "node": ">=18.x" + } + }, "node_modules/@icon-park/vue-next": { "version": "1.4.2", "resolved": "https://registry.npmmirror.com/@icon-park/vue-next/-/vue-next-1.4.2.tgz", @@ -10141,15 +10172,6 @@ "node": ">=18" } }, - "node_modules/mp4box": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/mp4box/-/mp4box-2.1.1.tgz", - "integrity": "sha512-gttYFNmlCjredsdnxqNC6ho0bx6zEwOqAwSKZNQXtsBqvSN1CjtzlTLY9Kfhvt14Co8Iu+qMuOOpnPIRjvvFtw==", - "license": "BSD-3-Clause", - "engines": { - "node": ">=20.8.1" - } - }, "node_modules/mri": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz", diff --git a/frontend_nuxt/package.json b/frontend_nuxt/package.json index 935d6db93..31f873a29 100644 --- a/frontend_nuxt/package.json +++ b/frontend_nuxt/package.json @@ -13,6 +13,8 @@ }, "dependencies": { "@icon-park/vue-next": "^1.4.2", + "@ffmpeg/ffmpeg": "^0.12.15", + "@ffmpeg/util": "^0.12.2", "@nuxt/image": "^1.11.0", "@stomp/stompjs": "^7.0.0", "cropperjs": "^1.6.2", @@ -25,7 +27,6 @@ "ldrs": "^1.0.0", "markdown-it": "^14.1.0", "mermaid": "^10.9.4", - "mp4box": "^2.1.1", "nanoid": "^5.1.5", "nprogress": "^0.2.0", "nuxt": "latest", diff --git a/frontend_nuxt/plugins/ffmpeg.client.ts b/frontend_nuxt/plugins/ffmpeg.client.ts new file mode 100644 index 000000000..562a93aa2 --- /dev/null +++ b/frontend_nuxt/plugins/ffmpeg.client.ts @@ -0,0 +1,37 @@ +import { FFmpeg } from '@ffmpeg/ffmpeg' +import { toBlobURL } from '@ffmpeg/util' +import { defineNuxtPlugin, useRuntimeConfig } from 'nuxt/app' + +let ffmpeg: FFmpeg | null = null + +export default defineNuxtPlugin(() => { + const { + public: { ffmpegVersion }, + } = useRuntimeConfig() + + return { + provide: { + ffmpeg: async () => { + if (ffmpeg) return ffmpeg + + ffmpeg = new FFmpeg() + + const mtOk = + typeof crossOriginIsolated !== 'undefined' && + crossOriginIsolated && + typeof SharedArrayBuffer !== 'undefined' + + const pkg = mtOk ? '@ffmpeg/core-mt' : '@ffmpeg/core-st' + const base = `https://unpkg.com/${pkg}@${ffmpegVersion}/dist/umd` + + await ffmpeg.load({ + coreURL: await toBlobURL(`${base}/ffmpeg-core.js`, 'text/javascript'), + wasmURL: await toBlobURL(`${base}/ffmpeg-core.wasm`, 'application/wasm'), + workerURL: await toBlobURL(`${base}/ffmpeg-core.worker.js`, 'text/javascript'), + }) + + return ffmpeg + }, + }, + } +}) diff --git a/frontend_nuxt/utils/ffmpegVideoCompressor.js b/frontend_nuxt/utils/ffmpegVideoCompressor.js new file mode 100644 index 000000000..2aa155049 --- /dev/null +++ b/frontend_nuxt/utils/ffmpegVideoCompressor.js @@ -0,0 +1,327 @@ +/** + * FFmpeg.wasm 视频压缩器 + * + * 用法: + * const { $ffmpeg } = useNuxtApp() + * const ff = await $ffmpeg() // 插件里已完成 ffmpeg.load() + * const out = await compressVideoWithFFmpeg(ff, file, { onProgress, strictSize: false }) + * + * 设计要点: + * - 本文件不再负责加载/初始化,只负责转码逻辑;和 Nuxt 插件解耦。 + * - 针对【同一个 ffmpeg 实例】做串行队列,避免并发 exec 踩内存文件系统。 + * - 使用 nanoid 生成唯一文件名;日志环形缓冲;默认 CRF+VBV,可选 strictSize(two-pass)。 + * - 体积明显小于目标时直通返回,减少无谓重编码。 + */ + +import { fetchFile } from '@ffmpeg/util' +import { nanoid } from 'nanoid' +import { UPLOAD_CONFIG } from '../config/uploadConfig.js' + +/************************* + * 每实例一个串行队列 * + *************************/ +// WeakMapPromise)[], running: boolean, resolvers: {res,rej}[] }> +const queues = new WeakMap() + +function enqueueOn(instance, taskFn) { + return new Promise((res, rej) => { + let st = queues.get(instance) + if (!st) { + st = { q: [], running: false, resolvers: [] } + queues.set(instance, st) + } + st.q.push(taskFn) + st.resolvers.push({ res, rej }) + drain(instance) + }) +} + +async function drain(instance) { + const st = queues.get(instance) + if (!st || st.running) return + st.running = true + try { + while (st.q.length) { + const task = st.q.shift() + const rr = st.resolvers.shift() + try { + rr.res(await task()) + } catch (e) { + rr.rej(e) + } + } + } finally { + st.running = false + } +} + +/***************** + * 工具函数 * + *****************/ +function decideScale(widthHint) { + if (!widthHint) return { filter: null, width: null } + const evenW = widthHint % 2 === 0 ? widthHint : widthHint - 1 + return { filter: `scale=${evenW}:-2:flags=bicubic,setsar=1`, width: evenW } +} + +function calculateParamsByRatio(originalSize, targetSize) { + const ratio = Math.min(targetSize / originalSize, 1) + const crf = ratio < 0.35 ? 29 : ratio < 0.5 ? 27 : ratio < 0.7 ? 25 : 23 + const preset = ratio < 0.35 ? 'slow' : ratio < 0.5 ? 'medium' : 'veryfast' + const s = + ratio < 0.35 + ? decideScale(720) + : ratio < 0.6 + ? decideScale(960) + : ratio < 0.8 + ? decideScale(1280) + : { filter: null, width: null } + const audioBitrateK = ratio < 0.5 ? 96 : ratio < 0.7 ? 128 : 160 + const profile = s.width && s.width <= 1280 ? 'main' : 'high' + return { crf, preset, scaleFilter: s.filter, scaleWidth: s.width, audioBitrateK, profile } +} + +function makeRingLogger(capBytes = 4000) { + const buf = [] + let total = 0 + function push(s) { + if (!s) return + buf.push(s) + total += s.length + while (total > capBytes) total -= buf.shift().length + } + return { push, dump: () => buf.slice() } +} + +function parseDurationFromLogs(logs) { + // 避免正则:查找 Duration: 后的 00:00:00.xx + const text = logs.join(' ') + const idx = text.indexOf('Duration:') + if (idx === -1) return null + let i = idx + 'Duration:'.length + while (i < text.length && text[i] === ' ') i++ + function read2(start) { + const a = text.charCodeAt(start) - 48 + const b = text.charCodeAt(start + 1) - 48 + if (a < 0 || a > 9 || b < 0 || b > 9) return null + return a * 10 + b + } + const hh = read2(i) + if (hh === null) return null + i += 2 + if (text[i++] !== ':') return null + const mm = read2(i) + if (mm === null) return null + i += 2 + if (text[i++] !== ':') return null + const s1 = read2(i) + if (s1 === null) return null + i += 2 + if (text[i++] !== '.') return null + let j = i + while (j < text.length && text.charCodeAt(j) >= 48 && text.charCodeAt(j) <= 57) j++ + const frac = parseFloat('0.' + text.slice(i, j) || '0') + return hh * 3600 + mm * 60 + s1 + frac +} + +export function isFFmpegSupported() { + return typeof WebAssembly !== 'undefined' && typeof Worker !== 'undefined' +} + +/** + * 读取 ffmpeg 核心版本(通过 -version),会进入队列避免并发冲突 + */ +export async function getFFmpegInfo(ffmpegInstance) { + return enqueueOn(ffmpegInstance, async () => { + const logs = [] + const onLog = ({ type, message }) => { + if (type === 'info' || type === 'fferr') logs.push(message) + } + ffmpegInstance.on('log', onLog) + try { + await ffmpegInstance.exec(['-version']) + } finally { + ffmpegInstance.off('log', onLog) + } + const line = logs.find((l) => l.toLowerCase().includes('ffmpeg version')) || '' + const parts = line.trim().split(' ').filter(Boolean) + const version = parts.length > 2 ? parts[2] : parts[1] || null + return { version } + }) +} + +/** + * 压缩:接受一个已经 load() 完成的 ffmpeg 实例 + * @param {*} ffmpegInstance 已初始化的 FFmpeg 实例(来自 Nuxt 插件) + * @param {File|Blob} file 输入文件 + * @param {{ onProgress?:(p:{stage:string,progress:number})=>void, signal?:AbortSignal, strictSize?:boolean, targetSize?:number }} opts + */ +export async function compressVideoWithFFmpeg(ffmpegInstance, file, opts = {}) { + return enqueueOn(ffmpegInstance, () => doCompress(ffmpegInstance, file, opts)) +} + +async function doCompress(ffmpegInstance, file, opts) { + const onProgress = opts.onProgress || (() => {}) + const { signal, strictSize = false } = opts + + onProgress({ stage: 'preparing', progress: 10 }) + + const targetSize = opts.targetSize ?? UPLOAD_CONFIG?.VIDEO?.TARGET_SIZE ?? 12 * 1024 * 1024 + + // 小体积直通 + const sizeKnown = 'size' in file && typeof file.size === 'number' + if (sizeKnown && file.size <= targetSize * 0.9) { + onProgress({ stage: 'skipped', progress: 100 }) + return file + } + + const params = calculateParamsByRatio(sizeKnown ? file.size : targetSize * 2, targetSize) + const { crf, preset, scaleFilter, audioBitrateK, profile } = params + + const name = 'name' in file && typeof file.name === 'string' ? file.name : 'input.mp4' + const dot = name.lastIndexOf('.') + const outName = (dot > -1 ? name.slice(0, dot) : name) + '.mp4' + + const ext = dot > -1 ? name.slice(dot + 1).toLowerCase() : 'mp4' + const id = nanoid() + const inputName = `input-${id}.${ext}` + const outputName = `output-${id}.mp4` + const passlog = `ffpass-${id}` + + // 监听 + const ring = makeRingLogger() + const onFfmpegProgress = ({ progress: p }) => { + const adjusted = 20 + p * 70 + onProgress({ stage: 'compressing', progress: Math.min(90, adjusted) }) + } + const onFfmpegLog = ({ type, message }) => { + if (type === 'fferr' || type === 'info') ring.push(message) + } + ffmpegInstance.on('progress', onFfmpegProgress) + ffmpegInstance.on('log', onFfmpegLog) + + let aborted = false + const abortHandler = () => { + aborted = true + } + if (signal) signal.addEventListener('abort', abortHandler, { once: true }) + + try { + await ffmpegInstance.writeFile(inputName, await fetchFile(file)) + onProgress({ stage: 'analyzing', progress: 20 }) + + let durationSec = null + try { + await ffmpegInstance.exec(['-hide_banner', '-i', inputName, '-f', 'null', '-']) + durationSec = parseDurationFromLogs(ring.dump()) + } catch { + durationSec = durationSec ?? parseDurationFromLogs(ring.dump()) + } + + let videoBitrate = null + if (durationSec && sizeKnown && targetSize < file.size) { + const totalTargetBits = targetSize * 8 + const audioBits = audioBitrateK * 1000 * durationSec + const maxVideoBits = Math.max(totalTargetBits - audioBits, totalTargetBits * 0.7) + const bps = Math.max(180000, Math.floor(maxVideoBits / durationSec)) + videoBitrate = String(Math.min(bps, 5000000)) + } + + const baseArgs = [ + '-hide_banner', + '-i', + inputName, + '-c:v', + 'libx264', + '-pix_fmt', + 'yuv420p', + '-profile:v', + profile, + '-movflags', + '+faststart', + '-preset', + preset, + '-c:a', + 'aac', + '-b:a', + `${audioBitrateK}k`, + '-ac', + '2', + ] + if (scaleFilter) baseArgs.push('-vf', scaleFilter) + + const onePassArgs = [...baseArgs, '-crf', String(crf)] + if (videoBitrate) + onePassArgs.push('-maxrate', videoBitrate, '-bufsize', String(parseInt(videoBitrate, 10) * 2)) + + const twoPassFirst = [ + '-y', + '-hide_banner', + '-i', + inputName, + '-c:v', + 'libx264', + '-b:v', + `${videoBitrate || '1000000'}`, + '-pass', + '1', + '-passlogfile', + passlog, + '-an', + '-f', + 'mp4', + '/dev/null', + ] + const twoPassSecond = [ + ...baseArgs, + '-b:v', + `${videoBitrate || '1000000'}`, + '-pass', + '2', + '-passlogfile', + passlog, + outputName, + ] + + if (aborted) throw new DOMException('Aborted', 'AbortError') + + if (!strictSize) { + await ffmpegInstance.exec([...onePassArgs, outputName]) + } else { + if (!videoBitrate) videoBitrate = '1000000' + await ffmpegInstance.exec(twoPassFirst) + onProgress({ stage: 'second-pass', progress: 85 }) + await ffmpegInstance.exec(twoPassSecond) + } + + if (aborted) throw new DOMException('Aborted', 'AbortError') + + onProgress({ stage: 'finalizing', progress: 95 }) + const out = await ffmpegInstance.readFile(outputName) + + const mime = 'video/mp4' + const blob = new Blob([out], { type: mime }) + const hasFileCtor = typeof File === 'function' + const result = hasFileCtor ? new File([blob], outName, { type: mime }) : blob + + onProgress({ stage: 'completed', progress: 100 }) + return result + } finally { + try { + await ffmpegInstance.deleteFile(inputName) + } catch {} + try { + await ffmpegInstance.deleteFile(outputName) + } catch {} + try { + await ffmpegInstance.deleteFile(`${passlog}-0.log`) + } catch {} + try { + await ffmpegInstance.deleteFile(`${passlog}-0.log.mbtree`) + } catch {} + + ffmpegInstance.off('progress', onFfmpegProgress) + ffmpegInstance.off('log', onFfmpegLog) + if (signal) signal.removeEventListener('abort', abortHandler) + } +} diff --git a/frontend_nuxt/utils/vditor.js b/frontend_nuxt/utils/vditor.js index dbe6ae2bb..c2c6d7d9a 100644 --- a/frontend_nuxt/utils/vditor.js +++ b/frontend_nuxt/utils/vditor.js @@ -121,13 +121,14 @@ export function createVditor(editorId, options = {}) { vditor.tip('视频压缩中...', 0) vditor.disabled() - // 使用 WebCodecs 压缩视频 + // 使用 FFmpeg 压缩视频 processedFile = await compressVideo(file, (progress) => { const messages = { - initializing: '初始化编解码器', + initializing: '初始化 FFmpeg', preparing: '准备压缩', + analyzing: '分析视频', compressing: '压缩中', - packaging: '封装中', + finalizing: '完成压缩', completed: '压缩完成', } const message = messages[progress.stage] || progress.stage diff --git a/frontend_nuxt/utils/videoCompressor.js b/frontend_nuxt/utils/videoCompressor.js index 943551283..584d8a487 100644 --- a/frontend_nuxt/utils/videoCompressor.js +++ b/frontend_nuxt/utils/videoCompressor.js @@ -1,10 +1,11 @@ /** - * 基于 WebCodecs + MP4Box.js 的视频压缩工具 + * 基于 FFmpeg.wasm 的视频压缩工具 * 专为现代浏览器 (Chrome/Safari) 优化 */ import { UPLOAD_CONFIG } from '../config/uploadConfig.js' -import { compressVideoWithWebCodecs, isWebCodecSupported } from './webcodecVideoCompressor.js' +import { compressVideoWithFFmpeg, isFFmpegSupported } from './ffmpegVideoCompressor.js' +import { useNuxtApp } from '#app' // 导出配置供外部使用 export const VIDEO_CONFIG = UPLOAD_CONFIG.VIDEO @@ -33,7 +34,7 @@ export function formatFileSize(bytes) { } /** - * 压缩视频文件 - 使用 WebCodecs + * 压缩视频文件 - 使用 FFmpeg.wasm */ export async function compressVideo(file, onProgress = () => {}) { // 检查是否需要压缩 @@ -43,30 +44,36 @@ export async function compressVideo(file, onProgress = () => {}) { return file } - // 检查 WebCodecs 支持 - if (!isWebCodecSupported()) { + // 检查 FFmpeg 支持 + if (!isFFmpegSupported()) { throw new Error('当前浏览器不支持视频压缩功能,请使用 Chrome 或 Safari 浏览器') } try { - return await compressVideoWithWebCodecs(file, { onProgress }) + const { $ffmpeg } = useNuxtApp() + const ff = await $ffmpeg() + return await compressVideoWithFFmpeg(ff, file, { onProgress }) } catch (error) { - console.error('WebCodecs 压缩失败:', error) + console.error('FFmpeg 压缩失败:', error) throw new Error(`视频压缩失败: ${error.message}`) } } /** - * 预加载 WebCodecs(可选的性能优化) + * 预加载 FFmpeg(可选的性能优化) */ export async function preloadVideoCompressor() { try { - if (!isWebCodecSupported()) { - throw new Error('当前浏览器不支持 WebCodecs') + // FFmpeg 初始化现在通过 Nuxt 插件处理 + // 这里只需要检查支持性 + if (!isFFmpegSupported()) { + throw new Error('当前浏览器不支持 FFmpeg') } - return { success: true, message: 'WebCodecs 可用' } + const { $ffmpeg } = useNuxtApp() + await $ffmpeg() + return { success: true, message: 'FFmpeg 预加载成功' } } catch (error) { - console.warn('WebCodecs 预加载失败:', error) + console.warn('FFmpeg 预加载失败:', error) return { success: false, error: error.message } } } diff --git a/frontend_nuxt/utils/webcodecVideoCompressor.js b/frontend_nuxt/utils/webcodecVideoCompressor.js deleted file mode 100644 index eef17e2e6..000000000 --- a/frontend_nuxt/utils/webcodecVideoCompressor.js +++ /dev/null @@ -1,108 +0,0 @@ -/** - * WebCodecs + MP4Box.js video compressor - * Simplified transcoding using browser WebCodecs API - */ -import { createFile } from 'mp4box' -import { UPLOAD_CONFIG } from '../config/uploadConfig.js' - -export function isWebCodecSupported() { - return ( - typeof window !== 'undefined' && - 'VideoEncoder' in window && - 'MediaStreamTrackProcessor' in window && - 'VideoFrame' in window - ) -} - -/** - * Compress a video File using WebCodecs and MP4Box.js - * @param {File} file original video file - * @param {Object} options optional callbacks - * @param {Function} options.onProgress progress callback - * @returns {Promise} compressed file - */ -export async function compressVideoWithWebCodecs(file, { onProgress = () => {} } = {}) { - if (!isWebCodecSupported()) { - throw new Error('当前浏览器不支持 WebCodecs') - } - - onProgress({ stage: 'initializing', progress: 0 }) - - const url = URL.createObjectURL(file) - const video = document.createElement('video') - video.src = url - await video.play() - video.pause() - - onProgress({ stage: 'preparing', progress: 10 }) - - const stream = video.captureStream() - const track = stream.getVideoTracks()[0] - const processor = new MediaStreamTrackProcessor({ track }) - const reader = processor.readable.getReader() - - const { width, height, frameRate = 30 } = track.getSettings() - const bitrate = UPLOAD_CONFIG.VIDEO.TARGET_BITRATE || 1_000_000 - - const chunks = [] - const encoder = new VideoEncoder({ - output: (chunk) => { - const copy = new Uint8Array(chunk.byteLength) - chunk.copyTo(copy) - chunks.push({ type: chunk.type, timestamp: chunk.timestamp, data: copy }) - }, - error: (e) => console.error('编码失败', e), - }) - - encoder.configure({ - codec: 'avc1.42001E', - width, - height, - bitrate, - framerate: frameRate, - }) - - let processed = 0 - const totalFrames = Math.ceil(video.duration * frameRate) - - while (true) { - const { done, value } = await reader.read() - if (done) break - encoder.encode(value) - value.close() - processed++ - onProgress({ stage: 'compressing', progress: Math.round((processed / totalFrames) * 80) }) - } - - await encoder.flush() - - onProgress({ stage: 'packaging', progress: 90 }) - - const mp4 = createFile() - const trackId = mp4.addTrack({ - id: 1, - type: 'avc1', - width, - height, - timescale: frameRate, - }) - - chunks.forEach((chunk) => { - mp4.addSample(trackId, chunk.data.buffer, { - duration: 1, - dts: chunk.timestamp, - cts: 0, - is_sync: chunk.type === 'key', - }) - }) - - const streamOut = mp4.getBuffer() - const outBuffer = streamOut.buffer.slice(0, streamOut.position) - const outFile = new File([outBuffer], file.name.replace(/\.[^.]+$/, '.mp4'), { - type: 'video/mp4', - }) - - onProgress({ stage: 'completed', progress: 100 }) - - return outFile -} From 9421d004d4f4ba182cedd8cc9c58e58a930e2f87 Mon Sep 17 00:00:00 2001 From: jiahaosheng Date: Thu, 11 Sep 2025 17:27:54 +0800 Subject: [PATCH 05/26] =?UTF-8?q?feat(MessageEditor):=20=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E5=8F=91=E9=80=81=E6=B6=88=E6=81=AF=E7=9A=84=E5=BF=AB=E6=8D=B7?= =?UTF-8?q?=E9=94=AE=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend_nuxt/components/MessageEditor.vue | 45 +++++++++++++++++++++- frontend_nuxt/utils/is.js | 28 ++++++++++++++ 2 files changed, 71 insertions(+), 2 deletions(-) create mode 100644 frontend_nuxt/utils/is.js diff --git a/frontend_nuxt/components/MessageEditor.vue b/frontend_nuxt/components/MessageEditor.vue index ae3fbc9b3..e42331dd8 100644 --- a/frontend_nuxt/components/MessageEditor.vue +++ b/frontend_nuxt/components/MessageEditor.vue @@ -5,7 +5,10 @@
- +
@@ -21,6 +24,8 @@ import { getEditorTheme as getEditorThemeUtil, getPreviewTheme as getPreviewThemeUtil, } from '~/utils/vditor' +import { useIsMobile } from '~/utils/screen' +import { isMac } from '~/utils/is' import '~/assets/global.css' export default { @@ -44,6 +49,7 @@ export default { const vditorInstance = ref(null) const text = ref('') const editorId = ref(props.editorId) + const isMobile = useIsMobile() if (!editorId.value) { editorId.value = 'editor-' + useId() } @@ -84,6 +90,28 @@ export default { applyTheme() }, }) + + // 不是手机的情况下不添加快捷键 + if (!isMobile.value) { + // 添加快捷键监听 (Ctrl+Enter 或 Cmd+Enter) + const handleKeydown = (e) => { + if ((e.ctrlKey || e.metaKey) && e.key === 'Enter') { + e.preventDefault() + submit() + } + } + + const el = document.getElementById(editorId.value) + if (el) { + el.addEventListener('keydown', handleKeydown) + } + + onUnmounted(() => { + if (el) { + el.removeEventListener('keydown', handleKeydown) + } + }) + } }) onUnmounted(() => { @@ -121,7 +149,7 @@ export default { }, ) - return { submit, isDisabled, editorId } + return { submit, isDisabled, editorId, isMac, isMobile } }, } @@ -168,4 +196,17 @@ export default { .message-submit:not(.disabled):hover { background-color: var(--primary-color-hover); } + +/** 评论按钮快捷键样式 */ +.shortcut-icon { + padding: 2px 6px; + border-radius: 6px; + font-size: 12px; + font-weight: 500; + line-height: 1.2; + background-color: rgba(0, 0, 0, 0.25); +} +.comment-submit.disabled .shortcut-icon { + background-color: rgba(0, 0, 0, 0); +} diff --git a/frontend_nuxt/utils/is.js b/frontend_nuxt/utils/is.js new file mode 100644 index 000000000..e286a6a45 --- /dev/null +++ b/frontend_nuxt/utils/is.js @@ -0,0 +1,28 @@ +export const isClient = typeof window !== 'undefined' && typeof document !== 'undefined' + +export const isMac = getIsMac() + +function getIsMac() { + if (!isClient) { + return false + } + + try { + // 优先使用现代浏览器的 navigator.userAgentData API + if (navigator.userAgentData && navigator.userAgentData.platform) { + return navigator.userAgentData.platform === 'macOS' + } + + // 降级到传统的 User-Agent 检测 + if (navigator.userAgent) { + return /Mac|iPhone|iPad|iPod/i.test(navigator.userAgent) + } + + // 默认返回false + return false + } catch (error) { + // 异常处理,记录错误并返回默认值 + console.warn('检测Mac设备时发生错误:', error) + return false + } +} From dc6478527914faf2d81b34e084101e51d8a59665 Mon Sep 17 00:00:00 2001 From: jiahaosheng Date: Thu, 11 Sep 2025 17:53:08 +0800 Subject: [PATCH 06/26] feat: rename is.js to device.js --- frontend_nuxt/components/MessageEditor.vue | 2 +- frontend_nuxt/utils/{is.js => device.js} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename frontend_nuxt/utils/{is.js => device.js} (100%) diff --git a/frontend_nuxt/components/MessageEditor.vue b/frontend_nuxt/components/MessageEditor.vue index e42331dd8..c1ee6e7d5 100644 --- a/frontend_nuxt/components/MessageEditor.vue +++ b/frontend_nuxt/components/MessageEditor.vue @@ -25,7 +25,7 @@ import { getPreviewTheme as getPreviewThemeUtil, } from '~/utils/vditor' import { useIsMobile } from '~/utils/screen' -import { isMac } from '~/utils/is' +import { isMac } from '~/utils/device' import '~/assets/global.css' export default { diff --git a/frontend_nuxt/utils/is.js b/frontend_nuxt/utils/device.js similarity index 100% rename from frontend_nuxt/utils/is.js rename to frontend_nuxt/utils/device.js From ea079e8b8a7ef247cf5bf5db1aae0d6b06de46ea Mon Sep 17 00:00:00 2001 From: tim Date: Thu, 11 Sep 2025 18:36:47 +0800 Subject: [PATCH 07/26] =?UTF-8?q?fix:=20=E7=AE=80=E5=8C=96ffmpeg=E9=85=8D?= =?UTF-8?q?=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend_nuxt/.env.example | 5 - frontend_nuxt/config/uploadConfig.js | 45 +- frontend_nuxt/nuxt.config.ts | 36 +- frontend_nuxt/package-lock.json | 2325 +----------------------- frontend_nuxt/package.json | 2 +- frontend_nuxt/plugins/ffmpeg.client.ts | 17 +- 6 files changed, 9 insertions(+), 2421 deletions(-) diff --git a/frontend_nuxt/.env.example b/frontend_nuxt/.env.example index 2990fd052..dadb36387 100644 --- a/frontend_nuxt/.env.example +++ b/frontend_nuxt/.env.example @@ -17,8 +17,3 @@ NUXT_PUBLIC_GITHUB_CLIENT_ID=Ov23liVkO1NPAX5JyWxJ NUXT_PUBLIC_DISCORD_CLIENT_ID=1394985417044000779 NUXT_PUBLIC_TWITTER_CLIENT_ID=ZTRTU05KSk9KTTJrTTdrVC1tc1E6MTpjaQ NUXT_PUBLIC_TELEGRAM_BOT_ID=8450237135 - -# 视频压缩配置 - FFmpeg.wasm 专用 -# 支持 Chrome 60+ 和 Safari 11.1+ -NUXT_PUBLIC_VIDEO_MAX_SIZE=52428800 # 50MB (字节) -NUXT_PUBLIC_VIDEO_TARGET_SIZE=20971520 # 20MB (字节) \ No newline at end of file diff --git a/frontend_nuxt/config/uploadConfig.js b/frontend_nuxt/config/uploadConfig.js index e98f13d70..0172682b0 100644 --- a/frontend_nuxt/config/uploadConfig.js +++ b/frontend_nuxt/config/uploadConfig.js @@ -3,53 +3,12 @@ * 专注于 FFmpeg.wasm 视频压缩,支持 Chrome/Safari */ -// 声明全局变量以避免 TypeScript 错误 -/* global useRuntimeConfig */ - -// 简化的环境变量读取功能 -function getEnvNumber(key, defaultValue) { - if (typeof window !== 'undefined') { - // 客户端:尝试从 Nuxt 环境获取 - try { - // 使用 globalThis 避免直接引用未定义的变量 - const nuxtApp = globalThis.$nuxt || globalThis.nuxtApp - if (nuxtApp && nuxtApp.$config) { - const value = nuxtApp.$config.public?.[key.replace('NUXT_PUBLIC_', '').toLowerCase()] - return value ? Number(value) : defaultValue - } - return defaultValue - } catch { - return defaultValue - } - } - // 服务端:从 process.env 获取 - return process.env[key] ? Number(process.env[key]) : defaultValue -} - -function getEnvBoolean(key, defaultValue) { - if (typeof window !== 'undefined') { - try { - // 使用 globalThis 避免直接引用未定义的变量 - const nuxtApp = globalThis.$nuxt || globalThis.nuxtApp - if (nuxtApp && nuxtApp.$config) { - const value = nuxtApp.$config.public?.[key.replace('NUXT_PUBLIC_', '').toLowerCase()] - return value === 'true' || value === true - } - return defaultValue - } catch { - return defaultValue - } - } - const envValue = process.env[key] - return envValue ? envValue === 'true' : defaultValue -} - export const UPLOAD_CONFIG = { // 视频文件配置 - 专为 FFmpeg.wasm 优化 VIDEO: { // 文件大小限制 (字节) - MAX_SIZE: getEnvNumber('NUXT_PUBLIC_VIDEO_MAX_SIZE', 20 * 1024 * 1024), // 5MB - TARGET_SIZE: getEnvNumber('NUXT_PUBLIC_VIDEO_TARGET_SIZE', 5 * 1024 * 1024), // 5MB + MAX_SIZE: 20 * 1024 * 1024, + TARGET_SIZE: 5 * 1024 * 1024, // 5MB // 支持的输入格式 (FFmpeg.wasm 支持更多格式) SUPPORTED_FORMATS: ['mp4', 'webm', 'avi', 'mov', 'wmv', 'flv', 'mkv', 'm4v', 'ogv'], diff --git a/frontend_nuxt/nuxt.config.ts b/frontend_nuxt/nuxt.config.ts index dad43963c..5f4264567 100644 --- a/frontend_nuxt/nuxt.config.ts +++ b/frontend_nuxt/nuxt.config.ts @@ -1,17 +1,5 @@ import { defineNuxtConfig } from 'nuxt/config' -import { createRequire } from 'node:module' -const require = createRequire(import.meta.url) -const appPkg = require('./package.json') as { - dependencies?: Record - devDependencies?: Record -} -const ffmpegVersion = ( - process.env.NUXT_PUBLIC_FFMPEG_VERSION || - appPkg.dependencies?.['@ffmpeg/ffmpeg'] || - appPkg.devDependencies?.['@ffmpeg/ffmpeg'] || - '0.12.15' -).replace(/^[^\d]*/, '') export default defineNuxtConfig({ devServer: { host: '0.0.0.0', @@ -29,7 +17,6 @@ export default defineNuxtConfig({ discordClientId: process.env.NUXT_PUBLIC_DISCORD_CLIENT_ID || '', twitterClientId: process.env.NUXT_PUBLIC_TWITTER_CLIENT_ID || '', telegramBotId: process.env.NUXT_PUBLIC_TELEGRAM_BOT_ID || '', - ffmpegVersion, }, }, css: [ @@ -110,26 +97,9 @@ export default defineNuxtConfig({ }, }, vite: { - build: { - // increase warning limit and split large libraries into separate chunks - // chunkSizeWarningLimit: 1024, - // rollupOptions: { - // output: { - // manualChunks(id) { - // if (id.includes('node_modules')) { - // if (id.includes('vditor')) { - // return 'vditor' - // } - // if (id.includes('echarts')) { - // return 'echarts' - // } - // if (id.includes('highlight.js')) { - // return 'highlight' - // } - // } - // }, - // }, - // }, + optimizeDeps: { + include: ['@ffmpeg/ffmpeg', '@ffmpeg/util'], }, + build: {}, }, }) diff --git a/frontend_nuxt/package-lock.json b/frontend_nuxt/package-lock.json index 39770a80c..8493a2590 100644 --- a/frontend_nuxt/package-lock.json +++ b/frontend_nuxt/package-lock.json @@ -6,7 +6,7 @@ "": { "name": "frontend_nuxt", "dependencies": { - "@ffmpeg/ffmpeg": "^0.12.15", + "@ffmpeg/ffmpeg": "^0.12.10", "@ffmpeg/util": "^0.12.2", "@icon-park/vue-next": "^1.4.2", "@nuxt/image": "^1.11.0", @@ -561,70 +561,6 @@ "license": "0BSD", "optional": true }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.9.tgz", - "integrity": "sha512-OaGtL73Jck6pBKjNIe24BnFE6agGl+6KxDtTfHhy1HmhthfKouEcOhqpSL64K4/0WCtbKFLOdzD/44cJ4k9opA==", - "cpu": [ - "ppc64" - ], - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.9.tgz", - "integrity": "sha512-5WNI1DaMtxQ7t7B6xa572XMXpHAaI/9Hnhk8lcxF4zVN4xstUgTlvuGDorBguKEnZO70qwEcLpfifMLoxiPqHQ==", - "cpu": [ - "arm" - ], - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.9.tgz", - "integrity": "sha512-IDrddSmpSv51ftWslJMvl3Q2ZT98fUSL2/rlUXuVqRXHCs5EUF1/f+jbjF5+NG9UffUDMCiTyh8iec7u8RlTLg==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-x64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.9.tgz", - "integrity": "sha512-I853iMZ1hWZdNllhVZKm34f4wErd4lMyeV7BLzEExGEIZYsOzqDWDf+y082izYUE8gtJnYHdeDpN/6tUdwvfiw==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, "node_modules/@esbuild/darwin-arm64": { "version": "0.25.9", "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.9.tgz", @@ -641,342 +577,6 @@ "node": ">=18" } }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.9.tgz", - "integrity": "sha512-jhHfBzjYTA1IQu8VyrjCX4ApJDnH+ez+IYVEoJHeqJm9VhG9Dh2BYaJritkYK3vMaXrf7Ogr/0MQ8/MeIefsPQ==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.9.tgz", - "integrity": "sha512-z93DmbnY6fX9+KdD4Ue/H6sYs+bhFQJNCPZsi4XWJoYblUqT06MQUdBCpcSfuiN72AbqeBFu5LVQTjfXDE2A6Q==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.9.tgz", - "integrity": "sha512-mrKX6H/vOyo5v71YfXWJxLVxgy1kyt1MQaD8wZJgJfG4gq4DpQGpgTB74e5yBeQdyMTbgxp0YtNj7NuHN0PoZg==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.9.tgz", - "integrity": "sha512-HBU2Xv78SMgaydBmdor38lg8YDnFKSARg1Q6AT0/y2ezUAKiZvc211RDFHlEZRFNRVhcMamiToo7bDx3VEOYQw==", - "cpu": [ - "arm" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.9.tgz", - "integrity": "sha512-BlB7bIcLT3G26urh5Dmse7fiLmLXnRlopw4s8DalgZ8ef79Jj4aUcYbk90g8iCa2467HX8SAIidbL7gsqXHdRw==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.9.tgz", - "integrity": "sha512-e7S3MOJPZGp2QW6AK6+Ly81rC7oOSerQ+P8L0ta4FhVi+/j/v2yZzx5CqqDaWjtPFfYz21Vi1S0auHrap3Ma3A==", - "cpu": [ - "ia32" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.9.tgz", - "integrity": "sha512-Sbe10Bnn0oUAB2AalYztvGcK+o6YFFA/9829PhOCUS9vkJElXGdphz0A3DbMdP8gmKkqPmPcMJmJOrI3VYB1JQ==", - "cpu": [ - "loong64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.9.tgz", - "integrity": "sha512-YcM5br0mVyZw2jcQeLIkhWtKPeVfAerES5PvOzaDxVtIyZ2NUBZKNLjC5z3/fUlDgT6w89VsxP2qzNipOaaDyA==", - "cpu": [ - "mips64el" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.9.tgz", - "integrity": "sha512-++0HQvasdo20JytyDpFvQtNrEsAgNG2CY1CLMwGXfFTKGBGQT3bOeLSYE2l1fYdvML5KUuwn9Z8L1EWe2tzs1w==", - "cpu": [ - "ppc64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.9.tgz", - "integrity": "sha512-uNIBa279Y3fkjV+2cUjx36xkx7eSjb8IvnL01eXUKXez/CBHNRw5ekCGMPM0BcmqBxBcdgUWuUXmVWwm4CH9kg==", - "cpu": [ - "riscv64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.9.tgz", - "integrity": "sha512-Mfiphvp3MjC/lctb+7D287Xw1DGzqJPb/J2aHHcHxflUo+8tmN/6d4k6I2yFR7BVo5/g7x2Monq4+Yew0EHRIA==", - "cpu": [ - "s390x" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-x64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.9.tgz", - "integrity": "sha512-iSwByxzRe48YVkmpbgoxVzn76BXjlYFXC7NvLYq+b+kDjyyk30J0JY47DIn8z1MO3K0oSl9fZoRmZPQI4Hklzg==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-arm64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.9.tgz", - "integrity": "sha512-9jNJl6FqaUG+COdQMjSCGW4QiMHH88xWbvZ+kRVblZsWrkXlABuGdFJ1E9L7HK+T0Yqd4akKNa/lO0+jDxQD4Q==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.9.tgz", - "integrity": "sha512-RLLdkflmqRG8KanPGOU7Rpg829ZHu8nFy5Pqdi9U01VYtG9Y0zOG6Vr2z4/S+/3zIyOxiK6cCeYNWOFR9QP87g==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-arm64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.9.tgz", - "integrity": "sha512-YaFBlPGeDasft5IIM+CQAhJAqS3St3nJzDEgsgFixcfZeyGPCd6eJBWzke5piZuZ7CtL656eOSYKk4Ls2C0FRQ==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.9.tgz", - "integrity": "sha512-1MkgTCuvMGWuqVtAvkpkXFmtL8XhWy+j4jaSO2wxfJtilVCi0ZE37b8uOdMItIHz4I6z1bWWtEX4CJwcKYLcuA==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openharmony-arm64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.9.tgz", - "integrity": "sha512-4Xd0xNiMVXKh6Fa7HEJQbrpP3m3DDn43jKxMjxLLRjWnRsfxjORYJlXPO4JNcXtOyfajXorRKY9NkOpTHptErg==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "openharmony" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.9.tgz", - "integrity": "sha512-WjH4s6hzo00nNezhp3wFIAfmGZ8U7KtrJNlFMRKxiI9mxEK1scOMAaa9i4crUtu+tBr+0IN6JCuAcSBJZfnphw==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.9.tgz", - "integrity": "sha512-mGFrVJHmZiRqmP8xFOc6b84/7xa5y5YvR1x8djzXpJBSv/UsNK6aqec+6JDjConTgvvQefdGhFDAs2DLAds6gQ==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.9.tgz", - "integrity": "sha512-b33gLVU2k11nVx1OhX3C8QQP6UHQK4ZtN56oFWvVXvz2VkDoe6fbG8TOgHFxEvqeqohmRnIHe5A1+HADk4OQww==", - "cpu": [ - "ia32" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-x64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.9.tgz", - "integrity": "sha512-PPOl1mi6lpLNQxnGoyAfschAodRFYXJ+9fs6WHXz7CSWKbOqiMZsubC+BQsVKuul+3vKLuwTHsS2c2y9EoKwxQ==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, "node_modules/@fastify/accept-negotiator": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/@fastify/accept-negotiator/-/accept-negotiator-2.0.1.tgz", @@ -1064,28 +664,6 @@ "@img/sharp-libvips-darwin-arm64": "1.2.0" } }, - "node_modules/@img/sharp-darwin-x64": { - "version": "0.34.3", - "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.3.tgz", - "integrity": "sha512-yHpJYynROAj12TA6qil58hmPmAwxKKC7reUqtGLzsOHfP7/rniNGTL8tjWX6L3CTV4+5P4ypcS7Pp+7OB+8ihA==", - "cpu": [ - "x64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-darwin-x64": "1.2.0" - } - }, "node_modules/@img/sharp-libvips-darwin-arm64": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.2.0.tgz", @@ -1102,364 +680,6 @@ "url": "https://opencollective.com/libvips" } }, - "node_modules/@img/sharp-libvips-darwin-x64": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.2.0.tgz", - "integrity": "sha512-M64XVuL94OgiNHa5/m2YvEQI5q2cl9d/wk0qFTDVXcYzi43lxuiFTftMR1tOnFQovVXNZJ5TURSDK2pNe9Yzqg==", - "cpu": [ - "x64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "darwin" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linux-arm": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.2.0.tgz", - "integrity": "sha512-mWd2uWvDtL/nvIzThLq3fr2nnGfyr/XMXlq8ZJ9WMR6PXijHlC3ksp0IpuhK6bougvQrchUAfzRLnbsen0Cqvw==", - "cpu": [ - "arm" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linux-arm64": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.2.0.tgz", - "integrity": "sha512-RXwd0CgG+uPRX5YYrkzKyalt2OJYRiJQ8ED/fi1tq9WQW2jsQIn0tqrlR5l5dr/rjqq6AHAxURhj2DVjyQWSOA==", - "cpu": [ - "arm64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linux-ppc64": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.2.0.tgz", - "integrity": "sha512-Xod/7KaDDHkYu2phxxfeEPXfVXFKx70EAFZ0qyUdOjCcxbjqyJOEUpDe6RIyaunGxT34Anf9ue/wuWOqBW2WcQ==", - "cpu": [ - "ppc64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linux-s390x": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.2.0.tgz", - "integrity": "sha512-eMKfzDxLGT8mnmPJTNMcjfO33fLiTDsrMlUVcp6b96ETbnJmd4uvZxVJSKPQfS+odwfVaGifhsB07J1LynFehw==", - "cpu": [ - "s390x" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linux-x64": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.2.0.tgz", - "integrity": "sha512-ZW3FPWIc7K1sH9E3nxIGB3y3dZkpJlMnkk7z5tu1nSkBoCgw2nSRTFHI5pB/3CQaJM0pdzMF3paf9ckKMSE9Tg==", - "cpu": [ - "x64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linuxmusl-arm64": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.2.0.tgz", - "integrity": "sha512-UG+LqQJbf5VJ8NWJ5Z3tdIe/HXjuIdo4JeVNADXBFuG7z9zjoegpzzGIyV5zQKi4zaJjnAd2+g2nna8TZvuW9Q==", - "cpu": [ - "arm64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linuxmusl-x64": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.2.0.tgz", - "integrity": "sha512-SRYOLR7CXPgNze8akZwjoGBoN1ThNZoqpOgfnOxmWsklTGVfJiGJoC/Lod7aNMGA1jSsKWM1+HRX43OP6p9+6Q==", - "cpu": [ - "x64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-linux-arm": { - "version": "0.34.3", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.3.tgz", - "integrity": "sha512-oBK9l+h6KBN0i3dC8rYntLiVfW8D8wH+NPNT3O/WBHeW0OQWCjfWksLUaPidsrDKpJgXp3G3/hkmhptAW0I3+A==", - "cpu": [ - "arm" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-arm": "1.2.0" - } - }, - "node_modules/@img/sharp-linux-arm64": { - "version": "0.34.3", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.3.tgz", - "integrity": "sha512-QdrKe3EvQrqwkDrtuTIjI0bu6YEJHTgEeqdzI3uWJOH6G1O8Nl1iEeVYRGdj1h5I21CqxSvQp1Yv7xeU3ZewbA==", - "cpu": [ - "arm64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-arm64": "1.2.0" - } - }, - "node_modules/@img/sharp-linux-ppc64": { - "version": "0.34.3", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.34.3.tgz", - "integrity": "sha512-GLtbLQMCNC5nxuImPR2+RgrviwKwVql28FWZIW1zWruy6zLgA5/x2ZXk3mxj58X/tszVF69KK0Is83V8YgWhLA==", - "cpu": [ - "ppc64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-ppc64": "1.2.0" - } - }, - "node_modules/@img/sharp-linux-s390x": { - "version": "0.34.3", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.3.tgz", - "integrity": "sha512-3gahT+A6c4cdc2edhsLHmIOXMb17ltffJlxR0aC2VPZfwKoTGZec6u5GrFgdR7ciJSsHT27BD3TIuGcuRT0KmQ==", - "cpu": [ - "s390x" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-s390x": "1.2.0" - } - }, - "node_modules/@img/sharp-linux-x64": { - "version": "0.34.3", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.3.tgz", - "integrity": "sha512-8kYso8d806ypnSq3/Ly0QEw90V5ZoHh10yH0HnrzOCr6DKAPI6QVHvwleqMkVQ0m+fc7EH8ah0BB0QPuWY6zJQ==", - "cpu": [ - "x64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-x64": "1.2.0" - } - }, - "node_modules/@img/sharp-linuxmusl-arm64": { - "version": "0.34.3", - "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.3.tgz", - "integrity": "sha512-vAjbHDlr4izEiXM1OTggpCcPg9tn4YriK5vAjowJsHwdBIdx0fYRsURkxLG2RLm9gyBq66gwtWI8Gx0/ov+JKQ==", - "cpu": [ - "arm64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linuxmusl-arm64": "1.2.0" - } - }, - "node_modules/@img/sharp-linuxmusl-x64": { - "version": "0.34.3", - "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.3.tgz", - "integrity": "sha512-gCWUn9547K5bwvOn9l5XGAEjVTTRji4aPTqLzGXHvIr6bIDZKNTA34seMPgM0WmSf+RYBH411VavCejp3PkOeQ==", - "cpu": [ - "x64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linuxmusl-x64": "1.2.0" - } - }, - "node_modules/@img/sharp-wasm32": { - "version": "0.34.3", - "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.3.tgz", - "integrity": "sha512-+CyRcpagHMGteySaWos8IbnXcHgfDn7pO2fiC2slJxvNq9gDipYBN42/RagzctVRKgxATmfqOSulgZv5e1RdMg==", - "cpu": [ - "wasm32" - ], - "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", - "optional": true, - "dependencies": { - "@emnapi/runtime": "^1.4.4" - }, - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-win32-arm64": { - "version": "0.34.3", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.3.tgz", - "integrity": "sha512-MjnHPnbqMXNC2UgeLJtX4XqoVHHlZNd+nPt1kRPmj63wURegwBhZlApELdtxM2OIZDRv/DFtLcNhVbd1z8GYXQ==", - "cpu": [ - "arm64" - ], - "license": "Apache-2.0 AND LGPL-3.0-or-later", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-win32-ia32": { - "version": "0.34.3", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.3.tgz", - "integrity": "sha512-xuCdhH44WxuXgOM714hn4amodJMZl3OEvf0GVTm0BEyMeA2to+8HEdRPShH0SLYptJY1uBw+SCFP9WVQi1Q/cw==", - "cpu": [ - "ia32" - ], - "license": "Apache-2.0 AND LGPL-3.0-or-later", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-win32-x64": { - "version": "0.34.3", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.3.tgz", - "integrity": "sha512-OWwz05d++TxzLEv4VnsTz5CmZ6mI6S05sfQGEMrNrQcOEERbX46332IvE7pO/EUiw7jUrrS40z/M7kPyjfl04g==", - "cpu": [ - "x64" - ], - "license": "Apache-2.0 AND LGPL-3.0-or-later", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - } - }, "node_modules/@ioredis/commands": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/@ioredis/commands/-/commands-1.3.0.tgz", @@ -1783,70 +1003,6 @@ "node": ">=6.9.0" } }, - "node_modules/@netlify/zip-it-and-ship-it/node_modules/@esbuild/aix-ppc64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.5.tgz", - "integrity": "sha512-9o3TMmpmftaCMepOdA5k/yDw8SfInyzWWTjYTFCX3kPSDJMROQTb8jg+h9Cnwnmm1vOzvxN7gIfB5V2ewpjtGA==", - "cpu": [ - "ppc64" - ], - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@netlify/zip-it-and-ship-it/node_modules/@esbuild/android-arm": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.5.tgz", - "integrity": "sha512-AdJKSPeEHgi7/ZhuIPtcQKr5RQdo6OO2IL87JkianiMYMPbCtot9fxPbrMiBADOWWm3T2si9stAiVsGbTQFkbA==", - "cpu": [ - "arm" - ], - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@netlify/zip-it-and-ship-it/node_modules/@esbuild/android-arm64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.5.tgz", - "integrity": "sha512-VGzGhj4lJO+TVGV1v8ntCZWJktV7SGCs3Pn1GRWI1SBFtRALoomm8k5E9Pmwg3HOAal2VDc2F9+PM/rEY6oIDg==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@netlify/zip-it-and-ship-it/node_modules/@esbuild/android-x64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.5.tgz", - "integrity": "sha512-D2GyJT1kjvO//drbRT3Hib9XPwQeWd9vZoBJn+bu/lVsOZ13cqNdDeqIF/xQ5/VmWvMduP6AmXvylO/PIc2isw==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, "node_modules/@netlify/zip-it-and-ship-it/node_modules/@esbuild/darwin-arm64": { "version": "0.25.5", "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.5.tgz", @@ -1863,326 +1019,6 @@ "node": ">=18" } }, - "node_modules/@netlify/zip-it-and-ship-it/node_modules/@esbuild/darwin-x64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.5.tgz", - "integrity": "sha512-1iT4FVL0dJ76/q1wd7XDsXrSW+oLoquptvh4CLR4kITDtqi2e/xwXwdCVH8hVHU43wgJdsq7Gxuzcs6Iq/7bxQ==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@netlify/zip-it-and-ship-it/node_modules/@esbuild/freebsd-arm64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.5.tgz", - "integrity": "sha512-nk4tGP3JThz4La38Uy/gzyXtpkPW8zSAmoUhK9xKKXdBCzKODMc2adkB2+8om9BDYugz+uGV7sLmpTYzvmz6Sw==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@netlify/zip-it-and-ship-it/node_modules/@esbuild/freebsd-x64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.5.tgz", - "integrity": "sha512-PrikaNjiXdR2laW6OIjlbeuCPrPaAl0IwPIaRv+SMV8CiM8i2LqVUHFC1+8eORgWyY7yhQY+2U2fA55mBzReaw==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@netlify/zip-it-and-ship-it/node_modules/@esbuild/linux-arm": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.5.tgz", - "integrity": "sha512-cPzojwW2okgh7ZlRpcBEtsX7WBuqbLrNXqLU89GxWbNt6uIg78ET82qifUy3W6OVww6ZWobWub5oqZOVtwolfw==", - "cpu": [ - "arm" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@netlify/zip-it-and-ship-it/node_modules/@esbuild/linux-arm64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.5.tgz", - "integrity": "sha512-Z9kfb1v6ZlGbWj8EJk9T6czVEjjq2ntSYLY2cw6pAZl4oKtfgQuS4HOq41M/BcoLPzrUbNd+R4BXFyH//nHxVg==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@netlify/zip-it-and-ship-it/node_modules/@esbuild/linux-ia32": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.5.tgz", - "integrity": "sha512-sQ7l00M8bSv36GLV95BVAdhJ2QsIbCuCjh/uYrWiMQSUuV+LpXwIqhgJDcvMTj+VsQmqAHL2yYaasENvJ7CDKA==", - "cpu": [ - "ia32" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@netlify/zip-it-and-ship-it/node_modules/@esbuild/linux-loong64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.5.tgz", - "integrity": "sha512-0ur7ae16hDUC4OL5iEnDb0tZHDxYmuQyhKhsPBV8f99f6Z9KQM02g33f93rNH5A30agMS46u2HP6qTdEt6Q1kg==", - "cpu": [ - "loong64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@netlify/zip-it-and-ship-it/node_modules/@esbuild/linux-mips64el": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.5.tgz", - "integrity": "sha512-kB/66P1OsHO5zLz0i6X0RxlQ+3cu0mkxS3TKFvkb5lin6uwZ/ttOkP3Z8lfR9mJOBk14ZwZ9182SIIWFGNmqmg==", - "cpu": [ - "mips64el" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@netlify/zip-it-and-ship-it/node_modules/@esbuild/linux-ppc64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.5.tgz", - "integrity": "sha512-UZCmJ7r9X2fe2D6jBmkLBMQetXPXIsZjQJCjgwpVDz+YMcS6oFR27alkgGv3Oqkv07bxdvw7fyB71/olceJhkQ==", - "cpu": [ - "ppc64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@netlify/zip-it-and-ship-it/node_modules/@esbuild/linux-riscv64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.5.tgz", - "integrity": "sha512-kTxwu4mLyeOlsVIFPfQo+fQJAV9mh24xL+y+Bm6ej067sYANjyEw1dNHmvoqxJUCMnkBdKpvOn0Ahql6+4VyeA==", - "cpu": [ - "riscv64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@netlify/zip-it-and-ship-it/node_modules/@esbuild/linux-s390x": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.5.tgz", - "integrity": "sha512-K2dSKTKfmdh78uJ3NcWFiqyRrimfdinS5ErLSn3vluHNeHVnBAFWC8a4X5N+7FgVE1EjXS1QDZbpqZBjfrqMTQ==", - "cpu": [ - "s390x" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@netlify/zip-it-and-ship-it/node_modules/@esbuild/linux-x64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.5.tgz", - "integrity": "sha512-uhj8N2obKTE6pSZ+aMUbqq+1nXxNjZIIjCjGLfsWvVpy7gKCOL6rsY1MhRh9zLtUtAI7vpgLMK6DxjO8Qm9lJw==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@netlify/zip-it-and-ship-it/node_modules/@esbuild/netbsd-arm64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.5.tgz", - "integrity": "sha512-pwHtMP9viAy1oHPvgxtOv+OkduK5ugofNTVDilIzBLpoWAM16r7b/mxBvfpuQDpRQFMfuVr5aLcn4yveGvBZvw==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@netlify/zip-it-and-ship-it/node_modules/@esbuild/netbsd-x64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.5.tgz", - "integrity": "sha512-WOb5fKrvVTRMfWFNCroYWWklbnXH0Q5rZppjq0vQIdlsQKuw6mdSihwSo4RV/YdQ5UCKKvBy7/0ZZYLBZKIbwQ==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@netlify/zip-it-and-ship-it/node_modules/@esbuild/openbsd-arm64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.5.tgz", - "integrity": "sha512-7A208+uQKgTxHd0G0uqZO8UjK2R0DDb4fDmERtARjSHWxqMTye4Erz4zZafx7Di9Cv+lNHYuncAkiGFySoD+Mw==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@netlify/zip-it-and-ship-it/node_modules/@esbuild/openbsd-x64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.5.tgz", - "integrity": "sha512-G4hE405ErTWraiZ8UiSoesH8DaCsMm0Cay4fsFWOOUcz8b8rC6uCvnagr+gnioEjWn0wC+o1/TAHt+It+MpIMg==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@netlify/zip-it-and-ship-it/node_modules/@esbuild/sunos-x64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.5.tgz", - "integrity": "sha512-l+azKShMy7FxzY0Rj4RCt5VD/q8mG/e+mDivgspo+yL8zW7qEwctQ6YqKX34DTEleFAvCIUviCFX1SDZRSyMQA==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@netlify/zip-it-and-ship-it/node_modules/@esbuild/win32-arm64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.5.tgz", - "integrity": "sha512-O2S7SNZzdcFG7eFKgvwUEZ2VG9D/sn/eIiz8XRZ1Q/DO5a3s76Xv0mdBzVM5j5R639lXQmPmSo0iRpHqUUrsxw==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@netlify/zip-it-and-ship-it/node_modules/@esbuild/win32-ia32": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.5.tgz", - "integrity": "sha512-onOJ02pqs9h1iMJ1PQphR+VZv8qBMQ77Klcsqv9CNW2w6yLqoURLcgERAIurY6QE63bbLuqgP9ATqajFLK5AMQ==", - "cpu": [ - "ia32" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@netlify/zip-it-and-ship-it/node_modules/@esbuild/win32-x64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.5.tgz", - "integrity": "sha512-TXv6YnJ8ZMVdX+SXWVBo/0p8LTcrUYngpWjvm91TMjjBQii7Oz11Lw5lbDV5Y0TzuhSJHwiH4hEtC1I42mMS0g==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, "node_modules/@netlify/zip-it-and-ship-it/node_modules/@netlify/serverless-functions-api": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/@netlify/serverless-functions-api/-/serverless-functions-api-2.3.0.tgz", @@ -2738,22 +1574,6 @@ "node": ">=18.12.0" } }, - "node_modules/@oxc-minify/binding-android-arm64": { - "version": "0.80.0", - "resolved": "https://registry.npmjs.org/@oxc-minify/binding-android-arm64/-/binding-android-arm64-0.80.0.tgz", - "integrity": "sha512-OLelUqrLkSJwNyjLZHgpKy9n0+zHQiMX8A0GFovJIwhgfPxjT/mt2JMnGkSoDlTnf9cw6nvALFzCsJZLTyl8gg==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=14.0.0" - } - }, "node_modules/@oxc-minify/binding-darwin-arm64": { "version": "0.80.0", "resolved": "https://registry.npmjs.org/@oxc-minify/binding-darwin-arm64/-/binding-darwin-arm64-0.80.0.tgz", @@ -2770,230 +1590,6 @@ "node": ">=14.0.0" } }, - "node_modules/@oxc-minify/binding-darwin-x64": { - "version": "0.80.0", - "resolved": "https://registry.npmjs.org/@oxc-minify/binding-darwin-x64/-/binding-darwin-x64-0.80.0.tgz", - "integrity": "sha512-jKnRVtwVhspd8djNSQMICOZe6gQBwXTcfHylZ2Azw4ZXvqTyxDqgcEGgx0WyaqvUTLHdX42nJCHRHHy6MOVPOg==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@oxc-minify/binding-freebsd-x64": { - "version": "0.80.0", - "resolved": "https://registry.npmjs.org/@oxc-minify/binding-freebsd-x64/-/binding-freebsd-x64-0.80.0.tgz", - "integrity": "sha512-iO7KjJsFpDtG5w8T6twTxLsvffn8PsjBbBUwjzVPfSD4YlsHDd0GjIVYcP+1TXzLRlV4zWmd67SOBnNyreSGBg==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@oxc-minify/binding-linux-arm-gnueabihf": { - "version": "0.80.0", - "resolved": "https://registry.npmjs.org/@oxc-minify/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-0.80.0.tgz", - "integrity": "sha512-uwBdietv8USofOUAOcxyta14VbcJiFizQUMuCB9sLkK+Nh/CV5U2SVjsph5HlARGVu8V2DF+FXROD6sTl9DLiA==", - "cpu": [ - "arm" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@oxc-minify/binding-linux-arm-musleabihf": { - "version": "0.80.0", - "resolved": "https://registry.npmjs.org/@oxc-minify/binding-linux-arm-musleabihf/-/binding-linux-arm-musleabihf-0.80.0.tgz", - "integrity": "sha512-6QAWCjH9in7JvpHRxX8M1IEkf+Eot82Q02xmikcACyJag26196XdVq2T9ITcwFtliozYxYP6yPQ5OzLoeeqdmg==", - "cpu": [ - "arm" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@oxc-minify/binding-linux-arm64-gnu": { - "version": "0.80.0", - "resolved": "https://registry.npmjs.org/@oxc-minify/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-0.80.0.tgz", - "integrity": "sha512-1PxO983GNFSyvY6lpYpH3uA/5NHuei7CHExe+NSB+ZgQ1T/iBMjXxRml1Woedvi8odSSpZlivZxBiEojIcnfqw==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@oxc-minify/binding-linux-arm64-musl": { - "version": "0.80.0", - "resolved": "https://registry.npmjs.org/@oxc-minify/binding-linux-arm64-musl/-/binding-linux-arm64-musl-0.80.0.tgz", - "integrity": "sha512-D2j5L9Z4OO42We0Lo2GkXT/AaNikzZJ8KZ9V2VVwu7kofI4RsO8kSu8ydWlqRlRdiAprmUpRZU/pNW0ZA7A68w==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@oxc-minify/binding-linux-riscv64-gnu": { - "version": "0.80.0", - "resolved": "https://registry.npmjs.org/@oxc-minify/binding-linux-riscv64-gnu/-/binding-linux-riscv64-gnu-0.80.0.tgz", - "integrity": "sha512-2AztlLcio5OGil70wjRLbxbjlfS1yCTzO+CYan49vfUOCXpwSWwwLD2WDzFokhEXAzf8epbbu7pruYk8qorRRg==", - "cpu": [ - "riscv64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@oxc-minify/binding-linux-s390x-gnu": { - "version": "0.80.0", - "resolved": "https://registry.npmjs.org/@oxc-minify/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-0.80.0.tgz", - "integrity": "sha512-5GMKARe4gYHhA7utM8qOgv3WM7KAXGZGG3Jhvk4UQSRBp0v6PKFmHmz8Q93+Ep8w1m4NqRL30Zk9CZHMH/qi5g==", - "cpu": [ - "s390x" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@oxc-minify/binding-linux-x64-gnu": { - "version": "0.80.0", - "resolved": "https://registry.npmjs.org/@oxc-minify/binding-linux-x64-gnu/-/binding-linux-x64-gnu-0.80.0.tgz", - "integrity": "sha512-iw45N+OVnPioRQXLHfrsqEcTpydcGSHLphilS3aSpc4uVKnOqCybskKnbEnxsIJqHWbzDZeJgzuRuQa7EhNcqg==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@oxc-minify/binding-linux-x64-musl": { - "version": "0.80.0", - "resolved": "https://registry.npmjs.org/@oxc-minify/binding-linux-x64-musl/-/binding-linux-x64-musl-0.80.0.tgz", - "integrity": "sha512-4+dhYznVM+L9Jh855JBbqVyDjwi3p8rpL7RfgN+Ee1oQMaZl2ZPy2shS1Kj56Xr5haTTVGdRKcIqTU8SuF37UQ==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@oxc-minify/binding-wasm32-wasi": { - "version": "0.80.0", - "resolved": "https://registry.npmjs.org/@oxc-minify/binding-wasm32-wasi/-/binding-wasm32-wasi-0.80.0.tgz", - "integrity": "sha512-flADFeNwC1/XsBBsESAigsJZyONEBloQO86Z38ZNzLSuMmpGRdwB9gUwlPCQgDRND/aB+tvR29hKTSuQoS3yrg==", - "cpu": [ - "wasm32" - ], - "license": "MIT", - "optional": true, - "dependencies": { - "@napi-rs/wasm-runtime": "^1.0.1" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@oxc-minify/binding-win32-arm64-msvc": { - "version": "0.80.0", - "resolved": "https://registry.npmjs.org/@oxc-minify/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-0.80.0.tgz", - "integrity": "sha512-wFjaEHzczIG9GqnL4c4C3PoThzf1640weQ1eEjh96TnHVdZmiNT5lpGoziJhO/c+g9+6sNrTdz9sqsiVgKwdOg==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@oxc-minify/binding-win32-x64-msvc": { - "version": "0.80.0", - "resolved": "https://registry.npmjs.org/@oxc-minify/binding-win32-x64-msvc/-/binding-win32-x64-msvc-0.80.0.tgz", - "integrity": "sha512-PjMi5B3MvOmfZk5LTie6g3RHhhujFwgR4VbCrWUNNwSzdxzy3dULPT4PWGVbpTas/QLJzXs/CXlQfnaMeJZHKQ==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@oxc-parser/binding-android-arm64": { - "version": "0.80.0", - "resolved": "https://registry.npmjs.org/@oxc-parser/binding-android-arm64/-/binding-android-arm64-0.80.0.tgz", - "integrity": "sha512-H0S4QTRFhct1uO1ZOnzGQAoHSJVHCyZa+oivovHkbqA0z271ppRkXmJuLfjW+9CBW0577JNAhjTflKUDpCO4lg==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=20.0.0" - } - }, "node_modules/@oxc-parser/binding-darwin-arm64": { "version": "0.80.0", "resolved": "https://registry.npmjs.org/@oxc-parser/binding-darwin-arm64/-/binding-darwin-arm64-0.80.0.tgz", @@ -3010,214 +1606,6 @@ "node": ">=20.0.0" } }, - "node_modules/@oxc-parser/binding-darwin-x64": { - "version": "0.80.0", - "resolved": "https://registry.npmjs.org/@oxc-parser/binding-darwin-x64/-/binding-darwin-x64-0.80.0.tgz", - "integrity": "sha512-h7wRo10ywI2vLz9VljFeIaUh9u7l2l3kvF6FAteY3cPqbCA6JYUZGJaykhMqTxJoG6wrzf35sMA2ubvq67iAMA==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@oxc-parser/binding-freebsd-x64": { - "version": "0.80.0", - "resolved": "https://registry.npmjs.org/@oxc-parser/binding-freebsd-x64/-/binding-freebsd-x64-0.80.0.tgz", - "integrity": "sha512-KcJ+8w/wVwd/XfDmgA9QZJAWML3vPu2O2Y8XRkf3U9VsN5n8cZ5PXMbH4NBSb3O7ctdDSvwnnuApLOz3sTHsUw==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@oxc-parser/binding-linux-arm-gnueabihf": { - "version": "0.80.0", - "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-0.80.0.tgz", - "integrity": "sha512-5OCRxV5fX5RkVqsag55m4EFeudSZ0nSMYXgdtfR/5JZSiYmIYyPycafNNa52liqC2gx27vzrDRE4FdlG+5fhww==", - "cpu": [ - "arm" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@oxc-parser/binding-linux-arm-musleabihf": { - "version": "0.80.0", - "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-arm-musleabihf/-/binding-linux-arm-musleabihf-0.80.0.tgz", - "integrity": "sha512-kMa2PeA2GHMhvV617WdFzDAWCo2A00knPEe6rxFUO/Gr8TTLv1/LlEY6UqGseWrRfkkhFiAO496nRPW/6B5DCg==", - "cpu": [ - "arm" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@oxc-parser/binding-linux-arm64-gnu": { - "version": "0.80.0", - "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-0.80.0.tgz", - "integrity": "sha512-y2NEhbFfKPdOkf3ZR/3xwJFJVji6IKxwXKHUN4bEdqpcO0tkXSCiP0MzTxjEY6ql2/MXdkqK0Ym92dYsRsgsyg==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@oxc-parser/binding-linux-arm64-musl": { - "version": "0.80.0", - "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-arm64-musl/-/binding-linux-arm64-musl-0.80.0.tgz", - "integrity": "sha512-j3tKausSXwHS/Ej6ct2dmKJtw0UIME2XJmj6QfPT6LyUSNTndj4yXRXuMSrCOrX9/0qH9GhmqeL9ouU27dQRFw==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@oxc-parser/binding-linux-riscv64-gnu": { - "version": "0.80.0", - "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-riscv64-gnu/-/binding-linux-riscv64-gnu-0.80.0.tgz", - "integrity": "sha512-h+uPvyTcpTFd946fGPU57sZeec2qHPUYQRZeXHB2uuZjps+9pxQ5zIz0EBM/JgBtnwdtoR93RAu1YNAVbqY5Zw==", - "cpu": [ - "riscv64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@oxc-parser/binding-linux-s390x-gnu": { - "version": "0.80.0", - "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-0.80.0.tgz", - "integrity": "sha512-+u74hV+WwCPL4UBNOJaIGRozTCfZ7pM5JCEe8zAlMkKexftUzbtvW02314bVD9bqoRAL3Gg6jcZrjNjwDX2FwQ==", - "cpu": [ - "s390x" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@oxc-parser/binding-linux-x64-gnu": { - "version": "0.80.0", - "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-x64-gnu/-/binding-linux-x64-gnu-0.80.0.tgz", - "integrity": "sha512-N9UGnWVWMlOJH+6550tqyBxd9qkMd0f4m+YRA0gly6efJTuLbPQpjkJm7pJbMu+GULcvSJ/Y0bkMAIQTtwP0vQ==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@oxc-parser/binding-linux-x64-musl": { - "version": "0.80.0", - "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-x64-musl/-/binding-linux-x64-musl-0.80.0.tgz", - "integrity": "sha512-l2N/GlFEri27QBMi0e53V/SlpQotIvHbz+rZZG/EO+vn58ZEr0eTG+PjJoOY/T8+TQb8nrCtRe4S/zNDpV6zSQ==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@oxc-parser/binding-wasm32-wasi": { - "version": "0.80.0", - "resolved": "https://registry.npmjs.org/@oxc-parser/binding-wasm32-wasi/-/binding-wasm32-wasi-0.80.0.tgz", - "integrity": "sha512-5iEwQqMXU1HiRlWuD3f+8N2O3qWhS+nOFEAWgE3sjMUnTtILPJETYhaGBPqqPWg1iRO3+hE1lEBCdI91GS1CUQ==", - "cpu": [ - "wasm32" - ], - "license": "MIT", - "optional": true, - "dependencies": { - "@napi-rs/wasm-runtime": "^1.0.1" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@oxc-parser/binding-win32-arm64-msvc": { - "version": "0.80.0", - "resolved": "https://registry.npmjs.org/@oxc-parser/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-0.80.0.tgz", - "integrity": "sha512-HedSH/Db7OFR2SugTbuawaV1vjgUjCXzxPquow/1FLtpRT2wASbMaRRbyD/h2n4DJ8V2zGqnV8Q+vic+VNvnKg==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@oxc-parser/binding-win32-x64-msvc": { - "version": "0.80.0", - "resolved": "https://registry.npmjs.org/@oxc-parser/binding-win32-x64-msvc/-/binding-win32-x64-msvc-0.80.0.tgz", - "integrity": "sha512-SSiM0m7jG5yxVf0ivy1rF8OuTJo8ITgp1ccp2aqPZG6Qyl5QiVpf8HI1X5AvPFxts2B4Bv8U3Dip+FobqBkwcw==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=20.0.0" - } - }, "node_modules/@oxc-project/types": { "version": "0.80.0", "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.80.0.tgz", @@ -3227,22 +1615,6 @@ "url": "https://github.com/sponsors/Boshen" } }, - "node_modules/@oxc-transform/binding-android-arm64": { - "version": "0.80.0", - "resolved": "https://registry.npmjs.org/@oxc-transform/binding-android-arm64/-/binding-android-arm64-0.80.0.tgz", - "integrity": "sha512-HAK6zIUOteptOsSRqoGu41cez7kj/OPJqBGdgdP6FFh2RFcRfh0vqefjgF69af7TjzsRxVF8itiWvFsJHrIFoA==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=14.0.0" - } - }, "node_modules/@oxc-transform/binding-darwin-arm64": { "version": "0.80.0", "resolved": "https://registry.npmjs.org/@oxc-transform/binding-darwin-arm64/-/binding-darwin-arm64-0.80.0.tgz", @@ -3259,214 +1631,6 @@ "node": ">=14.0.0" } }, - "node_modules/@oxc-transform/binding-darwin-x64": { - "version": "0.80.0", - "resolved": "https://registry.npmjs.org/@oxc-transform/binding-darwin-x64/-/binding-darwin-x64-0.80.0.tgz", - "integrity": "sha512-MWmDTJszdO3X2LvbvIZocdfJnb/wjr3zhU99IlruwxsFfVNHbl03091bXi1ABsV5dyU+47V/A5jG3xOtg5X0vQ==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@oxc-transform/binding-freebsd-x64": { - "version": "0.80.0", - "resolved": "https://registry.npmjs.org/@oxc-transform/binding-freebsd-x64/-/binding-freebsd-x64-0.80.0.tgz", - "integrity": "sha512-fKuwj/iBfjfGePjcR9+j2TQ/7RlrUIT4ir/OAcHWYJ/kvxp4XY/juKYXo4lks/MW/dwe+UR1Lp6xiCQBuxpyIg==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@oxc-transform/binding-linux-arm-gnueabihf": { - "version": "0.80.0", - "resolved": "https://registry.npmjs.org/@oxc-transform/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-0.80.0.tgz", - "integrity": "sha512-R0QdfKiV+ZFiM28UnyylOEtTBFjAb4XuHvQltUSUpylXXIbGd+0Z1WF5lY3Z776Vy00HWhYj/Vo03rhvjdVDTA==", - "cpu": [ - "arm" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@oxc-transform/binding-linux-arm-musleabihf": { - "version": "0.80.0", - "resolved": "https://registry.npmjs.org/@oxc-transform/binding-linux-arm-musleabihf/-/binding-linux-arm-musleabihf-0.80.0.tgz", - "integrity": "sha512-hIfp4LwyQMRhsY9ptx4UleffoY9wZofTmnHFhZTMdb/hoE97Vuqw7Ub2cLcWMu0FYHIX8zXCMd1CJjs2MV1X3w==", - "cpu": [ - "arm" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@oxc-transform/binding-linux-arm64-gnu": { - "version": "0.80.0", - "resolved": "https://registry.npmjs.org/@oxc-transform/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-0.80.0.tgz", - "integrity": "sha512-mOYGji1m55BD2vV5m1qnrXbdqyPp/AU9p1Rn+0hM2zkE3pVkETCPvLevSvt4rHQZBZFIWeRGo47QNsNQyaZBsg==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@oxc-transform/binding-linux-arm64-musl": { - "version": "0.80.0", - "resolved": "https://registry.npmjs.org/@oxc-transform/binding-linux-arm64-musl/-/binding-linux-arm64-musl-0.80.0.tgz", - "integrity": "sha512-kBBCQwr1GCkr/b0iXH+ijsg+CSPCAMSV2tu4LmG2PFaxBnZilMYfUyWHCAiskbbUADikecUfwX6hHIaQoMaixg==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@oxc-transform/binding-linux-riscv64-gnu": { - "version": "0.80.0", - "resolved": "https://registry.npmjs.org/@oxc-transform/binding-linux-riscv64-gnu/-/binding-linux-riscv64-gnu-0.80.0.tgz", - "integrity": "sha512-8CGJhHoD2Ttw8HtCNd/IWnGtL0Nsn448L2hZJtbDDGVUZUF4bbZFdXPnRt0QrEbupywoH6InN6q2imLous6xnw==", - "cpu": [ - "riscv64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@oxc-transform/binding-linux-s390x-gnu": { - "version": "0.80.0", - "resolved": "https://registry.npmjs.org/@oxc-transform/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-0.80.0.tgz", - "integrity": "sha512-V/Lb6m5loWzvdB/qo6eYvVXidQku/PA706JbeE/PPCup8At+BwOXnZjktv7LDxrpuqnO32tZDHUUc9Y3bzOEBw==", - "cpu": [ - "s390x" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@oxc-transform/binding-linux-x64-gnu": { - "version": "0.80.0", - "resolved": "https://registry.npmjs.org/@oxc-transform/binding-linux-x64-gnu/-/binding-linux-x64-gnu-0.80.0.tgz", - "integrity": "sha512-03hHW04MQNb+ak27xo79nUkMjVu6146TNgeSapcDRATH4R0YMmXB2oPQK1K2nuBJzVZjBjH7Bus/I7tR3JasAg==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@oxc-transform/binding-linux-x64-musl": { - "version": "0.80.0", - "resolved": "https://registry.npmjs.org/@oxc-transform/binding-linux-x64-musl/-/binding-linux-x64-musl-0.80.0.tgz", - "integrity": "sha512-BkXniuuHpo9cR2S3JDKIvmUrNvmm335owGW4rfp07HjVUsbq9e7bSnvOnyA3gXGdrPR2IgCWGi5nnXk2NN5Q0A==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@oxc-transform/binding-wasm32-wasi": { - "version": "0.80.0", - "resolved": "https://registry.npmjs.org/@oxc-transform/binding-wasm32-wasi/-/binding-wasm32-wasi-0.80.0.tgz", - "integrity": "sha512-jfRRXLtfSgTeJXBHj6qb+HHUd6hmYcyUNMBcTY8/k+JVsx0ThfrmCIufNlSJTt1zB+ugnMVMuQGeB0oF+aa86w==", - "cpu": [ - "wasm32" - ], - "license": "MIT", - "optional": true, - "dependencies": { - "@napi-rs/wasm-runtime": "^1.0.1" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@oxc-transform/binding-win32-arm64-msvc": { - "version": "0.80.0", - "resolved": "https://registry.npmjs.org/@oxc-transform/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-0.80.0.tgz", - "integrity": "sha512-bofcVhlAV1AKzbE0TgDH+h813pbwWwwRhN6tv/hD4qEuWh/qEjv8Xb3Ar15xfBfyLI53FoJascuaJAFzX+IN9A==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@oxc-transform/binding-win32-x64-msvc": { - "version": "0.80.0", - "resolved": "https://registry.npmjs.org/@oxc-transform/binding-win32-x64-msvc/-/binding-win32-x64-msvc-0.80.0.tgz", - "integrity": "sha512-MT6hQo9Kw/VuQUfX0fc0OpUdZesQruT0UNY9hxIcqcli7pbxMrvFBjkXo7oUb2151s/n+F4fyQOWvaR6zwxtDA==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=14.0.0" - } - }, "node_modules/@parcel/watcher": { "version": "2.5.1", "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.1.tgz", @@ -3502,26 +1666,6 @@ "@parcel/watcher-win32-x64": "2.5.1" } }, - "node_modules/@parcel/watcher-android-arm64": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.1.tgz", - "integrity": "sha512-KF8+j9nNbUN8vzOFDpRMsaKBHZ/mcjEjMToVMJOhTozkDonQFFrRcfdLWn6yWKCmJKmdVxSgHiYvTCef4/qcBA==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, "node_modules/@parcel/watcher-darwin-arm64": { "version": "2.5.1", "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.1.tgz", @@ -3542,166 +1686,6 @@ "url": "https://opencollective.com/parcel" } }, - "node_modules/@parcel/watcher-darwin-x64": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.1.tgz", - "integrity": "sha512-1ZXDthrnNmwv10A0/3AJNZ9JGlzrF82i3gNQcWOzd7nJ8aj+ILyW1MTxVk35Db0u91oD5Nlk9MBiujMlwmeXZg==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-freebsd-x64": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.1.tgz", - "integrity": "sha512-SI4eljM7Flp9yPuKi8W0ird8TI/JK6CSxju3NojVI6BjHsTyK7zxA9urjVjEKJ5MBYC+bLmMcbAWlZ+rFkLpJQ==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-linux-arm-glibc": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.1.tgz", - "integrity": "sha512-RCdZlEyTs8geyBkkcnPWvtXLY44BCeZKmGYRtSgtwwnHR4dxfHRG3gR99XdMEdQ7KeiDdasJwwvNSF5jKtDwdA==", - "cpu": [ - "arm" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-linux-arm-musl": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.1.tgz", - "integrity": "sha512-6E+m/Mm1t1yhB8X412stiKFG3XykmgdIOqhjWj+VL8oHkKABfu/gjFj8DvLrYVHSBNC+/u5PeNrujiSQ1zwd1Q==", - "cpu": [ - "arm" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-linux-arm64-glibc": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.1.tgz", - "integrity": "sha512-LrGp+f02yU3BN9A+DGuY3v3bmnFUggAITBGriZHUREfNEzZh/GO06FF5u2kx8x+GBEUYfyTGamol4j3m9ANe8w==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-linux-arm64-musl": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.1.tgz", - "integrity": "sha512-cFOjABi92pMYRXS7AcQv9/M1YuKRw8SZniCDw0ssQb/noPkRzA+HBDkwmyOJYp5wXcsTrhxO0zq1U11cK9jsFg==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-linux-x64-glibc": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.1.tgz", - "integrity": "sha512-GcESn8NZySmfwlTsIur+49yDqSny2IhPeZfXunQi48DMugKeZ7uy1FX83pO0X22sHntJ4Ub+9k34XQCX+oHt2A==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-linux-x64-musl": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.1.tgz", - "integrity": "sha512-n0E2EQbatQ3bXhcH2D1XIAANAcTZkQICBPVaxMeaCVBtOpBZpWJuf7LwyWPSBDITb7In8mqQgJ7gH8CILCURXg==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, "node_modules/@parcel/watcher-wasm": { "version": "2.5.1", "resolved": "https://registry.npmjs.org/@parcel/watcher-wasm/-/watcher-wasm-2.5.1.tgz", @@ -3728,66 +1712,6 @@ "inBundle": true, "license": "MIT" }, - "node_modules/@parcel/watcher-win32-arm64": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.1.tgz", - "integrity": "sha512-RFzklRvmc3PkjKjry3hLF9wD7ppR4AKcWNzH7kXR7GUe0Igb3Nz8fyPwtZCSquGrhU5HhUNDr/mKBqj7tqA2Vw==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-win32-ia32": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.1.tgz", - "integrity": "sha512-c2KkcVN+NJmuA7CGlaGD1qJh1cLfDnQsHjE89E60vUEMlqduHGCdCLJCID5geFVM0dOtA3ZiIO8BoEQmzQVfpQ==", - "cpu": [ - "ia32" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-win32-x64": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.1.tgz", - "integrity": "sha512-9lHBdJITeNR++EvSQVUcaZoWupyHfXe1jZvGZ06O/5MflPcuPLtEphScIBL+AiCWBO46tDSHzWyD0uDmmZqsgA==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, "node_modules/@pkgjs/parseargs": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", @@ -4098,32 +2022,6 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.49.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.49.0.tgz", - "integrity": "sha512-rlKIeL854Ed0e09QGYFlmDNbka6I3EQFw7iZuugQjMb11KMpJCLPFL4ZPbMfaEhLADEL1yx0oujGkBQ7+qW3eA==", - "cpu": [ - "arm" - ], - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-android-arm64": { - "version": "4.49.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.49.0.tgz", - "integrity": "sha512-cqPpZdKUSQYRtLLr6R4X3sD4jCBO1zUmeo3qrWBCqYIeH8Q3KRL4F3V7XJ2Rm8/RJOQBZuqzQGWPjjvFUcYa/w==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, "node_modules/@rollup/rollup-darwin-arm64": { "version": "4.49.0", "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.49.0.tgz", @@ -4137,227 +2035,6 @@ "darwin" ] }, - "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.49.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.49.0.tgz", - "integrity": "sha512-y8cXoD3wdWUDpjOLMKLx6l+NFz3NlkWKcBCBfttUn+VGSfgsQ5o/yDUGtzE9HvsodkP0+16N0P4Ty1VuhtRUGg==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.49.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.49.0.tgz", - "integrity": "sha512-3mY5Pr7qv4GS4ZvWoSP8zha8YoiqrU+e0ViPvB549jvliBbdNLrg2ywPGkgLC3cmvN8ya3za+Q2xVyT6z+vZqA==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.49.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.49.0.tgz", - "integrity": "sha512-C9KzzOAQU5gU4kG8DTk+tjdKjpWhVWd5uVkinCwwFub2m7cDYLOdtXoMrExfeBmeRy9kBQMkiyJ+HULyF1yj9w==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.49.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.49.0.tgz", - "integrity": "sha512-OVSQgEZDVLnTbMq5NBs6xkmz3AADByCWI4RdKSFNlDsYXdFtlxS59J+w+LippJe8KcmeSSM3ba+GlsM9+WwC1w==", - "cpu": [ - "arm" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.49.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.49.0.tgz", - "integrity": "sha512-ZnfSFA7fDUHNa4P3VwAcfaBLakCbYaxCk0jUnS3dTou9P95kwoOLAMlT3WmEJDBCSrOEFFV0Y1HXiwfLYJuLlA==", - "cpu": [ - "arm" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.49.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.49.0.tgz", - "integrity": "sha512-Z81u+gfrobVK2iV7GqZCBfEB1y6+I61AH466lNK+xy1jfqFLiQ9Qv716WUM5fxFrYxwC7ziVdZRU9qvGHkYIJg==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.49.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.49.0.tgz", - "integrity": "sha512-zoAwS0KCXSnTp9NH/h9aamBAIve0DXeYpll85shf9NJ0URjSTzzS+Z9evmolN+ICfD3v8skKUPyk2PO0uGdFqg==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-loongarch64-gnu": { - "version": "4.49.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.49.0.tgz", - "integrity": "sha512-2QyUyQQ1ZtwZGiq0nvODL+vLJBtciItC3/5cYN8ncDQcv5avrt2MbKt1XU/vFAJlLta5KujqyHdYtdag4YEjYQ==", - "cpu": [ - "loong64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-ppc64-gnu": { - "version": "4.49.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.49.0.tgz", - "integrity": "sha512-k9aEmOWt+mrMuD3skjVJSSxHckJp+SiFzFG+v8JLXbc/xi9hv2icSkR3U7uQzqy+/QbbYY7iNB9eDTwrELo14g==", - "cpu": [ - "ppc64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.49.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.49.0.tgz", - "integrity": "sha512-rDKRFFIWJ/zJn6uk2IdYLc09Z7zkE5IFIOWqpuU0o6ZpHcdniAyWkwSUWE/Z25N/wNDmFHHMzin84qW7Wzkjsw==", - "cpu": [ - "riscv64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.49.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.49.0.tgz", - "integrity": "sha512-FkkhIY/hYFVnOzz1WeV3S9Bd1h0hda/gRqvZCMpHWDHdiIHn6pqsY3b5eSbvGccWHMQ1uUzgZTKS4oGpykf8Tw==", - "cpu": [ - "riscv64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.49.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.49.0.tgz", - "integrity": "sha512-gRf5c+A7QiOG3UwLyOOtyJMD31JJhMjBvpfhAitPAoqZFcOeK3Kc1Veg1z/trmt+2P6F/biT02fU19GGTS529A==", - "cpu": [ - "s390x" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.49.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.49.0.tgz", - "integrity": "sha512-BR7+blScdLW1h/2hB/2oXM+dhTmpW3rQt1DeSiCP9mc2NMMkqVgjIN3DDsNpKmezffGC9R8XKVOLmBkRUcK/sA==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.49.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.49.0.tgz", - "integrity": "sha512-hDMOAe+6nX3V5ei1I7Au3wcr9h3ktKzDvF2ne5ovX8RZiAHEtX1A5SNNk4zt1Qt77CmnbqT+upb/umzoPMWiPg==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.49.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.49.0.tgz", - "integrity": "sha512-wkNRzfiIGaElC9kXUT+HLx17z7D0jl+9tGYRKwd8r7cUqTL7GYAvgUY++U2hK6Ar7z5Z6IRRoWC8kQxpmM7TDA==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.49.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.49.0.tgz", - "integrity": "sha512-gq5aW/SyNpjp71AAzroH37DtINDcX1Qw2iv9Chyz49ZgdOP3NV8QCyKZUrGsYX9Yyggj5soFiRCgsL3HwD8TdA==", - "cpu": [ - "ia32" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.49.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.49.0.tgz", - "integrity": "sha512-gEtqFbzmZLFk2xKh7g0Rlo8xzho8KrEFEkzvHbfUGkrgXOpZ4XagQ6n+wIZFNh1nTb8UD16J4nFSFKXYgnbdBg==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, "node_modules/@sindresorhus/is": { "version": "7.0.2", "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-7.0.2.tgz", diff --git a/frontend_nuxt/package.json b/frontend_nuxt/package.json index 31f873a29..43c4f2b60 100644 --- a/frontend_nuxt/package.json +++ b/frontend_nuxt/package.json @@ -13,7 +13,7 @@ }, "dependencies": { "@icon-park/vue-next": "^1.4.2", - "@ffmpeg/ffmpeg": "^0.12.15", + "@ffmpeg/ffmpeg": "^0.12.10", "@ffmpeg/util": "^0.12.2", "@nuxt/image": "^1.11.0", "@stomp/stompjs": "^7.0.0", diff --git a/frontend_nuxt/plugins/ffmpeg.client.ts b/frontend_nuxt/plugins/ffmpeg.client.ts index 562a93aa2..b4d6eee6b 100644 --- a/frontend_nuxt/plugins/ffmpeg.client.ts +++ b/frontend_nuxt/plugins/ffmpeg.client.ts @@ -1,29 +1,16 @@ import { FFmpeg } from '@ffmpeg/ffmpeg' import { toBlobURL } from '@ffmpeg/util' -import { defineNuxtPlugin, useRuntimeConfig } from 'nuxt/app' +import { defineNuxtPlugin } from 'nuxt/app' let ffmpeg: FFmpeg | null = null export default defineNuxtPlugin(() => { - const { - public: { ffmpegVersion }, - } = useRuntimeConfig() - return { provide: { ffmpeg: async () => { if (ffmpeg) return ffmpeg - ffmpeg = new FFmpeg() - - const mtOk = - typeof crossOriginIsolated !== 'undefined' && - crossOriginIsolated && - typeof SharedArrayBuffer !== 'undefined' - - const pkg = mtOk ? '@ffmpeg/core-mt' : '@ffmpeg/core-st' - const base = `https://unpkg.com/${pkg}@${ffmpegVersion}/dist/umd` - + const base = `https://unpkg.com/@ffmpeg/core-mt@0.12.10/dist/umd` await ffmpeg.load({ coreURL: await toBlobURL(`${base}/ffmpeg-core.js`, 'text/javascript'), wasmURL: await toBlobURL(`${base}/ffmpeg-core.wasm`, 'application/wasm'), From ab04a8b6b1e310d136fd1dd00db5fa3d07745167 Mon Sep 17 00:00:00 2001 From: tim Date: Thu, 11 Sep 2025 19:10:14 +0800 Subject: [PATCH 08/26] =?UTF-8?q?fix:=20ffmpeg=20=E5=8E=8B=E7=BC=A9?= =?UTF-8?q?=E9=80=82=E9=85=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend_nuxt/nuxt.config.ts | 2 +- frontend_nuxt/package-lock.json | 2 +- frontend_nuxt/package.json | 2 +- frontend_nuxt/plugins/ffmpeg.client.ts | 5 +++-- frontend_nuxt/utils/vditor.js | 2 +- 5 files changed, 7 insertions(+), 6 deletions(-) diff --git a/frontend_nuxt/nuxt.config.ts b/frontend_nuxt/nuxt.config.ts index 5f4264567..257566037 100644 --- a/frontend_nuxt/nuxt.config.ts +++ b/frontend_nuxt/nuxt.config.ts @@ -98,7 +98,7 @@ export default defineNuxtConfig({ }, vite: { optimizeDeps: { - include: ['@ffmpeg/ffmpeg', '@ffmpeg/util'], + exclude: ['@ffmpeg/ffmpeg', '@ffmpeg/util'], }, build: {}, }, diff --git a/frontend_nuxt/package-lock.json b/frontend_nuxt/package-lock.json index 8493a2590..06383280b 100644 --- a/frontend_nuxt/package-lock.json +++ b/frontend_nuxt/package-lock.json @@ -6,7 +6,7 @@ "": { "name": "frontend_nuxt", "dependencies": { - "@ffmpeg/ffmpeg": "^0.12.10", + "@ffmpeg/ffmpeg": "^0.12.2", "@ffmpeg/util": "^0.12.2", "@icon-park/vue-next": "^1.4.2", "@nuxt/image": "^1.11.0", diff --git a/frontend_nuxt/package.json b/frontend_nuxt/package.json index 43c4f2b60..2756684f9 100644 --- a/frontend_nuxt/package.json +++ b/frontend_nuxt/package.json @@ -13,7 +13,7 @@ }, "dependencies": { "@icon-park/vue-next": "^1.4.2", - "@ffmpeg/ffmpeg": "^0.12.10", + "@ffmpeg/ffmpeg": "^0.12.2", "@ffmpeg/util": "^0.12.2", "@nuxt/image": "^1.11.0", "@stomp/stompjs": "^7.0.0", diff --git a/frontend_nuxt/plugins/ffmpeg.client.ts b/frontend_nuxt/plugins/ffmpeg.client.ts index b4d6eee6b..9ea62e4e4 100644 --- a/frontend_nuxt/plugins/ffmpeg.client.ts +++ b/frontend_nuxt/plugins/ffmpeg.client.ts @@ -10,11 +10,12 @@ export default defineNuxtPlugin(() => { ffmpeg: async () => { if (ffmpeg) return ffmpeg ffmpeg = new FFmpeg() - const base = `https://unpkg.com/@ffmpeg/core-mt@0.12.10/dist/umd` + const base = `https://unpkg.com/@ffmpeg/core@0.12.2/dist/esm` + const libBase = `https://unpkg.com/@ffmpeg/ffmpeg@0.12.2/dist/esm` await ffmpeg.load({ coreURL: await toBlobURL(`${base}/ffmpeg-core.js`, 'text/javascript'), wasmURL: await toBlobURL(`${base}/ffmpeg-core.wasm`, 'application/wasm'), - workerURL: await toBlobURL(`${base}/ffmpeg-core.worker.js`, 'text/javascript'), + workerURL: await toBlobURL(`${libBase}/worker.js`, 'text/javascript'), }) return ffmpeg diff --git a/frontend_nuxt/utils/vditor.js b/frontend_nuxt/utils/vditor.js index c2c6d7d9a..3603fe542 100644 --- a/frontend_nuxt/utils/vditor.js +++ b/frontend_nuxt/utils/vditor.js @@ -118,7 +118,7 @@ export function createVditor(editorId, options = {}) { // 如果是视频文件且需要压缩 if (isVideo && sizeCheck.needsCompression) { try { - vditor.tip('视频压缩中...', 0) + vditor.tip('开始部署ffmpeg环境... 请稍等', 0) vditor.disabled() // 使用 FFmpeg 压缩视频 From 37bef0b2d7376fbf4ab24dd7c29282d3f52fa2e1 Mon Sep 17 00:00:00 2001 From: Tim Date: Fri, 12 Sep 2025 10:15:17 +0800 Subject: [PATCH 09/26] =?UTF-8?q?fix:=20remove=20=E4=BE=9D=E8=B5=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend_nuxt/package-lock.json | 81 --------------------------------- 1 file changed, 81 deletions(-) diff --git a/frontend_nuxt/package-lock.json b/frontend_nuxt/package-lock.json index 06383280b..f6f32e430 100644 --- a/frontend_nuxt/package-lock.json +++ b/frontend_nuxt/package-lock.json @@ -509,58 +509,6 @@ "node": ">=18" } }, - "node_modules/@emnapi/core": { - "version": "1.4.5", - "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.4.5.tgz", - "integrity": "sha512-XsLw1dEOpkSX/WucdqUhPWP7hDxSvZiY+fsUC14h+FtQ2Ifni4znbBt8punRX+Uj2JG/uDb8nEHVKvrVlvdZ5Q==", - "license": "MIT", - "optional": true, - "dependencies": { - "@emnapi/wasi-threads": "1.0.4", - "tslib": "^2.4.0" - } - }, - "node_modules/@emnapi/core/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD", - "optional": true - }, - "node_modules/@emnapi/runtime": { - "version": "1.4.5", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.4.5.tgz", - "integrity": "sha512-++LApOtY0pEEz1zrd9vy1/zXVaVJJ/EbAF3u0fXIzPJEDtnITsBGbbK0EkM72amhl/R5b+5xx0Y/QhcVOpuulg==", - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/@emnapi/runtime/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD", - "optional": true - }, - "node_modules/@emnapi/wasi-threads": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.0.4.tgz", - "integrity": "sha512-PJR+bOmMOPH8AtcTGAyYNiuJ3/Fcoj2XN/gBEWzDIKh254XO+mM9XoXHk5GNEhodxeMznbg7BlRojVbKN+gC6g==", - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/@emnapi/wasi-threads/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD", - "optional": true - }, "node_modules/@esbuild/darwin-arm64": { "version": "0.25.9", "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.9.tgz", @@ -815,18 +763,6 @@ "node": ">=8" } }, - "node_modules/@napi-rs/wasm-runtime": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.0.3.tgz", - "integrity": "sha512-rZxtMsLwjdXkMUGC3WwsPwLNVqVqnTJT6MNIB6e+5fhMcSCPP0AOsNWuMQ5mdCq6HNjs/ZeWAEchpqeprqBD2Q==", - "license": "MIT", - "optional": true, - "dependencies": { - "@emnapi/core": "^1.4.5", - "@emnapi/runtime": "^1.4.5", - "@tybys/wasm-util": "^0.10.0" - } - }, "node_modules/@netlify/binary-info": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/@netlify/binary-info/-/binary-info-1.0.0.tgz", @@ -2081,23 +2017,6 @@ "node": ">=10.13.0" } }, - "node_modules/@tybys/wasm-util": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.0.tgz", - "integrity": "sha512-VyyPYFlOMNylG45GoAe0xDoLwWuowvf92F9kySqzYh8vmYm7D2u4iUJKa1tOUpS70Ku13ASrOkS4ScXFsTaCNQ==", - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/@tybys/wasm-util/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD", - "optional": true - }, "node_modules/@types/d3-scale": { "version": "4.0.9", "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.9.tgz", From 6497cb92afd661175ea54302b647a5c875632dec Mon Sep 17 00:00:00 2001 From: Tim <135014430+nagisa77@users.noreply.github.com> Date: Fri, 12 Sep 2025 10:41:48 +0800 Subject: [PATCH 10/26] chore: remove ffmpeg video compression --- frontend_nuxt/config/uploadConfig.js | 12 +- frontend_nuxt/nuxt.config.ts | 4 +- frontend_nuxt/package-lock.json | 32 -- frontend_nuxt/package.json | 2 - frontend_nuxt/plugins/ffmpeg.client.ts | 25 -- frontend_nuxt/utils/ffmpegVideoCompressor.js | 327 ------------------- frontend_nuxt/utils/vditor.js | 59 +--- frontend_nuxt/utils/videoCompressor.js | 51 +-- 8 files changed, 8 insertions(+), 504 deletions(-) delete mode 100644 frontend_nuxt/plugins/ffmpeg.client.ts delete mode 100644 frontend_nuxt/utils/ffmpegVideoCompressor.js diff --git a/frontend_nuxt/config/uploadConfig.js b/frontend_nuxt/config/uploadConfig.js index 0172682b0..3c252ecc0 100644 --- a/frontend_nuxt/config/uploadConfig.js +++ b/frontend_nuxt/config/uploadConfig.js @@ -1,21 +1,15 @@ /** - * 文件上传配置 - 简化版 - * 专注于 FFmpeg.wasm 视频压缩,支持 Chrome/Safari + * 文件上传配置 */ export const UPLOAD_CONFIG = { - // 视频文件配置 - 专为 FFmpeg.wasm 优化 + // 视频文件配置 VIDEO: { // 文件大小限制 (字节) MAX_SIZE: 20 * 1024 * 1024, - TARGET_SIZE: 5 * 1024 * 1024, // 5MB - // 支持的输入格式 (FFmpeg.wasm 支持更多格式) + // 支持的输入格式 SUPPORTED_FORMATS: ['mp4', 'webm', 'avi', 'mov', 'wmv', 'flv', 'mkv', 'm4v', 'ogv'], - - // 输出格式 - MP4 (兼容性最好) - OUTPUT_FORMAT: 'mp4', - OUTPUT_CODEC: 'h264', }, // 图片文件配置 diff --git a/frontend_nuxt/nuxt.config.ts b/frontend_nuxt/nuxt.config.ts index 257566037..0c5bea8ac 100644 --- a/frontend_nuxt/nuxt.config.ts +++ b/frontend_nuxt/nuxt.config.ts @@ -97,9 +97,7 @@ export default defineNuxtConfig({ }, }, vite: { - optimizeDeps: { - exclude: ['@ffmpeg/ffmpeg', '@ffmpeg/util'], - }, + optimizeDeps: {}, build: {}, }, }) diff --git a/frontend_nuxt/package-lock.json b/frontend_nuxt/package-lock.json index f6f32e430..e1d3a692d 100644 --- a/frontend_nuxt/package-lock.json +++ b/frontend_nuxt/package-lock.json @@ -6,8 +6,6 @@ "": { "name": "frontend_nuxt", "dependencies": { - "@ffmpeg/ffmpeg": "^0.12.2", - "@ffmpeg/util": "^0.12.2", "@icon-park/vue-next": "^1.4.2", "@nuxt/image": "^1.11.0", "@stomp/stompjs": "^7.0.0", @@ -547,36 +545,6 @@ "integrity": "sha512-m9FVDXU3GT2ITSe0UaMA5rU3QkfC/UXtCU8y0gSN/GugTqtVldOBWIB5V6V3sbmenVZUIpU6f+mPEO2+m5iTaA==", "license": "MIT" }, - "node_modules/@ffmpeg/ffmpeg": { - "version": "0.12.15", - "resolved": "https://registry.npmmirror.com/@ffmpeg/ffmpeg/-/ffmpeg-0.12.15.tgz", - "integrity": "sha512-1C8Obr4GsN3xw+/1Ww6PFM84wSQAGsdoTuTWPOj2OizsRDLT4CXTaVjPhkw6ARyDus1B9X/L2LiXHqYYsGnRFw==", - "license": "MIT", - "dependencies": { - "@ffmpeg/types": "^0.12.4" - }, - "engines": { - "node": ">=18.x" - } - }, - "node_modules/@ffmpeg/types": { - "version": "0.12.4", - "resolved": "https://registry.npmmirror.com/@ffmpeg/types/-/types-0.12.4.tgz", - "integrity": "sha512-k9vJQNBGTxE5AhYDtOYR5rO5fKsspbg51gbcwtbkw2lCdoIILzklulcjJfIDwrtn7XhDeF2M+THwJ2FGrLeV6A==", - "license": "MIT", - "engines": { - "node": ">=16.x" - } - }, - "node_modules/@ffmpeg/util": { - "version": "0.12.2", - "resolved": "https://registry.npmmirror.com/@ffmpeg/util/-/util-0.12.2.tgz", - "integrity": "sha512-ouyoW+4JB7WxjeZ2y6KpRvB+dLp7Cp4ro8z0HIVpZVCM7AwFlHa0c4R8Y/a4M3wMqATpYKhC7lSFHQ0T11MEDw==", - "license": "MIT", - "engines": { - "node": ">=18.x" - } - }, "node_modules/@icon-park/vue-next": { "version": "1.4.2", "resolved": "https://registry.npmmirror.com/@icon-park/vue-next/-/vue-next-1.4.2.tgz", diff --git a/frontend_nuxt/package.json b/frontend_nuxt/package.json index 2756684f9..540a4f579 100644 --- a/frontend_nuxt/package.json +++ b/frontend_nuxt/package.json @@ -13,8 +13,6 @@ }, "dependencies": { "@icon-park/vue-next": "^1.4.2", - "@ffmpeg/ffmpeg": "^0.12.2", - "@ffmpeg/util": "^0.12.2", "@nuxt/image": "^1.11.0", "@stomp/stompjs": "^7.0.0", "cropperjs": "^1.6.2", diff --git a/frontend_nuxt/plugins/ffmpeg.client.ts b/frontend_nuxt/plugins/ffmpeg.client.ts deleted file mode 100644 index 9ea62e4e4..000000000 --- a/frontend_nuxt/plugins/ffmpeg.client.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { FFmpeg } from '@ffmpeg/ffmpeg' -import { toBlobURL } from '@ffmpeg/util' -import { defineNuxtPlugin } from 'nuxt/app' - -let ffmpeg: FFmpeg | null = null - -export default defineNuxtPlugin(() => { - return { - provide: { - ffmpeg: async () => { - if (ffmpeg) return ffmpeg - ffmpeg = new FFmpeg() - const base = `https://unpkg.com/@ffmpeg/core@0.12.2/dist/esm` - const libBase = `https://unpkg.com/@ffmpeg/ffmpeg@0.12.2/dist/esm` - await ffmpeg.load({ - coreURL: await toBlobURL(`${base}/ffmpeg-core.js`, 'text/javascript'), - wasmURL: await toBlobURL(`${base}/ffmpeg-core.wasm`, 'application/wasm'), - workerURL: await toBlobURL(`${libBase}/worker.js`, 'text/javascript'), - }) - - return ffmpeg - }, - }, - } -}) diff --git a/frontend_nuxt/utils/ffmpegVideoCompressor.js b/frontend_nuxt/utils/ffmpegVideoCompressor.js deleted file mode 100644 index 2aa155049..000000000 --- a/frontend_nuxt/utils/ffmpegVideoCompressor.js +++ /dev/null @@ -1,327 +0,0 @@ -/** - * FFmpeg.wasm 视频压缩器 - * - * 用法: - * const { $ffmpeg } = useNuxtApp() - * const ff = await $ffmpeg() // 插件里已完成 ffmpeg.load() - * const out = await compressVideoWithFFmpeg(ff, file, { onProgress, strictSize: false }) - * - * 设计要点: - * - 本文件不再负责加载/初始化,只负责转码逻辑;和 Nuxt 插件解耦。 - * - 针对【同一个 ffmpeg 实例】做串行队列,避免并发 exec 踩内存文件系统。 - * - 使用 nanoid 生成唯一文件名;日志环形缓冲;默认 CRF+VBV,可选 strictSize(two-pass)。 - * - 体积明显小于目标时直通返回,减少无谓重编码。 - */ - -import { fetchFile } from '@ffmpeg/util' -import { nanoid } from 'nanoid' -import { UPLOAD_CONFIG } from '../config/uploadConfig.js' - -/************************* - * 每实例一个串行队列 * - *************************/ -// WeakMapPromise)[], running: boolean, resolvers: {res,rej}[] }> -const queues = new WeakMap() - -function enqueueOn(instance, taskFn) { - return new Promise((res, rej) => { - let st = queues.get(instance) - if (!st) { - st = { q: [], running: false, resolvers: [] } - queues.set(instance, st) - } - st.q.push(taskFn) - st.resolvers.push({ res, rej }) - drain(instance) - }) -} - -async function drain(instance) { - const st = queues.get(instance) - if (!st || st.running) return - st.running = true - try { - while (st.q.length) { - const task = st.q.shift() - const rr = st.resolvers.shift() - try { - rr.res(await task()) - } catch (e) { - rr.rej(e) - } - } - } finally { - st.running = false - } -} - -/***************** - * 工具函数 * - *****************/ -function decideScale(widthHint) { - if (!widthHint) return { filter: null, width: null } - const evenW = widthHint % 2 === 0 ? widthHint : widthHint - 1 - return { filter: `scale=${evenW}:-2:flags=bicubic,setsar=1`, width: evenW } -} - -function calculateParamsByRatio(originalSize, targetSize) { - const ratio = Math.min(targetSize / originalSize, 1) - const crf = ratio < 0.35 ? 29 : ratio < 0.5 ? 27 : ratio < 0.7 ? 25 : 23 - const preset = ratio < 0.35 ? 'slow' : ratio < 0.5 ? 'medium' : 'veryfast' - const s = - ratio < 0.35 - ? decideScale(720) - : ratio < 0.6 - ? decideScale(960) - : ratio < 0.8 - ? decideScale(1280) - : { filter: null, width: null } - const audioBitrateK = ratio < 0.5 ? 96 : ratio < 0.7 ? 128 : 160 - const profile = s.width && s.width <= 1280 ? 'main' : 'high' - return { crf, preset, scaleFilter: s.filter, scaleWidth: s.width, audioBitrateK, profile } -} - -function makeRingLogger(capBytes = 4000) { - const buf = [] - let total = 0 - function push(s) { - if (!s) return - buf.push(s) - total += s.length - while (total > capBytes) total -= buf.shift().length - } - return { push, dump: () => buf.slice() } -} - -function parseDurationFromLogs(logs) { - // 避免正则:查找 Duration: 后的 00:00:00.xx - const text = logs.join(' ') - const idx = text.indexOf('Duration:') - if (idx === -1) return null - let i = idx + 'Duration:'.length - while (i < text.length && text[i] === ' ') i++ - function read2(start) { - const a = text.charCodeAt(start) - 48 - const b = text.charCodeAt(start + 1) - 48 - if (a < 0 || a > 9 || b < 0 || b > 9) return null - return a * 10 + b - } - const hh = read2(i) - if (hh === null) return null - i += 2 - if (text[i++] !== ':') return null - const mm = read2(i) - if (mm === null) return null - i += 2 - if (text[i++] !== ':') return null - const s1 = read2(i) - if (s1 === null) return null - i += 2 - if (text[i++] !== '.') return null - let j = i - while (j < text.length && text.charCodeAt(j) >= 48 && text.charCodeAt(j) <= 57) j++ - const frac = parseFloat('0.' + text.slice(i, j) || '0') - return hh * 3600 + mm * 60 + s1 + frac -} - -export function isFFmpegSupported() { - return typeof WebAssembly !== 'undefined' && typeof Worker !== 'undefined' -} - -/** - * 读取 ffmpeg 核心版本(通过 -version),会进入队列避免并发冲突 - */ -export async function getFFmpegInfo(ffmpegInstance) { - return enqueueOn(ffmpegInstance, async () => { - const logs = [] - const onLog = ({ type, message }) => { - if (type === 'info' || type === 'fferr') logs.push(message) - } - ffmpegInstance.on('log', onLog) - try { - await ffmpegInstance.exec(['-version']) - } finally { - ffmpegInstance.off('log', onLog) - } - const line = logs.find((l) => l.toLowerCase().includes('ffmpeg version')) || '' - const parts = line.trim().split(' ').filter(Boolean) - const version = parts.length > 2 ? parts[2] : parts[1] || null - return { version } - }) -} - -/** - * 压缩:接受一个已经 load() 完成的 ffmpeg 实例 - * @param {*} ffmpegInstance 已初始化的 FFmpeg 实例(来自 Nuxt 插件) - * @param {File|Blob} file 输入文件 - * @param {{ onProgress?:(p:{stage:string,progress:number})=>void, signal?:AbortSignal, strictSize?:boolean, targetSize?:number }} opts - */ -export async function compressVideoWithFFmpeg(ffmpegInstance, file, opts = {}) { - return enqueueOn(ffmpegInstance, () => doCompress(ffmpegInstance, file, opts)) -} - -async function doCompress(ffmpegInstance, file, opts) { - const onProgress = opts.onProgress || (() => {}) - const { signal, strictSize = false } = opts - - onProgress({ stage: 'preparing', progress: 10 }) - - const targetSize = opts.targetSize ?? UPLOAD_CONFIG?.VIDEO?.TARGET_SIZE ?? 12 * 1024 * 1024 - - // 小体积直通 - const sizeKnown = 'size' in file && typeof file.size === 'number' - if (sizeKnown && file.size <= targetSize * 0.9) { - onProgress({ stage: 'skipped', progress: 100 }) - return file - } - - const params = calculateParamsByRatio(sizeKnown ? file.size : targetSize * 2, targetSize) - const { crf, preset, scaleFilter, audioBitrateK, profile } = params - - const name = 'name' in file && typeof file.name === 'string' ? file.name : 'input.mp4' - const dot = name.lastIndexOf('.') - const outName = (dot > -1 ? name.slice(0, dot) : name) + '.mp4' - - const ext = dot > -1 ? name.slice(dot + 1).toLowerCase() : 'mp4' - const id = nanoid() - const inputName = `input-${id}.${ext}` - const outputName = `output-${id}.mp4` - const passlog = `ffpass-${id}` - - // 监听 - const ring = makeRingLogger() - const onFfmpegProgress = ({ progress: p }) => { - const adjusted = 20 + p * 70 - onProgress({ stage: 'compressing', progress: Math.min(90, adjusted) }) - } - const onFfmpegLog = ({ type, message }) => { - if (type === 'fferr' || type === 'info') ring.push(message) - } - ffmpegInstance.on('progress', onFfmpegProgress) - ffmpegInstance.on('log', onFfmpegLog) - - let aborted = false - const abortHandler = () => { - aborted = true - } - if (signal) signal.addEventListener('abort', abortHandler, { once: true }) - - try { - await ffmpegInstance.writeFile(inputName, await fetchFile(file)) - onProgress({ stage: 'analyzing', progress: 20 }) - - let durationSec = null - try { - await ffmpegInstance.exec(['-hide_banner', '-i', inputName, '-f', 'null', '-']) - durationSec = parseDurationFromLogs(ring.dump()) - } catch { - durationSec = durationSec ?? parseDurationFromLogs(ring.dump()) - } - - let videoBitrate = null - if (durationSec && sizeKnown && targetSize < file.size) { - const totalTargetBits = targetSize * 8 - const audioBits = audioBitrateK * 1000 * durationSec - const maxVideoBits = Math.max(totalTargetBits - audioBits, totalTargetBits * 0.7) - const bps = Math.max(180000, Math.floor(maxVideoBits / durationSec)) - videoBitrate = String(Math.min(bps, 5000000)) - } - - const baseArgs = [ - '-hide_banner', - '-i', - inputName, - '-c:v', - 'libx264', - '-pix_fmt', - 'yuv420p', - '-profile:v', - profile, - '-movflags', - '+faststart', - '-preset', - preset, - '-c:a', - 'aac', - '-b:a', - `${audioBitrateK}k`, - '-ac', - '2', - ] - if (scaleFilter) baseArgs.push('-vf', scaleFilter) - - const onePassArgs = [...baseArgs, '-crf', String(crf)] - if (videoBitrate) - onePassArgs.push('-maxrate', videoBitrate, '-bufsize', String(parseInt(videoBitrate, 10) * 2)) - - const twoPassFirst = [ - '-y', - '-hide_banner', - '-i', - inputName, - '-c:v', - 'libx264', - '-b:v', - `${videoBitrate || '1000000'}`, - '-pass', - '1', - '-passlogfile', - passlog, - '-an', - '-f', - 'mp4', - '/dev/null', - ] - const twoPassSecond = [ - ...baseArgs, - '-b:v', - `${videoBitrate || '1000000'}`, - '-pass', - '2', - '-passlogfile', - passlog, - outputName, - ] - - if (aborted) throw new DOMException('Aborted', 'AbortError') - - if (!strictSize) { - await ffmpegInstance.exec([...onePassArgs, outputName]) - } else { - if (!videoBitrate) videoBitrate = '1000000' - await ffmpegInstance.exec(twoPassFirst) - onProgress({ stage: 'second-pass', progress: 85 }) - await ffmpegInstance.exec(twoPassSecond) - } - - if (aborted) throw new DOMException('Aborted', 'AbortError') - - onProgress({ stage: 'finalizing', progress: 95 }) - const out = await ffmpegInstance.readFile(outputName) - - const mime = 'video/mp4' - const blob = new Blob([out], { type: mime }) - const hasFileCtor = typeof File === 'function' - const result = hasFileCtor ? new File([blob], outName, { type: mime }) : blob - - onProgress({ stage: 'completed', progress: 100 }) - return result - } finally { - try { - await ffmpegInstance.deleteFile(inputName) - } catch {} - try { - await ffmpegInstance.deleteFile(outputName) - } catch {} - try { - await ffmpegInstance.deleteFile(`${passlog}-0.log`) - } catch {} - try { - await ffmpegInstance.deleteFile(`${passlog}-0.log.mbtree`) - } catch {} - - ffmpegInstance.off('progress', onFfmpegProgress) - ffmpegInstance.off('log', onFfmpegLog) - if (signal) signal.removeEventListener('abort', abortHandler) - } -} diff --git a/frontend_nuxt/utils/vditor.js b/frontend_nuxt/utils/vditor.js index 3603fe542..bef1fdeee 100644 --- a/frontend_nuxt/utils/vditor.js +++ b/frontend_nuxt/utils/vditor.js @@ -3,8 +3,7 @@ import { getToken, authState } from './auth' import { searchUsers, fetchFollowings, fetchAdmins } from './user' import { tiebaEmoji } from './tiebaEmoji' import vditorPostCitation from './vditorPostCitation.js' -import { checkFileSize, formatFileSize, compressVideo, VIDEO_CONFIG } from './videoCompressor.js' -import { UPLOAD_CONFIG } from '../config/uploadConfig.js' +import { checkFileSize, formatFileSize } from './videoCompressor.js' export function getEditorTheme() { return document.documentElement.dataset.theme === 'dark' ? 'dark' : 'classic' @@ -95,7 +94,6 @@ export function createVditor(editorId, options = {}) { const file = files[0] const ext = file.name.split('.').pop().toLowerCase() const videoExts = ['mp4', 'webm', 'avi', 'mov', 'wmv', 'flv', 'mkv', 'm4v', 'ogv'] - const isVideo = videoExts.includes(ext) // 检查文件大小 const sizeCheck = checkFileSize(file) @@ -113,61 +111,10 @@ export function createVditor(editorId, options = {}) { return '文件过大' } - let processedFile = file - - // 如果是视频文件且需要压缩 - if (isVideo && sizeCheck.needsCompression) { - try { - vditor.tip('开始部署ffmpeg环境... 请稍等', 0) - vditor.disabled() - - // 使用 FFmpeg 压缩视频 - processedFile = await compressVideo(file, (progress) => { - const messages = { - initializing: '初始化 FFmpeg', - preparing: '准备压缩', - analyzing: '分析视频', - compressing: '压缩中', - finalizing: '完成压缩', - completed: '压缩完成', - } - const message = messages[progress.stage] || progress.stage - vditor.tip(`${message} ${progress.progress}%`, 0) - }) - - const originalSize = formatFileSize(file.size) - const compressedSize = formatFileSize(processedFile.size) - const savings = Math.round((1 - processedFile.size / file.size) * 100) - - vditor.tip(`压缩完成!${originalSize} → ${compressedSize} (节省 ${savings}%)`, 2000) - // 压缩成功但仍然超过最大限制,则阻止上传 - if (processedFile.size > VIDEO_CONFIG.MAX_SIZE) { - vditor.tip( - `压缩后仍超过限制 (${formatFileSize(VIDEO_CONFIG.MAX_SIZE)}). 请降低分辨率或码率后再上传。`, - 4000, - ) - vditor.enable() - return '压缩后仍超过大小限制' - } - } catch (error) { - // 压缩失败时,如果原文件超过最大限制,则阻止上传 - if (file.size > VIDEO_CONFIG.MAX_SIZE) { - vditor.tip( - `视频压缩失败,且文件超过限制 (${formatFileSize(VIDEO_CONFIG.MAX_SIZE)}). 请先压缩后再上传。`, - 4000, - ) - vditor.enable() - return '视频压缩失败且文件过大' - } - vditor.tip('视频压缩失败,将尝试上传原文件', 3000) - processedFile = file - } - } - vditor.tip('文件上传中', 0) vditor.disabled() const res = await fetch( - `${API_BASE_URL}/api/upload/presign?filename=${encodeURIComponent(processedFile.name)}`, + `${API_BASE_URL}/api/upload/presign?filename=${encodeURIComponent(file.name)}`, { headers: { Authorization: `Bearer ${getToken()}` } }, ) if (!res.ok) { @@ -176,7 +123,7 @@ export function createVditor(editorId, options = {}) { return '获取上传地址失败' } const info = await res.json() - const put = await fetch(info.uploadUrl, { method: 'PUT', body: processedFile }) + const put = await fetch(info.uploadUrl, { method: 'PUT', body: file }) if (!put.ok) { vditor.enable() vditor.tip('上传失败') diff --git a/frontend_nuxt/utils/videoCompressor.js b/frontend_nuxt/utils/videoCompressor.js index 584d8a487..bffa6c453 100644 --- a/frontend_nuxt/utils/videoCompressor.js +++ b/frontend_nuxt/utils/videoCompressor.js @@ -1,11 +1,8 @@ /** - * 基于 FFmpeg.wasm 的视频压缩工具 - * 专为现代浏览器 (Chrome/Safari) 优化 + * 视频上传工具 */ import { UPLOAD_CONFIG } from '../config/uploadConfig.js' -import { compressVideoWithFFmpeg, isFFmpegSupported } from './ffmpegVideoCompressor.js' -import { useNuxtApp } from '#app' // 导出配置供外部使用 export const VIDEO_CONFIG = UPLOAD_CONFIG.VIDEO @@ -18,7 +15,6 @@ export function checkFileSize(file) { isValid: file.size <= VIDEO_CONFIG.MAX_SIZE, actualSize: file.size, maxSize: VIDEO_CONFIG.MAX_SIZE, - needsCompression: file.size > VIDEO_CONFIG.TARGET_SIZE, } } @@ -32,48 +28,3 @@ export function formatFileSize(bytes) { const i = Math.floor(Math.log(bytes) / Math.log(k)) return parseFloat((bytes / Math.pow(k, i)).toFixed(1)) + ' ' + sizes[i] } - -/** - * 压缩视频文件 - 使用 FFmpeg.wasm - */ -export async function compressVideo(file, onProgress = () => {}) { - // 检查是否需要压缩 - const sizeCheck = checkFileSize(file) - if (!sizeCheck.needsCompression) { - onProgress({ stage: 'completed', progress: 100 }) - return file - } - - // 检查 FFmpeg 支持 - if (!isFFmpegSupported()) { - throw new Error('当前浏览器不支持视频压缩功能,请使用 Chrome 或 Safari 浏览器') - } - - try { - const { $ffmpeg } = useNuxtApp() - const ff = await $ffmpeg() - return await compressVideoWithFFmpeg(ff, file, { onProgress }) - } catch (error) { - console.error('FFmpeg 压缩失败:', error) - throw new Error(`视频压缩失败: ${error.message}`) - } -} - -/** - * 预加载 FFmpeg(可选的性能优化) - */ -export async function preloadVideoCompressor() { - try { - // FFmpeg 初始化现在通过 Nuxt 插件处理 - // 这里只需要检查支持性 - if (!isFFmpegSupported()) { - throw new Error('当前浏览器不支持 FFmpeg') - } - const { $ffmpeg } = useNuxtApp() - await $ffmpeg() - return { success: true, message: 'FFmpeg 预加载成功' } - } catch (error) { - console.warn('FFmpeg 预加载失败:', error) - return { success: false, error: error.message } - } -} From d8534fb94d65f1659a76c7857dc1f83bda996741 Mon Sep 17 00:00:00 2001 From: Tim Date: Fri, 12 Sep 2025 10:43:06 +0800 Subject: [PATCH 11/26] =?UTF-8?q?fix:=20=E8=AF=84=E8=AE=BA=E5=90=8E--?= =?UTF-8?q?=E9=9C=80=E8=A6=81=E5=88=B7=E6=96=B0=E5=B8=96=E5=AD=90=E5=86=85?= =?UTF-8?q?=E5=AE=B9=20#939?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend_nuxt/assets/global.css | 6 +++--- frontend_nuxt/pages/posts/[id]/index.vue | 21 +++++++++++---------- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/frontend_nuxt/assets/global.css b/frontend_nuxt/assets/global.css index f39535231..6105d1ab9 100644 --- a/frontend_nuxt/assets/global.css +++ b/frontend_nuxt/assets/global.css @@ -356,7 +356,7 @@ body { } .d2h-file-name { - font-size: 12px !important; + font-size: 14px !important; } .d2h-file-header { @@ -371,14 +371,14 @@ body { padding-left: 10px !important; } - .d2h-diff-table { + /* .d2h-diff-table { font-size: 6px !important; } .d2h-code-line ins { height: 100%; font-size: 13px !important; - } + } */ /* .d2h-code-line { height: 12px; diff --git a/frontend_nuxt/pages/posts/[id]/index.vue b/frontend_nuxt/pages/posts/[id]/index.vue index 9c491d71c..cad9525c8 100644 --- a/frontend_nuxt/pages/posts/[id]/index.vue +++ b/frontend_nuxt/pages/posts/[id]/index.vue @@ -445,7 +445,7 @@ const handleContentClick = (e) => { const onCommentDeleted = (id) => { removeCommentFromList(Number(id), comments.value) - fetchComments() + fetchTimeline() } const { @@ -557,7 +557,7 @@ const postComment = async (parentUserName, text, clear) => { if (res.ok) { const data = await res.json() console.debug('Post comment response data', data) - await fetchComments() + await fetchTimeline() clear() if (data.reward && data.reward > 0) { toast.success(`评论成功,获得 ${data.reward} 经验值`) @@ -612,7 +612,7 @@ const approvePost = async () => { status.value = 'PUBLISHED' toast.success('已通过审核') await refreshPost() - await fetchChangeLogs() + await fetchTimeline() } else { toast.error('操作失败') } @@ -628,7 +628,7 @@ const pinPost = async () => { if (res.ok) { toast.success('已置顶') await refreshPost() - await fetchChangeLogs() + await fetchTimeline() } else { toast.error('操作失败') } @@ -644,7 +644,7 @@ const unpinPost = async () => { if (res.ok) { toast.success('已取消置顶') await refreshPost() - await fetchChangeLogs() + await fetchTimeline() } else { toast.error('操作失败') } @@ -660,7 +660,7 @@ const excludeRss = async () => { if (res.ok) { rssExcluded.value = true toast.success('已标记为rss不推荐') - await fetchChangeLogs() + await fetchTimeline() } else { toast.error('操作失败') } @@ -676,7 +676,8 @@ const includeRss = async () => { if (res.ok) { rssExcluded.value = false toast.success('已标记为rss推荐') - await fetchChangeLogs() + await refreshPost() + await fetchTimeline() } else { toast.error('操作失败') } @@ -693,7 +694,7 @@ const closePost = async () => { closed.value = true toast.success('已关闭') await refreshPost() - await fetchChangeLogs() + await fetchTimeline() } else { toast.error('操作失败') } @@ -710,7 +711,7 @@ const reopenPost = async () => { closed.value = false toast.success('已重新打开') await refreshPost() - await fetchChangeLogs() + await fetchTimeline() } else { toast.error('操作失败') } @@ -755,7 +756,7 @@ const rejectPost = async () => { status.value = 'REJECTED' toast.success('已驳回') await refreshPost() - await fetchChangeLogs() + await fetchTimeline() } else { toast.error('操作失败') } From abbdb224e06f432ce3d93c78362e2e12656d47ca Mon Sep 17 00:00:00 2001 From: Tim <135014430+nagisa77@users.noreply.github.com> Date: Fri, 12 Sep 2025 10:50:15 +0800 Subject: [PATCH 12/26] fix: restrict image preview to markdown images --- frontend_nuxt/components/CommentItem.vue | 2 +- frontend_nuxt/pages/message-box/[id].vue | 6 +++++- frontend_nuxt/pages/posts/[id]/index.vue | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/frontend_nuxt/components/CommentItem.vue b/frontend_nuxt/components/CommentItem.vue index 5147db26d..584f0a90b 100644 --- a/frontend_nuxt/components/CommentItem.vue +++ b/frontend_nuxt/components/CommentItem.vue @@ -342,7 +342,7 @@ const copyCommentLink = () => { const handleContentClick = (e) => { handleMarkdownClick(e) - if (e.target.tagName === 'IMG') { + if (e.target.tagName === 'IMG' && !e.target.classList.contains('emoji')) { const container = e.target.parentNode const imgs = [...container.querySelectorAll('img')].map((i) => i.src) lightboxImgs.value = imgs diff --git a/frontend_nuxt/pages/message-box/[id].vue b/frontend_nuxt/pages/message-box/[id].vue index 39265b66a..ddd581136 100644 --- a/frontend_nuxt/pages/message-box/[id].vue +++ b/frontend_nuxt/pages/message-box/[id].vue @@ -463,7 +463,11 @@ function minimize() { function handleContentClick(e) { handleMarkdownClick(e) - if (e.target.tagName === 'IMG') { + if ( + e.target.tagName === 'IMG' && + !e.target.classList.contains('emoji') && + !e.target.closest('.reactions-container') + ) { const container = e.target.parentNode const imgs = [...container.querySelectorAll('img')].map((i) => i.src) lightboxImgs.value = imgs diff --git a/frontend_nuxt/pages/posts/[id]/index.vue b/frontend_nuxt/pages/posts/[id]/index.vue index 9c491d71c..2a9d08173 100644 --- a/frontend_nuxt/pages/posts/[id]/index.vue +++ b/frontend_nuxt/pages/posts/[id]/index.vue @@ -434,7 +434,7 @@ const removeCommentFromList = (id, list) => { const handleContentClick = (e) => { handleMarkdownClick(e) - if (e.target.tagName === 'IMG') { + if (e.target.tagName === 'IMG' && !e.target.classList.contains('emoji')) { const container = e.target.parentNode const imgs = [...container.querySelectorAll('img')].map((i) => i.src) lightboxImgs.value = imgs From c3758cafe8dd29c3fbf8962bd2b817f2676cbff3 Mon Sep 17 00:00:00 2001 From: tim Date: Fri, 12 Sep 2025 13:42:03 +0800 Subject: [PATCH 13/26] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E5=86=85?= =?UTF-8?q?=E5=AE=B9=E7=BB=91=E5=AE=9A=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend_nuxt/pages/message-box/[id].vue | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/frontend_nuxt/pages/message-box/[id].vue b/frontend_nuxt/pages/message-box/[id].vue index ddd581136..56fe7cefa 100644 --- a/frontend_nuxt/pages/message-box/[id].vue +++ b/frontend_nuxt/pages/message-box/[id].vue @@ -20,7 +20,7 @@ -
+
@@ -50,7 +50,11 @@
-
+
i.src) lightboxImgs.value = imgs From 134e3fc8662a10c3bacb18384704dc4972aae433 Mon Sep 17 00:00:00 2001 From: tim Date: Fri, 12 Sep 2025 14:27:01 +0800 Subject: [PATCH 14/26] fix: tags height --- frontend_nuxt/components/ArticleCategory.vue | 5 +++++ frontend_nuxt/components/ArticleTags.vue | 5 +++++ frontend_nuxt/pages/index.vue | 7 ------- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/frontend_nuxt/components/ArticleCategory.vue b/frontend_nuxt/components/ArticleCategory.vue index f1b445a04..4e229c80b 100644 --- a/frontend_nuxt/components/ArticleCategory.vue +++ b/frontend_nuxt/components/ArticleCategory.vue @@ -35,6 +35,7 @@ const isImageIcon = (icon) => { display: flex; flex-direction: row; gap: 10px; + min-height: 25px; } .article-info-item { @@ -63,5 +64,9 @@ const isImageIcon = (icon) => { .article-info-item { font-size: 10px; } + + .article-category-container { + min-height: 20px; + } } diff --git a/frontend_nuxt/components/ArticleTags.vue b/frontend_nuxt/components/ArticleTags.vue index fd7620dd2..09ef3aad2 100644 --- a/frontend_nuxt/components/ArticleTags.vue +++ b/frontend_nuxt/components/ArticleTags.vue @@ -44,6 +44,7 @@ const isImageIcon = (icon) => { display: flex; flex-direction: row; gap: 10px; + min-height: 25px; } .article-info-item { @@ -72,5 +73,9 @@ const isImageIcon = (icon) => { .article-info-item { font-size: 10px; } + + .article-tags-container { + min-height: 20px; + } } diff --git a/frontend_nuxt/pages/index.vue b/frontend_nuxt/pages/index.vue index 04013333e..a3e7989d7 100644 --- a/frontend_nuxt/pages/index.vue +++ b/frontend_nuxt/pages/index.vue @@ -594,13 +594,6 @@ const sanitizeDescription = (text) => stripMarkdown(text) margin-bottom: 10px; } -.article-tags-container { - display: flex; - flex-direction: row; - align-items: center; - gap: 10px; -} - .article-tag-item { display: flex; flex-direction: row; From c5c7066b92e8af036d98dc24dad879e5e960045c Mon Sep 17 00:00:00 2001 From: Tim Date: Sat, 13 Sep 2025 11:20:21 +0800 Subject: [PATCH 15/26] =?UTF-8?q?fix:=20ci=20=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend_nuxt/package-lock.json | 5107 +++++++++++++++---------------- 1 file changed, 2525 insertions(+), 2582 deletions(-) diff --git a/frontend_nuxt/package-lock.json b/frontend_nuxt/package-lock.json index e1d3a692d..4e626f7c3 100644 --- a/frontend_nuxt/package-lock.json +++ b/frontend_nuxt/package-lock.json @@ -34,19 +34,6 @@ "node": ">=20.0.0" } }, - "node_modules/@ampproject/remapping": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", - "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", - "license": "Apache-2.0", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/@babel/code-frame": { "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", @@ -62,30 +49,30 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.0.tgz", - "integrity": "sha512-60X7qkglvrap8mn1lh2ebxXdZYtUcpd7gsmy9kLaBJ4i/WdY8PqTSdxyA8qraikqKQK5C1KRBKXqznrVapyNaw==", + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.4.tgz", + "integrity": "sha512-YsmSKC29MJwf0gF8Rjjrg5LQCmyh+j/nD8/eP7f+BeoQTKYqs9RoWbjGOdy0+1Ekr68RJZMUOPVQaQisnIo4Rw==", "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.28.3", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.3.tgz", - "integrity": "sha512-yDBHV9kQNcr2/sUr9jghVyz9C3Y5G2zUM2H2lo+9mKv4sFgbA8s8Z9t8D1jiTkGoO/NoIfKMyKWr4s6CN23ZwQ==", + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.4.tgz", + "integrity": "sha512-2BCOP7TN8M+gVDj7/ht3hsaO/B/n5oDbiAyyvnRlNOs+u1o+JWNYTQrmpuNp1/Wq2gcFrI01JAW+paEKDMx/CA==", "license": "MIT", "dependencies": { - "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.28.3", "@babel/helper-compilation-targets": "^7.27.2", "@babel/helper-module-transforms": "^7.28.3", - "@babel/helpers": "^7.28.3", - "@babel/parser": "^7.28.3", + "@babel/helpers": "^7.28.4", + "@babel/parser": "^7.28.4", "@babel/template": "^7.27.2", - "@babel/traverse": "^7.28.3", - "@babel/types": "^7.28.2", + "@babel/traverse": "^7.28.4", + "@babel/types": "^7.28.4", + "@jridgewell/remapping": "^2.3.5", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -323,25 +310,25 @@ } }, "node_modules/@babel/helpers": { - "version": "7.28.3", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.3.tgz", - "integrity": "sha512-PTNtvUQihsAsDHMOP5pfobP8C6CM4JWXmP8DrEIt46c3r2bf87Ua1zoqevsMo9g+tWDwgWrFP5EIxuBx5RudAw==", + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.4.tgz", + "integrity": "sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w==", "license": "MIT", "dependencies": { "@babel/template": "^7.27.2", - "@babel/types": "^7.28.2" + "@babel/types": "^7.28.4" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/parser": { - "version": "7.28.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.3.tgz", - "integrity": "sha512-7+Ey1mAgYqFAx2h0RuoxcQT5+MlG3GTV0TQrgr7/ZliKsm/MNDxVVutlWaziMq7wJNAz8MTqz55XLpWvva6StA==", + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.4.tgz", + "integrity": "sha512-yZbBqeM6TkpP9du/I2pUZnJsRMGGvOuIrhjzC1AwHwW+6he4mni6Bp/m8ijn0iOuZuPI2BfkCoSRunpyjnrQKg==", "license": "MIT", "dependencies": { - "@babel/types": "^7.28.2" + "@babel/types": "^7.28.4" }, "bin": { "parser": "bin/babel-parser.js" @@ -414,17 +401,17 @@ } }, "node_modules/@babel/traverse": { - "version": "7.28.3", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.3.tgz", - "integrity": "sha512-7w4kZYHneL3A6NP2nxzHvT3HCZ7puDZZjFMqDpBPECub79sTtSO5CGXDkKrTQq8ksAwfD/XI2MRFX23njdDaIQ==", + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.4.tgz", + "integrity": "sha512-YEzuboP2qvQavAcjgQNVgsvHIDv6ZpwXvcvjmyySP2DIMuByS/6ioU5G9pYrWHM6T2YDfc7xga9iNzYOs12CFQ==", "license": "MIT", "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.28.3", "@babel/helper-globals": "^7.28.0", - "@babel/parser": "^7.28.3", + "@babel/parser": "^7.28.4", "@babel/template": "^7.27.2", - "@babel/types": "^7.28.2", + "@babel/types": "^7.28.4", "debug": "^4.3.1" }, "engines": { @@ -432,9 +419,9 @@ } }, "node_modules/@babel/types": { - "version": "7.28.2", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.2.tgz", - "integrity": "sha512-ruv7Ae4J5dUYULmeXw1gmb7rYRz57OWCPM57pHojnLq/3Z1CK2lNSLTCVjxVk1F/TZHwOZZrOWi0ur95BbLxNQ==", + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.4.tgz", + "integrity": "sha512-bkFqkLhh3pMBUQQkpVgWDWq/lqzc2678eUyDlTBhRqhCHFguYYGM0Efga7tYk4TogG/3x0EEl66/OQ+WGbWB/Q==", "license": "MIT", "dependencies": { "@babel/helper-string-parser": "^7.27.1", @@ -474,35 +461,118 @@ "node": ">=10.0.0" } }, - "node_modules/@colors/colors": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.6.0.tgz", - "integrity": "sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==", + "node_modules/@emnapi/core": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.5.0.tgz", + "integrity": "sha512-sbP8GzB1WDzacS8fgNPpHlp6C9VZe+SJP3F90W9rLemaQj2PzIuTEl1qDOYQf58YIpyjViI24y9aPWCjEzY2cg==", "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/wasi-threads": "1.1.0", + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/core/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD", + "optional": true + }, + "node_modules/@emnapi/runtime": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.5.0.tgz", + "integrity": "sha512-97/BJ3iXHww3djw6hYIfErCZFee7qCtrneuLa20UXFCOTCfBM2cvQHjWJ2EG0s0MtdNwInarqCTz35i4wWXHsQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/runtime/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD", + "optional": true + }, + "node_modules/@emnapi/wasi-threads": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.1.0.tgz", + "integrity": "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/wasi-threads/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD", + "optional": true + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.9.tgz", + "integrity": "sha512-OaGtL73Jck6pBKjNIe24BnFE6agGl+6KxDtTfHhy1HmhthfKouEcOhqpSL64K4/0WCtbKFLOdzD/44cJ4k9opA==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], "engines": { - "node": ">=0.1.90" + "node": ">=18" } }, - "node_modules/@dabh/diagnostics": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.3.tgz", - "integrity": "sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA==", + "node_modules/@esbuild/android-arm": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.9.tgz", + "integrity": "sha512-5WNI1DaMtxQ7t7B6xa572XMXpHAaI/9Hnhk8lcxF4zVN4xstUgTlvuGDorBguKEnZO70qwEcLpfifMLoxiPqHQ==", + "cpu": [ + "arm" + ], "license": "MIT", - "dependencies": { - "colorspace": "1.1.x", - "enabled": "2.0.x", - "kuler": "^2.0.0" + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" } }, - "node_modules/@dependents/detective-less": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@dependents/detective-less/-/detective-less-5.0.1.tgz", - "integrity": "sha512-Y6+WUMsTFWE5jb20IFP4YGa5IrGY/+a/FbOSjDF/wz9gepU2hwCYSXRHP/vPwBvwcY3SVMASt4yXxbXNXigmZQ==", + "node_modules/@esbuild/android-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.9.tgz", + "integrity": "sha512-IDrddSmpSv51ftWslJMvl3Q2ZT98fUSL2/rlUXuVqRXHCs5EUF1/f+jbjF5+NG9UffUDMCiTyh8iec7u8RlTLg==", + "cpu": [ + "arm64" + ], "license": "MIT", - "dependencies": { - "gonzales-pe": "^4.3.0", - "node-source-walk": "^7.0.1" - }, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.9.tgz", + "integrity": "sha512-I853iMZ1hWZdNllhVZKm34f4wErd4lMyeV7BLzEExGEIZYsOzqDWDf+y082izYUE8gtJnYHdeDpN/6tUdwvfiw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], "engines": { "node": ">=18" } @@ -523,6 +593,342 @@ "node": ">=18" } }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.9.tgz", + "integrity": "sha512-jhHfBzjYTA1IQu8VyrjCX4ApJDnH+ez+IYVEoJHeqJm9VhG9Dh2BYaJritkYK3vMaXrf7Ogr/0MQ8/MeIefsPQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.9.tgz", + "integrity": "sha512-z93DmbnY6fX9+KdD4Ue/H6sYs+bhFQJNCPZsi4XWJoYblUqT06MQUdBCpcSfuiN72AbqeBFu5LVQTjfXDE2A6Q==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.9.tgz", + "integrity": "sha512-mrKX6H/vOyo5v71YfXWJxLVxgy1kyt1MQaD8wZJgJfG4gq4DpQGpgTB74e5yBeQdyMTbgxp0YtNj7NuHN0PoZg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.9.tgz", + "integrity": "sha512-HBU2Xv78SMgaydBmdor38lg8YDnFKSARg1Q6AT0/y2ezUAKiZvc211RDFHlEZRFNRVhcMamiToo7bDx3VEOYQw==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.9.tgz", + "integrity": "sha512-BlB7bIcLT3G26urh5Dmse7fiLmLXnRlopw4s8DalgZ8ef79Jj4aUcYbk90g8iCa2467HX8SAIidbL7gsqXHdRw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.9.tgz", + "integrity": "sha512-e7S3MOJPZGp2QW6AK6+Ly81rC7oOSerQ+P8L0ta4FhVi+/j/v2yZzx5CqqDaWjtPFfYz21Vi1S0auHrap3Ma3A==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.9.tgz", + "integrity": "sha512-Sbe10Bnn0oUAB2AalYztvGcK+o6YFFA/9829PhOCUS9vkJElXGdphz0A3DbMdP8gmKkqPmPcMJmJOrI3VYB1JQ==", + "cpu": [ + "loong64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.9.tgz", + "integrity": "sha512-YcM5br0mVyZw2jcQeLIkhWtKPeVfAerES5PvOzaDxVtIyZ2NUBZKNLjC5z3/fUlDgT6w89VsxP2qzNipOaaDyA==", + "cpu": [ + "mips64el" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.9.tgz", + "integrity": "sha512-++0HQvasdo20JytyDpFvQtNrEsAgNG2CY1CLMwGXfFTKGBGQT3bOeLSYE2l1fYdvML5KUuwn9Z8L1EWe2tzs1w==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.9.tgz", + "integrity": "sha512-uNIBa279Y3fkjV+2cUjx36xkx7eSjb8IvnL01eXUKXez/CBHNRw5ekCGMPM0BcmqBxBcdgUWuUXmVWwm4CH9kg==", + "cpu": [ + "riscv64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.9.tgz", + "integrity": "sha512-Mfiphvp3MjC/lctb+7D287Xw1DGzqJPb/J2aHHcHxflUo+8tmN/6d4k6I2yFR7BVo5/g7x2Monq4+Yew0EHRIA==", + "cpu": [ + "s390x" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.9.tgz", + "integrity": "sha512-iSwByxzRe48YVkmpbgoxVzn76BXjlYFXC7NvLYq+b+kDjyyk30J0JY47DIn8z1MO3K0oSl9fZoRmZPQI4Hklzg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.9.tgz", + "integrity": "sha512-9jNJl6FqaUG+COdQMjSCGW4QiMHH88xWbvZ+kRVblZsWrkXlABuGdFJ1E9L7HK+T0Yqd4akKNa/lO0+jDxQD4Q==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.9.tgz", + "integrity": "sha512-RLLdkflmqRG8KanPGOU7Rpg829ZHu8nFy5Pqdi9U01VYtG9Y0zOG6Vr2z4/S+/3zIyOxiK6cCeYNWOFR9QP87g==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.9.tgz", + "integrity": "sha512-YaFBlPGeDasft5IIM+CQAhJAqS3St3nJzDEgsgFixcfZeyGPCd6eJBWzke5piZuZ7CtL656eOSYKk4Ls2C0FRQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.9.tgz", + "integrity": "sha512-1MkgTCuvMGWuqVtAvkpkXFmtL8XhWy+j4jaSO2wxfJtilVCi0ZE37b8uOdMItIHz4I6z1bWWtEX4CJwcKYLcuA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.9.tgz", + "integrity": "sha512-4Xd0xNiMVXKh6Fa7HEJQbrpP3m3DDn43jKxMjxLLRjWnRsfxjORYJlXPO4JNcXtOyfajXorRKY9NkOpTHptErg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.9.tgz", + "integrity": "sha512-WjH4s6hzo00nNezhp3wFIAfmGZ8U7KtrJNlFMRKxiI9mxEK1scOMAaa9i4crUtu+tBr+0IN6JCuAcSBJZfnphw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.9.tgz", + "integrity": "sha512-mGFrVJHmZiRqmP8xFOc6b84/7xa5y5YvR1x8djzXpJBSv/UsNK6aqec+6JDjConTgvvQefdGhFDAs2DLAds6gQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.9.tgz", + "integrity": "sha512-b33gLVU2k11nVx1OhX3C8QQP6UHQK4ZtN56oFWvVXvz2VkDoe6fbG8TOgHFxEvqeqohmRnIHe5A1+HADk4OQww==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.9.tgz", + "integrity": "sha512-PPOl1mi6lpLNQxnGoyAfschAodRFYXJ+9fs6WHXz7CSWKbOqiMZsubC+BQsVKuul+3vKLuwTHsS2c2y9EoKwxQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, "node_modules/@fastify/accept-negotiator": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/@fastify/accept-negotiator/-/accept-negotiator-2.0.1.tgz", @@ -539,15 +945,9 @@ ], "license": "MIT" }, - "node_modules/@fastify/busboy": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-3.2.0.tgz", - "integrity": "sha512-m9FVDXU3GT2ITSe0UaMA5rU3QkfC/UXtCU8y0gSN/GugTqtVldOBWIB5V6V3sbmenVZUIpU6f+mPEO2+m5iTaA==", - "license": "MIT" - }, "node_modules/@icon-park/vue-next": { "version": "1.4.2", - "resolved": "https://registry.npmmirror.com/@icon-park/vue-next/-/vue-next-1.4.2.tgz", + "resolved": "https://registry.npmjs.org/@icon-park/vue-next/-/vue-next-1.4.2.tgz", "integrity": "sha512-+QklF255wkfBOabY+xw6FAI0Bwln/RhdwCunNy/9sKdKuChtaU67QZqU67KGAvZUTeeBgsL+yaHHxqfQeGZXEQ==", "license": "Apache-2.0", "engines": { @@ -580,6 +980,28 @@ "@img/sharp-libvips-darwin-arm64": "1.2.0" } }, + "node_modules/@img/sharp-darwin-x64": { + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.3.tgz", + "integrity": "sha512-yHpJYynROAj12TA6qil58hmPmAwxKKC7reUqtGLzsOHfP7/rniNGTL8tjWX6L3CTV4+5P4ypcS7Pp+7OB+8ihA==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-x64": "1.2.0" + } + }, "node_modules/@img/sharp-libvips-darwin-arm64": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.2.0.tgz", @@ -596,10 +1018,368 @@ "url": "https://opencollective.com/libvips" } }, + "node_modules/@img/sharp-libvips-darwin-x64": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.2.0.tgz", + "integrity": "sha512-M64XVuL94OgiNHa5/m2YvEQI5q2cl9d/wk0qFTDVXcYzi43lxuiFTftMR1tOnFQovVXNZJ5TURSDK2pNe9Yzqg==", + "cpu": [ + "x64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.2.0.tgz", + "integrity": "sha512-mWd2uWvDtL/nvIzThLq3fr2nnGfyr/XMXlq8ZJ9WMR6PXijHlC3ksp0IpuhK6bougvQrchUAfzRLnbsen0Cqvw==", + "cpu": [ + "arm" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm64": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.2.0.tgz", + "integrity": "sha512-RXwd0CgG+uPRX5YYrkzKyalt2OJYRiJQ8ED/fi1tq9WQW2jsQIn0tqrlR5l5dr/rjqq6AHAxURhj2DVjyQWSOA==", + "cpu": [ + "arm64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-ppc64": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.2.0.tgz", + "integrity": "sha512-Xod/7KaDDHkYu2phxxfeEPXfVXFKx70EAFZ0qyUdOjCcxbjqyJOEUpDe6RIyaunGxT34Anf9ue/wuWOqBW2WcQ==", + "cpu": [ + "ppc64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-s390x": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.2.0.tgz", + "integrity": "sha512-eMKfzDxLGT8mnmPJTNMcjfO33fLiTDsrMlUVcp6b96ETbnJmd4uvZxVJSKPQfS+odwfVaGifhsB07J1LynFehw==", + "cpu": [ + "s390x" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-x64": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.2.0.tgz", + "integrity": "sha512-ZW3FPWIc7K1sH9E3nxIGB3y3dZkpJlMnkk7z5tu1nSkBoCgw2nSRTFHI5pB/3CQaJM0pdzMF3paf9ckKMSE9Tg==", + "cpu": [ + "x64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-arm64": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.2.0.tgz", + "integrity": "sha512-UG+LqQJbf5VJ8NWJ5Z3tdIe/HXjuIdo4JeVNADXBFuG7z9zjoegpzzGIyV5zQKi4zaJjnAd2+g2nna8TZvuW9Q==", + "cpu": [ + "arm64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-x64": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.2.0.tgz", + "integrity": "sha512-SRYOLR7CXPgNze8akZwjoGBoN1ThNZoqpOgfnOxmWsklTGVfJiGJoC/Lod7aNMGA1jSsKWM1+HRX43OP6p9+6Q==", + "cpu": [ + "x64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-linux-arm": { + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.3.tgz", + "integrity": "sha512-oBK9l+h6KBN0i3dC8rYntLiVfW8D8wH+NPNT3O/WBHeW0OQWCjfWksLUaPidsrDKpJgXp3G3/hkmhptAW0I3+A==", + "cpu": [ + "arm" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm": "1.2.0" + } + }, + "node_modules/@img/sharp-linux-arm64": { + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.3.tgz", + "integrity": "sha512-QdrKe3EvQrqwkDrtuTIjI0bu6YEJHTgEeqdzI3uWJOH6G1O8Nl1iEeVYRGdj1h5I21CqxSvQp1Yv7xeU3ZewbA==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm64": "1.2.0" + } + }, + "node_modules/@img/sharp-linux-ppc64": { + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.34.3.tgz", + "integrity": "sha512-GLtbLQMCNC5nxuImPR2+RgrviwKwVql28FWZIW1zWruy6zLgA5/x2ZXk3mxj58X/tszVF69KK0Is83V8YgWhLA==", + "cpu": [ + "ppc64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-ppc64": "1.2.0" + } + }, + "node_modules/@img/sharp-linux-s390x": { + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.3.tgz", + "integrity": "sha512-3gahT+A6c4cdc2edhsLHmIOXMb17ltffJlxR0aC2VPZfwKoTGZec6u5GrFgdR7ciJSsHT27BD3TIuGcuRT0KmQ==", + "cpu": [ + "s390x" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-s390x": "1.2.0" + } + }, + "node_modules/@img/sharp-linux-x64": { + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.3.tgz", + "integrity": "sha512-8kYso8d806ypnSq3/Ly0QEw90V5ZoHh10yH0HnrzOCr6DKAPI6QVHvwleqMkVQ0m+fc7EH8ah0BB0QPuWY6zJQ==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-x64": "1.2.0" + } + }, + "node_modules/@img/sharp-linuxmusl-arm64": { + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.3.tgz", + "integrity": "sha512-vAjbHDlr4izEiXM1OTggpCcPg9tn4YriK5vAjowJsHwdBIdx0fYRsURkxLG2RLm9gyBq66gwtWI8Gx0/ov+JKQ==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-arm64": "1.2.0" + } + }, + "node_modules/@img/sharp-linuxmusl-x64": { + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.3.tgz", + "integrity": "sha512-gCWUn9547K5bwvOn9l5XGAEjVTTRji4aPTqLzGXHvIr6bIDZKNTA34seMPgM0WmSf+RYBH411VavCejp3PkOeQ==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-x64": "1.2.0" + } + }, + "node_modules/@img/sharp-wasm32": { + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.3.tgz", + "integrity": "sha512-+CyRcpagHMGteySaWos8IbnXcHgfDn7pO2fiC2slJxvNq9gDipYBN42/RagzctVRKgxATmfqOSulgZv5e1RdMg==", + "cpu": [ + "wasm32" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", + "optional": true, + "dependencies": { + "@emnapi/runtime": "^1.4.4" + }, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-arm64": { + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.3.tgz", + "integrity": "sha512-MjnHPnbqMXNC2UgeLJtX4XqoVHHlZNd+nPt1kRPmj63wURegwBhZlApELdtxM2OIZDRv/DFtLcNhVbd1z8GYXQ==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-ia32": { + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.3.tgz", + "integrity": "sha512-xuCdhH44WxuXgOM714hn4amodJMZl3OEvf0GVTm0BEyMeA2to+8HEdRPShH0SLYptJY1uBw+SCFP9WVQi1Q/cw==", + "cpu": [ + "ia32" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-x64": { + "version": "0.34.3", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.3.tgz", + "integrity": "sha512-OWwz05d++TxzLEv4VnsTz5CmZ6mI6S05sfQGEMrNrQcOEERbX46332IvE7pO/EUiw7jUrrS40z/M7kPyjfl04g==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, "node_modules/@ioredis/commands": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@ioredis/commands/-/commands-1.3.0.tgz", - "integrity": "sha512-M/T6Zewn7sDaBQEqIZ8Rb+i9y8qfGmq+5SDFSf9sA2lUZTmdDLVdOiQaeDp+Q4wElZ9HG1GAX5KhDaidp6LQsQ==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@ioredis/commands/-/commands-1.3.1.tgz", + "integrity": "sha512-bYtU8avhGIcje3IhvF9aSjsa5URMZBHnwKtOvXsT4sfYy9gppW11gLPT/9oNqlJZD47yPKveQFTAFWpHjKvUoQ==", "license": "MIT" }, "node_modules/@isaacs/cliui": { @@ -677,9 +1457,9 @@ "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.30", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.30.tgz", - "integrity": "sha512-GQ7Nw5G2lTu/BtHTKfXhKHok2WGetd4XYcVKGx00SjAk8GMwgJM3zr6zORiPGuOE+/vkc90KtTosSSvaCjKb2Q==", + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", "license": "MIT", "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", @@ -722,6 +1502,15 @@ "node": ">=18" } }, + "node_modules/@mapbox/node-pre-gyp/node_modules/abbrev": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-3.0.1.tgz", + "integrity": "sha512-AO2ac6pjRB3SJmGJo+v5/aK6Omggp6fsLrs6wN9bd35ulu4cCwaAU9+7ZhXjeqHVkaHThLuzH0nZr0YpCDhygg==", + "license": "ISC", + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, "node_modules/@mapbox/node-pre-gyp/node_modules/detect-libc": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.4.tgz", @@ -731,245 +1520,31 @@ "node": ">=8" } }, - "node_modules/@netlify/binary-info": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@netlify/binary-info/-/binary-info-1.0.0.tgz", - "integrity": "sha512-4wMPu9iN3/HL97QblBsBay3E1etIciR84izI3U+4iALY+JHCrI+a2jO0qbAZ/nxKoegypYEaiiqWXylm+/zfrw==", - "license": "Apache 2" - }, - "node_modules/@netlify/blobs": { - "version": "9.1.2", - "resolved": "https://registry.npmjs.org/@netlify/blobs/-/blobs-9.1.2.tgz", - "integrity": "sha512-7dMjExSH4zj4ShvLem49mE3mf0K171Tx2pV4WDWhJbRUWW3SJIR2qntz0LvUGS97N5HO1SmnzrgWUhEXCsApiw==", - "license": "MIT", + "node_modules/@mapbox/node-pre-gyp/node_modules/nopt": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-8.1.0.tgz", + "integrity": "sha512-ieGu42u/Qsa4TFktmaKEwM6MQH0pOWnaB3htzh0JRtx84+Mebc0cbZYN5bC+6WTZ4+77xrL9Pn5m7CV6VIkV7A==", + "license": "ISC", "dependencies": { - "@netlify/dev-utils": "2.2.0", - "@netlify/runtime-utils": "1.3.1" - }, - "engines": { - "node": "^14.16.0 || >=16.0.0" - } - }, - "node_modules/@netlify/dev-utils": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@netlify/dev-utils/-/dev-utils-2.2.0.tgz", - "integrity": "sha512-5XUvZuffe3KetyhbWwd4n2ktd7wraocCYw10tlM+/u/95iAz29GjNiuNxbCD1T6Bn1MyGc4QLVNKOWhzJkVFAw==", - "license": "MIT", - "dependencies": { - "@whatwg-node/server": "^0.9.60", - "chokidar": "^4.0.1", - "decache": "^4.6.2", - "dot-prop": "9.0.0", - "env-paths": "^3.0.0", - "find-up": "7.0.0", - "lodash.debounce": "^4.0.8", - "netlify": "^13.3.5", - "parse-gitignore": "^2.0.0", - "uuid": "^11.1.0", - "write-file-atomic": "^6.0.0" - }, - "engines": { - "node": "^14.16.0 || >=16.0.0" - } - }, - "node_modules/@netlify/dev-utils/node_modules/uuid": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.0.tgz", - "integrity": "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==", - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], - "license": "MIT", - "bin": { - "uuid": "dist/esm/bin/uuid" - } - }, - "node_modules/@netlify/functions": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/@netlify/functions/-/functions-3.1.10.tgz", - "integrity": "sha512-sI93kcJ2cUoMgDRPnrEm0lZhuiDVDqM6ngS/UbHTApIH3+eg3yZM5p/0SDFQQq9Bad0/srFmgBmTdXushzY5kg==", - "license": "MIT", - "dependencies": { - "@netlify/blobs": "9.1.2", - "@netlify/dev-utils": "2.2.0", - "@netlify/serverless-functions-api": "1.41.2", - "@netlify/zip-it-and-ship-it": "^12.1.0", - "cron-parser": "^4.9.0", - "decache": "^4.6.2", - "extract-zip": "^2.0.1", - "is-stream": "^4.0.1", - "jwt-decode": "^4.0.0", - "lambda-local": "^2.2.0", - "read-package-up": "^11.0.0", - "source-map-support": "^0.5.21" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@netlify/functions/node_modules/is-stream": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-4.0.1.tgz", - "integrity": "sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@netlify/open-api": { - "version": "2.37.0", - "resolved": "https://registry.npmjs.org/@netlify/open-api/-/open-api-2.37.0.tgz", - "integrity": "sha512-zXnRFkxgNsalSgU8/vwTWnav3R+8KG8SsqHxqaoJdjjJtnZR7wo3f+qqu4z+WtZ/4V7fly91HFUwZ6Uz2OdW7w==", - "license": "MIT", - "engines": { - "node": ">=14.8.0" - } - }, - "node_modules/@netlify/runtime-utils": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@netlify/runtime-utils/-/runtime-utils-1.3.1.tgz", - "integrity": "sha512-7/vIJlMYrPJPlEW84V2yeRuG3QBu66dmlv9neTmZ5nXzwylhBEOhy11ai+34A8mHCSZI4mKns25w3HM9kaDdJg==", - "license": "MIT", - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@netlify/serverless-functions-api": { - "version": "1.41.2", - "resolved": "https://registry.npmjs.org/@netlify/serverless-functions-api/-/serverless-functions-api-1.41.2.tgz", - "integrity": "sha512-pfCkH50JV06SGMNsNPjn8t17hOcId4fA881HeYQgMBOrewjsw4csaYgHEnCxCEu24Y5x75E2ULbFpqm9CvRCqw==", - "license": "MIT", - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@netlify/zip-it-and-ship-it": { - "version": "12.2.1", - "resolved": "https://registry.npmjs.org/@netlify/zip-it-and-ship-it/-/zip-it-and-ship-it-12.2.1.tgz", - "integrity": "sha512-zAr+8Tg80y/sUbhdUkZsq4Uy1IMzkSB6H/sKRMrDQ2NJx4uPgf5X5jMdg9g2FljNcxzpfJwc1Gg4OXQrjD0Z4A==", - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.22.5", - "@babel/types": "7.28.0", - "@netlify/binary-info": "^1.0.0", - "@netlify/serverless-functions-api": "^2.1.3", - "@vercel/nft": "0.29.4", - "archiver": "^7.0.0", - "common-path-prefix": "^3.0.0", - "copy-file": "^11.0.0", - "es-module-lexer": "^1.0.0", - "esbuild": "0.25.5", - "execa": "^8.0.0", - "fast-glob": "^3.3.3", - "filter-obj": "^6.0.0", - "find-up": "^7.0.0", - "is-builtin-module": "^3.1.0", - "is-path-inside": "^4.0.0", - "junk": "^4.0.0", - "locate-path": "^7.0.0", - "merge-options": "^3.0.4", - "minimatch": "^9.0.0", - "normalize-path": "^3.0.0", - "p-map": "^7.0.0", - "path-exists": "^5.0.0", - "precinct": "^12.0.0", - "require-package-name": "^2.0.1", - "resolve": "^2.0.0-next.1", - "semver": "^7.3.8", - "tmp-promise": "^3.0.2", - "toml": "^3.0.0", - "unixify": "^1.0.0", - "urlpattern-polyfill": "8.0.2", - "yargs": "^17.0.0", - "zod": "^3.23.8" + "abbrev": "^3.0.0" }, "bin": { - "zip-it-and-ship-it": "bin.js" + "nopt": "bin/nopt.js" }, "engines": { - "node": ">=18.14.0" + "node": "^18.17.0 || >=20.5.0" } }, - "node_modules/@netlify/zip-it-and-ship-it/node_modules/@babel/types": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.0.tgz", - "integrity": "sha512-jYnje+JyZG5YThjHiF28oT4SIZLnYOcSBb6+SDaFIyzDVSkXQmQQYclJ2R+YxcdmK0AX6x1E5OQNtuh3jHDrUg==", - "license": "MIT", - "dependencies": { - "@babel/helper-string-parser": "^7.27.1", - "@babel/helper-validator-identifier": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@netlify/zip-it-and-ship-it/node_modules/@esbuild/darwin-arm64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.5.tgz", - "integrity": "sha512-GtaBgammVvdF7aPIgH2jxMDdivezgFu6iKpmT+48+F8Hhg5J/sfnDieg0aeG/jfSvkYQU2/pceFPDKlqZzwnfQ==", - "cpu": [ - "arm64" - ], + "node_modules/@napi-rs/wasm-runtime": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.0.4.tgz", + "integrity": "sha512-+ZEtJPp8EF8h4kN6rLQECRor00H7jtDgBVtttIUoxuDkXLiQMaSBqju3LV/IEsMvqVG5pviUvR4jYhIA1xNm8w==", "license": "MIT", "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@netlify/zip-it-and-ship-it/node_modules/@netlify/serverless-functions-api": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@netlify/serverless-functions-api/-/serverless-functions-api-2.3.0.tgz", - "integrity": "sha512-eSC+glm4bX+9t+ajNzAs4Bca0Q/xGLgcYYh6M2Z9Dcya/MjVod1UrjPB88b0ANSBAy/aGFpDhVbwLwBokfnppQ==", - "license": "MIT", - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@netlify/zip-it-and-ship-it/node_modules/esbuild": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.5.tgz", - "integrity": "sha512-P8OtKZRv/5J5hhz0cUAdu/cLuPIKXpQl1R9pZtvmHWQvrAUVd0UNIPT4IB4W3rNOqVO0rlqHmCIbSwxh/c9yUQ==", - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.25.5", - "@esbuild/android-arm": "0.25.5", - "@esbuild/android-arm64": "0.25.5", - "@esbuild/android-x64": "0.25.5", - "@esbuild/darwin-arm64": "0.25.5", - "@esbuild/darwin-x64": "0.25.5", - "@esbuild/freebsd-arm64": "0.25.5", - "@esbuild/freebsd-x64": "0.25.5", - "@esbuild/linux-arm": "0.25.5", - "@esbuild/linux-arm64": "0.25.5", - "@esbuild/linux-ia32": "0.25.5", - "@esbuild/linux-loong64": "0.25.5", - "@esbuild/linux-mips64el": "0.25.5", - "@esbuild/linux-ppc64": "0.25.5", - "@esbuild/linux-riscv64": "0.25.5", - "@esbuild/linux-s390x": "0.25.5", - "@esbuild/linux-x64": "0.25.5", - "@esbuild/netbsd-arm64": "0.25.5", - "@esbuild/netbsd-x64": "0.25.5", - "@esbuild/openbsd-arm64": "0.25.5", - "@esbuild/openbsd-x64": "0.25.5", - "@esbuild/sunos-x64": "0.25.5", - "@esbuild/win32-arm64": "0.25.5", - "@esbuild/win32-ia32": "0.25.5", - "@esbuild/win32-x64": "0.25.5" + "dependencies": { + "@emnapi/core": "^1.5.0", + "@emnapi/runtime": "^1.5.0", + "@tybys/wasm-util": "^0.10.0" } }, "node_modules/@nodelib/fs.scandir": { @@ -1316,9 +1891,9 @@ } }, "node_modules/@nuxt/kit": { - "version": "3.18.1", - "resolved": "https://registry.npmjs.org/@nuxt/kit/-/kit-3.18.1.tgz", - "integrity": "sha512-z6w1Fzv27CIKFlhct05rndkJSfoslplWH5fJ9dtusEvpYScLXp5cATWIbWkte9e9zFSmQTgDQJjNs3geQHE7og==", + "version": "3.19.2", + "resolved": "https://registry.npmjs.org/@nuxt/kit/-/kit-3.19.2.tgz", + "integrity": "sha512-+QiqO0WcIxsKLUqXdVn3m4rzTRm2fO9MZgd330utCAaagGmHsgiMJp67kE14boJEPutnikfz3qOmrzBnDIHUUg==", "license": "MIT", "dependencies": { "c12": "^3.2.0", @@ -1331,14 +1906,15 @@ "jiti": "^2.5.1", "klona": "^2.0.6", "knitwork": "^1.2.0", - "mlly": "^1.7.4", + "mlly": "^1.8.0", "ohash": "^2.0.11", "pathe": "^2.0.3", - "pkg-types": "^2.2.0", + "pkg-types": "^2.3.0", + "rc9": "^2.1.2", "scule": "^1.3.0", "semver": "^7.7.2", "std-env": "^3.9.0", - "tinyglobby": "^0.2.14", + "tinyglobby": "^0.2.15", "ufo": "^1.6.1", "unctx": "^2.4.1", "unimport": "^5.2.0", @@ -1349,15 +1925,16 @@ } }, "node_modules/@nuxt/schema": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/@nuxt/schema/-/schema-4.0.3.tgz", - "integrity": "sha512-acDigyy8tF8xDCMFee00mt5u2kE5Qx5Y34ButBlibLzhguQjc+6f6FpMGdieN07oahjpegWIQG66yQywjw+sKw==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/@nuxt/schema/-/schema-4.1.2.tgz", + "integrity": "sha512-uFr13C6c52OFbF3hZVIV65KvhQRyrwp1GlAm7EVNGjebY8279QEel57T4R9UA1dn2Et6CBynBFhWoFwwo97Pig==", "license": "MIT", "dependencies": { - "@vue/shared": "^3.5.18", + "@vue/shared": "^3.5.21", "consola": "^3.4.2", "defu": "^6.1.4", "pathe": "^2.0.3", + "pkg-types": "^2.3.0", "std-env": "^3.9.0", "ufo": "1.6.1" }, @@ -1404,39 +1981,39 @@ } }, "node_modules/@nuxt/vite-builder": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/@nuxt/vite-builder/-/vite-builder-4.0.3.tgz", - "integrity": "sha512-1eKm51V3Ine4DjxLUDnPIKewuIZwJjGh1oMvY3sAJ5RtdSngRonqkaoGV4EWtLH7cO+oTBbbdVg5O95chYYcLQ==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/@nuxt/vite-builder/-/vite-builder-4.1.2.tgz", + "integrity": "sha512-to9NKVtzMBtyuhIIVgwo/ph5UCONcxkVsoAjm8HnSkDi0o9nDPhHOAg1AUMlvPnHpdXOzwnSrXo/t8E7W+UZ/A==", "license": "MIT", "dependencies": { - "@nuxt/kit": "4.0.3", + "@nuxt/kit": "4.1.2", "@rollup/plugin-replace": "^6.0.2", "@vitejs/plugin-vue": "^6.0.1", - "@vitejs/plugin-vue-jsx": "^5.0.1", + "@vitejs/plugin-vue-jsx": "^5.1.1", "autoprefixer": "^10.4.21", "consola": "^3.4.2", - "cssnano": "^7.1.0", + "cssnano": "^7.1.1", "defu": "^6.1.4", - "esbuild": "^0.25.8", + "esbuild": "^0.25.9", "escape-string-regexp": "^5.0.0", "exsolve": "^1.0.7", "get-port-please": "^3.2.0", "h3": "^1.15.4", "jiti": "^2.5.1", "knitwork": "^1.2.0", - "magic-string": "^0.30.17", - "mlly": "^1.7.4", + "magic-string": "^0.30.19", + "mlly": "^1.8.0", "mocked-exports": "^0.1.1", "pathe": "^2.0.3", - "pkg-types": "^2.2.0", + "pkg-types": "^2.3.0", "postcss": "^8.5.6", "rollup-plugin-visualizer": "^6.0.3", "std-env": "^3.9.0", "ufo": "^1.6.1", - "unenv": "^2.0.0-rc.19", - "vite": "^7.0.6", + "unenv": "^2.0.0-rc.21", + "vite": "^7.1.5", "vite-node": "^3.2.4", - "vite-plugin-checker": "^0.10.2", + "vite-plugin-checker": "^0.10.3", "vue-bundle-renderer": "^2.1.2" }, "engines": { @@ -1447,9 +2024,9 @@ } }, "node_modules/@nuxt/vite-builder/node_modules/@nuxt/kit": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/@nuxt/kit/-/kit-4.0.3.tgz", - "integrity": "sha512-9+lwvP4n8KhO91azoebO0o39smESGzEV4HU6nef9HIFyt04YwlVMY37Pk63GgZn0WhWVjyPWcQWs0rUdZUYcPw==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/@nuxt/kit/-/kit-4.1.2.tgz", + "integrity": "sha512-P5q41xeEOa6ZQC0PvIP7TSBmOAMxXK4qihDcCbYIJq8RcVsEPbGZVlidmxE6EOw1ucSyodq9nbV31FAKwoL4NQ==", "license": "MIT", "dependencies": { "c12": "^3.2.0", @@ -1461,14 +2038,15 @@ "ignore": "^7.0.5", "jiti": "^2.5.1", "klona": "^2.0.6", - "mlly": "^1.7.4", + "mlly": "^1.8.0", "ohash": "^2.0.11", "pathe": "^2.0.3", - "pkg-types": "^2.2.0", + "pkg-types": "^2.3.0", + "rc9": "^2.1.2", "scule": "^1.3.0", "semver": "^7.7.2", "std-env": "^3.9.0", - "tinyglobby": "^0.2.14", + "tinyglobby": "^0.2.15", "ufo": "^1.6.1", "unctx": "^2.4.1", "unimport": "^5.2.0", @@ -1478,10 +2056,26 @@ "node": ">=18.12.0" } }, + "node_modules/@oxc-minify/binding-android-arm64": { + "version": "0.87.0", + "resolved": "https://registry.npmjs.org/@oxc-minify/binding-android-arm64/-/binding-android-arm64-0.87.0.tgz", + "integrity": "sha512-ZbJmAfXvNAamOSnXId3BiM3DiuzlD1isqKjtmRFb/hpvChHHA23FSPrFcO16w+ugZKg33sZ93FinFkKtlC4hww==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/@oxc-minify/binding-darwin-arm64": { - "version": "0.80.0", - "resolved": "https://registry.npmjs.org/@oxc-minify/binding-darwin-arm64/-/binding-darwin-arm64-0.80.0.tgz", - "integrity": "sha512-7vJjhKHGfFVit3PCerbnrXQI0XgmmgV5HTNxlNsvxcmjPRIoYVkuwwRkiBsxO4RiBwvRRkAFPop3fY/gpuflJA==", + "version": "0.87.0", + "resolved": "https://registry.npmjs.org/@oxc-minify/binding-darwin-arm64/-/binding-darwin-arm64-0.87.0.tgz", + "integrity": "sha512-ewmNsTY8YbjWOI8+EOWKTVATOYvG4Qq4zQHH5VFBeqhQPVusY1ORD6Ei+BijVKrnlbpjibLlkTl8IWqXCGK89A==", "cpu": [ "arm64" ], @@ -1494,10 +2088,234 @@ "node": ">=14.0.0" } }, + "node_modules/@oxc-minify/binding-darwin-x64": { + "version": "0.87.0", + "resolved": "https://registry.npmjs.org/@oxc-minify/binding-darwin-x64/-/binding-darwin-x64-0.87.0.tgz", + "integrity": "sha512-qDH4w4EYttSC3Cs2VCh+CiMYKrcL2SNmnguBZXoUXe/RNk3csM+RhgcwdpX687xGvOhTFhH5PCIA84qh3ZpIbQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@oxc-minify/binding-freebsd-x64": { + "version": "0.87.0", + "resolved": "https://registry.npmjs.org/@oxc-minify/binding-freebsd-x64/-/binding-freebsd-x64-0.87.0.tgz", + "integrity": "sha512-5kxjHlSev2A09rDeITk+LMHxSrU3Iu8pUb0Zp4m+ul8FKlB9FrvFkAYwbctin6g47O98s3Win7Ewhy0w8JaiUA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@oxc-minify/binding-linux-arm-gnueabihf": { + "version": "0.87.0", + "resolved": "https://registry.npmjs.org/@oxc-minify/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-0.87.0.tgz", + "integrity": "sha512-NjbGXnNaAl5EgyonaDg2cPyH2pTf5a/+AP/5SRCJ0KetpXV22ZSUCvcy04Yt4QqjMcDs+WnJaGVxwx15Ofr6Gw==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@oxc-minify/binding-linux-arm-musleabihf": { + "version": "0.87.0", + "resolved": "https://registry.npmjs.org/@oxc-minify/binding-linux-arm-musleabihf/-/binding-linux-arm-musleabihf-0.87.0.tgz", + "integrity": "sha512-llAjfCA0iV2LMMl+LTR3JhqAc2iQmj+DTKd0VWOrbNOuNczeE9D5kJFkqYplD73LrkuqxrX9oDeUjjeLdVBPXw==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@oxc-minify/binding-linux-arm64-gnu": { + "version": "0.87.0", + "resolved": "https://registry.npmjs.org/@oxc-minify/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-0.87.0.tgz", + "integrity": "sha512-tf2Shom09AaSmu7U1hYYcEFF/cd+20HtmQ8eyGsRkqD5bqUj6lDu8TNSU9FWZ9tcZ83NzyFMwXZWHyeeIIbpxw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@oxc-minify/binding-linux-arm64-musl": { + "version": "0.87.0", + "resolved": "https://registry.npmjs.org/@oxc-minify/binding-linux-arm64-musl/-/binding-linux-arm64-musl-0.87.0.tgz", + "integrity": "sha512-pgWeYfSprtpnJVea9Q5eI6Eo80lDGlMw2JdcSMXmShtBjEhBl6bvDNHlV+6kNfh7iT65y/uC6FR8utFrRghu8A==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@oxc-minify/binding-linux-riscv64-gnu": { + "version": "0.87.0", + "resolved": "https://registry.npmjs.org/@oxc-minify/binding-linux-riscv64-gnu/-/binding-linux-riscv64-gnu-0.87.0.tgz", + "integrity": "sha512-O1QPczlT+lqNZVeKOdFxxL+s1RIlnixaJYFLrcqDcRyn82MGKLz7sAenBTFRQoIfLnSxtMGL6dqHOefYkQx7Cg==", + "cpu": [ + "riscv64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@oxc-minify/binding-linux-s390x-gnu": { + "version": "0.87.0", + "resolved": "https://registry.npmjs.org/@oxc-minify/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-0.87.0.tgz", + "integrity": "sha512-tcwt3ZUWOKfNLXN2edxFVHMlIuPvbuyMaKmRopgljSCfFcNHWhfTNlxlvmECRNhuQ91EcGwte6F1dwoeMCNd7A==", + "cpu": [ + "s390x" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@oxc-minify/binding-linux-x64-gnu": { + "version": "0.87.0", + "resolved": "https://registry.npmjs.org/@oxc-minify/binding-linux-x64-gnu/-/binding-linux-x64-gnu-0.87.0.tgz", + "integrity": "sha512-Xf4AXF14KXUzSnfgTcFLFSM0TykJhFw14+xwNvlAb6WdqXAKlMrz9joIAezc8dkW1NNscCVTsqBUPJ4RhvCM1Q==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@oxc-minify/binding-linux-x64-musl": { + "version": "0.87.0", + "resolved": "https://registry.npmjs.org/@oxc-minify/binding-linux-x64-musl/-/binding-linux-x64-musl-0.87.0.tgz", + "integrity": "sha512-LIqvpx9UihEW4n9QbEljDnfUdAWqhr6dRqmzSFwVAeLZRUECluLCDdsdwemrC/aZkvnisA4w0LFcFr3HmeTLJg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@oxc-minify/binding-wasm32-wasi": { + "version": "0.87.0", + "resolved": "https://registry.npmjs.org/@oxc-minify/binding-wasm32-wasi/-/binding-wasm32-wasi-0.87.0.tgz", + "integrity": "sha512-h0xluvc+YryfH5G5dndjGHuA/D4Kp85EkPMxqoOjNudOKDCtdobEaC9horhCqnOOQ0lgn+PGFl3w8u4ToOuRrA==", + "cpu": [ + "wasm32" + ], + "license": "MIT", + "optional": true, + "dependencies": { + "@napi-rs/wasm-runtime": "^1.0.3" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@oxc-minify/binding-win32-arm64-msvc": { + "version": "0.87.0", + "resolved": "https://registry.npmjs.org/@oxc-minify/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-0.87.0.tgz", + "integrity": "sha512-fgxSx+TUc7e2rNtRAMnhHrjqh1e8p/JKmWxRZXtkILveMr/TOHGiDis7U3JJbwycmTZ+HSsJ/PNFQl+tKzmDxw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@oxc-minify/binding-win32-x64-msvc": { + "version": "0.87.0", + "resolved": "https://registry.npmjs.org/@oxc-minify/binding-win32-x64-msvc/-/binding-win32-x64-msvc-0.87.0.tgz", + "integrity": "sha512-K6TTrlitEJgD0FGIW2r0t3CIJNqBkzHT97h49gZLS24ey2UG1zKt27iSHkpXMJYDiG97ZD2yv3pSph1ctMlFXw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@oxc-parser/binding-android-arm64": { + "version": "0.87.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-android-arm64/-/binding-android-arm64-0.87.0.tgz", + "integrity": "sha512-3APxTyYaAjpW5zifjzfsPgoIa4YHwA5GBjtgLRQpGVXCykXBIEbUTokoAs411ZuOwS3sdTVXBTGAdziXRd8rUg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=20.0.0" + } + }, "node_modules/@oxc-parser/binding-darwin-arm64": { - "version": "0.80.0", - "resolved": "https://registry.npmjs.org/@oxc-parser/binding-darwin-arm64/-/binding-darwin-arm64-0.80.0.tgz", - "integrity": "sha512-cVGI6NeGs1u1Ev8yO7I+zXPQuduCwwhYXd/K64uygx+OFp7fC7zSIlkGpoxFRUuSxqyipC813foAfUOwM1Y0PA==", + "version": "0.87.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-darwin-arm64/-/binding-darwin-arm64-0.87.0.tgz", + "integrity": "sha512-99e8E76M+k3Gtwvs5EU3VTs2hQkJmvnrl/eu7HkBUc9jLFHA4nVjYSgukMuqahWe270udUYEPRfcWKmoE1Nukg==", "cpu": [ "arm64" ], @@ -1510,19 +2328,243 @@ "node": ">=20.0.0" } }, + "node_modules/@oxc-parser/binding-darwin-x64": { + "version": "0.87.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-darwin-x64/-/binding-darwin-x64-0.87.0.tgz", + "integrity": "sha512-2rRo6Dz560/4ot5Q0KPUTEunEObkP8mDC9mMiH0RJk1FiOb9c+xpPbkYoUHNKuVMm8uIoiBCxIAbPtBhs9QaXQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@oxc-parser/binding-freebsd-x64": { + "version": "0.87.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-freebsd-x64/-/binding-freebsd-x64-0.87.0.tgz", + "integrity": "sha512-uR+WZAvWkFQPVoeqXgQFr7iy+3hEI295qTbQ4ujmklgM5eTX3YgMFoIV00Stloxfd1irSDDSaK7ySnnzF6mRJg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@oxc-parser/binding-linux-arm-gnueabihf": { + "version": "0.87.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-0.87.0.tgz", + "integrity": "sha512-Emm1NpVGKbwzQOIZJI8ZuZu0z8FAd5xscqdS6qpDFpDdEMxk6ab7o3nM8V09RhNCORAzeUlk4TBHQ2Crzjd50A==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@oxc-parser/binding-linux-arm-musleabihf": { + "version": "0.87.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-arm-musleabihf/-/binding-linux-arm-musleabihf-0.87.0.tgz", + "integrity": "sha512-1PPCxRZSJXzQaqc8y+wH7EqPgSfQ/JU3pK6WTN/1SUe/8paNVSKKqk175a8BbRVxGUtPnwEG89pi+xfPTSE7GA==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@oxc-parser/binding-linux-arm64-gnu": { + "version": "0.87.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-0.87.0.tgz", + "integrity": "sha512-fcnnsfcyLamJOMVKq+BQ8dasb8gRnZtNpCUfZhaEFAdXQ7J2RmZreFzlygcn80iti0V7c5LejcjHbF4IdK3GAw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@oxc-parser/binding-linux-arm64-musl": { + "version": "0.87.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-arm64-musl/-/binding-linux-arm64-musl-0.87.0.tgz", + "integrity": "sha512-tBPkSPgRSSbmrje8CUovISi/Hj/tWjZJ3n/qnrjx2B+u86hWtwLsngtPDQa5d4seSyDaHSx6tNEUcH7+g5Ee0Q==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@oxc-parser/binding-linux-riscv64-gnu": { + "version": "0.87.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-riscv64-gnu/-/binding-linux-riscv64-gnu-0.87.0.tgz", + "integrity": "sha512-z4UKGM4wv2wEAQAlx2pBq6+pDJw5J/5oDEXqW6yBSLbWLjLDo4oagmRSE3+giOWteUa+0FVJ+ypq4iYxBkYSWg==", + "cpu": [ + "riscv64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@oxc-parser/binding-linux-s390x-gnu": { + "version": "0.87.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-0.87.0.tgz", + "integrity": "sha512-6W1ENe/nZtr2TBnrEzmdGEraEAdZOiH3YoUNNeQWuqwLkmpoHTJJdclieToPe/l2IKJ4WL3FsSLSGHE8yt/OEg==", + "cpu": [ + "s390x" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@oxc-parser/binding-linux-x64-gnu": { + "version": "0.87.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-x64-gnu/-/binding-linux-x64-gnu-0.87.0.tgz", + "integrity": "sha512-s3kB/Ii3X3IOZ27Iu7wx2zYkIcDO22Emu32SNC6kkUSy09dPBc1yaW14TnAkPMe/rvtuzR512JPWj3iGpl+Dng==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@oxc-parser/binding-linux-x64-musl": { + "version": "0.87.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-x64-musl/-/binding-linux-x64-musl-0.87.0.tgz", + "integrity": "sha512-3+M9hfrZSDi4+Uy4Ll3rtOuVG3IHDQlj027jgtmAAHJK1eqp4CQfC7rrwE+LFUqUwX+KD2GwlxR+eHyyEf5Gbg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@oxc-parser/binding-wasm32-wasi": { + "version": "0.87.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-wasm32-wasi/-/binding-wasm32-wasi-0.87.0.tgz", + "integrity": "sha512-2jgeEeOa4GbQQg2Et/gFTgs5wKS/+CxIg+CN2mMOJ4EqbmvUVeGiumO01oFOWTYnJy1oONwIocBzrnMuvOcItA==", + "cpu": [ + "wasm32" + ], + "license": "MIT", + "optional": true, + "dependencies": { + "@napi-rs/wasm-runtime": "^1.0.3" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@oxc-parser/binding-win32-arm64-msvc": { + "version": "0.87.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-0.87.0.tgz", + "integrity": "sha512-KZp9poaBaVvuFM0TrsHCDOjPQK5eMDXblz21boMhKHGW5/bOlkMlg3CYn5j0f67FkK68NSdNKREMxmibBeXllQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@oxc-parser/binding-win32-x64-msvc": { + "version": "0.87.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-win32-x64-msvc/-/binding-win32-x64-msvc-0.87.0.tgz", + "integrity": "sha512-86uisngtp/8XdcerIKxMyJTqgDSTJatkfpylpUH0d96W8Bb9E+bVvM2fIIhLWB0Eb03PeY2BdIT7DNIln9TnHg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=20.0.0" + } + }, "node_modules/@oxc-project/types": { - "version": "0.80.0", - "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.80.0.tgz", - "integrity": "sha512-xxHQm8wfCv2e8EmtaDwpMeAHOWqgQDAYg+BJouLXSQt5oTKu9TIXrgNMGSrM2fLvKmECsRd9uUFAAD+hPyootA==", + "version": "0.87.0", + "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.87.0.tgz", + "integrity": "sha512-ipZFWVGE9fADBVXXWJWY/cxpysc41Gt5upKDeb32F6WMgFyO7XETUMVq8UuREKCih+Km5E6p2VhEvf6Fuhey6g==", "license": "MIT", "funding": { "url": "https://github.com/sponsors/Boshen" } }, + "node_modules/@oxc-transform/binding-android-arm64": { + "version": "0.87.0", + "resolved": "https://registry.npmjs.org/@oxc-transform/binding-android-arm64/-/binding-android-arm64-0.87.0.tgz", + "integrity": "sha512-B7W6J8T9cS054LUGLfYkYz8bz5+t+4yPftZ67Bn6MJ03okMLnbbEfm1bID1tqcP5tJwMurTILVy/dQfDYDcMgQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/@oxc-transform/binding-darwin-arm64": { - "version": "0.80.0", - "resolved": "https://registry.npmjs.org/@oxc-transform/binding-darwin-arm64/-/binding-darwin-arm64-0.80.0.tgz", - "integrity": "sha512-sVcK4tjXbCfexlhquKVcwoKQrekQWDzRXtDwOWxm3CV1k5qGUm/rl5RAQLnXYtZVgu0U2dGEct9tNms+dzbACA==", + "version": "0.87.0", + "resolved": "https://registry.npmjs.org/@oxc-transform/binding-darwin-arm64/-/binding-darwin-arm64-0.87.0.tgz", + "integrity": "sha512-HImW3xOPx7FHKqfC5WfE82onhRfnWQUiB7R+JgYrk+7NR404h3zANSPzu3V/W9lbDxlmHTcqoD2LKbNC5j0TQA==", "cpu": [ "arm64" ], @@ -1535,6 +2577,214 @@ "node": ">=14.0.0" } }, + "node_modules/@oxc-transform/binding-darwin-x64": { + "version": "0.87.0", + "resolved": "https://registry.npmjs.org/@oxc-transform/binding-darwin-x64/-/binding-darwin-x64-0.87.0.tgz", + "integrity": "sha512-MDbgugi6mvuPTfS78E2jyozm7493Kuqmpc5r406CsUdEsXlnsF+xvmKlrW9ZIkisO74dD+HWouSiDtNyPQHjlw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@oxc-transform/binding-freebsd-x64": { + "version": "0.87.0", + "resolved": "https://registry.npmjs.org/@oxc-transform/binding-freebsd-x64/-/binding-freebsd-x64-0.87.0.tgz", + "integrity": "sha512-N0M5D/4haJw7BMn2WZ3CWz0WkdLyoK1+3KxOyCv2CPedMCxx6eQay2AtJxSzj9tjVU1+ukbSb2fDO24JIJGsVA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@oxc-transform/binding-linux-arm-gnueabihf": { + "version": "0.87.0", + "resolved": "https://registry.npmjs.org/@oxc-transform/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-0.87.0.tgz", + "integrity": "sha512-PubObCNOUOzm1S+P0yn7S+/6xRLbSPMqhgrb73L3p+J1Z20fv/FYVg0kFd36Yho24TSC/byOkebEZWAtxCasWw==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@oxc-transform/binding-linux-arm-musleabihf": { + "version": "0.87.0", + "resolved": "https://registry.npmjs.org/@oxc-transform/binding-linux-arm-musleabihf/-/binding-linux-arm-musleabihf-0.87.0.tgz", + "integrity": "sha512-Nk2d/FS7sMCmCl99vHojzigakjDPamkjOXs2i+H71o/NqytS0pk3M+tXat8M3IGpeLJIEszA5Mv+dcq731nlYA==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@oxc-transform/binding-linux-arm64-gnu": { + "version": "0.87.0", + "resolved": "https://registry.npmjs.org/@oxc-transform/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-0.87.0.tgz", + "integrity": "sha512-BxFkIcso2V1+FCDoU+KctxvJzSQVSnEZ5EEQ8O3Up9EoFVQRnZ8ktXvqYj2Oqvc4IYPskLPsKUgc9gdK8wGhUg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@oxc-transform/binding-linux-arm64-musl": { + "version": "0.87.0", + "resolved": "https://registry.npmjs.org/@oxc-transform/binding-linux-arm64-musl/-/binding-linux-arm64-musl-0.87.0.tgz", + "integrity": "sha512-MZ1/TNaebhXK73j1UDfwyBFnAy0tT3n6otOkhlt1vlJwqboUS/D7E/XrCZmAuHIfVPxAXRPovkl7kfxLB43SKw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@oxc-transform/binding-linux-riscv64-gnu": { + "version": "0.87.0", + "resolved": "https://registry.npmjs.org/@oxc-transform/binding-linux-riscv64-gnu/-/binding-linux-riscv64-gnu-0.87.0.tgz", + "integrity": "sha512-JCWE6n4Hicu0FVbvmLdH/dS8V6JykOUsbrbDYm6JwFlHr4eFTTlS2B+mh5KPOxcdeOlv/D/XRnvMJ6WGYs25EA==", + "cpu": [ + "riscv64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@oxc-transform/binding-linux-s390x-gnu": { + "version": "0.87.0", + "resolved": "https://registry.npmjs.org/@oxc-transform/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-0.87.0.tgz", + "integrity": "sha512-n2NTgM+3PqFagJV9UXRDNOmYesF+TO9SF9FeHqwVmW893ayef9KK+vfWAAhvOYHXYaKWT5XoHd87ODD7nruyhw==", + "cpu": [ + "s390x" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@oxc-transform/binding-linux-x64-gnu": { + "version": "0.87.0", + "resolved": "https://registry.npmjs.org/@oxc-transform/binding-linux-x64-gnu/-/binding-linux-x64-gnu-0.87.0.tgz", + "integrity": "sha512-ZOKW3wx0bW2O7jGdOzr8DyLZqX2C36sXvJdsHj3IueZZ//d/NjLZqEiUKz+q0JlERHtCVKShQ5PLaCx7NpuqNg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@oxc-transform/binding-linux-x64-musl": { + "version": "0.87.0", + "resolved": "https://registry.npmjs.org/@oxc-transform/binding-linux-x64-musl/-/binding-linux-x64-musl-0.87.0.tgz", + "integrity": "sha512-eIspx/JqkVMPK1CAYEOo2J8o49s4ZTf+32MSMUknIN2ZS1fvRmWS0D/xFFaLP/9UGhdrXRIPbn/iSYEA8JnV/g==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@oxc-transform/binding-wasm32-wasi": { + "version": "0.87.0", + "resolved": "https://registry.npmjs.org/@oxc-transform/binding-wasm32-wasi/-/binding-wasm32-wasi-0.87.0.tgz", + "integrity": "sha512-4uRjJQnt/+kmJUIC6Iwzn+MqqZhLP1zInPtDwgL37KI4VuUewUQWoL+sggMssMEgm7ZJwOPoZ6piuSWwMgOqgQ==", + "cpu": [ + "wasm32" + ], + "license": "MIT", + "optional": true, + "dependencies": { + "@napi-rs/wasm-runtime": "^1.0.3" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@oxc-transform/binding-win32-arm64-msvc": { + "version": "0.87.0", + "resolved": "https://registry.npmjs.org/@oxc-transform/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-0.87.0.tgz", + "integrity": "sha512-l/qSi4/N5W1yXKU9+1gWGo0tBoRpp4zvHYrpsbq3zbefPL4VYdA0gKF7O10/ZQVkYylzxiVh2zpYO34/FbZdIg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@oxc-transform/binding-win32-x64-msvc": { + "version": "0.87.0", + "resolved": "https://registry.npmjs.org/@oxc-transform/binding-win32-x64-msvc/-/binding-win32-x64-msvc-0.87.0.tgz", + "integrity": "sha512-jG/MhMjfSdyj5KyhnwNWr4mnAlAsz+gNUYpjQ+UXWsfsoB3f8HqbsTkG02RBtNa/IuVQYvYYVf1eIimNN3gBEQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/@parcel/watcher": { "version": "2.5.1", "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.1.tgz", @@ -1570,6 +2820,26 @@ "@parcel/watcher-win32-x64": "2.5.1" } }, + "node_modules/@parcel/watcher-android-arm64": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.1.tgz", + "integrity": "sha512-KF8+j9nNbUN8vzOFDpRMsaKBHZ/mcjEjMToVMJOhTozkDonQFFrRcfdLWn6yWKCmJKmdVxSgHiYvTCef4/qcBA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, "node_modules/@parcel/watcher-darwin-arm64": { "version": "2.5.1", "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.1.tgz", @@ -1590,6 +2860,166 @@ "url": "https://opencollective.com/parcel" } }, + "node_modules/@parcel/watcher-darwin-x64": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.1.tgz", + "integrity": "sha512-1ZXDthrnNmwv10A0/3AJNZ9JGlzrF82i3gNQcWOzd7nJ8aj+ILyW1MTxVk35Db0u91oD5Nlk9MBiujMlwmeXZg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-freebsd-x64": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.1.tgz", + "integrity": "sha512-SI4eljM7Flp9yPuKi8W0ird8TI/JK6CSxju3NojVI6BjHsTyK7zxA9urjVjEKJ5MBYC+bLmMcbAWlZ+rFkLpJQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm-glibc": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.1.tgz", + "integrity": "sha512-RCdZlEyTs8geyBkkcnPWvtXLY44BCeZKmGYRtSgtwwnHR4dxfHRG3gR99XdMEdQ7KeiDdasJwwvNSF5jKtDwdA==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm-musl": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.1.tgz", + "integrity": "sha512-6E+m/Mm1t1yhB8X412stiKFG3XykmgdIOqhjWj+VL8oHkKABfu/gjFj8DvLrYVHSBNC+/u5PeNrujiSQ1zwd1Q==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm64-glibc": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.1.tgz", + "integrity": "sha512-LrGp+f02yU3BN9A+DGuY3v3bmnFUggAITBGriZHUREfNEzZh/GO06FF5u2kx8x+GBEUYfyTGamol4j3m9ANe8w==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm64-musl": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.1.tgz", + "integrity": "sha512-cFOjABi92pMYRXS7AcQv9/M1YuKRw8SZniCDw0ssQb/noPkRzA+HBDkwmyOJYp5wXcsTrhxO0zq1U11cK9jsFg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-x64-glibc": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.1.tgz", + "integrity": "sha512-GcESn8NZySmfwlTsIur+49yDqSny2IhPeZfXunQi48DMugKeZ7uy1FX83pO0X22sHntJ4Ub+9k34XQCX+oHt2A==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-x64-musl": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.1.tgz", + "integrity": "sha512-n0E2EQbatQ3bXhcH2D1XIAANAcTZkQICBPVaxMeaCVBtOpBZpWJuf7LwyWPSBDITb7In8mqQgJ7gH8CILCURXg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, "node_modules/@parcel/watcher-wasm": { "version": "2.5.1", "resolved": "https://registry.npmjs.org/@parcel/watcher-wasm/-/watcher-wasm-2.5.1.tgz", @@ -1616,6 +3046,66 @@ "inBundle": true, "license": "MIT" }, + "node_modules/@parcel/watcher-win32-arm64": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.1.tgz", + "integrity": "sha512-RFzklRvmc3PkjKjry3hLF9wD7ppR4AKcWNzH7kXR7GUe0Igb3Nz8fyPwtZCSquGrhU5HhUNDr/mKBqj7tqA2Vw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-ia32": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.1.tgz", + "integrity": "sha512-c2KkcVN+NJmuA7CGlaGD1qJh1cLfDnQsHjE89E60vUEMlqduHGCdCLJCID5geFVM0dOtA3ZiIO8BoEQmzQVfpQ==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-x64": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.1.tgz", + "integrity": "sha512-9lHBdJITeNR++EvSQVUcaZoWupyHfXe1jZvGZ06O/5MflPcuPLtEphScIBL+AiCWBO46tDSHzWyD0uDmmZqsgA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, "node_modules/@pkgjs/parseargs": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", @@ -1823,26 +3313,6 @@ } } }, - "node_modules/@rollup/plugin-node-resolve/node_modules/resolve": { - "version": "1.22.10", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", - "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", - "license": "MIT", - "dependencies": { - "is-core-module": "^2.16.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/@rollup/plugin-replace": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/@rollup/plugin-replace/-/plugin-replace-6.0.2.tgz", @@ -1887,9 +3357,9 @@ } }, "node_modules/@rollup/pluginutils": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.2.0.tgz", - "integrity": "sha512-qWJ2ZTbmumwiLFomfzTyt5Kng4hwPi9rwCYN4SHb6eaRU1KNO4ccxINHr/VhH4GgPlt1XfSTLX2LBTme8ne4Zw==", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.3.0.tgz", + "integrity": "sha512-5EdhGZtnu3V88ces7s53hhfK5KSASnJZv8Lulpc04cWO3REESroJXg73DFsOmgbU2BhwV0E20bu2IDZb3VKW4Q==", "license": "MIT", "dependencies": { "@types/estree": "^1.0.0", @@ -1926,10 +3396,36 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.50.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.50.1.tgz", + "integrity": "sha512-HJXwzoZN4eYTdD8bVV22DN8gsPCAj3V20NHKOs8ezfXanGpmVPR7kalUHd+Y31IJp9stdB87VKPFbsGY3H/2ag==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.50.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.50.1.tgz", + "integrity": "sha512-PZlsJVcjHfcH53mOImyt3bc97Ep3FJDXRpk9sMdGX0qgLmY0EIWxCag6EigerGhLVuL8lDVYNnSo8qnTElO4xw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.49.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.49.0.tgz", - "integrity": "sha512-99kMMSMQT7got6iYX3yyIiJfFndpojBmkHfTc1rIje8VbjhmqBXE+nb7ZZP3A5skLyujvT0eIUCUsxAe6NjWbw==", + "version": "4.50.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.50.1.tgz", + "integrity": "sha512-xc6i2AuWh++oGi4ylOFPmzJOEeAa2lJeGUGb4MudOtgfyyjr4UPNK+eEWTPLvmPJIY/pgw6ssFIox23SyrkkJw==", "cpu": [ "arm64" ], @@ -1939,6 +3435,240 @@ "darwin" ] }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.50.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.50.1.tgz", + "integrity": "sha512-2ofU89lEpDYhdLAbRdeyz/kX3Y2lpYc6ShRnDjY35bZhd2ipuDMDi6ZTQ9NIag94K28nFMofdnKeHR7BT0CATw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.50.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.50.1.tgz", + "integrity": "sha512-wOsE6H2u6PxsHY/BeFHA4VGQN3KUJFZp7QJBmDYI983fgxq5Th8FDkVuERb2l9vDMs1D5XhOrhBrnqcEY6l8ZA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.50.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.50.1.tgz", + "integrity": "sha512-A/xeqaHTlKbQggxCqispFAcNjycpUEHP52mwMQZUNqDUJFFYtPHCXS1VAG29uMlDzIVr+i00tSFWFLivMcoIBQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.50.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.50.1.tgz", + "integrity": "sha512-54v4okehwl5TaSIkpp97rAHGp7t3ghinRd/vyC1iXqXMfjYUTm7TfYmCzXDoHUPTTf36L8pr0E7YsD3CfB3ZDg==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.50.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.50.1.tgz", + "integrity": "sha512-p/LaFyajPN/0PUHjv8TNyxLiA7RwmDoVY3flXHPSzqrGcIp/c2FjwPPP5++u87DGHtw+5kSH5bCJz0mvXngYxw==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.50.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.50.1.tgz", + "integrity": "sha512-2AbMhFFkTo6Ptna1zO7kAXXDLi7H9fGTbVaIq2AAYO7yzcAsuTNWPHhb2aTA6GPiP+JXh85Y8CiS54iZoj4opw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.50.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.50.1.tgz", + "integrity": "sha512-Cgef+5aZwuvesQNw9eX7g19FfKX5/pQRIyhoXLCiBOrWopjo7ycfB292TX9MDcDijiuIJlx1IzJz3IoCPfqs9w==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loongarch64-gnu": { + "version": "4.50.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.50.1.tgz", + "integrity": "sha512-RPhTwWMzpYYrHrJAS7CmpdtHNKtt2Ueo+BlLBjfZEhYBhK00OsEqM08/7f+eohiF6poe0YRDDd8nAvwtE/Y62Q==", + "cpu": [ + "loong64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.50.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.50.1.tgz", + "integrity": "sha512-eSGMVQw9iekut62O7eBdbiccRguuDgiPMsw++BVUg+1K7WjZXHOg/YOT9SWMzPZA+w98G+Fa1VqJgHZOHHnY0Q==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.50.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.50.1.tgz", + "integrity": "sha512-S208ojx8a4ciIPrLgazF6AgdcNJzQE4+S9rsmOmDJkusvctii+ZvEuIC4v/xFqzbuP8yDjn73oBlNDgF6YGSXQ==", + "cpu": [ + "riscv64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.50.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.50.1.tgz", + "integrity": "sha512-3Ag8Ls1ggqkGUvSZWYcdgFwriy2lWo+0QlYgEFra/5JGtAd6C5Hw59oojx1DeqcA2Wds2ayRgvJ4qxVTzCHgzg==", + "cpu": [ + "riscv64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.50.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.50.1.tgz", + "integrity": "sha512-t9YrKfaxCYe7l7ldFERE1BRg/4TATxIg+YieHQ966jwvo7ddHJxPj9cNFWLAzhkVsbBvNA4qTbPVNsZKBO4NSg==", + "cpu": [ + "s390x" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.50.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.50.1.tgz", + "integrity": "sha512-MCgtFB2+SVNuQmmjHf+wfI4CMxy3Tk8XjA5Z//A0AKD7QXUYFMQcns91K6dEHBvZPCnhJSyDWLApk40Iq/H3tA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.50.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.50.1.tgz", + "integrity": "sha512-nEvqG+0jeRmqaUMuwzlfMKwcIVffy/9KGbAGyoa26iu6eSngAYQ512bMXuqqPrlTyfqdlB9FVINs93j534UJrg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.50.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.50.1.tgz", + "integrity": "sha512-RDsLm+phmT3MJd9SNxA9MNuEAO/J2fhW8GXk62G/B4G7sLVumNFbRwDL6v5NrESb48k+QMqdGbHgEtfU0LCpbA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.50.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.50.1.tgz", + "integrity": "sha512-hpZB/TImk2FlAFAIsoElM3tLzq57uxnGYwplg6WDyAxbYczSi8O2eQ+H2Lx74504rwKtZ3N2g4bCUkiamzS6TQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.50.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.50.1.tgz", + "integrity": "sha512-SXjv8JlbzKM0fTJidX4eVsH+Wmnp0/WcD8gJxIZyR6Gay5Qcsmdbi9zVtnbkGPG8v2vMR1AD06lGWy5FLMcG7A==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.50.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.50.1.tgz", + "integrity": "sha512-StxAO/8ts62KZVRAm4JZYq9+NqNsV7RvimNK+YM7ry//zebEH6meuugqW/P5OFUCjyQgui+9fUxT6d5NShvMvA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, "node_modules/@sindresorhus/is": { "version": "7.0.2", "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-7.0.2.tgz", @@ -1985,6 +3715,23 @@ "node": ">=10.13.0" } }, + "node_modules/@tybys/wasm-util": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.1.tgz", + "integrity": "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==", + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@tybys/wasm-util/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD", + "optional": true + }, "node_modules/@types/d3-scale": { "version": "4.0.9", "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.9.tgz", @@ -2036,22 +3783,6 @@ "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==", "license": "MIT" }, - "node_modules/@types/node": { - "version": "24.3.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-24.3.0.tgz", - "integrity": "sha512-aPTXCrfwnDLj4VvXrm+UUCQjNEvJgNA8s5F1cvwQU+3KNltTOkBm1j30uNLyqqPNe7gE3KFzImYoZEfLhp4Yow==", - "license": "MIT", - "optional": true, - "dependencies": { - "undici-types": "~7.10.0" - } - }, - "node_modules/@types/normalize-package-data": { - "version": "2.4.4", - "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz", - "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==", - "license": "MIT" - }, "node_modules/@types/parse-path": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/@types/parse-path/-/parse-path-7.0.3.tgz", @@ -2064,123 +3795,12 @@ "integrity": "sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==", "license": "MIT" }, - "node_modules/@types/triple-beam": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/@types/triple-beam/-/triple-beam-1.3.5.tgz", - "integrity": "sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw==", - "license": "MIT" - }, "node_modules/@types/unist": { "version": "2.0.11", "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz", "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==", "license": "MIT" }, - "node_modules/@types/yauzl": { - "version": "2.10.3", - "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz", - "integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==", - "license": "MIT", - "optional": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@typescript-eslint/project-service": { - "version": "8.41.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.41.0.tgz", - "integrity": "sha512-b8V9SdGBQzQdjJ/IO3eDifGpDBJfvrNTp2QD9P2BeqWTGrRibgfgIlBSw6z3b6R7dPzg752tOs4u/7yCLxksSQ==", - "license": "MIT", - "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.41.0", - "@typescript-eslint/types": "^8.41.0", - "debug": "^4.3.4" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "typescript": ">=4.8.4 <6.0.0" - } - }, - "node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.41.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.41.0.tgz", - "integrity": "sha512-TDhxYFPUYRFxFhuU5hTIJk+auzM/wKvWgoNYOPcOf6i4ReYlOoYN8q1dV5kOTjNQNJgzWN3TUUQMtlLOcUgdUw==", - "license": "MIT", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "typescript": ">=4.8.4 <6.0.0" - } - }, - "node_modules/@typescript-eslint/types": { - "version": "8.41.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.41.0.tgz", - "integrity": "sha512-9EwxsWdVqh42afLbHP90n2VdHaWU/oWgbH2P0CfcNfdKL7CuKpwMQGjwev56vWu9cSKU7FWSu6r9zck6CVfnag==", - "license": "MIT", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.41.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.41.0.tgz", - "integrity": "sha512-D43UwUYJmGhuwHfY7MtNKRZMmfd8+p/eNSfFe6tH5mbVDto+VQCayeAt35rOx3Cs6wxD16DQtIKw/YXxt5E0UQ==", - "license": "MIT", - "dependencies": { - "@typescript-eslint/project-service": "8.41.0", - "@typescript-eslint/tsconfig-utils": "8.41.0", - "@typescript-eslint/types": "8.41.0", - "@typescript-eslint/visitor-keys": "8.41.0", - "debug": "^4.3.4", - "fast-glob": "^3.3.2", - "is-glob": "^4.0.3", - "minimatch": "^9.0.4", - "semver": "^7.6.0", - "ts-api-utils": "^2.1.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "typescript": ">=4.8.4 <6.0.0" - } - }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.41.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.41.0.tgz", - "integrity": "sha512-+GeGMebMCy0elMNg67LRNoVnUFPIm37iu5CmHESVx56/9Jsfdpsvbv605DQ81Pi/x11IdKUsS5nzgTYbCQU9fg==", - "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "8.41.0", - "eslint-visitor-keys": "^4.2.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, "node_modules/@unhead/vue": { "version": "2.0.14", "resolved": "https://registry.npmjs.org/@unhead/vue/-/vue-2.0.14.tgz", @@ -2198,9 +3818,9 @@ } }, "node_modules/@vercel/nft": { - "version": "0.29.4", - "resolved": "https://registry.npmjs.org/@vercel/nft/-/nft-0.29.4.tgz", - "integrity": "sha512-6lLqMNX3TuycBPABycx7A9F1bHQR7kiQln6abjFbPrf5C/05qHM9M5E4PeTE59c7z8g6vHnx1Ioihb2AQl7BTA==", + "version": "0.30.1", + "resolved": "https://registry.npmjs.org/@vercel/nft/-/nft-0.30.1.tgz", + "integrity": "sha512-2mgJZv4AYBFkD/nJ4QmiX5Ymxi+AisPLPcS/KPXVqniyQNqKXX+wjieAbDXQP3HcogfEbpHoRMs49Cd4pfkk8g==", "license": "MIT", "dependencies": { "@mapbox/node-pre-gyp": "^2.0.0", @@ -2278,9 +3898,9 @@ } }, "node_modules/@vitejs/plugin-vue-jsx/node_modules/@rolldown/pluginutils": { - "version": "1.0.0-beta.34", - "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.34.tgz", - "integrity": "sha512-LyAREkZHP5pMom7c24meKmJCdhf2hEyvam2q0unr3or9ydwDL+DJ8chTF6Av/RFPb3rH8UFBdMzO5MxTZW97oA==", + "version": "1.0.0-beta.37", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.37.tgz", + "integrity": "sha512-0taU1HpxFzrukvWIhLRI4YssJX2wOW5q1MxPXWztltsQ13TE51/larZIwhFdpyk7+K43TH7x6GJ8oEqAo+vDbA==", "license": "MIT" }, "node_modules/@volar/language-core": { @@ -2376,13 +3996,13 @@ } }, "node_modules/@vue/compiler-core": { - "version": "3.5.20", - "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.20.tgz", - "integrity": "sha512-8TWXUyiqFd3GmP4JTX9hbiTFRwYHgVL/vr3cqhr4YQ258+9FADwvj7golk2sWNGHR67QgmCZ8gz80nQcMokhwg==", + "version": "3.5.21", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.21.tgz", + "integrity": "sha512-8i+LZ0vf6ZgII5Z9XmUvrCyEzocvWT+TeR2VBUVlzIH6Tyv57E20mPZ1bCS+tbejgUgmjrEh7q/0F0bibskAmw==", "license": "MIT", "dependencies": { "@babel/parser": "^7.28.3", - "@vue/shared": "3.5.20", + "@vue/shared": "3.5.21", "entities": "^4.5.0", "estree-walker": "^2.0.2", "source-map-js": "^1.2.1" @@ -2395,28 +4015,28 @@ "license": "MIT" }, "node_modules/@vue/compiler-dom": { - "version": "3.5.20", - "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.20.tgz", - "integrity": "sha512-whB44M59XKjqUEYOMPYU0ijUV0G+4fdrHVKDe32abNdX/kJe1NUEMqsi4cwzXa9kyM9w5S8WqFsrfo1ogtBZGQ==", + "version": "3.5.21", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.21.tgz", + "integrity": "sha512-jNtbu/u97wiyEBJlJ9kmdw7tAr5Vy0Aj5CgQmo+6pxWNQhXZDPsRr1UWPN4v3Zf82s2H3kF51IbzZ4jMWAgPlQ==", "license": "MIT", "dependencies": { - "@vue/compiler-core": "3.5.20", - "@vue/shared": "3.5.20" + "@vue/compiler-core": "3.5.21", + "@vue/shared": "3.5.21" } }, "node_modules/@vue/compiler-sfc": { - "version": "3.5.20", - "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.20.tgz", - "integrity": "sha512-SFcxapQc0/feWiSBfkGsa1v4DOrnMAQSYuvDMpEaxbpH5dKbnEM5KobSNSgU+1MbHCl+9ftm7oQWxvwDB6iBfw==", + "version": "3.5.21", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.21.tgz", + "integrity": "sha512-SXlyk6I5eUGBd2v8Ie7tF6ADHE9kCR6mBEuPyH1nUZ0h6Xx6nZI29i12sJKQmzbDyr2tUHMhhTt51Z6blbkTTQ==", "license": "MIT", "dependencies": { "@babel/parser": "^7.28.3", - "@vue/compiler-core": "3.5.20", - "@vue/compiler-dom": "3.5.20", - "@vue/compiler-ssr": "3.5.20", - "@vue/shared": "3.5.20", + "@vue/compiler-core": "3.5.21", + "@vue/compiler-dom": "3.5.21", + "@vue/compiler-ssr": "3.5.21", + "@vue/shared": "3.5.21", "estree-walker": "^2.0.2", - "magic-string": "^0.30.17", + "magic-string": "^0.30.18", "postcss": "^8.5.6", "source-map-js": "^1.2.1" } @@ -2428,13 +4048,13 @@ "license": "MIT" }, "node_modules/@vue/compiler-ssr": { - "version": "3.5.20", - "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.20.tgz", - "integrity": "sha512-RSl5XAMc5YFUXpDQi+UQDdVjH9FnEpLDHIALg5J0ITHxkEzJ8uQLlo7CIbjPYqmZtt6w0TsIPbo1izYXwDG7JA==", + "version": "3.5.21", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.21.tgz", + "integrity": "sha512-vKQ5olH5edFZdf5ZrlEgSO1j1DMA4u23TVK5XR1uMhvwnYvVdDF0nHXJUblL/GvzlShQbjhZZ2uvYmDlAbgo9w==", "license": "MIT", "dependencies": { - "@vue/compiler-dom": "3.5.20", - "@vue/shared": "3.5.20" + "@vue/compiler-dom": "3.5.21", + "@vue/shared": "3.5.21" } }, "node_modules/@vue/compiler-vue2": { @@ -2495,9 +4115,9 @@ } }, "node_modules/@vue/language-core": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/@vue/language-core/-/language-core-3.0.6.tgz", - "integrity": "sha512-e2RRzYWm+qGm8apUHW1wA5RQxzNhkqbbKdbKhiDUcmMrNAZGyM8aTiL3UrTqkaFI5s7wJRGGrp4u3jgusuBp2A==", + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@vue/language-core/-/language-core-3.0.7.tgz", + "integrity": "sha512-0sqqyqJ0Gn33JH3TdIsZLCZZ8Gr4kwlg8iYOnOrDDkJKSjFurlQY/bEFQx5zs7SX2C/bjMkmPYq/NiyY1fTOkw==", "license": "MIT", "dependencies": { "@volar/language-core": "2.4.23", @@ -2531,161 +4151,60 @@ } }, "node_modules/@vue/reactivity": { - "version": "3.5.20", - "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.20.tgz", - "integrity": "sha512-hS8l8x4cl1fmZpSQX/NXlqWKARqEsNmfkwOIYqtR2F616NGfsLUm0G6FQBK6uDKUCVyi1YOL8Xmt/RkZcd/jYQ==", + "version": "3.5.21", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.21.tgz", + "integrity": "sha512-3ah7sa+Cwr9iiYEERt9JfZKPw4A2UlbY8RbbnH2mGCE8NwHkhmlZt2VsH0oDA3P08X3jJd29ohBDtX+TbD9AsA==", "license": "MIT", "dependencies": { - "@vue/shared": "3.5.20" + "@vue/shared": "3.5.21" } }, "node_modules/@vue/runtime-core": { - "version": "3.5.20", - "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.20.tgz", - "integrity": "sha512-vyQRiH5uSZlOa+4I/t4Qw/SsD/gbth0SW2J7oMeVlMFMAmsG1rwDD6ok0VMmjXY3eI0iHNSSOBilEDW98PLRKw==", + "version": "3.5.21", + "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.21.tgz", + "integrity": "sha512-+DplQlRS4MXfIf9gfD1BOJpk5RSyGgGXD/R+cumhe8jdjUcq/qlxDawQlSI8hCKupBlvM+3eS1se5xW+SuNAwA==", "license": "MIT", "dependencies": { - "@vue/reactivity": "3.5.20", - "@vue/shared": "3.5.20" + "@vue/reactivity": "3.5.21", + "@vue/shared": "3.5.21" } }, "node_modules/@vue/runtime-dom": { - "version": "3.5.20", - "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.20.tgz", - "integrity": "sha512-KBHzPld/Djw3im0CQ7tGCpgRedryIn4CcAl047EhFTCCPT2xFf4e8j6WeKLgEEoqPSl9TYqShc3Q6tpWpz/Xgw==", + "version": "3.5.21", + "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.21.tgz", + "integrity": "sha512-3M2DZsOFwM5qI15wrMmNF5RJe1+ARijt2HM3TbzBbPSuBHOQpoidE+Pa+XEaVN+czbHf81ETRoG1ltztP2em8w==", "license": "MIT", "dependencies": { - "@vue/reactivity": "3.5.20", - "@vue/runtime-core": "3.5.20", - "@vue/shared": "3.5.20", + "@vue/reactivity": "3.5.21", + "@vue/runtime-core": "3.5.21", + "@vue/shared": "3.5.21", "csstype": "^3.1.3" } }, "node_modules/@vue/server-renderer": { - "version": "3.5.20", - "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.20.tgz", - "integrity": "sha512-HthAS0lZJDH21HFJBVNTtx+ULcIbJQRpjSVomVjfyPkFSpCwvsPTA+jIzOaUm3Hrqx36ozBHePztQFg6pj5aKg==", + "version": "3.5.21", + "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.21.tgz", + "integrity": "sha512-qr8AqgD3DJPJcGvLcJKQo2tAc8OnXRcfxhOJCPF+fcfn5bBGz7VCcO7t+qETOPxpWK1mgysXvVT/j+xWaHeMWA==", "license": "MIT", "dependencies": { - "@vue/compiler-ssr": "3.5.20", - "@vue/shared": "3.5.20" + "@vue/compiler-ssr": "3.5.21", + "@vue/shared": "3.5.21" }, "peerDependencies": { - "vue": "3.5.20" + "vue": "3.5.21" } }, "node_modules/@vue/shared": { - "version": "3.5.20", - "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.20.tgz", - "integrity": "sha512-SoRGP596KU/ig6TfgkCMbXkr4YJ91n/QSdMuqeP5r3hVIYA3CPHUBCc7Skak0EAKV+5lL4KyIh61VA/pK1CIAA==", + "version": "3.5.21", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.21.tgz", + "integrity": "sha512-+2k1EQpnYuVuu3N7atWyG3/xoFWIVJZq4Mz8XNOdScFI0etES75fbny/oU4lKWk/577P1zmg0ioYvpGEDZ3DLw==", "license": "MIT" }, - "node_modules/@whatwg-node/disposablestack": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/@whatwg-node/disposablestack/-/disposablestack-0.0.6.tgz", - "integrity": "sha512-LOtTn+JgJvX8WfBVJtF08TGrdjuFzGJc4mkP8EdDI8ADbvO7kiexYep1o8dwnt0okb0jYclCDXF13xU7Ge4zSw==", - "license": "MIT", - "dependencies": { - "@whatwg-node/promise-helpers": "^1.0.0", - "tslib": "^2.6.3" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@whatwg-node/disposablestack/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" - }, - "node_modules/@whatwg-node/fetch": { - "version": "0.10.10", - "resolved": "https://registry.npmjs.org/@whatwg-node/fetch/-/fetch-0.10.10.tgz", - "integrity": "sha512-watz4i/Vv4HpoJ+GranJ7HH75Pf+OkPQ63NoVmru6Srgc8VezTArB00i/oQlnn0KWh14gM42F22Qcc9SU9mo/w==", - "license": "MIT", - "dependencies": { - "@whatwg-node/node-fetch": "^0.7.25", - "urlpattern-polyfill": "^10.0.0" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@whatwg-node/fetch/node_modules/urlpattern-polyfill": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/urlpattern-polyfill/-/urlpattern-polyfill-10.1.0.tgz", - "integrity": "sha512-IGjKp/o0NL3Bso1PymYURCJxMPNAf/ILOpendP9f5B6e1rTJgdgiOvgfoT8VxCAdY+Wisb9uhGaJJf3yZ2V9nw==", - "license": "MIT" - }, - "node_modules/@whatwg-node/node-fetch": { - "version": "0.7.25", - "resolved": "https://registry.npmjs.org/@whatwg-node/node-fetch/-/node-fetch-0.7.25.tgz", - "integrity": "sha512-szCTESNJV+Xd56zU6ShOi/JWROxE9IwCic8o5D9z5QECZloas6Ez5tUuKqXTAdu6fHFx1t6C+5gwj8smzOLjtg==", - "license": "MIT", - "dependencies": { - "@fastify/busboy": "^3.1.1", - "@whatwg-node/disposablestack": "^0.0.6", - "@whatwg-node/promise-helpers": "^1.3.2", - "tslib": "^2.6.3" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@whatwg-node/node-fetch/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" - }, - "node_modules/@whatwg-node/promise-helpers": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@whatwg-node/promise-helpers/-/promise-helpers-1.3.2.tgz", - "integrity": "sha512-Nst5JdK47VIl9UcGwtv2Rcgyn5lWtZ0/mhRQ4G8NN2isxpq2TO30iqHzmwoJycjWuyUfg3GFXqP/gFHXeV57IA==", - "license": "MIT", - "dependencies": { - "tslib": "^2.6.3" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@whatwg-node/promise-helpers/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" - }, - "node_modules/@whatwg-node/server": { - "version": "0.9.71", - "resolved": "https://registry.npmjs.org/@whatwg-node/server/-/server-0.9.71.tgz", - "integrity": "sha512-ueFCcIPaMgtuYDS9u0qlUoEvj6GiSsKrwnOLPp9SshqjtcRaR1IEHRjoReq3sXNydsF5i0ZnmuYgXq9dV53t0g==", - "license": "MIT", - "dependencies": { - "@whatwg-node/disposablestack": "^0.0.6", - "@whatwg-node/fetch": "^0.10.5", - "@whatwg-node/promise-helpers": "^1.2.2", - "tslib": "^2.6.3" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@whatwg-node/server/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" - }, "node_modules/abbrev": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-3.0.1.tgz", - "integrity": "sha512-AO2ac6pjRB3SJmGJo+v5/aK6Omggp6fsLrs6wN9bd35ulu4cCwaAU9+7ZhXjeqHVkaHThLuzH0nZr0YpCDhygg==", - "license": "ISC", - "engines": { - "node": "^18.17.0 || >=20.5.0" - } + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "license": "ISC" }, "node_modules/abort-controller": { "version": "3.0.0", @@ -2736,9 +4255,9 @@ "license": "MIT" }, "node_modules/ansi-regex": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.0.tgz", - "integrity": "sha512-TKY5pyBkHyADOPYlRT9Lx6F544mPl0vS5Ew7BJ45hA08Q+t3GjbueLliBWN3sMICk6+y7HdyxSzC4bWS8baBdg==", + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", "license": "MIT", "engines": { "node": ">=12" @@ -2748,9 +4267,9 @@ } }, "node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", "license": "MIT", "engines": { "node": ">=12" @@ -2851,15 +4370,6 @@ "url": "https://github.com/sponsors/sxzz" } }, - "node_modules/ast-module-types": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ast-module-types/-/ast-module-types-6.0.1.tgz", - "integrity": "sha512-WHw67kLXYbZuHTmcdbIrVArCq5wxo6NEuj3hiYAWr8mwJeC+C2mMCIBIWCiDoCye/OF/xelc+teJ1ERoWmnEIA==", - "license": "MIT", - "engines": { - "node": ">=18" - } - }, "node_modules/ast-walker-scope": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/ast-walker-scope/-/ast-walker-scope-0.8.2.tgz", @@ -2926,10 +4436,18 @@ } }, "node_modules/b4a": { - "version": "1.6.7", - "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.7.tgz", - "integrity": "sha512-OnAYlL5b7LEkALw87fUVafQw5rVR9RjwGd4KUwNQ6DrrNmaVaUCgLipfVlzrPQ4tWOR9P0IXGNOx50jYCCdSJg==", - "license": "Apache-2.0" + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.7.1.tgz", + "integrity": "sha512-ZovbrBV0g6JxK5cGUF1Suby1vLfKjv4RWi8IxoaO/Mon8BDD9I21RxjHFtgQ+kskJqLAVyQZly3uMBui+vhc8Q==", + "license": "Apache-2.0", + "peerDependencies": { + "react-native-b4a": "*" + }, + "peerDependenciesMeta": { + "react-native-b4a": { + "optional": true + } + } }, "node_modules/balanced-match": { "version": "1.0.2", @@ -2945,15 +4463,17 @@ "optional": true }, "node_modules/bare-fs": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/bare-fs/-/bare-fs-4.2.1.tgz", - "integrity": "sha512-mELROzV0IhqilFgsl1gyp48pnZsaV9xhQapHLDsvn4d4ZTfbFhcghQezl7FTEDNBcGqLUnNI3lUlm6ecrLWdFA==", + "version": "4.4.4", + "resolved": "https://registry.npmjs.org/bare-fs/-/bare-fs-4.4.4.tgz", + "integrity": "sha512-Q8yxM1eLhJfuM7KXVP3zjhBvtMJCYRByoTT+wHXjpdMELv0xICFJX+1w4c7csa+WZEOsq4ItJ4RGwvzid6m/dw==", "license": "Apache-2.0", "optional": true, "dependencies": { "bare-events": "^2.5.4", "bare-path": "^3.0.0", - "bare-stream": "^2.6.4" + "bare-stream": "^2.6.4", + "bare-url": "^2.2.2", + "fast-fifo": "^1.3.2" }, "engines": { "bare": ">=1.16.0" @@ -3009,6 +4529,16 @@ } } }, + "node_modules/bare-url": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/bare-url/-/bare-url-2.2.2.tgz", + "integrity": "sha512-g+ueNGKkrjMazDG3elZO1pNs3HY5+mMmOet1jtKyhOaCnkLzitxf26z7hoAEkDNgdNmnc1KIlt/dw6Po6xZMpA==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "bare-path": "^3.0.0" + } + }, "node_modules/base64-js": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", @@ -3029,6 +4559,15 @@ ], "license": "MIT" }, + "node_modules/baseline-browser-mapping": { + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.2.tgz", + "integrity": "sha512-NvcIedLxrs9llVpX7wI+Jz4Hn9vJQkCPKrTaHIE0sW/Rj1iq6Fzby4NbyTZjQJNoypBXNaG7tEHkTgONZpwgxQ==", + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.js" + } + }, "node_modules/bindings": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", @@ -3127,9 +4666,9 @@ } }, "node_modules/browserslist": { - "version": "4.25.4", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.4.tgz", - "integrity": "sha512-4jYpcjabC606xJ3kw2QwGEZKX0Aw7sgQdZCvIK9dhVSPh76BKo+C+btT1RRofH7B+8iNpEbgGNVWiLki5q93yg==", + "version": "4.26.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.26.0.tgz", + "integrity": "sha512-P9go2WrP9FiPwLv3zqRD/Uoxo0RSHjzFCiQz7d4vbmwNqQFo9T9WCeP/Qn5EbcKQY6DBbkxEXNcpJOmncNrb7A==", "funding": [ { "type": "opencollective", @@ -3146,9 +4685,10 @@ ], "license": "MIT", "dependencies": { - "caniuse-lite": "^1.0.30001737", - "electron-to-chromium": "^1.5.211", - "node-releases": "^2.0.19", + "baseline-browser-mapping": "^2.8.2", + "caniuse-lite": "^1.0.30001741", + "electron-to-chromium": "^1.5.218", + "node-releases": "^2.0.21", "update-browserslist-db": "^1.1.3" }, "bin": { @@ -3197,18 +4737,6 @@ "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", "license": "MIT" }, - "node_modules/builtin-modules": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz", - "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==", - "license": "MIT", - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/bundle-name": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-4.1.0.tgz", @@ -3261,43 +4789,6 @@ "node": ">=8" } }, - "node_modules/call-bind-apply-helpers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", - "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/call-bound": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", - "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.2", - "get-intrinsic": "^1.3.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/callsite": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz", - "integrity": "sha512-0vdNRFXn5q+dtOqjfFtmtlI9N2eVZ7LMyEV2iKC5mEEFvSg/69Ml6b/WU2qF8W1nLRa0wiSrDT3Y5jOHZCwKPQ==", - "engines": { - "node": "*" - } - }, "node_modules/caniuse-api": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz", @@ -3311,9 +4802,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001737", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001737.tgz", - "integrity": "sha512-BiloLiXtQNrY5UyF0+1nSJLXUENuhka2pzy2Fx5pGxqavdrxSCW4U6Pn/PoG3Efspi2frRbHpBV2XsrPE6EDlw==", + "version": "1.0.30001741", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001741.tgz", + "integrity": "sha512-QGUGitqsc8ARjLdgAfxETDhRbJ0REsP6O3I96TAth/mVjh2cYzN2u+3AzPP3aVSm2FehEItaJw1xd+IGBXWeSw==", "funding": [ { "type": "opencollective", @@ -3533,41 +5024,6 @@ "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==", "license": "MIT" }, - "node_modules/colorspace": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/colorspace/-/colorspace-1.1.4.tgz", - "integrity": "sha512-BgvKJiuVu1igBUF2kEjRCZXol6wiiGbY5ipL/oVPwm0BL9sIpMIzM8IK7vwuxIIzOXMV3Ey5w+vxhm0rR/TN8w==", - "license": "MIT", - "dependencies": { - "color": "^3.1.3", - "text-hex": "1.0.x" - } - }, - "node_modules/colorspace/node_modules/color": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/color/-/color-3.2.1.tgz", - "integrity": "sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==", - "license": "MIT", - "dependencies": { - "color-convert": "^1.9.3", - "color-string": "^1.6.0" - } - }, - "node_modules/colorspace/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "license": "MIT", - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/colorspace/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "license": "MIT" - }, "node_modules/commander": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", @@ -3577,12 +5033,6 @@ "node": ">= 10" } }, - "node_modules/common-path-prefix": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/common-path-prefix/-/common-path-prefix-3.0.0.tgz", - "integrity": "sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w==", - "license": "ISC" - }, "node_modules/commondir": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", @@ -3674,22 +5124,6 @@ "url": "https://github.com/sponsors/mesqueeb" } }, - "node_modules/copy-file": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/copy-file/-/copy-file-11.1.0.tgz", - "integrity": "sha512-X8XDzyvYaA6msMyAM575CUoygY5b44QzLcGRKsK3MFmXcOvQa518dNPLsKYwkYsn72g3EiW+LE0ytd/FlqWmyw==", - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.2.11", - "p-event": "^6.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/core-util-is": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", @@ -3730,18 +5164,6 @@ "node": ">= 14" } }, - "node_modules/cron-parser": { - "version": "4.9.0", - "resolved": "https://registry.npmjs.org/cron-parser/-/cron-parser-4.9.0.tgz", - "integrity": "sha512-p0SaNjrHOnQeR8/VnfGbmg9te2kfyYSQ7Sc/j/6DtPL3JQvKxmjO9TSjNFpujqV3vEYYBvNNvXSxzyksBWAx1Q==", - "license": "MIT", - "dependencies": { - "luxon": "^3.2.1" - }, - "engines": { - "node": ">=12.0.0" - } - }, "node_modules/croner": { "version": "9.1.0", "resolved": "https://registry.npmjs.org/croner/-/croner-9.1.0.tgz", @@ -4438,19 +5860,10 @@ "lodash-es": "^4.17.21" } }, - "node_modules/data-uri-to-buffer": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", - "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", - "license": "MIT", - "engines": { - "node": ">= 12" - } - }, "node_modules/dayjs": { - "version": "1.11.15", - "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.15.tgz", - "integrity": "sha512-MC+DfnSWiM9APs7fpiurHGCoeIx0Gdl6QZBy+5lu8MbYKN5FZEXqOgrundfibdfhGZ15o9hzmZ2xJjZnbvgKXQ==", + "version": "1.11.18", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.18.tgz", + "integrity": "sha512-zFBQ7WFRvVRhKcWoUh+ZA1g2HVgUbsZm9sbddh8EC5iv93sui8DVVz1Npvz+r6meo9VKfa8NyLWBsQK1VvIKPA==", "license": "MIT" }, "node_modules/db0": { @@ -4510,15 +5923,6 @@ } } }, - "node_modules/decache": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/decache/-/decache-4.6.2.tgz", - "integrity": "sha512-2LPqkLeu8XWHU8qNCS3kcF6sCcb5zIzvWaAHYSvPfwhdd7mHuah29NssMzrTYyHN4F5oFy2ko9OBYxegtU0FEw==", - "license": "MIT", - "dependencies": { - "callsite": "^1.0.0" - } - }, "node_modules/decode-named-character-reference": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.2.0.tgz", @@ -4664,138 +6068,6 @@ "node": ">=0.10" } }, - "node_modules/detective-amd": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/detective-amd/-/detective-amd-6.0.1.tgz", - "integrity": "sha512-TtyZ3OhwUoEEIhTFoc1C9IyJIud3y+xYkSRjmvCt65+ycQuc3VcBrPRTMWoO/AnuCyOB8T5gky+xf7Igxtjd3g==", - "license": "MIT", - "dependencies": { - "ast-module-types": "^6.0.1", - "escodegen": "^2.1.0", - "get-amd-module-type": "^6.0.1", - "node-source-walk": "^7.0.1" - }, - "bin": { - "detective-amd": "bin/cli.js" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/detective-cjs": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/detective-cjs/-/detective-cjs-6.0.1.tgz", - "integrity": "sha512-tLTQsWvd2WMcmn/60T2inEJNhJoi7a//PQ7DwRKEj1yEeiQs4mrONgsUtEJKnZmrGWBBmE0kJ1vqOG/NAxwaJw==", - "license": "MIT", - "dependencies": { - "ast-module-types": "^6.0.1", - "node-source-walk": "^7.0.1" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/detective-es6": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/detective-es6/-/detective-es6-5.0.1.tgz", - "integrity": "sha512-XusTPuewnSUdoxRSx8OOI6xIA/uld/wMQwYsouvFN2LAg7HgP06NF1lHRV3x6BZxyL2Kkoih4ewcq8hcbGtwew==", - "license": "MIT", - "dependencies": { - "node-source-walk": "^7.0.1" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/detective-postcss": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/detective-postcss/-/detective-postcss-7.0.1.tgz", - "integrity": "sha512-bEOVpHU9picRZux5XnwGsmCN4+8oZo7vSW0O0/Enq/TO5R2pIAP2279NsszpJR7ocnQt4WXU0+nnh/0JuK4KHQ==", - "license": "MIT", - "dependencies": { - "is-url": "^1.2.4", - "postcss-values-parser": "^6.0.2" - }, - "engines": { - "node": "^14.0.0 || >=16.0.0" - }, - "peerDependencies": { - "postcss": "^8.4.47" - } - }, - "node_modules/detective-sass": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/detective-sass/-/detective-sass-6.0.1.tgz", - "integrity": "sha512-jSGPO8QDy7K7pztUmGC6aiHkexBQT4GIH+mBAL9ZyBmnUIOFbkfZnO8wPRRJFP/QP83irObgsZHCoDHZ173tRw==", - "license": "MIT", - "dependencies": { - "gonzales-pe": "^4.3.0", - "node-source-walk": "^7.0.1" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/detective-scss": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/detective-scss/-/detective-scss-5.0.1.tgz", - "integrity": "sha512-MAyPYRgS6DCiS6n6AoSBJXLGVOydsr9huwXORUlJ37K3YLyiN0vYHpzs3AdJOgHobBfispokoqrEon9rbmKacg==", - "license": "MIT", - "dependencies": { - "gonzales-pe": "^4.3.0", - "node-source-walk": "^7.0.1" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/detective-stylus": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/detective-stylus/-/detective-stylus-5.0.1.tgz", - "integrity": "sha512-Dgn0bUqdGbE3oZJ+WCKf8Dmu7VWLcmRJGc6RCzBgG31DLIyai9WAoEhYRgIHpt/BCRMrnXLbGWGPQuBUrnF0TA==", - "license": "MIT", - "engines": { - "node": ">=18" - } - }, - "node_modules/detective-typescript": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/detective-typescript/-/detective-typescript-14.0.0.tgz", - "integrity": "sha512-pgN43/80MmWVSEi5LUuiVvO/0a9ss5V7fwVfrJ4QzAQRd3cwqU1SfWGXJFcNKUqoD5cS+uIovhw5t/0rSeC5Mw==", - "license": "MIT", - "dependencies": { - "@typescript-eslint/typescript-estree": "^8.23.0", - "ast-module-types": "^6.0.1", - "node-source-walk": "^7.0.1" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "typescript": "^5.4.4" - } - }, - "node_modules/detective-vue2": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/detective-vue2/-/detective-vue2-2.2.0.tgz", - "integrity": "sha512-sVg/t6O2z1zna8a/UIV6xL5KUa2cMTQbdTIIvqNM0NIPswp52fe43Nwmbahzj3ww4D844u/vC2PYfiGLvD3zFA==", - "license": "MIT", - "dependencies": { - "@dependents/detective-less": "^5.0.1", - "@vue/compiler-sfc": "^3.5.13", - "detective-es6": "^5.0.1", - "detective-sass": "^6.0.1", - "detective-scss": "^5.0.1", - "detective-stylus": "^5.0.1", - "detective-typescript": "^14.0.0" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "typescript": "^5.4.4" - } - }, "node_modules/devalue": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/devalue/-/devalue-5.3.2.tgz", @@ -4819,7 +6091,7 @@ }, "node_modules/diff2html": { "version": "3.4.52", - "resolved": "https://registry.npmmirror.com/diff2html/-/diff2html-3.4.52.tgz", + "resolved": "https://registry.npmjs.org/diff2html/-/diff2html-3.4.52.tgz", "integrity": "sha512-qhMg8/I3sZ4zm/6R/Kh0xd6qG6Vm86w6M+C9W+DuH1V8ACz+1cgEC8/k0ucjv6AGqZWzHm/8G1gh7IlrUqCMhg==", "license": "MIT", "dependencies": { @@ -4835,7 +6107,7 @@ }, "node_modules/diff2html/node_modules/diff": { "version": "7.0.0", - "resolved": "https://registry.npmmirror.com/diff/-/diff-7.0.0.tgz", + "resolved": "https://registry.npmjs.org/diff/-/diff-7.0.0.tgz", "integrity": "sha512-PJWHUb1RFevKCwaFA9RlG5tCd+FO5iRh9A8HEtkmBH2Li03iJriB6m6JIN4rGz3K3JLawI7/veA1xzRKP6ISBw==", "license": "BSD-3-Clause", "engines": { @@ -4844,7 +6116,7 @@ }, "node_modules/diff2html/node_modules/highlight.js": { "version": "11.9.0", - "resolved": "https://registry.npmmirror.com/highlight.js/-/highlight.js-11.9.0.tgz", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-11.9.0.tgz", "integrity": "sha512-fJ7cW7fQGCYAkgv4CPfwFHrfd/cLS4Hau96JuJ+ZTOWhjnhoeN1ub1tFmALm/+lW5z4WCAuAV9bm05AP0mS6Gw==", "license": "BSD-3-Clause", "optional": true, @@ -4929,9 +6201,9 @@ } }, "node_modules/dotenv": { - "version": "17.2.1", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.2.1.tgz", - "integrity": "sha512-kQhDYKZecqnM0fCnzI5eIv5L4cAe/iRI+HqMbO/hbRdTAeXDG+M9FjipUxNfbARuEg4iHIbhnhs78BCHNbSxEQ==", + "version": "17.2.2", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.2.2.tgz", + "integrity": "sha512-Sf2LSQP+bOlhKWWyhFsn0UsfdK/kCWRv1iuA2gXAwt3dyNabr6QSj00I2V10pidqz69soatm9ZwZvpQMTIOd5Q==", "license": "BSD-2-Clause", "engines": { "node": ">=12" @@ -4940,20 +6212,6 @@ "url": "https://dotenvx.com" } }, - "node_modules/dunder-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", - "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.1", - "es-errors": "^1.3.0", - "gopd": "^1.2.0" - }, - "engines": { - "node": ">= 0.4" - } - }, "node_modules/duplexer": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", @@ -4983,9 +6241,9 @@ "license": "MIT" }, "node_modules/electron-to-chromium": { - "version": "1.5.211", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.211.tgz", - "integrity": "sha512-IGBvimJkotaLzFnwIVgW9/UD/AOJ2tByUmeOrtqBfACSbAw5b1G0XpvdaieKyc7ULmbwXVx+4e4Be8pOPBrYkw==", + "version": "1.5.218", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.218.tgz", + "integrity": "sha512-uwwdN0TUHs8u6iRgN8vKeWZMRll4gBkz+QMqdS7DDe49uiK68/UX92lFb61oiFPrpYZNeZIqa4bA7O6Aiasnzg==", "license": "ISC" }, "node_modules/elkjs": { @@ -5000,12 +6258,6 @@ "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", "license": "MIT" }, - "node_modules/enabled": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/enabled/-/enabled-2.0.0.tgz", - "integrity": "sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==", - "license": "MIT" - }, "node_modules/encodeurl": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", @@ -5020,6 +6272,7 @@ "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", "license": "MIT", + "optional": true, "dependencies": { "once": "^1.4.0" } @@ -5036,18 +6289,6 @@ "url": "https://github.com/fb55/entities?sponsor=1" } }, - "node_modules/env-paths": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-3.0.0.tgz", - "integrity": "sha512-dtJUTepzMW3Lm/NPxRf3wP4642UWhjL2sQxc+ym2YMj1m/H2zDNQOlezafzkHwn6sMstjHTwG6iQQsctDW/b1A==", - "license": "MIT", - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/error-stack-parser-es": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/error-stack-parser-es/-/error-stack-parser-es-1.0.5.tgz", @@ -5063,42 +6304,12 @@ "integrity": "sha512-fZmsRiDNv07K6s2KkKFTiD2aIvECa7++PKyD5NC32tpRw46qZA3sOz+aM+/V9V0GDHxVTKLziveV4JhzBHDp9Q==", "license": "MIT" }, - "node_modules/es-define-property": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", - "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-errors": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", - "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, "node_modules/es-module-lexer": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz", "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==", "license": "MIT" }, - "node_modules/es-object-atoms": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", - "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0" - }, - "engines": { - "node": ">= 0.4" - } - }, "node_modules/esbuild": { "version": "0.25.9", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.9.tgz", @@ -5167,71 +6378,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/escodegen": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz", - "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", - "license": "BSD-2-Clause", - "dependencies": { - "esprima": "^4.0.1", - "estraverse": "^5.2.0", - "esutils": "^2.0.2" - }, - "bin": { - "escodegen": "bin/escodegen.js", - "esgenerate": "bin/esgenerate.js" - }, - "engines": { - "node": ">=6.0" - }, - "optionalDependencies": { - "source-map": "~0.6.1" - } - }, - "node_modules/escodegen/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "license": "BSD-3-Clause", - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/eslint-visitor-keys": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", - "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", - "license": "Apache-2.0", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "license": "BSD-2-Clause", - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "license": "BSD-2-Clause", - "engines": { - "node": ">=4.0" - } - }, "node_modules/estree-walker": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", @@ -5241,15 +6387,6 @@ "@types/estree": "^1.0.0" } }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "license": "BSD-2-Clause", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/etag": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", @@ -5325,41 +6462,6 @@ "integrity": "sha512-VO5fQUzZtI6C+vx4w/4BWJpg3s/5l+6pRQEHzFRM8WFi4XffSP1Z+4qi7GbjWbvRQEbdIco5mIMq+zX4rPuLrw==", "license": "MIT" }, - "node_modules/extract-zip": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", - "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", - "license": "BSD-2-Clause", - "dependencies": { - "debug": "^4.1.1", - "get-stream": "^5.1.0", - "yauzl": "^2.10.0" - }, - "bin": { - "extract-zip": "cli.js" - }, - "engines": { - "node": ">= 10.17.0" - }, - "optionalDependencies": { - "@types/yauzl": "^2.9.1" - } - }, - "node_modules/extract-zip/node_modules/get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "license": "MIT", - "dependencies": { - "pump": "^3.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/fast-fifo": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz", @@ -5412,44 +6514,6 @@ "node": ">=0.8.0" } }, - "node_modules/fd-slicer": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", - "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", - "license": "MIT", - "dependencies": { - "pend": "~1.2.0" - } - }, - "node_modules/fecha": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.3.tgz", - "integrity": "sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==", - "license": "MIT" - }, - "node_modules/fetch-blob": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", - "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/jimmywarting" - }, - { - "type": "paypal", - "url": "https://paypal.me/jimmywarting" - } - ], - "license": "MIT", - "dependencies": { - "node-domexception": "^1.0.0", - "web-streams-polyfill": "^3.0.3" - }, - "engines": { - "node": "^12.20 || >= 14.13" - } - }, "node_modules/file-uri-to-path": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", @@ -5468,59 +6532,12 @@ "node": ">=8" } }, - "node_modules/filter-obj": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/filter-obj/-/filter-obj-6.1.0.tgz", - "integrity": "sha512-xdMtCAODmPloU9qtmPcdBV9Kd27NtMse+4ayThxqIHUES5Z2S6bGpap5PpdmNM56ub7y3i1eyr+vJJIIgWGKmA==", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/find-up": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-7.0.0.tgz", - "integrity": "sha512-YyZM99iHrqLKjmt4LJDj58KI+fYyufRLBSYcqycxf//KpBk9FoewoGX0450m9nB44qrZnovzC2oeP5hUibxc/g==", - "license": "MIT", - "dependencies": { - "locate-path": "^7.2.0", - "path-exists": "^5.0.0", - "unicorn-magic": "^0.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/find-up-simple": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/find-up-simple/-/find-up-simple-1.0.1.tgz", - "integrity": "sha512-afd4O7zpqHeRyg4PfDQsXmlDe2PfdHtJt6Akt8jOWaApLOZk5JXs6VMR29lz03pRe9mpykrRCYIYxaJYcfpncQ==", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/flatpickr": { "version": "4.6.13", "resolved": "https://registry.npmjs.org/flatpickr/-/flatpickr-4.6.13.tgz", "integrity": "sha512-97PMG/aywoYpB4IvbvUJi0RQi8vearvU0oov1WW3k0WZPBMrTQVqekSX5CjSG/M4Q3i6A/0FKXC7RyAoAUUSPw==", "license": "MIT" }, - "node_modules/fn.name": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz", - "integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==", - "license": "MIT" - }, "node_modules/foreground-child": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", @@ -5537,18 +6554,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/formdata-polyfill": { - "version": "4.0.10", - "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", - "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", - "license": "MIT", - "dependencies": { - "fetch-blob": "^3.1.2" - }, - "engines": { - "node": ">=12.20.0" - } - }, "node_modules/fraction.js": { "version": "4.3.7", "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", @@ -5619,19 +6624,6 @@ "node": ">=6.9.0" } }, - "node_modules/get-amd-module-type": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-amd-module-type/-/get-amd-module-type-6.0.1.tgz", - "integrity": "sha512-MtjsmYiCXcYDDrGqtNbeIYdAl85n+5mSv2r3FbzER/YV3ZILw4HNNIw34HuV5pyl0jzs6GFYU1VHVEefhgcNHQ==", - "license": "MIT", - "dependencies": { - "ast-module-types": "^6.0.1", - "node-source-walk": "^7.0.1" - }, - "engines": { - "node": ">=18" - } - }, "node_modules/get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", @@ -5641,49 +6633,12 @@ "node": "6.* || 8.* || >= 10.*" } }, - "node_modules/get-intrinsic": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", - "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.2", - "es-define-property": "^1.0.1", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.1.1", - "function-bind": "^1.1.2", - "get-proto": "^1.0.1", - "gopd": "^1.2.0", - "has-symbols": "^1.1.0", - "hasown": "^2.0.2", - "math-intrinsics": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/get-port-please": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/get-port-please/-/get-port-please-3.2.0.tgz", "integrity": "sha512-I9QVvBw5U/hw3RmWpYKRumUeaDgxTPd401x364rLmWBJcOQ753eov1eTgzDqRG9bqFIfDc7gfzcQEWrUri3o1A==", "license": "MIT" }, - "node_modules/get-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", - "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", - "license": "MIT", - "dependencies": { - "dunder-proto": "^1.0.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, "node_modules/get-stream": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", @@ -5806,45 +6761,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/globby/node_modules/unicorn-magic": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.3.0.tgz", - "integrity": "sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/gonzales-pe": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/gonzales-pe/-/gonzales-pe-4.3.0.tgz", - "integrity": "sha512-otgSPpUmdWJ43VXyiNgEYE4luzHCL2pz4wQ0OnDluC6Eg4Ko3Vexy/SrSynglw/eR+OhkzmqFCZa/OFa/RgAOQ==", - "license": "MIT", - "dependencies": { - "minimist": "^1.2.5" - }, - "bin": { - "gonzales": "bin/gonzales.js" - }, - "engines": { - "node": ">=0.6.0" - } - }, - "node_modules/gopd": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", - "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", @@ -5883,18 +6799,6 @@ "uncrypto": "^0.1.3" } }, - "node_modules/has-symbols": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", - "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/hasown": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", @@ -5927,7 +6831,7 @@ }, "node_modules/hogan.js": { "version": "3.0.2", - "resolved": "https://registry.npmmirror.com/hogan.js/-/hogan.js-3.0.2.tgz", + "resolved": "https://registry.npmjs.org/hogan.js/-/hogan.js-3.0.2.tgz", "integrity": "sha512-RqGs4wavGYJWE07t35JQccByczmNUXQT0E12ZYV1VKYu5UiAU9lsos/yBAcf840+zrUQQxgVduCR5/B8nNtibg==", "dependencies": { "mkdirp": "0.3.0", @@ -5937,61 +6841,12 @@ "hulk": "bin/hulk" } }, - "node_modules/hogan.js/node_modules/abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmmirror.com/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", - "license": "ISC" - }, - "node_modules/hogan.js/node_modules/mkdirp": { - "version": "0.3.0", - "resolved": "https://registry.npmmirror.com/mkdirp/-/mkdirp-0.3.0.tgz", - "integrity": "sha512-OHsdUcVAQ6pOtg5JYWpCBo9W/GySVuwvP9hueRMW7UqshC0tbfzLv8wjySTPm3tfUZ/21CE9E1pJagOA91Pxew==", - "deprecated": "Legacy versions of mkdirp are no longer supported. Please update to mkdirp 1.x. (Note that the API surface has changed to use Promises in 1.x.)", - "license": "MIT/X11", - "engines": { - "node": "*" - } - }, - "node_modules/hogan.js/node_modules/nopt": { - "version": "1.0.10", - "resolved": "https://registry.npmmirror.com/nopt/-/nopt-1.0.10.tgz", - "integrity": "sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==", - "license": "MIT", - "dependencies": { - "abbrev": "1" - }, - "bin": { - "nopt": "bin/nopt.js" - }, - "engines": { - "node": "*" - } - }, "node_modules/hookable": { "version": "5.5.3", "resolved": "https://registry.npmjs.org/hookable/-/hookable-5.5.3.tgz", "integrity": "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==", "license": "MIT" }, - "node_modules/hosted-git-info": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-7.0.2.tgz", - "integrity": "sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==", - "license": "ISC", - "dependencies": { - "lru-cache": "^10.0.1" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/hosted-git-info/node_modules/lru-cache": { - "version": "10.4.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", - "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", - "license": "ISC" - }, "node_modules/htmlparser2": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz", @@ -6140,27 +6995,6 @@ "unplugin-utils": "^0.2.4" } }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "license": "MIT", - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/index-to-position": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/index-to-position/-/index-to-position-1.1.0.tgz", - "integrity": "sha512-XPdx9Dq4t9Qk1mTMbWONJqU7boCoumEH7fRET37HX5+khDUl3J2W6PdALxhILYlIYx2amlwYcRPp28p0tSiojg==", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", @@ -6211,7 +7045,7 @@ }, "node_modules/ipx": { "version": "3.1.1", - "resolved": "https://registry.npmmirror.com/ipx/-/ipx-3.1.1.tgz", + "resolved": "https://registry.npmjs.org/ipx/-/ipx-3.1.1.tgz", "integrity": "sha512-7Xnt54Dco7uYkfdAw0r2vCly3z0rSaVhEXMzPvl3FndsTVm5p26j+PO+gyinkYmcsEUvX2Rh7OGK7KzYWRu6BA==", "license": "MIT", "dependencies": { @@ -6251,21 +7085,6 @@ "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==", "license": "MIT" }, - "node_modules/is-builtin-module": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-3.2.1.tgz", - "integrity": "sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==", - "license": "MIT", - "dependencies": { - "builtin-modules": "^3.3.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/is-core-module": { "version": "2.16.1", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", @@ -6387,15 +7206,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-plain-obj": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", - "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/is-plain-object": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", @@ -6435,24 +7245,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-url": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/is-url/-/is-url-1.2.4.tgz", - "integrity": "sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==", - "license": "MIT" - }, - "node_modules/is-url-superb": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-url-superb/-/is-url-superb-4.0.0.tgz", - "integrity": "sha512-GI+WjezhPPcbM+tqE9LnmsY5qqjwHzTvjJ36wxYX5ujNXefSUJ/T17r5bqDV8yLhcgB59KTPNOc9O9cmHTPWsA==", - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/is-what": { "version": "4.1.16", "resolved": "https://registry.npmjs.org/is-what/-/is-what-4.1.16.tgz", @@ -6561,27 +7353,6 @@ "node": ">=6" } }, - "node_modules/junk": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/junk/-/junk-4.0.1.tgz", - "integrity": "sha512-Qush0uP+G8ZScpGMZvHUiRfI0YBWuB3gVBYlI0v0vvOJt5FLicco+IkP0a50LqTTQhmts/m6tP5SWE+USyIvcQ==", - "license": "MIT", - "engines": { - "node": ">=12.20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/jwt-decode": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-4.0.0.tgz", - "integrity": "sha512-+KJGIyHgkGuIq3IEBNftfhW/LfWhXUIY6OmyVWjliu5KH1y0fw7VQ8YndE2O4qZdMSd9SqbnC8GOcZEy0Om7sA==", - "license": "MIT", - "engines": { - "node": ">=18" - } - }, "node_modules/katex": { "version": "0.16.22", "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.22.tgz", @@ -6636,50 +7407,6 @@ "integrity": "sha512-xYSH7AvuQ6nXkq42x0v5S8/Iry+cfulBz/DJQzhIyESdLD7425jXsPy4vn5cCXU+HhRN2kVw51Vd1K6/By4BQg==", "license": "MIT" }, - "node_modules/kuler": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz", - "integrity": "sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==", - "license": "MIT" - }, - "node_modules/lambda-local": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/lambda-local/-/lambda-local-2.2.0.tgz", - "integrity": "sha512-bPcgpIXbHnVGfI/omZIlgucDqlf4LrsunwoKue5JdZeGybt8L6KyJz2Zu19ffuZwIwLj2NAI2ZyaqNT6/cetcg==", - "license": "MIT", - "dependencies": { - "commander": "^10.0.1", - "dotenv": "^16.3.1", - "winston": "^3.10.0" - }, - "bin": { - "lambda-local": "build/cli.js" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/lambda-local/node_modules/commander": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", - "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", - "license": "MIT", - "engines": { - "node": ">=14" - } - }, - "node_modules/lambda-local/node_modules/dotenv": { - "version": "16.6.1", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz", - "integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==", - "license": "BSD-2-Clause", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://dotenvx.com" - } - }, "node_modules/launch-editor": { "version": "2.11.1", "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.11.1.tgz", @@ -6818,21 +7545,6 @@ "url": "https://github.com/sponsors/antfu" } }, - "node_modules/locate-path": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-7.2.0.tgz", - "integrity": "sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==", - "license": "MIT", - "dependencies": { - "p-locate": "^6.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", @@ -6845,12 +7557,6 @@ "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==", "license": "MIT" }, - "node_modules/lodash.debounce": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", - "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", - "license": "MIT" - }, "node_modules/lodash.defaults": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", @@ -6875,23 +7581,6 @@ "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==", "license": "MIT" }, - "node_modules/logform": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/logform/-/logform-2.7.0.tgz", - "integrity": "sha512-TFYA4jnP7PVbmlBIfhlSe+WKxs9dklXMTEGcBCIvLhE/Tn3H6Gk1norupVW7m5Cnd4bLcr08AytbyV/xj7f/kQ==", - "license": "MIT", - "dependencies": { - "@colors/colors": "1.6.0", - "@types/triple-beam": "^1.3.2", - "fecha": "^4.2.0", - "ms": "^2.1.1", - "safe-stable-stringify": "^2.3.1", - "triple-beam": "^1.3.0" - }, - "engines": { - "node": ">= 12.0.0" - } - }, "node_modules/lru-cache": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", @@ -6901,15 +7590,6 @@ "yallist": "^3.0.2" } }, - "node_modules/luxon": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/luxon/-/luxon-3.7.1.tgz", - "integrity": "sha512-RkRWjA926cTvz5rAb1BqyWkKbbjzCGchDUIKMCUvNi17j6f6j8uHGDV82Aqcqtzd+icoYpELmG3ksgGiFNNcNg==", - "license": "MIT", - "engines": { - "node": ">=12" - } - }, "node_modules/magic-regexp": { "version": "0.10.0", "resolved": "https://registry.npmjs.org/magic-regexp/-/magic-regexp-0.10.0.tgz", @@ -6926,9 +7606,9 @@ } }, "node_modules/magic-string": { - "version": "0.30.18", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.18.tgz", - "integrity": "sha512-yi8swmWbO17qHhwIBNeeZxTceJMeBvWJaId6dyvTSOwTipqeHhMhOrz6513r1sOKnpvQ7zkhlG8tPrpilwTxHQ==", + "version": "0.30.19", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.19.tgz", + "integrity": "sha512-2N21sPY9Ws53PZvsEpVtNuSW+ScYbQdp4b9qUaL+9QkHUrGFKo56Lg9Emg5s9V/qrtNBmiR01sYhUOwu3H+VOw==", "license": "MIT", "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" @@ -6977,15 +7657,6 @@ "markdown-it": "bin/markdown-it.mjs" } }, - "node_modules/math-intrinsics": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", - "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, "node_modules/mdast-util-from-markdown": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-1.3.1.tgz", @@ -7035,18 +7706,6 @@ "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==", "license": "MIT" }, - "node_modules/merge-options": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/merge-options/-/merge-options-3.0.4.tgz", - "integrity": "sha512-2Sug1+knBjkaMsMgf1ctR1Ujx+Ayku4EdJN4Z+C2+JzoeF7A3OZ9KM2GY0CpQS51NR61LTurMJrRKPhSs3ZRTQ==", - "license": "MIT", - "dependencies": { - "is-plain-obj": "^2.1.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", @@ -7090,12 +7749,6 @@ "web-worker": "^1.2.0" } }, - "node_modules/micro-api-client": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/micro-api-client/-/micro-api-client-3.3.0.tgz", - "integrity": "sha512-y0y6CUB9RLVsy3kfgayU28746QrNMpSm9O/AYGNsBgOkJr/X/Jk0VLGoO8Ude7Bpa8adywzF+MzXNZRFRsNPhg==", - "license": "ISC" - }, "node_modules/micromark": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/micromark/-/micromark-3.2.0.tgz", @@ -7552,9 +8205,9 @@ } }, "node_modules/mime": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/mime/-/mime-4.0.7.tgz", - "integrity": "sha512-2OfDPL+e03E0LrXaGYOtTFIYhiuzep94NSsuhrNULq+stylcJedcHdzHtz0atMUuGwJfFYs0YL5xeC/Ca2x0eQ==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-4.1.0.tgz", + "integrity": "sha512-X5ju04+cAzsojXKes0B/S4tcYtFAJ6tTMuSPBEn9CPGlrWr8Fiw7qYeLT0XyH80HSoAoqWCaz+MWKh22P7G1cw==", "funding": [ "https://github.com/sponsors/broofa" ], @@ -7632,6 +8285,7 @@ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", "license": "MIT", + "optional": true, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -7664,18 +8318,13 @@ "license": "MIT" }, "node_modules/mkdirp": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz", - "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==", - "license": "MIT", - "bin": { - "mkdirp": "dist/cjs/src/bin.js" - }, + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.0.tgz", + "integrity": "sha512-OHsdUcVAQ6pOtg5JYWpCBo9W/GySVuwvP9hueRMW7UqshC0tbfzLv8wjySTPm3tfUZ/21CE9E1pJagOA91Pxew==", + "deprecated": "Legacy versions of mkdirp are no longer supported. Please update to mkdirp 1.x. (Note that the API surface has changed to use Promises in 1.x.)", + "license": "MIT/X11", "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": "*" } }, "node_modules/mkdirp-classic": { @@ -7720,22 +8369,6 @@ "integrity": "sha512-aF7yRQr/Q0O2/4pIXm6PZ5G+jAd7QS4Yu8m+WEeEHGnbo+7mE36CbLSDQiXYV8bVL3NfmdeqPJct0tUlnjVSnA==", "license": "MIT" }, - "node_modules/module-definition": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/module-definition/-/module-definition-6.0.1.tgz", - "integrity": "sha512-FeVc50FTfVVQnolk/WQT8MX+2WVcDnTGiq6Wo+/+lJ2ET1bRVi3HG3YlJUfqagNMc/kUlFSoR96AJkxGpKz13g==", - "license": "MIT", - "dependencies": { - "ast-module-types": "^6.0.1", - "node-source-walk": "^7.0.1" - }, - "bin": { - "module-definition": "bin/cli.js" - }, - "engines": { - "node": ">=18" - } - }, "node_modules/mri": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz", @@ -7768,7 +8401,7 @@ }, "node_modules/nanoid": { "version": "5.1.5", - "resolved": "https://registry.npmmirror.com/nanoid/-/nanoid-5.1.5.tgz", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.1.5.tgz", "integrity": "sha512-Ir/+ZpE9fDsNH0hQ3C68uyThDXzYcim2EqcZ8zn8Chtt1iylPT9xXJB0kPCnqzgcEGikO9RxSrh63MsmVCU7Fw==", "funding": [ { @@ -7797,49 +8430,13 @@ "license": "MIT", "optional": true }, - "node_modules/netlify": { - "version": "13.3.5", - "resolved": "https://registry.npmjs.org/netlify/-/netlify-13.3.5.tgz", - "integrity": "sha512-Nc3loyVASW59W+8fLDZT1lncpG7llffyZ2o0UQLx/Fr20i7P8oP+lE7+TEcFvXj9IUWU6LjB9P3BH+iFGyp+mg==", - "license": "MIT", - "dependencies": { - "@netlify/open-api": "^2.37.0", - "lodash-es": "^4.17.21", - "micro-api-client": "^3.3.0", - "node-fetch": "^3.0.0", - "p-wait-for": "^5.0.0", - "qs": "^6.9.6" - }, - "engines": { - "node": "^14.16.0 || >=16.0.0" - } - }, - "node_modules/netlify/node_modules/node-fetch": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", - "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", - "license": "MIT", - "dependencies": { - "data-uri-to-buffer": "^4.0.0", - "fetch-blob": "^3.1.4", - "formdata-polyfill": "^4.0.10" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/node-fetch" - } - }, "node_modules/nitropack": { - "version": "2.12.4", - "resolved": "https://registry.npmjs.org/nitropack/-/nitropack-2.12.4.tgz", - "integrity": "sha512-MPmPRJWTeH03f/NmpN4q3iI3Woik4uaaWIoX34W3gMJiW06Vm1te/lPzuu5EXpXOK7Q2m3FymGMPXcExqih96Q==", + "version": "2.12.6", + "resolved": "https://registry.npmjs.org/nitropack/-/nitropack-2.12.6.tgz", + "integrity": "sha512-DEq31s0SP4/Z5DIoVBRo9DbWFPWwIoYD4cQMEz7eE+iJMiAP+1k9A3B9kcc6Ihc0jDJmfUcHYyh6h2XlynCx6g==", "license": "MIT", "dependencies": { "@cloudflare/kv-asset-handler": "^0.4.0", - "@netlify/functions": "^3.1.10", "@rollup/plugin-alias": "^5.1.1", "@rollup/plugin-commonjs": "^28.0.6", "@rollup/plugin-inject": "^5.0.5", @@ -7847,9 +8444,9 @@ "@rollup/plugin-node-resolve": "^16.0.1", "@rollup/plugin-replace": "^6.0.2", "@rollup/plugin-terser": "^0.4.4", - "@vercel/nft": "^0.29.4", + "@vercel/nft": "^0.30.1", "archiver": "^7.0.1", - "c12": "^3.1.0", + "c12": "^3.2.0", "chokidar": "^4.0.3", "citty": "^0.1.6", "compatx": "^0.2.0", @@ -7862,52 +8459,52 @@ "defu": "^6.1.4", "destr": "^2.0.5", "dot-prop": "^9.0.0", - "esbuild": "^0.25.6", + "esbuild": "^0.25.9", "escape-string-regexp": "^5.0.0", "etag": "^1.8.1", "exsolve": "^1.0.7", "globby": "^14.1.0", "gzip-size": "^7.0.0", - "h3": "^1.15.3", + "h3": "^1.15.4", "hookable": "^5.5.3", "httpxy": "^0.1.7", - "ioredis": "^5.6.1", - "jiti": "^2.4.2", + "ioredis": "^5.7.0", + "jiti": "^2.5.1", "klona": "^2.0.6", "knitwork": "^1.2.0", "listhen": "^1.9.0", - "magic-string": "^0.30.17", + "magic-string": "^0.30.19", "magicast": "^0.3.5", "mime": "^4.0.7", - "mlly": "^1.7.4", - "node-fetch-native": "^1.6.6", - "node-mock-http": "^1.0.1", + "mlly": "^1.8.0", + "node-fetch-native": "^1.6.7", + "node-mock-http": "^1.0.3", "ofetch": "^1.4.1", "ohash": "^2.0.11", "pathe": "^2.0.3", - "perfect-debounce": "^1.0.0", - "pkg-types": "^2.2.0", - "pretty-bytes": "^6.1.1", + "perfect-debounce": "^2.0.0", + "pkg-types": "^2.3.0", + "pretty-bytes": "^7.0.1", "radix3": "^1.1.2", - "rollup": "^4.45.0", + "rollup": "^4.50.1", "rollup-plugin-visualizer": "^6.0.3", "scule": "^1.3.0", "semver": "^7.7.2", "serve-placeholder": "^2.0.2", "serve-static": "^2.2.0", - "source-map": "^0.7.4", + "source-map": "^0.7.6", "std-env": "^3.9.0", "ufo": "^1.6.1", "ultrahtml": "^1.6.0", "uncrypto": "^0.1.3", "unctx": "^2.4.1", - "unenv": "^2.0.0-rc.18", - "unimport": "^5.1.0", - "unplugin-utils": "^0.2.4", - "unstorage": "^1.16.1", + "unenv": "^2.0.0-rc.21", + "unimport": "^5.2.0", + "unplugin-utils": "^0.3.0", + "unstorage": "^1.17.1", "untyped": "^2.0.0", - "unwasm": "^0.3.9", - "youch": "4.1.0-beta.8", + "unwasm": "^0.3.11", + "youch": "^4.1.0-beta.11", "youch-core": "^0.3.3" }, "bin": { @@ -7915,7 +8512,7 @@ "nitropack": "dist/cli/index.mjs" }, "engines": { - "node": "^16.11.0 || >=17.0.0" + "node": "^20.19.0 || >=22.12.0" }, "peerDependencies": { "xml2js": "^0.6.2" @@ -7932,26 +8529,44 @@ "integrity": "sha512-RAj4E421UYRgqokKUmotqAwuplYw15qtdXfY+hGzgCJ/MBjCVZcSoHK/kH9kocfjRjcDME7IiDWR/1WX1TM2Pg==", "license": "MIT" }, - "node_modules/nitropack/node_modules/youch": { - "version": "4.1.0-beta.8", - "resolved": "https://registry.npmjs.org/youch/-/youch-4.1.0-beta.8.tgz", - "integrity": "sha512-rY2A2lSF7zC+l7HH9Mq+83D1dLlsPnEvy8jTouzaptDZM6geqZ3aJe/b7ULCwRURPtWV3vbDjA2DDMdoBol0HQ==", + "node_modules/nitropack/node_modules/perfect-debounce": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-2.0.0.tgz", + "integrity": "sha512-fkEH/OBiKrqqI/yIgjR92lMfs2K8105zt/VT6+7eTjNwisrsh47CeIED9z58zI7DfKdH3uHAn25ziRZn3kgAow==", + "license": "MIT" + }, + "node_modules/nitropack/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/nitropack/node_modules/unplugin-utils": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/unplugin-utils/-/unplugin-utils-0.3.0.tgz", + "integrity": "sha512-JLoggz+PvLVMJo+jZt97hdIIIZ2yTzGgft9e9q8iMrC4ewufl62ekeW7mixBghonn2gVb/ICjyvlmOCUBnJLQg==", "license": "MIT", "dependencies": { - "@poppinss/colors": "^4.1.4", - "@poppinss/dumper": "^0.6.3", - "@speed-highlight/core": "^1.2.7", - "cookie": "^1.0.2", - "youch-core": "^0.3.1" + "pathe": "^2.0.3", + "picomatch": "^4.0.3" }, "engines": { - "node": ">=18" + "node": ">=20.19.0" + }, + "funding": { + "url": "https://github.com/sponsors/sxzz" } }, "node_modules/node-abi": { - "version": "3.75.0", - "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.75.0.tgz", - "integrity": "sha512-OhYaY5sDsIka7H7AtijtI9jwGYLyl29eQn/W623DiN/MIv5sUqc4g7BIDThX+gb7di9f6xK02nkp8sdfFWZLTg==", + "version": "3.77.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.77.0.tgz", + "integrity": "sha512-DSmt0OEcLoK4i3NuscSbGjOf3bqiDEutejqENSplMSFA/gmB8mkED9G4pKWnPl7MDU4rSHebKPHeitpDfyH0cQ==", "license": "MIT", "optional": true, "dependencies": { @@ -7967,26 +8582,6 @@ "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", "license": "MIT" }, - "node_modules/node-domexception": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", - "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", - "deprecated": "Use your platform's native DOMException instead", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/jimmywarting" - }, - { - "type": "github", - "url": "https://paypal.me/jimmywarting" - } - ], - "license": "MIT", - "engines": { - "node": ">=10.5.0" - } - }, "node_modules/node-fetch": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", @@ -8034,29 +8629,17 @@ } }, "node_modules/node-mock-http": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/node-mock-http/-/node-mock-http-1.0.2.tgz", - "integrity": "sha512-zWaamgDUdo9SSLw47we78+zYw/bDr5gH8pH7oRRs8V3KmBtu8GLgGIbV2p/gRPd3LWpEOpjQj7X1FOU3VFMJ8g==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/node-mock-http/-/node-mock-http-1.0.3.tgz", + "integrity": "sha512-jN8dK25fsfnMrVsEhluUTPkBFY+6ybu7jSB1n+ri/vOGjJxU8J9CZhpSGkHXSkFjtUhbmoncG/YG9ta5Ludqog==", "license": "MIT" }, "node_modules/node-releases": { - "version": "2.0.19", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", - "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", + "version": "2.0.21", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.21.tgz", + "integrity": "sha512-5b0pgg78U3hwXkCM8Z9b2FJdPZlr9Psr9V2gQPESdGHqbntyFJKFW4r5TeWGFzafGY3hzs1JC62VEQMbl1JFkw==", "license": "MIT" }, - "node_modules/node-source-walk": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/node-source-walk/-/node-source-walk-7.0.1.tgz", - "integrity": "sha512-3VW/8JpPqPvnJvseXowjZcirPisssnBuDikk6JIZ8jQzF7KJQX52iPFX4RYYxLycYH7IbMRSPUOga/esVjy5Yg==", - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.26.7" - }, - "engines": { - "node": ">=18" - } - }, "node_modules/non-layered-tidy-tree-layout": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/non-layered-tidy-tree-layout/-/non-layered-tidy-tree-layout-2.0.2.tgz", @@ -8064,32 +8647,18 @@ "license": "MIT" }, "node_modules/nopt": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-8.1.0.tgz", - "integrity": "sha512-ieGu42u/Qsa4TFktmaKEwM6MQH0pOWnaB3htzh0JRtx84+Mebc0cbZYN5bC+6WTZ4+77xrL9Pn5m7CV6VIkV7A==", - "license": "ISC", + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", + "integrity": "sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==", + "license": "MIT", "dependencies": { - "abbrev": "^3.0.0" + "abbrev": "1" }, "bin": { "nopt": "bin/nopt.js" }, "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/normalize-package-data": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-6.0.2.tgz", - "integrity": "sha512-V6gygoYb/5EmNI+MEGrWkC+e6+Rr7mTmfHrxDbLzxQogBkgzo76rkok0Am6thgSF7Mv2nLOajAJj5vDJZEFn7g==", - "license": "BSD-2-Clause", - "dependencies": { - "hosted-git-info": "^7.0.0", - "semver": "^7.3.5", - "validate-npm-package-license": "^3.0.4" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" + "node": "*" } }, "node_modules/normalize-path": { @@ -8156,20 +8725,20 @@ } }, "node_modules/nuxt": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/nuxt/-/nuxt-4.0.3.tgz", - "integrity": "sha512-skRFoxY/1nphk+viF5ZEDLNEMJse0J/U5+wAYtJfYQ86EcEpLMm9v78FwdCc5IioKpgmSda6ZlLxY1DgK+6SDw==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/nuxt/-/nuxt-4.1.2.tgz", + "integrity": "sha512-g5mwszCZT4ZeGJm83nxoZvtvZoAEaY65VDdn7p7UgznePbRaEJJ1KS1OIld4FPVkoDZ8TEVuDNqI9gUn12Exvg==", "license": "MIT", "dependencies": { - "@nuxt/cli": "^3.27.0", + "@nuxt/cli": "^3.28.0", "@nuxt/devalue": "^2.0.2", - "@nuxt/devtools": "^2.6.2", - "@nuxt/kit": "4.0.3", - "@nuxt/schema": "4.0.3", + "@nuxt/devtools": "^2.6.3", + "@nuxt/kit": "4.1.2", + "@nuxt/schema": "4.1.2", "@nuxt/telemetry": "^2.6.6", - "@nuxt/vite-builder": "4.0.3", - "@unhead/vue": "^2.0.13", - "@vue/shared": "^3.5.18", + "@nuxt/vite-builder": "4.1.2", + "@unhead/vue": "^2.0.14", + "@vue/shared": "^3.5.21", "c12": "^3.2.0", "chokidar": "^4.0.3", "compatx": "^0.2.0", @@ -8177,9 +8746,9 @@ "cookie-es": "^2.0.0", "defu": "^6.1.4", "destr": "^2.0.5", - "devalue": "^5.1.1", + "devalue": "^5.3.2", "errx": "^0.1.0", - "esbuild": "^0.25.8", + "esbuild": "^0.25.9", "escape-string-regexp": "^5.0.0", "estree-walker": "^3.0.3", "exsolve": "^1.0.7", @@ -8190,38 +8759,37 @@ "jiti": "^2.5.1", "klona": "^2.0.6", "knitwork": "^1.2.0", - "magic-string": "^0.30.17", - "mlly": "^1.7.4", + "magic-string": "^0.30.19", + "mlly": "^1.8.0", "mocked-exports": "^0.1.1", "nanotar": "^0.2.0", - "nitropack": "^2.12.4", + "nitropack": "^2.12.5", "nypm": "^0.6.1", "ofetch": "^1.4.1", "ohash": "^2.0.11", "on-change": "^5.0.1", - "oxc-minify": "^0.80.0", - "oxc-parser": "^0.80.0", - "oxc-transform": "^0.80.0", - "oxc-walker": "^0.4.0", + "oxc-minify": "^0.87.0", + "oxc-parser": "^0.87.0", + "oxc-transform": "^0.87.0", + "oxc-walker": "^0.5.2", "pathe": "^2.0.3", - "perfect-debounce": "^1.0.0", - "pkg-types": "^2.2.0", + "perfect-debounce": "^2.0.0", + "pkg-types": "^2.3.0", "radix3": "^1.1.2", "scule": "^1.3.0", "semver": "^7.7.2", "std-env": "^3.9.0", - "strip-literal": "^3.0.0", - "tinyglobby": "0.2.14", + "tinyglobby": "^0.2.15", "ufo": "^1.6.1", "ultrahtml": "^1.6.0", "uncrypto": "^0.1.3", "unctx": "^2.4.1", "unimport": "^5.2.0", - "unplugin": "^2.3.5", + "unplugin": "^2.3.10", "unplugin-vue-router": "^0.15.0", - "unstorage": "^1.16.1", + "unstorage": "^1.17.1", "untyped": "^2.0.0", - "vue": "^3.5.18", + "vue": "^3.5.21", "vue-bundle-renderer": "^2.1.2", "vue-devtools-stub": "^0.1.0", "vue-router": "^4.5.1" @@ -8247,9 +8815,9 @@ } }, "node_modules/nuxt/node_modules/@nuxt/kit": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/@nuxt/kit/-/kit-4.0.3.tgz", - "integrity": "sha512-9+lwvP4n8KhO91azoebO0o39smESGzEV4HU6nef9HIFyt04YwlVMY37Pk63GgZn0WhWVjyPWcQWs0rUdZUYcPw==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/@nuxt/kit/-/kit-4.1.2.tgz", + "integrity": "sha512-P5q41xeEOa6ZQC0PvIP7TSBmOAMxXK4qihDcCbYIJq8RcVsEPbGZVlidmxE6EOw1ucSyodq9nbV31FAKwoL4NQ==", "license": "MIT", "dependencies": { "c12": "^3.2.0", @@ -8261,14 +8829,15 @@ "ignore": "^7.0.5", "jiti": "^2.5.1", "klona": "^2.0.6", - "mlly": "^1.7.4", + "mlly": "^1.8.0", "ohash": "^2.0.11", "pathe": "^2.0.3", - "pkg-types": "^2.2.0", + "pkg-types": "^2.3.0", + "rc9": "^2.1.2", "scule": "^1.3.0", "semver": "^7.7.2", "std-env": "^3.9.0", - "tinyglobby": "^0.2.14", + "tinyglobby": "^0.2.15", "ufo": "^1.6.1", "unctx": "^2.4.1", "unimport": "^5.2.0", @@ -8284,6 +8853,12 @@ "integrity": "sha512-RAj4E421UYRgqokKUmotqAwuplYw15qtdXfY+hGzgCJ/MBjCVZcSoHK/kH9kocfjRjcDME7IiDWR/1WX1TM2Pg==", "license": "MIT" }, + "node_modules/nuxt/node_modules/perfect-debounce": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-2.0.0.tgz", + "integrity": "sha512-fkEH/OBiKrqqI/yIgjR92lMfs2K8105zt/VT6+7eTjNwisrsh47CeIED9z58zI7DfKdH3uHAn25ziRZn3kgAow==", + "license": "MIT" + }, "node_modules/nypm": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/nypm/-/nypm-0.6.1.tgz", @@ -8303,18 +8878,6 @@ "node": "^14.16.0 || >=16.10.0" } }, - "node_modules/object-inspect": { - "version": "1.13.4", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", - "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/ofetch": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/ofetch/-/ofetch-1.4.1.tgz", @@ -8361,19 +8924,11 @@ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", "license": "ISC", + "optional": true, "dependencies": { "wrappy": "1" } }, - "node_modules/one-time": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/one-time/-/one-time-1.0.0.tgz", - "integrity": "sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==", - "license": "MIT", - "dependencies": { - "fn.name": "1.x.x" - } - }, "node_modules/onetime": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", @@ -8434,9 +8989,9 @@ } }, "node_modules/oxc-minify": { - "version": "0.80.0", - "resolved": "https://registry.npmjs.org/oxc-minify/-/oxc-minify-0.80.0.tgz", - "integrity": "sha512-kMMb3dC8KlQ+Bzf/UhepYsq1ukorCOJu038rSxF7kTbsCLx1Ojet9Hc9gKqKR/Wpih5GWnOA2DvLe20ZtxbJ2Q==", + "version": "0.87.0", + "resolved": "https://registry.npmjs.org/oxc-minify/-/oxc-minify-0.87.0.tgz", + "integrity": "sha512-+UHWp6+0mdq0S2rEsZx9mqgL6JnG9ogO+CU17XccVrPUFtISFcZzk/biTn1JdBYFQ3kztof19pv8blMtgStQ2g==", "license": "MIT", "engines": { "node": ">=14.0.0" @@ -8445,30 +9000,30 @@ "url": "https://github.com/sponsors/Boshen" }, "optionalDependencies": { - "@oxc-minify/binding-android-arm64": "0.80.0", - "@oxc-minify/binding-darwin-arm64": "0.80.0", - "@oxc-minify/binding-darwin-x64": "0.80.0", - "@oxc-minify/binding-freebsd-x64": "0.80.0", - "@oxc-minify/binding-linux-arm-gnueabihf": "0.80.0", - "@oxc-minify/binding-linux-arm-musleabihf": "0.80.0", - "@oxc-minify/binding-linux-arm64-gnu": "0.80.0", - "@oxc-minify/binding-linux-arm64-musl": "0.80.0", - "@oxc-minify/binding-linux-riscv64-gnu": "0.80.0", - "@oxc-minify/binding-linux-s390x-gnu": "0.80.0", - "@oxc-minify/binding-linux-x64-gnu": "0.80.0", - "@oxc-minify/binding-linux-x64-musl": "0.80.0", - "@oxc-minify/binding-wasm32-wasi": "0.80.0", - "@oxc-minify/binding-win32-arm64-msvc": "0.80.0", - "@oxc-minify/binding-win32-x64-msvc": "0.80.0" + "@oxc-minify/binding-android-arm64": "0.87.0", + "@oxc-minify/binding-darwin-arm64": "0.87.0", + "@oxc-minify/binding-darwin-x64": "0.87.0", + "@oxc-minify/binding-freebsd-x64": "0.87.0", + "@oxc-minify/binding-linux-arm-gnueabihf": "0.87.0", + "@oxc-minify/binding-linux-arm-musleabihf": "0.87.0", + "@oxc-minify/binding-linux-arm64-gnu": "0.87.0", + "@oxc-minify/binding-linux-arm64-musl": "0.87.0", + "@oxc-minify/binding-linux-riscv64-gnu": "0.87.0", + "@oxc-minify/binding-linux-s390x-gnu": "0.87.0", + "@oxc-minify/binding-linux-x64-gnu": "0.87.0", + "@oxc-minify/binding-linux-x64-musl": "0.87.0", + "@oxc-minify/binding-wasm32-wasi": "0.87.0", + "@oxc-minify/binding-win32-arm64-msvc": "0.87.0", + "@oxc-minify/binding-win32-x64-msvc": "0.87.0" } }, "node_modules/oxc-parser": { - "version": "0.80.0", - "resolved": "https://registry.npmjs.org/oxc-parser/-/oxc-parser-0.80.0.tgz", - "integrity": "sha512-lTEUQs+WBOXPUzMR/tWY4yT9D7xXwnENtRR7Epw/QcuYpV4fRveEA+zq8IGUwyyuWecl8jHrddCCuadw+kZOSA==", + "version": "0.87.0", + "resolved": "https://registry.npmjs.org/oxc-parser/-/oxc-parser-0.87.0.tgz", + "integrity": "sha512-uc47XrtHwkBoES4HFgwgfH9sqwAtJXgAIBq4fFBMZ4hWmgVZoExyn+L4g4VuaecVKXkz1bvlaHcfwHAJPQb5Gw==", "license": "MIT", "dependencies": { - "@oxc-project/types": "^0.80.0" + "@oxc-project/types": "^0.87.0" }, "engines": { "node": ">=20.0.0" @@ -8477,27 +9032,27 @@ "url": "https://github.com/sponsors/Boshen" }, "optionalDependencies": { - "@oxc-parser/binding-android-arm64": "0.80.0", - "@oxc-parser/binding-darwin-arm64": "0.80.0", - "@oxc-parser/binding-darwin-x64": "0.80.0", - "@oxc-parser/binding-freebsd-x64": "0.80.0", - "@oxc-parser/binding-linux-arm-gnueabihf": "0.80.0", - "@oxc-parser/binding-linux-arm-musleabihf": "0.80.0", - "@oxc-parser/binding-linux-arm64-gnu": "0.80.0", - "@oxc-parser/binding-linux-arm64-musl": "0.80.0", - "@oxc-parser/binding-linux-riscv64-gnu": "0.80.0", - "@oxc-parser/binding-linux-s390x-gnu": "0.80.0", - "@oxc-parser/binding-linux-x64-gnu": "0.80.0", - "@oxc-parser/binding-linux-x64-musl": "0.80.0", - "@oxc-parser/binding-wasm32-wasi": "0.80.0", - "@oxc-parser/binding-win32-arm64-msvc": "0.80.0", - "@oxc-parser/binding-win32-x64-msvc": "0.80.0" + "@oxc-parser/binding-android-arm64": "0.87.0", + "@oxc-parser/binding-darwin-arm64": "0.87.0", + "@oxc-parser/binding-darwin-x64": "0.87.0", + "@oxc-parser/binding-freebsd-x64": "0.87.0", + "@oxc-parser/binding-linux-arm-gnueabihf": "0.87.0", + "@oxc-parser/binding-linux-arm-musleabihf": "0.87.0", + "@oxc-parser/binding-linux-arm64-gnu": "0.87.0", + "@oxc-parser/binding-linux-arm64-musl": "0.87.0", + "@oxc-parser/binding-linux-riscv64-gnu": "0.87.0", + "@oxc-parser/binding-linux-s390x-gnu": "0.87.0", + "@oxc-parser/binding-linux-x64-gnu": "0.87.0", + "@oxc-parser/binding-linux-x64-musl": "0.87.0", + "@oxc-parser/binding-wasm32-wasi": "0.87.0", + "@oxc-parser/binding-win32-arm64-msvc": "0.87.0", + "@oxc-parser/binding-win32-x64-msvc": "0.87.0" } }, "node_modules/oxc-transform": { - "version": "0.80.0", - "resolved": "https://registry.npmjs.org/oxc-transform/-/oxc-transform-0.80.0.tgz", - "integrity": "sha512-hWusSpynsn4MZP1KJa7e254xyVmowTUshvttpk7JfTt055YEJ+ad6memMJ9GJqPeeyydfnwwKkLy6eiwDn12xA==", + "version": "0.87.0", + "resolved": "https://registry.npmjs.org/oxc-transform/-/oxc-transform-0.87.0.tgz", + "integrity": "sha512-dt6INKWY2DKbSc8yR9VQoqBsCjPQ3z/SKv882UqlwFve+K38xtpi2avDlvNd35SpHUwDLDFoV3hMX0U3qOSaaQ==", "license": "MIT", "engines": { "node": ">=14.0.0" @@ -8506,120 +9061,35 @@ "url": "https://github.com/sponsors/Boshen" }, "optionalDependencies": { - "@oxc-transform/binding-android-arm64": "0.80.0", - "@oxc-transform/binding-darwin-arm64": "0.80.0", - "@oxc-transform/binding-darwin-x64": "0.80.0", - "@oxc-transform/binding-freebsd-x64": "0.80.0", - "@oxc-transform/binding-linux-arm-gnueabihf": "0.80.0", - "@oxc-transform/binding-linux-arm-musleabihf": "0.80.0", - "@oxc-transform/binding-linux-arm64-gnu": "0.80.0", - "@oxc-transform/binding-linux-arm64-musl": "0.80.0", - "@oxc-transform/binding-linux-riscv64-gnu": "0.80.0", - "@oxc-transform/binding-linux-s390x-gnu": "0.80.0", - "@oxc-transform/binding-linux-x64-gnu": "0.80.0", - "@oxc-transform/binding-linux-x64-musl": "0.80.0", - "@oxc-transform/binding-wasm32-wasi": "0.80.0", - "@oxc-transform/binding-win32-arm64-msvc": "0.80.0", - "@oxc-transform/binding-win32-x64-msvc": "0.80.0" + "@oxc-transform/binding-android-arm64": "0.87.0", + "@oxc-transform/binding-darwin-arm64": "0.87.0", + "@oxc-transform/binding-darwin-x64": "0.87.0", + "@oxc-transform/binding-freebsd-x64": "0.87.0", + "@oxc-transform/binding-linux-arm-gnueabihf": "0.87.0", + "@oxc-transform/binding-linux-arm-musleabihf": "0.87.0", + "@oxc-transform/binding-linux-arm64-gnu": "0.87.0", + "@oxc-transform/binding-linux-arm64-musl": "0.87.0", + "@oxc-transform/binding-linux-riscv64-gnu": "0.87.0", + "@oxc-transform/binding-linux-s390x-gnu": "0.87.0", + "@oxc-transform/binding-linux-x64-gnu": "0.87.0", + "@oxc-transform/binding-linux-x64-musl": "0.87.0", + "@oxc-transform/binding-wasm32-wasi": "0.87.0", + "@oxc-transform/binding-win32-arm64-msvc": "0.87.0", + "@oxc-transform/binding-win32-x64-msvc": "0.87.0" } }, "node_modules/oxc-walker": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/oxc-walker/-/oxc-walker-0.4.0.tgz", - "integrity": "sha512-x5TJAZQD3kRnRBGZ+8uryMZUwkTYddwzBftkqyJIcmpBOXmoK/fwriRKATjZroR2d+aS7+2w1B0oz189bBTwfw==", + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/oxc-walker/-/oxc-walker-0.5.2.tgz", + "integrity": "sha512-XYoZqWwApSKUmSDEFeOKdy3Cdh95cOcSU8f7yskFWE4Rl3cfL5uwyY+EV7Brk9mdNLy+t5SseJajd6g7KncvlA==", "license": "MIT", "dependencies": { - "estree-walker": "^3.0.3", "magic-regexp": "^0.10.0" }, "peerDependencies": { "oxc-parser": ">=0.72.0" } }, - "node_modules/p-event": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/p-event/-/p-event-6.0.1.tgz", - "integrity": "sha512-Q6Bekk5wpzW5qIyUP4gdMEujObYstZl6DMMOSenwBvV0BlE5LkDwkjs5yHbZmdCEq2o4RJx4tE1vwxFVf2FG1w==", - "license": "MIT", - "dependencies": { - "p-timeout": "^6.1.2" - }, - "engines": { - "node": ">=16.17" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-limit": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz", - "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==", - "license": "MIT", - "dependencies": { - "yocto-queue": "^1.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-6.0.0.tgz", - "integrity": "sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==", - "license": "MIT", - "dependencies": { - "p-limit": "^4.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-map": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-7.0.3.tgz", - "integrity": "sha512-VkndIv2fIB99swvQoA65bm+fsmt6UNdGeIB0oxBs+WhAhdh08QA04JXpI7rbB9r08/nkbysKoya9rtDERYOYMA==", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-timeout": { - "version": "6.1.4", - "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-6.1.4.tgz", - "integrity": "sha512-MyIV3ZA/PmyBN/ud8vV9XzwTrNtR4jFrObymZYnZqMmW0zA8Z17vnT0rBgFE/TlohB+YCHqXMgZzb3Csp49vqg==", - "license": "MIT", - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-wait-for": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/p-wait-for/-/p-wait-for-5.0.2.tgz", - "integrity": "sha512-lwx6u1CotQYPVju77R+D0vFomni/AqRfqLmqQ8hekklqZ6gAY9rONh7lBQ0uxWMkC2AuX9b2DVAl8To0NyP1JA==", - "license": "MIT", - "dependencies": { - "p-timeout": "^6.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/package-json-from-dist": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", @@ -8632,32 +9102,6 @@ "integrity": "sha512-ZsEbbZORsyHuO00lY1kV3/t72yp6Ysay6Pd17ZAlNGuGwmWDLCJxFpRs0IzfXfj1o4icJOkUEioexFHzyPurSQ==", "license": "MIT" }, - "node_modules/parse-gitignore": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/parse-gitignore/-/parse-gitignore-2.0.0.tgz", - "integrity": "sha512-RmVuCHWsfu0QPNW+mraxh/xjQVw/lhUCUru8Zni3Ctq3AoMhpDTq0OVdKS6iesd6Kqb7viCV3isAL43dciOSog==", - "license": "MIT", - "engines": { - "node": ">=14" - } - }, - "node_modules/parse-json": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-8.3.0.tgz", - "integrity": "sha512-ybiGyvspI+fAoRQbIPRddCcSTV9/LsJbf0e/S85VLowVGzRmokfneg2kwVW/KU5rOXrPSbF1qAKPMgNTqqROQQ==", - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.26.2", - "index-to-position": "^1.1.0", - "type-fest": "^4.39.1" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/parse-path": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/parse-path/-/parse-path-7.1.0.tgz", @@ -8701,15 +9145,6 @@ "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", "license": "MIT" }, - "node_modules/path-exists": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz", - "integrity": "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==", - "license": "MIT", - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - } - }, "node_modules/path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", @@ -8765,12 +9200,6 @@ "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", "license": "MIT" }, - "node_modules/pend": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", - "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", - "license": "MIT" - }, "node_modules/perfect-debounce": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-1.0.0.tgz", @@ -9264,23 +9693,6 @@ "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", "license": "MIT" }, - "node_modules/postcss-values-parser": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/postcss-values-parser/-/postcss-values-parser-6.0.2.tgz", - "integrity": "sha512-YLJpK0N1brcNJrs9WatuJFtHaV9q5aAOj+S4DI5S7jgHlRfm0PIbDCAFRYMQD5SHq7Fy6xsDhyutgS0QOAs0qw==", - "license": "MPL-2.0", - "dependencies": { - "color-name": "^1.1.4", - "is-url-superb": "^4.0.0", - "quote-unquote": "^1.0.0" - }, - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "postcss": "^8.2.9" - } - }, "node_modules/postcss/node_modules/nanoid": { "version": "3.3.11", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", @@ -9388,51 +9800,13 @@ "node": ">=6" } }, - "node_modules/precinct": { - "version": "12.2.0", - "resolved": "https://registry.npmjs.org/precinct/-/precinct-12.2.0.tgz", - "integrity": "sha512-NFBMuwIfaJ4SocE9YXPU/n4AcNSoFMVFjP72nvl3cx69j/ke61/hPOWFREVxLkFhhEGnA8ZuVfTqJBa+PK3b5w==", - "license": "MIT", - "dependencies": { - "@dependents/detective-less": "^5.0.1", - "commander": "^12.1.0", - "detective-amd": "^6.0.1", - "detective-cjs": "^6.0.1", - "detective-es6": "^5.0.1", - "detective-postcss": "^7.0.1", - "detective-sass": "^6.0.1", - "detective-scss": "^5.0.1", - "detective-stylus": "^5.0.1", - "detective-typescript": "^14.0.0", - "detective-vue2": "^2.2.0", - "module-definition": "^6.0.1", - "node-source-walk": "^7.0.1", - "postcss": "^8.5.1", - "typescript": "^5.7.3" - }, - "bin": { - "precinct": "bin/cli.js" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/precinct/node_modules/commander": { - "version": "12.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", - "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", - "license": "MIT", - "engines": { - "node": ">=18" - } - }, "node_modules/pretty-bytes": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-6.1.1.tgz", - "integrity": "sha512-mQUvGU6aUFQ+rNvTIAcZuWGRT9a6f6Yrg9bHs4ImKF+HZCEK+plBvnAZYSIQztknZF2qnzNtr6F8s0+IuptdlQ==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-7.0.1.tgz", + "integrity": "sha512-285/jRCYIbMGDciDdrw0KPNC4LKEEwz/bwErcYNxSJOi4CpGUuLpb9gQpg3XJP0XYj9ldSRluXxih4lX2YN8Xw==", "license": "MIT", "engines": { - "node": "^14.13.1 || >=16.0.0" + "node": ">=20" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -9477,6 +9851,7 @@ "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.3.tgz", "integrity": "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==", "license": "MIT", + "optional": true, "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" @@ -9491,21 +9866,6 @@ "node": ">=6" } }, - "node_modules/qs": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", - "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", - "license": "BSD-3-Clause", - "dependencies": { - "side-channel": "^1.1.0" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/quansync": { "version": "0.2.11", "resolved": "https://registry.npmjs.org/quansync/-/quansync-0.2.11.tgz", @@ -9548,12 +9908,6 @@ ], "license": "MIT" }, - "node_modules/quote-unquote": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/quote-unquote/-/quote-unquote-1.0.0.tgz", - "integrity": "sha512-twwRO/ilhlG/FIgYeKGFqyHhoEhqgnKVkcmqMKi2r524gz3ZbDTcyFt38E9xjJI2vT+KbRNHVbnJ/e0I25Azwg==", - "license": "MIT" - }, "node_modules/radix3": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/radix3/-/radix3-1.1.2.tgz", @@ -9611,42 +9965,6 @@ "destr": "^2.0.3" } }, - "node_modules/read-package-up": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/read-package-up/-/read-package-up-11.0.0.tgz", - "integrity": "sha512-MbgfoNPANMdb4oRBNg5eqLbB2t2r+o5Ua1pNt8BqGp4I0FJZhuVSOj3PaBPni4azWuSzEdNn2evevzVmEk1ohQ==", - "license": "MIT", - "dependencies": { - "find-up-simple": "^1.0.0", - "read-pkg": "^9.0.0", - "type-fest": "^4.6.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/read-pkg": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-9.0.1.tgz", - "integrity": "sha512-9viLL4/n1BJUCT1NXVTdS1jtm80yDEgR5T4yCelII49Mbj0v1rZdKqj7zCiYdbB0CuCgdrvHcNogAKTFPBocFA==", - "license": "MIT", - "dependencies": { - "@types/normalize-package-data": "^2.4.3", - "normalize-package-data": "^6.0.0", - "parse-json": "^8.0.0", - "type-fest": "^4.6.0", - "unicorn-magic": "^0.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/readable-stream": { "version": "4.7.0", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.7.0.tgz", @@ -9727,12 +10045,6 @@ "regexp-tree": "bin/regexp-tree" } }, - "node_modules/remove-trailing-separator": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", - "integrity": "sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw==", - "license": "ISC" - }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -9742,12 +10054,6 @@ "node": ">=0.10.0" } }, - "node_modules/require-package-name": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/require-package-name/-/require-package-name-2.0.1.tgz", - "integrity": "sha512-uuoJ1hU/k6M0779t3VMVIYpb2VMJk05cehCaABFhXaibcbvfgR8wKiozLjVFSzJPmQMRqIcO0HMyTFqfV09V6Q==", - "license": "MIT" - }, "node_modules/requires-port": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", @@ -9755,18 +10061,21 @@ "license": "MIT" }, "node_modules/resolve": { - "version": "2.0.0-next.5", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz", - "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==", + "version": "1.22.10", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", + "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", "license": "MIT", "dependencies": { - "is-core-module": "^2.13.0", + "is-core-module": "^2.16.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" }, + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -9803,9 +10112,9 @@ "license": "Unlicense" }, "node_modules/rollup": { - "version": "4.49.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.49.0.tgz", - "integrity": "sha512-3IVq0cGJ6H7fKXXEdVt+RcYvRCt8beYY9K1760wGQwSAHZcS9eot1zDG5axUbcp/kWRi5zKIIDX8MoKv/TzvZA==", + "version": "4.50.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.50.1.tgz", + "integrity": "sha512-78E9voJHwnXQMiQdiqswVLZwJIzdBKJ1GdI5Zx6XwoFKUIk09/sSrr+05QFzvYb8q6Y9pPV45zzDuYa3907TZA==", "license": "MIT", "dependencies": { "@types/estree": "1.0.8" @@ -9818,26 +10127,27 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.49.0", - "@rollup/rollup-android-arm64": "4.49.0", - "@rollup/rollup-darwin-arm64": "4.49.0", - "@rollup/rollup-darwin-x64": "4.49.0", - "@rollup/rollup-freebsd-arm64": "4.49.0", - "@rollup/rollup-freebsd-x64": "4.49.0", - "@rollup/rollup-linux-arm-gnueabihf": "4.49.0", - "@rollup/rollup-linux-arm-musleabihf": "4.49.0", - "@rollup/rollup-linux-arm64-gnu": "4.49.0", - "@rollup/rollup-linux-arm64-musl": "4.49.0", - "@rollup/rollup-linux-loongarch64-gnu": "4.49.0", - "@rollup/rollup-linux-ppc64-gnu": "4.49.0", - "@rollup/rollup-linux-riscv64-gnu": "4.49.0", - "@rollup/rollup-linux-riscv64-musl": "4.49.0", - "@rollup/rollup-linux-s390x-gnu": "4.49.0", - "@rollup/rollup-linux-x64-gnu": "4.49.0", - "@rollup/rollup-linux-x64-musl": "4.49.0", - "@rollup/rollup-win32-arm64-msvc": "4.49.0", - "@rollup/rollup-win32-ia32-msvc": "4.49.0", - "@rollup/rollup-win32-x64-msvc": "4.49.0", + "@rollup/rollup-android-arm-eabi": "4.50.1", + "@rollup/rollup-android-arm64": "4.50.1", + "@rollup/rollup-darwin-arm64": "4.50.1", + "@rollup/rollup-darwin-x64": "4.50.1", + "@rollup/rollup-freebsd-arm64": "4.50.1", + "@rollup/rollup-freebsd-x64": "4.50.1", + "@rollup/rollup-linux-arm-gnueabihf": "4.50.1", + "@rollup/rollup-linux-arm-musleabihf": "4.50.1", + "@rollup/rollup-linux-arm64-gnu": "4.50.1", + "@rollup/rollup-linux-arm64-musl": "4.50.1", + "@rollup/rollup-linux-loongarch64-gnu": "4.50.1", + "@rollup/rollup-linux-ppc64-gnu": "4.50.1", + "@rollup/rollup-linux-riscv64-gnu": "4.50.1", + "@rollup/rollup-linux-riscv64-musl": "4.50.1", + "@rollup/rollup-linux-s390x-gnu": "4.50.1", + "@rollup/rollup-linux-x64-gnu": "4.50.1", + "@rollup/rollup-linux-x64-musl": "4.50.1", + "@rollup/rollup-openharmony-arm64": "4.50.1", + "@rollup/rollup-win32-arm64-msvc": "4.50.1", + "@rollup/rollup-win32-ia32-msvc": "4.50.1", + "@rollup/rollup-win32-x64-msvc": "4.50.1", "fsevents": "~2.3.2" } }, @@ -9884,9 +10194,9 @@ } }, "node_modules/run-applescript": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.0.0.tgz", - "integrity": "sha512-9by4Ij99JUr/MCFBUkDKLWK3G9HVXmabKz9U5MlIAIuvuzkiOicRYs8XJLxX+xahD+mLiiCYDqF9dKAgtzKP1A==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.1.0.tgz", + "integrity": "sha512-DPe5pVFaAsinSaV6QjQ6gdiedWDcRCbUuiQfQa2wmWV7+xC9bGulGI8+TdRmoFkAPaBXk8CrAbnlY2ISniJ47Q==", "license": "MIT", "engines": { "node": ">=18" @@ -9956,15 +10266,6 @@ ], "license": "MIT" }, - "node_modules/safe-stable-stringify": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz", - "integrity": "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==", - "license": "MIT", - "engines": { - "node": ">=10" - } - }, "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", @@ -10166,78 +10467,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/side-channel": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", - "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "object-inspect": "^1.13.3", - "side-channel-list": "^1.0.0", - "side-channel-map": "^1.0.1", - "side-channel-weakmap": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/side-channel-list": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", - "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "object-inspect": "^1.13.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/side-channel-map": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", - "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.5", - "object-inspect": "^1.13.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/side-channel-weakmap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", - "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.5", - "object-inspect": "^1.13.3", - "side-channel-map": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/signal-exit": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", @@ -10322,9 +10551,9 @@ } }, "node_modules/sirv": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/sirv/-/sirv-3.0.1.tgz", - "integrity": "sha512-FoqMu0NCGBLCcAkS1qA+XJIQTR6/JHfQXl+uGteNCQ76T91DMUjPa9xfmeqMY3z80nLSg9yQmNjK0Px6RWsH/A==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/sirv/-/sirv-3.0.2.tgz", + "integrity": "sha512-2wcC/oGxHis/BoHkkPwldgiPSYcpZK3JU28WoMVv55yHJgcZ8rlXvuG9iZggz+sU1d4bRgIGASwyWqjxu3FM0g==", "license": "MIT", "dependencies": { "@polka/url": "^1.0.0-next.24", @@ -10424,38 +10653,6 @@ "node": ">=0.10.0" } }, - "node_modules/spdx-correct": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", - "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", - "license": "Apache-2.0", - "dependencies": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-exceptions": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", - "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", - "license": "CC-BY-3.0" - }, - "node_modules/spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", - "license": "MIT", - "dependencies": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-license-ids": { - "version": "3.0.22", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.22.tgz", - "integrity": "sha512-4PRT4nh1EImPbt2jASOKHX7PB7I+e4IWNLvkKFDxNhJlfjbYlleYQh285Z/3mPTHSAK/AvdMmw5BNNuYH8ShgQ==", - "license": "CC0-1.0" - }, "node_modules/speakingurl": { "version": "14.0.1", "resolved": "https://registry.npmjs.org/speakingurl/-/speakingurl-14.0.1.tgz", @@ -10465,15 +10662,6 @@ "node": ">=0.10.0" } }, - "node_modules/stack-trace": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", - "integrity": "sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==", - "license": "MIT", - "engines": { - "node": "*" - } - }, "node_modules/standard-as-callback": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/standard-as-callback/-/standard-as-callback-2.1.0.tgz", @@ -10577,9 +10765,9 @@ } }, "node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", + "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", "license": "MIT", "dependencies": { "ansi-regex": "^6.0.1" @@ -10694,9 +10882,9 @@ } }, "node_modules/supports-color": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-10.2.0.tgz", - "integrity": "sha512-5eG9FQjEjDbAlI5+kdpdyPIBMRH4GfTVDGREVupaZHmVoppknhM29b/S9BkQz7cathp85BVgRi/As3Siln7e0Q==", + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-10.2.2.tgz", + "integrity": "sha512-SS+jx45GF1QjgEXQx4NJZV9ImqmO2NPz5FNsIHrsDjh2YsHnawpan7SNQ1o8NuhrbHZy9AZhIoCUiCeaW/C80g==", "license": "MIT", "engines": { "node": ">=18" @@ -10806,6 +10994,21 @@ "streamx": "^2.15.0" } }, + "node_modules/tar/node_modules/mkdirp": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz", + "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==", + "license": "MIT", + "bin": { + "mkdirp": "dist/cjs/src/bin.js" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/tar/node_modules/yallist": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", @@ -10816,13 +11019,13 @@ } }, "node_modules/terser": { - "version": "5.43.1", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.43.1.tgz", - "integrity": "sha512-+6erLbBm0+LROX2sPXlUYx/ux5PyE9K/a92Wrt6oA+WDAoFTdpHE5tCYCI5PNzq2y8df4rA+QgHLJuR4jNymsg==", + "version": "5.44.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.44.0.tgz", + "integrity": "sha512-nIVck8DK+GM/0Frwd+nIhZ84pR/BX7rmXMfYwyg+Sri5oGVE99/E3KvXqpC2xHFxyqXyGHTKBSioxxplrO4I4w==", "license": "BSD-2-Clause", "dependencies": { "@jridgewell/source-map": "^0.3.3", - "acorn": "^8.14.0", + "acorn": "^8.15.0", "commander": "^2.20.0", "source-map-support": "~0.5.20" }, @@ -10848,12 +11051,6 @@ "b4a": "^1.6.4" } }, - "node_modules/text-hex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz", - "integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==", - "license": "MIT" - }, "node_modules/tiny-invariant": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz", @@ -10867,13 +11064,13 @@ "license": "MIT" }, "node_modules/tinyglobby": { - "version": "0.2.14", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.14.tgz", - "integrity": "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==", + "version": "0.2.15", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", "license": "MIT", "dependencies": { - "fdir": "^6.4.4", - "picomatch": "^4.0.2" + "fdir": "^6.5.0", + "picomatch": "^4.0.3" }, "engines": { "node": ">=12.0.0" @@ -10911,24 +11108,6 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/tmp": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.5.tgz", - "integrity": "sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow==", - "license": "MIT", - "engines": { - "node": ">=14.14" - } - }, - "node_modules/tmp-promise": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/tmp-promise/-/tmp-promise-3.0.3.tgz", - "integrity": "sha512-RwM7MoPojPxsOBYnyd2hy0bxtIlVrihNs9pj5SUvY8Zz1sQcQG2tG1hSr8PDxfgEB8RNKDhqbIlroIarSNDNsQ==", - "license": "MIT", - "dependencies": { - "tmp": "^0.2.0" - } - }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -10950,12 +11129,6 @@ "node": ">=0.6" } }, - "node_modules/toml": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/toml/-/toml-3.0.0.tgz", - "integrity": "sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w==", - "license": "MIT" - }, "node_modules/totalist": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz", @@ -10971,27 +11144,6 @@ "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", "license": "MIT" }, - "node_modules/triple-beam": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.4.1.tgz", - "integrity": "sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg==", - "license": "MIT", - "engines": { - "node": ">= 14.0.0" - } - }, - "node_modules/ts-api-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz", - "integrity": "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==", - "license": "MIT", - "engines": { - "node": ">=18.12" - }, - "peerDependencies": { - "typescript": ">=4.8.4" - } - }, "node_modules/ts-dedent": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/ts-dedent/-/ts-dedent-2.2.0.tgz", @@ -11038,19 +11190,6 @@ "integrity": "sha512-wTk4DH3cxwk196uGLK/E9pE45aLfeKJacKmcEgEOA/q5dnPGNxXt0cfYdFxb57L+sEpf1oJH4Dnx/pnRcku9jg==", "license": "MIT" }, - "node_modules/typescript": { - "version": "5.9.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.2.tgz", - "integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==", - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, "node_modules/uc.micro": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz", @@ -11087,17 +11226,10 @@ "unplugin": "^2.1.0" } }, - "node_modules/undici-types": { - "version": "7.10.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.10.0.tgz", - "integrity": "sha512-t5Fy/nfn+14LuOc2KNYg75vZqClpAiqscVvMygNnlsHBFpSXdJaYtXMcdNLpl/Qvc3P2cB3s6lOV51nqsFq4ag==", - "license": "MIT", - "optional": true - }, "node_modules/unenv": { - "version": "2.0.0-rc.19", - "resolved": "https://registry.npmjs.org/unenv/-/unenv-2.0.0-rc.19.tgz", - "integrity": "sha512-t/OMHBNAkknVCI7bVB9OWjUUAwhVv9vsPIAGnNUxnu3FxPQN11rjh0sksLMzc3g7IlTgvHmOTl4JM7JHpcv5wA==", + "version": "2.0.0-rc.21", + "resolved": "https://registry.npmjs.org/unenv/-/unenv-2.0.0-rc.21.tgz", + "integrity": "sha512-Wj7/AMtE9MRnAXa6Su3Lk0LNCfqDYgfwVjwRFVum9U7wsto1imuHqk4kTm7Jni+5A0Hn7dttL6O/zjvUvoo+8A==", "license": "MIT", "dependencies": { "defu": "^6.1.4", @@ -11120,9 +11252,9 @@ } }, "node_modules/unicorn-magic": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.1.0.tgz", - "integrity": "sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==", + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.3.0.tgz", + "integrity": "sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==", "license": "MIT", "engines": { "node": ">=18" @@ -11181,34 +11313,10 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/unixify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unixify/-/unixify-1.0.0.tgz", - "integrity": "sha512-6bc58dPYhCMHHuwxldQxO3RRNZ4eCogZ/st++0+fcC1nr0jiGUtAdBJ2qzmLQWSxbtz42pWt4QQMiZ9HvZf5cg==", - "license": "MIT", - "dependencies": { - "normalize-path": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/unixify/node_modules/normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==", - "license": "MIT", - "dependencies": { - "remove-trailing-separator": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/unplugin": { - "version": "2.3.9", - "resolved": "https://registry.npmjs.org/unplugin/-/unplugin-2.3.9.tgz", - "integrity": "sha512-2dcbZq6aprwXTkzptq3k5qm5B8cvpjG9ynPd5fyM2wDJuuF7PeUK64Sxf0d+X1ZyDOeGydbNzMqBSIVlH8GIfA==", + "version": "2.3.10", + "resolved": "https://registry.npmjs.org/unplugin/-/unplugin-2.3.10.tgz", + "integrity": "sha512-6NCPkv1ClwH+/BGE9QeoTIl09nuiAt0gS28nn1PvYXsGKRwM2TCbFA2QiilmehPDTXIe684k4rZI1yl3A1PCUw==", "license": "MIT", "dependencies": { "@jridgewell/remapping": "^2.3.5", @@ -11306,9 +11414,9 @@ } }, "node_modules/unstorage": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/unstorage/-/unstorage-1.17.0.tgz", - "integrity": "sha512-l9Z7lBiwtNp8ZmcoZ/dmPkFXFdtEdZtTZafCSnEIj3YvtkXeGAtL2rN8MQFy/0cs4eOLpuRJMp9ivdug7TCvww==", + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/unstorage/-/unstorage-1.17.1.tgz", + "integrity": "sha512-KKGwRTT0iVBCErKemkJCLs7JdxNVfqTPc/85ae1XES0+bsHbc/sFBfVi5kJp156cc51BHinIH2l3k0EZ24vOBQ==", "license": "MIT", "dependencies": { "anymatch": "^3.1.3", @@ -11333,7 +11441,7 @@ "@planetscale/database": "^1.19.0", "@upstash/redis": "^1.34.3", "@vercel/blob": ">=0.27.1", - "@vercel/functions": "^2.2.12", + "@vercel/functions": "^2.2.12 || ^3.0.0", "@vercel/kv": "^1.0.1", "aws4fetch": "^1.0.20", "db0": ">=0.2.1", @@ -11503,12 +11611,6 @@ "requires-port": "^1.0.0" } }, - "node_modules/urlpattern-polyfill": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/urlpattern-polyfill/-/urlpattern-polyfill-8.0.2.tgz", - "integrity": "sha512-Qp95D4TPJl1kC9SKigDcqgyM2VDVO4RiJc2d4qe5GrYm+zbIQCWWKAFaJNQ4BhdFeDGwBmAxqJBwWSJDb9T3BQ==", - "license": "MIT" - }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -11564,20 +11666,10 @@ "node": ">=6" } }, - "node_modules/validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "license": "Apache-2.0", - "dependencies": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, "node_modules/vditor": { - "version": "3.11.1", - "resolved": "https://registry.npmjs.org/vditor/-/vditor-3.11.1.tgz", - "integrity": "sha512-7rjNSXYVyZG0mVZpUG2tfxwnoNtkcRCnwdSju+Zvpjf/r72iQa6kLpeThFMIKPuQ5CRnQQv6gnR3eNU6UGbC2Q==", + "version": "3.11.2", + "resolved": "https://registry.npmjs.org/vditor/-/vditor-3.11.2.tgz", + "integrity": "sha512-8QguQQUPWbBFocnfQmWjz4jiykQnvsmCuhOomGIVVK7vc+dQq2h8w9qQQuEjUTZpnZT5fEdYbj4aLr1NGdAZaA==", "license": "MIT", "dependencies": { "diff-match-patch": "^1.0.5" @@ -11587,9 +11679,9 @@ } }, "node_modules/vite": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/vite/-/vite-7.1.3.tgz", - "integrity": "sha512-OOUi5zjkDxYrKhTV3V7iKsoS37VUM7v40+HuwEmcrsf11Cdx9y3DIr2Px6liIcZFwt3XSRpQvFpL3WVy7ApkGw==", + "version": "7.1.5", + "resolved": "https://registry.npmjs.org/vite/-/vite-7.1.5.tgz", + "integrity": "sha512-4cKBO9wR75r0BeIWWWId9XK9Lj6La5X846Zw9dFfzMRw38IlTk2iCcUt6hsyiDRcPidc55ZParFYDXi0nXOeLQ==", "license": "MIT", "dependencies": { "esbuild": "^0.25.0", @@ -11597,7 +11689,7 @@ "picomatch": "^4.0.3", "postcss": "^8.5.6", "rollup": "^4.43.0", - "tinyglobby": "^0.2.14" + "tinyglobby": "^0.2.15" }, "bin": { "vite": "bin/vite.js" @@ -11811,18 +11903,6 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/vite-plugin-checker/node_modules/unicorn-magic": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.3.0.tgz", - "integrity": "sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/vite-plugin-inspect": { "version": "11.3.3", "resolved": "https://registry.npmjs.org/vite-plugin-inspect/-/vite-plugin-inspect-11.3.3.tgz", @@ -11974,16 +12054,16 @@ "license": "MIT" }, "node_modules/vue": { - "version": "3.5.20", - "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.20.tgz", - "integrity": "sha512-2sBz0x/wis5TkF1XZ2vH25zWq3G1bFEPOfkBcx2ikowmphoQsPH6X0V3mmPCXA2K1N/XGTnifVyDQP4GfDDeQw==", + "version": "3.5.21", + "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.21.tgz", + "integrity": "sha512-xxf9rum9KtOdwdRkiApWL+9hZEMWE90FHh8yS1+KJAiWYh+iGWV1FquPjoO9VUHQ+VIhsCXNNyZ5Sf4++RVZBA==", "license": "MIT", "dependencies": { - "@vue/compiler-dom": "3.5.20", - "@vue/compiler-sfc": "3.5.20", - "@vue/runtime-dom": "3.5.20", - "@vue/server-renderer": "3.5.20", - "@vue/shared": "3.5.20" + "@vue/compiler-dom": "3.5.21", + "@vue/compiler-sfc": "3.5.21", + "@vue/runtime-dom": "3.5.21", + "@vue/server-renderer": "3.5.21", + "@vue/shared": "3.5.21" }, "peerDependencies": { "typescript": "*" @@ -12105,15 +12185,6 @@ "vue": "^3.0.2" } }, - "node_modules/web-streams-polyfill": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", - "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==", - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, "node_modules/web-worker": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/web-worker/-/web-worker-1.5.0.tgz", @@ -12180,82 +12251,6 @@ "node": ">= 8" } }, - "node_modules/winston": { - "version": "3.17.0", - "resolved": "https://registry.npmjs.org/winston/-/winston-3.17.0.tgz", - "integrity": "sha512-DLiFIXYC5fMPxaRg832S6F5mJYvePtmO5G9v9IgUFPhXm9/GkXarH/TUrBAVzhTCzAj9anE/+GjrgXp/54nOgw==", - "license": "MIT", - "dependencies": { - "@colors/colors": "^1.6.0", - "@dabh/diagnostics": "^2.0.2", - "async": "^3.2.3", - "is-stream": "^2.0.0", - "logform": "^2.7.0", - "one-time": "^1.0.0", - "readable-stream": "^3.4.0", - "safe-stable-stringify": "^2.3.1", - "stack-trace": "0.0.x", - "triple-beam": "^1.3.0", - "winston-transport": "^4.9.0" - }, - "engines": { - "node": ">= 12.0.0" - } - }, - "node_modules/winston-transport": { - "version": "4.9.0", - "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.9.0.tgz", - "integrity": "sha512-8drMJ4rkgaPo1Me4zD/3WLfI/zPdA9o2IipKODunnGDcuqbHwjsbB79ylv04LCGGzU0xQ6vTznOMpQGaLhhm6A==", - "license": "MIT", - "dependencies": { - "logform": "^2.7.0", - "readable-stream": "^3.6.2", - "triple-beam": "^1.3.0" - }, - "engines": { - "node": ">= 12.0.0" - } - }, - "node_modules/winston-transport/node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "license": "MIT", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/winston/node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/winston/node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "license": "MIT", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/wrap-ansi": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", @@ -12351,20 +12346,8 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "license": "ISC" - }, - "node_modules/write-file-atomic": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-6.0.0.tgz", - "integrity": "sha512-GmqrO8WJ1NuzJ2DrziEI2o57jKAVIQNf8a18W3nCYU3H7PNWqCCVTeH6/NQE93CIllIgQS98rrmVkYgTX9fFJQ==", "license": "ISC", - "dependencies": { - "imurmurhash": "^0.1.4", - "signal-exit": "^4.0.1" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } + "optional": true }, "node_modules/ws": { "version": "8.18.3", @@ -12519,37 +12502,6 @@ "node": ">=8" } }, - "node_modules/yauzl": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", - "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", - "license": "MIT", - "dependencies": { - "buffer-crc32": "~0.2.3", - "fd-slicer": "~1.1.0" - } - }, - "node_modules/yauzl/node_modules/buffer-crc32": { - "version": "0.2.13", - "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", - "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", - "license": "MIT", - "engines": { - "node": "*" - } - }, - "node_modules/yocto-queue": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.2.1.tgz", - "integrity": "sha512-AyeEbWOu/TAXdxlV9wmGcR0+yh2j3vYPGOECcIj2S7MkrLyC7ne+oye2BKTItt0ii2PHk4cDy+95+LshzbXnGg==", - "license": "MIT", - "engines": { - "node": ">=12.20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/youch": { "version": "4.1.0-beta.11", "resolved": "https://registry.npmjs.org/youch/-/youch-4.1.0-beta.11.tgz", @@ -12587,15 +12539,6 @@ "node": ">= 14" } }, - "node_modules/zod": { - "version": "3.25.76", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", - "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/colinhacks" - } - }, "node_modules/zrender": { "version": "5.6.1", "resolved": "https://registry.npmjs.org/zrender/-/zrender-5.6.1.tgz", From 6ea9b4a33c05d1700a19386d738dc3ee395d7c07 Mon Sep 17 00:00:00 2001 From: wangshun <932054296@qq.com> Date: Mon, 15 Sep 2025 11:23:31 +0800 Subject: [PATCH 16/26] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E9=97=AE=E9=A2=98#927,?= =?UTF-8?q?#860=201.=E4=BC=98=E5=8C=96=E8=AF=84=E8=AE=BA=E8=AF=B7=E6=B1=82?= =?UTF-8?q?=EF=BC=8C=E5=B0=86=E4=B8=A4=E4=B8=AA=E8=AF=B7=E6=B1=82=E5=90=88?= =?UTF-8?q?=E5=B9=B6=E4=B8=BA=E4=B8=80=E4=B8=AA=202.=E4=BF=AE=E6=94=B9?= =?UTF-8?q?=E4=B8=AA=E4=BA=BA=E4=B8=BB=E9=A1=B5=E6=8C=89=E9=92=AE=E7=9A=84?= =?UTF-8?q?=E4=B8=BB=E6=AC=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/CommentController.java | 53 ++++++++++++--- .../com/openisle/dto/TimelineItemDto.java | 20 ++++++ frontend_nuxt/assets/global.css | 2 + frontend_nuxt/pages/posts/[id]/index.vue | 66 +++++++++---------- frontend_nuxt/pages/users/[id].vue | 22 ++++++- 5 files changed, 117 insertions(+), 46 deletions(-) create mode 100644 backend/src/main/java/com/openisle/dto/TimelineItemDto.java diff --git a/backend/src/main/java/com/openisle/controller/CommentController.java b/backend/src/main/java/com/openisle/controller/CommentController.java index d611e9622..fb53f35d2 100644 --- a/backend/src/main/java/com/openisle/controller/CommentController.java +++ b/backend/src/main/java/com/openisle/controller/CommentController.java @@ -1,13 +1,14 @@ package com.openisle.controller; +import com.openisle.dto.PostChangeLogDto; +import com.openisle.dto.TimelineItemDto; +import com.openisle.mapper.PostChangeLogMapper; import com.openisle.model.Comment; import com.openisle.dto.CommentDto; import com.openisle.dto.CommentRequest; import com.openisle.mapper.CommentMapper; -import com.openisle.service.CaptchaService; -import com.openisle.service.CommentService; -import com.openisle.service.LevelService; -import com.openisle.service.PointService; +import com.openisle.model.CommentSort; +import com.openisle.service.*; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; @@ -21,6 +22,8 @@ import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.security.SecurityRequirement; +import java.util.ArrayList; +import java.util.Comparator; import java.util.List; import java.util.stream.Collectors; @@ -34,6 +37,8 @@ public class CommentController { private final CaptchaService captchaService; private final CommentMapper commentMapper; private final PointService pointService; + private final PostChangeLogService changeLogService; + private final PostChangeLogMapper postChangeLogMapper; @Value("${app.captcha.enabled:false}") private boolean captchaEnabled; @@ -85,15 +90,43 @@ public class CommentController { @GetMapping("/posts/{postId}/comments") @Operation(summary = "List comments", description = "List comments for a post") @ApiResponse(responseCode = "200", description = "Comments", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = CommentDto.class)))) - public List listComments(@PathVariable Long postId, - @RequestParam(value = "sort", required = false, defaultValue = "OLDEST") com.openisle.model.CommentSort sort) { + content = @Content(array = @ArraySchema(schema = @Schema(implementation = TimelineItemDto.class)))) + public List> listComments(@PathVariable Long postId, + @RequestParam(value = "sort", required = false, defaultValue = "OLDEST") CommentSort sort) { log.debug("listComments called for post {} with sort {}", postId, sort); - List list = commentService.getCommentsForPost(postId, sort).stream() + List commentDtoList = commentService.getCommentsForPost(postId, sort).stream() .map(commentMapper::toDtoWithReplies) .collect(Collectors.toList()); - log.debug("listComments returning {} comments", list.size()); - return list; + List postChangeLogDtoList = changeLogService.listLogs(postId).stream() + .map(postChangeLogMapper::toDto) + .collect(Collectors.toList()); + List> itemDtoList = new ArrayList<>(); + + itemDtoList.addAll(commentDtoList.stream() + .map(c -> new TimelineItemDto<>( + c.getId(), + "comment", + c.getCreatedAt(), + c // payload 是 CommentDto + )) + .toList()); + + itemDtoList.addAll(postChangeLogDtoList.stream() + .map(l -> new TimelineItemDto<>( + l.getId(), + "log", + l.getTime(), // 注意字段名不一样 + l // payload 是 PostChangeLogDto + )) + .toList()); + // 排序 + Comparator> comparator = Comparator.comparing(TimelineItemDto::getCreatedAt); + if (CommentSort.NEWEST.equals(sort)) { + comparator = comparator.reversed(); + } + itemDtoList.sort(comparator); + log.debug("listComments returning {} comments", itemDtoList.size()); + return itemDtoList; } @DeleteMapping("/comments/{id}") diff --git a/backend/src/main/java/com/openisle/dto/TimelineItemDto.java b/backend/src/main/java/com/openisle/dto/TimelineItemDto.java new file mode 100644 index 000000000..7e53f8a9c --- /dev/null +++ b/backend/src/main/java/com/openisle/dto/TimelineItemDto.java @@ -0,0 +1,20 @@ +package com.openisle.dto; + +import lombok.*; + +import java.time.LocalDateTime; + +/** + * comment and change_log Dto + */ +@Getter +@Setter +@AllArgsConstructor +@NoArgsConstructor +public class TimelineItemDto { + + private Long id; + private String kind; // "comment" | "log" + private LocalDateTime createdAt; + private T payload; // 泛型,具体类型由外部决定 +} diff --git a/frontend_nuxt/assets/global.css b/frontend_nuxt/assets/global.css index 6105d1ab9..3d610cc33 100644 --- a/frontend_nuxt/assets/global.css +++ b/frontend_nuxt/assets/global.css @@ -2,6 +2,8 @@ --primary-color-hover: rgb(9, 95, 105); --primary-color: rgb(10, 110, 120); --primary-color-disabled: rgba(93, 152, 156, 0.5); + --secondary-color:rgb(255, 255, 255); + --secondary-color-hover:rgba(165, 255, 255, 0.447); --new-post-icon-color: rgba(10, 111, 120, 0.598); --header-height: 60px; --header-background-color: white; diff --git a/frontend_nuxt/pages/posts/[id]/index.vue b/frontend_nuxt/pages/posts/[id]/index.vue index 5aa2bf57e..ad31ff183 100644 --- a/frontend_nuxt/pages/posts/[id]/index.vue +++ b/frontend_nuxt/pages/posts/[id]/index.vue @@ -320,6 +320,7 @@ const mapComment = ( level = 0, ) => ({ id: c.id, + kind: 'comment', userName: c.author.username, medal: c.author.displayMedal, userId: c.author.id, @@ -374,6 +375,7 @@ const changeLogIcon = (l) => { const mapChangeLog = (l) => ({ id: l.id, + kind: 'log', username: l.username, userAvatar: l.userAvatar, type: l.type, @@ -788,9 +790,9 @@ const fetchCommentSorts = () => { ]) } -const fetchComments = async () => { +const fetchCommentsAndChangeLog = async () => { isFetchingComments.value = true - console.debug('Fetching comments', { postId, sort: commentSort.value }) + console.info('Fetching comments and chang log', { postId, sort: commentSort.value }) try { const token = getToken() const res = await fetch( @@ -799,11 +801,34 @@ const fetchComments = async () => { headers: { Authorization: token ? `Bearer ${token}` : '' }, }, ) - console.debug('Fetch comments response status', res.status) + console.info('Fetch comments response status', res.status) if (res.ok) { const data = await res.json() - console.debug('Fetched comments count', data.length) - comments.value = data.map(mapComment) + console.info('Fetched comments data', data) + + const commentList = [] + const changeLogList = [] + // 时间线列表,包含评论和日志 + const newTimelineItemList = [] + + for (const item of data) { + const mappedPayload = + item.kind === 'comment' + ? mapComment(item.payload) + : mapChangeLog(item.payload) + newTimelineItemList.push(mappedPayload) + + if (item.kind === 'comment') { + commentList.push(mappedPayload) + } else { + changeLogList.push(mappedPayload) + } + } + + comments.value = commentList + changeLogs.value = changeLogList + timelineItems.value = newTimelineItemList + isFetchingComments.value = false await nextTick() gatherPostItems() @@ -815,37 +840,8 @@ const fetchComments = async () => { } } -const fetchChangeLogs = async () => { - try { - const res = await fetch(`${API_BASE_URL}/api/posts/${postId}/change-logs`) - if (res.ok) { - const data = await res.json() - changeLogs.value = data.map(mapChangeLog) - await nextTick() - gatherPostItems() - } - } catch (e) { - console.debug('Fetch change logs error', e) - } -} - -// -// todo(tim): fetchComments, fetchChangeLogs 整合到一个请求,并且取消前端排序 -// const fetchTimeline = async () => { - await Promise.all([fetchComments(), fetchChangeLogs()]) - const cs = comments.value.map((c) => ({ ...c, kind: 'comment' })) - const ls = changeLogs.value.map((l) => ({ ...l, kind: 'log' })) - - if (commentSort.value === 'NEWEST') { - timelineItems.value = [...cs, ...ls].sort( - (a, b) => new Date(b.createdAt) - new Date(a.createdAt), - ) - } else { - timelineItems.value = [...cs, ...ls].sort( - (a, b) => new Date(a.createdAt) - new Date(b.createdAt), - ) - } + await fetchCommentsAndChangeLog() } watch(commentSort, async () => { diff --git a/frontend_nuxt/pages/users/[id].vue b/frontend_nuxt/pages/users/[id].vue index 4e810e2b7..0e7107964 100644 --- a/frontend_nuxt/pages/users/[id].vue +++ b/frontend_nuxt/pages/users/[id].vue @@ -29,7 +29,7 @@ 取消关注
-
+
发私信
@@ -703,6 +703,26 @@ watch(selectedTab, async (val) => { cursor: pointer; } +.profile-page-header-send-mail-button { + display: flex; + flex-direction: row; + gap: 5px; + align-items: center; + font-size: 14px; + border-radius: 8px; + padding: 5px 10px; + color: var(--primary-color); + background-color: var(--secondary-color); + border: 1px solid var(--primary-color); + margin-top: 15px; + width: fit-content; + cursor: pointer; +} + +.profile-page-header-send-mail-button:hover { + background-color: var(--secondary-color-hover); +} + .profile-level-container { display: flex; flex-direction: column; From 6db969cc4d594c5d47906c88fccee0e275087225 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=A4=A2=E5=A4=A2=E3=81=AE=E5=B9=BB=E6=83=B3=E9=83=B7?= <932054296@qq.com> Date: Mon, 15 Sep 2025 11:30:37 +0800 Subject: [PATCH 17/26] Update deploy-staging.yml MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 只有主仓库的时候才执行 --- .github/workflows/deploy-staging.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/deploy-staging.yml b/.github/workflows/deploy-staging.yml index 2b9fae188..f62be188d 100644 --- a/.github/workflows/deploy-staging.yml +++ b/.github/workflows/deploy-staging.yml @@ -12,6 +12,7 @@ jobs: build-and-deploy: runs-on: ubuntu-latest environment: Deploy + if: ${{ !github.event.repository.fork }} # 只有非 fork 才执行 steps: - uses: actions/checkout@v4 From 6f968d16aa9bf5b497b1f4976dff646d44135c86 Mon Sep 17 00:00:00 2001 From: Tim Date: Wed, 17 Sep 2025 11:41:35 +0800 Subject: [PATCH 18/26] =?UTF-8?q?fix:=20=E5=A4=84=E7=90=86=E9=A6=96?= =?UTF-8?q?=E5=B1=8F=E8=BF=94=E5=9B=9E=E7=A9=BA=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/com/openisle/controller/PostController.java | 4 ++-- backend/src/main/java/com/openisle/mapper/PostMapper.java | 3 --- .../java/com/openisle/scheduler/UserVisitScheduler.java | 6 +++--- .../main/java/com/openisle/service/UserVisitService.java | 4 ++-- 4 files changed, 7 insertions(+), 10 deletions(-) diff --git a/backend/src/main/java/com/openisle/controller/PostController.java b/backend/src/main/java/com/openisle/controller/PostController.java index 907358c30..963e06bb6 100644 --- a/backend/src/main/java/com/openisle/controller/PostController.java +++ b/backend/src/main/java/com/openisle/controller/PostController.java @@ -203,8 +203,8 @@ public class PostController { // userVisitService.recordVisit(auth.getName()); // } - return postService.listPostsByLatestReply(ids, tids, page, pageSize) - .stream().map(postMapper::toSummaryDto).collect(Collectors.toList()); + List posts = postService.listPostsByLatestReply(ids, tids, page, pageSize); + return posts.stream().map(postMapper::toSummaryDto).collect(Collectors.toList()); } @GetMapping("/featured") diff --git a/backend/src/main/java/com/openisle/mapper/PostMapper.java b/backend/src/main/java/com/openisle/mapper/PostMapper.java index bd4a04826..959129236 100644 --- a/backend/src/main/java/com/openisle/mapper/PostMapper.java +++ b/backend/src/main/java/com/openisle/mapper/PostMapper.java @@ -96,8 +96,6 @@ public class PostMapper { l.setPointCost(lp.getPointCost()); l.setStartTime(lp.getStartTime()); l.setEndTime(lp.getEndTime()); - l.setParticipants(lp.getParticipants().stream().map(userMapper::toAuthorDto).collect(Collectors.toList())); - l.setWinners(lp.getWinners().stream().map(userMapper::toAuthorDto).collect(Collectors.toList())); dto.setLottery(l); } @@ -106,7 +104,6 @@ public class PostMapper { p.setOptions(pp.getOptions()); p.setVotes(pp.getVotes()); p.setEndTime(pp.getEndTime()); - p.setParticipants(pp.getParticipants().stream().map(userMapper::toAuthorDto).collect(Collectors.toList())); Map> optionParticipants = pollVoteRepository.findByPostId(pp.getId()).stream() .collect(Collectors.groupingBy(PollVote::getOptionIndex, Collectors.mapping(v -> userMapper.toAuthorDto(v.getUser()), Collectors.toList()))); diff --git a/backend/src/main/java/com/openisle/scheduler/UserVisitScheduler.java b/backend/src/main/java/com/openisle/scheduler/UserVisitScheduler.java index ff16fe3c4..139963587 100644 --- a/backend/src/main/java/com/openisle/scheduler/UserVisitScheduler.java +++ b/backend/src/main/java/com/openisle/scheduler/UserVisitScheduler.java @@ -27,12 +27,12 @@ public class UserVisitScheduler { private final UserRepository userRepository; private final UserVisitRepository userVisitRepository; - @Scheduled(cron = "0 5 0 * * ?")// 每天 00:05 执行 + @Scheduled(cron = "0 5 0 * * ?") // 每天 00:05 执行 public void persistDailyVisits(){ LocalDate yesterday = LocalDate.now().minusDays(1); - String key = CachingConfig.VISIT_CACHE_NAME+":"+ yesterday; + String key = CachingConfig.VISIT_CACHE_NAME + ":" + yesterday; Set usernames = redisTemplate.opsForSet().members(key); - if(!CollectionUtils.isEmpty(usernames)){ + if (!CollectionUtils.isEmpty(usernames)) { for(String username: usernames){ User user = userRepository.findByUsername(username).orElse(null); if(user != null){ diff --git a/backend/src/main/java/com/openisle/service/UserVisitService.java b/backend/src/main/java/com/openisle/service/UserVisitService.java index 272c846de..9182e145f 100644 --- a/backend/src/main/java/com/openisle/service/UserVisitService.java +++ b/backend/src/main/java/com/openisle/service/UserVisitService.java @@ -49,9 +49,9 @@ public class UserVisitService { .orElseThrow(() -> new com.openisle.exception.NotFoundException("User not found")); // 如果缓存存在就返回 - String key1 = CachingConfig.VISIT_CACHE_NAME + ":"+LocalDate.now()+":count:"+username; + String key1 = CachingConfig.VISIT_CACHE_NAME + ":" +LocalDate.now() + ":count:" + username; Integer cached = (Integer) redisTemplate.opsForValue().get(key1); - if(cached != null){ + if (cached != null){ return cached.longValue(); } From 063866cc3a3e7ddbd0063f459b56eb4d4dcd345b Mon Sep 17 00:00:00 2001 From: Tim <135014430+nagisa77@users.noreply.github.com> Date: Wed, 17 Sep 2025 11:52:42 +0800 Subject: [PATCH 19/26] Fix post cache keys to include pagination --- .../com/openisle/service/CommentService.java | 8 ++++---- .../java/com/openisle/service/PostService.java | 18 +++++++++--------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/backend/src/main/java/com/openisle/service/CommentService.java b/backend/src/main/java/com/openisle/service/CommentService.java index e9456caf7..cf09f2a19 100644 --- a/backend/src/main/java/com/openisle/service/CommentService.java +++ b/backend/src/main/java/com/openisle/service/CommentService.java @@ -52,7 +52,7 @@ public class CommentService { @CacheEvict( value = CachingConfig.POST_CACHE_NAME, - key = "'latest_reply'" + allEntries = true ) @Transactional public Comment addComment(String username, Long postId, String content) { @@ -104,7 +104,7 @@ public class CommentService { @CacheEvict( value = CachingConfig.POST_CACHE_NAME, - key = "'latest_reply'" + allEntries = true ) @Transactional public Comment addReply(String username, Long parentId, String content) { @@ -241,7 +241,7 @@ public class CommentService { @CacheEvict( value = CachingConfig.POST_CACHE_NAME, - key = "'latest_reply'" + allEntries = true ) @Transactional public void deleteComment(String username, Long id) { @@ -260,7 +260,7 @@ public class CommentService { @CacheEvict( value = CachingConfig.POST_CACHE_NAME, - key = "'latest_reply'" + allEntries = true ) @Transactional public void deleteCommentCascade(Comment comment) { diff --git a/backend/src/main/java/com/openisle/service/PostService.java b/backend/src/main/java/com/openisle/service/PostService.java index 65092d0b7..36796e346 100644 --- a/backend/src/main/java/com/openisle/service/PostService.java +++ b/backend/src/main/java/com/openisle/service/PostService.java @@ -509,7 +509,7 @@ public class PostService { @Cacheable( value = CachingConfig.POST_CACHE_NAME, - key = "'latest_reply'" + key = "new org.springframework.cache.interceptor.SimpleKey('latest_reply', #categoryIds, #tagIds, #page, #pageSize)" ) public List listPostsByLatestReply(java.util.List categoryIds, java.util.List tagIds, @@ -648,7 +648,7 @@ public class PostService { */ @Cacheable( value = CachingConfig.POST_CACHE_NAME, - key = "'default'" + key = "new org.springframework.cache.interceptor.SimpleKey('default', #ids, #tids, #page, #pageSize)" ) public List defaultListPosts(List ids, List tids, Integer page, Integer pageSize){ boolean hasCategories = !CollectionUtils.isEmpty(ids); @@ -673,7 +673,7 @@ public class PostService { @CacheEvict( value = CachingConfig.POST_CACHE_NAME, - key = "'default'" + allEntries = true ) public Post approvePost(Long id) { Post post = postRepository.findById(id) @@ -713,7 +713,7 @@ public class PostService { @CacheEvict( value = CachingConfig.POST_CACHE_NAME, - key = "'default'" + allEntries = true ) public Post pinPost(Long id, String username) { Post post = postRepository.findById(id) @@ -729,7 +729,7 @@ public class PostService { @CacheEvict( value = CachingConfig.POST_CACHE_NAME, - key = "'default'" + allEntries = true ) public Post unpinPost(Long id, String username) { Post post = postRepository.findById(id) @@ -745,7 +745,7 @@ public class PostService { @CacheEvict( value = CachingConfig.POST_CACHE_NAME, - key = "'default'" + allEntries = true ) public Post closePost(Long id, String username) { Post post = postRepository.findById(id) @@ -764,7 +764,7 @@ public class PostService { @CacheEvict( value = CachingConfig.POST_CACHE_NAME, - key = "'default'" + allEntries = true ) public Post reopenPost(Long id, String username) { Post post = postRepository.findById(id) @@ -783,7 +783,7 @@ public class PostService { @CacheEvict( value = CachingConfig.POST_CACHE_NAME, - key = "'default'" + allEntries = true ) @Transactional public Post updatePost(Long id, @@ -840,7 +840,7 @@ public class PostService { @CacheEvict( value = CachingConfig.POST_CACHE_NAME, - key = "'default'" + allEntries = true ) @Transactional public void deletePost(Long id, String username) { From 7067630bcc1993bd0da1cf086cf686e0ccf56841 Mon Sep 17 00:00:00 2001 From: Tim Date: Wed, 17 Sep 2025 12:06:02 +0800 Subject: [PATCH 20/26] =?UTF-8?q?fix:=20=E9=AA=8C=E8=AF=81=E7=A0=81?= =?UTF-8?q?=E9=83=A8=E5=88=86=E9=AA=8C=E8=AF=81=E5=AE=8C=E6=AF=95=EF=BC=8C?= =?UTF-8?q?=E6=8F=90=E4=BA=A4=E5=B0=8F=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/src/main/java/com/openisle/service/UserService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/main/java/com/openisle/service/UserService.java b/backend/src/main/java/com/openisle/service/UserService.java index a3352901f..4bef6dbc7 100644 --- a/backend/src/main/java/com/openisle/service/UserService.java +++ b/backend/src/main/java/com/openisle/service/UserService.java @@ -100,7 +100,7 @@ public class UserService { * @param user */ public void sendVerifyMail(User user, VerifyType verifyType){ - //缓存验证码 + // 缓存验证码 String code = genCode(); String key; String subject; From b4a811ff4e40e4aa1a2947f719e94aa91709085b Mon Sep 17 00:00:00 2001 From: Tim <135014430+nagisa77@users.noreply.github.com> Date: Wed, 17 Sep 2025 12:21:17 +0800 Subject: [PATCH 21/26] Handle point history cleanup when deleting posts --- .../repository/PointHistoryRepository.java | 5 ++++- .../java/com/openisle/service/PostService.java | 16 ++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/backend/src/main/java/com/openisle/repository/PointHistoryRepository.java b/backend/src/main/java/com/openisle/repository/PointHistoryRepository.java index 2e3d6647e..f22af7eee 100644 --- a/backend/src/main/java/com/openisle/repository/PointHistoryRepository.java +++ b/backend/src/main/java/com/openisle/repository/PointHistoryRepository.java @@ -3,6 +3,7 @@ package com.openisle.repository; import com.openisle.model.PointHistory; import com.openisle.model.User; import com.openisle.model.Comment; +import com.openisle.model.Post; import org.springframework.data.jpa.repository.JpaRepository; import java.time.LocalDateTime; @@ -14,6 +15,8 @@ public interface PointHistoryRepository extends JpaRepository findByUserAndCreatedAtAfterOrderByCreatedAtDesc(User user, LocalDateTime createdAt); - + List findByComment(Comment comment); + + List findByPost(Post post); } diff --git a/backend/src/main/java/com/openisle/service/PostService.java b/backend/src/main/java/com/openisle/service/PostService.java index 36796e346..88c6b2b85 100644 --- a/backend/src/main/java/com/openisle/service/PostService.java +++ b/backend/src/main/java/com/openisle/service/PostService.java @@ -16,6 +16,7 @@ import com.openisle.repository.CommentRepository; import com.openisle.repository.ReactionRepository; import com.openisle.repository.PostSubscriptionRepository; import com.openisle.repository.NotificationRepository; +import com.openisle.repository.PointHistoryRepository; import com.openisle.repository.PollVoteRepository; import com.openisle.exception.RateLimitException; import lombok.extern.slf4j.Slf4j; @@ -67,6 +68,7 @@ public class PostService { private final ReactionRepository reactionRepository; private final PostSubscriptionRepository postSubscriptionRepository; private final NotificationRepository notificationRepository; + private final PointHistoryRepository pointHistoryRepository; private final PostReadService postReadService; private final ImageUploader imageUploader; private final TaskScheduler taskScheduler; @@ -95,6 +97,7 @@ public class PostService { ReactionRepository reactionRepository, PostSubscriptionRepository postSubscriptionRepository, NotificationRepository notificationRepository, + PointHistoryRepository pointHistoryRepository, PostReadService postReadService, ImageUploader imageUploader, TaskScheduler taskScheduler, @@ -118,6 +121,7 @@ public class PostService { this.reactionRepository = reactionRepository; this.postSubscriptionRepository = postSubscriptionRepository; this.notificationRepository = notificationRepository; + this.pointHistoryRepository = pointHistoryRepository; this.postReadService = postReadService; this.imageUploader = imageUploader; this.taskScheduler = taskScheduler; @@ -860,6 +864,18 @@ public class PostService { postSubscriptionRepository.findByPost(post).forEach(postSubscriptionRepository::delete); notificationRepository.deleteAll(notificationRepository.findByPost(post)); postReadService.deleteByPost(post); + List pointHistories = pointHistoryRepository.findByPost(post); + Set usersToRecalculate = pointHistories.stream() + .map(PointHistory::getUser) + .collect(Collectors.toSet()); + pointHistoryRepository.deleteAll(pointHistories); + if (!usersToRecalculate.isEmpty()) { + for (User affectedUser : usersToRecalculate) { + int newPoints = pointService.recalculateUserPoints(affectedUser); + affectedUser.setPoint(newPoints); + } + userRepository.saveAll(usersToRecalculate); + } imageUploader.removeReferences(imageUploader.extractUrls(post.getContent())); if (post instanceof LotteryPost lp) { ScheduledFuture future = scheduledFinalizations.remove(lp.getId()); From 89842b82e9526abeaa9c1d976964778156a40fb9 Mon Sep 17 00:00:00 2001 From: Tim Date: Wed, 17 Sep 2025 12:23:20 +0800 Subject: [PATCH 22/26] =?UTF-8?q?fix:=20=E6=96=87=E7=AB=A0=E7=BC=93?= =?UTF-8?q?=E5=AD=98=E4=BF=AE=E6=94=B9=E4=B8=BA=2010=20min?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/src/main/java/com/openisle/config/CachingConfig.java | 2 ++ backend/src/main/java/com/openisle/service/PostService.java | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/backend/src/main/java/com/openisle/config/CachingConfig.java b/backend/src/main/java/com/openisle/config/CachingConfig.java index 9094efa1a..70c14f593 100644 --- a/backend/src/main/java/com/openisle/config/CachingConfig.java +++ b/backend/src/main/java/com/openisle/config/CachingConfig.java @@ -97,8 +97,10 @@ public class CachingConfig { // 个别缓存单独设置 TTL 时间 Map cacheConfigs = new HashMap<>(); RedisCacheConfiguration oneHourConfig = config.entryTtl(Duration.ofHours(1)); + RedisCacheConfiguration tenMinutesConfig = config.entryTtl(Duration.ofMinutes(10)); cacheConfigs.put(TAG_CACHE_NAME, oneHourConfig); cacheConfigs.put(CATEGORY_CACHE_NAME, oneHourConfig); + cacheConfigs.put(POST_CACHE_NAME, tenMinutesConfig); return RedisCacheManager.builder(connectionFactory) .cacheDefaults(config) diff --git a/backend/src/main/java/com/openisle/service/PostService.java b/backend/src/main/java/com/openisle/service/PostService.java index 36796e346..b9774bf34 100644 --- a/backend/src/main/java/com/openisle/service/PostService.java +++ b/backend/src/main/java/com/openisle/service/PostService.java @@ -190,7 +190,7 @@ public class PostService { return saved; } @CacheEvict( - value = CachingConfig.POST_CACHE_NAME, allEntries = true + value = CachingConfig.POST_CACHE_NAME, allEntries = true ) public Post createPost(String username, Long categoryId, From e93e33fe436a510f9b7475902c969104188505a1 Mon Sep 17 00:00:00 2001 From: Tim Date: Wed, 17 Sep 2025 12:27:07 +0800 Subject: [PATCH 23/26] Revert "Handle point history cleanup when deleting posts" This reverts commit b4a811ff4e40e4aa1a2947f719e94aa91709085b. --- .../repository/PointHistoryRepository.java | 5 +---- .../java/com/openisle/service/PostService.java | 16 ---------------- 2 files changed, 1 insertion(+), 20 deletions(-) diff --git a/backend/src/main/java/com/openisle/repository/PointHistoryRepository.java b/backend/src/main/java/com/openisle/repository/PointHistoryRepository.java index f22af7eee..2e3d6647e 100644 --- a/backend/src/main/java/com/openisle/repository/PointHistoryRepository.java +++ b/backend/src/main/java/com/openisle/repository/PointHistoryRepository.java @@ -3,7 +3,6 @@ package com.openisle.repository; import com.openisle.model.PointHistory; import com.openisle.model.User; import com.openisle.model.Comment; -import com.openisle.model.Post; import org.springframework.data.jpa.repository.JpaRepository; import java.time.LocalDateTime; @@ -15,8 +14,6 @@ public interface PointHistoryRepository extends JpaRepository findByUserAndCreatedAtAfterOrderByCreatedAtDesc(User user, LocalDateTime createdAt); - + List findByComment(Comment comment); - - List findByPost(Post post); } diff --git a/backend/src/main/java/com/openisle/service/PostService.java b/backend/src/main/java/com/openisle/service/PostService.java index 4563f2a8f..b9774bf34 100644 --- a/backend/src/main/java/com/openisle/service/PostService.java +++ b/backend/src/main/java/com/openisle/service/PostService.java @@ -16,7 +16,6 @@ import com.openisle.repository.CommentRepository; import com.openisle.repository.ReactionRepository; import com.openisle.repository.PostSubscriptionRepository; import com.openisle.repository.NotificationRepository; -import com.openisle.repository.PointHistoryRepository; import com.openisle.repository.PollVoteRepository; import com.openisle.exception.RateLimitException; import lombok.extern.slf4j.Slf4j; @@ -68,7 +67,6 @@ public class PostService { private final ReactionRepository reactionRepository; private final PostSubscriptionRepository postSubscriptionRepository; private final NotificationRepository notificationRepository; - private final PointHistoryRepository pointHistoryRepository; private final PostReadService postReadService; private final ImageUploader imageUploader; private final TaskScheduler taskScheduler; @@ -97,7 +95,6 @@ public class PostService { ReactionRepository reactionRepository, PostSubscriptionRepository postSubscriptionRepository, NotificationRepository notificationRepository, - PointHistoryRepository pointHistoryRepository, PostReadService postReadService, ImageUploader imageUploader, TaskScheduler taskScheduler, @@ -121,7 +118,6 @@ public class PostService { this.reactionRepository = reactionRepository; this.postSubscriptionRepository = postSubscriptionRepository; this.notificationRepository = notificationRepository; - this.pointHistoryRepository = pointHistoryRepository; this.postReadService = postReadService; this.imageUploader = imageUploader; this.taskScheduler = taskScheduler; @@ -864,18 +860,6 @@ public class PostService { postSubscriptionRepository.findByPost(post).forEach(postSubscriptionRepository::delete); notificationRepository.deleteAll(notificationRepository.findByPost(post)); postReadService.deleteByPost(post); - List pointHistories = pointHistoryRepository.findByPost(post); - Set usersToRecalculate = pointHistories.stream() - .map(PointHistory::getUser) - .collect(Collectors.toSet()); - pointHistoryRepository.deleteAll(pointHistories); - if (!usersToRecalculate.isEmpty()) { - for (User affectedUser : usersToRecalculate) { - int newPoints = pointService.recalculateUserPoints(affectedUser); - affectedUser.setPoint(newPoints); - } - userRepository.saveAll(usersToRecalculate); - } imageUploader.removeReferences(imageUploader.extractUrls(post.getContent())); if (post instanceof LotteryPost lp) { ScheduledFuture future = scheduledFinalizations.remove(lp.getId()); From 28e3ebb911e68463570fdcc45bd1d226b6fd7d7b Mon Sep 17 00:00:00 2001 From: Tim <135014430+nagisa77@users.noreply.github.com> Date: Wed, 17 Sep 2025 12:29:09 +0800 Subject: [PATCH 24/26] Handle point history cleanup when deleting posts --- .../repository/PointHistoryRepository.java | 9 +- .../com/openisle/service/PostService.java | 26 +++++- .../com/openisle/service/PostServiceTest.java | 90 ++++++++++++++++++- 3 files changed, 115 insertions(+), 10 deletions(-) diff --git a/backend/src/main/java/com/openisle/repository/PointHistoryRepository.java b/backend/src/main/java/com/openisle/repository/PointHistoryRepository.java index 2e3d6647e..876b183d1 100644 --- a/backend/src/main/java/com/openisle/repository/PointHistoryRepository.java +++ b/backend/src/main/java/com/openisle/repository/PointHistoryRepository.java @@ -1,8 +1,9 @@ package com.openisle.repository; -import com.openisle.model.PointHistory; -import com.openisle.model.User; import com.openisle.model.Comment; +import com.openisle.model.PointHistory; +import com.openisle.model.Post; +import com.openisle.model.User; import org.springframework.data.jpa.repository.JpaRepository; import java.time.LocalDateTime; @@ -14,6 +15,8 @@ public interface PointHistoryRepository extends JpaRepository findByUserAndCreatedAtAfterOrderByCreatedAtDesc(User user, LocalDateTime createdAt); - + List findByComment(Comment comment); + + List findByPost(Post post); } diff --git a/backend/src/main/java/com/openisle/service/PostService.java b/backend/src/main/java/com/openisle/service/PostService.java index 36796e346..afba1b87e 100644 --- a/backend/src/main/java/com/openisle/service/PostService.java +++ b/backend/src/main/java/com/openisle/service/PostService.java @@ -9,14 +9,12 @@ import com.openisle.repository.PollPostRepository; import com.openisle.repository.UserRepository; import com.openisle.repository.CategoryRepository; import com.openisle.repository.TagRepository; -import com.openisle.service.SubscriptionService; -import com.openisle.service.CommentService; -import com.openisle.service.PostChangeLogService; import com.openisle.repository.CommentRepository; import com.openisle.repository.ReactionRepository; import com.openisle.repository.PostSubscriptionRepository; import com.openisle.repository.NotificationRepository; import com.openisle.repository.PollVoteRepository; +import com.openisle.repository.PointHistoryRepository; import com.openisle.exception.RateLimitException; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; @@ -74,6 +72,7 @@ public class PostService { private final ApplicationContext applicationContext; private final PointService pointService; private final PostChangeLogService postChangeLogService; + private final PointHistoryRepository pointHistoryRepository; private final ConcurrentMap> scheduledFinalizations = new ConcurrentHashMap<>(); @Value("${app.website-url:https://www.open-isle.com}") private String websiteUrl; @@ -102,6 +101,7 @@ public class PostService { ApplicationContext applicationContext, PointService pointService, PostChangeLogService postChangeLogService, + PointHistoryRepository pointHistoryRepository, @Value("${app.post.publish-mode:DIRECT}") PublishMode publishMode, RedisTemplate redisTemplate) { this.postRepository = postRepository; @@ -125,6 +125,7 @@ public class PostService { this.applicationContext = applicationContext; this.pointService = pointService; this.postChangeLogService = postChangeLogService; + this.pointHistoryRepository = pointHistoryRepository; this.publishMode = publishMode; this.redisTemplate = redisTemplate; @@ -861,6 +862,25 @@ public class PostService { notificationRepository.deleteAll(notificationRepository.findByPost(post)); postReadService.deleteByPost(post); imageUploader.removeReferences(imageUploader.extractUrls(post.getContent())); + List pointHistories = pointHistoryRepository.findByPost(post); + Set usersToRecalculate = pointHistories.stream() + .map(PointHistory::getUser) + .collect(Collectors.toSet()); + if (!pointHistories.isEmpty()) { + LocalDateTime deletedAt = LocalDateTime.now(); + for (PointHistory history : pointHistories) { + history.setDeletedAt(deletedAt); + history.setPost(null); + } + pointHistoryRepository.saveAll(pointHistories); + } + if (!usersToRecalculate.isEmpty()) { + for (User affected : usersToRecalculate) { + int newPoints = pointService.recalculateUserPoints(affected); + affected.setPoint(newPoints); + } + userRepository.saveAll(usersToRecalculate); + } if (post instanceof LotteryPost lp) { ScheduledFuture future = scheduledFinalizations.remove(lp.getId()); if (future != null) { diff --git a/backend/src/test/java/com/openisle/service/PostServiceTest.java b/backend/src/test/java/com/openisle/service/PostServiceTest.java index 998fe0175..46efaa5c0 100644 --- a/backend/src/test/java/com/openisle/service/PostServiceTest.java +++ b/backend/src/test/java/com/openisle/service/PostServiceTest.java @@ -10,8 +10,11 @@ import org.springframework.data.redis.core.RedisTemplate; import static org.junit.jupiter.api.Assertions.*; -import java.util.Optional; +import java.time.LocalDateTime; import java.util.List; +import java.util.Optional; + +import org.mockito.ArgumentCaptor; import static org.mockito.Mockito.*; @@ -39,12 +42,14 @@ class PostServiceTest { ApplicationContext context = mock(ApplicationContext.class); PointService pointService = mock(PointService.class); PostChangeLogService postChangeLogService = mock(PostChangeLogService.class); + PointHistoryRepository pointHistoryRepository = mock(PointHistoryRepository.class); RedisTemplate redisTemplate = mock(RedisTemplate.class); PostService service = new PostService(postRepo, userRepo, catRepo, tagRepo, lotteryRepo, pollPostRepo, pollVoteRepo, notifService, subService, commentService, commentRepo, reactionRepo, subRepo, notificationRepo, postReadService, - imageUploader, taskScheduler, emailSender, context, pointService, postChangeLogService, PublishMode.DIRECT, redisTemplate); + imageUploader, taskScheduler, emailSender, context, pointService, postChangeLogService, + pointHistoryRepository, PublishMode.DIRECT, redisTemplate); when(context.getBean(PostService.class)).thenReturn(service); Post post = new Post(); @@ -60,6 +65,7 @@ class PostServiceTest { when(reactionRepo.findByPost(post)).thenReturn(List.of()); when(subRepo.findByPost(post)).thenReturn(List.of()); when(notificationRepo.findByPost(post)).thenReturn(List.of()); + when(pointHistoryRepository.findByPost(post)).thenReturn(List.of()); service.deletePost(1L, "alice"); @@ -90,12 +96,14 @@ class PostServiceTest { ApplicationContext context = mock(ApplicationContext.class); PointService pointService = mock(PointService.class); PostChangeLogService postChangeLogService = mock(PostChangeLogService.class); + PointHistoryRepository pointHistoryRepository = mock(PointHistoryRepository.class); RedisTemplate redisTemplate = mock(RedisTemplate.class); PostService service = new PostService(postRepo, userRepo, catRepo, tagRepo, lotteryRepo, pollPostRepo, pollVoteRepo, notifService, subService, commentService, commentRepo, reactionRepo, subRepo, notificationRepo, postReadService, - imageUploader, taskScheduler, emailSender, context, pointService, postChangeLogService, PublishMode.DIRECT, redisTemplate); + imageUploader, taskScheduler, emailSender, context, pointService, postChangeLogService, + pointHistoryRepository, PublishMode.DIRECT, redisTemplate); when(context.getBean(PostService.class)).thenReturn(service); Post post = new Post(); @@ -117,6 +125,7 @@ class PostServiceTest { when(reactionRepo.findByPost(post)).thenReturn(List.of()); when(subRepo.findByPost(post)).thenReturn(List.of()); when(notificationRepo.findByPost(post)).thenReturn(List.of()); + when(pointHistoryRepository.findByPost(post)).thenReturn(List.of()); service.deletePost(1L, "admin"); @@ -147,12 +156,14 @@ class PostServiceTest { ApplicationContext context = mock(ApplicationContext.class); PointService pointService = mock(PointService.class); PostChangeLogService postChangeLogService = mock(PostChangeLogService.class); + PointHistoryRepository pointHistoryRepository = mock(PointHistoryRepository.class); RedisTemplate redisTemplate = mock(RedisTemplate.class); PostService service = new PostService(postRepo, userRepo, catRepo, tagRepo, lotteryRepo, pollPostRepo, pollVoteRepo, notifService, subService, commentService, commentRepo, reactionRepo, subRepo, notificationRepo, postReadService, - imageUploader, taskScheduler, emailSender, context, pointService, postChangeLogService, PublishMode.DIRECT, redisTemplate); + imageUploader, taskScheduler, emailSender, context, pointService, postChangeLogService, + pointHistoryRepository, PublishMode.DIRECT, redisTemplate); when(context.getBean(PostService.class)).thenReturn(service); when(postRepo.countByAuthorAfter(eq("alice"), any())).thenReturn(1L); @@ -162,6 +173,77 @@ class PostServiceTest { null, null, null, null, null, null, null, null, null)); } + @Test + void deletePostRemovesPointHistoriesAndRecalculatesPoints() { + PostRepository postRepo = mock(PostRepository.class); + UserRepository userRepo = mock(UserRepository.class); + CategoryRepository catRepo = mock(CategoryRepository.class); + TagRepository tagRepo = mock(TagRepository.class); + LotteryPostRepository lotteryRepo = mock(LotteryPostRepository.class); + PollPostRepository pollPostRepo = mock(PollPostRepository.class); + PollVoteRepository pollVoteRepo = mock(PollVoteRepository.class); + NotificationService notifService = mock(NotificationService.class); + SubscriptionService subService = mock(SubscriptionService.class); + CommentService commentService = mock(CommentService.class); + CommentRepository commentRepo = mock(CommentRepository.class); + ReactionRepository reactionRepo = mock(ReactionRepository.class); + PostSubscriptionRepository subRepo = mock(PostSubscriptionRepository.class); + NotificationRepository notificationRepo = mock(NotificationRepository.class); + PostReadService postReadService = mock(PostReadService.class); + ImageUploader imageUploader = mock(ImageUploader.class); + TaskScheduler taskScheduler = mock(TaskScheduler.class); + EmailSender emailSender = mock(EmailSender.class); + ApplicationContext context = mock(ApplicationContext.class); + PointService pointService = mock(PointService.class); + PostChangeLogService postChangeLogService = mock(PostChangeLogService.class); + PointHistoryRepository pointHistoryRepository = mock(PointHistoryRepository.class); + RedisTemplate redisTemplate = mock(RedisTemplate.class); + + PostService service = new PostService(postRepo, userRepo, catRepo, tagRepo, lotteryRepo, + pollPostRepo, pollVoteRepo, notifService, subService, commentService, commentRepo, + reactionRepo, subRepo, notificationRepo, postReadService, + imageUploader, taskScheduler, emailSender, context, pointService, postChangeLogService, + pointHistoryRepository, PublishMode.DIRECT, redisTemplate); + when(context.getBean(PostService.class)).thenReturn(service); + + Post post = new Post(); + post.setId(10L); + User author = new User(); + author.setId(20L); + author.setRole(Role.USER); + post.setAuthor(author); + + User historyUser = new User(); + historyUser.setId(30L); + + PointHistory history = new PointHistory(); + history.setUser(historyUser); + history.setPost(post); + + when(postRepo.findById(10L)).thenReturn(Optional.of(post)); + when(userRepo.findByUsername("author")).thenReturn(Optional.of(author)); + when(commentRepo.findByPostAndParentIsNullOrderByCreatedAtAsc(post)).thenReturn(List.of()); + when(reactionRepo.findByPost(post)).thenReturn(List.of()); + when(subRepo.findByPost(post)).thenReturn(List.of()); + when(notificationRepo.findByPost(post)).thenReturn(List.of()); + when(pointHistoryRepository.findByPost(post)).thenReturn(List.of(history)); + when(pointService.recalculateUserPoints(historyUser)).thenReturn(0); + + service.deletePost(10L, "author"); + + ArgumentCaptor> captor = ArgumentCaptor.forClass(List.class); + verify(pointHistoryRepository).saveAll(captor.capture()); + List savedHistories = captor.getValue(); + assertEquals(1, savedHistories.size()); + PointHistory savedHistory = savedHistories.get(0); + assertNull(savedHistory.getPost()); + assertNotNull(savedHistory.getDeletedAt()); + assertTrue(savedHistory.getDeletedAt().isBefore(LocalDateTime.now().plusSeconds(1))); + + verify(pointService).recalculateUserPoints(historyUser); + verify(userRepo).saveAll(any()); + } + @Test void finalizeLotteryNotifiesAuthor() { PostRepository postRepo = mock(PostRepository.class); From 5d499956d7a74685282ccc8a5c1ee0f1756d7327 Mon Sep 17 00:00:00 2001 From: Tim <135014430+nagisa77@users.noreply.github.com> Date: Wed, 17 Sep 2025 13:30:58 +0800 Subject: [PATCH 25/26] Delete post change logs before removing posts --- .../java/com/openisle/repository/PostChangeLogRepository.java | 2 ++ .../main/java/com/openisle/service/PostChangeLogService.java | 4 ++++ backend/src/main/java/com/openisle/service/PostService.java | 1 + .../src/test/java/com/openisle/service/PostServiceTest.java | 1 + 4 files changed, 8 insertions(+) diff --git a/backend/src/main/java/com/openisle/repository/PostChangeLogRepository.java b/backend/src/main/java/com/openisle/repository/PostChangeLogRepository.java index c9e700fc0..324ac8506 100644 --- a/backend/src/main/java/com/openisle/repository/PostChangeLogRepository.java +++ b/backend/src/main/java/com/openisle/repository/PostChangeLogRepository.java @@ -8,4 +8,6 @@ import java.util.List; public interface PostChangeLogRepository extends JpaRepository { List findByPostOrderByCreatedAtAsc(Post post); + + void deleteByPost(Post post); } diff --git a/backend/src/main/java/com/openisle/service/PostChangeLogService.java b/backend/src/main/java/com/openisle/service/PostChangeLogService.java index aeb6c2bc5..ec15508d1 100644 --- a/backend/src/main/java/com/openisle/service/PostChangeLogService.java +++ b/backend/src/main/java/com/openisle/service/PostChangeLogService.java @@ -109,6 +109,10 @@ public class PostChangeLogService { logRepository.save(log); } + public void deleteLogsForPost(Post post) { + logRepository.deleteByPost(post); + } + public List listLogs(Long postId) { Post post = postRepository.findById(postId) .orElseThrow(() -> new com.openisle.exception.NotFoundException("Post not found")); diff --git a/backend/src/main/java/com/openisle/service/PostService.java b/backend/src/main/java/com/openisle/service/PostService.java index daddffe5e..a948bf801 100644 --- a/backend/src/main/java/com/openisle/service/PostService.java +++ b/backend/src/main/java/com/openisle/service/PostService.java @@ -888,6 +888,7 @@ public class PostService { } } String title = post.getTitle(); + postChangeLogService.deleteLogsForPost(post); postRepository.delete(post); if (adminDeleting) { notificationService.createNotification(author, NotificationType.POST_DELETED, diff --git a/backend/src/test/java/com/openisle/service/PostServiceTest.java b/backend/src/test/java/com/openisle/service/PostServiceTest.java index 46efaa5c0..b6997d59e 100644 --- a/backend/src/test/java/com/openisle/service/PostServiceTest.java +++ b/backend/src/test/java/com/openisle/service/PostServiceTest.java @@ -71,6 +71,7 @@ class PostServiceTest { verify(postReadService).deleteByPost(post); verify(postRepo).delete(post); + verify(postChangeLogService).deleteLogsForPost(post); } @Test From 6baa4d423363528207adcf1dfc916447c884f5c5 Mon Sep 17 00:00:00 2001 From: Tim Date: Wed, 17 Sep 2025 13:37:52 +0800 Subject: [PATCH 26/26] =?UTF-8?q?fix:=20=E7=AE=80=E5=8D=95=E8=B0=83?= =?UTF-8?q?=E6=95=B4=E6=8C=89=E9=92=AE=E6=A0=BC=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend_nuxt/assets/global.css | 4 ++-- frontend_nuxt/pages/users/[id].vue | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/frontend_nuxt/assets/global.css b/frontend_nuxt/assets/global.css index 3d610cc33..edb5f246b 100644 --- a/frontend_nuxt/assets/global.css +++ b/frontend_nuxt/assets/global.css @@ -2,8 +2,8 @@ --primary-color-hover: rgb(9, 95, 105); --primary-color: rgb(10, 110, 120); --primary-color-disabled: rgba(93, 152, 156, 0.5); - --secondary-color:rgb(255, 255, 255); - --secondary-color-hover:rgba(165, 255, 255, 0.447); + --secondary-color: rgb(255, 255, 255); + --secondary-color-hover: rgba(10, 111, 120, 0.184); --new-post-icon-color: rgba(10, 111, 120, 0.598); --header-height: 60px; --header-background-color: white; diff --git a/frontend_nuxt/pages/users/[id].vue b/frontend_nuxt/pages/users/[id].vue index 0e7107964..b78aa56f6 100644 --- a/frontend_nuxt/pages/users/[id].vue +++ b/frontend_nuxt/pages/users/[id].vue @@ -712,13 +712,13 @@ watch(selectedTab, async (val) => { border-radius: 8px; padding: 5px 10px; color: var(--primary-color); - background-color: var(--secondary-color); border: 1px solid var(--primary-color); margin-top: 15px; width: fit-content; cursor: pointer; } +.profile-page-header-unsubscribe-button:hover, .profile-page-header-send-mail-button:hover { background-color: var(--secondary-color-hover); }