From ef9fd49b05c2383bf30964ba6ac052724fd74596 Mon Sep 17 00:00:00 2001 From: Peter Dave Hello Date: Tue, 2 Sep 2025 02:51:54 +0800 Subject: [PATCH 1/3] Refactor build pipeline for performance and config Adopt esbuild minification, enable thread-loader by default, and support parallel production builds while keeping cache compression configurable. Consolidate boolean env parsing, cache the Sass implementation per process, and tune worker defaults for more predictable build behavior. --- .github/workflows/pre-release-build.yml | 13 + AGENTS.md | 19 + build.mjs | 432 +++++- package-lock.json | 1768 ++++++++++++++++++----- package.json | 11 +- 5 files changed, 1844 insertions(+), 399 deletions(-) diff --git a/.github/workflows/pre-release-build.yml b/.github/workflows/pre-release-build.yml index 0b3fa545..641e6458 100644 --- a/.github/workflows/pre-release-build.yml +++ b/.github/workflows/pre-release-build.yml @@ -24,7 +24,20 @@ jobs: - uses: actions/setup-node@v6 with: node-version: 20 + cache: 'npm' + cache-dependency-path: '**/package-lock.json' + - name: Detect Node major version + run: echo "NODE_MAJOR=$(node -p 'process.versions.node.split(".")[0]')" >> $GITHUB_ENV - run: npm ci + - name: Cache Webpack filesystem cache + uses: actions/cache@v4 + with: + path: | + .cache/webpack + node_modules/.cache/webpack + key: ${{ runner.os }}-node${{ env.NODE_MAJOR }}-webpack-${{ hashFiles('**/package-lock.json', 'build.mjs') }} + restore-keys: | + ${{ runner.os }}-node${{ env.NODE_MAJOR }}-webpack- - run: npm run build - uses: josStorer/get-current-time@v2 diff --git a/AGENTS.md b/AGENTS.md index 7ac6f62d..ed6243cf 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -17,6 +17,25 @@ Always reference these instructions first and fall back to search or bash comman - Lint code: `npm run lint` -- uses ESLint. - Safari build: `npm run build:safari` (see Platform-Specific Instructions for details) +### Build Performance Options + +- BUILD_PARALLEL: Toggle parallel build of production variants + - Default: on (parallel). Set to `0` to run sequentially (lower CPU/IO spikes on low-core machines) +- BUILD_THREAD / BUILD_THREAD_WORKERS: Control Babel parallelism via thread-loader + - Default: threads enabled in dev/prod; workers = CPU cores + - Set `BUILD_THREAD=0` to disable; set `BUILD_THREAD_WORKERS=` to override worker count +- BUILD_CACHE_COMPRESSION: Webpack filesystem cache compression + - Default: `0` (no compression) for faster warm builds on CPU-bound SSD machines + - Options: `0|false|none`, `gzip` (or `brotli` if explicitly desired) + - Affects only `.cache/webpack` size/speed; does not change final artifacts +- BUILD_WATCH_ONCE (dev): When set, `npm run dev` runs a single build and exits (useful for timing) +- BUILD_POOL_TIMEOUT: Override thread-loader production pool timeout (ms) + - Default: `2000`. Increase if workers recycle too aggressively on slow machines/CI +- Source maps (dev): Dev builds emit external `.map` files next to JS bundles for CSP-safe debugging; production builds disable source maps +- Symlinks: Webpack uses `resolve.symlinks: false` to improve performance and ensure consistent module identity; if you rely on `npm link`/pnpm workspaces, temporarily enable symlink resolution while developing linked packages + +Performance defaults: esbuild handles JS/CSS minification. In development, CSS is injected via style-loader; in production, CSS is extracted via MiniCssExtractPlugin. Thread-loader is enabled by default in both dev and prod. + ### Build Output Structure Production build creates multiple variants in `build/` directory: diff --git a/build.mjs b/build.mjs index 5dd87a03..b229263e 100644 --- a/build.mjs +++ b/build.mjs @@ -2,10 +2,11 @@ import archiver from 'archiver' import fs from 'fs-extra' import path from 'path' import webpack from 'webpack' +import os from 'os' import ProgressBarPlugin from 'progress-bar-webpack-plugin' import CssMinimizerPlugin from 'css-minimizer-webpack-plugin' import MiniCssExtractPlugin from 'mini-css-extract-plugin' -import TerserPlugin from 'terser-webpack-plugin' +import { EsbuildPlugin } from 'esbuild-loader' import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer' const outdir = 'build' @@ -13,12 +14,100 @@ const outdir = 'build' const __dirname = path.resolve() const isProduction = process.argv[2] !== '--development' // --production and --analyze are both production const isAnalyzing = process.argv[2] === '--analyze' +// Env helpers +function getBooleanEnv(val, defaultValue) { + if (val == null) return defaultValue + const s = String(val).trim().toLowerCase() + if (s === '' || s === '0' || s === 'false' || s === 'no' || s === 'off') { + return false + } + if (s === '1' || s === 'true' || s === 'yes' || s === 'on') { + return true + } + console.warn(`[build] Unknown boolean env value "${val}", defaulting to ${defaultValue}`) + return defaultValue +} +// Default: parallel build ON unless explicitly disabled +const parallelBuild = getBooleanEnv(process.env.BUILD_PARALLEL, true) +const isWatchOnce = getBooleanEnv(process.env.BUILD_WATCH_ONCE, false) +// Cache compression control: default none; allow override via env +function parseCacheCompressionOption(envVal) { + if (envVal == null) return undefined + const v = String(envVal).trim().toLowerCase() + if (v === '' || v === '0' || v === 'false' || v === 'none') return false + if (v === 'gzip' || v === 'brotli') return v + console.warn(`[build] Unknown BUILD_CACHE_COMPRESSION="${envVal}", defaulting to no compression`) + return false +} +const cacheCompressionOption = parseCacheCompressionOption(process.env.BUILD_CACHE_COMPRESSION) +let cpuCount = 1 +try { + // os.cpus() returns an array in Node.js; guard with try/catch for portability + cpuCount = Math.max(1, os.cpus().length || 1) +} catch { + cpuCount = 1 +} +function parseThreadWorkerCount(envValue, cpuCount) { + const maxWorkers = Math.max(1, cpuCount - 1) + if (envValue !== undefined && envValue !== null) { + const rawStr = String(envValue).trim() + if (/^[1-9]\d*$/.test(rawStr)) { + const raw = Number(rawStr) + if (raw > cpuCount) { + console.warn( + `[build] BUILD_THREAD_WORKERS=${raw} exceeds CPU count (${cpuCount}); capping to ${cpuCount}`, + ) + } + return Math.min(raw, cpuCount) + } + console.warn(`[build] Invalid BUILD_THREAD_WORKERS="${envValue}", defaulting to ${maxWorkers}`) + } + return maxWorkers +} +const threadWorkers = parseThreadWorkerCount(process.env.BUILD_THREAD_WORKERS, cpuCount) +// Thread-loader pool timeout constants (allow override via env) +let PRODUCTION_POOL_TIMEOUT_MS = 2000 +if (process.env.BUILD_POOL_TIMEOUT) { + const n = parseInt(process.env.BUILD_POOL_TIMEOUT, 10) + if (Number.isFinite(n) && n > 0) { + PRODUCTION_POOL_TIMEOUT_MS = n + } else { + console.warn( + `[build] Invalid BUILD_POOL_TIMEOUT="${process.env.BUILD_POOL_TIMEOUT}", keep default ${PRODUCTION_POOL_TIMEOUT_MS}ms`, + ) + } +} +// Enable threads by default; allow disabling via BUILD_THREAD=0/false/no/off +const enableThread = getBooleanEnv(process.env.BUILD_THREAD, true) + +// Cache and resolve Sass implementation once per process +let sassImplPromise +async function getSassImplementation() { + if (!sassImplPromise) { + sassImplPromise = (async () => { + try { + const mod = await import('sass-embedded') + return mod.default || mod + } catch (e1) { + try { + const mod = await import('sass') + return mod.default || mod + } catch (e2) { + console.error('[build] Failed to load sass-embedded:', e1 && e1.message ? e1.message : e1) + console.error('[build] Failed to load sass:', e2 && e2.message ? e2.message : e2) + throw new Error("No Sass implementation available. Install 'sass-embedded' or 'sass'.") + } + } + })() + } + return sassImplPromise +} async function deleteOldDir() { await fs.rm(outdir, { recursive: true, force: true }) } -async function runWebpack(isWithoutKatex, isWithoutTiktoken, minimal, callback) { +async function runWebpack(isWithoutKatex, isWithoutTiktoken, minimal, sourceBuildDir, callback) { const shared = [ 'preact', 'webextension-polyfill', @@ -33,6 +122,18 @@ async function runWebpack(isWithoutKatex, isWithoutTiktoken, minimal, callback) ] if (isWithoutKatex) shared.push('./src/components') + const sassImpl = await getSassImplementation() + + const dirKey = path.basename(sourceBuildDir || outdir) + const variantParts = [ + isWithoutKatex ? 'no-katex' : 'with-katex', + isWithoutTiktoken ? 'no-tiktoken' : 'with-tiktoken', + minimal ? 'minimal' : 'full', + dirKey, + isProduction ? 'prod' : 'dev', + ] + const variantId = variantParts.join('__') + const compiler = webpack({ entry: { 'content-script': { @@ -54,18 +155,38 @@ async function runWebpack(isWithoutKatex, isWithoutTiktoken, minimal, callback) }, output: { filename: '[name].js', - path: path.resolve(__dirname, outdir), + path: path.resolve(__dirname, sourceBuildDir || outdir), }, mode: isProduction ? 'production' : 'development', - devtool: isProduction ? false : 'inline-source-map', + devtool: isProduction ? false : 'cheap-module-source-map', + cache: { + type: 'filesystem', + name: `webpack-${variantId}`, + // Only include dimensions that affect module outputs to avoid + // unnecessary cache invalidations across machines/CI runners + version: JSON.stringify({ PROD: isProduction }), + // default none; override via BUILD_CACHE_COMPRESSION=gzip|brotli + compression: cacheCompressionOption ?? false, + buildDependencies: { + config: [ + path.resolve('build.mjs'), + ...['package.json', 'package-lock.json'] + .map((p) => path.resolve(p)) + .filter((p) => fs.existsSync(p)), + ], + }, + }, optimization: { minimizer: [ - new TerserPlugin({ - terserOptions: { - output: { ascii_only: true }, - }, + // Use esbuild for JS minification (faster than Terser) + new EsbuildPlugin({ + target: 'es2017', + legalComments: 'none', + }), + // Use esbuild-based CSS minify via css-minimizer plugin + new CssMinimizerPlugin({ + minify: CssMinimizerPlugin.esbuildMinify, }), - new CssMinimizerPlugin(), ], concatenateModules: !isAnalyzing, }, @@ -103,6 +224,9 @@ async function runWebpack(isWithoutKatex, isWithoutTiktoken, minimal, callback) ], resolve: { extensions: ['.jsx', '.mjs', '.js'], + // Disable symlink resolution for consistent behavior/perf; note this can + // affect `npm link`/pnpm workspaces during local development + symlinks: false, alias: { parse5: path.resolve(__dirname, 'node_modules/parse5'), ...(minimal @@ -124,16 +248,30 @@ async function runWebpack(isWithoutKatex, isWithoutTiktoken, minimal, callback) fullySpecified: false, }, use: [ + ...(enableThread + ? [ + { + loader: 'thread-loader', + options: { + workers: threadWorkers, + // Ensure one-off dev build exits quickly + poolTimeout: isProduction + ? PRODUCTION_POOL_TIMEOUT_MS + : isWatchOnce + ? 0 + : Infinity, + }, + }, + ] + : []), { loader: 'babel-loader', options: { - presets: [ - '@babel/preset-env', - { - plugins: ['@babel/plugin-transform-runtime'], - }, - ], + cacheDirectory: true, + cacheCompression: false, + presets: ['@babel/preset-env'], plugins: [ + ['@babel/plugin-transform-runtime'], [ '@babel/plugin-transform-react-jsx', { @@ -149,7 +287,7 @@ async function runWebpack(isWithoutKatex, isWithoutTiktoken, minimal, callback) { test: /\.s[ac]ss$/, use: [ - MiniCssExtractPlugin.loader, + isProduction ? MiniCssExtractPlugin.loader : 'style-loader', { loader: 'css-loader', options: { @@ -158,13 +296,14 @@ async function runWebpack(isWithoutKatex, isWithoutTiktoken, minimal, callback) }, { loader: 'sass-loader', + options: { implementation: sassImpl }, }, ], }, { test: /\.less$/, use: [ - MiniCssExtractPlugin.loader, + isProduction ? MiniCssExtractPlugin.loader : 'style-loader', { loader: 'css-loader', options: { @@ -179,7 +318,7 @@ async function runWebpack(isWithoutKatex, isWithoutTiktoken, minimal, callback) { test: /\.css$/, use: [ - MiniCssExtractPlugin.loader, + isProduction ? MiniCssExtractPlugin.loader : 'style-loader', { loader: 'css-loader', }, @@ -257,47 +396,162 @@ async function runWebpack(isWithoutKatex, isWithoutTiktoken, minimal, callback) ], }, }) - if (isProduction) compiler.run(callback) - else compiler.watch({}, callback) + if (isProduction) { + // Ensure compiler is properly closed after production runs + compiler.run((err, stats) => { + const finishClose = () => + compiler.close((closeErr) => { + if (closeErr) { + console.error('Error closing compiler:', closeErr) + process.exitCode = 1 + } + }) + try { + const ret = callback(err, stats) + if (ret && typeof ret.then === 'function') { + ret.then(finishClose, finishClose) + } else { + finishClose() + } + } catch (_) { + finishClose() + } + }) + } else { + const watching = compiler.watch({}, (err, stats) => { + const hasErrors = !!( + err || + (stats && typeof stats.hasErrors === 'function' && stats.hasErrors()) + ) + // Normalize callback return into a Promise to catch synchronous throws + const ret = Promise.resolve().then(() => callback(err, stats)) + if (isWatchOnce) { + const finalize = (callbackFailed = false) => + watching.close((closeErr) => { + if (closeErr) console.error('Error closing watcher:', closeErr) + // Exit explicitly to prevent hanging processes in CI + // Use non-zero exit code when errors occurred, including callback failures + const shouldFail = hasErrors || closeErr || callbackFailed + process.exit(shouldFail ? 1 : 0) + }) + ret.then( + () => finalize(false), + () => finalize(true), + ) + } + }) + } } async function zipFolder(dir) { - const output = fs.createWriteStream(`${dir}.zip`) - const archive = archiver('zip', { - zlib: { level: 9 }, + const zipPath = `${dir}.zip` + await fs.ensureDir(path.dirname(zipPath)) + await new Promise((resolve, reject) => { + const output = fs.createWriteStream(zipPath) + const archive = archiver('zip', { zlib: { level: 9 } }) + let settled = false + const fail = (err) => { + if (!settled) { + settled = true + reject(err) + } + } + const done = () => { + if (!settled) { + settled = true + resolve() + } + } + output.once('error', fail) + archive.once('error', fail) + archive.on('warning', (err) => { + // Log non-fatal archive warnings for diagnostics + console.warn('[build][zip] warning:', err) + }) + // Resolve on close to ensure FD is flushed and closed + output.once('close', done) + // Ensure close is emitted after finish on some fast runners + output.once('finish', () => { + try { + if (typeof output.close === 'function') output.close() + } catch (_) { + // ignore + } + }) + archive.pipe(output) + archive.directory(dir, false) + archive.finalize() }) - archive.pipe(output) - archive.directory(dir, false) - await archive.finalize() } async function copyFiles(entryPoints, targetDir) { - if (!fs.existsSync(targetDir)) await fs.mkdir(targetDir) + await fs.ensureDir(targetDir) await Promise.all( entryPoints.map(async (entryPoint) => { - await fs.copy(entryPoint.src, `${targetDir}/${entryPoint.dst}`) + try { + await fs.copy(entryPoint.src, `${targetDir}/${entryPoint.dst}`) + } catch (e) { + const isCss = String(entryPoint.dst).endsWith('.css') + if (e && e.code === 'ENOENT') { + if (!isProduction && isCss) { + console.log( + `[build] Skipping missing CSS file: ${entryPoint.src} -> ${entryPoint.dst} (placeholder will be created)`, + ) + return + } + console.error('Missing build artifact:', `${entryPoint.src} -> ${entryPoint.dst}`) + } else { + console.error('Copy failed:', `${entryPoint.src} -> ${entryPoint.dst}`, e) + } + throw e + } }), ) } -async function finishOutput(outputDirSuffix) { +// In development, create placeholder CSS and sourcemap files to avoid 404 noise +async function ensureDevCssPlaceholders(targetDir) { + if (isProduction) return + const cssFiles = [path.join(targetDir, 'popup.css'), path.join(targetDir, 'content-script.css')] + for (const cssPath of cssFiles) { + if (!(await fs.pathExists(cssPath))) { + await fs.outputFile(cssPath, '/* dev placeholder */\n') + } + const mapPath = `${cssPath}.map` + if (!(await fs.pathExists(mapPath))) { + await fs.outputFile(mapPath, '{"version":3,"sources":[],"mappings":"","names":[]}') + } + } +} + +async function finishOutput(outputDirSuffix, sourceBuildDir = outdir) { const commonFiles = [ { src: 'src/logo.png', dst: 'logo.png' }, { src: 'src/rules.json', dst: 'rules.json' }, - { src: 'build/shared.js', dst: 'shared.js' }, - { src: 'build/content-script.css', dst: 'content-script.css' }, // shared + { src: `${sourceBuildDir}/shared.js`, dst: 'shared.js' }, + { src: `${sourceBuildDir}/content-script.css`, dst: 'content-script.css' }, // shared - { src: 'build/content-script.js', dst: 'content-script.js' }, + { src: `${sourceBuildDir}/content-script.js`, dst: 'content-script.js' }, - { src: 'build/background.js', dst: 'background.js' }, + { src: `${sourceBuildDir}/background.js`, dst: 'background.js' }, - { src: 'build/popup.js', dst: 'popup.js' }, - { src: 'build/popup.css', dst: 'popup.css' }, + { src: `${sourceBuildDir}/popup.js`, dst: 'popup.js' }, + { src: `${sourceBuildDir}/popup.css`, dst: 'popup.css' }, { src: 'src/popup/index.html', dst: 'popup.html' }, - { src: 'build/IndependentPanel.js', dst: 'IndependentPanel.js' }, + { src: `${sourceBuildDir}/IndependentPanel.js`, dst: 'IndependentPanel.js' }, { src: 'src/pages/IndependentPanel/index.html', dst: 'IndependentPanel.html' }, + // Dev-only: copy external source maps for CSP-safe debugging + ...(isProduction + ? [] + : [ + { src: `${sourceBuildDir}/shared.js.map`, dst: 'shared.js.map' }, + { src: `${sourceBuildDir}/content-script.js.map`, dst: 'content-script.js.map' }, + { src: `${sourceBuildDir}/background.js.map`, dst: 'background.js.map' }, + { src: `${sourceBuildDir}/popup.js.map`, dst: 'popup.js.map' }, + { src: `${sourceBuildDir}/IndependentPanel.js.map`, dst: 'IndependentPanel.js.map' }, + ]), ] // chromium @@ -306,6 +560,7 @@ async function finishOutput(outputDirSuffix) { [...commonFiles, { src: 'src/manifest.json', dst: 'manifest.json' }], chromiumOutputDir, ) + await ensureDevCssPlaceholders(chromiumOutputDir) if (isProduction) await zipFolder(chromiumOutputDir) // firefox @@ -314,44 +569,85 @@ async function finishOutput(outputDirSuffix) { [...commonFiles, { src: 'src/manifest.v2.json', dst: 'manifest.json' }], firefoxOutputDir, ) + await ensureDevCssPlaceholders(firefoxOutputDir) if (isProduction) await zipFolder(firefoxOutputDir) } -function generateWebpackCallback(finishOutputFunc) { - return async function webpackCallback(err, stats) { - if (err || stats.hasErrors()) { - console.error(err || stats.toString()) - return - } - // console.log(stats.toString()) - - await finishOutputFunc() - } -} - async function build() { await deleteOldDir() + function createWebpackBuildPromise(isWithoutKatex, isWithoutTiktoken, minimal, tmpDir, suffix) { + return new Promise((resolve, reject) => { + const ret = runWebpack( + isWithoutKatex, + isWithoutTiktoken, + minimal, + tmpDir, + async (err, stats) => { + if (err || (stats && typeof stats.hasErrors === 'function' && stats.hasErrors())) { + console.error(err || stats.toString()) + reject(err || new Error('webpack error')) + return + } + try { + await finishOutput(suffix, tmpDir) + resolve() + } catch (copyErr) { + reject(copyErr) + } + }, + ) + // runWebpack is async; catch early rejections (e.g., failed dynamic imports) + if (ret && typeof ret.then === 'function') ret.catch(reject) + }) + } if (isProduction && !isAnalyzing) { - // await runWebpack( - // true, - // false, - // generateWebpackCallback(() => finishOutput('-without-katex')), - // ) - // await new Promise((r) => setTimeout(r, 5000)) - await runWebpack( - true, - true, - true, - generateWebpackCallback(() => finishOutput('-without-katex-and-tiktoken')), - ) - await new Promise((r) => setTimeout(r, 10000)) + const tmpFull = `${outdir}/.tmp-full` + const tmpMin = `${outdir}/.tmp-min` + try { + if (parallelBuild) { + await Promise.all([ + createWebpackBuildPromise(true, true, true, tmpMin, '-without-katex-and-tiktoken'), + createWebpackBuildPromise(false, false, false, tmpFull, ''), + ]) + } else { + await createWebpackBuildPromise(true, true, true, tmpMin, '-without-katex-and-tiktoken') + await createWebpackBuildPromise(false, false, false, tmpFull, '') + } + } finally { + await fs.rm(tmpFull, { recursive: true, force: true }) + await fs.rm(tmpMin, { recursive: true, force: true }) + } + return } - await runWebpack( - false, - false, - false, - generateWebpackCallback(() => finishOutput('')), - ) + + await new Promise((resolve, reject) => { + const ret = runWebpack(false, false, false, outdir, async (err, stats) => { + const hasErrors = !!( + err || + (stats && typeof stats.hasErrors === 'function' && stats.hasErrors()) + ) + if (hasErrors) { + console.error(err || stats.toString()) + // In normal dev watch, keep process alive on initial errors; only fail when watch-once + if (isWatchOnce) { + reject(err || new Error('webpack error')) + } + return + } + try { + await finishOutput('') + resolve() + } catch (e) { + // Packaging failure should stop even in dev to avoid silent success + reject(e) + } + }) + // Early setup failures (e.g., dynamic imports) should fail fast + if (ret && typeof ret.then === 'function') ret.catch(reject) + }) } -build() +build().catch((e) => { + console.error(e) + process.exit(1) +}) diff --git a/package-lock.json b/package-lock.json index 92c40029..feaccfdd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6,6 +6,7 @@ "": { "name": "chatgptbox", "dependencies": { + "@babel/runtime": "^7.24.7", "@mozilla/readability": "^0.6.0", "@nem035/gpt-3-encoder": "^1.1.7", "@picocss/pico": "^1.5.13", @@ -61,6 +62,8 @@ "babel-loader": "^9.1.3", "css-loader": "^6.11.0", "css-minimizer-webpack-plugin": "^5.0.1", + "esbuild": "^0.25.9", + "esbuild-loader": "^4.3.0", "eslint": "^8.57.1", "eslint-plugin-react": "^7.34.3", "fs-extra": "^11.2.0", @@ -73,10 +76,12 @@ "prettier": "^2.8.8", "progress-bar-webpack-plugin": "^2.1.0", "run-script-os": "^1.1.6", - "sass": "^1.77.6", - "sass-loader": "^13.3.3", + "sass": "^1.91.0", + "sass-embedded": "^1.91.0", + "sass-loader": "^16.0.5", "string-replace-loader": "^3.1.0", - "terser-webpack-plugin": "^5.3.10", + "style-loader": "^4.0.0", + "thread-loader": "^4.0.4", "webpack": "^5.92.1", "webpack-bundle-analyzer": "^4.10.2" } @@ -1864,9 +1869,9 @@ "dev": true }, "node_modules/@babel/runtime": { - "version": "7.28.2", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.2.tgz", - "integrity": "sha512-KHp2IflsnGywDjBWDkR9iEqiWSpc8GIi0lgTT3mOElT0PP1tG26P4tmFI2YvAdzgq9RGyoHZQEIEdZy6Ec5xCA==", + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.4.tgz", + "integrity": "sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==", "license": "MIT", "engines": { "node": ">=6.9.0" @@ -1923,6 +1928,13 @@ "node": ">=6.9.0" } }, + "node_modules/@bufbuild/protobuf": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/@bufbuild/protobuf/-/protobuf-2.7.0.tgz", + "integrity": "sha512-qn6tAIZEw5i/wiESBF4nQxZkl86aY4KoO0IkUa2Lh+rya64oTOdJQFlZuMwI1Qz9VBJQrQC4QlSA2DNek5gCOA==", + "dev": true, + "license": "(Apache-2.0 AND BSD-3-Clause)" + }, "node_modules/@discoveryjs/json-ext": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", @@ -1932,6 +1944,448 @@ "node": ">=10.0.0" } }, + "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" + ], + "dev": true, + "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" + ], + "dev": true, + "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" + ], + "dev": true, + "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" + ], + "dev": true, + "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", + "integrity": "sha512-XIpIDMAjOELi/9PB30vEbVMs3GV1v2zkkPnuyRRURbhqjyzIINwj+nbQATh4H9GxUgH1kFsEyQMxwiLFKUS6Rg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "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" + ], + "dev": true, + "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" + ], + "dev": true, + "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" + ], + "dev": true, + "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" + ], + "dev": true, + "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" + ], + "dev": true, + "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" + ], + "dev": true, + "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" + ], + "dev": true, + "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" + ], + "dev": true, + "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" + ], + "dev": true, + "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" + ], + "dev": true, + "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" + ], + "dev": true, + "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" + ], + "dev": true, + "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" + ], + "dev": true, + "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" + ], + "dev": true, + "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" + ], + "dev": true, + "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" + ], + "dev": true, + "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" + ], + "dev": true, + "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" + ], + "dev": true, + "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" + ], + "dev": true, + "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" + ], + "dev": true, + "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" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, "node_modules/@eslint-community/eslint-utils": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", @@ -2121,15 +2575,6 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, - "node_modules/@jest/types/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/@jest/types/node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -2253,14 +2698,324 @@ "node": ">= 8" } }, - "node_modules/@picocss/pico": { - "version": "1.5.13", - "resolved": "https://registry.npmjs.org/@picocss/pico/-/pico-1.5.13.tgz", - "integrity": "sha512-BPTeE4JC95+7/vsG9r+6hDR1qUkV4YZ1blI/TI6peOmM94XubjmUDE3jUi4f6DBV6WmCL76ueTct/NerJ33E8A==", - "license": "MIT" - }, - "node_modules/@polka/url": { - "version": "1.0.0-next.23", + "node_modules/@parcel/watcher": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.1.tgz", + "integrity": "sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "dependencies": { + "detect-libc": "^1.0.3", + "is-glob": "^4.0.3", + "micromatch": "^4.0.5", + "node-addon-api": "^7.0.0" + }, + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "@parcel/watcher-android-arm64": "2.5.1", + "@parcel/watcher-darwin-arm64": "2.5.1", + "@parcel/watcher-darwin-x64": "2.5.1", + "@parcel/watcher-freebsd-x64": "2.5.1", + "@parcel/watcher-linux-arm-glibc": "2.5.1", + "@parcel/watcher-linux-arm-musl": "2.5.1", + "@parcel/watcher-linux-arm64-glibc": "2.5.1", + "@parcel/watcher-linux-arm64-musl": "2.5.1", + "@parcel/watcher-linux-x64-glibc": "2.5.1", + "@parcel/watcher-linux-x64-musl": "2.5.1", + "@parcel/watcher-win32-arm64": "2.5.1", + "@parcel/watcher-win32-ia32": "2.5.1", + "@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" + ], + "dev": true, + "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", + "integrity": "sha512-eAzPv5osDmZyBhou8PoF4i6RQXAfeKL9tjb3QzYuccXFMQU0ruIc/POh30ePnaOyD1UXdlKguHBmsTs53tVoPw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "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" + ], + "dev": true, + "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" + ], + "dev": true, + "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" + ], + "dev": true, + "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" + ], + "dev": true, + "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" + ], + "dev": true, + "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" + ], + "dev": true, + "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" + ], + "dev": true, + "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" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "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" + ], + "dev": true, + "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" + ], + "dev": true, + "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" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@picocss/pico": { + "version": "1.5.13", + "resolved": "https://registry.npmjs.org/@picocss/pico/-/pico-1.5.13.tgz", + "integrity": "sha512-BPTeE4JC95+7/vsG9r+6hDR1qUkV4YZ1blI/TI6peOmM94XubjmUDE3jUi4f6DBV6WmCL76ueTct/NerJ33E8A==", + "license": "MIT" + }, + "node_modules/@polka/url": { + "version": "1.0.0-next.23", "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.23.tgz", "integrity": "sha512-C16M+IYz0rgRhWZdCmK+h58JMv8vijAA61gmz2rspCSwKwzBebpdcsiUmwrtJRdphuY30i6BSLEOP8ppbNLyLg==", "dev": true @@ -2846,19 +3601,6 @@ "node": ">=8" } }, - "node_modules/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dev": true, - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, "node_modules/archiver": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/archiver/-/archiver-5.3.2.tgz", @@ -3241,15 +3983,6 @@ "node": "*" } }, - "node_modules/binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/bl": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", @@ -3316,6 +4049,7 @@ "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dev": true, "license": "MIT", + "optional": true, "dependencies": { "fill-range": "^7.1.1" }, @@ -3446,6 +4180,13 @@ "ieee754": "^1.2.1" } }, + "node_modules/buffer-builder": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/buffer-builder/-/buffer-builder-0.2.0.tgz", + "integrity": "sha512-7VPMEPuYznPSoR21NE1zvd2Xna6c/CloiZCfcMXR1Jny6PjX0N4Nsa38zcBFo/FMK+BlA+FLKbJCQ0i2yxp+Xg==", + "dev": true, + "license": "MIT/X11" + }, "node_modules/buffer-crc32": { "version": "0.2.13", "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", @@ -3591,42 +4332,19 @@ } }, "node_modules/chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], + "license": "MIT", "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" + "readdirp": "^4.0.1" }, "engines": { - "node": ">= 8.10.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/chokidar/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" + "node": ">= 14.16.0" }, - "engines": { - "node": ">= 6" + "funding": { + "url": "https://paulmillr.com/funding/" } }, "node_modules/chrome-trace-event": { @@ -3681,6 +4399,13 @@ "dev": true, "license": "MIT" }, + "node_modules/colorjs.io": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/colorjs.io/-/colorjs.io-0.5.2.tgz", + "integrity": "sha512-twmVoizEW7ylZSN32OgKdXRmo1qg+wT5/6C3xu5b9QsWzSFAhHLn2xd8ro0diCsKfCj1RdaTP/nrcW+vAoQPIw==", + "dev": true, + "license": "MIT" + }, "node_modules/combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -4454,6 +5179,20 @@ "minimalistic-assert": "^1.0.0" } }, + "node_modules/detect-libc": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", + "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==", + "dev": true, + "license": "Apache-2.0", + "optional": true, + "bin": { + "detect-libc": "bin/detect-libc.js" + }, + "engines": { + "node": ">=0.10" + } + }, "node_modules/diff": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", @@ -4663,20 +5402,6 @@ "url": "https://github.com/fb55/entities?sponsor=1" } }, - "node_modules/errno": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz", - "integrity": "sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==", - "dev": true, - "optional": true, - "peer": true, - "dependencies": { - "prr": "~1.0.1" - }, - "bin": { - "errno": "cli.js" - } - }, "node_modules/es-abstract": { "version": "1.23.3", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz", @@ -4842,10 +5567,82 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/escalade": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", - "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "node_modules/esbuild": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.9.tgz", + "integrity": "sha512-CRbODhYyQx3qp7ZEwzxOk4JBqmD/seJrzPa/cGjY1VtIn5E09Oi9/dB4JwctnfZ8Q8iT7rioVv5k/FNT/uf54g==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.25.9", + "@esbuild/android-arm": "0.25.9", + "@esbuild/android-arm64": "0.25.9", + "@esbuild/android-x64": "0.25.9", + "@esbuild/darwin-arm64": "0.25.9", + "@esbuild/darwin-x64": "0.25.9", + "@esbuild/freebsd-arm64": "0.25.9", + "@esbuild/freebsd-x64": "0.25.9", + "@esbuild/linux-arm": "0.25.9", + "@esbuild/linux-arm64": "0.25.9", + "@esbuild/linux-ia32": "0.25.9", + "@esbuild/linux-loong64": "0.25.9", + "@esbuild/linux-mips64el": "0.25.9", + "@esbuild/linux-ppc64": "0.25.9", + "@esbuild/linux-riscv64": "0.25.9", + "@esbuild/linux-s390x": "0.25.9", + "@esbuild/linux-x64": "0.25.9", + "@esbuild/netbsd-arm64": "0.25.9", + "@esbuild/netbsd-x64": "0.25.9", + "@esbuild/openbsd-arm64": "0.25.9", + "@esbuild/openbsd-x64": "0.25.9", + "@esbuild/openharmony-arm64": "0.25.9", + "@esbuild/sunos-x64": "0.25.9", + "@esbuild/win32-arm64": "0.25.9", + "@esbuild/win32-ia32": "0.25.9", + "@esbuild/win32-x64": "0.25.9" + } + }, + "node_modules/esbuild-loader": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esbuild-loader/-/esbuild-loader-4.3.0.tgz", + "integrity": "sha512-D7HeJNdkDKKMarPQO/3dlJT6RwN2YJO7ENU6RPlpOz5YxSHnUNi2yvW41Bckvi1EVwctIaLzlb0ni5ag2GINYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "^0.25.0", + "get-tsconfig": "^4.7.0", + "loader-utils": "^2.0.4", + "webpack-sources": "^1.4.3" + }, + "funding": { + "url": "https://github.com/privatenumber/esbuild-loader?sponsor=1" + }, + "peerDependencies": { + "webpack": "^4.40.0 || ^5.0.0" + } + }, + "node_modules/esbuild-loader/node_modules/webpack-sources": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", + "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "source-list-map": "^2.0.0", + "source-map": "~0.6.1" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", "dev": true, "license": "MIT", "engines": { @@ -5099,15 +5896,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/eslint/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/eslint/node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -5304,6 +6092,7 @@ "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dev": true, "license": "MIT", + "optional": true, "dependencies": { "to-regex-range": "^5.0.1" }, @@ -5446,20 +6235,6 @@ "dev": true, "license": "ISC" }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, "node_modules/function-bind": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", @@ -5559,6 +6334,19 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/get-tsconfig": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.10.1.tgz", + "integrity": "sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, "node_modules/github-markdown-css": { "version": "5.6.1", "resolved": "https://registry.npmjs.org/github-markdown-css/-/github-markdown-css-5.6.1.tgz", @@ -5715,6 +6503,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/has-property-descriptors": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", @@ -6150,25 +6948,12 @@ "node": ">= 4" } }, - "node_modules/image-size": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.5.5.tgz", - "integrity": "sha512-6TDAlDPZxUFCv+fuOkIoXT/V/f3Qbq8e37p+YOiYrUv3v9cc3/6x78VdfPgFVaB9dZYeLUfKgHRebpkm/oP2VQ==", - "dev": true, - "optional": true, - "peer": true, - "bin": { - "image-size": "bin/image-size.js" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/immutable": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.4.tgz", - "integrity": "sha512-fsXeu4J4i6WNWSikpI88v/PcVflZz+6kMhUfIwc5SY+poQRPnaf5V7qds6SUyUN3cVxEzuCab7QIoLOQ+DQ1wA==", - "dev": true + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-5.1.3.tgz", + "integrity": "sha512-+chQdDfvscSF1SJqv2gn4SRO2ZyS3xL3r7IW/wWEEzrzLisnOlKiQu5ytC/BVNcS15C39WT2Hg/bjKjDMcu+zg==", + "dev": true, + "license": "MIT" }, "node_modules/import-fresh": { "version": "3.3.0", @@ -6293,18 +7078,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/is-boolean-object": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", @@ -6460,6 +7233,7 @@ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true, "license": "MIT", + "optional": true, "engines": { "node": ">=0.12.0" } @@ -6738,15 +7512,6 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, - "node_modules/jest-util/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/jest-util/node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -6774,30 +7539,6 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-worker/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-worker/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, "node_modules/js-sha3": { "version": "0.9.3", "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.9.3.tgz", @@ -6900,6 +7641,13 @@ "dev": true, "license": "MIT" }, + "node_modules/json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "dev": true, + "license": "MIT" + }, "node_modules/json-parse-even-better-errors": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", @@ -7347,32 +8095,6 @@ "yallist": "^3.0.2" } }, - "node_modules/make-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", - "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", - "dev": true, - "optional": true, - "peer": true, - "dependencies": { - "pify": "^4.0.1", - "semver": "^5.6.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/make-dir/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true, - "optional": true, - "peer": true, - "bin": { - "semver": "bin/semver" - } - }, "node_modules/markdown-table": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.3.tgz", @@ -8245,6 +8967,21 @@ } ] }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, "node_modules/miller-rabin": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", @@ -8262,20 +8999,6 @@ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" }, - "node_modules/mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "dev": true, - "optional": true, - "peer": true, - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/mime-db": { "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", @@ -8387,42 +9110,20 @@ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", "dev": true }, - "node_modules/needle": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/needle/-/needle-3.2.0.tgz", - "integrity": "sha512-oUvzXnyLiVyVGoianLijF9O/RecZUf7TkBfimjGrLM4eQhXyeJwM6GeAWccwfQ9aa4gMCZKqhAOuLaMIcQxajQ==", - "dev": true, - "optional": true, - "peer": true, - "dependencies": { - "debug": "^3.2.6", - "iconv-lite": "^0.6.3", - "sax": "^1.2.4" - }, - "bin": { - "needle": "bin/needle" - }, - "engines": { - "node": ">= 4.4.x" - } - }, - "node_modules/needle/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "optional": true, - "peer": true, - "dependencies": { - "ms": "^2.1.1" - } - }, "node_modules/neo-async": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", "dev": true }, + "node_modules/node-addon-api": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", + "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", + "dev": true, + "license": "MIT", + "optional": true + }, "node_modules/node-domexception": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", @@ -8832,17 +9533,6 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", - "dev": true, - "optional": true, - "peer": true, - "engines": { - "node": ">=6" - } - }, "node_modules/pkg-dir": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-7.0.0.tgz", @@ -9690,15 +10380,6 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, - "node_modules/progress-bar-webpack-plugin/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/progress-bar-webpack-plugin/node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -9730,14 +10411,6 @@ "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/prr": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", - "integrity": "sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==", - "dev": true, - "optional": true, - "peer": true - }, "node_modules/pseudomap": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", @@ -10011,15 +10684,17 @@ } }, "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", + "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", "dev": true, - "dependencies": { - "picomatch": "^2.2.1" - }, + "license": "MIT", "engines": { - "node": ">=8.10.0" + "node": ">= 14.18.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" } }, "node_modules/reflect.getprototypeof": { @@ -10299,6 +10974,16 @@ "node": ">=4" } }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, "node_modules/reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", @@ -10375,6 +11060,16 @@ "run-script-os": "index.js" } }, + "node_modules/rxjs": { + "version": "7.8.2", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz", + "integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.1.0" + } + }, "node_modules/sade": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/sade/-/sade-1.8.1.tgz", @@ -10448,48 +11143,400 @@ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, "node_modules/sass": { - "version": "1.77.6", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.77.6.tgz", - "integrity": "sha512-ByXE1oLD79GVq9Ht1PeHWCPMPB8XHpBuz1r85oByKHjZY6qV6rWnQovQzXJXuQ/XyE1Oj3iPk3lo28uzaRA2/Q==", + "version": "1.91.0", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.91.0.tgz", + "integrity": "sha512-aFOZHGf+ur+bp1bCHZ+u8otKGh77ZtmFyXDo4tlYvT7PWql41Kwd8wdkPqhhT+h2879IVblcHFglIMofsFd1EA==", "dev": true, "license": "MIT", "dependencies": { - "chokidar": ">=3.0.0 <4.0.0", - "immutable": "^4.0.0", + "chokidar": "^4.0.0", + "immutable": "^5.0.2", "source-map-js": ">=0.6.2 <2.0.0" }, "bin": { "sass": "sass.js" }, + "engines": { + "node": ">=14.0.0" + }, + "optionalDependencies": { + "@parcel/watcher": "^2.4.1" + } + }, + "node_modules/sass-embedded": { + "version": "1.91.0", + "resolved": "https://registry.npmjs.org/sass-embedded/-/sass-embedded-1.91.0.tgz", + "integrity": "sha512-VTckYcH1AglrZ3VpPETilTo3Ef472XKwP13lrNfbOHSR6Eo5p27XTkIi+6lrCbuhBFFGAmy+4BRoLaeFUgn+eg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@bufbuild/protobuf": "^2.5.0", + "buffer-builder": "^0.2.0", + "colorjs.io": "^0.5.0", + "immutable": "^5.0.2", + "rxjs": "^7.4.0", + "supports-color": "^8.1.1", + "sync-child-process": "^1.0.2", + "varint": "^6.0.0" + }, + "bin": { + "sass": "dist/bin/sass.js" + }, + "engines": { + "node": ">=16.0.0" + }, + "optionalDependencies": { + "sass-embedded-all-unknown": "1.91.0", + "sass-embedded-android-arm": "1.91.0", + "sass-embedded-android-arm64": "1.91.0", + "sass-embedded-android-riscv64": "1.91.0", + "sass-embedded-android-x64": "1.91.0", + "sass-embedded-darwin-arm64": "1.91.0", + "sass-embedded-darwin-x64": "1.91.0", + "sass-embedded-linux-arm": "1.91.0", + "sass-embedded-linux-arm64": "1.91.0", + "sass-embedded-linux-musl-arm": "1.91.0", + "sass-embedded-linux-musl-arm64": "1.91.0", + "sass-embedded-linux-musl-riscv64": "1.91.0", + "sass-embedded-linux-musl-x64": "1.91.0", + "sass-embedded-linux-riscv64": "1.91.0", + "sass-embedded-linux-x64": "1.91.0", + "sass-embedded-unknown-all": "1.91.0", + "sass-embedded-win32-arm64": "1.91.0", + "sass-embedded-win32-x64": "1.91.0" + } + }, + "node_modules/sass-embedded-all-unknown": { + "version": "1.91.0", + "resolved": "https://registry.npmjs.org/sass-embedded-all-unknown/-/sass-embedded-all-unknown-1.91.0.tgz", + "integrity": "sha512-AXC1oPqDfLnLtcoxM+XwSnbhcQs0TxAiA5JDEstl6+tt6fhFLKxdyl1Hla39SFtxvMfB2QDUYE3Dmx49O59vYg==", + "cpu": [ + "!arm", + "!arm64", + "!riscv64", + "!x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "sass": "1.91.0" + } + }, + "node_modules/sass-embedded-android-arm": { + "version": "1.91.0", + "resolved": "https://registry.npmjs.org/sass-embedded-android-arm/-/sass-embedded-android-arm-1.91.0.tgz", + "integrity": "sha512-DSh1V8TlLIcpklAbn4NINEFs3yD2OzVTbawEXK93IH990upoGNFVNRTstFQ/gcvlbWph3Y3FjAJvo37zUO485A==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-embedded-android-arm64": { + "version": "1.91.0", + "resolved": "https://registry.npmjs.org/sass-embedded-android-arm64/-/sass-embedded-android-arm64-1.91.0.tgz", + "integrity": "sha512-I8Eeg2CeVcZIhXcQLNEY6ZBRF0m7jc818/fypwMwvIdbxGWBekTzc3aKHTLhdBpFzGnDIyR4s7oB0/OjIpzD1A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-embedded-android-riscv64": { + "version": "1.91.0", + "resolved": "https://registry.npmjs.org/sass-embedded-android-riscv64/-/sass-embedded-android-riscv64-1.91.0.tgz", + "integrity": "sha512-qmsl1a7IIJL0fCOwzmRB+6nxeJK5m9/W8LReXUrdgyJNH5RyxChDg+wwQPVATFffOuztmWMnlJ5CV2sCLZrXcQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-embedded-android-x64": { + "version": "1.91.0", + "resolved": "https://registry.npmjs.org/sass-embedded-android-x64/-/sass-embedded-android-x64-1.91.0.tgz", + "integrity": "sha512-/wN0HBLATOVSeN3Tzg0yxxNTo1IQvOxxxwFv7Ki/1/UCg2AqZPxTpNoZj/mn8tUPtiVogMGbC8qclYMq1aRZsQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-embedded-darwin-arm64": { + "version": "1.91.0", + "resolved": "https://registry.npmjs.org/sass-embedded-darwin-arm64/-/sass-embedded-darwin-arm64-1.91.0.tgz", + "integrity": "sha512-gQ6ScInxAN+BDUXy426BSYLRawkmGYlHpQ9i6iOxorr64dtIb3l6eb9YaBV8lPlroUnugylmwN2B3FU9BuPfhA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-embedded-darwin-x64": { + "version": "1.91.0", + "resolved": "https://registry.npmjs.org/sass-embedded-darwin-x64/-/sass-embedded-darwin-x64-1.91.0.tgz", + "integrity": "sha512-DSvFMtECL2blYVTFMO5fLeNr5bX437Lrz8R47fdo5438TRyOkSgwKTkECkfh3YbnrL86yJIN2QQlmBMF17Z/iw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-embedded-linux-arm": { + "version": "1.91.0", + "resolved": "https://registry.npmjs.org/sass-embedded-linux-arm/-/sass-embedded-linux-arm-1.91.0.tgz", + "integrity": "sha512-ppAZLp3eZ9oTjYdQDf4nM7EehDpkxq5H1hE8FOrx8LpY7pxn6QF+SRpAbRjdfFChRw0K7vh+IiCnQEMp7uLNAg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-embedded-linux-arm64": { + "version": "1.91.0", + "resolved": "https://registry.npmjs.org/sass-embedded-linux-arm64/-/sass-embedded-linux-arm64-1.91.0.tgz", + "integrity": "sha512-OnKCabD7f420ZEC/6YI9WhCVGMZF+ybZ5NbAB9SsG1xlxrKbWQ1s7CIl0w/6RDALtJ+Fjn8+mrxsxqakoAkeuA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-embedded-linux-musl-arm": { + "version": "1.91.0", + "resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-arm/-/sass-embedded-linux-musl-arm-1.91.0.tgz", + "integrity": "sha512-znEsNC2FurPF9+XwQQ6e/fVoic3e5D3/kMB41t/bE8byJVRdaPhkdsszt3pZUE56nNGYoCuieSXUkk7VvyPHsw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-embedded-linux-musl-arm64": { + "version": "1.91.0", + "resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-arm64/-/sass-embedded-linux-musl-arm64-1.91.0.tgz", + "integrity": "sha512-VfbPpID1C5TT7rukob6CKgefx/TsLE+XZieMNd00hvfJ8XhqPr5DGvSMCNpXlwaedzTirbJu357m+n2PJI9TFQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-embedded-linux-musl-riscv64": { + "version": "1.91.0", + "resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-riscv64/-/sass-embedded-linux-musl-riscv64-1.91.0.tgz", + "integrity": "sha512-ZfLGldKEEeZjuljKks835LTq7jDRI3gXsKKXXgZGzN6Yymd4UpBOGWiDQlWsWTvw5UwDU2xfFh0wSXbLGHTjVA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-embedded-linux-musl-x64": { + "version": "1.91.0", + "resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-x64/-/sass-embedded-linux-musl-x64-1.91.0.tgz", + "integrity": "sha512-4kSiSGPKFMbLvTRbP/ibyiKheOA3fwsJKWU0SOuekSPmybMdrhNkTm0REp6+nehZRE60kC3lXmEV4a7w8Jrwyg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-embedded-linux-riscv64": { + "version": "1.91.0", + "resolved": "https://registry.npmjs.org/sass-embedded-linux-riscv64/-/sass-embedded-linux-riscv64-1.91.0.tgz", + "integrity": "sha512-Y3Fj94SYYvMX9yo49T78yBgBWXtG3EyYUT5K05XyCYkcdl1mVXJSrEmqmRfe4vQGUCaSe/6s7MmsA9Q+mQez7Q==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-embedded-linux-x64": { + "version": "1.91.0", + "resolved": "https://registry.npmjs.org/sass-embedded-linux-x64/-/sass-embedded-linux-x64-1.91.0.tgz", + "integrity": "sha512-XwIUaE7pQP/ezS5te80hlyheYiUlo0FolQ0HBtxohpavM+DVX2fjwFm5LOUJHrLAqP+TLBtChfFeLj1Ie4Aenw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-embedded-unknown-all": { + "version": "1.91.0", + "resolved": "https://registry.npmjs.org/sass-embedded-unknown-all/-/sass-embedded-unknown-all-1.91.0.tgz", + "integrity": "sha512-Bj6v7ScQp/HtO91QBy6ood9AArSIN7/RNcT4E7P9QoY3o+e6621Vd28lV81vdepPrt6u6PgJoVKmLNODqB6Q+A==", + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "!android", + "!darwin", + "!linux", + "!win32" + ], + "dependencies": { + "sass": "1.91.0" + } + }, + "node_modules/sass-embedded-win32-arm64": { + "version": "1.91.0", + "resolved": "https://registry.npmjs.org/sass-embedded-win32-arm64/-/sass-embedded-win32-arm64-1.91.0.tgz", + "integrity": "sha512-yDCwTiPRex03i1yo7LwiAl1YQ21UyfOxPobD7UjI8AE8ZcB0mQ28VVX66lsZ+qm91jfLslNFOFCD4v79xCG9hA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-embedded-win32-x64": { + "version": "1.91.0", + "resolved": "https://registry.npmjs.org/sass-embedded-win32-x64/-/sass-embedded-win32-x64-1.91.0.tgz", + "integrity": "sha512-wiuMz/cx4vsk6rYCnNyoGE5pd73aDJ/zF3qJDose3ZLT1/vV943doJE5pICnS/v5DrUqzV6a1CNq4fN+xeSgFQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], "engines": { "node": ">=14.0.0" } }, "node_modules/sass-loader": { - "version": "13.3.3", - "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-13.3.3.tgz", - "integrity": "sha512-mt5YN2F1MOZr3d/wBRcZxeFgwgkH44wVc2zohO2YF6JiOMkiXe4BYRZpSu2sO1g71mo/j16txzUhsKZlqjVGzA==", + "version": "16.0.5", + "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-16.0.5.tgz", + "integrity": "sha512-oL+CMBXrj6BZ/zOq4os+UECPL+bWqt6OAC6DWS8Ln8GZRcMDjlJ4JC3FBDuHJdYaFWIdKNIBYmtZtK2MaMkNIw==", "dev": true, "license": "MIT", "dependencies": { "neo-async": "^2.6.2" }, "engines": { - "node": ">= 14.15.0" + "node": ">= 18.12.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/webpack" }, "peerDependencies": { - "fibers": ">= 3.1.0", + "@rspack/core": "0.x || 1.x", "node-sass": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0", "sass": "^1.3.0", "sass-embedded": "*", "webpack": "^5.0.0" }, "peerDependenciesMeta": { - "fibers": { + "@rspack/core": { "optional": true }, "node-sass": { @@ -10500,17 +11547,12 @@ }, "sass-embedded": { "optional": true + }, + "webpack": { + "optional": true } } }, - "node_modules/sax": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.3.0.tgz", - "integrity": "sha512-0s+oAmw9zLl1V1cS9BtZN7JAd0cW5e0QH4W3LWEK6a4LaLEA2OTpGYWDY+6XasBLtz6wkm3u1xRw95mRuJ59WA==", - "dev": true, - "optional": true, - "peer": true - }, "node_modules/saxes": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", @@ -10703,6 +11745,13 @@ "node": ">= 10" } }, + "node_modules/source-list-map": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", + "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==", + "dev": true, + "license": "MIT" + }, "node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -10906,6 +11955,23 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/style-loader": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-4.0.0.tgz", + "integrity": "sha512-1V4WqhhZZgjVAVJyt7TdDPZoPBPNHbekX4fWnCJL1yQukhCeZhJySUL+gL9y6sNdN95uEOS83Y55SqHcP7MzLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 18.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.27.0" + } + }, "node_modules/style-to-object": { "version": "0.4.4", "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-0.4.4.tgz", @@ -10931,6 +11997,22 @@ "postcss": "^8.4.31" } }, + "node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, "node_modules/supports-preserve-symlinks-flag": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", @@ -10985,6 +12067,29 @@ "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", "dev": true }, + "node_modules/sync-child-process": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/sync-child-process/-/sync-child-process-1.0.2.tgz", + "integrity": "sha512-8lD+t2KrrScJ/7KXCSyfhT3/hRq78rC0wBFqNJXv3mZyn6hW2ypM05JmlSvtqRbeq6jqA94oHbxAr2vYsJ8vDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "sync-message-port": "^1.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/sync-message-port": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/sync-message-port/-/sync-message-port-1.1.3.tgz", + "integrity": "sha512-GTt8rSKje5FilG+wEdfCkOcLL7LWqpMlr2c3LRuKt/YXxcJ52aGSbGBAdI4L3aaqfrBt6y711El53ItyH1NWzg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16.0.0" + } + }, "node_modules/tapable": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", @@ -11065,15 +12170,6 @@ } } }, - "node_modules/terser-webpack-plugin/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/terser-webpack-plugin/node_modules/jest-worker": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", @@ -11106,21 +12202,6 @@ "url": "https://opencollective.com/webpack" } }, - "node_modules/terser-webpack-plugin/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, "node_modules/terser/node_modules/commander": { "version": "2.20.3", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", @@ -11134,6 +12215,29 @@ "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", "dev": true }, + "node_modules/thread-loader": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/thread-loader/-/thread-loader-4.0.4.tgz", + "integrity": "sha512-tXagu6Hivd03wB2tiS1bqvw345sc7mKei32EgpYpq31ZLes9FN0mEK2nKzXLRFgwt3PsBB0E/MZDp159rDoqwg==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-parse-better-errors": "^1.0.2", + "loader-runner": "^4.1.0", + "neo-async": "^2.6.2", + "schema-utils": "^4.2.0" + }, + "engines": { + "node": ">= 16.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + } + }, "node_modules/to-buffer": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.2.1.tgz", @@ -11154,6 +12258,7 @@ "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, "license": "MIT", + "optional": true, "dependencies": { "is-number": "^7.0.0" }, @@ -11649,6 +12754,13 @@ "node": ">=8" } }, + "node_modules/varint": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/varint/-/varint-6.0.0.tgz", + "integrity": "sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg==", + "dev": true, + "license": "MIT" + }, "node_modules/vfile": { "version": "5.3.7", "resolved": "https://registry.npmjs.org/vfile/-/vfile-5.3.7.tgz", diff --git a/package.json b/package.json index e2e1ae3d..99b0ec87 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,7 @@ "lint" ], "dependencies": { + "@babel/runtime": "^7.24.7", "@mozilla/readability": "^0.6.0", "@nem035/gpt-3-encoder": "^1.1.7", "@picocss/pico": "^1.5.13", @@ -74,6 +75,8 @@ "babel-loader": "^9.1.3", "css-loader": "^6.11.0", "css-minimizer-webpack-plugin": "^5.0.1", + "esbuild": "^0.25.9", + "esbuild-loader": "^4.3.0", "eslint": "^8.57.1", "eslint-plugin-react": "^7.34.3", "fs-extra": "^11.2.0", @@ -86,10 +89,12 @@ "prettier": "^2.8.8", "progress-bar-webpack-plugin": "^2.1.0", "run-script-os": "^1.1.6", - "sass": "^1.77.6", - "sass-loader": "^13.3.3", + "sass": "^1.91.0", + "sass-embedded": "^1.91.0", + "sass-loader": "^16.0.5", "string-replace-loader": "^3.1.0", - "terser-webpack-plugin": "^5.3.10", + "style-loader": "^4.0.0", + "thread-loader": "^4.0.4", "webpack": "^5.92.1", "webpack-bundle-analyzer": "^4.10.2" } From ede3559e6d1bd5c1b456bf150e5dff87e56554b9 Mon Sep 17 00:00:00 2001 From: Peter Dave Hello Date: Fri, 26 Sep 2025 03:30:40 +0800 Subject: [PATCH 2/3] Harden build failures and dev CSS placeholders Propagate webpack build failures via explicit exit codes so production builds fail loudly. Derive dev CSS placeholders from the computed output list to avoid hardcoded filenames. --- build.mjs | 68 +++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 51 insertions(+), 17 deletions(-) diff --git a/build.mjs b/build.mjs index b229263e..9e22b9a2 100644 --- a/build.mjs +++ b/build.mjs @@ -399,21 +399,34 @@ async function runWebpack(isWithoutKatex, isWithoutTiktoken, minimal, sourceBuil if (isProduction) { // Ensure compiler is properly closed after production runs compiler.run((err, stats) => { + const hasErrors = !!( + err || + (stats && typeof stats.hasErrors === 'function' && stats.hasErrors()) + ) + let callbackFailed = false const finishClose = () => compiler.close((closeErr) => { if (closeErr) { console.error('Error closing compiler:', closeErr) process.exitCode = 1 } + if (hasErrors || callbackFailed) { + process.exitCode = 1 + } }) try { const ret = callback(err, stats) if (ret && typeof ret.then === 'function') { - ret.then(finishClose, finishClose) + ret.then(finishClose, () => { + callbackFailed = true + finishClose() + }) } else { finishClose() } - } catch (_) { + } catch (err) { + console.error('[build] Callback error:', err) + callbackFailed = true finishClose() } }) @@ -510,18 +523,19 @@ async function copyFiles(entryPoints, targetDir) { } // In development, create placeholder CSS and sourcemap files to avoid 404 noise -async function ensureDevCssPlaceholders(targetDir) { - if (isProduction) return - const cssFiles = [path.join(targetDir, 'popup.css'), path.join(targetDir, 'content-script.css')] - for (const cssPath of cssFiles) { - if (!(await fs.pathExists(cssPath))) { - await fs.outputFile(cssPath, '/* dev placeholder */\n') - } - const mapPath = `${cssPath}.map` - if (!(await fs.pathExists(mapPath))) { - await fs.outputFile(mapPath, '{"version":3,"sources":[],"mappings":"","names":[]}') - } - } +async function ensureDevCssPlaceholders(cssFiles) { + if (isProduction || cssFiles.length === 0) return + await Promise.all( + cssFiles.map(async (cssPath) => { + if (!(await fs.pathExists(cssPath))) { + await fs.outputFile(cssPath, '/* dev placeholder */\n') + } + const mapPath = `${cssPath}.map` + if (!(await fs.pathExists(mapPath))) { + await fs.outputFile(mapPath, '{"version":3,"sources":[],"mappings":"","names":[]}') + } + }), + ) } async function finishOutput(outputDirSuffix, sourceBuildDir = outdir) { @@ -560,7 +574,15 @@ async function finishOutput(outputDirSuffix, sourceBuildDir = outdir) { [...commonFiles, { src: 'src/manifest.json', dst: 'manifest.json' }], chromiumOutputDir, ) - await ensureDevCssPlaceholders(chromiumOutputDir) + await ensureDevCssPlaceholders( + Array.from( + new Set( + commonFiles + .filter((file) => file.dst.endsWith('.css')) + .map((file) => path.join(chromiumOutputDir, file.dst)), + ), + ), + ) if (isProduction) await zipFolder(chromiumOutputDir) // firefox @@ -569,7 +591,15 @@ async function finishOutput(outputDirSuffix, sourceBuildDir = outdir) { [...commonFiles, { src: 'src/manifest.v2.json', dst: 'manifest.json' }], firefoxOutputDir, ) - await ensureDevCssPlaceholders(firefoxOutputDir) + await ensureDevCssPlaceholders( + Array.from( + new Set( + commonFiles + .filter((file) => file.dst.endsWith('.css')) + .map((file) => path.join(firefoxOutputDir, file.dst)), + ), + ), + ) if (isProduction) await zipFolder(firefoxOutputDir) } @@ -605,10 +635,14 @@ async function build() { const tmpMin = `${outdir}/.tmp-min` try { if (parallelBuild) { - await Promise.all([ + const results = await Promise.allSettled([ createWebpackBuildPromise(true, true, true, tmpMin, '-without-katex-and-tiktoken'), createWebpackBuildPromise(false, false, false, tmpFull, ''), ]) + const failed = results.find((result) => result.status === 'rejected') + if (failed) { + throw failed.reason + } } else { await createWebpackBuildPromise(true, true, true, tmpMin, '-without-katex-and-tiktoken') await createWebpackBuildPromise(false, false, false, tmpFull, '') From 88bc3bc5d48e0a0547b882bdbc900a7ec5d43333 Mon Sep 17 00:00:00 2001 From: Peter Dave Hello Date: Fri, 26 Sep 2025 03:42:51 +0800 Subject: [PATCH 3/3] Refine build helpers and CI cache docs Document BUILD_RESOLVE_SYMLINKS and cache compression behavior, and tighten related parsing in the build script. Ensure watch-once packaging failures exit non-zero and simplify error logging. Key CI webpack cache by full Node version for safety. --- .github/workflows/pre-release-build.yml | 8 ++-- AGENTS.md | 3 +- build.mjs | 52 +++++++++++++------------ 3 files changed, 33 insertions(+), 30 deletions(-) diff --git a/.github/workflows/pre-release-build.yml b/.github/workflows/pre-release-build.yml index 641e6458..20c8f945 100644 --- a/.github/workflows/pre-release-build.yml +++ b/.github/workflows/pre-release-build.yml @@ -26,8 +26,8 @@ jobs: node-version: 20 cache: 'npm' cache-dependency-path: '**/package-lock.json' - - name: Detect Node major version - run: echo "NODE_MAJOR=$(node -p 'process.versions.node.split(".")[0]')" >> $GITHUB_ENV + - name: Detect Node version + run: echo "NODE_VERSION=$(node -p 'process.versions.node')" >> $GITHUB_ENV - run: npm ci - name: Cache Webpack filesystem cache uses: actions/cache@v4 @@ -35,9 +35,9 @@ jobs: path: | .cache/webpack node_modules/.cache/webpack - key: ${{ runner.os }}-node${{ env.NODE_MAJOR }}-webpack-${{ hashFiles('**/package-lock.json', 'build.mjs') }} + key: ${{ runner.os }}-node${{ env.NODE_VERSION }}-webpack-${{ hashFiles('**/package-lock.json', 'build.mjs') }} restore-keys: | - ${{ runner.os }}-node${{ env.NODE_MAJOR }}-webpack- + ${{ runner.os }}-node${{ env.NODE_VERSION }}-webpack- - run: npm run build - uses: josStorer/get-current-time@v2 diff --git a/AGENTS.md b/AGENTS.md index ed6243cf..262672de 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -28,11 +28,12 @@ Always reference these instructions first and fall back to search or bash comman - Default: `0` (no compression) for faster warm builds on CPU-bound SSD machines - Options: `0|false|none`, `gzip` (or `brotli` if explicitly desired) - Affects only `.cache/webpack` size/speed; does not change final artifacts + - Note: Babel loader cache uses its own compression setting (currently disabled for speed) and is independent of BUILD_CACHE_COMPRESSION - BUILD_WATCH_ONCE (dev): When set, `npm run dev` runs a single build and exits (useful for timing) - BUILD_POOL_TIMEOUT: Override thread-loader production pool timeout (ms) - Default: `2000`. Increase if workers recycle too aggressively on slow machines/CI +- BUILD_RESOLVE_SYMLINKS: When set to `1`/`true`, re-enable Webpack symlink resolution for `npm link`/pnpm workspace development. Default is `false` to improve performance and ensure consistent module identity (avoids duplicate module instances) - Source maps (dev): Dev builds emit external `.map` files next to JS bundles for CSP-safe debugging; production builds disable source maps -- Symlinks: Webpack uses `resolve.symlinks: false` to improve performance and ensure consistent module identity; if you rely on `npm link`/pnpm workspaces, temporarily enable symlink resolution while developing linked packages Performance defaults: esbuild handles JS/CSS minification. In development, CSS is injected via style-loader; in production, CSS is extracted via MiniCssExtractPlugin. Thread-loader is enabled by default in both dev and prod. diff --git a/build.mjs b/build.mjs index 9e22b9a2..ea2a6399 100644 --- a/build.mjs +++ b/build.mjs @@ -32,7 +32,7 @@ const parallelBuild = getBooleanEnv(process.env.BUILD_PARALLEL, true) const isWatchOnce = getBooleanEnv(process.env.BUILD_WATCH_ONCE, false) // Cache compression control: default none; allow override via env function parseCacheCompressionOption(envVal) { - if (envVal == null) return undefined + if (envVal == null) return false const v = String(envVal).trim().toLowerCase() if (v === '' || v === '0' || v === 'false' || v === 'none') return false if (v === 'gzip' || v === 'brotli') return v @@ -48,7 +48,7 @@ try { cpuCount = 1 } function parseThreadWorkerCount(envValue, cpuCount) { - const maxWorkers = Math.max(1, cpuCount - 1) + const maxWorkers = Math.max(1, cpuCount) if (envValue !== undefined && envValue !== null) { const rawStr = String(envValue).trim() if (/^[1-9]\d*$/.test(rawStr)) { @@ -66,6 +66,7 @@ function parseThreadWorkerCount(envValue, cpuCount) { } const threadWorkers = parseThreadWorkerCount(process.env.BUILD_THREAD_WORKERS, cpuCount) // Thread-loader pool timeout constants (allow override via env) +// Keep worker pool warm briefly to amortize repeated builds while still exiting quickly in CI let PRODUCTION_POOL_TIMEOUT_MS = 2000 if (process.env.BUILD_POOL_TIMEOUT) { const n = parseInt(process.env.BUILD_POOL_TIMEOUT, 10) @@ -79,6 +80,8 @@ if (process.env.BUILD_POOL_TIMEOUT) { } // Enable threads by default; allow disabling via BUILD_THREAD=0/false/no/off const enableThread = getBooleanEnv(process.env.BUILD_THREAD, true) +// Allow opt-in symlink resolution for linked/workspace development when needed +const resolveSymlinks = getBooleanEnv(process.env.BUILD_RESOLVE_SYMLINKS, false) // Cache and resolve Sass implementation once per process let sassImplPromise @@ -93,8 +96,8 @@ async function getSassImplementation() { const mod = await import('sass') return mod.default || mod } catch (e2) { - console.error('[build] Failed to load sass-embedded:', e1 && e1.message ? e1.message : e1) - console.error('[build] Failed to load sass:', e2 && e2.message ? e2.message : e2) + console.error('[build] Failed to load sass-embedded:', e1) + console.error('[build] Failed to load sass:', e2) throw new Error("No Sass implementation available. Install 'sass-embedded' or 'sass'.") } } @@ -166,7 +169,7 @@ async function runWebpack(isWithoutKatex, isWithoutTiktoken, minimal, sourceBuil // unnecessary cache invalidations across machines/CI runners version: JSON.stringify({ PROD: isProduction }), // default none; override via BUILD_CACHE_COMPRESSION=gzip|brotli - compression: cacheCompressionOption ?? false, + compression: cacheCompressionOption, buildDependencies: { config: [ path.resolve('build.mjs'), @@ -224,9 +227,8 @@ async function runWebpack(isWithoutKatex, isWithoutTiktoken, minimal, sourceBuil ], resolve: { extensions: ['.jsx', '.mjs', '.js'], - // Disable symlink resolution for consistent behavior/perf; note this can - // affect `npm link`/pnpm workspaces during local development - symlinks: false, + // Disable symlink resolution for consistent behavior/perf; enable via BUILD_RESOLVE_SYMLINKS=1 when working with linked deps + symlinks: resolveSymlinks, alias: { parse5: path.resolve(__dirname, 'node_modules/parse5'), ...(minimal @@ -296,7 +298,12 @@ async function runWebpack(isWithoutKatex, isWithoutTiktoken, minimal, sourceBuil }, { loader: 'sass-loader', - options: { implementation: sassImpl }, + options: { + implementation: sassImpl, + sassOptions: { + quietDeps: true, + }, + }, }, ], }, @@ -399,10 +406,7 @@ async function runWebpack(isWithoutKatex, isWithoutTiktoken, minimal, sourceBuil if (isProduction) { // Ensure compiler is properly closed after production runs compiler.run((err, stats) => { - const hasErrors = !!( - err || - (stats && typeof stats.hasErrors === 'function' && stats.hasErrors()) - ) + const hasErrors = !!(err || stats?.hasErrors?.()) let callbackFailed = false const finishClose = () => compiler.close((closeErr) => { @@ -424,18 +428,15 @@ async function runWebpack(isWithoutKatex, isWithoutTiktoken, minimal, sourceBuil } else { finishClose() } - } catch (err) { - console.error('[build] Callback error:', err) + } catch (callbackErr) { + console.error('[build] Callback error:', callbackErr) callbackFailed = true finishClose() } }) } else { const watching = compiler.watch({}, (err, stats) => { - const hasErrors = !!( - err || - (stats && typeof stats.hasErrors === 'function' && stats.hasErrors()) - ) + const hasErrors = !!(err || stats?.hasErrors?.()) // Normalize callback return into a Promise to catch synchronous throws const ret = Promise.resolve().then(() => callback(err, stats)) if (isWatchOnce) { @@ -504,7 +505,7 @@ async function copyFiles(entryPoints, targetDir) { try { await fs.copy(entryPoint.src, `${targetDir}/${entryPoint.dst}`) } catch (e) { - const isCss = String(entryPoint.dst).endsWith('.css') + const isCss = typeof entryPoint.dst === 'string' && entryPoint.dst.endsWith('.css') if (e && e.code === 'ENOENT') { if (!isProduction && isCss) { console.log( @@ -613,7 +614,7 @@ async function build() { minimal, tmpDir, async (err, stats) => { - if (err || (stats && typeof stats.hasErrors === 'function' && stats.hasErrors())) { + if (err || stats?.hasErrors?.()) { console.error(err || stats.toString()) reject(err || new Error('webpack error')) return @@ -656,10 +657,7 @@ async function build() { await new Promise((resolve, reject) => { const ret = runWebpack(false, false, false, outdir, async (err, stats) => { - const hasErrors = !!( - err || - (stats && typeof stats.hasErrors === 'function' && stats.hasErrors()) - ) + const hasErrors = !!(err || stats?.hasErrors?.()) if (hasErrors) { console.error(err || stats.toString()) // In normal dev watch, keep process alive on initial errors; only fail when watch-once @@ -674,6 +672,10 @@ async function build() { } catch (e) { // Packaging failure should stop even in dev to avoid silent success reject(e) + if (isWatchOnce) { + // Re-throw to surface an error and exit non-zero even if rejection isn't awaited + throw e + } } }) // Early setup failures (e.g., dynamic imports) should fail fast