diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index d90991de..c558e27f 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -80,7 +80,7 @@ jobs: run: | npm run start:backend & npm run build:test-app - npm run e2e + npm run e2e -w apps/cache-testing - uses: actions/upload-artifact@v4 if: always() with: diff --git a/.vscode/extensions.json b/.vscode/extensions.json index 82701650..e2eca8ca 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -1,3 +1,11 @@ { - "recommendations": ["biomejs.biome", "dbaeumer.vscode-eslint", "esbenp.prettier-vscode", "unifiedjs.vscode-mdx"] + "recommendations": [ + "biomejs.biome", + "dbaeumer.vscode-eslint", + "esbenp.prettier-vscode", + "unifiedjs.vscode-mdx", + "Vercel.turbo-vsc", + "ms-playwright.playwright", + "streetsidesoftware.code-spell-checker" + ] } diff --git a/.vscode/settings.json b/.vscode/settings.json index 4e604e2e..5e35e630 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -46,5 +46,6 @@ "[typescriptreact]": { "editor.defaultFormatter": "biomejs.biome" }, - "grammarly.files.include": ["**/*.md", "**/*.mdx"] + "grammarly.files.include": ["**/*.md", "**/*.mdx"], + "turbo.useLocalTurbo": true } diff --git a/apps/cache-testing-15-app/.env.example b/apps/cache-testing-15-app/.env.example new file mode 100644 index 00000000..4cebeb6c --- /dev/null +++ b/apps/cache-testing-15-app/.env.example @@ -0,0 +1,5 @@ +REDIS_URL=redis://localhost:6379 +REMOTE_CACHE_SERVER_BASE_URL=http://localhost:8080 +HOSTNAME=localhost +PPR_ENABLED=false +NEXT_PRIVATE_DEBUG_CACHE=1 diff --git a/apps/cache-testing-15-app/.eslintrc.js b/apps/cache-testing-15-app/.eslintrc.js new file mode 100644 index 00000000..60546512 --- /dev/null +++ b/apps/cache-testing-15-app/.eslintrc.js @@ -0,0 +1,10 @@ +/** @type {import("eslint").Linter.Config} */ +module.exports = { + root: true, + extends: ['@repo/eslint-config/next.js'], + parser: '@typescript-eslint/parser', + parserOptions: { + project: true, + }, + ignorePatterns: ['*.mjs'], +}; diff --git a/apps/cache-testing-15-app/README.md b/apps/cache-testing-15-app/README.md new file mode 100644 index 00000000..e69de29b diff --git a/apps/cache-testing-15-app/cache-handler-local.mjs b/apps/cache-testing-15-app/cache-handler-local.mjs new file mode 100644 index 00000000..8b25938c --- /dev/null +++ b/apps/cache-testing-15-app/cache-handler-local.mjs @@ -0,0 +1,14 @@ +// @ts-check + +import { CacheHandler } from '@neshca/cache-handler'; +import createLruHandler from '@neshca/cache-handler/local-lru'; + +CacheHandler.onCreation(() => { + const localHandler = createLruHandler(); + + return { + handlers: [localHandler], + }; +}); + +export default CacheHandler; diff --git a/apps/cache-testing-15-app/cache-handler-next-example.js b/apps/cache-testing-15-app/cache-handler-next-example.js new file mode 100644 index 00000000..7eed4af9 --- /dev/null +++ b/apps/cache-testing-15-app/cache-handler-next-example.js @@ -0,0 +1,35 @@ +const cache = new Map(); + +module.exports = class CacheHandler { + constructor(options) { + this.options = options; + } + + // biome-ignore lint/suspicious/useAwait: don't bother + async get(key) { + // This could be stored anywhere, like durable storage + return cache.get(key); + } + + // biome-ignore lint/suspicious/useAwait: don't bother + async set(key, data, ctx) { + // This could be stored anywhere, like durable storage + cache.set(key, { + value: data, + lastModified: Date.now(), + tags: ctx.tags, + }); + } + + // biome-ignore lint/suspicious/useAwait: don't bother + async revalidateTag(tag) { + // Iterate over all entries in the cache + // biome-ignore lint/style/useConst: don't bother + for (let [key, value] of cache) { + // If the value's tags include the specified tag, delete this entry + if (value.tags.includes(tag)) { + cache.delete(key); + } + } + } +}; diff --git a/apps/cache-testing-15-app/cache-handler-redis-stack.js b/apps/cache-testing-15-app/cache-handler-redis-stack.js new file mode 100644 index 00000000..3e2cc048 --- /dev/null +++ b/apps/cache-testing-15-app/cache-handler-redis-stack.js @@ -0,0 +1,80 @@ +// @ts-check + +const { CacheHandler } = require('@neshca/cache-handler'); +const createLruHandler = require('@neshca/cache-handler/local-lru').default; +const createRedisHandler = require('@neshca/cache-handler/redis-stack').default; +const { createClient } = require('redis'); + +CacheHandler.onCreation(async () => { + if (!process.env.REDIS_URL) { + console.warn('Make sure that REDIS_URL is added to the .env.local file and loaded properly.'); + } + + let client; + + try { + // Create a Redis client. + client = createClient({ + url: process.env.REDIS_URL, + name: `cache-handler:${process.env.PORT ?? process.pid}`, + }); + + // Redis won't work without error handling. https://github.com/redis/node-redis?tab=readme-ov-file#events + client.on('error', (error) => { + if (typeof process.env.NEXT_PRIVATE_DEBUG_CACHE !== 'undefined') { + console.error('Redis client error:', error); + } + }); + } catch (error) { + console.warn('Failed to create Redis client:', error); + } + + if (client) { + try { + console.info('Connecting Redis client...'); + + // Wait for the client to connect. + // Caveat: This will block the server from starting until the client is connected. + // And there is no timeout. Make your own timeout if needed. + await client.connect(); + console.info('Redis client connected.'); + } catch (error) { + console.warn('Failed to connect Redis client:', error); + + console.warn('Disconnecting the Redis client...'); + // Try to disconnect the client to stop it from reconnecting. + client + .disconnect() + .then(() => { + console.info('Redis client disconnected.'); + }) + .catch(() => { + console.warn('Failed to quit the Redis client after failing to connect.'); + }); + } + } + + /** @type {import("@neshca/cache-handler").Handler | null} */ + let handler; + + if (client) { + // Create the `redis-stack` Handler if the client is available. + handler = createRedisHandler({ + client, + keyPrefix: 'JSON:', + timeoutMs: 1000, + }); + } else { + // Fallback to LRU handler if Redis client is not available. + // The application will still work, but the cache will be in-memory only and not shared. + handler = createLruHandler(); + console.warn('Falling back to LRU handler because Redis client is not available.'); + } + + return { + handlers: [handler], + ttl: { defaultStaleAge: 60, estimateExpireAge: (staleAge) => staleAge * 2 }, + }; +}); + +module.exports = CacheHandler; diff --git a/apps/cache-testing-15-app/cache-handler-redis-stack.mjs b/apps/cache-testing-15-app/cache-handler-redis-stack.mjs new file mode 100644 index 00000000..5b3ba53d --- /dev/null +++ b/apps/cache-testing-15-app/cache-handler-redis-stack.mjs @@ -0,0 +1,80 @@ +// @ts-check + +import { CacheHandler } from '@neshca/cache-handler'; +import createLruHandler from '@neshca/cache-handler/local-lru'; +import createRedisHandler from '@neshca/cache-handler/redis-stack'; +import { createClient } from 'redis'; + +CacheHandler.onCreation(async () => { + if (!process.env.REDIS_URL) { + console.warn('Make sure that REDIS_URL is added to the .env.local file and loaded properly.'); + } + + let client; + + try { + // Create a Redis client. + client = createClient({ + url: process.env.REDIS_URL, + name: `cache-handler:${process.env.PORT ?? process.pid}`, + }); + + // Redis won't work without error handling. https://github.com/redis/node-redis?tab=readme-ov-file#events + client.on('error', (error) => { + if (typeof process.env.NEXT_PRIVATE_DEBUG_CACHE !== 'undefined') { + console.error('Redis client error:', error); + } + }); + } catch (error) { + console.warn('Failed to create Redis client:', error); + } + + if (client) { + try { + console.info('Connecting Redis client...'); + + // Wait for the client to connect. + // Caveat: This will block the server from starting until the client is connected. + // And there is no timeout. Make your own timeout if needed. + await client.connect(); + console.info('Redis client connected.'); + } catch (error) { + console.warn('Failed to connect Redis client:', error); + + console.warn('Disconnecting the Redis client...'); + // Try to disconnect the client to stop it from reconnecting. + client + .disconnect() + .then(() => { + console.info('Redis client disconnected.'); + }) + .catch(() => { + console.warn('Failed to quit the Redis client after failing to connect.'); + }); + } + } + + /** @type {import("@neshca/cache-handler").Handler | null} */ + let handler; + + if (client) { + // Create the `redis-stack` Handler if the client is available. + handler = createRedisHandler({ + client, + keyPrefix: 'JSON:', + timeoutMs: 1000, + }); + } else { + // Fallback to LRU handler if Redis client is not available. + // The application will still work, but the cache will be in-memory only and not shared. + handler = createLruHandler(); + console.warn('Falling back to LRU handler because Redis client is not available.'); + } + + return { + handlers: [handler], + ttl: { defaultStaleAge: 60, estimateExpireAge: (staleAge) => staleAge * 2 }, + }; +}); + +export default CacheHandler; diff --git a/apps/cache-testing-15-app/cache-handler-redis-strings.mjs b/apps/cache-testing-15-app/cache-handler-redis-strings.mjs new file mode 100644 index 00000000..eb2196d6 --- /dev/null +++ b/apps/cache-testing-15-app/cache-handler-redis-strings.mjs @@ -0,0 +1,42 @@ +// @ts-check + +import { CacheHandler } from '@neshca/cache-handler'; +import createRedisHandler from '@neshca/cache-handler/redis-strings'; +import { createClient } from 'redis'; + +CacheHandler.onCreation(async () => { + if (!process.env.REDIS_URL) { + console.warn('Make sure that REDIS_URL is added to the .env.local file and loaded properly.'); + } + + const PREFIX = 'string:'; + + /** @type {import("redis").RedisClientType} */ + const client = createClient({ + url: process.env.REDIS_URL, + name: `cache-handler:${PREFIX}${process.env.PORT ?? process.pid}`, + }); + + // Redis won't work without error handling. https://github.com/redis/node-redis?tab=readme-ov-file#events + client.on('error', (error) => { + if (typeof process.env.NEXT_PRIVATE_DEBUG_CACHE !== 'undefined') { + console.error('Redis client error:', error); + } + }); + + console.info('Connecting Redis client...'); + await client.connect(); + console.info('Redis client connected.'); + + const redisHandler = createRedisHandler({ + client, + keyPrefix: PREFIX, + }); + + return { + handlers: [redisHandler], + ttl: { defaultStaleAge: 60, estimateExpireAge: (staleAge) => staleAge * 2 }, + }; +}); + +export default CacheHandler; diff --git a/apps/cache-testing-15-app/cluster.config.js b/apps/cache-testing-15-app/cluster.config.js new file mode 100644 index 00000000..a89a1401 --- /dev/null +++ b/apps/cache-testing-15-app/cluster.config.js @@ -0,0 +1,16 @@ +module.exports = { + apps: [ + { + name: 'app', + script: '.next/__instances/3000/server.js', + instances: 2, + exec_mode: 'cluster', + env_production: { + NODE_ENV: 'production', + HOSTNAME: 'localhost', + REDIS_URL: 'redis://localhost:6379', + SERVER_STARTED: '1', + }, + }, + ], +}; diff --git a/apps/cache-testing-15-app/create-instances.sh b/apps/cache-testing-15-app/create-instances.sh new file mode 100755 index 00000000..2b50a58e --- /dev/null +++ b/apps/cache-testing-15-app/create-instances.sh @@ -0,0 +1,41 @@ +#!/bin/bash + +# Set common paths +STANDALONE_DIR="$PWD/.next/standalone" +APP_DIR="$STANDALONE_DIR/apps/cache-testing-15-app" +PUBLIC_DIR="$PWD/public" +STATIC_DIR="$PWD/.next/static" +FETCH_CACHE_DIR="$PWD/.next/cache/fetch-cache" +INSTANCES_DIR="$PWD/.next/__instances" + +copy_dir() { + if ! cp -r "$1" "$2"; then + echo "Failed to copy from $1 to $2" + exit 1 + fi +} + +# Copy public directory to standalone app directory +copy_dir "$PUBLIC_DIR/" "$APP_DIR/public" + +# Copy static directory to standalone app/.next directory +copy_dir "$STATIC_DIR/" "$APP_DIR/.next/static" + +# Copy fetch cache directory to standalone app/.next directory +mkdir -p "$APP_DIR/.next/cache/fetch-cache/" +cp $FETCH_CACHE_DIR/* $APP_DIR/.next/cache/fetch-cache/ + +create_instance_dir() { + if ! mkdir -p "$INSTANCES_DIR/$1"; then + echo "Failed to create $INSTANCES_DIR/$1 directory" + exit 1 + fi +} + +# Create instance directories +create_instance_dir 3000 +create_instance_dir 3001 + +# Copy files from standalone directory to instance directories +copy_dir "$STANDALONE_DIR/." "$INSTANCES_DIR/3000" +copy_dir "$STANDALONE_DIR/." "$INSTANCES_DIR/3001" diff --git a/apps/cache-testing-15-app/next.config.mjs b/apps/cache-testing-15-app/next.config.mjs new file mode 100644 index 00000000..c39cd212 --- /dev/null +++ b/apps/cache-testing-15-app/next.config.mjs @@ -0,0 +1,22 @@ +// @ts-check + +import path from 'node:path'; + +const cacheHandler = path.resolve('./cache-handler-redis-stack.mjs'); + +/** @type {import('next').NextConfig} */ +const nextConfig = { + poweredByHeader: false, + reactStrictMode: true, + output: 'standalone', + cacheHandler: process.env.NODE_ENV !== 'development' ? cacheHandler : undefined, + cacheMaxMemorySize: 0, // disable default in-memory caching + outputFileTracingRoot: path.join(import.meta.dirname, '../../'), + experimental: { + // PPR should only be configured via the PPR_ENABLED env variable due to conditional logic in tests. + ppr: process.env.PPR_ENABLED === 'true', + largePageDataBytes: 1024 * 1024, // 1MB + }, +}; + +export default nextConfig; diff --git a/apps/cache-testing-15-app/package.json b/apps/cache-testing-15-app/package.json new file mode 100644 index 00000000..8c199767 --- /dev/null +++ b/apps/cache-testing-15-app/package.json @@ -0,0 +1,45 @@ +{ + "name": "@repo/cache-testing-15-app", + "version": "0.0.0", + "private": true, + "license": "MIT", + "scripts": { + "build": "next build && ./create-instances.sh", + "cluster:start": "pm2 start cluster.config.js --env production", + "cluster:stop": "pm2 kill", + "e2e": "playwright test --config=./playwright.config.ts", + "e2e:ui": "playwright test --ui --config=./playwright.config.ts", + "eslint:check": "next lint", + "eslint:fix": "next lint --fix", + "playwright:install": "playwright install chromium", + "start": "dotenv -e .env.local -v SERVER_STARTED=1 node .next/standalone/apps/cache-testing-15-app/server.js" + }, + "dependencies": { + "@neshca/cache-handler": "*", + "axios": "1.7.7", + "next": "15.0.0", + "react": "19.0.0-rc-65a56d0e-20241020", + "react-dom": "19.0.0-rc-65a56d0e-20241020", + "redis": "4.7.0" + }, + "devDependencies": { + "@next/eslint-plugin-next": "15.0.0", + "@playwright/test": "1.48.1", + "@repo/eslint-config": "*", + "@repo/typescript-config": "*", + "@types/eslint": "8.56.12", + "@types/node": "22.7.7", + "@types/react": "npm:types-react@19.0.0-rc.1", + "@types/react-dom": "npm:types-react-dom@19.0.0-rc.1", + "dotenv-cli": "7.4.2", + "eslint": "8.57.1", + "fastify": "5.0.0", + "pm2": "5.4.2", + "tsx": "4.19.1", + "typescript": "5.6.3" + }, + "overrides": { + "@types/react": "npm:types-react@19.0.0-rc.1", + "@types/react-dom": "npm:types-react-dom@19.0.0-rc.1" + } +} diff --git a/apps/cache-testing-15-app/playwright.config.ts b/apps/cache-testing-15-app/playwright.config.ts new file mode 100644 index 00000000..27b2df43 --- /dev/null +++ b/apps/cache-testing-15-app/playwright.config.ts @@ -0,0 +1,26 @@ +import { defineConfig, devices } from '@playwright/test'; + +const ports = ['3000', '3001']; + +export default defineConfig({ + testDir: './tests', + fullyParallel: false, + forbidOnly: Boolean(process.env.CI), + retries: 0, + workers: 1, + reporter: 'html', + use: { baseURL: 'http://localhost', trace: 'on-first-retry', testIdAttribute: 'data-pw' }, + projects: [ + { + name: 'chromium', + use: { ...devices['Desktop Chrome'] }, + }, + ], + webServer: { + command: `node --import tsx ./run-app-instances.ts ports=${ports.join(',')}`, + url: 'http://localhost:9000', + reuseExistingServer: !process.env.CI, + stdout: 'pipe', + stderr: 'pipe', + }, +}); diff --git a/apps/cache-testing-15-app/public/circles.svg b/apps/cache-testing-15-app/public/circles.svg new file mode 100644 index 00000000..6533be5b --- /dev/null +++ b/apps/cache-testing-15-app/public/circles.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/apps/cache-testing-15-app/public/next.svg b/apps/cache-testing-15-app/public/next.svg new file mode 100644 index 00000000..5174b28c --- /dev/null +++ b/apps/cache-testing-15-app/public/next.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/cache-testing-15-app/public/turborepo.svg b/apps/cache-testing-15-app/public/turborepo.svg new file mode 100644 index 00000000..2f9aa1f3 --- /dev/null +++ b/apps/cache-testing-15-app/public/turborepo.svg @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/cache-testing-15-app/public/vercel.svg b/apps/cache-testing-15-app/public/vercel.svg new file mode 100644 index 00000000..d2f84222 --- /dev/null +++ b/apps/cache-testing-15-app/public/vercel.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/cache-testing-15-app/run-app-instances.ts b/apps/cache-testing-15-app/run-app-instances.ts new file mode 100644 index 00000000..c60c26c8 --- /dev/null +++ b/apps/cache-testing-15-app/run-app-instances.ts @@ -0,0 +1,89 @@ +#!/usr/bin/env node + +import { scheduler } from 'node:timers/promises'; +import Fastify from 'fastify'; +// biome-ignore lint/style/noNamespaceImport: pm2 works only with Namespace import +import * as pm2Default from 'pm2'; + +const { default: pm2 } = pm2Default as unknown as { default: typeof import('pm2') }; + +const args = process.argv.slice(2).reduce>((acc, arg) => { + const [key, value] = arg.split('='); + + if (!(key && value)) { + throw new Error(`Invalid argument: ${arg}`); + } + + acc[key] = value; + return acc; +}, {}); + +const { hostname = 'localhost', ports = '3000' } = args; + +function getNameByPort(port: string): string { + return `@repo/cache-testing-15-app-${port}`; +} + +pm2.connect(true, (connectError?: Error) => { + if (connectError) { + console.error(connectError); + process.exit(1); + } + + for (const port of ports.split(',')) { + const name = getNameByPort(port); + + pm2.start( + { + script: `.next/__instances/${port}/apps/cache-testing-15-app/server.js`, + name, + env: { + ...process.env, + PORT: port, + HOSTNAME: hostname, + SERVER_STARTED: '1', + }, + }, + (startError?: Error) => { + if (startError) { + console.error(startError); + } + }, + ); + } +}); + +const app = Fastify(); + +app.get('/', async (_request, reply) => { + await reply.send('ok'); +}); + +app.get('/restart/:port', async (request, reply) => { + const { port } = request.params as { port: string }; + + const name = getNameByPort(port); + + pm2.restart(name, (restartError: unknown) => { + if (restartError) { + console.error(restartError); + + reply.code(500).send({ status: 'error' }); + } + + // workaround for unstable tests + scheduler.wait(1000).then(async () => { + await reply.code(200).send({ restarted: name }); + }); + }); + + return reply; +}); + +app.listen({ port: 9000, host: 'localhost' }, (error, address) => { + if (error) { + console.error(error); + process.exit(1); + } + console.info(`orchestration listening on ${address}`); +}); diff --git a/apps/cache-testing-15-app/src/app/api/revalidate-app/route.ts b/apps/cache-testing-15-app/src/app/api/revalidate-app/route.ts new file mode 100644 index 00000000..b29f5149 --- /dev/null +++ b/apps/cache-testing-15-app/src/app/api/revalidate-app/route.ts @@ -0,0 +1,40 @@ +import { revalidatePath, revalidateTag } from 'next/cache'; +import type { NextRequest } from 'next/server'; +import { NextResponse } from 'next/server'; + +import { formatTime } from 'cache-testing-15-app/utils/format-time'; + +export function GET(request: NextRequest): Promise { + const path = request.nextUrl.searchParams.get('path'); + const tag = request.nextUrl.searchParams.get('tag'); + + const time = formatTime(Date.now(), 3); + + if (path) { + revalidatePath(path); + return Promise.resolve( + NextResponse.json({ + revalidated: true, + now: time, + }), + ); + } + + if (tag) { + revalidateTag(tag); + return Promise.resolve( + NextResponse.json({ + revalidated: true, + now: time, + }), + ); + } + + return Promise.resolve( + NextResponse.json({ + revalidated: false, + now: time, + message: 'Missing path to revalidate', + }), + ); +} diff --git a/apps/cache-testing-15-app/src/app/app/no-params/dynamic-false/[slug]/page.tsx b/apps/cache-testing-15-app/src/app/app/no-params/dynamic-false/[slug]/page.tsx new file mode 100644 index 00000000..318de293 --- /dev/null +++ b/apps/cache-testing-15-app/src/app/app/no-params/dynamic-false/[slug]/page.tsx @@ -0,0 +1,27 @@ +import { notFound } from 'next/navigation'; + +import { CommonAppPage } from 'cache-testing-15-app/utils/common-app-page'; +import { createGetData } from 'cache-testing-15-app/utils/create-get-data'; + +import type { JSX } from 'react'; + +export const dynamicParams = false; + +export const revalidate = 5; + +type PageParams = { params: Promise<{ slug: string }> }; + +const getData = createGetData('app/no-params/dynamic-false'); + +export default async function Index(props: PageParams): Promise { + const params = await props.params; + const data = await getData(params.slug); + + if (!data) { + notFound(); + } + + const { count, path, time } = data; + + return ; +} diff --git a/apps/cache-testing-15-app/src/app/app/no-params/dynamic-true/[slug]/page.tsx b/apps/cache-testing-15-app/src/app/app/no-params/dynamic-true/[slug]/page.tsx new file mode 100644 index 00000000..2fd0d6dd --- /dev/null +++ b/apps/cache-testing-15-app/src/app/app/no-params/dynamic-true/[slug]/page.tsx @@ -0,0 +1,27 @@ +import { notFound } from 'next/navigation'; + +import { CommonAppPage } from 'cache-testing-15-app/utils/common-app-page'; +import { createGetData } from 'cache-testing-15-app/utils/create-get-data'; + +import type { JSX } from 'react'; + +export const dynamicParams = true; + +export const revalidate = 5; + +type PageParams = { params: Promise<{ slug: string }> }; + +const getData = createGetData('app/no-params/dynamic-true'); + +export default async function Index(props: PageParams): Promise { + const params = await props.params; + const data = await getData(params.slug); + + if (!data) { + notFound(); + } + + const { count, path, time } = data; + + return ; +} diff --git a/apps/cache-testing-15-app/src/app/app/no-params/ssr/200/page.tsx b/apps/cache-testing-15-app/src/app/app/no-params/ssr/200/page.tsx new file mode 100644 index 00000000..0fa061d8 --- /dev/null +++ b/apps/cache-testing-15-app/src/app/app/no-params/ssr/200/page.tsx @@ -0,0 +1,20 @@ +import { notFound } from 'next/navigation'; + +import { CommonAppPage } from 'cache-testing-15-app/utils/common-app-page'; +import { createGetData } from 'cache-testing-15-app/utils/create-get-data'; + +import type { JSX } from 'react'; + +const getData = createGetData('app/no-params/ssr', undefined, 'no-store'); + +export default async function Index(): Promise { + const data = await getData('200'); + + if (!data) { + notFound(); + } + + const { count, path, time } = data; + + return ; +} diff --git a/apps/cache-testing-15-app/src/app/app/ppr/page.tsx b/apps/cache-testing-15-app/src/app/app/ppr/page.tsx new file mode 100644 index 00000000..ac44c883 --- /dev/null +++ b/apps/cache-testing-15-app/src/app/app/ppr/page.tsx @@ -0,0 +1,36 @@ +import { unstable_noStore as noStore } from 'next/cache'; +import { type JSX, Suspense } from 'react'; + +import { formatTime } from 'cache-testing-15-app/utils/format-time'; +import type { TimeBackendApiResponseJson } from 'cache-testing-15-app/utils/types'; + +async function ActualData(): Promise { + noStore(); + + const response = await fetch('http://localhost:8081/time', { + next: { tags: ['/app/ppr'] }, + }); + + if (!response.ok) { + throw new Error('Failed to fetch unix time'); + } + + const data = (await response.json()) as TimeBackendApiResponseJson; + + return
{formatTime(data.unixTimeMs)}
; +} + +function Skeleton(): JSX.Element { + return
Skeleton
; +} + +export default function Page(): JSX.Element { + return ( +
+

Partial Prerendering

+ }> + + +
+ ); +} diff --git a/apps/cache-testing-15-app/src/app/app/randomHex/[length]/page.tsx b/apps/cache-testing-15-app/src/app/app/randomHex/[length]/page.tsx new file mode 100644 index 00000000..b7d74cb7 --- /dev/null +++ b/apps/cache-testing-15-app/src/app/app/randomHex/[length]/page.tsx @@ -0,0 +1,46 @@ +import { notFound } from 'next/navigation'; +import { type JSX, Suspense } from 'react'; + +import { CacheStateWatcher } from 'cache-testing-15-app/components/cache-state-watcher'; +import { PreRenderedAt } from 'cache-testing-15-app/components/pre-rendered-at'; +import type { RandomHexPageProps } from 'cache-testing-15-app/utils/types'; + +const lengthSteps = new Array(5).fill(0).map((_, i) => 10 ** (i + 1)); + +type PageParams = { params: Promise<{ length: string }> }; + +export function generateStaticParams(): PageParams['params'][] { + return lengthSteps.map((length) => Promise.resolve({ length: `${length}` })); +} + +export default async function Page(props0: PageParams): Promise { + const params = await props0.params; + + const { length } = params; + + const path = `/randomHex/app/${length}`; + + const url = new URL(path, 'http://localhost:8081'); + + const result = await fetch(url, { + next: { + tags: [`/app/randomHex/${length}`], + }, + }); + + if (!result.ok) { + notFound(); + } + + const props = (await result.json()) as RandomHexPageProps; + + return ( +
+
{props.randomHex}
+ + + + +
+ ); +} diff --git a/apps/cache-testing-15-app/src/app/app/static/route.ts b/apps/cache-testing-15-app/src/app/app/static/route.ts new file mode 100644 index 00000000..1b9fe80e --- /dev/null +++ b/apps/cache-testing-15-app/src/app/app/static/route.ts @@ -0,0 +1,3 @@ +export function GET() { + return Promise.resolve(new Response('OK', { status: 200 })); +} diff --git a/apps/cache-testing-15-app/src/app/app/with-params/dynamic-false/[slug]/page.tsx b/apps/cache-testing-15-app/src/app/app/with-params/dynamic-false/[slug]/page.tsx new file mode 100644 index 00000000..1c0f3402 --- /dev/null +++ b/apps/cache-testing-15-app/src/app/app/with-params/dynamic-false/[slug]/page.tsx @@ -0,0 +1,35 @@ +import { notFound } from 'next/navigation'; + +import { CommonAppPage } from 'cache-testing-15-app/utils/common-app-page'; +import { createGetData } from 'cache-testing-15-app/utils/create-get-data'; + +import type { JSX } from 'react'; + +type PageParams = { params: Promise<{ slug: string }> }; + +export const dynamicParams = false; + +export const revalidate = 5; + +const getData = createGetData('app/with-params/dynamic-false'); + +export function generateStaticParams(): Promise { + return Promise.resolve([ + Promise.resolve({ slug: '200' }), + Promise.resolve({ slug: '404' }), + Promise.resolve({ slug: 'alternate-200-404' }), + ]); +} + +export default async function Index(props: PageParams): Promise { + const params = await props.params; + const data = await getData(params.slug); + + if (!data) { + notFound(); + } + + const { count, path, time } = data; + + return ; +} diff --git a/apps/cache-testing-15-app/src/app/app/with-params/dynamic-true/[slug]/page.tsx b/apps/cache-testing-15-app/src/app/app/with-params/dynamic-true/[slug]/page.tsx new file mode 100644 index 00000000..e7a2703f --- /dev/null +++ b/apps/cache-testing-15-app/src/app/app/with-params/dynamic-true/[slug]/page.tsx @@ -0,0 +1,35 @@ +import { notFound } from 'next/navigation'; + +import { CommonAppPage } from 'cache-testing-15-app/utils/common-app-page'; +import { createGetData } from 'cache-testing-15-app/utils/create-get-data'; + +import type { JSX } from 'react'; + +type PageParams = { params: Promise<{ slug: string }> }; + +export const dynamicParams = true; + +export const revalidate = 5; + +const getData = createGetData('app/with-params/dynamic-true'); + +export function generateStaticParams(): Promise { + return Promise.resolve([ + Promise.resolve({ slug: '200' }), + Promise.resolve({ slug: '404' }), + Promise.resolve({ slug: 'alternate-200-404' }), + ]); +} + +export default async function Index(props: PageParams): Promise { + const params = await props.params; + const data = await getData(params.slug); + + if (!data) { + notFound(); + } + + const { count, path, time } = data; + + return ; +} diff --git a/apps/cache-testing-15-app/src/app/app/with-params/nesh-cache/[slug]/page.tsx b/apps/cache-testing-15-app/src/app/app/with-params/nesh-cache/[slug]/page.tsx new file mode 100644 index 00000000..cff8eed0 --- /dev/null +++ b/apps/cache-testing-15-app/src/app/app/with-params/nesh-cache/[slug]/page.tsx @@ -0,0 +1,35 @@ +import { notFound } from 'next/navigation'; + +import { CommonAppPage } from 'cache-testing-15-app/utils/common-app-page'; +import { createGetData } from 'cache-testing-15-app/utils/create-get-data'; + +import type { JSX } from 'react'; + +type PageParams = { params: Promise<{ slug: string }> }; + +export const dynamicParams = true; + +export const revalidate = 5; + +const getData = createGetData('app/with-params/nesh-cache', revalidate, 'nesh-cache'); + +export function generateStaticParams(): Promise { + return Promise.resolve([ + Promise.resolve({ slug: '200' }), + Promise.resolve({ slug: '404' }), + Promise.resolve({ slug: 'alternate-200-404' }), + ]); +} + +export default async function Index(props: PageParams): Promise { + const params = await props.params; + const data = await getData(params.slug); + + if (!data) { + notFound(); + } + + const { count, path, time } = data; + + return ; +} diff --git a/apps/cache-testing-15-app/src/app/app/with-params/unstable-cache/[slug]/page.tsx b/apps/cache-testing-15-app/src/app/app/with-params/unstable-cache/[slug]/page.tsx new file mode 100644 index 00000000..e6633669 --- /dev/null +++ b/apps/cache-testing-15-app/src/app/app/with-params/unstable-cache/[slug]/page.tsx @@ -0,0 +1,35 @@ +import { notFound } from 'next/navigation'; + +import { CommonAppPage } from 'cache-testing-15-app/utils/common-app-page'; +import { createGetData } from 'cache-testing-15-app/utils/create-get-data'; + +import type { JSX } from 'react'; + +type PageParams = { params: Promise<{ slug: string }> }; + +export const dynamicParams = true; + +export const revalidate = 5; + +const getData = createGetData('app/with-params/unstable-cache', revalidate, 'unstable-cache'); + +export function generateStaticParams(): Promise { + return Promise.resolve([ + Promise.resolve({ slug: '200' }), + Promise.resolve({ slug: '404' }), + Promise.resolve({ slug: 'alternate-200-404' }), + ]); +} + +export default async function Index(props: PageParams): Promise { + const params = await props.params; + const data = await getData(params.slug); + + if (!data) { + notFound(); + } + + const { count, path, time } = data; + + return ; +} diff --git a/apps/cache-testing-15-app/src/app/favicon.ico b/apps/cache-testing-15-app/src/app/favicon.ico new file mode 100644 index 00000000..718d6fea Binary files /dev/null and b/apps/cache-testing-15-app/src/app/favicon.ico differ diff --git a/apps/cache-testing-15-app/src/app/layout.tsx b/apps/cache-testing-15-app/src/app/layout.tsx new file mode 100644 index 00000000..f6e0f286 --- /dev/null +++ b/apps/cache-testing-15-app/src/app/layout.tsx @@ -0,0 +1,26 @@ +import type { JSX, PropsWithChildren } from 'react'; +import { Suspense } from 'react'; + +import { RestartButton } from 'cache-testing-15-app/components/restart-button'; +import { RevalidateButton } from 'cache-testing-15-app/components/revalidate-button'; +import 'cache-testing-15-app/globals.css'; + +export const metadata = { + title: 'Cache testing app', + description: '', +}; + +export default function RootLayout({ children }: PropsWithChildren): JSX.Element { + return ( + + + {children} + + + + + + + + ); +} diff --git a/apps/cache-testing-15-app/src/components/cache-state-watcher.tsx b/apps/cache-testing-15-app/src/components/cache-state-watcher.tsx new file mode 100644 index 00000000..09e5b80a --- /dev/null +++ b/apps/cache-testing-15-app/src/components/cache-state-watcher.tsx @@ -0,0 +1,50 @@ +'use client'; + +import { type JSX, useEffect, useState } from 'react'; + +type CacheStateWatcherProps = { time: number; revalidateAfter: number }; + +export function CacheStateWatcher({ time, revalidateAfter }: CacheStateWatcherProps): JSX.Element { + const [cacheState, setCacheState] = useState(''); + const [countDown, setCountDown] = useState(''); + + useEffect(() => { + if (!Number.isFinite(revalidateAfter)) { + setCacheState('fresh'); + setCountDown((0).toFixed(3)); + + return; + } + + let id = -1; + + function check(): void { + const now = Date.now(); + + setCountDown(Math.max(0, (time + revalidateAfter - now) / 1000).toFixed(3)); + + if (now > time + revalidateAfter) { + setCacheState('stale'); + + return; + } + + setCacheState('fresh'); + + id = requestAnimationFrame(check); + } + + id = requestAnimationFrame(check); + + return () => { + cancelAnimationFrame(id); + }; + }, [revalidateAfter, time]); + + return ( +
+
Cache state: {cacheState}
+
Stale after: {countDown}
+
+ ); +} diff --git a/apps/cache-testing-15-app/src/components/pre-rendered-at.tsx b/apps/cache-testing-15-app/src/components/pre-rendered-at.tsx new file mode 100644 index 00000000..b672fac9 --- /dev/null +++ b/apps/cache-testing-15-app/src/components/pre-rendered-at.tsx @@ -0,0 +1,11 @@ +import { formatTime } from 'cache-testing-15-app/utils/format-time'; + +import type { JSX } from 'react'; + +type CacheStateWatcherProps = { time: number; isFallback?: boolean }; + +export function PreRenderedAt({ time, isFallback }: CacheStateWatcherProps): JSX.Element { + const preRenderTime = isFallback ? '' : formatTime(time, 3); + + return
Pre-rendered at {preRenderTime}
; +} diff --git a/apps/cache-testing-15-app/src/components/restart-button.tsx b/apps/cache-testing-15-app/src/components/restart-button.tsx new file mode 100644 index 00000000..26e57f07 --- /dev/null +++ b/apps/cache-testing-15-app/src/components/restart-button.tsx @@ -0,0 +1,26 @@ +'use client'; + +import { type JSX, useState } from 'react'; + +export function RestartButton(): JSX.Element { + const [restartState, setRestartState] = useState(''); + + function restart(): void { + fetch('/api/restart-app').then((result) => { + if (!result.ok) { + setRestartState('Fail to restart'); + } + }); + + setRestartState('Restarting...'); + } + + return ( +
+ +
{restartState}
+
+ ); +} diff --git a/apps/cache-testing-15-app/src/components/revalidate-button.tsx b/apps/cache-testing-15-app/src/components/revalidate-button.tsx new file mode 100644 index 00000000..ada33465 --- /dev/null +++ b/apps/cache-testing-15-app/src/components/revalidate-button.tsx @@ -0,0 +1,52 @@ +'use client'; + +import { usePathname } from 'next/navigation'; +import { type JSX, useState } from 'react'; + +type RevalidateButtonAppProps = { + nextApi: 'app'; + type: 'path' | 'tag'; +}; + +type RevalidateButtonPagesProps = { + nextApi: 'pages'; + type: 'path'; +}; + +export function RevalidateButton({ + nextApi, + type, +}: RevalidateButtonAppProps | RevalidateButtonPagesProps): JSX.Element { + const pathname = usePathname(); + + const [revalidation, setRevalidation] = useState(''); + + function handleRevalidation(): void { + const searchParams = new URLSearchParams(); + + if (pathname) { + searchParams.set(type, pathname); + } + + fetch(`/api/revalidate-${nextApi}?${searchParams.toString()}`).then(async (result) => { + if (!result.ok) { + setRevalidation('Fail to revalidate'); + + return; + } + + const json = (await result.json()) as { now: string }; + + setRevalidation(`Revalidated at ${json.now}`); + }); + } + + return ( +
+ +
{revalidation}
+
+ ); +} diff --git a/apps/cache-testing-15-app/src/globals.css b/apps/cache-testing-15-app/src/globals.css new file mode 100644 index 00000000..b635028d --- /dev/null +++ b/apps/cache-testing-15-app/src/globals.css @@ -0,0 +1,89 @@ +:root { + --max-width: 1100px; + --border-radius: 12px; + --font-mono: + ui-monospace, Menlo, Monaco, "Cascadia Mono", "Segoe UI Mono", "Roboto Mono", "Oxygen Mono", + "Ubuntu Monospace", "Source Code Pro", "Fira Mono", "Droid Sans Mono", "Courier New", monospace; + + --foreground-rgb: 0, 0, 0; + --background-start-rgb: 214, 219, 220; + --background-end-rgb: 255, 255, 255; + + --primary-glow: conic-gradient( + from 180deg at 50% 50%, + #16abff33 0deg, + #0885ff33 55deg, + #54d6ff33 120deg, + #0071ff33 160deg, + transparent 360deg + ); + --secondary-glow: radial-gradient(rgba(255, 255, 255, 1), rgba(255, 255, 255, 0)); + + --tile-start-rgb: 239, 245, 249; + --tile-end-rgb: 228, 232, 233; + --tile-border: conic-gradient(#00000080, #00000040, #00000030, #00000020, #00000010, #00000010, #00000080); + + --callout-rgb: 238, 240, 241; + --callout-border-rgb: 172, 175, 176; + --card-rgb: 180, 185, 188; + --card-border-rgb: 131, 134, 135; +} + +@media (prefers-color-scheme: dark) { + :root { + --foreground-rgb: 255, 255, 255; + --background-start-rgb: 0, 0, 0; + --background-end-rgb: 0, 0, 0; + + --primary-glow: radial-gradient(rgba(1, 65, 255, 0.4), rgba(1, 65, 255, 0)); + --secondary-glow: linear-gradient( + to bottom right, + rgba(1, 65, 255, 0), + rgba(1, 65, 255, 0), + rgba(1, 65, 255, 0.3) + ); + + --tile-start-rgb: 2, 13, 46; + --tile-end-rgb: 2, 5, 19; + --tile-border: conic-gradient(#ffffff80, #ffffff40, #ffffff30, #ffffff20, #ffffff10, #ffffff10, #ffffff80); + + --callout-rgb: 20, 20, 20; + --callout-border-rgb: 108, 108, 108; + --card-rgb: 100, 100, 100; + --card-border-rgb: 200, 200, 200; + } +} + +* { + box-sizing: border-box; + padding: 0; + margin: 0; +} + +html, +body { + max-width: 100vw; + overflow-x: hidden; + font-family: "Courier New", Courier, monospace; +} + +body { + color: rgb(var(--foreground-rgb)); + background: linear-gradient(to bottom, transparent, rgb(var(--background-end-rgb))) rgb(var(--background-start-rgb)); + margin: 16px; +} + +a { + color: inherit; + text-decoration: none; +} + +@media (prefers-color-scheme: dark) { + html { + color-scheme: dark; + } +} + +.header { + display: grid; +} diff --git a/apps/cache-testing-15-app/src/instrumentation.ts b/apps/cache-testing-15-app/src/instrumentation.ts new file mode 100644 index 00000000..be821101 --- /dev/null +++ b/apps/cache-testing-15-app/src/instrumentation.ts @@ -0,0 +1,7 @@ +export async function register() { + if (process.env.NEXT_RUNTIME === 'nodejs') { + const { registerInitialCache } = await import('@neshca/cache-handler/instrumentation'); + const CacheHandler = (await import('../cache-handler-redis-stack.mjs')).default; + await registerInitialCache(CacheHandler); + } +} diff --git a/apps/cache-testing-15-app/src/utils/common-app-page.tsx b/apps/cache-testing-15-app/src/utils/common-app-page.tsx new file mode 100644 index 00000000..aeeea006 --- /dev/null +++ b/apps/cache-testing-15-app/src/utils/common-app-page.tsx @@ -0,0 +1,20 @@ +import { type JSX, Suspense } from 'react'; + +import type { PageProps } from './types'; + +import { CacheStateWatcher } from 'cache-testing-15-app/components/cache-state-watcher'; +import { PreRenderedAt } from 'cache-testing-15-app/components/pre-rendered-at'; + +export function CommonAppPage({ count, revalidateAfter, time, path }: PageProps): JSX.Element { + return ( +
+
+ {count} +
+ + + + +
+ ); +} diff --git a/apps/cache-testing-15-app/src/utils/create-get-data.ts b/apps/cache-testing-15-app/src/utils/create-get-data.ts new file mode 100644 index 00000000..d98e4eed --- /dev/null +++ b/apps/cache-testing-15-app/src/utils/create-get-data.ts @@ -0,0 +1,90 @@ +import { neshCache } from '@neshca/cache-handler/functions'; +import axios from 'axios'; +import { unstable_cache } from 'next/cache'; +import { normalizeSlug } from './normalize-slug'; +import type { CountBackendApiResponseJson, PageProps } from './types'; + +async function getViaAxios(url: URL) { + try { + return (await axios.get(url.href)).data; + } catch (_error) { + return null; + } +} + +const cachedAxios = neshCache(getViaAxios); + +export function createGetData( + path: string, + revalidate?: number, + cache?: RequestCache | 'unstable-cache' | 'nesh-cache', +) { + return async function getData(slug: string): Promise | null> { + const splittedPath = path.split('/'); + + splittedPath[0] = `next-15-${splittedPath[0]}`; + + const pathAndTag = `/${splittedPath.join('/')}/${normalizeSlug(slug)}`; + + const url = new URL(`/count${pathAndTag}`, 'http://localhost:8081'); + + let parsedResult: CountBackendApiResponseJson; + + const tags = [pathAndTag, 'whole-app-route']; + + switch (cache) { + case 'unstable-cache': { + const cachedGet = unstable_cache(getViaAxios, tags, { + revalidate, + tags, + }); + + const data = await cachedGet(url); + + if (!data) { + return null; + } + + parsedResult = data; + + break; + } + case 'nesh-cache': { + const data = await cachedAxios( + { + revalidate, + tags, + }, + url, + ); + + if (!data) { + return null; + } + + parsedResult = data; + + break; + } + + default: { + const result = await fetch(url, { + cache, + next: { revalidate, tags }, + }); + + if (!result.ok) { + return null; + } + + parsedResult = (await result.json()) as CountBackendApiResponseJson; + + break; + } + } + + const newData = { count: parsedResult.count, path, time: parsedResult.unixTimeMs }; + + return newData; + }; +} diff --git a/apps/cache-testing-15-app/src/utils/format-time.ts b/apps/cache-testing-15-app/src/utils/format-time.ts new file mode 100644 index 00000000..dc12046b --- /dev/null +++ b/apps/cache-testing-15-app/src/utils/format-time.ts @@ -0,0 +1,8 @@ +export function formatTime(time: number | string | Date = Date.now(), fractionalSecondDigits?: 1 | 2 | 3): string { + return new Date(time).toLocaleTimeString('en-GB', { + fractionalSecondDigits, + hour: '2-digit', + minute: '2-digit', + second: '2-digit', + }); +} diff --git a/apps/cache-testing-15-app/src/utils/normalize-slug.ts b/apps/cache-testing-15-app/src/utils/normalize-slug.ts new file mode 100644 index 00000000..5315af87 --- /dev/null +++ b/apps/cache-testing-15-app/src/utils/normalize-slug.ts @@ -0,0 +1,9 @@ +export function normalizeSlug(slug = ''): string { + switch (slug) { + case '404': + case 'alternate-200-404': + return slug; + default: + return '200'; + } +} diff --git a/apps/cache-testing-15-app/src/utils/types.ts b/apps/cache-testing-15-app/src/utils/types.ts new file mode 100644 index 00000000..232ae0d6 --- /dev/null +++ b/apps/cache-testing-15-app/src/utils/types.ts @@ -0,0 +1,11 @@ +export type PageProps = { count: number; time: number; revalidateAfter: number; path: string }; + +export type WorldTimeApiResponseJson = { unixtime: number }; + +export type TimeBackendApiResponseJson = { unixTimeMs: number }; + +export type CountBackendApiResponseJson = { count: number; unixTimeMs: number }; + +export type RandomHexBackendApiResponseJson = { randomHex: number; unixTimeMs: number }; + +export type RandomHexPageProps = RandomHexBackendApiResponseJson; diff --git a/apps/cache-testing-15-app/tests/app.spec.ts b/apps/cache-testing-15-app/tests/app.spec.ts new file mode 100644 index 00000000..f0a57e49 --- /dev/null +++ b/apps/cache-testing-15-app/tests/app.spec.ts @@ -0,0 +1,377 @@ +import Timers from 'node:timers/promises'; +import { expect, test } from '@playwright/test'; +import { refreshPageCache, revalidateByPath, revalidateByTag } from './test-helpers'; + +const paths = [ + '/app/with-params/dynamic-true/200', + '/app/with-params/nesh-cache/200', + // '/app/with-params/dynamic-false/200', // this fails with native next.js cache + '/app/no-params/dynamic-true/200', + '/app/no-params/dynamic-false/200', +]; + +test.describe('On-demand revalidation', () => { + for (const path of paths) { + test(`If revalidate by tag is clicked, then page should be fresh after reload ${path}`, async ({ + page, + baseURL, + }) => { + const url = new URL(path, `${baseURL}:3000`); + + await page.goto(url.href); + + await refreshPageCache(page, 'tag'); + + const valueFromPage = Number.parseInt((await page.getByTestId('data').innerText()).valueOf(), 10); + + await refreshPageCache(page, 'tag'); + + await expect(page.getByTestId('cache-state')).toContainText('fresh'); + + const valueFromPageAfterReload = Number.parseInt( + (await page.getByTestId('data').innerText()).valueOf(), + 10, + ); + + expect(valueFromPageAfterReload - valueFromPage === 1).toBe(true); + }); + } + + for (const path of paths) { + test(`If revalidate by path is clicked, then page should be fresh after reload ${path}`, async ({ + page, + baseURL, + }) => { + const url = new URL(path, `${baseURL}:3000`); + + await page.goto(url.href); + + await refreshPageCache(page, 'path'); + + const valueFromPage = Number.parseInt((await page.getByTestId('data').innerText()).valueOf(), 10); + + await refreshPageCache(page, 'path'); + + await expect(page.getByTestId('cache-state')).toContainText('fresh'); + + const valueFromPageAfterReload = Number.parseInt( + (await page.getByTestId('data').innerText()).valueOf(), + 10, + ); + + expect(valueFromPageAfterReload - valueFromPage === 1).toBe(true); + }); + } + + for (const path of paths) { + test(`If revalidate by path is clicked on page A, then page B should be fresh on load ${path}`, async ({ + context, + baseURL, + }) => { + const appAUrl = new URL(path, `${baseURL}:3000`); + + const appA = await context.newPage(); + + await appA.goto(appAUrl.href); + + await revalidateByPath(appA); + + const appBUrl = new URL(path, `${baseURL}:3001`); + + const appB = await context.newPage(); + + await appB.goto(appBUrl.href); + + const valueFromPageA = Number.parseInt((await appA.getByTestId('data').innerText()).valueOf(), 10); + + const valueFromPageB = Number.parseInt((await appB.getByTestId('data').innerText()).valueOf(), 10); + + expect(valueFromPageB - valueFromPageA === 1).toBe(true); + }); + } + + for (const path of paths) { + test(`If revalidate by tag is clicked on page A, then page B should be fresh on load ${path}`, async ({ + context, + baseURL, + }) => { + const appAUrl = new URL(path, `${baseURL}:3000`); + + const appA = await context.newPage(); + + await appA.goto(appAUrl.href); + + await revalidateByTag(appA); + + const appBUrl = new URL(path, `${baseURL}:3001`); + + const appB = await context.newPage(); + + await appB.goto(appBUrl.href); + + const valueFromPageA = Number.parseInt((await appA.getByTestId('data').innerText()).valueOf(), 10); + + const valueFromPageB = Number.parseInt((await appB.getByTestId('data').innerText()).valueOf(), 10); + + expect(valueFromPageB - valueFromPageA === 1).toBe(true); + }); + } +}); + +test.describe('Time-based revalidation', () => { + for (const path of paths) { + test(`Page should be fresh after becoming stale and reloaded twice ${path}`, async ({ page, baseURL }) => { + const url = new URL(path, `${baseURL}:3000`); + + await page.goto(url.href); + + await refreshPageCache(page, 'tag'); + + const pageValue = (await page.getByTestId('data').innerText()).valueOf(); + + await page.reload(); + + await expect(page.getByTestId('data')).toHaveText(pageValue); + + await expect(page.getByTestId('cache-state')).toContainText('stale', { timeout: 7500 }); + + // Temporary workaround: Addressing intermittent test failures observed in GitHub Actions. + await Timers.scheduler.wait(1000); + + await page.reload(); + + await expect(page.getByTestId('data')).toHaveText(pageValue); + + await page.reload(); + + await expect(page.getByTestId('data')).not.toHaveText(pageValue); + }); + } + + for (const path of paths) { + test(`Page should be fresh after reloaded once if becoming stale and waiting the same time for cache expiration ${path}`, async ({ + page, + baseURL, + }) => { + const url = new URL(path, `${baseURL}:3000`); + + const startTime = Date.now(); + + await page.goto(url.href); + + await refreshPageCache(page, 'tag'); + + const pageValue = (await page.getByTestId('data').innerText()).valueOf(); + + await page.reload(); + + await expect(page.getByTestId('data')).toHaveText(pageValue); + + await expect(page.getByTestId('cache-state')).toContainText('stale', { timeout: 7500 }); + + const elapsedTime = Date.now() - startTime; + + await Timers.scheduler.wait(elapsedTime); + + await page.reload(); + + await expect(page.getByTestId('data')).not.toHaveText(pageValue); + }); + } + + for (const path of paths) { + test(`If page A is stale, then page B should be fresh after load and reload ${path}`, async ({ + context, + baseURL, + }) => { + const appA = await context.newPage(); + + const appAUrl = new URL(path, `${baseURL}:3000`); + + await appA.goto(appAUrl.href); + + await refreshPageCache(appA, 'tag'); + + await expect(appA.getByTestId('cache-state')).toContainText('stale', { timeout: 7500 }); + + const appB = await context.newPage(); + + const appBUrl = new URL(path, `${baseURL}:3001`); + + await appB.goto(appBUrl.href); + + await expect(appB.getByTestId('cache-state')).toContainText('stale', { timeout: 7500 }); + + await appB.reload(); + + const valueFromPageA = Number.parseInt((await appA.getByTestId('data').innerText()).valueOf(), 10); + + const valueFromPageB = Number.parseInt((await appB.getByTestId('data').innerText()).valueOf(), 10); + + if (valueFromPageB - valueFromPageA > 1) { + console.warn('Page B is more than one revalidation ahead of page A.'); + } + + expect(valueFromPageA < valueFromPageB).toBe(true); + }); + } + + for (const path of paths) { + test(`If page A is stale and reloaded, then page B should be fresh after load ${path}`, async ({ + context, + baseURL, + }) => { + const appAUrl = new URL(path, `${baseURL}:3000`); + + const appA = await context.newPage(); + + await appA.goto(appAUrl.href); + + await refreshPageCache(appA, 'tag'); + + await expect(appA.getByTestId('cache-state')).toContainText('stale', { timeout: 7500 }); + + await appA.reload(); + + await appA.reload(); + + const appB = await context.newPage(); + + const appBUrl = new URL(path, `${baseURL}:3001`); + + await appB.goto(appBUrl.href); + + const valueFromPageA = Number.parseInt((await appA.getByTestId('data').innerText()).valueOf(), 10); + + const valueFromPageB = Number.parseInt((await appA.getByTestId('data').innerText()).valueOf(), 10); + + expect(valueFromPageA === valueFromPageB).toBe(true); + }); + } +}); + +test.describe('Data consistency between two app instances for the same page', () => { + for (const path of paths) { + test(`Should be maintained when loaded at the same time ${path}`, async ({ context, baseURL }) => { + const appAUrl = new URL(path, `${baseURL}:3000`); + const appBUrl = new URL(path, `${baseURL}:3001`); + + const appA = await context.newPage(); + const appB = await context.newPage(); + + await appA.goto(appAUrl.href); + await appB.goto(appBUrl.href); + + await refreshPageCache(appA, 'tag'); + + await appA.reload(); + await appB.reload(); + + const valueFromPageA = Number.parseInt((await appA.getByTestId('data').innerText()).valueOf(), 10); + + const valueFromPageB = Number.parseInt((await appB.getByTestId('data').innerText()).valueOf(), 10); + + expect(valueFromPageA === valueFromPageB).toBe(true); + }); + } +}); + +test.describe('Data consistency after server restart', () => { + for (const path of paths) { + test(`Should be maintained between App A and App B after App B server restarts ${path}`, async ({ + context, + baseURL, + }) => { + const appAUrl = new URL(path, `${baseURL}:3000`); + const appBUrl = new URL(path, `${baseURL}:3001`); + + const appA = await context.newPage(); + const appB = await context.newPage(); + + await appA.goto(appAUrl.href); + await appB.goto(appBUrl.href); + + await refreshPageCache(appA, 'tag'); + + await appA.reload(); + await appB.reload(); + + let valueFromPageA = Number.parseInt((await appA.getByTestId('data').innerText()).valueOf(), 10); + + const valueFromPageB = Number.parseInt((await appB.getByTestId('data').innerText()).valueOf(), 10); + + expect(valueFromPageA === valueFromPageB).toBe(true); + + const restartResult = await fetch(`${baseURL}:9000/restart/${appBUrl.port}`); + + expect(restartResult.status).toBe(200); + + for await (const _ of [1, 2, 3]) { + await refreshPageCache(appA, 'tag'); + } + + valueFromPageA = Number.parseInt((await appA.getByTestId('data').innerText()).valueOf(), 10); + + await appB.reload(); + + const valueFromPageBAfterRestart = Number.parseInt( + (await appB.getByTestId('data').innerText()).valueOf(), + 10, + ); + + expect(valueFromPageBAfterRestart === valueFromPageA).toBe(true); + }); + } +}); + +test.describe('SSR', () => { + test('verify initial cache state is fresh on SSR page load', async ({ page, baseURL }) => { + const url = new URL('/app/no-params/ssr/200', `${baseURL}:3000`); + + await page.goto(url.href); + + await expect(page.getByTestId('cache-state')).toContainText('fresh'); + }); + + test('ensure data value increments by 1 on SSR page reload', async ({ page, baseURL }) => { + const url = new URL('/app/no-params/ssr/200', `${baseURL}:3000`); + + await page.goto(url.href); + + const valueFromPage = Number.parseInt((await page.getByTestId('data').innerText()).valueOf(), 10); + + await page.reload(); + + const valueFromPageAfterReload = Number.parseInt((await page.getByTestId('data').innerText()).valueOf(), 10); + + expect(valueFromPageAfterReload - valueFromPage === 1).toBe(true); + }); +}); + +test.describe('Routes', () => { + test('static route return OK', async ({ page, baseURL }) => { + const url = new URL('/app/static', `${baseURL}:3000`); + + await page.goto(url.href); + + const message = await page.getByText('OK').innerText(); + + expect(message).toBe('OK'); + }); +}); + +test.describe('unstable_cache', () => { + test('unstable_cache works', async ({ page, baseURL }) => { + const url = new URL('/app/with-params/unstable-cache/200', `${baseURL}:3000`); + + await page.goto(url.href); + + const valueFromPage = Number.parseInt((await page.getByTestId('data').innerText()).valueOf(), 10); + + await page.reload(); + + const valueFromPageAfterReload = Number.parseInt((await page.getByTestId('data').innerText()).valueOf(), 10); + + expect(valueFromPageAfterReload === valueFromPage).toBe(true); + }); +}); diff --git a/apps/cache-testing-15-app/tests/test-helpers.ts b/apps/cache-testing-15-app/tests/test-helpers.ts new file mode 100644 index 00000000..079475d6 --- /dev/null +++ b/apps/cache-testing-15-app/tests/test-helpers.ts @@ -0,0 +1,56 @@ +import { type Page, expect } from '@playwright/test'; + +export async function revalidateByTag(page: Page) { + await page.getByTestId('revalidate-button-tag').click(); + + await expect(page.getByTestId('is-revalidated-by-tag')).toContainText('Revalidated at'); +} + +export async function revalidateByPath(page: Page) { + await page.getByTestId('revalidate-button-path').click(); + + await expect(page.getByTestId('is-revalidated-by-path')).toContainText('Revalidated at'); +} + +export async function refreshPageCache(page: Page, by: 'tag' | 'path') { + switch (by) { + case 'tag': { + await revalidateByTag(page); + break; + } + case 'path': { + await revalidateByPath(page); + break; + } + default: { + throw new Error(`Invalid by: ${by}`); + } + } + + await page.reload(); +} + +export async function revalidateByApi( + path: string, + base: string, + router: 'app' | 'pages' = 'app', + by: 'path' | 'tag' = 'tag', +): Promise<{ revalidated: boolean; now: string }> { + const url = new URL(`/api/revalidate-${router}`, base); + + url.searchParams.append(by, path); + + const response = await fetch(url); + + if (!response.ok) { + throw new Error('Failed to revalidate'); + } + + const json = (await response.json()) as { revalidated: boolean; now: string }; + + if (!json.revalidated) { + throw new Error('Failed to revalidate'); + } + + return json; +} diff --git a/apps/cache-testing-15-app/tsconfig.json b/apps/cache-testing-15-app/tsconfig.json new file mode 100644 index 00000000..b4e1e653 --- /dev/null +++ b/apps/cache-testing-15-app/tsconfig.json @@ -0,0 +1,16 @@ +{ + "extends": "@repo/typescript-config/nextjs.json", + "compilerOptions": { + "paths": { + "cache-testing-15-app/*": ["./src/*"] + }, + "plugins": [ + { + "name": "next" + } + ], + "strictNullChecks": true + }, + "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts", "run-app-instances.ts"], + "exclude": ["node_modules"] +} diff --git a/apps/cache-testing/package.json b/apps/cache-testing/package.json index a3f0640d..64c4dfc3 100644 --- a/apps/cache-testing/package.json +++ b/apps/cache-testing/package.json @@ -17,13 +17,13 @@ "dependencies": { "@neshca/cache-handler": "*", "axios": "1.7.7", - "next": "14.2.15", + "next": "14.2.16", "react": "18.3.1", "react-dom": "18.3.1", "redis": "4.7.0" }, "devDependencies": { - "@next/eslint-plugin-next": "14.2.15", + "@next/eslint-plugin-next": "14.2.16", "@playwright/test": "1.48.2", "@repo/eslint-config": "*", "@repo/typescript-config": "*", diff --git a/docs/cache-handler-docs/package.json b/docs/cache-handler-docs/package.json index cf8a392c..f342b415 100644 --- a/docs/cache-handler-docs/package.json +++ b/docs/cache-handler-docs/package.json @@ -11,14 +11,14 @@ "start:docs": "serve out" }, "dependencies": { - "next": "14.2.15", + "next": "14.2.16", "nextra": "3.2.0", "nextra-theme-docs": "3.2.0", "react": "18.3.1", "react-dom": "18.3.1" }, "devDependencies": { - "@next/eslint-plugin-next": "14.2.15", + "@next/eslint-plugin-next": "14.2.16", "@repo/eslint-config": "*", "@repo/typescript-config": "*", "@types/eslint": "8.56.12", diff --git a/internal/next-common/package.json b/internal/next-common/package.json index 8bf071d1..5128b97a 100644 --- a/internal/next-common/package.json +++ b/internal/next-common/package.json @@ -8,7 +8,7 @@ "types": "./src/next-common.ts" }, "dependencies": { - "next": "14.2.15" + "next": "15.0.0" }, "devDependencies": { "@repo/typescript-config": "*", diff --git a/internal/next-common/src/next-common.ts b/internal/next-common/src/next-common.ts index 41dc4788..5933ba27 100644 --- a/internal/next-common/src/next-common.ts +++ b/internal/next-common/src/next-common.ts @@ -2,27 +2,59 @@ import type { OutgoingHttpHeaders } from 'http'; import type { CacheHandler, CacheHandlerValue as NextCacheHandlerValue } from 'next/dist/server/lib/incremental-cache'; import type FileSystemCache from 'next/dist/server/lib/incremental-cache/file-system-cache'; -import type { IncrementalCacheValue } from 'next/dist/server/response-cache/types'; - -export type { PrerenderManifest } from 'next/dist/build'; -export type { CacheHandler, CacheHandlerContext } from 'next/dist/server/lib/incremental-cache'; -export type { +import type { + CachedImageValue, CachedRedirectValue, + CachedRouteKind, CachedRouteValue, - CachedImageValue, - CachedFetchValue, - IncrementalCacheValue, - IncrementalCacheEntry, + IncrementalCacheValue as IncrementalCacheValueNextApi, + IncrementalCachedAppPageValue, + CachedFetchValue as NextCachedFetchValue, } from 'next/dist/server/response-cache/types'; +export type { PrerenderManifest } from 'next/dist/build'; +export type { CacheHandler, CacheHandlerContext } from 'next/dist/server/lib/incremental-cache'; + +type Override = Omit & U; + +type ExtractIncrementalCacheKind = T extends { kind: Kind } ? T : never; + +export type Revalidate = false | number; + +export type IncrementalCachedPageValue = ExtractIncrementalCacheKind< + IncrementalCacheValueNextApi, + CachedRouteKind.PAGES +>; + +export type LegacyIncrementalCachedPageValue = Override & { + postponed: string | undefined; +}; + +export type CachedFetchValue = Override; + +export type IncrementalCacheValue = + | Override + | LegacyIncrementalCachedPageValue + | Override + | Override + | Override + | CachedFetchValue + | Override; + +export type IncrementalCacheEntry = { + curRevalidate?: Revalidate; + revalidateAfter: Revalidate; + isStale?: boolean | -1; + value: IncrementalCacheValue | null; + isFallback: boolean | undefined; +}; + export type NextRouteMetadata = { status: number | undefined; headers: OutgoingHttpHeaders | undefined; postponed: string | undefined; }; -export type Revalidate = false | number; - /** * A set of time periods and timestamps for controlling cache behavior. */ @@ -55,23 +87,28 @@ export type LifespanParameters = { readonly revalidate: Revalidate | undefined; }; -export type CacheHandlerValue = NextCacheHandlerValue & { - /** - * Timestamp in milliseconds when the cache entry was last modified. - */ - lastModified: number; - /** - * Tags associated with the cache entry. They are used for on-demand revalidation. - */ - tags: Readonly; - /** - * The lifespan parameters for the cache entry. - * - * Null for pages with `fallback: false` in `getStaticPaths`. - * Consider these pages as always fresh and never stale. - */ - lifespan: LifespanParameters | null; -}; +export type CacheHandlerValue = Override< + NextCacheHandlerValue & { + /** + * Timestamp in milliseconds when the cache entry was last modified. + */ + lastModified: number; + /** + * Tags associated with the cache entry. They are used for on-demand revalidation. + */ + tags: Readonly; + /** + * The lifespan parameters for the cache entry. + * + * Null for pages with `fallback: false` in `getStaticPaths`. + * Consider these pages as always fresh and never stale. + */ + lifespan: LifespanParameters | null; + }, + { + value: IncrementalCacheValue | null; + } +>; export type RouteMetadata = NextRouteMetadata; @@ -101,13 +138,9 @@ export type UnwrappedCacheHandler = { revalidateTag(...args: CacheHandlerParametersRevalidateTag): Awaited; }; -type ExtractIncrementalCacheKind = T extends { kind: Kind } ? T : never; - -export type IncrementalCachedPageValue = ExtractIncrementalCacheKind; - export type TagsManifest = { version: 1; items: Record; }; -export const NEXT_CACHE_IMPLICIT_TAG_ID = '_N_T_'; +export type NextCacheImplicitTagId = '_N_T_'; diff --git a/internal/next-lru-cache/src/cache-types/next-cache-handler-value.ts b/internal/next-lru-cache/src/cache-types/next-cache-handler-value.ts index 3088d0e0..deb86fd0 100644 --- a/internal/next-lru-cache/src/cache-types/next-cache-handler-value.ts +++ b/internal/next-lru-cache/src/cache-types/next-cache-handler-value.ts @@ -11,6 +11,28 @@ function calculateObjectSize({ value }: CacheHandlerValue): number { } switch (value.kind) { + case 'FETCH': { + // Calculate size based on the length of the stringified data + return JSON.stringify(value.data || '').length; + } + case 'APP_PAGE': { + return value.html.length + (JSON.stringify(value.rscData)?.length || 0); + } + case 'PAGES': { + return value.html.length + (JSON.stringify(value.pageData)?.length || 0); + } + + case 'PAGE': { + const pageDataLength = value.pageData ? JSON.stringify(value.pageData).length : 0; + + return value.html.length + pageDataLength; + } + + case 'ROUTE': + case 'APP_ROUTE': { + // Size based on the length of the body + return value.body.length; + } case 'REDIRECT': { // Calculate size based on the length of the stringified props return JSON.stringify(value.props).length; @@ -19,19 +41,9 @@ function calculateObjectSize({ value }: CacheHandlerValue): number { // Throw a specific error for image kind throw new Error('Image kind should not be used for incremental-cache calculations.'); } - case 'FETCH': { - // Calculate size based on the length of the stringified data - return JSON.stringify(value.data || '').length; - } - case 'ROUTE': { - // Size based on the length of the body - return value.body.length; - } default: { - // Rough estimate calculation for other types - // Combine HTML length and page data length - const pageDataLength = value.pageData ? JSON.stringify(value.pageData).length : 0; - return value.html.length + pageDataLength; + // @ts-expect-error + throw new Error(`Invalid kind: ${value.kind}`); } } } diff --git a/package-lock.json b/package-lock.json index c0e16f77..9085af97 100644 --- a/package-lock.json +++ b/package-lock.json @@ -39,13 +39,13 @@ "dependencies": { "@neshca/cache-handler": "*", "axios": "1.7.7", - "next": "14.2.15", + "next": "14.2.16", "react": "18.3.1", "react-dom": "18.3.1", "redis": "4.7.0" }, "devDependencies": { - "@next/eslint-plugin-next": "14.2.15", + "@next/eslint-plugin-next": "14.2.16", "@playwright/test": "1.48.2", "@repo/eslint-config": "*", "@repo/typescript-config": "*", @@ -61,18 +61,208 @@ "typescript": "5.6.3" } }, + "apps/cache-testing-15-app": { + "name": "@repo/cache-testing-15-app", + "version": "0.0.0", + "license": "MIT", + "dependencies": { + "@neshca/cache-handler": "*", + "axios": "1.7.7", + "next": "15.0.0", + "react": "19.0.0-rc-65a56d0e-20241020", + "react-dom": "19.0.0-rc-65a56d0e-20241020", + "redis": "4.7.0" + }, + "devDependencies": { + "@next/eslint-plugin-next": "15.0.0", + "@playwright/test": "1.48.1", + "@repo/eslint-config": "*", + "@repo/typescript-config": "*", + "@types/eslint": "8.56.12", + "@types/node": "22.7.7", + "@types/react": "npm:types-react@19.0.0-rc.1", + "@types/react-dom": "npm:types-react-dom@19.0.0-rc.1", + "dotenv-cli": "7.4.2", + "eslint": "8.57.1", + "fastify": "5.0.0", + "pm2": "5.4.2", + "tsx": "4.19.1", + "typescript": "5.6.3" + } + }, + "apps/cache-testing-15-app/node_modules/@next/eslint-plugin-next": { + "version": "15.0.0", + "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-15.0.0.tgz", + "integrity": "sha512-UG/Gnsq6Sc4wRhO9qk+vc/2v4OfRXH7GEH6/TGlNF5eU/vI9PIO7q+kgd65X2DxJ+qIpHWpzWwlPLmqMi1FE9A==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-glob": "3.3.1" + } + }, + "apps/cache-testing-15-app/node_modules/@playwright/test": { + "version": "1.48.1", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.48.1.tgz", + "integrity": "sha512-s9RtWoxkOLmRJdw3oFvhFbs9OJS0BzrLUc8Hf6l2UdCNd1rqeEyD4BhCJkvzeEoD1FsK4mirsWwGerhVmYKtZg==", + "devOptional": true, + "license": "Apache-2.0", + "dependencies": { + "playwright": "1.48.1" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + } + }, + "apps/cache-testing-15-app/node_modules/@types/node": { + "version": "22.7.7", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.7.tgz", + "integrity": "sha512-SRxCrrg9CL/y54aiMCG3edPKdprgMVGDXjA3gB8UmmBW5TcXzRUYAh8EWzTnSJFAd1rgImPELza+A3bJ+qxz8Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.19.2" + } + }, + "apps/cache-testing-15-app/node_modules/@types/react": { + "name": "types-react", + "version": "19.0.0-rc.1", + "resolved": "https://registry.npmjs.org/types-react/-/types-react-19.0.0-rc.1.tgz", + "integrity": "sha512-RshndUfqTW6K3STLPis8BtAYCGOkMbtvYsi90gmVNDZBXUyUc5juf2PE9LfS/JmOlUIRO8cWTS/1MTnmhjDqyQ==", + "dev": true, + "dependencies": { + "csstype": "^3.0.2" + } + }, + "apps/cache-testing-15-app/node_modules/@types/react-dom": { + "name": "types-react-dom", + "version": "19.0.0-rc.1", + "resolved": "https://registry.npmjs.org/types-react-dom/-/types-react-dom-19.0.0-rc.1.tgz", + "integrity": "sha512-VSLZJl8VXCD0fAWp7DUTFUDCcZ8DVXOQmjhJMD03odgeFmu14ZQJHCXeETm3BEAhJqfgJaFkLnGkQv88sRx0fQ==", + "dev": true, + "dependencies": { + "@types/react": "*" + } + }, + "apps/cache-testing-15-app/node_modules/next": { + "version": "15.0.0", + "resolved": "https://registry.npmjs.org/next/-/next-15.0.0.tgz", + "integrity": "sha512-/ivqF6gCShXpKwY9hfrIQYh8YMge8L3W+w1oRLv/POmK4MOQnh+FscZ8a0fRFTSQWE+2z9ctNYvELD9vP2FV+A==", + "license": "MIT", + "dependencies": { + "@next/env": "15.0.0", + "@swc/counter": "0.1.3", + "@swc/helpers": "0.5.13", + "busboy": "1.6.0", + "caniuse-lite": "^1.0.30001579", + "postcss": "8.4.31", + "styled-jsx": "5.1.6" + }, + "bin": { + "next": "dist/bin/next" + }, + "engines": { + "node": ">=18.18.0" + }, + "optionalDependencies": { + "@next/swc-darwin-arm64": "15.0.0", + "@next/swc-darwin-x64": "15.0.0", + "@next/swc-linux-arm64-gnu": "15.0.0", + "@next/swc-linux-arm64-musl": "15.0.0", + "@next/swc-linux-x64-gnu": "15.0.0", + "@next/swc-linux-x64-musl": "15.0.0", + "@next/swc-win32-arm64-msvc": "15.0.0", + "@next/swc-win32-x64-msvc": "15.0.0", + "sharp": "^0.33.5" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.1.0", + "@playwright/test": "^1.41.2", + "babel-plugin-react-compiler": "*", + "react": "^18.2.0 || 19.0.0-rc-65a56d0e-20241020", + "react-dom": "^18.2.0 || 19.0.0-rc-65a56d0e-20241020", + "sass": "^1.3.0" + }, + "peerDependenciesMeta": { + "@opentelemetry/api": { + "optional": true + }, + "@playwright/test": { + "optional": true + }, + "babel-plugin-react-compiler": { + "optional": true + }, + "sass": { + "optional": true + } + } + }, + "apps/cache-testing-15-app/node_modules/react": { + "version": "19.0.0-rc-65a56d0e-20241020", + "resolved": "https://registry.npmjs.org/react/-/react-19.0.0-rc-65a56d0e-20241020.tgz", + "integrity": "sha512-rZqpfd9PP/A97j9L1MR6fvWSMgs3khgIyLd0E+gYoCcLrxXndj+ySPRVlDPDC3+f7rm8efHNL4B6HeapqU6gzw==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "apps/cache-testing-15-app/node_modules/react-dom": { + "version": "19.0.0-rc-65a56d0e-20241020", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.0.0-rc-65a56d0e-20241020.tgz", + "integrity": "sha512-OrsgAX3LQ6JtdBJayK4nG1Hj5JebzWyhKSsrP/bmkeFxulb0nG2LaPloJ6kBkAxtgjiwRyGUciJ4+Qu64gy/KA==", + "license": "MIT", + "dependencies": { + "scheduler": "0.25.0-rc-65a56d0e-20241020" + }, + "peerDependencies": { + "react": "19.0.0-rc-65a56d0e-20241020" + } + }, + "apps/cache-testing-15-app/node_modules/tsx": { + "version": "4.19.1", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.19.1.tgz", + "integrity": "sha512-0flMz1lh74BR4wOvBjuh9olbnwqCPc35OOlfyzHba0Dc+QNUeWX/Gq2YTbnwcWPO3BMd8fkzRVrHcsR+a7z7rA==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "~0.23.0", + "get-tsconfig": "^4.7.5" + }, + "bin": { + "tsx": "dist/cli.mjs" + }, + "engines": { + "node": ">=18.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + } + }, + "apps/cache-testing/node_modules/@types/node": { + "version": "22.8.4", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.8.4.tgz", + "integrity": "sha512-SpNNxkftTJOPk0oN+y2bIqurEXHTA2AOZ3EJDDKeJ5VzkvvORSvmQXGQarcOzWV1ac7DCaPBEdMDxBsM+d8jWw==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.19.8" + } + }, "docs/cache-handler-docs": { "name": "@repo/cache-handler-docs", "version": "0.0.0", "dependencies": { - "next": "14.2.15", + "next": "14.2.16", "nextra": "3.2.0", "nextra-theme-docs": "3.2.0", "react": "18.3.1", "react-dom": "18.3.1" }, "devDependencies": { - "@next/eslint-plugin-next": "14.2.15", + "@next/eslint-plugin-next": "14.2.16", "@repo/eslint-config": "*", "@repo/typescript-config": "*", "@types/eslint": "8.56.12", @@ -84,6 +274,16 @@ "typescript": "5.6.3" } }, + "docs/cache-handler-docs/node_modules/@types/node": { + "version": "22.8.4", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.8.4.tgz", + "integrity": "sha512-SpNNxkftTJOPk0oN+y2bIqurEXHTA2AOZ3EJDDKeJ5VzkvvORSvmQXGQarcOzWV1ac7DCaPBEdMDxBsM+d8jWw==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.19.8" + } + }, "internal/backend": { "name": "@repo/backend", "version": "0.0.0", @@ -100,6 +300,16 @@ "typescript": "5.6.3" } }, + "internal/backend/node_modules/@types/node": { + "version": "22.8.4", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.8.4.tgz", + "integrity": "sha512-SpNNxkftTJOPk0oN+y2bIqurEXHTA2AOZ3EJDDKeJ5VzkvvORSvmQXGQarcOzWV1ac7DCaPBEdMDxBsM+d8jWw==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.19.8" + } + }, "internal/eslint-config": { "name": "@repo/eslint-config", "version": "0.0.0", @@ -118,7 +328,7 @@ "version": "0.0.0", "license": "MIT", "dependencies": { - "next": "14.2.15" + "next": "15.0.0" }, "devDependencies": { "@repo/typescript-config": "*", @@ -126,6 +336,70 @@ "typescript": "5.6.3" } }, + "internal/next-common/node_modules/@types/node": { + "version": "22.8.4", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.8.4.tgz", + "integrity": "sha512-SpNNxkftTJOPk0oN+y2bIqurEXHTA2AOZ3EJDDKeJ5VzkvvORSvmQXGQarcOzWV1ac7DCaPBEdMDxBsM+d8jWw==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.19.8" + } + }, + "internal/next-common/node_modules/next": { + "version": "15.0.0", + "resolved": "https://registry.npmjs.org/next/-/next-15.0.0.tgz", + "integrity": "sha512-/ivqF6gCShXpKwY9hfrIQYh8YMge8L3W+w1oRLv/POmK4MOQnh+FscZ8a0fRFTSQWE+2z9ctNYvELD9vP2FV+A==", + "license": "MIT", + "dependencies": { + "@next/env": "15.0.0", + "@swc/counter": "0.1.3", + "@swc/helpers": "0.5.13", + "busboy": "1.6.0", + "caniuse-lite": "^1.0.30001579", + "postcss": "8.4.31", + "styled-jsx": "5.1.6" + }, + "bin": { + "next": "dist/bin/next" + }, + "engines": { + "node": ">=18.18.0" + }, + "optionalDependencies": { + "@next/swc-darwin-arm64": "15.0.0", + "@next/swc-darwin-x64": "15.0.0", + "@next/swc-linux-arm64-gnu": "15.0.0", + "@next/swc-linux-arm64-musl": "15.0.0", + "@next/swc-linux-x64-gnu": "15.0.0", + "@next/swc-linux-x64-musl": "15.0.0", + "@next/swc-win32-arm64-msvc": "15.0.0", + "@next/swc-win32-x64-msvc": "15.0.0", + "sharp": "^0.33.5" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.1.0", + "@playwright/test": "^1.41.2", + "babel-plugin-react-compiler": "*", + "react": "^18.2.0 || 19.0.0-rc-65a56d0e-20241020", + "react-dom": "^18.2.0 || 19.0.0-rc-65a56d0e-20241020", + "sass": "^1.3.0" + }, + "peerDependenciesMeta": { + "@opentelemetry/api": { + "optional": true + }, + "@playwright/test": { + "optional": true + }, + "babel-plugin-react-compiler": { + "optional": true + }, + "sass": { + "optional": true + } + } + }, "internal/next-lru-cache": { "name": "@repo/next-lru-cache", "version": "0.0.0", @@ -140,6 +414,16 @@ "typescript": "5.6.3" } }, + "internal/next-lru-cache/node_modules/@types/node": { + "version": "22.8.4", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.8.4.tgz", + "integrity": "sha512-SpNNxkftTJOPk0oN+y2bIqurEXHTA2AOZ3EJDDKeJ5VzkvvORSvmQXGQarcOzWV1ac7DCaPBEdMDxBsM+d8jWw==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.19.8" + } + }, "internal/prettier-config": { "name": "@repo/prettier-config", "version": "0.0.0", @@ -229,13 +513,14 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.25.7.tgz", - "integrity": "sha512-0xZJFNE5XMpENsgfHYTw8FbX4kv53mFLn2i3XPoq69LyhYSCBJtitaHx9QnsVTrsogI4Z3+HtEfZ2/GFPOtf5g==", + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.0.tgz", + "integrity": "sha512-INCKxTtbXtcNbUZ3YXutwMpEleqttcswhAdee7dhuoVrD2cnuc3PqtERBtxkX5nziX9vnBL8WXmSGwv8CuPV6g==", "dev": true, "license": "MIT", "dependencies": { - "@babel/highlight": "^7.25.7", + "@babel/helper-validator-identifier": "^7.25.9", + "js-tokens": "^4.0.0", "picocolors": "^1.0.0" }, "engines": { @@ -243,9 +528,9 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.25.8", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.25.8.tgz", - "integrity": "sha512-ZsysZyXY4Tlx+Q53XdnOFmqwfB9QDTHYxaZYajWRoBLuLEAwI2UIbtxOjWh/cFaa9IKUlcB+DDuoskLuKu56JA==", + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.0.tgz", + "integrity": "sha512-qETICbZSLe7uXv9VE8T/RWOdIE5qqyTucOt4zLYMafj2MRO271VGgLd4RACJMeBO37UPWhXiKMBk7YlJ0fOzQA==", "dev": true, "license": "MIT", "engines": { @@ -253,22 +538,22 @@ } }, "node_modules/@babel/core": { - "version": "7.25.8", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.25.8.tgz", - "integrity": "sha512-Oixnb+DzmRT30qu9d3tJSQkxuygWm32DFykT4bRoORPa9hZ/L4KhVB/XiRm6KG+roIEM7DBQlmg27kw2HZkdZg==", + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.0.tgz", + "integrity": "sha512-i1SLeK+DzNnQ3LL/CswPCa/E5u4lh1k6IAEphON8F+cXt0t9euTshDru0q7/IqMa1PMPz5RnHuHscF8/ZJsStg==", "dev": true, "license": "MIT", "dependencies": { "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.25.7", - "@babel/generator": "^7.25.7", - "@babel/helper-compilation-targets": "^7.25.7", - "@babel/helper-module-transforms": "^7.25.7", - "@babel/helpers": "^7.25.7", - "@babel/parser": "^7.25.8", - "@babel/template": "^7.25.7", - "@babel/traverse": "^7.25.7", - "@babel/types": "^7.25.8", + "@babel/code-frame": "^7.26.0", + "@babel/generator": "^7.26.0", + "@babel/helper-compilation-targets": "^7.25.9", + "@babel/helper-module-transforms": "^7.26.0", + "@babel/helpers": "^7.26.0", + "@babel/parser": "^7.26.0", + "@babel/template": "^7.25.9", + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.26.0", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -294,9 +579,9 @@ } }, "node_modules/@babel/eslint-parser": { - "version": "7.25.8", - "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.25.8.tgz", - "integrity": "sha512-Po3VLMN7fJtv0nsOjBDSbO1J71UhzShE9MuOSkWEV9IZQXzhZklYtzKZ8ZD/Ij3a0JBv1AG3Ny2L3jvAHQVOGg==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.25.9.tgz", + "integrity": "sha512-5UXfgpK0j0Xr/xIdgdLEhOFxaDZ0bRPWJJchRpqOSur/3rZoPbqqki5mm0p4NE2cs28krBEiSM2MB7//afRSQQ==", "dev": true, "license": "MIT", "dependencies": { @@ -333,13 +618,14 @@ } }, "node_modules/@babel/generator": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.25.7.tgz", - "integrity": "sha512-5Dqpl5fyV9pIAD62yK9P7fcA768uVPUyrQmqpqstHWgMma4feF1x/oFysBCVZLY5wJ2GkMUCdsNDnGZrPoR6rA==", + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.0.tgz", + "integrity": "sha512-/AIkAmInnWwgEAJGQr9vY0c66Mj6kjkE2ZPB1PurTRaRAh3U+J45sAQMjQDJdh4WbR3l0x5xkimXBKyBXXAu2w==", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.25.7", + "@babel/parser": "^7.26.0", + "@babel/types": "^7.26.0", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^3.0.2" @@ -349,14 +635,14 @@ } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.7.tgz", - "integrity": "sha512-DniTEax0sv6isaw6qSQSfV4gVRNtw2rte8HHM45t9ZR0xILaufBRNkpMifCRiAPyvL4ACD6v0gfCwCmtOQaV4A==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.9.tgz", + "integrity": "sha512-j9Db8Suy6yV/VHa4qzrj9yZfZxhLWQdVnRlXxmKLYlhWUVB1sB2G5sxuWYXk/whHD9iW76PmNzxZ4UCnTQTVEQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.25.7", - "@babel/helper-validator-option": "^7.25.7", + "@babel/compat-data": "^7.25.9", + "@babel/helper-validator-option": "^7.25.9", "browserslist": "^4.24.0", "lru-cache": "^5.1.1", "semver": "^6.3.1" @@ -393,30 +679,29 @@ "license": "ISC" }, "node_modules/@babel/helper-module-imports": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.7.tgz", - "integrity": "sha512-o0xCgpNmRohmnoWKQ0Ij8IdddjyBFE4T2kagL/x6M3+4zUgc+4qTOUBoNe4XxDskt1HPKO007ZPiMgLDq2s7Kw==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz", + "integrity": "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/traverse": "^7.25.7", - "@babel/types": "^7.25.7" + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.25.7.tgz", - "integrity": "sha512-k/6f8dKG3yDz/qCwSM+RKovjMix563SLxQFo0UhRNo239SP6n9u5/eLtKD6EAjwta2JHJ49CsD8pms2HdNiMMQ==", + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz", + "integrity": "sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-module-imports": "^7.25.7", - "@babel/helper-simple-access": "^7.25.7", - "@babel/helper-validator-identifier": "^7.25.7", - "@babel/traverse": "^7.25.7" + "@babel/helper-module-imports": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9", + "@babel/traverse": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -425,24 +710,10 @@ "@babel/core": "^7.0.0" } }, - "node_modules/@babel/helper-simple-access": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.25.7.tgz", - "integrity": "sha512-FPGAkJmyoChQeM+ruBGIDyrT2tKfZJO8NcxdC+CWNJi7N8/rZpSxK7yvBJ5O/nF1gfu5KzN7VKG3YVSLFfRSxQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/traverse": "^7.25.7", - "@babel/types": "^7.25.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/helper-string-parser": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.7.tgz", - "integrity": "sha512-CbkjYdsJNHFk8uqpEkpCvRs3YRp9tY6FmFY7wLMSYuGYkrdUi7r2lc4/wqsvlHoMznX3WJ9IP8giGPq68T/Y6g==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", + "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", "dev": true, "license": "MIT", "engines": { @@ -450,9 +721,9 @@ } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.7.tgz", - "integrity": "sha512-AM6TzwYqGChO45oiuPqwL2t20/HdMC1rTPAesnBCgPCSF1x3oN9MVUwQV2iyz4xqWrctwK5RNC8LV22kaQCNYg==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", + "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", "dev": true, "license": "MIT", "engines": { @@ -460,9 +731,9 @@ } }, "node_modules/@babel/helper-validator-option": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.7.tgz", - "integrity": "sha512-ytbPLsm+GjArDYXJ8Ydr1c/KJuutjF2besPNbIZnZ6MKUxi/uTA22t2ymmA4WFjZFpjiAMO0xuuJPqK2nvDVfQ==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz", + "integrity": "sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==", "dev": true, "license": "MIT", "engines": { @@ -470,121 +741,27 @@ } }, "node_modules/@babel/helpers": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.25.7.tgz", - "integrity": "sha512-Sv6pASx7Esm38KQpF/U/OXLwPPrdGHNKoeblRxgZRLXnAtnkEe4ptJPDtAZM7fBLadbc1Q07kQpSiGQ0Jg6tRA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/template": "^7.25.7", - "@babel/types": "^7.25.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.25.7.tgz", - "integrity": "sha512-iYyACpW3iW8Fw+ZybQK+drQre+ns/tKpXbNESfrhNnPLIklLbXr7MYJ6gPEd0iETGLOK+SxMjVvKb/ffmk+FEw==", + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.26.0.tgz", + "integrity": "sha512-tbhNuIxNcVb21pInl3ZSjksLCvgdZy9KwJ8brv993QtIVKJBBkYXz4q4ZbAv31GdnC+R90np23L5FbEBlthAEw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-validator-identifier": "^7.25.7", - "chalk": "^2.4.2", - "js-tokens": "^4.0.0", - "picocolors": "^1.0.0" + "@babel/template": "^7.25.9", + "@babel/types": "^7.26.0" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/highlight/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/@babel/highlight/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@babel/highlight/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/@babel/highlight/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/@babel/parser": { - "version": "7.25.8", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.8.tgz", - "integrity": "sha512-HcttkxzdPucv3nNFmfOOMfFf64KgdJVqm1KaCm25dPGMLElo9nsLvXeJECQg8UzPuBGLyTSA0ZzqCtDSzKTEoQ==", + "version": "7.26.1", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.1.tgz", + "integrity": "sha512-reoQYNiAJreZNsJzyrDNzFQ+IQ5JFiIzAHJg9bn94S3l+4++J7RsIhNMoB+lgP/9tpmiAQqspv+xfdxTSzREOw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.25.8" + "@babel/types": "^7.26.0" }, "bin": { "parser": "bin/babel-parser.js" @@ -594,9 +771,9 @@ } }, "node_modules/@babel/runtime": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.25.7.tgz", - "integrity": "sha512-FjoyLe754PMiYsFaN5C94ttGiOmBNYTf6pLr4xXHAT5uctHb092PBszndLDR5XA/jghQvn4n7JMHl7dmTgbm9w==", + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.0.tgz", + "integrity": "sha512-FDSOghenHTiToteC/QRlv2q3DhPZ/oOXTBoirfWNx1Cx3TMVcGWQtMMmQcSvb/JjpNeGzx8Pq/b4fKEJuWm1sw==", "license": "MIT", "dependencies": { "regenerator-runtime": "^0.14.0" @@ -606,32 +783,32 @@ } }, "node_modules/@babel/template": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.7.tgz", - "integrity": "sha512-wRwtAgI3bAS+JGU2upWNL9lSlDcRCqD05BZ1n3X2ONLH1WilFP6O1otQjeMK/1g0pvYcXC7b/qVUB1keofjtZA==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.9.tgz", + "integrity": "sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.25.7", - "@babel/parser": "^7.25.7", - "@babel/types": "^7.25.7" + "@babel/code-frame": "^7.25.9", + "@babel/parser": "^7.25.9", + "@babel/types": "^7.25.9" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.7.tgz", - "integrity": "sha512-jatJPT1Zjqvh/1FyJs6qAHL+Dzb7sTb+xr7Q+gM1b+1oBsMsQQ4FkVKb6dFlJvLlVssqkRzV05Jzervt9yhnzg==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.9.tgz", + "integrity": "sha512-ZCuvfwOwlz/bawvAuvcj8rrithP2/N55Tzz342AkTvq4qaWbGfmCk/tKhNaV2cthijKrPAA8SRJV5WWe7IBMJw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.25.7", - "@babel/generator": "^7.25.7", - "@babel/parser": "^7.25.7", - "@babel/template": "^7.25.7", - "@babel/types": "^7.25.7", + "@babel/code-frame": "^7.25.9", + "@babel/generator": "^7.25.9", + "@babel/parser": "^7.25.9", + "@babel/template": "^7.25.9", + "@babel/types": "^7.25.9", "debug": "^4.3.1", "globals": "^11.1.0" }, @@ -650,15 +827,14 @@ } }, "node_modules/@babel/types": { - "version": "7.25.8", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.8.tgz", - "integrity": "sha512-JWtuCu8VQsMladxVz/P4HzHUGCAwpuqacmowgXFs5XjxIgKuNjnLokQzuVjlTvIzODaDmpjT3oxcC48vyk9EWg==", + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.0.tgz", + "integrity": "sha512-Z/yiTPj+lDVnF7lWeKCIJzaIkI0vYO87dMpZ4bg4TDrFe4XXLFWL1TbXU27gBP3QccxV9mZICCrnjnYlJjXHOA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-string-parser": "^7.25.7", - "@babel/helper-validator-identifier": "^7.25.7", - "to-fast-properties": "^2.0.0" + "@babel/helper-string-parser": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -670,6 +846,7 @@ "integrity": "sha512-1rkd7G70+o9KkTn5KLmDYXihGoTaIGO9PIIN2ZB7UJxFrWw04CZHPYiMRjYsaDvVV7hP1dYNRLxSANLaBFGpog==", "dev": true, "hasInstallScript": true, + "license": "MIT OR Apache-2.0", "bin": { "biome": "bin/biome" }, @@ -699,6 +876,7 @@ "arm64" ], "dev": true, + "license": "MIT OR Apache-2.0", "optional": true, "os": [ "darwin" @@ -715,6 +893,7 @@ "x64" ], "dev": true, + "license": "MIT OR Apache-2.0", "optional": true, "os": [ "darwin" @@ -731,6 +910,7 @@ "arm64" ], "dev": true, + "license": "MIT OR Apache-2.0", "optional": true, "os": [ "linux" @@ -747,6 +927,7 @@ "arm64" ], "dev": true, + "license": "MIT OR Apache-2.0", "optional": true, "os": [ "linux" @@ -763,6 +944,7 @@ "x64" ], "dev": true, + "license": "MIT OR Apache-2.0", "optional": true, "os": [ "linux" @@ -779,6 +961,7 @@ "x64" ], "dev": true, + "license": "MIT OR Apache-2.0", "optional": true, "os": [ "linux" @@ -795,6 +978,7 @@ "arm64" ], "dev": true, + "license": "MIT OR Apache-2.0", "optional": true, "os": [ "win32" @@ -811,6 +995,7 @@ "x64" ], "dev": true, + "license": "MIT OR Apache-2.0", "optional": true, "os": [ "win32" @@ -1120,6 +1305,16 @@ "integrity": "sha512-YslZMgtJUyuMbZ+aKvfF3x1f5liK4mWNxghFRv7jqRR9C3R3fAOGTTKvxXDa2Y1s9zSbcpuO0cAxDYsc9SrXoQ==", "license": "Apache-2.0" }, + "node_modules/@emnapi/runtime": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.3.1.tgz", + "integrity": "sha512-kEBmG8KyqtxJZv+ygbEim+KCGtIq1fC22Ms3S4ziXmYKm8uyoLX0MHONVKwp+9opg390VaKRNt4a7A9NwmpNhw==", + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, "node_modules/@esbuild/aix-ppc64": { "version": "0.23.1", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.23.1.tgz", @@ -1529,25 +1724,28 @@ } }, "node_modules/@eslint-community/eslint-utils": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", - "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz", + "integrity": "sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==", "dev": true, "license": "MIT", "dependencies": { - "eslint-visitor-keys": "^3.3.0" + "eslint-visitor-keys": "^3.4.3" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, + "funding": { + "url": "https://opencollective.com/eslint" + }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "node_modules/@eslint-community/regexpp": { - "version": "4.11.1", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.1.tgz", - "integrity": "sha512-m4DVN9ZqskZoLU5GlWZadwDnYo3vAEydiUayB9widCl9ffWx2IvPnp6n3on5rJmziJSw9Bv+Z3ChDVdMwXCY8Q==", + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", + "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", "dev": true, "license": "MIT", "engines": { @@ -1675,144 +1873,505 @@ "fast-deep-equal": "^3.1.3" } }, - "node_modules/@floating-ui/core": { - "version": "1.6.8", - "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.8.tgz", - "integrity": "sha512-7XJ9cPU+yI2QeLS+FCSlqNFZJq8arvswefkZrYI1yQBbftw6FyrZOxYSh+9S7z7TpeWlRt9zJ5IhM1WIL334jA==", - "license": "MIT", - "dependencies": { - "@floating-ui/utils": "^0.2.8" + "node_modules/@floating-ui/core": { + "version": "1.6.8", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.8.tgz", + "integrity": "sha512-7XJ9cPU+yI2QeLS+FCSlqNFZJq8arvswefkZrYI1yQBbftw6FyrZOxYSh+9S7z7TpeWlRt9zJ5IhM1WIL334jA==", + "license": "MIT", + "dependencies": { + "@floating-ui/utils": "^0.2.8" + } + }, + "node_modules/@floating-ui/dom": { + "version": "1.6.12", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.12.tgz", + "integrity": "sha512-NP83c0HjokcGVEMeoStg317VD9W7eDlGK7457dMBANbKA6GJZdc7rjujdgqzTaz93jkGgc5P/jeWbaCHnMNc+w==", + "license": "MIT", + "dependencies": { + "@floating-ui/core": "^1.6.0", + "@floating-ui/utils": "^0.2.8" + } + }, + "node_modules/@floating-ui/react": { + "version": "0.26.26", + "resolved": "https://registry.npmjs.org/@floating-ui/react/-/react-0.26.26.tgz", + "integrity": "sha512-iv2BjdcyoF1j1708Z9CrGtMc9ZZvMPZnDqyB1FrSWYCi+/nlPArUO/u9QhwC4E1Pi4T0g18GZ4W702m0NDh9bw==", + "license": "MIT", + "dependencies": { + "@floating-ui/react-dom": "^2.1.2", + "@floating-ui/utils": "^0.2.8", + "tabbable": "^6.0.0" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/@floating-ui/react-dom": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.2.tgz", + "integrity": "sha512-06okr5cgPzMNBy+Ycse2A6udMi4bqwW/zgBF/rwjcNqWkyr82Mcg8b0vjX8OJpZFy/FKjJmw6wV7t44kK6kW7A==", + "license": "MIT", + "dependencies": { + "@floating-ui/dom": "^1.0.0" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/@floating-ui/utils": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.8.tgz", + "integrity": "sha512-kym7SodPp8/wloecOpcmSnWJsK7M0E5Wg8UcFA+uO4B9s5d0ywXOEro/8HM9x0rW+TljRzul/14UYz3TleT3ig==", + "license": "MIT" + }, + "node_modules/@formatjs/intl-localematcher": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/@formatjs/intl-localematcher/-/intl-localematcher-0.5.6.tgz", + "integrity": "sha512-roz1+Ba5e23AHX6KUAWmLEyTRZegM5YDuxuvkHCyK3RJddf/UXB2f+s7pOMm9ktfPGla0g+mQXOn5vsuYirnaA==", + "license": "MIT", + "dependencies": { + "tslib": "2" + } + }, + "node_modules/@headlessui/react": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@headlessui/react/-/react-2.2.0.tgz", + "integrity": "sha512-RzCEg+LXsuI7mHiSomsu/gBJSjpupm6A1qIZ5sWjd7JhARNlMiSA4kKfJpCKwU9tE+zMRterhhrP74PvfJrpXQ==", + "license": "MIT", + "dependencies": { + "@floating-ui/react": "^0.26.16", + "@react-aria/focus": "^3.17.1", + "@react-aria/interactions": "^3.21.3", + "@tanstack/react-virtual": "^3.8.1" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "react": "^18 || ^19 || ^19.0.0-rc", + "react-dom": "^18 || ^19 || ^19.0.0-rc" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", + "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", + "deprecated": "Use @eslint/config-array instead", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanwhocodes/object-schema": "^2.0.3", + "debug": "^4.3.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", + "deprecated": "Use @eslint/object-schema instead", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@iconify/types": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@iconify/types/-/types-2.0.0.tgz", + "integrity": "sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==", + "license": "MIT" + }, + "node_modules/@iconify/utils": { + "version": "2.1.33", + "resolved": "https://registry.npmjs.org/@iconify/utils/-/utils-2.1.33.tgz", + "integrity": "sha512-jP9h6v/g0BIZx0p7XGJJVtkVnydtbgTgt9mVNcGDYwaa7UhdHdI9dvoq+gKj9sijMSJKxUPEG2JyjsgXjxL7Kw==", + "license": "MIT", + "dependencies": { + "@antfu/install-pkg": "^0.4.0", + "@antfu/utils": "^0.7.10", + "@iconify/types": "^2.0.0", + "debug": "^4.3.6", + "kolorist": "^1.8.0", + "local-pkg": "^0.5.0", + "mlly": "^1.7.1" + } + }, + "node_modules/@img/sharp-darwin-arm64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.33.5.tgz", + "integrity": "sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-arm64": "1.0.4" + } + }, + "node_modules/@img/sharp-darwin-x64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.33.5.tgz", + "integrity": "sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-x64": "1.0.4" + } + }, + "node_modules/@img/sharp-libvips-darwin-arm64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.0.4.tgz", + "integrity": "sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg==", + "cpu": [ + "arm64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-darwin-x64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.0.4.tgz", + "integrity": "sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ==", + "cpu": [ + "x64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.0.5.tgz", + "integrity": "sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g==", + "cpu": [ + "arm" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.0.4.tgz", + "integrity": "sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA==", + "cpu": [ + "arm64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-s390x": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.0.4.tgz", + "integrity": "sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA==", + "cpu": [ + "s390x" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-x64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.0.4.tgz", + "integrity": "sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw==", + "cpu": [ + "x64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-arm64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.0.4.tgz", + "integrity": "sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA==", + "cpu": [ + "arm64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-x64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.0.4.tgz", + "integrity": "sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw==", + "cpu": [ + "x64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@floating-ui/dom": { - "version": "1.6.11", - "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.11.tgz", - "integrity": "sha512-qkMCxSR24v2vGkhYDo/UzxfJN3D4syqSjyuTFz6C7XcpU1pASPRieNI0Kj5VP3/503mOfYiGY891ugBX1GlABQ==", - "license": "MIT", - "dependencies": { - "@floating-ui/core": "^1.6.0", - "@floating-ui/utils": "^0.2.8" + "node_modules/@img/sharp-linux-arm": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.33.5.tgz", + "integrity": "sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ==", + "cpu": [ + "arm" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm": "1.0.5" } }, - "node_modules/@floating-ui/react": { - "version": "0.26.25", - "resolved": "https://registry.npmjs.org/@floating-ui/react/-/react-0.26.25.tgz", - "integrity": "sha512-hZOmgN0NTOzOuZxI1oIrDu3Gcl8WViIkvPMpB4xdd4QD6xAMtwgwr3VPoiyH/bLtRcS1cDnhxLSD1NsMJmwh/A==", - "license": "MIT", - "dependencies": { - "@floating-ui/react-dom": "^2.1.2", - "@floating-ui/utils": "^0.2.8", - "tabbable": "^6.0.0" + "node_modules/@img/sharp-linux-arm64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.33.5.tgz", + "integrity": "sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" }, - "peerDependencies": { - "react": ">=16.8.0", - "react-dom": ">=16.8.0" + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm64": "1.0.4" } }, - "node_modules/@floating-ui/react-dom": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.2.tgz", - "integrity": "sha512-06okr5cgPzMNBy+Ycse2A6udMi4bqwW/zgBF/rwjcNqWkyr82Mcg8b0vjX8OJpZFy/FKjJmw6wV7t44kK6kW7A==", - "license": "MIT", - "dependencies": { - "@floating-ui/dom": "^1.0.0" + "node_modules/@img/sharp-linux-s390x": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.33.5.tgz", + "integrity": "sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q==", + "cpu": [ + "s390x" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" }, - "peerDependencies": { - "react": ">=16.8.0", - "react-dom": ">=16.8.0" + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-s390x": "1.0.4" } }, - "node_modules/@floating-ui/utils": { - "version": "0.2.8", - "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.8.tgz", - "integrity": "sha512-kym7SodPp8/wloecOpcmSnWJsK7M0E5Wg8UcFA+uO4B9s5d0ywXOEro/8HM9x0rW+TljRzul/14UYz3TleT3ig==", - "license": "MIT" - }, - "node_modules/@formatjs/intl-localematcher": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/@formatjs/intl-localematcher/-/intl-localematcher-0.5.5.tgz", - "integrity": "sha512-t5tOGMgZ/i5+ALl2/offNqAQq/lfUnKLEw0mXQI4N4bqpedhrSE+fyKLpwnd22sK0dif6AV+ufQcTsKShB9J1g==", - "license": "MIT", - "dependencies": { - "tslib": "^2.7.0" + "node_modules/@img/sharp-linux-x64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.33.5.tgz", + "integrity": "sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-x64": "1.0.4" } }, - "node_modules/@headlessui/react": { - "version": "2.1.10", - "resolved": "https://registry.npmjs.org/@headlessui/react/-/react-2.1.10.tgz", - "integrity": "sha512-6mLa2fjMDAFQi+/R10B+zU3edsUk/MDtENB2zHho0lqKU1uzhAfJLUduWds4nCo8wbl3vULtC5rJfZAQ1yqIng==", - "license": "MIT", - "dependencies": { - "@floating-ui/react": "^0.26.16", - "@react-aria/focus": "^3.17.1", - "@react-aria/interactions": "^3.21.3", - "@tanstack/react-virtual": "^3.8.1" - }, + "node_modules/@img/sharp-linuxmusl-arm64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.33.5.tgz", + "integrity": "sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=10" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" }, - "peerDependencies": { - "react": "^18", - "react-dom": "^18" + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-arm64": "1.0.4" } }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.13.0", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", - "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", - "deprecated": "Use @eslint/config-array instead", - "dev": true, + "node_modules/@img/sharp-linuxmusl-x64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.33.5.tgz", + "integrity": "sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw==", + "cpu": [ + "x64" + ], "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-x64": "1.0.4" + } + }, + "node_modules/@img/sharp-wasm32": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.33.5.tgz", + "integrity": "sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg==", + "cpu": [ + "wasm32" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", + "optional": true, "dependencies": { - "@humanwhocodes/object-schema": "^2.0.3", - "debug": "^4.3.1", - "minimatch": "^3.0.5" + "@emnapi/runtime": "^1.2.0" }, "engines": { - "node": ">=10.10.0" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", - "dev": true, - "license": "Apache-2.0", + "node_modules/@img/sharp-win32-ia32": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.33.5.tgz", + "integrity": "sha512-T36PblLaTwuVJ/zw/LaH0PdZkRz5rd3SmMHX8GSmR7vtNSP5Z6bQkExdSK7xGWyxLw4sUknBuugTelgw2faBbQ==", + "cpu": [ + "ia32" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=12.22" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" + "url": "https://opencollective.com/libvips" } }, - "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", - "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", - "deprecated": "Use @eslint/object-schema instead", - "dev": true, - "license": "BSD-3-Clause" - }, - "node_modules/@iconify/types": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@iconify/types/-/types-2.0.0.tgz", - "integrity": "sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==", - "license": "MIT" - }, - "node_modules/@iconify/utils": { - "version": "2.1.33", - "resolved": "https://registry.npmjs.org/@iconify/utils/-/utils-2.1.33.tgz", - "integrity": "sha512-jP9h6v/g0BIZx0p7XGJJVtkVnydtbgTgt9mVNcGDYwaa7UhdHdI9dvoq+gKj9sijMSJKxUPEG2JyjsgXjxL7Kw==", - "license": "MIT", - "dependencies": { - "@antfu/install-pkg": "^0.4.0", - "@antfu/utils": "^0.7.10", - "@iconify/types": "^2.0.0", - "debug": "^4.3.6", - "kolorist": "^1.8.0", - "local-pkg": "^0.5.0", - "mlly": "^1.7.1" + "node_modules/@img/sharp-win32-x64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.33.5.tgz", + "integrity": "sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" } }, "node_modules/@isaacs/cliui": { @@ -1927,11 +2486,6 @@ "fs-extra": "^8.1.0" } }, - "node_modules/@manypkg/find-root/node_modules/@types/node": { - "version": "12.20.55", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.55.tgz", - "integrity": "sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==" - }, "node_modules/@manypkg/find-root/node_modules/fs-extra": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", @@ -1981,9 +2535,9 @@ } }, "node_modules/@mdx-js/mdx": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@mdx-js/mdx/-/mdx-3.0.1.tgz", - "integrity": "sha512-eIQ4QTrOWyL3LWEe/bu6Taqzq2HQvHcyTMaOrI95P2/LmJE7AsfPfgJGuFLPVqBUE1BC1rik3VIhU+s9u72arA==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@mdx-js/mdx/-/mdx-3.1.0.tgz", + "integrity": "sha512-/QxEhPAvGwbQmy1Px8F899L5Uc2KZ6JtXwlCgJmjSTBedwOZkByYcBG4GceIGPXRDsmfxhHazuS+hlOShRLeDw==", "license": "MIT", "dependencies": { "@types/estree": "^1.0.0", @@ -1992,14 +2546,15 @@ "@types/mdx": "^2.0.0", "collapse-white-space": "^2.0.0", "devlop": "^1.0.0", - "estree-util-build-jsx": "^3.0.0", "estree-util-is-identifier-name": "^3.0.0", - "estree-util-to-js": "^2.0.0", + "estree-util-scope": "^1.0.0", "estree-walker": "^3.0.0", - "hast-util-to-estree": "^3.0.0", "hast-util-to-jsx-runtime": "^2.0.0", "markdown-extensions": "^2.0.0", - "periscopic": "^3.0.0", + "recma-build-jsx": "^1.0.0", + "recma-jsx": "^1.0.0", + "recma-stringify": "^1.0.0", + "rehype-recma": "^1.0.0", "remark-mdx": "^3.0.0", "remark-parse": "^11.0.0", "remark-rehype": "^11.0.0", @@ -2016,9 +2571,9 @@ } }, "node_modules/@mdx-js/react": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-3.0.1.tgz", - "integrity": "sha512-9ZrPIU4MGf6et1m1ov3zKf+q9+deetI51zprKB1D/z3NOb+rUxxtEl3mCjW5wTGh6VhRdwPueh1oRzi6ezkA8A==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-3.1.0.tgz", + "integrity": "sha512-QjHtSaoameoalGnKDT3FoIl4+9RwyTmo9ZJGBdLOks/YOiWHoRDI3PUwEzOE7kEmGcV3AFcp9K6dYu9rEuKLAQ==", "license": "MIT", "dependencies": { "@types/mdx": "^2.0.0" @@ -2337,15 +2892,15 @@ "link": true }, "node_modules/@next/env": { - "version": "14.2.15", - "resolved": "https://registry.npmjs.org/@next/env/-/env-14.2.15.tgz", - "integrity": "sha512-S1qaj25Wru2dUpcIZMjxeMVSwkt8BK4dmWHHiBuRstcIyOsMapqT4A4jSB6onvqeygkSSmOkyny9VVx8JIGamQ==", + "version": "15.0.0", + "resolved": "https://registry.npmjs.org/@next/env/-/env-15.0.0.tgz", + "integrity": "sha512-Mcv8ZVmEgTO3bePiH/eJ7zHqQEs2gCqZ0UId2RxHmDDc7Pw6ngfSrOFlxG8XDpaex+n2G+TKPsQAf28MO+88Gw==", "license": "MIT" }, "node_modules/@next/eslint-plugin-next": { - "version": "14.2.15", - "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-14.2.15.tgz", - "integrity": "sha512-pKU0iqKRBlFB/ocOI1Ip2CkKePZpYpnw5bEItEkuZ/Nr9FQP1+p7VDWr4VfOdff4i9bFmrOaeaU1bFEyAcxiMQ==", + "version": "14.2.16", + "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-14.2.16.tgz", + "integrity": "sha512-noORwKUMkKc96MWjTOwrsUCjky0oFegHbeJ1yEnQBGbMHAaTEIgLZIIfsYF0x3a06PiS+2TXppfifR+O6VWslg==", "dev": true, "license": "MIT", "dependencies": { @@ -2438,9 +2993,9 @@ } }, "node_modules/@next/swc-darwin-arm64": { - "version": "14.2.15", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.2.15.tgz", - "integrity": "sha512-Rvh7KU9hOUBnZ9TJ28n2Oa7dD9cvDBKua9IKx7cfQQ0GoYUwg9ig31O2oMwH3wm+pE3IkAQ67ZobPfEgurPZIA==", + "version": "15.0.0", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-15.0.0.tgz", + "integrity": "sha512-Gjgs3N7cFa40a9QT9AEHnuGKq69/bvIOn0SLGDV+ordq07QOP4k1GDOVedMHEjVeqy1HBLkL8rXnNTuMZIv79A==", "cpu": [ "arm64" ], @@ -2454,9 +3009,9 @@ } }, "node_modules/@next/swc-darwin-x64": { - "version": "14.2.15", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.2.15.tgz", - "integrity": "sha512-5TGyjFcf8ampZP3e+FyCax5zFVHi+Oe7sZyaKOngsqyaNEpOgkKB3sqmymkZfowy3ufGA/tUgDPPxpQx931lHg==", + "version": "15.0.0", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-15.0.0.tgz", + "integrity": "sha512-BUtTvY5u9s5berAuOEydAUlVMjnl6ZjXS+xVrMt317mglYZ2XXjY8YRDCaz9vYMjBNPXH8Gh75Cew5CMdVbWTw==", "cpu": [ "x64" ], @@ -2470,9 +3025,9 @@ } }, "node_modules/@next/swc-linux-arm64-gnu": { - "version": "14.2.15", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.2.15.tgz", - "integrity": "sha512-3Bwv4oc08ONiQ3FiOLKT72Q+ndEMyLNsc/D3qnLMbtUYTQAmkx9E/JRu0DBpHxNddBmNT5hxz1mYBphJ3mfrrw==", + "version": "15.0.0", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-15.0.0.tgz", + "integrity": "sha512-sbCoEpuWUBpYoLSgYrk0CkBv8RFv4ZlPxbwqRHr/BWDBJppTBtF53EvsntlfzQJ9fosYX12xnS6ltxYYwsMBjg==", "cpu": [ "arm64" ], @@ -2486,9 +3041,9 @@ } }, "node_modules/@next/swc-linux-arm64-musl": { - "version": "14.2.15", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.2.15.tgz", - "integrity": "sha512-k5xf/tg1FBv/M4CMd8S+JL3uV9BnnRmoe7F+GWC3DxkTCD9aewFRH1s5rJ1zkzDa+Do4zyN8qD0N8c84Hu96FQ==", + "version": "15.0.0", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-15.0.0.tgz", + "integrity": "sha512-JAw84qfL81aQCirXKP4VkgmhiDpXJupGjt8ITUkHrOVlBd+3h5kjfPva5M0tH2F9KKSgJQHEo3F5S5tDH9h2ww==", "cpu": [ "arm64" ], @@ -2502,9 +3057,9 @@ } }, "node_modules/@next/swc-linux-x64-gnu": { - "version": "14.2.15", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.2.15.tgz", - "integrity": "sha512-kE6q38hbrRbKEkkVn62reLXhThLRh6/TvgSP56GkFNhU22TbIrQDEMrO7j0IcQHcew2wfykq8lZyHFabz0oBrA==", + "version": "15.0.0", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-15.0.0.tgz", + "integrity": "sha512-r5Smd03PfxrGKMewdRf2RVNA1CU5l2rRlvZLQYZSv7FUsXD5bKEcOZ/6/98aqRwL7diXOwD8TCWJk1NbhATQHg==", "cpu": [ "x64" ], @@ -2518,9 +3073,9 @@ } }, "node_modules/@next/swc-linux-x64-musl": { - "version": "14.2.15", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.2.15.tgz", - "integrity": "sha512-PZ5YE9ouy/IdO7QVJeIcyLn/Rc4ml9M2G4y3kCM9MNf1YKvFY4heg3pVa/jQbMro+tP6yc4G2o9LjAz1zxD7tQ==", + "version": "15.0.0", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-15.0.0.tgz", + "integrity": "sha512-fM6qocafz4Xjhh79CuoQNeGPhDHGBBUbdVtgNFJOUM8Ih5ZpaDZlTvqvqsh5IoO06CGomxurEGqGz/4eR/FaMQ==", "cpu": [ "x64" ], @@ -2534,9 +3089,9 @@ } }, "node_modules/@next/swc-win32-arm64-msvc": { - "version": "14.2.15", - "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.2.15.tgz", - "integrity": "sha512-2raR16703kBvYEQD9HNLyb0/394yfqzmIeyp2nDzcPV4yPjqNUG3ohX6jX00WryXz6s1FXpVhsCo3i+g4RUX+g==", + "version": "15.0.0", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-15.0.0.tgz", + "integrity": "sha512-ZOd7c/Lz1lv7qP/KzR513XEa7QzW5/P0AH3A5eR1+Z/KmDOvMucht0AozccPc0TqhdV1xaXmC0Fdx0hoNzk6ng==", "cpu": [ "arm64" ], @@ -2550,9 +3105,9 @@ } }, "node_modules/@next/swc-win32-ia32-msvc": { - "version": "14.2.15", - "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.2.15.tgz", - "integrity": "sha512-fyTE8cklgkyR1p03kJa5zXEaZ9El+kDNM5A+66+8evQS5e/6v0Gk28LqA0Jet8gKSOyP+OTm/tJHzMlGdQerdQ==", + "version": "14.2.16", + "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.2.16.tgz", + "integrity": "sha512-jhPl3nN0oKEshJBNDAo0etGMzv0j3q3VYorTSFqH1o3rwv1MQRdor27u1zhkgsHPNeY1jxcgyx1ZsCkDD1IHgg==", "cpu": [ "ia32" ], @@ -2566,9 +3121,9 @@ } }, "node_modules/@next/swc-win32-x64-msvc": { - "version": "14.2.15", - "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.2.15.tgz", - "integrity": "sha512-SzqGbsLsP9OwKNUG9nekShTwhj6JSB9ZLMWQ8g1gG6hdE5gQLncbnbymrwy2yVmH9nikSLYRYxYMFu78Ggp7/g==", + "version": "15.0.0", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-15.0.0.tgz", + "integrity": "sha512-2RVWcLtsqg4LtaoJ3j7RoKpnWHgcrz5XvuUGE7vBYU2i6M2XeD9Y8RlLaF770LEIScrrl8MdWsp6odtC6sZccg==", "cpu": [ "x64" ], @@ -2689,6 +3244,7 @@ "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.48.2.tgz", "integrity": "sha512-54w1xCWfXuax7dz4W2M9uw0gDyh+ti/0K/MxcCUxChFh37kkdxPdfZDw5QBbuPUJHr1CiHJ1hXgSs+GgeQc5Zw==", "devOptional": true, + "license": "Apache-2.0", "dependencies": { "playwright": "1.48.2" }, @@ -2699,6 +3255,53 @@ "node": ">=18" } }, + "node_modules/@playwright/test/node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "peer": true, + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/@playwright/test/node_modules/playwright": { + "version": "1.48.2", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.48.2.tgz", + "integrity": "sha512-NjYvYgp4BPmiwfe31j4gHLa3J7bD2WiBz8Lk2RoSsmX38SVIARZ18VYjxLjAcDsAhA+F4iSEXTSGgjua0rrlgQ==", + "devOptional": true, + "license": "Apache-2.0", + "dependencies": { + "playwright-core": "1.48.2" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "fsevents": "2.3.2" + } + }, + "node_modules/@playwright/test/node_modules/playwright-core": { + "version": "1.48.2", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.48.2.tgz", + "integrity": "sha512-sjjw+qrLFlriJo64du+EK0kJgZzoQPsabGF4lBvsid+3CNIZIYLgnMj9V6JY5VhM2Peh20DJWIVpVljLLnlawA==", + "devOptional": true, + "license": "Apache-2.0", + "bin": { + "playwright-core": "cli.js" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/@pm2/agent": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/@pm2/agent/-/agent-2.0.4.tgz", @@ -3049,6 +3652,10 @@ "resolved": "apps/cache-testing", "link": true }, + "node_modules/@repo/cache-testing-15-app": { + "resolved": "apps/cache-testing-15-app", + "link": true + }, "node_modules/@repo/eslint-config": { "resolved": "internal/eslint-config", "link": true @@ -3070,9 +3677,9 @@ "link": true }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.24.0.tgz", - "integrity": "sha512-Q6HJd7Y6xdB48x8ZNVDOqsbh2uByBhgK8PiQgPhwkIw/HC/YX5Ghq2mQY5sRMZWHb3VsFkWooUVOZHKr7DmDIA==", + "version": "4.24.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.24.3.tgz", + "integrity": "sha512-ufb2CH2KfBWPJok95frEZZ82LtDl0A6QKTa8MoM+cWwDZvVGl5/jNb79pIhRvAalUu+7LD91VYR0nwRD799HkQ==", "cpu": [ "arm" ], @@ -3084,9 +3691,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.24.0.tgz", - "integrity": "sha512-ijLnS1qFId8xhKjT81uBHuuJp2lU4x2yxa4ctFPtG+MqEE6+C5f/+X/bStmxapgmwLwiL3ih122xv8kVARNAZA==", + "version": "4.24.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.24.3.tgz", + "integrity": "sha512-iAHpft/eQk9vkWIV5t22V77d90CRofgR2006UiCjHcHJFVI1E0oBkQIAbz+pLtthFw3hWEmVB4ilxGyBf48i2Q==", "cpu": [ "arm64" ], @@ -3098,9 +3705,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.24.0.tgz", - "integrity": "sha512-bIv+X9xeSs1XCk6DVvkO+S/z8/2AMt/2lMqdQbMrmVpgFvXlmde9mLcbQpztXm1tajC3raFDqegsH18HQPMYtA==", + "version": "4.24.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.24.3.tgz", + "integrity": "sha512-QPW2YmkWLlvqmOa2OwrfqLJqkHm7kJCIMq9kOz40Zo9Ipi40kf9ONG5Sz76zszrmIZZ4hgRIkez69YnTHgEz1w==", "cpu": [ "arm64" ], @@ -3112,9 +3719,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.24.0.tgz", - "integrity": "sha512-X6/nOwoFN7RT2svEQWUsW/5C/fYMBe4fnLK9DQk4SX4mgVBiTA9h64kjUYPvGQ0F/9xwJ5U5UfTbl6BEjaQdBQ==", + "version": "4.24.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.24.3.tgz", + "integrity": "sha512-KO0pN5x3+uZm1ZXeIfDqwcvnQ9UEGN8JX5ufhmgH5Lz4ujjZMAnxQygZAVGemFWn+ZZC0FQopruV4lqmGMshow==", "cpu": [ "x64" ], @@ -3125,10 +3732,38 @@ "darwin" ] }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.24.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.24.3.tgz", + "integrity": "sha512-CsC+ZdIiZCZbBI+aRlWpYJMSWvVssPuWqrDy/zi9YfnatKKSLFCe6fjna1grHuo/nVaHG+kiglpRhyBQYRTK4A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.24.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.24.3.tgz", + "integrity": "sha512-F0nqiLThcfKvRQhZEzMIXOQG4EeX61im61VYL1jo4eBxv4aZRmpin6crnBJQ/nWnCsjH5F6J3W6Stdm0mBNqBg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.24.0.tgz", - "integrity": "sha512-0KXvIJQMOImLCVCz9uvvdPgfyWo93aHHp8ui3FrtOP57svqrF/roSSR5pjqL2hcMp0ljeGlU4q9o/rQaAQ3AYA==", + "version": "4.24.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.24.3.tgz", + "integrity": "sha512-KRSFHyE/RdxQ1CSeOIBVIAxStFC/hnBgVcaiCkQaVC+EYDtTe4X7z5tBkFyRoBgUGtB6Xg6t9t2kulnX6wJc6A==", "cpu": [ "arm" ], @@ -3140,9 +3775,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.24.0.tgz", - "integrity": "sha512-it2BW6kKFVh8xk/BnHfakEeoLPv8STIISekpoF+nBgWM4d55CZKc7T4Dx1pEbTnYm/xEKMgy1MNtYuoA8RFIWw==", + "version": "4.24.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.24.3.tgz", + "integrity": "sha512-h6Q8MT+e05zP5BxEKz0vi0DhthLdrNEnspdLzkoFqGwnmOzakEHSlXfVyA4HJ322QtFy7biUAVFPvIDEDQa6rw==", "cpu": [ "arm" ], @@ -3154,9 +3789,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.24.0.tgz", - "integrity": "sha512-i0xTLXjqap2eRfulFVlSnM5dEbTVque/3Pi4g2y7cxrs7+a9De42z4XxKLYJ7+OhE3IgxvfQM7vQc43bwTgPwA==", + "version": "4.24.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.24.3.tgz", + "integrity": "sha512-fKElSyXhXIJ9pqiYRqisfirIo2Z5pTTve5K438URf08fsypXrEkVmShkSfM8GJ1aUyvjakT+fn2W7Czlpd/0FQ==", "cpu": [ "arm64" ], @@ -3168,9 +3803,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.24.0.tgz", - "integrity": "sha512-9E6MKUJhDuDh604Qco5yP/3qn3y7SLXYuiC0Rpr89aMScS2UAmK1wHP2b7KAa1nSjWJc/f/Lc0Wl1L47qjiyQw==", + "version": "4.24.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.24.3.tgz", + "integrity": "sha512-YlddZSUk8G0px9/+V9PVilVDC6ydMz7WquxozToozSnfFK6wa6ne1ATUjUvjin09jp34p84milxlY5ikueoenw==", "cpu": [ "arm64" ], @@ -3182,9 +3817,9 @@ ] }, "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.24.0.tgz", - "integrity": "sha512-2XFFPJ2XMEiF5Zi2EBf4h73oR1V/lycirxZxHZNc93SqDN/IWhYYSYj8I9381ikUFXZrz2v7r2tOVk2NBwxrWw==", + "version": "4.24.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.24.3.tgz", + "integrity": "sha512-yNaWw+GAO8JjVx3s3cMeG5Esz1cKVzz8PkTJSfYzE5u7A+NvGmbVFEHP+BikTIyYWuz0+DX9kaA3pH9Sqxp69g==", "cpu": [ "ppc64" ], @@ -3196,9 +3831,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.24.0.tgz", - "integrity": "sha512-M3Dg4hlwuntUCdzU7KjYqbbd+BLq3JMAOhCKdBE3TcMGMZbKkDdJ5ivNdehOssMCIokNHFOsv7DO4rlEOfyKpg==", + "version": "4.24.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.24.3.tgz", + "integrity": "sha512-lWKNQfsbpv14ZCtM/HkjCTm4oWTKTfxPmr7iPfp3AHSqyoTz5AgLemYkWLwOBWc+XxBbrU9SCokZP0WlBZM9lA==", "cpu": [ "riscv64" ], @@ -3210,9 +3845,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.24.0.tgz", - "integrity": "sha512-mjBaoo4ocxJppTorZVKWFpy1bfFj9FeCMJqzlMQGjpNPY9JwQi7OuS1axzNIk0nMX6jSgy6ZURDZ2w0QW6D56g==", + "version": "4.24.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.24.3.tgz", + "integrity": "sha512-HoojGXTC2CgCcq0Woc/dn12wQUlkNyfH0I1ABK4Ni9YXyFQa86Fkt2Q0nqgLfbhkyfQ6003i3qQk9pLh/SpAYw==", "cpu": [ "s390x" ], @@ -3224,9 +3859,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.24.0.tgz", - "integrity": "sha512-ZXFk7M72R0YYFN5q13niV0B7G8/5dcQ9JDp8keJSfr3GoZeXEoMHP/HlvqROA3OMbMdfr19IjCeNAnPUG93b6A==", + "version": "4.24.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.24.3.tgz", + "integrity": "sha512-mnEOh4iE4USSccBOtcrjF5nj+5/zm6NcNhbSEfR3Ot0pxBwvEn5QVUXcuOwwPkapDtGZ6pT02xLoPaNv06w7KQ==", "cpu": [ "x64" ], @@ -3238,9 +3873,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.24.0.tgz", - "integrity": "sha512-w1i+L7kAXZNdYl+vFvzSZy8Y1arS7vMgIy8wusXJzRrPyof5LAb02KGr1PD2EkRcl73kHulIID0M501lN+vobQ==", + "version": "4.24.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.24.3.tgz", + "integrity": "sha512-rMTzawBPimBQkG9NKpNHvquIUTQPzrnPxPbCY1Xt+mFkW7pshvyIS5kYgcf74goxXOQk0CP3EoOC1zcEezKXhw==", "cpu": [ "x64" ], @@ -3252,9 +3887,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.24.0.tgz", - "integrity": "sha512-VXBrnPWgBpVDCVY6XF3LEW0pOU51KbaHhccHw6AS6vBWIC60eqsH19DAeeObl+g8nKAz04QFdl/Cefta0xQtUQ==", + "version": "4.24.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.24.3.tgz", + "integrity": "sha512-2lg1CE305xNvnH3SyiKwPVsTVLCg4TmNCF1z7PSHX2uZY2VbUpdkgAllVoISD7JO7zu+YynpWNSKAtOrX3AiuA==", "cpu": [ "arm64" ], @@ -3266,9 +3901,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.24.0.tgz", - "integrity": "sha512-xrNcGDU0OxVcPTH/8n/ShH4UevZxKIO6HJFK0e15XItZP2UcaiLFd5kiX7hJnqCbSztUF8Qot+JWBC/QXRPYWQ==", + "version": "4.24.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.24.3.tgz", + "integrity": "sha512-9SjYp1sPyxJsPWuhOCX6F4jUMXGbVVd5obVpoVEi8ClZqo52ViZewA6eFz85y8ezuOA+uJMP5A5zo6Oz4S5rVQ==", "cpu": [ "ia32" ], @@ -3280,9 +3915,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.24.0.tgz", - "integrity": "sha512-fbMkAF7fufku0N2dE5TBXcNlg0pt0cJue4xBRE2Qc5Vqikxr4VCgKj/ht6SMdFcOacVA9rqF70APJ8RN/4vMJw==", + "version": "4.24.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.24.3.tgz", + "integrity": "sha512-HGZgRFFYrMrP3TJlq58nR1xy8zHKId25vhmm5S9jETEfDf6xybPxsavFTJaufe2zgOGYJBskGlj49CwtEuFhWQ==", "cpu": [ "x64" ], @@ -3308,55 +3943,55 @@ "license": "MIT" }, "node_modules/@shikijs/core": { - "version": "1.22.0", - "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-1.22.0.tgz", - "integrity": "sha512-S8sMe4q71TJAW+qG93s5VaiihujRK6rqDFqBnxqvga/3LvqHEnxqBIOPkt//IdXVtHkQWKu4nOQNk0uBGicU7Q==", + "version": "1.22.2", + "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-1.22.2.tgz", + "integrity": "sha512-bvIQcd8BEeR1yFvOYv6HDiyta2FFVePbzeowf5pPS1avczrPK+cjmaxxh0nx5QzbON7+Sv0sQfQVciO7bN72sg==", "license": "MIT", "dependencies": { - "@shikijs/engine-javascript": "1.22.0", - "@shikijs/engine-oniguruma": "1.22.0", - "@shikijs/types": "1.22.0", + "@shikijs/engine-javascript": "1.22.2", + "@shikijs/engine-oniguruma": "1.22.2", + "@shikijs/types": "1.22.2", "@shikijs/vscode-textmate": "^9.3.0", "@types/hast": "^3.0.4", "hast-util-to-html": "^9.0.3" } }, "node_modules/@shikijs/engine-javascript": { - "version": "1.22.0", - "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-1.22.0.tgz", - "integrity": "sha512-AeEtF4Gcck2dwBqCFUKYfsCq0s+eEbCEbkUuFou53NZ0sTGnJnJ/05KHQFZxpii5HMXbocV9URYVowOP2wH5kw==", + "version": "1.22.2", + "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-1.22.2.tgz", + "integrity": "sha512-iOvql09ql6m+3d1vtvP8fLCVCK7BQD1pJFmHIECsujB0V32BJ0Ab6hxk1ewVSMFA58FI0pR2Had9BKZdyQrxTw==", "license": "MIT", "dependencies": { - "@shikijs/types": "1.22.0", + "@shikijs/types": "1.22.2", "@shikijs/vscode-textmate": "^9.3.0", "oniguruma-to-js": "0.4.3" } }, "node_modules/@shikijs/engine-oniguruma": { - "version": "1.22.0", - "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-1.22.0.tgz", - "integrity": "sha512-5iBVjhu/DYs1HB0BKsRRFipRrD7rqjxlWTj4F2Pf+nQSPqc3kcyqFFeZXnBMzDf0HdqaFVvhDRAGiYNvyLP+Mw==", + "version": "1.22.2", + "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-1.22.2.tgz", + "integrity": "sha512-GIZPAGzQOy56mGvWMoZRPggn0dTlBf1gutV5TdceLCZlFNqWmuc7u+CzD0Gd9vQUTgLbrt0KLzz6FNprqYAxlA==", "license": "MIT", "dependencies": { - "@shikijs/types": "1.22.0", + "@shikijs/types": "1.22.2", "@shikijs/vscode-textmate": "^9.3.0" } }, "node_modules/@shikijs/twoslash": { - "version": "1.22.0", - "resolved": "https://registry.npmjs.org/@shikijs/twoslash/-/twoslash-1.22.0.tgz", - "integrity": "sha512-r5F/x4GTh18XzhAREehgT9lCDFZlISBSIsOFZQQaqjiOLG81PIqJN1I1D6XY58UN9OJt+3mffuKq19K4FOJKJA==", + "version": "1.22.2", + "resolved": "https://registry.npmjs.org/@shikijs/twoslash/-/twoslash-1.22.2.tgz", + "integrity": "sha512-4R3A7aH/toZgtlveXHKk01nIsvn8hjAfPJ1aT550zcV4qK6vK/tfaEyYtaljOaY1wig2l5+8sKjNSEz3PcSiEw==", "license": "MIT", "dependencies": { - "@shikijs/core": "1.22.0", - "@shikijs/types": "1.22.0", + "@shikijs/core": "1.22.2", + "@shikijs/types": "1.22.2", "twoslash": "^0.2.12" } }, "node_modules/@shikijs/types": { - "version": "1.22.0", - "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-1.22.0.tgz", - "integrity": "sha512-Fw/Nr7FGFhlQqHfxzZY8Cwtwk5E9nKDUgeLjZgt3UuhcM3yJR9xj3ZGNravZZok8XmEZMiYkSMTPlPkULB8nww==", + "version": "1.22.2", + "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-1.22.2.tgz", + "integrity": "sha512-NCWDa6LGZqTuzjsGfXOBWfjS/fDIbDdmVDug+7ykVe1IKT4c1gakrvlfFYp5NhAXH/lyqLM8wsAPo5wNy73Feg==", "license": "MIT", "dependencies": { "@shikijs/vscode-textmate": "^9.3.0", @@ -3376,12 +4011,11 @@ "license": "Apache-2.0" }, "node_modules/@swc/helpers": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.5.tgz", - "integrity": "sha512-KGYxvIOXcceOAbEk4bi/dVLEK9z8sZ0uBB3Il5b1rhfClSpcX0yfRO0KmTkqR2cnQDymwLB+25ZyMzICg/cm/A==", + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.13.tgz", + "integrity": "sha512-UoKGxQ3r5kYI9dALKJapMmuK+1zWM/H17Z1+iwnNmzcJRnfFuevZs375TA5rW31pu4BS4NoSy1fRsexDXfWn5w==", "license": "Apache-2.0", "dependencies": { - "@swc/counter": "^0.1.3", "tslib": "^2.4.0" } }, @@ -3426,9 +4060,9 @@ } }, "node_modules/@theguild/remark-npm2yarn": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@theguild/remark-npm2yarn/-/remark-npm2yarn-0.3.2.tgz", - "integrity": "sha512-H9T/GOuS/+4H7AY1cfD5DJIIIcGIIw1zMCB8OeTgXk7azJULsnuOurZ/CR54rvuTD+Krx0MVQccaUCvCWfP+vw==", + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@theguild/remark-npm2yarn/-/remark-npm2yarn-0.3.3.tgz", + "integrity": "sha512-ma6DvR03gdbvwqfKx1omqhg9May/VYGdMHvTzB4VuxkyS7KzfZ/lzrj43hmcsggpMje0x7SADA/pcMph0ejRnA==", "license": "MIT", "dependencies": { "npm-to-yarn": "^3.0.0", @@ -3546,13 +4180,10 @@ } }, "node_modules/@types/node": { - "version": "22.8.4", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.8.4.tgz", - "integrity": "sha512-SpNNxkftTJOPk0oN+y2bIqurEXHTA2AOZ3EJDDKeJ5VzkvvORSvmQXGQarcOzWV1ac7DCaPBEdMDxBsM+d8jWw==", - "dev": true, - "dependencies": { - "undici-types": "~6.19.8" - } + "version": "12.20.55", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.55.tgz", + "integrity": "sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==", + "license": "MIT" }, "node_modules/@types/normalize-package-data": { "version": "2.4.4", @@ -3571,6 +4202,7 @@ "version": "18.3.12", "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.12.tgz", "integrity": "sha512-D2wOSq/d6Agt28q7rSI3jhU7G6aiuzljDGZ2hTZHIkrTLUI+AF3WMeKkEZ9nN2fkBAlcktT6vcZjDFiIhMYEQw==", + "license": "MIT", "dependencies": { "@types/prop-types": "*", "csstype": "^3.0.2" @@ -3953,10 +4585,20 @@ "node": ">= 0.6" } }, + "node_modules/accepts/node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/acorn": { - "version": "8.13.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.13.0.tgz", - "integrity": "sha512-8zSiw54Oxrdym50NlZ9sUusyO1Z1ZchgRLWRaK6c86XJFClyCgFKetdowBg5bKxyp/u+CDBJG4Mpp0m3HLZl9w==", + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", + "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", "license": "MIT", "bin": { "acorn": "bin/acorn" @@ -4168,9 +4810,10 @@ "license": "MIT" }, "node_modules/arg": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/arg/-/arg-1.0.0.tgz", - "integrity": "sha512-Wk7TEzl1KqvTGs/uyhmHO/3XLd3t1UeU4IstvPXVzGPM522cTjqjNZ99esCkcL52sjqjo8e8CTBcWhkxvGzoAw==", + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", + "dev": true, "license": "MIT" }, "node_modules/argparse": { @@ -4183,13 +4826,13 @@ } }, "node_modules/aria-query": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.1.3.tgz", - "integrity": "sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==", + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz", + "integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==", "dev": true, "license": "Apache-2.0", - "dependencies": { - "deep-equal": "^2.0.5" + "engines": { + "node": ">= 0.4" } }, "node_modules/array-buffer-byte-length": { @@ -4447,9 +5090,9 @@ } }, "node_modules/axe-core": { - "version": "4.10.1", - "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.10.1.tgz", - "integrity": "sha512-qPC9o+kD8Tir0lzNGLeghbOrWMr3ZJpaRlCIb6Uobt/7N4FiEDvqUMnxzCHRHmg8vOg14kr5gVNyScRmbMaJ9g==", + "version": "4.10.2", + "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.10.2.tgz", + "integrity": "sha512-RE3mdQ7P3FRSe7eqCWoeQ/Z9QXrtniSjp1wUjt5nRC3WIpz5rSCve6o3fsZ2aCpJtrZjSZgjwXAoTO5k4tEI0w==", "dev": true, "license": "MPL-2.0", "engines": { @@ -4655,9 +5298,9 @@ } }, "node_modules/browserslist": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.0.tgz", - "integrity": "sha512-Rmb62sR1Zpjql25eSanFGEhAxcFwfA1K0GuQcLoaJBAcENegrQut3hYdhXFF1obQfiDyqIW/cLM5HSJ/9k884A==", + "version": "4.24.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.2.tgz", + "integrity": "sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg==", "dev": true, "funding": [ { @@ -4675,10 +5318,10 @@ ], "license": "MIT", "dependencies": { - "caniuse-lite": "^1.0.30001663", - "electron-to-chromium": "^1.5.28", + "caniuse-lite": "^1.0.30001669", + "electron-to-chromium": "^1.5.41", "node-releases": "^2.0.18", - "update-browserslist-db": "^1.1.0" + "update-browserslist-db": "^1.1.1" }, "bin": { "browserslist": "cli.js" @@ -4823,9 +5466,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001669", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001669.tgz", - "integrity": "sha512-DlWzFDJqstqtIVx1zeSpIMLjunf5SmwOw0N2Ck/QSQdS8PLS4+9HrLaYei4w8BIAL7IB/UEDu889d8vhCTPA0w==", + "version": "1.0.30001675", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001675.tgz", + "integrity": "sha512-/wV1bQwPrkLiQMjaJF5yUMVM/VdRPOCU8QZ+PmG6uW6DvYSrNY1bpwHI/3mOcUosLaJCzYDi5o91IQB51ft6cg==", "funding": [ { "type": "opencollective", @@ -5086,16 +5729,21 @@ "license": "MIT" }, "node_modules/clipboardy": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/clipboardy/-/clipboardy-1.2.2.tgz", - "integrity": "sha512-16KrBOV7bHmHdxcQiCvfUFYVFyEah4FI8vYT1Fr7CGSA4G+xBWMEfUEQJS1hxeHGtI9ju1Bzs9uXSbj5HZKArw==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/clipboardy/-/clipboardy-3.0.0.tgz", + "integrity": "sha512-Su+uU5sr1jkUy1sGRpLKjKrvEOVXgSgiSInwa/qeID6aJ07yh+5NWc3h2QfjHjBnfX4LhtFcuAWKUsJ3r+fjbg==", + "dev": true, "license": "MIT", "dependencies": { - "arch": "^2.1.0", - "execa": "^0.8.0" + "arch": "^2.2.0", + "execa": "^5.1.1", + "is-wsl": "^2.2.0" }, "engines": { - "node": ">=4" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/clsx": { @@ -5126,11 +5774,25 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/color": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz", + "integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==", + "license": "MIT", + "optional": true, + "dependencies": { + "color-convert": "^2.0.1", + "color-string": "^1.9.0" + }, + "engines": { + "node": ">=12.5.0" + } + }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "color-name": "~1.1.4" @@ -5143,9 +5805,20 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true, + "devOptional": true, "license": "MIT" }, + "node_modules/color-string": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", + "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", + "license": "MIT", + "optional": true, + "dependencies": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } + }, "node_modules/colorette": { "version": "2.0.20", "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", @@ -5287,12 +5960,12 @@ "license": "MIT" }, "node_modules/cookie": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", - "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.0.1.tgz", + "integrity": "sha512-Xd8lFX4LM9QEEwxQpF9J9NTUh8pmdJO0cyRJhFiDoLTk2eH8FXlRv2IFGYVadZpqI3j8fhNrSdKCeYPxiAhLXw==", "license": "MIT", "engines": { - "node": ">= 0.6" + "node": ">=18" } }, "node_modules/core-js-compat": { @@ -5354,9 +6027,9 @@ "license": "MIT" }, "node_modules/cytoscape": { - "version": "3.30.2", - "resolved": "https://registry.npmjs.org/cytoscape/-/cytoscape-3.30.2.tgz", - "integrity": "sha512-oICxQsjW8uSaRmn4UK/jkczKOqTrVqt5/1WL0POiJUT2EKNc9STM4hYFHv917yu55aTBMFNRzymlJhVAiWPCxw==", + "version": "3.30.3", + "resolved": "https://registry.npmjs.org/cytoscape/-/cytoscape-3.30.3.tgz", + "integrity": "sha512-HncJ9gGJbVtw7YXtIs3+6YAFSSiKsom0amWc33Z7QbylbY2JGMrA0yz4EwrdTScZxnwclXeEZHzO5pxoy0ZE4g==", "license": "MIT", "engines": { "node": ">=0.10" @@ -5990,39 +6663,6 @@ "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/deep-equal": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.3.tgz", - "integrity": "sha512-ZIwpnevOurS8bpT4192sqAowWM76JDKSHYzMLty3BZGSswgq6pBaH3DhCSW5xVAZICZyKdOBPjwww5wfgT/6PA==", - "dev": true, - "license": "MIT", - "dependencies": { - "array-buffer-byte-length": "^1.0.0", - "call-bind": "^1.0.5", - "es-get-iterator": "^1.1.3", - "get-intrinsic": "^1.2.2", - "is-arguments": "^1.1.1", - "is-array-buffer": "^3.0.2", - "is-date-object": "^1.0.5", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", - "isarray": "^2.0.5", - "object-is": "^1.1.5", - "object-keys": "^1.1.1", - "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.5.1", - "side-channel": "^1.0.4", - "which-boxed-primitive": "^1.0.2", - "which-collection": "^1.0.1", - "which-typed-array": "^1.1.13" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/deep-extend": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", @@ -6127,6 +6767,16 @@ "node": ">=8" } }, + "node_modules/detect-libc": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz", + "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==", + "license": "Apache-2.0", + "optional": true, + "engines": { + "node": ">=8" + } + }, "node_modules/detect-newline": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-4.0.1.tgz", @@ -6231,9 +6881,9 @@ "license": "MIT" }, "node_modules/electron-to-chromium": { - "version": "1.5.41", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.41.tgz", - "integrity": "sha512-dfdv/2xNjX0P8Vzme4cfzHqnPm5xsZXwsolTYr0eyW18IUmNyG08vL+fttvinTfhKfIKdRoqkDIC9e9iWQCNYQ==", + "version": "1.5.49", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.49.tgz", + "integrity": "sha512-ZXfs1Of8fDb6z7WEYZjXpgIRF6MEu8JdeGA0A40aZq6OQbS+eJpnnV49epZRna2DU/YsEjSQuGtQPPtvt6J65A==", "dev": true, "license": "ISC" }, @@ -6303,6 +6953,13 @@ "is-arrayish": "^0.2.1" } }, + "node_modules/error-ex/node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true, + "license": "MIT" + }, "node_modules/es-abstract": { "version": "1.23.3", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz", @@ -6387,27 +7044,6 @@ "node": ">= 0.4" } }, - "node_modules/es-get-iterator": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz", - "integrity": "sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.3", - "has-symbols": "^1.0.3", - "is-arguments": "^1.1.1", - "is-map": "^2.0.2", - "is-set": "^2.0.2", - "is-string": "^1.0.7", - "isarray": "^2.0.5", - "stop-iteration-iterator": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/es-iterator-helpers": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.1.0.tgz", @@ -6490,6 +7126,38 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/esast-util-from-estree": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/esast-util-from-estree/-/esast-util-from-estree-2.0.0.tgz", + "integrity": "sha512-4CyanoAudUSBAn5K13H4JhsMH6L9ZP7XbLVe/dKybkxMO7eDyLsT8UHl9TRNrU2Gr9nz+FovfSIjuXWJ81uVwQ==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "devlop": "^1.0.0", + "estree-util-visit": "^2.0.0", + "unist-util-position-from-estree": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/esast-util-from-js": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/esast-util-from-js/-/esast-util-from-js-2.0.1.tgz", + "integrity": "sha512-8Ja+rNJ0Lt56Pcf3TAmpBZjmx8ZcK5Ts4cAzIOjsjevg9oSXJnl6SUQ2EevU8tv3h6ZLWmoKL5H4fgWvdvfETw==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "acorn": "^8.0.0", + "esast-util-from-estree": "^2.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/esbuild": { "version": "0.23.1", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.23.1.tgz", @@ -6661,6 +7329,7 @@ "resolved": "https://registry.npmjs.org/eslint-config-turbo/-/eslint-config-turbo-2.2.3.tgz", "integrity": "sha512-/zwNU+G2w0HszXzWILdl6/Catt86ejUG7vsFSdpnFzFAAUbbT2TxgoCFvC1fKtm6+SkQsXwkRRe9tFz0aMftpg==", "dev": true, + "license": "MIT", "dependencies": { "eslint-plugin-turbo": "2.2.3" }, @@ -6739,6 +7408,36 @@ } } }, + "node_modules/eslint-import-resolver-typescript/node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/eslint-import-resolver-typescript/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/eslint-module-utils": { "version": "2.12.0", "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.12.0.tgz", @@ -7020,13 +7719,13 @@ } }, "node_modules/eslint-plugin-jsx-a11y": { - "version": "6.10.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.10.0.tgz", - "integrity": "sha512-ySOHvXX8eSN6zz8Bywacm7CvGNhUtdjvqfQDVe6020TUK34Cywkw7m0KsCCk1Qtm9G1FayfTN1/7mMYnYO2Bhg==", + "version": "6.10.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.10.2.tgz", + "integrity": "sha512-scB3nz4WmG75pV8+3eRUQOHZlNSUhFNq37xnpgRkCCELU3XMvXAxLk1eqWWyE22Ki4Q01Fnsw9BA3cJHDPgn2Q==", "dev": true, "license": "MIT", "dependencies": { - "aria-query": "~5.1.3", + "aria-query": "^5.3.2", "array-includes": "^3.1.8", "array.prototype.flatmap": "^1.3.2", "ast-types-flow": "^0.0.8", @@ -7034,14 +7733,13 @@ "axobject-query": "^4.1.0", "damerau-levenshtein": "^1.0.8", "emoji-regex": "^9.2.2", - "es-iterator-helpers": "^1.0.19", "hasown": "^2.0.2", "jsx-ast-utils": "^3.3.5", "language-tags": "^1.0.9", "minimatch": "^3.1.2", "object.fromentries": "^2.0.8", "safe-regex-test": "^1.0.3", - "string.prototype.includes": "^2.0.0" + "string.prototype.includes": "^2.0.1" }, "engines": { "node": ">=4.0" @@ -7061,9 +7759,9 @@ } }, "node_modules/eslint-plugin-playwright": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-playwright/-/eslint-plugin-playwright-1.7.0.tgz", - "integrity": "sha512-pDp2jFeWbBmlwDfZ39Ypdlz1+IafmRKvFTnnonX0TbS7hAByy4oh7Y6ioZRKvLGE+djd/e2VbqOo9sxgZSY2ow==", + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-playwright/-/eslint-plugin-playwright-1.8.3.tgz", + "integrity": "sha512-h87JPFHkz8a6oPhn8GRGGhSQoAJjx0AkOv1jME6NoMk2FpEsfvfJJNaQDxLSqSALkCr0IJXPGTnp6SIRVu5Nqg==", "dev": true, "license": "MIT", "workspaces": [ @@ -7086,9 +7784,9 @@ } }, "node_modules/eslint-plugin-react": { - "version": "7.37.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.1.tgz", - "integrity": "sha512-xwTnwDqzbDRA8uJ7BMxPs/EXRB3i8ZfnOIp8BsxEQkT0nHPp+WWceqGgo6rKb9ctNi8GJLDT4Go5HAWELa/WMg==", + "version": "7.37.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.2.tgz", + "integrity": "sha512-EsTAnj9fLVr/GZleBLFbj/sSuXeWmp1eXIN60ceYnZveqEaUCyW4X+Vh4WTdUhCkW4xutXYqTXCUSyqD4rB75w==", "dev": true, "license": "MIT", "dependencies": { @@ -7097,7 +7795,7 @@ "array.prototype.flatmap": "^1.3.2", "array.prototype.tosorted": "^1.1.4", "doctrine": "^2.1.0", - "es-iterator-helpers": "^1.0.19", + "es-iterator-helpers": "^1.1.0", "estraverse": "^5.3.0", "hasown": "^2.0.2", "jsx-ast-utils": "^2.4.1 || ^3.0.0", @@ -7173,20 +7871,20 @@ } }, "node_modules/eslint-plugin-testing-library": { - "version": "6.3.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-testing-library/-/eslint-plugin-testing-library-6.3.2.tgz", - "integrity": "sha512-Z+6gPhoxXoypKSX+GC3UNfxQtqE5VhBTymU8WmLqpfWCPZIEu+2UZcNYJbwuuGclWQtt6LzN95yEq79o5u4URA==", + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-testing-library/-/eslint-plugin-testing-library-6.4.0.tgz", + "integrity": "sha512-yeWF+YgCgvNyPNI9UKnG0FjeE2sk93N/3lsKqcmR8dSfeXJwFT5irnWo7NjLf152HkRzfoFjh3LsBUrhvFz4eA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/utils": "^5.58.0" + "@typescript-eslint/utils": "^5.62.0" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0", "npm": ">=6" }, "peerDependencies": { - "eslint": "^7.5.0 || ^8.0.0" + "eslint": "^7.5.0 || ^8.0.0 || ^9.0.0" } }, "node_modules/eslint-plugin-testing-library/node_modules/@typescript-eslint/scope-manager": { @@ -7334,6 +8032,7 @@ "resolved": "https://registry.npmjs.org/eslint-plugin-turbo/-/eslint-plugin-turbo-2.2.3.tgz", "integrity": "sha512-LHt35VwxthdGVO6hQRfvmFb6ee8/exAzAYWCy4o87Bnp7urltP8qg7xMd4dPSLAhtfnI2xSo1WgeVaR3MeItxw==", "dev": true, + "license": "MIT", "dependencies": { "dotenv": "16.0.3" }, @@ -7346,6 +8045,7 @@ "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.3.tgz", "integrity": "sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==", "dev": true, + "license": "BSD-2-Clause", "engines": { "node": ">=12" } @@ -7630,6 +8330,20 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/estree-util-scope": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/estree-util-scope/-/estree-util-scope-1.0.0.tgz", + "integrity": "sha512-2CAASclonf+JFWBNJPndcOpA8EMJwa0Q8LUFJEKqXLW6+qBvbFZuF5gItbQOs/umBUkjviCSDCbBwU2cXbmrhQ==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "devlop": "^1.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/estree-util-to-js": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/estree-util-to-js/-/estree-util-to-js-2.0.0.tgz", @@ -7714,91 +8428,38 @@ "dev": true, "license": "MIT", "engines": { - "node": ">=0.8.x" - } - }, - "node_modules/execa": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-0.8.0.tgz", - "integrity": "sha512-zDWS+Rb1E8BlqqhALSt9kUhss8Qq4nN3iof3gsOdyINksElaPyNBtKUMTR62qhvgVWR0CqCX7sdnKe4MnUbFEA==", - "license": "MIT", - "dependencies": { - "cross-spawn": "^5.0.1", - "get-stream": "^3.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/execa/node_modules/cross-spawn": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", - "integrity": "sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A==", - "license": "MIT", - "dependencies": { - "lru-cache": "^4.0.1", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - } - }, - "node_modules/execa/node_modules/lru-cache": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", - "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", - "license": "ISC", - "dependencies": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" - } - }, - "node_modules/execa/node_modules/shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", - "license": "MIT", - "dependencies": { - "shebang-regex": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" + "node": ">=0.8.x" } }, - "node_modules/execa/node_modules/shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", + "node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, "license": "MIT", + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, "engines": { - "node": ">=0.10.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, "node_modules/execa/node_modules/signal-exit": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "license": "ISC" - }, - "node_modules/execa/node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "license": "ISC", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" - } - }, - "node_modules/execa/node_modules/yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==", + "dev": true, "license": "ISC" }, "node_modules/extend": { @@ -7869,9 +8530,9 @@ "license": "MIT" }, "node_modules/fast-glob": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", - "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz", + "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==", "license": "MIT", "dependencies": { "@nodelib/fs.stat": "^2.0.2", @@ -8278,9 +8939,10 @@ "license": "ISC" }, "node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, "hasInstallScript": true, "license": "MIT", "optional": true, @@ -8383,12 +9045,16 @@ } }, "node_modules/get-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", - "integrity": "sha512-GlhdIUuVakc8SJ6kK0zAFbiGzRFzNnY4jUuEbV9UROo4Y+0Ny4fjvcZFVTeDA4odpFyOQzaw6hXukJSq/f28sQ==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, "license": "MIT", "engines": { - "node": ">=4" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/get-symbol-description": { @@ -9315,23 +9981,6 @@ "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/is-arguments": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", - "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/is-array-buffer": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", @@ -9350,11 +9999,11 @@ } }, "node_modules/is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", - "dev": true, - "license": "MIT" + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==", + "license": "MIT", + "optional": true }, "node_modules/is-async-function": { "version": "2.0.0", @@ -9693,15 +10342,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-reference": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-3.0.2.tgz", - "integrity": "sha512-v3rht/LgVcsdZa3O2Nqs+NMowLOxeOm7Ay9+/ARQ2F+qEoANRcqrjAZKGN0v8ymUetZGgkp26LTnGT7H0Qo9Pg==", - "license": "MIT", - "dependencies": { - "@types/estree": "*" - } - }, "node_modules/is-regex": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", @@ -9749,12 +10389,16 @@ } }, "node_modules/is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true, "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/is-string": { @@ -10193,12 +10837,12 @@ } }, "node_modules/light-my-request": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/light-my-request/-/light-my-request-6.1.0.tgz", - "integrity": "sha512-+NFuhlOGoEwxeQfJ/pobkVFxcnKyDtiX847hLjuB/IzBxIl3q4VJeFI8uRCgb3AlTWL1lgOr+u5+8QdUcr33ng==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/light-my-request/-/light-my-request-6.3.0.tgz", + "integrity": "sha512-bWTAPJmeWQH5suJNYwG0f5cs0p6ho9e6f1Ppoxv5qMosY+s9Ir2+ZLvvHcgA7VTDop4zl/NCHhOVVqU+kd++Ow==", "license": "BSD-3-Clause", "dependencies": { - "cookie": "^0.7.0", + "cookie": "^1.0.1", "process-warning": "^4.0.0", "set-cookie-parser": "^2.6.0" } @@ -10335,9 +10979,9 @@ } }, "node_modules/markdown-table": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.3.tgz", - "integrity": "sha512-Z1NL3Tb1M9wH4XESsCDEksWoKTdlUafKc4pt0GRwjUyXaCFZ+dc3g2erqB6zm3szA2IUSi7VnPI+o/9jnxh9hw==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.4.tgz", + "integrity": "sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw==", "license": "MIT", "funding": { "type": "github", @@ -10397,9 +11041,9 @@ } }, "node_modules/mdast-util-from-markdown": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.1.tgz", - "integrity": "sha512-aJEUyzZ6TzlsX2s5B4Of7lN7EQtAxvtradMMglCQDyaTFgse6CmtmdJ15ElnVRlCg1vpNyVtbem0PWzlNieZsA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.2.tgz", + "integrity": "sha512-uZhTV/8NBuw0WHkPTrCqDOl0zVe1BIng5ZtHoDk49ME1qqcjYmmLmOf0gELgcRMxN4w2iuIeVso5/6QymSrgmA==", "license": "MIT", "dependencies": { "@types/mdast": "^4.0.0", @@ -10683,9 +11327,9 @@ } }, "node_modules/mdast-util-to-markdown": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.0.tgz", - "integrity": "sha512-SR2VnIEdVNCJbP6y7kVTJgPLifdr8WEU440fQec7qHoHOUz/oJ2jmNRqdDQ3rbiStOXb2mCDGTuwsK5OPUgYlQ==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.1.tgz", + "integrity": "sha512-OrkcCoqAkEg9b1ykXBrA0ehRc8H4fGU/03cACmW2xXzau1+dIdS+qJugh1Cqex3hMumSBgSE/5pc7uqP12nLAw==", "license": "MIT", "dependencies": { "@types/mdast": "^4.0.0", @@ -10693,6 +11337,7 @@ "longest-streak": "^3.0.0", "mdast-util-phrasing": "^4.0.0", "mdast-util-to-string": "^4.0.0", + "micromark-util-classify-character": "^2.0.0", "micromark-util-decode-string": "^2.0.0", "unist-util-visit": "^5.0.0", "zwitch": "^2.0.0" @@ -11731,10 +12376,9 @@ } }, "node_modules/negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", - "dev": true, + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", + "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", "license": "MIT", "engines": { "node": ">= 0.6" @@ -11751,12 +12395,12 @@ } }, "node_modules/next": { - "version": "14.2.15", - "resolved": "https://registry.npmjs.org/next/-/next-14.2.15.tgz", - "integrity": "sha512-h9ctmOokpoDphRvMGnwOJAedT6zKhwqyZML9mDtspgf4Rh3Pn7UTYKqePNoDvhsWBAO5GoPNYshnAUGIazVGmw==", + "version": "14.2.16", + "resolved": "https://registry.npmjs.org/next/-/next-14.2.16.tgz", + "integrity": "sha512-LcO7WnFu6lYSvCzZoo1dB+IO0xXz5uEv52HF1IUN0IqVTUIZGHuuR10I5efiLadGt+4oZqTcNZyVVEem/TM5nA==", "license": "MIT", "dependencies": { - "@next/env": "14.2.15", + "@next/env": "14.2.16", "@swc/helpers": "0.5.5", "busboy": "1.6.0", "caniuse-lite": "^1.0.30001579", @@ -11771,15 +12415,15 @@ "node": ">=18.17.0" }, "optionalDependencies": { - "@next/swc-darwin-arm64": "14.2.15", - "@next/swc-darwin-x64": "14.2.15", - "@next/swc-linux-arm64-gnu": "14.2.15", - "@next/swc-linux-arm64-musl": "14.2.15", - "@next/swc-linux-x64-gnu": "14.2.15", - "@next/swc-linux-x64-musl": "14.2.15", - "@next/swc-win32-arm64-msvc": "14.2.15", - "@next/swc-win32-ia32-msvc": "14.2.15", - "@next/swc-win32-x64-msvc": "14.2.15" + "@next/swc-darwin-arm64": "14.2.16", + "@next/swc-darwin-x64": "14.2.16", + "@next/swc-linux-arm64-gnu": "14.2.16", + "@next/swc-linux-arm64-musl": "14.2.16", + "@next/swc-linux-x64-gnu": "14.2.16", + "@next/swc-linux-x64-musl": "14.2.16", + "@next/swc-win32-arm64-msvc": "14.2.16", + "@next/swc-win32-ia32-msvc": "14.2.16", + "@next/swc-win32-x64-msvc": "14.2.16" }, "peerDependencies": { "@opentelemetry/api": "^1.1.0", @@ -11795,25 +12439,193 @@ "@playwright/test": { "optional": true }, - "sass": { + "sass": { + "optional": true + } + } + }, + "node_modules/next-themes": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/next-themes/-/next-themes-0.3.0.tgz", + "integrity": "sha512-/QHIrsYpd6Kfk7xakK4svpDI5mmXP0gfvCoJdGpZQ2TOrQZmsW0QxjaiLn8wbIKjtm4BTSqLoix4lxYYOnLJ/w==", + "license": "MIT", + "peerDependencies": { + "react": "^16.8 || ^17 || ^18", + "react-dom": "^16.8 || ^17 || ^18" + } + }, + "node_modules/next/node_modules/@next/env": { + "version": "14.2.16", + "resolved": "https://registry.npmjs.org/@next/env/-/env-14.2.16.tgz", + "integrity": "sha512-fLrX5TfJzHCbnZ9YUSnGW63tMV3L4nSfhgOQ0iCcX21Pt+VSTDuaLsSuL8J/2XAiVA5AnzvXDpf6pMs60QxOag==", + "license": "MIT" + }, + "node_modules/next/node_modules/@next/swc-darwin-arm64": { + "version": "14.2.16", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.2.16.tgz", + "integrity": "sha512-uFT34QojYkf0+nn6MEZ4gIWQ5aqGF11uIZ1HSxG+cSbj+Mg3+tYm8qXYd3dKN5jqKUm5rBVvf1PBRO/MeQ6rxw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/next/node_modules/@next/swc-darwin-x64": { + "version": "14.2.16", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.2.16.tgz", + "integrity": "sha512-mCecsFkYezem0QiZlg2bau3Xul77VxUD38b/auAjohMA22G9KTJneUYMv78vWoCCFkleFAhY1NIvbyjj1ncG9g==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/next/node_modules/@next/swc-linux-arm64-gnu": { + "version": "14.2.16", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.2.16.tgz", + "integrity": "sha512-yhkNA36+ECTC91KSyZcgWgKrYIyDnXZj8PqtJ+c2pMvj45xf7y/HrgI17hLdrcYamLfVt7pBaJUMxADtPaczHA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/next/node_modules/@next/swc-linux-arm64-musl": { + "version": "14.2.16", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.2.16.tgz", + "integrity": "sha512-X2YSyu5RMys8R2lA0yLMCOCtqFOoLxrq2YbazFvcPOE4i/isubYjkh+JCpRmqYfEuCVltvlo+oGfj/b5T2pKUA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/next/node_modules/@next/swc-linux-x64-gnu": { + "version": "14.2.16", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.2.16.tgz", + "integrity": "sha512-9AGcX7VAkGbc5zTSa+bjQ757tkjr6C/pKS7OK8cX7QEiK6MHIIezBLcQ7gQqbDW2k5yaqba2aDtaBeyyZh1i6Q==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/next/node_modules/@next/swc-linux-x64-musl": { + "version": "14.2.16", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.2.16.tgz", + "integrity": "sha512-Klgeagrdun4WWDaOizdbtIIm8khUDQJ/5cRzdpXHfkbY91LxBXeejL4kbZBrpR/nmgRrQvmz4l3OtttNVkz2Sg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/next/node_modules/@next/swc-win32-arm64-msvc": { + "version": "14.2.16", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.2.16.tgz", + "integrity": "sha512-PwW8A1UC1Y0xIm83G3yFGPiOBftJK4zukTmk7DI1CebyMOoaVpd8aSy7K6GhobzhkjYvqS/QmzcfsWG2Dwizdg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/next/node_modules/@next/swc-win32-x64-msvc": { + "version": "14.2.16", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.2.16.tgz", + "integrity": "sha512-OA7NtfxgirCjfqt+02BqxC3MIgM/JaGjw9tOe4fyZgPsqfseNiMPnCRP44Pfs+Gpo9zPN+SXaFsgP6vk8d571A==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/next/node_modules/@swc/helpers": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.5.tgz", + "integrity": "sha512-KGYxvIOXcceOAbEk4bi/dVLEK9z8sZ0uBB3Il5b1rhfClSpcX0yfRO0KmTkqR2cnQDymwLB+25ZyMzICg/cm/A==", + "license": "Apache-2.0", + "dependencies": { + "@swc/counter": "^0.1.3", + "tslib": "^2.4.0" + } + }, + "node_modules/next/node_modules/styled-jsx": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.1.tgz", + "integrity": "sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==", + "license": "MIT", + "dependencies": { + "client-only": "0.0.1" + }, + "engines": { + "node": ">= 12.0.0" + }, + "peerDependencies": { + "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + }, + "babel-plugin-macros": { "optional": true } } }, - "node_modules/next-themes": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/next-themes/-/next-themes-0.3.0.tgz", - "integrity": "sha512-/QHIrsYpd6Kfk7xakK4svpDI5mmXP0gfvCoJdGpZQ2TOrQZmsW0QxjaiLn8wbIKjtm4BTSqLoix4lxYYOnLJ/w==", - "license": "MIT", - "peerDependencies": { - "react": "^16.8 || ^17 || ^18", - "react-dom": "^16.8 || ^17 || ^18" - } - }, "node_modules/nextra": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/nextra/-/nextra-3.2.0.tgz", "integrity": "sha512-Gi+Q6BI9rFmQdy3e4FXCqgaSUcv8CGRVOVWbgY6/GTAWKMKK4v5M1gxYNhxdOywSkIoXrxSeXbIaj0qgNdjv3A==", + "license": "MIT", "dependencies": { "@formatjs/intl-localematcher": "^0.5.4", "@headlessui/react": "^2.1.2", @@ -11867,6 +12679,7 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/nextra-theme-docs/-/nextra-theme-docs-3.2.0.tgz", "integrity": "sha512-bUa0W3rh+OgUrE8aJXqYpjVAu0AmkJuHZd9Me0qjGK5YinSvQv7jzAWI7+Af4vnWdRkPlh6MIUUHAOPo+Yalcw==", + "license": "MIT", "dependencies": { "@headlessui/react": "^2.1.2", "clsx": "^2.0.0", @@ -11895,14 +12708,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/nextra/node_modules/negotiator": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", - "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", - "engines": { - "node": ">= 0.6" - } - }, "node_modules/nextra/node_modules/p-limit": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-6.1.0.tgz", @@ -11996,24 +12801,16 @@ } }, "node_modules/npm-run-path": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", - "integrity": "sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, "license": "MIT", "dependencies": { - "path-key": "^2.0.0" + "path-key": "^3.0.0" }, "engines": { - "node": ">=4" - } - }, - "node_modules/npm-run-path/node_modules/path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", - "license": "MIT", - "engines": { - "node": ">=4" + "node": ">=8" } }, "node_modules/npm-to-yarn": { @@ -12072,23 +12869,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/object-is": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.6.tgz", - "integrity": "sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/object-keys": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", @@ -12478,9 +13258,9 @@ "license": "ISC" }, "node_modules/parse5": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.2.0.tgz", - "integrity": "sha512-ZkDsAOcxsUMZ4Lz5fVciOehNcJ+Gb8gTzcA4yl3wnc273BAybYWrQ+Ks/OjCjSEpjvQkDSeZbybK9qj2VHHdGA==", + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.2.1.tgz", + "integrity": "sha512-BuBYQYlv1ckiPdQi/ohiivi9Sagc9JG+Ozs0r7b/0iK3sKmrb0b9FdWdBbOdx6hBCM/F9Ir82ofnBhtZOjCRPQ==", "license": "MIT", "dependencies": { "entities": "^4.5.0" @@ -12587,17 +13367,6 @@ "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==", "license": "MIT" }, - "node_modules/periscopic": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/periscopic/-/periscopic-3.1.0.tgz", - "integrity": "sha512-vKiQ8RRtkl9P+r/+oefh25C3fhybptkHKCZSPlcXiJux2tJF55GnEj3BVn4A5gKfq9NWWXXrxkHBwVPUfH0opw==", - "license": "MIT", - "dependencies": { - "@types/estree": "^1.0.0", - "estree-walker": "^3.0.0", - "is-reference": "^3.0.0" - } - }, "node_modules/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", @@ -12723,12 +13492,13 @@ } }, "node_modules/playwright": { - "version": "1.48.2", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.48.2.tgz", - "integrity": "sha512-NjYvYgp4BPmiwfe31j4gHLa3J7bD2WiBz8Lk2RoSsmX38SVIARZ18VYjxLjAcDsAhA+F4iSEXTSGgjua0rrlgQ==", + "version": "1.48.1", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.48.1.tgz", + "integrity": "sha512-j8CiHW/V6HxmbntOfyB4+T/uk08tBy6ph0MpBXwuoofkSnLmlfdYNNkFTYD6ofzzlSqLA1fwH4vwvVFvJgLN0w==", "devOptional": true, + "license": "Apache-2.0", "dependencies": { - "playwright-core": "1.48.2" + "playwright-core": "1.48.1" }, "bin": { "playwright": "cli.js" @@ -12741,10 +13511,11 @@ } }, "node_modules/playwright-core": { - "version": "1.48.2", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.48.2.tgz", - "integrity": "sha512-sjjw+qrLFlriJo64du+EK0kJgZzoQPsabGF4lBvsid+3CNIZIYLgnMj9V6JY5VhM2Peh20DJWIVpVljLLnlawA==", + "version": "1.48.1", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.48.1.tgz", + "integrity": "sha512-Yw/t4VAFX/bBr1OzwCuOMZkY1Cnb4z/doAFSwf4huqAGWmf9eMNjmK7NiOljCdLmxeRYcGPPmcDgU0zOlzP0YA==", "devOptional": true, + "license": "Apache-2.0", "bin": { "playwright-core": "cli.js" }, @@ -12752,6 +13523,21 @@ "node": ">=18" } }, + "node_modules/playwright/node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, "node_modules/pluralize": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", @@ -13308,6 +14094,15 @@ "react": "^18.3.1" } }, + "node_modules/react-dom/node_modules/scheduler": { + "version": "0.23.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", + "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0" + } + }, "node_modules/react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", @@ -13442,6 +14237,70 @@ "node": ">= 12.13.0" } }, + "node_modules/recma-build-jsx": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/recma-build-jsx/-/recma-build-jsx-1.0.0.tgz", + "integrity": "sha512-8GtdyqaBcDfva+GUKDr3nev3VpKAhup1+RvkMvUxURHpW7QyIvk9F5wz7Vzo06CEMSilw6uArgRqhpiUcWp8ew==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "estree-util-build-jsx": "^3.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/recma-jsx": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/recma-jsx/-/recma-jsx-1.0.0.tgz", + "integrity": "sha512-5vwkv65qWwYxg+Atz95acp8DMu1JDSqdGkA2Of1j6rCreyFUE/gp15fC8MnGEuG1W68UKjM6x6+YTWIh7hZM/Q==", + "license": "MIT", + "dependencies": { + "acorn-jsx": "^5.0.0", + "estree-util-to-js": "^2.0.0", + "recma-parse": "^1.0.0", + "recma-stringify": "^1.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/recma-parse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/recma-parse/-/recma-parse-1.0.0.tgz", + "integrity": "sha512-OYLsIGBB5Y5wjnSnQW6t3Xg7q3fQ7FWbw/vcXtORTnyaSFscOtABg+7Pnz6YZ6c27fG1/aN8CjfwoUEUIdwqWQ==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "esast-util-from-js": "^2.0.0", + "unified": "^11.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/recma-stringify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/recma-stringify/-/recma-stringify-1.0.0.tgz", + "integrity": "sha512-cjwII1MdIIVloKvC9ErQ+OgAtwHBmcZ0Bg4ciz78FtbT8In39aAYbaA7zvxQ61xVMSPE8WxhLwLbhif4Js2C+g==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "estree-util-to-js": "^2.0.0", + "unified": "^11.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/redis": { "version": "4.7.0", "resolved": "https://registry.npmjs.org/redis/-/redis-4.7.0.tgz", @@ -13637,6 +14496,21 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/rehype-recma": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/rehype-recma/-/rehype-recma-1.0.0.tgz", + "integrity": "sha512-lqA4rGUf1JmacCNWWZx0Wv1dHqMwxzsDWYMTowuplHF3xH0N/MmrZ/G3BDZnzAkRmxDadujCjaKM2hqYdCBOGw==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "@types/hast": "^3.0.0", + "hast-util-to-estree": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/remark-frontmatter": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/remark-frontmatter/-/remark-frontmatter-5.0.0.tgz", @@ -13688,9 +14562,9 @@ } }, "node_modules/remark-mdx": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/remark-mdx/-/remark-mdx-3.0.1.tgz", - "integrity": "sha512-3Pz3yPQ5Rht2pM5R+0J2MrGoBSrzf+tJG94N+t/ilfdh8YLyyKYtidAYwTveB20BoHAcwIopOUqhcmh2F7hGYA==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/remark-mdx/-/remark-mdx-3.1.0.tgz", + "integrity": "sha512-Ngl/H3YXyBV9RcRNdlYsZujAmhsxwzxpDzpDEhFBVAGthS4GDgnctpDjgFl/ULx5UEDzqtW1cyBSNKqYYrqLBA==", "license": "MIT", "dependencies": { "mdast-util-mdx": "^3.0.0", @@ -14032,9 +14906,9 @@ "license": "Unlicense" }, "node_modules/rollup": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.24.0.tgz", - "integrity": "sha512-DOmrlGSXNk1DM0ljiQA+i+o0rSLhtii1je5wgk60j49d1jHT5YYttBv1iWOnYSTG+fZZESUOSNiAl89SIet+Cg==", + "version": "4.24.3", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.24.3.tgz", + "integrity": "sha512-HBW896xR5HGmoksbi3JBDtmVzWiPAYqp7wip50hjQ67JbDz61nyoMPdqu1DvVW9asYb2M65Z20ZHsyJCMqMyDg==", "dev": true, "license": "MIT", "dependencies": { @@ -14048,22 +14922,24 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.24.0", - "@rollup/rollup-android-arm64": "4.24.0", - "@rollup/rollup-darwin-arm64": "4.24.0", - "@rollup/rollup-darwin-x64": "4.24.0", - "@rollup/rollup-linux-arm-gnueabihf": "4.24.0", - "@rollup/rollup-linux-arm-musleabihf": "4.24.0", - "@rollup/rollup-linux-arm64-gnu": "4.24.0", - "@rollup/rollup-linux-arm64-musl": "4.24.0", - "@rollup/rollup-linux-powerpc64le-gnu": "4.24.0", - "@rollup/rollup-linux-riscv64-gnu": "4.24.0", - "@rollup/rollup-linux-s390x-gnu": "4.24.0", - "@rollup/rollup-linux-x64-gnu": "4.24.0", - "@rollup/rollup-linux-x64-musl": "4.24.0", - "@rollup/rollup-win32-arm64-msvc": "4.24.0", - "@rollup/rollup-win32-ia32-msvc": "4.24.0", - "@rollup/rollup-win32-x64-msvc": "4.24.0", + "@rollup/rollup-android-arm-eabi": "4.24.3", + "@rollup/rollup-android-arm64": "4.24.3", + "@rollup/rollup-darwin-arm64": "4.24.3", + "@rollup/rollup-darwin-x64": "4.24.3", + "@rollup/rollup-freebsd-arm64": "4.24.3", + "@rollup/rollup-freebsd-x64": "4.24.3", + "@rollup/rollup-linux-arm-gnueabihf": "4.24.3", + "@rollup/rollup-linux-arm-musleabihf": "4.24.3", + "@rollup/rollup-linux-arm64-gnu": "4.24.3", + "@rollup/rollup-linux-arm64-musl": "4.24.3", + "@rollup/rollup-linux-powerpc64le-gnu": "4.24.3", + "@rollup/rollup-linux-riscv64-gnu": "4.24.3", + "@rollup/rollup-linux-s390x-gnu": "4.24.3", + "@rollup/rollup-linux-x64-gnu": "4.24.3", + "@rollup/rollup-linux-x64-musl": "4.24.3", + "@rollup/rollup-win32-arm64-msvc": "4.24.3", + "@rollup/rollup-win32-ia32-msvc": "4.24.3", + "@rollup/rollup-win32-x64-msvc": "4.24.3", "fsevents": "~2.3.2" } }, @@ -14219,13 +15095,10 @@ "license": "ISC" }, "node_modules/scheduler": { - "version": "0.23.2", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", - "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", - "license": "MIT", - "dependencies": { - "loose-envify": "^1.1.0" - } + "version": "0.25.0-rc-65a56d0e-20241020", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.25.0-rc-65a56d0e-20241020.tgz", + "integrity": "sha512-HxWcXSy0sNnf+TKRkMwyVD1z19AAVQ4gUub8m7VxJUUfSu3J4lr1T+AagohKEypiW5dbQhJuCtAumPY6z9RQ1g==", + "license": "MIT" }, "node_modules/scroll-into-view-if-needed": { "version": "3.1.0", @@ -14349,13 +15222,6 @@ "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/serve/node_modules/arg": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", - "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", - "dev": true, - "license": "MIT" - }, "node_modules/serve/node_modules/chalk": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.0.1.tgz", @@ -14366,108 +15232,20 @@ "node": "^12.17.0 || ^14.13 || >=16.0.0" }, "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/serve/node_modules/clipboardy": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/clipboardy/-/clipboardy-3.0.0.tgz", - "integrity": "sha512-Su+uU5sr1jkUy1sGRpLKjKrvEOVXgSgiSInwa/qeID6aJ07yh+5NWc3h2QfjHjBnfX4LhtFcuAWKUsJ3r+fjbg==", - "dev": true, - "license": "MIT", - "dependencies": { - "arch": "^2.2.0", - "execa": "^5.1.1", - "is-wsl": "^2.2.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/serve/node_modules/execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "dev": true, - "license": "MIT", - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/serve/node_modules/get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/serve/node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/serve/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true, - "license": "MIT" - }, - "node_modules/serve/node_modules/npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "license": "MIT", - "dependencies": { - "path-key": "^3.0.0" - }, - "engines": { - "node": ">=8" + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/serve/node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "node_modules/serve/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", "dev": true, - "license": "ISC" + "license": "MIT" }, "node_modules/set-cookie-parser": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.0.tgz", - "integrity": "sha512-lXLOiqpkUumhRdFF3k1osNXCy9akgx/dyPZ5p8qAg9seJzXr5ZrlqZuWIMuY6ejOsVLE6flJ5/h3lsn57fQ/PQ==", + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz", + "integrity": "sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==", "license": "MIT" }, "node_modules/set-function-length": { @@ -14504,6 +15282,46 @@ "node": ">= 0.4" } }, + "node_modules/sharp": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.33.5.tgz", + "integrity": "sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw==", + "hasInstallScript": true, + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "color": "^4.2.3", + "detect-libc": "^2.0.3", + "semver": "^7.6.3" + }, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-darwin-arm64": "0.33.5", + "@img/sharp-darwin-x64": "0.33.5", + "@img/sharp-libvips-darwin-arm64": "1.0.4", + "@img/sharp-libvips-darwin-x64": "1.0.4", + "@img/sharp-libvips-linux-arm": "1.0.5", + "@img/sharp-libvips-linux-arm64": "1.0.4", + "@img/sharp-libvips-linux-s390x": "1.0.4", + "@img/sharp-libvips-linux-x64": "1.0.4", + "@img/sharp-libvips-linuxmusl-arm64": "1.0.4", + "@img/sharp-libvips-linuxmusl-x64": "1.0.4", + "@img/sharp-linux-arm": "0.33.5", + "@img/sharp-linux-arm64": "0.33.5", + "@img/sharp-linux-s390x": "0.33.5", + "@img/sharp-linux-x64": "0.33.5", + "@img/sharp-linuxmusl-arm64": "0.33.5", + "@img/sharp-linuxmusl-x64": "0.33.5", + "@img/sharp-wasm32": "0.33.5", + "@img/sharp-win32-ia32": "0.33.5", + "@img/sharp-win32-x64": "0.33.5" + } + }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -14528,15 +15346,15 @@ } }, "node_modules/shiki": { - "version": "1.22.0", - "resolved": "https://registry.npmjs.org/shiki/-/shiki-1.22.0.tgz", - "integrity": "sha512-/t5LlhNs+UOKQCYBtl5ZsH/Vclz73GIqT2yQsCBygr8L/ppTdmpL4w3kPLoZJbMKVWtoG77Ue1feOjZfDxvMkw==", + "version": "1.22.2", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-1.22.2.tgz", + "integrity": "sha512-3IZau0NdGKXhH2bBlUk4w1IHNxPh6A5B2sUpyY+8utLu2j/h1QpFkAaUA1bAMxOWWGtTWcAh531vnS4NJKS/lA==", "license": "MIT", "dependencies": { - "@shikijs/core": "1.22.0", - "@shikijs/engine-javascript": "1.22.0", - "@shikijs/engine-oniguruma": "1.22.0", - "@shikijs/types": "1.22.0", + "@shikijs/core": "1.22.2", + "@shikijs/engine-javascript": "1.22.2", + "@shikijs/engine-oniguruma": "1.22.2", + "@shikijs/types": "1.22.2", "@shikijs/vscode-textmate": "^9.3.0", "@types/hast": "^3.0.4" } @@ -14580,6 +15398,16 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/simple-swizzle": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", + "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==", + "license": "MIT", + "optional": true, + "dependencies": { + "is-arrayish": "^0.3.1" + } + }, "node_modules/slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", @@ -14908,19 +15736,6 @@ "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", "license": "BSD-3-Clause" }, - "node_modules/stop-iteration-iterator": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz", - "integrity": "sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "internal-slot": "^1.0.4" - }, - "engines": { - "node": ">= 0.4" - } - }, "node_modules/streamsearch": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", @@ -15227,9 +16042,9 @@ } }, "node_modules/styled-jsx": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.1.tgz", - "integrity": "sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==", + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.6.tgz", + "integrity": "sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA==", "license": "MIT", "dependencies": { "client-only": "0.0.1" @@ -15238,7 +16053,7 @@ "node": ">= 12.0.0" }, "peerDependencies": { - "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0" + "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0 || ^19.0.0-0" }, "peerDependenciesMeta": { "@babel/core": { @@ -15513,13 +16328,13 @@ "license": "MIT" }, "node_modules/tinyglobby": { - "version": "0.2.9", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.9.tgz", - "integrity": "sha512-8or1+BGEdk1Zkkw2ii16qSS7uVrQJPre5A9o/XkWPATkk23FZh/15BKFxPnlTy6vkljZxLqYCzzBMj30ZrSvjw==", + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.10.tgz", + "integrity": "sha512-Zc+8eJlFMvgatPZTl6A9L/yht8QqdmUNtURHaKZLmKBE12hNPSrqNkUp2cs3M/UKmNVVAMFQYSjYIVHDjW5zew==", "dev": true, "license": "MIT", "dependencies": { - "fdir": "^6.4.0", + "fdir": "^6.4.2", "picomatch": "^4.0.2" }, "engines": { @@ -15581,6 +16396,12 @@ "node": ">=4" } }, + "node_modules/title/node_modules/arg": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/arg/-/arg-1.0.0.tgz", + "integrity": "sha512-Wk7TEzl1KqvTGs/uyhmHO/3XLd3t1UeU4IstvPXVzGPM522cTjqjNZ99esCkcL52sjqjo8e8CTBcWhkxvGzoAw==", + "license": "MIT" + }, "node_modules/title/node_modules/chalk": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", @@ -15595,6 +16416,19 @@ "node": ">=4" } }, + "node_modules/title/node_modules/clipboardy": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/clipboardy/-/clipboardy-1.2.2.tgz", + "integrity": "sha512-16KrBOV7bHmHdxcQiCvfUFYVFyEah4FI8vYT1Fr7CGSA4G+xBWMEfUEQJS1hxeHGtI9ju1Bzs9uXSbj5HZKArw==", + "license": "MIT", + "dependencies": { + "arch": "^2.1.0", + "execa": "^0.8.0" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/title/node_modules/color-convert": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", @@ -15610,6 +16444,17 @@ "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", "license": "MIT" }, + "node_modules/title/node_modules/cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A==", + "license": "MIT", + "dependencies": { + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, "node_modules/title/node_modules/escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", @@ -15619,6 +16464,33 @@ "node": ">=0.8.0" } }, + "node_modules/title/node_modules/execa": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.8.0.tgz", + "integrity": "sha512-zDWS+Rb1E8BlqqhALSt9kUhss8Qq4nN3iof3gsOdyINksElaPyNBtKUMTR62qhvgVWR0CqCX7sdnKe4MnUbFEA==", + "license": "MIT", + "dependencies": { + "cross-spawn": "^5.0.1", + "get-stream": "^3.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/title/node_modules/get-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha512-GlhdIUuVakc8SJ6kK0zAFbiGzRFzNnY4jUuEbV9UROo4Y+0Ny4fjvcZFVTeDA4odpFyOQzaw6hXukJSq/f28sQ==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/title/node_modules/has-flag": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", @@ -15628,6 +16500,73 @@ "node": ">=0.10.0" } }, + "node_modules/title/node_modules/is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/title/node_modules/lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "license": "ISC", + "dependencies": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "node_modules/title/node_modules/npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==", + "license": "MIT", + "dependencies": { + "path-key": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/title/node_modules/path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/title/node_modules/shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", + "license": "MIT", + "dependencies": { + "shebang-regex": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/title/node_modules/shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/title/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "license": "ISC" + }, "node_modules/title/node_modules/supports-color": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", @@ -15640,6 +16579,24 @@ "node": ">=4" } }, + "node_modules/title/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/title/node_modules/yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==", + "license": "ISC" + }, "node_modules/titleize": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/titleize/-/titleize-1.0.0.tgz", @@ -15661,16 +16618,6 @@ "node": ">=0.6.0" } }, - "node_modules/to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -15798,6 +16745,7 @@ "resolved": "https://registry.npmjs.org/tsup/-/tsup-8.3.5.tgz", "integrity": "sha512-Tunf6r6m6tnZsG9GYWndg0z8dEV7fD733VBFzFJ5Vcm1FtlXB8xBD/rtrBi2a3YKEV7hHtxiZtW5EAVADoe1pA==", "dev": true, + "license": "MIT", "dependencies": { "bundle-require": "^5.0.0", "cac": "^6.7.14", @@ -15852,6 +16800,7 @@ "ppc64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "aix" @@ -15868,6 +16817,7 @@ "arm" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "android" @@ -15884,6 +16834,7 @@ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "android" @@ -15900,6 +16851,7 @@ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "android" @@ -15916,6 +16868,7 @@ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "darwin" @@ -15932,6 +16885,7 @@ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "darwin" @@ -15948,6 +16902,7 @@ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "freebsd" @@ -15964,6 +16919,7 @@ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "freebsd" @@ -15980,6 +16936,7 @@ "arm" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -15996,6 +16953,7 @@ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -16012,6 +16970,7 @@ "ia32" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -16028,6 +16987,7 @@ "loong64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -16044,6 +17004,7 @@ "mips64el" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -16060,6 +17021,7 @@ "ppc64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -16076,6 +17038,7 @@ "riscv64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -16092,6 +17055,7 @@ "s390x" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -16108,6 +17072,7 @@ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -16124,6 +17089,7 @@ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "netbsd" @@ -16140,6 +17106,7 @@ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "openbsd" @@ -16156,6 +17123,7 @@ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "openbsd" @@ -16172,6 +17140,7 @@ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "sunos" @@ -16188,6 +17157,7 @@ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "win32" @@ -16204,6 +17174,7 @@ "ia32" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "win32" @@ -16220,6 +17191,7 @@ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "win32" @@ -16233,6 +17205,7 @@ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.1.tgz", "integrity": "sha512-n8enUVCED/KVRQlab1hr3MVpcVMvxtZjmEa956u+4YijlmQED223XMSYj2tLuKvr4jcCTzNNMpQDUer72MMmzA==", "dev": true, + "license": "MIT", "dependencies": { "readdirp": "^4.0.1" }, @@ -16249,6 +17222,7 @@ "integrity": "sha512-FuLPevChGDshgSicjisSooU0cemp/sGXR841D5LHMB7mTVOmsEHcAxaH3irL53+8YDIeVNQEySh4DaYU/iuPqQ==", "dev": true, "hasInstallScript": true, + "license": "MIT", "bin": { "esbuild": "bin/esbuild" }, @@ -16287,6 +17261,7 @@ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.0.2.tgz", "integrity": "sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA==", "dev": true, + "license": "MIT", "engines": { "node": ">= 14.16.0" }, @@ -16336,6 +17311,7 @@ "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.19.2.tgz", "integrity": "sha512-pOUl6Vo2LUq/bSa8S5q7b91cgNSjctn9ugq/+Mvow99qW6x/UZYwzxy/3NmqoT66eHYfCVvFvACC58UBPFf28g==", "dev": true, + "license": "MIT", "dependencies": { "esbuild": "~0.23.0", "get-tsconfig": "^4.7.5" @@ -16350,21 +17326,6 @@ "fsevents": "~2.3.3" } }, - "node_modules/tsx/node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, "node_modules/tunnel": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", @@ -16380,6 +17341,7 @@ "resolved": "https://registry.npmjs.org/turbo/-/turbo-2.2.3.tgz", "integrity": "sha512-5lDvSqIxCYJ/BAd6rQGK/AzFRhBkbu4JHVMLmGh/hCb7U3CqSnr5Tjwfy9vc+/5wG2DJ6wttgAaA7MoCgvBKZQ==", "dev": true, + "license": "MIT", "bin": { "turbo": "bin/turbo" }, @@ -16400,6 +17362,7 @@ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "darwin" @@ -16413,6 +17376,7 @@ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "darwin" @@ -16426,6 +17390,7 @@ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -16439,6 +17404,7 @@ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -16452,6 +17418,7 @@ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "win32" @@ -16465,6 +17432,7 @@ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "win32" @@ -17442,6 +18410,16 @@ "redis": ">= 4.6" } }, + "packages/cache-handler/node_modules/@types/node": { + "version": "22.8.4", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.8.4.tgz", + "integrity": "sha512-SpNNxkftTJOPk0oN+y2bIqurEXHTA2AOZ3EJDDKeJ5VzkvvORSvmQXGQarcOzWV1ac7DCaPBEdMDxBsM+d8jWw==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.19.8" + } + }, "packages/json-replacer-reviver": { "name": "@neshca/json-replacer-reviver", "version": "1.1.3", @@ -17454,6 +18432,16 @@ "typescript": "5.6.3" } }, + "packages/json-replacer-reviver/node_modules/@types/node": { + "version": "22.8.4", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.8.4.tgz", + "integrity": "sha512-SpNNxkftTJOPk0oN+y2bIqurEXHTA2AOZ3EJDDKeJ5VzkvvORSvmQXGQarcOzWV1ac7DCaPBEdMDxBsM+d8jWw==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.19.8" + } + }, "packages/server": { "name": "@neshca/server", "version": "1.1.2", @@ -17474,6 +18462,16 @@ "tsx": "4.19.2", "typescript": "5.6.3" } + }, + "packages/server/node_modules/@types/node": { + "version": "22.8.4", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.8.4.tgz", + "integrity": "sha512-SpNNxkftTJOPk0oN+y2bIqurEXHTA2AOZ3EJDDKeJ5VzkvvORSvmQXGQarcOzWV1ac7DCaPBEdMDxBsM+d8jWw==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.19.8" + } } } } diff --git a/package.json b/package.json index 03326a6d..de4a4d50 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,7 @@ "build:docs": "turbo run build:docs --filter=@repo/cache-handler-docs", "build:packages": "turbo run build --filter=!./apps/* --filter=!./docs/*", "build:test-app": "turbo run build --filter=@repo/cache-testing", + "build:test-app-15-app": "turbo run build --filter=@repo/cache-testing-15-app", "changeset": "changeset", "ci:publish": "changeset publish", "ci:version": "changeset version && npm run codestyle:fix", @@ -28,6 +29,7 @@ "prettier:fix": "prettier --write **/*.{md,mdx,yml,json}", "start:backend": "turbo run start --filter=@repo/backend", "start:test-app": "turbo run start --filter=@repo/cache-testing", + "start:test-app-15-app": "turbo run start --filter=@repo/cache-testing-15-app", "test": "turbo run test" }, "dependencies": { diff --git a/packages/cache-handler/src/cache-handler.ts b/packages/cache-handler/src/cache-handler.ts index 9089ea26..d2032c6a 100644 --- a/packages/cache-handler/src/cache-handler.ts +++ b/packages/cache-handler/src/cache-handler.ts @@ -7,7 +7,9 @@ import type { CacheHandlerParametersSet, CacheHandlerValue, FileSystemCacheContext, + IncrementalCacheValue, IncrementalCachedPageValue, + LegacyIncrementalCachedPageValue, LifespanParameters, CacheHandler as NextCacheHandler, PrerenderManifest, @@ -391,13 +393,15 @@ export class CacheHandler implements NextCacheHandler { try { const pageHtmlPath = path.join(CacheHandler.#serverDistDir, 'pages', `${cacheKey}.html`); const pageDataPath = path.join(CacheHandler.#serverDistDir, 'pages', `${cacheKey}.json`); + const pageKindPath = path.join(CacheHandler.#serverDistDir, 'pages', `${cacheKey}.kind`); pageHtmlHandle = await fsPromises.open(pageHtmlPath, 'r'); - const [pageHtmlFile, { mtimeMs }, pageData] = await Promise.all([ + const [pageHtmlFile, { mtimeMs }, pageData, pageKind] = await Promise.all([ pageHtmlHandle.readFile('utf-8'), pageHtmlHandle.stat(), fsPromises.readFile(pageDataPath, 'utf-8').then((data) => JSON.parse(data) as object), + fsPromises.readFile(pageKindPath, 'utf-8').then((data) => data.trim() as 'PAGES' | 'PAGE'), ]); if (CacheHandler.#debug) { @@ -415,7 +419,7 @@ export class CacheHandler implements NextCacheHandler { lifespan: null, tags: [], value: { - kind: 'PAGE', + kind: pageKind, html: pageHtmlFile, pageData, postponed: undefined, @@ -442,16 +446,21 @@ export class CacheHandler implements NextCacheHandler { return cacheHandlerValue; } - static async #writePagesRouterPage(cacheKey: string, pageData: IncrementalCachedPageValue): Promise { + static async #writePagesRouterPage( + cacheKey: string, + pageData: IncrementalCachedPageValue | LegacyIncrementalCachedPageValue, + ): Promise { try { const pageHtmlPath = path.join(CacheHandler.#serverDistDir, 'pages', `${cacheKey}.html`); const pageDataPath = path.join(CacheHandler.#serverDistDir, 'pages', `${cacheKey}.json`); + const pageKindPath = path.join(CacheHandler.#serverDistDir, 'pages', `${cacheKey}.kind`); await fsPromises.mkdir(path.dirname(pageHtmlPath), { recursive: true }); await Promise.all([ fsPromises.writeFile(pageHtmlPath, pageData.html), fsPromises.writeFile(pageDataPath, JSON.stringify(pageData.pageData)), + fsPromises.writeFile(pageKindPath, pageData.kind), ]); if (CacheHandler.#debug) { @@ -751,8 +760,10 @@ export class CacheHandler implements NextCacheHandler { } } + // @ts-expect-error async get( cacheKey: CacheHandlerParametersGet[0], + // @ts-expect-error ctx: CacheHandlerParametersGet[1] = {}, ): Promise { await CacheHandler.#configureCacheHandler(); @@ -819,13 +830,15 @@ export class CacheHandler implements NextCacheHandler { let cacheHandlerValueTags = tags; - let value = incrementalCacheValue; + let value = incrementalCacheValue as IncrementalCacheValue; switch (value?.kind) { - case 'PAGE': { + case 'PAGE': + case 'APP_PAGE': { cacheHandlerValueTags = getTagsFromHeaders(value.headers ?? {}); break; } + case 'APP_ROUTE': case 'ROUTE': { // create a new object to avoid mutating the original value value = { @@ -852,7 +865,11 @@ export class CacheHandler implements NextCacheHandler { await CacheHandler.#mergedHandler.set(cacheKey, cacheHandlerValue); - if (hasFallbackFalse && cacheHandlerValue.value?.kind === 'PAGE') { + if ( + hasFallbackFalse && + (cacheHandlerValue.value?.kind === 'PAGE' || cacheHandlerValue.value?.kind === 'PAGES') + ) { + // @ts-expect-error await CacheHandler.#writePagesRouterPage(cacheKey, cacheHandlerValue.value); } } diff --git a/packages/cache-handler/src/functions/nesh-cache.ts b/packages/cache-handler/src/functions/nesh-cache.ts index b108639e..5106df0b 100644 --- a/packages/cache-handler/src/functions/nesh-cache.ts +++ b/packages/cache-handler/src/functions/nesh-cache.ts @@ -1,11 +1,13 @@ import assert from 'node:assert/strict'; -import { type IncrementalCacheEntry, NEXT_CACHE_IMPLICIT_TAG_ID, type Revalidate } from '@repo/next-common'; +import type { IncrementalCacheEntry, NextCacheImplicitTagId, Revalidate } from '@repo/next-common'; import { type StaticGenerationStore, staticGenerationAsyncStorage, } from 'next/dist/client/components/static-generation-async-storage.external.js'; import { TIME_ONE_YEAR } from '../constants'; +const NEXT_CACHE_IMPLICIT_TAG_ID: NextCacheImplicitTagId = '_N_T_'; + function getDerivedTags(pathname: string): string[] { const derivedTags: string[] = ['/layout']; @@ -270,6 +272,7 @@ export function neshCache