diff --git a/.config/eslint.config.js b/.config/eslint.config.js index 3200a6807..fd788f886 100644 --- a/.config/eslint.config.js +++ b/.config/eslint.config.js @@ -10,6 +10,6 @@ export default [ }, }, { - ignores: ['dist/', 'node_modules/', '.astro/', '.netlify/', '.vercel/'], + ignores: ['**/dist/', '**/node_modules/', '.astro/', '.netlify/', '.vercel/'], }, ]; diff --git a/.env.sample b/.env.sample index 2781bbaf0..56c2c1919 100644 --- a/.env.sample +++ b/.env.sample @@ -23,8 +23,9 @@ WHO_API_KEY='' # PUBLIC_API_TIMEOUT_LIMIT='25000'# Timeout for API requests, in milliseconds # API_CORS_ORIGIN='*' # Enable CORS, by setting your allowed hostname(s) here # API_ENABLE_RATE_LIMIT='true' # Enable rate limiting for the API -# REACT_APP_API_ENDPOINT='/api' # The endpoint for the API (can be local or remote) +# PUBLIC_API_ENDPOINT='/api' # The endpoint for the API (can be local or remote) +# APP_STATIC_DIR='' # Override location of the built React app (defaults to ../app/dist) +# BOSS_SERVER='true' # Set on the official public instance only, builds the Astro marketing pages # ENABLE_ANALYTICS='false' # Enable Plausible hit counter for the frontend -# BOSS_SERVER='false' # Marketing homepage (only used by official instance) # TRUST_PROXY='1' # Set if running behind a reverse proxy (Traefik, nginx, etc). # Use a number of hops (e.g. '1'), 'true', or a CIDR list. diff --git a/.github/README.md b/.github/README.md index aa3696cb3..92204b633 100644 --- a/.github/README.md +++ b/.github/README.md @@ -900,9 +900,9 @@ Install the prerequisites listed in the [Developing](#developing) section, then ```bash git clone https://github.com/Lissy93/web-check.git # Download the code from GitHub cd web-check # Navigate into the project dir -yarn install # Install the NPM dependencies -yarn build # Build the app for production -yarn serve # Start the app (API and GUI) +yarn install # Install workspace dependencies +yarn build # Build the api wrappers, app and site +yarn start # Run the Express server (api and GUI) ``` --- @@ -947,7 +947,8 @@ But there are some optional environmental variables that you can set to give you | `API_CORS_ORIGIN` | Enable CORS, by setting your allowed hostname(s) here (e.g. `example.com`) | | `CHROME_PATH` | The path the Chromium executable (e.g. `/usr/bin/chromium`) | | `DISABLE_GUI` | Disable the GUI, and only serve the API (e.g. `false`) | -| `REACT_APP_API_ENDPOINT` | The endpoint for the API, either local or remote (e.g. `/api`) | +| `PUBLIC_API_ENDPOINT` | The endpoint for the API, either local or remote (e.g. `/api`) | +| `APP_STATIC_DIR` | Override path to the built React app (defaults to `packages/app/dist`) | All values are optional. @@ -964,7 +965,7 @@ Note that keys that are prefixed with `REACT_APP_` are used client-side, and as 3. Install dependencies: `yarn` 4. Start the dev server, with `yarn dev` -You'll need [Node.js](https://nodejs.org/en) (V 18.16.1 or later) installed, plus [yarn](https://yarnpkg.com/getting-started/install) as well as [git](https://git-scm.com/). +You'll need [Node.js](https://nodejs.org/en) (V 22 or later) installed, plus [yarn](https://yarnpkg.com/getting-started/install) as well as [git](https://git-scm.com/). Some checks also require `chromium`, `traceroute` and `dns` to be installed within your environment. These jobs will just be skipped if those packages aren't present. --- diff --git a/.github/workflows/bump-and-tag.yml b/.github/workflows/bump-and-tag.yml index bb2c7287d..2f5d078a1 100644 --- a/.github/workflows/bump-and-tag.yml +++ b/.github/workflows/bump-and-tag.yml @@ -68,7 +68,7 @@ jobs: github.rest.pulls.listFiles, { owner, repo, pull_number } ); const codePatterns = [ - /^src\//, /^api\//, /^public\//, /^Dockerfile$/, /^[^/]+\.(js|mjs)$/, + /^packages\//, /^scripts\//, /^Dockerfile$/, /^[^/]+\.(js|mjs)$/, ]; const codeChanged = files.some(f => codePatterns.some(p => p.test(f.filename)) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a2257b4f6..19d0dc2ed 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -105,12 +105,20 @@ jobs: - name: ✅ Verify Build Output run: | - if [ ! -d "dist/client" ]; then - echo "❌ Build failed: dist/client directory not created" + if [ ! -f "packages/site/dist/index.html" ]; then + echo "❌ Build failed: site index not found" exit 1 fi - if [ ! -f "dist/server/entry.mjs" ]; then - echo "❌ Build failed: SSR entry not found" + if [ ! -f "packages/site/dist/check/index.html" ]; then + echo "❌ Build failed: check SPA shell not found" + exit 1 + fi + if [ ! -f "packages/app/dist/index.html" ]; then + echo "❌ Build failed: app standalone build not found" + exit 1 + fi + if [ "$(ls -1 api/*.js 2>/dev/null | wc -l)" -lt 30 ]; then + echo "❌ Build failed: vercel api wrappers not generated" exit 1 fi echo "✅ Build successful" diff --git a/.github/workflows/deploy-aws.yml b/.github/workflows/deploy-aws.yml deleted file mode 100644 index 426035ef4..000000000 --- a/.github/workflows/deploy-aws.yml +++ /dev/null @@ -1,127 +0,0 @@ -name: 🚀 Deploy to AWS - -on: - workflow_dispatch: - push: - branches: - - master - tags: - - '*' - paths: - - api/** - - serverless.yml - - package.json - - .github/workflows/deploy-aws.yml - -jobs: - deploy-api: - runs-on: ubuntu-latest - - steps: - - name: Checkout code - uses: actions/checkout@v4 - - - name: Setup Node.js - uses: actions/setup-node@v4 - with: - node-version: 16 - - - name: Cache node_modules - uses: actions/cache@v4 - with: - path: node_modules - key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} - restore-keys: | - ${{ runner.os }}-yarn- - - - name: Create GitHub deployment for API - uses: chrnorm/deployment-action@releases/v2 - id: deployment_api - with: - token: ${{ secrets.BOT_TOKEN || secrets.GITHUB_TOKEN }} - environment: AWS (Backend API) - ref: ${{ github.ref }} - - - name: Install Serverless CLI and dependencies - run: | - npm i -g serverless - yarn - - - name: Deploy to AWS - env: - AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} - AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} - AWS_ACCOUNT_ID: ${{ secrets.AWS_ACCOUNT_ID }} - run: serverless deploy - - - name: Update GitHub deployment status (API) - if: always() - uses: chrnorm/deployment-status@v2 - with: - token: ${{ secrets.BOT_TOKEN || secrets.GITHUB_TOKEN }} - state: '${{ job.status }}' - deployment_id: ${{ steps.deployment_api.outputs.deployment_id }} - ref: ${{ github.ref }} - - deploy-frontend: - runs-on: ubuntu-latest - - steps: - - name: Checkout code - uses: actions/checkout@v4 - - - name: Setup Node.js - uses: actions/setup-node@v4 - with: - node-version: 16 - - - name: Cache node_modules - uses: actions/cache@v4 - with: - path: node_modules - key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} - restore-keys: | - ${{ runner.os }}-yarn- - - - name: Create GitHub deployment for Frontend - uses: chrnorm/deployment-action@v2 - id: deployment_frontend - with: - token: ${{ secrets.BOT_TOKEN || secrets.GITHUB_TOKEN }} - environment: AWS (Frontend Web UI) - ref: ${{ github.ref }} - - - name: Install dependencies and build - run: | - yarn install - yarn build - - - name: Setup AWS - uses: aws-actions/configure-aws-credentials@v4 - with: - aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} - aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} - aws-region: us-east-1 - - - name: Upload to S3 - env: - AWS_S3_BUCKET: 'web-check-frontend' - run: aws s3 sync ./build/ s3://$AWS_S3_BUCKET/ --delete - - - name: Invalidate CloudFront cache - uses: chetan/invalidate-cloudfront-action@v2 - env: - DISTRIBUTION: E30XKAM2TG9FD8 - PATHS: '/*' - AWS_REGION: 'us-east-1' - AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} - AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} - - - name: Update GitHub deployment status (Frontend) - if: always() - uses: chrnorm/deployment-status@v2 - with: - token: ${{ secrets.BOT_TOKEN || secrets.GITHUB_TOKEN }} - state: '${{ job.status }}' - deployment_id: ${{ steps.deployment_frontend.outputs.deployment_id }} - ref: ${{ github.ref }} diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index fa950e2ca..81583e8be 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -8,9 +8,8 @@ on: tags: - '*' paths: - - src/** - - api/** - - public/** + - packages/** + - scripts/** - Dockerfile permissions: diff --git a/.yarnrc b/.yarnrc index 93303a220..976983813 100644 --- a/.yarnrc +++ b/.yarnrc @@ -1,4 +1,2 @@ -# engines.node is pinned to 20.x so @astrojs/vercel@7.x emits a supported -# Vercel runtime for the SSR _render function. Local devs on a different -# Node version can still run yarn install via this flag. +# Allow workspace install to proceed when sub-deps disagree on engine ranges --install.ignore-engines true diff --git a/Dockerfile b/Dockerfile index f61566264..0e502470f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,64 +1,61 @@ -# Specify the Node.js version to use ARG NODE_VERSION=22 - -# Specify the Debian version to use, the default is "bullseye" ARG DEBIAN_VERSION=bullseye -# Use Node.js Docker image as the base image, with specific Node and Debian versions FROM node:${NODE_VERSION}-${DEBIAN_VERSION} AS build -# Set the container's default shell to Bash and enable some options SHELL ["/bin/bash", "-euo", "pipefail", "-c"] -# Install Chromium browser and Download and verify Google Chrome’s signing key +# Install chromium plus build tooling so puppeteer and friends compile cleanly RUN apt-get update -qq --fix-missing && \ apt-get -qqy install --allow-unauthenticated gnupg wget && \ - wget --quiet --output-document=- https://dl-ssl.google.com/linux/linux_signing_key.pub | gpg --dearmor > /etc/apt/trusted.gpg.d/google-archive.gpg && \ - echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" > /etc/apt/sources.list.d/google.list && \ + wget --quiet --output-document=- \ + https://dl-ssl.google.com/linux/linux_signing_key.pub | \ + gpg --dearmor > /etc/apt/trusted.gpg.d/google-archive.gpg && \ + echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" \ + > /etc/apt/sources.list.d/google.list && \ apt-get update -qq && \ - apt-get -qqy --no-install-recommends install chromium traceroute python make g++ && \ - rm -rf /var/lib/apt/lists/* - -# Run the Chromium browser's version command and redirect its output to the /etc/chromium-version file -RUN /usr/bin/chromium --no-sandbox --version > /etc/chromium-version + apt-get -qqy --no-install-recommends install \ + chromium traceroute python make g++ && \ + rm -rf /var/lib/apt/lists/* -# Set the working directory to /app WORKDIR /app -# Copy package.json and yarn.lock to the working directory +# Copy workspace manifests first so yarn can plan and cache the dependency graph COPY package.json yarn.lock ./ +COPY packages/api/package.json ./packages/api/package.json +COPY packages/app/package.json ./packages/app/package.json +COPY packages/site/package.json ./packages/site/package.json -# Run yarn install to install dependencies and clear yarn cache -RUN apt-get update && \ - yarn install --frozen-lockfile --network-timeout 100000 && \ +RUN yarn install --frozen-lockfile --network-timeout 100000 && \ rm -rf /app/node_modules/.cache -# Copy all files to working directory -COPY . . +# Copy api and app sources plus the site's shared public assets +# (fonts, icons) which the standalone app build pulls in. Site src is skipped. +COPY packages/api ./packages/api +COPY packages/app ./packages/app +COPY packages/site/public ./packages/site/public -# Run yarn build to build the application -RUN yarn build --production +RUN yarn build:docker -# Final stage -FROM node:${NODE_VERSION}-${DEBIAN_VERSION} AS final +FROM node:${NODE_VERSION}-${DEBIAN_VERSION} AS final WORKDIR /app -COPY package.json yarn.lock ./ -COPY --from=build /app . - RUN apt-get update && \ apt-get install -y --no-install-recommends chromium traceroute && \ chmod 755 /usr/bin/chromium && \ - rm -rf /var/lib/apt/lists/* /app/node_modules/.cache + rm -rf /var/lib/apt/lists/* /tmp/* + +COPY --from=build /app/package.json /app/yarn.lock ./ +COPY --from=build /app/node_modules ./node_modules +COPY --from=build /app/packages/api ./packages/api +COPY --from=build /app/packages/app/package.json ./packages/app/package.json +COPY --from=build /app/packages/app/dist ./packages/app/dist -# Exposed container port, the default is 3000, which can be modified through the environment variable PORT EXPOSE ${PORT:-3000} -# Point Chromium-using libs at the system binary, skip puppeteer's bundled download ENV CHROME_PATH='/usr/bin/chromium' \ PUPPETEER_EXECUTABLE_PATH='/usr/bin/chromium' \ PUPPETEER_SKIP_DOWNLOAD='true' -# Define the command executed when the container starts and start the server.js of the Node.js application -CMD ["yarn", "start"] +CMD ["node", "packages/api/server.js"] diff --git a/api/_common/aws-webpack.config.js b/api/_common/aws-webpack.config.js deleted file mode 100644 index 7f6fe93ab..000000000 --- a/api/_common/aws-webpack.config.js +++ /dev/null @@ -1,50 +0,0 @@ -const path = require('path'); -const nodeExternals = require('webpack-node-externals'); - -module.exports = { - target: 'node', - mode: 'production', - entry: { - carbon: './api/carbon.js', - cookies: './api/cookies.js', - 'dns-server': './api/dns-server.js', - dns: './api/dns.js', - dnssec: './api/dnssec.js', - 'get-ip': './api/get-ip.js', - headers: './api/headers.js', - hsts: './api/hsts.js', - 'linked-pages': './api/linked-pages.js', - 'mail-config': './api/mail-config.js', - ports: './api/ports.js', - quality: './api/quality.js', - redirects: './api/redirects.js', - 'robots-txt': './api/robots-txt.js', - screenshot: './api/screenshot.js', - 'security-txt': './api/security-txt.js', - sitemap: './api/sitemap.js', - 'social-tags': './api/social-tags.js', - ssl: './api/ssl.js', - status: './api/status.js', - 'tech-stack': './api/tech-stack.js', - 'trace-route': './api/trace-route.js', - 'txt-records': './api/txt-records.js', - whois: './api/whois.js', - }, - externals: [nodeExternals()], - output: { - filename: '[name].js', - path: path.resolve(__dirname, '.webpack'), - libraryTarget: 'commonjs2', - }, - module: { - rules: [ - { - test: /\.js$/, - use: { - loader: 'babel-loader', - }, - exclude: /node_modules/, - }, - ], - }, -}; diff --git a/api/archives.js b/api/archives.js index 4818c2a2a..bba53ab44 100644 --- a/api/archives.js +++ b/api/archives.js @@ -1,84 +1,3 @@ -import middleware from './_common/middleware.js'; -import { httpGet } from './_common/http.js'; - -const convertTimestampToDate = (timestamp) => { - const [year, month, day, hour, minute, second] = [ - timestamp.slice(0, 4), - timestamp.slice(4, 6) - 1, - timestamp.slice(6, 8), - timestamp.slice(8, 10), - timestamp.slice(10, 12), - timestamp.slice(12, 14), - ].map((num) => parseInt(num, 10)); - - return new Date(year, month, day, hour, minute, second); -}; - -const countPageChanges = (results) => { - let prevDigest = null; - return results.reduce((acc, curr) => { - if (curr[2] !== prevDigest) { - prevDigest = curr[2]; - return acc + 1; - } - return acc; - }, -1); -}; - -const getAveragePageSize = (scans) => { - const totalSize = scans.map((scan) => parseInt(scan[3], 10)).reduce((sum, size) => sum + size, 0); - return Math.round(totalSize / scans.length); -}; - -const getScanFrequency = (firstScan, lastScan, totalScans, changeCount) => { - const formatToTwoDecimal = (num) => parseFloat(num.toFixed(2)); - - const dayFactor = (lastScan - firstScan) / (1000 * 60 * 60 * 24); - const daysBetweenScans = formatToTwoDecimal(dayFactor / totalScans); - const daysBetweenChanges = formatToTwoDecimal(dayFactor / changeCount); - const scansPerDay = formatToTwoDecimal((totalScans - 1) / dayFactor); - const changesPerDay = formatToTwoDecimal(changeCount / dayFactor); - return { - daysBetweenScans, - daysBetweenChanges, - scansPerDay, - changesPerDay, - }; -}; - -const wayBackHandler = async (url) => { - const cdxUrl = `https://web.archive.org/cdx/search/cdx?url=${url}&output=json&fl=timestamp,statuscode,digest,length,offset`; - - try { - const { data } = await httpGet(cdxUrl); - - // Check there's data - if (!data || !Array.isArray(data) || data.length <= 1) { - return { skipped: 'Site has never before been archived via the Wayback Machine' }; - } - - // Remove the header row - data.shift(); - - // Process and return the results - const firstScan = convertTimestampToDate(data[0][0]); - const lastScan = convertTimestampToDate(data[data.length - 1][0]); - const totalScans = data.length; - const changeCount = countPageChanges(data); - return { - firstScan, - lastScan, - totalScans, - changeCount, - averagePageSize: getAveragePageSize(data), - scanFrequency: getScanFrequency(firstScan, lastScan, totalScans, changeCount), - scans: data, - scanUrl: url, - }; - } catch (err) { - return { error: `Error fetching Wayback data: ${err.message}` }; - } -}; - -export const handler = middleware(wayBackHandler); -export default handler; +// Generated by scripts/sync-vercel-api.js, do not edit by hand +// Source of truth lives in packages/api/handlers +export { default, handler } from '../packages/api/handlers/archives.js'; diff --git a/api/block-lists.js b/api/block-lists.js index f34c0250b..663b5381b 100644 --- a/api/block-lists.js +++ b/api/block-lists.js @@ -1,62 +1,3 @@ -import dns from 'dns'; -import middleware from './_common/middleware.js'; -import { parseTarget } from './_common/parse-target.js'; - -const DNS_SERVERS = [ - { name: 'AdGuard', ip: '176.103.130.130' }, - { name: 'AdGuard Family', ip: '176.103.130.132' }, - { name: 'CleanBrowsing Adult', ip: '185.228.168.10' }, - { name: 'CleanBrowsing Family', ip: '185.228.168.168' }, - { name: 'CleanBrowsing Security', ip: '185.228.168.9' }, - { name: 'CloudFlare', ip: '1.1.1.1' }, - { name: 'CloudFlare Family', ip: '1.1.1.3' }, - { name: 'Comodo Secure', ip: '8.26.56.26' }, - { name: 'Google DNS', ip: '8.8.8.8' }, - { name: 'OpenDNS', ip: '208.67.222.222' }, - { name: 'OpenDNS Family', ip: '208.67.222.123' }, - { name: 'Quad9', ip: '9.9.9.9' }, -]; - -// Sink IPs used by blocking DNS servers -const SINK_IPS = new Set(['0.0.0.0', '127.0.0.1', '::1', '::', '0:0:0:0:0:0:0:0']); - -// Resolve a domain via a specific DNS server -const queryServer = (domain, serverIp) => - new Promise((resolve) => { - const resolver = new dns.Resolver({ timeout: 3000, tries: 1 }); - resolver.setServers([serverIp]); - resolver.resolve4(domain, (err, addrs) => { - if (err) return resolve({ err: err.code }); - resolve({ addrs }); - }); - }); - -// A domain is blocked if the resolver returns a sink IP or refuses -// to resolve a domain that a neutral resolver can resolve -const isBlocked = (result, refResolved) => { - if (!refResolved) return false; - if (result.err === 'NXDOMAIN' || result.err === 'SERVFAIL') return true; - if (!result.addrs) return false; - return result.addrs.every((ip) => SINK_IPS.has(ip)); -}; - -const blockListHandler = async (url) => { - const { hostname: domain } = parseTarget(url); - const ref = await queryServer(domain, '8.8.8.8'); - const refResolved = !!ref.addrs?.length; - - const results = await Promise.all( - DNS_SERVERS.map(async ({ name, ip }) => { - const result = await queryServer(domain, ip); - return { - server: name, - serverIp: ip, - isBlocked: isBlocked(result, refResolved), - }; - }), - ); - return { blocklists: results }; -}; - -export const handler = middleware(blockListHandler); -export default handler; +// Generated by scripts/sync-vercel-api.js, do not edit by hand +// Source of truth lives in packages/api/handlers +export { default, handler } from '../packages/api/handlers/block-lists.js'; diff --git a/api/carbon.js b/api/carbon.js index 1e8e01665..834d48204 100644 --- a/api/carbon.js +++ b/api/carbon.js @@ -1,79 +1,3 @@ -import middleware from './_common/middleware.js'; -import { createLogger } from './_common/logger.js'; - -const log = createLogger('carbon'); - -const TIMEOUT = 8000; -const MAX_BYTES = 10 * 1024 * 1024; -const USER_AGENT = 'Mozilla/5.0 (compatible; WebCheck/2.0; +https://web-check.xyz)'; - -// Sustainable Web Design model v3 constants, matches websitecarbon.com formula -const KWH_PER_GB = 0.81; -const FIRST_VISIT = 0.25; -const RETURN_VISIT = 0.75; -const RETURN_DATA_PCT = 0.02; -const GRID_INTENSITY = 442; -const RENEWABLE_INTENSITY = 50; -const LITRES_PER_GRAM = 0.5562; - -// Stream the response, cap at MAX_BYTES so huge pages can't blow memory or time -const fetchByteCount = async (url) => { - const r = await fetch(url, { - signal: AbortSignal.timeout(TIMEOUT), - redirect: 'follow', - headers: { 'user-agent': USER_AGENT, accept: 'text/html,*/*;q=0.1' }, - }); - if (!r.ok) throw new Error(`status ${r.status}`); - if (!r.body) return 0; - const reader = r.body.getReader(); - let total = 0; - while (total < MAX_BYTES) { - const { value, done } = await reader.read(); - if (done) break; - total += value.length; - } - reader.cancel().catch(() => {}); - return total; -}; - -// SWD-based stats matching websitecarbon /data response shape -const computeCarbon = (bytes) => { - const adjustedBytes = bytes * (FIRST_VISIT + RETURN_VISIT * RETURN_DATA_PCT); - const energy = (adjustedBytes / 1073741824) * KWH_PER_GB; - const gridGrams = energy * GRID_INTENSITY; - const renewableGrams = energy * RENEWABLE_INTENSITY; - return { - adjustedBytes, - energy, - co2: { - grid: { grams: gridGrams, litres: gridGrams * LITRES_PER_GRAM }, - renewable: { - grams: renewableGrams, - litres: renewableGrams * LITRES_PER_GRAM, - }, - }, - }; -}; - -// Fetch site, count bytes, compute SWD carbon stats locally, no third-party API -const carbonHandler = async (url) => { - let bytes; - try { - bytes = await fetchByteCount(url); - } catch (error) { - log.warn(`fetch failed for ${url}`, error.message); - return { error: `Failed to fetch site: ${error.message}` }; - } - if (!bytes) return { skipped: 'Site returned no content, cannot calculate carbon' }; - log.debug(`measured ${bytes} bytes for ${url}`); - return { - url, - bytes, - green: false, - statistics: computeCarbon(bytes), - scanUrl: url, - }; -}; - -export const handler = middleware(carbonHandler); -export default handler; +// Generated by scripts/sync-vercel-api.js, do not edit by hand +// Source of truth lives in packages/api/handlers +export { default, handler } from '../packages/api/handlers/carbon.js'; diff --git a/api/cookies.js b/api/cookies.js index bc6093211..785487708 100644 --- a/api/cookies.js +++ b/api/cookies.js @@ -1,51 +1,3 @@ -import puppeteer from 'puppeteer'; -import middleware from './_common/middleware.js'; -import { httpGet } from './_common/http.js'; - -const getPuppeteerCookies = async (url) => { - const browser = await puppeteer.launch({ - headless: true, - args: ['--no-sandbox', '--disable-setuid-sandbox'], - }); - - try { - const page = await browser.newPage(); - const navigationPromise = page.goto(url, { waitUntil: 'networkidle2' }); - const timeoutPromise = new Promise((_, reject) => - setTimeout(() => reject(new Error('Puppeteer took too long!')), 3000), - ); - await Promise.race([navigationPromise, timeoutPromise]); - return await browser.cookies(); - } finally { - await browser.close(); - } -}; - -const cookieHandler = async (url) => { - let headerCookies = null; - let clientCookies = null; - - try { - const response = await httpGet(url); - headerCookies = response.headers['set-cookie']; - } catch (error) { - if (error.response) { - return { error: `Request failed with status ${error.response.status}: ${error.message}` }; - } - return { error: `No response received: ${error.message}` }; - } - - try { - clientCookies = await getPuppeteerCookies(url); - } catch (_) { - clientCookies = null; - } - - return { - headerCookies: headerCookies || [], - clientCookies: clientCookies || [], - }; -}; - -export const handler = middleware(cookieHandler); -export default handler; +// Generated by scripts/sync-vercel-api.js, do not edit by hand +// Source of truth lives in packages/api/handlers +export { default, handler } from '../packages/api/handlers/cookies.js'; diff --git a/api/dns-server.js b/api/dns-server.js index b4b6b5077..a021b9a51 100644 --- a/api/dns-server.js +++ b/api/dns-server.js @@ -1,33 +1,3 @@ -import { promises as dnsPromises } from 'dns'; -import middleware from './_common/middleware.js'; -import { parseTarget } from './_common/parse-target.js'; -import { upstreamError } from './_common/upstream.js'; - -// Resolve a nameserver hostname to its IP addresses -const resolveNs = async (ns) => { - try { - return (await dnsPromises.resolve4(ns))[0]; - } catch { - return null; - } -}; - -const dnsHandler = async (url) => { - const { hostname: domain } = parseTarget(url); - let nameservers; - try { - nameservers = await dnsPromises.resolveNs(domain); - } catch (error) { - return upstreamError(error, 'DNS server lookup'); - } - const results = await Promise.all( - nameservers.map(async (ns) => { - const ip = await resolveNs(ns); - return { address: ip, hostname: ns }; - }), - ); - return { domain, dns: results }; -}; - -export const handler = middleware(dnsHandler); -export default handler; +// Generated by scripts/sync-vercel-api.js, do not edit by hand +// Source of truth lives in packages/api/handlers +export { default, handler } from '../packages/api/handlers/dns-server.js'; diff --git a/api/dns.js b/api/dns.js index 307853eea..e8893447c 100644 --- a/api/dns.js +++ b/api/dns.js @@ -1,23 +1,3 @@ -import dns from 'dns/promises'; -import middleware from './_common/middleware.js'; -import { parseTarget } from './_common/parse-target.js'; - -const dnsHandler = async (url) => { - const { hostname } = parseTarget(url); - const safe = (fn) => fn.catch(() => []); - const [a, aaaa, mx, txt, ns, cname, soa, srv, ptr] = await Promise.all([ - safe(dns.resolve4(hostname)), - safe(dns.resolve6(hostname)), - safe(dns.resolveMx(hostname)), - safe(dns.resolveTxt(hostname)), - safe(dns.resolveNs(hostname)), - safe(dns.resolveCname(hostname)), - dns.resolveSoa(hostname).catch(() => null), - safe(dns.resolveSrv(hostname)), - safe(dns.resolvePtr(hostname)), - ]); - return { A: a, AAAA: aaaa, MX: mx, TXT: txt, NS: ns, CNAME: cname, SOA: soa, SRV: srv, PTR: ptr }; -}; - -export const handler = middleware(dnsHandler); -export default handler; +// Generated by scripts/sync-vercel-api.js, do not edit by hand +// Source of truth lives in packages/api/handlers +export { default, handler } from '../packages/api/handlers/dns.js'; diff --git a/api/dnssec.js b/api/dnssec.js index 6ef983b9c..f52d82fd1 100644 --- a/api/dnssec.js +++ b/api/dnssec.js @@ -1,38 +1,3 @@ -import middleware from './_common/middleware.js'; -import { httpGet } from './_common/http.js'; -import { parseTarget } from './_common/parse-target.js'; - -// Query Google's public DNS JSON API for a given record type -const queryDns = async (domain, type) => { - const res = await httpGet('https://dns.google/resolve', { - params: { name: domain, type }, - headers: { Accept: 'application/dns-json' }, - timeout: 5000, - }); - return res.data; -}; - -const dnsSecHandler = async (url) => { - const { hostname } = parseTarget(url); - const [dnskey, ds, aRecord] = await Promise.all([ - queryDns(hostname, 'DNSKEY'), - queryDns(hostname, 'DS'), - queryDns(hostname, 'A'), - ]); - return { - DNSKEY: dnskey.Answer - ? { isFound: true, answer: dnskey.Answer, response: dnskey.Answer } - : { isFound: false, answer: null, response: dnskey }, - DS: ds.Answer - ? { isFound: true, answer: ds.Answer, response: ds.Answer } - : { isFound: false, answer: null, response: ds }, - RRSIG: { - isFound: !!aRecord.AD, - answer: null, - response: aRecord, - }, - }; -}; - -export const handler = middleware(dnsSecHandler); -export default handler; +// Generated by scripts/sync-vercel-api.js, do not edit by hand +// Source of truth lives in packages/api/handlers +export { default, handler } from '../packages/api/handlers/dnssec.js'; diff --git a/api/firewall.js b/api/firewall.js index 497c595b4..236583a2c 100644 --- a/api/firewall.js +++ b/api/firewall.js @@ -1,112 +1,3 @@ -import middleware from './_common/middleware.js'; -import { httpGet } from './_common/http.js'; -import { parseTarget } from './_common/parse-target.js'; -import { upstreamError } from './_common/upstream.js'; - -const hasWaf = (waf) => ({ hasWaf: true, waf }); - -const firewallHandler = async (url) => { - const { href } = parseTarget(url); - try { - const response = await httpGet(href, { - validateStatus: () => true, - }); - const headers = response.headers; - - if (headers['server'] && headers['server'].includes('cloudflare')) { - return hasWaf('Cloudflare'); - } - - if (headers['x-powered-by'] && headers['x-powered-by'].includes('AWS Lambda')) { - return hasWaf('AWS WAF'); - } - - if (headers['server'] && headers['server'].includes('AkamaiGHost')) { - return hasWaf('Akamai'); - } - - if (headers['server'] && headers['server'].includes('Sucuri')) { - return hasWaf('Sucuri'); - } - - if (headers['server'] && headers['server'].includes('BarracudaWAF')) { - return hasWaf('Barracuda WAF'); - } - - if ( - headers['server'] && - (headers['server'].includes('F5 BIG-IP') || headers['server'].includes('BIG-IP')) - ) { - return hasWaf('F5 BIG-IP'); - } - - if (headers['x-sucuri-id'] || headers['x-sucuri-cache']) { - return hasWaf('Sucuri CloudProxy WAF'); - } - - if (headers['server'] && headers['server'].includes('FortiWeb')) { - return hasWaf('Fortinet FortiWeb WAF'); - } - - if (headers['server'] && headers['server'].includes('Imperva')) { - return hasWaf('Imperva SecureSphere WAF'); - } - - if (headers['x-protected-by'] && headers['x-protected-by'].includes('Sqreen')) { - return hasWaf('Sqreen'); - } - - if (headers['x-waf-event-info']) { - return hasWaf('Reblaze WAF'); - } - - if (headers['set-cookie'] && headers['set-cookie'].includes('_citrix_ns_id')) { - return hasWaf('Citrix NetScaler'); - } - - if (headers['x-denied-reason'] || headers['x-wzws-requested-method']) { - return hasWaf('WangZhanBao WAF'); - } - - if (headers['x-webcoment']) { - return hasWaf('Webcoment Firewall'); - } - - if (headers['server'] && headers['server'].includes('Yundun')) { - return hasWaf('Yundun WAF'); - } - - if (headers['x-yd-waf-info'] || headers['x-yd-info']) { - return hasWaf('Yundun WAF'); - } - - if (headers['server'] && headers['server'].includes('Safe3WAF')) { - return hasWaf('Safe3 Web Application Firewall'); - } - - if (headers['server'] && headers['server'].includes('NAXSI')) { - return hasWaf('NAXSI WAF'); - } - - if (headers['x-datapower-transactionid']) { - return hasWaf('IBM WebSphere DataPower'); - } - - if (headers['server'] && headers['server'].includes('QRATOR')) { - return hasWaf('QRATOR WAF'); - } - - if (headers['server'] && headers['server'].includes('ddos-guard')) { - return hasWaf('DDoS-Guard WAF'); - } - - return { - hasWaf: false, - }; - } catch (error) { - return upstreamError(error, 'Firewall check'); - } -}; - -export const handler = middleware(firewallHandler); -export default handler; +// Generated by scripts/sync-vercel-api.js, do not edit by hand +// Source of truth lives in packages/api/handlers +export { default, handler } from '../packages/api/handlers/firewall.js'; diff --git a/api/get-ip.js b/api/get-ip.js index 87c13ce73..9b0dd499f 100644 --- a/api/get-ip.js +++ b/api/get-ip.js @@ -1,19 +1,3 @@ -import dns from 'dns'; -import middleware from './_common/middleware.js'; -import { parseTarget } from './_common/parse-target.js'; - -const lookupAsync = (address) => - new Promise((resolve, reject) => { - dns.lookup(address, (err, ip, family) => { - if (err) reject(err); - else resolve({ ip, family }); - }); - }); - -const ipHandler = async (url) => { - const { hostname } = parseTarget(url); - return await lookupAsync(hostname); -}; - -export const handler = middleware(ipHandler); -export default handler; +// Generated by scripts/sync-vercel-api.js, do not edit by hand +// Source of truth lives in packages/api/handlers +export { default, handler } from '../packages/api/handlers/get-ip.js'; diff --git a/api/headers.js b/api/headers.js index c84be1970..f2c357f75 100644 --- a/api/headers.js +++ b/api/headers.js @@ -1,17 +1,3 @@ -import middleware from './_common/middleware.js'; -import { httpGet } from './_common/http.js'; -import { upstreamError } from './_common/upstream.js'; - -const headersHandler = async (url) => { - try { - const response = await httpGet(url, { - validateStatus: (status) => status >= 200 && status < 600, - }); - return response.headers; - } catch (error) { - return upstreamError(error, 'Headers fetch'); - } -}; - -export const handler = middleware(headersHandler); -export default handler; +// Generated by scripts/sync-vercel-api.js, do not edit by hand +// Source of truth lives in packages/api/handlers +export { default, handler } from '../packages/api/handlers/headers.js'; diff --git a/api/hsts.js b/api/hsts.js index 63c6f074f..338781553 100644 --- a/api/hsts.js +++ b/api/hsts.js @@ -1,42 +1,3 @@ -import https from 'https'; -import middleware from './_common/middleware.js'; - -const MIN_MAX_AGE = 10886400; - -const verdict = (message, compatible = false, hstsHeader = null) => ({ - message, - compatible, - hstsHeader, -}); - -const evaluate = (header) => { - if (!header) return verdict('Site does not serve any HSTS headers.'); - const lower = header.toLowerCase(); - const maxAge = parseInt(lower.match(/max-age=(\d+)/)?.[1] || '0', 10); - if (maxAge < MIN_MAX_AGE) - return verdict(`HSTS max-age is ${maxAge}, below the ${MIN_MAX_AGE} minimum.`, false, header); - if (!lower.includes('includesubdomains')) - return verdict('HSTS header does not include all subdomains.', false, header); - if (!lower.includes('preload')) - return verdict('HSTS header does not contain the preload directive.', false, header); - return verdict('Site is compatible with the HSTS preload list!', true, header); -}; - -const REQUEST_TIMEOUT = 5000; - -const hstsHandler = async (url) => - new Promise((resolve) => { - const req = https.request(url, (res) => { - resolve(evaluate(res.headers['strict-transport-security'])); - res.resume(); - }); - req.setTimeout(REQUEST_TIMEOUT, () => { - req.destroy(); - resolve({ error: 'HSTS check timed out' }); - }); - req.on('error', (e) => resolve({ error: `HSTS check failed: ${e.message}` })); - req.end(); - }); - -export const handler = middleware(hstsHandler); -export default handler; +// Generated by scripts/sync-vercel-api.js, do not edit by hand +// Source of truth lives in packages/api/handlers +export { default, handler } from '../packages/api/handlers/hsts.js'; diff --git a/api/http-security.js b/api/http-security.js index d86686055..08cd030f1 100644 --- a/api/http-security.js +++ b/api/http-security.js @@ -1,30 +1,3 @@ -import middleware from './_common/middleware.js'; -import { httpGet } from './_common/http.js'; - -// Security headers to check, mapped to response field names -const HEADERS = { - 'content-security-policy': 'contentSecurityPolicy', - 'strict-transport-security': 'strictTransportPolicy', - 'x-content-type-options': 'xContentTypeOptions', - 'x-frame-options': 'xFrameOptions', - 'x-xss-protection': 'xXSSProtection', - 'referrer-policy': 'referrerPolicy', - 'permissions-policy': 'permissionsPolicy', - 'cross-origin-opener-policy': 'crossOriginOpenerPolicy', - 'cross-origin-resource-policy': 'crossOriginResourcePolicy', - 'cross-origin-embedder-policy': 'crossOriginEmbedderPolicy', -}; - -const httpsSecHandler = async (url) => { - try { - const { headers } = await httpGet(url, { - validateStatus: () => true, - }); - return Object.fromEntries(Object.entries(HEADERS).map(([h, key]) => [key, !!headers[h]])); - } catch (error) { - return { error: `Unable to fetch headers: ${error.message}` }; - } -}; - -export const handler = middleware(httpsSecHandler); -export default handler; +// Generated by scripts/sync-vercel-api.js, do not edit by hand +// Source of truth lives in packages/api/handlers +export { default, handler } from '../packages/api/handlers/http-security.js'; diff --git a/api/linked-pages.js b/api/linked-pages.js index dafa883c0..129fdc974 100644 --- a/api/linked-pages.js +++ b/api/linked-pages.js @@ -1,53 +1,3 @@ -import * as cheerio from 'cheerio'; -import urlLib from 'url'; -import middleware from './_common/middleware.js'; -import { httpGet } from './_common/http.js'; -import { upstreamError } from './_common/upstream.js'; - -const linkedPagesHandler = async (url) => { - let response; - try { - response = await httpGet(url); - } catch (error) { - return upstreamError(error, 'Linked pages fetch'); - } - const html = response.data; - const $ = cheerio.load(html); - const internalLinksMap = new Map(); - const externalLinksMap = new Map(); - - // Get all links on the page - $('a[href]').each((i, link) => { - const href = $(link).attr('href'); - const absoluteUrl = urlLib.resolve(url, href); - - // Check if absolute / relative, append to appropriate map or increment occurrence count - if (absoluteUrl.startsWith(url)) { - const count = internalLinksMap.get(absoluteUrl) || 0; - internalLinksMap.set(absoluteUrl, count + 1); - } else if (href.startsWith('http://') || href.startsWith('https://')) { - const count = externalLinksMap.get(absoluteUrl) || 0; - externalLinksMap.set(absoluteUrl, count + 1); - } - }); - - // Sort by most occurrences, remove supplicates, and convert to array - const internalLinks = [...internalLinksMap.entries()] - .sort((a, b) => b[1] - a[1]) - .map((entry) => entry[0]); - const externalLinks = [...externalLinksMap.entries()] - .sort((a, b) => b[1] - a[1]) - .map((entry) => entry[0]); - - if (!internalLinks.length && !externalLinks.length) { - return { - skipped: - 'No internal or external links found in the page HTML. ' + - 'This often happens with single-page apps that render content client-side.', - }; - } - return { internal: internalLinks, external: externalLinks }; -}; - -export const handler = middleware(linkedPagesHandler); -export default handler; +// Generated by scripts/sync-vercel-api.js, do not edit by hand +// Source of truth lives in packages/api/handlers +export { default, handler } from '../packages/api/handlers/linked-pages.js'; diff --git a/api/location.js b/api/location.js index de4f58561..c9f282d3f 100644 --- a/api/location.js +++ b/api/location.js @@ -1,184 +1,3 @@ -import { promises as dns } from 'dns'; -import middleware from './_common/middleware.js'; -import { parseTarget } from './_common/parse-target.js'; -import { createLogger } from './_common/logger.js'; - -const log = createLogger('location'); -const TIMEOUT = 4000; - -// Server-side fetch, no-cors so providers don't reject Sec-Fetch-Mode: cors -const getJson = async (url, signal) => { - const r = await fetch(url, { mode: 'no-cors', signal }); - if (!r.ok) throw new Error(`status ${r.status}`); - return r.json(); -}; - -// Geo providers, each parser normalises to a shared field shape -const providers = [ - { - name: 'ipwho.is', - url: (ip) => `https://ipwho.is/${ip}`, - parse: (d) => - d?.success === false - ? null - : { - ip: d.ip, - city: d.city, - region: d.region, - country_name: d.country, - country_code: d.country_code, - region_code: d.region_code, - postal: d.postal, - latitude: d.latitude, - longitude: d.longitude, - org: d.connection?.isp || d.connection?.org, - timezone: d.timezone?.id, - }, - }, - { - name: 'ip-api.com', - url: (ip) => `http://ip-api.com/json/${ip}`, - parse: (d) => - d?.status === 'success' - ? { - ip: d.query, - city: d.city, - region: d.regionName, - country_name: d.country, - country_code: d.countryCode, - region_code: d.region, - postal: d.zip, - latitude: d.lat, - longitude: d.lon, - org: d.isp || d.org, - timezone: d.timezone, - } - : null, - }, - { - name: 'geojs.io', - url: (ip) => `https://get.geojs.io/v1/ip/geo/${ip}.json`, - parse: (d) => - d?.country_code - ? { - ip: d.ip, - city: d.city, - region: d.region, - country_name: d.country, - country_code: d.country_code, - latitude: d.latitude !== 'nil' ? parseFloat(d.latitude) : undefined, - longitude: d.longitude !== 'nil' ? parseFloat(d.longitude) : undefined, - org: d.organization_name, - timezone: d.timezone, - } - : null, - }, - { - name: 'reallyfreegeoip.org', - url: (ip) => `https://reallyfreegeoip.org/json/${ip}`, - parse: (d) => - d?.country_code - ? { - ip: d.ip, - city: d.city, - region: d.region_name, - country_name: d.country_name, - country_code: d.country_code, - region_code: d.region_code, - postal: d.zip_code, - latitude: d.latitude, - longitude: d.longitude, - timezone: d.time_zone, - } - : null, - }, -]; - -// Query a single provider, throw unless it yields a usable result -const tryProvider = async (p, ip, signal) => { - const parsed = p.parse(await getJson(p.url(ip), signal)); - if (!parsed?.country_code) throw new Error('no usable data'); - log.debug(`${p.name} resolved ${ip} to ${parsed.country_code}`); - return parsed; -}; - -// Race all providers, first successful result wins, abort the rest -const lookupGeo = async (ip) => { - const ac = new AbortController(); - const signal = AbortSignal.any([ac.signal, AbortSignal.timeout(TIMEOUT)]); - const tasks = providers.map((p) => - tryProvider(p, ip, signal).catch((e) => { - if (e.name !== 'AbortError') log.warn(`${p.name} failed for ${ip}`, e.message); - throw e; - }), - ); - try { - const result = await Promise.any(tasks); - ac.abort(); - return result; - } catch { - return null; - } -}; - -// Fetch country-level metadata to fill fields not provided by every geo source -const enrichCountry = async (code) => { - if (!code) return {}; - try { - const data = await getJson( - `https://restcountries.com/v3.1/alpha/${code}` + - '?fields=tld,languages,currencies,area,population', - ); - const c = Array.isArray(data) ? data[0] : data; - if (!c) { - log.debug(`restcountries returned no entry for ${code}`); - return {}; - } - const languages = c.languages ? Object.values(c.languages).join(', ') : undefined; - const currCode = c.currencies ? Object.keys(c.currencies)[0] : undefined; - const curr = currCode ? c.currencies[currCode] : null; - return { - country_tld: c.tld?.[0], - languages, - currency: currCode, - currency_name: curr?.name, - country_area: c.area, - country_population: c.population, - }; - } catch (error) { - log.debug(`restcountries enrichment failed for ${code}`, error.message); - return {}; - } -}; - -// Strip empty values so they don't shadow enrichment defaults during merge -const compact = (o) => - Object.fromEntries( - Object.entries(o).filter(([, v]) => v !== undefined && v !== null && v !== ''), - ); - -// Resolve hostname to IP so providers requiring a numeric address still work -const resolveHost = async (hostname) => { - try { - return (await dns.lookup(hostname)).address; - } catch (error) { - log.warn(`DNS lookup failed for ${hostname}, falling through with raw host`, error.message); - return hostname; - } -}; - -// Resolve geographic info for a host via a chain of providers with country enrichment -const locationHandler = async (url) => { - const { hostname } = parseTarget(url); - const ip = await resolveHost(hostname); - const geo = await lookupGeo(ip); - if (!geo) { - log.error(`all geo providers failed for ${ip}`); - return { error: 'IP location lookup unavailable across all providers, please try again later' }; - } - const enrichment = await enrichCountry(geo.country_code); - return { ...enrichment, ...compact(geo) }; -}; - -export const handler = middleware(locationHandler); -export default handler; +// Generated by scripts/sync-vercel-api.js, do not edit by hand +// Source of truth lives in packages/api/handlers +export { default, handler } from '../packages/api/handlers/location.js'; diff --git a/api/mail-config.js b/api/mail-config.js index 71ac95ee7..715f68966 100644 --- a/api/mail-config.js +++ b/api/mail-config.js @@ -1,99 +1,3 @@ -import dns from 'dns/promises'; -import middleware from './_common/middleware.js'; -import { parseTarget } from './_common/parse-target.js'; - -// Safely query TXT, returning [] on ENODATA/ENOTFOUND -const safeTxt = (name) => dns.resolveTxt(name).catch(() => []); - -// Try common DKIM selectors to detect if DKIM is configured -const DKIM_SELECTORS = [ - 'default', - 'google', - 'selector1', - 'selector2', - 'k1', - 'k2', - 'k3', - 's1', - 's2', - 'dkim', - 'mail', -]; -const findDkim = async (domain) => { - const checks = DKIM_SELECTORS.map((s) => - safeTxt(`${s}._domainkey.${domain}`).then((r) => { - if (!r.length) return null; - const txt = r[0].join(''); - // Skip revoked keys (empty p= value) - if (/p=\s*(;|$)/.test(txt)) return null; - return { selector: s, record: r[0] }; - }), - ); - const results = await Promise.all(checks); - return results.filter(Boolean); -}; - -// Detect mail provider from MX exchange hostnames -const MX_PROVIDERS = [ - [/google(mail)?\.com$/i, 'Google Workspace'], - [/outlook\.com$|microsoft\.com$/i, 'Microsoft 365'], - [/protonmail\.ch$|protonme\.ch$/i, 'ProtonMail'], - [/zoho\.(com|eu|in)$/i, 'Zoho Mail'], - [/yahoodns\.net$/i, 'Yahoo Mail'], - [/mimecast\.com$/i, 'Mimecast'], - [/pphosted\.com$/i, 'Proofpoint'], - [/messagelabs\.com$/i, 'Broadcom Email Security'], - [/iphmx\.com$/i, 'Cisco Email Security'], - [/mailgun\.org$/i, 'Mailgun'], - [/sendgrid\.net$/i, 'SendGrid'], - [/fireeyecloud\.com$/i, 'Trellix Email Security'], - [/barracudanetworks\.com$/i, 'Barracuda'], -]; - -const detectProviders = (mxRecords) => { - const seen = new Set(); - return mxRecords.reduce((out, { exchange }) => { - const match = MX_PROVIDERS.find(([re]) => re.test(exchange)); - if (match && !seen.has(match[1])) { - seen.add(match[1]); - out.push({ provider: match[1], value: exchange }); - } - return out; - }, []); -}; - -const mailConfigHandler = async (url) => { - const { hostname: domain } = parseTarget(url); - try { - const [mxRecords, rootTxt, dmarcTxt, bimiTxt, dkimResults] = await Promise.all([ - dns.resolveMx(domain), - safeTxt(domain), - safeTxt(`_dmarc.${domain}`), - safeTxt(`default._bimi.${domain}`), - findDkim(domain), - ]); - - // Collect email-relevant TXT records - const emailTxt = rootTxt.filter((r) => { - const s = r.join('').toLowerCase(); - return s.startsWith('v=spf1'); - }); - dmarcTxt.forEach((r) => emailTxt.push(r)); - bimiTxt.forEach((r) => emailTxt.push(r)); - dkimResults.forEach(({ record }) => emailTxt.push(record)); - - return { - mxRecords, - txtRecords: emailTxt, - mailServices: detectProviders(mxRecords), - }; - } catch (error) { - if (error.code === 'ENOTFOUND' || error.code === 'ENODATA') { - return { skipped: 'No mail server in use on this domain' }; - } - return { error: `Mail config lookup failed: ${error.message}` }; - } -}; - -export const handler = middleware(mailConfigHandler); -export default handler; +// Generated by scripts/sync-vercel-api.js, do not edit by hand +// Source of truth lives in packages/api/handlers +export { default, handler } from '../packages/api/handlers/mail-config.js'; diff --git a/api/ports.js b/api/ports.js index 6345ccb4c..3fa40511d 100644 --- a/api/ports.js +++ b/api/ports.js @@ -1,99 +1,3 @@ -import net from 'net'; -import middleware from './_common/middleware.js'; -import { parseTarget } from './_common/parse-target.js'; - -// A list of commonly used ports. -const DEFAULT_PORTS_TO_CHECK = [ - 20, 21, 22, 23, 25, 53, 80, 67, 68, 69, 110, 119, 123, 143, 156, 161, 162, 179, 194, 389, 443, - 587, 993, 995, 3000, 3306, 3389, 5060, 5900, 8000, 8080, 8888, -]; -/* - * Checks if the env PORTS_TO_CHECK is set, if so the string is split via "," to get an array of ports to check. - * If the env is not set, return the default commonly used ports. - */ -const PORTS = process.env.PORTS_TO_CHECK - ? process.env.PORTS_TO_CHECK.split(',') - : DEFAULT_PORTS_TO_CHECK; - -async function checkPort(port, domain) { - return new Promise((resolve, reject) => { - const socket = new net.Socket(); - - socket.setTimeout(1500); - - socket.once('connect', () => { - socket.destroy(); - resolve(port); - }); - - socket.once('timeout', () => { - socket.destroy(); - reject(new Error(`Timeout at port: ${port}`)); - }); - - socket.once('error', (e) => { - socket.destroy(); - reject(e); - }); - - socket.connect(port, domain); - }); -} - -const portsHandler = async (url, event, context) => { - const { hostname: domain } = parseTarget(url); - - const delay = (ms) => new Promise((res) => setTimeout(res, ms)); - const timeout = delay(9000); - - const openPorts = []; - const failedPorts = []; - - const promises = PORTS.map((port) => - checkPort(port, domain) - .then(() => { - openPorts.push(port); - return { status: 'fulfilled', port }; - }) - .catch(() => { - failedPorts.push(port); - return { status: 'rejected', port }; - }), - ); - - let timeoutReached = false; - - for (const promise of promises) { - const result = await Promise.race([ - promise, - timeout.then(() => ({ status: 'timeout', timeout: true })), - ]); - if (result.status === 'timeout') { - timeoutReached = true; - if (result.timeout) { - // Add the ports not checked yet to the failedPorts array - const checkedPorts = [...openPorts, ...failedPorts]; - const portsNotChecked = PORTS.filter((port) => !checkedPorts.includes(port)); - failedPorts.push(...portsNotChecked); - } - break; - } - } - - if (timeoutReached) { - return errorResponse('The function timed out before completing.'); - } - - // Sort openPorts and failedPorts before returning - openPorts.sort((a, b) => a - b); - failedPorts.sort((a, b) => a - b); - - return { openPorts, failedPorts }; -}; - -const errorResponse = (message, statusCode = 444) => { - return { error: message }; -}; - -export const handler = middleware(portsHandler); -export default handler; +// Generated by scripts/sync-vercel-api.js, do not edit by hand +// Source of truth lives in packages/api/handlers +export { default, handler } from '../packages/api/handlers/ports.js'; diff --git a/api/quality.js b/api/quality.js index f0347f8de..ccbd13106 100644 --- a/api/quality.js +++ b/api/quality.js @@ -1,28 +1,3 @@ -import middleware from './_common/middleware.js'; -import { httpGet } from './_common/http.js'; -import { requireEnv, upstreamError } from './_common/upstream.js'; - -const qualityHandler = async (url) => { - const auth = requireEnv('GOOGLE_CLOUD_API_KEY', 'Quality check'); - if (auth.skipped) return auth; - const endpoint = - `https://www.googleapis.com/pagespeedonline/v5/runPagespeed?` + - `url=${encodeURIComponent(url)}&category=PERFORMANCE&category=ACCESSIBILITY` + - `&category=BEST_PRACTICES&category=SEO&category=PWA&strategy=mobile` + - `&key=${auth.value}`; - - let data; - try { - data = (await httpGet(endpoint)).data; - } catch (error) { - return upstreamError(error, 'Quality check'); - } - const result = data.lighthouseResult || data; - if (!result?.categories || !Object.keys(result.categories).length) { - return { skipped: 'No quality report available for this URL' }; - } - return result; -}; - -export const handler = middleware(qualityHandler); -export default handler; +// Generated by scripts/sync-vercel-api.js, do not edit by hand +// Source of truth lives in packages/api/handlers +export { default, handler } from '../packages/api/handlers/quality.js'; diff --git a/api/rank.js b/api/rank.js index b5d45d5be..395690522 100644 --- a/api/rank.js +++ b/api/rank.js @@ -1,29 +1,3 @@ -import middleware from './_common/middleware.js'; -import { httpGet } from './_common/http.js'; -import { parseTarget } from './_common/parse-target.js'; -import { upstreamError } from './_common/upstream.js'; - -const rankHandler = async (url) => { - const { hostname: domain } = parseTarget(url); - const { TRANCO_USERNAME, TRANCO_API_KEY } = process.env; - const auth = TRANCO_API_KEY - ? { auth: { username: TRANCO_USERNAME, password: TRANCO_API_KEY } } - : {}; - try { - const response = await httpGet(`https://tranco-list.eu/api/ranks/domain/${domain}`, { - timeout: 5000, - ...auth, - }); - if (!response.data?.ranks?.length) { - return { - skipped: `${domain} isn't ranked in the top 1 million sites yet`, - }; - } - return response.data; - } catch (error) { - return upstreamError(error, 'Tranco rank lookup'); - } -}; - -export const handler = middleware(rankHandler); -export default handler; +// Generated by scripts/sync-vercel-api.js, do not edit by hand +// Source of truth lives in packages/api/handlers +export { default, handler } from '../packages/api/handlers/rank.js'; diff --git a/api/redirects.js b/api/redirects.js index f6df1ef43..bb3319a3f 100644 --- a/api/redirects.js +++ b/api/redirects.js @@ -1,43 +1,3 @@ -import middleware from './_common/middleware.js'; -import { upstreamError } from './_common/upstream.js'; - -const MAX_REDIRECTS = 12; -const TIMEOUT_MS = 10000; -const USER_AGENT = 'Mozilla/5.0 (compatible; WebCheck/2.0; +https://web-check.xyz)'; - -// Walks the redirect chain manually, recording each Location header as got did -const redirectsHandler = async (url) => { - const redirects = [url]; - let current = url; - try { - for (let i = 0; i < MAX_REDIRECTS; i++) { - const response = await fetch(current, { - redirect: 'manual', - signal: AbortSignal.timeout(TIMEOUT_MS), - headers: { 'user-agent': USER_AGENT }, - }); - if (response.status < 300 || response.status >= 400) { - if (response.status >= 400) { - const err = new Error(`HTTP ${response.status}`); - err.response = { status: response.status }; - throw err; - } - break; - } - const location = response.headers.get('location'); - if (!location) break; - redirects.push(location); - current = new URL(location, current).href; - } - return { redirects }; - } catch (error) { - if (error.cause?.code) error.code = error.cause.code; - if (error.name === 'TimeoutError' || error.name === 'AbortError') { - error.code = 'ECONNABORTED'; - } - return upstreamError(error, 'Redirect lookup'); - } -}; - -export const handler = middleware(redirectsHandler); -export default handler; +// Generated by scripts/sync-vercel-api.js, do not edit by hand +// Source of truth lives in packages/api/handlers +export { default, handler } from '../packages/api/handlers/redirects.js'; diff --git a/api/robots-txt.js b/api/robots-txt.js index 57d776197..8f5405e00 100644 --- a/api/robots-txt.js +++ b/api/robots-txt.js @@ -1,33 +1,3 @@ -import middleware from './_common/middleware.js'; -import { httpGet } from './_common/http.js'; -import { parseTarget } from './_common/parse-target.js'; -import { upstreamError } from './_common/upstream.js'; - -// Extract User-agent / Allow / Disallow rules from a robots.txt body -const parseRobotsTxt = (content) => { - const rules = []; - for (let line of content.split('\n')) { - line = line.trim(); - const ruleMatch = line.match(/^(Allow|Disallow|User-agent):\s*(\S*)$/i); - if (ruleMatch) rules.push({ lbl: ruleMatch[1], val: ruleMatch[2] }); - } - return { robots: rules }; -}; - -const robotsHandler = async (url) => { - const { protocol, hostname } = parseTarget(url); - const host = hostname.includes(':') ? `[${hostname}]` : hostname; - try { - const res = await httpGet(`${protocol}//${host}/robots.txt`); - const parsed = parseRobotsTxt(res.data || ''); - return parsed.robots.length ? parsed : { skipped: 'No robots.txt rules found for this host' }; - } catch (error) { - if (error.response?.status === 404) { - return { skipped: 'No robots.txt file present on this host' }; - } - return upstreamError(error, 'robots.txt fetch'); - } -}; - -export const handler = middleware(robotsHandler); -export default handler; +// Generated by scripts/sync-vercel-api.js, do not edit by hand +// Source of truth lives in packages/api/handlers +export { default, handler } from '../packages/api/handlers/robots-txt.js'; diff --git a/api/screenshot.js b/api/screenshot.js index 725841b35..37b22a74d 100644 --- a/api/screenshot.js +++ b/api/screenshot.js @@ -1,96 +1,3 @@ -import puppeteer from 'puppeteer-core'; -import chromium from '@sparticuz/chromium'; -import { randomUUID } from 'crypto'; -import { execFile } from 'child_process'; -import { promises as fs } from 'fs'; -import path from 'path'; -import middleware from './_common/middleware.js'; -import { createLogger } from './_common/logger.js'; - -const log = createLogger('screenshot'); - -// Screenshot via the system Chromium binary -const directChromiumScreenshot = async (url) => { - const tmpDir = '/tmp'; - const screenshotPath = path.join(tmpDir, `screenshot-${randomUUID()}.png`); - log.debug(`direct method, saving to ${screenshotPath}`); - - return new Promise((resolve, reject) => { - const chromePath = process.env.CHROME_PATH || '/usr/bin/chromium'; - const args = [ - '--headless', - '--disable-gpu', - '--no-sandbox', - `--screenshot=${screenshotPath}`, - url, - ]; - execFile(chromePath, args, async (error) => { - if (error) return reject(error); - try { - const buf = await fs.readFile(screenshotPath); - await fs - .unlink(screenshotPath) - .catch((err) => log.warn(`temp cleanup failed: ${err.message}`)); - resolve(buf.toString('base64')); - } catch (readError) { - reject(readError); - } - }); - }); -}; - -// Fallback to puppeteer when the direct Chromium binary call fails -const puppeteerScreenshot = async (targetUrl) => { - let browser = null; - try { - browser = await puppeteer.launch({ - args: [...chromium.args, '--no-sandbox'], - defaultViewport: { width: 800, height: 600 }, - executablePath: process.env.CHROME_PATH || (await chromium.executablePath()), - headless: true, - acceptInsecureCerts: true, - ignoreDefaultArgs: ['--disable-extensions'], - }); - const page = await browser.newPage(); - await page.emulateMediaFeatures([{ name: 'prefers-color-scheme', value: 'dark' }]); - page.setDefaultNavigationTimeout(8000); - await page.goto(targetUrl, { waitUntil: 'domcontentloaded' }); - await page.evaluate(() => { - if (!document.querySelector('body')) { - throw new Error('No body element found on the page'); - } - }); - const buffer = await page.screenshot(); - return buffer.toString('base64'); - } finally { - if (browser) await browser.close().catch(() => {}); - } -}; - -const screenshotHandler = async (targetUrl) => { - if (!targetUrl) throw new Error('URL is missing from queryStringParameters'); - try { - new URL(targetUrl); - } catch { - throw new Error('URL provided is invalid'); - } - - log.debug(`request received: ${targetUrl}`); - try { - return { image: await directChromiumScreenshot(targetUrl) }; - } catch (directError) { - log.warn(`direct chromium failed, falling back to puppeteer: ${directError.message}`); - } - try { - return { image: await puppeteerScreenshot(targetUrl) }; - } catch (error) { - if (/ENOENT|Browser was not found|Could not find Chromium/i.test(error.message)) { - return { skipped: error.message }; - } - log.error(`puppeteer screenshot failed: ${error.message}`); - throw error; - } -}; - -export const handler = middleware(screenshotHandler); -export default handler; +// Generated by scripts/sync-vercel-api.js, do not edit by hand +// Source of truth lives in packages/api/handlers +export { default, handler } from '../packages/api/handlers/screenshot.js'; diff --git a/api/security-txt.js b/api/security-txt.js index f773d6a3a..3c0e88bb1 100644 --- a/api/security-txt.js +++ b/api/security-txt.js @@ -1,80 +1,3 @@ -import { URL } from 'url'; -import middleware from './_common/middleware.js'; -import { httpGet } from './_common/http.js'; - -// RFC 9116 recommends .well-known first, legacy /security.txt as fallback -const SECURITY_TXT_PATHS = ['/.well-known/security.txt', '/security.txt']; - -const parseResult = (result) => { - let output = {}; - let counts = {}; - const lines = result.split('\n'); - const regex = /^([^:]+):\s*(.+)$/; - - for (const line of lines) { - if (!line.startsWith('#') && !line.startsWith('-----') && line.trim() !== '') { - const match = line.match(regex); - if (match && match.length > 2) { - let key = match[1].trim(); - const value = match[2].trim(); - if (output.hasOwnProperty(key)) { - counts[key] = counts[key] ? counts[key] + 1 : 1; - key += counts[key]; - } - output[key] = value; - } - } - } - - return output; -}; - -const isPgpSigned = (result) => { - if (result.includes('-----BEGIN PGP SIGNED MESSAGE-----')) { - return true; - } - return false; -}; - -const securityTxtHandler = async (urlParam) => { - let url; - try { - url = new URL(urlParam.includes('://') ? urlParam : 'https://' + urlParam); - } catch (error) { - throw new Error('Invalid URL format'); - } - url.pathname = ''; - - for (let path of SECURITY_TXT_PATHS) { - try { - const result = await fetchSecurityTxt(url, path); - if (result && result.toLowerCase().includes(' { - const url = new URL(path, baseURL); - const res = await httpGet(url.toString(), { - headers: { 'User-Agent': 'curl/8.0.0' }, - validateStatus: () => true, - }); - return res.status === 200 ? res.data : null; -}; - -export const handler = middleware(securityTxtHandler); -export default handler; +// Generated by scripts/sync-vercel-api.js, do not edit by hand +// Source of truth lives in packages/api/handlers +export { default, handler } from '../packages/api/handlers/security-txt.js'; diff --git a/api/shodan.js b/api/shodan.js index 06156814f..d87837f28 100644 --- a/api/shodan.js +++ b/api/shodan.js @@ -1,22 +1,3 @@ -import middleware from './_common/middleware.js'; -import { httpGet } from './_common/http.js'; -import { parseTarget } from './_common/parse-target.js'; -import { requireEnv, upstreamError } from './_common/upstream.js'; - -// Server-side Shodan lookup so the API key never touches the client -const shodanHandler = async (url) => { - const auth = requireEnv('SHODAN_API_KEY', 'Shodan'); - if (auth.skipped) return auth; - const { hostname } = parseTarget(url); - try { - const res = await httpGet(`https://api.shodan.io/shodan/host/${hostname}?key=${auth.value}`, { - timeout: 8000, - }); - return res.data; - } catch (error) { - return upstreamError(error, 'Shodan lookup'); - } -}; - -export const handler = middleware(shodanHandler); -export default handler; +// Generated by scripts/sync-vercel-api.js, do not edit by hand +// Source of truth lives in packages/api/handlers +export { default, handler } from '../packages/api/handlers/shodan.js'; diff --git a/api/sitemap.js b/api/sitemap.js index ef7859ee5..3739692b9 100644 --- a/api/sitemap.js +++ b/api/sitemap.js @@ -1,129 +1,3 @@ -import xml2js from 'xml2js'; -import middleware from './_common/middleware.js'; -import { httpGet } from './_common/http.js'; -import { upstreamError } from './_common/upstream.js'; -import { createLogger } from './_common/logger.js'; - -const log = createLogger('sitemap'); -const TIMEOUT = 6000; -const MAX_DEPTH = 3; -const MAX_CHILD_SITEMAPS = 25; -const MAX_URLS = 5000; - -// Browser-ish headers so picky CDNs do not return 406/403 to the default Node UA -const HEADERS = { - 'user-agent': 'Mozilla/5.0 (compatible; web-check-bot/1.0; +https://web-check.xyz)', - accept: 'application/xml, text/xml, application/rss+xml, */*;q=0.1', -}; - -// Reduce a target URL to its origin so child paths resolve cleanly -const toOrigin = (url) => { - try { - return new URL(url).origin; - } catch { - return url.replace(/\/+$/, ''); - } -}; - -// Fetch and parse XML in lenient mode so minor well-formedness errors do not abort -const fetchSitemap = async (sitemapUrl) => { - const res = await httpGet(sitemapUrl, { timeout: TIMEOUT, headers: HEADERS }); - return new xml2js.Parser({ strict: false, normalizeTags: true }).parseStringPromise(res.data); -}; - -// Pull the first Sitemap: directive out of robots.txt, if any -const findSitemapInRobots = async (origin) => { - try { - const robots = await httpGet(`${origin}/robots.txt`, { timeout: TIMEOUT, headers: HEADERS }); - for (const line of String(robots.data).split('\n')) { - if (line.toLowerCase().startsWith('sitemap:')) { - return line.split(/\s+/)[1]?.trim() || null; - } - } - } catch (error) { - log.debug(`robots.txt fetch failed for ${origin}`, error.message); - } - return null; -}; - -// Recursively flatten a sitemap-index into its child url sets -const expandSitemap = async (parsed, depth) => { - if (!parsed?.sitemapindex?.sitemap || depth >= MAX_DEPTH) return parsed; - const children = parsed.sitemapindex.sitemap - .map((s) => s?.loc?.[0]) - .filter(Boolean) - .slice(0, MAX_CHILD_SITEMAPS); - const fetched = await Promise.all( - children.map((loc) => - fetchSitemap(loc).catch((error) => { - log.debug(`child sitemap failed for ${loc}`, error.message); - return null; - }), - ), - ); - const expanded = await Promise.all( - fetched.map((child) => (child ? expandSitemap(child, depth + 1) : null)), - ); - const urls = expanded.flatMap((child) => child?.urlset?.url || []); - return { - sitemapindex: parsed.sitemapindex, - urlset: urls.length ? { url: urls } : undefined, - sources: children, - }; -}; - -// Whether the parsed XML matched one of the canonical sitemap shapes -const isValidSitemap = (p) => !!(p?.urlset?.url?.length || p?.sitemapindex?.sitemap?.length); - -// Keep only the four fields the frontend renders, dropping locale alternates and image/video extras -const slimUrl = (u) => { - const out = { loc: u.loc }; - if (u.lastmod) out.lastmod = u.lastmod; - if (u.changefreq) out.changefreq = u.changefreq; - if (u.priority) out.priority = u.priority; - return out; -}; - -// Drop bulky XML extensions and cap total entries so the JSON payload stays sane -const slimResult = (r) => { - if (!r) return r; - const out = {}; - if (r.urlset?.url) out.urlset = { url: r.urlset.url.slice(0, MAX_URLS).map(slimUrl) }; - if (r.sitemapindex?.sitemap) { - out.sitemapindex = { - sitemap: r.sitemapindex.sitemap.map((s) => ({ loc: s.loc })), - }; - } - if (r.sources) out.sources = r.sources; - return out; -}; - -// Try a candidate URL, return parsed result only when it looks like a real sitemap -const tryFetch = async (target, label) => { - try { - const parsed = await fetchSitemap(target); - if (isValidSitemap(parsed)) return parsed; - log.debug(`${label} parsed but lacked urlset/sitemapindex (${target})`); - } catch (error) { - log.debug(`${label} fetch failed (${target})`, error.message); - } - return null; -}; - -const sitemapHandler = async (url) => { - const origin = toOrigin(url); - let parsed = await tryFetch(`${origin}/sitemap.xml`, 'sitemap.xml'); - if (!parsed) { - const fromRobots = await findSitemapInRobots(origin); - if (fromRobots) parsed = await tryFetch(fromRobots, 'robots-listed sitemap'); - } - if (!parsed) return { skipped: 'No sitemap found for this site' }; - try { - return slimResult(await expandSitemap(parsed, 0)); - } catch (error) { - return upstreamError(error, 'Sitemap fetch'); - } -}; - -export const handler = middleware(sitemapHandler); -export default handler; +// Generated by scripts/sync-vercel-api.js, do not edit by hand +// Source of truth lives in packages/api/handlers +export { default, handler } from '../packages/api/handlers/sitemap.js'; diff --git a/api/social-tags.js b/api/social-tags.js index 7902f60cf..78506452b 100644 --- a/api/social-tags.js +++ b/api/social-tags.js @@ -1,76 +1,3 @@ -import * as cheerio from 'cheerio'; -import middleware from './_common/middleware.js'; -import { httpGet } from './_common/http.js'; -import { upstreamError } from './_common/upstream.js'; - -const socialTagsHandler = async (url) => { - let response; - try { - response = await httpGet(url); - } catch (error) { - return upstreamError(error, 'Social tags fetch'); - } - try { - const $ = cheerio.load(response.data); - - const metadata = { - // Basic meta tags - title: $('head title').text(), - description: $('meta[name="description"]').attr('content'), - keywords: $('meta[name="keywords"]').attr('content'), - canonicalUrl: $('link[rel="canonical"]').attr('href'), - - // OpenGraph Protocol - ogTitle: $('meta[property="og:title"]').attr('content'), - ogType: $('meta[property="og:type"]').attr('content'), - ogImage: $('meta[property="og:image"]').attr('content'), - ogUrl: $('meta[property="og:url"]').attr('content'), - ogDescription: $('meta[property="og:description"]').attr('content'), - ogSiteName: $('meta[property="og:site_name"]').attr('content'), - - // Twitter Cards - twitterCard: $('meta[name="twitter:card"]').attr('content'), - twitterSite: $('meta[name="twitter:site"]').attr('content'), - twitterCreator: $('meta[name="twitter:creator"]').attr('content'), - twitterTitle: $('meta[name="twitter:title"]').attr('content'), - twitterDescription: $('meta[name="twitter:description"]').attr('content'), - twitterImage: $('meta[name="twitter:image"]').attr('content'), - - // Misc - themeColor: $('meta[name="theme-color"]').attr('content'), - robots: $('meta[name="robots"]').attr('content'), - googlebot: $('meta[name="googlebot"]').attr('content'), - generator: $('meta[name="generator"]').attr('content'), - viewport: $('meta[name="viewport"]').attr('content'), - author: $('meta[name="author"]').attr('content'), - publisher: $('link[rel="publisher"]').attr('href'), - favicon: $('link[rel="icon"]').attr('href'), - }; - - const SOCIAL_FIELDS = [ - 'title', - 'description', - 'keywords', - 'canonicalUrl', - 'ogTitle', - 'ogImage', - 'ogDescription', - 'ogSiteName', - 'twitterTitle', - 'twitterDescription', - 'twitterImage', - 'author', - 'publisher', - 'themeColor', - ]; - if (!SOCIAL_FIELDS.some((f) => metadata[f])) { - return { skipped: 'No social tags found on this page' }; - } - return metadata; - } catch (error) { - return { error: `Failed parsing social tags: ${error.message}` }; - } -}; - -export const handler = middleware(socialTagsHandler); -export default handler; +// Generated by scripts/sync-vercel-api.js, do not edit by hand +// Source of truth lives in packages/api/handlers +export { default, handler } from '../packages/api/handlers/social-tags.js'; diff --git a/api/ssl.js b/api/ssl.js index fe166d5c1..996c6f0c4 100644 --- a/api/ssl.js +++ b/api/ssl.js @@ -1,36 +1,3 @@ -import tls from 'tls'; -import middleware from './_common/middleware.js'; - -const sslHandler = async (urlString) => { - const parsedUrl = new URL(urlString); - const options = { - host: parsedUrl.hostname, - port: parsedUrl.port || 443, - servername: parsedUrl.hostname, - rejectUnauthorized: false, - }; - - return new Promise((resolve, reject) => { - const socket = tls.connect(options, () => { - const cert = socket.getPeerCertificate(); - if (!cert || Object.keys(cert).length === 0) { - reject(new Error('No certificate presented by the server')); - socket.end(); - return; - } - const { raw, issuerCertificate, ...certData } = cert; - resolve({ - ...certData, - isValid: socket.authorized, - authError: socket.authorizationError || null, - }); - socket.end(); - }); - socket.on('error', (e) => { - reject(new Error(`SSL connection failed: ${e.message}`)); - }); - }); -}; - -export const handler = middleware(sslHandler); -export default handler; +// Generated by scripts/sync-vercel-api.js, do not edit by hand +// Source of truth lives in packages/api/handlers +export { default, handler } from '../packages/api/handlers/ssl.js'; diff --git a/api/status.js b/api/status.js index d3e37c9ca..b17a64665 100644 --- a/api/status.js +++ b/api/status.js @@ -1,58 +1,3 @@ -import https from 'https'; -import { performance, PerformanceObserver } from 'perf_hooks'; -import middleware from './_common/middleware.js'; - -const statusHandler = async (url) => { - if (!url) { - throw new Error('You must provide a URL query parameter!'); - } - - let dnsLookupTime; - let responseCode; - let startTime; - - const obs = new PerformanceObserver((items) => { - dnsLookupTime = items.getEntries()[0].duration; - performance.clearMarks(); - }); - - obs.observe({ entryTypes: ['measure'] }); - - performance.mark('A'); - - try { - startTime = performance.now(); - const response = await new Promise((resolve, reject) => { - const req = https.get(url, (res) => { - let data = ''; - responseCode = res.statusCode; - res.on('data', (chunk) => { - data += chunk; - }); - res.on('end', () => { - resolve(res); - }); - }); - - req.on('error', reject); - req.end(); - }); - - if (responseCode < 200 || responseCode >= 400) { - throw new Error(`Received non-success response code: ${responseCode}`); - } - - performance.mark('B'); - performance.measure('A to B', 'A', 'B'); - let responseTime = performance.now() - startTime; - obs.disconnect(); - - return { isUp: true, dnsLookupTime, responseTime, responseCode }; - } catch (error) { - obs.disconnect(); - throw error; - } -}; - -export const handler = middleware(statusHandler); -export default handler; +// Generated by scripts/sync-vercel-api.js, do not edit by hand +// Source of truth lives in packages/api/handlers +export { default, handler } from '../packages/api/handlers/status.js'; diff --git a/api/tech-stack.js b/api/tech-stack.js index 2d62eff3b..bf04066b3 100644 --- a/api/tech-stack.js +++ b/api/tech-stack.js @@ -1,47 +1,3 @@ -import chromium from '@sparticuz/chromium'; -import middleware from './_common/middleware.js'; - -// Wappalyzer reads CHROMIUM_BIN at module load, so we must resolve -// the path before importing it (hence the dynamic import in the handler) -const ensureChromiumBin = async () => { - if (process.env.CHROMIUM_BIN) return; - const envPath = process.env.CHROME_PATH || process.env.PUPPETEER_EXECUTABLE_PATH; - if (envPath) { - process.env.CHROMIUM_BIN = envPath; - return; - } - // On serverless, puppeteer has no cached binary, use @sparticuz/chromium - if (process.env.AWS_LAMBDA_FUNCTION_NAME || process.env.NETLIFY) { - process.env.CHROMIUM_BIN = await chromium.executablePath(); - // Avoid conflict with @sparticuz/chromium's extraction path at /tmp/chromium - if (!process.env.CHROMIUM_DATA_DIR) { - process.env.CHROMIUM_DATA_DIR = '/tmp/chromium-data'; - } - } -}; - -const techStackHandler = async (url) => { - await ensureChromiumBin(); - const { default: Wappalyzer } = await import('wappalyzer'); - const wappalyzer = new Wappalyzer({}); - - try { - await wappalyzer.init(); - const site = await wappalyzer.open(url, {}, { local: {}, session: {} }); - const results = await site.analyze(); - if (!results.technologies || results.technologies.length === 0) { - throw new Error('Unable to find any technologies for site'); - } - return results; - } catch (error) { - if (/ENOENT|Browser was not found|Could not find Chromium/i.test(error.message)) { - return { skipped: error.message }; - } - throw new Error(error.message); - } finally { - await wappalyzer.destroy(); - } -}; - -export const handler = middleware(techStackHandler); -export default handler; +// Generated by scripts/sync-vercel-api.js, do not edit by hand +// Source of truth lives in packages/api/handlers +export { default, handler } from '../packages/api/handlers/tech-stack.js'; diff --git a/api/threats.js b/api/threats.js index 1f8d72655..fb7d2cfca 100644 --- a/api/threats.js +++ b/api/threats.js @@ -1,96 +1,3 @@ -import xml2js from 'xml2js'; -import middleware from './_common/middleware.js'; -import { httpPost } from './_common/http.js'; -import { parseTarget } from './_common/parse-target.js'; -import { requireEnv, upstreamError } from './_common/upstream.js'; - -const safeBrowsing = async (url) => { - const auth = requireEnv('GOOGLE_CLOUD_API_KEY', 'Google Safe Browsing'); - if (auth.skipped) return auth; - try { - const res = await httpPost( - `https://safebrowsing.googleapis.com/v4/threatMatches:find?key=${auth.value}`, - { - threatInfo: { - threatTypes: [ - 'MALWARE', - 'SOCIAL_ENGINEERING', - 'UNWANTED_SOFTWARE', - 'POTENTIALLY_HARMFUL_APPLICATION', - 'API_ABUSE', - ], - platformTypes: ['ANY_PLATFORM'], - threatEntryTypes: ['URL'], - threatEntries: [{ url }], - }, - }, - ); - return res.data?.matches ? { unsafe: true, details: res.data.matches } : { unsafe: false }; - } catch (error) { - return upstreamError(error, 'Google Safe Browsing'); - } -}; - -const urlHaus = async (url) => { - const { hostname } = parseTarget(url); - try { - const res = await httpPost('https://urlhaus-api.abuse.ch/v1/host/', `host=${hostname}`, { - headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, - }); - return res.data; - } catch (error) { - return upstreamError(error, 'URLhaus'); - } -}; - -const phishTank = async (url) => { - try { - const encoded = Buffer.from(url).toString('base64'); - const res = await httpPost(`https://checkurl.phishtank.com/checkurl/?url=${encoded}`, null, { - headers: { 'User-Agent': 'phishtank/web-check' }, - timeout: 3000, - }); - const parsed = await xml2js.parseStringPromise(res.data, { explicitArray: false }); - return parsed.response.results; - } catch (error) { - return upstreamError(error, 'PhishTank'); - } -}; - -const cloudmersive = async (url) => { - const auth = requireEnv('CLOUDMERSIVE_API_KEY', 'Cloudmersive'); - if (auth.skipped) return auth; - try { - const res = await httpPost( - 'https://api.cloudmersive.com/virus/scan/website', - `Url=${encodeURIComponent(url)}`, - { - headers: { - 'Content-Type': 'application/x-www-form-urlencoded', - Apikey: auth.value, - }, - }, - ); - return res.data; - } catch (error) { - return upstreamError(error, 'Cloudmersive'); - } -}; - -// Aggregate four threat-feed lookups; skip the card if every source failed -const threatsHandler = async (url) => { - const sources = await Promise.all([ - safeBrowsing(url), - urlHaus(url), - phishTank(url), - cloudmersive(url), - ]); - const [safe, haus, phish, cloud] = sources; - if (sources.every((s) => s?.error || s?.skipped)) { - return { skipped: 'No threat sources returned data for this host' }; - } - return { safeBrowsing: safe, urlHaus: haus, phishTank: phish, cloudmersive: cloud }; -}; - -export const handler = middleware(threatsHandler); -export default handler; +// Generated by scripts/sync-vercel-api.js, do not edit by hand +// Source of truth lives in packages/api/handlers +export { default, handler } from '../packages/api/handlers/threats.js'; diff --git a/api/tls-connection.js b/api/tls-connection.js index 329b09c62..748ff8be2 100644 --- a/api/tls-connection.js +++ b/api/tls-connection.js @@ -1,84 +1,3 @@ -import tls from 'tls'; -import middleware from './_common/middleware.js'; -import { parseTarget } from './_common/parse-target.js'; - -const HANDSHAKE_TIMEOUT = 4000; - -const isIp = (h) => /^[\d.]+$/.test(h) || h.includes(':'); - -// Open one TLS handshake to the host and capture what was negotiated -const handshake = ({ hostname, port }) => - new Promise((resolve, reject) => { - let ocspStapled = false; - const socket = tls.connect({ - host: hostname, - port: port ? Number(port) : 443, - ...(isIp(hostname) ? {} : { servername: hostname }), - ALPNProtocols: ['h2', 'http/1.1'], - rejectUnauthorized: false, - requestOCSP: true, - }); - socket.on('OCSPResponse', (res) => { - ocspStapled = res?.length > 0; - }); - - let settled = false; - const finish = (fn) => (arg) => { - if (settled) return; - settled = true; - fn(arg); - }; - socket.setTimeout(HANDSHAKE_TIMEOUT); - socket.once( - 'secureConnect', - finish(() => { - const cipher = socket.getCipher(); - const protocol = socket.getProtocol(); - const ephemeral = - typeof socket.getEphemeralKeyInfo === 'function' ? socket.getEphemeralKeyInfo() : null; - const result = { - protocol, - cipher: cipher && { - name: cipher.name, - standardName: cipher.standardName, - version: cipher.version, - }, - alpnProtocol: socket.alpnProtocol || null, - sessionResumption: !!socket.getSession(), - forwardSecrecy: protocol === 'TLSv1.3' || (!!cipher && /^(ECDHE|DHE)/.test(cipher.name)), - authorized: socket.authorized, - authError: socket.authorizationError ? String(socket.authorizationError) : null, - ephemeralKey: ephemeral && { - type: ephemeral.type || null, - name: ephemeral.name || null, - size: ephemeral.size || null, - }, - ocspStapled, - }; - socket.end(); - resolve(result); - }), - ); - socket.once( - 'timeout', - finish(() => { - socket.destroy(); - reject(new Error('TLS handshake timed-out')); - }), - ); - socket.once( - 'error', - finish((err) => { - socket.destroy(); - reject(err); - }), - ); - }); - -const tlsConnectionHandler = async (url) => { - const { hostname, port } = parseTarget(url); - return handshake({ hostname, port }); -}; - -export const handler = middleware(tlsConnectionHandler); -export default handler; +// Generated by scripts/sync-vercel-api.js, do not edit by hand +// Source of truth lives in packages/api/handlers +export { default, handler } from '../packages/api/handlers/tls-connection.js'; diff --git a/api/tls-labs.js b/api/tls-labs.js index 900a3a7d7..c4596e17f 100644 --- a/api/tls-labs.js +++ b/api/tls-labs.js @@ -1,32 +1,3 @@ -import middleware from './_common/middleware.js'; -import { httpGet } from './_common/http.js'; -import { parseTarget } from './_common/parse-target.js'; -import { upstreamError } from './_common/upstream.js'; - -const SSL_LABS = 'https://api.ssllabs.com/api/v3/analyze'; - -// Pull a cached SSL Labs report; skip if no fresh cache available -const tlsLabsHandler = async (url) => { - const { hostname } = parseTarget(url); - try { - const res = await httpGet(SSL_LABS, { - params: { host: hostname, fromCache: 'on', maxAge: 24, all: 'done' }, - timeout: 8000, - headers: { 'User-Agent': 'web-check (https://web-check.xyz)' }, - }); - const data = res.data; - if (!data || data.status !== 'READY' || !data.endpoints?.length) { - return { - skipped: - 'No cached SSL Labs report for this host. ' + - 'Run a fresh scan at https://www.ssllabs.com/ssltest/', - }; - } - return data; - } catch (error) { - return upstreamError(error, 'SSL Labs lookup'); - } -}; - -export const handler = middleware(tlsLabsHandler); -export default handler; +// Generated by scripts/sync-vercel-api.js, do not edit by hand +// Source of truth lives in packages/api/handlers +export { default, handler } from '../packages/api/handlers/tls-labs.js'; diff --git a/api/trace-route.js b/api/trace-route.js index c181bdb91..557f36ff4 100644 --- a/api/trace-route.js +++ b/api/trace-route.js @@ -1,58 +1,3 @@ -import { execFile } from 'child_process'; -import middleware from './_common/middleware.js'; -import { parseTarget } from './_common/parse-target.js'; - -const LOCAL_TIMEOUT = 8000; - -// Parse traceroute -n output into [{ip, time}] entries, skipping unanswered hops -const parseHops = (stdout) => { - const hops = []; - for (const line of stdout.split('\n')) { - const m = line.match(/^\s*\d+\s+([\d.]+|\S*::\S*)\s+([\d.]+)\s*ms/); - if (m) hops.push({ ip: m[1], time: Number(m[2]) }); - } - return hops; -}; - -// Run the system traceroute binary via execFile (no shell, no injection) -const runTraceroute = (host) => - new Promise((resolve, reject) => { - execFile( - 'traceroute', - ['-q', '1', '-n', '-w', '2', host], - { timeout: LOCAL_TIMEOUT }, - (err, stdout) => (err ? reject(err) : resolve(parseHops(stdout))), - ); - }); - -const isMissingBinary = (err) => - err?.code === 'ENOENT' || /command not found|not installed/i.test(err?.message || ''); - -const traceRouteHandler = async (url) => { - const start = Date.now(); - const { hostname } = parseTarget(url); - let hops; - try { - hops = await runTraceroute(hostname); - } catch (err) { - if (isMissingBinary(err)) { - return { - skipped: - 'Traceroute is not installed in this environment. ' + - 'Install via your package manager, or run web-check via Docker.', - }; - } - return { error: `Traceroute failed: ${err.message}` }; - } - if (!hops.length) { - return { skipped: 'Traceroute returned no answered hops for this host' }; - } - return { - message: 'Traceroute completed!', - result: hops.map(({ ip, time }) => ({ [ip]: [time] })), - timeTaken: Date.now() - start, - }; -}; - -export const handler = middleware(traceRouteHandler); -export default handler; +// Generated by scripts/sync-vercel-api.js, do not edit by hand +// Source of truth lives in packages/api/handlers +export { default, handler } from '../packages/api/handlers/trace-route.js'; diff --git a/api/txt-records.js b/api/txt-records.js index 76303605a..564a51d86 100644 --- a/api/txt-records.js +++ b/api/txt-records.js @@ -1,22 +1,3 @@ -import dns from 'dns/promises'; -import middleware from './_common/middleware.js'; -import { parseTarget } from './_common/parse-target.js'; - -const txtRecordHandler = async (url) => { - const { hostname } = parseTarget(url); - const txtRecords = await dns.resolveTxt(hostname); - // Join chunks (DNS splits long records at 255 bytes), then key=value - const result = {}; - for (const chunks of txtRecords) { - const full = chunks.join(''); - const eq = full.indexOf('='); - let key = eq > 0 ? full.slice(0, eq) : full; - const val = eq > 0 ? full.slice(eq + 1) : ''; - while (key in result) key += '_'; - result[key] = val; - } - return result; -}; - -export const handler = middleware(txtRecordHandler); -export default handler; +// Generated by scripts/sync-vercel-api.js, do not edit by hand +// Source of truth lives in packages/api/handlers +export { default, handler } from '../packages/api/handlers/txt-records.js'; diff --git a/api/whois.js b/api/whois.js index 9a3e0ec13..977476f81 100644 --- a/api/whois.js +++ b/api/whois.js @@ -1,135 +1,3 @@ -import net from 'net'; -import psl from 'psl'; -import { whoisDomain } from 'whoiser'; -import middleware from './_common/middleware.js'; -import { parseTarget } from './_common/parse-target.js'; -import { createLogger } from './_common/logger.js'; - -const log = createLogger('whois'); -const TIMEOUT = 8000; - -// Walk every WHOIS/RDAP source, return the first non-empty value across the given keys -const pick = (results, ...keys) => { - for (const src of Object.values(results)) { - for (const key of keys) { - const v = src?.[key]; - if (v === undefined || v === null) continue; - if (typeof v === 'string' && !v.trim()) continue; - if (Array.isArray(v) && !v.length) continue; - return v; - } - } - return undefined; -}; - -// Lower-case + dedupe nameservers, drop empty entries -const cleanNs = (ns) => { - if (!Array.isArray(ns)) return undefined; - const out = [...new Set(ns.map((n) => String(n).trim().toLowerCase()).filter(Boolean))]; - return out.length ? out : undefined; -}; - -// Convert a date string to ISO 8601 when parseable, otherwise return the raw value -const toIso = (raw) => { - if (!raw || typeof raw !== 'string') return raw; - const trimmed = raw.trim().replace(/\s*#.*$/, ''); - const t = Date.parse(trimmed); - if (!Number.isNaN(t)) return new Date(t).toISOString(); - const m = trimmed.match(/^(\d{4})(\d{2})(\d{2})$/); - if (m) return new Date(`${m[1]}-${m[2]}-${m[3]}T00:00:00Z`).toISOString(); - return raw; -}; - -// Reduce a hostname to its registrable domain so registry WHOIS lookups succeed -const baseDomain = (host) => psl.parse(host)?.domain || host; - -// Pull the formatted-name value out of an RDAP entity vCard -const vcardFn = (vcard) => { - if (!Array.isArray(vcard?.[1])) return undefined; - const fn = vcard[1].find((f) => Array.isArray(f) && f[0] === 'fn'); - return fn?.[3] || undefined; -}; - -// Map an RDAP response into the same field names whoiser exposes, so pick() works uniformly -const rdapToWhoiserShape = (data) => { - if (!data || data.errorCode || data.objectClassName === 'error') return null; - const events = data.events || []; - const evt = (a) => events.find((e) => e.eventAction === a)?.eventDate; - const registrar = (data.entities || []).find((e) => (e.roles || []).includes('registrar')); - const ianaId = registrar?.publicIds?.find((p) => /iana/i.test(p.type))?.identifier; - const registrarUrlEntry = registrar?.links?.find((l) => l.rel === 'about' || l.rel === 'related'); - return { - 'Domain Name': data.ldhName, - 'Created Date': evt('registration'), - 'Updated Date': evt('last changed') || evt('last update of RDAP database'), - 'Expiry Date': evt('expiration'), - 'Registry Domain ID': data.handle, - Registrar: vcardFn(registrar?.vcardArray), - 'Registrar IANA ID': ianaId, - 'Registrar URL': registrarUrlEntry?.href, - 'Domain Status': data.status, - 'Name Server': (data.nameservers || []).map((n) => n.ldhName).filter(Boolean), - DNSSEC: data.secureDNS?.delegationSigned ? 'signed' : 'unsigned', - }; -}; - -// Last-resort lookup via rdap.org (a meta-resolver that bootstraps the right RDAP server) -const fetchRdapFallback = async (domain) => { - try { - const res = await fetch(`https://rdap.org/domain/${encodeURIComponent(domain)}`, { - signal: AbortSignal.timeout(TIMEOUT), - }); - if (!res.ok) return null; - return rdapToWhoiserShape(await res.json()); - } catch { - return null; - } -}; - -// Whether a parsed result set has anything worth returning to the frontend -const hasUsefulData = (r) => - r && - (pick(r, 'Created Date', 'Creation Date') || - pick(r, 'Updated Date') || - pick(r, 'Expiry Date', 'Registry Expiry Date') || - pick(r, 'Registrar') || - cleanNs(pick(r, 'Name Server'))); - -// Resolve domain registration data via whoiser, with rdap.org as a fallback for TLD gaps -const whoisHandler = async (url) => { - const { hostname } = parseTarget(url); - if (net.isIP(hostname)) { - return { skipped: 'WHOIS lookups apply to domains, not IP addresses' }; - } - const target = baseDomain(hostname); - let results = {}; - try { - results = await whoisDomain(target, { follow: 2, timeout: TIMEOUT }); - } catch (error) { - log.debug(`whoisDomain failed for ${target}: ${error.message}`); - } - if (!hasUsefulData(results)) { - const rdap = await fetchRdapFallback(target); - if (rdap) results = { ...results, 'rdap.org': rdap }; - } - if (!hasUsefulData(results)) { - return { skipped: 'No WHOIS data available for this domain' }; - } - return { - domain: pick(results, 'Domain Name') || target, - registrar: pick(results, 'Registrar'), - registrarUrl: pick(results, 'Registrar URL'), - registrarIanaId: pick(results, 'Registrar IANA ID'), - registrarWhoisServer: pick(results, 'Registrar WHOIS Server'), - registryDomainId: pick(results, 'Registry Domain ID'), - created: toIso(pick(results, 'Created Date', 'Creation Date')), - updated: toIso(pick(results, 'Updated Date')), - expires: toIso(pick(results, 'Expiry Date', 'Registry Expiry Date', 'Expiration Date')), - nameservers: cleanNs(pick(results, 'Name Server')), - status: pick(results, 'Domain Status'), - dnssec: pick(results, 'DNSSEC'), - }; -}; - -export const handler = middleware(whoisHandler); -export default handler; +// Generated by scripts/sync-vercel-api.js, do not edit by hand +// Source of truth lives in packages/api/handlers +export { default, handler } from '../packages/api/handlers/whois.js'; diff --git a/astro.config.mjs b/astro.config.mjs deleted file mode 100644 index a5d02e47c..000000000 --- a/astro.config.mjs +++ /dev/null @@ -1,78 +0,0 @@ -import { defineConfig } from 'astro/config'; - -// Integrations -import svelte from '@astrojs/svelte'; -import react from '@astrojs/react'; -import partytown from '@astrojs/partytown'; -import sitemap from '@astrojs/sitemap'; - -// Adapters -import vercelAdapter from '@astrojs/vercel'; -import netlifyAdapter from '@astrojs/netlify'; -import nodeAdapter from '@astrojs/node'; -import cloudflareAdapter from '@astrojs/cloudflare'; - -// Helper function to unwrap both Vite and Node environment variables -const unwrapEnvVar = (varName, fallbackValue) => { - const classicEnvVar = process?.env && process.env[varName]; - const viteEnvVar = import.meta.env[varName]; - return classicEnvVar || viteEnvVar || fallbackValue; -}; - -// Determine the deploy target (vercel, netlify, cloudflare, node) -const deployTarget = unwrapEnvVar('PLATFORM', 'node').toLowerCase(); - -// Determine the output mode (static or server). Mixed prerender supported in static mode -const output = unwrapEnvVar('OUTPUT', 'static'); - -// The FQDN of where the site is hosted (used for sitemaps & canonical URLs) -const site = unwrapEnvVar('SITE_URL', 'https://web-check.xyz'); - -// The base URL of the site (if serving from a subdirectory) -const base = unwrapEnvVar('BASE_URL', '/'); - -// Should run the app in boss-mode (requires extra configuration) -const isBossServer = unwrapEnvVar('BOSS_SERVER', false); - -// Initialize Astro integrations -const integrations = [svelte(), react(), partytown(), sitemap()]; - -// Set the appropriate adapter, based on the deploy target -function getAdapter(target) { - switch (target) { - case 'vercel': - return vercelAdapter(); - case 'netlify': - return netlifyAdapter(); - case 'cloudflare': - return cloudflareAdapter(); - case 'node': - return nodeAdapter({ mode: 'middleware' }); - default: - throw new Error(`Unsupported deploy target: ${target}`); - } -} -const adapter = getAdapter(deployTarget); - -// Print build information to console -console.log( - `\n\x1b[1m\x1b[35m Preparing to start build of Web Check.... \x1b[0m\n`, - `\x1b[35m\x1b[2mCompiling for "${deployTarget}" using "${output}" mode, ` + - `to deploy to "${site}" at "${base}"\x1b[0m\n`, - `\x1b[2m\x1b[36m🛟 For documentation and support, visit the GitHub repo: ` + - `https://github.com/lissy93/web-check \n`, - `💖 Found Web-Check useful? Consider sponsoring us on GitHub ` + - `to help fund maintenance & development.\x1b[0m\n`, -); - -const redirects = { - '/about': '/check/about', -}; - -// Skip the marketing homepage for self-hosted users -if (!isBossServer && isBossServer !== true) { - redirects['/'] = '/check'; -} - -// Export Astro configuration -export default defineConfig({ output, base, integrations, site, adapter, redirects }); diff --git a/netlify.toml b/netlify.toml index 136485ec2..0c9717d29 100644 --- a/netlify.toml +++ b/netlify.toml @@ -1,41 +1,27 @@ -# Build settings and site core config [build] base = "/" command = "yarn build" - publish = "dist" - functions = "api" + publish = "packages/site/dist" + functions = "packages/api/handlers" -# Environmental variables and optional secrets [build.environment] PLATFORM = "netlify" - PUBLIC_API_ENDPOINT = "/.netlify/functions" - # Build configuration env vars (uncomment if you want to conigure these) - # CI="false" # Set CI to false, to prevent warnings from exiting the build - # CHROME_PATH='/usr/bin/chromium' # Path to Chromium binary - # NODE_VERSION = "16.16.0" # Set the version of Node.js to use - # Optional secrets and API keys (uncomment if you want to add these) - # GOOGLE_CLOUD_API_KEY='' # Google Cloud API key, for running Lighthouse scans - # BUILT_WITH_API_KEY='' # BuiltWith API key, for detecting site features - # REACT_APP_SHODAN_API_KEY='' # Shodan API key, for using Shodan scan API - # REACT_APP_WHO_API_KEY='' # WhoAPI key, for iniiating client-side whois lookup - -# Redirect the /api/* path to the lambda functions [[redirects]] from = "/api/*" to = "/.netlify/functions/:splat" - status = 301 - force = true + status = 200 + +[[redirects]] + from = "/check/*" + to = "/check/index.html" + status = 200 -# Plugins [[plugins]] -package = "netlify-plugin-chromium" + package = "netlify-plugin-chromium" [plugins.inputs] - packageManager = "yarn" + packageManager = "yarn" -# Set any security headers here [[headers]] for = "/*" [headers.values] - # Uncomment to enable Netlify user control. Requires premium plan. - # Basic-Auth = "someuser:somepassword anotheruser:anotherpassword" diff --git a/package.json b/package.json index 541838a44..037e93fcc 100644 --- a/package.json +++ b/package.json @@ -2,60 +2,38 @@ "name": "web-check", "type": "module", "version": "2.1.0", + "private": true, "homepage": "https://web-check.xyz", "engines": { "node": ">=22" }, + "workspaces": [ + "packages/*" + ], "scripts": { - "start": "node server", - "build": "astro check && astro build", + "start": "yarn workspace @web-check/api start", + "prebuild": "node scripts/sync-vercel-api.js", + "build": "yarn workspace @web-check/app build && yarn workspace @web-check/site build", + "build:app": "yarn workspace @web-check/app build", + "build:site": "yarn workspace @web-check/site build", + "build:docker": "yarn build:app", + "dev:api": "yarn workspace @web-check/api dev", + "dev:site": "yarn workspace @web-check/site dev", "dev:vercel": "PLATFORM='vercel' npx vercel dev", "dev:netlify": "PLATFORM='netlify' npx netlify dev", - "dev:api": "DISABLE_GUI='true' PORT='3001' nodemon server", - "dev:astro": "PUBLIC_API_ENDPOINT=http://localhost:3001/api astro dev", - "dev": "concurrently -c magenta,cyan -n backend,frontend 'yarn dev:api' 'yarn dev:astro'", - "typecheck": "astro check", + "dev": "concurrently -c magenta,cyan -n backend,frontend 'yarn dev:api' 'yarn dev:site'", + "typecheck": "yarn workspace @web-check/site typecheck", "lint": "eslint --config .config/eslint.config.js .", "format:check": "prettier --check --ignore-unknown '!yarn.lock' '!**/*.md' .", "format:fix": "prettier --write --ignore-unknown '!yarn.lock' '!**/*.md' ." }, - "dependencies": { - "@astrojs/check": "^0.9.9", - "@astrojs/react": "^5.0.4", - "@emotion/react": "^11.14.0", - "@emotion/styled": "^11.14.1", - "@fortawesome/fontawesome-svg-core": "^7.2.0", - "@fortawesome/free-brands-svg-icons": "^7.2.0", - "@fortawesome/free-regular-svg-icons": "^7.2.0", - "@fortawesome/free-solid-svg-icons": "^7.2.0", - "@fortawesome/svelte-fontawesome": "^0.2.4", - "@sparticuz/chromium": "^148.0.0", - "@types/react": "^19.2.14", - "@types/react-dom": "^19.2.3", - "astro": "^6.2.2", - "cheerio": "^1.2.0", - "chromium": "^3.0.3", - "cors": "^2.8.6", - "dotenv": "^17.4.2", - "express": "^5.2.1", - "express-rate-limit": "^8.5.0", - "framer-motion": "^12.38.0", - "prop-types": "^15.8.1", - "psl": "^1.15.0", - "puppeteer": "^24.42.0", - "puppeteer-core": "^24.42.0", - "react": "^19.2.5", - "react-dom": "^19.2.5", - "react-masonry-css": "^1.0.16", - "react-router-dom": "^7.14.2", - "react-simple-maps": "^3.0.0", - "react-toastify": "^11.1.0", - "recharts": "^3.8.1", - "svelte": "^5.55.5", - "typescript": "^6.0.3", - "wappalyzer": "^6.10.66", - "whoiser": "^2.0.0-beta.10", - "xml2js": "^0.6.2" + "devDependencies": { + "@typescript-eslint/parser": "^8.59.2", + "concurrently": "^9.2.1", + "eslint": "^10.3.0", + "eslint-plugin-astro": "^1.7.0", + "prettier": "^3.8.3", + "prettier-plugin-astro": "^0.14.1" }, "resolutions": { "tar-fs": "^2.1.4", @@ -69,24 +47,6 @@ "uuid": "^14.0.0", "yaml": "^2.8.3" }, - "devDependencies": { - "@astrojs/cloudflare": "^13.3.1", - "@astrojs/netlify": "^7.0.8", - "@astrojs/node": "^10.0.6", - "@astrojs/partytown": "^2.1.7", - "@astrojs/sitemap": "^3.7.2", - "@astrojs/svelte": "^8.1.0", - "@astrojs/ts-plugin": "^1.10.7", - "@astrojs/vercel": "^10.0.6", - "@typescript-eslint/parser": "^8.59.2", - "concurrently": "^9.2.1", - "eslint": "^10.3.0", - "eslint-plugin-astro": "^1.7.0", - "nodemon": "^3.1.14", - "prettier": "^3.8.3", - "prettier-plugin-astro": "^0.14.1", - "sass": "^1.99.0" - }, "prettier": { "printWidth": 100, "semi": true, diff --git a/api/_common/http.js b/packages/api/handlers/_common/http.js similarity index 100% rename from api/_common/http.js rename to packages/api/handlers/_common/http.js diff --git a/api/_common/logger.js b/packages/api/handlers/_common/logger.js similarity index 100% rename from api/_common/logger.js rename to packages/api/handlers/_common/logger.js diff --git a/api/_common/middleware.js b/packages/api/handlers/_common/middleware.js similarity index 96% rename from api/_common/middleware.js rename to packages/api/handlers/_common/middleware.js index e96cb30d5..44dd42da6 100644 --- a/api/_common/middleware.js +++ b/packages/api/handlers/_common/middleware.js @@ -116,6 +116,8 @@ const commonMiddleware = (handler) => { return nativeMode ? vercelHandler : netlifyHandler; }; +// Netlify bundles handlers as CJS, esbuild's interop loses the default export +// unless module.exports is the function itself. Do not remove the CJS branch if (PLATFORM === 'NETLIFY') { module.exports = commonMiddleware; } diff --git a/api/_common/parse-target.js b/packages/api/handlers/_common/parse-target.js similarity index 100% rename from api/_common/parse-target.js rename to packages/api/handlers/_common/parse-target.js diff --git a/api/_common/upstream.js b/packages/api/handlers/_common/upstream.js similarity index 100% rename from api/_common/upstream.js rename to packages/api/handlers/_common/upstream.js diff --git a/packages/api/handlers/archives.js b/packages/api/handlers/archives.js new file mode 100644 index 000000000..4818c2a2a --- /dev/null +++ b/packages/api/handlers/archives.js @@ -0,0 +1,84 @@ +import middleware from './_common/middleware.js'; +import { httpGet } from './_common/http.js'; + +const convertTimestampToDate = (timestamp) => { + const [year, month, day, hour, minute, second] = [ + timestamp.slice(0, 4), + timestamp.slice(4, 6) - 1, + timestamp.slice(6, 8), + timestamp.slice(8, 10), + timestamp.slice(10, 12), + timestamp.slice(12, 14), + ].map((num) => parseInt(num, 10)); + + return new Date(year, month, day, hour, minute, second); +}; + +const countPageChanges = (results) => { + let prevDigest = null; + return results.reduce((acc, curr) => { + if (curr[2] !== prevDigest) { + prevDigest = curr[2]; + return acc + 1; + } + return acc; + }, -1); +}; + +const getAveragePageSize = (scans) => { + const totalSize = scans.map((scan) => parseInt(scan[3], 10)).reduce((sum, size) => sum + size, 0); + return Math.round(totalSize / scans.length); +}; + +const getScanFrequency = (firstScan, lastScan, totalScans, changeCount) => { + const formatToTwoDecimal = (num) => parseFloat(num.toFixed(2)); + + const dayFactor = (lastScan - firstScan) / (1000 * 60 * 60 * 24); + const daysBetweenScans = formatToTwoDecimal(dayFactor / totalScans); + const daysBetweenChanges = formatToTwoDecimal(dayFactor / changeCount); + const scansPerDay = formatToTwoDecimal((totalScans - 1) / dayFactor); + const changesPerDay = formatToTwoDecimal(changeCount / dayFactor); + return { + daysBetweenScans, + daysBetweenChanges, + scansPerDay, + changesPerDay, + }; +}; + +const wayBackHandler = async (url) => { + const cdxUrl = `https://web.archive.org/cdx/search/cdx?url=${url}&output=json&fl=timestamp,statuscode,digest,length,offset`; + + try { + const { data } = await httpGet(cdxUrl); + + // Check there's data + if (!data || !Array.isArray(data) || data.length <= 1) { + return { skipped: 'Site has never before been archived via the Wayback Machine' }; + } + + // Remove the header row + data.shift(); + + // Process and return the results + const firstScan = convertTimestampToDate(data[0][0]); + const lastScan = convertTimestampToDate(data[data.length - 1][0]); + const totalScans = data.length; + const changeCount = countPageChanges(data); + return { + firstScan, + lastScan, + totalScans, + changeCount, + averagePageSize: getAveragePageSize(data), + scanFrequency: getScanFrequency(firstScan, lastScan, totalScans, changeCount), + scans: data, + scanUrl: url, + }; + } catch (err) { + return { error: `Error fetching Wayback data: ${err.message}` }; + } +}; + +export const handler = middleware(wayBackHandler); +export default handler; diff --git a/packages/api/handlers/block-lists.js b/packages/api/handlers/block-lists.js new file mode 100644 index 000000000..f34c0250b --- /dev/null +++ b/packages/api/handlers/block-lists.js @@ -0,0 +1,62 @@ +import dns from 'dns'; +import middleware from './_common/middleware.js'; +import { parseTarget } from './_common/parse-target.js'; + +const DNS_SERVERS = [ + { name: 'AdGuard', ip: '176.103.130.130' }, + { name: 'AdGuard Family', ip: '176.103.130.132' }, + { name: 'CleanBrowsing Adult', ip: '185.228.168.10' }, + { name: 'CleanBrowsing Family', ip: '185.228.168.168' }, + { name: 'CleanBrowsing Security', ip: '185.228.168.9' }, + { name: 'CloudFlare', ip: '1.1.1.1' }, + { name: 'CloudFlare Family', ip: '1.1.1.3' }, + { name: 'Comodo Secure', ip: '8.26.56.26' }, + { name: 'Google DNS', ip: '8.8.8.8' }, + { name: 'OpenDNS', ip: '208.67.222.222' }, + { name: 'OpenDNS Family', ip: '208.67.222.123' }, + { name: 'Quad9', ip: '9.9.9.9' }, +]; + +// Sink IPs used by blocking DNS servers +const SINK_IPS = new Set(['0.0.0.0', '127.0.0.1', '::1', '::', '0:0:0:0:0:0:0:0']); + +// Resolve a domain via a specific DNS server +const queryServer = (domain, serverIp) => + new Promise((resolve) => { + const resolver = new dns.Resolver({ timeout: 3000, tries: 1 }); + resolver.setServers([serverIp]); + resolver.resolve4(domain, (err, addrs) => { + if (err) return resolve({ err: err.code }); + resolve({ addrs }); + }); + }); + +// A domain is blocked if the resolver returns a sink IP or refuses +// to resolve a domain that a neutral resolver can resolve +const isBlocked = (result, refResolved) => { + if (!refResolved) return false; + if (result.err === 'NXDOMAIN' || result.err === 'SERVFAIL') return true; + if (!result.addrs) return false; + return result.addrs.every((ip) => SINK_IPS.has(ip)); +}; + +const blockListHandler = async (url) => { + const { hostname: domain } = parseTarget(url); + const ref = await queryServer(domain, '8.8.8.8'); + const refResolved = !!ref.addrs?.length; + + const results = await Promise.all( + DNS_SERVERS.map(async ({ name, ip }) => { + const result = await queryServer(domain, ip); + return { + server: name, + serverIp: ip, + isBlocked: isBlocked(result, refResolved), + }; + }), + ); + return { blocklists: results }; +}; + +export const handler = middleware(blockListHandler); +export default handler; diff --git a/packages/api/handlers/carbon.js b/packages/api/handlers/carbon.js new file mode 100644 index 000000000..1e8e01665 --- /dev/null +++ b/packages/api/handlers/carbon.js @@ -0,0 +1,79 @@ +import middleware from './_common/middleware.js'; +import { createLogger } from './_common/logger.js'; + +const log = createLogger('carbon'); + +const TIMEOUT = 8000; +const MAX_BYTES = 10 * 1024 * 1024; +const USER_AGENT = 'Mozilla/5.0 (compatible; WebCheck/2.0; +https://web-check.xyz)'; + +// Sustainable Web Design model v3 constants, matches websitecarbon.com formula +const KWH_PER_GB = 0.81; +const FIRST_VISIT = 0.25; +const RETURN_VISIT = 0.75; +const RETURN_DATA_PCT = 0.02; +const GRID_INTENSITY = 442; +const RENEWABLE_INTENSITY = 50; +const LITRES_PER_GRAM = 0.5562; + +// Stream the response, cap at MAX_BYTES so huge pages can't blow memory or time +const fetchByteCount = async (url) => { + const r = await fetch(url, { + signal: AbortSignal.timeout(TIMEOUT), + redirect: 'follow', + headers: { 'user-agent': USER_AGENT, accept: 'text/html,*/*;q=0.1' }, + }); + if (!r.ok) throw new Error(`status ${r.status}`); + if (!r.body) return 0; + const reader = r.body.getReader(); + let total = 0; + while (total < MAX_BYTES) { + const { value, done } = await reader.read(); + if (done) break; + total += value.length; + } + reader.cancel().catch(() => {}); + return total; +}; + +// SWD-based stats matching websitecarbon /data response shape +const computeCarbon = (bytes) => { + const adjustedBytes = bytes * (FIRST_VISIT + RETURN_VISIT * RETURN_DATA_PCT); + const energy = (adjustedBytes / 1073741824) * KWH_PER_GB; + const gridGrams = energy * GRID_INTENSITY; + const renewableGrams = energy * RENEWABLE_INTENSITY; + return { + adjustedBytes, + energy, + co2: { + grid: { grams: gridGrams, litres: gridGrams * LITRES_PER_GRAM }, + renewable: { + grams: renewableGrams, + litres: renewableGrams * LITRES_PER_GRAM, + }, + }, + }; +}; + +// Fetch site, count bytes, compute SWD carbon stats locally, no third-party API +const carbonHandler = async (url) => { + let bytes; + try { + bytes = await fetchByteCount(url); + } catch (error) { + log.warn(`fetch failed for ${url}`, error.message); + return { error: `Failed to fetch site: ${error.message}` }; + } + if (!bytes) return { skipped: 'Site returned no content, cannot calculate carbon' }; + log.debug(`measured ${bytes} bytes for ${url}`); + return { + url, + bytes, + green: false, + statistics: computeCarbon(bytes), + scanUrl: url, + }; +}; + +export const handler = middleware(carbonHandler); +export default handler; diff --git a/packages/api/handlers/cookies.js b/packages/api/handlers/cookies.js new file mode 100644 index 000000000..bc6093211 --- /dev/null +++ b/packages/api/handlers/cookies.js @@ -0,0 +1,51 @@ +import puppeteer from 'puppeteer'; +import middleware from './_common/middleware.js'; +import { httpGet } from './_common/http.js'; + +const getPuppeteerCookies = async (url) => { + const browser = await puppeteer.launch({ + headless: true, + args: ['--no-sandbox', '--disable-setuid-sandbox'], + }); + + try { + const page = await browser.newPage(); + const navigationPromise = page.goto(url, { waitUntil: 'networkidle2' }); + const timeoutPromise = new Promise((_, reject) => + setTimeout(() => reject(new Error('Puppeteer took too long!')), 3000), + ); + await Promise.race([navigationPromise, timeoutPromise]); + return await browser.cookies(); + } finally { + await browser.close(); + } +}; + +const cookieHandler = async (url) => { + let headerCookies = null; + let clientCookies = null; + + try { + const response = await httpGet(url); + headerCookies = response.headers['set-cookie']; + } catch (error) { + if (error.response) { + return { error: `Request failed with status ${error.response.status}: ${error.message}` }; + } + return { error: `No response received: ${error.message}` }; + } + + try { + clientCookies = await getPuppeteerCookies(url); + } catch (_) { + clientCookies = null; + } + + return { + headerCookies: headerCookies || [], + clientCookies: clientCookies || [], + }; +}; + +export const handler = middleware(cookieHandler); +export default handler; diff --git a/packages/api/handlers/dns-server.js b/packages/api/handlers/dns-server.js new file mode 100644 index 000000000..b4b6b5077 --- /dev/null +++ b/packages/api/handlers/dns-server.js @@ -0,0 +1,33 @@ +import { promises as dnsPromises } from 'dns'; +import middleware from './_common/middleware.js'; +import { parseTarget } from './_common/parse-target.js'; +import { upstreamError } from './_common/upstream.js'; + +// Resolve a nameserver hostname to its IP addresses +const resolveNs = async (ns) => { + try { + return (await dnsPromises.resolve4(ns))[0]; + } catch { + return null; + } +}; + +const dnsHandler = async (url) => { + const { hostname: domain } = parseTarget(url); + let nameservers; + try { + nameservers = await dnsPromises.resolveNs(domain); + } catch (error) { + return upstreamError(error, 'DNS server lookup'); + } + const results = await Promise.all( + nameservers.map(async (ns) => { + const ip = await resolveNs(ns); + return { address: ip, hostname: ns }; + }), + ); + return { domain, dns: results }; +}; + +export const handler = middleware(dnsHandler); +export default handler; diff --git a/packages/api/handlers/dns.js b/packages/api/handlers/dns.js new file mode 100644 index 000000000..307853eea --- /dev/null +++ b/packages/api/handlers/dns.js @@ -0,0 +1,23 @@ +import dns from 'dns/promises'; +import middleware from './_common/middleware.js'; +import { parseTarget } from './_common/parse-target.js'; + +const dnsHandler = async (url) => { + const { hostname } = parseTarget(url); + const safe = (fn) => fn.catch(() => []); + const [a, aaaa, mx, txt, ns, cname, soa, srv, ptr] = await Promise.all([ + safe(dns.resolve4(hostname)), + safe(dns.resolve6(hostname)), + safe(dns.resolveMx(hostname)), + safe(dns.resolveTxt(hostname)), + safe(dns.resolveNs(hostname)), + safe(dns.resolveCname(hostname)), + dns.resolveSoa(hostname).catch(() => null), + safe(dns.resolveSrv(hostname)), + safe(dns.resolvePtr(hostname)), + ]); + return { A: a, AAAA: aaaa, MX: mx, TXT: txt, NS: ns, CNAME: cname, SOA: soa, SRV: srv, PTR: ptr }; +}; + +export const handler = middleware(dnsHandler); +export default handler; diff --git a/packages/api/handlers/dnssec.js b/packages/api/handlers/dnssec.js new file mode 100644 index 000000000..6ef983b9c --- /dev/null +++ b/packages/api/handlers/dnssec.js @@ -0,0 +1,38 @@ +import middleware from './_common/middleware.js'; +import { httpGet } from './_common/http.js'; +import { parseTarget } from './_common/parse-target.js'; + +// Query Google's public DNS JSON API for a given record type +const queryDns = async (domain, type) => { + const res = await httpGet('https://dns.google/resolve', { + params: { name: domain, type }, + headers: { Accept: 'application/dns-json' }, + timeout: 5000, + }); + return res.data; +}; + +const dnsSecHandler = async (url) => { + const { hostname } = parseTarget(url); + const [dnskey, ds, aRecord] = await Promise.all([ + queryDns(hostname, 'DNSKEY'), + queryDns(hostname, 'DS'), + queryDns(hostname, 'A'), + ]); + return { + DNSKEY: dnskey.Answer + ? { isFound: true, answer: dnskey.Answer, response: dnskey.Answer } + : { isFound: false, answer: null, response: dnskey }, + DS: ds.Answer + ? { isFound: true, answer: ds.Answer, response: ds.Answer } + : { isFound: false, answer: null, response: ds }, + RRSIG: { + isFound: !!aRecord.AD, + answer: null, + response: aRecord, + }, + }; +}; + +export const handler = middleware(dnsSecHandler); +export default handler; diff --git a/packages/api/handlers/firewall.js b/packages/api/handlers/firewall.js new file mode 100644 index 000000000..497c595b4 --- /dev/null +++ b/packages/api/handlers/firewall.js @@ -0,0 +1,112 @@ +import middleware from './_common/middleware.js'; +import { httpGet } from './_common/http.js'; +import { parseTarget } from './_common/parse-target.js'; +import { upstreamError } from './_common/upstream.js'; + +const hasWaf = (waf) => ({ hasWaf: true, waf }); + +const firewallHandler = async (url) => { + const { href } = parseTarget(url); + try { + const response = await httpGet(href, { + validateStatus: () => true, + }); + const headers = response.headers; + + if (headers['server'] && headers['server'].includes('cloudflare')) { + return hasWaf('Cloudflare'); + } + + if (headers['x-powered-by'] && headers['x-powered-by'].includes('AWS Lambda')) { + return hasWaf('AWS WAF'); + } + + if (headers['server'] && headers['server'].includes('AkamaiGHost')) { + return hasWaf('Akamai'); + } + + if (headers['server'] && headers['server'].includes('Sucuri')) { + return hasWaf('Sucuri'); + } + + if (headers['server'] && headers['server'].includes('BarracudaWAF')) { + return hasWaf('Barracuda WAF'); + } + + if ( + headers['server'] && + (headers['server'].includes('F5 BIG-IP') || headers['server'].includes('BIG-IP')) + ) { + return hasWaf('F5 BIG-IP'); + } + + if (headers['x-sucuri-id'] || headers['x-sucuri-cache']) { + return hasWaf('Sucuri CloudProxy WAF'); + } + + if (headers['server'] && headers['server'].includes('FortiWeb')) { + return hasWaf('Fortinet FortiWeb WAF'); + } + + if (headers['server'] && headers['server'].includes('Imperva')) { + return hasWaf('Imperva SecureSphere WAF'); + } + + if (headers['x-protected-by'] && headers['x-protected-by'].includes('Sqreen')) { + return hasWaf('Sqreen'); + } + + if (headers['x-waf-event-info']) { + return hasWaf('Reblaze WAF'); + } + + if (headers['set-cookie'] && headers['set-cookie'].includes('_citrix_ns_id')) { + return hasWaf('Citrix NetScaler'); + } + + if (headers['x-denied-reason'] || headers['x-wzws-requested-method']) { + return hasWaf('WangZhanBao WAF'); + } + + if (headers['x-webcoment']) { + return hasWaf('Webcoment Firewall'); + } + + if (headers['server'] && headers['server'].includes('Yundun')) { + return hasWaf('Yundun WAF'); + } + + if (headers['x-yd-waf-info'] || headers['x-yd-info']) { + return hasWaf('Yundun WAF'); + } + + if (headers['server'] && headers['server'].includes('Safe3WAF')) { + return hasWaf('Safe3 Web Application Firewall'); + } + + if (headers['server'] && headers['server'].includes('NAXSI')) { + return hasWaf('NAXSI WAF'); + } + + if (headers['x-datapower-transactionid']) { + return hasWaf('IBM WebSphere DataPower'); + } + + if (headers['server'] && headers['server'].includes('QRATOR')) { + return hasWaf('QRATOR WAF'); + } + + if (headers['server'] && headers['server'].includes('ddos-guard')) { + return hasWaf('DDoS-Guard WAF'); + } + + return { + hasWaf: false, + }; + } catch (error) { + return upstreamError(error, 'Firewall check'); + } +}; + +export const handler = middleware(firewallHandler); +export default handler; diff --git a/packages/api/handlers/get-ip.js b/packages/api/handlers/get-ip.js new file mode 100644 index 000000000..87c13ce73 --- /dev/null +++ b/packages/api/handlers/get-ip.js @@ -0,0 +1,19 @@ +import dns from 'dns'; +import middleware from './_common/middleware.js'; +import { parseTarget } from './_common/parse-target.js'; + +const lookupAsync = (address) => + new Promise((resolve, reject) => { + dns.lookup(address, (err, ip, family) => { + if (err) reject(err); + else resolve({ ip, family }); + }); + }); + +const ipHandler = async (url) => { + const { hostname } = parseTarget(url); + return await lookupAsync(hostname); +}; + +export const handler = middleware(ipHandler); +export default handler; diff --git a/packages/api/handlers/headers.js b/packages/api/handlers/headers.js new file mode 100644 index 000000000..c84be1970 --- /dev/null +++ b/packages/api/handlers/headers.js @@ -0,0 +1,17 @@ +import middleware from './_common/middleware.js'; +import { httpGet } from './_common/http.js'; +import { upstreamError } from './_common/upstream.js'; + +const headersHandler = async (url) => { + try { + const response = await httpGet(url, { + validateStatus: (status) => status >= 200 && status < 600, + }); + return response.headers; + } catch (error) { + return upstreamError(error, 'Headers fetch'); + } +}; + +export const handler = middleware(headersHandler); +export default handler; diff --git a/packages/api/handlers/hsts.js b/packages/api/handlers/hsts.js new file mode 100644 index 000000000..63c6f074f --- /dev/null +++ b/packages/api/handlers/hsts.js @@ -0,0 +1,42 @@ +import https from 'https'; +import middleware from './_common/middleware.js'; + +const MIN_MAX_AGE = 10886400; + +const verdict = (message, compatible = false, hstsHeader = null) => ({ + message, + compatible, + hstsHeader, +}); + +const evaluate = (header) => { + if (!header) return verdict('Site does not serve any HSTS headers.'); + const lower = header.toLowerCase(); + const maxAge = parseInt(lower.match(/max-age=(\d+)/)?.[1] || '0', 10); + if (maxAge < MIN_MAX_AGE) + return verdict(`HSTS max-age is ${maxAge}, below the ${MIN_MAX_AGE} minimum.`, false, header); + if (!lower.includes('includesubdomains')) + return verdict('HSTS header does not include all subdomains.', false, header); + if (!lower.includes('preload')) + return verdict('HSTS header does not contain the preload directive.', false, header); + return verdict('Site is compatible with the HSTS preload list!', true, header); +}; + +const REQUEST_TIMEOUT = 5000; + +const hstsHandler = async (url) => + new Promise((resolve) => { + const req = https.request(url, (res) => { + resolve(evaluate(res.headers['strict-transport-security'])); + res.resume(); + }); + req.setTimeout(REQUEST_TIMEOUT, () => { + req.destroy(); + resolve({ error: 'HSTS check timed out' }); + }); + req.on('error', (e) => resolve({ error: `HSTS check failed: ${e.message}` })); + req.end(); + }); + +export const handler = middleware(hstsHandler); +export default handler; diff --git a/packages/api/handlers/http-security.js b/packages/api/handlers/http-security.js new file mode 100644 index 000000000..d86686055 --- /dev/null +++ b/packages/api/handlers/http-security.js @@ -0,0 +1,30 @@ +import middleware from './_common/middleware.js'; +import { httpGet } from './_common/http.js'; + +// Security headers to check, mapped to response field names +const HEADERS = { + 'content-security-policy': 'contentSecurityPolicy', + 'strict-transport-security': 'strictTransportPolicy', + 'x-content-type-options': 'xContentTypeOptions', + 'x-frame-options': 'xFrameOptions', + 'x-xss-protection': 'xXSSProtection', + 'referrer-policy': 'referrerPolicy', + 'permissions-policy': 'permissionsPolicy', + 'cross-origin-opener-policy': 'crossOriginOpenerPolicy', + 'cross-origin-resource-policy': 'crossOriginResourcePolicy', + 'cross-origin-embedder-policy': 'crossOriginEmbedderPolicy', +}; + +const httpsSecHandler = async (url) => { + try { + const { headers } = await httpGet(url, { + validateStatus: () => true, + }); + return Object.fromEntries(Object.entries(HEADERS).map(([h, key]) => [key, !!headers[h]])); + } catch (error) { + return { error: `Unable to fetch headers: ${error.message}` }; + } +}; + +export const handler = middleware(httpsSecHandler); +export default handler; diff --git a/packages/api/handlers/linked-pages.js b/packages/api/handlers/linked-pages.js new file mode 100644 index 000000000..dafa883c0 --- /dev/null +++ b/packages/api/handlers/linked-pages.js @@ -0,0 +1,53 @@ +import * as cheerio from 'cheerio'; +import urlLib from 'url'; +import middleware from './_common/middleware.js'; +import { httpGet } from './_common/http.js'; +import { upstreamError } from './_common/upstream.js'; + +const linkedPagesHandler = async (url) => { + let response; + try { + response = await httpGet(url); + } catch (error) { + return upstreamError(error, 'Linked pages fetch'); + } + const html = response.data; + const $ = cheerio.load(html); + const internalLinksMap = new Map(); + const externalLinksMap = new Map(); + + // Get all links on the page + $('a[href]').each((i, link) => { + const href = $(link).attr('href'); + const absoluteUrl = urlLib.resolve(url, href); + + // Check if absolute / relative, append to appropriate map or increment occurrence count + if (absoluteUrl.startsWith(url)) { + const count = internalLinksMap.get(absoluteUrl) || 0; + internalLinksMap.set(absoluteUrl, count + 1); + } else if (href.startsWith('http://') || href.startsWith('https://')) { + const count = externalLinksMap.get(absoluteUrl) || 0; + externalLinksMap.set(absoluteUrl, count + 1); + } + }); + + // Sort by most occurrences, remove supplicates, and convert to array + const internalLinks = [...internalLinksMap.entries()] + .sort((a, b) => b[1] - a[1]) + .map((entry) => entry[0]); + const externalLinks = [...externalLinksMap.entries()] + .sort((a, b) => b[1] - a[1]) + .map((entry) => entry[0]); + + if (!internalLinks.length && !externalLinks.length) { + return { + skipped: + 'No internal or external links found in the page HTML. ' + + 'This often happens with single-page apps that render content client-side.', + }; + } + return { internal: internalLinks, external: externalLinks }; +}; + +export const handler = middleware(linkedPagesHandler); +export default handler; diff --git a/packages/api/handlers/location.js b/packages/api/handlers/location.js new file mode 100644 index 000000000..de4f58561 --- /dev/null +++ b/packages/api/handlers/location.js @@ -0,0 +1,184 @@ +import { promises as dns } from 'dns'; +import middleware from './_common/middleware.js'; +import { parseTarget } from './_common/parse-target.js'; +import { createLogger } from './_common/logger.js'; + +const log = createLogger('location'); +const TIMEOUT = 4000; + +// Server-side fetch, no-cors so providers don't reject Sec-Fetch-Mode: cors +const getJson = async (url, signal) => { + const r = await fetch(url, { mode: 'no-cors', signal }); + if (!r.ok) throw new Error(`status ${r.status}`); + return r.json(); +}; + +// Geo providers, each parser normalises to a shared field shape +const providers = [ + { + name: 'ipwho.is', + url: (ip) => `https://ipwho.is/${ip}`, + parse: (d) => + d?.success === false + ? null + : { + ip: d.ip, + city: d.city, + region: d.region, + country_name: d.country, + country_code: d.country_code, + region_code: d.region_code, + postal: d.postal, + latitude: d.latitude, + longitude: d.longitude, + org: d.connection?.isp || d.connection?.org, + timezone: d.timezone?.id, + }, + }, + { + name: 'ip-api.com', + url: (ip) => `http://ip-api.com/json/${ip}`, + parse: (d) => + d?.status === 'success' + ? { + ip: d.query, + city: d.city, + region: d.regionName, + country_name: d.country, + country_code: d.countryCode, + region_code: d.region, + postal: d.zip, + latitude: d.lat, + longitude: d.lon, + org: d.isp || d.org, + timezone: d.timezone, + } + : null, + }, + { + name: 'geojs.io', + url: (ip) => `https://get.geojs.io/v1/ip/geo/${ip}.json`, + parse: (d) => + d?.country_code + ? { + ip: d.ip, + city: d.city, + region: d.region, + country_name: d.country, + country_code: d.country_code, + latitude: d.latitude !== 'nil' ? parseFloat(d.latitude) : undefined, + longitude: d.longitude !== 'nil' ? parseFloat(d.longitude) : undefined, + org: d.organization_name, + timezone: d.timezone, + } + : null, + }, + { + name: 'reallyfreegeoip.org', + url: (ip) => `https://reallyfreegeoip.org/json/${ip}`, + parse: (d) => + d?.country_code + ? { + ip: d.ip, + city: d.city, + region: d.region_name, + country_name: d.country_name, + country_code: d.country_code, + region_code: d.region_code, + postal: d.zip_code, + latitude: d.latitude, + longitude: d.longitude, + timezone: d.time_zone, + } + : null, + }, +]; + +// Query a single provider, throw unless it yields a usable result +const tryProvider = async (p, ip, signal) => { + const parsed = p.parse(await getJson(p.url(ip), signal)); + if (!parsed?.country_code) throw new Error('no usable data'); + log.debug(`${p.name} resolved ${ip} to ${parsed.country_code}`); + return parsed; +}; + +// Race all providers, first successful result wins, abort the rest +const lookupGeo = async (ip) => { + const ac = new AbortController(); + const signal = AbortSignal.any([ac.signal, AbortSignal.timeout(TIMEOUT)]); + const tasks = providers.map((p) => + tryProvider(p, ip, signal).catch((e) => { + if (e.name !== 'AbortError') log.warn(`${p.name} failed for ${ip}`, e.message); + throw e; + }), + ); + try { + const result = await Promise.any(tasks); + ac.abort(); + return result; + } catch { + return null; + } +}; + +// Fetch country-level metadata to fill fields not provided by every geo source +const enrichCountry = async (code) => { + if (!code) return {}; + try { + const data = await getJson( + `https://restcountries.com/v3.1/alpha/${code}` + + '?fields=tld,languages,currencies,area,population', + ); + const c = Array.isArray(data) ? data[0] : data; + if (!c) { + log.debug(`restcountries returned no entry for ${code}`); + return {}; + } + const languages = c.languages ? Object.values(c.languages).join(', ') : undefined; + const currCode = c.currencies ? Object.keys(c.currencies)[0] : undefined; + const curr = currCode ? c.currencies[currCode] : null; + return { + country_tld: c.tld?.[0], + languages, + currency: currCode, + currency_name: curr?.name, + country_area: c.area, + country_population: c.population, + }; + } catch (error) { + log.debug(`restcountries enrichment failed for ${code}`, error.message); + return {}; + } +}; + +// Strip empty values so they don't shadow enrichment defaults during merge +const compact = (o) => + Object.fromEntries( + Object.entries(o).filter(([, v]) => v !== undefined && v !== null && v !== ''), + ); + +// Resolve hostname to IP so providers requiring a numeric address still work +const resolveHost = async (hostname) => { + try { + return (await dns.lookup(hostname)).address; + } catch (error) { + log.warn(`DNS lookup failed for ${hostname}, falling through with raw host`, error.message); + return hostname; + } +}; + +// Resolve geographic info for a host via a chain of providers with country enrichment +const locationHandler = async (url) => { + const { hostname } = parseTarget(url); + const ip = await resolveHost(hostname); + const geo = await lookupGeo(ip); + if (!geo) { + log.error(`all geo providers failed for ${ip}`); + return { error: 'IP location lookup unavailable across all providers, please try again later' }; + } + const enrichment = await enrichCountry(geo.country_code); + return { ...enrichment, ...compact(geo) }; +}; + +export const handler = middleware(locationHandler); +export default handler; diff --git a/packages/api/handlers/mail-config.js b/packages/api/handlers/mail-config.js new file mode 100644 index 000000000..71ac95ee7 --- /dev/null +++ b/packages/api/handlers/mail-config.js @@ -0,0 +1,99 @@ +import dns from 'dns/promises'; +import middleware from './_common/middleware.js'; +import { parseTarget } from './_common/parse-target.js'; + +// Safely query TXT, returning [] on ENODATA/ENOTFOUND +const safeTxt = (name) => dns.resolveTxt(name).catch(() => []); + +// Try common DKIM selectors to detect if DKIM is configured +const DKIM_SELECTORS = [ + 'default', + 'google', + 'selector1', + 'selector2', + 'k1', + 'k2', + 'k3', + 's1', + 's2', + 'dkim', + 'mail', +]; +const findDkim = async (domain) => { + const checks = DKIM_SELECTORS.map((s) => + safeTxt(`${s}._domainkey.${domain}`).then((r) => { + if (!r.length) return null; + const txt = r[0].join(''); + // Skip revoked keys (empty p= value) + if (/p=\s*(;|$)/.test(txt)) return null; + return { selector: s, record: r[0] }; + }), + ); + const results = await Promise.all(checks); + return results.filter(Boolean); +}; + +// Detect mail provider from MX exchange hostnames +const MX_PROVIDERS = [ + [/google(mail)?\.com$/i, 'Google Workspace'], + [/outlook\.com$|microsoft\.com$/i, 'Microsoft 365'], + [/protonmail\.ch$|protonme\.ch$/i, 'ProtonMail'], + [/zoho\.(com|eu|in)$/i, 'Zoho Mail'], + [/yahoodns\.net$/i, 'Yahoo Mail'], + [/mimecast\.com$/i, 'Mimecast'], + [/pphosted\.com$/i, 'Proofpoint'], + [/messagelabs\.com$/i, 'Broadcom Email Security'], + [/iphmx\.com$/i, 'Cisco Email Security'], + [/mailgun\.org$/i, 'Mailgun'], + [/sendgrid\.net$/i, 'SendGrid'], + [/fireeyecloud\.com$/i, 'Trellix Email Security'], + [/barracudanetworks\.com$/i, 'Barracuda'], +]; + +const detectProviders = (mxRecords) => { + const seen = new Set(); + return mxRecords.reduce((out, { exchange }) => { + const match = MX_PROVIDERS.find(([re]) => re.test(exchange)); + if (match && !seen.has(match[1])) { + seen.add(match[1]); + out.push({ provider: match[1], value: exchange }); + } + return out; + }, []); +}; + +const mailConfigHandler = async (url) => { + const { hostname: domain } = parseTarget(url); + try { + const [mxRecords, rootTxt, dmarcTxt, bimiTxt, dkimResults] = await Promise.all([ + dns.resolveMx(domain), + safeTxt(domain), + safeTxt(`_dmarc.${domain}`), + safeTxt(`default._bimi.${domain}`), + findDkim(domain), + ]); + + // Collect email-relevant TXT records + const emailTxt = rootTxt.filter((r) => { + const s = r.join('').toLowerCase(); + return s.startsWith('v=spf1'); + }); + dmarcTxt.forEach((r) => emailTxt.push(r)); + bimiTxt.forEach((r) => emailTxt.push(r)); + dkimResults.forEach(({ record }) => emailTxt.push(record)); + + return { + mxRecords, + txtRecords: emailTxt, + mailServices: detectProviders(mxRecords), + }; + } catch (error) { + if (error.code === 'ENOTFOUND' || error.code === 'ENODATA') { + return { skipped: 'No mail server in use on this domain' }; + } + return { error: `Mail config lookup failed: ${error.message}` }; + } +}; + +export const handler = middleware(mailConfigHandler); +export default handler; diff --git a/packages/api/handlers/ports.js b/packages/api/handlers/ports.js new file mode 100644 index 000000000..6345ccb4c --- /dev/null +++ b/packages/api/handlers/ports.js @@ -0,0 +1,99 @@ +import net from 'net'; +import middleware from './_common/middleware.js'; +import { parseTarget } from './_common/parse-target.js'; + +// A list of commonly used ports. +const DEFAULT_PORTS_TO_CHECK = [ + 20, 21, 22, 23, 25, 53, 80, 67, 68, 69, 110, 119, 123, 143, 156, 161, 162, 179, 194, 389, 443, + 587, 993, 995, 3000, 3306, 3389, 5060, 5900, 8000, 8080, 8888, +]; +/* + * Checks if the env PORTS_TO_CHECK is set, if so the string is split via "," to get an array of ports to check. + * If the env is not set, return the default commonly used ports. + */ +const PORTS = process.env.PORTS_TO_CHECK + ? process.env.PORTS_TO_CHECK.split(',') + : DEFAULT_PORTS_TO_CHECK; + +async function checkPort(port, domain) { + return new Promise((resolve, reject) => { + const socket = new net.Socket(); + + socket.setTimeout(1500); + + socket.once('connect', () => { + socket.destroy(); + resolve(port); + }); + + socket.once('timeout', () => { + socket.destroy(); + reject(new Error(`Timeout at port: ${port}`)); + }); + + socket.once('error', (e) => { + socket.destroy(); + reject(e); + }); + + socket.connect(port, domain); + }); +} + +const portsHandler = async (url, event, context) => { + const { hostname: domain } = parseTarget(url); + + const delay = (ms) => new Promise((res) => setTimeout(res, ms)); + const timeout = delay(9000); + + const openPorts = []; + const failedPorts = []; + + const promises = PORTS.map((port) => + checkPort(port, domain) + .then(() => { + openPorts.push(port); + return { status: 'fulfilled', port }; + }) + .catch(() => { + failedPorts.push(port); + return { status: 'rejected', port }; + }), + ); + + let timeoutReached = false; + + for (const promise of promises) { + const result = await Promise.race([ + promise, + timeout.then(() => ({ status: 'timeout', timeout: true })), + ]); + if (result.status === 'timeout') { + timeoutReached = true; + if (result.timeout) { + // Add the ports not checked yet to the failedPorts array + const checkedPorts = [...openPorts, ...failedPorts]; + const portsNotChecked = PORTS.filter((port) => !checkedPorts.includes(port)); + failedPorts.push(...portsNotChecked); + } + break; + } + } + + if (timeoutReached) { + return errorResponse('The function timed out before completing.'); + } + + // Sort openPorts and failedPorts before returning + openPorts.sort((a, b) => a - b); + failedPorts.sort((a, b) => a - b); + + return { openPorts, failedPorts }; +}; + +const errorResponse = (message, statusCode = 444) => { + return { error: message }; +}; + +export const handler = middleware(portsHandler); +export default handler; diff --git a/packages/api/handlers/quality.js b/packages/api/handlers/quality.js new file mode 100644 index 000000000..f0347f8de --- /dev/null +++ b/packages/api/handlers/quality.js @@ -0,0 +1,28 @@ +import middleware from './_common/middleware.js'; +import { httpGet } from './_common/http.js'; +import { requireEnv, upstreamError } from './_common/upstream.js'; + +const qualityHandler = async (url) => { + const auth = requireEnv('GOOGLE_CLOUD_API_KEY', 'Quality check'); + if (auth.skipped) return auth; + const endpoint = + `https://www.googleapis.com/pagespeedonline/v5/runPagespeed?` + + `url=${encodeURIComponent(url)}&category=PERFORMANCE&category=ACCESSIBILITY` + + `&category=BEST_PRACTICES&category=SEO&category=PWA&strategy=mobile` + + `&key=${auth.value}`; + + let data; + try { + data = (await httpGet(endpoint)).data; + } catch (error) { + return upstreamError(error, 'Quality check'); + } + const result = data.lighthouseResult || data; + if (!result?.categories || !Object.keys(result.categories).length) { + return { skipped: 'No quality report available for this URL' }; + } + return result; +}; + +export const handler = middleware(qualityHandler); +export default handler; diff --git a/packages/api/handlers/rank.js b/packages/api/handlers/rank.js new file mode 100644 index 000000000..b5d45d5be --- /dev/null +++ b/packages/api/handlers/rank.js @@ -0,0 +1,29 @@ +import middleware from './_common/middleware.js'; +import { httpGet } from './_common/http.js'; +import { parseTarget } from './_common/parse-target.js'; +import { upstreamError } from './_common/upstream.js'; + +const rankHandler = async (url) => { + const { hostname: domain } = parseTarget(url); + const { TRANCO_USERNAME, TRANCO_API_KEY } = process.env; + const auth = TRANCO_API_KEY + ? { auth: { username: TRANCO_USERNAME, password: TRANCO_API_KEY } } + : {}; + try { + const response = await httpGet(`https://tranco-list.eu/api/ranks/domain/${domain}`, { + timeout: 5000, + ...auth, + }); + if (!response.data?.ranks?.length) { + return { + skipped: `${domain} isn't ranked in the top 1 million sites yet`, + }; + } + return response.data; + } catch (error) { + return upstreamError(error, 'Tranco rank lookup'); + } +}; + +export const handler = middleware(rankHandler); +export default handler; diff --git a/packages/api/handlers/redirects.js b/packages/api/handlers/redirects.js new file mode 100644 index 000000000..f6df1ef43 --- /dev/null +++ b/packages/api/handlers/redirects.js @@ -0,0 +1,43 @@ +import middleware from './_common/middleware.js'; +import { upstreamError } from './_common/upstream.js'; + +const MAX_REDIRECTS = 12; +const TIMEOUT_MS = 10000; +const USER_AGENT = 'Mozilla/5.0 (compatible; WebCheck/2.0; +https://web-check.xyz)'; + +// Walks the redirect chain manually, recording each Location header as got did +const redirectsHandler = async (url) => { + const redirects = [url]; + let current = url; + try { + for (let i = 0; i < MAX_REDIRECTS; i++) { + const response = await fetch(current, { + redirect: 'manual', + signal: AbortSignal.timeout(TIMEOUT_MS), + headers: { 'user-agent': USER_AGENT }, + }); + if (response.status < 300 || response.status >= 400) { + if (response.status >= 400) { + const err = new Error(`HTTP ${response.status}`); + err.response = { status: response.status }; + throw err; + } + break; + } + const location = response.headers.get('location'); + if (!location) break; + redirects.push(location); + current = new URL(location, current).href; + } + return { redirects }; + } catch (error) { + if (error.cause?.code) error.code = error.cause.code; + if (error.name === 'TimeoutError' || error.name === 'AbortError') { + error.code = 'ECONNABORTED'; + } + return upstreamError(error, 'Redirect lookup'); + } +}; + +export const handler = middleware(redirectsHandler); +export default handler; diff --git a/packages/api/handlers/robots-txt.js b/packages/api/handlers/robots-txt.js new file mode 100644 index 000000000..57d776197 --- /dev/null +++ b/packages/api/handlers/robots-txt.js @@ -0,0 +1,33 @@ +import middleware from './_common/middleware.js'; +import { httpGet } from './_common/http.js'; +import { parseTarget } from './_common/parse-target.js'; +import { upstreamError } from './_common/upstream.js'; + +// Extract User-agent / Allow / Disallow rules from a robots.txt body +const parseRobotsTxt = (content) => { + const rules = []; + for (let line of content.split('\n')) { + line = line.trim(); + const ruleMatch = line.match(/^(Allow|Disallow|User-agent):\s*(\S*)$/i); + if (ruleMatch) rules.push({ lbl: ruleMatch[1], val: ruleMatch[2] }); + } + return { robots: rules }; +}; + +const robotsHandler = async (url) => { + const { protocol, hostname } = parseTarget(url); + const host = hostname.includes(':') ? `[${hostname}]` : hostname; + try { + const res = await httpGet(`${protocol}//${host}/robots.txt`); + const parsed = parseRobotsTxt(res.data || ''); + return parsed.robots.length ? parsed : { skipped: 'No robots.txt rules found for this host' }; + } catch (error) { + if (error.response?.status === 404) { + return { skipped: 'No robots.txt file present on this host' }; + } + return upstreamError(error, 'robots.txt fetch'); + } +}; + +export const handler = middleware(robotsHandler); +export default handler; diff --git a/packages/api/handlers/screenshot.js b/packages/api/handlers/screenshot.js new file mode 100644 index 000000000..725841b35 --- /dev/null +++ b/packages/api/handlers/screenshot.js @@ -0,0 +1,96 @@ +import puppeteer from 'puppeteer-core'; +import chromium from '@sparticuz/chromium'; +import { randomUUID } from 'crypto'; +import { execFile } from 'child_process'; +import { promises as fs } from 'fs'; +import path from 'path'; +import middleware from './_common/middleware.js'; +import { createLogger } from './_common/logger.js'; + +const log = createLogger('screenshot'); + +// Screenshot via the system Chromium binary +const directChromiumScreenshot = async (url) => { + const tmpDir = '/tmp'; + const screenshotPath = path.join(tmpDir, `screenshot-${randomUUID()}.png`); + log.debug(`direct method, saving to ${screenshotPath}`); + + return new Promise((resolve, reject) => { + const chromePath = process.env.CHROME_PATH || '/usr/bin/chromium'; + const args = [ + '--headless', + '--disable-gpu', + '--no-sandbox', + `--screenshot=${screenshotPath}`, + url, + ]; + execFile(chromePath, args, async (error) => { + if (error) return reject(error); + try { + const buf = await fs.readFile(screenshotPath); + await fs + .unlink(screenshotPath) + .catch((err) => log.warn(`temp cleanup failed: ${err.message}`)); + resolve(buf.toString('base64')); + } catch (readError) { + reject(readError); + } + }); + }); +}; + +// Fallback to puppeteer when the direct Chromium binary call fails +const puppeteerScreenshot = async (targetUrl) => { + let browser = null; + try { + browser = await puppeteer.launch({ + args: [...chromium.args, '--no-sandbox'], + defaultViewport: { width: 800, height: 600 }, + executablePath: process.env.CHROME_PATH || (await chromium.executablePath()), + headless: true, + acceptInsecureCerts: true, + ignoreDefaultArgs: ['--disable-extensions'], + }); + const page = await browser.newPage(); + await page.emulateMediaFeatures([{ name: 'prefers-color-scheme', value: 'dark' }]); + page.setDefaultNavigationTimeout(8000); + await page.goto(targetUrl, { waitUntil: 'domcontentloaded' }); + await page.evaluate(() => { + if (!document.querySelector('body')) { + throw new Error('No body element found on the page'); + } + }); + const buffer = await page.screenshot(); + return buffer.toString('base64'); + } finally { + if (browser) await browser.close().catch(() => {}); + } +}; + +const screenshotHandler = async (targetUrl) => { + if (!targetUrl) throw new Error('URL is missing from queryStringParameters'); + try { + new URL(targetUrl); + } catch { + throw new Error('URL provided is invalid'); + } + + log.debug(`request received: ${targetUrl}`); + try { + return { image: await directChromiumScreenshot(targetUrl) }; + } catch (directError) { + log.warn(`direct chromium failed, falling back to puppeteer: ${directError.message}`); + } + try { + return { image: await puppeteerScreenshot(targetUrl) }; + } catch (error) { + if (/ENOENT|Browser was not found|Could not find Chromium/i.test(error.message)) { + return { skipped: error.message }; + } + log.error(`puppeteer screenshot failed: ${error.message}`); + throw error; + } +}; + +export const handler = middleware(screenshotHandler); +export default handler; diff --git a/packages/api/handlers/security-txt.js b/packages/api/handlers/security-txt.js new file mode 100644 index 000000000..f773d6a3a --- /dev/null +++ b/packages/api/handlers/security-txt.js @@ -0,0 +1,80 @@ +import { URL } from 'url'; +import middleware from './_common/middleware.js'; +import { httpGet } from './_common/http.js'; + +// RFC 9116 recommends .well-known first, legacy /security.txt as fallback +const SECURITY_TXT_PATHS = ['/.well-known/security.txt', '/security.txt']; + +const parseResult = (result) => { + let output = {}; + let counts = {}; + const lines = result.split('\n'); + const regex = /^([^:]+):\s*(.+)$/; + + for (const line of lines) { + if (!line.startsWith('#') && !line.startsWith('-----') && line.trim() !== '') { + const match = line.match(regex); + if (match && match.length > 2) { + let key = match[1].trim(); + const value = match[2].trim(); + if (output.hasOwnProperty(key)) { + counts[key] = counts[key] ? counts[key] + 1 : 1; + key += counts[key]; + } + output[key] = value; + } + } + } + + return output; +}; + +const isPgpSigned = (result) => { + if (result.includes('-----BEGIN PGP SIGNED MESSAGE-----')) { + return true; + } + return false; +}; + +const securityTxtHandler = async (urlParam) => { + let url; + try { + url = new URL(urlParam.includes('://') ? urlParam : 'https://' + urlParam); + } catch (error) { + throw new Error('Invalid URL format'); + } + url.pathname = ''; + + for (let path of SECURITY_TXT_PATHS) { + try { + const result = await fetchSecurityTxt(url, path); + if (result && result.toLowerCase().includes(' { + const url = new URL(path, baseURL); + const res = await httpGet(url.toString(), { + headers: { 'User-Agent': 'curl/8.0.0' }, + validateStatus: () => true, + }); + return res.status === 200 ? res.data : null; +}; + +export const handler = middleware(securityTxtHandler); +export default handler; diff --git a/packages/api/handlers/shodan.js b/packages/api/handlers/shodan.js new file mode 100644 index 000000000..06156814f --- /dev/null +++ b/packages/api/handlers/shodan.js @@ -0,0 +1,22 @@ +import middleware from './_common/middleware.js'; +import { httpGet } from './_common/http.js'; +import { parseTarget } from './_common/parse-target.js'; +import { requireEnv, upstreamError } from './_common/upstream.js'; + +// Server-side Shodan lookup so the API key never touches the client +const shodanHandler = async (url) => { + const auth = requireEnv('SHODAN_API_KEY', 'Shodan'); + if (auth.skipped) return auth; + const { hostname } = parseTarget(url); + try { + const res = await httpGet(`https://api.shodan.io/shodan/host/${hostname}?key=${auth.value}`, { + timeout: 8000, + }); + return res.data; + } catch (error) { + return upstreamError(error, 'Shodan lookup'); + } +}; + +export const handler = middleware(shodanHandler); +export default handler; diff --git a/packages/api/handlers/sitemap.js b/packages/api/handlers/sitemap.js new file mode 100644 index 000000000..ef7859ee5 --- /dev/null +++ b/packages/api/handlers/sitemap.js @@ -0,0 +1,129 @@ +import xml2js from 'xml2js'; +import middleware from './_common/middleware.js'; +import { httpGet } from './_common/http.js'; +import { upstreamError } from './_common/upstream.js'; +import { createLogger } from './_common/logger.js'; + +const log = createLogger('sitemap'); +const TIMEOUT = 6000; +const MAX_DEPTH = 3; +const MAX_CHILD_SITEMAPS = 25; +const MAX_URLS = 5000; + +// Browser-ish headers so picky CDNs do not return 406/403 to the default Node UA +const HEADERS = { + 'user-agent': 'Mozilla/5.0 (compatible; web-check-bot/1.0; +https://web-check.xyz)', + accept: 'application/xml, text/xml, application/rss+xml, */*;q=0.1', +}; + +// Reduce a target URL to its origin so child paths resolve cleanly +const toOrigin = (url) => { + try { + return new URL(url).origin; + } catch { + return url.replace(/\/+$/, ''); + } +}; + +// Fetch and parse XML in lenient mode so minor well-formedness errors do not abort +const fetchSitemap = async (sitemapUrl) => { + const res = await httpGet(sitemapUrl, { timeout: TIMEOUT, headers: HEADERS }); + return new xml2js.Parser({ strict: false, normalizeTags: true }).parseStringPromise(res.data); +}; + +// Pull the first Sitemap: directive out of robots.txt, if any +const findSitemapInRobots = async (origin) => { + try { + const robots = await httpGet(`${origin}/robots.txt`, { timeout: TIMEOUT, headers: HEADERS }); + for (const line of String(robots.data).split('\n')) { + if (line.toLowerCase().startsWith('sitemap:')) { + return line.split(/\s+/)[1]?.trim() || null; + } + } + } catch (error) { + log.debug(`robots.txt fetch failed for ${origin}`, error.message); + } + return null; +}; + +// Recursively flatten a sitemap-index into its child url sets +const expandSitemap = async (parsed, depth) => { + if (!parsed?.sitemapindex?.sitemap || depth >= MAX_DEPTH) return parsed; + const children = parsed.sitemapindex.sitemap + .map((s) => s?.loc?.[0]) + .filter(Boolean) + .slice(0, MAX_CHILD_SITEMAPS); + const fetched = await Promise.all( + children.map((loc) => + fetchSitemap(loc).catch((error) => { + log.debug(`child sitemap failed for ${loc}`, error.message); + return null; + }), + ), + ); + const expanded = await Promise.all( + fetched.map((child) => (child ? expandSitemap(child, depth + 1) : null)), + ); + const urls = expanded.flatMap((child) => child?.urlset?.url || []); + return { + sitemapindex: parsed.sitemapindex, + urlset: urls.length ? { url: urls } : undefined, + sources: children, + }; +}; + +// Whether the parsed XML matched one of the canonical sitemap shapes +const isValidSitemap = (p) => !!(p?.urlset?.url?.length || p?.sitemapindex?.sitemap?.length); + +// Keep only the four fields the frontend renders, dropping locale alternates and image/video extras +const slimUrl = (u) => { + const out = { loc: u.loc }; + if (u.lastmod) out.lastmod = u.lastmod; + if (u.changefreq) out.changefreq = u.changefreq; + if (u.priority) out.priority = u.priority; + return out; +}; + +// Drop bulky XML extensions and cap total entries so the JSON payload stays sane +const slimResult = (r) => { + if (!r) return r; + const out = {}; + if (r.urlset?.url) out.urlset = { url: r.urlset.url.slice(0, MAX_URLS).map(slimUrl) }; + if (r.sitemapindex?.sitemap) { + out.sitemapindex = { + sitemap: r.sitemapindex.sitemap.map((s) => ({ loc: s.loc })), + }; + } + if (r.sources) out.sources = r.sources; + return out; +}; + +// Try a candidate URL, return parsed result only when it looks like a real sitemap +const tryFetch = async (target, label) => { + try { + const parsed = await fetchSitemap(target); + if (isValidSitemap(parsed)) return parsed; + log.debug(`${label} parsed but lacked urlset/sitemapindex (${target})`); + } catch (error) { + log.debug(`${label} fetch failed (${target})`, error.message); + } + return null; +}; + +const sitemapHandler = async (url) => { + const origin = toOrigin(url); + let parsed = await tryFetch(`${origin}/sitemap.xml`, 'sitemap.xml'); + if (!parsed) { + const fromRobots = await findSitemapInRobots(origin); + if (fromRobots) parsed = await tryFetch(fromRobots, 'robots-listed sitemap'); + } + if (!parsed) return { skipped: 'No sitemap found for this site' }; + try { + return slimResult(await expandSitemap(parsed, 0)); + } catch (error) { + return upstreamError(error, 'Sitemap fetch'); + } +}; + +export const handler = middleware(sitemapHandler); +export default handler; diff --git a/packages/api/handlers/social-tags.js b/packages/api/handlers/social-tags.js new file mode 100644 index 000000000..7902f60cf --- /dev/null +++ b/packages/api/handlers/social-tags.js @@ -0,0 +1,76 @@ +import * as cheerio from 'cheerio'; +import middleware from './_common/middleware.js'; +import { httpGet } from './_common/http.js'; +import { upstreamError } from './_common/upstream.js'; + +const socialTagsHandler = async (url) => { + let response; + try { + response = await httpGet(url); + } catch (error) { + return upstreamError(error, 'Social tags fetch'); + } + try { + const $ = cheerio.load(response.data); + + const metadata = { + // Basic meta tags + title: $('head title').text(), + description: $('meta[name="description"]').attr('content'), + keywords: $('meta[name="keywords"]').attr('content'), + canonicalUrl: $('link[rel="canonical"]').attr('href'), + + // OpenGraph Protocol + ogTitle: $('meta[property="og:title"]').attr('content'), + ogType: $('meta[property="og:type"]').attr('content'), + ogImage: $('meta[property="og:image"]').attr('content'), + ogUrl: $('meta[property="og:url"]').attr('content'), + ogDescription: $('meta[property="og:description"]').attr('content'), + ogSiteName: $('meta[property="og:site_name"]').attr('content'), + + // Twitter Cards + twitterCard: $('meta[name="twitter:card"]').attr('content'), + twitterSite: $('meta[name="twitter:site"]').attr('content'), + twitterCreator: $('meta[name="twitter:creator"]').attr('content'), + twitterTitle: $('meta[name="twitter:title"]').attr('content'), + twitterDescription: $('meta[name="twitter:description"]').attr('content'), + twitterImage: $('meta[name="twitter:image"]').attr('content'), + + // Misc + themeColor: $('meta[name="theme-color"]').attr('content'), + robots: $('meta[name="robots"]').attr('content'), + googlebot: $('meta[name="googlebot"]').attr('content'), + generator: $('meta[name="generator"]').attr('content'), + viewport: $('meta[name="viewport"]').attr('content'), + author: $('meta[name="author"]').attr('content'), + publisher: $('link[rel="publisher"]').attr('href'), + favicon: $('link[rel="icon"]').attr('href'), + }; + + const SOCIAL_FIELDS = [ + 'title', + 'description', + 'keywords', + 'canonicalUrl', + 'ogTitle', + 'ogImage', + 'ogDescription', + 'ogSiteName', + 'twitterTitle', + 'twitterDescription', + 'twitterImage', + 'author', + 'publisher', + 'themeColor', + ]; + if (!SOCIAL_FIELDS.some((f) => metadata[f])) { + return { skipped: 'No social tags found on this page' }; + } + return metadata; + } catch (error) { + return { error: `Failed parsing social tags: ${error.message}` }; + } +}; + +export const handler = middleware(socialTagsHandler); +export default handler; diff --git a/packages/api/handlers/ssl.js b/packages/api/handlers/ssl.js new file mode 100644 index 000000000..fe166d5c1 --- /dev/null +++ b/packages/api/handlers/ssl.js @@ -0,0 +1,36 @@ +import tls from 'tls'; +import middleware from './_common/middleware.js'; + +const sslHandler = async (urlString) => { + const parsedUrl = new URL(urlString); + const options = { + host: parsedUrl.hostname, + port: parsedUrl.port || 443, + servername: parsedUrl.hostname, + rejectUnauthorized: false, + }; + + return new Promise((resolve, reject) => { + const socket = tls.connect(options, () => { + const cert = socket.getPeerCertificate(); + if (!cert || Object.keys(cert).length === 0) { + reject(new Error('No certificate presented by the server')); + socket.end(); + return; + } + const { raw, issuerCertificate, ...certData } = cert; + resolve({ + ...certData, + isValid: socket.authorized, + authError: socket.authorizationError || null, + }); + socket.end(); + }); + socket.on('error', (e) => { + reject(new Error(`SSL connection failed: ${e.message}`)); + }); + }); +}; + +export const handler = middleware(sslHandler); +export default handler; diff --git a/packages/api/handlers/status.js b/packages/api/handlers/status.js new file mode 100644 index 000000000..d3e37c9ca --- /dev/null +++ b/packages/api/handlers/status.js @@ -0,0 +1,58 @@ +import https from 'https'; +import { performance, PerformanceObserver } from 'perf_hooks'; +import middleware from './_common/middleware.js'; + +const statusHandler = async (url) => { + if (!url) { + throw new Error('You must provide a URL query parameter!'); + } + + let dnsLookupTime; + let responseCode; + let startTime; + + const obs = new PerformanceObserver((items) => { + dnsLookupTime = items.getEntries()[0].duration; + performance.clearMarks(); + }); + + obs.observe({ entryTypes: ['measure'] }); + + performance.mark('A'); + + try { + startTime = performance.now(); + const response = await new Promise((resolve, reject) => { + const req = https.get(url, (res) => { + let data = ''; + responseCode = res.statusCode; + res.on('data', (chunk) => { + data += chunk; + }); + res.on('end', () => { + resolve(res); + }); + }); + + req.on('error', reject); + req.end(); + }); + + if (responseCode < 200 || responseCode >= 400) { + throw new Error(`Received non-success response code: ${responseCode}`); + } + + performance.mark('B'); + performance.measure('A to B', 'A', 'B'); + let responseTime = performance.now() - startTime; + obs.disconnect(); + + return { isUp: true, dnsLookupTime, responseTime, responseCode }; + } catch (error) { + obs.disconnect(); + throw error; + } +}; + +export const handler = middleware(statusHandler); +export default handler; diff --git a/packages/api/handlers/tech-stack.js b/packages/api/handlers/tech-stack.js new file mode 100644 index 000000000..2d62eff3b --- /dev/null +++ b/packages/api/handlers/tech-stack.js @@ -0,0 +1,47 @@ +import chromium from '@sparticuz/chromium'; +import middleware from './_common/middleware.js'; + +// Wappalyzer reads CHROMIUM_BIN at module load, so we must resolve +// the path before importing it (hence the dynamic import in the handler) +const ensureChromiumBin = async () => { + if (process.env.CHROMIUM_BIN) return; + const envPath = process.env.CHROME_PATH || process.env.PUPPETEER_EXECUTABLE_PATH; + if (envPath) { + process.env.CHROMIUM_BIN = envPath; + return; + } + // On serverless, puppeteer has no cached binary, use @sparticuz/chromium + if (process.env.AWS_LAMBDA_FUNCTION_NAME || process.env.NETLIFY) { + process.env.CHROMIUM_BIN = await chromium.executablePath(); + // Avoid conflict with @sparticuz/chromium's extraction path at /tmp/chromium + if (!process.env.CHROMIUM_DATA_DIR) { + process.env.CHROMIUM_DATA_DIR = '/tmp/chromium-data'; + } + } +}; + +const techStackHandler = async (url) => { + await ensureChromiumBin(); + const { default: Wappalyzer } = await import('wappalyzer'); + const wappalyzer = new Wappalyzer({}); + + try { + await wappalyzer.init(); + const site = await wappalyzer.open(url, {}, { local: {}, session: {} }); + const results = await site.analyze(); + if (!results.technologies || results.technologies.length === 0) { + throw new Error('Unable to find any technologies for site'); + } + return results; + } catch (error) { + if (/ENOENT|Browser was not found|Could not find Chromium/i.test(error.message)) { + return { skipped: error.message }; + } + throw new Error(error.message); + } finally { + await wappalyzer.destroy(); + } +}; + +export const handler = middleware(techStackHandler); +export default handler; diff --git a/packages/api/handlers/threats.js b/packages/api/handlers/threats.js new file mode 100644 index 000000000..1f8d72655 --- /dev/null +++ b/packages/api/handlers/threats.js @@ -0,0 +1,96 @@ +import xml2js from 'xml2js'; +import middleware from './_common/middleware.js'; +import { httpPost } from './_common/http.js'; +import { parseTarget } from './_common/parse-target.js'; +import { requireEnv, upstreamError } from './_common/upstream.js'; + +const safeBrowsing = async (url) => { + const auth = requireEnv('GOOGLE_CLOUD_API_KEY', 'Google Safe Browsing'); + if (auth.skipped) return auth; + try { + const res = await httpPost( + `https://safebrowsing.googleapis.com/v4/threatMatches:find?key=${auth.value}`, + { + threatInfo: { + threatTypes: [ + 'MALWARE', + 'SOCIAL_ENGINEERING', + 'UNWANTED_SOFTWARE', + 'POTENTIALLY_HARMFUL_APPLICATION', + 'API_ABUSE', + ], + platformTypes: ['ANY_PLATFORM'], + threatEntryTypes: ['URL'], + threatEntries: [{ url }], + }, + }, + ); + return res.data?.matches ? { unsafe: true, details: res.data.matches } : { unsafe: false }; + } catch (error) { + return upstreamError(error, 'Google Safe Browsing'); + } +}; + +const urlHaus = async (url) => { + const { hostname } = parseTarget(url); + try { + const res = await httpPost('https://urlhaus-api.abuse.ch/v1/host/', `host=${hostname}`, { + headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, + }); + return res.data; + } catch (error) { + return upstreamError(error, 'URLhaus'); + } +}; + +const phishTank = async (url) => { + try { + const encoded = Buffer.from(url).toString('base64'); + const res = await httpPost(`https://checkurl.phishtank.com/checkurl/?url=${encoded}`, null, { + headers: { 'User-Agent': 'phishtank/web-check' }, + timeout: 3000, + }); + const parsed = await xml2js.parseStringPromise(res.data, { explicitArray: false }); + return parsed.response.results; + } catch (error) { + return upstreamError(error, 'PhishTank'); + } +}; + +const cloudmersive = async (url) => { + const auth = requireEnv('CLOUDMERSIVE_API_KEY', 'Cloudmersive'); + if (auth.skipped) return auth; + try { + const res = await httpPost( + 'https://api.cloudmersive.com/virus/scan/website', + `Url=${encodeURIComponent(url)}`, + { + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + Apikey: auth.value, + }, + }, + ); + return res.data; + } catch (error) { + return upstreamError(error, 'Cloudmersive'); + } +}; + +// Aggregate four threat-feed lookups; skip the card if every source failed +const threatsHandler = async (url) => { + const sources = await Promise.all([ + safeBrowsing(url), + urlHaus(url), + phishTank(url), + cloudmersive(url), + ]); + const [safe, haus, phish, cloud] = sources; + if (sources.every((s) => s?.error || s?.skipped)) { + return { skipped: 'No threat sources returned data for this host' }; + } + return { safeBrowsing: safe, urlHaus: haus, phishTank: phish, cloudmersive: cloud }; +}; + +export const handler = middleware(threatsHandler); +export default handler; diff --git a/packages/api/handlers/tls-connection.js b/packages/api/handlers/tls-connection.js new file mode 100644 index 000000000..329b09c62 --- /dev/null +++ b/packages/api/handlers/tls-connection.js @@ -0,0 +1,84 @@ +import tls from 'tls'; +import middleware from './_common/middleware.js'; +import { parseTarget } from './_common/parse-target.js'; + +const HANDSHAKE_TIMEOUT = 4000; + +const isIp = (h) => /^[\d.]+$/.test(h) || h.includes(':'); + +// Open one TLS handshake to the host and capture what was negotiated +const handshake = ({ hostname, port }) => + new Promise((resolve, reject) => { + let ocspStapled = false; + const socket = tls.connect({ + host: hostname, + port: port ? Number(port) : 443, + ...(isIp(hostname) ? {} : { servername: hostname }), + ALPNProtocols: ['h2', 'http/1.1'], + rejectUnauthorized: false, + requestOCSP: true, + }); + socket.on('OCSPResponse', (res) => { + ocspStapled = res?.length > 0; + }); + + let settled = false; + const finish = (fn) => (arg) => { + if (settled) return; + settled = true; + fn(arg); + }; + socket.setTimeout(HANDSHAKE_TIMEOUT); + socket.once( + 'secureConnect', + finish(() => { + const cipher = socket.getCipher(); + const protocol = socket.getProtocol(); + const ephemeral = + typeof socket.getEphemeralKeyInfo === 'function' ? socket.getEphemeralKeyInfo() : null; + const result = { + protocol, + cipher: cipher && { + name: cipher.name, + standardName: cipher.standardName, + version: cipher.version, + }, + alpnProtocol: socket.alpnProtocol || null, + sessionResumption: !!socket.getSession(), + forwardSecrecy: protocol === 'TLSv1.3' || (!!cipher && /^(ECDHE|DHE)/.test(cipher.name)), + authorized: socket.authorized, + authError: socket.authorizationError ? String(socket.authorizationError) : null, + ephemeralKey: ephemeral && { + type: ephemeral.type || null, + name: ephemeral.name || null, + size: ephemeral.size || null, + }, + ocspStapled, + }; + socket.end(); + resolve(result); + }), + ); + socket.once( + 'timeout', + finish(() => { + socket.destroy(); + reject(new Error('TLS handshake timed-out')); + }), + ); + socket.once( + 'error', + finish((err) => { + socket.destroy(); + reject(err); + }), + ); + }); + +const tlsConnectionHandler = async (url) => { + const { hostname, port } = parseTarget(url); + return handshake({ hostname, port }); +}; + +export const handler = middleware(tlsConnectionHandler); +export default handler; diff --git a/packages/api/handlers/tls-labs.js b/packages/api/handlers/tls-labs.js new file mode 100644 index 000000000..900a3a7d7 --- /dev/null +++ b/packages/api/handlers/tls-labs.js @@ -0,0 +1,32 @@ +import middleware from './_common/middleware.js'; +import { httpGet } from './_common/http.js'; +import { parseTarget } from './_common/parse-target.js'; +import { upstreamError } from './_common/upstream.js'; + +const SSL_LABS = 'https://api.ssllabs.com/api/v3/analyze'; + +// Pull a cached SSL Labs report; skip if no fresh cache available +const tlsLabsHandler = async (url) => { + const { hostname } = parseTarget(url); + try { + const res = await httpGet(SSL_LABS, { + params: { host: hostname, fromCache: 'on', maxAge: 24, all: 'done' }, + timeout: 8000, + headers: { 'User-Agent': 'web-check (https://web-check.xyz)' }, + }); + const data = res.data; + if (!data || data.status !== 'READY' || !data.endpoints?.length) { + return { + skipped: + 'No cached SSL Labs report for this host. ' + + 'Run a fresh scan at https://www.ssllabs.com/ssltest/', + }; + } + return data; + } catch (error) { + return upstreamError(error, 'SSL Labs lookup'); + } +}; + +export const handler = middleware(tlsLabsHandler); +export default handler; diff --git a/packages/api/handlers/trace-route.js b/packages/api/handlers/trace-route.js new file mode 100644 index 000000000..c181bdb91 --- /dev/null +++ b/packages/api/handlers/trace-route.js @@ -0,0 +1,58 @@ +import { execFile } from 'child_process'; +import middleware from './_common/middleware.js'; +import { parseTarget } from './_common/parse-target.js'; + +const LOCAL_TIMEOUT = 8000; + +// Parse traceroute -n output into [{ip, time}] entries, skipping unanswered hops +const parseHops = (stdout) => { + const hops = []; + for (const line of stdout.split('\n')) { + const m = line.match(/^\s*\d+\s+([\d.]+|\S*::\S*)\s+([\d.]+)\s*ms/); + if (m) hops.push({ ip: m[1], time: Number(m[2]) }); + } + return hops; +}; + +// Run the system traceroute binary via execFile (no shell, no injection) +const runTraceroute = (host) => + new Promise((resolve, reject) => { + execFile( + 'traceroute', + ['-q', '1', '-n', '-w', '2', host], + { timeout: LOCAL_TIMEOUT }, + (err, stdout) => (err ? reject(err) : resolve(parseHops(stdout))), + ); + }); + +const isMissingBinary = (err) => + err?.code === 'ENOENT' || /command not found|not installed/i.test(err?.message || ''); + +const traceRouteHandler = async (url) => { + const start = Date.now(); + const { hostname } = parseTarget(url); + let hops; + try { + hops = await runTraceroute(hostname); + } catch (err) { + if (isMissingBinary(err)) { + return { + skipped: + 'Traceroute is not installed in this environment. ' + + 'Install via your package manager, or run web-check via Docker.', + }; + } + return { error: `Traceroute failed: ${err.message}` }; + } + if (!hops.length) { + return { skipped: 'Traceroute returned no answered hops for this host' }; + } + return { + message: 'Traceroute completed!', + result: hops.map(({ ip, time }) => ({ [ip]: [time] })), + timeTaken: Date.now() - start, + }; +}; + +export const handler = middleware(traceRouteHandler); +export default handler; diff --git a/packages/api/handlers/txt-records.js b/packages/api/handlers/txt-records.js new file mode 100644 index 000000000..76303605a --- /dev/null +++ b/packages/api/handlers/txt-records.js @@ -0,0 +1,22 @@ +import dns from 'dns/promises'; +import middleware from './_common/middleware.js'; +import { parseTarget } from './_common/parse-target.js'; + +const txtRecordHandler = async (url) => { + const { hostname } = parseTarget(url); + const txtRecords = await dns.resolveTxt(hostname); + // Join chunks (DNS splits long records at 255 bytes), then key=value + const result = {}; + for (const chunks of txtRecords) { + const full = chunks.join(''); + const eq = full.indexOf('='); + let key = eq > 0 ? full.slice(0, eq) : full; + const val = eq > 0 ? full.slice(eq + 1) : ''; + while (key in result) key += '_'; + result[key] = val; + } + return result; +}; + +export const handler = middleware(txtRecordHandler); +export default handler; diff --git a/packages/api/handlers/whois.js b/packages/api/handlers/whois.js new file mode 100644 index 000000000..9a3e0ec13 --- /dev/null +++ b/packages/api/handlers/whois.js @@ -0,0 +1,135 @@ +import net from 'net'; +import psl from 'psl'; +import { whoisDomain } from 'whoiser'; +import middleware from './_common/middleware.js'; +import { parseTarget } from './_common/parse-target.js'; +import { createLogger } from './_common/logger.js'; + +const log = createLogger('whois'); +const TIMEOUT = 8000; + +// Walk every WHOIS/RDAP source, return the first non-empty value across the given keys +const pick = (results, ...keys) => { + for (const src of Object.values(results)) { + for (const key of keys) { + const v = src?.[key]; + if (v === undefined || v === null) continue; + if (typeof v === 'string' && !v.trim()) continue; + if (Array.isArray(v) && !v.length) continue; + return v; + } + } + return undefined; +}; + +// Lower-case + dedupe nameservers, drop empty entries +const cleanNs = (ns) => { + if (!Array.isArray(ns)) return undefined; + const out = [...new Set(ns.map((n) => String(n).trim().toLowerCase()).filter(Boolean))]; + return out.length ? out : undefined; +}; + +// Convert a date string to ISO 8601 when parseable, otherwise return the raw value +const toIso = (raw) => { + if (!raw || typeof raw !== 'string') return raw; + const trimmed = raw.trim().replace(/\s*#.*$/, ''); + const t = Date.parse(trimmed); + if (!Number.isNaN(t)) return new Date(t).toISOString(); + const m = trimmed.match(/^(\d{4})(\d{2})(\d{2})$/); + if (m) return new Date(`${m[1]}-${m[2]}-${m[3]}T00:00:00Z`).toISOString(); + return raw; +}; + +// Reduce a hostname to its registrable domain so registry WHOIS lookups succeed +const baseDomain = (host) => psl.parse(host)?.domain || host; + +// Pull the formatted-name value out of an RDAP entity vCard +const vcardFn = (vcard) => { + if (!Array.isArray(vcard?.[1])) return undefined; + const fn = vcard[1].find((f) => Array.isArray(f) && f[0] === 'fn'); + return fn?.[3] || undefined; +}; + +// Map an RDAP response into the same field names whoiser exposes, so pick() works uniformly +const rdapToWhoiserShape = (data) => { + if (!data || data.errorCode || data.objectClassName === 'error') return null; + const events = data.events || []; + const evt = (a) => events.find((e) => e.eventAction === a)?.eventDate; + const registrar = (data.entities || []).find((e) => (e.roles || []).includes('registrar')); + const ianaId = registrar?.publicIds?.find((p) => /iana/i.test(p.type))?.identifier; + const registrarUrlEntry = registrar?.links?.find((l) => l.rel === 'about' || l.rel === 'related'); + return { + 'Domain Name': data.ldhName, + 'Created Date': evt('registration'), + 'Updated Date': evt('last changed') || evt('last update of RDAP database'), + 'Expiry Date': evt('expiration'), + 'Registry Domain ID': data.handle, + Registrar: vcardFn(registrar?.vcardArray), + 'Registrar IANA ID': ianaId, + 'Registrar URL': registrarUrlEntry?.href, + 'Domain Status': data.status, + 'Name Server': (data.nameservers || []).map((n) => n.ldhName).filter(Boolean), + DNSSEC: data.secureDNS?.delegationSigned ? 'signed' : 'unsigned', + }; +}; + +// Last-resort lookup via rdap.org (a meta-resolver that bootstraps the right RDAP server) +const fetchRdapFallback = async (domain) => { + try { + const res = await fetch(`https://rdap.org/domain/${encodeURIComponent(domain)}`, { + signal: AbortSignal.timeout(TIMEOUT), + }); + if (!res.ok) return null; + return rdapToWhoiserShape(await res.json()); + } catch { + return null; + } +}; + +// Whether a parsed result set has anything worth returning to the frontend +const hasUsefulData = (r) => + r && + (pick(r, 'Created Date', 'Creation Date') || + pick(r, 'Updated Date') || + pick(r, 'Expiry Date', 'Registry Expiry Date') || + pick(r, 'Registrar') || + cleanNs(pick(r, 'Name Server'))); + +// Resolve domain registration data via whoiser, with rdap.org as a fallback for TLD gaps +const whoisHandler = async (url) => { + const { hostname } = parseTarget(url); + if (net.isIP(hostname)) { + return { skipped: 'WHOIS lookups apply to domains, not IP addresses' }; + } + const target = baseDomain(hostname); + let results = {}; + try { + results = await whoisDomain(target, { follow: 2, timeout: TIMEOUT }); + } catch (error) { + log.debug(`whoisDomain failed for ${target}: ${error.message}`); + } + if (!hasUsefulData(results)) { + const rdap = await fetchRdapFallback(target); + if (rdap) results = { ...results, 'rdap.org': rdap }; + } + if (!hasUsefulData(results)) { + return { skipped: 'No WHOIS data available for this domain' }; + } + return { + domain: pick(results, 'Domain Name') || target, + registrar: pick(results, 'Registrar'), + registrarUrl: pick(results, 'Registrar URL'), + registrarIanaId: pick(results, 'Registrar IANA ID'), + registrarWhoisServer: pick(results, 'Registrar WHOIS Server'), + registryDomainId: pick(results, 'Registry Domain ID'), + created: toIso(pick(results, 'Created Date', 'Creation Date')), + updated: toIso(pick(results, 'Updated Date')), + expires: toIso(pick(results, 'Expiry Date', 'Registry Expiry Date', 'Expiration Date')), + nameservers: cleanNs(pick(results, 'Name Server')), + status: pick(results, 'Domain Status'), + dnssec: pick(results, 'DNSSEC'), + }; +}; + +export const handler = middleware(whoisHandler); +export default handler; diff --git a/packages/api/package.json b/packages/api/package.json new file mode 100644 index 000000000..27a3fcd18 --- /dev/null +++ b/packages/api/package.json @@ -0,0 +1,28 @@ +{ + "name": "@web-check/api", + "version": "2.1.0", + "private": true, + "type": "module", + "main": "./server.js", + "scripts": { + "start": "node server.js", + "dev": "DISABLE_GUI='true' PORT='3001' nodemon server.js" + }, + "dependencies": { + "@sparticuz/chromium": "^148.0.0", + "cheerio": "^1.2.0", + "cors": "^2.8.6", + "dotenv": "^17.4.2", + "express": "^5.2.1", + "express-rate-limit": "^8.5.0", + "psl": "^1.15.0", + "puppeteer": "^24.42.0", + "puppeteer-core": "^24.42.0", + "wappalyzer": "^6.10.66", + "whoiser": "^2.0.0-beta.10", + "xml2js": "^0.6.2" + }, + "devDependencies": { + "nodemon": "^3.1.14" + } +} diff --git a/packages/api/server.js b/packages/api/server.js new file mode 100644 index 000000000..8853f452b --- /dev/null +++ b/packages/api/server.js @@ -0,0 +1,203 @@ +import fs from 'fs'; +import path from 'path'; +import { fileURLToPath } from 'url'; +import cors from 'cors'; +import dotenv from 'dotenv'; +import express from 'express'; +import rateLimit from 'express-rate-limit'; +import { createLogger } from './handlers/_common/logger.js'; + +const __dirname = path.dirname(fileURLToPath(import.meta.url)); + +// Load env from the monorepo root so all workspaces share one .env file +dotenv.config({ path: path.resolve(__dirname, '..', '..', '.env') }); + +const log = createLogger('server'); + +const PORT = parseInt(process.env.PORT || '3000', 10); +const API_DIR = '/api'; +const HANDLERS_DIR = path.join(__dirname, 'handlers'); +const STATIC_DIR = path.join(__dirname, 'static'); +const APP_DIST = process.env.APP_STATIC_DIR || path.resolve(__dirname, '..', 'app', 'dist'); +const APP_INDEX = path.join(APP_DIST, 'index.html'); + +// Tells middleware to use the express-style handler signature +process.env.WC_SERVER = 'true'; + +const app = express(); + +// Honour TRUST_PROXY when set, parsing booleans and integer hop counts +const trustProxy = process.env.TRUST_PROXY; +if (trustProxy) { + const parsed = /^\d+$/.test(trustProxy) + ? parseInt(trustProxy, 10) + : trustProxy === 'true' + ? true + : trustProxy === 'false' + ? false + : trustProxy; + app.set('trust proxy', parsed); +} + +app.use(cors({ origin: process.env.API_CORS_ORIGIN || '*' })); + +const RATE_LIMITS = [ + { window: 10 * 60, max: 100, label: '10 minutes' }, + { window: 60 * 60, max: 250, label: '1 hour' }, + { window: 12 * 60 * 60, max: 500, label: '12 hours' }, +]; + +const rateLimitMessage = (label) => + `You've been rate-limited, please try again in ${label}.\n` + + 'This keeps the service running smoothly for everyone. ' + + 'You can get around these limits by running your own instance of Web Check.'; + +if (process.env.API_ENABLE_RATE_LIMIT === 'true') { + for (const limit of RATE_LIMITS) { + app.use( + API_DIR, + rateLimit({ + windowMs: limit.window * 1000, + limit: limit.max, + standardHeaders: true, + legacyHeaders: false, + message: { error: rateLimitMessage(limit.label) }, + }), + ); + } +} + +const handlers = {}; + +// Discover and dynamically import every handler module under ./handlers +const loadHandlers = async () => { + const entries = await fs.promises.readdir(HANDLERS_DIR, { withFileTypes: true }); + const files = entries.filter((e) => e.isFile() && e.name.endsWith('.js')); + await Promise.all( + files.map(async (entry) => { + const route = `${API_DIR}/${entry.name.replace(/\.js$/, '')}`; + try { + const mod = await import(path.join(HANDLERS_DIR, entry.name)); + const handler = mod.default || mod.handler; + if (typeof handler === 'function') handlers[route] = handler; + } catch (err) { + log.error(`failed to load handler ${entry.name}: ${err.message}`); + } + }), + ); + + for (const [route, handler] of Object.entries(handlers)) { + app.get(route, async (req, res) => { + try { + await handler(req, res); + } catch (err) { + res.status(500).json({ error: err.message }); + } + }); + } +}; + +// Render the static placeholder template with a status message +const renderPlaceholder = async (res, msgId, logs) => { + const messages = { + notCompiled: + 'Looks like the GUI app has not yet been compiled.
' + + 'Run yarn build to continue, then restart the server.', + disabledGui: + 'Web-Check API is up and running!
Access the endpoints at ' + + `${API_DIR}`, + }; + const tail = logs ? `
${logs}
` : ''; + const body = (messages[msgId] || 'An unknown error occurred') + tail; + try { + const tplPath = path.join(STATIC_DIR, 'placeholder.html'); + const tpl = await fs.promises.readFile(tplPath, 'utf-8'); + res.status(500).send(tpl.replace('', body)); + } catch { + res.status(500).send(`
${body}
`); + } +}; + +// Aggregate every handler in parallel for the bare /api endpoint +app.get(API_DIR, async (req, res) => { + const { url } = req.query; + const maxMs = parseInt(process.env.PUBLIC_API_TIMEOUT_LIMIT || '60000', 10); + + const runHandler = async (handler, name) => { + let captured; + const mockRes = { status: () => mockRes, json: (body) => (captured = body) }; + let timer; + const timeout = new Promise((resolve) => { + timer = setTimeout(() => { + const seconds = maxMs / 1000; + resolve({ error: `Timed out after ${seconds} seconds, when executing ${name}` }); + }, maxMs); + }); + const work = handler({ ...req, query: { url } }, mockRes) + .then(() => captured) + .catch((err) => ({ error: err.message })); + const result = await Promise.race([work, timeout]); + clearTimeout(timer); + return result; + }; + + const results = {}; + await Promise.all( + Object.entries(handlers).map(async ([route, handler]) => { + const name = route.replace(`${API_DIR}/`, ''); + results[name] = await runHandler(handler, name); + }), + ); + res.json(results); +}); + +await loadHandlers(); + +const guiDisabled = process.env.DISABLE_GUI && process.env.DISABLE_GUI !== 'false'; +const guiAvailable = !guiDisabled && fs.existsSync(APP_INDEX); + +// Redirect bare root to the React app, unless the GUI has been disabled +app.get('/', (_req, res) => { + if (guiDisabled) return renderPlaceholder(res, 'disabledGui'); + if (!guiAvailable) return renderPlaceholder(res, 'notCompiled'); + res.redirect(302, '/check'); +}); + +if (guiAvailable) { + app.use(express.static(APP_DIST, { index: false })); + // SPA fallback: serve app shell for /check, redirect other paths to it + app.use((req, res, next) => { + if (req.method !== 'GET' || req.path.startsWith(`${API_DIR}/`)) return next(); + if (req.path === '/check' || req.path.startsWith('/check/')) { + return res.sendFile(APP_INDEX); + } + res.redirect(302, '/check'); + }); +} + +// Final fallback for unmatched paths +app.use((req, res) => { + if (req.path.startsWith(`${API_DIR}/`)) { + res.status(404).json({ error: 'Not found' }); + } else if (!guiAvailable) { + renderPlaceholder(res, 'notCompiled'); + } else { + res.status(404).sendFile(path.join(STATIC_DIR, 'error.html')); + } +}); + +const banner = () => { + process.stdout.write( + '\x1b[36m\n' + + ' __ __ _ ___ _ _ \n' + + ' \\ \\ / /__| |__ ___ / __| |_ ___ __| |__\n' + + " \\ \\/\\/ / -_) '_ \\___| (__| ' \\/ -_) _| / /\n" + + ' \\_/\\_/\\___|_.__/ \\___|_||_\\___\\__|_\\_\\\n' + + '\x1b[0m\n' + + `\x1b[1m\x1b[32mWeb-Check is up and running at ` + + `http://localhost:${PORT}\x1b[0m\n` + + '\x1b[2m\x1b[36m https://github.com/lissy93/web-check\x1b[0m\n\n', + ); +}; + +app.listen(PORT, banner); diff --git a/public/error.html b/packages/api/static/error.html similarity index 100% rename from public/error.html rename to packages/api/static/error.html diff --git a/public/placeholder.html b/packages/api/static/placeholder.html similarity index 100% rename from public/placeholder.html rename to packages/api/static/placeholder.html diff --git a/packages/app/index.html b/packages/app/index.html new file mode 100644 index 000000000..1d1501a46 --- /dev/null +++ b/packages/app/index.html @@ -0,0 +1,13 @@ + + + + + + + Web Check + + +
+ + + diff --git a/packages/app/package.json b/packages/app/package.json new file mode 100644 index 000000000..76a5d2962 --- /dev/null +++ b/packages/app/package.json @@ -0,0 +1,36 @@ +{ + "name": "@web-check/app", + "version": "2.1.0", + "private": true, + "type": "module", + "exports": { + "./main": "./src/main.tsx", + "./styles/*": "./src/styles/*", + "./*": "./src/*" + }, + "scripts": { + "dev": "vite", + "build": "vite build", + "preview": "vite preview" + }, + "dependencies": { + "@emotion/react": "^11.14.0", + "@emotion/styled": "^11.14.1", + "framer-motion": "^12.38.0", + "prop-types": "^15.8.1", + "react": "^19.2.5", + "react-dom": "^19.2.5", + "react-masonry-css": "^1.0.16", + "react-router-dom": "^7.14.2", + "react-simple-maps": "^3.0.0", + "react-toastify": "^11.1.0", + "recharts": "^3.8.1" + }, + "devDependencies": { + "@types/react": "^19.2.14", + "@types/react-dom": "^19.2.3", + "@vitejs/plugin-react": "^5.0.4", + "typescript": "^6.0.3", + "vite": "^7.2.0" + } +} diff --git a/src/web-check-live/App.tsx b/packages/app/src/App.tsx similarity index 100% rename from src/web-check-live/App.tsx rename to packages/app/src/App.tsx diff --git a/src/web-check-live/assets/data/map-features.json b/packages/app/src/assets/data/map-features.json similarity index 100% rename from src/web-check-live/assets/data/map-features.json rename to packages/app/src/assets/data/map-features.json diff --git a/src/web-check-live/components/Form/Button.tsx b/packages/app/src/components/Form/Button.tsx similarity index 100% rename from src/web-check-live/components/Form/Button.tsx rename to packages/app/src/components/Form/Button.tsx diff --git a/src/web-check-live/components/Form/Card.tsx b/packages/app/src/components/Form/Card.tsx similarity index 100% rename from src/web-check-live/components/Form/Card.tsx rename to packages/app/src/components/Form/Card.tsx diff --git a/src/web-check-live/components/Form/Heading.tsx b/packages/app/src/components/Form/Heading.tsx similarity index 100% rename from src/web-check-live/components/Form/Heading.tsx rename to packages/app/src/components/Form/Heading.tsx diff --git a/src/web-check-live/components/Form/Input.tsx b/packages/app/src/components/Form/Input.tsx similarity index 100% rename from src/web-check-live/components/Form/Input.tsx rename to packages/app/src/components/Form/Input.tsx diff --git a/src/web-check-live/components/Form/Modal.tsx b/packages/app/src/components/Form/Modal.tsx similarity index 100% rename from src/web-check-live/components/Form/Modal.tsx rename to packages/app/src/components/Form/Modal.tsx diff --git a/src/web-check-live/components/Form/Nav.tsx b/packages/app/src/components/Form/Nav.tsx similarity index 100% rename from src/web-check-live/components/Form/Nav.tsx rename to packages/app/src/components/Form/Nav.tsx diff --git a/src/web-check-live/components/Form/Row.tsx b/packages/app/src/components/Form/Row.tsx similarity index 100% rename from src/web-check-live/components/Form/Row.tsx rename to packages/app/src/components/Form/Row.tsx diff --git a/src/web-check-live/components/Results/Archives.tsx b/packages/app/src/components/Results/Archives.tsx similarity index 100% rename from src/web-check-live/components/Results/Archives.tsx rename to packages/app/src/components/Results/Archives.tsx diff --git a/src/web-check-live/components/Results/BlockLists.tsx b/packages/app/src/components/Results/BlockLists.tsx similarity index 100% rename from src/web-check-live/components/Results/BlockLists.tsx rename to packages/app/src/components/Results/BlockLists.tsx diff --git a/src/web-check-live/components/Results/BuiltWith.tsx b/packages/app/src/components/Results/BuiltWith.tsx similarity index 100% rename from src/web-check-live/components/Results/BuiltWith.tsx rename to packages/app/src/components/Results/BuiltWith.tsx diff --git a/src/web-check-live/components/Results/CarbonFootprint.tsx b/packages/app/src/components/Results/CarbonFootprint.tsx similarity index 100% rename from src/web-check-live/components/Results/CarbonFootprint.tsx rename to packages/app/src/components/Results/CarbonFootprint.tsx diff --git a/src/web-check-live/components/Results/ContentLinks.tsx b/packages/app/src/components/Results/ContentLinks.tsx similarity index 100% rename from src/web-check-live/components/Results/ContentLinks.tsx rename to packages/app/src/components/Results/ContentLinks.tsx diff --git a/src/web-check-live/components/Results/Cookies.tsx b/packages/app/src/components/Results/Cookies.tsx similarity index 100% rename from src/web-check-live/components/Results/Cookies.tsx rename to packages/app/src/components/Results/Cookies.tsx diff --git a/src/web-check-live/components/Results/DnsRecords.tsx b/packages/app/src/components/Results/DnsRecords.tsx similarity index 100% rename from src/web-check-live/components/Results/DnsRecords.tsx rename to packages/app/src/components/Results/DnsRecords.tsx diff --git a/src/web-check-live/components/Results/DnsSec.tsx b/packages/app/src/components/Results/DnsSec.tsx similarity index 100% rename from src/web-check-live/components/Results/DnsSec.tsx rename to packages/app/src/components/Results/DnsSec.tsx diff --git a/src/web-check-live/components/Results/DnsServer.tsx b/packages/app/src/components/Results/DnsServer.tsx similarity index 100% rename from src/web-check-live/components/Results/DnsServer.tsx rename to packages/app/src/components/Results/DnsServer.tsx diff --git a/src/web-check-live/components/Results/DomainLookup.tsx b/packages/app/src/components/Results/DomainLookup.tsx similarity index 100% rename from src/web-check-live/components/Results/DomainLookup.tsx rename to packages/app/src/components/Results/DomainLookup.tsx diff --git a/src/web-check-live/components/Results/Firewall.tsx b/packages/app/src/components/Results/Firewall.tsx similarity index 100% rename from src/web-check-live/components/Results/Firewall.tsx rename to packages/app/src/components/Results/Firewall.tsx diff --git a/src/web-check-live/components/Results/Headers.tsx b/packages/app/src/components/Results/Headers.tsx similarity index 100% rename from src/web-check-live/components/Results/Headers.tsx rename to packages/app/src/components/Results/Headers.tsx diff --git a/src/web-check-live/components/Results/HostNames.tsx b/packages/app/src/components/Results/HostNames.tsx similarity index 100% rename from src/web-check-live/components/Results/HostNames.tsx rename to packages/app/src/components/Results/HostNames.tsx diff --git a/src/web-check-live/components/Results/Hsts.tsx b/packages/app/src/components/Results/Hsts.tsx similarity index 100% rename from src/web-check-live/components/Results/Hsts.tsx rename to packages/app/src/components/Results/Hsts.tsx diff --git a/src/web-check-live/components/Results/HttpSecurity.tsx b/packages/app/src/components/Results/HttpSecurity.tsx similarity index 100% rename from src/web-check-live/components/Results/HttpSecurity.tsx rename to packages/app/src/components/Results/HttpSecurity.tsx diff --git a/src/web-check-live/components/Results/Lighthouse.tsx b/packages/app/src/components/Results/Lighthouse.tsx similarity index 100% rename from src/web-check-live/components/Results/Lighthouse.tsx rename to packages/app/src/components/Results/Lighthouse.tsx diff --git a/src/web-check-live/components/Results/MailConfig.tsx b/packages/app/src/components/Results/MailConfig.tsx similarity index 100% rename from src/web-check-live/components/Results/MailConfig.tsx rename to packages/app/src/components/Results/MailConfig.tsx diff --git a/src/web-check-live/components/Results/OpenPorts.tsx b/packages/app/src/components/Results/OpenPorts.tsx similarity index 100% rename from src/web-check-live/components/Results/OpenPorts.tsx rename to packages/app/src/components/Results/OpenPorts.tsx diff --git a/src/web-check-live/components/Results/Rank.tsx b/packages/app/src/components/Results/Rank.tsx similarity index 100% rename from src/web-check-live/components/Results/Rank.tsx rename to packages/app/src/components/Results/Rank.tsx diff --git a/src/web-check-live/components/Results/Redirects.tsx b/packages/app/src/components/Results/Redirects.tsx similarity index 100% rename from src/web-check-live/components/Results/Redirects.tsx rename to packages/app/src/components/Results/Redirects.tsx diff --git a/src/web-check-live/components/Results/RobotsTxt.tsx b/packages/app/src/components/Results/RobotsTxt.tsx similarity index 100% rename from src/web-check-live/components/Results/RobotsTxt.tsx rename to packages/app/src/components/Results/RobotsTxt.tsx diff --git a/src/web-check-live/components/Results/Screenshot.tsx b/packages/app/src/components/Results/Screenshot.tsx similarity index 100% rename from src/web-check-live/components/Results/Screenshot.tsx rename to packages/app/src/components/Results/Screenshot.tsx diff --git a/src/web-check-live/components/Results/SecurityTxt.tsx b/packages/app/src/components/Results/SecurityTxt.tsx similarity index 100% rename from src/web-check-live/components/Results/SecurityTxt.tsx rename to packages/app/src/components/Results/SecurityTxt.tsx diff --git a/src/web-check-live/components/Results/ServerInfo.tsx b/packages/app/src/components/Results/ServerInfo.tsx similarity index 100% rename from src/web-check-live/components/Results/ServerInfo.tsx rename to packages/app/src/components/Results/ServerInfo.tsx diff --git a/src/web-check-live/components/Results/ServerLocation.tsx b/packages/app/src/components/Results/ServerLocation.tsx similarity index 100% rename from src/web-check-live/components/Results/ServerLocation.tsx rename to packages/app/src/components/Results/ServerLocation.tsx diff --git a/src/web-check-live/components/Results/ServerStatus.tsx b/packages/app/src/components/Results/ServerStatus.tsx similarity index 100% rename from src/web-check-live/components/Results/ServerStatus.tsx rename to packages/app/src/components/Results/ServerStatus.tsx diff --git a/src/web-check-live/components/Results/Sitemap.tsx b/packages/app/src/components/Results/Sitemap.tsx similarity index 100% rename from src/web-check-live/components/Results/Sitemap.tsx rename to packages/app/src/components/Results/Sitemap.tsx diff --git a/src/web-check-live/components/Results/SocialTags.tsx b/packages/app/src/components/Results/SocialTags.tsx similarity index 100% rename from src/web-check-live/components/Results/SocialTags.tsx rename to packages/app/src/components/Results/SocialTags.tsx diff --git a/src/web-check-live/components/Results/SslCert.tsx b/packages/app/src/components/Results/SslCert.tsx similarity index 100% rename from src/web-check-live/components/Results/SslCert.tsx rename to packages/app/src/components/Results/SslCert.tsx diff --git a/src/web-check-live/components/Results/TechStack.tsx b/packages/app/src/components/Results/TechStack.tsx similarity index 100% rename from src/web-check-live/components/Results/TechStack.tsx rename to packages/app/src/components/Results/TechStack.tsx diff --git a/src/web-check-live/components/Results/Threats.tsx b/packages/app/src/components/Results/Threats.tsx similarity index 100% rename from src/web-check-live/components/Results/Threats.tsx rename to packages/app/src/components/Results/Threats.tsx diff --git a/src/web-check-live/components/Results/TlsClientCompat.tsx b/packages/app/src/components/Results/TlsClientCompat.tsx similarity index 100% rename from src/web-check-live/components/Results/TlsClientCompat.tsx rename to packages/app/src/components/Results/TlsClientCompat.tsx diff --git a/src/web-check-live/components/Results/TlsConnection.tsx b/packages/app/src/components/Results/TlsConnection.tsx similarity index 100% rename from src/web-check-live/components/Results/TlsConnection.tsx rename to packages/app/src/components/Results/TlsConnection.tsx diff --git a/src/web-check-live/components/Results/TlsSecurityAudit.tsx b/packages/app/src/components/Results/TlsSecurityAudit.tsx similarity index 100% rename from src/web-check-live/components/Results/TlsSecurityAudit.tsx rename to packages/app/src/components/Results/TlsSecurityAudit.tsx diff --git a/src/web-check-live/components/Results/TraceRoute.tsx b/packages/app/src/components/Results/TraceRoute.tsx similarity index 100% rename from src/web-check-live/components/Results/TraceRoute.tsx rename to packages/app/src/components/Results/TraceRoute.tsx diff --git a/src/web-check-live/components/Results/TxtRecords.tsx b/packages/app/src/components/Results/TxtRecords.tsx similarity index 100% rename from src/web-check-live/components/Results/TxtRecords.tsx rename to packages/app/src/components/Results/TxtRecords.tsx diff --git a/src/web-check-live/components/Results/WhoIs.tsx b/packages/app/src/components/Results/WhoIs.tsx similarity index 100% rename from src/web-check-live/components/Results/WhoIs.tsx rename to packages/app/src/components/Results/WhoIs.tsx diff --git a/src/web-check-live/components/boundaries/PageError.tsx b/packages/app/src/components/boundaries/PageError.tsx similarity index 100% rename from src/web-check-live/components/boundaries/PageError.tsx rename to packages/app/src/components/boundaries/PageError.tsx diff --git a/src/web-check-live/components/misc/ActionButtons.tsx b/packages/app/src/components/misc/ActionButtons.tsx similarity index 100% rename from src/web-check-live/components/misc/ActionButtons.tsx rename to packages/app/src/components/misc/ActionButtons.tsx diff --git a/src/web-check-live/components/misc/AdditionalResources.tsx b/packages/app/src/components/misc/AdditionalResources.tsx similarity index 100% rename from src/web-check-live/components/misc/AdditionalResources.tsx rename to packages/app/src/components/misc/AdditionalResources.tsx diff --git a/src/web-check-live/components/misc/DocContent.tsx b/packages/app/src/components/misc/DocContent.tsx similarity index 100% rename from src/web-check-live/components/misc/DocContent.tsx rename to packages/app/src/components/misc/DocContent.tsx diff --git a/src/web-check-live/components/misc/ErrorBoundary.tsx b/packages/app/src/components/misc/ErrorBoundary.tsx similarity index 100% rename from src/web-check-live/components/misc/ErrorBoundary.tsx rename to packages/app/src/components/misc/ErrorBoundary.tsx diff --git a/src/web-check-live/components/misc/FancyBackground.tsx b/packages/app/src/components/misc/FancyBackground.tsx similarity index 100% rename from src/web-check-live/components/misc/FancyBackground.tsx rename to packages/app/src/components/misc/FancyBackground.tsx diff --git a/src/web-check-live/components/misc/Flag.tsx b/packages/app/src/components/misc/Flag.tsx similarity index 100% rename from src/web-check-live/components/misc/Flag.tsx rename to packages/app/src/components/misc/Flag.tsx diff --git a/src/web-check-live/components/misc/Footer.tsx b/packages/app/src/components/misc/Footer.tsx similarity index 100% rename from src/web-check-live/components/misc/Footer.tsx rename to packages/app/src/components/misc/Footer.tsx diff --git a/src/web-check-live/components/misc/Loader.tsx b/packages/app/src/components/misc/Loader.tsx similarity index 100% rename from src/web-check-live/components/misc/Loader.tsx rename to packages/app/src/components/misc/Loader.tsx diff --git a/src/web-check-live/components/misc/LocationMap.tsx b/packages/app/src/components/misc/LocationMap.tsx similarity index 100% rename from src/web-check-live/components/misc/LocationMap.tsx rename to packages/app/src/components/misc/LocationMap.tsx diff --git a/src/web-check-live/components/misc/ProgressBar.tsx b/packages/app/src/components/misc/ProgressBar.tsx similarity index 100% rename from src/web-check-live/components/misc/ProgressBar.tsx rename to packages/app/src/components/misc/ProgressBar.tsx diff --git a/src/web-check-live/components/misc/SelfScanMsg.tsx b/packages/app/src/components/misc/SelfScanMsg.tsx similarity index 100% rename from src/web-check-live/components/misc/SelfScanMsg.tsx rename to packages/app/src/components/misc/SelfScanMsg.tsx diff --git a/src/web-check-live/components/misc/ViewRaw.tsx b/packages/app/src/components/misc/ViewRaw.tsx similarity index 100% rename from src/web-check-live/components/misc/ViewRaw.tsx rename to packages/app/src/components/misc/ViewRaw.tsx diff --git a/packages/app/src/entry.tsx b/packages/app/src/entry.tsx new file mode 100644 index 000000000..e606d3c57 --- /dev/null +++ b/packages/app/src/entry.tsx @@ -0,0 +1,7 @@ +import { createRoot } from 'react-dom/client'; +import Main from './main'; +import './styles/index.css'; + +// Standalone mount used by vite build and the Express server +const container = document.getElementById('root'); +if (container) createRoot(container).render(
); diff --git a/src/web-check-live/hooks/useJobs.ts b/packages/app/src/hooks/useJobs.ts similarity index 100% rename from src/web-check-live/hooks/useJobs.ts rename to packages/app/src/hooks/useJobs.ts diff --git a/src/web-check-live/jobs/registry.ts b/packages/app/src/jobs/registry.ts similarity index 100% rename from src/web-check-live/jobs/registry.ts rename to packages/app/src/jobs/registry.ts diff --git a/src/web-check-live/jobs/types.ts b/packages/app/src/jobs/types.ts similarity index 100% rename from src/web-check-live/jobs/types.ts rename to packages/app/src/jobs/types.ts diff --git a/src/web-check-live/main.tsx b/packages/app/src/main.tsx similarity index 100% rename from src/web-check-live/main.tsx rename to packages/app/src/main.tsx diff --git a/src/web-check-live/styles/colors.ts b/packages/app/src/styles/colors.ts similarity index 100% rename from src/web-check-live/styles/colors.ts rename to packages/app/src/styles/colors.ts diff --git a/src/web-check-live/styles/dimensions.ts b/packages/app/src/styles/dimensions.ts similarity index 100% rename from src/web-check-live/styles/dimensions.ts rename to packages/app/src/styles/dimensions.ts diff --git a/src/web-check-live/styles/globals.tsx b/packages/app/src/styles/globals.tsx similarity index 100% rename from src/web-check-live/styles/globals.tsx rename to packages/app/src/styles/globals.tsx diff --git a/src/web-check-live/styles/index.css b/packages/app/src/styles/index.css similarity index 100% rename from src/web-check-live/styles/index.css rename to packages/app/src/styles/index.css diff --git a/src/web-check-live/styles/typography.ts b/packages/app/src/styles/typography.ts similarity index 100% rename from src/web-check-live/styles/typography.ts rename to packages/app/src/styles/typography.ts diff --git a/src/web-check-live/typings/file-types.d.ts b/packages/app/src/typings/file-types.d.ts similarity index 100% rename from src/web-check-live/typings/file-types.d.ts rename to packages/app/src/typings/file-types.d.ts diff --git a/src/web-check-live/typings/jsx.d.ts b/packages/app/src/typings/jsx.d.ts similarity index 100% rename from src/web-check-live/typings/jsx.d.ts rename to packages/app/src/typings/jsx.d.ts diff --git a/src/web-check-live/typings/react-simple-maps.d.ts b/packages/app/src/typings/react-simple-maps.d.ts similarity index 100% rename from src/web-check-live/typings/react-simple-maps.d.ts rename to packages/app/src/typings/react-simple-maps.d.ts diff --git a/src/web-check-live/utils/address-type-checker.ts b/packages/app/src/utils/address-type-checker.ts similarity index 100% rename from src/web-check-live/utils/address-type-checker.ts rename to packages/app/src/utils/address-type-checker.ts diff --git a/src/web-check-live/utils/docs.ts b/packages/app/src/utils/docs.ts similarity index 100% rename from src/web-check-live/utils/docs.ts rename to packages/app/src/utils/docs.ts diff --git a/src/web-check-live/utils/get-keys.ts b/packages/app/src/utils/get-keys.ts similarity index 100% rename from src/web-check-live/utils/get-keys.ts rename to packages/app/src/utils/get-keys.ts diff --git a/src/web-check-live/utils/logger.ts b/packages/app/src/utils/logger.ts similarity index 100% rename from src/web-check-live/utils/logger.ts rename to packages/app/src/utils/logger.ts diff --git a/src/web-check-live/utils/parse-json.ts b/packages/app/src/utils/parse-json.ts similarity index 100% rename from src/web-check-live/utils/parse-json.ts rename to packages/app/src/utils/parse-json.ts diff --git a/src/web-check-live/utils/result-processor.ts b/packages/app/src/utils/result-processor.ts similarity index 100% rename from src/web-check-live/utils/result-processor.ts rename to packages/app/src/utils/result-processor.ts diff --git a/src/web-check-live/views/About.tsx b/packages/app/src/views/About.tsx similarity index 100% rename from src/web-check-live/views/About.tsx rename to packages/app/src/views/About.tsx diff --git a/src/web-check-live/views/Home.tsx b/packages/app/src/views/Home.tsx similarity index 74% rename from src/web-check-live/views/Home.tsx rename to packages/app/src/views/Home.tsx index 0abcf1c50..e31b5b36e 100644 --- a/src/web-check-live/views/Home.tsx +++ b/packages/app/src/views/Home.tsx @@ -38,59 +38,6 @@ const UserInputMain = styled.form` z-index: 2; `; -const SponsorCard = styled.div` - background: ${colors.backgroundLighter}; - box-shadow: 4px 4px 0px ${colors.bgShadowColor}; - border-radius: 8px; - padding: 1rem; - z-index: 5; - margin: 1rem; - width: calc(100% - 2rem); - max-width: 60rem; - z-index: 2; - .inner { - display: flex; - justify-content: space-between; - flex-wrap: wrap; - gap: 1rem; - p { - margin: 0.25rem 0; - } - } - a { - color: ${colors.textColor}; - } - img { - border-radius: 0.25rem; - box-shadow: 2px 2px 0px ${colors.fgShadowColor}; - transition: box-shadow 0.2s; - margin: 0 auto; - display: block; - width: 200px; - &:hover { - box-shadow: 4px 4px 0px ${colors.fgShadowColor}; - } - &:active { - box-shadow: -2px -2px 0px ${colors.fgShadowColor}; - } - } - .cta { - font-size: 0.78rem; - a { - color: ${colors.primary}; - } - } -`; - -// const FindIpButton = styled.a` -// margin: 0.5rem; -// cursor: pointer; -// display: block; -// text-align: center; -// color: ${colors.primary}; -// text-decoration: underline; -// `; - const ErrorMessage = styled.p` color: ${colors.danger}; margin: 0.5rem; @@ -241,46 +188,6 @@ const Home = (): JSX.Element => { Analyze! - - - Sponsored by - -
-

- - Terminal Trove - {' '} - - The $HOME of all things in the terminal. -
- - Get updates on the latest CLI/TUI tools via the{' '} - - Terminal Trove newsletter - - -

- - Terminal Trove - -
-
diff --git a/src/web-check-live/views/NotFound.tsx b/packages/app/src/views/NotFound.tsx similarity index 100% rename from src/web-check-live/views/NotFound.tsx rename to packages/app/src/views/NotFound.tsx diff --git a/src/web-check-live/views/Results.tsx b/packages/app/src/views/Results.tsx similarity index 100% rename from src/web-check-live/views/Results.tsx rename to packages/app/src/views/Results.tsx diff --git a/packages/app/tsconfig.json b/packages/app/tsconfig.json new file mode 100644 index 000000000..534e0deaf --- /dev/null +++ b/packages/app/tsconfig.json @@ -0,0 +1,25 @@ +{ + "compilerOptions": { + "target": "ES2020", + "module": "ES2020", + "moduleResolution": "node", + "allowImportingTsExtensions": true, + "lib": ["DOM", "DOM.Iterable", "ES2020"], + "skipLibCheck": true, + "esModuleInterop": true, + "allowSyntheticDefaultImports": true, + "strict": true, + "forceConsistentCasingInFileNames": true, + "noFallthroughCasesInSwitch": true, + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "react-jsx", + "jsxImportSource": "react", + "baseUrl": ".", + "paths": { + "web-check-live/*": ["src/*"] + } + }, + "include": ["src"] +} diff --git a/packages/app/vite.config.js b/packages/app/vite.config.js new file mode 100644 index 000000000..6ace65de2 --- /dev/null +++ b/packages/app/vite.config.js @@ -0,0 +1,22 @@ +import { defineConfig } from 'vite'; +import react from '@vitejs/plugin-react'; +import { fileURLToPath } from 'url'; +import { dirname, resolve } from 'path'; + +const __dirname = dirname(fileURLToPath(import.meta.url)); + +export default defineConfig({ + plugins: [react({ jsxImportSource: '@emotion/react' })], + // Shared brand assets (fonts, favicons, web-check.png) are owned by the site + // package, so the standalone app build copies them into dist from there + publicDir: resolve(__dirname, '..', 'site', 'public'), + resolve: { + alias: { 'web-check-live': resolve(__dirname, 'src') }, + }, + build: { + outDir: 'dist', + sourcemap: false, + emptyOutDir: true, + }, + server: { port: 5173 }, +}); diff --git a/packages/site/astro.config.mjs b/packages/site/astro.config.mjs new file mode 100644 index 000000000..01d32676f --- /dev/null +++ b/packages/site/astro.config.mjs @@ -0,0 +1,56 @@ +import { defineConfig } from 'astro/config'; +import { fileURLToPath } from 'url'; +import dotenv from 'dotenv'; +import svelte from '@astrojs/svelte'; +import react from '@astrojs/react'; +import partytown from '@astrojs/partytown'; +import sitemap from '@astrojs/sitemap'; + +// Load env vars at build-time from root +dotenv.config({ path: fileURLToPath(new URL('../../.env', import.meta.url)) }); + +const env = (key, fallback) => process?.env?.[key] || fallback; +const site = env('SITE_URL', 'https://web-check.xyz'); +const base = env('BASE_URL', '/'); + +// Main instance shoes marketing pages +const isBossServer = env('BOSS_SERVER', '') === 'true'; + +const redirects = { '/about': '/check/about' }; +if (!isBossServer) redirects['/'] = '/check'; + +// Resolves the React app source so internal `web-check-live/*` imports resolve +const appSrc = fileURLToPath(new URL('../app/src', import.meta.url)); + +// Load .env from the monorepo root so all workspaces share one file +const envDir = fileURLToPath(new URL('../..', import.meta.url)); + +// Dev-only rewrite so deep /check/ URLs serve the SPA shell +// In production this is handled by the platform redirect rules +const checkSpaFallback = { + name: 'check-spa-fallback', + apply: 'serve', + configureServer(server) { + server.middlewares.use((req, _res, next) => { + const url = req.url || ''; + if (url.startsWith('/check/') && url !== '/check/') { + const queryIdx = url.indexOf('?'); + req.url = '/check' + (queryIdx >= 0 ? url.slice(queryIdx) : ''); + } + next(); + }); + }, +}; + +export default defineConfig({ + output: 'static', + site, + base, + integrations: [svelte(), react(), partytown(), sitemap()], + redirects, + vite: { + envDir, + resolve: { alias: { 'web-check-live': appSrc } }, + plugins: [checkSpaFallback], + }, +}); diff --git a/packages/site/package.json b/packages/site/package.json new file mode 100644 index 000000000..f73f56374 --- /dev/null +++ b/packages/site/package.json @@ -0,0 +1,40 @@ +{ + "name": "@web-check/site", + "version": "2.1.0", + "private": true, + "type": "module", + "scripts": { + "dev": "PUBLIC_API_ENDPOINT=http://localhost:3001/api astro dev", + "build": "astro check && astro build", + "preview": "astro preview", + "typecheck": "astro check" + }, + "dependencies": { + "@astrojs/partytown": "^2.1.7", + "@astrojs/react": "^5.0.4", + "@astrojs/sitemap": "^3.7.2", + "@astrojs/svelte": "^8.1.0", + "@emotion/react": "^11.14.0", + "@emotion/styled": "^11.14.1", + "@fortawesome/fontawesome-svg-core": "^7.2.0", + "@fortawesome/free-brands-svg-icons": "^7.2.0", + "@fortawesome/free-regular-svg-icons": "^7.2.0", + "@fortawesome/free-solid-svg-icons": "^7.2.0", + "@fortawesome/svelte-fontawesome": "^0.2.4", + "@web-check/app": "*", + "astro": "^6.2.2", + "framer-motion": "^12.38.0", + "react": "^19.2.5", + "react-dom": "^19.2.5", + "svelte": "^5.55.5" + }, + "devDependencies": { + "@astrojs/check": "^0.9.9", + "@astrojs/ts-plugin": "^1.10.7", + "@types/react": "^19.2.14", + "@types/react-dom": "^19.2.3", + "dotenv": "^17.4.2", + "sass": "^1.99.0", + "typescript": "^6.0.3" + } +} diff --git a/public/android-chrome-192x192.png b/packages/site/public/android-chrome-192x192.png similarity index 100% rename from public/android-chrome-192x192.png rename to packages/site/public/android-chrome-192x192.png diff --git a/public/android-chrome-512x512.png b/packages/site/public/android-chrome-512x512.png similarity index 100% rename from public/android-chrome-512x512.png rename to packages/site/public/android-chrome-512x512.png diff --git a/public/apple-touch-icon.png b/packages/site/public/apple-touch-icon.png similarity index 100% rename from public/apple-touch-icon.png rename to packages/site/public/apple-touch-icon.png diff --git a/public/assets/badges/dockerhub.svg b/packages/site/public/assets/badges/dockerhub.svg similarity index 100% rename from public/assets/badges/dockerhub.svg rename to packages/site/public/assets/badges/dockerhub.svg diff --git a/public/assets/badges/github.svg b/packages/site/public/assets/badges/github.svg similarity index 100% rename from public/assets/badges/github.svg rename to packages/site/public/assets/badges/github.svg diff --git a/public/assets/badges/sponsor.svg b/packages/site/public/assets/badges/sponsor.svg similarity index 100% rename from public/assets/badges/sponsor.svg rename to packages/site/public/assets/badges/sponsor.svg diff --git a/public/assets/badges/webcheck.svg b/packages/site/public/assets/badges/webcheck.svg similarity index 100% rename from public/assets/badges/webcheck.svg rename to packages/site/public/assets/badges/webcheck.svg diff --git a/public/assets/images/background-dots.svg b/packages/site/public/assets/images/background-dots.svg similarity index 100% rename from public/assets/images/background-dots.svg rename to packages/site/public/assets/images/background-dots.svg diff --git a/public/assets/images/docker.svg b/packages/site/public/assets/images/docker.svg similarity index 100% rename from public/assets/images/docker.svg rename to packages/site/public/assets/images/docker.svg diff --git a/public/assets/images/fly.svg b/packages/site/public/assets/images/fly.svg similarity index 100% rename from public/assets/images/fly.svg rename to packages/site/public/assets/images/fly.svg diff --git a/public/assets/images/github.svg b/packages/site/public/assets/images/github.svg similarity index 100% rename from public/assets/images/github.svg rename to packages/site/public/assets/images/github.svg diff --git a/public/assets/images/netlify.svg b/packages/site/public/assets/images/netlify.svg similarity index 100% rename from public/assets/images/netlify.svg rename to packages/site/public/assets/images/netlify.svg diff --git a/public/assets/images/swagger.svg b/packages/site/public/assets/images/swagger.svg similarity index 100% rename from public/assets/images/swagger.svg rename to packages/site/public/assets/images/swagger.svg diff --git a/public/assets/images/vercel.svg b/packages/site/public/assets/images/vercel.svg similarity index 100% rename from public/assets/images/vercel.svg rename to packages/site/public/assets/images/vercel.svg diff --git a/public/assets/images/webauthn.svg b/packages/site/public/assets/images/webauthn.svg similarity index 100% rename from public/assets/images/webauthn.svg rename to packages/site/public/assets/images/webauthn.svg diff --git a/public/banner.png b/packages/site/public/banner.png similarity index 100% rename from public/banner.png rename to packages/site/public/banner.png diff --git a/public/favicon-16x16.png b/packages/site/public/favicon-16x16.png similarity index 100% rename from public/favicon-16x16.png rename to packages/site/public/favicon-16x16.png diff --git a/public/favicon-32x32.png b/packages/site/public/favicon-32x32.png similarity index 100% rename from public/favicon-32x32.png rename to packages/site/public/favicon-32x32.png diff --git a/public/favicon.ico b/packages/site/public/favicon.ico similarity index 100% rename from public/favicon.ico rename to packages/site/public/favicon.ico diff --git a/public/favicon.svg b/packages/site/public/favicon.svg similarity index 100% rename from public/favicon.svg rename to packages/site/public/favicon.svg diff --git a/public/fonts/Hubot-Sans/Hubot-Sans.ttf b/packages/site/public/fonts/Hubot-Sans/Hubot-Sans.ttf similarity index 100% rename from public/fonts/Hubot-Sans/Hubot-Sans.ttf rename to packages/site/public/fonts/Hubot-Sans/Hubot-Sans.ttf diff --git a/public/fonts/Hubot-Sans/Hubot-Sans.woff2 b/packages/site/public/fonts/Hubot-Sans/Hubot-Sans.woff2 similarity index 100% rename from public/fonts/Hubot-Sans/Hubot-Sans.woff2 rename to packages/site/public/fonts/Hubot-Sans/Hubot-Sans.woff2 diff --git a/public/fonts/Hubot-Sans/LICENSE b/packages/site/public/fonts/Hubot-Sans/LICENSE similarity index 100% rename from public/fonts/Hubot-Sans/LICENSE rename to packages/site/public/fonts/Hubot-Sans/LICENSE diff --git a/public/fonts/Hubot-Sans/OTF/HubotSans-Black.otf b/packages/site/public/fonts/Hubot-Sans/OTF/HubotSans-Black.otf similarity index 100% rename from public/fonts/Hubot-Sans/OTF/HubotSans-Black.otf rename to packages/site/public/fonts/Hubot-Sans/OTF/HubotSans-Black.otf diff --git a/public/fonts/Hubot-Sans/OTF/HubotSans-BlackItalic.otf b/packages/site/public/fonts/Hubot-Sans/OTF/HubotSans-BlackItalic.otf similarity index 100% rename from public/fonts/Hubot-Sans/OTF/HubotSans-BlackItalic.otf rename to packages/site/public/fonts/Hubot-Sans/OTF/HubotSans-BlackItalic.otf diff --git a/public/fonts/Hubot-Sans/OTF/HubotSans-Bold.otf b/packages/site/public/fonts/Hubot-Sans/OTF/HubotSans-Bold.otf similarity index 100% rename from public/fonts/Hubot-Sans/OTF/HubotSans-Bold.otf rename to packages/site/public/fonts/Hubot-Sans/OTF/HubotSans-Bold.otf diff --git a/public/fonts/Hubot-Sans/OTF/HubotSans-BoldItalic.otf b/packages/site/public/fonts/Hubot-Sans/OTF/HubotSans-BoldItalic.otf similarity index 100% rename from public/fonts/Hubot-Sans/OTF/HubotSans-BoldItalic.otf rename to packages/site/public/fonts/Hubot-Sans/OTF/HubotSans-BoldItalic.otf diff --git a/public/fonts/Hubot-Sans/OTF/HubotSans-ExtraBold.otf b/packages/site/public/fonts/Hubot-Sans/OTF/HubotSans-ExtraBold.otf similarity index 100% rename from public/fonts/Hubot-Sans/OTF/HubotSans-ExtraBold.otf rename to packages/site/public/fonts/Hubot-Sans/OTF/HubotSans-ExtraBold.otf diff --git a/public/fonts/Hubot-Sans/OTF/HubotSans-ExtraBoldItalic.otf b/packages/site/public/fonts/Hubot-Sans/OTF/HubotSans-ExtraBoldItalic.otf similarity index 100% rename from public/fonts/Hubot-Sans/OTF/HubotSans-ExtraBoldItalic.otf rename to packages/site/public/fonts/Hubot-Sans/OTF/HubotSans-ExtraBoldItalic.otf diff --git a/public/fonts/Hubot-Sans/OTF/HubotSans-ExtraLight.otf b/packages/site/public/fonts/Hubot-Sans/OTF/HubotSans-ExtraLight.otf similarity index 100% rename from public/fonts/Hubot-Sans/OTF/HubotSans-ExtraLight.otf rename to packages/site/public/fonts/Hubot-Sans/OTF/HubotSans-ExtraLight.otf diff --git a/public/fonts/Hubot-Sans/OTF/HubotSans-ExtraLightItalic.otf b/packages/site/public/fonts/Hubot-Sans/OTF/HubotSans-ExtraLightItalic.otf similarity index 100% rename from public/fonts/Hubot-Sans/OTF/HubotSans-ExtraLightItalic.otf rename to packages/site/public/fonts/Hubot-Sans/OTF/HubotSans-ExtraLightItalic.otf diff --git a/public/fonts/Hubot-Sans/OTF/HubotSans-Italic.otf b/packages/site/public/fonts/Hubot-Sans/OTF/HubotSans-Italic.otf similarity index 100% rename from public/fonts/Hubot-Sans/OTF/HubotSans-Italic.otf rename to packages/site/public/fonts/Hubot-Sans/OTF/HubotSans-Italic.otf diff --git a/public/fonts/Hubot-Sans/OTF/HubotSans-Light.otf b/packages/site/public/fonts/Hubot-Sans/OTF/HubotSans-Light.otf similarity index 100% rename from public/fonts/Hubot-Sans/OTF/HubotSans-Light.otf rename to packages/site/public/fonts/Hubot-Sans/OTF/HubotSans-Light.otf diff --git a/public/fonts/Hubot-Sans/OTF/HubotSans-LightItalic.otf b/packages/site/public/fonts/Hubot-Sans/OTF/HubotSans-LightItalic.otf similarity index 100% rename from public/fonts/Hubot-Sans/OTF/HubotSans-LightItalic.otf rename to packages/site/public/fonts/Hubot-Sans/OTF/HubotSans-LightItalic.otf diff --git a/public/fonts/Hubot-Sans/OTF/HubotSans-Medium.otf b/packages/site/public/fonts/Hubot-Sans/OTF/HubotSans-Medium.otf similarity index 100% rename from public/fonts/Hubot-Sans/OTF/HubotSans-Medium.otf rename to packages/site/public/fonts/Hubot-Sans/OTF/HubotSans-Medium.otf diff --git a/public/fonts/Hubot-Sans/OTF/HubotSans-MediumItalic.otf b/packages/site/public/fonts/Hubot-Sans/OTF/HubotSans-MediumItalic.otf similarity index 100% rename from public/fonts/Hubot-Sans/OTF/HubotSans-MediumItalic.otf rename to packages/site/public/fonts/Hubot-Sans/OTF/HubotSans-MediumItalic.otf diff --git a/public/fonts/Hubot-Sans/OTF/HubotSans-Regular.otf b/packages/site/public/fonts/Hubot-Sans/OTF/HubotSans-Regular.otf similarity index 100% rename from public/fonts/Hubot-Sans/OTF/HubotSans-Regular.otf rename to packages/site/public/fonts/Hubot-Sans/OTF/HubotSans-Regular.otf diff --git a/public/fonts/Hubot-Sans/OTF/HubotSans-SemiBold.otf b/packages/site/public/fonts/Hubot-Sans/OTF/HubotSans-SemiBold.otf similarity index 100% rename from public/fonts/Hubot-Sans/OTF/HubotSans-SemiBold.otf rename to packages/site/public/fonts/Hubot-Sans/OTF/HubotSans-SemiBold.otf diff --git a/public/fonts/Hubot-Sans/OTF/HubotSans-SemiBoldItalic.otf b/packages/site/public/fonts/Hubot-Sans/OTF/HubotSans-SemiBoldItalic.otf similarity index 100% rename from public/fonts/Hubot-Sans/OTF/HubotSans-SemiBoldItalic.otf rename to packages/site/public/fonts/Hubot-Sans/OTF/HubotSans-SemiBoldItalic.otf diff --git a/public/fonts/Hubot-Sans/OTF/HubotSansCondensed-Black.otf b/packages/site/public/fonts/Hubot-Sans/OTF/HubotSansCondensed-Black.otf similarity index 100% rename from public/fonts/Hubot-Sans/OTF/HubotSansCondensed-Black.otf rename to packages/site/public/fonts/Hubot-Sans/OTF/HubotSansCondensed-Black.otf diff --git a/public/fonts/Hubot-Sans/OTF/HubotSansCondensed-BlackItalic.otf b/packages/site/public/fonts/Hubot-Sans/OTF/HubotSansCondensed-BlackItalic.otf similarity index 100% rename from public/fonts/Hubot-Sans/OTF/HubotSansCondensed-BlackItalic.otf rename to packages/site/public/fonts/Hubot-Sans/OTF/HubotSansCondensed-BlackItalic.otf diff --git a/public/fonts/Hubot-Sans/OTF/HubotSansCondensed-Bold.otf b/packages/site/public/fonts/Hubot-Sans/OTF/HubotSansCondensed-Bold.otf similarity index 100% rename from public/fonts/Hubot-Sans/OTF/HubotSansCondensed-Bold.otf rename to packages/site/public/fonts/Hubot-Sans/OTF/HubotSansCondensed-Bold.otf diff --git a/public/fonts/Hubot-Sans/OTF/HubotSansCondensed-BoldItalic.otf b/packages/site/public/fonts/Hubot-Sans/OTF/HubotSansCondensed-BoldItalic.otf similarity index 100% rename from public/fonts/Hubot-Sans/OTF/HubotSansCondensed-BoldItalic.otf rename to packages/site/public/fonts/Hubot-Sans/OTF/HubotSansCondensed-BoldItalic.otf diff --git a/public/fonts/Hubot-Sans/OTF/HubotSansCondensed-ExtraBold.otf b/packages/site/public/fonts/Hubot-Sans/OTF/HubotSansCondensed-ExtraBold.otf similarity index 100% rename from public/fonts/Hubot-Sans/OTF/HubotSansCondensed-ExtraBold.otf rename to packages/site/public/fonts/Hubot-Sans/OTF/HubotSansCondensed-ExtraBold.otf diff --git a/public/fonts/Hubot-Sans/OTF/HubotSansCondensed-ExtraBoldItalic.otf b/packages/site/public/fonts/Hubot-Sans/OTF/HubotSansCondensed-ExtraBoldItalic.otf similarity index 100% rename from public/fonts/Hubot-Sans/OTF/HubotSansCondensed-ExtraBoldItalic.otf rename to packages/site/public/fonts/Hubot-Sans/OTF/HubotSansCondensed-ExtraBoldItalic.otf diff --git a/public/fonts/Hubot-Sans/OTF/HubotSansCondensed-ExtraLight.otf b/packages/site/public/fonts/Hubot-Sans/OTF/HubotSansCondensed-ExtraLight.otf similarity index 100% rename from public/fonts/Hubot-Sans/OTF/HubotSansCondensed-ExtraLight.otf rename to packages/site/public/fonts/Hubot-Sans/OTF/HubotSansCondensed-ExtraLight.otf diff --git a/public/fonts/Hubot-Sans/OTF/HubotSansCondensed-ExtraLightItalic.otf b/packages/site/public/fonts/Hubot-Sans/OTF/HubotSansCondensed-ExtraLightItalic.otf similarity index 100% rename from public/fonts/Hubot-Sans/OTF/HubotSansCondensed-ExtraLightItalic.otf rename to packages/site/public/fonts/Hubot-Sans/OTF/HubotSansCondensed-ExtraLightItalic.otf diff --git a/public/fonts/Hubot-Sans/OTF/HubotSansCondensed-Italic.otf b/packages/site/public/fonts/Hubot-Sans/OTF/HubotSansCondensed-Italic.otf similarity index 100% rename from public/fonts/Hubot-Sans/OTF/HubotSansCondensed-Italic.otf rename to packages/site/public/fonts/Hubot-Sans/OTF/HubotSansCondensed-Italic.otf diff --git a/public/fonts/Hubot-Sans/OTF/HubotSansCondensed-Light.otf b/packages/site/public/fonts/Hubot-Sans/OTF/HubotSansCondensed-Light.otf similarity index 100% rename from public/fonts/Hubot-Sans/OTF/HubotSansCondensed-Light.otf rename to packages/site/public/fonts/Hubot-Sans/OTF/HubotSansCondensed-Light.otf diff --git a/public/fonts/Hubot-Sans/OTF/HubotSansCondensed-LightItalic.otf b/packages/site/public/fonts/Hubot-Sans/OTF/HubotSansCondensed-LightItalic.otf similarity index 100% rename from public/fonts/Hubot-Sans/OTF/HubotSansCondensed-LightItalic.otf rename to packages/site/public/fonts/Hubot-Sans/OTF/HubotSansCondensed-LightItalic.otf diff --git a/public/fonts/Hubot-Sans/OTF/HubotSansCondensed-Medium.otf b/packages/site/public/fonts/Hubot-Sans/OTF/HubotSansCondensed-Medium.otf similarity index 100% rename from public/fonts/Hubot-Sans/OTF/HubotSansCondensed-Medium.otf rename to packages/site/public/fonts/Hubot-Sans/OTF/HubotSansCondensed-Medium.otf diff --git a/public/fonts/Hubot-Sans/OTF/HubotSansCondensed-MediumItalic.otf b/packages/site/public/fonts/Hubot-Sans/OTF/HubotSansCondensed-MediumItalic.otf similarity index 100% rename from public/fonts/Hubot-Sans/OTF/HubotSansCondensed-MediumItalic.otf rename to packages/site/public/fonts/Hubot-Sans/OTF/HubotSansCondensed-MediumItalic.otf diff --git a/public/fonts/Hubot-Sans/OTF/HubotSansCondensed-Regular.otf b/packages/site/public/fonts/Hubot-Sans/OTF/HubotSansCondensed-Regular.otf similarity index 100% rename from public/fonts/Hubot-Sans/OTF/HubotSansCondensed-Regular.otf rename to packages/site/public/fonts/Hubot-Sans/OTF/HubotSansCondensed-Regular.otf diff --git a/public/fonts/Hubot-Sans/OTF/HubotSansCondensed-SemiBold.otf b/packages/site/public/fonts/Hubot-Sans/OTF/HubotSansCondensed-SemiBold.otf similarity index 100% rename from public/fonts/Hubot-Sans/OTF/HubotSansCondensed-SemiBold.otf rename to packages/site/public/fonts/Hubot-Sans/OTF/HubotSansCondensed-SemiBold.otf diff --git a/public/fonts/Hubot-Sans/OTF/HubotSansCondensed-SemiBoldItalic.otf b/packages/site/public/fonts/Hubot-Sans/OTF/HubotSansCondensed-SemiBoldItalic.otf similarity index 100% rename from public/fonts/Hubot-Sans/OTF/HubotSansCondensed-SemiBoldItalic.otf rename to packages/site/public/fonts/Hubot-Sans/OTF/HubotSansCondensed-SemiBoldItalic.otf diff --git a/public/fonts/Hubot-Sans/OTF/HubotSansExpanded-Black.otf b/packages/site/public/fonts/Hubot-Sans/OTF/HubotSansExpanded-Black.otf similarity index 100% rename from public/fonts/Hubot-Sans/OTF/HubotSansExpanded-Black.otf rename to packages/site/public/fonts/Hubot-Sans/OTF/HubotSansExpanded-Black.otf diff --git a/public/fonts/Hubot-Sans/OTF/HubotSansExpanded-BlackItalic.otf b/packages/site/public/fonts/Hubot-Sans/OTF/HubotSansExpanded-BlackItalic.otf similarity index 100% rename from public/fonts/Hubot-Sans/OTF/HubotSansExpanded-BlackItalic.otf rename to packages/site/public/fonts/Hubot-Sans/OTF/HubotSansExpanded-BlackItalic.otf diff --git a/public/fonts/Hubot-Sans/OTF/HubotSansExpanded-Bold.otf b/packages/site/public/fonts/Hubot-Sans/OTF/HubotSansExpanded-Bold.otf similarity index 100% rename from public/fonts/Hubot-Sans/OTF/HubotSansExpanded-Bold.otf rename to packages/site/public/fonts/Hubot-Sans/OTF/HubotSansExpanded-Bold.otf diff --git a/public/fonts/Hubot-Sans/OTF/HubotSansExpanded-BoldItalic.otf b/packages/site/public/fonts/Hubot-Sans/OTF/HubotSansExpanded-BoldItalic.otf similarity index 100% rename from public/fonts/Hubot-Sans/OTF/HubotSansExpanded-BoldItalic.otf rename to packages/site/public/fonts/Hubot-Sans/OTF/HubotSansExpanded-BoldItalic.otf diff --git a/public/fonts/Hubot-Sans/OTF/HubotSansExpanded-ExtraBold.otf b/packages/site/public/fonts/Hubot-Sans/OTF/HubotSansExpanded-ExtraBold.otf similarity index 100% rename from public/fonts/Hubot-Sans/OTF/HubotSansExpanded-ExtraBold.otf rename to packages/site/public/fonts/Hubot-Sans/OTF/HubotSansExpanded-ExtraBold.otf diff --git a/public/fonts/Hubot-Sans/OTF/HubotSansExpanded-ExtraBoldItalic.otf b/packages/site/public/fonts/Hubot-Sans/OTF/HubotSansExpanded-ExtraBoldItalic.otf similarity index 100% rename from public/fonts/Hubot-Sans/OTF/HubotSansExpanded-ExtraBoldItalic.otf rename to packages/site/public/fonts/Hubot-Sans/OTF/HubotSansExpanded-ExtraBoldItalic.otf diff --git a/public/fonts/Hubot-Sans/OTF/HubotSansExpanded-ExtraLight.otf b/packages/site/public/fonts/Hubot-Sans/OTF/HubotSansExpanded-ExtraLight.otf similarity index 100% rename from public/fonts/Hubot-Sans/OTF/HubotSansExpanded-ExtraLight.otf rename to packages/site/public/fonts/Hubot-Sans/OTF/HubotSansExpanded-ExtraLight.otf diff --git a/public/fonts/Hubot-Sans/OTF/HubotSansExpanded-ExtraLightItalic.otf b/packages/site/public/fonts/Hubot-Sans/OTF/HubotSansExpanded-ExtraLightItalic.otf similarity index 100% rename from public/fonts/Hubot-Sans/OTF/HubotSansExpanded-ExtraLightItalic.otf rename to packages/site/public/fonts/Hubot-Sans/OTF/HubotSansExpanded-ExtraLightItalic.otf diff --git a/public/fonts/Hubot-Sans/OTF/HubotSansExpanded-Italic.otf b/packages/site/public/fonts/Hubot-Sans/OTF/HubotSansExpanded-Italic.otf similarity index 100% rename from public/fonts/Hubot-Sans/OTF/HubotSansExpanded-Italic.otf rename to packages/site/public/fonts/Hubot-Sans/OTF/HubotSansExpanded-Italic.otf diff --git a/public/fonts/Hubot-Sans/OTF/HubotSansExpanded-Light.otf b/packages/site/public/fonts/Hubot-Sans/OTF/HubotSansExpanded-Light.otf similarity index 100% rename from public/fonts/Hubot-Sans/OTF/HubotSansExpanded-Light.otf rename to packages/site/public/fonts/Hubot-Sans/OTF/HubotSansExpanded-Light.otf diff --git a/public/fonts/Hubot-Sans/OTF/HubotSansExpanded-LightItalic.otf b/packages/site/public/fonts/Hubot-Sans/OTF/HubotSansExpanded-LightItalic.otf similarity index 100% rename from public/fonts/Hubot-Sans/OTF/HubotSansExpanded-LightItalic.otf rename to packages/site/public/fonts/Hubot-Sans/OTF/HubotSansExpanded-LightItalic.otf diff --git a/public/fonts/Hubot-Sans/OTF/HubotSansExpanded-Medium.otf b/packages/site/public/fonts/Hubot-Sans/OTF/HubotSansExpanded-Medium.otf similarity index 100% rename from public/fonts/Hubot-Sans/OTF/HubotSansExpanded-Medium.otf rename to packages/site/public/fonts/Hubot-Sans/OTF/HubotSansExpanded-Medium.otf diff --git a/public/fonts/Hubot-Sans/OTF/HubotSansExpanded-MediumItalic.otf b/packages/site/public/fonts/Hubot-Sans/OTF/HubotSansExpanded-MediumItalic.otf similarity index 100% rename from public/fonts/Hubot-Sans/OTF/HubotSansExpanded-MediumItalic.otf rename to packages/site/public/fonts/Hubot-Sans/OTF/HubotSansExpanded-MediumItalic.otf diff --git a/public/fonts/Hubot-Sans/OTF/HubotSansExpanded-Regular.otf b/packages/site/public/fonts/Hubot-Sans/OTF/HubotSansExpanded-Regular.otf similarity index 100% rename from public/fonts/Hubot-Sans/OTF/HubotSansExpanded-Regular.otf rename to packages/site/public/fonts/Hubot-Sans/OTF/HubotSansExpanded-Regular.otf diff --git a/public/fonts/Hubot-Sans/OTF/HubotSansExpanded-SemiBold.otf b/packages/site/public/fonts/Hubot-Sans/OTF/HubotSansExpanded-SemiBold.otf similarity index 100% rename from public/fonts/Hubot-Sans/OTF/HubotSansExpanded-SemiBold.otf rename to packages/site/public/fonts/Hubot-Sans/OTF/HubotSansExpanded-SemiBold.otf diff --git a/public/fonts/Hubot-Sans/OTF/HubotSansExpanded-SemiBoldItalic.otf b/packages/site/public/fonts/Hubot-Sans/OTF/HubotSansExpanded-SemiBoldItalic.otf similarity index 100% rename from public/fonts/Hubot-Sans/OTF/HubotSansExpanded-SemiBoldItalic.otf rename to packages/site/public/fonts/Hubot-Sans/OTF/HubotSansExpanded-SemiBoldItalic.otf diff --git a/public/fonts/Hubot-Sans/TTF/HubotSans-Black.ttf b/packages/site/public/fonts/Hubot-Sans/TTF/HubotSans-Black.ttf similarity index 100% rename from public/fonts/Hubot-Sans/TTF/HubotSans-Black.ttf rename to packages/site/public/fonts/Hubot-Sans/TTF/HubotSans-Black.ttf diff --git a/public/fonts/Hubot-Sans/TTF/HubotSans-BlackItalic.ttf b/packages/site/public/fonts/Hubot-Sans/TTF/HubotSans-BlackItalic.ttf similarity index 100% rename from public/fonts/Hubot-Sans/TTF/HubotSans-BlackItalic.ttf rename to packages/site/public/fonts/Hubot-Sans/TTF/HubotSans-BlackItalic.ttf diff --git a/public/fonts/Hubot-Sans/TTF/HubotSans-Bold.ttf b/packages/site/public/fonts/Hubot-Sans/TTF/HubotSans-Bold.ttf similarity index 100% rename from public/fonts/Hubot-Sans/TTF/HubotSans-Bold.ttf rename to packages/site/public/fonts/Hubot-Sans/TTF/HubotSans-Bold.ttf diff --git a/public/fonts/Hubot-Sans/TTF/HubotSans-BoldItalic.ttf b/packages/site/public/fonts/Hubot-Sans/TTF/HubotSans-BoldItalic.ttf similarity index 100% rename from public/fonts/Hubot-Sans/TTF/HubotSans-BoldItalic.ttf rename to packages/site/public/fonts/Hubot-Sans/TTF/HubotSans-BoldItalic.ttf diff --git a/public/fonts/Hubot-Sans/TTF/HubotSans-ExtraBold.ttf b/packages/site/public/fonts/Hubot-Sans/TTF/HubotSans-ExtraBold.ttf similarity index 100% rename from public/fonts/Hubot-Sans/TTF/HubotSans-ExtraBold.ttf rename to packages/site/public/fonts/Hubot-Sans/TTF/HubotSans-ExtraBold.ttf diff --git a/public/fonts/Hubot-Sans/TTF/HubotSans-ExtraBoldItalic.ttf b/packages/site/public/fonts/Hubot-Sans/TTF/HubotSans-ExtraBoldItalic.ttf similarity index 100% rename from public/fonts/Hubot-Sans/TTF/HubotSans-ExtraBoldItalic.ttf rename to packages/site/public/fonts/Hubot-Sans/TTF/HubotSans-ExtraBoldItalic.ttf diff --git a/public/fonts/Hubot-Sans/TTF/HubotSans-ExtraLight.ttf b/packages/site/public/fonts/Hubot-Sans/TTF/HubotSans-ExtraLight.ttf similarity index 100% rename from public/fonts/Hubot-Sans/TTF/HubotSans-ExtraLight.ttf rename to packages/site/public/fonts/Hubot-Sans/TTF/HubotSans-ExtraLight.ttf diff --git a/public/fonts/Hubot-Sans/TTF/HubotSans-ExtraLightItalic.ttf b/packages/site/public/fonts/Hubot-Sans/TTF/HubotSans-ExtraLightItalic.ttf similarity index 100% rename from public/fonts/Hubot-Sans/TTF/HubotSans-ExtraLightItalic.ttf rename to packages/site/public/fonts/Hubot-Sans/TTF/HubotSans-ExtraLightItalic.ttf diff --git a/public/fonts/Hubot-Sans/TTF/HubotSans-Italic.ttf b/packages/site/public/fonts/Hubot-Sans/TTF/HubotSans-Italic.ttf similarity index 100% rename from public/fonts/Hubot-Sans/TTF/HubotSans-Italic.ttf rename to packages/site/public/fonts/Hubot-Sans/TTF/HubotSans-Italic.ttf diff --git a/public/fonts/Hubot-Sans/TTF/HubotSans-Light.ttf b/packages/site/public/fonts/Hubot-Sans/TTF/HubotSans-Light.ttf similarity index 100% rename from public/fonts/Hubot-Sans/TTF/HubotSans-Light.ttf rename to packages/site/public/fonts/Hubot-Sans/TTF/HubotSans-Light.ttf diff --git a/public/fonts/Hubot-Sans/TTF/HubotSans-LightItalic.ttf b/packages/site/public/fonts/Hubot-Sans/TTF/HubotSans-LightItalic.ttf similarity index 100% rename from public/fonts/Hubot-Sans/TTF/HubotSans-LightItalic.ttf rename to packages/site/public/fonts/Hubot-Sans/TTF/HubotSans-LightItalic.ttf diff --git a/public/fonts/Hubot-Sans/TTF/HubotSans-Medium.ttf b/packages/site/public/fonts/Hubot-Sans/TTF/HubotSans-Medium.ttf similarity index 100% rename from public/fonts/Hubot-Sans/TTF/HubotSans-Medium.ttf rename to packages/site/public/fonts/Hubot-Sans/TTF/HubotSans-Medium.ttf diff --git a/public/fonts/Hubot-Sans/TTF/HubotSans-MediumItalic.ttf b/packages/site/public/fonts/Hubot-Sans/TTF/HubotSans-MediumItalic.ttf similarity index 100% rename from public/fonts/Hubot-Sans/TTF/HubotSans-MediumItalic.ttf rename to packages/site/public/fonts/Hubot-Sans/TTF/HubotSans-MediumItalic.ttf diff --git a/public/fonts/Hubot-Sans/TTF/HubotSans-Regular.ttf b/packages/site/public/fonts/Hubot-Sans/TTF/HubotSans-Regular.ttf similarity index 100% rename from public/fonts/Hubot-Sans/TTF/HubotSans-Regular.ttf rename to packages/site/public/fonts/Hubot-Sans/TTF/HubotSans-Regular.ttf diff --git a/public/fonts/Hubot-Sans/TTF/HubotSans-SemiBold.ttf b/packages/site/public/fonts/Hubot-Sans/TTF/HubotSans-SemiBold.ttf similarity index 100% rename from public/fonts/Hubot-Sans/TTF/HubotSans-SemiBold.ttf rename to packages/site/public/fonts/Hubot-Sans/TTF/HubotSans-SemiBold.ttf diff --git a/public/fonts/Hubot-Sans/TTF/HubotSans-SemiBoldItalic.ttf b/packages/site/public/fonts/Hubot-Sans/TTF/HubotSans-SemiBoldItalic.ttf similarity index 100% rename from public/fonts/Hubot-Sans/TTF/HubotSans-SemiBoldItalic.ttf rename to packages/site/public/fonts/Hubot-Sans/TTF/HubotSans-SemiBoldItalic.ttf diff --git a/public/fonts/Hubot-Sans/TTF/HubotSansCondensed-Black.ttf b/packages/site/public/fonts/Hubot-Sans/TTF/HubotSansCondensed-Black.ttf similarity index 100% rename from public/fonts/Hubot-Sans/TTF/HubotSansCondensed-Black.ttf rename to packages/site/public/fonts/Hubot-Sans/TTF/HubotSansCondensed-Black.ttf diff --git a/public/fonts/Hubot-Sans/TTF/HubotSansCondensed-BlackItalic.ttf b/packages/site/public/fonts/Hubot-Sans/TTF/HubotSansCondensed-BlackItalic.ttf similarity index 100% rename from public/fonts/Hubot-Sans/TTF/HubotSansCondensed-BlackItalic.ttf rename to packages/site/public/fonts/Hubot-Sans/TTF/HubotSansCondensed-BlackItalic.ttf diff --git a/public/fonts/Hubot-Sans/TTF/HubotSansCondensed-Bold.ttf b/packages/site/public/fonts/Hubot-Sans/TTF/HubotSansCondensed-Bold.ttf similarity index 100% rename from public/fonts/Hubot-Sans/TTF/HubotSansCondensed-Bold.ttf rename to packages/site/public/fonts/Hubot-Sans/TTF/HubotSansCondensed-Bold.ttf diff --git a/public/fonts/Hubot-Sans/TTF/HubotSansCondensed-BoldItalic.ttf b/packages/site/public/fonts/Hubot-Sans/TTF/HubotSansCondensed-BoldItalic.ttf similarity index 100% rename from public/fonts/Hubot-Sans/TTF/HubotSansCondensed-BoldItalic.ttf rename to packages/site/public/fonts/Hubot-Sans/TTF/HubotSansCondensed-BoldItalic.ttf diff --git a/public/fonts/Hubot-Sans/TTF/HubotSansCondensed-ExtraBold.ttf b/packages/site/public/fonts/Hubot-Sans/TTF/HubotSansCondensed-ExtraBold.ttf similarity index 100% rename from public/fonts/Hubot-Sans/TTF/HubotSansCondensed-ExtraBold.ttf rename to packages/site/public/fonts/Hubot-Sans/TTF/HubotSansCondensed-ExtraBold.ttf diff --git a/public/fonts/Hubot-Sans/TTF/HubotSansCondensed-ExtraBoldItalic.ttf b/packages/site/public/fonts/Hubot-Sans/TTF/HubotSansCondensed-ExtraBoldItalic.ttf similarity index 100% rename from public/fonts/Hubot-Sans/TTF/HubotSansCondensed-ExtraBoldItalic.ttf rename to packages/site/public/fonts/Hubot-Sans/TTF/HubotSansCondensed-ExtraBoldItalic.ttf diff --git a/public/fonts/Hubot-Sans/TTF/HubotSansCondensed-ExtraLight.ttf b/packages/site/public/fonts/Hubot-Sans/TTF/HubotSansCondensed-ExtraLight.ttf similarity index 100% rename from public/fonts/Hubot-Sans/TTF/HubotSansCondensed-ExtraLight.ttf rename to packages/site/public/fonts/Hubot-Sans/TTF/HubotSansCondensed-ExtraLight.ttf diff --git a/public/fonts/Hubot-Sans/TTF/HubotSansCondensed-ExtraLightItalic.ttf b/packages/site/public/fonts/Hubot-Sans/TTF/HubotSansCondensed-ExtraLightItalic.ttf similarity index 100% rename from public/fonts/Hubot-Sans/TTF/HubotSansCondensed-ExtraLightItalic.ttf rename to packages/site/public/fonts/Hubot-Sans/TTF/HubotSansCondensed-ExtraLightItalic.ttf diff --git a/public/fonts/Hubot-Sans/TTF/HubotSansCondensed-Italic.ttf b/packages/site/public/fonts/Hubot-Sans/TTF/HubotSansCondensed-Italic.ttf similarity index 100% rename from public/fonts/Hubot-Sans/TTF/HubotSansCondensed-Italic.ttf rename to packages/site/public/fonts/Hubot-Sans/TTF/HubotSansCondensed-Italic.ttf diff --git a/public/fonts/Hubot-Sans/TTF/HubotSansCondensed-Light.ttf b/packages/site/public/fonts/Hubot-Sans/TTF/HubotSansCondensed-Light.ttf similarity index 100% rename from public/fonts/Hubot-Sans/TTF/HubotSansCondensed-Light.ttf rename to packages/site/public/fonts/Hubot-Sans/TTF/HubotSansCondensed-Light.ttf diff --git a/public/fonts/Hubot-Sans/TTF/HubotSansCondensed-LightItalic.ttf b/packages/site/public/fonts/Hubot-Sans/TTF/HubotSansCondensed-LightItalic.ttf similarity index 100% rename from public/fonts/Hubot-Sans/TTF/HubotSansCondensed-LightItalic.ttf rename to packages/site/public/fonts/Hubot-Sans/TTF/HubotSansCondensed-LightItalic.ttf diff --git a/public/fonts/Hubot-Sans/TTF/HubotSansCondensed-Medium.ttf b/packages/site/public/fonts/Hubot-Sans/TTF/HubotSansCondensed-Medium.ttf similarity index 100% rename from public/fonts/Hubot-Sans/TTF/HubotSansCondensed-Medium.ttf rename to packages/site/public/fonts/Hubot-Sans/TTF/HubotSansCondensed-Medium.ttf diff --git a/public/fonts/Hubot-Sans/TTF/HubotSansCondensed-MediumItalic.ttf b/packages/site/public/fonts/Hubot-Sans/TTF/HubotSansCondensed-MediumItalic.ttf similarity index 100% rename from public/fonts/Hubot-Sans/TTF/HubotSansCondensed-MediumItalic.ttf rename to packages/site/public/fonts/Hubot-Sans/TTF/HubotSansCondensed-MediumItalic.ttf diff --git a/public/fonts/Hubot-Sans/TTF/HubotSansCondensed-Regular.ttf b/packages/site/public/fonts/Hubot-Sans/TTF/HubotSansCondensed-Regular.ttf similarity index 100% rename from public/fonts/Hubot-Sans/TTF/HubotSansCondensed-Regular.ttf rename to packages/site/public/fonts/Hubot-Sans/TTF/HubotSansCondensed-Regular.ttf diff --git a/public/fonts/Hubot-Sans/TTF/HubotSansCondensed-SemiBold.ttf b/packages/site/public/fonts/Hubot-Sans/TTF/HubotSansCondensed-SemiBold.ttf similarity index 100% rename from public/fonts/Hubot-Sans/TTF/HubotSansCondensed-SemiBold.ttf rename to packages/site/public/fonts/Hubot-Sans/TTF/HubotSansCondensed-SemiBold.ttf diff --git a/public/fonts/Hubot-Sans/TTF/HubotSansCondensed-SemiBoldItalic.ttf b/packages/site/public/fonts/Hubot-Sans/TTF/HubotSansCondensed-SemiBoldItalic.ttf similarity index 100% rename from public/fonts/Hubot-Sans/TTF/HubotSansCondensed-SemiBoldItalic.ttf rename to packages/site/public/fonts/Hubot-Sans/TTF/HubotSansCondensed-SemiBoldItalic.ttf diff --git a/public/fonts/Hubot-Sans/TTF/HubotSansExpanded-Black.ttf b/packages/site/public/fonts/Hubot-Sans/TTF/HubotSansExpanded-Black.ttf similarity index 100% rename from public/fonts/Hubot-Sans/TTF/HubotSansExpanded-Black.ttf rename to packages/site/public/fonts/Hubot-Sans/TTF/HubotSansExpanded-Black.ttf diff --git a/public/fonts/Hubot-Sans/TTF/HubotSansExpanded-BlackItalic.ttf b/packages/site/public/fonts/Hubot-Sans/TTF/HubotSansExpanded-BlackItalic.ttf similarity index 100% rename from public/fonts/Hubot-Sans/TTF/HubotSansExpanded-BlackItalic.ttf rename to packages/site/public/fonts/Hubot-Sans/TTF/HubotSansExpanded-BlackItalic.ttf diff --git a/public/fonts/Hubot-Sans/TTF/HubotSansExpanded-Bold.ttf b/packages/site/public/fonts/Hubot-Sans/TTF/HubotSansExpanded-Bold.ttf similarity index 100% rename from public/fonts/Hubot-Sans/TTF/HubotSansExpanded-Bold.ttf rename to packages/site/public/fonts/Hubot-Sans/TTF/HubotSansExpanded-Bold.ttf diff --git a/public/fonts/Hubot-Sans/TTF/HubotSansExpanded-BoldItalic.ttf b/packages/site/public/fonts/Hubot-Sans/TTF/HubotSansExpanded-BoldItalic.ttf similarity index 100% rename from public/fonts/Hubot-Sans/TTF/HubotSansExpanded-BoldItalic.ttf rename to packages/site/public/fonts/Hubot-Sans/TTF/HubotSansExpanded-BoldItalic.ttf diff --git a/public/fonts/Hubot-Sans/TTF/HubotSansExpanded-ExtraBold.ttf b/packages/site/public/fonts/Hubot-Sans/TTF/HubotSansExpanded-ExtraBold.ttf similarity index 100% rename from public/fonts/Hubot-Sans/TTF/HubotSansExpanded-ExtraBold.ttf rename to packages/site/public/fonts/Hubot-Sans/TTF/HubotSansExpanded-ExtraBold.ttf diff --git a/public/fonts/Hubot-Sans/TTF/HubotSansExpanded-ExtraBoldItalic.ttf b/packages/site/public/fonts/Hubot-Sans/TTF/HubotSansExpanded-ExtraBoldItalic.ttf similarity index 100% rename from public/fonts/Hubot-Sans/TTF/HubotSansExpanded-ExtraBoldItalic.ttf rename to packages/site/public/fonts/Hubot-Sans/TTF/HubotSansExpanded-ExtraBoldItalic.ttf diff --git a/public/fonts/Hubot-Sans/TTF/HubotSansExpanded-ExtraLight.ttf b/packages/site/public/fonts/Hubot-Sans/TTF/HubotSansExpanded-ExtraLight.ttf similarity index 100% rename from public/fonts/Hubot-Sans/TTF/HubotSansExpanded-ExtraLight.ttf rename to packages/site/public/fonts/Hubot-Sans/TTF/HubotSansExpanded-ExtraLight.ttf diff --git a/public/fonts/Hubot-Sans/TTF/HubotSansExpanded-ExtraLightItalic.ttf b/packages/site/public/fonts/Hubot-Sans/TTF/HubotSansExpanded-ExtraLightItalic.ttf similarity index 100% rename from public/fonts/Hubot-Sans/TTF/HubotSansExpanded-ExtraLightItalic.ttf rename to packages/site/public/fonts/Hubot-Sans/TTF/HubotSansExpanded-ExtraLightItalic.ttf diff --git a/public/fonts/Hubot-Sans/TTF/HubotSansExpanded-Italic.ttf b/packages/site/public/fonts/Hubot-Sans/TTF/HubotSansExpanded-Italic.ttf similarity index 100% rename from public/fonts/Hubot-Sans/TTF/HubotSansExpanded-Italic.ttf rename to packages/site/public/fonts/Hubot-Sans/TTF/HubotSansExpanded-Italic.ttf diff --git a/public/fonts/Hubot-Sans/TTF/HubotSansExpanded-Light.ttf b/packages/site/public/fonts/Hubot-Sans/TTF/HubotSansExpanded-Light.ttf similarity index 100% rename from public/fonts/Hubot-Sans/TTF/HubotSansExpanded-Light.ttf rename to packages/site/public/fonts/Hubot-Sans/TTF/HubotSansExpanded-Light.ttf diff --git a/public/fonts/Hubot-Sans/TTF/HubotSansExpanded-LightItalic.ttf b/packages/site/public/fonts/Hubot-Sans/TTF/HubotSansExpanded-LightItalic.ttf similarity index 100% rename from public/fonts/Hubot-Sans/TTF/HubotSansExpanded-LightItalic.ttf rename to packages/site/public/fonts/Hubot-Sans/TTF/HubotSansExpanded-LightItalic.ttf diff --git a/public/fonts/Hubot-Sans/TTF/HubotSansExpanded-Medium.ttf b/packages/site/public/fonts/Hubot-Sans/TTF/HubotSansExpanded-Medium.ttf similarity index 100% rename from public/fonts/Hubot-Sans/TTF/HubotSansExpanded-Medium.ttf rename to packages/site/public/fonts/Hubot-Sans/TTF/HubotSansExpanded-Medium.ttf diff --git a/public/fonts/Hubot-Sans/TTF/HubotSansExpanded-MediumItalic.ttf b/packages/site/public/fonts/Hubot-Sans/TTF/HubotSansExpanded-MediumItalic.ttf similarity index 100% rename from public/fonts/Hubot-Sans/TTF/HubotSansExpanded-MediumItalic.ttf rename to packages/site/public/fonts/Hubot-Sans/TTF/HubotSansExpanded-MediumItalic.ttf diff --git a/public/fonts/Hubot-Sans/TTF/HubotSansExpanded-Regular.ttf b/packages/site/public/fonts/Hubot-Sans/TTF/HubotSansExpanded-Regular.ttf similarity index 100% rename from public/fonts/Hubot-Sans/TTF/HubotSansExpanded-Regular.ttf rename to packages/site/public/fonts/Hubot-Sans/TTF/HubotSansExpanded-Regular.ttf diff --git a/public/fonts/Hubot-Sans/TTF/HubotSansExpanded-SemiBold.ttf b/packages/site/public/fonts/Hubot-Sans/TTF/HubotSansExpanded-SemiBold.ttf similarity index 100% rename from public/fonts/Hubot-Sans/TTF/HubotSansExpanded-SemiBold.ttf rename to packages/site/public/fonts/Hubot-Sans/TTF/HubotSansExpanded-SemiBold.ttf diff --git a/public/fonts/Hubot-Sans/TTF/HubotSansExpanded-SemiBoldItalic.ttf b/packages/site/public/fonts/Hubot-Sans/TTF/HubotSansExpanded-SemiBoldItalic.ttf similarity index 100% rename from public/fonts/Hubot-Sans/TTF/HubotSansExpanded-SemiBoldItalic.ttf rename to packages/site/public/fonts/Hubot-Sans/TTF/HubotSansExpanded-SemiBoldItalic.ttf diff --git a/public/fonts/Hubot-Sans/WOFF2/HubotSans-Black.woff2 b/packages/site/public/fonts/Hubot-Sans/WOFF2/HubotSans-Black.woff2 similarity index 100% rename from public/fonts/Hubot-Sans/WOFF2/HubotSans-Black.woff2 rename to packages/site/public/fonts/Hubot-Sans/WOFF2/HubotSans-Black.woff2 diff --git a/public/fonts/Hubot-Sans/WOFF2/HubotSans-BlackItalic.woff2 b/packages/site/public/fonts/Hubot-Sans/WOFF2/HubotSans-BlackItalic.woff2 similarity index 100% rename from public/fonts/Hubot-Sans/WOFF2/HubotSans-BlackItalic.woff2 rename to packages/site/public/fonts/Hubot-Sans/WOFF2/HubotSans-BlackItalic.woff2 diff --git a/public/fonts/Hubot-Sans/WOFF2/HubotSans-Bold.woff2 b/packages/site/public/fonts/Hubot-Sans/WOFF2/HubotSans-Bold.woff2 similarity index 100% rename from public/fonts/Hubot-Sans/WOFF2/HubotSans-Bold.woff2 rename to packages/site/public/fonts/Hubot-Sans/WOFF2/HubotSans-Bold.woff2 diff --git a/public/fonts/Hubot-Sans/WOFF2/HubotSans-BoldItalic.woff2 b/packages/site/public/fonts/Hubot-Sans/WOFF2/HubotSans-BoldItalic.woff2 similarity index 100% rename from public/fonts/Hubot-Sans/WOFF2/HubotSans-BoldItalic.woff2 rename to packages/site/public/fonts/Hubot-Sans/WOFF2/HubotSans-BoldItalic.woff2 diff --git a/public/fonts/Hubot-Sans/WOFF2/HubotSans-ExtraBold.woff2 b/packages/site/public/fonts/Hubot-Sans/WOFF2/HubotSans-ExtraBold.woff2 similarity index 100% rename from public/fonts/Hubot-Sans/WOFF2/HubotSans-ExtraBold.woff2 rename to packages/site/public/fonts/Hubot-Sans/WOFF2/HubotSans-ExtraBold.woff2 diff --git a/public/fonts/Hubot-Sans/WOFF2/HubotSans-ExtraBoldItalic.woff2 b/packages/site/public/fonts/Hubot-Sans/WOFF2/HubotSans-ExtraBoldItalic.woff2 similarity index 100% rename from public/fonts/Hubot-Sans/WOFF2/HubotSans-ExtraBoldItalic.woff2 rename to packages/site/public/fonts/Hubot-Sans/WOFF2/HubotSans-ExtraBoldItalic.woff2 diff --git a/public/fonts/Hubot-Sans/WOFF2/HubotSans-ExtraLight.woff2 b/packages/site/public/fonts/Hubot-Sans/WOFF2/HubotSans-ExtraLight.woff2 similarity index 100% rename from public/fonts/Hubot-Sans/WOFF2/HubotSans-ExtraLight.woff2 rename to packages/site/public/fonts/Hubot-Sans/WOFF2/HubotSans-ExtraLight.woff2 diff --git a/public/fonts/Hubot-Sans/WOFF2/HubotSans-ExtraLightItalic.woff2 b/packages/site/public/fonts/Hubot-Sans/WOFF2/HubotSans-ExtraLightItalic.woff2 similarity index 100% rename from public/fonts/Hubot-Sans/WOFF2/HubotSans-ExtraLightItalic.woff2 rename to packages/site/public/fonts/Hubot-Sans/WOFF2/HubotSans-ExtraLightItalic.woff2 diff --git a/public/fonts/Hubot-Sans/WOFF2/HubotSans-Italic.woff2 b/packages/site/public/fonts/Hubot-Sans/WOFF2/HubotSans-Italic.woff2 similarity index 100% rename from public/fonts/Hubot-Sans/WOFF2/HubotSans-Italic.woff2 rename to packages/site/public/fonts/Hubot-Sans/WOFF2/HubotSans-Italic.woff2 diff --git a/public/fonts/Hubot-Sans/WOFF2/HubotSans-Light.woff2 b/packages/site/public/fonts/Hubot-Sans/WOFF2/HubotSans-Light.woff2 similarity index 100% rename from public/fonts/Hubot-Sans/WOFF2/HubotSans-Light.woff2 rename to packages/site/public/fonts/Hubot-Sans/WOFF2/HubotSans-Light.woff2 diff --git a/public/fonts/Hubot-Sans/WOFF2/HubotSans-LightItalic.woff2 b/packages/site/public/fonts/Hubot-Sans/WOFF2/HubotSans-LightItalic.woff2 similarity index 100% rename from public/fonts/Hubot-Sans/WOFF2/HubotSans-LightItalic.woff2 rename to packages/site/public/fonts/Hubot-Sans/WOFF2/HubotSans-LightItalic.woff2 diff --git a/public/fonts/Hubot-Sans/WOFF2/HubotSans-Medium.woff2 b/packages/site/public/fonts/Hubot-Sans/WOFF2/HubotSans-Medium.woff2 similarity index 100% rename from public/fonts/Hubot-Sans/WOFF2/HubotSans-Medium.woff2 rename to packages/site/public/fonts/Hubot-Sans/WOFF2/HubotSans-Medium.woff2 diff --git a/public/fonts/Hubot-Sans/WOFF2/HubotSans-MediumItalic.woff2 b/packages/site/public/fonts/Hubot-Sans/WOFF2/HubotSans-MediumItalic.woff2 similarity index 100% rename from public/fonts/Hubot-Sans/WOFF2/HubotSans-MediumItalic.woff2 rename to packages/site/public/fonts/Hubot-Sans/WOFF2/HubotSans-MediumItalic.woff2 diff --git a/public/fonts/Hubot-Sans/WOFF2/HubotSans-Regular.woff2 b/packages/site/public/fonts/Hubot-Sans/WOFF2/HubotSans-Regular.woff2 similarity index 100% rename from public/fonts/Hubot-Sans/WOFF2/HubotSans-Regular.woff2 rename to packages/site/public/fonts/Hubot-Sans/WOFF2/HubotSans-Regular.woff2 diff --git a/public/fonts/Hubot-Sans/WOFF2/HubotSans-SemiBold.woff2 b/packages/site/public/fonts/Hubot-Sans/WOFF2/HubotSans-SemiBold.woff2 similarity index 100% rename from public/fonts/Hubot-Sans/WOFF2/HubotSans-SemiBold.woff2 rename to packages/site/public/fonts/Hubot-Sans/WOFF2/HubotSans-SemiBold.woff2 diff --git a/public/fonts/Hubot-Sans/WOFF2/HubotSans-SemiBoldItalic.woff2 b/packages/site/public/fonts/Hubot-Sans/WOFF2/HubotSans-SemiBoldItalic.woff2 similarity index 100% rename from public/fonts/Hubot-Sans/WOFF2/HubotSans-SemiBoldItalic.woff2 rename to packages/site/public/fonts/Hubot-Sans/WOFF2/HubotSans-SemiBoldItalic.woff2 diff --git a/public/fonts/Hubot-Sans/WOFF2/HubotSansCondensed-Black.woff2 b/packages/site/public/fonts/Hubot-Sans/WOFF2/HubotSansCondensed-Black.woff2 similarity index 100% rename from public/fonts/Hubot-Sans/WOFF2/HubotSansCondensed-Black.woff2 rename to packages/site/public/fonts/Hubot-Sans/WOFF2/HubotSansCondensed-Black.woff2 diff --git a/public/fonts/Hubot-Sans/WOFF2/HubotSansCondensed-BlackItalic.woff2 b/packages/site/public/fonts/Hubot-Sans/WOFF2/HubotSansCondensed-BlackItalic.woff2 similarity index 100% rename from public/fonts/Hubot-Sans/WOFF2/HubotSansCondensed-BlackItalic.woff2 rename to packages/site/public/fonts/Hubot-Sans/WOFF2/HubotSansCondensed-BlackItalic.woff2 diff --git a/public/fonts/Hubot-Sans/WOFF2/HubotSansCondensed-Bold.woff2 b/packages/site/public/fonts/Hubot-Sans/WOFF2/HubotSansCondensed-Bold.woff2 similarity index 100% rename from public/fonts/Hubot-Sans/WOFF2/HubotSansCondensed-Bold.woff2 rename to packages/site/public/fonts/Hubot-Sans/WOFF2/HubotSansCondensed-Bold.woff2 diff --git a/public/fonts/Hubot-Sans/WOFF2/HubotSansCondensed-BoldItalic.woff2 b/packages/site/public/fonts/Hubot-Sans/WOFF2/HubotSansCondensed-BoldItalic.woff2 similarity index 100% rename from public/fonts/Hubot-Sans/WOFF2/HubotSansCondensed-BoldItalic.woff2 rename to packages/site/public/fonts/Hubot-Sans/WOFF2/HubotSansCondensed-BoldItalic.woff2 diff --git a/public/fonts/Hubot-Sans/WOFF2/HubotSansCondensed-ExtraBold.woff2 b/packages/site/public/fonts/Hubot-Sans/WOFF2/HubotSansCondensed-ExtraBold.woff2 similarity index 100% rename from public/fonts/Hubot-Sans/WOFF2/HubotSansCondensed-ExtraBold.woff2 rename to packages/site/public/fonts/Hubot-Sans/WOFF2/HubotSansCondensed-ExtraBold.woff2 diff --git a/public/fonts/Hubot-Sans/WOFF2/HubotSansCondensed-ExtraBoldItalic.woff2 b/packages/site/public/fonts/Hubot-Sans/WOFF2/HubotSansCondensed-ExtraBoldItalic.woff2 similarity index 100% rename from public/fonts/Hubot-Sans/WOFF2/HubotSansCondensed-ExtraBoldItalic.woff2 rename to packages/site/public/fonts/Hubot-Sans/WOFF2/HubotSansCondensed-ExtraBoldItalic.woff2 diff --git a/public/fonts/Hubot-Sans/WOFF2/HubotSansCondensed-ExtraLight.woff2 b/packages/site/public/fonts/Hubot-Sans/WOFF2/HubotSansCondensed-ExtraLight.woff2 similarity index 100% rename from public/fonts/Hubot-Sans/WOFF2/HubotSansCondensed-ExtraLight.woff2 rename to packages/site/public/fonts/Hubot-Sans/WOFF2/HubotSansCondensed-ExtraLight.woff2 diff --git a/public/fonts/Hubot-Sans/WOFF2/HubotSansCondensed-ExtraLightItalic.woff2 b/packages/site/public/fonts/Hubot-Sans/WOFF2/HubotSansCondensed-ExtraLightItalic.woff2 similarity index 100% rename from public/fonts/Hubot-Sans/WOFF2/HubotSansCondensed-ExtraLightItalic.woff2 rename to packages/site/public/fonts/Hubot-Sans/WOFF2/HubotSansCondensed-ExtraLightItalic.woff2 diff --git a/public/fonts/Hubot-Sans/WOFF2/HubotSansCondensed-Italic.woff2 b/packages/site/public/fonts/Hubot-Sans/WOFF2/HubotSansCondensed-Italic.woff2 similarity index 100% rename from public/fonts/Hubot-Sans/WOFF2/HubotSansCondensed-Italic.woff2 rename to packages/site/public/fonts/Hubot-Sans/WOFF2/HubotSansCondensed-Italic.woff2 diff --git a/public/fonts/Hubot-Sans/WOFF2/HubotSansCondensed-Light.woff2 b/packages/site/public/fonts/Hubot-Sans/WOFF2/HubotSansCondensed-Light.woff2 similarity index 100% rename from public/fonts/Hubot-Sans/WOFF2/HubotSansCondensed-Light.woff2 rename to packages/site/public/fonts/Hubot-Sans/WOFF2/HubotSansCondensed-Light.woff2 diff --git a/public/fonts/Hubot-Sans/WOFF2/HubotSansCondensed-LightItalic.woff2 b/packages/site/public/fonts/Hubot-Sans/WOFF2/HubotSansCondensed-LightItalic.woff2 similarity index 100% rename from public/fonts/Hubot-Sans/WOFF2/HubotSansCondensed-LightItalic.woff2 rename to packages/site/public/fonts/Hubot-Sans/WOFF2/HubotSansCondensed-LightItalic.woff2 diff --git a/public/fonts/Hubot-Sans/WOFF2/HubotSansCondensed-Medium.woff2 b/packages/site/public/fonts/Hubot-Sans/WOFF2/HubotSansCondensed-Medium.woff2 similarity index 100% rename from public/fonts/Hubot-Sans/WOFF2/HubotSansCondensed-Medium.woff2 rename to packages/site/public/fonts/Hubot-Sans/WOFF2/HubotSansCondensed-Medium.woff2 diff --git a/public/fonts/Hubot-Sans/WOFF2/HubotSansCondensed-MediumItalic.woff2 b/packages/site/public/fonts/Hubot-Sans/WOFF2/HubotSansCondensed-MediumItalic.woff2 similarity index 100% rename from public/fonts/Hubot-Sans/WOFF2/HubotSansCondensed-MediumItalic.woff2 rename to packages/site/public/fonts/Hubot-Sans/WOFF2/HubotSansCondensed-MediumItalic.woff2 diff --git a/public/fonts/Hubot-Sans/WOFF2/HubotSansCondensed-Regular.woff2 b/packages/site/public/fonts/Hubot-Sans/WOFF2/HubotSansCondensed-Regular.woff2 similarity index 100% rename from public/fonts/Hubot-Sans/WOFF2/HubotSansCondensed-Regular.woff2 rename to packages/site/public/fonts/Hubot-Sans/WOFF2/HubotSansCondensed-Regular.woff2 diff --git a/public/fonts/Hubot-Sans/WOFF2/HubotSansCondensed-SemiBold.woff2 b/packages/site/public/fonts/Hubot-Sans/WOFF2/HubotSansCondensed-SemiBold.woff2 similarity index 100% rename from public/fonts/Hubot-Sans/WOFF2/HubotSansCondensed-SemiBold.woff2 rename to packages/site/public/fonts/Hubot-Sans/WOFF2/HubotSansCondensed-SemiBold.woff2 diff --git a/public/fonts/Hubot-Sans/WOFF2/HubotSansCondensed-SemiBoldItalic.woff2 b/packages/site/public/fonts/Hubot-Sans/WOFF2/HubotSansCondensed-SemiBoldItalic.woff2 similarity index 100% rename from public/fonts/Hubot-Sans/WOFF2/HubotSansCondensed-SemiBoldItalic.woff2 rename to packages/site/public/fonts/Hubot-Sans/WOFF2/HubotSansCondensed-SemiBoldItalic.woff2 diff --git a/public/fonts/Hubot-Sans/WOFF2/HubotSansExpanded-Black.woff2 b/packages/site/public/fonts/Hubot-Sans/WOFF2/HubotSansExpanded-Black.woff2 similarity index 100% rename from public/fonts/Hubot-Sans/WOFF2/HubotSansExpanded-Black.woff2 rename to packages/site/public/fonts/Hubot-Sans/WOFF2/HubotSansExpanded-Black.woff2 diff --git a/public/fonts/Hubot-Sans/WOFF2/HubotSansExpanded-BlackItalic.woff2 b/packages/site/public/fonts/Hubot-Sans/WOFF2/HubotSansExpanded-BlackItalic.woff2 similarity index 100% rename from public/fonts/Hubot-Sans/WOFF2/HubotSansExpanded-BlackItalic.woff2 rename to packages/site/public/fonts/Hubot-Sans/WOFF2/HubotSansExpanded-BlackItalic.woff2 diff --git a/public/fonts/Hubot-Sans/WOFF2/HubotSansExpanded-Bold.woff2 b/packages/site/public/fonts/Hubot-Sans/WOFF2/HubotSansExpanded-Bold.woff2 similarity index 100% rename from public/fonts/Hubot-Sans/WOFF2/HubotSansExpanded-Bold.woff2 rename to packages/site/public/fonts/Hubot-Sans/WOFF2/HubotSansExpanded-Bold.woff2 diff --git a/public/fonts/Hubot-Sans/WOFF2/HubotSansExpanded-BoldItalic.woff2 b/packages/site/public/fonts/Hubot-Sans/WOFF2/HubotSansExpanded-BoldItalic.woff2 similarity index 100% rename from public/fonts/Hubot-Sans/WOFF2/HubotSansExpanded-BoldItalic.woff2 rename to packages/site/public/fonts/Hubot-Sans/WOFF2/HubotSansExpanded-BoldItalic.woff2 diff --git a/public/fonts/Hubot-Sans/WOFF2/HubotSansExpanded-ExtraBold.woff2 b/packages/site/public/fonts/Hubot-Sans/WOFF2/HubotSansExpanded-ExtraBold.woff2 similarity index 100% rename from public/fonts/Hubot-Sans/WOFF2/HubotSansExpanded-ExtraBold.woff2 rename to packages/site/public/fonts/Hubot-Sans/WOFF2/HubotSansExpanded-ExtraBold.woff2 diff --git a/public/fonts/Hubot-Sans/WOFF2/HubotSansExpanded-ExtraBoldItalic.woff2 b/packages/site/public/fonts/Hubot-Sans/WOFF2/HubotSansExpanded-ExtraBoldItalic.woff2 similarity index 100% rename from public/fonts/Hubot-Sans/WOFF2/HubotSansExpanded-ExtraBoldItalic.woff2 rename to packages/site/public/fonts/Hubot-Sans/WOFF2/HubotSansExpanded-ExtraBoldItalic.woff2 diff --git a/public/fonts/Hubot-Sans/WOFF2/HubotSansExpanded-ExtraLight.woff2 b/packages/site/public/fonts/Hubot-Sans/WOFF2/HubotSansExpanded-ExtraLight.woff2 similarity index 100% rename from public/fonts/Hubot-Sans/WOFF2/HubotSansExpanded-ExtraLight.woff2 rename to packages/site/public/fonts/Hubot-Sans/WOFF2/HubotSansExpanded-ExtraLight.woff2 diff --git a/public/fonts/Hubot-Sans/WOFF2/HubotSansExpanded-ExtraLightItalic.woff2 b/packages/site/public/fonts/Hubot-Sans/WOFF2/HubotSansExpanded-ExtraLightItalic.woff2 similarity index 100% rename from public/fonts/Hubot-Sans/WOFF2/HubotSansExpanded-ExtraLightItalic.woff2 rename to packages/site/public/fonts/Hubot-Sans/WOFF2/HubotSansExpanded-ExtraLightItalic.woff2 diff --git a/public/fonts/Hubot-Sans/WOFF2/HubotSansExpanded-Italic.woff2 b/packages/site/public/fonts/Hubot-Sans/WOFF2/HubotSansExpanded-Italic.woff2 similarity index 100% rename from public/fonts/Hubot-Sans/WOFF2/HubotSansExpanded-Italic.woff2 rename to packages/site/public/fonts/Hubot-Sans/WOFF2/HubotSansExpanded-Italic.woff2 diff --git a/public/fonts/Hubot-Sans/WOFF2/HubotSansExpanded-Light.woff2 b/packages/site/public/fonts/Hubot-Sans/WOFF2/HubotSansExpanded-Light.woff2 similarity index 100% rename from public/fonts/Hubot-Sans/WOFF2/HubotSansExpanded-Light.woff2 rename to packages/site/public/fonts/Hubot-Sans/WOFF2/HubotSansExpanded-Light.woff2 diff --git a/public/fonts/Hubot-Sans/WOFF2/HubotSansExpanded-LightItalic.woff2 b/packages/site/public/fonts/Hubot-Sans/WOFF2/HubotSansExpanded-LightItalic.woff2 similarity index 100% rename from public/fonts/Hubot-Sans/WOFF2/HubotSansExpanded-LightItalic.woff2 rename to packages/site/public/fonts/Hubot-Sans/WOFF2/HubotSansExpanded-LightItalic.woff2 diff --git a/public/fonts/Hubot-Sans/WOFF2/HubotSansExpanded-Medium.woff2 b/packages/site/public/fonts/Hubot-Sans/WOFF2/HubotSansExpanded-Medium.woff2 similarity index 100% rename from public/fonts/Hubot-Sans/WOFF2/HubotSansExpanded-Medium.woff2 rename to packages/site/public/fonts/Hubot-Sans/WOFF2/HubotSansExpanded-Medium.woff2 diff --git a/public/fonts/Hubot-Sans/WOFF2/HubotSansExpanded-MediumItalic.woff2 b/packages/site/public/fonts/Hubot-Sans/WOFF2/HubotSansExpanded-MediumItalic.woff2 similarity index 100% rename from public/fonts/Hubot-Sans/WOFF2/HubotSansExpanded-MediumItalic.woff2 rename to packages/site/public/fonts/Hubot-Sans/WOFF2/HubotSansExpanded-MediumItalic.woff2 diff --git a/public/fonts/Hubot-Sans/WOFF2/HubotSansExpanded-Regular.woff2 b/packages/site/public/fonts/Hubot-Sans/WOFF2/HubotSansExpanded-Regular.woff2 similarity index 100% rename from public/fonts/Hubot-Sans/WOFF2/HubotSansExpanded-Regular.woff2 rename to packages/site/public/fonts/Hubot-Sans/WOFF2/HubotSansExpanded-Regular.woff2 diff --git a/public/fonts/Hubot-Sans/WOFF2/HubotSansExpanded-SemiBold.woff2 b/packages/site/public/fonts/Hubot-Sans/WOFF2/HubotSansExpanded-SemiBold.woff2 similarity index 100% rename from public/fonts/Hubot-Sans/WOFF2/HubotSansExpanded-SemiBold.woff2 rename to packages/site/public/fonts/Hubot-Sans/WOFF2/HubotSansExpanded-SemiBold.woff2 diff --git a/public/fonts/Hubot-Sans/WOFF2/HubotSansExpanded-SemiBoldItalic.woff2 b/packages/site/public/fonts/Hubot-Sans/WOFF2/HubotSansExpanded-SemiBoldItalic.woff2 similarity index 100% rename from public/fonts/Hubot-Sans/WOFF2/HubotSansExpanded-SemiBoldItalic.woff2 rename to packages/site/public/fonts/Hubot-Sans/WOFF2/HubotSansExpanded-SemiBoldItalic.woff2 diff --git a/public/fonts/Hubot-Sans/WOFF2/HubotSans[slnt,wdth,wght].woff2 b/packages/site/public/fonts/Hubot-Sans/WOFF2/HubotSans[slnt,wdth,wght].woff2 similarity index 100% rename from public/fonts/Hubot-Sans/WOFF2/HubotSans[slnt,wdth,wght].woff2 rename to packages/site/public/fonts/Hubot-Sans/WOFF2/HubotSans[slnt,wdth,wght].woff2 diff --git a/public/fonts/Inter-Black.ttf b/packages/site/public/fonts/Inter-Black.ttf similarity index 100% rename from public/fonts/Inter-Black.ttf rename to packages/site/public/fonts/Inter-Black.ttf diff --git a/public/fonts/Inter-Bold.ttf b/packages/site/public/fonts/Inter-Bold.ttf similarity index 100% rename from public/fonts/Inter-Bold.ttf rename to packages/site/public/fonts/Inter-Bold.ttf diff --git a/public/fonts/Inter-ExtraBold.ttf b/packages/site/public/fonts/Inter-ExtraBold.ttf similarity index 100% rename from public/fonts/Inter-ExtraBold.ttf rename to packages/site/public/fonts/Inter-ExtraBold.ttf diff --git a/public/fonts/Inter-ExtraLight.ttf b/packages/site/public/fonts/Inter-ExtraLight.ttf similarity index 100% rename from public/fonts/Inter-ExtraLight.ttf rename to packages/site/public/fonts/Inter-ExtraLight.ttf diff --git a/public/fonts/Inter-Light.ttf b/packages/site/public/fonts/Inter-Light.ttf similarity index 100% rename from public/fonts/Inter-Light.ttf rename to packages/site/public/fonts/Inter-Light.ttf diff --git a/public/fonts/Inter-Medium.ttf b/packages/site/public/fonts/Inter-Medium.ttf similarity index 100% rename from public/fonts/Inter-Medium.ttf rename to packages/site/public/fonts/Inter-Medium.ttf diff --git a/public/fonts/Inter-Regular.ttf b/packages/site/public/fonts/Inter-Regular.ttf similarity index 100% rename from public/fonts/Inter-Regular.ttf rename to packages/site/public/fonts/Inter-Regular.ttf diff --git a/public/fonts/Inter-SemiBold.ttf b/packages/site/public/fonts/Inter-SemiBold.ttf similarity index 100% rename from public/fonts/Inter-SemiBold.ttf rename to packages/site/public/fonts/Inter-SemiBold.ttf diff --git a/public/fonts/Inter-Thin.ttf b/packages/site/public/fonts/Inter-Thin.ttf similarity index 100% rename from public/fonts/Inter-Thin.ttf rename to packages/site/public/fonts/Inter-Thin.ttf diff --git a/public/fonts/Inter-VariableFont_slnt,wght.ttf b/packages/site/public/fonts/Inter-VariableFont_slnt,wght.ttf similarity index 100% rename from public/fonts/Inter-VariableFont_slnt,wght.ttf rename to packages/site/public/fonts/Inter-VariableFont_slnt,wght.ttf diff --git a/public/fonts/PTMono-Regular.ttf b/packages/site/public/fonts/PTMono-Regular.ttf similarity index 100% rename from public/fonts/PTMono-Regular.ttf rename to packages/site/public/fonts/PTMono-Regular.ttf diff --git a/public/manifest.json b/packages/site/public/manifest.json similarity index 100% rename from public/manifest.json rename to packages/site/public/manifest.json diff --git a/public/resources/openapi-spec.yml b/packages/site/public/resources/openapi-spec.yml similarity index 100% rename from public/resources/openapi-spec.yml rename to packages/site/public/resources/openapi-spec.yml diff --git a/public/robots.txt b/packages/site/public/robots.txt similarity index 100% rename from public/robots.txt rename to packages/site/public/robots.txt diff --git a/public/security.txt b/packages/site/public/security.txt similarity index 100% rename from public/security.txt rename to packages/site/public/security.txt diff --git a/public/web-check.png b/packages/site/public/web-check.png similarity index 100% rename from public/web-check.png rename to packages/site/public/web-check.png diff --git a/src/components/homepage/AboutSection.astro b/packages/site/src/components/homepage/AboutSection.astro similarity index 100% rename from src/components/homepage/AboutSection.astro rename to packages/site/src/components/homepage/AboutSection.astro diff --git a/src/components/homepage/AnimatedButton.astro b/packages/site/src/components/homepage/AnimatedButton.astro similarity index 100% rename from src/components/homepage/AnimatedButton.astro rename to packages/site/src/components/homepage/AnimatedButton.astro diff --git a/src/components/homepage/AnimatedInput.astro b/packages/site/src/components/homepage/AnimatedInput.astro similarity index 100% rename from src/components/homepage/AnimatedInput.astro rename to packages/site/src/components/homepage/AnimatedInput.astro diff --git a/src/components/homepage/ButtonGroup.astro b/packages/site/src/components/homepage/ButtonGroup.astro similarity index 100% rename from src/components/homepage/ButtonGroup.astro rename to packages/site/src/components/homepage/ButtonGroup.astro diff --git a/src/components/homepage/Features.astro b/packages/site/src/components/homepage/Features.astro similarity index 100% rename from src/components/homepage/Features.astro rename to packages/site/src/components/homepage/Features.astro diff --git a/src/components/homepage/HeroForm.astro b/packages/site/src/components/homepage/HeroForm.astro similarity index 100% rename from src/components/homepage/HeroForm.astro rename to packages/site/src/components/homepage/HeroForm.astro diff --git a/src/components/homepage/HomeBackground.tsx b/packages/site/src/components/homepage/HomeBackground.tsx similarity index 100% rename from src/components/homepage/HomeBackground.tsx rename to packages/site/src/components/homepage/HomeBackground.tsx diff --git a/src/components/homepage/Screenshots.astro b/packages/site/src/components/homepage/Screenshots.astro similarity index 100% rename from src/components/homepage/Screenshots.astro rename to packages/site/src/components/homepage/Screenshots.astro diff --git a/src/components/homepage/SponsorSegment.astro b/packages/site/src/components/homepage/SponsorSegment.astro similarity index 100% rename from src/components/homepage/SponsorSegment.astro rename to packages/site/src/components/homepage/SponsorSegment.astro diff --git a/src/components/homepage/TempDisabled.astro b/packages/site/src/components/homepage/TempDisabled.astro similarity index 100% rename from src/components/homepage/TempDisabled.astro rename to packages/site/src/components/homepage/TempDisabled.astro diff --git a/src/components/molecules/Icon.svelte b/packages/site/src/components/molecules/Icon.svelte similarity index 100% rename from src/components/molecules/Icon.svelte rename to packages/site/src/components/molecules/Icon.svelte diff --git a/src/components/scafold/Footer.astro b/packages/site/src/components/scafold/Footer.astro similarity index 100% rename from src/components/scafold/Footer.astro rename to packages/site/src/components/scafold/Footer.astro diff --git a/src/components/scafold/Nav.astro b/packages/site/src/components/scafold/Nav.astro similarity index 100% rename from src/components/scafold/Nav.astro rename to packages/site/src/components/scafold/Nav.astro diff --git a/src/env.d.ts b/packages/site/src/env.d.ts similarity index 100% rename from src/env.d.ts rename to packages/site/src/env.d.ts diff --git a/src/layouts/Base.astro b/packages/site/src/layouts/Base.astro similarity index 100% rename from src/layouts/Base.astro rename to packages/site/src/layouts/Base.astro diff --git a/src/layouts/MetaTags.astro b/packages/site/src/layouts/MetaTags.astro similarity index 100% rename from src/layouts/MetaTags.astro rename to packages/site/src/layouts/MetaTags.astro diff --git a/src/pages/account/index.astro b/packages/site/src/pages/account/index.astro similarity index 100% rename from src/pages/account/index.astro rename to packages/site/src/pages/account/index.astro diff --git a/packages/site/src/pages/check/index.astro b/packages/site/src/pages/check/index.astro new file mode 100644 index 000000000..760297b63 --- /dev/null +++ b/packages/site/src/pages/check/index.astro @@ -0,0 +1,28 @@ +--- +import BaseLayout from '@layouts/Base.astro'; +import Main from '@web-check/app/main'; +import '@web-check/app/styles/index.css'; +--- + + +
+ + + diff --git a/src/pages/index.astro b/packages/site/src/pages/index.astro similarity index 87% rename from src/pages/index.astro rename to packages/site/src/pages/index.astro index f5e27d4c8..508047722 100644 --- a/src/pages/index.astro +++ b/packages/site/src/pages/index.astro @@ -6,15 +6,10 @@ import HomeBackground from '@/components/homepage/HomeBackground'; import AboutSection from '@/components/homepage/AboutSection.astro'; import Footer from '@components/scafold/Footer.astro'; -const isBossServer = import.meta.env.BOSS_SERVER === 'true'; - const disableEverything = import.meta.env.VITE_DISABLE_EVERYTHING === true; --- - - {!isBossServer && } - {disableEverything && }
diff --git a/src/pages/self-hosted-setup.astro b/packages/site/src/pages/self-hosted-setup.astro similarity index 100% rename from src/pages/self-hosted-setup.astro rename to packages/site/src/pages/self-hosted-setup.astro diff --git a/src/pages/web-check-api/index.astro b/packages/site/src/pages/web-check-api/index.astro similarity index 100% rename from src/pages/web-check-api/index.astro rename to packages/site/src/pages/web-check-api/index.astro diff --git a/src/pages/web-check-api/spec.astro b/packages/site/src/pages/web-check-api/spec.astro similarity index 100% rename from src/pages/web-check-api/spec.astro rename to packages/site/src/pages/web-check-api/spec.astro diff --git a/src/styles/colors.scss b/packages/site/src/styles/colors.scss similarity index 100% rename from src/styles/colors.scss rename to packages/site/src/styles/colors.scss diff --git a/src/styles/global.scss b/packages/site/src/styles/global.scss similarity index 100% rename from src/styles/global.scss rename to packages/site/src/styles/global.scss diff --git a/src/styles/media-queries.scss b/packages/site/src/styles/media-queries.scss similarity index 100% rename from src/styles/media-queries.scss rename to packages/site/src/styles/media-queries.scss diff --git a/src/styles/typography.scss b/packages/site/src/styles/typography.scss similarity index 100% rename from src/styles/typography.scss rename to packages/site/src/styles/typography.scss diff --git a/svelte.config.js b/packages/site/svelte.config.js similarity index 100% rename from svelte.config.js rename to packages/site/svelte.config.js diff --git a/tsconfig.json b/packages/site/tsconfig.json similarity index 81% rename from tsconfig.json rename to packages/site/tsconfig.json index bd8d9d624..755de5688 100644 --- a/tsconfig.json +++ b/packages/site/tsconfig.json @@ -2,13 +2,9 @@ "compilerOptions": { "target": "ES2020", "module": "ES2020", - "moduleResolution": "node", + "moduleResolution": "bundler", "allowImportingTsExtensions": true, - "plugins": [ - { - "name": "@astrojs/ts-plugin" - } - ], + "plugins": [{ "name": "@astrojs/ts-plugin" }], "lib": ["DOM", "DOM.Iterable", "ES2020"], "allowJs": true, "skipLibCheck": true, @@ -29,7 +25,8 @@ "@layouts/*": ["layouts/*"], "@pages/*": ["pages/*"], "@styles/*": ["styles/*"], - "@assets/*": ["assets/*"] + "@assets/*": ["assets/*"], + "web-check-live/*": ["../../app/src/*"] } }, "include": ["src"] diff --git a/scripts/sync-vercel-api.js b/scripts/sync-vercel-api.js new file mode 100644 index 000000000..bc20b1910 --- /dev/null +++ b/scripts/sync-vercel-api.js @@ -0,0 +1,60 @@ +import fs from 'node:fs'; +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; + +// Vercel only discovers serverless functions in /api at the project root, so we +// emit thin re-export wrappers from the canonical handlers in packages/api +const __dirname = path.dirname(fileURLToPath(import.meta.url)); +const HANDLERS_DIR = path.resolve(__dirname, '../packages/api/handlers'); +const OUT_DIR = path.resolve(__dirname, '../api'); +const HEADER = + '// Generated by scripts/sync-vercel-api.js, do not edit by hand\n' + + '// Source of truth lives in packages/api/handlers\n'; + +const readIfExists = (file) => { + try { + return fs.readFileSync(file, 'utf-8'); + } catch { + return null; + } +}; + +const sync = () => { + fs.mkdirSync(OUT_DIR, { recursive: true }); + + const sources = fs + .readdirSync(HANDLERS_DIR, { withFileTypes: true }) + .filter((e) => e.isFile() && e.name.endsWith('.js')) + .map((e) => e.name); + + let written = 0; + for (const name of sources) { + const out = path.join(OUT_DIR, name); + const target = path.join(HANDLERS_DIR, name); + const rel = path.relative(OUT_DIR, target).split(path.sep).join('/'); + const body = `${HEADER}export { default, handler } from '${rel}';\n`; + if (readIfExists(out) !== body) { + fs.writeFileSync(out, body); + written += 1; + } + } + + let removed = 0; + const existing = fs + .readdirSync(OUT_DIR, { withFileTypes: true }) + .filter((e) => e.isFile() && e.name.endsWith('.js')) + .map((e) => e.name); + + for (const name of existing) { + if (!sources.includes(name)) { + fs.unlinkSync(path.join(OUT_DIR, name)); + removed += 1; + } + } + + process.stdout.write( + `Vercel api wrappers: ${sources.length} total, ` + `${written} written, ${removed} removed\n`, + ); +}; + +sync(); diff --git a/server.js b/server.js deleted file mode 100644 index 49f33328a..000000000 --- a/server.js +++ /dev/null @@ -1,226 +0,0 @@ -import fs from 'fs'; -import path from 'path'; -import cors from 'cors'; -import dotenv from 'dotenv'; -import express from 'express'; -import rateLimit from 'express-rate-limit'; - -// Load environment variables from .env file -dotenv.config(); - -// Create the Express app -const app = express(); - -const trustProxy = process.env.TRUST_PROXY; -if (trustProxy) { - const parsed = /^\d+$/.test(trustProxy) - ? parseInt(trustProxy, 10) - : trustProxy === 'true' - ? true - : trustProxy === 'false' - ? false - : trustProxy; - app.set('trust proxy', parsed); -} - -const __filename = new URL(import.meta.url).pathname; -const __dirname = path.dirname(__filename); - -const port = process.env.PORT || 3000; // The port to run the server on -const API_DIR = '/api'; // Name of the dir containing the lambda functions -const dirPath = path.join(__dirname, API_DIR); // Path to the lambda functions dir -const guiPath = path.join(__dirname, 'dist', 'client'); -const placeholderFilePath = path.join(__dirname, 'public', 'placeholder.html'); -const handlers = {}; // Will store list of API endpoints -process.env.WC_SERVER = 'true'; // Tells middleware to return in non-lambda mode - -// Enable CORS -app.use( - cors({ - origin: process.env.API_CORS_ORIGIN || '*', - }), -); - -// Define max requests within each time frame -const limits = [ - { timeFrame: 10 * 60, max: 100, messageTime: '10 minutes' }, - { timeFrame: 60 * 60, max: 250, messageTime: '1 hour' }, - { timeFrame: 12 * 60 * 60, max: 500, messageTime: '12 hours' }, -]; - -// Construct a message to be returned if the user has been rate-limited -const makeLimiterResponseMsg = (retryAfter) => { - const why = - 'This keeps the service running smoothly for everyone. ' + - 'You can get around these limits by running your own instance of Web Check.'; - return `You've been rate-limited, please try again in ${retryAfter} seconds.\n${why}`; -}; - -// Create rate limiters for each time frame -const limiters = limits.map((limit) => - rateLimit({ - windowMs: limit.timeFrame * 1000, - limit: limit.max, - standardHeaders: true, - legacyHeaders: false, - message: { error: makeLimiterResponseMsg(limit.messageTime) }, - }), -); - -// If rate-limiting enabled, then apply the limiters to the /api endpoint -if (process.env.API_ENABLE_RATE_LIMIT === 'true') { - app.use(API_DIR, limiters); -} - -// Read and register each API function as an Express routes -fs.readdirSync(dirPath, { withFileTypes: true }) - .filter((dirent) => dirent.isFile() && dirent.name.endsWith('.js')) - .forEach(async (dirent) => { - const routeName = dirent.name.split('.')[0]; - const route = `${API_DIR}/${routeName}`; - // const handler = require(path.join(dirPath, dirent.name)); - - const handlerModule = await import(path.join(dirPath, dirent.name)); - const handler = handlerModule.default || handlerModule; - handlers[route] = handler; - - app.get(route, async (req, res) => { - try { - await handler(req, res); - } catch (err) { - res.status(500).json({ error: err.message }); - } - }); - }); - -const renderPlaceholderPage = async (res, msgId, logs) => { - const errorMessages = { - notCompiled: - 'Looks like the GUI app has not yet been compiled.
' + - 'Run yarn build to continue, then restart the server.', - notCompiledSsrHandler: - 'Server-side rendering failed to initiate, as SSR handler not found.
' + - 'This can be fixed by running yarn build, then restarting the server.
', - disabledGui: - 'Web-Check API is up and running!
Access the endpoints at ' + - `${API_DIR}`, - }; - const logOutput = logs ? `
${logs}
` : ''; - const errorMessage = (errorMessages[msgId] || 'An mystery error occurred.') + logOutput; - const placeholderContent = await fs.promises.readFile(placeholderFilePath, 'utf-8'); - const htmlContent = placeholderContent.replace('', errorMessage); - res.status(500).send(htmlContent); -}; - -// Create a single API endpoint to execute all lambda functions -app.get(API_DIR, async (req, res) => { - const results = {}; - const { url } = req.query; - const maxExecutionTime = process.env.PUBLIC_API_TIMEOUT_LIMIT || 60000; - - const executeHandler = async (handler, req) => { - return new Promise(async (resolve, reject) => { - try { - const mockRes = { - status: () => mockRes, - json: (body) => resolve({ body }), - }; - await handler({ ...req, query: { url } }, mockRes); - } catch (err) { - reject(err); - } - }); - }; - - const timeout = (ms, jobName = null) => { - return new Promise((_, reject) => { - setTimeout(() => { - reject( - new Error( - `Timed out after ${ms / 1000} seconds${jobName ? `, when executing ${jobName}` : ''}`, - ), - ); - }, ms); - }); - }; - - const handlerPromises = Object.entries(handlers).map(async ([route, handler]) => { - const routeName = route.replace(`${API_DIR}/`, ''); - - try { - const result = await Promise.race([ - executeHandler(handler, req, res), - timeout(maxExecutionTime, routeName), - ]); - results[routeName] = result.body; - } catch (err) { - results[routeName] = { error: err.message }; - } - }); - - await Promise.all(handlerPromises); - res.json(results); -}); - -// Skip the marketing homepage, for self-hosted users -app.use((req, res, next) => { - if (req.path === '/' && process.env.BOSS_SERVER !== 'true' && !process.env.DISABLE_GUI) { - return res.redirect(302, '/check'); - } - next(); -}); - -// Serve up the GUI - if build dir exists, and GUI feature enabled -if (process.env.DISABLE_GUI && process.env.DISABLE_GUI !== 'false') { - app.get('/', async (req, res) => { - renderPlaceholderPage(res, 'disabledGui'); - }); -} else if (!fs.existsSync(guiPath)) { - app.get('/', async (req, res) => { - renderPlaceholderPage(res, 'notCompiled'); - }); -} else { - // GUI enabled, and build files present, let's go!! - app.use(express.static('dist/client/')); - app.use(async (req, res, next) => { - const ssrHandlerPath = path.join(__dirname, 'dist', 'server', 'entry.mjs'); - import(ssrHandlerPath) - .then(({ handler: ssrHandler }) => { - ssrHandler(req, res, next); - }) - .catch(async (err) => { - renderPlaceholderPage(res, 'notCompiledSsrHandler', err.message); - }); - }); -} - -// Anything left unhandled (which isn't an API endpoint), return a 404 -app.use((req, res, next) => { - if (!req.path.startsWith(`${API_DIR}/`)) { - res.status(404).sendFile(path.join(__dirname, 'public', 'error.html')); - } else { - next(); - } -}); - -// Print nice welcome message to user -const printMessage = () => { - console.log( - `\x1b[36m\n` + - ' __ __ _ ___ _ _ \n' + - ' \\ \\ / /__| |__ ___ / __| |_ ___ __| |__\n' + - " \\ \\/\\/ / -_) '_ \\___| (__| ' \\/ -_) _| / /\n" + - ' \\_/\\_/\\___|_.__/ \\___|_||_\\___\\__|_\\_\\\n' + - `\x1b[0m\n`, - `\x1b[1m\x1b[32m🚀 Web-Check is up and running at http://localhost:${port} \x1b[0m\n\n`, - `\x1b[2m\x1b[36m🛟 For documentation and support, visit the GitHub repo: ` + - `https://github.com/lissy93/web-check \n`, - `💖 Found Web-Check useful? Consider sponsoring us on GitHub ` + - `to help fund maintenance & development.\x1b[0m`, - ); -}; - -// Create server -app.listen(port, () => { - printMessage(); -}); diff --git a/src/pages/check/[...target].astro b/src/pages/check/[...target].astro deleted file mode 100644 index b69e2f4b0..000000000 --- a/src/pages/check/[...target].astro +++ /dev/null @@ -1,40 +0,0 @@ ---- -import BaseLayout from '@layouts/Base.astro'; -import Main from '../../web-check-live/main.tsx'; -import '../../web-check-live/styles/index.css'; - -export const prerender = false; - -const { search } = new URL(Astro.request.url); - -const searchUrl = new URLSearchParams(search).get('url'); - -if (searchUrl) { - Astro.redirect(`/check/${encodeURIComponent(searchUrl)}`); -} ---- - - -
- - - diff --git a/vercel.json b/vercel.json index 22d403e59..595989fcf 100644 --- a/vercel.json +++ b/vercel.json @@ -1,15 +1,13 @@ { "version": 2, - "routes": [ - { - "src": "/api/(.*)", - "dest": "/api/$1.js" - } + "buildCommand": "yarn build", + "outputDirectory": "packages/site/dist", + "rewrites": [ + { "source": "/check", "destination": "/check/index.html" }, + { "source": "/check/:path*", "destination": "/check/index.html" } ], "functions": { - "api/*.js": { - "maxDuration": 20 - } + "api/*.js": { "maxDuration": 20 } }, "env": { "PLATFORM": "vercel", @@ -17,8 +15,6 @@ "CHROME_PATH": "/usr/bin/chromium" }, "build": { - "env": { - "PLATFORM": "vercel" - } + "env": { "PLATFORM": "vercel" } } } diff --git a/vite.config.js b/vite.config.js deleted file mode 100644 index 73acc9227..000000000 --- a/vite.config.js +++ /dev/null @@ -1,14 +0,0 @@ -// vite.config.js -import { defineConfig } from 'vite'; -import react from '@vitejs/plugin-react'; - -export default defineConfig({ - plugins: [ - react({ - jsxImportSource: '@emotion/react', - babel: { - plugins: ['babel-plugin-styled-components'], - }, - }), - ], -}); diff --git a/yarn.lock b/yarn.lock index 8d57936c9..c7db7dc45 100644 --- a/yarn.lock +++ b/yarn.lock @@ -12,18 +12,6 @@ kleur "^4.1.5" yargs "^17.7.2" -"@astrojs/cloudflare@^13.3.1": - version "13.3.1" - resolved "https://registry.npmjs.org/@astrojs/cloudflare/-/cloudflare-13.3.1.tgz" - integrity sha512-I2HcdP1KVppLMd0lXARI+/MKXbvrZdTvkLLKSBNtj5zhRhnDhugnyewjGKN0Ap5+khktD+rime7BgjfUlJ9iZw== - dependencies: - "@astrojs/internal-helpers" "0.9.0" - "@astrojs/underscore-redirects" "1.0.3" - "@cloudflare/vite-plugin" "^1.32.3" - piccolore "^0.1.3" - tinyglobby "^0.2.15" - vite "^7.3.2" - "@astrojs/compiler@^2.0.0 || ^3.0.0", "@astrojs/compiler@^2.13.1", "@astrojs/compiler@^2.9.1": version "2.13.1" resolved "https://registry.npmjs.org/@astrojs/compiler/-/compiler-2.13.1.tgz" @@ -92,30 +80,6 @@ unist-util-visit-parents "^6.0.2" vfile "^6.0.3" -"@astrojs/netlify@^7.0.8": - version "7.0.8" - resolved "https://registry.npmjs.org/@astrojs/netlify/-/netlify-7.0.8.tgz" - integrity sha512-wOkOMoiUePWrGGOEvaXAC8PzUUYIWB16oChOzH/Ziy9teMkgc56TifNW9SiIussylMJQNjhC+AJYoWUHkKiiuQ== - dependencies: - "@astrojs/internal-helpers" "0.9.0" - "@astrojs/underscore-redirects" "1.0.3" - "@netlify/blobs" "^10.7.0" - "@netlify/functions" "^5.1.2" - "@netlify/vite-plugin" "^2.10.3" - "@vercel/nft" "^1.3.2" - esbuild "^0.27.3" - tinyglobby "^0.2.15" - vite "^7.3.2" - -"@astrojs/node@^10.0.6": - version "10.0.6" - resolved "https://registry.npmjs.org/@astrojs/node/-/node-10.0.6.tgz" - integrity sha512-e8JmaP4sGxqvdei14kmBzhAqgd5/L5MTExW3Hks5DOt9LDvGzlsFZwnXVXzWPVjW/PErl7t9uLg7xWhCqfkSrA== - dependencies: - "@astrojs/internal-helpers" "0.9.0" - send "^1.2.1" - server-destroy "^1.0.1" - "@astrojs/partytown@^2.1.7": version "2.1.7" resolved "https://registry.npmjs.org/@astrojs/partytown/-/partytown-2.1.7.tgz" @@ -186,24 +150,6 @@ semver "^7.7.4" vscode-languageserver-textdocument "^1.0.12" -"@astrojs/underscore-redirects@1.0.3": - version "1.0.3" - resolved "https://registry.npmjs.org/@astrojs/underscore-redirects/-/underscore-redirects-1.0.3.tgz" - integrity sha512-cxnGSw+sJigBLdX4TMSZKkzV6C3gMLJMucDk2W+n281Xhie68T2/9f1+1NMNDCZsc5i0FED7Qt5I10g2O9wtZg== - -"@astrojs/vercel@^10.0.6": - version "10.0.6" - resolved "https://registry.npmjs.org/@astrojs/vercel/-/vercel-10.0.6.tgz" - integrity sha512-Ubd1M77QWqXXluFNL8/ynmfyZCfIUVuL6QRpPXGYOIQ8Dv3QBXM34e0CMig3OgmihSIWNv9sqQHzEHDyDJV9QQ== - dependencies: - "@astrojs/internal-helpers" "0.9.0" - "@vercel/analytics" "^1.6.1" - "@vercel/functions" "^3.4.3" - "@vercel/nft" "^1.3.2" - "@vercel/routing-utils" "^5.3.3" - esbuild "^0.27.3" - tinyglobby "^0.2.15" - "@astrojs/yaml2ts@^0.2.3": version "0.2.3" resolved "https://registry.npmjs.org/@astrojs/yaml2ts/-/yaml2ts-0.2.3.tgz" @@ -211,7 +157,7 @@ dependencies: yaml "^2.8.2" -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.16.0", "@babel/code-frame@^7.26.2", "@babel/code-frame@^7.28.6", "@babel/code-frame@^7.29.0": +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.28.6", "@babel/code-frame@^7.29.0": version "7.29.0" resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz" integrity sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw== @@ -318,7 +264,7 @@ "@babel/template" "^7.28.6" "@babel/types" "^7.29.0" -"@babel/parser@^7.1.0", "@babel/parser@^7.20.7", "@babel/parser@^7.22.5", "@babel/parser@^7.28.6", "@babel/parser@^7.29.0", "@babel/parser@^7.29.2": +"@babel/parser@^7.1.0", "@babel/parser@^7.20.7", "@babel/parser@^7.28.6", "@babel/parser@^7.29.0": version "7.29.3" resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.29.3.tgz" integrity sha512-b3ctpQwp+PROvU/cttc4OYl4MzfJUWy6FZg+PMXfzmt/+39iHVF0sDfqay8TQM3JA2EUOyKcFZt75jWriQijsA== @@ -366,7 +312,7 @@ "@babel/types" "^7.29.0" debug "^4.3.1" -"@babel/types@^7.0.0", "@babel/types@^7.20.7", "@babel/types@^7.28.2", "@babel/types@^7.28.5", "@babel/types@^7.28.6", "@babel/types@^7.29.0": +"@babel/types@^7.0.0", "@babel/types@^7.20.7", "@babel/types@^7.28.2", "@babel/types@^7.28.6", "@babel/types@^7.29.0": version "7.29.0" resolved "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz" integrity sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A== @@ -399,86 +345,6 @@ fast-wrap-ansi "^0.2.0" sisteransi "^1.0.5" -"@cloudflare/kv-asset-handler@0.5.0": - version "0.5.0" - resolved "https://registry.npmjs.org/@cloudflare/kv-asset-handler/-/kv-asset-handler-0.5.0.tgz" - integrity sha512-jxQYkj8dSIzc0cD6cMMNdOc1UVjqSqu8BZdor5s8cGjW2I8BjODt/kWPVdY+u9zj3ms75Q5qaZgnxUad83+eAg== - -"@cloudflare/unenv-preset@2.16.1": - version "2.16.1" - resolved "https://registry.npmjs.org/@cloudflare/unenv-preset/-/unenv-preset-2.16.1.tgz" - integrity sha512-ECxObrMfyTl5bhQf/lZCXwo5G6xX9IAUo+nDMKK4SZ8m4Jvvxp52vilxyySSWh2YTZz8+HQ07qGH/2rEom1vDw== - -"@cloudflare/vite-plugin@^1.32.3": - version "1.35.0" - resolved "https://registry.npmjs.org/@cloudflare/vite-plugin/-/vite-plugin-1.35.0.tgz" - integrity sha512-TtyBYqeIcRrbEAShwnNOyaMHA8SnwIFQ5h9OtMF3mr0xEF9XHqnICkZqMLGOFSP9INrjtJKUBIDlWbK+fjSBmA== - dependencies: - "@cloudflare/unenv-preset" "2.16.1" - miniflare "4.20260430.0" - unenv "2.0.0-rc.24" - wrangler "4.87.0" - ws "8.18.0" - -"@cloudflare/workerd-darwin-64@1.20260430.1": - version "1.20260430.1" - resolved "https://registry.yarnpkg.com/@cloudflare/workerd-darwin-64/-/workerd-darwin-64-1.20260430.1.tgz#1dbf994e7a02d5014254e237fb28157309401a5e" - integrity sha512-ADohZUHf7NBvPp2PdZig2Opxx+hDkk3ve7jrTne3JRx9kDSB73zc4LzcEeEN8LKkbAcqZmvfRJfpChSlusu0lA== - -"@cloudflare/workerd-darwin-arm64@1.20260430.1": - version "1.20260430.1" - resolved "https://registry.yarnpkg.com/@cloudflare/workerd-darwin-arm64/-/workerd-darwin-arm64-1.20260430.1.tgz#6e9953dfa763eb946f65fdfb77597668a6f21077" - integrity sha512-/DoYC/1wHs+YRZzzqSQg1/EHB4hiv1yV5U8FnmapRRIzVaPtnt+ApeOXeMrIdKidgKOI8TqQzgBU8xbIM7Cl4Q== - -"@cloudflare/workerd-linux-64@1.20260430.1": - version "1.20260430.1" - resolved "https://registry.npmjs.org/@cloudflare/workerd-linux-64/-/workerd-linux-64-1.20260430.1.tgz" - integrity sha512-koJhBWvEVZPKCVFtMLp2iMHlYr+lFCF47wGbnlKdHVlemV0zTxJEyHI8aLlrhPLhBmOmYLp46rXw09/qJkRIhQ== - -"@cloudflare/workerd-linux-arm64@1.20260430.1": - version "1.20260430.1" - resolved "https://registry.yarnpkg.com/@cloudflare/workerd-linux-arm64/-/workerd-linux-arm64-1.20260430.1.tgz#05940bc745d4c70eccb8341ef9bd30e72faa1d93" - integrity sha512-hMdapNAzNQZDXGGkg4Slydc3fRJP5FUZLJVVcZCW/+imhhJro9Z1rv5n/wfR+txKoSWhTYR8eOp8Pyi2bzLzlw== - -"@cloudflare/workerd-windows-64@1.20260430.1": - version "1.20260430.1" - resolved "https://registry.yarnpkg.com/@cloudflare/workerd-windows-64/-/workerd-windows-64-1.20260430.1.tgz#5240fb60d9f2879d70e1a106fbcea2a3f9295efe" - integrity sha512-jS3ffixjb5USOwz4frw4WzCz0HrjVxkgyU3WiYb06N7hBAfN6eOrveAJ4QRef0+suK4V1vQFoB1oKdRBsXe9Dw== - -"@colors/colors@1.6.0", "@colors/colors@^1.6.0": - version "1.6.0" - resolved "https://registry.npmjs.org/@colors/colors/-/colors-1.6.0.tgz" - integrity sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA== - -"@cspotcode/source-map-support@0.8.1": - version "0.8.1" - resolved "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz" - integrity sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw== - dependencies: - "@jridgewell/trace-mapping" "0.3.9" - -"@dabh/diagnostics@^2.0.8": - version "2.0.8" - resolved "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.8.tgz" - integrity sha512-R4MSXTVnuMzGD7bzHdW2ZhhdPC/igELENcq5IjEverBvq5hn1SXCWcsi6eSsdWP0/Ur+SItRRjAktmdoX/8R/Q== - dependencies: - "@so-ric/colorspace" "^1.1.6" - enabled "2.0.x" - kuler "^2.0.0" - -"@dependents/detective-less@^5.0.1": - version "5.0.3" - resolved "https://registry.npmjs.org/@dependents/detective-less/-/detective-less-5.0.3.tgz" - integrity sha512-v6oD9Ukp+N7V4n6p5I/+mM5fIohSfkrDSGlFm5w/pYmchvbk+sMIHsLxrFJ5Lnujewj1BzWL0K84d88lwZAMQA== - dependencies: - gonzales-pe "^4.3.0" - node-source-walk "^7.0.1" - -"@electric-sql/pglite@^0.3.15": - version "0.3.16" - resolved "https://registry.npmjs.org/@electric-sql/pglite/-/pglite-0.3.16.tgz" - integrity sha512-mZkZfOd9OqTMHsK+1cje8OSzfAQcpD7JmILXTl5ahdempjUDdmg4euf1biDex5/LfQIDJ3gvCu6qDgdnDxfJmA== - "@emmetio/abbreviation@^2.3.3": version "2.3.3" resolved "https://registry.npmjs.org/@emmetio/abbreviation/-/abbreviation-2.3.3.tgz" @@ -637,269 +503,131 @@ resolved "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.4.0.tgz" integrity sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg== -"@envelop/instrumentation@^1.0.0": - version "1.0.0" - resolved "https://registry.npmjs.org/@envelop/instrumentation/-/instrumentation-1.0.0.tgz" - integrity sha512-cxgkB66RQB95H3X27jlnxCRNTmPuSTgmBAq6/4n2Dtv4hsk4yz8FadA1ggmd0uZzvKqWD6CR+WFgTjhDqg7eyw== - dependencies: - "@whatwg-node/promise-helpers" "^1.2.1" - tslib "^2.5.0" - -"@esbuild/aix-ppc64@0.27.3": - version "0.27.3" - resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.27.3.tgz#815b39267f9bffd3407ea6c376ac32946e24f8d2" - integrity sha512-9fJMTNFTWZMh5qwrBItuziu834eOCUcEqymSH7pY+zoMVEZg3gcPuBNxH1EvfVYe9h0x/Ptw8KBzv7qxb7l8dg== - "@esbuild/aix-ppc64@0.27.7": version "0.27.7" resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.27.7.tgz#82b74f92aa78d720b714162939fb248c90addf53" integrity sha512-EKX3Qwmhz1eMdEJokhALr0YiD0lhQNwDqkPYyPhiSwKrh7/4KRjQc04sZ8db+5DVVnZ1LmbNDI1uAMPEUBnQPg== -"@esbuild/android-arm64@0.27.3": - version "0.27.3" - resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.27.3.tgz#19b882408829ad8e12b10aff2840711b2da361e8" - integrity sha512-YdghPYUmj/FX2SYKJ0OZxf+iaKgMsKHVPF1MAq/P8WirnSpCStzKJFjOjzsW0QQ7oIAiccHdcqjbHmJxRb/dmg== - "@esbuild/android-arm64@0.27.7": version "0.27.7" resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.27.7.tgz#f78cb8a3121fc205a53285adb24972db385d185d" integrity sha512-62dPZHpIXzvChfvfLJow3q5dDtiNMkwiRzPylSCfriLvZeq0a1bWChrGx/BbUbPwOrsWKMn8idSllklzBy+dgQ== -"@esbuild/android-arm@0.27.3": - version "0.27.3" - resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.27.3.tgz#90be58de27915efa27b767fcbdb37a4470627d7b" - integrity sha512-i5D1hPY7GIQmXlXhs2w8AWHhenb00+GxjxRncS2ZM7YNVGNfaMxgzSGuO8o8SJzRc/oZwU2bcScvVERk03QhzA== - "@esbuild/android-arm@0.27.7": version "0.27.7" resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.27.7.tgz#593e10a1450bbfcac6cb321f61f468453bac209d" integrity sha512-jbPXvB4Yj2yBV7HUfE2KHe4GJX51QplCN1pGbYjvsyCZbQmies29EoJbkEc+vYuU5o45AfQn37vZlyXy4YJ8RQ== -"@esbuild/android-x64@0.27.3": - version "0.27.3" - resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.27.3.tgz#d7dcc976f16e01a9aaa2f9b938fbec7389f895ac" - integrity sha512-IN/0BNTkHtk8lkOM8JWAYFg4ORxBkZQf9zXiEOfERX/CzxW3Vg1ewAhU7QSWQpVIzTW+b8Xy+lGzdYXV6UZObQ== - "@esbuild/android-x64@0.27.7": version "0.27.7" resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.27.7.tgz#453143d073326033d2d22caf9e48de4bae274b07" integrity sha512-x5VpMODneVDb70PYV2VQOmIUUiBtY3D3mPBG8NxVk5CogneYhkR7MmM3yR/uMdITLrC1ml/NV1rj4bMJuy9MCg== -"@esbuild/darwin-arm64@0.27.3": - version "0.27.3" - resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.27.3.tgz#9f6cac72b3a8532298a6a4493ed639a8988e8abd" - integrity sha512-Re491k7ByTVRy0t3EKWajdLIr0gz2kKKfzafkth4Q8A5n1xTHrkqZgLLjFEHVD+AXdUGgQMq+Godfq45mGpCKg== - "@esbuild/darwin-arm64@0.27.7": version "0.27.7" resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.27.7.tgz#6f23000fb9b40b7e04b7d0606c0693bd0632f322" integrity sha512-5lckdqeuBPlKUwvoCXIgI2D9/ABmPq3Rdp7IfL70393YgaASt7tbju3Ac+ePVi3KDH6N2RqePfHnXkaDtY9fkw== -"@esbuild/darwin-x64@0.27.3": - version "0.27.3" - resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.27.3.tgz#ac61d645faa37fd650340f1866b0812e1fb14d6a" - integrity sha512-vHk/hA7/1AckjGzRqi6wbo+jaShzRowYip6rt6q7VYEDX4LEy1pZfDpdxCBnGtl+A5zq8iXDcyuxwtv3hNtHFg== - "@esbuild/darwin-x64@0.27.7": version "0.27.7" resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.27.7.tgz#27393dd18bb1263c663979c5f1576e00c2d024be" integrity sha512-rYnXrKcXuT7Z+WL5K980jVFdvVKhCHhUwid+dDYQpH+qu+TefcomiMAJpIiC2EM3Rjtq0sO3StMV/+3w3MyyqQ== -"@esbuild/freebsd-arm64@0.27.3": - version "0.27.3" - resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.3.tgz#b8625689d73cf1830fe58c39051acdc12474ea1b" - integrity sha512-ipTYM2fjt3kQAYOvo6vcxJx3nBYAzPjgTCk7QEgZG8AUO3ydUhvelmhrbOheMnGOlaSFUoHXB6un+A7q4ygY9w== - "@esbuild/freebsd-arm64@0.27.7": version "0.27.7" resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.7.tgz#22e4638fa502d1c0027077324c97640e3adf3a62" integrity sha512-B48PqeCsEgOtzME2GbNM2roU29AMTuOIN91dsMO30t+Ydis3z/3Ngoj5hhnsOSSwNzS+6JppqWsuhTp6E82l2w== -"@esbuild/freebsd-x64@0.27.3": - version "0.27.3" - resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.27.3.tgz#07be7dd3c9d42fe0eccd2ab9f9ded780bc53bead" - integrity sha512-dDk0X87T7mI6U3K9VjWtHOXqwAMJBNN2r7bejDsc+j03SEjtD9HrOl8gVFByeM0aJksoUuUVU9TBaZa2rgj0oA== - "@esbuild/freebsd-x64@0.27.7": version "0.27.7" resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.27.7.tgz#9224b8e4fea924ce2194e3efc3e9aebf822192d6" integrity sha512-jOBDK5XEjA4m5IJK3bpAQF9/Lelu/Z9ZcdhTRLf4cajlB+8VEhFFRjWgfy3M1O4rO2GQ/b2dLwCUGpiF/eATNQ== -"@esbuild/linux-arm64@0.27.3": - version "0.27.3" - resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.27.3.tgz#bf31918fe5c798586460d2b3d6c46ed2c01ca0b6" - integrity sha512-sZOuFz/xWnZ4KH3YfFrKCf1WyPZHakVzTiqji3WDc0BCl2kBwiJLCXpzLzUBLgmp4veFZdvN5ChW4Eq/8Fc2Fg== - "@esbuild/linux-arm64@0.27.7": version "0.27.7" resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.27.7.tgz#4f5d1c27527d817b35684ae21419e57c2bda0966" integrity sha512-RZPHBoxXuNnPQO9rvjh5jdkRmVizktkT7TCDkDmQ0W2SwHInKCAV95GRuvdSvA7w4VMwfCjUiPwDi0ZO6Nfe9A== -"@esbuild/linux-arm@0.27.3": - version "0.27.3" - resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.27.3.tgz#28493ee46abec1dc3f500223cd9f8d2df08f9d11" - integrity sha512-s6nPv2QkSupJwLYyfS+gwdirm0ukyTFNl3KTgZEAiJDd+iHZcbTPPcWCcRYH+WlNbwChgH2QkE9NSlNrMT8Gfw== - "@esbuild/linux-arm@0.27.7": version "0.27.7" resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.27.7.tgz#b9e9d070c8c1c0449cf12b20eac37d70a4595921" integrity sha512-RkT/YXYBTSULo3+af8Ib0ykH8u2MBh57o7q/DAs3lTJlyVQkgQvlrPTnjIzzRPQyavxtPtfg0EopvDyIt0j1rA== -"@esbuild/linux-ia32@0.27.3": - version "0.27.3" - resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.27.3.tgz#750752a8b30b43647402561eea764d0a41d0ee29" - integrity sha512-yGlQYjdxtLdh0a3jHjuwOrxQjOZYD/C9PfdbgJJF3TIZWnm/tMd/RcNiLngiu4iwcBAOezdnSLAwQDPqTmtTYg== - "@esbuild/linux-ia32@0.27.7": version "0.27.7" resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.27.7.tgz#3f80fb696aa96051a94047f35c85b08b21c36f9e" integrity sha512-GA48aKNkyQDbd3KtkplYWT102C5sn/EZTY4XROkxONgruHPU72l+gW+FfF8tf2cFjeHaRbWpOYa/uRBz/Xq1Pg== -"@esbuild/linux-loong64@0.27.3": - version "0.27.3" - resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.27.3.tgz#a5a92813a04e71198c50f05adfaf18fc1e95b9ed" - integrity sha512-WO60Sn8ly3gtzhyjATDgieJNet/KqsDlX5nRC5Y3oTFcS1l0KWba+SEa9Ja1GfDqSF1z6hif/SkpQJbL63cgOA== - "@esbuild/linux-loong64@0.27.7": version "0.27.7" resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.27.7.tgz#9be1f2c28210b13ebb4156221bba356fe1675205" integrity sha512-a4POruNM2oWsD4WKvBSEKGIiWQF8fZOAsycHOt6JBpZ+JN2n2JH9WAv56SOyu9X5IqAjqSIPTaJkqN8F7XOQ5Q== -"@esbuild/linux-mips64el@0.27.3": - version "0.27.3" - resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.27.3.tgz#deb45d7fd2d2161eadf1fbc593637ed766d50bb1" - integrity sha512-APsymYA6sGcZ4pD6k+UxbDjOFSvPWyZhjaiPyl/f79xKxwTnrn5QUnXR5prvetuaSMsb4jgeHewIDCIWljrSxw== - "@esbuild/linux-mips64el@0.27.7": version "0.27.7" resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.27.7.tgz#4ab5ee67a3dfcbcb5e8fd7883dae6e735b1163b8" integrity sha512-KabT5I6StirGfIz0FMgl1I+R1H73Gp0ofL9A3nG3i/cYFJzKHhouBV5VWK1CSgKvVaG4q1RNpCTR2LuTVB3fIw== -"@esbuild/linux-ppc64@0.27.3": - version "0.27.3" - resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.27.3.tgz#6f39ae0b8c4d3d2d61a65b26df79f6e12a1c3d78" - integrity sha512-eizBnTeBefojtDb9nSh4vvVQ3V9Qf9Df01PfawPcRzJH4gFSgrObw+LveUyDoKU3kxi5+9RJTCWlj4FjYXVPEA== - "@esbuild/linux-ppc64@0.27.7": version "0.27.7" resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.27.7.tgz#dac78c689f6499459c4321e5c15032c12307e7ea" integrity sha512-gRsL4x6wsGHGRqhtI+ifpN/vpOFTQtnbsupUF5R5YTAg+y/lKelYR1hXbnBdzDjGbMYjVJLJTd2OFmMewAgwlQ== -"@esbuild/linux-riscv64@0.27.3": - version "0.27.3" - resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.27.3.tgz#4c5c19c3916612ec8e3915187030b9df0b955c1d" - integrity sha512-3Emwh0r5wmfm3ssTWRQSyVhbOHvqegUDRd0WhmXKX2mkHJe1SFCMJhagUleMq+Uci34wLSipf8Lagt4LlpRFWQ== - "@esbuild/linux-riscv64@0.27.7": version "0.27.7" resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.27.7.tgz#050f7d3b355c3a98308e935bc4d6325da91b0027" integrity sha512-hL25LbxO1QOngGzu2U5xeXtxXcW+/GvMN3ejANqXkxZ/opySAZMrc+9LY/WyjAan41unrR3YrmtTsUpwT66InQ== -"@esbuild/linux-s390x@0.27.3": - version "0.27.3" - resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.27.3.tgz#9ed17b3198fa08ad5ccaa9e74f6c0aff7ad0156d" - integrity sha512-pBHUx9LzXWBc7MFIEEL0yD/ZVtNgLytvx60gES28GcWMqil8ElCYR4kvbV2BDqsHOvVDRrOxGySBM9Fcv744hw== - "@esbuild/linux-s390x@0.27.7": version "0.27.7" resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.27.7.tgz#d61f715ce61d43fe5844ad0d8f463f88cbe4fef6" integrity sha512-2k8go8Ycu1Kb46vEelhu1vqEP+UeRVj2zY1pSuPdgvbd5ykAw82Lrro28vXUrRmzEsUV0NzCf54yARIK8r0fdw== -"@esbuild/linux-x64@0.27.3": - version "0.27.3" - resolved "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.3.tgz" - integrity sha512-Czi8yzXUWIQYAtL/2y6vogER8pvcsOsk5cpwL4Gk5nJqH5UZiVByIY8Eorm5R13gq+DQKYg0+JyQoytLQas4dA== - "@esbuild/linux-x64@0.27.7": version "0.27.7" resolved "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.7.tgz" integrity sha512-hzznmADPt+OmsYzw1EE33ccA+HPdIqiCRq7cQeL1Jlq2gb1+OyWBkMCrYGBJ+sxVzve2ZJEVeePbLM2iEIZSxA== -"@esbuild/netbsd-arm64@0.27.3": - version "0.27.3" - resolved "https://registry.yarnpkg.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.3.tgz#dd0cb2fa543205fcd931df44f4786bfcce6df7d7" - integrity sha512-sDpk0RgmTCR/5HguIZa9n9u+HVKf40fbEUt+iTzSnCaGvY9kFP0YKBWZtJaraonFnqef5SlJ8/TiPAxzyS+UoA== - "@esbuild/netbsd-arm64@0.27.7": version "0.27.7" resolved "https://registry.yarnpkg.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.7.tgz#1650f2c1b948deeb3ef948f2fc30614723c09690" integrity sha512-b6pqtrQdigZBwZxAn1UpazEisvwaIDvdbMbmrly7cDTMFnw/+3lVxxCTGOrkPVnsYIosJJXAsILG9XcQS+Yu6w== -"@esbuild/netbsd-x64@0.27.3": - version "0.27.3" - resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.27.3.tgz#028ad1807a8e03e155153b2d025b506c3787354b" - integrity sha512-P14lFKJl/DdaE00LItAukUdZO5iqNH7+PjoBm+fLQjtxfcfFE20Xf5CrLsmZdq5LFFZzb5JMZ9grUwvtVYzjiA== - "@esbuild/netbsd-x64@0.27.7": version "0.27.7" resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.27.7.tgz#65772ab342c4b3319bf0705a211050aac1b6e320" integrity sha512-OfatkLojr6U+WN5EDYuoQhtM+1xco+/6FSzJJnuWiUw5eVcicbyK3dq5EeV/QHT1uy6GoDhGbFpprUiHUYggrw== -"@esbuild/openbsd-arm64@0.27.3": - version "0.27.3" - resolved "https://registry.yarnpkg.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.3.tgz#e3c16ff3490c9b59b969fffca87f350ffc0e2af5" - integrity sha512-AIcMP77AvirGbRl/UZFTq5hjXK+2wC7qFRGoHSDrZ5v5b8DK/GYpXW3CPRL53NkvDqb9D+alBiC/dV0Fb7eJcw== - "@esbuild/openbsd-arm64@0.27.7": version "0.27.7" resolved "https://registry.yarnpkg.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.7.tgz#37ed7cfa66549d7955852fce37d0c3de4e715ea1" integrity sha512-AFuojMQTxAz75Fo8idVcqoQWEHIXFRbOc1TrVcFSgCZtQfSdc1RXgB3tjOn/krRHENUB4j00bfGjyl2mJrU37A== -"@esbuild/openbsd-x64@0.27.3": - version "0.27.3" - resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.27.3.tgz#c5a4693fcb03d1cbecbf8b422422468dfc0d2a8b" - integrity sha512-DnW2sRrBzA+YnE70LKqnM3P+z8vehfJWHXECbwBmH/CU51z6FiqTQTHFenPlHmo3a8UgpLyH3PT+87OViOh1AQ== - "@esbuild/openbsd-x64@0.27.7": version "0.27.7" resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.27.7.tgz#01bf3d385855ef50cb33db7c4b52f957c34cd179" integrity sha512-+A1NJmfM8WNDv5CLVQYJ5PshuRm/4cI6WMZRg1by1GwPIQPCTs1GLEUHwiiQGT5zDdyLiRM/l1G0Pv54gvtKIg== -"@esbuild/openharmony-arm64@0.27.3": - version "0.27.3" - resolved "https://registry.yarnpkg.com/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.3.tgz#082082444f12db564a0775a41e1991c0e125055e" - integrity sha512-NinAEgr/etERPTsZJ7aEZQvvg/A6IsZG/LgZy+81wON2huV7SrK3e63dU0XhyZP4RKGyTm7aOgmQk0bGp0fy2g== - "@esbuild/openharmony-arm64@0.27.7": version "0.27.7" resolved "https://registry.yarnpkg.com/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.7.tgz#6c1f94b34086599aabda4eac8f638294b9877410" integrity sha512-+KrvYb/C8zA9CU/g0sR6w2RBw7IGc5J2BPnc3dYc5VJxHCSF1yNMxTV5LQ7GuKteQXZtspjFbiuW5/dOj7H4Yw== -"@esbuild/sunos-x64@0.27.3": - version "0.27.3" - resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.27.3.tgz#5ab036c53f929e8405c4e96e865a424160a1b537" - integrity sha512-PanZ+nEz+eWoBJ8/f8HKxTTD172SKwdXebZ0ndd953gt1HRBbhMsaNqjTyYLGLPdoWHy4zLU7bDVJztF5f3BHA== - "@esbuild/sunos-x64@0.27.7": version "0.27.7" resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.27.7.tgz#4b0dd17ae0a6941d2d0fd35a906392517071a90d" integrity sha512-ikktIhFBzQNt/QDyOL580ti9+5mL/YZeUPKU2ivGtGjdTYoqz6jObj6nOMfhASpS4GU4Q/Clh1QtxWAvcYKamA== -"@esbuild/win32-arm64@0.27.3": - version "0.27.3" - resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.27.3.tgz#38de700ef4b960a0045370c171794526e589862e" - integrity sha512-B2t59lWWYrbRDw/tjiWOuzSsFh1Y/E95ofKz7rIVYSQkUYBjfSgf6oeYPNWHToFRr2zx52JKApIcAS/D5TUBnA== - "@esbuild/win32-arm64@0.27.7": version "0.27.7" resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.27.7.tgz#34193ab5565d6ff68ca928ac04be75102ccb2e77" integrity sha512-7yRhbHvPqSpRUV7Q20VuDwbjW5kIMwTHpptuUzV+AA46kiPze5Z7qgt6CLCK3pWFrHeNfDd1VKgyP4O+ng17CA== -"@esbuild/win32-ia32@0.27.3": - version "0.27.3" - resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.27.3.tgz#451b93dc03ec5d4f38619e6cd64d9f9eff06f55c" - integrity sha512-QLKSFeXNS8+tHW7tZpMtjlNb7HKau0QDpwm49u0vUp9y1WOF+PEzkU84y9GqYaAVW8aH8f3GcBck26jh54cX4Q== - "@esbuild/win32-ia32@0.27.7": version "0.27.7" resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.27.7.tgz#eb67f0e4482515d8c1894ede631c327a4da9fc4d" integrity sha512-SmwKXe6VHIyZYbBLJrhOoCJRB/Z1tckzmgTLfFYOfpMAx63BJEaL9ExI8x7v0oAO3Zh6D/Oi1gVxEYr5oUCFhw== -"@esbuild/win32-x64@0.27.3": - version "0.27.3" - resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.27.3.tgz#0eaf705c941a218a43dba8e09f1df1d6cd2f1f17" - integrity sha512-4uJGhsxuptu3OcpVAzli+/gWusVGwZZHTlS63hh++ehExkVT8SgiEf7/uC/PclrPPkLhZqGgCTjd0VWLo6xMqA== - "@esbuild/win32-x64@0.27.7": version "0.27.7" resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.27.7.tgz#8fe30b3088b89b4873c3a6cc87597ae3920c0a8b" @@ -953,16 +681,6 @@ "@eslint/core" "^1.2.1" levn "^0.4.1" -"@fastify/accept-negotiator@^2.0.1": - version "2.0.1" - resolved "https://registry.npmjs.org/@fastify/accept-negotiator/-/accept-negotiator-2.0.1.tgz" - integrity sha512-/c/TW2bO/v9JeEgoD/g1G5GxGeCF1Hafdf79WPmUlgYiBXummY0oX3VVq4yFkKKVBKDNlaDUYoab7g38RpPqCQ== - -"@fastify/busboy@^3.1.1": - version "3.2.0" - resolved "https://registry.npmjs.org/@fastify/busboy/-/busboy-3.2.0.tgz" - integrity sha512-m9FVDXU3GT2ITSe0UaMA5rU3QkfC/UXtCU8y0gSN/GugTqtVldOBWIB5V6V3sbmenVZUIpU6f+mPEO2+m5iTaA== - "@fortawesome/fontawesome-common-types@7.2.0": version "7.2.0" resolved "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-7.2.0.tgz" @@ -1027,21 +745,11 @@ resolved "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz" integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA== -"@humanwhocodes/momoa@^2.0.2": - version "2.0.4" - resolved "https://registry.npmjs.org/@humanwhocodes/momoa/-/momoa-2.0.4.tgz" - integrity sha512-RE815I4arJFtt+FVeU1Tgp9/Xvecacji8w/V6XtXsWWH/wz/eNkNbhb+ny/+PlVZjV0rxQpRSQKNKE3lcktHEA== - "@humanwhocodes/retry@^0.4.0", "@humanwhocodes/retry@^0.4.2": version "0.4.3" resolved "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz" integrity sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ== -"@iarna/toml@^2.2.5": - version "2.2.5" - resolved "https://registry.npmjs.org/@iarna/toml/-/toml-2.2.5.tgz" - integrity sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg== - "@img/colour@^1.0.0": version "1.1.0" resolved "https://registry.npmjs.org/@img/colour/-/colour-1.1.0.tgz" @@ -1189,30 +897,6 @@ resolved "https://registry.yarnpkg.com/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.5.tgz#a81ffb00e69267cd0a1d626eaedb8a8430b2b2f8" integrity sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw== -"@import-maps/resolve@^2.0.0": - version "2.0.0" - resolved "https://registry.npmjs.org/@import-maps/resolve/-/resolve-2.0.0.tgz" - integrity sha512-RwzRTpmrrS6Q1ZhQExwuxJGK1Wqhv4stt+OF2JzS+uawewpwNyU7EJL1WpBex7aDiiGLs4FsXGkfUBdYuX7xiQ== - -"@isaacs/cliui@^8.0.2": - version "8.0.2" - resolved "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz" - integrity sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA== - dependencies: - string-width "^5.1.2" - string-width-cjs "npm:string-width@^4.2.0" - strip-ansi "^7.0.1" - strip-ansi-cjs "npm:strip-ansi@^6.0.1" - wrap-ansi "^8.1.0" - wrap-ansi-cjs "npm:wrap-ansi@^7.0.0" - -"@isaacs/fs-minipass@^4.0.0": - version "4.0.1" - resolved "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz" - integrity sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w== - dependencies: - minipass "^7.0.4" - "@jridgewell/gen-mapping@^0.3.12", "@jridgewell/gen-mapping@^0.3.5": version "0.3.13" resolved "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz" @@ -1229,24 +913,16 @@ "@jridgewell/gen-mapping" "^0.3.5" "@jridgewell/trace-mapping" "^0.3.24" -"@jridgewell/resolve-uri@^3.0.3", "@jridgewell/resolve-uri@^3.1.0": +"@jridgewell/resolve-uri@^3.1.0": version "3.1.2" resolved "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz" integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw== -"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14", "@jridgewell/sourcemap-codec@^1.4.15", "@jridgewell/sourcemap-codec@^1.5.0", "@jridgewell/sourcemap-codec@^1.5.5": +"@jridgewell/sourcemap-codec@^1.4.14", "@jridgewell/sourcemap-codec@^1.4.15", "@jridgewell/sourcemap-codec@^1.5.0", "@jridgewell/sourcemap-codec@^1.5.5": version "1.5.5" resolved "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz" integrity sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og== -"@jridgewell/trace-mapping@0.3.9": - version "0.3.9" - resolved "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz" - integrity sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ== - dependencies: - "@jridgewell/resolve-uri" "^3.0.3" - "@jridgewell/sourcemap-codec" "^1.4.10" - "@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.28": version "0.3.31" resolved "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz" @@ -1255,358 +931,6 @@ "@jridgewell/resolve-uri" "^3.1.0" "@jridgewell/sourcemap-codec" "^1.4.14" -"@mapbox/node-pre-gyp@^2.0.0": - version "2.0.3" - resolved "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-2.0.3.tgz" - integrity sha512-uwPAhccfFJlsfCxMYTwOdVfOz3xqyj8xYL3zJj8f0pb30tLohnnFPhLuqp4/qoEz8sNxe4SESZedcBojRefIzg== - dependencies: - consola "^3.2.3" - detect-libc "^2.0.0" - https-proxy-agent "^7.0.5" - node-fetch "^2.6.7" - nopt "^8.0.0" - semver "^7.5.3" - tar "^7.4.0" - -"@netlify/ai@^0.4.1": - version "0.4.1" - resolved "https://registry.npmjs.org/@netlify/ai/-/ai-0.4.1.tgz" - integrity sha512-ETLtV/9taYrcGhszwO+BLFgFJJ2MCnJp8BwxfwV6Z/+z3SsaUG4ExC8x4xzNCdB2GPWxXrXkvR2LFNsPFSLcRA== - dependencies: - "@netlify/api" "^14.0.18" - -"@netlify/api@^14.0.18": - version "14.0.18" - resolved "https://registry.npmjs.org/@netlify/api/-/api-14.0.18.tgz" - integrity sha512-4STtNybPXALobjTHEIU48Huv9Si1sNxgHbtYslNBPvQu9/aTpxhRHDZuUOkE/QuhHSbaCNCWJSYFGIRxpCdXxg== - dependencies: - "@netlify/open-api" "^2.51.0" - node-fetch "^3.0.0" - p-wait-for "^5.0.0" - picoquery "^2.5.0" - -"@netlify/binary-info@^1.0.0": - version "1.0.0" - resolved "https://registry.npmjs.org/@netlify/binary-info/-/binary-info-1.0.0.tgz" - integrity sha512-4wMPu9iN3/HL97QblBsBay3E1etIciR84izI3U+4iALY+JHCrI+a2jO0qbAZ/nxKoegypYEaiiqWXylm+/zfrw== - -"@netlify/blobs@10.7.4", "@netlify/blobs@^10.7.0", "@netlify/blobs@^10.7.4": - version "10.7.4" - resolved "https://registry.npmjs.org/@netlify/blobs/-/blobs-10.7.4.tgz" - integrity sha512-03lXstB4xxDKeYs2RTTZrUGRC0ea2nVZvkdGlw2A42AdK7KA6N0ocVmkIn9x91oqFsqK3dWJTAv2bzaLjsehXg== - dependencies: - "@netlify/dev-utils" "4.4.3" - "@netlify/otel" "^5.1.5" - "@netlify/runtime-utils" "2.3.0" - -"@netlify/cache@3.4.4": - version "3.4.4" - resolved "https://registry.npmjs.org/@netlify/cache/-/cache-3.4.4.tgz" - integrity sha512-CL9WZjbxe9/Gkcpfkl6h1F0BkBxUg9b4HHleGjmo0rs/PDUJ2NDQVKtEospllH2+KDUdB6EsPhiJN+v9Jcdv1g== - dependencies: - "@netlify/runtime-utils" "2.3.0" - -"@netlify/config@^24.4.3": - version "24.5.0" - resolved "https://registry.npmjs.org/@netlify/config/-/config-24.5.0.tgz" - integrity sha512-d9M/H9ouQUlu6OnEYa9z4Sa+RZUn7OioS6bw6kKRtalllkQiSAtbgzjXz/2umgABsJGmxYXyjSOk7P8QcKluJg== - dependencies: - "@iarna/toml" "^2.2.5" - "@netlify/api" "^14.0.18" - "@netlify/headers-parser" "^9.0.3" - "@netlify/redirect-parser" "^15.0.4" - chalk "^5.0.0" - cron-parser "^4.1.0" - deepmerge "^4.2.2" - dot-prop "^9.0.0" - execa "^8.0.0" - fast-safe-stringify "^2.0.7" - figures "^6.0.0" - filter-obj "^6.0.0" - find-up "^7.0.0" - indent-string "^5.0.0" - is-plain-obj "^4.0.0" - map-obj "^5.0.0" - omit.js "^2.0.2" - p-locate "^6.0.0" - path-type "^6.0.0" - read-package-up "^11.0.0" - tomlify-j0.4 "^3.0.0" - validate-npm-package-name "^5.0.0" - yaml "^2.8.0" - yargs "^17.6.0" - zod "^4.0.5" - -"@netlify/database-dev@0.10.1": - version "0.10.1" - resolved "https://registry.npmjs.org/@netlify/database-dev/-/database-dev-0.10.1.tgz" - integrity sha512-kHLdS6r45TsDiS5aBrHUmzqPvoaWQEUZnaZeMwnIrLMwX8f2bIa6YAMOJJYJhyKm2drVo3C/T92/lJ5iGV/VBQ== - dependencies: - "@electric-sql/pglite" "^0.3.15" - pg-gateway "0.3.0-beta.4" - -"@netlify/dev-utils@4.4.3", "@netlify/dev-utils@^4.4.3": - version "4.4.3" - resolved "https://registry.npmjs.org/@netlify/dev-utils/-/dev-utils-4.4.3.tgz" - integrity sha512-VkMD8YACshR6pHgoub6nikkI+SQVdhjVvLsOK2ZSpN2wMlDHdsD8uRjESfzv/yYfq5jlsGskfx1cf1FUurWt9A== - dependencies: - "@whatwg-node/server" "^0.10.0" - ansis "^4.1.0" - chokidar "^4.0.1" - decache "^4.6.2" - dettle "^1.0.5" - dot-prop "9.0.0" - empathic "^2.0.0" - env-paths "^3.0.0" - image-size "^2.0.2" - js-image-generator "^1.0.4" - parse-gitignore "^2.0.0" - semver "^7.7.2" - tmp-promise "^3.0.3" - uuid "^13.0.0" - write-file-atomic "^5.0.1" - -"@netlify/dev@4.18.1": - version "4.18.1" - resolved "https://registry.npmjs.org/@netlify/dev/-/dev-4.18.1.tgz" - integrity sha512-qbLvurzxBiLbBo4z2GfoXnFU5OS7QcGZTLzI1L31i3YahXPWJV7tnTn0kEAeyRV0tHmmVBF/FEzTws8cFzFSjQ== - dependencies: - "@netlify/ai" "^0.4.1" - "@netlify/blobs" "10.7.4" - "@netlify/config" "^24.4.3" - "@netlify/database-dev" "0.10.1" - "@netlify/dev-utils" "4.4.3" - "@netlify/edge-functions-dev" "1.0.16" - "@netlify/functions-dev" "1.2.6" - "@netlify/headers" "2.1.8" - "@netlify/images" "1.3.7" - "@netlify/redirects" "3.1.10" - "@netlify/runtime" "4.1.20" - "@netlify/static" "3.1.7" - ulid "^3.0.0" - -"@netlify/edge-bundler@^14.9.15": - version "14.10.1" - resolved "https://registry.npmjs.org/@netlify/edge-bundler/-/edge-bundler-14.10.1.tgz" - integrity sha512-Kg/LHnLZnv18qzAQonnFMYcGbair/z5DI40le1L9PJlz+S7lR2xOVg0gBzTRccG1VylXozwp4GVYhVT4v7n2GA== - dependencies: - "@import-maps/resolve" "^2.0.0" - "@sveltejs/acorn-typescript" "^1.0.9" - acorn "^8.15.0" - ajv "^8.11.2" - ajv-errors "^3.0.0" - better-ajv-errors "^1.2.0" - common-path-prefix "^3.0.0" - env-paths "^3.0.0" - esbuild "0.27.3" - execa "^8.0.0" - find-up "^7.0.0" - get-port "^7.0.0" - node-stream-zip "^1.15.0" - p-retry "^6.0.0" - p-wait-for "^5.0.0" - parse-imports "^2.2.1" - path-key "^4.0.0" - semver "^7.3.8" - tar "^7.5.12" - tmp-promise "^3.0.3" - urlpattern-polyfill "8.0.2" - uuid "^11.0.0" - -"@netlify/edge-functions-bootstrap@2.16.0": - version "2.16.0" - resolved "https://registry.npmjs.org/@netlify/edge-functions-bootstrap/-/edge-functions-bootstrap-2.16.0.tgz" - integrity sha512-v8QQihSbBHj3JxtJsHoepXALpNumD9M7egHoc8z62FYl5it34dWczkaJoFFopEyhiBVKi4K/n0ZYpdzwfujd6g== - -"@netlify/edge-functions-dev@1.0.16": - version "1.0.16" - resolved "https://registry.npmjs.org/@netlify/edge-functions-dev/-/edge-functions-dev-1.0.16.tgz" - integrity sha512-QQGUNPRvynKg4NJ7iiR0mYcsdA/QwIdUB/Fb4SGhhqBPicTcW4V5bEZ/JaMvEBMd2ZY8EKuWQ63Ryl4TVHI+QQ== - dependencies: - "@netlify/dev-utils" "4.4.3" - "@netlify/edge-bundler" "^14.9.15" - "@netlify/edge-functions" "3.0.6" - "@netlify/edge-functions-bootstrap" "2.16.0" - "@netlify/runtime-utils" "2.3.0" - get-port "^7.1.0" - -"@netlify/edge-functions@3.0.6": - version "3.0.6" - resolved "https://registry.npmjs.org/@netlify/edge-functions/-/edge-functions-3.0.6.tgz" - integrity sha512-xkVcTcpAuQKAY5GXKOjPTIct5Mz53NPHXOasggA+LTAxDDV4ohqSM8BIaXh1SgbcniHZyFhBqhc5hxZ+fFz5bQ== - dependencies: - "@netlify/types" "2.6.0" - -"@netlify/functions-dev@1.2.6": - version "1.2.6" - resolved "https://registry.npmjs.org/@netlify/functions-dev/-/functions-dev-1.2.6.tgz" - integrity sha512-hhfgKGZ2mQAv85jb3o4hYZ7s8Ad/+99qz51AoxhE26KkU1IKuRuKwEowWZUtvih0KPmvmGcVHbd49KYVIlf0tA== - dependencies: - "@netlify/blobs" "10.7.4" - "@netlify/dev-utils" "4.4.3" - "@netlify/functions" "5.2.0" - "@netlify/zip-it-and-ship-it" "^14.5.0" - cron-parser "^4.9.0" - decache "^4.6.2" - extract-zip "^2.0.1" - is-stream "^4.0.1" - jwt-decode "^4.0.0" - lambda-local "^2.2.0" - read-package-up "^11.0.0" - semver "^7.6.3" - source-map-support "^0.5.21" - -"@netlify/functions@5.2.0", "@netlify/functions@^5.1.2": - version "5.2.0" - resolved "https://registry.npmjs.org/@netlify/functions/-/functions-5.2.0.tgz" - integrity sha512-Pj93qeQd1tkQ5xm9gWJZmBf/1riLYqYHc0OzFukrJomrj82Ott53Rr/Q88H1ms5cF+P5QXRKWmA2JSxSybKfjA== - dependencies: - "@netlify/types" "2.6.0" - -"@netlify/headers-parser@^9.0.3": - version "9.0.3" - resolved "https://registry.npmjs.org/@netlify/headers-parser/-/headers-parser-9.0.3.tgz" - integrity sha512-KNzC9RaKDwJVS44iTK6JxNA6LeXH0PUw0pLktWpmMVI/0FR98bvxaHcAisjHqbThAjxL9QjL1UZh0KzHCkxpNQ== - dependencies: - "@iarna/toml" "^2.2.5" - escape-string-regexp "^5.0.0" - fast-safe-stringify "^2.0.7" - is-plain-obj "^4.0.0" - map-obj "^5.0.0" - path-exists "^5.0.0" - -"@netlify/headers@2.1.8": - version "2.1.8" - resolved "https://registry.npmjs.org/@netlify/headers/-/headers-2.1.8.tgz" - integrity sha512-OhHT8nq84tSvXWaOMCLgcaGKnUccbIYg7/Ink4NyVHNwJ7L2fFGb6Mi4lPWluHhncYJE9p0eK7JMiKKj49Q0Qw== - dependencies: - "@netlify/headers-parser" "^9.0.3" - -"@netlify/images@1.3.7": - version "1.3.7" - resolved "https://registry.npmjs.org/@netlify/images/-/images-1.3.7.tgz" - integrity sha512-qWKCbtYQbyHtzVjLcaAxZsxrd8qpIVnLWwvn2635E8zQSO7L0wb2oPTUhMEOOIxIurWuY3JSRGevpve6ifataQ== - dependencies: - ipx "^3.1.1" - -"@netlify/open-api@^2.51.0": - version "2.53.0" - resolved "https://registry.npmjs.org/@netlify/open-api/-/open-api-2.53.0.tgz" - integrity sha512-CcIhcB+XzY77nze7vLTdxkqS/uX5DXleo3adE8H+M7TapLX6GTXp5qMIsq8bAuHy5eGw0ijRrAnSUmkOP4DM2w== - -"@netlify/otel@^5.1.5": - version "5.1.5" - resolved "https://registry.npmjs.org/@netlify/otel/-/otel-5.1.5.tgz" - integrity sha512-RORbePN1ghdHp4pIkG3ccFMqmx5hwMfSyLGKp7bKVf1F5rSe1QjrCBp5xihEWI3xuh3fAqQroTlNYnoOud8RTQ== - dependencies: - "@opentelemetry/api" "1.9.0" - "@opentelemetry/core" "1.30.1" - "@opentelemetry/instrumentation" "^0.203.0" - "@opentelemetry/resources" "1.30.1" - "@opentelemetry/sdk-trace-node" "1.30.1" - -"@netlify/redirect-parser@^15.0.4": - version "15.0.4" - resolved "https://registry.npmjs.org/@netlify/redirect-parser/-/redirect-parser-15.0.4.tgz" - integrity sha512-UYHRCO4HZI6WMpf8RheaCWnGafeJeFTsp/5yK887fyGqohDmFbc26NuFUvRl7J6sNu+di/1lLmRXP+yJ1X9TDA== - dependencies: - "@iarna/toml" "^2.2.5" - fast-safe-stringify "^2.1.1" - is-plain-obj "^4.0.0" - path-exists "^5.0.0" - -"@netlify/redirects@3.1.10": - version "3.1.10" - resolved "https://registry.npmjs.org/@netlify/redirects/-/redirects-3.1.10.tgz" - integrity sha512-q4PbtkeNDxKqfOemsrG5F/vkpNfLwjVQpx69+sS2Qg/PYOOneayKJOlCKhVc6QQUtDuhFV6WZ8JHielYMj1pVw== - dependencies: - "@netlify/dev-utils" "4.4.3" - "@netlify/redirect-parser" "^15.0.4" - cookie "^1.0.2" - jsonwebtoken "9.0.3" - netlify-redirector "^0.5.0" - -"@netlify/runtime-utils@2.3.0": - version "2.3.0" - resolved "https://registry.npmjs.org/@netlify/runtime-utils/-/runtime-utils-2.3.0.tgz" - integrity sha512-cW8weDvsKV7zfia2m5EcBy6KILGoPD+eYZ3qWNGnIo05DGF28goPES0xKSDkNYgAF/2rRSIhie2qcBhbGVgSRg== - -"@netlify/runtime@4.1.20": - version "4.1.20" - resolved "https://registry.npmjs.org/@netlify/runtime/-/runtime-4.1.20.tgz" - integrity sha512-maPRSTG+q9rTkeP+hj5X8PN6OkUShp1E62+GBtZrVRVrkTYLiF3mz2JGUw32lCbw2OqqvlUab85N4OMPSdP5HA== - dependencies: - "@netlify/blobs" "^10.7.4" - "@netlify/cache" "3.4.4" - "@netlify/runtime-utils" "2.3.0" - "@netlify/types" "2.6.0" - -"@netlify/serverless-functions-api@2.15.0": - version "2.15.0" - resolved "https://registry.npmjs.org/@netlify/serverless-functions-api/-/serverless-functions-api-2.15.0.tgz" - integrity sha512-FDZwRBWq6zgmuYkszHGcN1qYliTOY7/ZzuWWxJy1WoB4cZt6gdzgN5Gx9zuIKfiL9KelL0iAnd/bZrrfLZZ5ig== - dependencies: - "@netlify/types" "^2.6.0" - -"@netlify/static@3.1.7": - version "3.1.7" - resolved "https://registry.npmjs.org/@netlify/static/-/static-3.1.7.tgz" - integrity sha512-7gfDmUJKIFiVvqoqAoN7wkZkQx8KgVw5+ancu4v+QFU/hLt+gWqNH+ngxaCKCA0hmDE4oD1xNbClxlh9bNOetw== - dependencies: - mime-types "^3.0.0" - -"@netlify/types@2.6.0", "@netlify/types@^2.6.0": - version "2.6.0" - resolved "https://registry.npmjs.org/@netlify/types/-/types-2.6.0.tgz" - integrity sha512-yD20EizHJDQxajJ66Vo8RTwLwR2jMNVxufPG8MHd2AScX8jW4z0VPnnJHArq2GYPFTFZRHmiAhDrXr5m8zof6w== - -"@netlify/vite-plugin@^2.10.3": - version "2.12.1" - resolved "https://registry.npmjs.org/@netlify/vite-plugin/-/vite-plugin-2.12.1.tgz" - integrity sha512-P5WErLc6/E3eiNit1HQpWfEePvl528op/I84yxqJEOUa15NzxJYSbPDQ8CYUmz7ifhiZDbi1RFFmGoz0eA6aSA== - dependencies: - "@netlify/dev" "4.18.1" - "@netlify/dev-utils" "^4.4.3" - dedent "^1.7.0" - -"@netlify/zip-it-and-ship-it@^14.5.0": - version "14.5.4" - resolved "https://registry.npmjs.org/@netlify/zip-it-and-ship-it/-/zip-it-and-ship-it-14.5.4.tgz" - integrity sha512-kaX/03YsBy/9ZOTNF/EtbBkof/Uukul5mnxs/SHD8LPY9Co6TcdMz61ZfDNyAYeIdfTMDIs4EFNBQPvzHexEMg== - dependencies: - "@babel/parser" "^7.22.5" - "@babel/types" "^7.28.5" - "@netlify/binary-info" "^1.0.0" - "@netlify/serverless-functions-api" "2.15.0" - "@vercel/nft" "0.29.4" - archiver "^7.0.0" - common-path-prefix "^3.0.0" - copy-file "^11.0.0" - es-module-lexer "^1.0.0" - esbuild "0.27.3" - execa "^8.0.0" - fast-glob "^3.3.3" - filter-obj "^6.0.0" - find-up "^7.0.0" - is-path-inside "^4.0.0" - junk "^4.0.0" - locate-path "^7.0.0" - merge-options "^3.0.4" - minimatch "^10.2.4" - normalize-path "^3.0.0" - p-map "^7.0.0" - path-exists "^5.0.0" - precinct "^12.0.0" - require-package-name "^2.0.1" - resolve "^2.0.0-next.1" - semver "^7.3.8" - tmp-promise "^3.0.2" - toml "^3.0.0" - unixify "^1.0.0" - urlpattern-polyfill "8.0.2" - yargs "^17.0.0" - zod "^3.23.8" - "@nodelib/fs.scandir@2.1.5": version "2.1.5" resolved "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz" @@ -1628,92 +952,6 @@ "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" -"@opentelemetry/api-logs@0.203.0": - version "0.203.0" - resolved "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.203.0.tgz" - integrity sha512-9B9RU0H7Ya1Dx/Rkyc4stuBZSGVQF27WigitInx2QQoj6KUpEFYPKoWjdFTunJYxmXmh17HeBvbMa1EhGyPmqQ== - dependencies: - "@opentelemetry/api" "^1.3.0" - -"@opentelemetry/api@1.9.0": - version "1.9.0" - resolved "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.0.tgz" - integrity sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg== - -"@opentelemetry/api@^1.3.0": - version "1.9.1" - resolved "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.1.tgz" - integrity sha512-gLyJlPHPZYdAk1JENA9LeHejZe1Ti77/pTeFm/nMXmQH/HFZlcS/O2XJB+L8fkbrNSqhdtlvjBVjxwUYanNH5Q== - -"@opentelemetry/context-async-hooks@1.30.1": - version "1.30.1" - resolved "https://registry.npmjs.org/@opentelemetry/context-async-hooks/-/context-async-hooks-1.30.1.tgz" - integrity sha512-s5vvxXPVdjqS3kTLKMeBMvop9hbWkwzBpu+mUO2M7sZtlkyDJGwFe33wRKnbaYDo8ExRVBIIdwIGrqpxHuKttA== - -"@opentelemetry/core@1.30.1": - version "1.30.1" - resolved "https://registry.npmjs.org/@opentelemetry/core/-/core-1.30.1.tgz" - integrity sha512-OOCM2C/QIURhJMuKaekP3TRBxBKxG/TWWA0TL2J6nXUtDnuCtccy49LUJF8xPFXMX+0LMcxFpCo8M9cGY1W6rQ== - dependencies: - "@opentelemetry/semantic-conventions" "1.28.0" - -"@opentelemetry/instrumentation@^0.203.0": - version "0.203.0" - resolved "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.203.0.tgz" - integrity sha512-ke1qyM+3AK2zPuBPb6Hk/GCsc5ewbLvPNkEuELx/JmANeEp6ZjnZ+wypPAJSucTw0wvCGrUaibDSdcrGFoWxKQ== - dependencies: - "@opentelemetry/api-logs" "0.203.0" - import-in-the-middle "^1.8.1" - require-in-the-middle "^7.1.1" - -"@opentelemetry/propagator-b3@1.30.1": - version "1.30.1" - resolved "https://registry.npmjs.org/@opentelemetry/propagator-b3/-/propagator-b3-1.30.1.tgz" - integrity sha512-oATwWWDIJzybAZ4pO76ATN5N6FFbOA1otibAVlS8v90B4S1wClnhRUk7K+2CHAwN1JKYuj4jh/lpCEG5BAqFuQ== - dependencies: - "@opentelemetry/core" "1.30.1" - -"@opentelemetry/propagator-jaeger@1.30.1": - version "1.30.1" - resolved "https://registry.npmjs.org/@opentelemetry/propagator-jaeger/-/propagator-jaeger-1.30.1.tgz" - integrity sha512-Pj/BfnYEKIOImirH76M4hDaBSx6HyZ2CXUqk+Kj02m6BB80c/yo4BdWkn/1gDFfU+YPY+bPR2U0DKBfdxCKwmg== - dependencies: - "@opentelemetry/core" "1.30.1" - -"@opentelemetry/resources@1.30.1": - version "1.30.1" - resolved "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.30.1.tgz" - integrity sha512-5UxZqiAgLYGFjS4s9qm5mBVo433u+dSPUFWVWXmLAD4wB65oMCoXaJP1KJa9DIYYMeHu3z4BZcStG3LC593cWA== - dependencies: - "@opentelemetry/core" "1.30.1" - "@opentelemetry/semantic-conventions" "1.28.0" - -"@opentelemetry/sdk-trace-base@1.30.1": - version "1.30.1" - resolved "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.30.1.tgz" - integrity sha512-jVPgBbH1gCy2Lb7X0AVQ8XAfgg0pJ4nvl8/IiQA6nxOsPvS+0zMJaFSs2ltXe0J6C8dqjcnpyqINDJmU30+uOg== - dependencies: - "@opentelemetry/core" "1.30.1" - "@opentelemetry/resources" "1.30.1" - "@opentelemetry/semantic-conventions" "1.28.0" - -"@opentelemetry/sdk-trace-node@1.30.1": - version "1.30.1" - resolved "https://registry.npmjs.org/@opentelemetry/sdk-trace-node/-/sdk-trace-node-1.30.1.tgz" - integrity sha512-cBjYOINt1JxXdpw1e5MlHmFRc5fgj4GW/86vsKFxJCJ8AL4PdVtYH41gWwl4qd4uQjqEL1oJVrXkSy5cnduAnQ== - dependencies: - "@opentelemetry/context-async-hooks" "1.30.1" - "@opentelemetry/core" "1.30.1" - "@opentelemetry/propagator-b3" "1.30.1" - "@opentelemetry/propagator-jaeger" "1.30.1" - "@opentelemetry/sdk-trace-base" "1.30.1" - semver "^7.5.2" - -"@opentelemetry/semantic-conventions@1.28.0": - version "1.28.0" - resolved "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.28.0.tgz" - integrity sha512-lp4qAiMTD4sNWW4DbKLBkfiMZ4jbAboJIGOQr5DvciMRI494OapieI9qiODpOt0XBr1LjIDy1xAGAnVs5supTA== - "@oslojs/encoding@^1.1.0": version "1.1.0" resolved "https://registry.npmjs.org/@oslojs/encoding/-/encoding-1.1.0.tgz" @@ -1769,15 +1007,6 @@ resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.6.tgz#02400c54b4a67efcc7e2327b249711920ac969e2" integrity sha512-1JRFeC+h7RdXwldHzTsmdtYR/Ku8SylLgTU/reMuqdVD7CtLwf0VR1FqeprZ0eHQkO0vqsbvFLXUmYm/uNKJBg== -"@parcel/watcher-wasm@^2.5.6": - version "2.5.6" - resolved "https://registry.npmjs.org/@parcel/watcher-wasm/-/watcher-wasm-2.5.6.tgz" - integrity sha512-byAiBZ1t3tXQvc8dMD/eoyE7lTXYorhn+6uVW5AC+JGI1KtJC/LvDche5cfUE+qiefH+Ybq0bUCJU0aB1cSHUA== - dependencies: - is-glob "^4.0.3" - napi-wasm "^1.1.0" - picomatch "^4.0.3" - "@parcel/watcher-win32-arm64@2.5.6": version "2.5.6" resolved "https://registry.yarnpkg.com/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.6.tgz#caae3d3c7583ca0a7171e6bd142c34d20ea1691e" @@ -1793,7 +1022,7 @@ resolved "https://registry.yarnpkg.com/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.6.tgz#73fdafba2e21c448f0e456bbe13178d8fe11739d" integrity sha512-hbQlYcCq5dlAX9Qx+kFb0FHue6vbjlf0FrNzSKdYK2APUf7tGfGxQCk2ihEREmbR6ZMc0MVAD5RIX/41gpUzTw== -"@parcel/watcher@^2.4.1", "@parcel/watcher@^2.5.6": +"@parcel/watcher@^2.4.1": version "2.5.6" resolved "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.6.tgz" integrity sha512-tmmZ3lQxAe/k/+rNnXQRawJ4NjxO2hqiOLTHvWchtGZULp4RyFeh6aU4XdOYBFe2KE1oShQTv4AblOs2iOrNnQ== @@ -1817,37 +1046,11 @@ "@parcel/watcher-win32-ia32" "2.5.6" "@parcel/watcher-win32-x64" "2.5.6" -"@pkgjs/parseargs@^0.11.0": - version "0.11.0" - resolved "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz" - integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg== - "@pkgr/core@^0.2.9": version "0.2.9" resolved "https://registry.npmjs.org/@pkgr/core/-/core-0.2.9.tgz" integrity sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA== -"@poppinss/colors@^4.1.5": - version "4.1.6" - resolved "https://registry.npmjs.org/@poppinss/colors/-/colors-4.1.6.tgz" - integrity sha512-H9xkIdFswbS8n1d6vmRd8+c10t2Qe+rZITbbDHHkQixH5+2x1FDGmi/0K+WgWiqQFKPSlIYB7jlH6Kpfn6Fleg== - dependencies: - kleur "^4.1.5" - -"@poppinss/dumper@^0.6.4": - version "0.6.5" - resolved "https://registry.npmjs.org/@poppinss/dumper/-/dumper-0.6.5.tgz" - integrity sha512-NBdYIb90J7LfOI32dOewKI1r7wnkiH6m920puQ3qHUeZkxNkQiFnXVWoE6YtFSv6QOiPPf7ys6i+HWWecDz7sw== - dependencies: - "@poppinss/colors" "^4.1.5" - "@sindresorhus/is" "^7.0.2" - supports-color "^10.0.0" - -"@poppinss/exception@^1.2.2": - version "1.2.3" - resolved "https://registry.npmjs.org/@poppinss/exception/-/exception-1.2.3.tgz" - integrity sha512-dCED+QRChTVatE9ibtoaxc+WkdzOSjYTKi/+uacHWIsfodVfpsueo3+DKpgU5Px8qXjgmXkSvhXvSCz3fnP9lw== - "@puppeteer/browsers@2.13.0": version "2.13.0" resolved "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-2.13.0.tgz" @@ -1885,7 +1088,7 @@ resolved "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.3.tgz" integrity sha512-eybk3TjzzzV97Dlj5c+XrBFW57eTNhzod66y9HrBlzJ6NsCrWCp/2kaPS3K9wJmurBC0Tdw4yPjXKZqlznim3Q== -"@rollup/pluginutils@^5.1.3", "@rollup/pluginutils@^5.3.0": +"@rollup/pluginutils@^5.3.0": version "5.3.0" resolved "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.3.0.tgz" integrity sha512-5EdhGZtnu3V88ces7s53hhfK5KSASnJZv8Lulpc04cWO3REESroJXg73DFsOmgbU2BhwV0E20bu2IDZb3VKW4Q== @@ -2083,24 +1286,6 @@ resolved "https://registry.npmjs.org/@shikijs/vscode-textmate/-/vscode-textmate-10.0.2.tgz" integrity sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg== -"@sindresorhus/is@^4.0.0": - version "4.6.0" - resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-4.6.0.tgz#3c7c9c46e678feefe7a2e5bb609d3dbd665ffb3f" - integrity sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw== - -"@sindresorhus/is@^7.0.2": - version "7.2.0" - resolved "https://registry.npmjs.org/@sindresorhus/is/-/is-7.2.0.tgz" - integrity sha512-P1Cz1dWaFfR4IR+U13mqqiGsLFf1KbayybWwdd2vfctdV6hDpUkgCY0nKOLLTMSoRd/jJNjtbqzf13K8DCCXQw== - -"@so-ric/colorspace@^1.1.6": - version "1.1.6" - resolved "https://registry.npmjs.org/@so-ric/colorspace/-/colorspace-1.1.6.tgz" - integrity sha512-/KiKkpHNOBgkFJwu9sh48LkHSMYGyuTcSFK/qMBdnOAlrRJzRSXAOFB5qwzaVQuDl8wAvHVMkaASQDReTahxuw== - dependencies: - color "^5.0.2" - text-hex "1.0.x" - "@sparticuz/chromium@^148.0.0": version "148.0.0" resolved "https://registry.npmjs.org/@sparticuz/chromium/-/chromium-148.0.0.tgz" @@ -2108,11 +1293,6 @@ dependencies: tar-fs "^3.1.2" -"@speed-highlight/core@^1.2.7": - version "1.2.15" - resolved "https://registry.npmjs.org/@speed-highlight/core/-/core-1.2.15.tgz" - integrity sha512-BMq1K3DsElxDWawkX6eLg9+CKJrTVGCBAWVuHXVUV2u0s2711qiChLSId6ikYPfxhdYocLNt3wWwSvDiTvFabw== - "@standard-schema/spec@^1.0.0": version "1.1.0" resolved "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz" @@ -2123,7 +1303,7 @@ resolved "https://registry.npmjs.org/@standard-schema/utils/-/utils-0.3.0.tgz" integrity sha512-e7Mew686owMaPJVNNLs55PUvgz371nKgwsc4vxE49zsODpJEnxgxRo2y/OKrqueavXgZNMDVj3DdHFlaSAeU8g== -"@sveltejs/acorn-typescript@^1.0.5", "@sveltejs/acorn-typescript@^1.0.9": +"@sveltejs/acorn-typescript@^1.0.5": version "1.0.9" resolved "https://registry.npmjs.org/@sveltejs/acorn-typescript/-/acorn-typescript-1.0.9.tgz" integrity sha512-lVJX6qEgs/4DOcRTpo56tmKzVPtoWAaVbL4hfO7t7NVwl9AAXzQR6cihesW1BmNMPl+bK6dreu2sOKBP2Q9CIA== @@ -2146,13 +1326,6 @@ obug "^2.1.0" vitefu "^1.1.1" -"@szmarczak/http-timer@^4.0.5": - version "4.0.6" - resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-4.0.6.tgz#b4a914bb62e7c272d4e5989fe4440f812ab1d807" - integrity sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w== - dependencies: - defer-to-connect "^2.0.0" - "@tootallnate/quickjs-emscripten@^0.23.0": version "0.23.0" resolved "https://registry.npmjs.org/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz" @@ -2191,16 +1364,6 @@ dependencies: "@babel/types" "^7.28.2" -"@types/cacheable-request@^6.0.1": - version "6.0.3" - resolved "https://registry.yarnpkg.com/@types/cacheable-request/-/cacheable-request-6.0.3.tgz#a430b3260466ca7b5ca5bfd735693b36e7a9d183" - integrity sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw== - dependencies: - "@types/http-cache-semantics" "*" - "@types/keyv" "^3.1.4" - "@types/node" "*" - "@types/responselike" "^1.0.0" - "@types/d3-array@^3.0.3": version "3.2.2" resolved "https://registry.npmjs.org/@types/d3-array/-/d3-array-3.2.2.tgz" @@ -2276,23 +1439,11 @@ dependencies: "@types/unist" "*" -"@types/http-cache-semantics@*": - version "4.2.0" - resolved "https://registry.yarnpkg.com/@types/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz#f6a7788f438cbfde15f29acad46512b4c01913b3" - integrity sha512-L3LgimLHXtGkWikKnsPg0/VFx9OGZaC+eN1u4r+OB1XRqH3meBIAVC2zr1WdMH+RHmnRkqliQAOHNJ/E0j/e0Q== - "@types/json-schema@^7.0.15": version "7.0.15" resolved "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz" integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== -"@types/keyv@^3.1.4": - version "3.1.4" - resolved "https://registry.yarnpkg.com/@types/keyv/-/keyv-3.1.4.tgz#3ccdb1c6751b0c7e52300bcdacd5bcbf8faa75b6" - integrity sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg== - dependencies: - "@types/node" "*" - "@types/mdast@^4.0.0": version "4.0.4" resolved "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz" @@ -2326,11 +1477,6 @@ dependencies: undici-types "~7.16.0" -"@types/normalize-package-data@^2.4.3": - version "2.4.4" - resolved "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz" - integrity sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA== - "@types/parse-json@^4.0.0": version "4.0.2" resolved "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz" @@ -2348,18 +1494,6 @@ dependencies: csstype "^3.2.2" -"@types/responselike@^1.0.0": - version "1.0.3" - resolved "https://registry.yarnpkg.com/@types/responselike/-/responselike-1.0.3.tgz#cc29706f0a397cfe6df89debfe4bf5cea159db50" - integrity sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw== - dependencies: - "@types/node" "*" - -"@types/retry@0.12.2": - version "0.12.2" - resolved "https://registry.npmjs.org/@types/retry/-/retry-0.12.2.tgz" - integrity sha512-XISRgDJ2Tc5q4TRqvgJtzsRkFYNJzZrhTdtMoGVBttwzzQJkPnS3WWTFc7kuDRoPtPakl+T+OfdEUjYJj7Jbow== - "@types/sax@^1.2.1": version "1.2.7" resolved "https://registry.npmjs.org/@types/sax/-/sax-1.2.7.tgz" @@ -2367,11 +1501,6 @@ dependencies: "@types/node" "*" -"@types/triple-beam@^1.3.2": - version "1.3.5" - resolved "https://registry.npmjs.org/@types/triple-beam/-/triple-beam-1.3.5.tgz" - integrity sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw== - "@types/trusted-types@^2.0.7": version "2.0.7" resolved "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz" @@ -2432,7 +1561,7 @@ resolved "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.59.2.tgz" integrity sha512-e82GVOE8Ps3E++Egvb6Y3Dw0S10u8NkQ9KXmtRhCWJJ8kDhOJTvtMAWnFL16kB1583goCWXsr0NieKCZMs2/0Q== -"@typescript-eslint/typescript-estree@8.59.2", "@typescript-eslint/typescript-estree@^8.58.2": +"@typescript-eslint/typescript-estree@8.59.2": version "8.59.2" resolved "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.59.2.tgz" integrity sha512-o0XPGNwcWw+FIwStOWn+BwBuEmL6QXP0rsvAFg7ET1dey1Nr6Wb1ac8p5HEsK0ygO/6mUxlk+YWQD9xcb/nnXg== @@ -2460,70 +1589,7 @@ resolved "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz" integrity sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g== -"@vercel/analytics@^1.6.1": - version "1.6.1" - resolved "https://registry.npmjs.org/@vercel/analytics/-/analytics-1.6.1.tgz" - integrity sha512-oH9He/bEM+6oKlv3chWuOOcp8Y6fo6/PSro8hEkgCW3pu9/OiCXiUpRUogDh3Fs3LH2sosDrx8CxeOLBEE+afg== - -"@vercel/functions@^3.4.3": - version "3.5.0" - resolved "https://registry.npmjs.org/@vercel/functions/-/functions-3.5.0.tgz" - integrity sha512-+RokZ+4gkYyOsKBuJ29cQ8iSZG123LLJbZfPry20kkTgrN9U0277La4feP4DnWVo3sGoYa4plCEKY9XKUYoX9g== - dependencies: - "@vercel/oidc" "3.4.0" - -"@vercel/nft@0.29.4": - version "0.29.4" - resolved "https://registry.npmjs.org/@vercel/nft/-/nft-0.29.4.tgz" - integrity sha512-6lLqMNX3TuycBPABycx7A9F1bHQR7kiQln6abjFbPrf5C/05qHM9M5E4PeTE59c7z8g6vHnx1Ioihb2AQl7BTA== - dependencies: - "@mapbox/node-pre-gyp" "^2.0.0" - "@rollup/pluginutils" "^5.1.3" - acorn "^8.6.0" - acorn-import-attributes "^1.9.5" - async-sema "^3.1.1" - bindings "^1.4.0" - estree-walker "2.0.2" - glob "^10.4.5" - graceful-fs "^4.2.9" - node-gyp-build "^4.2.2" - picomatch "^4.0.2" - resolve-from "^5.0.0" - -"@vercel/nft@^1.3.2": - version "1.5.0" - resolved "https://registry.npmjs.org/@vercel/nft/-/nft-1.5.0.tgz" - integrity sha512-IWTDeIoWhQ7ZtRO/JRKH+jhmeQvZYhtGPmzw/QGDY+wDCQqfm25P9yIdoAFagu4fWsK4IwZXDFIjrmp5rRm/sA== - dependencies: - "@mapbox/node-pre-gyp" "^2.0.0" - "@rollup/pluginutils" "^5.1.3" - acorn "^8.6.0" - acorn-import-attributes "^1.9.5" - async-sema "^3.1.1" - bindings "^1.4.0" - estree-walker "2.0.2" - glob "^13.0.0" - graceful-fs "^4.2.9" - node-gyp-build "^4.2.2" - picomatch "^4.0.2" - resolve-from "^5.0.0" - -"@vercel/oidc@3.4.0": - version "3.4.0" - resolved "https://registry.npmjs.org/@vercel/oidc/-/oidc-3.4.0.tgz" - integrity sha512-p0sKfHkfRmMaqqDwNL4tjnX9TgRrLMlEtUjIxfrEns8pOxz1R9ztqOVI+ehqiq93/2/HnfPe/UBZkfAZwnx0UA== - -"@vercel/routing-utils@^5.3.3": - version "5.3.3" - resolved "https://registry.npmjs.org/@vercel/routing-utils/-/routing-utils-5.3.3.tgz" - integrity sha512-KYm2sLNUD48gDScv8ob4ejc3Gww2jcJyW80hTdYlenAPz/5BQar1Gyh38xrUuZ532TUwSb5mV1uRbAuiykq0EQ== - dependencies: - path-to-regexp "6.1.0" - path-to-regexp-updated "npm:path-to-regexp@6.3.0" - optionalDependencies: - ajv "^6.12.3" - -"@vitejs/plugin-react@^5.2.0": +"@vitejs/plugin-react@^5.0.4", "@vitejs/plugin-react@^5.2.0": version "5.2.0" resolved "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-5.2.0.tgz" integrity sha512-YmKkfhOAi3wsB1PhJq5Scj3GXMn3WvtQ/JC0xoopuHoXSdmtdStOpFrYaT1kie2YgFBcIe64ROzMYRjCrYOdYw== @@ -2608,109 +1674,6 @@ resolved "https://registry.npmjs.org/@vscode/l10n/-/l10n-0.0.18.tgz" integrity sha512-KYSIHVmslkaCDyw013pphY+d7x1qV8IZupYfeIfzNA+nsaWHbn5uPuQRvdRFsa9zFzGeudPuoGoZ1Op4jrJXIQ== -"@vue/compiler-core@3.5.33": - version "3.5.33" - resolved "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.33.tgz" - integrity sha512-3PZLQwFw4Za3TC8t0FvTy3wI16Kt+pmwcgNZca4Pj9iWL2E72a/gZlpBtAJvEdDMdCxdG/qq0C7PN0bsJuv0Rw== - dependencies: - "@babel/parser" "^7.29.2" - "@vue/shared" "3.5.33" - entities "^7.0.1" - estree-walker "^2.0.2" - source-map-js "^1.2.1" - -"@vue/compiler-dom@3.5.33": - version "3.5.33" - resolved "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.33.tgz" - integrity sha512-PXq0yrfCLzzL07rbXO4awtXY1Z06LG2eu6Adg3RJFa/j3Cii217XxxLXG22N330gw7GmALCY0Z8RgXEviwgpjA== - dependencies: - "@vue/compiler-core" "3.5.33" - "@vue/shared" "3.5.33" - -"@vue/compiler-sfc@^3.5.32": - version "3.5.33" - resolved "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.33.tgz" - integrity sha512-UTUvRO9cY+rROrx/pvN9P5Z7FgA6QGfokUCfhQE4EnmUj3rVnK+CHI0LsEO1pg+I7//iRYMUfcNcCPe7tg0CoA== - dependencies: - "@babel/parser" "^7.29.2" - "@vue/compiler-core" "3.5.33" - "@vue/compiler-dom" "3.5.33" - "@vue/compiler-ssr" "3.5.33" - "@vue/shared" "3.5.33" - estree-walker "^2.0.2" - magic-string "^0.30.21" - postcss "^8.5.10" - source-map-js "^1.2.1" - -"@vue/compiler-ssr@3.5.33": - version "3.5.33" - resolved "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.33.tgz" - integrity sha512-IErjYdnj1qIupG5xxiVIYiiRvDhGWV4zuh/RCrwfYpuL+HWQzeU6lCk/nF9r7olWMnjKxCAkOctT2qFWFkzb1A== - dependencies: - "@vue/compiler-dom" "3.5.33" - "@vue/shared" "3.5.33" - -"@vue/shared@3.5.33": - version "3.5.33" - resolved "https://registry.npmjs.org/@vue/shared/-/shared-3.5.33.tgz" - integrity sha512-5vR2QIlmaLG77Ygd4pMP6+SGQ5yox9VhtnbDWTy9DzMzdmeLxZ1QqxrywEZ9sa1AVubfIJyaCG3ytyWU81ufcQ== - -"@whatwg-node/disposablestack@^0.0.6": - version "0.0.6" - resolved "https://registry.npmjs.org/@whatwg-node/disposablestack/-/disposablestack-0.0.6.tgz" - integrity sha512-LOtTn+JgJvX8WfBVJtF08TGrdjuFzGJc4mkP8EdDI8ADbvO7kiexYep1o8dwnt0okb0jYclCDXF13xU7Ge4zSw== - dependencies: - "@whatwg-node/promise-helpers" "^1.0.0" - tslib "^2.6.3" - -"@whatwg-node/fetch@^0.10.13": - version "0.10.13" - resolved "https://registry.npmjs.org/@whatwg-node/fetch/-/fetch-0.10.13.tgz" - integrity sha512-b4PhJ+zYj4357zwk4TTuF2nEe0vVtOrwdsrNo5hL+u1ojXNhh1FgJ6pg1jzDlwlT4oBdzfSwaBwMCtFCsIWg8Q== - dependencies: - "@whatwg-node/node-fetch" "^0.8.3" - urlpattern-polyfill "^10.0.0" - -"@whatwg-node/node-fetch@^0.8.3": - version "0.8.5" - resolved "https://registry.npmjs.org/@whatwg-node/node-fetch/-/node-fetch-0.8.5.tgz" - integrity sha512-4xzCl/zphPqlp9tASLVeUhB5+WJHbuWGYpfoC2q1qh5dw0AqZBW7L27V5roxYWijPxj4sspRAAoOH3d2ztaHUQ== - dependencies: - "@fastify/busboy" "^3.1.1" - "@whatwg-node/disposablestack" "^0.0.6" - "@whatwg-node/promise-helpers" "^1.3.2" - tslib "^2.6.3" - -"@whatwg-node/promise-helpers@^1.0.0", "@whatwg-node/promise-helpers@^1.2.1", "@whatwg-node/promise-helpers@^1.3.2": - version "1.3.2" - resolved "https://registry.npmjs.org/@whatwg-node/promise-helpers/-/promise-helpers-1.3.2.tgz" - integrity sha512-Nst5JdK47VIl9UcGwtv2Rcgyn5lWtZ0/mhRQ4G8NN2isxpq2TO30iqHzmwoJycjWuyUfg3GFXqP/gFHXeV57IA== - dependencies: - tslib "^2.6.3" - -"@whatwg-node/server@^0.10.0": - version "0.10.18" - resolved "https://registry.npmjs.org/@whatwg-node/server/-/server-0.10.18.tgz" - integrity sha512-kMwLlxUbduttIgaPdSkmEarFpP+mSY8FEm+QWMBRJwxOHWkri+cxd8KZHO9EMrB9vgUuz+5WEaCawaL5wGVoXg== - dependencies: - "@envelop/instrumentation" "^1.0.0" - "@whatwg-node/disposablestack" "^0.0.6" - "@whatwg-node/fetch" "^0.10.13" - "@whatwg-node/promise-helpers" "^1.3.2" - tslib "^2.6.3" - -abbrev@^3.0.0: - version "3.0.1" - resolved "https://registry.npmjs.org/abbrev/-/abbrev-3.0.1.tgz" - integrity sha512-AO2ac6pjRB3SJmGJo+v5/aK6Omggp6fsLrs6wN9bd35ulu4cCwaAU9+7ZhXjeqHVkaHThLuzH0nZr0YpCDhygg== - -abort-controller@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz" - integrity sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg== - dependencies: - event-target-shim "^5.0.0" - accepts@^2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz" @@ -2719,17 +1682,12 @@ accepts@^2.0.0: mime-types "^3.0.0" negotiator "^1.0.0" -acorn-import-attributes@^1.9.5: - version "1.9.5" - resolved "https://registry.npmjs.org/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz" - integrity sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ== - acorn-jsx@^5.3.2: version "5.3.2" resolved "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz" integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== -acorn@^8.12.1, acorn@^8.14.0, acorn@^8.15.0, acorn@^8.16.0, acorn@^8.6.0: +acorn@^8.12.1, acorn@^8.15.0, acorn@^8.16.0: version "8.16.0" resolved "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz" integrity sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw== @@ -2751,12 +1709,7 @@ ajv-draft-04@^1.0.0: resolved "https://registry.npmjs.org/ajv-draft-04/-/ajv-draft-04-1.0.0.tgz" integrity sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw== -ajv-errors@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/ajv-errors/-/ajv-errors-3.0.0.tgz" - integrity sha512-V3wD15YHfHz6y0KdhYFjyy9vWtEVALT9UrxfN3zqlI6dMioHnJrqOYfyPKol3oqrnCM9uwkcdCwkJ0WUcbLMTQ== - -ajv@^6.12.3, ajv@^6.14.0: +ajv@^6.14.0: version "6.15.0" resolved "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz" integrity sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw== @@ -2766,7 +1719,7 @@ ajv@^6.12.3, ajv@^6.14.0: json-schema-traverse "^0.4.1" uri-js "^4.2.2" -ajv@^8.11.2, ajv@^8.17.1: +ajv@^8.17.1: version "8.20.0" resolved "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz" integrity sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA== @@ -2781,11 +1734,6 @@ ansi-regex@^5.0.1: resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz" integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== -ansi-regex@^6.2.2: - version "6.2.2" - resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz" - integrity sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg== - ansi-styles@^4.0.0, ansi-styles@^4.1.0: version "4.3.0" resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz" @@ -2793,16 +1741,6 @@ ansi-styles@^4.0.0, ansi-styles@^4.1.0: dependencies: color-convert "^2.0.1" -ansi-styles@^6.1.0: - version "6.2.3" - resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz" - integrity sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg== - -ansis@^4.1.0: - version "4.2.0" - resolved "https://registry.npmjs.org/ansis/-/ansis-4.2.0.tgz" - integrity sha512-HqZ5rWlFjGiV0tDm3UxxgNRqsOTniqoKZu0pIAfh7TZQMGuZK+hH0drySty0si0QXj1ieop4+SkSfPZBPPkHig== - anymatch@^3.1.3, anymatch@~3.1.2: version "3.1.3" resolved "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz" @@ -2811,32 +1749,6 @@ anymatch@^3.1.3, anymatch@~3.1.2: normalize-path "^3.0.0" picomatch "^2.0.4" -archiver-utils@^5.0.0, archiver-utils@^5.0.2: - version "5.0.2" - resolved "https://registry.npmjs.org/archiver-utils/-/archiver-utils-5.0.2.tgz" - integrity sha512-wuLJMmIBQYCsGZgYLTy5FIB2pF6Lfb6cXMSF8Qywwk3t20zWnAi7zLcQFdKQmIB8wyZpY5ER38x08GbwtR2cLA== - dependencies: - glob "^10.0.0" - graceful-fs "^4.2.0" - is-stream "^2.0.1" - lazystream "^1.0.0" - lodash "^4.17.15" - normalize-path "^3.0.0" - readable-stream "^4.0.0" - -archiver@^7.0.0: - version "7.0.1" - resolved "https://registry.npmjs.org/archiver/-/archiver-7.0.1.tgz" - integrity sha512-ZcbTaIqJOfCc03QwD468Unz/5Ir8ATtvAHsK+FdXbDIbGfihqh9mrvdcYunQzqn4HrvWWaFyaxJhGZagaJJpPQ== - dependencies: - archiver-utils "^5.0.2" - async "^3.2.4" - buffer-crc32 "^1.0.0" - readable-stream "^4.0.0" - readdir-glob "^1.1.2" - tar-stream "^3.0.0" - zip-stream "^6.0.1" - arg@^5.0.0: version "5.0.2" resolved "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz" @@ -2857,47 +1769,11 @@ aria-query@^5.3.2: resolved "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz" integrity sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw== -array-buffer-byte-length@^1.0.1, array-buffer-byte-length@^1.0.2: - version "1.0.2" - resolved "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz" - integrity sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw== - dependencies: - call-bound "^1.0.3" - is-array-buffer "^3.0.5" - array-iterate@^2.0.0: version "2.0.1" resolved "https://registry.npmjs.org/array-iterate/-/array-iterate-2.0.1.tgz" integrity sha512-I1jXZMjAgCMmxT4qxXfPXa6SthSoE8h6gkSI9BGGNv8mP8G/v0blc+qFnZu6K42vTOiuME596QaLO0TP3Lk0xg== -array.prototype.flatmap@^1.3.3: - version "1.3.3" - resolved "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.3.tgz" - integrity sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg== - dependencies: - call-bind "^1.0.8" - define-properties "^1.2.1" - es-abstract "^1.23.5" - es-shim-unscopables "^1.0.2" - -arraybuffer.prototype.slice@^1.0.4: - version "1.0.4" - resolved "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz" - integrity sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ== - dependencies: - array-buffer-byte-length "^1.0.1" - call-bind "^1.0.8" - define-properties "^1.2.1" - es-abstract "^1.23.5" - es-errors "^1.3.0" - get-intrinsic "^1.2.6" - is-array-buffer "^3.0.4" - -ast-module-types@^6.0.1: - version "6.0.1" - resolved "https://registry.npmjs.org/ast-module-types/-/ast-module-types-6.0.1.tgz" - integrity sha512-WHw67kLXYbZuHTmcdbIrVArCq5wxo6NEuj3hiYAWr8mwJeC+C2mMCIBIWCiDoCye/OF/xelc+teJ1ERoWmnEIA== - ast-types@^0.13.4: version "0.13.4" resolved "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz" @@ -2993,38 +1869,11 @@ astrojs-compiler-sync@^1.0.0: dependencies: synckit "^0.11.0" -async-function@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz" - integrity sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA== - -async-sema@^3.1.1: - version "3.1.1" - resolved "https://registry.npmjs.org/async-sema/-/async-sema-3.1.1.tgz" - integrity sha512-tLRNUXati5MFePdAk8dw7Qt7DpxPB60ofAgn8WRhW6a2rcimZnYBP9oxHiv0OHy+Wz7kPMG+t4LGdt31+4EmGg== - -async@^3.2.3, async@^3.2.4: - version "3.2.6" - resolved "https://registry.npmjs.org/async/-/async-3.2.6.tgz" - integrity sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA== - -available-typed-arrays@^1.0.7: - version "1.0.7" - resolved "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz" - integrity sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ== - dependencies: - possible-typed-array-names "^1.0.0" - axobject-query@^4.1.0: version "4.1.0" resolved "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz" integrity sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ== -b4a@^1.6.4: - version "1.8.1" - resolved "https://registry.npmjs.org/b4a/-/b4a-1.8.1.tgz" - integrity sha512-aiqre1Nr0B/6DgE2N5vwTc+2/oQZ4Wh1t4NznYY4E00y8LCt6NqdRv81so00oo27D8MVKTpUa/MwUUtBLXCoDw== - babel-plugin-macros@^3.1.0: version "3.1.0" resolved "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz" @@ -3049,53 +1898,10 @@ balanced-match@^4.0.2: resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz" integrity sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA== -bare-events@^2.5.4, bare-events@^2.7.0: - version "2.8.2" - resolved "https://registry.npmjs.org/bare-events/-/bare-events-2.8.2.tgz" - integrity sha512-riJjyv1/mHLIPX4RwiK+oW9/4c3TEUeORHKefKAKnZ5kyslbN+HXowtbaVEqt4IMUB7OXlfixcs6gsFeo/jhiQ== - -bare-fs@^4.5.5: - version "4.7.1" - resolved "https://registry.npmjs.org/bare-fs/-/bare-fs-4.7.1.tgz" - integrity sha512-WDRsyVN52eAx/lBamKD6uyw8H4228h/x0sGGGegOamM2cd7Pag88GfMQalobXI+HaEUxpCkbKQUDOQqt9wawRw== - dependencies: - bare-events "^2.5.4" - bare-path "^3.0.0" - bare-stream "^2.6.4" - bare-url "^2.2.2" - fast-fifo "^1.3.2" - -bare-os@^3.0.1: - version "3.9.1" - resolved "https://registry.npmjs.org/bare-os/-/bare-os-3.9.1.tgz" - integrity sha512-6M5XjcnsygQNPMCMPXSK379xrJFiZ/AEMNBmFEmQW8d/789VQATvriyi5r0HYTL9TkQ26rn3kgdTG3aisbrXkQ== - -bare-path@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/bare-path/-/bare-path-3.0.0.tgz" - integrity sha512-tyfW2cQcB5NN8Saijrhqn0Zh7AnFNsnczRcuWODH0eYAXBsJ5gVxAUuNr7tsHSC6IZ77cA0SitzT+s47kot8Mw== - dependencies: - bare-os "^3.0.1" - -bare-stream@^2.6.4: - version "2.13.1" - resolved "https://registry.npmjs.org/bare-stream/-/bare-stream-2.13.1.tgz" - integrity sha512-Vp0cnjYyrEC4whYTymQ+YZi6pBpfiICZO3cfRG8sy67ZNWe951urv1x4eW1BKNngw3U+3fPYb5JQvHbCtxH7Ow== - dependencies: - streamx "^2.25.0" - teex "^1.0.1" - -bare-url@^2.2.2: - version "2.4.2" - resolved "https://registry.npmjs.org/bare-url/-/bare-url-2.4.2.tgz" - integrity sha512-/9a2j4ac6ckpmAHvod/ob7x439OAHst/drc2Clnq+reRYd/ovddwcF4LfoxHyNk5AuGBnPg+HqFjmE/Zpq6v0A== - dependencies: - bare-path "^3.0.0" - -base64-js@^1.3.1: - version "1.5.1" - resolved "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz" - integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== +base64-js@^1.3.1: + version "1.5.1" + resolved "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz" + integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== baseline-browser-mapping@^2.10.12: version "2.10.27" @@ -3107,29 +1913,11 @@ basic-ftp@^5.0.2, basic-ftp@^5.2.0: resolved "https://registry.yarnpkg.com/basic-ftp/-/basic-ftp-5.3.1.tgz#3148ee9af43c0522514a4f973fecb1d3cbb6d71e" integrity sha512-bopVNp6ugyA150DDuZfPFdt1KZ5a94ZDiwX4hMgZDzF+GttD80lEy8kj98kbyhLXnPvhtIo93mdnLIjpCAeeOw== -better-ajv-errors@^1.2.0: - version "1.2.0" - resolved "https://registry.npmjs.org/better-ajv-errors/-/better-ajv-errors-1.2.0.tgz" - integrity sha512-UW+IsFycygIo7bclP9h5ugkNH8EjCSgqyFB/yQ4Hqqa1OEYDtb0uFIkYE0b6+CjkgJYVM5UKI/pJPxjYe9EZlA== - dependencies: - "@babel/code-frame" "^7.16.0" - "@humanwhocodes/momoa" "^2.0.2" - chalk "^4.1.2" - jsonpointer "^5.0.0" - leven "^3.1.0 < 4" - binary-extensions@^2.0.0: version "2.3.0" resolved "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz" integrity sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw== -bindings@^1.4.0: - version "1.5.0" - resolved "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz" - integrity sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ== - dependencies: - file-uri-to-path "1.0.0" - bl@^4.0.3: version "4.1.0" resolved "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz" @@ -3139,11 +1927,6 @@ bl@^4.0.3: inherits "^2.0.4" readable-stream "^3.4.0" -blake3-wasm@2.1.5: - version "2.1.5" - resolved "https://registry.npmjs.org/blake3-wasm/-/blake3-wasm-2.1.5.tgz" - integrity sha512-F1+K8EbfOZE49dtoPtmxUQrpXaBIl3ICvasLh+nJta0xkz+9kF/7uet9fLnwKqhDrmj6g+6K3Tw9yQPUg2ka5g== - body-parser@^2.2.1: version "2.2.2" resolved "https://registry.npmjs.org/body-parser/-/body-parser-2.2.2.tgz" @@ -3164,15 +1947,7 @@ boolbase@^1.0.0: resolved "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz" integrity sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww== -brace-expansion@^1.1.7: - version "1.1.14" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.14.tgz#d9de602370d91347cd9ddad1224d4fd701eb348b" - integrity sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g== - dependencies: - balanced-match "^1.0.0" - concat-map "0.0.1" - -brace-expansion@^2.0.1, brace-expansion@^2.0.2: +brace-expansion@^2.0.1: version "2.1.0" resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.0.tgz" integrity sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w== @@ -3204,26 +1979,11 @@ browserslist@^4.24.0: node-releases "^2.0.36" update-browserslist-db "^1.2.3" -buffer-crc32@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-1.0.0.tgz" - integrity sha512-Db1SbgBS/fg/392AblrMJk97KggmvYhr4pB5ZIMTWtaivCPMWLkmb7m21cJvpvgK+J3nsU2CmmixNBZx4vFj/w== - buffer-crc32@~0.2.3: version "0.2.13" resolved "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz" integrity sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ== -buffer-equal-constant-time@^1.0.1: - version "1.0.1" - resolved "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz" - integrity sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA== - -buffer-from@^1.0.0: - version "1.1.2" - resolved "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz" - integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== - buffer@^5.2.1, buffer@^5.5.0: version "5.7.1" resolved "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz" @@ -3232,42 +1992,11 @@ buffer@^5.2.1, buffer@^5.5.0: base64-js "^1.3.1" ieee754 "^1.1.13" -buffer@^6.0.3: - version "6.0.3" - resolved "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz" - integrity sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA== - dependencies: - base64-js "^1.3.1" - ieee754 "^1.2.1" - bytes@^3.1.2, bytes@~3.1.2: version "3.1.2" resolved "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz" integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== -cacheable-lookup@^5.0.3: - version "5.0.4" - resolved "https://registry.yarnpkg.com/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz#5a6b865b2c44357be3d5ebc2a467b032719a7005" - integrity sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA== - -cacheable-request@^7.0.2: - version "7.0.4" - resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-7.0.4.tgz#7a33ebf08613178b403635be7b899d3e69bbe817" - integrity sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg== - dependencies: - clone-response "^1.0.2" - get-stream "^5.1.0" - http-cache-semantics "^4.0.0" - keyv "^4.0.0" - lowercase-keys "^2.0.0" - normalize-url "^6.0.1" - responselike "^2.0.0" - -cachedir@^2.3.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/cachedir/-/cachedir-2.4.0.tgz#7fef9cf7367233d7c88068fe6e34ed0d355a610d" - integrity sha512-9EtFOZR8g22CL7BWjJ9BUx1+A/djkofnyW3aOXZORNW2kxoUpx2h+uN2cOqwPmFhnpVmxg+KW2OjOSgChTEvsQ== - call-bind-apply-helpers@^1.0.1, call-bind-apply-helpers@^1.0.2: version "1.0.2" resolved "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz" @@ -3276,17 +2005,7 @@ call-bind-apply-helpers@^1.0.1, call-bind-apply-helpers@^1.0.2: es-errors "^1.3.0" function-bind "^1.1.2" -call-bind@^1.0.7, call-bind@^1.0.8, call-bind@^1.0.9: - version "1.0.9" - resolved "https://registry.npmjs.org/call-bind/-/call-bind-1.0.9.tgz" - integrity sha512-a/hy+pNsFUTR+Iz8TCJvXudKVLAnz/DyeSUo10I5yvFDQJBFU2s9uqQpoSrJlroHUKoKqzg+epxyP9lqFdzfBQ== - dependencies: - call-bind-apply-helpers "^1.0.2" - es-define-property "^1.0.1" - get-intrinsic "^1.3.0" - set-function-length "^1.2.2" - -call-bound@^1.0.2, call-bound@^1.0.3, call-bound@^1.0.4: +call-bound@^1.0.2: version "1.0.4" resolved "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz" integrity sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg== @@ -3294,11 +2013,6 @@ call-bound@^1.0.2, call-bound@^1.0.3, call-bound@^1.0.4: call-bind-apply-helpers "^1.0.2" get-intrinsic "^1.3.0" -callsite@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz" - integrity sha512-0vdNRFXn5q+dtOqjfFtmtlI9N2eVZ7LMyEV2iKC5mEEFvSg/69Ml6b/WU2qF8W1nLRa0wiSrDT3Y5jOHZCwKPQ== - callsites@^3.0.0: version "3.1.0" resolved "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz" @@ -3314,7 +2028,7 @@ ccount@^2.0.0: resolved "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz" integrity sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg== -chalk@4.1.2, chalk@^4.1.2: +chalk@4.1.2: version "4.1.2" resolved "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz" integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== @@ -3322,11 +2036,6 @@ chalk@4.1.2, chalk@^4.1.2: ansi-styles "^4.1.0" supports-color "^7.1.0" -chalk@^5.0.0: - version "5.6.2" - resolved "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz" - integrity sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA== - character-entities-html4@^2.0.0: version "2.1.0" resolved "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-2.1.0.tgz" @@ -3386,7 +2095,7 @@ chokidar@^3.5.2: optionalDependencies: fsevents "~2.3.2" -chokidar@^4.0.0, chokidar@^4.0.1, chokidar@^4.0.3: +chokidar@^4.0.0, chokidar@^4.0.3: version "4.0.3" resolved "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz" integrity sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA== @@ -3405,11 +2114,6 @@ chownr@^1.1.1: resolved "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz" integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg== -chownr@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz" - integrity sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g== - chromium-bidi@0.4.5: version "0.4.5" resolved "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-0.4.5.tgz" @@ -3425,42 +2129,11 @@ chromium-bidi@14.0.0: mitt "^3.0.1" zod "^3.24.1" -chromium@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/chromium/-/chromium-3.0.3.tgz#0f776510d6b2749d3cf5632383c6e15a97390e9c" - integrity sha512-TfbzP/3t38Us5xrbb9x87M/y5I/j3jx0zeJhhQ72gjp6dwJuhVP6hBZnBH4wEg7512VVXk9zCfTuPFOdw7bQqg== - dependencies: - cachedir "^2.3.0" - debug "^4.1.0" - extract-zip "^1.7.0" - got "^11.5.1" - progress "^2.0.3" - rimraf "^2.7.1" - tmp "0.0.33" - tunnel "^0.0.6" - ci-info@^4.4.0: version "4.4.0" resolved "https://registry.npmjs.org/ci-info/-/ci-info-4.4.0.tgz" integrity sha512-77PSwercCZU2Fc4sX94eF8k8Pxte6JAwL4/ICZLFjJLqegs7kCuAsqqj/70NQF6TvDpgFjkubQB2FW2ZZddvQg== -citty@^0.1.5, citty@^0.1.6: - version "0.1.6" - resolved "https://registry.npmjs.org/citty/-/citty-0.1.6.tgz" - integrity sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ== - dependencies: - consola "^3.2.3" - -citty@^0.2.2: - version "0.2.2" - resolved "https://registry.npmjs.org/citty/-/citty-0.2.2.tgz" - integrity sha512-+6vJA3L98yv+IdfKGZHBNiGW5KHn22e/JwID0Strsz8h4S/csAu/OuICwxrg44k5MRiZHWIo8XXuJgQTriRP4w== - -cjs-module-lexer@^1.2.2: - version "1.4.3" - resolved "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.3.tgz" - integrity sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q== - cliui@^8.0.1: version "8.0.1" resolved "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz" @@ -3470,13 +2143,6 @@ cliui@^8.0.1: strip-ansi "^6.0.1" wrap-ansi "^7.0.0" -clone-response@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.3.tgz#af2032aa47816399cf5f0a1d0db902f517abb8c3" - integrity sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA== - dependencies: - mimic-response "^1.0.0" - clsx@^2.1.1: version "2.1.1" resolved "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz" @@ -3489,99 +2155,31 @@ color-convert@^2.0.1: dependencies: color-name "~1.1.4" -color-convert@^3.1.3: - version "3.1.3" - resolved "https://registry.npmjs.org/color-convert/-/color-convert-3.1.3.tgz" - integrity sha512-fasDH2ont2GqF5HpyO4w0+BcewlhHEZOFn9c1ckZdHpJ56Qb7MHhH/IcJZbBGgvdtwdwNbLvxiBEdg336iA9Sg== - dependencies: - color-name "^2.0.0" - -color-name@^1.1.4, color-name@~1.1.4: +color-name@~1.1.4: version "1.1.4" resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== -color-name@^2.0.0: - version "2.1.0" - resolved "https://registry.npmjs.org/color-name/-/color-name-2.1.0.tgz" - integrity sha512-1bPaDNFm0axzE4MEAzKPuqKWeRaT43U/hyxKPBdqTfmPF+d6n7FSoTFxLVULUJOmiLp01KjhIPPH+HrXZJN4Rg== - -color-string@^2.1.3: - version "2.1.4" - resolved "https://registry.npmjs.org/color-string/-/color-string-2.1.4.tgz" - integrity sha512-Bb6Cq8oq0IjDOe8wJmi4JeNn763Xs9cfrBcaylK1tPypWzyoy2G3l90v9k64kjphl/ZJjPIShFztenRomi8WTg== - dependencies: - color-name "^2.0.0" - -color@^5.0.2: - version "5.0.3" - resolved "https://registry.npmjs.org/color/-/color-5.0.3.tgz" - integrity sha512-ezmVcLR3xAVp8kYOm4GS45ZLLgIE6SPAFoduLr6hTDajwb3KZ2F46gulK3XpcwRFb5KKGCSezCBAY4Dw4HsyXA== - dependencies: - color-convert "^3.1.3" - color-string "^2.1.3" - comma-separated-tokens@^2.0.0: version "2.0.3" resolved "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz" integrity sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg== -commander@2, commander@^2.20.3: +commander@2: version "2.20.3" resolved "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz" integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== -commander@^10.0.1: - version "10.0.1" - resolved "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz" - integrity sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug== - commander@^11.1.0: version "11.1.0" resolved "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz" integrity sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ== -commander@^12.1.0: - version "12.1.0" - resolved "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz" - integrity sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA== - common-ancestor-path@^2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/common-ancestor-path/-/common-ancestor-path-2.0.0.tgz" integrity sha512-dnN3ibLeoRf2HNC+OlCiNc5d2zxbLJXOtiZUudNFSXZrNSydxcCsSpRzXwfu7BBWCIfHPw+xTayeBvJCP/D8Ng== -common-path-prefix@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/common-path-prefix/-/common-path-prefix-3.0.0.tgz" - integrity sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w== - -compress-commons@^6.0.2: - version "6.0.2" - resolved "https://registry.npmjs.org/compress-commons/-/compress-commons-6.0.2.tgz" - integrity sha512-6FqVXeETqWPoGcfzrXb37E50NP0LXT8kAMu5ooZayhWWdgEY4lBEEcbQNXtkuKQsGduxiIcI4gOTsxTmuq/bSg== - dependencies: - crc-32 "^1.2.0" - crc32-stream "^6.0.0" - is-stream "^2.0.1" - normalize-path "^3.0.0" - readable-stream "^4.0.0" - -concat-map@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== - -concat-stream@^1.6.2: - version "1.6.2" - resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" - integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw== - dependencies: - buffer-from "^1.0.0" - inherits "^2.0.3" - readable-stream "^2.2.2" - typedarray "^0.0.6" - concurrently@^9.2.1: version "9.2.1" resolved "https://registry.npmjs.org/concurrently/-/concurrently-9.2.1.tgz" @@ -3594,16 +2192,6 @@ concurrently@^9.2.1: tree-kill "1.2.2" yargs "17.7.2" -confbox@^0.1.8: - version "0.1.8" - resolved "https://registry.npmjs.org/confbox/-/confbox-0.1.8.tgz" - integrity sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w== - -consola@^3.2.3, consola@^3.4.2: - version "3.4.2" - resolved "https://registry.npmjs.org/consola/-/consola-3.4.2.tgz" - integrity sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA== - content-disposition@^1.0.0: version "1.1.0" resolved "https://registry.npmjs.org/content-disposition/-/content-disposition-1.1.0.tgz" @@ -3639,24 +2227,11 @@ cookie@^0.7.1: resolved "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz" integrity sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w== -cookie@^1.0.1, cookie@^1.0.2, cookie@^1.1.1: +cookie@^1.0.1, cookie@^1.1.1: version "1.1.1" resolved "https://registry.npmjs.org/cookie/-/cookie-1.1.1.tgz" integrity sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ== -copy-file@^11.0.0: - version "11.1.0" - resolved "https://registry.npmjs.org/copy-file/-/copy-file-11.1.0.tgz" - integrity sha512-X8XDzyvYaA6msMyAM575CUoygY5b44QzLcGRKsK3MFmXcOvQa518dNPLsKYwkYsn72g3EiW+LE0ytd/FlqWmyw== - dependencies: - graceful-fs "^4.2.11" - p-event "^6.0.0" - -core-util-is@~1.0.0: - version "1.0.3" - resolved "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz" - integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== - cors@^2.8.6: version "2.8.6" resolved "https://registry.npmjs.org/cors/-/cors-2.8.6.tgz" @@ -3696,26 +2271,6 @@ cosmiconfig@^9.0.0: js-yaml "^4.1.0" parse-json "^5.2.0" -crc-32@^1.2.0: - version "1.2.2" - resolved "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz" - integrity sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ== - -crc32-stream@^6.0.0: - version "6.0.0" - resolved "https://registry.npmjs.org/crc32-stream/-/crc32-stream-6.0.0.tgz" - integrity sha512-piICUB6ei4IlTv1+653yq5+KoqfBYmj9bw6LqXoOneTMDXk5nM1qt12mFW1caG3LlJXEKW1Bp0WggEmIfQB34g== - dependencies: - crc-32 "^1.2.0" - readable-stream "^4.0.0" - -cron-parser@^4.1.0, cron-parser@^4.9.0: - version "4.9.0" - resolved "https://registry.npmjs.org/cron-parser/-/cron-parser-4.9.0.tgz" - integrity sha512-p0SaNjrHOnQeR8/VnfGbmg9te2kfyYSQ7Sc/j/6DtPL3JQvKxmjO9TSjNFpujqV3vEYYBvNNvXSxzyksBWAx1Q== - dependencies: - luxon "^3.2.1" - cross-fetch@3.1.5: version "3.1.5" resolved "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.5.tgz" @@ -3723,7 +2278,7 @@ cross-fetch@3.1.5: dependencies: node-fetch "2.6.7" -cross-spawn@^7.0.3, cross-spawn@^7.0.6: +cross-spawn@^7.0.6: version "7.0.6" resolved "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz" integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA== @@ -3732,11 +2287,6 @@ cross-spawn@^7.0.3, cross-spawn@^7.0.6: shebang-command "^2.0.0" which "^2.0.1" -"crossws@>=0.2.0 <0.5.0": - version "0.4.5" - resolved "https://registry.npmjs.org/crossws/-/crossws-0.4.5.tgz" - integrity sha512-wUR89x/Rw7/8t+vn0CmGDYM9TD6VtARGb0LD5jq2wjtMy1vCP4M+sm6N6TigWeTYvnA8MoW29NqqXD0ep0rfBA== - crossws@^0.3.5: version "0.3.5" resolved "https://registry.npmjs.org/crossws/-/crossws-0.3.5.tgz" @@ -3781,11 +2331,6 @@ cssesc@^3.0.0: resolved "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz" integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg== -cssfilter@0.0.10: - version "0.0.10" - resolved "https://registry.npmjs.org/cssfilter/-/cssfilter-0.0.10.tgz" - integrity sha512-FAaLDaplstoRsDR8XGYH51znUN0UY7nMc6Z9/fvE8EXGwvJE9hu7W2vHwx1+bd6gCYnln9nLbzxFTrcO9YQDZw== - csso@^5.0.5: version "5.0.5" resolved "https://registry.npmjs.org/csso/-/csso-5.0.5.tgz" @@ -3940,44 +2485,12 @@ d3-zoom@^2.0.0: d3-selection "2" d3-transition "2" -data-uri-to-buffer@^4.0.0: - version "4.0.1" - resolved "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz" - integrity sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A== - data-uri-to-buffer@^6.0.2: version "6.0.2" resolved "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-6.0.2.tgz" integrity sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw== -data-view-buffer@^1.0.2: - version "1.0.2" - resolved "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz" - integrity sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ== - dependencies: - call-bound "^1.0.3" - es-errors "^1.3.0" - is-data-view "^1.0.2" - -data-view-byte-length@^1.0.2: - version "1.0.2" - resolved "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz" - integrity sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ== - dependencies: - call-bound "^1.0.3" - es-errors "^1.3.0" - is-data-view "^1.0.2" - -data-view-byte-offset@^1.0.1: - version "1.0.1" - resolved "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz" - integrity sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ== - dependencies: - call-bound "^1.0.2" - es-errors "^1.3.0" - is-data-view "^1.0.1" - -debug@4, debug@^4, debug@^4.0.0, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4, debug@^4.3.5, debug@^4.4.0, debug@^4.4.3: +debug@4, debug@^4, debug@^4.0.0, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4, debug@^4.4.0, debug@^4.4.3: version "4.4.3" resolved "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz" integrity sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA== @@ -3991,20 +2504,6 @@ debug@4.3.4: dependencies: ms "2.1.2" -debug@^2.6.9: - version "2.6.9" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" - integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== - dependencies: - ms "2.0.0" - -decache@^4.6.2: - version "4.6.2" - resolved "https://registry.npmjs.org/decache/-/decache-4.6.2.tgz" - integrity sha512-2LPqkLeu8XWHU8qNCS3kcF6sCcb5zIzvWaAHYSvPfwhdd7mHuah29NssMzrTYyHN4F5oFy2ko9OBYxegtU0FEw== - dependencies: - callsite "^1.0.0" - decimal.js-light@^2.5.1: version "2.5.1" resolved "https://registry.npmjs.org/decimal.js-light/-/decimal.js-light-2.5.1.tgz" @@ -4017,57 +2516,22 @@ decode-named-character-reference@^1.0.0: dependencies: character-entities "^2.0.0" -decompress-response@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-6.0.0.tgz#ca387612ddb7e104bd16d85aab00d5ecf09c66fc" - integrity sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ== - dependencies: - mimic-response "^3.1.0" - dedent-js@^1.0.1: version "1.0.1" resolved "https://registry.npmjs.org/dedent-js/-/dedent-js-1.0.1.tgz" integrity sha512-OUepMozQULMLUmhxS95Vudo0jb0UchLimi3+pQ2plj61Fcy8axbP9hbiD4Sz6DPqn6XG3kfmziVfQ1rSys5AJQ== -dedent@^1.7.0: - version "1.7.2" - resolved "https://registry.npmjs.org/dedent/-/dedent-1.7.2.tgz" - integrity sha512-WzMx3mW98SN+zn3hgemf4OzdmyNhhhKz5Ay0pUfQiMQ3e1g+xmTJWp/pKdwKVXhdSkAEGIIzqeuWrL3mV/AXbA== - deep-is@^0.1.3: version "0.1.4" resolved "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz" integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== -deepmerge@^4.2.2, deepmerge@^4.3.1: +deepmerge@^4.3.1: version "4.3.1" resolved "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz" integrity sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A== -defer-to-connect@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-2.0.1.tgz#8016bdb4143e4632b77a3449c6236277de520587" - integrity sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg== - -define-data-property@^1.0.1, define-data-property@^1.1.4: - version "1.1.4" - resolved "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz" - integrity sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A== - dependencies: - es-define-property "^1.0.0" - es-errors "^1.3.0" - gopd "^1.0.1" - -define-properties@^1.2.1: - version "1.2.1" - resolved "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz" - integrity sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg== - dependencies: - define-data-property "^1.0.1" - has-property-descriptors "^1.0.0" - object-keys "^1.1.1" - -defu@^6.1.4, defu@^6.1.6, defu@^6.1.7: +defu@^6.1.6: version "6.1.7" resolved "https://registry.npmjs.org/defu/-/defu-6.1.7.tgz" integrity sha512-7z22QmUWiQ/2d0KkdYmANbRUVABpZ9SNYyH5vx6PZ+nE5bcC0l7uFvEfHlyld/HcGBFTL536ClDt3DEcSlEJAQ== @@ -4096,92 +2560,11 @@ destr@^2.0.5: resolved "https://registry.npmjs.org/destr/-/destr-2.0.5.tgz" integrity sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA== -detect-libc@^2.0.0, detect-libc@^2.0.3, detect-libc@^2.1.2: +detect-libc@^2.0.3, detect-libc@^2.1.2: version "2.1.2" resolved "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz" integrity sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ== -detective-amd@^6.0.1: - version "6.1.0" - resolved "https://registry.npmjs.org/detective-amd/-/detective-amd-6.1.0.tgz" - integrity sha512-fmI6LGMvotqd49QaA3ZYw+q0aGp2yXmMjzIuY6fH9j9YFIXY/73yDhMwhX9cPbhWd+AH06NH1Di/LKOuCH0Ubg== - dependencies: - ast-module-types "^6.0.1" - escodegen "^2.1.0" - get-amd-module-type "^6.0.2" - node-source-walk "^7.0.1" - -detective-cjs@^6.1.0: - version "6.1.1" - resolved "https://registry.npmjs.org/detective-cjs/-/detective-cjs-6.1.1.tgz" - integrity sha512-pSh7mkCKEtLlmANqLu3KDFS3NV8Hx41jy/JF1/gAWOgU+Uo5QTkeI1tWNP4dWGo4L0E9j18Ez9EPsTleautKqA== - dependencies: - ast-module-types "^6.0.1" - node-source-walk "^7.0.1" - -detective-es6@^5.0.1: - version "5.0.2" - resolved "https://registry.npmjs.org/detective-es6/-/detective-es6-5.0.2.tgz" - integrity sha512-+qHHGYhjupiVs4rnIpI9nZ5B130A4AmE35ZX1w33hb46vcZ7T3jfDbvmPw0FhWtMHn5BS5HHu7ZtnZ53bMcXZA== - dependencies: - node-source-walk "^7.0.1" - -detective-postcss@^7.0.1: - version "7.0.1" - resolved "https://registry.npmjs.org/detective-postcss/-/detective-postcss-7.0.1.tgz" - integrity sha512-bEOVpHU9picRZux5XnwGsmCN4+8oZo7vSW0O0/Enq/TO5R2pIAP2279NsszpJR7ocnQt4WXU0+nnh/0JuK4KHQ== - dependencies: - is-url "^1.2.4" - postcss-values-parser "^6.0.2" - -detective-sass@^6.0.1: - version "6.0.2" - resolved "https://registry.npmjs.org/detective-sass/-/detective-sass-6.0.2.tgz" - integrity sha512-i3xpXHDKS0qI2aFW4asQ7fqlPK00ndOVZELvQapFJCaF0VxYmsNWtd0AmvXbTLMk7bfO5VdIeorhY9KfmHVoVA== - dependencies: - gonzales-pe "^4.3.0" - node-source-walk "^7.0.1" - -detective-scss@^5.0.1: - version "5.0.2" - resolved "https://registry.npmjs.org/detective-scss/-/detective-scss-5.0.2.tgz" - integrity sha512-9JOEMZ8pDh3ShXmftq7hoQqqJsClaGgxo1hghfCeFlmKf5TC/Twtwb0PAaK8dXwpg9Z0uCmEYSrCxO+kel2eEg== - dependencies: - gonzales-pe "^4.3.0" - node-source-walk "^7.0.1" - -detective-stylus@^5.0.1: - version "5.0.1" - resolved "https://registry.npmjs.org/detective-stylus/-/detective-stylus-5.0.1.tgz" - integrity sha512-Dgn0bUqdGbE3oZJ+WCKf8Dmu7VWLcmRJGc6RCzBgG31DLIyai9WAoEhYRgIHpt/BCRMrnXLbGWGPQuBUrnF0TA== - -detective-typescript@^14.1.0, detective-typescript@^14.1.1: - version "14.1.2" - resolved "https://registry.npmjs.org/detective-typescript/-/detective-typescript-14.1.2.tgz" - integrity sha512-bIeEn0eVi/JRsE1YizBR2ilnMlWRAIBJJ6kXCKNFxEEWhUcEY3R6I3KYIAy48ieURbD1hcb3Ebvl8AqeoPMSzg== - dependencies: - "@typescript-eslint/typescript-estree" "^8.58.2" - ast-module-types "^6.0.1" - node-source-walk "^7.0.1" - -detective-vue2@^2.3.0: - version "2.3.0" - resolved "https://registry.npmjs.org/detective-vue2/-/detective-vue2-2.3.0.tgz" - integrity sha512-3gwbZPqVTm9sL9XdZsgEJ7x4x99O853VVZHapQAiEkGuMJMpFPjHDrecSgfqnS5JW3FJfYXesLZGvUOibjn49g== - dependencies: - "@dependents/detective-less" "^5.0.1" - "@vue/compiler-sfc" "^3.5.32" - detective-es6 "^5.0.1" - detective-sass "^6.0.1" - detective-scss "^5.0.1" - detective-stylus "^5.0.1" - detective-typescript "^14.1.0" - -dettle@^1.0.5: - version "1.0.5" - resolved "https://registry.npmjs.org/dettle/-/dettle-1.0.5.tgz" - integrity sha512-ZVyjhAJ7sCe1PNXEGveObOH9AC8QvMga3HJIghHawtG7mE4K5pW9nz/vDGAr/U7a3LWgdOzEE7ac9MURnyfaTA== - devalue@^5.6.3, devalue@^5.6.4: version "5.8.0" resolved "https://registry.npmjs.org/devalue/-/devalue-5.8.0.tgz" @@ -4244,14 +2627,7 @@ domutils@^3.0.1, domutils@^3.2.2: domelementtype "^2.3.0" domhandler "^5.0.3" -dot-prop@9.0.0, dot-prop@^9.0.0: - version "9.0.0" - resolved "https://registry.npmjs.org/dot-prop/-/dot-prop-9.0.0.tgz" - integrity sha512-1gxPBJpI/pcjQhKgIU91II6Wkay+dLcN3M6rf2uwP8hRur3HtQXjVrdAK3sjC0piaEuxzMwjXChcETiJl47lAQ== - dependencies: - type-fest "^4.18.2" - -dotenv@^16.3.1, dotenv@^16.4.7: +dotenv@^16.4.7: version "16.6.1" resolved "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz" integrity sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow== @@ -4266,7 +2642,7 @@ dset@^3.1.4: resolved "https://registry.npmjs.org/dset/-/dset-3.1.4.tgz" integrity sha512-2QF/g9/zTaPDc3BjNcVTGoBbXBgYfMTTceLaYcFJ/W9kggFUkhxD/hMEeuLKbugyef9SqAx8cpgwlIP/jinUTA== -dunder-proto@^1.0.0, dunder-proto@^1.0.1: +dunder-proto@^1.0.1: version "1.0.1" resolved "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz" integrity sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A== @@ -4275,18 +2651,6 @@ dunder-proto@^1.0.0, dunder-proto@^1.0.1: es-errors "^1.3.0" gopd "^1.2.0" -eastasianwidth@^0.2.0: - version "0.2.0" - resolved "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz" - integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA== - -ecdsa-sig-formatter@1.0.11: - version "1.0.11" - resolved "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz" - integrity sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ== - dependencies: - safe-buffer "^5.0.1" - ee-first@1.1.1: version "1.1.1" resolved "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz" @@ -4310,21 +2674,6 @@ emoji-regex@^8.0.0: resolved "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz" integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== -emoji-regex@^9.2.2: - version "9.2.2" - resolved "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz" - integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== - -empathic@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/empathic/-/empathic-2.0.0.tgz" - integrity sha512-i6UzDscO/XfAcNYD75CfICkmfLedpyPDdozrLMmQc5ORaQcdMoc21OnlEylMIqI7U8eniKrPMxxtj8k0vhmJhA== - -enabled@2.0.x: - version "2.0.0" - resolved "https://registry.npmjs.org/enabled/-/enabled-2.0.0.tgz" - integrity sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ== - encodeurl@^2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz" @@ -4365,11 +2714,6 @@ env-paths@^2.2.1: resolved "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz" integrity sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A== -env-paths@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/env-paths/-/env-paths-3.0.0.tgz" - integrity sha512-dtJUTepzMW3Lm/NPxRf3wP4642UWhjL2sQxc+ym2YMj1m/H2zDNQOlezafzkHwn6sMstjHTwG6iQQsctDW/b1A== - error-ex@^1.3.1: version "1.3.4" resolved "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz" @@ -4377,72 +2721,7 @@ error-ex@^1.3.1: dependencies: is-arrayish "^0.2.1" -error-stack-parser-es@^1.0.5: - version "1.0.5" - resolved "https://registry.npmjs.org/error-stack-parser-es/-/error-stack-parser-es-1.0.5.tgz" - integrity sha512-5qucVt2XcuGMcEGgWI7i+yZpmpByQ8J1lHhcL7PwqCwu9FPP3VUXzT4ltHe5i2z9dePwEHcDVOAfSnHsOlCXRA== - -es-abstract@^1.23.5, es-abstract@^1.23.9: - version "1.24.2" - resolved "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.2.tgz" - integrity sha512-2FpH9Q5i2RRwyEP1AylXe6nYLR5OhaJTZwmlcP0dL/+JCbgg7yyEo/sEK6HeGZRf3dFpWwThaRHVApXSkW3xeg== - dependencies: - array-buffer-byte-length "^1.0.2" - arraybuffer.prototype.slice "^1.0.4" - available-typed-arrays "^1.0.7" - call-bind "^1.0.8" - call-bound "^1.0.4" - data-view-buffer "^1.0.2" - data-view-byte-length "^1.0.2" - data-view-byte-offset "^1.0.1" - es-define-property "^1.0.1" - es-errors "^1.3.0" - es-object-atoms "^1.1.1" - es-set-tostringtag "^2.1.0" - es-to-primitive "^1.3.0" - function.prototype.name "^1.1.8" - get-intrinsic "^1.3.0" - get-proto "^1.0.1" - get-symbol-description "^1.1.0" - globalthis "^1.0.4" - gopd "^1.2.0" - has-property-descriptors "^1.0.2" - has-proto "^1.2.0" - has-symbols "^1.1.0" - hasown "^2.0.2" - internal-slot "^1.1.0" - is-array-buffer "^3.0.5" - is-callable "^1.2.7" - is-data-view "^1.0.2" - is-negative-zero "^2.0.3" - is-regex "^1.2.1" - is-set "^2.0.3" - is-shared-array-buffer "^1.0.4" - is-string "^1.1.1" - is-typed-array "^1.1.15" - is-weakref "^1.1.1" - math-intrinsics "^1.1.0" - object-inspect "^1.13.4" - object-keys "^1.1.1" - object.assign "^4.1.7" - own-keys "^1.0.1" - regexp.prototype.flags "^1.5.4" - safe-array-concat "^1.1.3" - safe-push-apply "^1.0.0" - safe-regex-test "^1.1.0" - set-proto "^1.0.0" - stop-iteration-iterator "^1.1.0" - string.prototype.trim "^1.2.10" - string.prototype.trimend "^1.0.9" - string.prototype.trimstart "^1.0.8" - typed-array-buffer "^1.0.3" - typed-array-byte-length "^1.0.3" - typed-array-byte-offset "^1.0.4" - typed-array-length "^1.0.7" - unbox-primitive "^1.1.0" - which-typed-array "^1.1.19" - -es-define-property@^1.0.0, es-define-property@^1.0.1: +es-define-property@^1.0.1: version "1.0.1" resolved "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz" integrity sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g== @@ -4452,11 +2731,6 @@ es-errors@^1.3.0: resolved "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz" integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw== -es-module-lexer@^1.0.0, es-module-lexer@^1.5.3: - version "1.7.0" - resolved "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz" - integrity sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA== - es-module-lexer@^2.0.0: version "2.1.0" resolved "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.1.0.tgz" @@ -4469,69 +2743,11 @@ es-object-atoms@^1.0.0, es-object-atoms@^1.1.1: dependencies: es-errors "^1.3.0" -es-set-tostringtag@^2.1.0: - version "2.1.0" - resolved "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz" - integrity sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA== - dependencies: - es-errors "^1.3.0" - get-intrinsic "^1.2.6" - has-tostringtag "^1.0.2" - hasown "^2.0.2" - -es-shim-unscopables@^1.0.2: - version "1.1.0" - resolved "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.1.0.tgz" - integrity sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw== - dependencies: - hasown "^2.0.2" - -es-to-primitive@^1.3.0: - version "1.3.0" - resolved "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.0.tgz" - integrity sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g== - dependencies: - is-callable "^1.2.7" - is-date-object "^1.0.5" - is-symbol "^1.0.4" - es-toolkit@^1.39.3: version "1.46.1" resolved "https://registry.npmjs.org/es-toolkit/-/es-toolkit-1.46.1.tgz" integrity sha512-5eNtXOs3tbfxXOj04tjjseeWkRWaoCjdEI+96DgwzZoe6c9juL49pXlzAFTI72aWC9Y8p7168g6XIKjh7k6pyQ== -esbuild@0.27.3: - version "0.27.3" - resolved "https://registry.npmjs.org/esbuild/-/esbuild-0.27.3.tgz" - integrity sha512-8VwMnyGCONIs6cWue2IdpHxHnAjzxnw2Zr7MkVxB2vjmQ2ivqGFb4LEG3SMnv0Gb2F/G/2yA8zUaiL1gywDCCg== - optionalDependencies: - "@esbuild/aix-ppc64" "0.27.3" - "@esbuild/android-arm" "0.27.3" - "@esbuild/android-arm64" "0.27.3" - "@esbuild/android-x64" "0.27.3" - "@esbuild/darwin-arm64" "0.27.3" - "@esbuild/darwin-x64" "0.27.3" - "@esbuild/freebsd-arm64" "0.27.3" - "@esbuild/freebsd-x64" "0.27.3" - "@esbuild/linux-arm" "0.27.3" - "@esbuild/linux-arm64" "0.27.3" - "@esbuild/linux-ia32" "0.27.3" - "@esbuild/linux-loong64" "0.27.3" - "@esbuild/linux-mips64el" "0.27.3" - "@esbuild/linux-ppc64" "0.27.3" - "@esbuild/linux-riscv64" "0.27.3" - "@esbuild/linux-s390x" "0.27.3" - "@esbuild/linux-x64" "0.27.3" - "@esbuild/netbsd-arm64" "0.27.3" - "@esbuild/netbsd-x64" "0.27.3" - "@esbuild/openbsd-arm64" "0.27.3" - "@esbuild/openbsd-x64" "0.27.3" - "@esbuild/openharmony-arm64" "0.27.3" - "@esbuild/sunos-x64" "0.27.3" - "@esbuild/win32-arm64" "0.27.3" - "@esbuild/win32-ia32" "0.27.3" - "@esbuild/win32-x64" "0.27.3" - esbuild@^0.27.0, esbuild@^0.27.3: version "0.27.7" resolved "https://registry.npmjs.org/esbuild/-/esbuild-0.27.7.tgz" @@ -4739,7 +2955,7 @@ estraverse@^5.1.0, estraverse@^5.2.0: resolved "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz" integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== -estree-walker@2.0.2, estree-walker@^2.0.2: +estree-walker@^2.0.2: version "2.0.2" resolved "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz" integrity sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w== @@ -4754,43 +2970,11 @@ etag@^1.8.1: resolved "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz" integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== -event-target-shim@^5.0.0: - version "5.0.1" - resolved "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz" - integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ== - eventemitter3@^5.0.1, eventemitter3@^5.0.4: version "5.0.4" resolved "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.4.tgz" integrity sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw== -events-universal@^1.0.0: - version "1.0.1" - resolved "https://registry.npmjs.org/events-universal/-/events-universal-1.0.1.tgz" - integrity sha512-LUd5euvbMLpwOF8m6ivPCbhQeSiYVNb8Vs0fQ8QjXo0JTkEHpz8pxdQf0gStltaPpw0Cca8b39KxvK9cfKRiAw== - dependencies: - bare-events "^2.7.0" - -events@^3.3.0: - version "3.3.0" - resolved "https://registry.npmjs.org/events/-/events-3.3.0.tgz" - integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== - -execa@^8.0.0: - version "8.0.1" - resolved "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz" - integrity sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg== - dependencies: - cross-spawn "^7.0.3" - get-stream "^8.0.1" - human-signals "^5.0.0" - is-stream "^3.0.0" - merge-stream "^2.0.0" - npm-run-path "^5.1.0" - onetime "^6.0.0" - signal-exit "^4.1.0" - strip-final-newline "^3.0.0" - express-rate-limit@^8.5.0: version "8.5.0" resolved "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-8.5.0.tgz" @@ -4848,26 +3032,11 @@ extract-zip@2.0.1, extract-zip@^2.0.1: optionalDependencies: "@types/yauzl" "^2.9.1" -extract-zip@^1.7.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-1.7.0.tgz#556cc3ae9df7f452c493a0cfb51cc30277940927" - integrity sha512-xoh5G1W/PB0/27lXgMQyIhP5DSY/LhoCsOyZgb+6iMmRtCwVBo55uKaMoEYrDCKQhWvqEip5ZPKAc6eFNyf/MA== - dependencies: - concat-stream "^1.6.2" - debug "^2.6.9" - mkdirp "^0.5.4" - yauzl "^2.10.0" - fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: version "3.1.3" resolved "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz" integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== -fast-fifo@^1.2.0, fast-fifo@^1.3.2: - version "1.3.2" - resolved "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz" - integrity sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ== - fast-glob@^3.3.3: version "3.3.3" resolved "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz" @@ -4889,11 +3058,6 @@ fast-levenshtein@^2.0.6: resolved "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz" integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== -fast-safe-stringify@^2.0.7, fast-safe-stringify@^2.1.1: - version "2.1.1" - resolved "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz" - integrity sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA== - fast-string-truncated-width@^3.0.2: version "3.0.3" resolved "https://registry.npmjs.org/fast-string-truncated-width/-/fast-string-truncated-width-3.0.3.tgz" @@ -4937,26 +3101,6 @@ fdir@^6.5.0: resolved "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz" integrity sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg== -fecha@^4.2.0: - version "4.2.3" - resolved "https://registry.npmjs.org/fecha/-/fecha-4.2.3.tgz" - integrity sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw== - -fetch-blob@^3.1.2, fetch-blob@^3.1.4: - version "3.2.0" - resolved "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz" - integrity sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ== - dependencies: - node-domexception "^1.0.0" - web-streams-polyfill "^3.0.3" - -figures@^6.0.0: - version "6.1.0" - resolved "https://registry.npmjs.org/figures/-/figures-6.1.0.tgz" - integrity sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg== - dependencies: - is-unicode-supported "^2.0.0" - file-entry-cache@^8.0.0: version "8.0.0" resolved "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz" @@ -4964,11 +3108,6 @@ file-entry-cache@^8.0.0: dependencies: flat-cache "^4.0.0" -file-uri-to-path@1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz" - integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw== - fill-range@^7.1.1: version "7.1.1" resolved "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz" @@ -4976,11 +3115,6 @@ fill-range@^7.1.1: dependencies: to-regex-range "^5.0.1" -filter-obj@^6.0.0: - version "6.1.0" - resolved "https://registry.npmjs.org/filter-obj/-/filter-obj-6.1.0.tgz" - integrity sha512-xdMtCAODmPloU9qtmPcdBV9Kd27NtMse+4ayThxqIHUES5Z2S6bGpap5PpdmNM56ub7y3i1eyr+vJJIIgWGKmA== - finalhandler@^2.1.0: version "2.1.1" resolved "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.1.tgz" @@ -4998,11 +3132,6 @@ find-root@^1.1.0: resolved "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz" integrity sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng== -find-up-simple@^1.0.0: - version "1.0.1" - resolved "https://registry.npmjs.org/find-up-simple/-/find-up-simple-1.0.1.tgz" - integrity sha512-afd4O7zpqHeRyg4PfDQsXmlDe2PfdHtJt6Akt8jOWaApLOZk5JXs6VMR29lz03pRe9mpykrRCYIYxaJYcfpncQ== - find-up@^5.0.0: version "5.0.0" resolved "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz" @@ -5011,15 +3140,6 @@ find-up@^5.0.0: locate-path "^6.0.0" path-exists "^4.0.0" -find-up@^7.0.0: - version "7.0.0" - resolved "https://registry.npmjs.org/find-up/-/find-up-7.0.0.tgz" - integrity sha512-YyZM99iHrqLKjmt4LJDj58KI+fYyufRLBSYcqycxf//KpBk9FoewoGX0450m9nB44qrZnovzC2oeP5hUibxc/g== - dependencies: - locate-path "^7.2.0" - path-exists "^5.0.0" - unicorn-magic "^0.1.0" - flat-cache@^4.0.0: version "4.0.1" resolved "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz" @@ -5038,11 +3158,6 @@ flattie@^1.1.1: resolved "https://registry.npmjs.org/flattie/-/flattie-1.1.1.tgz" integrity sha512-9UbaD6XdAL97+k/n+N7JwX46K/M6Zc6KcFYskrYL8wbBV/Uyk0CTAMY0VT+qiK5PM7AIc9aTWYtq65U7T+aCNQ== -fn.name@1.x.x: - version "1.1.0" - resolved "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz" - integrity sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw== - fontace@~0.4.1: version "0.4.1" resolved "https://registry.npmjs.org/fontace/-/fontace-0.4.1.tgz" @@ -5057,28 +3172,6 @@ fontkitten@^1.0.0, fontkitten@^1.0.2: dependencies: tiny-inflate "^1.0.3" -for-each@^0.3.3, for-each@^0.3.5: - version "0.3.5" - resolved "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz" - integrity sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg== - dependencies: - is-callable "^1.2.7" - -foreground-child@^3.1.0: - version "3.3.1" - resolved "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz" - integrity sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw== - dependencies: - cross-spawn "^7.0.6" - signal-exit "^4.0.1" - -formdata-polyfill@^4.0.10: - version "4.0.10" - resolved "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz" - integrity sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g== - dependencies: - fetch-blob "^3.1.2" - forwarded@0.2.0: version "0.2.0" resolved "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz" @@ -5118,47 +3211,17 @@ function-bind@^1.1.2: resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz" integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== -function.prototype.name@^1.1.6, function.prototype.name@^1.1.8: - version "1.1.8" - resolved "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.8.tgz" - integrity sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q== - dependencies: - call-bind "^1.0.8" - call-bound "^1.0.3" - define-properties "^1.2.1" - functions-have-names "^1.2.3" - hasown "^2.0.2" - is-callable "^1.2.7" - -functions-have-names@^1.2.3: - version "1.2.3" - resolved "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz" - integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ== - -generator-function@^2.0.0: - version "2.0.1" - resolved "https://registry.npmjs.org/generator-function/-/generator-function-2.0.1.tgz" - integrity sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g== - gensync@^1.0.0-beta.2: version "1.0.0-beta.2" resolved "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz" integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== -get-amd-module-type@^6.0.2: - version "6.0.2" - resolved "https://registry.npmjs.org/get-amd-module-type/-/get-amd-module-type-6.0.2.tgz" - integrity sha512-7zShVYAYtMnj9S65CfN+hvpBCByfuB1OY8xID01nZEzXTZbx4YyysAfi+nMl95JSR6odt4q8TCj2W63KAoyVLQ== - dependencies: - ast-module-types "^6.0.1" - node-source-walk "^7.0.1" - get-caller-file@^2.0.5: version "2.0.5" resolved "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== -get-intrinsic@^1.2.4, get-intrinsic@^1.2.5, get-intrinsic@^1.2.6, get-intrinsic@^1.2.7, get-intrinsic@^1.3.0: +get-intrinsic@^1.2.5, get-intrinsic@^1.3.0: version "1.3.0" resolved "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz" integrity sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ== @@ -5174,16 +3237,6 @@ get-intrinsic@^1.2.4, get-intrinsic@^1.2.5, get-intrinsic@^1.2.6, get-intrinsic@ hasown "^2.0.2" math-intrinsics "^1.1.0" -get-port-please@^3.2.0: - version "3.2.0" - resolved "https://registry.npmjs.org/get-port-please/-/get-port-please-3.2.0.tgz" - integrity sha512-I9QVvBw5U/hw3RmWpYKRumUeaDgxTPd401x364rLmWBJcOQ753eov1eTgzDqRG9bqFIfDc7gfzcQEWrUri3o1A== - -get-port@^7.0.0, get-port@^7.1.0: - version "7.2.0" - resolved "https://registry.npmjs.org/get-port/-/get-port-7.2.0.tgz" - integrity sha512-afP4W205ONCuMoPBqcR6PSXnzX35KTcJygfJfcp+QY+uwm3p20p1YczWXhlICIzGMCxYBQcySEcOgsJcrkyobg== - get-proto@^1.0.1: version "1.0.1" resolved "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz" @@ -5199,20 +3252,6 @@ get-stream@^5.1.0: dependencies: pump "^3.0.0" -get-stream@^8.0.1: - version "8.0.1" - resolved "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz" - integrity sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA== - -get-symbol-description@^1.1.0: - version "1.1.0" - resolved "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz" - integrity sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg== - dependencies: - call-bound "^1.0.3" - es-errors "^1.3.0" - get-intrinsic "^1.2.6" - get-tsconfig@5.0.0-beta.4: version "5.0.0-beta.4" resolved "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-5.0.0-beta.4.tgz" @@ -5248,39 +3287,6 @@ glob-parent@^6.0.2: dependencies: is-glob "^4.0.3" -glob@^10.0.0, glob@^10.4.5: - version "10.5.0" - resolved "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz" - integrity sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg== - dependencies: - foreground-child "^3.1.0" - jackspeak "^3.1.2" - minimatch "^9.0.4" - minipass "^7.1.2" - package-json-from-dist "^1.0.0" - path-scurry "^1.11.1" - -glob@^13.0.0: - version "13.0.6" - resolved "https://registry.npmjs.org/glob/-/glob-13.0.6.tgz" - integrity sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw== - dependencies: - minimatch "^10.2.2" - minipass "^7.1.3" - path-scurry "^2.0.2" - -glob@^7.1.3: - version "7.2.3" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" - integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.1.1" - once "^1.3.0" - path-is-absolute "^1.0.0" - glob@^9.2.0: version "9.3.5" resolved "https://registry.npmjs.org/glob/-/glob-9.3.5.tgz" @@ -5296,49 +3302,12 @@ globals@^16.0.0: resolved "https://registry.npmjs.org/globals/-/globals-16.5.0.tgz" integrity sha512-c/c15i26VrJ4IRt5Z89DnIzCGDn9EcebibhAOjw5ibqEHsE1wLUgkPn9RDmNcUKyU87GeaL633nyJ+pplFR2ZQ== -globalthis@^1.0.4: - version "1.0.4" - resolved "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz" - integrity sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ== - dependencies: - define-properties "^1.2.1" - gopd "^1.0.1" - -gonzales-pe@^4.3.0: - version "4.3.0" - resolved "https://registry.npmjs.org/gonzales-pe/-/gonzales-pe-4.3.0.tgz" - integrity sha512-otgSPpUmdWJ43VXyiNgEYE4luzHCL2pz4wQ0OnDluC6Eg4Ko3Vexy/SrSynglw/eR+OhkzmqFCZa/OFa/RgAOQ== - dependencies: - minimist "^1.2.5" - -gopd@^1.0.1, gopd@^1.2.0: +gopd@^1.2.0: version "1.2.0" resolved "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz" integrity sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg== -got@^11.5.1: - version "11.8.6" - resolved "https://registry.yarnpkg.com/got/-/got-11.8.6.tgz#276e827ead8772eddbcfc97170590b841823233a" - integrity sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g== - dependencies: - "@sindresorhus/is" "^4.0.0" - "@szmarczak/http-timer" "^4.0.5" - "@types/cacheable-request" "^6.0.1" - "@types/responselike" "^1.0.0" - cacheable-lookup "^5.0.3" - cacheable-request "^7.0.2" - decompress-response "^6.0.0" - http2-wrapper "^1.0.0-beta.5.2" - lowercase-keys "^2.0.0" - p-cancelable "^2.0.0" - responselike "^2.0.0" - -graceful-fs@^4.2.0, graceful-fs@^4.2.11, graceful-fs@^4.2.9: - version "4.2.11" - resolved "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz" - integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== - -h3@^1.15.10, h3@^1.15.11, h3@^1.15.3: +h3@^1.15.10: version "1.15.11" resolved "https://registry.npmjs.org/h3/-/h3-1.15.11.tgz" integrity sha512-L3THSe2MPeBwgIZVSH5zLdBBU90TOxarvhK9d04IDY2AmVS8j2Jz2LIWtwsGOU3lu2I5jCN7FNvVfY2+XyF+mg== @@ -5353,11 +3322,6 @@ h3@^1.15.10, h3@^1.15.11, h3@^1.15.3: ufo "^1.6.3" uncrypto "^0.1.3" -has-bigints@^1.0.2: - version "1.1.0" - resolved "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz" - integrity sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg== - has-flag@^3.0.0: version "3.0.0" resolved "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz" @@ -5368,32 +3332,11 @@ has-flag@^4.0.0: resolved "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz" integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== -has-property-descriptors@^1.0.0, has-property-descriptors@^1.0.2: - version "1.0.2" - resolved "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz" - integrity sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg== - dependencies: - es-define-property "^1.0.0" - -has-proto@^1.2.0: - version "1.2.0" - resolved "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz" - integrity sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ== - dependencies: - dunder-proto "^1.0.0" - -has-symbols@^1.0.3, has-symbols@^1.1.0: +has-symbols@^1.1.0: version "1.1.0" resolved "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz" integrity sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ== -has-tostringtag@^1.0.2: - version "1.0.2" - resolved "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz" - integrity sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw== - dependencies: - has-symbols "^1.0.3" - hasown@^2.0.2: version "2.0.3" resolved "https://registry.npmjs.org/hasown/-/hasown-2.0.3.tgz" @@ -5525,13 +3468,6 @@ hoist-non-react-statics@^3.3.1: dependencies: react-is "^16.7.0" -hosted-git-info@^7.0.0: - version "7.0.2" - resolved "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-7.0.2.tgz" - integrity sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w== - dependencies: - lru-cache "^10.0.1" - html-escaper@3.0.3: version "3.0.3" resolved "https://registry.npmjs.org/html-escaper/-/html-escaper-3.0.3.tgz" @@ -5552,7 +3488,7 @@ htmlparser2@^10.1.0: domutils "^3.2.2" entities "^7.0.1" -http-cache-semantics@^4.0.0, http-cache-semantics@^4.2.0: +http-cache-semantics@^4.2.0: version "4.2.0" resolved "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz" integrity sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ== @@ -5576,19 +3512,6 @@ http-proxy-agent@^7.0.0, http-proxy-agent@^7.0.1: agent-base "^7.1.0" debug "^4.3.4" -http-shutdown@^1.2.2: - version "1.2.2" - resolved "https://registry.npmjs.org/http-shutdown/-/http-shutdown-1.2.2.tgz" - integrity sha512-S9wWkJ/VSY9/k4qcjG318bqJNruzE4HySUhFYknwmu6LBP97KLLfwNf+n4V1BHurvFNkSKLFnK/RsuUnRTf9Vw== - -http2-wrapper@^1.0.0-beta.5.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/http2-wrapper/-/http2-wrapper-1.0.3.tgz#b8f55e0c1f25d4ebd08b3b0c2c079f9590800b3d" - integrity sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg== - dependencies: - quick-lru "^5.1.1" - resolve-alpn "^1.0.0" - https-proxy-agent@5.0.1: version "5.0.1" resolved "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz" @@ -5597,7 +3520,7 @@ https-proxy-agent@5.0.1: agent-base "6" debug "4" -https-proxy-agent@^7.0.5, https-proxy-agent@^7.0.6: +https-proxy-agent@^7.0.6: version "7.0.6" resolved "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz" integrity sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw== @@ -5605,11 +3528,6 @@ https-proxy-agent@^7.0.5, https-proxy-agent@^7.0.6: agent-base "^7.1.2" debug "4" -human-signals@^5.0.0: - version "5.0.0" - resolved "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz" - integrity sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ== - iconv-lite@0.6.3, iconv-lite@^0.6.3: version "0.6.3" resolved "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz" @@ -5624,7 +3542,7 @@ iconv-lite@^0.7.0, iconv-lite@~0.7.0: dependencies: safer-buffer ">= 2.1.2 < 3.0.0" -ieee754@^1.1.13, ieee754@^1.2.1: +ieee754@^1.1.13: version "1.2.1" resolved "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz" integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== @@ -5639,16 +3557,6 @@ ignore@^5.2.0: resolved "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz" integrity sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g== -image-meta@^0.2.1: - version "0.2.2" - resolved "https://registry.npmjs.org/image-meta/-/image-meta-0.2.2.tgz" - integrity sha512-3MOLanc3sb3LNGWQl1RlQlNWURE5g32aUphrDyFeCsxBTk08iE3VNe4CwsUZ0Qs1X+EfX0+r29Sxdpza4B+yRA== - -image-size@^2.0.2: - version "2.0.2" - resolved "https://registry.npmjs.org/image-size/-/image-size-2.0.2.tgz" - integrity sha512-IRqXKlaXwgSMAMtpNzZa1ZAe8m+Sa1770Dhk8VkSsP9LS+iHD62Zd8FQKs8fbPiagBE7BzoFX23cxFnwshpV6w== - immer@^10.1.1: version "10.2.0" resolved "https://registry.npmjs.org/immer/-/immer-10.2.0.tgz" @@ -5672,53 +3580,16 @@ import-fresh@^3.2.1, import-fresh@^3.3.0: parent-module "^1.0.0" resolve-from "^4.0.0" -import-in-the-middle@^1.8.1: - version "1.15.0" - resolved "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.15.0.tgz" - integrity sha512-bpQy+CrsRmYmoPMAE/0G33iwRqwW4ouqdRg8jgbH3aKuCtOc8lxgmYXg2dMM92CRiGP660EtBcymH/eVUpCSaA== - dependencies: - acorn "^8.14.0" - acorn-import-attributes "^1.9.5" - cjs-module-lexer "^1.2.2" - module-details-from-path "^1.0.3" - imurmurhash@^0.1.4: version "0.1.4" resolved "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz" integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== -indent-string@^5.0.0: - version "5.0.0" - resolved "https://registry.npmjs.org/indent-string/-/indent-string-5.0.0.tgz" - integrity sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg== - -index-to-position@^1.1.0: - version "1.2.0" - resolved "https://registry.npmjs.org/index-to-position/-/index-to-position-1.2.0.tgz" - integrity sha512-Yg7+ztRkqslMAS2iFaU+Oa4KTSidr63OsFGlOrJoW981kIYO3CGCS3wA95P1mUi/IVSJkn0D479KTJpVpvFNuw== - -inflight@^1.0.4: - version "1.0.6" - resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" - integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== - dependencies: - once "^1.3.0" - wrappy "1" - -inherits@2, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.3, inherits@~2.0.4: +inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.4: version "2.0.4" resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== -internal-slot@^1.1.0: - version "1.1.0" - resolved "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz" - integrity sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw== - dependencies: - es-errors "^1.3.0" - hasown "^2.0.2" - side-channel "^1.1.0" - "internmap@1 - 2": version "2.0.3" resolved "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz" @@ -5744,65 +3615,16 @@ ipaddr.js@1.9.1: resolved "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz" integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== -ipx@^3.1.1: - version "3.1.1" - resolved "https://registry.npmjs.org/ipx/-/ipx-3.1.1.tgz" - integrity sha512-7Xnt54Dco7uYkfdAw0r2vCly3z0rSaVhEXMzPvl3FndsTVm5p26j+PO+gyinkYmcsEUvX2Rh7OGK7KzYWRu6BA== - dependencies: - "@fastify/accept-negotiator" "^2.0.1" - citty "^0.1.6" - consola "^3.4.2" - defu "^6.1.4" - destr "^2.0.5" - etag "^1.8.1" - h3 "^1.15.3" - image-meta "^0.2.1" - listhen "^1.9.0" - ofetch "^1.4.1" - pathe "^2.0.3" - sharp "^0.34.3" - svgo "^4.0.0" - ufo "^1.6.1" - unstorage "^1.16.1" - xss "^1.0.15" - iron-webcrypto@^1.2.1: version "1.2.1" resolved "https://registry.npmjs.org/iron-webcrypto/-/iron-webcrypto-1.2.1.tgz" integrity sha512-feOM6FaSr6rEABp/eDfVseKyTMDt+KGpeB35SkVn9Tyn0CqvVsY3EwI0v5i8nMHyJnzCIQf7nsy3p41TPkJZhg== -is-array-buffer@^3.0.4, is-array-buffer@^3.0.5: - version "3.0.5" - resolved "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz" - integrity sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A== - dependencies: - call-bind "^1.0.8" - call-bound "^1.0.3" - get-intrinsic "^1.2.6" - is-arrayish@^0.2.1: version "0.2.1" resolved "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz" integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== -is-async-function@^2.0.0: - version "2.1.1" - resolved "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz" - integrity sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ== - dependencies: - async-function "^1.0.0" - call-bound "^1.0.3" - get-proto "^1.0.1" - has-tostringtag "^1.0.2" - safe-regex-test "^1.1.0" - -is-bigint@^1.1.0: - version "1.1.0" - resolved "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz" - integrity sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ== - dependencies: - has-bigints "^1.0.2" - is-binary-path@~2.1.0: version "2.1.0" resolved "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz" @@ -5810,19 +3632,6 @@ is-binary-path@~2.1.0: dependencies: binary-extensions "^2.0.0" -is-boolean-object@^1.2.1: - version "1.2.2" - resolved "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz" - integrity sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A== - dependencies: - call-bound "^1.0.3" - has-tostringtag "^1.0.2" - -is-callable@^1.2.7: - version "1.2.7" - resolved "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz" - integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== - is-core-module@^2.16.1: version "2.16.1" resolved "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz" @@ -5830,23 +3639,6 @@ is-core-module@^2.16.1: dependencies: hasown "^2.0.2" -is-data-view@^1.0.1, is-data-view@^1.0.2: - version "1.0.2" - resolved "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz" - integrity sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw== - dependencies: - call-bound "^1.0.2" - get-intrinsic "^1.2.6" - is-typed-array "^1.1.13" - -is-date-object@^1.0.5, is-date-object@^1.1.0: - version "1.1.0" - resolved "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz" - integrity sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg== - dependencies: - call-bound "^1.0.2" - has-tostringtag "^1.0.2" - is-docker@^3.0.0: version "3.0.0" resolved "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz" @@ -5862,29 +3654,11 @@ is-extglob@^2.1.1: resolved "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz" integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== -is-finalizationregistry@^1.1.0: - version "1.1.1" - resolved "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz" - integrity sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg== - dependencies: - call-bound "^1.0.3" - is-fullwidth-code-point@^3.0.0: version "3.0.0" resolved "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz" integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== -is-generator-function@^1.0.10: - version "1.1.2" - resolved "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.2.tgz" - integrity sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA== - dependencies: - call-bound "^1.0.4" - generator-function "^2.0.0" - get-proto "^1.0.1" - has-tostringtag "^1.0.2" - safe-regex-test "^1.1.0" - is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: version "4.0.3" resolved "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz" @@ -5899,156 +3673,27 @@ is-inside-container@^1.0.0: dependencies: is-docker "^3.0.0" -is-map@^2.0.3: - version "2.0.3" - resolved "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz" - integrity sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw== - -is-negative-zero@^2.0.3: - version "2.0.3" - resolved "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz" - integrity sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw== - -is-network-error@^1.0.0: - version "1.3.1" - resolved "https://registry.npmjs.org/is-network-error/-/is-network-error-1.3.1.tgz" - integrity sha512-6QCxa49rQbmUWLfk0nuGqzql9U8uaV2H6279bRErPBHe/109hCzsLUBUHfbEtvLIHBd6hyXbgedBSHevm43Edw== - -is-number-object@^1.1.1: - version "1.1.1" - resolved "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz" - integrity sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw== - dependencies: - call-bound "^1.0.3" - has-tostringtag "^1.0.2" - is-number@^7.0.0: version "7.0.0" resolved "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz" - integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== - -is-path-inside@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/is-path-inside/-/is-path-inside-4.0.0.tgz" - integrity sha512-lJJV/5dYS+RcL8uQdBDW9c9uWFLLBNRyFhnAKXw5tVqLlKZ4RMGZKv+YQ/IA3OhD+RpbJa1LLFM1FQPGyIXvOA== - -is-plain-obj@^2.1.0: - version "2.1.0" - resolved "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz" - integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== - -is-plain-obj@^4.0.0: - version "4.1.0" - resolved "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz" - integrity sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg== - -is-promise@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz" - integrity sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ== - -is-reference@^3.0.3: - version "3.0.3" - resolved "https://registry.npmjs.org/is-reference/-/is-reference-3.0.3.tgz" - integrity sha512-ixkJoqQvAP88E6wLydLGGqCJsrFUnqoH6HnaczB8XmDH1oaWU+xxdptvikTgaEhtZ53Ky6YXiBuUI2WXLMCwjw== - dependencies: - "@types/estree" "^1.0.6" - -is-regex@^1.2.1: - version "1.2.1" - resolved "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz" - integrity sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g== - dependencies: - call-bound "^1.0.2" - gopd "^1.2.0" - has-tostringtag "^1.0.2" - hasown "^2.0.2" - -is-set@^2.0.3: - version "2.0.3" - resolved "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz" - integrity sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg== - -is-shared-array-buffer@^1.0.4: - version "1.0.4" - resolved "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz" - integrity sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A== - dependencies: - call-bound "^1.0.3" - -is-stream@^2.0.0, is-stream@^2.0.1: - version "2.0.1" - resolved "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz" - integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== - -is-stream@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz" - integrity sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA== - -is-stream@^4.0.1: - version "4.0.1" - resolved "https://registry.npmjs.org/is-stream/-/is-stream-4.0.1.tgz" - integrity sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A== - -is-string@^1.1.1: - version "1.1.1" - resolved "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz" - integrity sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA== - dependencies: - call-bound "^1.0.3" - has-tostringtag "^1.0.2" - -is-symbol@^1.0.4, is-symbol@^1.1.1: - version "1.1.1" - resolved "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz" - integrity sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w== - dependencies: - call-bound "^1.0.2" - has-symbols "^1.1.0" - safe-regex-test "^1.1.0" - -is-typed-array@^1.1.13, is-typed-array@^1.1.14, is-typed-array@^1.1.15: - version "1.1.15" - resolved "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz" - integrity sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ== - dependencies: - which-typed-array "^1.1.16" - -is-unicode-supported@^2.0.0: - version "2.1.0" - resolved "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-2.1.0.tgz" - integrity sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ== - -is-url-superb@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/is-url-superb/-/is-url-superb-4.0.0.tgz" - integrity sha512-GI+WjezhPPcbM+tqE9LnmsY5qqjwHzTvjJ36wxYX5ujNXefSUJ/T17r5bqDV8yLhcgB59KTPNOc9O9cmHTPWsA== - -is-url@^1.2.4: - version "1.2.4" - resolved "https://registry.npmjs.org/is-url/-/is-url-1.2.4.tgz" - integrity sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww== + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== -is-weakmap@^2.0.2: - version "2.0.2" - resolved "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz" - integrity sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w== +is-plain-obj@^4.0.0: + version "4.1.0" + resolved "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz" + integrity sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg== -is-weakref@^1.0.2, is-weakref@^1.1.1: - version "1.1.1" - resolved "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.1.tgz" - integrity sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew== - dependencies: - call-bound "^1.0.3" +is-promise@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz" + integrity sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ== -is-weakset@^2.0.3: - version "2.0.4" - resolved "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz" - integrity sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ== +is-reference@^3.0.3: + version "3.0.3" + resolved "https://registry.npmjs.org/is-reference/-/is-reference-3.0.3.tgz" + integrity sha512-ixkJoqQvAP88E6wLydLGGqCJsrFUnqoH6HnaczB8XmDH1oaWU+xxdptvikTgaEhtZ53Ky6YXiBuUI2WXLMCwjw== dependencies: - call-bound "^1.0.3" - get-intrinsic "^1.2.6" + "@types/estree" "^1.0.6" is-wsl@^3.1.1: version "3.1.1" @@ -6057,47 +3702,11 @@ is-wsl@^3.1.1: dependencies: is-inside-container "^1.0.0" -isarray@^2.0.5: - version "2.0.5" - resolved "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz" - integrity sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw== - -isarray@~1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz" - integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== - isexe@^2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz" integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== -jackspeak@^3.1.2: - version "3.4.3" - resolved "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz" - integrity sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw== - dependencies: - "@isaacs/cliui" "^8.0.2" - optionalDependencies: - "@pkgjs/parseargs" "^0.11.0" - -jiti@^2.6.1: - version "2.6.1" - resolved "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz" - integrity sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ== - -jpeg-js@^0.4.2: - version "0.4.4" - resolved "https://registry.npmjs.org/jpeg-js/-/jpeg-js-0.4.4.tgz" - integrity sha512-WZzeDOEtTOBK4Mdsar0IqEU5sMr3vSV2RqkAIzUEV2BHnUfKGyswWFPFwK5EeDo93K3FohSHbLAjj0s1Wzd+dg== - -js-image-generator@^1.0.4: - version "1.0.4" - resolved "https://registry.npmjs.org/js-image-generator/-/js-image-generator-1.0.4.tgz" - integrity sha512-ckb7kyVojGAnArouVR+5lBIuwU1fcrn7E/YYSd0FK7oIngAkMmRvHASLro9Zt5SQdWToaI66NybG+OGxPw/HlQ== - dependencies: - jpeg-js "^0.4.2" - "js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz" @@ -6155,55 +3764,7 @@ jsonc-parser@^3.0.0, jsonc-parser@^3.3.1: resolved "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.3.1.tgz" integrity sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ== -jsonpointer@^5.0.0: - version "5.0.1" - resolved "https://registry.npmjs.org/jsonpointer/-/jsonpointer-5.0.1.tgz" - integrity sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ== - -jsonwebtoken@9.0.3: - version "9.0.3" - resolved "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.3.tgz" - integrity sha512-MT/xP0CrubFRNLNKvxJ2BYfy53Zkm++5bX9dtuPbqAeQpTVe0MQTFhao8+Cp//EmJp244xt6Drw/GVEGCUj40g== - dependencies: - jws "^4.0.1" - lodash.includes "^4.3.0" - lodash.isboolean "^3.0.3" - lodash.isinteger "^4.0.4" - lodash.isnumber "^3.0.3" - lodash.isplainobject "^4.0.6" - lodash.isstring "^4.0.1" - lodash.once "^4.0.0" - ms "^2.1.1" - semver "^7.5.4" - -junk@^4.0.0: - version "4.0.1" - resolved "https://registry.npmjs.org/junk/-/junk-4.0.1.tgz" - integrity sha512-Qush0uP+G8ZScpGMZvHUiRfI0YBWuB3gVBYlI0v0vvOJt5FLicco+IkP0a50LqTTQhmts/m6tP5SWE+USyIvcQ== - -jwa@^2.0.1: - version "2.0.1" - resolved "https://registry.npmjs.org/jwa/-/jwa-2.0.1.tgz" - integrity sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg== - dependencies: - buffer-equal-constant-time "^1.0.1" - ecdsa-sig-formatter "1.0.11" - safe-buffer "^5.0.1" - -jws@^4.0.1: - version "4.0.1" - resolved "https://registry.npmjs.org/jws/-/jws-4.0.1.tgz" - integrity sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA== - dependencies: - jwa "^2.0.1" - safe-buffer "^5.0.1" - -jwt-decode@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/jwt-decode/-/jwt-decode-4.0.0.tgz" - integrity sha512-+KJGIyHgkGuIq3IEBNftfhW/LfWhXUIY6OmyVWjliu5KH1y0fw7VQ8YndE2O4qZdMSd9SqbnC8GOcZEy0Om7sA== - -keyv@^4.0.0, keyv@^4.5.4: +keyv@^4.5.4: version "4.5.4" resolved "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz" integrity sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw== @@ -6215,32 +3776,6 @@ kleur@^4.1.5: resolved "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz" integrity sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ== -kuler@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz" - integrity sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A== - -lambda-local@^2.2.0: - version "2.2.0" - resolved "https://registry.npmjs.org/lambda-local/-/lambda-local-2.2.0.tgz" - integrity sha512-bPcgpIXbHnVGfI/omZIlgucDqlf4LrsunwoKue5JdZeGybt8L6KyJz2Zu19ffuZwIwLj2NAI2ZyaqNT6/cetcg== - dependencies: - commander "^10.0.1" - dotenv "^16.3.1" - winston "^3.10.0" - -lazystream@^1.0.0: - version "1.0.1" - resolved "https://registry.npmjs.org/lazystream/-/lazystream-1.0.1.tgz" - integrity sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw== - dependencies: - readable-stream "^2.0.5" - -"leven@^3.1.0 < 4": - version "3.1.0" - resolved "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz" - integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== - levn@^0.4.1: version "0.4.1" resolved "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz" @@ -6254,30 +3789,6 @@ lines-and-columns@^1.1.6: resolved "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz" integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== -listhen@^1.9.0: - version "1.10.0" - resolved "https://registry.npmjs.org/listhen/-/listhen-1.10.0.tgz" - integrity sha512-kfz4C0OrC6IpaVMtYDJtf6PFjurxe9NBBoDAh/o2p587INryFOO4DQ9OetbCdDrWFt1m1CJKvYrzkGsuPHw8nQ== - dependencies: - "@parcel/watcher" "^2.5.6" - "@parcel/watcher-wasm" "^2.5.6" - citty "^0.2.2" - consola "^3.4.2" - crossws ">=0.2.0 <0.5.0" - defu "^6.1.7" - get-port-please "^3.2.0" - h3 "^1.15.11" - http-shutdown "^1.2.2" - jiti "^2.6.1" - mlly "^1.8.2" - node-forge "^1.4.0" - pathe "^2.0.3" - std-env "^4.1.0" - tinyclip "^0.1.12" - ufo "^1.6.4" - untun "^0.1.3" - uqr "^0.1.3" - locate-character@^3.0.0: version "3.0.0" resolved "https://registry.npmjs.org/locate-character/-/locate-character-3.0.0.tgz" @@ -6290,65 +3801,6 @@ locate-path@^6.0.0: dependencies: p-locate "^5.0.0" -locate-path@^7.0.0, locate-path@^7.2.0: - version "7.2.0" - resolved "https://registry.npmjs.org/locate-path/-/locate-path-7.2.0.tgz" - integrity sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA== - dependencies: - p-locate "^6.0.0" - -lodash.includes@^4.3.0: - version "4.3.0" - resolved "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz" - integrity sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w== - -lodash.isboolean@^3.0.3: - version "3.0.3" - resolved "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz" - integrity sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg== - -lodash.isinteger@^4.0.4: - version "4.0.4" - resolved "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz" - integrity sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA== - -lodash.isnumber@^3.0.3: - version "3.0.3" - resolved "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz" - integrity sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw== - -lodash.isplainobject@^4.0.6: - version "4.0.6" - resolved "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz" - integrity sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA== - -lodash.isstring@^4.0.1: - version "4.0.1" - resolved "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz" - integrity sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw== - -lodash.once@^4.0.0: - version "4.1.1" - resolved "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz" - integrity sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg== - -lodash@^4.17.15: - version "4.18.1" - resolved "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz" - integrity sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q== - -logform@^2.7.0: - version "2.7.0" - resolved "https://registry.npmjs.org/logform/-/logform-2.7.0.tgz" - integrity sha512-TFYA4jnP7PVbmlBIfhlSe+WKxs9dklXMTEGcBCIvLhE/Tn3H6Gk1norupVW7m5Cnd4bLcr08AytbyV/xj7f/kQ== - dependencies: - "@colors/colors" "1.6.0" - "@types/triple-beam" "^1.3.2" - fecha "^4.2.0" - ms "^2.1.1" - safe-stable-stringify "^2.3.1" - triple-beam "^1.3.0" - longest-streak@^3.0.0: version "3.1.0" resolved "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz" @@ -6361,17 +3813,12 @@ loose-envify@^1.4.0: dependencies: js-tokens "^3.0.0 || ^4.0.0" -lowercase-keys@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-2.0.0.tgz#2603e78b7b4b0006cbca2fbcc8a3202558ac9479" - integrity sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA== - -lru-cache@^10.0.1, lru-cache@^10.2.0: +lru-cache@^10.2.0: version "10.4.3" resolved "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz" integrity sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ== -lru-cache@^11.0.0, lru-cache@^11.2.7: +lru-cache@^11.2.7: version "11.3.6" resolved "https://registry.npmjs.org/lru-cache/-/lru-cache-11.3.6.tgz" integrity sha512-Gf/KoL3C/MlI7Bt0PGI9I+TeTC/I6r/csU58N4BSNc4lppLBeKsOdFYkK+dX0ABDUMJNfCHTyPpzwwO21Awd3A== @@ -6388,11 +3835,6 @@ lru-cache@^7.14.1: resolved "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz" integrity sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA== -luxon@^3.2.1: - version "3.7.2" - resolved "https://registry.npmjs.org/luxon/-/luxon-3.7.2.tgz" - integrity sha512-vtEhXh/gNjI9Yg1u4jX/0YVPMvxzHuGgCm6tC5kZyb08yjGWGnqAjGJvcXbqQR2P3MyMEFnRbpcdFS6PBcLqew== - magic-string@^0.30.11, magic-string@^0.30.21: version "0.30.21" resolved "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz" @@ -6409,11 +3851,6 @@ magicast@^0.5.2: "@babel/types" "^7.29.0" source-map-js "^1.2.1" -map-obj@^5.0.0: - version "5.0.2" - resolved "https://registry.npmjs.org/map-obj/-/map-obj-5.0.2.tgz" - integrity sha512-K6K2NgKnTXimT3779/4KxSvobxOtMmx1LBZ3NwRxT/MDIR3Br/fQ4Q+WCX5QxjyUR8zg5+RV9Tbf2c5pAWTD2A== - markdown-table@^3.0.0: version "3.0.4" resolved "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.4.tgz" @@ -6591,18 +4028,6 @@ merge-descriptors@^2.0.0: resolved "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz" integrity sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g== -merge-options@^3.0.4: - version "3.0.4" - resolved "https://registry.npmjs.org/merge-options/-/merge-options-3.0.4.tgz" - integrity sha512-2Sug1+knBjkaMsMgf1ctR1Ujx+Ayku4EdJN4Z+C2+JzoeF7A3OZ9KM2GY0CpQS51NR61LTurMJrRKPhSs3ZRTQ== - dependencies: - is-plain-obj "^2.1.0" - -merge-stream@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz" - integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== - merge2@^1.3.0: version "1.4.1" resolved "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz" @@ -6901,33 +4326,6 @@ mime-types@^3.0.0, mime-types@^3.0.2: dependencies: mime-db "^1.54.0" -mimic-fn@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz" - integrity sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw== - -mimic-response@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b" - integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ== - -mimic-response@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-3.1.0.tgz#2d1d59af9c1b129815accc2c46a022a5ce1fa3c9" - integrity sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ== - -miniflare@4.20260430.0: - version "4.20260430.0" - resolved "https://registry.npmjs.org/miniflare/-/miniflare-4.20260430.0.tgz" - integrity sha512-MWvMm3Siho9Yj7lbJZidLs8hbrRvIcOrif2mnsHQZdvoKfedpea+GaN8XJxbpRcq0B2WzNI1BB1ihdnqes3/ZA== - dependencies: - "@cspotcode/source-map-support" "0.8.1" - sharp "^0.34.5" - undici "7.24.8" - workerd "1.20260430.1" - ws "8.18.0" - youch "4.1.0-beta.10" - minimatch@^10.2.1, minimatch@^10.2.2, minimatch@^10.2.4: version "10.2.5" resolved "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz" @@ -6935,20 +4333,6 @@ minimatch@^10.2.1, minimatch@^10.2.2, minimatch@^10.2.4: dependencies: brace-expansion "^5.0.5" -minimatch@^3.1.1: - version "3.1.5" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.5.tgz#580c88f8d5445f2bd6aa8f3cadefa0de79fbd69e" - integrity sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w== - dependencies: - brace-expansion "^1.1.7" - -minimatch@^5.1.0: - version "5.1.9" - resolved "https://registry.npmjs.org/minimatch/-/minimatch-5.1.9.tgz" - integrity sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw== - dependencies: - brace-expansion "^2.0.1" - minimatch@^8.0.2: version "8.0.7" resolved "https://registry.npmjs.org/minimatch/-/minimatch-8.0.7.tgz" @@ -6956,35 +4340,16 @@ minimatch@^8.0.2: dependencies: brace-expansion "^2.0.1" -minimatch@^9.0.4: - version "9.0.9" - resolved "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz" - integrity sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg== - dependencies: - brace-expansion "^2.0.2" - -minimist@^1.2.5, minimist@^1.2.6: - version "1.2.8" - resolved "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz" - integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== - minipass@^4.2.4: version "4.2.8" resolved "https://registry.npmjs.org/minipass/-/minipass-4.2.8.tgz" integrity sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ== -"minipass@^5.0.0 || ^6.0.2 || ^7.0.0", minipass@^7.0.4, minipass@^7.1.2, minipass@^7.1.3: +"minipass@^5.0.0 || ^6.0.2 || ^7.0.0": version "7.1.3" resolved "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz" integrity sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A== -minizlib@^3.1.0: - version "3.1.0" - resolved "https://registry.npmjs.org/minizlib/-/minizlib-3.1.0.tgz" - integrity sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw== - dependencies: - minipass "^7.1.2" - mitt@3.0.0: version "3.0.0" resolved "https://registry.npmjs.org/mitt/-/mitt-3.0.0.tgz" @@ -7000,36 +4365,6 @@ mkdirp-classic@^0.5.2: resolved "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz" integrity sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A== -mkdirp@^0.5.4: - version "0.5.6" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6" - integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw== - dependencies: - minimist "^1.2.6" - -mlly@^1.7.4, mlly@^1.8.2: - version "1.8.2" - resolved "https://registry.npmjs.org/mlly/-/mlly-1.8.2.tgz" - integrity sha512-d+ObxMQFmbt10sretNDytwt85VrbkhhUA/JBGm1MPaWJ65Cl4wOgLaB1NYvJSZ0Ef03MMEU/0xpPMXUIQ29UfA== - dependencies: - acorn "^8.16.0" - pathe "^2.0.3" - pkg-types "^1.3.1" - ufo "^1.6.3" - -module-definition@^6.0.1: - version "6.0.2" - resolved "https://registry.npmjs.org/module-definition/-/module-definition-6.0.2.tgz" - integrity sha512-SvAU3lB0+Yjbq55yHY3wkRZBOh+fhU1SnIF3IFbTewv6mtAh7yUT8ACHAJ2mGIJ7tCes2QuCL/cl6m0JSZ/ArA== - dependencies: - ast-module-types "^6.0.1" - node-source-walk "^7.0.1" - -module-details-from-path@^1.0.3: - version "1.0.4" - resolved "https://registry.npmjs.org/module-details-from-path/-/module-details-from-path-1.0.4.tgz" - integrity sha512-EGWKgxALGMgzvxYF1UyGTy0HXX/2vHLkw6+NvDKW2jypWbHpjQuj4UMcqQWXHERJhVGKikolT06G3bcKe4fi7w== - motion-dom@^12.38.0: version "12.38.0" resolved "https://registry.npmjs.org/motion-dom/-/motion-dom-12.38.0.tgz" @@ -7047,17 +4382,12 @@ mrmime@^2.0.1: resolved "https://registry.npmjs.org/mrmime/-/mrmime-2.0.1.tgz" integrity sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ== -ms@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" - integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== - ms@2.1.2: version "2.1.2" resolved "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== -ms@^2.1.1, ms@^2.1.3: +ms@^2.1.3: version "2.1.3" resolved "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== @@ -7072,11 +4402,6 @@ nanoid@^3.3.11: resolved "https://registry.npmjs.org/nanoid/-/nanoid-3.3.12.tgz" integrity sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ== -napi-wasm@^1.1.0: - version "1.1.3" - resolved "https://registry.yarnpkg.com/napi-wasm/-/napi-wasm-1.1.3.tgz#7bb95c88e6561f84880bb67195437b1cfbe99224" - integrity sha512-h/4nMGsHjZDCYmQVNODIrYACVJ+I9KItbG+0si6W/jSjdA9JbWDoU4LLeMXVcEQGHjttI2tuXqDrbGF7qkUHHg== - natural-compare@^1.4.0: version "1.4.0" resolved "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz" @@ -7092,11 +4417,6 @@ neotraverse@^0.6.18: resolved "https://registry.npmjs.org/neotraverse/-/neotraverse-0.6.18.tgz" integrity sha512-Z4SmBUweYa09+o6pG+eASabEpP6QkQ70yHj351pQoEXIs8uHbaU2DWVmzBANKgflPa47A50PtB2+NgRpQvr7vA== -netlify-redirector@^0.5.0: - version "0.5.0" - resolved "https://registry.npmjs.org/netlify-redirector/-/netlify-redirector-0.5.0.tgz" - integrity sha512-4zdzIP+6muqPCuE8avnrgDJ6KW/2+UpHTRcTbMXCIRxiRmyrX+IZ4WSJGZdHPWF3WmQpXpy603XxecZ9iygN7w== - netmask@^2.0.2: version "2.1.1" resolved "https://registry.npmjs.org/netmask/-/netmask-2.1.1.tgz" @@ -7114,21 +4434,6 @@ node-addon-api@^7.0.0: resolved "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz" integrity sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ== -node-domexception@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz" - integrity sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ== - -node-exports-info@^1.6.0: - version "1.6.0" - resolved "https://registry.npmjs.org/node-exports-info/-/node-exports-info-1.6.0.tgz" - integrity sha512-pyFS63ptit/P5WqUkt+UUfe+4oevH+bFeIiPPdfb0pFeYEu/1ELnJu5l+5EcTKYL5M7zaAa7S8ddywgXypqKCw== - dependencies: - array.prototype.flatmap "^1.3.3" - es-errors "^1.3.0" - object.entries "^1.1.9" - semver "^6.3.1" - node-fetch-native@^1.6.7: version "1.6.7" resolved "https://registry.npmjs.org/node-fetch-native/-/node-fetch-native-1.6.7.tgz" @@ -7141,32 +4446,6 @@ node-fetch@2.6.7: dependencies: whatwg-url "^5.0.0" -node-fetch@^2.6.7: - version "2.7.0" - resolved "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz" - integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== - dependencies: - whatwg-url "^5.0.0" - -node-fetch@^3.0.0: - version "3.3.2" - resolved "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz" - integrity sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA== - dependencies: - data-uri-to-buffer "^4.0.0" - fetch-blob "^3.1.4" - formdata-polyfill "^4.0.10" - -node-forge@^1.4.0: - version "1.4.0" - resolved "https://registry.npmjs.org/node-forge/-/node-forge-1.4.0.tgz" - integrity sha512-LarFH0+6VfriEhqMMcLX2F7SwSXeWwnEAJEsYm5QKWchiVYVvJyV9v7UDvUv+w5HO23ZpQTXDv/GxdDdMyOuoQ== - -node-gyp-build@^4.2.2: - version "4.8.4" - resolved "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.4.tgz" - integrity sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ== - node-mock-http@^1.0.4: version "1.0.4" resolved "https://registry.npmjs.org/node-mock-http/-/node-mock-http-1.0.4.tgz" @@ -7177,18 +4456,6 @@ node-releases@^2.0.36: resolved "https://registry.npmjs.org/node-releases/-/node-releases-2.0.38.tgz" integrity sha512-3qT/88Y3FbH/Kx4szpQQ4HzUbVrHPKTLVpVocKiLfoYvw9XSGOX2FmD2d6DrXbVYyAQTF2HeF6My8jmzx7/CRw== -node-source-walk@^7.0.1: - version "7.0.2" - resolved "https://registry.npmjs.org/node-source-walk/-/node-source-walk-7.0.2.tgz" - integrity sha512-71kFFjYaSshDTA8/a2HiTYPLdASWjLJxUyJxGE+ffxU+KhxSBtM9kiLUX+R2yooFdSFKMFpi4n3PFtDy6qXv8A== - dependencies: - "@babel/parser" "^7.29.0" - -node-stream-zip@^1.15.0: - version "1.15.0" - resolved "https://registry.npmjs.org/node-stream-zip/-/node-stream-zip-1.15.0.tgz" - integrity sha512-LN4fydt9TqhZhThkZIVQnF9cwjU3qmUH9h78Mx/K7d3VvfRqqwthLwJEUOEL0QPZ0XQmNN7be5Ggit5+4dq3Bw== - nodemon@^3.1.14: version "3.1.14" resolved "https://registry.npmjs.org/nodemon/-/nodemon-3.1.14.tgz" @@ -7205,46 +4472,11 @@ nodemon@^3.1.14: touch "^3.1.0" undefsafe "^2.0.5" -nopt@^8.0.0: - version "8.1.0" - resolved "https://registry.npmjs.org/nopt/-/nopt-8.1.0.tgz" - integrity sha512-ieGu42u/Qsa4TFktmaKEwM6MQH0pOWnaB3htzh0JRtx84+Mebc0cbZYN5bC+6WTZ4+77xrL9Pn5m7CV6VIkV7A== - dependencies: - abbrev "^3.0.0" - -normalize-package-data@^6.0.0: - version "6.0.2" - resolved "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-6.0.2.tgz" - integrity sha512-V6gygoYb/5EmNI+MEGrWkC+e6+Rr7mTmfHrxDbLzxQogBkgzo76rkok0Am6thgSF7Mv2nLOajAJj5vDJZEFn7g== - dependencies: - hosted-git-info "^7.0.0" - semver "^7.3.5" - validate-npm-package-license "^3.0.4" - -normalize-path@^2.1.1: - version "2.1.1" - resolved "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz" - integrity sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w== - dependencies: - remove-trailing-separator "^1.0.1" - normalize-path@^3.0.0, normalize-path@~3.0.0: version "3.0.0" resolved "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz" integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== -normalize-url@^6.0.1: - version "6.1.0" - resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-6.1.0.tgz#40d0885b535deffe3f3147bec877d05fe4c5668a" - integrity sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A== - -npm-run-path@^5.1.0: - version "5.3.0" - resolved "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz" - integrity sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ== - dependencies: - path-key "^4.0.0" - nth-check@^2.0.1: version "2.1.1" resolved "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz" @@ -7262,39 +4494,12 @@ object-inspect@^1.13.3, object-inspect@^1.13.4: resolved "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz" integrity sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew== -object-keys@^1.1.1: - version "1.1.1" - resolved "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz" - integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== - -object.assign@^4.1.7: - version "4.1.7" - resolved "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz" - integrity sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw== - dependencies: - call-bind "^1.0.8" - call-bound "^1.0.3" - define-properties "^1.2.1" - es-object-atoms "^1.0.0" - has-symbols "^1.1.0" - object-keys "^1.1.1" - -object.entries@^1.1.9: - version "1.1.9" - resolved "https://registry.npmjs.org/object.entries/-/object.entries-1.1.9.tgz" - integrity sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw== - dependencies: - call-bind "^1.0.8" - call-bound "^1.0.4" - define-properties "^1.2.1" - es-object-atoms "^1.1.1" - obug@^2.1.0, obug@^2.1.1: version "2.1.1" resolved "https://registry.npmjs.org/obug/-/obug-2.1.1.tgz" integrity sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ== -ofetch@^1.4.1, ofetch@^1.5.1: +ofetch@^1.5.1: version "1.5.1" resolved "https://registry.npmjs.org/ofetch/-/ofetch-1.5.1.tgz" integrity sha512-2W4oUZlVaqAPAil6FUg/difl6YhqhUR7x2eZY4bQCko22UXg3hptq9KLQdqFClV+Wu85UX7hNtdGTngi/1BxcA== @@ -7308,11 +4513,6 @@ ohash@^2.0.11: resolved "https://registry.npmjs.org/ohash/-/ohash-2.0.11.tgz" integrity sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ== -omit.js@^2.0.2: - version "2.0.2" - resolved "https://registry.npmjs.org/omit.js/-/omit.js-2.0.2.tgz" - integrity sha512-hJmu9D+bNB40YpL9jYebQl4lsTW6yEHRTroJzNLqQJYHm7c+NQnJGfZmIWh8S3q3KoaxV1aLhV6B3+0N0/kyJg== - on-finished@^2.4.1: version "2.4.1" resolved "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz" @@ -7320,27 +4520,13 @@ on-finished@^2.4.1: dependencies: ee-first "1.1.1" -once@^1.3.0, once@^1.3.1, once@^1.4.0: +once@^1.3.1, once@^1.4.0: version "1.4.0" resolved "https://registry.npmjs.org/once/-/once-1.4.0.tgz" integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== dependencies: wrappy "1" -one-time@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/one-time/-/one-time-1.0.0.tgz" - integrity sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g== - dependencies: - fn.name "1.x.x" - -onetime@^6.0.0: - version "6.0.0" - resolved "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz" - integrity sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ== - dependencies: - mimic-fn "^4.0.0" - oniguruma-parser@^0.12.2: version "0.12.2" resolved "https://registry.npmjs.org/oniguruma-parser/-/oniguruma-parser-0.12.2.tgz" @@ -7367,32 +4553,6 @@ optionator@^0.9.3: type-check "^0.4.0" word-wrap "^1.2.5" -os-tmpdir@~1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" - integrity sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g== - -own-keys@^1.0.1: - version "1.0.1" - resolved "https://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz" - integrity sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg== - dependencies: - get-intrinsic "^1.2.6" - object-keys "^1.1.1" - safe-push-apply "^1.0.0" - -p-cancelable@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-2.1.1.tgz#aab7fbd416582fa32a3db49859c122487c5ed2cf" - integrity sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg== - -p-event@^6.0.0: - version "6.0.1" - resolved "https://registry.npmjs.org/p-event/-/p-event-6.0.1.tgz" - integrity sha512-Q6Bekk5wpzW5qIyUP4gdMEujObYstZl6DMMOSenwBvV0BlE5LkDwkjs5yHbZmdCEq2o4RJx4tE1vwxFVf2FG1w== - dependencies: - p-timeout "^6.1.2" - p-limit@^3.0.2: version "3.1.0" resolved "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz" @@ -7400,13 +4560,6 @@ p-limit@^3.0.2: dependencies: yocto-queue "^0.1.0" -p-limit@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz" - integrity sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ== - dependencies: - yocto-queue "^1.0.0" - p-limit@^7.3.0: version "7.3.0" resolved "https://registry.npmjs.org/p-limit/-/p-limit-7.3.0.tgz" @@ -7421,18 +4574,6 @@ p-locate@^5.0.0: dependencies: p-limit "^3.0.2" -p-locate@^6.0.0: - version "6.0.0" - resolved "https://registry.npmjs.org/p-locate/-/p-locate-6.0.0.tgz" - integrity sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw== - dependencies: - p-limit "^4.0.0" - -p-map@^7.0.0: - version "7.0.4" - resolved "https://registry.npmjs.org/p-map/-/p-map-7.0.4.tgz" - integrity sha512-tkAQEw8ysMzmkhgw8k+1U/iPhWNhykKnSk4Rd5zLoPJCuJaGRPo6YposrZgaxHKzDHdDWWZvE/Sk7hsL2X/CpQ== - p-queue@^9.1.0: version "9.2.0" resolved "https://registry.npmjs.org/p-queue/-/p-queue-9.2.0.tgz" @@ -7441,32 +4582,11 @@ p-queue@^9.1.0: eventemitter3 "^5.0.4" p-timeout "^7.0.0" -p-retry@^6.0.0: - version "6.2.1" - resolved "https://registry.npmjs.org/p-retry/-/p-retry-6.2.1.tgz" - integrity sha512-hEt02O4hUct5wtwg4H4KcWgDdm+l1bOaEy/hWzd8xtXB9BqxTWBBhb+2ImAtH4Cv4rPjV76xN3Zumqk3k3AhhQ== - dependencies: - "@types/retry" "0.12.2" - is-network-error "^1.0.0" - retry "^0.13.1" - -p-timeout@^6.0.0, p-timeout@^6.1.2: - version "6.1.4" - resolved "https://registry.npmjs.org/p-timeout/-/p-timeout-6.1.4.tgz" - integrity sha512-MyIV3ZA/PmyBN/ud8vV9XzwTrNtR4jFrObymZYnZqMmW0zA8Z17vnT0rBgFE/TlohB+YCHqXMgZzb3Csp49vqg== - p-timeout@^7.0.0: version "7.0.1" resolved "https://registry.npmjs.org/p-timeout/-/p-timeout-7.0.1.tgz" integrity sha512-AxTM2wDGORHGEkPCt8yqxOTMgpfbEHqF51f/5fJCmwFC3C/zNcGT63SymH2ttOAaiIws2zVg4+izQCjrakcwHg== -p-wait-for@^5.0.0: - version "5.0.2" - resolved "https://registry.npmjs.org/p-wait-for/-/p-wait-for-5.0.2.tgz" - integrity sha512-lwx6u1CotQYPVju77R+D0vFomni/AqRfqLmqQ8hekklqZ6gAY9rONh7lBQ0uxWMkC2AuX9b2DVAl8To0NyP1JA== - dependencies: - p-timeout "^6.0.0" - pac-proxy-agent@^7.1.0: version "7.2.0" resolved "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-7.2.0.tgz" @@ -7489,11 +4609,6 @@ pac-resolver@^7.0.1: degenerator "^5.0.0" netmask "^2.0.2" -package-json-from-dist@^1.0.0: - version "1.0.1" - resolved "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz" - integrity sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw== - package-manager-detector@^1.6.0: version "1.6.0" resolved "https://registry.npmjs.org/package-manager-detector/-/package-manager-detector-1.6.0.tgz" @@ -7506,19 +4621,6 @@ parent-module@^1.0.0: dependencies: callsites "^3.0.0" -parse-gitignore@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/parse-gitignore/-/parse-gitignore-2.0.0.tgz" - integrity sha512-RmVuCHWsfu0QPNW+mraxh/xjQVw/lhUCUru8Zni3Ctq3AoMhpDTq0OVdKS6iesd6Kqb7viCV3isAL43dciOSog== - -parse-imports@^2.2.1: - version "2.2.1" - resolved "https://registry.npmjs.org/parse-imports/-/parse-imports-2.2.1.tgz" - integrity sha512-OL/zLggRp8mFhKL0rNORUTR4yBYujK/uU+xZL+/0Rgm2QE4nLO9v8PzEweSJEbMGKmDRjJE4R3IMJlL2di4JeQ== - dependencies: - es-module-lexer "^1.5.3" - slashes "^3.0.12" - parse-json@^5.0.0, parse-json@^5.2.0: version "5.2.0" resolved "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz" @@ -7529,15 +4631,6 @@ parse-json@^5.0.0, parse-json@^5.2.0: json-parse-even-better-errors "^2.3.0" lines-and-columns "^1.1.6" -parse-json@^8.0.0: - version "8.3.0" - resolved "https://registry.npmjs.org/parse-json/-/parse-json-8.3.0.tgz" - integrity sha512-ybiGyvspI+fAoRQbIPRddCcSTV9/LsJbf0e/S85VLowVGzRmokfneg2kwVW/KU5rOXrPSbF1qAKPMgNTqqROQQ== - dependencies: - "@babel/code-frame" "^7.26.2" - index-to-position "^1.1.0" - type-fest "^4.39.1" - parse-latin@^7.0.0: version "7.0.0" resolved "https://registry.npmjs.org/parse-latin/-/parse-latin-7.0.0.tgz" @@ -7587,32 +4680,17 @@ path-exists@^4.0.0: resolved "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz" integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== -path-exists@^5.0.0: - version "5.0.0" - resolved "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz" - integrity sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ== - -path-is-absolute@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" - integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== - path-key@^3.1.0: version "3.1.1" resolved "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz" integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== -path-key@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz" - integrity sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ== - path-parse@^1.0.7: version "1.0.7" resolved "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz" integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== -path-scurry@^1.11.1, path-scurry@^1.6.1: +path-scurry@^1.6.1: version "1.11.1" resolved "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz" integrity sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA== @@ -7620,25 +4698,7 @@ path-scurry@^1.11.1, path-scurry@^1.6.1: lru-cache "^10.2.0" minipass "^5.0.0 || ^6.0.2 || ^7.0.0" -path-scurry@^2.0.2: - version "2.0.2" - resolved "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.2.tgz" - integrity sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg== - dependencies: - lru-cache "^11.0.0" - minipass "^7.1.2" - -"path-to-regexp-updated@npm:path-to-regexp@6.3.0": - version "6.3.0" - resolved "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.3.0.tgz" - integrity sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ== - -path-to-regexp@6.1.0: - version "6.1.0" - resolved "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.1.0.tgz" - integrity sha512-h9DqehX3zZZDCEm+xbfU0ZmwCGFCAAraPJWMXJ4+v32NjZJilVg3k1TcKsRgIb8IQ/izZSaydDc1OhJCZvs2Dw== - -path-to-regexp@6.3.0, path-to-regexp@^6.3.0: +path-to-regexp@^6.3.0: version "6.3.0" resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-6.3.0.tgz#2b6a26a337737a8e1416f9272ed0766b1c0389f4" integrity sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ== @@ -7653,31 +4713,11 @@ path-type@^4.0.0: resolved "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz" integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== -path-type@^6.0.0: - version "6.0.0" - resolved "https://registry.npmjs.org/path-type/-/path-type-6.0.0.tgz" - integrity sha512-Vj7sf++t5pBD637NSfkxpHSMfWaeig5+DKWLhcqIYx6mWQz5hdJTGDVMQiJcw1ZYkhs7AazKDGpRVji1LJCZUQ== - -pathe@^1.1.1: - version "1.1.2" - resolved "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz" - integrity sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ== - -pathe@^2.0.1, pathe@^2.0.3: - version "2.0.3" - resolved "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz" - integrity sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w== - pend@~1.2.0: version "1.2.0" resolved "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz" integrity sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg== -pg-gateway@0.3.0-beta.4: - version "0.3.0-beta.4" - resolved "https://registry.npmjs.org/pg-gateway/-/pg-gateway-0.3.0-beta.4.tgz" - integrity sha512-CTjsM7Z+0Nx2/dyZ6r8zRsc3f9FScoD5UAOlfUx1Fdv/JOIWvRbF7gou6l6vP+uypXQVoYPgw8xZDXgMGvBa4Q== - piccolore@^0.1.3: version "0.1.3" resolved "https://registry.npmjs.org/piccolore/-/piccolore-0.1.3.tgz" @@ -7693,25 +4733,6 @@ picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1, picomatch@^2.3.2, picomatc resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.2.tgz#5a942915e26b372dc0f0e6753149a16e6b1c5601" integrity sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA== -picoquery@^2.5.0: - version "2.5.0" - resolved "https://registry.npmjs.org/picoquery/-/picoquery-2.5.0.tgz" - integrity sha512-j1kgOFxtaCyoFCkpoYG2Oj3OdGakadO7HZ7o5CqyRazlmBekKhbDoUnNnXASE07xSY4nDImWZkrZv7toSxMi/g== - -pkg-types@^1.3.1: - version "1.3.1" - resolved "https://registry.npmjs.org/pkg-types/-/pkg-types-1.3.1.tgz" - integrity sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ== - dependencies: - confbox "^0.1.8" - mlly "^1.7.4" - pathe "^2.0.1" - -possible-typed-array-names@^1.0.0: - version "1.1.0" - resolved "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz" - integrity sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg== - postcss-selector-parser@^7.0.0: version "7.1.1" resolved "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz" @@ -7720,16 +4741,7 @@ postcss-selector-parser@^7.0.0: cssesc "^3.0.0" util-deprecate "^1.0.2" -postcss-values-parser@^6.0.2: - version "6.0.2" - resolved "https://registry.npmjs.org/postcss-values-parser/-/postcss-values-parser-6.0.2.tgz" - integrity sha512-YLJpK0N1brcNJrs9WatuJFtHaV9q5aAOj+S4DI5S7jgHlRfm0PIbDCAFRYMQD5SHq7Fy6xsDhyutgS0QOAs0qw== - dependencies: - color-name "^1.1.4" - is-url-superb "^4.0.0" - quote-unquote "^1.0.0" - -postcss@^8.4.14, postcss@^8.5.10, postcss@^8.5.6: +postcss@^8.4.14, postcss@^8.5.6: version "8.5.14" resolved "https://registry.npmjs.org/postcss/-/postcss-8.5.14.tgz" integrity sha512-SoSL4+OSEtR99LHFZQiJLkT59C5B1amGO1NzTwj7TT1qCUgUO6hxOvzkOYxD+vMrXBM3XJIKzokoERdqQq/Zmg== @@ -7738,27 +4750,6 @@ postcss@^8.4.14, postcss@^8.5.10, postcss@^8.5.6: picocolors "^1.1.1" source-map-js "^1.2.1" -precinct@^12.0.0: - version "12.3.1" - resolved "https://registry.npmjs.org/precinct/-/precinct-12.3.1.tgz" - integrity sha512-wGyTIvtxh2S2NAHxTJj0YymxWOIcEDotu17yHoQUd2Bz2C07LrS28L1nvXDMxrCHvHmV6KTlaIQy5PzRm7Y8rg== - dependencies: - "@dependents/detective-less" "^5.0.1" - commander "^12.1.0" - detective-amd "^6.0.1" - detective-cjs "^6.1.0" - detective-es6 "^5.0.1" - detective-postcss "^7.0.1" - detective-sass "^6.0.1" - detective-scss "^5.0.1" - detective-stylus "^5.0.1" - detective-typescript "^14.1.1" - detective-vue2 "^2.3.0" - module-definition "^6.0.1" - node-source-walk "^7.0.1" - postcss "^8.5.10" - typescript "^5.9.3" - prelude-ls@^1.2.1: version "1.2.1" resolved "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz" @@ -7783,16 +4774,6 @@ prismjs@^1.30.0: resolved "https://registry.npmjs.org/prismjs/-/prismjs-1.30.0.tgz" integrity sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw== -process-nextick-args@~2.0.0: - version "2.0.1" - resolved "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz" - integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== - -process@^0.11.10: - version "0.11.10" - resolved "https://registry.npmjs.org/process/-/process-0.11.10.tgz" - integrity sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A== - progress@2.0.3, progress@^2.0.3: version "2.0.3" resolved "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz" @@ -7934,16 +4915,6 @@ queue-microtask@^1.2.2: resolved "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz" integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== -quick-lru@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-5.1.1.tgz#366493e6b3e42a3a6885e2e99d18f80fb7a8c932" - integrity sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA== - -quote-unquote@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/quote-unquote/-/quote-unquote-1.0.0.tgz" - integrity sha512-twwRO/ilhlG/FIgYeKGFqyHhoEhqgnKVkcmqMKi2r524gz3ZbDTcyFt38E9xjJI2vT+KbRNHVbnJ/e0I25Azwg== - radix3@^1.1.2: version "1.1.2" resolved "https://registry.npmjs.org/radix3/-/radix3-1.1.2.tgz" @@ -8031,40 +5002,7 @@ react@^19.2.5: resolved "https://registry.npmjs.org/react/-/react-19.2.5.tgz" integrity sha512-llUJLzz1zTUBrskt2pwZgLq59AemifIftw4aB7JxOqf1HY2FDaGDxgwpAPVzHU1kdWabH7FauP4i1oEeer2WCA== -read-package-up@^11.0.0: - version "11.0.0" - resolved "https://registry.npmjs.org/read-package-up/-/read-package-up-11.0.0.tgz" - integrity sha512-MbgfoNPANMdb4oRBNg5eqLbB2t2r+o5Ua1pNt8BqGp4I0FJZhuVSOj3PaBPni4azWuSzEdNn2evevzVmEk1ohQ== - dependencies: - find-up-simple "^1.0.0" - read-pkg "^9.0.0" - type-fest "^4.6.0" - -read-pkg@^9.0.0: - version "9.0.1" - resolved "https://registry.npmjs.org/read-pkg/-/read-pkg-9.0.1.tgz" - integrity sha512-9viLL4/n1BJUCT1NXVTdS1jtm80yDEgR5T4yCelII49Mbj0v1rZdKqj7zCiYdbB0CuCgdrvHcNogAKTFPBocFA== - dependencies: - "@types/normalize-package-data" "^2.4.3" - normalize-package-data "^6.0.0" - parse-json "^8.0.0" - type-fest "^4.6.0" - unicorn-magic "^0.1.0" - -readable-stream@^2.0.5, readable-stream@^2.2.2: - version "2.3.8" - resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz" - integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA== - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.3" - isarray "~1.0.0" - process-nextick-args "~2.0.0" - safe-buffer "~5.1.1" - string_decoder "~1.1.1" - util-deprecate "~1.0.1" - -readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.6.2: +readable-stream@^3.1.1, readable-stream@^3.4.0: version "3.6.2" resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz" integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== @@ -8073,24 +5011,6 @@ readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.6.2: string_decoder "^1.1.1" util-deprecate "^1.0.1" -readable-stream@^4.0.0: - version "4.7.0" - resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-4.7.0.tgz" - integrity sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg== - dependencies: - abort-controller "^3.0.0" - buffer "^6.0.3" - events "^3.3.0" - process "^0.11.10" - string_decoder "^1.3.0" - -readdir-glob@^1.1.2: - version "1.1.3" - resolved "https://registry.npmjs.org/readdir-glob/-/readdir-glob-1.1.3.tgz" - integrity sha512-v05I2k7xN8zXvPD9N+z/uhXPaj0sUFCe2rcWZIpBsqxfP7xXFQ0tipAd/wjj1YxWyWtUS5IDJpOG82JKt2EAVA== - dependencies: - minimatch "^5.1.0" - readdirp@^4.0.1: version "4.1.2" resolved "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz" @@ -8135,20 +5055,6 @@ redux@^5.0.1: resolved "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz" integrity sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w== -reflect.getprototypeof@^1.0.6, reflect.getprototypeof@^1.0.9: - version "1.0.10" - resolved "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz" - integrity sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw== - dependencies: - call-bind "^1.0.8" - define-properties "^1.2.1" - es-abstract "^1.23.9" - es-errors "^1.3.0" - es-object-atoms "^1.0.0" - get-intrinsic "^1.2.7" - get-proto "^1.0.1" - which-builtin-type "^1.2.1" - regex-recursion@^6.0.2: version "6.0.2" resolved "https://registry.npmjs.org/regex-recursion/-/regex-recursion-6.0.2.tgz" @@ -8168,18 +5074,6 @@ regex@^6.1.0: dependencies: regex-utilities "^2.3.0" -regexp.prototype.flags@^1.5.4: - version "1.5.4" - resolved "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz" - integrity sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA== - dependencies: - call-bind "^1.0.8" - define-properties "^1.2.1" - es-errors "^1.3.0" - get-proto "^1.0.1" - gopd "^1.2.0" - set-function-name "^2.0.2" - rehype-parse@^9.0.0: version "9.0.1" resolved "https://registry.npmjs.org/rehype-parse/-/rehype-parse-9.0.1.tgz" @@ -8269,11 +5163,6 @@ remark-stringify@^11.0.0: mdast-util-to-markdown "^2.0.0" unified "^11.0.0" -remove-trailing-separator@^1.0.1: - version "1.1.0" - resolved "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz" - integrity sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw== - request-light@^0.5.7: version "0.5.8" resolved "https://registry.npmjs.org/request-light/-/request-light-0.5.8.tgz" @@ -8294,46 +5183,22 @@ require-from-string@^2.0.2: resolved "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz" integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== -require-in-the-middle@^7.1.1: - version "7.5.2" - resolved "https://registry.npmjs.org/require-in-the-middle/-/require-in-the-middle-7.5.2.tgz" - integrity sha512-gAZ+kLqBdHarXB64XpAe2VCjB7rIRv+mU8tfRWziHRJ5umKsIHN2tLLv6EtMw7WCdP19S0ERVMldNvxYCHnhSQ== - dependencies: - debug "^4.3.5" - module-details-from-path "^1.0.3" - resolve "^1.22.8" - -require-package-name@^2.0.1: - version "2.0.1" - resolved "https://registry.npmjs.org/require-package-name/-/require-package-name-2.0.1.tgz" - integrity sha512-uuoJ1hU/k6M0779t3VMVIYpb2VMJk05cehCaABFhXaibcbvfgR8wKiozLjVFSzJPmQMRqIcO0HMyTFqfV09V6Q== - reselect@5.1.1, reselect@^5.1.0: version "5.1.1" resolved "https://registry.npmjs.org/reselect/-/reselect-5.1.1.tgz" integrity sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w== -resolve-alpn@^1.0.0: - version "1.2.1" - resolved "https://registry.yarnpkg.com/resolve-alpn/-/resolve-alpn-1.2.1.tgz#b7adbdac3546aaaec20b45e7d8265927072726f9" - integrity sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g== - resolve-from@^4.0.0: version "4.0.0" resolved "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz" integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== -resolve-from@^5.0.0: - version "5.0.0" - resolved "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz" - integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== - resolve-pkg-maps@^1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz" integrity sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw== -resolve@^1.19.0, resolve@^1.22.8: +resolve@^1.19.0: version "1.22.12" resolved "https://registry.npmjs.org/resolve/-/resolve-1.22.12.tgz" integrity sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA== @@ -8343,25 +5208,6 @@ resolve@^1.19.0, resolve@^1.22.8: path-parse "^1.0.7" supports-preserve-symlinks-flag "^1.0.0" -resolve@^2.0.0-next.1: - version "2.0.0-next.6" - resolved "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.6.tgz" - integrity sha512-3JmVl5hMGtJ3kMmB3zi3DL25KfkCEyy3Tw7Gmw7z5w8M9WlwoPFnIvwChzu1+cF3iaK3sp18hhPz8ANeimdJfA== - dependencies: - es-errors "^1.3.0" - is-core-module "^2.16.1" - node-exports-info "^1.6.0" - object-keys "^1.1.1" - path-parse "^1.0.7" - supports-preserve-symlinks-flag "^1.0.0" - -responselike@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/responselike/-/responselike-2.0.1.tgz#9a0bc8fdc252f3fb1cca68b016591059ba1422bc" - integrity sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw== - dependencies: - lowercase-keys "^2.0.0" - retext-latin@^4.0.0: version "4.0.0" resolved "https://registry.npmjs.org/retext-latin/-/retext-latin-4.0.0.tgz" @@ -8399,11 +5245,6 @@ retext@^9.0.0: retext-stringify "^4.0.0" unified "^11.0.0" -retry@^0.13.1: - version "0.13.1" - resolved "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz" - integrity sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg== - reusify@^1.0.4: version "1.1.0" resolved "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz" @@ -8416,13 +5257,6 @@ rimraf@4.4.0: dependencies: glob "^9.2.0" -rimraf@^2.7.1: - version "2.7.1" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" - integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== - dependencies: - glob "^7.1.3" - rollup@^4.43.0: version "4.60.3" resolved "https://registry.npmjs.org/rollup/-/rollup-4.60.3.tgz" @@ -8487,49 +5321,11 @@ s.color@0.0.15: resolved "https://registry.npmjs.org/s.color/-/s.color-0.0.15.tgz" integrity sha512-AUNrbEUHeKY8XsYr/DYpl+qk5+aM+DChopnWOPEzn8YKzOhv4l2zH6LzZms3tOZP3wwdOyc0RmTciyi46HLIuA== -safe-array-concat@^1.1.3: - version "1.1.4" - resolved "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.4.tgz" - integrity sha512-wtZlHyOje6OZTGqAoaDKxFkgRtkF9CnHAVnCHKfuj200wAgL+bSJhdsCD2l0Qx/2ekEXjPWcyKkfGb5CPboslg== - dependencies: - call-bind "^1.0.9" - call-bound "^1.0.4" - get-intrinsic "^1.3.0" - has-symbols "^1.1.0" - isarray "^2.0.5" - -safe-buffer@^5.0.1, safe-buffer@~5.2.0: +safe-buffer@~5.2.0: version "5.2.1" resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== -safe-buffer@~5.1.0, safe-buffer@~5.1.1: - version "5.1.2" - resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz" - integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== - -safe-push-apply@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz" - integrity sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA== - dependencies: - es-errors "^1.3.0" - isarray "^2.0.5" - -safe-regex-test@^1.1.0: - version "1.1.0" - resolved "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz" - integrity sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw== - dependencies: - call-bound "^1.0.2" - es-errors "^1.3.0" - is-regex "^1.2.1" - -safe-stable-stringify@^2.3.1: - version "2.5.0" - resolved "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz" - integrity sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA== - "safer-buffer@>= 2.1.2 < 3.0.0": version "2.1.2" resolved "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz" @@ -8573,12 +5369,12 @@ semver@^6.3.1: resolved "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz" integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== -semver@^7.3.5, semver@^7.3.8, semver@^7.5.2, semver@^7.5.3, semver@^7.5.4, semver@^7.6.2, semver@^7.6.3, semver@^7.7.2, semver@^7.7.3, semver@^7.7.4: +semver@^7.3.8, semver@^7.5.3, semver@^7.5.4, semver@^7.6.2, semver@^7.7.3, semver@^7.7.4: version "7.7.4" resolved "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz" integrity sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA== -send@^1.1.0, send@^1.2.0, send@^1.2.1: +send@^1.1.0, send@^1.2.0: version "1.2.1" resolved "https://registry.npmjs.org/send/-/send-1.2.1.tgz" integrity sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ== @@ -8605,53 +5401,17 @@ serve-static@^2.2.0: parseurl "^1.3.3" send "^1.2.0" -server-destroy@^1.0.1: - version "1.0.1" - resolved "https://registry.npmjs.org/server-destroy/-/server-destroy-1.0.1.tgz" - integrity sha512-rb+9B5YBIEzYcD6x2VKidaa+cqYBJQKnU4oe4E3ANwRRN56yk/ua1YCJT1n21NTS8w6CcOclAKNP3PhdCXKYtQ== - set-cookie-parser@^2.6.0: version "2.7.2" resolved "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.2.tgz" integrity sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw== -set-function-length@^1.2.2: - version "1.2.2" - resolved "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz" - integrity sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg== - dependencies: - define-data-property "^1.1.4" - es-errors "^1.3.0" - function-bind "^1.1.2" - get-intrinsic "^1.2.4" - gopd "^1.0.1" - has-property-descriptors "^1.0.2" - -set-function-name@^2.0.2: - version "2.0.2" - resolved "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz" - integrity sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ== - dependencies: - define-data-property "^1.1.4" - es-errors "^1.3.0" - functions-have-names "^1.2.3" - has-property-descriptors "^1.0.2" - -set-proto@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz" - integrity sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw== - dependencies: - dunder-proto "^1.0.1" - es-errors "^1.3.0" - es-object-atoms "^1.0.0" - setprototypeof@~1.2.0: version "1.2.0" resolved "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz" integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== -sharp@^0.34.0, sharp@^0.34.3, sharp@^0.34.5: +sharp@^0.34.0: version "0.34.5" resolved "https://registry.npmjs.org/sharp/-/sharp-0.34.5.tgz" integrity sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg== @@ -8756,11 +5516,6 @@ side-channel@^1.1.0: side-channel-map "^1.0.1" side-channel-weakmap "^1.0.2" -signal-exit@^4.0.1, signal-exit@^4.1.0: - version "4.1.0" - resolved "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz" - integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw== - simple-update-notifier@^2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz" @@ -8783,11 +5538,6 @@ sitemap@^9.0.0: arg "^5.0.0" sax "^1.4.1" -slashes@^3.0.12: - version "3.0.12" - resolved "https://registry.npmjs.org/slashes/-/slashes-3.0.12.tgz" - integrity sha512-Q9VME8WyGkc7pJf6QEkj3wE+2CnvZMI+XJhwdTPR8Z/kWQRXi7boAWLDibRPyHRTUTPx5FaU7MsyrjI3yLB4HA== - smart-buffer@^4.2.0: version "4.2.0" resolved "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz" @@ -8820,20 +5570,12 @@ socks@^2.8.3: resolved "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz" integrity sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA== -source-map-support@^0.5.21: - version "0.5.21" - resolved "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz" - integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== - dependencies: - buffer-from "^1.0.0" - source-map "^0.6.0" - source-map@^0.5.7: version "0.5.7" resolved "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz" integrity sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ== -source-map@^0.6.0, source-map@~0.6.1: +source-map@~0.6.1: version "0.6.1" resolved "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== @@ -8843,78 +5585,16 @@ space-separated-tokens@^2.0.0: resolved "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz" integrity sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q== -spdx-correct@^3.0.0: - version "3.2.0" - resolved "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz" - integrity sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA== - dependencies: - spdx-expression-parse "^3.0.0" - spdx-license-ids "^3.0.0" - -spdx-exceptions@^2.1.0: - version "2.5.0" - resolved "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz" - integrity sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w== - -spdx-expression-parse@^3.0.0: - version "3.0.1" - resolved "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz" - integrity sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q== - dependencies: - spdx-exceptions "^2.1.0" - spdx-license-ids "^3.0.0" - -spdx-license-ids@^3.0.0: - version "3.0.23" - resolved "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.23.tgz" - integrity sha512-CWLcCCH7VLu13TgOH+r8p1O/Znwhqv/dbb6lqWy67G+pT1kHmeD/+V36AVb/vq8QMIQwVShJ6Ssl5FPh0fuSdw== - -stack-trace@0.0.x: - version "0.0.10" - resolved "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz" - integrity sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg== - statuses@^2.0.1, statuses@^2.0.2, statuses@~2.0.2: version "2.0.2" resolved "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz" integrity sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw== -std-env@^4.1.0: - version "4.1.0" - resolved "https://registry.npmjs.org/std-env/-/std-env-4.1.0.tgz" - integrity sha512-Rq7ybcX2RuC55r9oaPVEW7/xu3tj8u4GeBYHBWCychFtzMIr86A7e3PPEBPT37sHStKX3+TiX/Fr/ACmJLVlLQ== - -stop-iteration-iterator@^1.1.0: - version "1.1.0" - resolved "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz" - integrity sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ== - dependencies: - es-errors "^1.3.0" - internal-slot "^1.1.0" - stream-replace-string@^2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/stream-replace-string/-/stream-replace-string-2.0.0.tgz" integrity sha512-TlnjJ1C0QrmxRNrON00JvaFFlNh5TTG00APw23j74ET7gkQpTASi6/L2fuiav8pzK715HXtUeClpBTw2NPSn6w== -streamx@^2.12.5, streamx@^2.15.0, streamx@^2.25.0: - version "2.25.0" - resolved "https://registry.npmjs.org/streamx/-/streamx-2.25.0.tgz" - integrity sha512-0nQuG6jf1w+wddNEEXCF4nTg3LtufWINB5eFEN+5TNZW7KWJp6x87+JFL43vaAUPyCfH1wID+mNVyW6OHtFamg== - dependencies: - events-universal "^1.0.0" - fast-fifo "^1.3.2" - text-decoder "^1.1.0" - -"string-width-cjs@npm:string-width@^4.2.0": - version "4.2.3" - resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz" @@ -8924,61 +5604,13 @@ string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: is-fullwidth-code-point "^3.0.0" strip-ansi "^6.0.1" -string-width@^5.0.1, string-width@^5.1.2: - version "5.1.2" - resolved "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz" - integrity sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA== - dependencies: - eastasianwidth "^0.2.0" - emoji-regex "^9.2.2" - strip-ansi "^7.0.1" - -string.prototype.trim@^1.2.10: - version "1.2.10" - resolved "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz" - integrity sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA== - dependencies: - call-bind "^1.0.8" - call-bound "^1.0.2" - define-data-property "^1.1.4" - define-properties "^1.2.1" - es-abstract "^1.23.5" - es-object-atoms "^1.0.0" - has-property-descriptors "^1.0.2" - -string.prototype.trimend@^1.0.9: - version "1.0.9" - resolved "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz" - integrity sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ== - dependencies: - call-bind "^1.0.8" - call-bound "^1.0.2" - define-properties "^1.2.1" - es-object-atoms "^1.0.0" - -string.prototype.trimstart@^1.0.8: - version "1.0.8" - resolved "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz" - integrity sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg== - dependencies: - call-bind "^1.0.7" - define-properties "^1.2.1" - es-object-atoms "^1.0.0" - -string_decoder@^1.1.1, string_decoder@^1.3.0: +string_decoder@^1.1.1: version "1.3.0" resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz" integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== dependencies: safe-buffer "~5.2.0" -string_decoder@~1.1.1: - version "1.1.1" - resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz" - integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== - dependencies: - safe-buffer "~5.1.0" - stringify-entities@^4.0.0: version "4.0.4" resolved "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.4.tgz" @@ -8987,13 +5619,6 @@ stringify-entities@^4.0.0: character-entities-html4 "^2.0.0" character-entities-legacy "^3.0.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1": - version "6.0.1" - resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz" @@ -9001,18 +5626,6 @@ strip-ansi@^6.0.0, strip-ansi@^6.0.1: dependencies: ansi-regex "^5.0.1" -strip-ansi@^7.0.1: - version "7.2.0" - resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz" - integrity sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w== - dependencies: - ansi-regex "^6.2.2" - -strip-final-newline@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz" - integrity sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw== - stylis@4.2.0: version "4.2.0" resolved "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz" @@ -9032,11 +5645,6 @@ supports-color@8.1.1: dependencies: has-flag "^4.0.0" -supports-color@^10.0.0: - version "10.2.2" - resolved "https://registry.npmjs.org/supports-color/-/supports-color-10.2.2.tgz" - integrity sha512-SS+jx45GF1QjgEXQx4NJZV9ImqmO2NPz5FNsIHrsDjh2YsHnawpan7SNQ1o8NuhrbHZy9AZhIoCUiCeaW/C80g== - supports-color@^5.5.0: version "5.5.0" resolved "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz" @@ -9086,7 +5694,7 @@ svelte@^5.55.5: magic-string "^0.30.11" zimmerframe "^1.1.2" -svgo@^4.0.0, svgo@^4.0.1: +svgo@^4.0.1: version "4.0.1" resolved "https://registry.npmjs.org/svgo/-/svgo-4.0.1.tgz" integrity sha512-XDpWUOPC6FEibaLzjfe0ucaV0YrOjYotGJO1WpF0Zd+n6ZGEQUsSugaoLq9QkEZtAfQIxT42UChcssDVPP3+/w== @@ -9132,46 +5740,6 @@ tar-stream@^2.1.4: inherits "^2.0.3" readable-stream "^3.1.1" -tar-stream@^3.0.0: - version "3.2.0" - resolved "https://registry.npmjs.org/tar-stream/-/tar-stream-3.2.0.tgz" - integrity sha512-ojzvCvVaNp6aOTFmG7jaRD0meowIAuPc3cMMhSgKiVWws1GyHbGd/xvnyuRKcKlMpt3qvxx6r0hreCNITP9hIg== - dependencies: - b4a "^1.6.4" - bare-fs "^4.5.5" - fast-fifo "^1.2.0" - streamx "^2.15.0" - -tar@^7.4.0, tar@^7.5.12: - version "7.5.13" - resolved "https://registry.npmjs.org/tar/-/tar-7.5.13.tgz" - integrity sha512-tOG/7GyXpFevhXVh8jOPJrmtRpOTsYqUIkVdVooZYJS/z8WhfQUX8RJILmeuJNinGAMSu1veBr4asSHFt5/hng== - dependencies: - "@isaacs/fs-minipass" "^4.0.0" - chownr "^3.0.0" - minipass "^7.1.2" - minizlib "^3.1.0" - yallist "^5.0.0" - -teex@^1.0.1: - version "1.0.1" - resolved "https://registry.npmjs.org/teex/-/teex-1.0.1.tgz" - integrity sha512-eYE6iEI62Ni1H8oIa7KlDU6uQBtqr4Eajni3wX7rpfXD8ysFx8z0+dri+KWEPWpBsxXfxu58x/0jvTVT1ekOSg== - dependencies: - streamx "^2.12.5" - -text-decoder@^1.1.0: - version "1.2.7" - resolved "https://registry.npmjs.org/text-decoder/-/text-decoder-1.2.7.tgz" - integrity sha512-vlLytXkeP4xvEq2otHeJfSQIRyWxo/oZGEbXrtEEF9Hnmrdly59sUbzZ/QgyWuLYHctCHxFF4tRQZNQ9k60ExQ== - dependencies: - b4a "^1.6.4" - -text-hex@1.0.x: - version "1.0.0" - resolved "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz" - integrity sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg== - through@^2.3.8: version "2.3.8" resolved "https://registry.npmjs.org/through/-/through-2.3.8.tgz" @@ -9205,25 +5773,6 @@ tinyglobby@^0.2.15, tinyglobby@^0.2.16: fdir "^6.5.0" picomatch "^4.0.4" -tmp-promise@^3.0.2, tmp-promise@^3.0.3: - version "3.0.3" - resolved "https://registry.npmjs.org/tmp-promise/-/tmp-promise-3.0.3.tgz" - integrity sha512-RwM7MoPojPxsOBYnyd2hy0bxtIlVrihNs9pj5SUvY8Zz1sQcQG2tG1hSr8PDxfgEB8RNKDhqbIlroIarSNDNsQ== - dependencies: - tmp "^0.2.0" - -tmp@0.0.33: - version "0.0.33" - resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" - integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== - dependencies: - os-tmpdir "~1.0.2" - -tmp@^0.2.0: - version "0.2.5" - resolved "https://registry.npmjs.org/tmp/-/tmp-0.2.5.tgz" - integrity sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow== - to-regex-range@^5.0.1: version "5.0.1" resolved "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz" @@ -9236,16 +5785,6 @@ toidentifier@~1.0.1: resolved "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz" integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== -toml@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/toml/-/toml-3.0.0.tgz" - integrity sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w== - -tomlify-j0.4@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/tomlify-j0.4/-/tomlify-j0.4-3.0.0.tgz" - integrity sha512-2Ulkc8T7mXJ2l0W476YC/A209PR38Nw8PuaCNtk9uI3t1zzFdGQeWYGQvmj2PZkVvRC/Yoi4xQKMRnWc/N29tQ== - topojson-client@^3.1.0: version "3.1.0" resolved "https://registry.npmjs.org/topojson-client/-/topojson-client-3.1.0.tgz" @@ -9273,11 +5812,6 @@ trim-lines@^3.0.0: resolved "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz" integrity sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg== -triple-beam@^1.3.0: - version "1.4.1" - resolved "https://registry.npmjs.org/triple-beam/-/triple-beam-1.4.1.tgz" - integrity sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg== - trough@^2.0.0: version "2.2.0" resolved "https://registry.npmjs.org/trough/-/trough-2.2.0.tgz" @@ -9288,16 +5822,11 @@ ts-api-utils@^2.5.0: resolved "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.5.0.tgz" integrity sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA== -tslib@^2.0.1, tslib@^2.1.0, tslib@^2.4.0, tslib@^2.5.0, tslib@^2.6.3: +tslib@^2.0.1, tslib@^2.1.0, tslib@^2.4.0: version "2.8.1" resolved "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz" integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== -tunnel@^0.0.6: - version "0.0.6" - resolved "https://registry.yarnpkg.com/tunnel/-/tunnel-0.0.6.tgz#72f1314b34a5b192db012324df2cc587ca47f92c" - integrity sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg== - type-check@^0.4.0, type-check@~0.4.0: version "0.4.0" resolved "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz" @@ -9305,11 +5834,6 @@ type-check@^0.4.0, type-check@~0.4.0: dependencies: prelude-ls "^1.2.1" -type-fest@^4.18.2, type-fest@^4.39.1, type-fest@^4.6.0: - version "4.41.0" - resolved "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz" - integrity sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA== - type-is@^2.0.1: version "2.0.1" resolved "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz" @@ -9319,61 +5843,11 @@ type-is@^2.0.1: media-typer "^1.1.0" mime-types "^3.0.0" -typed-array-buffer@^1.0.3: - version "1.0.3" - resolved "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz" - integrity sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw== - dependencies: - call-bound "^1.0.3" - es-errors "^1.3.0" - is-typed-array "^1.1.14" - -typed-array-byte-length@^1.0.3: - version "1.0.3" - resolved "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz" - integrity sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg== - dependencies: - call-bind "^1.0.8" - for-each "^0.3.3" - gopd "^1.2.0" - has-proto "^1.2.0" - is-typed-array "^1.1.14" - -typed-array-byte-offset@^1.0.4: - version "1.0.4" - resolved "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz" - integrity sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ== - dependencies: - available-typed-arrays "^1.0.7" - call-bind "^1.0.8" - for-each "^0.3.3" - gopd "^1.2.0" - has-proto "^1.2.0" - is-typed-array "^1.1.15" - reflect.getprototypeof "^1.0.9" - -typed-array-length@^1.0.7: - version "1.0.7" - resolved "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.7.tgz" - integrity sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg== - dependencies: - call-bind "^1.0.7" - for-each "^0.3.3" - gopd "^1.0.1" - is-typed-array "^1.1.13" - possible-typed-array-names "^1.0.0" - reflect.getprototypeof "^1.0.6" - typed-query-selector@^2.12.1: version "2.12.2" resolved "https://registry.npmjs.org/typed-query-selector/-/typed-query-selector-2.12.2.tgz" integrity sha512-EOPFbyIub4ngnEdqi2yOcNeDLaX/0jcE1JoAXQDDMIthap7FoN795lc/SHfIq2d416VufXpM8z/lD+WRm2gfOQ== -typedarray@^0.0.6: - version "0.0.6" - resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" - integrity sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA== - typesafe-path@^0.2.2: version "0.2.2" resolved "https://registry.npmjs.org/typesafe-path/-/typesafe-path-0.2.2.tgz" @@ -9386,41 +5860,21 @@ typescript-auto-import-cache@^0.3.5: dependencies: semver "^7.3.8" -typescript@^5.9.3: - version "5.9.3" - resolved "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz" - integrity sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw== - typescript@^6.0.3: version "6.0.3" resolved "https://registry.npmjs.org/typescript/-/typescript-6.0.3.tgz" integrity sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw== -ufo@^1.6.1, ufo@^1.6.3, ufo@^1.6.4: +ufo@^1.6.1, ufo@^1.6.3: version "1.6.4" resolved "https://registry.npmjs.org/ufo/-/ufo-1.6.4.tgz" integrity sha512-JFNbkD1Svwe0KvGi8GOeLcP4kAWQ609twvCdcHxq1oSL8svv39ZuSvajcD8B+5D0eL4+s1Is2D/O6KN3qcTeRA== -ulid@^3.0.0: - version "3.0.2" - resolved "https://registry.npmjs.org/ulid/-/ulid-3.0.2.tgz" - integrity sha512-yu26mwteFYzBAot7KVMqFGCVpsF6g8wXfJzQUHvu1no3+rRRSFcSV2nKeYvNPLD2J4b08jYBDhHUjeH0ygIl9w== - ultrahtml@^1.6.0: version "1.6.0" resolved "https://registry.npmjs.org/ultrahtml/-/ultrahtml-1.6.0.tgz" integrity sha512-R9fBn90VTJrqqLDwyMph+HGne8eqY1iPfYhPzZrvKpIfwkWZbcYlfpsb8B9dTvBfpy1/hqAD7Wi8EKfP9e8zdw== -unbox-primitive@^1.1.0: - version "1.1.0" - resolved "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz" - integrity sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw== - dependencies: - call-bound "^1.0.3" - has-bigints "^1.0.2" - has-symbols "^1.1.0" - which-boxed-primitive "^1.1.1" - unbzip2-stream@1.4.3: version "1.4.3" resolved "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz" @@ -9449,28 +5903,11 @@ undici-types@~7.19.0: resolved "https://registry.npmjs.org/undici-types/-/undici-types-7.19.2.tgz" integrity sha512-qYVnV5OEm2AW8cJMCpdV20CDyaN3g0AjDlOGf1OW4iaDEx8MwdtChUp4zu4H0VP3nDRF/8RKWH+IPp9uW0YGZg== -undici@7.24.8: - version "7.24.8" - resolved "https://registry.npmjs.org/undici/-/undici-7.24.8.tgz" - integrity sha512-6KQ/+QxK49Z/p3HO6E5ZCZWNnCasyZLa5ExaVYyvPxUwKtbCPMKELJOqh7EqOle0t9cH/7d2TaaTRRa6Nhs4YQ== - undici@^7.19.0: version "7.25.0" resolved "https://registry.npmjs.org/undici/-/undici-7.25.0.tgz" integrity sha512-xXnp4kTyor2Zq+J1FfPI6Eq3ew5h6Vl0F/8d9XU5zZQf1tX9s2Su1/3PiMmUANFULpmksxkClamIZcaUqryHsQ== -unenv@2.0.0-rc.24: - version "2.0.0-rc.24" - resolved "https://registry.npmjs.org/unenv/-/unenv-2.0.0-rc.24.tgz" - integrity sha512-i7qRCmY42zmCwnYlh9H2SvLEypEFGye5iRmEMKjcGi7zk9UquigRjFtTLz0TYqr0ZGLZhaMHl/foy1bZR+Cwlw== - dependencies: - pathe "^2.0.3" - -unicorn-magic@^0.1.0: - version "0.1.0" - resolved "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.1.0.tgz" - integrity sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ== - unified@^11.0.0, unified@^11.0.4, unified@^11.0.5: version "11.0.5" resolved "https://registry.npmjs.org/unified/-/unified-11.0.5.tgz" @@ -9562,19 +5999,12 @@ unist-util-visit@^5.0.0, unist-util-visit@^5.1.0: unist-util-is "^6.0.0" unist-util-visit-parents "^6.0.0" -unixify@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/unixify/-/unixify-1.0.0.tgz" - integrity sha512-6bc58dPYhCMHHuwxldQxO3RRNZ4eCogZ/st++0+fcC1nr0jiGUtAdBJ2qzmLQWSxbtz42pWt4QQMiZ9HvZf5cg== - dependencies: - normalize-path "^2.1.1" - unpipe@~1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz" integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== -unstorage@^1.16.1, unstorage@^1.17.5: +unstorage@^1.17.5: version "1.17.5" resolved "https://registry.npmjs.org/unstorage/-/unstorage-1.17.5.tgz" integrity sha512-0i3iqvRfx29hkNntHyQvJTpf5W9dQ9ZadSoRU8+xVlhVtT7jAX57fazYO9EHvcRCfBCyi5YRya7XCDOsbTgkPg== @@ -9588,15 +6018,6 @@ unstorage@^1.16.1, unstorage@^1.17.5: ofetch "^1.5.1" ufo "^1.6.3" -untun@^0.1.3: - version "0.1.3" - resolved "https://registry.npmjs.org/untun/-/untun-0.1.3.tgz" - integrity sha512-4luGP9LMYszMRZwsvyUd9MrxgEGZdZuZgpVQHEEX0lCYFESasVRvZd0EYpCkOIbJKHMuv0LskpXc/8Un+MJzEQ== - dependencies: - citty "^0.1.5" - consola "^3.2.3" - pathe "^1.1.1" - update-browserslist-db@^1.2.3: version "1.2.3" resolved "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz" @@ -9605,11 +6026,6 @@ update-browserslist-db@^1.2.3: escalade "^3.2.0" picocolors "^1.1.1" -uqr@^0.1.3: - version "0.1.3" - resolved "https://registry.npmjs.org/uqr/-/uqr-0.1.3.tgz" - integrity sha512-0rjE8iEJe4YmT9TOhwsZtqCMRLc5DXZUI2UEYUUg63ikBkqqE5EYWaI0etFe/5KUcmcYwLih2RND1kq+hrUJXA== - uri-js@^4.2.2: version "4.4.1" resolved "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz" @@ -9617,44 +6033,21 @@ uri-js@^4.2.2: dependencies: punycode "^2.1.0" -urlpattern-polyfill@8.0.2: - version "8.0.2" - resolved "https://registry.npmjs.org/urlpattern-polyfill/-/urlpattern-polyfill-8.0.2.tgz" - integrity sha512-Qp95D4TPJl1kC9SKigDcqgyM2VDVO4RiJc2d4qe5GrYm+zbIQCWWKAFaJNQ4BhdFeDGwBmAxqJBwWSJDb9T3BQ== - -urlpattern-polyfill@^10.0.0: - version "10.1.0" - resolved "https://registry.npmjs.org/urlpattern-polyfill/-/urlpattern-polyfill-10.1.0.tgz" - integrity sha512-IGjKp/o0NL3Bso1PymYURCJxMPNAf/ILOpendP9f5B6e1rTJgdgiOvgfoT8VxCAdY+Wisb9uhGaJJf3yZ2V9nw== - use-sync-external-store@^1.2.2, use-sync-external-store@^1.4.0: version "1.6.0" resolved "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.6.0.tgz" integrity sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w== -util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1: +util-deprecate@^1.0.1, util-deprecate@^1.0.2: version "1.0.2" resolved "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== -uuid@^11.0.0, uuid@^13.0.0, uuid@^14.0.0: +uuid@^14.0.0: version "14.0.0" resolved "https://registry.yarnpkg.com/uuid/-/uuid-14.0.0.tgz#0af883220163d264ffe0c084f6b8a89b9666966d" integrity sha512-Qo+uWgilfSmAhXCMav1uYFynlQO7fMFiMVZsQqZRMIXp0O7rR7qjkj+cPvBHLgBqi960QCoo/PH2/6ZtVqKvrg== -validate-npm-package-license@^3.0.4: - version "3.0.4" - resolved "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz" - integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew== - dependencies: - spdx-correct "^3.0.0" - spdx-expression-parse "^3.0.0" - -validate-npm-package-name@^5.0.0: - version "5.0.1" - resolved "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-5.0.1.tgz" - integrity sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ== - vary@^1, vary@^1.1.2: version "1.1.2" resolved "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz" @@ -9704,6 +6097,20 @@ victory-vendor@^37.0.2: d3-time "^3.0.0" d3-timer "^3.0.1" +vite@^7.2.0: + version "7.3.3" + resolved "https://registry.yarnpkg.com/vite/-/vite-7.3.3.tgz#d7e07a52b5873fb86f902a3f4b3d17410337450f" + integrity sha512-/4XH147Ui7OGTjg3HbdWe5arnZQSbfuRzdr9Ec7TQi5I7R+ir0Rlc9GIvD4v0XZurELqA035KVXJXpR61xhiTA== + dependencies: + esbuild "^0.27.0" + fdir "^6.5.0" + picomatch "^4.0.3" + postcss "^8.5.6" + rollup "^4.43.0" + tinyglobby "^0.2.15" + optionalDependencies: + fsevents "~2.3.3" + vite@^7.3.2: version "7.3.2" resolved "https://registry.npmjs.org/vite/-/vite-7.3.2.tgz" @@ -9868,11 +6275,6 @@ web-namespaces@^2.0.0: resolved "https://registry.npmjs.org/web-namespaces/-/web-namespaces-2.0.1.tgz" integrity sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ== -web-streams-polyfill@^3.0.3: - version "3.3.3" - resolved "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz" - integrity sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw== - webdriver-bidi-protocol@0.4.1: version "0.4.1" resolved "https://registry.npmjs.org/webdriver-bidi-protocol/-/webdriver-bidi-protocol-0.4.1.tgz" @@ -9903,64 +6305,11 @@ whatwg-url@^5.0.0: tr46 "~0.0.3" webidl-conversions "^3.0.0" -which-boxed-primitive@^1.1.0, which-boxed-primitive@^1.1.1: - version "1.1.1" - resolved "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz" - integrity sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA== - dependencies: - is-bigint "^1.1.0" - is-boolean-object "^1.2.1" - is-number-object "^1.1.1" - is-string "^1.1.1" - is-symbol "^1.1.1" - -which-builtin-type@^1.2.1: - version "1.2.1" - resolved "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.1.tgz" - integrity sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q== - dependencies: - call-bound "^1.0.2" - function.prototype.name "^1.1.6" - has-tostringtag "^1.0.2" - is-async-function "^2.0.0" - is-date-object "^1.1.0" - is-finalizationregistry "^1.1.0" - is-generator-function "^1.0.10" - is-regex "^1.2.1" - is-weakref "^1.0.2" - isarray "^2.0.5" - which-boxed-primitive "^1.1.0" - which-collection "^1.0.2" - which-typed-array "^1.1.16" - -which-collection@^1.0.2: - version "1.0.2" - resolved "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz" - integrity sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw== - dependencies: - is-map "^2.0.3" - is-set "^2.0.3" - is-weakmap "^2.0.2" - is-weakset "^2.0.3" - which-pm-runs@^1.1.0: version "1.1.0" resolved "https://registry.npmjs.org/which-pm-runs/-/which-pm-runs-1.1.0.tgz" integrity sha512-n1brCuqClxfFfq/Rb0ICg9giSZqCS+pLtccdag6C2HyufBrh3fBOiy9nb6ggRMvWOVH5GrdJskj5iGTZNxd7SA== -which-typed-array@^1.1.16, which-typed-array@^1.1.19: - version "1.1.20" - resolved "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.20.tgz" - integrity sha512-LYfpUkmqwl0h9A2HL09Mms427Q1RZWuOHsukfVcKRq9q95iQxdw0ix1JQrqbcDR9PH1QDwf5Qo8OZb5lksZ8Xg== - dependencies: - available-typed-arrays "^1.0.7" - call-bind "^1.0.8" - call-bound "^1.0.4" - for-each "^0.3.5" - get-proto "^1.0.1" - gopd "^1.2.0" - has-tostringtag "^1.0.2" - which@^2.0.1: version "2.0.2" resolved "https://registry.npmjs.org/which/-/which-2.0.2.tgz" @@ -9975,73 +6324,11 @@ whoiser@^2.0.0-beta.10: dependencies: punycode-esm "^1.0.15" -winston-transport@^4.9.0: - version "4.9.0" - resolved "https://registry.npmjs.org/winston-transport/-/winston-transport-4.9.0.tgz" - integrity sha512-8drMJ4rkgaPo1Me4zD/3WLfI/zPdA9o2IipKODunnGDcuqbHwjsbB79ylv04LCGGzU0xQ6vTznOMpQGaLhhm6A== - dependencies: - logform "^2.7.0" - readable-stream "^3.6.2" - triple-beam "^1.3.0" - -winston@^3.10.0: - version "3.19.0" - resolved "https://registry.npmjs.org/winston/-/winston-3.19.0.tgz" - integrity sha512-LZNJgPzfKR+/J3cHkxcpHKpKKvGfDZVPS4hfJCc4cCG0CgYzvlD6yE/S3CIL/Yt91ak327YCpiF/0MyeZHEHKA== - dependencies: - "@colors/colors" "^1.6.0" - "@dabh/diagnostics" "^2.0.8" - async "^3.2.3" - is-stream "^2.0.0" - logform "^2.7.0" - one-time "^1.0.0" - readable-stream "^3.4.0" - safe-stable-stringify "^2.3.1" - stack-trace "0.0.x" - triple-beam "^1.3.0" - winston-transport "^4.9.0" - word-wrap@^1.2.5: version "1.2.5" resolved "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz" integrity sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA== -workerd@1.20260430.1: - version "1.20260430.1" - resolved "https://registry.npmjs.org/workerd/-/workerd-1.20260430.1.tgz" - integrity sha512-KEgIWyiw3Jmn+DCd/L3ePo5fmiiYb/UcwKvDWPf/nLLOiwShDFzDSsegU5NY/JcwgvO/QsLHVi2FYrbkcXNY5Q== - optionalDependencies: - "@cloudflare/workerd-darwin-64" "1.20260430.1" - "@cloudflare/workerd-darwin-arm64" "1.20260430.1" - "@cloudflare/workerd-linux-64" "1.20260430.1" - "@cloudflare/workerd-linux-arm64" "1.20260430.1" - "@cloudflare/workerd-windows-64" "1.20260430.1" - -wrangler@4.87.0: - version "4.87.0" - resolved "https://registry.npmjs.org/wrangler/-/wrangler-4.87.0.tgz" - integrity sha512-lfhfKwLfQlowwgV0xhlYgE9fU3n0I30d4ccGY/rTCEm/n42Mjvlr0Ng3ZPNqlsrsKBcDR531V7dsPkgELvrk/Q== - dependencies: - "@cloudflare/kv-asset-handler" "0.5.0" - "@cloudflare/unenv-preset" "2.16.1" - blake3-wasm "2.1.5" - esbuild "0.27.3" - miniflare "4.20260430.0" - path-to-regexp "6.3.0" - unenv "2.0.0-rc.24" - workerd "1.20260430.1" - optionalDependencies: - fsevents "~2.3.2" - -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": - version "7.0.0" - resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz" - integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - wrap-ansi@^7.0.0: version "7.0.0" resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz" @@ -10051,38 +6338,21 @@ wrap-ansi@^7.0.0: string-width "^4.1.0" strip-ansi "^6.0.0" -wrap-ansi@^8.1.0: - version "8.1.0" - resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz" - integrity sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ== - dependencies: - ansi-styles "^6.1.0" - string-width "^5.0.1" - strip-ansi "^7.0.1" - wrappy@1: version "1.0.2" resolved "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== -write-file-atomic@^5.0.1: - version "5.0.1" - resolved "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.1.tgz" - integrity sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw== - dependencies: - imurmurhash "^0.1.4" - signal-exit "^4.0.1" +ws@8.12.1: + version "8.12.1" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.12.1.tgz#c51e583d79140b5e42e39be48c934131942d4a8f" + integrity sha512-1qo+M9Ba+xNhPB+YTWUlK6M17brTut5EXbcBaMRN5pH5dFrXz7lzz1ChFSUq3bOUl8yEvSenhHmYUNJxFzdJew== -ws@8.12.1, ws@^8.17.1, ws@^8.19.0: +ws@^8.17.1, ws@^8.19.0: version "8.20.0" resolved "https://registry.yarnpkg.com/ws/-/ws-8.20.0.tgz#4cd9532358eba60bc863aad1623dfb045a4d4af8" integrity sha512-sAt8BhgNbzCtgGbt2OxmpuryO63ZoDk/sqaB/znQm94T4fCEsy/yV+7CdC1kJhOU9lboAEU7R3kquuycDoibVA== -ws@8.18.0: - version "8.18.0" - resolved "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz" - integrity sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw== - xml2js@^0.6.2: version "0.6.2" resolved "https://registry.npmjs.org/xml2js/-/xml2js-0.6.2.tgz" @@ -10096,14 +6366,6 @@ xmlbuilder@~11.0.0: resolved "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz" integrity sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA== -xss@^1.0.15: - version "1.0.15" - resolved "https://registry.npmjs.org/xss/-/xss-1.0.15.tgz" - integrity sha512-FVdlVVC67WOIPvfOwhoMETV72f6GbW7aOabBC3WxN/oUdoEMDyLz4OgRv5/gck2ZeNqEQu+Tb0kloovXOfpYVg== - dependencies: - commander "^2.20.3" - cssfilter "0.0.10" - xxhash-wasm@^1.1.0: version "1.1.0" resolved "https://registry.npmjs.org/xxhash-wasm/-/xxhash-wasm-1.1.0.tgz" @@ -10119,11 +6381,6 @@ yallist@^3.0.2: resolved "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz" integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== -yallist@^5.0.0: - version "5.0.0" - resolved "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz" - integrity sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw== - yaml-language-server@~1.20.0: version "1.20.0" resolved "https://registry.npmjs.org/yaml-language-server/-/yaml-language-server-1.20.0.tgz" @@ -10141,7 +6398,7 @@ yaml-language-server@~1.20.0: vscode-uri "^3.0.2" yaml "2.7.1" -yaml@2.7.1, yaml@^1.10.0, yaml@^2.8.0, yaml@^2.8.2, yaml@^2.8.3: +yaml@2.7.1, yaml@^1.10.0, yaml@^2.8.2, yaml@^2.8.3: version "2.8.4" resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.8.4.tgz#4b5f411dd25f9544914d8673d4da7f29248e5e2e" integrity sha512-ml/JPOj9fOQK8RNnWojA67GbZ0ApXAUlN2UQclwv2eVgTgn7O9gg9o7paZWKMp4g0H3nTLtS9LVzhkpOFIKzog== @@ -10156,7 +6413,7 @@ yargs-parser@^22.0.0: resolved "https://registry.npmjs.org/yargs-parser/-/yargs-parser-22.0.0.tgz" integrity sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw== -yargs@17.7.2, yargs@^17.0.0, yargs@^17.6.0, yargs@^17.7.2: +yargs@17.7.2, yargs@^17.7.2: version "17.7.2" resolved "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz" integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== @@ -10182,50 +6439,22 @@ yocto-queue@^0.1.0: resolved "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz" integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== -yocto-queue@^1.0.0, yocto-queue@^1.2.1: +yocto-queue@^1.2.1: version "1.2.2" resolved "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.2.2.tgz" integrity sha512-4LCcse/U2MHZ63HAJVE+v71o7yOdIe4cZ70Wpf8D/IyjDKYQLV5GD46B+hSTjJsvV5PztjvHoU580EftxjDZFQ== -youch-core@^0.3.3: - version "0.3.3" - resolved "https://registry.npmjs.org/youch-core/-/youch-core-0.3.3.tgz" - integrity sha512-ho7XuGjLaJ2hWHoK8yFnsUGy2Y5uDpqSTq1FkHLK4/oqKtyUU1AFbOOxY4IpC9f0fTLjwYbslUz0Po5BpD1wrA== - dependencies: - "@poppinss/exception" "^1.2.2" - error-stack-parser-es "^1.0.5" - -youch@4.1.0-beta.10: - version "4.1.0-beta.10" - resolved "https://registry.npmjs.org/youch/-/youch-4.1.0-beta.10.tgz" - integrity sha512-rLfVLB4FgQneDr0dv1oddCVZmKjcJ6yX6mS4pU82Mq/Dt9a3cLZQ62pDBL4AUO+uVrCvtWz3ZFUL2HFAFJ/BXQ== - dependencies: - "@poppinss/colors" "^4.1.5" - "@poppinss/dumper" "^0.6.4" - "@speed-highlight/core" "^1.2.7" - cookie "^1.0.2" - youch-core "^0.3.3" - zimmerframe@^1.1.2: version "1.1.4" resolved "https://registry.npmjs.org/zimmerframe/-/zimmerframe-1.1.4.tgz" integrity sha512-B58NGBEoc8Y9MWWCQGl/gq9xBCe4IiKM0a2x7GZdQKOW5Exr8S1W24J6OgM1njK8xCRGvAJIL/MxXHf6SkmQKQ== -zip-stream@^6.0.1: - version "6.0.1" - resolved "https://registry.npmjs.org/zip-stream/-/zip-stream-6.0.1.tgz" - integrity sha512-zK7YHHz4ZXpW89AHXUPbQVGKI7uvkd3hzusTdotCg1UxyaVtg0zFJSTfW/Dq5f7OBBVnq6cZIaC8Ti4hb6dtCA== - dependencies: - archiver-utils "^5.0.0" - compress-commons "^6.0.2" - readable-stream "^4.0.0" - -zod@^3.23.8, zod@^3.24.1: +zod@^3.24.1: version "3.25.76" resolved "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz" integrity sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ== -zod@^4.0.5, zod@^4.3.6: +zod@^4.3.6: version "4.4.3" resolved "https://registry.npmjs.org/zod/-/zod-4.4.3.tgz" integrity sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==