diff --git a/apps/electron/package.json b/apps/electron/package.json index 9f165cb01b..3cd5038b2f 100644 --- a/apps/electron/package.json +++ b/apps/electron/package.json @@ -17,6 +17,9 @@ "electron-builder": "26.9.1", "wait-on": "^7.2.0" }, + "dependencies": { + "@stagetimerio/grandiose": "0.2.0" + }, "scripts": { "dev:electron": "wait-on http://localhost:3000 && cross-env NODE_ENV=development electron .", "lint": "oxlint --quiet --type-aware", @@ -28,6 +31,9 @@ "productName": "ontime", "appId": "no.lightdev.ontime", "asar": true, + "asarUnpack": [ + "node_modules/@stagetimerio/grandiose/dist/**" + ], "dmg": { "artifactName": "ontime-macOS-${arch}.dmg" }, diff --git a/apps/electron/src/main.js b/apps/electron/src/main.js index c6dffd9074..59254ba202 100644 --- a/apps/electron/src/main.js +++ b/apps/electron/src/main.js @@ -3,6 +3,7 @@ const path = require('path'); const { getApplicationMenu } = require('./menu/applicationMenu.js'); const { getTrayMenu } = require('./menu/trayMenu.js'); +const { NdiOutputManager } = require('./ndi/NdiOutputManager.js'); const electronConfig = require('./electron.config.js'); const { @@ -35,6 +36,8 @@ let isQuitting = false; let win; let splash; let tray = null; +let ndiOutputManager; +let refreshApplicationMenu = () => {}; /** * Coordinates the node process startup @@ -76,6 +79,8 @@ function showNotification(title, body) { * Terminate node service and close electron app */ function appShutdown() { + ndiOutputManager?.stopAll(); + // terminate node service (async () => { const ontimeServer = require(nodePath); @@ -199,14 +204,29 @@ app.whenReady().then(() => { } createWindow(); + ndiOutputManager = new NdiOutputManager({ + icon: appIcon, + onError: (title, message) => dialog.showErrorBox(title, message), + }); + startBackend() .then((port) => { const clientUrl = getClientUrl(port); const serverUrl = getServerUrl(port); - const menu = getApplicationMenu(askToQuit, clientUrl, serverUrl, redirectWindow, showDialog, (url) => - win.webContents.downloadURL(url), - ); - Menu.setApplicationMenu(menu); + refreshApplicationMenu = () => { + const menu = getApplicationMenu( + askToQuit, + clientUrl, + serverUrl, + redirectWindow, + showDialog, + (url) => win.webContents.downloadURL(url), + ndiOutputManager, + refreshApplicationMenu, + ); + Menu.setApplicationMenu(menu); + }; + refreshApplicationMenu(); win .loadURL(`${clientUrl}/editor`) diff --git a/apps/electron/src/menu/applicationMenu.js b/apps/electron/src/menu/applicationMenu.js index bc96d52359..36a166f399 100644 --- a/apps/electron/src/menu/applicationMenu.js +++ b/apps/electron/src/menu/applicationMenu.js @@ -23,14 +23,26 @@ const { * @param {function} redirectWindow - function to redirect main window content * @param {function} showDialog - asks the react app to show a user dialog * @param {function} download - function to download a resource from url + * @param {import('../ndi/NdiOutputManager.js').NdiOutputManager} ndiOutputManager - NDI output manager + * @param {function} refreshMenu - rebuilds the application menu * @returns {Menu} - application menu */ -function getApplicationMenu(askToQuit, clientUrl, serverUrl, redirectWindow, showDialog, download) { +function getApplicationMenu( + askToQuit, + clientUrl, + serverUrl, + redirectWindow, + showDialog, + download, + ndiOutputManager, + refreshMenu, +) { const template = [ ...(isMac ? [makeMacMenu(askToQuit)] : []), makeFileMenu(askToQuit, serverUrl, redirectWindow, showDialog, download), makeEditMenu(), makeViewMenu(clientUrl), + makeNdiMenu(clientUrl, ndiOutputManager, refreshMenu), makeSettingsMenu(redirectWindow), makeHelpMenu(redirectWindow), ...(isProduction ? [] : [{ label: 'Dev', submenu: [{ role: 'toggleDevTools' }] }]), @@ -173,6 +185,91 @@ function makeViewMenu(clientUrl) { }; } +const ndiViews = [ + { id: 'timer', label: 'Timer', path: '/timer' }, + { id: 'backstage', label: 'Backstage', path: '/backstage' }, + { id: 'studio', label: 'Studio Clock', path: '/studio' }, + { id: 'countdown', label: 'Countdown', path: '/countdown' }, + { id: 'info', label: 'Project info', path: '/info' }, +]; + +const ndiResolutions = [ + { label: '720p', width: 1280, height: 720 }, + { label: '1080p', width: 1920, height: 1080 }, + { label: '1440p', width: 2560, height: 1440 }, + { label: '2160p', width: 3840, height: 2160 }, +]; + +const ndiFrameRates = [25, 30, 50, 60]; + +/** + * Utility function generates the NDI menu + * @param {string} clientUrl - base url for the application + * @param {import('../ndi/NdiOutputManager.js').NdiOutputManager} ndiOutputManager - NDI output manager + * @param {function} refreshMenu - rebuilds the application menu + * @returns {Object} + */ +function makeNdiMenu(clientUrl, ndiOutputManager, refreshMenu) { + const format = ndiOutputManager.getFormat(); + const hasActiveOutputs = ndiViews.some((view) => ndiOutputManager.isActive(view.id)); + + return { + label: 'NDI', + submenu: [ + { + label: `Resolution: ${format.width}x${format.height}`, + submenu: ndiResolutions.map((resolution) => ({ + label: `${resolution.label} (${resolution.width}x${resolution.height})`, + type: 'radio', + checked: format.width === resolution.width && format.height === resolution.height, + click: async () => { + await ndiOutputManager.setFormat(resolution); + refreshMenu(); + }, + })), + }, + { + label: `Frame rate: ${format.fps}fps`, + submenu: ndiFrameRates.map((fps) => ({ + label: `${fps}fps`, + type: 'radio', + checked: format.fps === fps, + click: async () => { + await ndiOutputManager.setFormat({ fps }); + refreshMenu(); + }, + })), + }, + { type: 'separator' }, + ...ndiViews.map((view) => ({ + label: `Output ${view.label}`, + type: 'checkbox', + checked: ndiOutputManager.isActive(view.id), + click: async () => { + if (ndiOutputManager.isActive(view.id)) { + ndiOutputManager.stopOutput(view.id); + } else { + await ndiOutputManager.startOutput(view.id, { + name: `Ontime ${view.label}`, + url: `${clientUrl}${view.path}?n=1`, + }); + } + refreshMenu(); + }, + })), + { type: 'separator' }, + { + label: 'Stop all NDI outputs', + enabled: hasActiveOutputs, + click: () => { + ndiOutputManager.stopAll(); + refreshMenu(); + }, + }, + ], + }; +} + /** * Utility function generates the settings menu * @param {function} redirectWindow - function to redirect main window content diff --git a/apps/electron/src/ndi/NdiOutputManager.js b/apps/electron/src/ndi/NdiOutputManager.js new file mode 100644 index 0000000000..c29a329128 --- /dev/null +++ b/apps/electron/src/ndi/NdiOutputManager.js @@ -0,0 +1,213 @@ +const { BrowserWindow } = require('electron'); + +const FOURCC_BGRA = 1095911234; +const DEFAULT_WIDTH = 1920; +const DEFAULT_HEIGHT = 1080; +const DEFAULT_FPS = 50; + +function loadGrandiose() { + try { + return require('@stagetimerio/grandiose'); + } catch (error) { + return { error }; + } +} + +function getBitmapFrame(image) { + const scaleFactors = image.getScaleFactors(); + const scaleFactor = scaleFactors.at(-1) ?? 1; + const data = image.toBitmap({ scaleFactor }); + let { width, height } = image.getSize(scaleFactor); + + if (data.length !== width * height * 4) { + const scale = Math.sqrt(data.length / (width * height * 4)); + width = Math.round(width * scale); + height = Math.round(height * scale); + } + + return { data, width, height }; +} + +function makeFrame(grandiose, image, fps) { + const { data, width, height } = getBitmapFrame(image); + + return { + xres: width, + yres: height, + frameRateN: fps * 1000, + frameRateD: 1000, + fourCC: grandiose.FOURCC_BGRA ?? FOURCC_BGRA, + pictureAspectRatio: width / height, + frameFormatType: grandiose.FORMAT_TYPE_PROGRESSIVE, + lineStrideBytes: width * 4, + data, + }; +} + +class NdiOutputManager { + constructor({ icon, onError }) { + this.icon = icon; + this.onError = onError; + this.outputs = new Map(); + this.format = { + width: DEFAULT_WIDTH, + height: DEFAULT_HEIGHT, + fps: DEFAULT_FPS, + }; + } + + isAvailable() { + const grandiose = loadGrandiose(); + return !grandiose.error && grandiose.isSupportedCPU(); + } + + isActive(id) { + return this.outputs.has(id); + } + + getFormat() { + return { ...this.format }; + } + + async setFormat(format) { + this.format = { + width: format.width ?? this.format.width, + height: format.height ?? this.format.height, + fps: format.fps ?? this.format.fps, + }; + + const activeOutputs = Array.from(this.outputs.values()).map((output) => output.options); + this.stopAll(); + + for (const outputOptions of activeOutputs) { + await this.startOutput(outputOptions.id, outputOptions); + } + } + + async startOutput(id, options) { + if (this.outputs.has(id)) { + return; + } + + const grandiose = loadGrandiose(); + if (grandiose.error) { + this.handleError( + 'NDI is unavailable', + 'The grandiose native NDI module could not be loaded. Install dependencies and rebuild native modules for Electron.', + grandiose.error, + ); + return; + } + + if (!grandiose.isSupportedCPU()) { + this.handleError('NDI is unavailable', 'This CPU is not supported by the installed NDI runtime.'); + return; + } + + const width = options.width ?? this.format.width; + const height = options.height ?? this.format.height; + const fps = options.fps ?? this.format.fps; + const output = { + id, + name: options.name, + options: { + ...options, + id, + }, + sender: null, + window: null, + sending: false, + pendingFrame: null, + }; + + try { + output.sender = await grandiose.send({ + name: options.name, + clockVideo: true, + clockAudio: false, + }); + + output.window = new BrowserWindow({ + width, + height, + show: false, + frame: false, + icon: this.icon, + paintWhenInitiallyHidden: true, + webPreferences: { + offscreen: true, + nodeIntegration: false, + contextIsolation: true, + backgroundThrottling: false, + }, + }); + + output.window.webContents.setFrameRate(fps); + output.window.webContents.setBackgroundThrottling(false); + output.window.webContents.on('paint', (_event, _dirty, image) => { + output.pendingFrame = makeFrame(grandiose, image, fps); + this.flushFrame(output); + }); + output.window.once('closed', () => { + this.outputs.delete(id); + }); + + this.outputs.set(id, output); + await output.window.loadURL(options.url); + } catch (error) { + this.stopOutput(id); + this.handleError('Could not start NDI output', `Failed to start ${options.name}.`, error); + } + } + + async flushFrame(output) { + if (output.sending || !output.pendingFrame || !output.sender) { + return; + } + + const frame = output.pendingFrame; + output.pendingFrame = null; + output.sending = true; + + try { + await output.sender.video(frame); + } catch (error) { + this.handleError('NDI output error', `Failed to send a frame for ${output.name}.`, error); + this.stopOutput(output.id); + } finally { + output.sending = false; + if (output.pendingFrame) { + this.flushFrame(output); + } + } + } + + stopOutput(id) { + const output = this.outputs.get(id); + if (!output) { + return; + } + + this.outputs.delete(id); + output.window?.destroy(); + output.sender?.destroy?.().catch((error) => { + this.handleError('NDI output error', `Failed to stop ${output.name}.`, error); + }); + output.sender = null; + } + + stopAll() { + for (const id of this.outputs.keys()) { + this.stopOutput(id); + } + } + + handleError(title, message, error) { + if (error) { + console.error(title, error); + } + this.onError?.(title, message); + } +} + +module.exports = { NdiOutputManager }; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8e3ec0331c..38a1825c77 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -196,6 +196,10 @@ importers: version: 4.0.17(@types/node@25.4.0)(happy-dom@20.9.0)(jiti@2.6.1)(lightningcss@1.32.0)(sass@1.92.0)(terser@5.46.2)(tsx@4.20.5) apps/electron: + dependencies: + '@stagetimerio/grandiose': + specifier: 0.2.0 + version: 0.2.0 devDependencies: electron: specifier: 38.2.1 @@ -1505,6 +1509,9 @@ packages: '@jridgewell/trace-mapping@0.3.30': resolution: {integrity: sha512-GQ7Nw5G2lTu/BtHTKfXhKHok2WGetd4XYcVKGx00SjAk8GMwgJM3zr6zORiPGuOE+/vkc90KtTosSSvaCjKb2Q==} + '@keyv/serialize@1.1.1': + resolution: {integrity: sha512-dXn3FZhPv0US+7dtJsIi2R+c7qWYiReoEh5zUntWCf4oSpMNib8FDhSoed6m3QyZdx5hK7iLFkYk3rNxwt8vTA==} + '@lezer/common@1.5.1': resolution: {integrity: sha512-6YRVG9vBkaY7p1IVxL4s44n5nUnaNnGM2/AckNgYOnxTG2kWh1vR8BMxPseWPjRNpb5VtXnMpeYAEAADoRV1Iw==} @@ -1536,6 +1543,18 @@ packages: '@napi-rs/wasm-runtime@1.1.1': resolution: {integrity: sha512-p64ah1M1ld8xjWv3qbvFwHiFVWrq1yFvV4f7w+mzaqiR4IlSgkqhcRdHwsGgomwzBH51sRY4NEowLxnaBjcW/A==} + '@nodelib/fs.scandir@2.1.5': + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + + '@nodelib/fs.stat@2.0.5': + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} + + '@nodelib/fs.walk@1.2.8': + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} + '@oxc-project/types@0.120.0': resolution: {integrity: sha512-k1YNu55DuvAip/MGE1FTsIuU3FUCn6v/ujG9V7Nq5Df/kX2CWb13hhwD0lmJGMGqE+bE1MXvv9SZVnMzEXlWcg==} @@ -2258,6 +2277,9 @@ packages: cpu: [x64] os: [win32] + '@sec-ant/readable-stream@0.4.1': + resolution: {integrity: sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg==} + '@sentry-internal/browser-utils@10.9.0': resolution: {integrity: sha512-TqTFvD4jw8uq4uYTrQAZvQx7iz7eZzHjMBaiuPj5v9nt9nfb5SZU+EOV49aaSdNspf0UF+meq1xLDWaHY5Ogug==} engines: {node: '>=18'} @@ -2371,6 +2393,17 @@ packages: resolution: {integrity: sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==} engines: {node: '>=10'} + '@sindresorhus/is@7.2.0': + resolution: {integrity: sha512-P1Cz1dWaFfR4IR+U13mqqiGsLFf1KbayybWwdd2vfctdV6hDpUkgCY0nKOLLTMSoRd/jJNjtbqzf13K8DCCXQw==} + engines: {node: '>=18'} + + '@sindresorhus/merge-streams@4.0.0': + resolution: {integrity: sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==} + engines: {node: '>=18'} + + '@stagetimerio/grandiose@0.2.0': + resolution: {integrity: sha512-sNu2sba0UFI0a8Ip5Z6DiWnW4fmr5pN5rm/Ix4pF/wGgOTWDx5dzAz4IFJhx+qkjsnAussm3b6uMwI7bNoOIHg==} + '@standard-schema/spec@1.1.0': resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==} @@ -2569,6 +2602,9 @@ packages: '@types/http-cache-semantics@4.0.4': resolution: {integrity: sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==} + '@types/http-cache-semantics@4.2.0': + resolution: {integrity: sha512-L3LgimLHXtGkWikKnsPg0/VFx9OGZaC+eN1u4r+OB1XRqH3meBIAVC2zr1WdMH+RHmnRkqliQAOHNJ/E0j/e0Q==} + '@types/jsesc@2.5.1': resolution: {integrity: sha512-9VN+6yxLOPLOav+7PwjZbxiID2bVaeq0ED4qSQmdQTdjnXJSaCVKTR58t15oqH1H5t8Ng2ZX1SabJVoN9Q34bw==} @@ -2880,6 +2916,10 @@ packages: resolution: {integrity: sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==} engines: {node: '>=10.16.0'} + byte-counter@0.1.0: + resolution: {integrity: sha512-jheRLVMeUKrDBjVw2O5+k4EvR4t9wtxHL+bo/LxfkxsVeuGMy3a5SEGgXdAFA4FSzTrU8rQXQIrsZ3oBq5a0pQ==} + engines: {node: '>=20'} + bytes@3.1.2: resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} engines: {node: '>= 0.8'} @@ -2892,6 +2932,14 @@ packages: resolution: {integrity: sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==} engines: {node: '>=10.6.0'} + cacheable-lookup@7.0.0: + resolution: {integrity: sha512-+qJyx4xiKra8mZrcwhjMRMUhD5NR1R8esPkzIYxX96JiecFoxAXFuz/GpR3+ev4PE1WamHip78wV0vcmPQtp8w==} + engines: {node: '>=14.16'} + + cacheable-request@13.0.19: + resolution: {integrity: sha512-SVXGH037+Mo1aIMO5B2UcleR43FGjFdN+M8JObSyEoQ2Mn4CODRWx28gN5jiTF0n5ItsgtIZfyargMNs8GX4kg==} + engines: {node: '>=18'} + cacheable-request@7.0.4: resolution: {integrity: sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg==} engines: {node: '>=8'} @@ -3076,6 +3124,10 @@ packages: resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} engines: {node: '>= 8'} + cross-zip@4.0.1: + resolution: {integrity: sha512-n63i0lZ0rvQ6FXiGQ+/JFCKAUyPFhLQYJIqKaa+tSJtfKeULF/IDNDAbdnSIxgS4NTuw2b0+lj8LzfITuq+ZxQ==} + engines: {node: '>=12.10'} + csstype@3.1.2: resolution: {integrity: sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==} @@ -3095,6 +3147,10 @@ packages: resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==} engines: {node: '>=0.10.0'} + decompress-response@10.0.0: + resolution: {integrity: sha512-oj7KWToJuuxlPr7VV0vabvxEIiqNMo+q0NueIiL3XhtwC6FVOX7Hr1c0C4eD0bmf7Zr+S/dSf2xvkH3Ad6sU3Q==} + engines: {node: '>=20'} + decompress-response@6.0.0: resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==} engines: {node: '>=10'} @@ -3305,6 +3361,14 @@ packages: resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} engines: {node: '>= 0.6'} + execa@5.1.1: + resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} + engines: {node: '>=10'} + + execa@9.6.1: + resolution: {integrity: sha512-9Be3ZoN4LmYR90tUoVu2te2BsbzHfhJyfEiAVfz7N5/zv+jduIfLrV2xdQXOHbaD6KgpGdO9PRPM1Y4Q9QkPkA==} + engines: {node: ^18.19.0 || >=20.5.0} + expect-type@1.3.0: resolution: {integrity: sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==} engines: {node: '>=12.0.0'} @@ -3342,9 +3406,16 @@ packages: resolution: {integrity: sha512-V7/RktU11J3I36Nwq2JnZEM7tNm17eBJz+u25qdxBZeCKiX6BkVSZQjwWIr+IobgnZy+ag73tTZgZi7tr0LrBw==} engines: {node: '>=6.0.0'} + fast-glob@3.3.3: + resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==} + engines: {node: '>=8.6.0'} + fast-json-stable-stringify@2.1.0: resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + fastq@1.20.1: + resolution: {integrity: sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==} + fd-slicer@1.1.0: resolution: {integrity: sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==} @@ -3357,6 +3428,10 @@ packages: picomatch: optional: true + figures@6.1.0: + resolution: {integrity: sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg==} + engines: {node: '>=18'} + filelist@1.0.6: resolution: {integrity: sha512-5giy2PkLYY1cP39p17Ech+2xlpTRL9HLspOfEgm0L6CwBXBTgsK5ou0JtzYuepxkaQ/tvhCFIJ5uXo0OrM2DxA==} @@ -3389,6 +3464,10 @@ packages: resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} engines: {node: '>=14'} + form-data-encoder@4.1.0: + resolution: {integrity: sha512-G6NsmEW15s0Uw9XnCg+33H3ViYRyiM0hMrMhhqQOR8NFc5GhYrI+6I3u7OTw7b91J2g8rtvMBZJDbcGb2YUniw==} + engines: {node: '>= 18'} + form-data@4.0.5: resolution: {integrity: sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==} engines: {node: '>= 6'} @@ -3469,9 +3548,21 @@ packages: resolution: {integrity: sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==} engines: {node: '>=8'} + get-stream@6.0.1: + resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} + engines: {node: '>=10'} + + get-stream@9.0.1: + resolution: {integrity: sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA==} + engines: {node: '>=18'} + get-tsconfig@4.13.7: resolution: {integrity: sha512-7tN6rFgBlMgpBML5j8typ92BKFi2sFQvIdpAqLA2beia5avZDrMs0FLZiM5etShWq5irVyGcGMEA1jcDaK7A/Q==} + glob-parent@5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + glob@11.1.0: resolution: {integrity: sha512-vuNwKSaKiqm7g0THUBu2x7ckSs3XJLXE+2ssL7/MfTGPLLcrJQ/4Uq1CjPTtO5cCIiRxqvN6Twy1qOwhL0Xjcw==} engines: {node: 20 || >=22} @@ -3510,6 +3601,10 @@ packages: resolution: {integrity: sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==} engines: {node: '>=10.19.0'} + got@14.6.6: + resolution: {integrity: sha512-QLV1qeYSo5l13mQzWgP/y0LbMr5Plr5fJilgAIwgnwseproEbtNym8xpLsDzeZ6MWXgNE6kdWGBjdh3zT/Qerg==} + engines: {node: '>=20'} + graceful-fs@4.2.11: resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} @@ -3565,6 +3660,10 @@ packages: resolution: {integrity: sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==} engines: {node: '>=10.19.0'} + http2-wrapper@2.2.1: + resolution: {integrity: sha512-V5nVw1PAOgfI3Lmeaj2Exmeg7fenjhRUgz1lPSezy1CuhPYbgQtbQj4jZfEAEMlaL+vupsvhjqCyjzob0yxsmQ==} + engines: {node: '>=10.19.0'} + https-proxy-agent@5.0.1: resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} engines: {node: '>= 6'} @@ -3573,6 +3672,14 @@ packages: resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==} engines: {node: '>= 14'} + human-signals@2.1.0: + resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} + engines: {node: '>=10.17.0'} + + human-signals@8.0.1: + resolution: {integrity: sha512-eKCa6bwnJhvxj14kZk5NCPc6Hb6BdsU9DZcOnmQKSnO1VKrfV0zCvtttPZUsBvjmNDn8rpcJfpwSYnHBjc95MQ==} + engines: {node: '>=18.18.0'} + iconv-corefoundation@1.1.7: resolution: {integrity: sha512-T10qvkw0zz4wnm560lOEg0PovVqUXuOFhhHAkixw8/sycy7TJt7v/RrkEKEQnAw2viPSJu6iAkErxnzR0g8PpQ==} engines: {node: ^8.11.2 || >=10} @@ -3630,6 +3737,10 @@ packages: resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} engines: {node: '>=0.12.0'} + is-plain-obj@4.1.0: + resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==} + engines: {node: '>=12'} + is-promise@4.0.0: resolution: {integrity: sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==} @@ -3637,6 +3748,14 @@ packages: resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} engines: {node: '>=8'} + is-stream@4.0.1: + resolution: {integrity: sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==} + engines: {node: '>=18'} + + is-unicode-supported@2.1.0: + resolution: {integrity: sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==} + engines: {node: '>=18'} + isbinaryfile@4.0.10: resolution: {integrity: sha512-iHrqe5shvBUcFbmZq9zOQHBoeOhZJu6RQGrDpBgenUm/Am+F3JM2MgQj+rK3Z601fzrL5gLZWtAPH2OBaSVcyw==} engines: {node: '>= 8.0.0'} @@ -3719,6 +3838,9 @@ packages: keyv@4.5.4: resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} + keyv@5.6.0: + resolution: {integrity: sha512-CYDD3SOtsHtyXeEORYRx2qBtpDJFjRTGXUtmNEMGyzYOKj1TE3tycdlho7kA1Ufx9OYWZzg52QFBGALTirzDSw==} + lazy-val@1.0.5: resolution: {integrity: sha512-0/BnGCCfyUMkBpeDgWihanIAF9JmZhHBgUhEqzvf+adhNGLoP6TaiI5oF8oyb3I45P+PcnrqihSf01M0l0G5+Q==} @@ -3824,6 +3946,10 @@ packages: resolution: {integrity: sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==} engines: {node: '>=8'} + lowercase-keys@3.0.0: + resolution: {integrity: sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + lru-cache@11.3.6: resolution: {integrity: sha512-Gf/KoL3C/MlI7Bt0PGI9I+TeTC/I6r/csU58N4BSNc4lppLBeKsOdFYkK+dX0ABDUMJNfCHTyPpzwwO21Awd3A==} engines: {node: 20 || >=22} @@ -3862,6 +3988,13 @@ packages: resolution: {integrity: sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==} engines: {node: '>=18'} + merge-stream@2.0.0: + resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} + + merge2@1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} + micromatch@4.0.8: resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} engines: {node: '>=8.6'} @@ -3887,6 +4020,10 @@ packages: engines: {node: '>=4.0.0'} hasBin: true + mimic-fn@2.1.0: + resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} + engines: {node: '>=6'} + mimic-response@1.0.1: resolution: {integrity: sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==} engines: {node: '>=4'} @@ -3895,6 +4032,10 @@ packages: resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==} engines: {node: '>=10'} + mimic-response@4.0.0: + resolution: {integrity: sha512-e5ISH9xMYU0DzrT+jl8q2ze9D6eWBto+I8CNpe+VI+K2J/F/k3PdkdTdz4wvGVH4NTpo+NRYTVIuMQEMMcsLqg==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + minimatch@10.2.4: resolution: {integrity: sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==} engines: {node: 18 || 20 || >=22} @@ -3925,6 +4066,11 @@ packages: resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==} hasBin: true + mkdirp@3.0.1: + resolution: {integrity: sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==} + engines: {node: '>=10'} + hasBin: true + ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} @@ -3988,6 +4134,18 @@ packages: resolution: {integrity: sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==} engines: {node: '>=10'} + normalize-url@8.1.1: + resolution: {integrity: sha512-JYc0DPlpGWB40kH5g07gGTrYuMqV653k3uBKY6uITPWds3M0ov3GaWGp9lbE3Bzngx8+XkfzgvASb9vk9JDFXQ==} + engines: {node: '>=14.16'} + + npm-run-path@4.0.1: + resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} + engines: {node: '>=8'} + + npm-run-path@6.0.0: + resolution: {integrity: sha512-9qny7Z9DsQU8Ou39ERsPU4OZQlSTP47ShQzuKZ6PRXpYLtIFgl/DEBYEXKlvcEa+9tHVcK8CF81Y2V72qaZhWA==} + engines: {node: '>=18'} + object-assign@4.1.1: resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} engines: {node: '>=0.10.0'} @@ -4014,6 +4172,10 @@ packages: once@1.4.0: resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + onetime@5.1.2: + resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} + engines: {node: '>=6'} + osc-min@2.1.2: resolution: {integrity: sha512-dEhg7wBJ+QTHqY4iwnctkaFWzXLq+yHA2olxYfnxBw1fMy/iWJ/b7ovfXfwc/yxLXGiUHQhTxlQSHzL8ueHz6Q==} engines: {node: '>=0.10.0'} @@ -4041,6 +4203,10 @@ packages: resolution: {integrity: sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==} engines: {node: '>=8'} + p-cancelable@4.0.1: + resolution: {integrity: sha512-wBowNApzd45EIKdO1LaU+LrMBwAcjfPaYtVzV3lmfM3gf8Z4CHZsiIqlM8TZZ8okYvh5A1cP6gTfCRQtwUpaUg==} + engines: {node: '>=14.16'} + p-limit@2.3.0: resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} engines: {node: '>=6'} @@ -4072,6 +4238,10 @@ packages: resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} engines: {node: '>=8'} + parse-ms@4.0.0: + resolution: {integrity: sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw==} + engines: {node: '>=18'} + parseurl@1.3.3: resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} engines: {node: '>= 0.8'} @@ -4088,6 +4258,10 @@ packages: resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} engines: {node: '>=8'} + path-key@4.0.0: + resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==} + engines: {node: '>=12'} + path-parse@1.0.7: resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} @@ -4151,6 +4325,10 @@ packages: engines: {node: '>=14.0.0'} hasBin: true + pretty-ms@9.3.0: + resolution: {integrity: sha512-gjVS5hOP+M3wMm5nmNOucbIrqudzs9v/57bWRHQWLYklXqoXKrVfYW2W9+glfGsqtPgpiz5WwyEEB+ksXIx3gQ==} + engines: {node: '>=18'} + proc-log@6.1.0: resolution: {integrity: sha512-iG+GYldRf2BQ0UDUAd6JQ/RwzaQy6mXmsk/IzlYyal4A4SNFw54MeH4/tLkF4I5WoWG9SQwuqWzS99jaFQHBuQ==} engines: {node: ^20.17.0 || >=22.9.0} @@ -4192,6 +4370,9 @@ packages: quansync@1.0.0: resolution: {integrity: sha512-5xZacEEufv3HSTPQuchrvV6soaiACMFnq1H8wkVioctoH3TRha9Sz66lOxRwPK/qZj7HPiSveih9yAyh98gvqA==} + queue-microtask@1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + quick-lru@5.1.1: resolution: {integrity: sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==} engines: {node: '>=10'} @@ -4321,10 +4502,18 @@ packages: responselike@2.0.1: resolution: {integrity: sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==} + responselike@4.0.2: + resolution: {integrity: sha512-cGk8IbWEAnaCpdAt1BHzJ3Ahz5ewDJa0KseTsE3qIRMJ3C698W8psM7byCeWVpd/Ha7FUYzuRVzXoKoM6nRUbA==} + engines: {node: '>=20'} + retry@0.12.0: resolution: {integrity: sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==} engines: {node: '>= 4'} + reusify@1.1.0: + resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + rimraf@2.6.3: resolution: {integrity: sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==} deprecated: Rimraf versions prior to v4 are no longer supported @@ -4377,6 +4566,9 @@ packages: resolution: {integrity: sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==} engines: {node: '>= 18'} + run-parallel@1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + rxjs@7.8.1: resolution: {integrity: sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==} @@ -4449,6 +4641,10 @@ packages: resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} engines: {node: '>=8'} + shelljs@0.10.0: + resolution: {integrity: sha512-Jex+xw5Mg2qMZL3qnzXIfaxEtBaC4n7xifqaqtrZDdlheR70OGkydrPJWT0V1cA1k3nanC86x9FwAmQl6w3Klw==} + engines: {node: '>=18'} + side-channel-list@1.0.0: resolution: {integrity: sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==} engines: {node: '>= 0.4'} @@ -4541,6 +4737,14 @@ packages: resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} engines: {node: '>=8'} + strip-final-newline@2.0.0: + resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} + engines: {node: '>=6'} + + strip-final-newline@4.0.0: + resolution: {integrity: sha512-aulFJcD6YK8V1G7iRB5tigAP4TsHBZZrOV8pjV++zdUwmeV8uzbY7yn6h9MswN62adStNZFuCIx4haBnRuMDaw==} + engines: {node: '>=18'} + style-mod@4.1.3: resolution: {integrity: sha512-i/n8VsZydrugj3Iuzll8+x/00GH2vnYsk1eomD8QiRrSAeW6ItbCQDtfXCeJHd0iwiNagqjQkvpvREEPtW3IoQ==} @@ -4683,6 +4887,10 @@ packages: resolution: {integrity: sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==} engines: {node: '>=10'} + type-fest@4.41.0: + resolution: {integrity: sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==} + engines: {node: '>=16'} + type-is@1.6.18: resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==} engines: {node: '>= 0.6'} @@ -4728,6 +4936,10 @@ packages: resolution: {integrity: sha512-hpbDzxUY9BFwX+UeBnxv3Sh1q7HFxj48DTmXchNgRa46lO8uj3/1iEn3MiNUYTg1g9ctIqXCCERn8gYZhHC5lQ==} engines: {node: '>=4'} + unicorn-magic@0.3.0: + resolution: {integrity: sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==} + engines: {node: '>=18'} + universalify@0.1.2: resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} engines: {node: '>= 4.0.0'} @@ -5036,6 +5248,10 @@ packages: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} + yoctocolors@2.1.2: + resolution: {integrity: sha512-CzhO+pFNo8ajLM2d2IW/R93ipy99LWjtwblvC1RsoSUMZgyLbYFr221TnSNT7GjGdYui6P459mw9JH/g/zW2ug==} + engines: {node: '>=18'} + zustand@5.0.9: resolution: {integrity: sha512-ALBtUj0AfjJt3uNRQoL1tL2tMvj6Gp/6e39dnfT6uzpelGru8v1tPOGBzayOWbPJvujM8JojDk3E1LxeFisBNg==} engines: {node: '>=12.20.0'} @@ -6248,6 +6464,8 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.5 + '@keyv/serialize@1.1.1': {} + '@lezer/common@1.5.1': {} '@lezer/css@1.3.3': @@ -6290,6 +6508,18 @@ snapshots: '@tybys/wasm-util': 0.10.1 optional: true + '@nodelib/fs.scandir@2.1.5': + dependencies: + '@nodelib/fs.stat': 2.0.5 + run-parallel: 1.2.0 + + '@nodelib/fs.stat@2.0.5': {} + + '@nodelib/fs.walk@1.2.8': + dependencies: + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.20.1 + '@oxc-project/types@0.120.0': {} '@oxc-project/types@0.122.0': {} @@ -6678,6 +6908,8 @@ snapshots: '@rollup/rollup-win32-x64-msvc@4.59.0': optional: true + '@sec-ant/readable-stream@0.4.1': {} + '@sentry-internal/browser-utils@10.9.0': dependencies: '@sentry/core': 10.9.0 @@ -6800,6 +7032,19 @@ snapshots: '@sindresorhus/is@4.6.0': {} + '@sindresorhus/is@7.2.0': {} + + '@sindresorhus/merge-streams@4.0.0': {} + + '@stagetimerio/grandiose@0.2.0': + dependencies: + cross-zip: 4.0.1 + execa: 9.6.1 + got: 14.6.6 + mkdirp: 3.0.1 + shelljs: 0.10.0 + tmp: 0.2.5 + '@standard-schema/spec@1.1.0': {} '@svgr/babel-plugin-add-jsx-attribute@8.0.0(@babel/core@7.29.0)': @@ -7004,6 +7249,8 @@ snapshots: '@types/http-cache-semantics@4.0.4': {} + '@types/http-cache-semantics@4.2.0': {} + '@types/jsesc@2.5.1': {} '@types/keyv@3.1.4': @@ -7362,7 +7609,6 @@ snapshots: braces@3.0.3: dependencies: fill-range: 7.1.1 - optional: true browserslist-to-esbuild@2.1.1(browserslist@4.28.2): dependencies: @@ -7421,12 +7667,26 @@ snapshots: dependencies: streamsearch: 1.1.0 + byte-counter@0.1.0: {} + bytes@3.1.2: {} cac@7.0.0: {} cacheable-lookup@5.0.4: {} + cacheable-lookup@7.0.0: {} + + cacheable-request@13.0.19: + dependencies: + '@types/http-cache-semantics': 4.2.0 + get-stream: 9.0.1 + http-cache-semantics: 4.2.0 + keyv: 5.6.0 + mimic-response: 4.0.0 + normalize-url: 8.1.1 + responselike: 4.0.2 + cacheable-request@7.0.4: dependencies: clone-response: 1.0.3 @@ -7597,6 +7857,8 @@ snapshots: shebang-command: 2.0.0 which: 2.0.2 + cross-zip@4.0.1: {} + csstype@3.1.2: {} csv-stringify@6.6.0: {} @@ -7607,6 +7869,10 @@ snapshots: decamelize@1.2.0: {} + decompress-response@10.0.0: + dependencies: + mimic-response: 4.0.0 + decompress-response@6.0.0: dependencies: mimic-response: 3.1.0 @@ -7908,6 +8174,33 @@ snapshots: etag@1.8.1: {} + execa@5.1.1: + dependencies: + cross-spawn: 7.0.6 + get-stream: 6.0.1 + human-signals: 2.1.0 + is-stream: 2.0.1 + merge-stream: 2.0.0 + npm-run-path: 4.0.1 + onetime: 5.1.2 + signal-exit: 3.0.7 + strip-final-newline: 2.0.0 + + execa@9.6.1: + dependencies: + '@sindresorhus/merge-streams': 4.0.0 + cross-spawn: 7.0.6 + figures: 6.1.0 + get-stream: 9.0.1 + human-signals: 8.0.1 + is-plain-obj: 4.1.0 + is-stream: 4.0.1 + npm-run-path: 6.0.0 + pretty-ms: 9.3.0 + signal-exit: 4.1.0 + strip-final-newline: 4.0.0 + yoctocolors: 2.1.2 + expect-type@1.3.0: {} exponential-backoff@3.1.3: {} @@ -7976,8 +8269,20 @@ snapshots: fast-equals@5.2.2: {} + fast-glob@3.3.3: + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.8 + fast-json-stable-stringify@2.1.0: {} + fastq@1.20.1: + dependencies: + reusify: 1.1.0 + fd-slicer@1.1.0: dependencies: pend: 1.2.0 @@ -7986,6 +8291,10 @@ snapshots: optionalDependencies: picomatch: 4.0.4 + figures@6.1.0: + dependencies: + is-unicode-supported: 2.1.0 + filelist@1.0.6: dependencies: minimatch: 5.1.9 @@ -7993,7 +8302,6 @@ snapshots: fill-range@7.1.1: dependencies: to-regex-range: 5.0.1 - optional: true finalhandler@2.1.0: dependencies: @@ -8023,6 +8331,8 @@ snapshots: cross-spawn: 7.0.6 signal-exit: 4.1.0 + form-data-encoder@4.1.0: {} + form-data@4.0.5: dependencies: asynckit: 0.4.0 @@ -8122,10 +8432,21 @@ snapshots: dependencies: pump: 3.0.0 + get-stream@6.0.1: {} + + get-stream@9.0.1: + dependencies: + '@sec-ant/readable-stream': 0.4.1 + is-stream: 4.0.1 + get-tsconfig@4.13.7: dependencies: resolve-pkg-maps: 1.0.0 + glob-parent@5.1.2: + dependencies: + is-glob: 4.0.3 + glob@11.1.0: dependencies: foreground-child: 3.3.1 @@ -8206,6 +8527,21 @@ snapshots: p-cancelable: 2.1.1 responselike: 2.0.1 + got@14.6.6: + dependencies: + '@sindresorhus/is': 7.2.0 + byte-counter: 0.1.0 + cacheable-lookup: 7.0.0 + cacheable-request: 13.0.19 + decompress-response: 10.0.0 + form-data-encoder: 4.1.0 + http2-wrapper: 2.2.1 + keyv: 5.6.0 + lowercase-keys: 3.0.0 + p-cancelable: 4.0.1 + responselike: 4.0.2 + type-fest: 4.41.0 + graceful-fs@4.2.11: {} gtoken@7.0.1: @@ -8277,6 +8613,11 @@ snapshots: quick-lru: 5.1.1 resolve-alpn: 1.2.1 + http2-wrapper@2.2.1: + dependencies: + quick-lru: 5.1.1 + resolve-alpn: 1.2.1 + https-proxy-agent@5.0.1: dependencies: agent-base: 6.0.2 @@ -8291,6 +8632,10 @@ snapshots: transitivePeerDependencies: - supports-color + human-signals@2.1.0: {} + + human-signals@8.0.1: {} + iconv-corefoundation@1.1.7: dependencies: cli-truncate: 2.1.0 @@ -8328,23 +8673,26 @@ snapshots: dependencies: hasown: 2.0.2 - is-extglob@2.1.1: - optional: true + is-extglob@2.1.1: {} is-fullwidth-code-point@3.0.0: {} is-glob@4.0.3: dependencies: is-extglob: 2.1.1 - optional: true - is-number@7.0.0: - optional: true + is-number@7.0.0: {} + + is-plain-obj@4.1.0: {} is-promise@4.0.0: {} is-stream@2.0.1: {} + is-stream@4.0.1: {} + + is-unicode-supported@2.1.0: {} + isbinaryfile@4.0.10: {} isbinaryfile@5.0.7: {} @@ -8423,6 +8771,10 @@ snapshots: dependencies: json-buffer: 3.0.1 + keyv@5.6.0: + dependencies: + '@keyv/serialize': 1.1.1 + lazy-val@1.0.5: {} lightningcss-android-arm64@1.32.0: @@ -8498,6 +8850,8 @@ snapshots: lowercase-keys@2.0.0: {} + lowercase-keys@3.0.0: {} + lru-cache@11.3.6: {} lru-cache@5.1.1: @@ -8527,11 +8881,14 @@ snapshots: merge-descriptors@2.0.0: {} + merge-stream@2.0.0: {} + + merge2@1.4.1: {} + micromatch@4.0.8: dependencies: braces: 3.0.3 picomatch: 2.3.1 - optional: true mime-db@1.52.0: {} @@ -8547,10 +8904,14 @@ snapshots: mime@2.6.0: {} + mimic-fn@2.1.0: {} + mimic-response@1.0.1: {} mimic-response@3.1.0: {} + mimic-response@4.0.0: {} + minimatch@10.2.4: dependencies: brace-expansion: 5.0.4 @@ -8579,6 +8940,8 @@ snapshots: dependencies: minimist: 1.2.8 + mkdirp@3.0.1: {} + ms@2.1.3: {} multer@2.1.0: @@ -8638,6 +9001,17 @@ snapshots: normalize-url@6.1.0: {} + normalize-url@8.1.1: {} + + npm-run-path@4.0.1: + dependencies: + path-key: 3.1.1 + + npm-run-path@6.0.0: + dependencies: + path-key: 4.0.0 + unicorn-magic: 0.3.0 + object-assign@4.1.1: {} object-inspect@1.13.4: {} @@ -8657,6 +9031,10 @@ snapshots: dependencies: wrappy: 1.0.2 + onetime@5.1.2: + dependencies: + mimic-fn: 2.1.0 + osc-min@2.1.2: {} oxfmt@0.42.0: @@ -8717,6 +9095,8 @@ snapshots: p-cancelable@2.1.1: {} + p-cancelable@4.0.1: {} + p-limit@2.3.0: dependencies: p-try: 2.2.0 @@ -8748,6 +9128,8 @@ snapshots: json-parse-even-better-errors: 2.3.1 lines-and-columns: 1.2.4 + parse-ms@4.0.0: {} + parseurl@1.3.3: {} path-exists@4.0.0: {} @@ -8756,6 +9138,8 @@ snapshots: path-key@3.1.1: {} + path-key@4.0.0: {} + path-parse@1.0.7: {} path-scurry@2.0.2: @@ -8775,8 +9159,7 @@ snapshots: picocolors@1.1.1: {} - picomatch@2.3.1: - optional: true + picomatch@2.3.1: {} picomatch@4.0.4: {} @@ -8807,6 +9190,10 @@ snapshots: commander: 9.5.0 optional: true + pretty-ms@9.3.0: + dependencies: + parse-ms: 4.0.0 + proc-log@6.1.0: {} progress@2.0.3: {} @@ -8848,6 +9235,8 @@ snapshots: quansync@1.0.0: {} + queue-microtask@1.2.3: {} + quick-lru@5.1.1: {} range-parser@1.2.1: {} @@ -8962,8 +9351,14 @@ snapshots: dependencies: lowercase-keys: 2.0.0 + responselike@4.0.2: + dependencies: + lowercase-keys: 3.0.0 + retry@0.12.0: {} + reusify@1.1.0: {} + rimraf@2.6.3: dependencies: glob: 7.2.3 @@ -9083,6 +9478,10 @@ snapshots: transitivePeerDependencies: - supports-color + run-parallel@1.2.0: + dependencies: + queue-microtask: 1.2.3 + rxjs@7.8.1: dependencies: tslib: 2.6.2 @@ -9163,6 +9562,11 @@ snapshots: shebang-regex@3.0.0: {} + shelljs@0.10.0: + dependencies: + execa: 5.1.1 + fast-glob: 3.3.3 + side-channel-list@1.0.0: dependencies: es-errors: 1.3.0 @@ -9258,6 +9662,10 @@ snapshots: dependencies: ansi-regex: 5.0.1 + strip-final-newline@2.0.0: {} + + strip-final-newline@4.0.0: {} + style-mod@4.1.3: {} sumchecker@3.0.1: @@ -9331,7 +9739,6 @@ snapshots: to-regex-range@5.0.1: dependencies: is-number: 7.0.0 - optional: true toidentifier@1.0.1: {} @@ -9395,6 +9802,8 @@ snapshots: type-fest@0.13.1: optional: true + type-fest@4.41.0: {} + type-is@1.6.18: dependencies: media-typer: 0.3.0 @@ -9432,6 +9841,8 @@ snapshots: unicode-property-aliases-ecmascript@2.2.0: {} + unicorn-magic@0.3.0: {} + universalify@0.1.2: {} universalify@2.0.1: {} @@ -9739,6 +10150,8 @@ snapshots: yocto-queue@0.1.0: {} + yoctocolors@2.1.2: {} + zustand@5.0.9(@types/react@19.1.12)(react@19.2.3)(use-sync-external-store@1.6.0(react@19.2.3)): optionalDependencies: '@types/react': 19.1.12 diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index d673a00e0d..888b3c8f25 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -12,6 +12,7 @@ catalog: allowBuilds: '@parcel/watcher': true '@sentry/cli': false + '@stagetimerio/grandiose': true core-js: false electron: true electron-winstaller: false