diff --git a/app/dashboard/users.tsx b/app/dashboard/users.tsx
index bea1789..3e1f502 100644
--- a/app/dashboard/users.tsx
+++ b/app/dashboard/users.tsx
@@ -34,7 +34,7 @@ export default function UserManagement({ session }: UserManagementProps) {
else setMsg("Failed.");
}
- if (session.user.role !== "admin") return null;
+ if (session.user.role !== "ADMIN") return null;
return (
@@ -52,8 +52,8 @@ export default function UserManagement({ session }: UserManagementProps) {
onChange={(e) => setRole(e.target.value)}
>
User
- Admin
- Auditor
+ Admin
+ Auditor
Access Denied
@@ -124,8 +124,8 @@ export default function UserManagementPage() {
onChange={(e) => setRole(e.target.value)}
>
User
- Admin
- Auditor
+ Admin
+ Auditor
@@ -183,9 +183,9 @@ export default function UserManagementPage() {
("");
const [password, setPassword] = useState("");
const [csvUrl, setCsvUrl] = useState("");
- const [role, setRole] = useState("admin"); // Default to admin for company registration
+ const [role, setRole] = useState("ADMIN"); // Default to ADMIN for company registration
const [error, setError] = useState("");
const router = useRouter();
@@ -66,7 +66,7 @@ export default function RegisterPage() {
>
Admin
User
- Auditor
+ Auditor
Register & Continue
diff --git a/jest.config.js b/jest.config.js
new file mode 100644
index 0000000..d85dac8
--- /dev/null
+++ b/jest.config.js
@@ -0,0 +1,22 @@
+/** @type {import('jest').Config} */
+module.exports = {
+ preset: 'ts-jest',
+ testEnvironment: 'node',
+ roots: ['/tests'],
+ testMatch: ['**/__tests__/**/*.ts', '**/?(*.)+(spec|test).ts'],
+ transform: {
+ '^.+\\.ts$': 'ts-jest',
+ },
+ collectCoverageFrom: [
+ 'lib/**/*.ts',
+ '!lib/**/*.d.ts',
+ '!lib/**/*.test.ts',
+ ],
+ coverageDirectory: 'coverage',
+ coverageReporters: ['text', 'lcov', 'html'],
+ setupFilesAfterEnv: ['/tests/setup.ts'],
+ moduleNameMapping: {
+ '^@/(.*)$': '/$1',
+ },
+ testTimeout: 10000,
+};
diff --git a/lib/env.ts b/lib/env.ts
new file mode 100644
index 0000000..3fc827f
--- /dev/null
+++ b/lib/env.ts
@@ -0,0 +1,111 @@
+// Centralized environment variable management
+import { readFileSync } from "fs";
+import { fileURLToPath } from "url";
+import { dirname, join } from "path";
+
+// Load environment variables from .env.local
+const __filename = fileURLToPath(import.meta.url);
+const __dirname = dirname(__filename);
+const envPath = join(__dirname, '..', '.env.local');
+
+// Load .env.local if it exists
+try {
+ const envFile = readFileSync(envPath, 'utf8');
+ const envVars = envFile.split('\n').filter(line => line.trim() && !line.startsWith('#'));
+
+ envVars.forEach(line => {
+ const [key, ...valueParts] = line.split('=');
+ if (key && valueParts.length > 0) {
+ const value = valueParts.join('=').trim();
+ if (!process.env[key.trim()]) {
+ process.env[key.trim()] = value;
+ }
+ }
+ });
+} catch (error) {
+ // Silently fail if .env.local doesn't exist
+}
+
+/**
+ * Typed environment variables with defaults
+ */
+export const env = {
+ // NextAuth
+ NEXTAUTH_URL: process.env.NEXTAUTH_URL || 'http://localhost:3000',
+ NEXTAUTH_SECRET: process.env.NEXTAUTH_SECRET || '',
+ NODE_ENV: process.env.NODE_ENV || 'development',
+
+ // OpenAI
+ OPENAI_API_KEY: process.env.OPENAI_API_KEY || '',
+
+ // Scheduler Configuration
+ SCHEDULER_ENABLED: process.env.SCHEDULER_ENABLED === 'true',
+ CSV_IMPORT_INTERVAL: process.env.CSV_IMPORT_INTERVAL || '*/15 * * * *',
+ IMPORT_PROCESSING_INTERVAL: process.env.IMPORT_PROCESSING_INTERVAL || '*/5 * * * *',
+ IMPORT_PROCESSING_BATCH_SIZE: parseInt(process.env.IMPORT_PROCESSING_BATCH_SIZE || '50', 10),
+ SESSION_PROCESSING_INTERVAL: process.env.SESSION_PROCESSING_INTERVAL || '0 * * * *',
+ SESSION_PROCESSING_BATCH_SIZE: parseInt(process.env.SESSION_PROCESSING_BATCH_SIZE || '0', 10),
+ SESSION_PROCESSING_CONCURRENCY: parseInt(process.env.SESSION_PROCESSING_CONCURRENCY || '5', 10),
+
+ // Server
+ PORT: parseInt(process.env.PORT || '3000', 10),
+} as const;
+
+/**
+ * Validate required environment variables
+ */
+export function validateEnv(): { valid: boolean; errors: string[] } {
+ const errors: string[] = [];
+
+ if (!env.NEXTAUTH_SECRET) {
+ errors.push('NEXTAUTH_SECRET is required');
+ }
+
+ if (!env.OPENAI_API_KEY && env.NODE_ENV === 'production') {
+ errors.push('OPENAI_API_KEY is required in production');
+ }
+
+ return {
+ valid: errors.length === 0,
+ errors,
+ };
+}
+
+/**
+ * Get scheduler configuration from environment variables
+ */
+export function getSchedulerConfig() {
+ return {
+ enabled: env.SCHEDULER_ENABLED,
+ csvImport: {
+ interval: env.CSV_IMPORT_INTERVAL,
+ },
+ importProcessing: {
+ interval: env.IMPORT_PROCESSING_INTERVAL,
+ batchSize: env.IMPORT_PROCESSING_BATCH_SIZE,
+ },
+ sessionProcessing: {
+ interval: env.SESSION_PROCESSING_INTERVAL,
+ batchSize: env.SESSION_PROCESSING_BATCH_SIZE,
+ concurrency: env.SESSION_PROCESSING_CONCURRENCY,
+ },
+ };
+}
+
+/**
+ * Log environment configuration (safe for production)
+ */
+export function logEnvConfig(): void {
+ console.log('[Environment] Configuration:');
+ console.log(` NODE_ENV: ${env.NODE_ENV}`);
+ console.log(` NEXTAUTH_URL: ${env.NEXTAUTH_URL}`);
+ console.log(` SCHEDULER_ENABLED: ${env.SCHEDULER_ENABLED}`);
+ console.log(` PORT: ${env.PORT}`);
+
+ if (env.SCHEDULER_ENABLED) {
+ console.log(' Scheduler intervals:');
+ console.log(` CSV Import: ${env.CSV_IMPORT_INTERVAL}`);
+ console.log(` Import Processing: ${env.IMPORT_PROCESSING_INTERVAL}`);
+ console.log(` Session Processing: ${env.SESSION_PROCESSING_INTERVAL}`);
+ }
+}
diff --git a/lib/importProcessor.ts b/lib/importProcessor.ts
new file mode 100644
index 0000000..7e2e838
--- /dev/null
+++ b/lib/importProcessor.ts
@@ -0,0 +1,225 @@
+// SessionImport to Session processor
+import { PrismaClient, ImportStatus, SentimentCategory } from "@prisma/client";
+import { getSchedulerConfig } from "./env";
+import { fetchTranscriptContent, isValidTranscriptUrl } from "./transcriptFetcher";
+import cron from "node-cron";
+
+const prisma = new PrismaClient();
+
+/**
+ * Process a single SessionImport record into a Session record
+ */
+async function processSingleImport(importRecord: any): Promise<{ success: boolean; error?: string }> {
+ try {
+ // Parse dates
+ const startTime = new Date(importRecord.startTimeRaw);
+ const endTime = new Date(importRecord.endTimeRaw);
+
+ // Validate dates
+ if (isNaN(startTime.getTime()) || isNaN(endTime.getTime())) {
+ throw new Error(`Invalid date format: start=${importRecord.startTimeRaw}, end=${importRecord.endTimeRaw}`);
+ }
+
+ // Process sentiment
+ let sentiment: number | null = null;
+ let sentimentCategory: SentimentCategory | null = null;
+
+ if (importRecord.sentimentRaw) {
+ const sentimentStr = importRecord.sentimentRaw.toLowerCase();
+ if (sentimentStr.includes('positive')) {
+ sentiment = 0.8;
+ sentimentCategory = SentimentCategory.POSITIVE;
+ } else if (sentimentStr.includes('negative')) {
+ sentiment = -0.8;
+ sentimentCategory = SentimentCategory.NEGATIVE;
+ } else {
+ sentiment = 0.0;
+ sentimentCategory = SentimentCategory.NEUTRAL;
+ }
+ }
+
+ // Process boolean fields
+ const escalated = importRecord.escalatedRaw ?
+ ['true', '1', 'yes', 'escalated'].includes(importRecord.escalatedRaw.toLowerCase()) : null;
+
+ const forwardedHr = importRecord.forwardedHrRaw ?
+ ['true', '1', 'yes', 'forwarded'].includes(importRecord.forwardedHrRaw.toLowerCase()) : null;
+
+ // Keep country code as-is, will be processed by OpenAI later
+ const country = importRecord.countryCode;
+
+ // Fetch transcript content if URL is provided and not already fetched
+ let transcriptContent = importRecord.rawTranscriptContent;
+ if (!transcriptContent && importRecord.fullTranscriptUrl && isValidTranscriptUrl(importRecord.fullTranscriptUrl)) {
+ console.log(`[Import Processor] Fetching transcript for ${importRecord.externalSessionId}...`);
+
+ // Get company credentials for transcript fetching
+ const company = await prisma.company.findUnique({
+ where: { id: importRecord.companyId },
+ select: { csvUsername: true, csvPassword: true },
+ });
+
+ const transcriptResult = await fetchTranscriptContent(
+ importRecord.fullTranscriptUrl,
+ company?.csvUsername || undefined,
+ company?.csvPassword || undefined
+ );
+
+ if (transcriptResult.success) {
+ transcriptContent = transcriptResult.content;
+ console.log(`[Import Processor] ✓ Fetched transcript for ${importRecord.externalSessionId} (${transcriptContent?.length} chars)`);
+
+ // Update the import record with the fetched content
+ await prisma.sessionImport.update({
+ where: { id: importRecord.id },
+ data: { rawTranscriptContent: transcriptContent },
+ });
+ } else {
+ console.log(`[Import Processor] ⚠️ Failed to fetch transcript for ${importRecord.externalSessionId}: ${transcriptResult.error}`);
+ }
+ }
+
+ // Create or update Session record
+ const session = await prisma.session.upsert({
+ where: {
+ importId: importRecord.id,
+ },
+ update: {
+ startTime,
+ endTime,
+ ipAddress: importRecord.ipAddress,
+ country,
+ language: importRecord.language,
+ messagesSent: importRecord.messagesSent,
+ sentiment,
+ sentimentCategory,
+ escalated,
+ forwardedHr,
+ fullTranscriptUrl: importRecord.fullTranscriptUrl,
+ avgResponseTime: importRecord.avgResponseTimeSeconds,
+ tokens: importRecord.tokens,
+ tokensEur: importRecord.tokensEur,
+ category: importRecord.category,
+ initialMsg: importRecord.initialMessage,
+ processed: false, // Will be processed later by AI
+ },
+ create: {
+ companyId: importRecord.companyId,
+ importId: importRecord.id,
+ startTime,
+ endTime,
+ ipAddress: importRecord.ipAddress,
+ country,
+ language: importRecord.language,
+ messagesSent: importRecord.messagesSent,
+ sentiment,
+ sentimentCategory,
+ escalated,
+ forwardedHr,
+ fullTranscriptUrl: importRecord.fullTranscriptUrl,
+ avgResponseTime: importRecord.avgResponseTimeSeconds,
+ tokens: importRecord.tokens,
+ tokensEur: importRecord.tokensEur,
+ category: importRecord.category,
+ initialMsg: importRecord.initialMessage,
+ processed: false, // Will be processed later by AI
+ },
+ });
+
+ // Update import status to DONE
+ await prisma.sessionImport.update({
+ where: { id: importRecord.id },
+ data: {
+ status: ImportStatus.DONE,
+ processedAt: new Date(),
+ errorMsg: null,
+ },
+ });
+
+ return { success: true };
+ } catch (error) {
+ // Update import status to ERROR
+ await prisma.sessionImport.update({
+ where: { id: importRecord.id },
+ data: {
+ status: ImportStatus.ERROR,
+ errorMsg: error instanceof Error ? error.message : String(error),
+ },
+ });
+
+ return {
+ success: false,
+ error: error instanceof Error ? error.message : String(error),
+ };
+ }
+}
+
+/**
+ * Process queued SessionImport records into Session records
+ */
+export async function processQueuedImports(batchSize: number = 50): Promise {
+ console.log('[Import Processor] Starting to process queued imports...');
+
+ // Find queued imports
+ const queuedImports = await prisma.sessionImport.findMany({
+ where: {
+ status: ImportStatus.QUEUED,
+ },
+ take: batchSize,
+ orderBy: {
+ createdAt: 'asc', // Process oldest first
+ },
+ });
+
+ if (queuedImports.length === 0) {
+ console.log('[Import Processor] No queued imports found');
+ return;
+ }
+
+ console.log(`[Import Processor] Processing ${queuedImports.length} queued imports...`);
+
+ let successCount = 0;
+ let errorCount = 0;
+
+ // Process each import
+ for (const importRecord of queuedImports) {
+ const result = await processSingleImport(importRecord);
+
+ if (result.success) {
+ successCount++;
+ console.log(`[Import Processor] ✓ Processed import ${importRecord.externalSessionId}`);
+ } else {
+ errorCount++;
+ console.log(`[Import Processor] ✗ Failed to process import ${importRecord.externalSessionId}: ${result.error}`);
+ }
+ }
+
+ console.log(`[Import Processor] Completed: ${successCount} successful, ${errorCount} failed`);
+}
+
+/**
+ * Start the import processing scheduler
+ */
+export function startImportProcessingScheduler(): void {
+ const config = getSchedulerConfig();
+
+ if (!config.enabled) {
+ console.log('[Import Processing Scheduler] Disabled via configuration');
+ return;
+ }
+
+ // Use a more frequent interval for import processing (every 5 minutes by default)
+ const interval = process.env.IMPORT_PROCESSING_INTERVAL || '*/5 * * * *';
+ const batchSize = parseInt(process.env.IMPORT_PROCESSING_BATCH_SIZE || '50', 10);
+
+ console.log(`[Import Processing Scheduler] Starting with interval: ${interval}`);
+ console.log(`[Import Processing Scheduler] Batch size: ${batchSize}`);
+
+ cron.schedule(interval, async () => {
+ try {
+ await processQueuedImports(batchSize);
+ } catch (error) {
+ console.error(`[Import Processing Scheduler] Error: ${error}`);
+ }
+ });
+}
diff --git a/lib/schedulerConfig.ts b/lib/schedulerConfig.ts
index fbb89e8..bffc988 100644
--- a/lib/schedulerConfig.ts
+++ b/lib/schedulerConfig.ts
@@ -1,30 +1,7 @@
-// Unified scheduler configuration
-import { readFileSync } from "fs";
-import { fileURLToPath } from "url";
-import { dirname, join } from "path";
+// Legacy scheduler configuration - now uses centralized env management
+// This file is kept for backward compatibility but delegates to lib/env.ts
-// Load environment variables from .env.local
-const __filename = fileURLToPath(import.meta.url);
-const __dirname = dirname(__filename);
-const envPath = join(__dirname, '..', '.env.local');
-
-// Load .env.local if it exists
-try {
- const envFile = readFileSync(envPath, 'utf8');
- const envVars = envFile.split('\n').filter(line => line.trim() && !line.startsWith('#'));
-
- envVars.forEach(line => {
- const [key, ...valueParts] = line.split('=');
- if (key && valueParts.length > 0) {
- const value = valueParts.join('=').trim();
- if (!process.env[key.trim()]) {
- process.env[key.trim()] = value;
- }
- }
- });
-} catch (error) {
- // Silently fail if .env.local doesn't exist
-}
+import { getSchedulerConfig as getEnvSchedulerConfig, logEnvConfig } from "./env";
export interface SchedulerConfig {
enabled: boolean;
@@ -40,43 +17,28 @@ export interface SchedulerConfig {
/**
* Get scheduler configuration from environment variables
+ * @deprecated Use getSchedulerConfig from lib/env.ts instead
*/
export function getSchedulerConfig(): SchedulerConfig {
- const enabled = process.env.SCHEDULER_ENABLED === 'true';
+ const config = getEnvSchedulerConfig();
- // Default values
- const defaults = {
- csvImportInterval: '*/15 * * * *', // Every 15 minutes
- sessionProcessingInterval: '0 * * * *', // Every hour
- sessionProcessingBatchSize: 0, // Unlimited
- sessionProcessingConcurrency: 5,
- };
-
return {
- enabled,
+ enabled: config.enabled,
csvImport: {
- interval: process.env.CSV_IMPORT_INTERVAL || defaults.csvImportInterval,
+ interval: config.csvImport.interval,
},
sessionProcessing: {
- interval: process.env.SESSION_PROCESSING_INTERVAL || defaults.sessionProcessingInterval,
- batchSize: parseInt(process.env.SESSION_PROCESSING_BATCH_SIZE || '0', 10) || defaults.sessionProcessingBatchSize,
- concurrency: parseInt(process.env.SESSION_PROCESSING_CONCURRENCY || '5', 10) || defaults.sessionProcessingConcurrency,
+ interval: config.sessionProcessing.interval,
+ batchSize: config.sessionProcessing.batchSize,
+ concurrency: config.sessionProcessing.concurrency,
},
};
}
/**
* Log scheduler configuration
+ * @deprecated Use logEnvConfig from lib/env.ts instead
*/
export function logSchedulerConfig(config: SchedulerConfig): void {
- if (!config.enabled) {
- console.log('[Scheduler] Schedulers are DISABLED (SCHEDULER_ENABLED=false)');
- return;
- }
-
- console.log('[Scheduler] Configuration:');
- console.log(` CSV Import: ${config.csvImport.interval}`);
- console.log(` Session Processing: ${config.sessionProcessing.interval}`);
- console.log(` Batch Size: ${config.sessionProcessing.batchSize === 0 ? 'unlimited' : config.sessionProcessing.batchSize}`);
- console.log(` Concurrency: ${config.sessionProcessing.concurrency}`);
+ logEnvConfig();
}
diff --git a/lib/transcriptFetcher.ts b/lib/transcriptFetcher.ts
new file mode 100644
index 0000000..60ddadc
--- /dev/null
+++ b/lib/transcriptFetcher.ts
@@ -0,0 +1,151 @@
+// Transcript fetching utility
+import fetch from "node-fetch";
+
+export interface TranscriptFetchResult {
+ success: boolean;
+ content?: string;
+ error?: string;
+}
+
+/**
+ * Fetch transcript content from a URL
+ * @param url The transcript URL
+ * @param username Optional username for authentication
+ * @param password Optional password for authentication
+ * @returns Promise with fetch result
+ */
+export async function fetchTranscriptContent(
+ url: string,
+ username?: string,
+ password?: string
+): Promise {
+ try {
+ if (!url || !url.trim()) {
+ return {
+ success: false,
+ error: 'No transcript URL provided',
+ };
+ }
+
+ // Prepare authentication header if credentials provided
+ const authHeader =
+ username && password
+ ? "Basic " + Buffer.from(`${username}:${password}`).toString("base64")
+ : undefined;
+
+ const headers: Record = {
+ 'User-Agent': 'LiveDash-Transcript-Fetcher/1.0',
+ };
+
+ if (authHeader) {
+ headers.Authorization = authHeader;
+ }
+
+ // Fetch the transcript with timeout
+ const controller = new AbortController();
+ const timeoutId = setTimeout(() => controller.abort(), 30000); // 30 second timeout
+
+ const response = await fetch(url, {
+ method: 'GET',
+ headers,
+ signal: controller.signal,
+ });
+
+ clearTimeout(timeoutId);
+
+ if (!response.ok) {
+ return {
+ success: false,
+ error: `HTTP ${response.status}: ${response.statusText}`,
+ };
+ }
+
+ const content = await response.text();
+
+ if (!content || content.trim().length === 0) {
+ return {
+ success: false,
+ error: 'Empty transcript content',
+ };
+ }
+
+ return {
+ success: true,
+ content: content.trim(),
+ };
+
+ } catch (error) {
+ const errorMessage = error instanceof Error ? error.message : String(error);
+
+ // Handle common network errors
+ if (errorMessage.includes('ENOTFOUND')) {
+ return {
+ success: false,
+ error: 'Domain not found',
+ };
+ }
+
+ if (errorMessage.includes('ECONNREFUSED')) {
+ return {
+ success: false,
+ error: 'Connection refused',
+ };
+ }
+
+ if (errorMessage.includes('timeout')) {
+ return {
+ success: false,
+ error: 'Request timeout',
+ };
+ }
+
+ return {
+ success: false,
+ error: errorMessage,
+ };
+ }
+}
+
+/**
+ * Validate if a URL looks like a valid transcript URL
+ * @param url The URL to validate
+ * @returns boolean indicating if URL appears valid
+ */
+export function isValidTranscriptUrl(url: string): boolean {
+ if (!url || typeof url !== 'string') {
+ return false;
+ }
+
+ try {
+ const parsedUrl = new URL(url);
+ return parsedUrl.protocol === 'http:' || parsedUrl.protocol === 'https:';
+ } catch {
+ return false;
+ }
+}
+
+/**
+ * Extract session ID from transcript content if possible
+ * This is a helper function that can be enhanced based on transcript format
+ * @param content The transcript content
+ * @returns Extracted session ID or null
+ */
+export function extractSessionIdFromTranscript(content: string): string | null {
+ if (!content) return null;
+
+ // Look for common session ID patterns
+ const patterns = [
+ /session[_-]?id[:\s]*([a-zA-Z0-9-]+)/i,
+ /id[:\s]*([a-zA-Z0-9-]{8,})/i,
+ /^([a-zA-Z0-9-]{8,})/m, // First line might be session ID
+ ];
+
+ for (const pattern of patterns) {
+ const match = content.match(pattern);
+ if (match && match[1]) {
+ return match[1].trim();
+ }
+ }
+
+ return null;
+}
diff --git a/package.json b/package.json
index 2d2ccb5..b0a1417 100644
--- a/package.json
+++ b/package.json
@@ -18,6 +18,9 @@
"prisma:push:force": "prisma db push --force-reset",
"prisma:studio": "prisma studio",
"start": "node server.mjs",
+ "test": "jest",
+ "test:watch": "jest --watch",
+ "test:coverage": "jest --coverage",
"lint:md": "markdownlint-cli2 \"**/*.md\" \"!.trunk/**\" \"!.venv/**\" \"!node_modules/**\"",
"lint:md:fix": "markdownlint-cli2 --fix \"**/*.md\" \"!.trunk/**\" \"!.venv/**\" \"!node_modules/**\""
},
@@ -54,9 +57,11 @@
"devDependencies": {
"@eslint/eslintrc": "^3.3.1",
"@eslint/js": "^9.27.0",
+ "@jest/globals": "^30.0.3",
"@playwright/test": "^1.52.0",
"@tailwindcss/postcss": "^4.1.7",
"@types/bcryptjs": "^2.4.2",
+ "@types/jest": "^30.0.0",
"@types/node": "^22.15.21",
"@types/node-cron": "^3.0.8",
"@types/react": "^19.1.5",
@@ -66,12 +71,14 @@
"eslint": "^9.27.0",
"eslint-config-next": "^15.3.2",
"eslint-plugin-prettier": "^5.4.0",
+ "jest": "^30.0.3",
"markdownlint-cli2": "^0.18.1",
"postcss": "^8.5.3",
"prettier": "^3.5.3",
"prettier-plugin-jinja-template": "^2.1.0",
"prisma": "^6.10.1",
"tailwindcss": "^4.1.7",
+ "ts-jest": "^29.4.0",
"ts-node": "^10.9.2",
"tsx": "^4.20.3",
"typescript": "^5.0.0"
diff --git a/pages/api/admin/refresh-sessions.ts b/pages/api/admin/refresh-sessions.ts
index f57377d..08a47d6 100644
--- a/pages/api/admin/refresh-sessions.ts
+++ b/pages/api/admin/refresh-sessions.ts
@@ -1,6 +1,7 @@
// API route to refresh (fetch+parse+update) session data for a company
import { NextApiRequest, NextApiResponse } from "next";
import { fetchAndParseCsv } from "../../../lib/csvFetcher";
+import { processQueuedImports } from "../../../lib/importProcessor";
import { prisma } from "../../../lib/prisma";
export default async function handler(
@@ -113,11 +114,21 @@ export default async function handler(
}
}
+ // Immediately process the queued imports to create Session records
+ console.log('[Refresh API] Processing queued imports...');
+ await processQueuedImports(100); // Process up to 100 imports immediately
+
+ // Count how many sessions were created
+ const sessionCount = await prisma.session.count({
+ where: { companyId: company.id }
+ });
+
res.json({
ok: true,
imported: importedCount,
total: rawSessionData.length,
- message: `Successfully imported ${importedCount} session records to SessionImport table`
+ sessions: sessionCount,
+ message: `Successfully imported ${importedCount} records and processed them into sessions. Total sessions: ${sessionCount}`
});
} catch (e) {
const error = e instanceof Error ? e.message : "An unknown error occurred";
diff --git a/pages/api/admin/trigger-processing.ts b/pages/api/admin/trigger-processing.ts
index 64fca6e..9d9e428 100644
--- a/pages/api/admin/trigger-processing.ts
+++ b/pages/api/admin/trigger-processing.ts
@@ -40,7 +40,7 @@ export default async function handler(
return res.status(401).json({ error: "No user found" });
}
- // Check if user has admin role
+ // Check if user has ADMIN role
if (user.role !== "ADMIN") {
return res.status(403).json({ error: "Admin access required" });
}
diff --git a/pages/api/dashboard/settings.ts b/pages/api/dashboard/settings.ts
index e0b6c0d..5bd33f8 100644
--- a/pages/api/dashboard/settings.ts
+++ b/pages/api/dashboard/settings.ts
@@ -8,7 +8,7 @@ export default async function handler(
res: NextApiResponse
) {
const session = await getServerSession(req, res, authOptions);
- if (!session?.user || session.user.role !== "admin")
+ if (!session?.user || session.user.role !== "ADMIN")
return res.status(403).json({ error: "Forbidden" });
const user = await prisma.user.findUnique({
diff --git a/pages/api/dashboard/users.ts b/pages/api/dashboard/users.ts
index 97ef027..dcdcc6f 100644
--- a/pages/api/dashboard/users.ts
+++ b/pages/api/dashboard/users.ts
@@ -17,7 +17,7 @@ export default async function handler(
res: NextApiResponse
) {
const session = await getServerSession(req, res, authOptions);
- if (!session?.user || session.user.role !== "admin")
+ if (!session?.user || session.user.role !== "ADMIN")
return res.status(403).json({ error: "Forbidden" });
const user = await prisma.user.findUnique({
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index c0b507f..96735e0 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -64,10 +64,10 @@ importers:
version: 1.9.4
next:
specifier: ^15.3.2
- version: 15.3.2(@playwright/test@1.52.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ version: 15.3.2(@babel/core@7.27.7)(@playwright/test@1.52.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
next-auth:
specifier: ^4.24.11
- version: 4.24.11(next@15.3.2(@playwright/test@1.52.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ version: 4.24.11(next@15.3.2(@babel/core@7.27.7)(@playwright/test@1.52.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
node-cron:
specifier: ^4.0.7
version: 4.0.7
@@ -99,6 +99,9 @@ importers:
'@eslint/js':
specifier: ^9.27.0
version: 9.27.0
+ '@jest/globals':
+ specifier: ^30.0.3
+ version: 30.0.3
'@playwright/test':
specifier: ^1.52.0
version: 1.52.0
@@ -108,6 +111,9 @@ importers:
'@types/bcryptjs':
specifier: ^2.4.2
version: 2.4.6
+ '@types/jest':
+ specifier: ^30.0.0
+ version: 30.0.0
'@types/node':
specifier: ^22.15.21
version: 22.15.21
@@ -135,6 +141,9 @@ importers:
eslint-plugin-prettier:
specifier: ^5.4.0
version: 5.4.0(eslint@9.27.0(jiti@2.4.2))(prettier@3.5.3)
+ jest:
+ specifier: ^30.0.3
+ version: 30.0.3(@types/node@22.15.21)(ts-node@10.9.2(@types/node@22.15.21)(typescript@5.8.3))
markdownlint-cli2:
specifier: ^0.18.1
version: 0.18.1
@@ -153,6 +162,9 @@ importers:
tailwindcss:
specifier: ^4.1.7
version: 4.1.7
+ ts-jest:
+ specifier: ^29.4.0
+ version: 29.4.0(@babel/core@7.27.7)(@jest/transform@30.0.2)(@jest/types@30.0.1)(babel-jest@30.0.2(@babel/core@7.27.7))(jest-util@30.0.2)(jest@30.0.3(@types/node@22.15.21)(ts-node@10.9.2(@types/node@22.15.21)(typescript@5.8.3)))(typescript@5.8.3)
ts-node:
specifier: ^10.9.2
version: 10.9.2(@types/node@22.15.21)(typescript@5.8.3)
@@ -173,10 +185,171 @@ packages:
resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==}
engines: {node: '>=6.0.0'}
+ '@babel/code-frame@7.27.1':
+ resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/compat-data@7.27.7':
+ resolution: {integrity: sha512-xgu/ySj2mTiUFmdE9yCMfBxLp4DHd5DwmbbD05YAuICfodYT3VvRxbrh81LGQ/8UpSdtMdfKMn3KouYDX59DGQ==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/core@7.27.7':
+ resolution: {integrity: sha512-BU2f9tlKQ5CAthiMIgpzAh4eDTLWo1mqi9jqE2OxMG0E/OM199VJt2q8BztTxpnSW0i1ymdwLXRJnYzvDM5r2w==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/generator@7.27.5':
+ resolution: {integrity: sha512-ZGhA37l0e/g2s1Cnzdix0O3aLYm66eF8aufiVteOgnwxgnRP8GoyMj7VWsgWnQbVKXyge7hqrFh2K2TQM6t1Hw==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helper-compilation-targets@7.27.2':
+ resolution: {integrity: sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helper-module-imports@7.27.1':
+ resolution: {integrity: sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helper-module-transforms@7.27.3':
+ resolution: {integrity: sha512-dSOvYwvyLsWBeIRyOeHXp5vPj5l1I011r52FM1+r1jCERv+aFXYk4whgQccYEGYxK2H3ZAIA8nuPkQ0HaUo3qg==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0
+
+ '@babel/helper-plugin-utils@7.27.1':
+ resolution: {integrity: sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helper-string-parser@7.27.1':
+ resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helper-validator-identifier@7.27.1':
+ resolution: {integrity: sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helper-validator-option@7.27.1':
+ resolution: {integrity: sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helpers@7.27.6':
+ resolution: {integrity: sha512-muE8Tt8M22638HU31A3CgfSUciwz1fhATfoVai05aPXGor//CdWDCbnlY1yvBPo07njuVOCNGCSp/GTt12lIug==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/parser@7.27.7':
+ resolution: {integrity: sha512-qnzXzDXdr/po3bOTbTIQZ7+TxNKxpkN5IifVLXS+r7qwynkZfPyjZfE7hCXbo7IoO9TNcSyibgONsf2HauUd3Q==}
+ engines: {node: '>=6.0.0'}
+ hasBin: true
+
+ '@babel/plugin-syntax-async-generators@7.8.4':
+ resolution: {integrity: sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-syntax-bigint@7.8.3':
+ resolution: {integrity: sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-syntax-class-properties@7.12.13':
+ resolution: {integrity: sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-syntax-class-static-block@7.14.5':
+ resolution: {integrity: sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-syntax-import-attributes@7.27.1':
+ resolution: {integrity: sha512-oFT0FrKHgF53f4vOsZGi2Hh3I35PfSmVs4IBFLFj4dnafP+hIWDLg3VyKmUHfLoLHlyxY4C7DGtmHuJgn+IGww==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-syntax-import-meta@7.10.4':
+ resolution: {integrity: sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-syntax-json-strings@7.8.3':
+ resolution: {integrity: sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-syntax-jsx@7.27.1':
+ resolution: {integrity: sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-syntax-logical-assignment-operators@7.10.4':
+ resolution: {integrity: sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3':
+ resolution: {integrity: sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-syntax-numeric-separator@7.10.4':
+ resolution: {integrity: sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-syntax-object-rest-spread@7.8.3':
+ resolution: {integrity: sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-syntax-optional-catch-binding@7.8.3':
+ resolution: {integrity: sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-syntax-optional-chaining@7.8.3':
+ resolution: {integrity: sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-syntax-private-property-in-object@7.14.5':
+ resolution: {integrity: sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-syntax-top-level-await@7.14.5':
+ resolution: {integrity: sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-syntax-typescript@7.27.1':
+ resolution: {integrity: sha512-xfYCBMxveHrRMnAWl1ZlPXOZjzkN82THFvLhQhFXFt81Z5HnN+EtUkZhv/zcKpmT3fzmWZB0ywiBrbC3vogbwQ==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
'@babel/runtime@7.27.1':
resolution: {integrity: sha512-1x3D2xEk2fRo3PAhwQwu5UubzgiVWSXTBfWpVd2Mx2AzRqJuDJCsgaDVZ7HB5iGzDW1Hl1sWN2mFyKjmR9uAog==}
engines: {node: '>=6.9.0'}
+ '@babel/template@7.27.2':
+ resolution: {integrity: sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/traverse@7.27.7':
+ resolution: {integrity: sha512-X6ZlfR/O/s5EQ/SnUSLzr+6kGnkg8HXGMzpgsMsrJVcfDtH1vIp6ctCN4eZ1LS5c0+te5Cb6Y514fASjMRJ1nw==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/types@7.27.7':
+ resolution: {integrity: sha512-8OLQgDScAOHXnAz2cV+RfzzNMipuLVBz2biuAJFMV9bfkNf393je3VM8CLkjQodW5+iWsSJdSgSWT6rsZoXHPw==}
+ engines: {node: '>=6.9.0'}
+
+ '@bcoe/v8-coverage@0.2.3':
+ resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==}
+
'@cspotcode/source-map-support@0.8.1':
resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==}
engines: {node: '>=12'}
@@ -514,10 +687,104 @@ packages:
cpu: [x64]
os: [win32]
+ '@isaacs/cliui@8.0.2':
+ resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==}
+ engines: {node: '>=12'}
+
'@isaacs/fs-minipass@4.0.1':
resolution: {integrity: sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==}
engines: {node: '>=18.0.0'}
+ '@istanbuljs/load-nyc-config@1.1.0':
+ resolution: {integrity: sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==}
+ engines: {node: '>=8'}
+
+ '@istanbuljs/schema@0.1.3':
+ resolution: {integrity: sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==}
+ engines: {node: '>=8'}
+
+ '@jest/console@30.0.2':
+ resolution: {integrity: sha512-krGElPU0FipAqpVZ/BRZOy0MZh/ARdJ0Nj+PiH1ykFY1+VpBlYNLjdjVA5CFKxnKR6PFqFutO4Z7cdK9BlGiDA==}
+ engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
+
+ '@jest/core@30.0.3':
+ resolution: {integrity: sha512-Mgs1N+NSHD3Fusl7bOq1jyxv1JDAUwjy+0DhVR93Q6xcBP9/bAQ+oZhXb5TTnP5sQzAHgb7ROCKQ2SnovtxYtg==}
+ engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
+ peerDependencies:
+ node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0
+ peerDependenciesMeta:
+ node-notifier:
+ optional: true
+
+ '@jest/diff-sequences@30.0.1':
+ resolution: {integrity: sha512-n5H8QLDJ47QqbCNn5SuFjCRDrOLEZ0h8vAHCK5RL9Ls7Xa8AQLa/YxAc9UjFqoEDM48muwtBGjtMY5cr0PLDCw==}
+ engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
+
+ '@jest/environment@30.0.2':
+ resolution: {integrity: sha512-hRLhZRJNxBiOhxIKSq2UkrlhMt3/zVFQOAi5lvS8T9I03+kxsbflwHJEF+eXEYXCrRGRhHwECT7CDk6DyngsRA==}
+ engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
+
+ '@jest/expect-utils@30.0.3':
+ resolution: {integrity: sha512-SMtBvf2sfX2agcT0dA9pXwcUrKvOSDqBY4e4iRfT+Hya33XzV35YVg+98YQFErVGA/VR1Gto5Y2+A6G9LSQ3Yg==}
+ engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
+
+ '@jest/expect@30.0.3':
+ resolution: {integrity: sha512-73BVLqfCeWjYWPEQoYjiRZ4xuQRhQZU0WdgvbyXGRHItKQqg5e6mt2y1kVhzLSuZpmUnccZHbGynoaL7IcLU3A==}
+ engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
+
+ '@jest/fake-timers@30.0.2':
+ resolution: {integrity: sha512-jfx0Xg7l0gmphTY9UKm5RtH12BlLYj/2Plj6wXjVW5Era4FZKfXeIvwC67WX+4q8UCFxYS20IgnMcFBcEU0DtA==}
+ engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
+
+ '@jest/get-type@30.0.1':
+ resolution: {integrity: sha512-AyYdemXCptSRFirI5EPazNxyPwAL0jXt3zceFjaj8NFiKP9pOi0bfXonf6qkf82z2t3QWPeLCWWw4stPBzctLw==}
+ engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
+
+ '@jest/globals@30.0.3':
+ resolution: {integrity: sha512-fIduqNyYpMeeSr5iEAiMn15KxCzvrmxl7X7VwLDRGj7t5CoHtbF+7K3EvKk32mOUIJ4kIvFRlaixClMH2h/Vaw==}
+ engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
+
+ '@jest/pattern@30.0.1':
+ resolution: {integrity: sha512-gWp7NfQW27LaBQz3TITS8L7ZCQ0TLvtmI//4OwlQRx4rnWxcPNIYjxZpDcN4+UlGxgm3jS5QPz8IPTCkb59wZA==}
+ engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
+
+ '@jest/reporters@30.0.2':
+ resolution: {integrity: sha512-l4QzS/oKf57F8WtPZK+vvF4Io6ukplc6XgNFu4Hd/QxaLEO9f+8dSFzUua62Oe0HKlCUjKHpltKErAgDiMJKsA==}
+ engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
+ peerDependencies:
+ node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0
+ peerDependenciesMeta:
+ node-notifier:
+ optional: true
+
+ '@jest/schemas@30.0.1':
+ resolution: {integrity: sha512-+g/1TKjFuGrf1Hh0QPCv0gISwBxJ+MQSNXmG9zjHy7BmFhtoJ9fdNhWJp3qUKRi93AOZHXtdxZgJ1vAtz6z65w==}
+ engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
+
+ '@jest/snapshot-utils@30.0.1':
+ resolution: {integrity: sha512-6Dpv7vdtoRiISEFwYF8/c7LIvqXD7xDXtLPNzC2xqAfBznKip0MQM+rkseKwUPUpv2PJ7KW/YsnwWXrIL2xF+A==}
+ engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
+
+ '@jest/source-map@30.0.1':
+ resolution: {integrity: sha512-MIRWMUUR3sdbP36oyNyhbThLHyJ2eEDClPCiHVbrYAe5g3CHRArIVpBw7cdSB5fr+ofSfIb2Tnsw8iEHL0PYQg==}
+ engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
+
+ '@jest/test-result@30.0.2':
+ resolution: {integrity: sha512-KKMuBKkkZYP/GfHMhI+cH2/P3+taMZS3qnqqiPC1UXZTJskkCS+YU/ILCtw5anw1+YsTulDHFpDo70mmCedW8w==}
+ engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
+
+ '@jest/test-sequencer@30.0.2':
+ resolution: {integrity: sha512-fbyU5HPka0rkalZ3MXVvq0hwZY8dx3Y6SCqR64zRmh+xXlDeFl0IdL4l9e7vp4gxEXTYHbwLFA1D+WW5CucaSw==}
+ engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
+
+ '@jest/transform@30.0.2':
+ resolution: {integrity: sha512-kJIuhLMTxRF7sc0gPzPtCDib/V9KwW3I2U25b+lYCYMVqHHSrcZopS8J8H+znx9yixuFv+Iozl8raLt/4MoxrA==}
+ engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
+
+ '@jest/types@30.0.1':
+ resolution: {integrity: sha512-HGwoYRVF0QSKJu1ZQX0o5ZrUrrhj0aOOFA8hXrumD7SIzjouevhawbTjmXdwOmURdGluU9DM/XvGm3NyFoiQjw==}
+ engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
+
'@jridgewell/gen-mapping@0.3.8':
resolution: {integrity: sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==}
engines: {node: '>=6.0.0'}
@@ -545,6 +812,9 @@ packages:
'@napi-rs/wasm-runtime@0.2.10':
resolution: {integrity: sha512-bCsCyeZEwVErsGmyPNSzwfwFn4OdxBj0mmv6hOFucB/k81Ojdu68RbZdxYsRQUPc9l6SU5F/cG+bXgWs3oUgsQ==}
+ '@napi-rs/wasm-runtime@0.2.11':
+ resolution: {integrity: sha512-9DPkXtvHydrcOsopiYpUgPHpmj0HWZKMUnL2dZqpvC42lsratuBG06V5ipyno0fUek5VlFsNQ+AcFATSrJXgMA==}
+
'@next/env@15.3.2':
resolution: {integrity: sha512-xURk++7P7qR9JG1jJtLzPzf0qEvqCN0A/T3DXf8IPMKo9/6FfjxtEffRJIIew/bIL4T3C2jLLqBor8B/zVlx6g==}
@@ -618,6 +888,10 @@ packages:
'@panva/hkdf@1.2.1':
resolution: {integrity: sha512-6oclG6Y3PiDFcoyk8srjLfVKyMfVCKJ27JwNPViuXziFpmdz+MZnZN/aKY0JGXgYuO/VghU0jcOAZgWXZ1Dmrw==}
+ '@pkgjs/parseargs@0.11.0':
+ resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==}
+ engines: {node: '>=14'}
+
'@pkgr/core@0.2.4':
resolution: {integrity: sha512-ROFF39F6ZrnzSUEmQQZUar0Jt4xVoP9WnDRdWwF4NNcXs3xBTLgBUDoOwW141y1jP+S8nahIbdxbFC7IShw9Iw==}
engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0}
@@ -674,10 +948,19 @@ packages:
'@rushstack/eslint-patch@1.11.0':
resolution: {integrity: sha512-zxnHvoMQVqewTJr/W4pKjF0bMGiKJv1WX7bSrkl46Hg0QjESbzBROWK0Wg4RphzSOS5Jiy7eFimmM3UgMrMZbQ==}
+ '@sinclair/typebox@0.34.37':
+ resolution: {integrity: sha512-2TRuQVgQYfy+EzHRTIvkhv2ADEouJ2xNS/Vq+W5EuuewBdOrvATvljZTxHWZSTYr2sTjTHpGvucaGAt67S2akw==}
+
'@sindresorhus/merge-streams@2.3.0':
resolution: {integrity: sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==}
engines: {node: '>=18'}
+ '@sinonjs/commons@3.0.1':
+ resolution: {integrity: sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==}
+
+ '@sinonjs/fake-timers@13.0.5':
+ resolution: {integrity: sha512-36/hTbH2uaWuGVERyC6da9YwGWnzUZXuPro/F2LfsdOsLnCojz/iSH8MxUt/FD2S5XBSVPhmArFUXcpCQ2Hkiw==}
+
'@swc/counter@0.1.3':
resolution: {integrity: sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==}
@@ -787,6 +1070,18 @@ packages:
'@tybys/wasm-util@0.9.0':
resolution: {integrity: sha512-6+7nlbMVX/PVDCwaIQ8nTOPveOcFLSt8GcXdx8hD0bt39uWxYT88uXzqTd4fTvqta7oeUJqudepapKNt2DYJFw==}
+ '@types/babel__core@7.20.5':
+ resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==}
+
+ '@types/babel__generator@7.27.0':
+ resolution: {integrity: sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==}
+
+ '@types/babel__template@7.4.4':
+ resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==}
+
+ '@types/babel__traverse@7.20.7':
+ resolution: {integrity: sha512-dkO5fhS7+/oos4ciWxyEyjWe48zmG6wbCheo/G2ZnHx4fs3EU6YC6UM8rk56gAjNJ9P3MTH2jo5jb92/K6wbng==}
+
'@types/bcryptjs@2.4.6':
resolution: {integrity: sha512-9xlo6R2qDs5uixm0bcIqCeMCE6HiQsIyel9KQySStiyqNl2tnj2mP3DX1Nf56MD6KMenNNlBBsy3LJ7gUEQPXQ==}
@@ -904,6 +1199,18 @@ packages:
'@types/hast@3.0.4':
resolution: {integrity: sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==}
+ '@types/istanbul-lib-coverage@2.0.6':
+ resolution: {integrity: sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==}
+
+ '@types/istanbul-lib-report@3.0.3':
+ resolution: {integrity: sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==}
+
+ '@types/istanbul-reports@3.0.4':
+ resolution: {integrity: sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==}
+
+ '@types/jest@30.0.0':
+ resolution: {integrity: sha512-XTYugzhuwqWjws0CVz8QpM36+T+Dz5mTEBKhNs/esGLnCIlGdRy+Dq78NRjd7ls7r8BC8ZRMOrKlkO1hU0JOwA==}
+
'@types/json-schema@7.0.15':
resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==}
@@ -939,12 +1246,21 @@ packages:
'@types/react@19.1.5':
resolution: {integrity: sha512-piErsCVVbpMMT2r7wbawdZsq4xMvIAhQuac2gedQHysu1TZYEigE6pnFfgZT+/jQnrRuF5r+SHzuehFjfRjr4g==}
+ '@types/stack-utils@2.0.3':
+ resolution: {integrity: sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==}
+
'@types/unist@2.0.11':
resolution: {integrity: sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==}
'@types/unist@3.0.3':
resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==}
+ '@types/yargs-parser@21.0.3':
+ resolution: {integrity: sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==}
+
+ '@types/yargs@17.0.33':
+ resolution: {integrity: sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==}
+
'@typescript-eslint/eslint-plugin@8.32.1':
resolution: {integrity: sha512-6u6Plg9nP/J1GRpe/vcjjabo6Uc5YQPAMxsgQyGC/I0RuukiG1wIe3+Vtg3IrSCVJDmqK3j8adrtzXSENRtFgg==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
@@ -995,91 +1311,186 @@ packages:
'@ungap/structured-clone@1.3.0':
resolution: {integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==}
+ '@unrs/resolver-binding-android-arm-eabi@1.9.2':
+ resolution: {integrity: sha512-tS+lqTU3N0kkthU+rYp0spAYq15DU8ld9kXkaKg9sbQqJNF+WPMuNHZQGCgdxrUOEO0j22RKMwRVhF1HTl+X8A==}
+ cpu: [arm]
+ os: [android]
+
+ '@unrs/resolver-binding-android-arm64@1.9.2':
+ resolution: {integrity: sha512-MffGiZULa/KmkNjHeuuflLVqfhqLv1vZLm8lWIyeADvlElJ/GLSOkoUX+5jf4/EGtfwrNFcEaB8BRas03KT0/Q==}
+ cpu: [arm64]
+ os: [android]
+
'@unrs/resolver-binding-darwin-arm64@1.7.2':
resolution: {integrity: sha512-vxtBno4xvowwNmO/ASL0Y45TpHqmNkAaDtz4Jqb+clmcVSSl8XCG/PNFFkGsXXXS6AMjP+ja/TtNCFFa1QwLRg==}
cpu: [arm64]
os: [darwin]
+ '@unrs/resolver-binding-darwin-arm64@1.9.2':
+ resolution: {integrity: sha512-dzJYK5rohS1sYl1DHdJ3mwfwClJj5BClQnQSyAgEfggbUwA9RlROQSSbKBLqrGfsiC/VyrDPtbO8hh56fnkbsQ==}
+ cpu: [arm64]
+ os: [darwin]
+
'@unrs/resolver-binding-darwin-x64@1.7.2':
resolution: {integrity: sha512-qhVa8ozu92C23Hsmv0BF4+5Dyyd5STT1FolV4whNgbY6mj3kA0qsrGPe35zNR3wAN7eFict3s4Rc2dDTPBTuFQ==}
cpu: [x64]
os: [darwin]
+ '@unrs/resolver-binding-darwin-x64@1.9.2':
+ resolution: {integrity: sha512-gaIMWK+CWtXcg9gUyznkdV54LzQ90S3X3dn8zlh+QR5Xy7Y+Efqw4Rs4im61K1juy4YNb67vmJsCDAGOnIeffQ==}
+ cpu: [x64]
+ os: [darwin]
+
'@unrs/resolver-binding-freebsd-x64@1.7.2':
resolution: {integrity: sha512-zKKdm2uMXqLFX6Ac7K5ElnnG5VIXbDlFWzg4WJ8CGUedJryM5A3cTgHuGMw1+P5ziV8CRhnSEgOnurTI4vpHpg==}
cpu: [x64]
os: [freebsd]
+ '@unrs/resolver-binding-freebsd-x64@1.9.2':
+ resolution: {integrity: sha512-S7QpkMbVoVJb0xwHFwujnwCAEDe/596xqY603rpi/ioTn9VDgBHnCCxh+UFrr5yxuMH+dliHfjwCZJXOPJGPnw==}
+ cpu: [x64]
+ os: [freebsd]
+
'@unrs/resolver-binding-linux-arm-gnueabihf@1.7.2':
resolution: {integrity: sha512-8N1z1TbPnHH+iDS/42GJ0bMPLiGK+cUqOhNbMKtWJ4oFGzqSJk/zoXFzcQkgtI63qMcUI7wW1tq2usZQSb2jxw==}
cpu: [arm]
os: [linux]
+ '@unrs/resolver-binding-linux-arm-gnueabihf@1.9.2':
+ resolution: {integrity: sha512-+XPUMCuCCI80I46nCDFbGum0ZODP5NWGiwS3Pj8fOgsG5/ctz+/zzuBlq/WmGa+EjWZdue6CF0aWWNv84sE1uw==}
+ cpu: [arm]
+ os: [linux]
+
'@unrs/resolver-binding-linux-arm-musleabihf@1.7.2':
resolution: {integrity: sha512-tjYzI9LcAXR9MYd9rO45m1s0B/6bJNuZ6jeOxo1pq1K6OBuRMMmfyvJYval3s9FPPGmrldYA3mi4gWDlWuTFGA==}
cpu: [arm]
os: [linux]
+ '@unrs/resolver-binding-linux-arm-musleabihf@1.9.2':
+ resolution: {integrity: sha512-sqvUyAd1JUpwbz33Ce2tuTLJKM+ucSsYpPGl2vuFwZnEIg0CmdxiZ01MHQ3j6ExuRqEDUCy8yvkDKvjYFPb8Zg==}
+ cpu: [arm]
+ os: [linux]
+
'@unrs/resolver-binding-linux-arm64-gnu@1.7.2':
resolution: {integrity: sha512-jon9M7DKRLGZ9VYSkFMflvNqu9hDtOCEnO2QAryFWgT6o6AXU8du56V7YqnaLKr6rAbZBWYsYpikF226v423QA==}
cpu: [arm64]
os: [linux]
+ '@unrs/resolver-binding-linux-arm64-gnu@1.9.2':
+ resolution: {integrity: sha512-UYA0MA8ajkEDCFRQdng/FVx3F6szBvk3EPnkTTQuuO9lV1kPGuTB+V9TmbDxy5ikaEgyWKxa4CI3ySjklZ9lFA==}
+ cpu: [arm64]
+ os: [linux]
+
'@unrs/resolver-binding-linux-arm64-musl@1.7.2':
resolution: {integrity: sha512-c8Cg4/h+kQ63pL43wBNaVMmOjXI/X62wQmru51qjfTvI7kmCy5uHTJvK/9LrF0G8Jdx8r34d019P1DVJmhXQpA==}
cpu: [arm64]
os: [linux]
+ '@unrs/resolver-binding-linux-arm64-musl@1.9.2':
+ resolution: {integrity: sha512-P/CO3ODU9YJIHFqAkHbquKtFst0COxdphc8TKGL5yCX75GOiVpGqd1d15ahpqu8xXVsqP4MGFP2C3LRZnnL5MA==}
+ cpu: [arm64]
+ os: [linux]
+
'@unrs/resolver-binding-linux-ppc64-gnu@1.7.2':
resolution: {integrity: sha512-A+lcwRFyrjeJmv3JJvhz5NbcCkLQL6Mk16kHTNm6/aGNc4FwPHPE4DR9DwuCvCnVHvF5IAd9U4VIs/VvVir5lg==}
cpu: [ppc64]
os: [linux]
+ '@unrs/resolver-binding-linux-ppc64-gnu@1.9.2':
+ resolution: {integrity: sha512-uKStFlOELBxBum2s1hODPtgJhY4NxYJE9pAeyBgNEzHgTqTiVBPjfTlPFJkfxyTjQEuxZbbJlJnMCrRgD7ubzw==}
+ cpu: [ppc64]
+ os: [linux]
+
'@unrs/resolver-binding-linux-riscv64-gnu@1.7.2':
resolution: {integrity: sha512-hQQ4TJQrSQW8JlPm7tRpXN8OCNP9ez7PajJNjRD1ZTHQAy685OYqPrKjfaMw/8LiHCt8AZ74rfUVHP9vn0N69Q==}
cpu: [riscv64]
os: [linux]
+ '@unrs/resolver-binding-linux-riscv64-gnu@1.9.2':
+ resolution: {integrity: sha512-LkbNnZlhINfY9gK30AHs26IIVEZ9PEl9qOScYdmY2o81imJYI4IMnJiW0vJVtXaDHvBvxeAgEy5CflwJFIl3tQ==}
+ cpu: [riscv64]
+ os: [linux]
+
'@unrs/resolver-binding-linux-riscv64-musl@1.7.2':
resolution: {integrity: sha512-NoAGbiqrxtY8kVooZ24i70CjLDlUFI7nDj3I9y54U94p+3kPxwd2L692YsdLa+cqQ0VoqMWoehDFp21PKRUoIQ==}
cpu: [riscv64]
os: [linux]
+ '@unrs/resolver-binding-linux-riscv64-musl@1.9.2':
+ resolution: {integrity: sha512-vI+e6FzLyZHSLFNomPi+nT+qUWN4YSj8pFtQZSFTtmgFoxqB6NyjxSjAxEC1m93qn6hUXhIsh8WMp+fGgxCoRg==}
+ cpu: [riscv64]
+ os: [linux]
+
'@unrs/resolver-binding-linux-s390x-gnu@1.7.2':
resolution: {integrity: sha512-KaZByo8xuQZbUhhreBTW+yUnOIHUsv04P8lKjQ5otiGoSJ17ISGYArc+4vKdLEpGaLbemGzr4ZeUbYQQsLWFjA==}
cpu: [s390x]
os: [linux]
+ '@unrs/resolver-binding-linux-s390x-gnu@1.9.2':
+ resolution: {integrity: sha512-sSO4AlAYhSM2RAzBsRpahcJB1msc6uYLAtP6pesPbZtptF8OU/CbCPhSRW6cnYOGuVmEmWVW5xVboAqCnWTeHQ==}
+ cpu: [s390x]
+ os: [linux]
+
'@unrs/resolver-binding-linux-x64-gnu@1.7.2':
resolution: {integrity: sha512-dEidzJDubxxhUCBJ/SHSMJD/9q7JkyfBMT77Px1npl4xpg9t0POLvnWywSk66BgZS/b2Hy9Y1yFaoMTFJUe9yg==}
cpu: [x64]
os: [linux]
+ '@unrs/resolver-binding-linux-x64-gnu@1.9.2':
+ resolution: {integrity: sha512-jkSkwch0uPFva20Mdu8orbQjv2A3G88NExTN2oPTI1AJ+7mZfYW3cDCTyoH6OnctBKbBVeJCEqh0U02lTkqD5w==}
+ cpu: [x64]
+ os: [linux]
+
'@unrs/resolver-binding-linux-x64-musl@1.7.2':
resolution: {integrity: sha512-RvP+Ux3wDjmnZDT4XWFfNBRVG0fMsc+yVzNFUqOflnDfZ9OYujv6nkh+GOr+watwrW4wdp6ASfG/e7bkDradsw==}
cpu: [x64]
os: [linux]
+ '@unrs/resolver-binding-linux-x64-musl@1.9.2':
+ resolution: {integrity: sha512-Uk64NoiTpQbkpl+bXsbeyOPRpUoMdcUqa+hDC1KhMW7aN1lfW8PBlBH4mJ3n3Y47dYE8qi0XTxy1mBACruYBaw==}
+ cpu: [x64]
+ os: [linux]
+
'@unrs/resolver-binding-wasm32-wasi@1.7.2':
resolution: {integrity: sha512-y797JBmO9IsvXVRCKDXOxjyAE4+CcZpla2GSoBQ33TVb3ILXuFnMrbR/QQZoauBYeOFuu4w3ifWLw52sdHGz6g==}
engines: {node: '>=14.0.0'}
cpu: [wasm32]
+ '@unrs/resolver-binding-wasm32-wasi@1.9.2':
+ resolution: {integrity: sha512-EpBGwkcjDicjR/ybC0g8wO5adPNdVuMrNalVgYcWi+gYtC1XYNuxe3rufcO7dA76OHGeVabcO6cSkPJKVcbCXQ==}
+ engines: {node: '>=14.0.0'}
+ cpu: [wasm32]
+
'@unrs/resolver-binding-win32-arm64-msvc@1.7.2':
resolution: {integrity: sha512-gtYTh4/VREVSLA+gHrfbWxaMO/00y+34htY7XpioBTy56YN2eBjkPrY1ML1Zys89X3RJDKVaogzwxlM1qU7egg==}
cpu: [arm64]
os: [win32]
+ '@unrs/resolver-binding-win32-arm64-msvc@1.9.2':
+ resolution: {integrity: sha512-EdFbGn7o1SxGmN6aZw9wAkehZJetFPao0VGZ9OMBwKx6TkvDuj6cNeLimF/Psi6ts9lMOe+Dt6z19fZQ9Ye2fw==}
+ cpu: [arm64]
+ os: [win32]
+
'@unrs/resolver-binding-win32-ia32-msvc@1.7.2':
resolution: {integrity: sha512-Ywv20XHvHTDRQs12jd3MY8X5C8KLjDbg/jyaal/QLKx3fAShhJyD4blEANInsjxW3P7isHx1Blt56iUDDJO3jg==}
cpu: [ia32]
os: [win32]
+ '@unrs/resolver-binding-win32-ia32-msvc@1.9.2':
+ resolution: {integrity: sha512-JY9hi1p7AG+5c/dMU8o2kWemM8I6VZxfGwn1GCtf3c5i+IKcMo2NQ8OjZ4Z3/itvY/Si3K10jOBQn7qsD/whUA==}
+ cpu: [ia32]
+ os: [win32]
+
'@unrs/resolver-binding-win32-x64-msvc@1.7.2':
resolution: {integrity: sha512-friS8NEQfHaDbkThxopGk+LuE5v3iY0StruifjQEt7SLbA46OnfgMO15sOTkbpJkol6RB+1l1TYPXh0sCddpvA==}
cpu: [x64]
os: [win32]
+ '@unrs/resolver-binding-win32-x64-msvc@1.9.2':
+ resolution: {integrity: sha512-ryoo+EB19lMxAd80ln9BVf8pdOAxLb97amrQ3SFN9OCRn/5M5wvwDgAe4i8ZjhpbiHoDeP8yavcTEnpKBo7lZg==}
+ cpu: [x64]
+ os: [win32]
+
acorn-jsx@5.3.2:
resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==}
peerDependencies:
@@ -1097,13 +1508,40 @@ packages:
ajv@6.12.6:
resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==}
+ ansi-escapes@4.3.2:
+ resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==}
+ engines: {node: '>=8'}
+
+ ansi-regex@5.0.1:
+ resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
+ engines: {node: '>=8'}
+
+ ansi-regex@6.1.0:
+ resolution: {integrity: sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==}
+ engines: {node: '>=12'}
+
ansi-styles@4.3.0:
resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
engines: {node: '>=8'}
+ ansi-styles@5.2.0:
+ resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==}
+ engines: {node: '>=10'}
+
+ ansi-styles@6.2.1:
+ resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==}
+ engines: {node: '>=12'}
+
+ anymatch@3.1.3:
+ resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==}
+ engines: {node: '>= 8'}
+
arg@4.1.3:
resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==}
+ argparse@1.0.10:
+ resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==}
+
argparse@2.0.1:
resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==}
@@ -1150,6 +1588,9 @@ packages:
resolution: {integrity: sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==}
engines: {node: '>= 0.4'}
+ async@3.2.6:
+ resolution: {integrity: sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==}
+
asynckit@0.4.0:
resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==}
@@ -1165,6 +1606,31 @@ packages:
resolution: {integrity: sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==}
engines: {node: '>= 0.4'}
+ babel-jest@30.0.2:
+ resolution: {integrity: sha512-A5kqR1/EUTidM2YC2YMEUDP2+19ppgOwK0IAd9Swc3q2KqFb5f9PtRUXVeZcngu0z5mDMyZ9zH2huJZSOMLiTQ==}
+ engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
+ peerDependencies:
+ '@babel/core': ^7.11.0
+
+ babel-plugin-istanbul@7.0.0:
+ resolution: {integrity: sha512-C5OzENSx/A+gt7t4VH1I2XsflxyPUmXRFPKBxt33xncdOmq7oROVM3bZv9Ysjjkv8OJYDMa+tKuKMvqU/H3xdw==}
+ engines: {node: '>=12'}
+
+ babel-plugin-jest-hoist@30.0.1:
+ resolution: {integrity: sha512-zTPME3pI50NsFW8ZBaVIOeAxzEY7XHlmWeXXu9srI+9kNfzCUTy8MFan46xOGZY8NZThMqq+e3qZUKsvXbasnQ==}
+ engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
+
+ babel-preset-current-node-syntax@1.1.0:
+ resolution: {integrity: sha512-ldYss8SbBlWva1bs28q78Ju5Zq1F+8BrqBZZ0VFhLBvhh6lCpC2o3gDJi/5DRLs9FgYZCnmPYIVFU4lRXCkyUw==}
+ peerDependencies:
+ '@babel/core': ^7.0.0
+
+ babel-preset-jest@30.0.1:
+ resolution: {integrity: sha512-+YHejD5iTWI46cZmcc/YtX4gaKBtdqCHCVfuVinizVpbmyjO3zYmeuyFdfA8duRqQZfgCAMlsfmkVbJ+e2MAJw==}
+ engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
+ peerDependencies:
+ '@babel/core': ^7.11.0
+
bail@2.0.2:
resolution: {integrity: sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==}
@@ -1185,6 +1651,21 @@ packages:
resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==}
engines: {node: '>=8'}
+ browserslist@4.25.1:
+ resolution: {integrity: sha512-KGj0KoOMXLpSNkkEI6Z6mShmQy0bc1I+T7K9N81k4WWMrfz+6fQ6es80B/YLAeRoKvjYE1YSHHOW1qe9xIVzHw==}
+ engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
+ hasBin: true
+
+ bs-logger@0.2.6:
+ resolution: {integrity: sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==}
+ engines: {node: '>= 6'}
+
+ bser@2.1.1:
+ resolution: {integrity: sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==}
+
+ buffer-from@1.1.2:
+ resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==}
+
busboy@1.6.0:
resolution: {integrity: sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==}
engines: {node: '>=10.16.0'}
@@ -1205,9 +1686,20 @@ packages:
resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==}
engines: {node: '>=6'}
+ camelcase@5.3.1:
+ resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==}
+ engines: {node: '>=6'}
+
+ camelcase@6.3.0:
+ resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==}
+ engines: {node: '>=10'}
+
caniuse-lite@1.0.30001718:
resolution: {integrity: sha512-AflseV1ahcSunK53NfEs9gFWgOEmzr0f+kaMFA4xiLZlr9Hzt7HxcSpIFcnNCUkz6R6dWKa54rUz3HUmI3nVcw==}
+ caniuse-lite@1.0.30001726:
+ resolution: {integrity: sha512-VQAUIUzBiZ/UnlM28fSp2CRF3ivUn1BWEvxMcVTNwpw91Py1pGbPIyIKtd+tzct9C3ouceCVdGAXxZOpZAsgdw==}
+
ccount@2.0.1:
resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==}
@@ -1215,6 +1707,10 @@ packages:
resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==}
engines: {node: '>=10'}
+ char-regex@1.0.2:
+ resolution: {integrity: sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==}
+ engines: {node: '>=10'}
+
character-entities-html4@2.1.0:
resolution: {integrity: sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==}
@@ -1240,9 +1736,27 @@ packages:
resolution: {integrity: sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==}
engines: {node: '>=18'}
+ ci-info@4.2.0:
+ resolution: {integrity: sha512-cYY9mypksY8NRqgDB1XD1RiJL338v/551niynFTGkZOO2LHuB2OmOYxDIe/ttN9AHwrqdum1360G3ald0W9kCg==}
+ engines: {node: '>=8'}
+
+ cjs-module-lexer@2.1.0:
+ resolution: {integrity: sha512-UX0OwmYRYQQetfrLEZeewIFFI+wSTofC+pMBLNuH3RUuu/xzG1oz84UCEDOSoQlN3fZ4+AzmV50ZYvGqkMh9yA==}
+
client-only@0.0.1:
resolution: {integrity: sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==}
+ cliui@8.0.1:
+ resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==}
+ engines: {node: '>=12'}
+
+ co@4.6.0:
+ resolution: {integrity: sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==}
+ engines: {iojs: '>= 1.0.0', node: '>= 0.12.0'}
+
+ collect-v8-coverage@1.0.2:
+ resolution: {integrity: sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==}
+
color-convert@2.0.1:
resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
engines: {node: '>=7.0.0'}
@@ -1275,6 +1789,9 @@ packages:
concat-map@0.0.1:
resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
+ convert-source-map@2.0.0:
+ resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==}
+
cookie@0.7.2:
resolution: {integrity: sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==}
engines: {node: '>= 0.6'}
@@ -1464,9 +1981,21 @@ packages:
decode-named-character-reference@1.1.0:
resolution: {integrity: sha512-Wy+JTSbFThEOXQIR2L6mxJvEs+veIzpmqD7ynWxMXGpnk3smkHQOp6forLdHsKpAMW9iJpaBBIxz285t1n1C3w==}
+ dedent@1.6.0:
+ resolution: {integrity: sha512-F1Z+5UCFpmQUzJa11agbyPVMbpgT/qA3/SKyJ1jyBgm7dUcUEa8v9JwDkerSQXfakBwFljIxhOJqGkjUwZ9FSA==}
+ peerDependencies:
+ babel-plugin-macros: ^3.1.0
+ peerDependenciesMeta:
+ babel-plugin-macros:
+ optional: true
+
deep-is@0.1.4:
resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==}
+ deepmerge@4.3.1:
+ resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==}
+ engines: {node: '>=0.10.0'}
+
define-data-property@1.1.4:
resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==}
engines: {node: '>= 0.4'}
@@ -1490,6 +2019,10 @@ packages:
resolution: {integrity: sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==}
engines: {node: '>=8'}
+ detect-newline@3.1.0:
+ resolution: {integrity: sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==}
+ engines: {node: '>=8'}
+
devlop@1.1.0:
resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==}
@@ -1508,6 +2041,24 @@ packages:
resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==}
engines: {node: '>= 0.4'}
+ eastasianwidth@0.2.0:
+ resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==}
+
+ ejs@3.1.10:
+ resolution: {integrity: sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==}
+ engines: {node: '>=0.10.0'}
+ hasBin: true
+
+ electron-to-chromium@1.5.177:
+ resolution: {integrity: sha512-7EH2G59nLsEMj97fpDuvVcYi6lwTcM1xuWw3PssD8xzboAW7zj7iB3COEEEATUfjLHrs5uKBLQT03V/8URx06g==}
+
+ emittery@0.13.1:
+ resolution: {integrity: sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==}
+ engines: {node: '>=12'}
+
+ emoji-regex@8.0.0:
+ resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
+
emoji-regex@9.2.2:
resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==}
@@ -1523,6 +2074,9 @@ packages:
resolution: {integrity: sha512-aKstq2TDOndCn4diEyp9Uq/Flu2i1GlLkc6XIDQSDMuaFE3OPW5OphLCyQ5SpSJZTb4reN+kTcYru5yIfXoRPw==}
engines: {node: '>=0.12'}
+ error-ex@1.3.2:
+ resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==}
+
es-abstract@1.23.9:
resolution: {integrity: sha512-py07lI0wjxAC/DcfK1S6G7iANonniZwTISvdPzk9hzeH0IZIshbuuFxLIU96OyF89Yb9hiqWn8M/bY83KY5vzA==}
engines: {node: '>= 0.4'}
@@ -1560,6 +2114,14 @@ packages:
engines: {node: '>=18'}
hasBin: true
+ escalade@3.2.0:
+ resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==}
+ engines: {node: '>=6'}
+
+ escape-string-regexp@2.0.0:
+ resolution: {integrity: sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==}
+ engines: {node: '>=8'}
+
escape-string-regexp@4.0.0:
resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==}
engines: {node: '>=10'}
@@ -1678,6 +2240,11 @@ packages:
resolution: {integrity: sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+ esprima@4.0.1:
+ resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==}
+ engines: {node: '>=4'}
+ hasBin: true
+
esquery@1.6.0:
resolution: {integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==}
engines: {node: '>=0.10'}
@@ -1697,6 +2264,18 @@ packages:
resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==}
engines: {node: '>=0.10.0'}
+ execa@5.1.1:
+ resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==}
+ engines: {node: '>=10'}
+
+ exit-x@0.2.2:
+ resolution: {integrity: sha512-+I6B/IkJc1o/2tiURyz/ivu/O0nKNEArIUB5O7zBrlDVJr22SCLH3xTeEry428LvFhRzIA1g8izguxJ/gbNcVQ==}
+ engines: {node: '>= 0.8.0'}
+
+ expect@30.0.3:
+ resolution: {integrity: sha512-HXg6NvK35/cSYZCUKAtmlgCFyqKM4frEPbzrav5hRqb0GMz0E0lS5hfzYjSaiaE5ysnp/qI2aeZkeyeIAOeXzQ==}
+ engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
+
extend@3.0.2:
resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==}
@@ -1723,6 +2302,9 @@ packages:
fastq@1.19.1:
resolution: {integrity: sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==}
+ fb-watchman@2.0.2:
+ resolution: {integrity: sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==}
+
fdir@6.4.4:
resolution: {integrity: sha512-1NZP+GK4GfuAv3PqKvxQRDMjdSRZjnkq7KfhlNrCNNlZ0ygQFpebfrnfnq/W7fpUnAv9aGWmY1zKx7FYL3gwhg==}
peerDependencies:
@@ -1739,10 +2321,17 @@ packages:
resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==}
engines: {node: '>=16.0.0'}
+ filelist@1.0.4:
+ resolution: {integrity: sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==}
+
fill-range@7.1.1:
resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==}
engines: {node: '>=8'}
+ find-up@4.1.0:
+ resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==}
+ engines: {node: '>=8'}
+
find-up@5.0.0:
resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==}
engines: {node: '>=10'}
@@ -1758,6 +2347,10 @@ packages:
resolution: {integrity: sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==}
engines: {node: '>= 0.4'}
+ foreground-child@3.3.1:
+ resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==}
+ engines: {node: '>=14'}
+
form-data@4.0.2:
resolution: {integrity: sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==}
engines: {node: '>= 6'}
@@ -1766,6 +2359,9 @@ packages:
resolution: {integrity: sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==}
engines: {node: '>=12.20.0'}
+ fs.realpath@1.0.0:
+ resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==}
+
fsevents@2.3.2:
resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==}
engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
@@ -1786,14 +2382,30 @@ packages:
functions-have-names@1.2.3:
resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==}
+ gensync@1.0.0-beta.2:
+ resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==}
+ engines: {node: '>=6.9.0'}
+
+ get-caller-file@2.0.5:
+ resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==}
+ engines: {node: 6.* || 8.* || >= 10.*}
+
get-intrinsic@1.3.0:
resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==}
engines: {node: '>= 0.4'}
+ get-package-type@0.1.0:
+ resolution: {integrity: sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==}
+ engines: {node: '>=8.0.0'}
+
get-proto@1.0.1:
resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==}
engines: {node: '>= 0.4'}
+ get-stream@6.0.1:
+ resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==}
+ engines: {node: '>=10'}
+
get-symbol-description@1.1.0:
resolution: {integrity: sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==}
engines: {node: '>= 0.4'}
@@ -1809,6 +2421,18 @@ packages:
resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==}
engines: {node: '>=10.13.0'}
+ glob@10.4.5:
+ resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==}
+ hasBin: true
+
+ glob@7.2.3:
+ resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==}
+ deprecated: Glob versions prior to v9 are no longer supported
+
+ globals@11.12.0:
+ resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==}
+ engines: {node: '>=4'}
+
globals@14.0.0:
resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==}
engines: {node: '>=18'}
@@ -1879,12 +2503,19 @@ packages:
hastscript@9.0.1:
resolution: {integrity: sha512-g7df9rMFX/SPi34tyGCyUBREQoKkapwdY/T04Qn9TDWfHhAYt4/I0gMVirzK5wEzeUqIjEB+LXC/ypb7Aqno5w==}
+ html-escaper@2.0.2:
+ resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==}
+
html-url-attributes@3.0.1:
resolution: {integrity: sha512-ol6UPyBWqsrO6EJySPz2O7ZSr856WDrEzM5zMqp+FJJLGMW35cLYmmZnl0vztAZxRUoNZJFTCohfjuIJ8I4QBQ==}
html-void-elements@3.0.0:
resolution: {integrity: sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==}
+ human-signals@2.1.0:
+ resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==}
+ engines: {node: '>=10.17.0'}
+
i18n-iso-countries@7.14.0:
resolution: {integrity: sha512-nXHJZYtNrfsi1UQbyRqm3Gou431elgLjKl//CYlnBGt5aTWdRPH1PiS2T/p/n8Q8LnqYqzQJik3Q7mkwvLokeg==}
engines: {node: '>= 12'}
@@ -1905,10 +2536,22 @@ packages:
resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==}
engines: {node: '>=6'}
+ import-local@3.2.0:
+ resolution: {integrity: sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==}
+ engines: {node: '>=8'}
+ hasBin: true
+
imurmurhash@0.1.4:
resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==}
engines: {node: '>=0.8.19'}
+ inflight@1.0.6:
+ resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==}
+ deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.
+
+ inherits@2.0.4:
+ resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
+
inline-style-parser@0.2.4:
resolution: {integrity: sha512-0aO8FkhNZlj/ZIbNi7Lxxr12obT7cL1moPfE4tg1LkX7LlLfC6DeX4l2ZEud1ukP9jNQyNnfzQVqwbwmAATY4Q==}
@@ -1930,6 +2573,9 @@ packages:
resolution: {integrity: sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==}
engines: {node: '>= 0.4'}
+ is-arrayish@0.2.1:
+ resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==}
+
is-arrayish@0.3.2:
resolution: {integrity: sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==}
@@ -1975,6 +2621,14 @@ packages:
resolution: {integrity: sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==}
engines: {node: '>= 0.4'}
+ is-fullwidth-code-point@3.0.0:
+ resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==}
+ engines: {node: '>=8'}
+
+ is-generator-fn@2.1.0:
+ resolution: {integrity: sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==}
+ engines: {node: '>=6'}
+
is-generator-function@1.1.0:
resolution: {integrity: sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ==}
engines: {node: '>= 0.4'}
@@ -2014,6 +2668,10 @@ packages:
resolution: {integrity: sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==}
engines: {node: '>= 0.4'}
+ is-stream@2.0.1:
+ resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==}
+ engines: {node: '>=8'}
+
is-string@1.1.1:
resolution: {integrity: sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==}
engines: {node: '>= 0.4'}
@@ -2048,10 +2706,166 @@ packages:
resolution: {integrity: sha512-gXkz5+KN7HrG0Q5UGqSMO2qB9AsbEeyLP54kF1YrMsIxmu+g4BdB7rflReZTSTZGpfj8wywu6pfPBCylPIzGQA==}
engines: {node: '>=6.0'}
+ istanbul-lib-coverage@3.2.2:
+ resolution: {integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==}
+ engines: {node: '>=8'}
+
+ istanbul-lib-instrument@6.0.3:
+ resolution: {integrity: sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==}
+ engines: {node: '>=10'}
+
+ istanbul-lib-report@3.0.1:
+ resolution: {integrity: sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==}
+ engines: {node: '>=10'}
+
+ istanbul-lib-source-maps@5.0.6:
+ resolution: {integrity: sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A==}
+ engines: {node: '>=10'}
+
+ istanbul-reports@3.1.7:
+ resolution: {integrity: sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==}
+ engines: {node: '>=8'}
+
iterator.prototype@1.1.5:
resolution: {integrity: sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==}
engines: {node: '>= 0.4'}
+ jackspeak@3.4.3:
+ resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==}
+
+ jake@10.9.2:
+ resolution: {integrity: sha512-2P4SQ0HrLQ+fw6llpLnOaGAvN2Zu6778SJMrCUwns4fOoG9ayrTiZk3VV8sCPkVZF8ab0zksVpS8FDY5pRCNBA==}
+ engines: {node: '>=10'}
+ hasBin: true
+
+ jest-changed-files@30.0.2:
+ resolution: {integrity: sha512-Ius/iRST9FKfJI+I+kpiDh8JuUlAISnRszF9ixZDIqJF17FckH5sOzKC8a0wd0+D+8em5ADRHA5V5MnfeDk2WA==}
+ engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
+
+ jest-circus@30.0.3:
+ resolution: {integrity: sha512-rD9qq2V28OASJHJWDRVdhoBdRs6k3u3EmBzDYcyuMby8XCO3Ll1uq9kyqM41ZcC4fMiPulMVh3qMw0cBvDbnyg==}
+ engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
+
+ jest-cli@30.0.3:
+ resolution: {integrity: sha512-UWDSj0ayhumEAxpYRlqQLrssEi29kdQ+kddP94AuHhZknrE+mT0cR0J+zMHKFe9XPfX3dKQOc2TfWki3WhFTsA==}
+ engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
+ hasBin: true
+ peerDependencies:
+ node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0
+ peerDependenciesMeta:
+ node-notifier:
+ optional: true
+
+ jest-config@30.0.3:
+ resolution: {integrity: sha512-j0L4oRCtJwNyZktXIqwzEiDVQXBbQ4dqXuLD/TZdn++hXIcIfZmjHgrViEy5s/+j4HvITmAXbexVZpQ/jnr0bg==}
+ engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
+ peerDependencies:
+ '@types/node': '*'
+ esbuild-register: '>=3.4.0'
+ ts-node: '>=9.0.0'
+ peerDependenciesMeta:
+ '@types/node':
+ optional: true
+ esbuild-register:
+ optional: true
+ ts-node:
+ optional: true
+
+ jest-diff@30.0.3:
+ resolution: {integrity: sha512-Q1TAV0cUcBTic57SVnk/mug0/ASyAqtSIOkr7RAlxx97llRYsM74+E8N5WdGJUlwCKwgxPAkVjKh653h1+HA9A==}
+ engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
+
+ jest-docblock@30.0.1:
+ resolution: {integrity: sha512-/vF78qn3DYphAaIc3jy4gA7XSAz167n9Bm/wn/1XhTLW7tTBIzXtCJpb/vcmc73NIIeeohCbdL94JasyXUZsGA==}
+ engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
+
+ jest-each@30.0.2:
+ resolution: {integrity: sha512-ZFRsTpe5FUWFQ9cWTMguCaiA6kkW5whccPy9JjD1ezxh+mJeqmz8naL8Fl/oSbNJv3rgB0x87WBIkA5CObIUZQ==}
+ engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
+
+ jest-environment-node@30.0.2:
+ resolution: {integrity: sha512-XsGtZ0H+a70RsxAQkKuIh0D3ZlASXdZdhpOSBq9WRPq6lhe0IoQHGW0w9ZUaPiZQ/CpkIdprvlfV1QcXcvIQLQ==}
+ engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
+
+ jest-haste-map@30.0.2:
+ resolution: {integrity: sha512-telJBKpNLeCb4MaX+I5k496556Y2FiKR/QLZc0+MGBYl4k3OO0472drlV2LUe7c1Glng5HuAu+5GLYp//GpdOQ==}
+ engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
+
+ jest-leak-detector@30.0.2:
+ resolution: {integrity: sha512-U66sRrAYdALq+2qtKffBLDWsQ/XoNNs2Lcr83sc9lvE/hEpNafJlq2lXCPUBMNqamMECNxSIekLfe69qg4KMIQ==}
+ engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
+
+ jest-matcher-utils@30.0.3:
+ resolution: {integrity: sha512-hMpVFGFOhYmIIRGJ0HgM9htC5qUiJ00famcc9sRFchJJiLZbbVKrAztcgE6VnXLRxA3XZ0bvNA7hQWh3oHXo/A==}
+ engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
+
+ jest-message-util@30.0.2:
+ resolution: {integrity: sha512-vXywcxmr0SsKXF/bAD7t7nMamRvPuJkras00gqYeB1V0WllxZrbZ0paRr3XqpFU2sYYjD0qAaG2fRyn/CGZ0aw==}
+ engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
+
+ jest-mock@30.0.2:
+ resolution: {integrity: sha512-PnZOHmqup/9cT/y+pXIVbbi8ID6U1XHRmbvR7MvUy4SLqhCbwpkmXhLbsWbGewHrV5x/1bF7YDjs+x24/QSvFA==}
+ engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
+
+ jest-pnp-resolver@1.2.3:
+ resolution: {integrity: sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==}
+ engines: {node: '>=6'}
+ peerDependencies:
+ jest-resolve: '*'
+ peerDependenciesMeta:
+ jest-resolve:
+ optional: true
+
+ jest-regex-util@30.0.1:
+ resolution: {integrity: sha512-jHEQgBXAgc+Gh4g0p3bCevgRCVRkB4VB70zhoAE48gxeSr1hfUOsM/C2WoJgVL7Eyg//hudYENbm3Ne+/dRVVA==}
+ engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
+
+ jest-resolve-dependencies@30.0.3:
+ resolution: {integrity: sha512-FlL6u7LiHbF0Oe27k7DHYMq2T2aNpPhxnNo75F7lEtu4A6sSw+TKkNNUGNcVckdFoL0RCWREJsC1HsKDwKRZzQ==}
+ engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
+
+ jest-resolve@30.0.2:
+ resolution: {integrity: sha512-q/XT0XQvRemykZsvRopbG6FQUT6/ra+XV6rPijyjT6D0msOyCvR2A5PlWZLd+fH0U8XWKZfDiAgrUNDNX2BkCw==}
+ engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
+
+ jest-runner@30.0.3:
+ resolution: {integrity: sha512-CxYBzu9WStOBBXAKkLXGoUtNOWsiS1RRmUQb6SsdUdTcqVncOau7m8AJ4cW3Mz+YL1O9pOGPSYLyvl8HBdFmkQ==}
+ engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
+
+ jest-runtime@30.0.3:
+ resolution: {integrity: sha512-Xjosq0C48G9XEQOtmgrjXJwPaUPaq3sPJwHDRaiC+5wi4ZWxO6Lx6jNkizK/0JmTulVNuxP8iYwt77LGnfg3/w==}
+ engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
+
+ jest-snapshot@30.0.3:
+ resolution: {integrity: sha512-F05JCohd3OA1N9+5aEPXA6I0qOfZDGIx0zTq5Z4yMBg2i1p5ELfBusjYAWwTkC12c7dHcbyth4QAfQbS7cRjow==}
+ engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
+
+ jest-util@30.0.2:
+ resolution: {integrity: sha512-8IyqfKS4MqprBuUpZNlFB5l+WFehc8bfCe1HSZFHzft2mOuND8Cvi9r1musli+u6F3TqanCZ/Ik4H4pXUolZIg==}
+ engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
+
+ jest-validate@30.0.2:
+ resolution: {integrity: sha512-noOvul+SFER4RIvNAwGn6nmV2fXqBq67j+hKGHKGFCmK4ks/Iy1FSrqQNBLGKlu4ZZIRL6Kg1U72N1nxuRCrGQ==}
+ engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
+
+ jest-watcher@30.0.2:
+ resolution: {integrity: sha512-vYO5+E7jJuF+XmONr6CrbXdlYrgvZqtkn6pdkgjt/dU64UAdc0v1cAVaAeWtAfUUMScxNmnUjKPUMdCpNVASwg==}
+ engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
+
+ jest-worker@30.0.2:
+ resolution: {integrity: sha512-RN1eQmx7qSLFA+o9pfJKlqViwL5wt+OL3Vff/A+/cPsmuw7NPwfgl33AP+/agRmHzPOFgXviRycR9kYwlcRQXg==}
+ engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
+
+ jest@30.0.3:
+ resolution: {integrity: sha512-Uy8xfeE/WpT2ZLGDXQmaYNzw2v8NUKuYeKGtkS6sDxwsdQihdgYCXaKIYnph1h95DN5H35ubFDm0dfmsQnjn4Q==}
+ engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
+ hasBin: true
+ peerDependencies:
+ node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0
+ peerDependenciesMeta:
+ node-notifier:
+ optional: true
+
jiti@2.4.2:
resolution: {integrity: sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==}
hasBin: true
@@ -2062,13 +2876,25 @@ packages:
js-tokens@4.0.0:
resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
+ js-yaml@3.14.1:
+ resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==}
+ hasBin: true
+
js-yaml@4.1.0:
resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==}
hasBin: true
+ jsesc@3.1.0:
+ resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==}
+ engines: {node: '>=6'}
+ hasBin: true
+
json-buffer@3.0.1:
resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==}
+ json-parse-even-better-errors@2.3.1:
+ resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==}
+
json-schema-traverse@0.4.1:
resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==}
@@ -2079,6 +2905,11 @@ packages:
resolution: {integrity: sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==}
hasBin: true
+ json5@2.2.3:
+ resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==}
+ engines: {node: '>=6'}
+ hasBin: true
+
jsonc-parser@3.3.1:
resolution: {integrity: sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==}
@@ -2103,6 +2934,10 @@ packages:
leaflet@1.9.4:
resolution: {integrity: sha512-nxS1ynzJOmOlHp+iL3FyWqK89GtNL8U8rvlMOsQdTTssxZwCXh8N2NB3GDQOL+YR3XnWyZAxwQixURb+FA74PA==}
+ leven@3.1.0:
+ resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==}
+ engines: {node: '>=6'}
+
levn@0.4.1:
resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==}
engines: {node: '>= 0.8.0'}
@@ -2174,13 +3009,23 @@ packages:
lineclip@1.1.5:
resolution: {integrity: sha512-KlA/wRSjpKl7tS9iRUdlG72oQ7qZ1IlVbVgHwoO10TBR/4gQ86uhKow6nlzMAJJhjCWKto8OeoAzzIzKSmN25A==}
+ lines-and-columns@1.2.4:
+ resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==}
+
linkify-it@5.0.0:
resolution: {integrity: sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==}
+ locate-path@5.0.0:
+ resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==}
+ engines: {node: '>=8'}
+
locate-path@6.0.0:
resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==}
engines: {node: '>=10'}
+ lodash.memoize@4.1.2:
+ resolution: {integrity: sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==}
+
lodash.merge@4.6.2:
resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==}
@@ -2191,6 +3036,12 @@ packages:
resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==}
hasBin: true
+ lru-cache@10.4.3:
+ resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==}
+
+ lru-cache@5.1.1:
+ resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==}
+
lru-cache@6.0.0:
resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==}
engines: {node: '>=10'}
@@ -2198,9 +3049,16 @@ packages:
magic-string@0.30.17:
resolution: {integrity: sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==}
+ make-dir@4.0.0:
+ resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==}
+ engines: {node: '>=10'}
+
make-error@1.3.6:
resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==}
+ makeerror@1.0.12:
+ resolution: {integrity: sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==}
+
markdown-it@14.1.0:
resolution: {integrity: sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==}
hasBin: true
@@ -2250,6 +3108,9 @@ packages:
mdurl@2.0.0:
resolution: {integrity: sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==}
+ merge-stream@2.0.0:
+ resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==}
+
merge2@1.4.1:
resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==}
engines: {node: '>= 8'}
@@ -2344,9 +3205,17 @@ packages:
resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==}
engines: {node: '>= 0.6'}
+ mimic-fn@2.1.0:
+ resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==}
+ engines: {node: '>=6'}
+
minimatch@3.1.2:
resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==}
+ minimatch@5.1.6:
+ resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==}
+ engines: {node: '>=10'}
+
minimatch@9.0.5:
resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==}
engines: {node: '>=16 || 14 >=14.17'}
@@ -2431,6 +3300,20 @@ packages:
resolution: {integrity: sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==}
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
+ node-int64@0.4.0:
+ resolution: {integrity: sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==}
+
+ node-releases@2.0.19:
+ resolution: {integrity: sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==}
+
+ normalize-path@3.0.0:
+ resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==}
+ engines: {node: '>=0.10.0'}
+
+ npm-run-path@4.0.1:
+ resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==}
+ engines: {node: '>=8'}
+
oauth@0.9.15:
resolution: {integrity: sha512-a5ERWK1kh38ExDEfoO6qUHJb32rd7aYmPHuyCu3Fta/cnICvYmgd2uhuKXvPD+PXB+gCEYYEaQdIRAjCOwAKNA==}
@@ -2474,6 +3357,13 @@ packages:
resolution: {integrity: sha512-y0W+X7Ppo7oZX6eovsRkuzcSM40Bicg2JEJkDJ4irIt1wsYAP5MLSNv+QAogO8xivMffw/9OvV3um1pxXgt1uA==}
engines: {node: ^10.13.0 || >=12.0.0}
+ once@1.4.0:
+ resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==}
+
+ onetime@5.1.2:
+ resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==}
+ engines: {node: '>=6'}
+
openid-client@5.7.1:
resolution: {integrity: sha512-jDBPgSVfTnkIh71Hg9pRvtJc6wTwqjRkN88+gCFtYWrlP4Yx2Dsrow8uPi3qLr/aeymPF3o2+dS+wOpglK04ew==}
@@ -2485,14 +3375,29 @@ packages:
resolution: {integrity: sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==}
engines: {node: '>= 0.4'}
+ p-limit@2.3.0:
+ resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==}
+ engines: {node: '>=6'}
+
p-limit@3.1.0:
resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==}
engines: {node: '>=10'}
+ p-locate@4.1.0:
+ resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==}
+ engines: {node: '>=8'}
+
p-locate@5.0.0:
resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==}
engines: {node: '>=10'}
+ p-try@2.2.0:
+ resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==}
+ engines: {node: '>=6'}
+
+ package-json-from-dist@1.0.1:
+ resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==}
+
parent-module@1.0.1:
resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==}
engines: {node: '>=6'}
@@ -2500,6 +3405,10 @@ packages:
parse-entities@4.0.2:
resolution: {integrity: sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw==}
+ parse-json@5.2.0:
+ resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==}
+ engines: {node: '>=8'}
+
parse5@7.3.0:
resolution: {integrity: sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==}
@@ -2507,6 +3416,10 @@ packages:
resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==}
engines: {node: '>=8'}
+ path-is-absolute@1.0.1:
+ resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==}
+ engines: {node: '>=0.10.0'}
+
path-key@3.1.1:
resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==}
engines: {node: '>=8'}
@@ -2514,6 +3427,10 @@ packages:
path-parse@1.0.7:
resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==}
+ path-scurry@1.11.1:
+ resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==}
+ engines: {node: '>=16 || 14 >=14.18'}
+
path-type@6.0.0:
resolution: {integrity: sha512-Vj7sf++t5pBD637NSfkxpHSMfWaeig5+DKWLhcqIYx6mWQz5hdJTGDVMQiJcw1ZYkhs7AazKDGpRVji1LJCZUQ==}
engines: {node: '>=18'}
@@ -2529,6 +3446,14 @@ packages:
resolution: {integrity: sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==}
engines: {node: '>=12'}
+ pirates@4.0.7:
+ resolution: {integrity: sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==}
+ engines: {node: '>= 6'}
+
+ pkg-dir@4.2.0:
+ resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==}
+ engines: {node: '>=8'}
+
playwright-core@1.52.0:
resolution: {integrity: sha512-l2osTgLXSMeuLZOML9qYODUQoPPnUsKsb5/P6LJ2e6uPKXUdPK5WYhN4z03G+YNbWmGDY4YENauNu4ZKczreHg==}
engines: {node: '>=18'}
@@ -2580,6 +3505,10 @@ packages:
pretty-format@3.8.0:
resolution: {integrity: sha512-WuxUnVtlWL1OfZFQFuqvnvs6MiAGk9UNsBostyBOB0Is9wb5uRESevA6rnl/rkksXaGX3GzZhPup5d6Vp1nFew==}
+ pretty-format@30.0.2:
+ resolution: {integrity: sha512-yC5/EBSOrTtqhCKfLHqoUIAXVRZnukHPwWBJWR7h84Q3Be1DRQZLncwcfLoPA5RPQ65qfiCMqgYwdUuQ//eVpg==}
+ engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0}
+
prisma@6.10.1:
resolution: {integrity: sha512-khhlC/G49E4+uyA3T3H5PRBut486HD2bDqE2+rvkU0pwk9IAqGFacLFUyIx9Uw+W2eCtf6XGwsp+/strUwMNPw==}
engines: {node: '>=18.18'}
@@ -2607,6 +3536,9 @@ packages:
resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==}
engines: {node: '>=6'}
+ pure-rand@7.0.1:
+ resolution: {integrity: sha512-oTUZM/NAZS8p7ANR3SHh30kXB+zK2r2BPcEn/awJIbOvq82WoMN4p62AWWp3Hhw50G0xMsw1mhIBLqHw64EcNQ==}
+
queue-microtask@1.2.3:
resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
@@ -2630,6 +3562,9 @@ packages:
react-is@16.13.1:
resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==}
+ react-is@18.3.1:
+ resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==}
+
react-leaflet@5.0.0:
resolution: {integrity: sha512-CWbTpr5vcHw5bt9i4zSlPEVQdTVcML390TjeDG0cK59z1ylexpqC6M1PJFjV8jD7CF+ACBFsLIDs6DRMoLEofw==}
peerDependencies:
@@ -2664,10 +3599,22 @@ packages:
remark-rehype@11.1.2:
resolution: {integrity: sha512-Dh7l57ianaEoIpzbp0PC9UKAdCSVklD8E5Rpw7ETfbTl3FqcOOgq5q2LVDhgGCkaBv7p24JXikPdvhhmHvKMsw==}
+ require-directory@2.1.1:
+ resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==}
+ engines: {node: '>=0.10.0'}
+
+ resolve-cwd@3.0.0:
+ resolution: {integrity: sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==}
+ engines: {node: '>=8'}
+
resolve-from@4.0.0:
resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==}
engines: {node: '>=4'}
+ resolve-from@5.0.0:
+ resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==}
+ engines: {node: '>=8'}
+
resolve-pkg-maps@1.0.0:
resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==}
@@ -2760,9 +3707,20 @@ packages:
resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==}
engines: {node: '>= 0.4'}
+ signal-exit@3.0.7:
+ resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==}
+
+ signal-exit@4.1.0:
+ resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==}
+ engines: {node: '>=14'}
+
simple-swizzle@0.2.2:
resolution: {integrity: sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==}
+ slash@3.0.0:
+ resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==}
+ engines: {node: '>=8'}
+
slash@5.1.0:
resolution: {integrity: sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==}
engines: {node: '>=14.16'}
@@ -2771,16 +3729,42 @@ packages:
resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
engines: {node: '>=0.10.0'}
+ source-map-support@0.5.13:
+ resolution: {integrity: sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==}
+
+ source-map@0.6.1:
+ resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==}
+ engines: {node: '>=0.10.0'}
+
space-separated-tokens@2.0.2:
resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==}
+ sprintf-js@1.0.3:
+ resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==}
+
stable-hash@0.0.5:
resolution: {integrity: sha512-+L3ccpzibovGXFK+Ap/f8LOS0ahMrHTf3xu7mMLSpEGU0EO9ucaysSylKo9eRDFNhWve/y275iPmIZ4z39a9iA==}
+ stack-utils@2.0.6:
+ resolution: {integrity: sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==}
+ engines: {node: '>=10'}
+
streamsearch@1.1.0:
resolution: {integrity: sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==}
engines: {node: '>=10.0.0'}
+ string-length@4.0.2:
+ resolution: {integrity: sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==}
+ engines: {node: '>=10'}
+
+ string-width@4.2.3:
+ resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==}
+ engines: {node: '>=8'}
+
+ string-width@5.1.2:
+ resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==}
+ engines: {node: '>=12'}
+
string.prototype.includes@2.0.1:
resolution: {integrity: sha512-o7+c9bW6zpAdJHTtujeePODAhkuicdAryFsfVKwA+wGw89wJ4GTY484WTucM9hLtDEOpOvI+aHnzqnC5lHp4Rg==}
engines: {node: '>= 0.4'}
@@ -2807,10 +3791,26 @@ packages:
stringify-entities@4.0.4:
resolution: {integrity: sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==}
+ strip-ansi@6.0.1:
+ resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==}
+ engines: {node: '>=8'}
+
+ strip-ansi@7.1.0:
+ resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==}
+ engines: {node: '>=12'}
+
strip-bom@3.0.0:
resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==}
engines: {node: '>=4'}
+ strip-bom@4.0.0:
+ resolution: {integrity: sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==}
+ engines: {node: '>=8'}
+
+ strip-final-newline@2.0.0:
+ resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==}
+ engines: {node: '>=6'}
+
strip-json-comments@3.1.1:
resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==}
engines: {node: '>=8'}
@@ -2838,6 +3838,10 @@ packages:
resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==}
engines: {node: '>=8'}
+ supports-color@8.1.1:
+ resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==}
+ engines: {node: '>=10'}
+
supports-preserve-symlinks-flag@1.0.0:
resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
engines: {node: '>= 0.4'}
@@ -2846,6 +3850,10 @@ packages:
resolution: {integrity: sha512-2pR2ubZSV64f/vqm9eLPz/KOvR9Dm+Co/5ChLgeHl0yEDRc6h5hXHoxEQH8Y5Ljycozd3p1k5TTSVdzYGkPvLw==}
engines: {node: ^14.18.0 || >=16.0.0}
+ synckit@0.11.8:
+ resolution: {integrity: sha512-+XZ+r1XGIJGeQk3VvXhT6xx/VpbHsRzsTkGgF6E5RX9TTXD0118l87puaEBZ566FhqblC6U0d4XnubznJDm30A==}
+ engines: {node: ^14.18.0 || >=16.0.0}
+
tailwindcss@4.1.7:
resolution: {integrity: sha512-kr1o/ErIdNhTz8uzAYL7TpaUuzKIE6QPQ4qmSdxnoX/lo+5wmUHQA6h3L5yIqEImSRnAAURDirLu/BgiXGPAhg==}
@@ -2857,10 +3865,17 @@ packages:
resolution: {integrity: sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==}
engines: {node: '>=18'}
+ test-exclude@6.0.0:
+ resolution: {integrity: sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==}
+ engines: {node: '>=8'}
+
tinyglobby@0.2.13:
resolution: {integrity: sha512-mEwzpUgrLySlveBwEVDMKk5B57bhLPYovRfPAXD5gA/98Opn0rCDj3GtLwFvCvH5RK9uPCExUROW5NjDwvqkxw==}
engines: {node: '>=12.0.0'}
+ tmpl@1.0.5:
+ resolution: {integrity: sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==}
+
to-regex-range@5.0.1:
resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
engines: {node: '>=8.0'}
@@ -2877,6 +3892,33 @@ packages:
peerDependencies:
typescript: '>=4.8.4'
+ ts-jest@29.4.0:
+ resolution: {integrity: sha512-d423TJMnJGu80/eSgfQ5w/R+0zFJvdtTxwtF9KzFFunOpSeD+79lHJQIiAhluJoyGRbvj9NZJsl9WjCUo0ND7Q==}
+ engines: {node: ^14.15.0 || ^16.10.0 || ^18.0.0 || >=20.0.0}
+ hasBin: true
+ peerDependencies:
+ '@babel/core': '>=7.0.0-beta.0 <8'
+ '@jest/transform': ^29.0.0 || ^30.0.0
+ '@jest/types': ^29.0.0 || ^30.0.0
+ babel-jest: ^29.0.0 || ^30.0.0
+ esbuild: '*'
+ jest: ^29.0.0 || ^30.0.0
+ jest-util: ^29.0.0 || ^30.0.0
+ typescript: '>=4.3 <6'
+ peerDependenciesMeta:
+ '@babel/core':
+ optional: true
+ '@jest/transform':
+ optional: true
+ '@jest/types':
+ optional: true
+ babel-jest:
+ optional: true
+ esbuild:
+ optional: true
+ jest-util:
+ optional: true
+
ts-node@10.9.2:
resolution: {integrity: sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==}
hasBin: true
@@ -2906,6 +3948,18 @@ packages:
resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==}
engines: {node: '>= 0.8.0'}
+ type-detect@4.0.8:
+ resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==}
+ engines: {node: '>=4'}
+
+ type-fest@0.21.3:
+ resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==}
+ engines: {node: '>=10'}
+
+ type-fest@4.41.0:
+ resolution: {integrity: sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==}
+ engines: {node: '>=16'}
+
typed-array-buffer@1.0.3:
resolution: {integrity: sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==}
engines: {node: '>= 0.4'}
@@ -2962,6 +4016,15 @@ packages:
unrs-resolver@1.7.2:
resolution: {integrity: sha512-BBKpaylOW8KbHsu378Zky/dGh4ckT/4NW/0SHRABdqRLcQJ2dAOjDo9g97p04sWflm0kqPqpUatxReNV/dqI5A==}
+ unrs-resolver@1.9.2:
+ resolution: {integrity: sha512-VUyWiTNQD7itdiMuJy+EuLEErLj3uwX/EpHQF8EOf33Dq3Ju6VW1GXm+swk6+1h7a49uv9fKZ+dft9jU7esdLA==}
+
+ update-browserslist-db@1.1.3:
+ resolution: {integrity: sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==}
+ hasBin: true
+ peerDependencies:
+ browserslist: '>= 4.21.0'
+
uri-js@4.4.1:
resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==}
@@ -2972,6 +4035,10 @@ packages:
v8-compile-cache-lib@3.0.1:
resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==}
+ v8-to-istanbul@9.3.0:
+ resolution: {integrity: sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==}
+ engines: {node: '>=10.12.0'}
+
vfile-location@5.0.3:
resolution: {integrity: sha512-5yXvWDEgqeiYiBe1lbxYF7UMAIm/IcopxMHrMQDq3nvKcjPKIhZklUKL+AE7J7uApI4kwe2snsK+eI6UTj9EHg==}
@@ -2981,6 +4048,9 @@ packages:
vfile@6.0.3:
resolution: {integrity: sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==}
+ walker@1.0.8:
+ resolution: {integrity: sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==}
+
web-namespaces@2.0.1:
resolution: {integrity: sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==}
@@ -3016,6 +4086,28 @@ packages:
resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==}
engines: {node: '>=0.10.0'}
+ wrap-ansi@7.0.0:
+ resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==}
+ engines: {node: '>=10'}
+
+ wrap-ansi@8.1.0:
+ resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==}
+ engines: {node: '>=12'}
+
+ wrappy@1.0.2:
+ resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==}
+
+ write-file-atomic@5.0.1:
+ resolution: {integrity: sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==}
+ engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
+
+ y18n@5.0.8:
+ resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==}
+ engines: {node: '>=10'}
+
+ yallist@3.1.1:
+ resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==}
+
yallist@4.0.0:
resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==}
@@ -3023,6 +4115,14 @@ packages:
resolution: {integrity: sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==}
engines: {node: '>=18'}
+ yargs-parser@21.1.1:
+ resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==}
+ engines: {node: '>=12'}
+
+ yargs@17.7.2:
+ resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==}
+ engines: {node: '>=12'}
+
yn@3.1.1:
resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==}
engines: {node: '>=6'}
@@ -3043,8 +4143,195 @@ snapshots:
'@jridgewell/gen-mapping': 0.3.8
'@jridgewell/trace-mapping': 0.3.25
+ '@babel/code-frame@7.27.1':
+ dependencies:
+ '@babel/helper-validator-identifier': 7.27.1
+ js-tokens: 4.0.0
+ picocolors: 1.1.1
+
+ '@babel/compat-data@7.27.7': {}
+
+ '@babel/core@7.27.7':
+ dependencies:
+ '@ampproject/remapping': 2.3.0
+ '@babel/code-frame': 7.27.1
+ '@babel/generator': 7.27.5
+ '@babel/helper-compilation-targets': 7.27.2
+ '@babel/helper-module-transforms': 7.27.3(@babel/core@7.27.7)
+ '@babel/helpers': 7.27.6
+ '@babel/parser': 7.27.7
+ '@babel/template': 7.27.2
+ '@babel/traverse': 7.27.7
+ '@babel/types': 7.27.7
+ convert-source-map: 2.0.0
+ debug: 4.4.1
+ gensync: 1.0.0-beta.2
+ json5: 2.2.3
+ semver: 6.3.1
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/generator@7.27.5':
+ dependencies:
+ '@babel/parser': 7.27.7
+ '@babel/types': 7.27.7
+ '@jridgewell/gen-mapping': 0.3.8
+ '@jridgewell/trace-mapping': 0.3.25
+ jsesc: 3.1.0
+
+ '@babel/helper-compilation-targets@7.27.2':
+ dependencies:
+ '@babel/compat-data': 7.27.7
+ '@babel/helper-validator-option': 7.27.1
+ browserslist: 4.25.1
+ lru-cache: 5.1.1
+ semver: 6.3.1
+
+ '@babel/helper-module-imports@7.27.1':
+ dependencies:
+ '@babel/traverse': 7.27.7
+ '@babel/types': 7.27.7
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/helper-module-transforms@7.27.3(@babel/core@7.27.7)':
+ dependencies:
+ '@babel/core': 7.27.7
+ '@babel/helper-module-imports': 7.27.1
+ '@babel/helper-validator-identifier': 7.27.1
+ '@babel/traverse': 7.27.7
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/helper-plugin-utils@7.27.1': {}
+
+ '@babel/helper-string-parser@7.27.1': {}
+
+ '@babel/helper-validator-identifier@7.27.1': {}
+
+ '@babel/helper-validator-option@7.27.1': {}
+
+ '@babel/helpers@7.27.6':
+ dependencies:
+ '@babel/template': 7.27.2
+ '@babel/types': 7.27.7
+
+ '@babel/parser@7.27.7':
+ dependencies:
+ '@babel/types': 7.27.7
+
+ '@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.27.7)':
+ dependencies:
+ '@babel/core': 7.27.7
+ '@babel/helper-plugin-utils': 7.27.1
+
+ '@babel/plugin-syntax-bigint@7.8.3(@babel/core@7.27.7)':
+ dependencies:
+ '@babel/core': 7.27.7
+ '@babel/helper-plugin-utils': 7.27.1
+
+ '@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.27.7)':
+ dependencies:
+ '@babel/core': 7.27.7
+ '@babel/helper-plugin-utils': 7.27.1
+
+ '@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.27.7)':
+ dependencies:
+ '@babel/core': 7.27.7
+ '@babel/helper-plugin-utils': 7.27.1
+
+ '@babel/plugin-syntax-import-attributes@7.27.1(@babel/core@7.27.7)':
+ dependencies:
+ '@babel/core': 7.27.7
+ '@babel/helper-plugin-utils': 7.27.1
+
+ '@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.27.7)':
+ dependencies:
+ '@babel/core': 7.27.7
+ '@babel/helper-plugin-utils': 7.27.1
+
+ '@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.27.7)':
+ dependencies:
+ '@babel/core': 7.27.7
+ '@babel/helper-plugin-utils': 7.27.1
+
+ '@babel/plugin-syntax-jsx@7.27.1(@babel/core@7.27.7)':
+ dependencies:
+ '@babel/core': 7.27.7
+ '@babel/helper-plugin-utils': 7.27.1
+
+ '@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.27.7)':
+ dependencies:
+ '@babel/core': 7.27.7
+ '@babel/helper-plugin-utils': 7.27.1
+
+ '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.27.7)':
+ dependencies:
+ '@babel/core': 7.27.7
+ '@babel/helper-plugin-utils': 7.27.1
+
+ '@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.27.7)':
+ dependencies:
+ '@babel/core': 7.27.7
+ '@babel/helper-plugin-utils': 7.27.1
+
+ '@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.27.7)':
+ dependencies:
+ '@babel/core': 7.27.7
+ '@babel/helper-plugin-utils': 7.27.1
+
+ '@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.27.7)':
+ dependencies:
+ '@babel/core': 7.27.7
+ '@babel/helper-plugin-utils': 7.27.1
+
+ '@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.27.7)':
+ dependencies:
+ '@babel/core': 7.27.7
+ '@babel/helper-plugin-utils': 7.27.1
+
+ '@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.27.7)':
+ dependencies:
+ '@babel/core': 7.27.7
+ '@babel/helper-plugin-utils': 7.27.1
+
+ '@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.27.7)':
+ dependencies:
+ '@babel/core': 7.27.7
+ '@babel/helper-plugin-utils': 7.27.1
+
+ '@babel/plugin-syntax-typescript@7.27.1(@babel/core@7.27.7)':
+ dependencies:
+ '@babel/core': 7.27.7
+ '@babel/helper-plugin-utils': 7.27.1
+
'@babel/runtime@7.27.1': {}
+ '@babel/template@7.27.2':
+ dependencies:
+ '@babel/code-frame': 7.27.1
+ '@babel/parser': 7.27.7
+ '@babel/types': 7.27.7
+
+ '@babel/traverse@7.27.7':
+ dependencies:
+ '@babel/code-frame': 7.27.1
+ '@babel/generator': 7.27.5
+ '@babel/parser': 7.27.7
+ '@babel/template': 7.27.2
+ '@babel/types': 7.27.7
+ debug: 4.4.1
+ globals: 11.12.0
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/types@7.27.7':
+ dependencies:
+ '@babel/helper-string-parser': 7.27.1
+ '@babel/helper-validator-identifier': 7.27.1
+
+ '@bcoe/v8-coverage@0.2.3': {}
+
'@cspotcode/source-map-support@0.8.1':
dependencies:
'@jridgewell/trace-mapping': 0.3.9
@@ -3278,10 +4565,208 @@ snapshots:
'@img/sharp-win32-x64@0.34.2':
optional: true
+ '@isaacs/cliui@8.0.2':
+ dependencies:
+ string-width: 5.1.2
+ string-width-cjs: string-width@4.2.3
+ strip-ansi: 7.1.0
+ strip-ansi-cjs: strip-ansi@6.0.1
+ wrap-ansi: 8.1.0
+ wrap-ansi-cjs: wrap-ansi@7.0.0
+
'@isaacs/fs-minipass@4.0.1':
dependencies:
minipass: 7.1.2
+ '@istanbuljs/load-nyc-config@1.1.0':
+ dependencies:
+ camelcase: 5.3.1
+ find-up: 4.1.0
+ get-package-type: 0.1.0
+ js-yaml: 3.14.1
+ resolve-from: 5.0.0
+
+ '@istanbuljs/schema@0.1.3': {}
+
+ '@jest/console@30.0.2':
+ dependencies:
+ '@jest/types': 30.0.1
+ '@types/node': 22.15.21
+ chalk: 4.1.2
+ jest-message-util: 30.0.2
+ jest-util: 30.0.2
+ slash: 3.0.0
+
+ '@jest/core@30.0.3(ts-node@10.9.2(@types/node@22.15.21)(typescript@5.8.3))':
+ dependencies:
+ '@jest/console': 30.0.2
+ '@jest/pattern': 30.0.1
+ '@jest/reporters': 30.0.2
+ '@jest/test-result': 30.0.2
+ '@jest/transform': 30.0.2
+ '@jest/types': 30.0.1
+ '@types/node': 22.15.21
+ ansi-escapes: 4.3.2
+ chalk: 4.1.2
+ ci-info: 4.2.0
+ exit-x: 0.2.2
+ graceful-fs: 4.2.11
+ jest-changed-files: 30.0.2
+ jest-config: 30.0.3(@types/node@22.15.21)(ts-node@10.9.2(@types/node@22.15.21)(typescript@5.8.3))
+ jest-haste-map: 30.0.2
+ jest-message-util: 30.0.2
+ jest-regex-util: 30.0.1
+ jest-resolve: 30.0.2
+ jest-resolve-dependencies: 30.0.3
+ jest-runner: 30.0.3
+ jest-runtime: 30.0.3
+ jest-snapshot: 30.0.3
+ jest-util: 30.0.2
+ jest-validate: 30.0.2
+ jest-watcher: 30.0.2
+ micromatch: 4.0.8
+ pretty-format: 30.0.2
+ slash: 3.0.0
+ transitivePeerDependencies:
+ - babel-plugin-macros
+ - esbuild-register
+ - supports-color
+ - ts-node
+
+ '@jest/diff-sequences@30.0.1': {}
+
+ '@jest/environment@30.0.2':
+ dependencies:
+ '@jest/fake-timers': 30.0.2
+ '@jest/types': 30.0.1
+ '@types/node': 22.15.21
+ jest-mock: 30.0.2
+
+ '@jest/expect-utils@30.0.3':
+ dependencies:
+ '@jest/get-type': 30.0.1
+
+ '@jest/expect@30.0.3':
+ dependencies:
+ expect: 30.0.3
+ jest-snapshot: 30.0.3
+ transitivePeerDependencies:
+ - supports-color
+
+ '@jest/fake-timers@30.0.2':
+ dependencies:
+ '@jest/types': 30.0.1
+ '@sinonjs/fake-timers': 13.0.5
+ '@types/node': 22.15.21
+ jest-message-util: 30.0.2
+ jest-mock: 30.0.2
+ jest-util: 30.0.2
+
+ '@jest/get-type@30.0.1': {}
+
+ '@jest/globals@30.0.3':
+ dependencies:
+ '@jest/environment': 30.0.2
+ '@jest/expect': 30.0.3
+ '@jest/types': 30.0.1
+ jest-mock: 30.0.2
+ transitivePeerDependencies:
+ - supports-color
+
+ '@jest/pattern@30.0.1':
+ dependencies:
+ '@types/node': 22.15.21
+ jest-regex-util: 30.0.1
+
+ '@jest/reporters@30.0.2':
+ dependencies:
+ '@bcoe/v8-coverage': 0.2.3
+ '@jest/console': 30.0.2
+ '@jest/test-result': 30.0.2
+ '@jest/transform': 30.0.2
+ '@jest/types': 30.0.1
+ '@jridgewell/trace-mapping': 0.3.25
+ '@types/node': 22.15.21
+ chalk: 4.1.2
+ collect-v8-coverage: 1.0.2
+ exit-x: 0.2.2
+ glob: 10.4.5
+ graceful-fs: 4.2.11
+ istanbul-lib-coverage: 3.2.2
+ istanbul-lib-instrument: 6.0.3
+ istanbul-lib-report: 3.0.1
+ istanbul-lib-source-maps: 5.0.6
+ istanbul-reports: 3.1.7
+ jest-message-util: 30.0.2
+ jest-util: 30.0.2
+ jest-worker: 30.0.2
+ slash: 3.0.0
+ string-length: 4.0.2
+ v8-to-istanbul: 9.3.0
+ transitivePeerDependencies:
+ - supports-color
+
+ '@jest/schemas@30.0.1':
+ dependencies:
+ '@sinclair/typebox': 0.34.37
+
+ '@jest/snapshot-utils@30.0.1':
+ dependencies:
+ '@jest/types': 30.0.1
+ chalk: 4.1.2
+ graceful-fs: 4.2.11
+ natural-compare: 1.4.0
+
+ '@jest/source-map@30.0.1':
+ dependencies:
+ '@jridgewell/trace-mapping': 0.3.25
+ callsites: 3.1.0
+ graceful-fs: 4.2.11
+
+ '@jest/test-result@30.0.2':
+ dependencies:
+ '@jest/console': 30.0.2
+ '@jest/types': 30.0.1
+ '@types/istanbul-lib-coverage': 2.0.6
+ collect-v8-coverage: 1.0.2
+
+ '@jest/test-sequencer@30.0.2':
+ dependencies:
+ '@jest/test-result': 30.0.2
+ graceful-fs: 4.2.11
+ jest-haste-map: 30.0.2
+ slash: 3.0.0
+
+ '@jest/transform@30.0.2':
+ dependencies:
+ '@babel/core': 7.27.7
+ '@jest/types': 30.0.1
+ '@jridgewell/trace-mapping': 0.3.25
+ babel-plugin-istanbul: 7.0.0
+ chalk: 4.1.2
+ convert-source-map: 2.0.0
+ fast-json-stable-stringify: 2.1.0
+ graceful-fs: 4.2.11
+ jest-haste-map: 30.0.2
+ jest-regex-util: 30.0.1
+ jest-util: 30.0.2
+ micromatch: 4.0.8
+ pirates: 4.0.7
+ slash: 3.0.0
+ write-file-atomic: 5.0.1
+ transitivePeerDependencies:
+ - supports-color
+
+ '@jest/types@30.0.1':
+ dependencies:
+ '@jest/pattern': 30.0.1
+ '@jest/schemas': 30.0.1
+ '@types/istanbul-lib-coverage': 2.0.6
+ '@types/istanbul-reports': 3.0.4
+ '@types/node': 22.15.21
+ '@types/yargs': 17.0.33
+ chalk: 4.1.2
+
'@jridgewell/gen-mapping@0.3.8':
dependencies:
'@jridgewell/set-array': 1.2.1
@@ -3313,6 +4798,13 @@ snapshots:
'@tybys/wasm-util': 0.9.0
optional: true
+ '@napi-rs/wasm-runtime@0.2.11':
+ dependencies:
+ '@emnapi/core': 1.4.3
+ '@emnapi/runtime': 1.4.3
+ '@tybys/wasm-util': 0.9.0
+ optional: true
+
'@next/env@15.3.2': {}
'@next/eslint-plugin-next@15.3.2':
@@ -3359,6 +4851,9 @@ snapshots:
'@panva/hkdf@1.2.1': {}
+ '@pkgjs/parseargs@0.11.0':
+ optional: true
+
'@pkgr/core@0.2.4': {}
'@playwright/test@1.52.0':
@@ -3409,8 +4904,18 @@ snapshots:
'@rushstack/eslint-patch@1.11.0': {}
+ '@sinclair/typebox@0.34.37': {}
+
'@sindresorhus/merge-streams@2.3.0': {}
+ '@sinonjs/commons@3.0.1':
+ dependencies:
+ type-detect: 4.0.8
+
+ '@sinonjs/fake-timers@13.0.5':
+ dependencies:
+ '@sinonjs/commons': 3.0.1
+
'@swc/counter@0.1.3': {}
'@swc/helpers@0.5.15':
@@ -3502,6 +5007,27 @@ snapshots:
tslib: 2.8.1
optional: true
+ '@types/babel__core@7.20.5':
+ dependencies:
+ '@babel/parser': 7.27.7
+ '@babel/types': 7.27.7
+ '@types/babel__generator': 7.27.0
+ '@types/babel__template': 7.4.4
+ '@types/babel__traverse': 7.20.7
+
+ '@types/babel__generator@7.27.0':
+ dependencies:
+ '@babel/types': 7.27.7
+
+ '@types/babel__template@7.4.4':
+ dependencies:
+ '@babel/parser': 7.27.7
+ '@babel/types': 7.27.7
+
+ '@types/babel__traverse@7.20.7':
+ dependencies:
+ '@babel/types': 7.27.7
+
'@types/bcryptjs@2.4.6': {}
'@types/d3-array@3.2.1': {}
@@ -3643,6 +5169,21 @@ snapshots:
dependencies:
'@types/unist': 3.0.3
+ '@types/istanbul-lib-coverage@2.0.6': {}
+
+ '@types/istanbul-lib-report@3.0.3':
+ dependencies:
+ '@types/istanbul-lib-coverage': 2.0.6
+
+ '@types/istanbul-reports@3.0.4':
+ dependencies:
+ '@types/istanbul-lib-report': 3.0.3
+
+ '@types/jest@30.0.0':
+ dependencies:
+ expect: 30.0.3
+ pretty-format: 30.0.2
+
'@types/json-schema@7.0.15': {}
'@types/json5@0.0.29': {}
@@ -3678,10 +5219,18 @@ snapshots:
dependencies:
csstype: 3.1.3
+ '@types/stack-utils@2.0.3': {}
+
'@types/unist@2.0.11': {}
'@types/unist@3.0.3': {}
+ '@types/yargs-parser@21.0.3': {}
+
+ '@types/yargs@17.0.33':
+ dependencies:
+ '@types/yargs-parser': 21.0.3
+
'@typescript-eslint/eslint-plugin@8.32.1(@typescript-eslint/parser@8.32.1(eslint@9.27.0(jiti@2.4.2))(typescript@5.8.3))(eslint@9.27.0(jiti@2.4.2))(typescript@5.8.3)':
dependencies:
'@eslint-community/regexpp': 4.12.1
@@ -3761,59 +5310,118 @@ snapshots:
'@ungap/structured-clone@1.3.0': {}
+ '@unrs/resolver-binding-android-arm-eabi@1.9.2':
+ optional: true
+
+ '@unrs/resolver-binding-android-arm64@1.9.2':
+ optional: true
+
'@unrs/resolver-binding-darwin-arm64@1.7.2':
optional: true
+ '@unrs/resolver-binding-darwin-arm64@1.9.2':
+ optional: true
+
'@unrs/resolver-binding-darwin-x64@1.7.2':
optional: true
+ '@unrs/resolver-binding-darwin-x64@1.9.2':
+ optional: true
+
'@unrs/resolver-binding-freebsd-x64@1.7.2':
optional: true
+ '@unrs/resolver-binding-freebsd-x64@1.9.2':
+ optional: true
+
'@unrs/resolver-binding-linux-arm-gnueabihf@1.7.2':
optional: true
+ '@unrs/resolver-binding-linux-arm-gnueabihf@1.9.2':
+ optional: true
+
'@unrs/resolver-binding-linux-arm-musleabihf@1.7.2':
optional: true
+ '@unrs/resolver-binding-linux-arm-musleabihf@1.9.2':
+ optional: true
+
'@unrs/resolver-binding-linux-arm64-gnu@1.7.2':
optional: true
+ '@unrs/resolver-binding-linux-arm64-gnu@1.9.2':
+ optional: true
+
'@unrs/resolver-binding-linux-arm64-musl@1.7.2':
optional: true
+ '@unrs/resolver-binding-linux-arm64-musl@1.9.2':
+ optional: true
+
'@unrs/resolver-binding-linux-ppc64-gnu@1.7.2':
optional: true
+ '@unrs/resolver-binding-linux-ppc64-gnu@1.9.2':
+ optional: true
+
'@unrs/resolver-binding-linux-riscv64-gnu@1.7.2':
optional: true
+ '@unrs/resolver-binding-linux-riscv64-gnu@1.9.2':
+ optional: true
+
'@unrs/resolver-binding-linux-riscv64-musl@1.7.2':
optional: true
+ '@unrs/resolver-binding-linux-riscv64-musl@1.9.2':
+ optional: true
+
'@unrs/resolver-binding-linux-s390x-gnu@1.7.2':
optional: true
+ '@unrs/resolver-binding-linux-s390x-gnu@1.9.2':
+ optional: true
+
'@unrs/resolver-binding-linux-x64-gnu@1.7.2':
optional: true
+ '@unrs/resolver-binding-linux-x64-gnu@1.9.2':
+ optional: true
+
'@unrs/resolver-binding-linux-x64-musl@1.7.2':
optional: true
+ '@unrs/resolver-binding-linux-x64-musl@1.9.2':
+ optional: true
+
'@unrs/resolver-binding-wasm32-wasi@1.7.2':
dependencies:
'@napi-rs/wasm-runtime': 0.2.10
optional: true
+ '@unrs/resolver-binding-wasm32-wasi@1.9.2':
+ dependencies:
+ '@napi-rs/wasm-runtime': 0.2.11
+ optional: true
+
'@unrs/resolver-binding-win32-arm64-msvc@1.7.2':
optional: true
+ '@unrs/resolver-binding-win32-arm64-msvc@1.9.2':
+ optional: true
+
'@unrs/resolver-binding-win32-ia32-msvc@1.7.2':
optional: true
+ '@unrs/resolver-binding-win32-ia32-msvc@1.9.2':
+ optional: true
+
'@unrs/resolver-binding-win32-x64-msvc@1.7.2':
optional: true
+ '@unrs/resolver-binding-win32-x64-msvc@1.9.2':
+ optional: true
+
acorn-jsx@5.3.2(acorn@8.14.1):
dependencies:
acorn: 8.14.1
@@ -3831,12 +5439,33 @@ snapshots:
json-schema-traverse: 0.4.1
uri-js: 4.4.1
+ ansi-escapes@4.3.2:
+ dependencies:
+ type-fest: 0.21.3
+
+ ansi-regex@5.0.1: {}
+
+ ansi-regex@6.1.0: {}
+
ansi-styles@4.3.0:
dependencies:
color-convert: 2.0.1
+ ansi-styles@5.2.0: {}
+
+ ansi-styles@6.2.1: {}
+
+ anymatch@3.1.3:
+ dependencies:
+ normalize-path: 3.0.0
+ picomatch: 2.3.1
+
arg@4.1.3: {}
+ argparse@1.0.10:
+ dependencies:
+ sprintf-js: 1.0.3
+
argparse@2.0.1: {}
aria-query@5.3.2: {}
@@ -3910,6 +5539,8 @@ snapshots:
async-function@1.0.0: {}
+ async@3.2.6: {}
+
asynckit@0.4.0: {}
available-typed-arrays@1.0.7:
@@ -3920,6 +5551,60 @@ snapshots:
axobject-query@4.1.0: {}
+ babel-jest@30.0.2(@babel/core@7.27.7):
+ dependencies:
+ '@babel/core': 7.27.7
+ '@jest/transform': 30.0.2
+ '@types/babel__core': 7.20.5
+ babel-plugin-istanbul: 7.0.0
+ babel-preset-jest: 30.0.1(@babel/core@7.27.7)
+ chalk: 4.1.2
+ graceful-fs: 4.2.11
+ slash: 3.0.0
+ transitivePeerDependencies:
+ - supports-color
+
+ babel-plugin-istanbul@7.0.0:
+ dependencies:
+ '@babel/helper-plugin-utils': 7.27.1
+ '@istanbuljs/load-nyc-config': 1.1.0
+ '@istanbuljs/schema': 0.1.3
+ istanbul-lib-instrument: 6.0.3
+ test-exclude: 6.0.0
+ transitivePeerDependencies:
+ - supports-color
+
+ babel-plugin-jest-hoist@30.0.1:
+ dependencies:
+ '@babel/template': 7.27.2
+ '@babel/types': 7.27.7
+ '@types/babel__core': 7.20.5
+
+ babel-preset-current-node-syntax@1.1.0(@babel/core@7.27.7):
+ dependencies:
+ '@babel/core': 7.27.7
+ '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.27.7)
+ '@babel/plugin-syntax-bigint': 7.8.3(@babel/core@7.27.7)
+ '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.27.7)
+ '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.27.7)
+ '@babel/plugin-syntax-import-attributes': 7.27.1(@babel/core@7.27.7)
+ '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.27.7)
+ '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.27.7)
+ '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.27.7)
+ '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.27.7)
+ '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.27.7)
+ '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.27.7)
+ '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.27.7)
+ '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.27.7)
+ '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.27.7)
+ '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.27.7)
+
+ babel-preset-jest@30.0.1(@babel/core@7.27.7):
+ dependencies:
+ '@babel/core': 7.27.7
+ babel-plugin-jest-hoist: 30.0.1
+ babel-preset-current-node-syntax: 1.1.0(@babel/core@7.27.7)
+
bail@2.0.2: {}
balanced-match@1.0.2: {}
@@ -3939,6 +5624,23 @@ snapshots:
dependencies:
fill-range: 7.1.1
+ browserslist@4.25.1:
+ dependencies:
+ caniuse-lite: 1.0.30001726
+ electron-to-chromium: 1.5.177
+ node-releases: 2.0.19
+ update-browserslist-db: 1.1.3(browserslist@4.25.1)
+
+ bs-logger@0.2.6:
+ dependencies:
+ fast-json-stable-stringify: 2.1.0
+
+ bser@2.1.1:
+ dependencies:
+ node-int64: 0.4.0
+
+ buffer-from@1.1.2: {}
+
busboy@1.6.0:
dependencies:
streamsearch: 1.1.0
@@ -3962,8 +5664,14 @@ snapshots:
callsites@3.1.0: {}
+ camelcase@5.3.1: {}
+
+ camelcase@6.3.0: {}
+
caniuse-lite@1.0.30001718: {}
+ caniuse-lite@1.0.30001726: {}
+
ccount@2.0.1: {}
chalk@4.1.2:
@@ -3971,6 +5679,8 @@ snapshots:
ansi-styles: 4.3.0
supports-color: 7.2.0
+ char-regex@1.0.2: {}
+
character-entities-html4@2.1.0: {}
character-entities-legacy@3.0.0: {}
@@ -3989,8 +5699,22 @@ snapshots:
chownr@3.0.0: {}
+ ci-info@4.2.0: {}
+
+ cjs-module-lexer@2.1.0: {}
+
client-only@0.0.1: {}
+ cliui@8.0.1:
+ dependencies:
+ string-width: 4.2.3
+ strip-ansi: 6.0.1
+ wrap-ansi: 7.0.0
+
+ co@4.6.0: {}
+
+ collect-v8-coverage@1.0.2: {}
+
color-convert@2.0.1:
dependencies:
color-name: 1.1.4
@@ -4021,6 +5745,8 @@ snapshots:
concat-map@0.0.1: {}
+ convert-source-map@2.0.0: {}
+
cookie@0.7.2: {}
create-require@1.1.1: {}
@@ -4227,8 +5953,12 @@ snapshots:
dependencies:
character-entities: 2.0.2
+ dedent@1.6.0: {}
+
deep-is@0.1.4: {}
+ deepmerge@4.3.1: {}
+
define-data-property@1.1.4:
dependencies:
es-define-property: 1.0.1
@@ -4251,6 +5981,8 @@ snapshots:
detect-libc@2.0.4: {}
+ detect-newline@3.1.0: {}
+
devlop@1.1.0:
dependencies:
dequal: 2.0.3
@@ -4269,6 +6001,18 @@ snapshots:
es-errors: 1.3.0
gopd: 1.2.0
+ eastasianwidth@0.2.0: {}
+
+ ejs@3.1.10:
+ dependencies:
+ jake: 10.9.2
+
+ electron-to-chromium@1.5.177: {}
+
+ emittery@0.13.1: {}
+
+ emoji-regex@8.0.0: {}
+
emoji-regex@9.2.2: {}
enhanced-resolve@5.18.1:
@@ -4280,6 +6024,10 @@ snapshots:
entities@6.0.0: {}
+ error-ex@1.3.2:
+ dependencies:
+ is-arrayish: 0.2.1
+
es-abstract@1.23.9:
dependencies:
array-buffer-byte-length: 1.0.2
@@ -4406,6 +6154,10 @@ snapshots:
'@esbuild/win32-ia32': 0.25.5
'@esbuild/win32-x64': 0.25.5
+ escalade@3.2.0: {}
+
+ escape-string-regexp@2.0.0: {}
+
escape-string-regexp@4.0.0: {}
eslint-config-next@15.3.2(eslint@9.27.0(jiti@2.4.2))(typescript@5.8.3):
@@ -4600,6 +6352,8 @@ snapshots:
acorn-jsx: 5.3.2(acorn@8.14.1)
eslint-visitor-keys: 4.2.0
+ esprima@4.0.1: {}
+
esquery@1.6.0:
dependencies:
estraverse: 5.3.0
@@ -4614,6 +6368,29 @@ snapshots:
esutils@2.0.3: {}
+ execa@5.1.1:
+ dependencies:
+ cross-spawn: 7.0.6
+ get-stream: 6.0.1
+ human-signals: 2.1.0
+ is-stream: 2.0.1
+ merge-stream: 2.0.0
+ npm-run-path: 4.0.1
+ onetime: 5.1.2
+ signal-exit: 3.0.7
+ strip-final-newline: 2.0.0
+
+ exit-x@0.2.2: {}
+
+ expect@30.0.3:
+ dependencies:
+ '@jest/expect-utils': 30.0.3
+ '@jest/get-type': 30.0.1
+ jest-matcher-utils: 30.0.3
+ jest-message-util: 30.0.2
+ jest-mock: 30.0.2
+ jest-util: 30.0.2
+
extend@3.0.2: {}
fast-deep-equal@3.1.3: {}
@@ -4644,6 +6421,10 @@ snapshots:
dependencies:
reusify: 1.1.0
+ fb-watchman@2.0.2:
+ dependencies:
+ bser: 2.1.1
+
fdir@6.4.4(picomatch@4.0.2):
optionalDependencies:
picomatch: 4.0.2
@@ -4657,10 +6438,19 @@ snapshots:
dependencies:
flat-cache: 4.0.1
+ filelist@1.0.4:
+ dependencies:
+ minimatch: 5.1.6
+
fill-range@7.1.1:
dependencies:
to-regex-range: 5.0.1
+ find-up@4.1.0:
+ dependencies:
+ locate-path: 5.0.0
+ path-exists: 4.0.0
+
find-up@5.0.0:
dependencies:
locate-path: 6.0.0
@@ -4677,6 +6467,11 @@ snapshots:
dependencies:
is-callable: 1.2.7
+ foreground-child@3.3.1:
+ dependencies:
+ cross-spawn: 7.0.6
+ signal-exit: 4.1.0
+
form-data@4.0.2:
dependencies:
asynckit: 0.4.0
@@ -4688,6 +6483,8 @@ snapshots:
dependencies:
fetch-blob: 3.2.0
+ fs.realpath@1.0.0: {}
+
fsevents@2.3.2:
optional: true
@@ -4707,6 +6504,10 @@ snapshots:
functions-have-names@1.2.3: {}
+ gensync@1.0.0-beta.2: {}
+
+ get-caller-file@2.0.5: {}
+
get-intrinsic@1.3.0:
dependencies:
call-bind-apply-helpers: 1.0.2
@@ -4720,11 +6521,15 @@ snapshots:
hasown: 2.0.2
math-intrinsics: 1.1.0
+ get-package-type@0.1.0: {}
+
get-proto@1.0.1:
dependencies:
dunder-proto: 1.0.1
es-object-atoms: 1.1.1
+ get-stream@6.0.1: {}
+
get-symbol-description@1.1.0:
dependencies:
call-bound: 1.0.4
@@ -4743,6 +6548,26 @@ snapshots:
dependencies:
is-glob: 4.0.3
+ glob@10.4.5:
+ dependencies:
+ foreground-child: 3.3.1
+ jackspeak: 3.4.3
+ minimatch: 9.0.5
+ minipass: 7.1.2
+ package-json-from-dist: 1.0.1
+ path-scurry: 1.11.1
+
+ glob@7.2.3:
+ dependencies:
+ fs.realpath: 1.0.0
+ inflight: 1.0.6
+ inherits: 2.0.4
+ minimatch: 3.1.2
+ once: 1.4.0
+ path-is-absolute: 1.0.1
+
+ globals@11.12.0: {}
+
globals@14.0.0: {}
globalthis@1.0.4:
@@ -4860,10 +6685,14 @@ snapshots:
property-information: 7.1.0
space-separated-tokens: 2.0.2
+ html-escaper@2.0.2: {}
+
html-url-attributes@3.0.1: {}
html-void-elements@3.0.0: {}
+ human-signals@2.1.0: {}
+
i18n-iso-countries@7.14.0:
dependencies:
diacritics: 1.3.0
@@ -4881,8 +6710,20 @@ snapshots:
parent-module: 1.0.1
resolve-from: 4.0.0
+ import-local@3.2.0:
+ dependencies:
+ pkg-dir: 4.2.0
+ resolve-cwd: 3.0.0
+
imurmurhash@0.1.4: {}
+ inflight@1.0.6:
+ dependencies:
+ once: 1.4.0
+ wrappy: 1.0.2
+
+ inherits@2.0.4: {}
+
inline-style-parser@0.2.4: {}
internal-slot@1.1.0:
@@ -4906,6 +6747,8 @@ snapshots:
call-bound: 1.0.4
get-intrinsic: 1.3.0
+ is-arrayish@0.2.1: {}
+
is-arrayish@0.3.2:
optional: true
@@ -4955,6 +6798,10 @@ snapshots:
dependencies:
call-bound: 1.0.4
+ is-fullwidth-code-point@3.0.0: {}
+
+ is-generator-fn@2.1.0: {}
+
is-generator-function@1.1.0:
dependencies:
call-bound: 1.0.4
@@ -4992,6 +6839,8 @@ snapshots:
dependencies:
call-bound: 1.0.4
+ is-stream@2.0.1: {}
+
is-string@1.1.1:
dependencies:
call-bound: 1.0.4
@@ -5024,6 +6873,37 @@ snapshots:
iso-639-1@3.1.5: {}
+ istanbul-lib-coverage@3.2.2: {}
+
+ istanbul-lib-instrument@6.0.3:
+ dependencies:
+ '@babel/core': 7.27.7
+ '@babel/parser': 7.27.7
+ '@istanbuljs/schema': 0.1.3
+ istanbul-lib-coverage: 3.2.2
+ semver: 7.7.2
+ transitivePeerDependencies:
+ - supports-color
+
+ istanbul-lib-report@3.0.1:
+ dependencies:
+ istanbul-lib-coverage: 3.2.2
+ make-dir: 4.0.0
+ supports-color: 7.2.0
+
+ istanbul-lib-source-maps@5.0.6:
+ dependencies:
+ '@jridgewell/trace-mapping': 0.3.25
+ debug: 4.4.1
+ istanbul-lib-coverage: 3.2.2
+ transitivePeerDependencies:
+ - supports-color
+
+ istanbul-reports@3.1.7:
+ dependencies:
+ html-escaper: 2.0.2
+ istanbul-lib-report: 3.0.1
+
iterator.prototype@1.1.5:
dependencies:
define-data-property: 1.1.4
@@ -5033,18 +6913,352 @@ snapshots:
has-symbols: 1.1.0
set-function-name: 2.0.2
+ jackspeak@3.4.3:
+ dependencies:
+ '@isaacs/cliui': 8.0.2
+ optionalDependencies:
+ '@pkgjs/parseargs': 0.11.0
+
+ jake@10.9.2:
+ dependencies:
+ async: 3.2.6
+ chalk: 4.1.2
+ filelist: 1.0.4
+ minimatch: 3.1.2
+
+ jest-changed-files@30.0.2:
+ dependencies:
+ execa: 5.1.1
+ jest-util: 30.0.2
+ p-limit: 3.1.0
+
+ jest-circus@30.0.3:
+ dependencies:
+ '@jest/environment': 30.0.2
+ '@jest/expect': 30.0.3
+ '@jest/test-result': 30.0.2
+ '@jest/types': 30.0.1
+ '@types/node': 22.15.21
+ chalk: 4.1.2
+ co: 4.6.0
+ dedent: 1.6.0
+ is-generator-fn: 2.1.0
+ jest-each: 30.0.2
+ jest-matcher-utils: 30.0.3
+ jest-message-util: 30.0.2
+ jest-runtime: 30.0.3
+ jest-snapshot: 30.0.3
+ jest-util: 30.0.2
+ p-limit: 3.1.0
+ pretty-format: 30.0.2
+ pure-rand: 7.0.1
+ slash: 3.0.0
+ stack-utils: 2.0.6
+ transitivePeerDependencies:
+ - babel-plugin-macros
+ - supports-color
+
+ jest-cli@30.0.3(@types/node@22.15.21)(ts-node@10.9.2(@types/node@22.15.21)(typescript@5.8.3)):
+ dependencies:
+ '@jest/core': 30.0.3(ts-node@10.9.2(@types/node@22.15.21)(typescript@5.8.3))
+ '@jest/test-result': 30.0.2
+ '@jest/types': 30.0.1
+ chalk: 4.1.2
+ exit-x: 0.2.2
+ import-local: 3.2.0
+ jest-config: 30.0.3(@types/node@22.15.21)(ts-node@10.9.2(@types/node@22.15.21)(typescript@5.8.3))
+ jest-util: 30.0.2
+ jest-validate: 30.0.2
+ yargs: 17.7.2
+ transitivePeerDependencies:
+ - '@types/node'
+ - babel-plugin-macros
+ - esbuild-register
+ - supports-color
+ - ts-node
+
+ jest-config@30.0.3(@types/node@22.15.21)(ts-node@10.9.2(@types/node@22.15.21)(typescript@5.8.3)):
+ dependencies:
+ '@babel/core': 7.27.7
+ '@jest/get-type': 30.0.1
+ '@jest/pattern': 30.0.1
+ '@jest/test-sequencer': 30.0.2
+ '@jest/types': 30.0.1
+ babel-jest: 30.0.2(@babel/core@7.27.7)
+ chalk: 4.1.2
+ ci-info: 4.2.0
+ deepmerge: 4.3.1
+ glob: 10.4.5
+ graceful-fs: 4.2.11
+ jest-circus: 30.0.3
+ jest-docblock: 30.0.1
+ jest-environment-node: 30.0.2
+ jest-regex-util: 30.0.1
+ jest-resolve: 30.0.2
+ jest-runner: 30.0.3
+ jest-util: 30.0.2
+ jest-validate: 30.0.2
+ micromatch: 4.0.8
+ parse-json: 5.2.0
+ pretty-format: 30.0.2
+ slash: 3.0.0
+ strip-json-comments: 3.1.1
+ optionalDependencies:
+ '@types/node': 22.15.21
+ ts-node: 10.9.2(@types/node@22.15.21)(typescript@5.8.3)
+ transitivePeerDependencies:
+ - babel-plugin-macros
+ - supports-color
+
+ jest-diff@30.0.3:
+ dependencies:
+ '@jest/diff-sequences': 30.0.1
+ '@jest/get-type': 30.0.1
+ chalk: 4.1.2
+ pretty-format: 30.0.2
+
+ jest-docblock@30.0.1:
+ dependencies:
+ detect-newline: 3.1.0
+
+ jest-each@30.0.2:
+ dependencies:
+ '@jest/get-type': 30.0.1
+ '@jest/types': 30.0.1
+ chalk: 4.1.2
+ jest-util: 30.0.2
+ pretty-format: 30.0.2
+
+ jest-environment-node@30.0.2:
+ dependencies:
+ '@jest/environment': 30.0.2
+ '@jest/fake-timers': 30.0.2
+ '@jest/types': 30.0.1
+ '@types/node': 22.15.21
+ jest-mock: 30.0.2
+ jest-util: 30.0.2
+ jest-validate: 30.0.2
+
+ jest-haste-map@30.0.2:
+ dependencies:
+ '@jest/types': 30.0.1
+ '@types/node': 22.15.21
+ anymatch: 3.1.3
+ fb-watchman: 2.0.2
+ graceful-fs: 4.2.11
+ jest-regex-util: 30.0.1
+ jest-util: 30.0.2
+ jest-worker: 30.0.2
+ micromatch: 4.0.8
+ walker: 1.0.8
+ optionalDependencies:
+ fsevents: 2.3.3
+
+ jest-leak-detector@30.0.2:
+ dependencies:
+ '@jest/get-type': 30.0.1
+ pretty-format: 30.0.2
+
+ jest-matcher-utils@30.0.3:
+ dependencies:
+ '@jest/get-type': 30.0.1
+ chalk: 4.1.2
+ jest-diff: 30.0.3
+ pretty-format: 30.0.2
+
+ jest-message-util@30.0.2:
+ dependencies:
+ '@babel/code-frame': 7.27.1
+ '@jest/types': 30.0.1
+ '@types/stack-utils': 2.0.3
+ chalk: 4.1.2
+ graceful-fs: 4.2.11
+ micromatch: 4.0.8
+ pretty-format: 30.0.2
+ slash: 3.0.0
+ stack-utils: 2.0.6
+
+ jest-mock@30.0.2:
+ dependencies:
+ '@jest/types': 30.0.1
+ '@types/node': 22.15.21
+ jest-util: 30.0.2
+
+ jest-pnp-resolver@1.2.3(jest-resolve@30.0.2):
+ optionalDependencies:
+ jest-resolve: 30.0.2
+
+ jest-regex-util@30.0.1: {}
+
+ jest-resolve-dependencies@30.0.3:
+ dependencies:
+ jest-regex-util: 30.0.1
+ jest-snapshot: 30.0.3
+ transitivePeerDependencies:
+ - supports-color
+
+ jest-resolve@30.0.2:
+ dependencies:
+ chalk: 4.1.2
+ graceful-fs: 4.2.11
+ jest-haste-map: 30.0.2
+ jest-pnp-resolver: 1.2.3(jest-resolve@30.0.2)
+ jest-util: 30.0.2
+ jest-validate: 30.0.2
+ slash: 3.0.0
+ unrs-resolver: 1.9.2
+
+ jest-runner@30.0.3:
+ dependencies:
+ '@jest/console': 30.0.2
+ '@jest/environment': 30.0.2
+ '@jest/test-result': 30.0.2
+ '@jest/transform': 30.0.2
+ '@jest/types': 30.0.1
+ '@types/node': 22.15.21
+ chalk: 4.1.2
+ emittery: 0.13.1
+ exit-x: 0.2.2
+ graceful-fs: 4.2.11
+ jest-docblock: 30.0.1
+ jest-environment-node: 30.0.2
+ jest-haste-map: 30.0.2
+ jest-leak-detector: 30.0.2
+ jest-message-util: 30.0.2
+ jest-resolve: 30.0.2
+ jest-runtime: 30.0.3
+ jest-util: 30.0.2
+ jest-watcher: 30.0.2
+ jest-worker: 30.0.2
+ p-limit: 3.1.0
+ source-map-support: 0.5.13
+ transitivePeerDependencies:
+ - supports-color
+
+ jest-runtime@30.0.3:
+ dependencies:
+ '@jest/environment': 30.0.2
+ '@jest/fake-timers': 30.0.2
+ '@jest/globals': 30.0.3
+ '@jest/source-map': 30.0.1
+ '@jest/test-result': 30.0.2
+ '@jest/transform': 30.0.2
+ '@jest/types': 30.0.1
+ '@types/node': 22.15.21
+ chalk: 4.1.2
+ cjs-module-lexer: 2.1.0
+ collect-v8-coverage: 1.0.2
+ glob: 10.4.5
+ graceful-fs: 4.2.11
+ jest-haste-map: 30.0.2
+ jest-message-util: 30.0.2
+ jest-mock: 30.0.2
+ jest-regex-util: 30.0.1
+ jest-resolve: 30.0.2
+ jest-snapshot: 30.0.3
+ jest-util: 30.0.2
+ slash: 3.0.0
+ strip-bom: 4.0.0
+ transitivePeerDependencies:
+ - supports-color
+
+ jest-snapshot@30.0.3:
+ dependencies:
+ '@babel/core': 7.27.7
+ '@babel/generator': 7.27.5
+ '@babel/plugin-syntax-jsx': 7.27.1(@babel/core@7.27.7)
+ '@babel/plugin-syntax-typescript': 7.27.1(@babel/core@7.27.7)
+ '@babel/types': 7.27.7
+ '@jest/expect-utils': 30.0.3
+ '@jest/get-type': 30.0.1
+ '@jest/snapshot-utils': 30.0.1
+ '@jest/transform': 30.0.2
+ '@jest/types': 30.0.1
+ babel-preset-current-node-syntax: 1.1.0(@babel/core@7.27.7)
+ chalk: 4.1.2
+ expect: 30.0.3
+ graceful-fs: 4.2.11
+ jest-diff: 30.0.3
+ jest-matcher-utils: 30.0.3
+ jest-message-util: 30.0.2
+ jest-util: 30.0.2
+ pretty-format: 30.0.2
+ semver: 7.7.2
+ synckit: 0.11.8
+ transitivePeerDependencies:
+ - supports-color
+
+ jest-util@30.0.2:
+ dependencies:
+ '@jest/types': 30.0.1
+ '@types/node': 22.15.21
+ chalk: 4.1.2
+ ci-info: 4.2.0
+ graceful-fs: 4.2.11
+ picomatch: 4.0.2
+
+ jest-validate@30.0.2:
+ dependencies:
+ '@jest/get-type': 30.0.1
+ '@jest/types': 30.0.1
+ camelcase: 6.3.0
+ chalk: 4.1.2
+ leven: 3.1.0
+ pretty-format: 30.0.2
+
+ jest-watcher@30.0.2:
+ dependencies:
+ '@jest/test-result': 30.0.2
+ '@jest/types': 30.0.1
+ '@types/node': 22.15.21
+ ansi-escapes: 4.3.2
+ chalk: 4.1.2
+ emittery: 0.13.1
+ jest-util: 30.0.2
+ string-length: 4.0.2
+
+ jest-worker@30.0.2:
+ dependencies:
+ '@types/node': 22.15.21
+ '@ungap/structured-clone': 1.3.0
+ jest-util: 30.0.2
+ merge-stream: 2.0.0
+ supports-color: 8.1.1
+
+ jest@30.0.3(@types/node@22.15.21)(ts-node@10.9.2(@types/node@22.15.21)(typescript@5.8.3)):
+ dependencies:
+ '@jest/core': 30.0.3(ts-node@10.9.2(@types/node@22.15.21)(typescript@5.8.3))
+ '@jest/types': 30.0.1
+ import-local: 3.2.0
+ jest-cli: 30.0.3(@types/node@22.15.21)(ts-node@10.9.2(@types/node@22.15.21)(typescript@5.8.3))
+ transitivePeerDependencies:
+ - '@types/node'
+ - babel-plugin-macros
+ - esbuild-register
+ - supports-color
+ - ts-node
+
jiti@2.4.2: {}
jose@4.15.9: {}
js-tokens@4.0.0: {}
+ js-yaml@3.14.1:
+ dependencies:
+ argparse: 1.0.10
+ esprima: 4.0.1
+
js-yaml@4.1.0:
dependencies:
argparse: 2.0.1
+ jsesc@3.1.0: {}
+
json-buffer@3.0.1: {}
+ json-parse-even-better-errors@2.3.1: {}
+
json-schema-traverse@0.4.1: {}
json-stable-stringify-without-jsonify@1.0.1: {}
@@ -5053,6 +7267,8 @@ snapshots:
dependencies:
minimist: 1.2.8
+ json5@2.2.3: {}
+
jsonc-parser@3.3.1: {}
jsx-ast-utils@3.3.5:
@@ -5078,6 +7294,8 @@ snapshots:
leaflet@1.9.4: {}
+ leven@3.1.0: {}
+
levn@0.4.1:
dependencies:
prelude-ls: 1.2.1
@@ -5130,14 +7348,22 @@ snapshots:
lineclip@1.1.5: {}
+ lines-and-columns@1.2.4: {}
+
linkify-it@5.0.0:
dependencies:
uc.micro: 2.1.0
+ locate-path@5.0.0:
+ dependencies:
+ p-locate: 4.1.0
+
locate-path@6.0.0:
dependencies:
p-locate: 5.0.0
+ lodash.memoize@4.1.2: {}
+
lodash.merge@4.6.2: {}
longest-streak@3.1.0: {}
@@ -5146,6 +7372,12 @@ snapshots:
dependencies:
js-tokens: 4.0.0
+ lru-cache@10.4.3: {}
+
+ lru-cache@5.1.1:
+ dependencies:
+ yallist: 3.1.1
+
lru-cache@6.0.0:
dependencies:
yallist: 4.0.0
@@ -5154,8 +7386,16 @@ snapshots:
dependencies:
'@jridgewell/sourcemap-codec': 1.5.0
+ make-dir@4.0.0:
+ dependencies:
+ semver: 7.7.2
+
make-error@1.3.6: {}
+ makeerror@1.0.12:
+ dependencies:
+ tmpl: 1.0.5
+
markdown-it@14.1.0:
dependencies:
argparse: 2.0.1
@@ -5287,6 +7527,8 @@ snapshots:
mdurl@2.0.0: {}
+ merge-stream@2.0.0: {}
+
merge2@1.4.1: {}
micromark-core-commonmark@2.0.3:
@@ -5479,10 +7721,16 @@ snapshots:
dependencies:
mime-db: 1.52.0
+ mimic-fn@2.1.0: {}
+
minimatch@3.1.2:
dependencies:
brace-expansion: 1.1.11
+ minimatch@5.1.6:
+ dependencies:
+ brace-expansion: 2.0.1
+
minimatch@9.0.5:
dependencies:
brace-expansion: 2.0.1
@@ -5505,13 +7753,13 @@ snapshots:
natural-compare@1.4.0: {}
- next-auth@4.24.11(next@15.3.2(@playwright/test@1.52.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react-dom@19.1.0(react@19.1.0))(react@19.1.0):
+ next-auth@4.24.11(next@15.3.2(@babel/core@7.27.7)(@playwright/test@1.52.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react-dom@19.1.0(react@19.1.0))(react@19.1.0):
dependencies:
'@babel/runtime': 7.27.1
'@panva/hkdf': 1.2.1
cookie: 0.7.2
jose: 4.15.9
- next: 15.3.2(@playwright/test@1.52.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
+ next: 15.3.2(@babel/core@7.27.7)(@playwright/test@1.52.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
oauth: 0.9.15
openid-client: 5.7.1
preact: 10.26.6
@@ -5520,7 +7768,7 @@ snapshots:
react-dom: 19.1.0(react@19.1.0)
uuid: 8.3.2
- next@15.3.2(@playwright/test@1.52.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0):
+ next@15.3.2(@babel/core@7.27.7)(@playwright/test@1.52.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0):
dependencies:
'@next/env': 15.3.2
'@swc/counter': 0.1.3
@@ -5530,7 +7778,7 @@ snapshots:
postcss: 8.4.31
react: 19.1.0
react-dom: 19.1.0(react@19.1.0)
- styled-jsx: 5.1.6(react@19.1.0)
+ styled-jsx: 5.1.6(@babel/core@7.27.7)(react@19.1.0)
optionalDependencies:
'@next/swc-darwin-arm64': 15.3.2
'@next/swc-darwin-x64': 15.3.2
@@ -5556,6 +7804,16 @@ snapshots:
fetch-blob: 3.2.0
formdata-polyfill: 4.0.10
+ node-int64@0.4.0: {}
+
+ node-releases@2.0.19: {}
+
+ normalize-path@3.0.0: {}
+
+ npm-run-path@4.0.1:
+ dependencies:
+ path-key: 3.1.1
+
oauth@0.9.15: {}
object-assign@4.1.1: {}
@@ -5604,6 +7862,14 @@ snapshots:
oidc-token-hash@5.1.0: {}
+ once@1.4.0:
+ dependencies:
+ wrappy: 1.0.2
+
+ onetime@5.1.2:
+ dependencies:
+ mimic-fn: 2.1.0
+
openid-client@5.7.1:
dependencies:
jose: 4.15.9
@@ -5626,14 +7892,26 @@ snapshots:
object-keys: 1.1.1
safe-push-apply: 1.0.0
+ p-limit@2.3.0:
+ dependencies:
+ p-try: 2.2.0
+
p-limit@3.1.0:
dependencies:
yocto-queue: 0.1.0
+ p-locate@4.1.0:
+ dependencies:
+ p-limit: 2.3.0
+
p-locate@5.0.0:
dependencies:
p-limit: 3.1.0
+ p-try@2.2.0: {}
+
+ package-json-from-dist@1.0.1: {}
+
parent-module@1.0.1:
dependencies:
callsites: 3.1.0
@@ -5648,16 +7926,30 @@ snapshots:
is-decimal: 2.0.1
is-hexadecimal: 2.0.1
+ parse-json@5.2.0:
+ dependencies:
+ '@babel/code-frame': 7.27.1
+ error-ex: 1.3.2
+ json-parse-even-better-errors: 2.3.1
+ lines-and-columns: 1.2.4
+
parse5@7.3.0:
dependencies:
entities: 6.0.0
path-exists@4.0.0: {}
+ path-is-absolute@1.0.1: {}
+
path-key@3.1.1: {}
path-parse@1.0.7: {}
+ path-scurry@1.11.1:
+ dependencies:
+ lru-cache: 10.4.3
+ minipass: 7.1.2
+
path-type@6.0.0: {}
picocolors@1.1.1: {}
@@ -5666,6 +7958,12 @@ snapshots:
picomatch@4.0.2: {}
+ pirates@4.0.7: {}
+
+ pkg-dir@4.2.0:
+ dependencies:
+ find-up: 4.1.0
+
playwright-core@1.52.0: {}
playwright@1.52.0:
@@ -5709,6 +8007,12 @@ snapshots:
pretty-format@3.8.0: {}
+ pretty-format@30.0.2:
+ dependencies:
+ '@jest/schemas': 30.0.1
+ ansi-styles: 5.2.0
+ react-is: 18.3.1
+
prisma@6.10.1(typescript@5.8.3):
dependencies:
'@prisma/config': 6.10.1
@@ -5730,6 +8034,8 @@ snapshots:
punycode@2.3.1: {}
+ pure-rand@7.0.1: {}
+
queue-microtask@1.2.3: {}
quickselect@1.1.1: {}
@@ -5750,6 +8056,8 @@ snapshots:
react-is@16.13.1: {}
+ react-is@18.3.1: {}
+
react-leaflet@5.0.0(leaflet@1.9.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0):
dependencies:
'@react-leaflet/core': 3.0.0(leaflet@1.9.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
@@ -5820,8 +8128,16 @@ snapshots:
unified: 11.0.5
vfile: 6.0.3
+ require-directory@2.1.1: {}
+
+ resolve-cwd@3.0.0:
+ dependencies:
+ resolve-from: 5.0.0
+
resolve-from@4.0.0: {}
+ resolve-from@5.0.0: {}
+
resolve-pkg-maps@1.0.0: {}
resolve@1.22.10:
@@ -5958,21 +8274,57 @@ snapshots:
side-channel-map: 1.0.1
side-channel-weakmap: 1.0.2
+ signal-exit@3.0.7: {}
+
+ signal-exit@4.1.0: {}
+
simple-swizzle@0.2.2:
dependencies:
is-arrayish: 0.3.2
optional: true
+ slash@3.0.0: {}
+
slash@5.1.0: {}
source-map-js@1.2.1: {}
+ source-map-support@0.5.13:
+ dependencies:
+ buffer-from: 1.1.2
+ source-map: 0.6.1
+
+ source-map@0.6.1: {}
+
space-separated-tokens@2.0.2: {}
+ sprintf-js@1.0.3: {}
+
stable-hash@0.0.5: {}
+ stack-utils@2.0.6:
+ dependencies:
+ escape-string-regexp: 2.0.0
+
streamsearch@1.1.0: {}
+ string-length@4.0.2:
+ dependencies:
+ char-regex: 1.0.2
+ strip-ansi: 6.0.1
+
+ string-width@4.2.3:
+ dependencies:
+ emoji-regex: 8.0.0
+ is-fullwidth-code-point: 3.0.0
+ strip-ansi: 6.0.1
+
+ string-width@5.1.2:
+ dependencies:
+ eastasianwidth: 0.2.0
+ emoji-regex: 9.2.2
+ strip-ansi: 7.1.0
+
string.prototype.includes@2.0.1:
dependencies:
call-bind: 1.0.8
@@ -6028,8 +8380,20 @@ snapshots:
character-entities-html4: 2.1.0
character-entities-legacy: 3.0.0
+ strip-ansi@6.0.1:
+ dependencies:
+ ansi-regex: 5.0.1
+
+ strip-ansi@7.1.0:
+ dependencies:
+ ansi-regex: 6.1.0
+
strip-bom@3.0.0: {}
+ strip-bom@4.0.0: {}
+
+ strip-final-newline@2.0.0: {}
+
strip-json-comments@3.1.1: {}
style-to-js@1.1.16:
@@ -6040,21 +8404,31 @@ snapshots:
dependencies:
inline-style-parser: 0.2.4
- styled-jsx@5.1.6(react@19.1.0):
+ styled-jsx@5.1.6(@babel/core@7.27.7)(react@19.1.0):
dependencies:
client-only: 0.0.1
react: 19.1.0
+ optionalDependencies:
+ '@babel/core': 7.27.7
supports-color@7.2.0:
dependencies:
has-flag: 4.0.0
+ supports-color@8.1.1:
+ dependencies:
+ has-flag: 4.0.0
+
supports-preserve-symlinks-flag@1.0.0: {}
synckit@0.11.6:
dependencies:
'@pkgr/core': 0.2.4
+ synckit@0.11.8:
+ dependencies:
+ '@pkgr/core': 0.2.4
+
tailwindcss@4.1.7: {}
tapable@2.2.2: {}
@@ -6068,11 +8442,19 @@ snapshots:
mkdirp: 3.0.1
yallist: 5.0.0
+ test-exclude@6.0.0:
+ dependencies:
+ '@istanbuljs/schema': 0.1.3
+ glob: 7.2.3
+ minimatch: 3.1.2
+
tinyglobby@0.2.13:
dependencies:
fdir: 6.4.4(picomatch@4.0.2)
picomatch: 4.0.2
+ tmpl@1.0.5: {}
+
to-regex-range@5.0.1:
dependencies:
is-number: 7.0.0
@@ -6085,6 +8467,26 @@ snapshots:
dependencies:
typescript: 5.8.3
+ ts-jest@29.4.0(@babel/core@7.27.7)(@jest/transform@30.0.2)(@jest/types@30.0.1)(babel-jest@30.0.2(@babel/core@7.27.7))(jest-util@30.0.2)(jest@30.0.3(@types/node@22.15.21)(ts-node@10.9.2(@types/node@22.15.21)(typescript@5.8.3)))(typescript@5.8.3):
+ dependencies:
+ bs-logger: 0.2.6
+ ejs: 3.1.10
+ fast-json-stable-stringify: 2.1.0
+ jest: 30.0.3(@types/node@22.15.21)(ts-node@10.9.2(@types/node@22.15.21)(typescript@5.8.3))
+ json5: 2.2.3
+ lodash.memoize: 4.1.2
+ make-error: 1.3.6
+ semver: 7.7.2
+ type-fest: 4.41.0
+ typescript: 5.8.3
+ yargs-parser: 21.1.1
+ optionalDependencies:
+ '@babel/core': 7.27.7
+ '@jest/transform': 30.0.2
+ '@jest/types': 30.0.1
+ babel-jest: 30.0.2(@babel/core@7.27.7)
+ jest-util: 30.0.2
+
ts-node@10.9.2(@types/node@22.15.21)(typescript@5.8.3):
dependencies:
'@cspotcode/source-map-support': 0.8.1
@@ -6123,6 +8525,12 @@ snapshots:
dependencies:
prelude-ls: 1.2.1
+ type-detect@4.0.8: {}
+
+ type-fest@0.21.3: {}
+
+ type-fest@4.41.0: {}
+
typed-array-buffer@1.0.3:
dependencies:
call-bound: 1.0.4
@@ -6226,6 +8634,36 @@ snapshots:
'@unrs/resolver-binding-win32-ia32-msvc': 1.7.2
'@unrs/resolver-binding-win32-x64-msvc': 1.7.2
+ unrs-resolver@1.9.2:
+ dependencies:
+ napi-postinstall: 0.2.4
+ optionalDependencies:
+ '@unrs/resolver-binding-android-arm-eabi': 1.9.2
+ '@unrs/resolver-binding-android-arm64': 1.9.2
+ '@unrs/resolver-binding-darwin-arm64': 1.9.2
+ '@unrs/resolver-binding-darwin-x64': 1.9.2
+ '@unrs/resolver-binding-freebsd-x64': 1.9.2
+ '@unrs/resolver-binding-linux-arm-gnueabihf': 1.9.2
+ '@unrs/resolver-binding-linux-arm-musleabihf': 1.9.2
+ '@unrs/resolver-binding-linux-arm64-gnu': 1.9.2
+ '@unrs/resolver-binding-linux-arm64-musl': 1.9.2
+ '@unrs/resolver-binding-linux-ppc64-gnu': 1.9.2
+ '@unrs/resolver-binding-linux-riscv64-gnu': 1.9.2
+ '@unrs/resolver-binding-linux-riscv64-musl': 1.9.2
+ '@unrs/resolver-binding-linux-s390x-gnu': 1.9.2
+ '@unrs/resolver-binding-linux-x64-gnu': 1.9.2
+ '@unrs/resolver-binding-linux-x64-musl': 1.9.2
+ '@unrs/resolver-binding-wasm32-wasi': 1.9.2
+ '@unrs/resolver-binding-win32-arm64-msvc': 1.9.2
+ '@unrs/resolver-binding-win32-ia32-msvc': 1.9.2
+ '@unrs/resolver-binding-win32-x64-msvc': 1.9.2
+
+ update-browserslist-db@1.1.3(browserslist@4.25.1):
+ dependencies:
+ browserslist: 4.25.1
+ escalade: 3.2.0
+ picocolors: 1.1.1
+
uri-js@4.4.1:
dependencies:
punycode: 2.3.1
@@ -6234,6 +8672,12 @@ snapshots:
v8-compile-cache-lib@3.0.1: {}
+ v8-to-istanbul@9.3.0:
+ dependencies:
+ '@jridgewell/trace-mapping': 0.3.25
+ '@types/istanbul-lib-coverage': 2.0.6
+ convert-source-map: 2.0.0
+
vfile-location@5.0.3:
dependencies:
'@types/unist': 3.0.3
@@ -6249,6 +8693,10 @@ snapshots:
'@types/unist': 3.0.3
vfile-message: 4.0.2
+ walker@1.0.8:
+ dependencies:
+ makeerror: 1.0.12
+
web-namespaces@2.0.1: {}
web-streams-polyfill@3.3.3: {}
@@ -6305,10 +8753,45 @@ snapshots:
word-wrap@1.2.5: {}
+ wrap-ansi@7.0.0:
+ dependencies:
+ ansi-styles: 4.3.0
+ string-width: 4.2.3
+ strip-ansi: 6.0.1
+
+ wrap-ansi@8.1.0:
+ dependencies:
+ ansi-styles: 6.2.1
+ string-width: 5.1.2
+ strip-ansi: 7.1.0
+
+ wrappy@1.0.2: {}
+
+ write-file-atomic@5.0.1:
+ dependencies:
+ imurmurhash: 0.1.4
+ signal-exit: 4.1.0
+
+ y18n@5.0.8: {}
+
+ yallist@3.1.1: {}
+
yallist@4.0.0: {}
yallist@5.0.0: {}
+ yargs-parser@21.1.1: {}
+
+ yargs@17.7.2:
+ dependencies:
+ cliui: 8.0.1
+ escalade: 3.2.0
+ get-caller-file: 2.0.5
+ require-directory: 2.1.1
+ string-width: 4.2.3
+ y18n: 5.0.8
+ yargs-parser: 21.1.1
+
yn@3.1.1: {}
yocto-queue@0.1.0: {}
diff --git a/prisma/schema.prisma b/prisma/schema.prisma
index 9ddc8f6..3cf8dac 100644
--- a/prisma/schema.prisma
+++ b/prisma/schema.prisma
@@ -155,6 +155,9 @@ model SessionImport {
category String?
initialMessage String?
+ // ─── Raw transcript content ─────────────────────────
+ rawTranscriptContent String? // Fetched content from fullTranscriptUrl
+
// ─── bookkeeping ─────────────────────────────────
status ImportStatus @default(QUEUED)
errorMsg String?
diff --git a/server.ts b/server.ts
index 3dd6bd9..961c148 100644
--- a/server.ts
+++ b/server.ts
@@ -3,8 +3,9 @@ import { createServer } from "http";
import { parse } from "url";
import next from "next";
import { startCsvImportScheduler } from "./lib/scheduler.js";
+import { startImportProcessingScheduler } from "./lib/importProcessor.js";
import { startProcessingScheduler } from "./lib/processingScheduler.js";
-import { getSchedulerConfig, logSchedulerConfig } from "./lib/schedulerConfig.js";
+import { getSchedulerConfig, logEnvConfig, validateEnv } from "./lib/env.js";
const dev = process.env.NODE_ENV !== "production";
const hostname = "localhost";
@@ -15,14 +16,22 @@ const app = next({ dev, hostname, port });
const handle = app.getRequestHandler();
app.prepare().then(() => {
- // Get and log scheduler configuration
+ // Validate and log environment configuration
+ const envValidation = validateEnv();
+ if (!envValidation.valid) {
+ console.error('[Environment] Validation errors:', envValidation.errors);
+ }
+
+ logEnvConfig();
+
+ // Get scheduler configuration
const config = getSchedulerConfig();
- logSchedulerConfig(config);
// Initialize schedulers based on configuration
if (config.enabled) {
console.log("Initializing schedulers...");
startCsvImportScheduler();
+ startImportProcessingScheduler();
startProcessingScheduler();
console.log("All schedulers initialized successfully");
}
diff --git a/tests/setup.ts b/tests/setup.ts
new file mode 100644
index 0000000..782d5b7
--- /dev/null
+++ b/tests/setup.ts
@@ -0,0 +1,25 @@
+// Jest test setup
+import { jest } from '@jest/globals';
+
+// Mock console methods to reduce noise in tests
+global.console = {
+ ...console,
+ log: jest.fn(),
+ warn: jest.fn(),
+ error: jest.fn(),
+};
+
+// Set test environment variables
+Object.defineProperty(process.env, 'NODE_ENV', {
+ value: 'test',
+ writable: true,
+ configurable: true,
+});
+process.env.NEXTAUTH_SECRET = 'test-secret';
+process.env.NEXTAUTH_URL = 'http://localhost:3000';
+
+// Mock node-fetch for transcript fetcher tests
+jest.mock('node-fetch', () => ({
+ __esModule: true,
+ default: jest.fn(),
+}));
diff --git a/tests/unit/env.test.ts b/tests/unit/env.test.ts
new file mode 100644
index 0000000..70f58d8
--- /dev/null
+++ b/tests/unit/env.test.ts
@@ -0,0 +1,174 @@
+// Unit tests for environment management
+import { describe, it, expect, beforeEach, afterEach } from '@jest/globals';
+import { env, validateEnv, getSchedulerConfig } from '../../lib/env';
+
+describe('Environment Management', () => {
+ let originalEnv: NodeJS.ProcessEnv;
+
+ beforeEach(() => {
+ // Save original environment
+ originalEnv = { ...process.env };
+ });
+
+ afterEach(() => {
+ // Restore original environment
+ process.env = originalEnv;
+ });
+
+ describe('env object', () => {
+ it('should have default values when environment variables are not set', () => {
+ // Clear relevant env vars
+ delete process.env.NEXTAUTH_URL;
+ delete process.env.SCHEDULER_ENABLED;
+ delete process.env.PORT;
+
+ // Re-import to get fresh env object
+ jest.resetModules();
+ const { env: freshEnv } = require('../../lib/env');
+
+ expect(freshEnv.NEXTAUTH_URL).toBe('http://localhost:3000');
+ expect(freshEnv.SCHEDULER_ENABLED).toBe(false);
+ expect(freshEnv.PORT).toBe(3000);
+ });
+
+ it('should use environment variables when set', () => {
+ process.env.NEXTAUTH_URL = 'https://example.com';
+ process.env.SCHEDULER_ENABLED = 'true';
+ process.env.PORT = '8080';
+
+ jest.resetModules();
+ const { env: freshEnv } = require('../../lib/env');
+
+ expect(freshEnv.NEXTAUTH_URL).toBe('https://example.com');
+ expect(freshEnv.SCHEDULER_ENABLED).toBe(true);
+ expect(freshEnv.PORT).toBe(8080);
+ });
+
+ it('should parse numeric environment variables correctly', () => {
+ process.env.IMPORT_PROCESSING_BATCH_SIZE = '100';
+ process.env.SESSION_PROCESSING_CONCURRENCY = '10';
+
+ jest.resetModules();
+ const { env: freshEnv } = require('../../lib/env');
+
+ expect(freshEnv.IMPORT_PROCESSING_BATCH_SIZE).toBe(100);
+ expect(freshEnv.SESSION_PROCESSING_CONCURRENCY).toBe(10);
+ });
+
+ it('should handle invalid numeric values gracefully', () => {
+ process.env.IMPORT_PROCESSING_BATCH_SIZE = 'invalid';
+ process.env.SESSION_PROCESSING_CONCURRENCY = '';
+
+ jest.resetModules();
+ const { env: freshEnv } = require('../../lib/env');
+
+ expect(freshEnv.IMPORT_PROCESSING_BATCH_SIZE).toBe(50); // default
+ expect(freshEnv.SESSION_PROCESSING_CONCURRENCY).toBe(5); // default
+ });
+ });
+
+ describe('validateEnv', () => {
+ it('should return valid when all required variables are set', () => {
+ process.env.NEXTAUTH_SECRET = 'test-secret';
+ process.env.OPENAI_API_KEY = 'test-key';
+ Object.defineProperty(process.env, 'NODE_ENV', {
+ value: 'production',
+ writable: true,
+ configurable: true,
+ });
+
+ jest.resetModules();
+ const { validateEnv: freshValidateEnv } = require('../../lib/env');
+
+ const result = freshValidateEnv();
+ expect(result.valid).toBe(true);
+ expect(result.errors).toHaveLength(0);
+ });
+
+ it('should return invalid when NEXTAUTH_SECRET is missing', () => {
+ delete process.env.NEXTAUTH_SECRET;
+
+ jest.resetModules();
+ const { validateEnv: freshValidateEnv } = require('../../lib/env');
+
+ const result = freshValidateEnv();
+ expect(result.valid).toBe(false);
+ expect(result.errors).toContain('NEXTAUTH_SECRET is required');
+ });
+
+ it('should require OPENAI_API_KEY in production', () => {
+ process.env.NEXTAUTH_SECRET = 'test-secret';
+ delete process.env.OPENAI_API_KEY;
+ Object.defineProperty(process.env, 'NODE_ENV', {
+ value: 'production',
+ writable: true,
+ configurable: true,
+ });
+
+ jest.resetModules();
+ const { validateEnv: freshValidateEnv } = require('../../lib/env');
+
+ const result = freshValidateEnv();
+ expect(result.valid).toBe(false);
+ expect(result.errors).toContain('OPENAI_API_KEY is required in production');
+ });
+
+ it('should not require OPENAI_API_KEY in development', () => {
+ process.env.NEXTAUTH_SECRET = 'test-secret';
+ delete process.env.OPENAI_API_KEY;
+ Object.defineProperty(process.env, 'NODE_ENV', {
+ value: 'development',
+ writable: true,
+ configurable: true,
+ });
+
+ jest.resetModules();
+ const { validateEnv: freshValidateEnv } = require('../../lib/env');
+
+ const result = freshValidateEnv();
+ expect(result.valid).toBe(true);
+ expect(result.errors).toHaveLength(0);
+ });
+ });
+
+ describe('getSchedulerConfig', () => {
+ it('should return correct scheduler configuration', () => {
+ process.env.SCHEDULER_ENABLED = 'true';
+ process.env.CSV_IMPORT_INTERVAL = '*/10 * * * *';
+ process.env.IMPORT_PROCESSING_INTERVAL = '*/3 * * * *';
+ process.env.IMPORT_PROCESSING_BATCH_SIZE = '25';
+ process.env.SESSION_PROCESSING_INTERVAL = '0 2 * * *';
+ process.env.SESSION_PROCESSING_BATCH_SIZE = '100';
+ process.env.SESSION_PROCESSING_CONCURRENCY = '8';
+
+ jest.resetModules();
+ const { getSchedulerConfig: freshGetSchedulerConfig } = require('../../lib/env');
+
+ const config = freshGetSchedulerConfig();
+
+ expect(config.enabled).toBe(true);
+ expect(config.csvImport.interval).toBe('*/10 * * * *');
+ expect(config.importProcessing.interval).toBe('*/3 * * * *');
+ expect(config.importProcessing.batchSize).toBe(25);
+ expect(config.sessionProcessing.interval).toBe('0 2 * * *');
+ expect(config.sessionProcessing.batchSize).toBe(100);
+ expect(config.sessionProcessing.concurrency).toBe(8);
+ });
+
+ it('should use defaults when environment variables are not set', () => {
+ delete process.env.SCHEDULER_ENABLED;
+ delete process.env.CSV_IMPORT_INTERVAL;
+ delete process.env.IMPORT_PROCESSING_INTERVAL;
+
+ jest.resetModules();
+ const { getSchedulerConfig: freshGetSchedulerConfig } = require('../../lib/env');
+
+ const config = freshGetSchedulerConfig();
+
+ expect(config.enabled).toBe(false);
+ expect(config.csvImport.interval).toBe('*/15 * * * *');
+ expect(config.importProcessing.interval).toBe('*/5 * * * *');
+ expect(config.importProcessing.batchSize).toBe(50);
+ });
+ });
+});
diff --git a/tests/unit/transcriptFetcher.test.ts b/tests/unit/transcriptFetcher.test.ts
new file mode 100644
index 0000000..08787c4
--- /dev/null
+++ b/tests/unit/transcriptFetcher.test.ts
@@ -0,0 +1,222 @@
+// Unit tests for transcript fetcher
+import { describe, it, expect, beforeEach, afterEach, jest } from '@jest/globals';
+import fetch from 'node-fetch';
+import {
+ fetchTranscriptContent,
+ isValidTranscriptUrl,
+ extractSessionIdFromTranscript
+} from '../../lib/transcriptFetcher';
+
+// Mock node-fetch
+const mockFetch = fetch as jest.MockedFunction;
+
+describe('Transcript Fetcher', () => {
+ beforeEach(() => {
+ jest.clearAllMocks();
+ });
+
+ describe('fetchTranscriptContent', () => {
+ it('should successfully fetch transcript content', async () => {
+ const mockResponse = {
+ ok: true,
+ text: jest.fn().mockResolvedValue('Session transcript content'),
+ };
+ mockFetch.mockResolvedValue(mockResponse as any);
+
+ const result = await fetchTranscriptContent('https://example.com/transcript');
+
+ expect(result.success).toBe(true);
+ expect(result.content).toBe('Session transcript content');
+ expect(result.error).toBeUndefined();
+ expect(mockFetch).toHaveBeenCalledWith('https://example.com/transcript', {
+ method: 'GET',
+ headers: {
+ 'User-Agent': 'LiveDash-Transcript-Fetcher/1.0',
+ },
+ signal: expect.any(AbortSignal),
+ });
+ });
+
+ it('should handle authentication with username and password', async () => {
+ const mockResponse = {
+ ok: true,
+ text: jest.fn().mockResolvedValue('Authenticated transcript'),
+ };
+ mockFetch.mockResolvedValue(mockResponse as any);
+
+ const result = await fetchTranscriptContent(
+ 'https://example.com/transcript',
+ 'user123',
+ 'pass456'
+ );
+
+ expect(result.success).toBe(true);
+ expect(result.content).toBe('Authenticated transcript');
+
+ const expectedAuth = 'Basic ' + Buffer.from('user123:pass456').toString('base64');
+ expect(mockFetch).toHaveBeenCalledWith('https://example.com/transcript', {
+ method: 'GET',
+ headers: {
+ 'User-Agent': 'LiveDash-Transcript-Fetcher/1.0',
+ 'Authorization': expectedAuth,
+ },
+ signal: expect.any(AbortSignal),
+ });
+ });
+
+ it('should handle HTTP errors', async () => {
+ const mockResponse = {
+ ok: false,
+ status: 404,
+ statusText: 'Not Found',
+ };
+ mockFetch.mockResolvedValue(mockResponse as any);
+
+ const result = await fetchTranscriptContent('https://example.com/transcript');
+
+ expect(result.success).toBe(false);
+ expect(result.error).toBe('HTTP 404: Not Found');
+ expect(result.content).toBeUndefined();
+ });
+
+ it('should handle empty transcript content', async () => {
+ const mockResponse = {
+ ok: true,
+ text: jest.fn().mockResolvedValue(' '),
+ };
+ mockFetch.mockResolvedValue(mockResponse as any);
+
+ const result = await fetchTranscriptContent('https://example.com/transcript');
+
+ expect(result.success).toBe(false);
+ expect(result.error).toBe('Empty transcript content');
+ expect(result.content).toBeUndefined();
+ });
+
+ it('should handle network errors', async () => {
+ mockFetch.mockRejectedValue(new Error('ENOTFOUND example.com'));
+
+ const result = await fetchTranscriptContent('https://example.com/transcript');
+
+ expect(result.success).toBe(false);
+ expect(result.error).toBe('Domain not found');
+ expect(result.content).toBeUndefined();
+ });
+
+ it('should handle connection refused errors', async () => {
+ mockFetch.mockRejectedValue(new Error('ECONNREFUSED'));
+
+ const result = await fetchTranscriptContent('https://example.com/transcript');
+
+ expect(result.success).toBe(false);
+ expect(result.error).toBe('Connection refused');
+ expect(result.content).toBeUndefined();
+ });
+
+ it('should handle timeout errors', async () => {
+ mockFetch.mockRejectedValue(new Error('Request timeout'));
+
+ const result = await fetchTranscriptContent('https://example.com/transcript');
+
+ expect(result.success).toBe(false);
+ expect(result.error).toBe('Request timeout');
+ expect(result.content).toBeUndefined();
+ });
+
+ it('should handle empty URL', async () => {
+ const result = await fetchTranscriptContent('');
+
+ expect(result.success).toBe(false);
+ expect(result.error).toBe('No transcript URL provided');
+ expect(result.content).toBeUndefined();
+ expect(mockFetch).not.toHaveBeenCalled();
+ });
+
+ it('should trim whitespace from content', async () => {
+ const mockResponse = {
+ ok: true,
+ text: jest.fn().mockResolvedValue(' \n Session content \n '),
+ };
+ mockFetch.mockResolvedValue(mockResponse as any);
+
+ const result = await fetchTranscriptContent('https://example.com/transcript');
+
+ expect(result.success).toBe(true);
+ expect(result.content).toBe('Session content');
+ });
+ });
+
+ describe('isValidTranscriptUrl', () => {
+ it('should validate HTTP URLs', () => {
+ expect(isValidTranscriptUrl('http://example.com/transcript')).toBe(true);
+ });
+
+ it('should validate HTTPS URLs', () => {
+ expect(isValidTranscriptUrl('https://example.com/transcript')).toBe(true);
+ });
+
+ it('should reject invalid URLs', () => {
+ expect(isValidTranscriptUrl('not-a-url')).toBe(false);
+ expect(isValidTranscriptUrl('ftp://example.com')).toBe(false);
+ expect(isValidTranscriptUrl('')).toBe(false);
+ expect(isValidTranscriptUrl(null as any)).toBe(false);
+ expect(isValidTranscriptUrl(undefined as any)).toBe(false);
+ });
+
+ it('should handle malformed URLs', () => {
+ expect(isValidTranscriptUrl('http://')).toBe(false);
+ expect(isValidTranscriptUrl('https://')).toBe(false);
+ expect(isValidTranscriptUrl('://example.com')).toBe(false);
+ });
+ });
+
+ describe('extractSessionIdFromTranscript', () => {
+ it('should extract session ID from session_id pattern', () => {
+ const content = 'session_id: abc123def456\nOther content...';
+ const result = extractSessionIdFromTranscript(content);
+ expect(result).toBe('abc123def456');
+ });
+
+ it('should extract session ID from sessionId pattern', () => {
+ const content = 'sessionId: xyz789\nTranscript data...';
+ const result = extractSessionIdFromTranscript(content);
+ expect(result).toBe('xyz789');
+ });
+
+ it('should extract session ID from id pattern', () => {
+ const content = 'id: session-12345678\nChat log...';
+ const result = extractSessionIdFromTranscript(content);
+ expect(result).toBe('session-12345678');
+ });
+
+ it('should extract session ID from first line', () => {
+ const content = 'abc123def456\nUser: Hello\nBot: Hi there';
+ const result = extractSessionIdFromTranscript(content);
+ expect(result).toBe('abc123def456');
+ });
+
+ it('should return null for content without session ID', () => {
+ const content = 'User: Hello\nBot: Hi there\nUser: How are you?';
+ const result = extractSessionIdFromTranscript(content);
+ expect(result).toBe(null);
+ });
+
+ it('should return null for empty content', () => {
+ expect(extractSessionIdFromTranscript('')).toBe(null);
+ expect(extractSessionIdFromTranscript(null as any)).toBe(null);
+ expect(extractSessionIdFromTranscript(undefined as any)).toBe(null);
+ });
+
+ it('should handle case-insensitive patterns', () => {
+ const content = 'SESSION_ID: ABC123\nContent...';
+ const result = extractSessionIdFromTranscript(content);
+ expect(result).toBe('ABC123');
+ });
+
+ it('should extract the first matching pattern', () => {
+ const content = 'session_id: first123\nid: second456\nMore content...';
+ const result = extractSessionIdFromTranscript(content);
+ expect(result).toBe('first123');
+ });
+ });
+});