diff --git a/apps/visualizer/.gitignore b/apps/visualizer/.gitignore new file mode 100644 index 000000000..50c8419df --- /dev/null +++ b/apps/visualizer/.gitignore @@ -0,0 +1,4 @@ +.vercel +.next +.env*.local +tsconfig.tsbuildinfo diff --git a/apps/visualizer/README.md b/apps/visualizer/README.md new file mode 100644 index 000000000..01718cf75 --- /dev/null +++ b/apps/visualizer/README.md @@ -0,0 +1,48 @@ +# Stripe Schema Visualizer + +This package contains the standalone browser UI for exploring generated Stripe schema data with PGlite. + +The visualizer has two parts: + +- `pnpm explorer:build` generates static artifacts. +- `apps/visualizer` loads those artifacts into PGlite and lets you run SQL in the browser. + +## Generated artifacts + +- `apps/visualizer/public/explorer-data/bootstrap.sql` +- `apps/visualizer/public/explorer-data/manifest.json` + +These files are generated and should stay out of version control. + +## Common commands + +```bash +pnpm explorer:build +pnpm visualizer +pnpm visualizer:with-data +``` + +`pnpm visualizer:with-data` rebuilds the explorer data and then starts the visualizer app. + +## How the app loads data + +At runtime, the app loads `manifest.json` first and then hydrates PGlite from `bootstrap.sql`. +After hydration, all SQL runs locally in the browser against the generated Stripe schema. + +## Direct phase debugging + +`pnpm explorer:build` is the normal command, but the underlying phase scripts still exist for debugging: + +```bash +bun run scripts/explorer-harness.ts start +bun run scripts/explorer-migrate.ts --api-version=2020-08-27 +bun run scripts/explorer-seed.ts --api-version=2020-08-27 --seed=42 +bun run scripts/explorer-export.ts +bun run scripts/explorer-harness.ts stop +``` + +## Notes + +- SQL bootstrap is preferred for speed and consistency. +- The build pipeline recreates the artifacts from scratch on each run. +- The deploy/install dashboard stays in `packages/dashboard`; this package only contains the schema visualizer UI. diff --git a/apps/visualizer/next-env.d.ts b/apps/visualizer/next-env.d.ts new file mode 100644 index 000000000..830fb594c --- /dev/null +++ b/apps/visualizer/next-env.d.ts @@ -0,0 +1,6 @@ +/// +/// +/// + +// NOTE: This file should not be edited +// see https://nextjs.org/docs/app/api-reference/config/typescript for more information. diff --git a/apps/visualizer/next.config.ts b/apps/visualizer/next.config.ts new file mode 100644 index 000000000..9463c230b --- /dev/null +++ b/apps/visualizer/next.config.ts @@ -0,0 +1,39 @@ +import type { NextConfig } from 'next' + +const nextConfig: NextConfig = { + typescript: { + ignoreBuildErrors: false, + }, + webpack: (config) => { + config.experiments = { + ...config.experiments, + asyncWebAssembly: true, + } + + config.module.rules.push({ + test: /\.wasm$/, + type: 'asset/resource', + }) + + return config + }, + async headers() { + return [ + { + source: '/(.*)', + headers: [ + { + key: 'Cross-Origin-Embedder-Policy', + value: 'require-corp', + }, + { + key: 'Cross-Origin-Opener-Policy', + value: 'same-origin', + }, + ], + }, + ] + }, +} + +export default nextConfig diff --git a/apps/visualizer/package.json b/apps/visualizer/package.json new file mode 100644 index 000000000..6c1ca2b45 --- /dev/null +++ b/apps/visualizer/package.json @@ -0,0 +1,32 @@ +{ + "name": "@stripe/sync-visualizer", + "version": "0.0.1", + "private": true, + "scripts": { + "dev": "next dev", + "build": "next build", + "start": "next start", + "lint": "next lint" + }, + "dependencies": { + "@stripe/sync-source-stripe": "workspace:*", + "@codemirror/lang-sql": "^6.7.0", + "@codemirror/state": "^6.4.0", + "@codemirror/view": "^6.26.0", + "@electric-sql/pglite": "^0.2.0", + "codemirror": "^6.0.1", + "next": "^15", + "react": "^19", + "react-dom": "^19" + }, + "devDependencies": { + "@tailwindcss/postcss": "^4.2.1", + "@types/node": "^22", + "@types/react": "^19", + "@types/react-dom": "^19", + "autoprefixer": "^10.4.27", + "postcss": "^8.5.8", + "tailwindcss": "^4.2.1", + "typescript": "^5" + } +} diff --git a/apps/visualizer/postcss.config.mjs b/apps/visualizer/postcss.config.mjs new file mode 100644 index 000000000..ae85b2fe4 --- /dev/null +++ b/apps/visualizer/postcss.config.mjs @@ -0,0 +1,7 @@ +const config = { + plugins: { + '@tailwindcss/postcss': {}, + }, +} + +export default config diff --git a/apps/visualizer/src/app/ExplorerClient.tsx b/apps/visualizer/src/app/ExplorerClient.tsx new file mode 100644 index 000000000..4cd37ff67 --- /dev/null +++ b/apps/visualizer/src/app/ExplorerClient.tsx @@ -0,0 +1,731 @@ +'use client' + +import { + useState, + useEffect, + useCallback, + useRef, + type PointerEvent as ReactPointerEvent, +} from 'react' +import { usePGlite } from '@/lib/pglite' +import { EditorView, keymap } from '@codemirror/view' +import { EditorState } from '@codemirror/state' +import { sql } from '@codemirror/lang-sql' +import { basicSetup } from 'codemirror' + +type QueryResult = { + rows: Record[] + fields: { name: string; dataTypeID: number }[] + rowCount: number +} + +type QueryContext = { mode: 'table'; tableName: string } | { mode: 'custom' } | null + +type DragState = + | { type: 'pane' } + | { + type: 'column' + columnKey: string + startWidth: number + startX: number + } + +const MIN_EDITOR_PANE_SIZE = 28 +const MAX_EDITOR_PANE_SIZE = 72 +const MIN_COLUMN_WIDTH = 140 +const DEFAULT_CELL_PREVIEW_LENGTH = 120 + +export default function ExplorerClient() { + const { status, error, query, manifest } = usePGlite() + const [selectedTable, setSelectedTable] = useState(null) + const [queryResult, setQueryResult] = useState(null) + const [queryError, setQueryError] = useState(null) + const [isExecuting, setIsExecuting] = useState(false) + const [editorPaneSize, setEditorPaneSize] = useState(44) + const [columnWidths, setColumnWidths] = useState>({}) + const [queryContext, setQueryContext] = useState(null) + const [currentPage, setCurrentPage] = useState(1) + const [rowsPerPage, setRowsPerPage] = useState(100) + const editorContainerRef = useRef(null) + const editorViewRef = useRef(null) + const mainPaneRef = useRef(null) + const dragStateRef = useRef(null) + const tableOrderByColumnRef = useRef>({}) + + const setEditorSql = useCallback((sqlText: string) => { + const editorView = editorViewRef.current + if (!editorView) return + + editorView.dispatch({ + changes: { + from: 0, + to: editorView.state.doc.length, + insert: sqlText, + }, + }) + }, []) + + const executeQuery = useCallback( + async (sqlText: string) => { + if (!sqlText.trim()) { + setQueryError('Please enter a SQL query') + return false + } + + setIsExecuting(true) + setQueryError(null) + setQueryResult(null) + + try { + const result = await query(sqlText) + const rows = (result.rows ?? []) as Record[] + const fields = (result.fields ?? []) as { name: string; dataTypeID: number }[] + + setQueryResult({ + rows, + fields, + rowCount: (result as { rowCount?: number }).rowCount ?? rows.length, + }) + return true + } catch (err) { + setQueryError(err instanceof Error ? err.message : 'Unknown error') + return false + } finally { + setIsExecuting(false) + } + }, + [query] + ) + + const runEditorQuery = useCallback( + async (sqlText: string) => { + setQueryContext({ mode: 'custom' }) + setCurrentPage(1) + await executeQuery(sqlText) + }, + [executeQuery] + ) + + const runTableQuery = useCallback( + async (tableName: string, page: number, pageSize: number) => { + const offset = (page - 1) * pageSize + let orderByColumn = tableOrderByColumnRef.current[tableName] + + if (!orderByColumn) { + try { + const primaryKeyResult = await query(` + SELECT kcu.column_name + FROM information_schema.table_constraints tc + JOIN information_schema.key_column_usage kcu + ON tc.constraint_name = kcu.constraint_name + AND tc.table_schema = kcu.table_schema + WHERE tc.table_schema = 'stripe' + AND tc.table_name = '${tableName}' + AND tc.constraint_type = 'PRIMARY KEY' + ORDER BY kcu.ordinal_position + LIMIT 1 + `) + + const primaryKeyRows = primaryKeyResult.rows ?? [] + const primaryKeyColumn = (primaryKeyRows[0] as { column_name?: string } | undefined) + ?.column_name + + orderByColumn = primaryKeyColumn ? primaryKeyColumn : 'ctid' + } catch { + orderByColumn = 'ctid' + } + + tableOrderByColumnRef.current[tableName] = orderByColumn + } + + const sqlText = `SELECT * FROM stripe.${tableName} ORDER BY ${quoteIdentifier(orderByColumn)} LIMIT ${pageSize} OFFSET ${offset}` + setEditorSql(sqlText) + const querySucceeded = await executeQuery(sqlText) + + if (!querySucceeded && orderByColumn !== 'ctid') { + tableOrderByColumnRef.current[tableName] = 'ctid' + const fallbackSqlText = `SELECT * FROM stripe.${tableName} ORDER BY ctid LIMIT ${pageSize} OFFSET ${offset}` + setEditorSql(fallbackSqlText) + await executeQuery(fallbackSqlText) + } + }, + [executeQuery, query, setEditorSql] + ) + + useEffect(() => { + if (status !== 'ready' || !editorContainerRef.current || editorViewRef.current) return + + let view: EditorView | null = null + + const runQuery = async () => { + if (!view) return + const sqlText = view.state.doc.toString() + await runEditorQuery(sqlText) + } + + const startState = EditorState.create({ + doc: '-- Select a table from the left or write your own SQL', + extensions: [ + basicSetup, + sql(), + keymap.of([ + { + key: 'Ctrl-Enter', + run: () => { + runQuery() + return true + }, + }, + { + key: 'Cmd-Enter', + run: () => { + runQuery() + return true + }, + }, + ]), + EditorView.theme({ + '&': { + height: '100%', + fontSize: '14px', + color: 'rgb(15 23 42)', + backgroundColor: 'rgb(255 255 255)', + }, + '&.cm-focused': { + outline: 'none', + }, + '.cm-scroller': { + overflow: 'auto', + fontFamily: + 'ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", monospace', + }, + '.cm-content': { + padding: '16px 0', + }, + '.cm-line': { + padding: '0 16px', + }, + '.cm-gutters': { + backgroundColor: 'rgb(255 255 255)', + color: 'rgb(148 163 184)', + borderRight: '1px solid rgb(226 232 240)', + }, + '.cm-activeLine': { + backgroundColor: 'rgba(99, 102, 241, 0.06)', + }, + '.cm-activeLineGutter': { + backgroundColor: 'rgba(99, 102, 241, 0.1)', + }, + '.cm-selectionBackground, ::selection': { + backgroundColor: 'rgba(99, 102, 241, 0.18)', + }, + '.cm-cursor': { + borderLeftColor: 'rgb(15 23 42)', + }, + }), + ], + }) + + view = new EditorView({ state: startState, parent: editorContainerRef.current }) + editorViewRef.current = view + + return () => { + if (view) view.destroy() + if (editorViewRef.current === view) editorViewRef.current = null + } + }, [runEditorQuery, status]) + + useEffect(() => { + const stopDragging = () => { + dragStateRef.current = null + document.body.style.removeProperty('cursor') + document.body.style.removeProperty('user-select') + } + + const handlePointerMove = (event: PointerEvent) => { + const dragState = dragStateRef.current + if (!dragState) return + + if (dragState.type === 'pane') { + const bounds = mainPaneRef.current?.getBoundingClientRect() + if (!bounds) return + + const nextSize = ((event.clientY - bounds.top) / bounds.height) * 100 + setEditorPaneSize(clamp(nextSize, MIN_EDITOR_PANE_SIZE, MAX_EDITOR_PANE_SIZE)) + return + } + + const nextWidth = Math.max( + MIN_COLUMN_WIDTH, + dragState.startWidth + (event.clientX - dragState.startX) + ) + + setColumnWidths((currentWidths) => { + if (currentWidths[dragState.columnKey] === nextWidth) { + return currentWidths + } + + return { + ...currentWidths, + [dragState.columnKey]: nextWidth, + } + }) + } + + window.addEventListener('pointermove', handlePointerMove) + window.addEventListener('pointerup', stopDragging) + window.addEventListener('pointercancel', stopDragging) + + return () => { + window.removeEventListener('pointermove', handlePointerMove) + window.removeEventListener('pointerup', stopDragging) + window.removeEventListener('pointercancel', stopDragging) + stopDragging() + } + }, []) + + const handleTableClick = useCallback( + async (tableName: string) => { + setSelectedTable(tableName) + setQueryContext({ mode: 'table', tableName }) + setCurrentPage(1) + await runTableQuery(tableName, 1, rowsPerPage) + }, + [rowsPerPage, runTableQuery] + ) + + const handleRunClick = useCallback(() => { + const editorView = editorViewRef.current + if (!editorView) return + void runEditorQuery(editorView.state.doc.toString()) + }, [runEditorQuery]) + + const isTableMode = queryContext?.mode === 'table' + const tableName = queryContext?.mode === 'table' ? queryContext.tableName : null + + const totalRecords = + isTableMode && tableName + ? (queryResult?.rows.length ?? 0) + : (queryResult?.rowCount ?? queryResult?.rows.length ?? 0) + + const pageCount = isTableMode ? Math.max(1, Math.ceil(totalRecords / rowsPerPage)) : 1 + + const displayedRows = queryResult?.rows ?? [] + + const changePage = useCallback( + async (nextPage: number) => { + if (!isTableMode) return + const boundedPage = clamp(nextPage, 1, pageCount) + if (boundedPage === currentPage) return + + setCurrentPage(boundedPage) + + if (queryContext?.mode === 'table') { + await runTableQuery(queryContext.tableName, boundedPage, rowsPerPage) + } + }, + [currentPage, isTableMode, pageCount, queryContext, rowsPerPage, runTableQuery] + ) + + const handleRowsPerPageChange = useCallback( + async (nextRowsPerPage: number) => { + if (nextRowsPerPage === rowsPerPage) return + setRowsPerPage(nextRowsPerPage) + setCurrentPage(1) + + if (!isTableMode) return + + if (queryContext?.mode === 'table') { + await runTableQuery(queryContext.tableName, 1, nextRowsPerPage) + } + }, + [isTableMode, queryContext, runTableQuery] + ) + + const handlePaneResizeStart = useCallback((event: ReactPointerEvent) => { + event.preventDefault() + dragStateRef.current = { type: 'pane' } + document.body.style.cursor = 'row-resize' + document.body.style.userSelect = 'none' + }, []) + + const handleColumnResizeStart = useCallback( + (event: ReactPointerEvent, columnKey: string, startingWidth: number) => { + event.preventDefault() + event.stopPropagation() + + dragStateRef.current = { + type: 'column', + columnKey, + startWidth: startingWidth, + startX: event.clientX, + } + + document.body.style.cursor = 'col-resize' + document.body.style.userSelect = 'none' + }, + [] + ) + + if (status === 'loading') { + return ( +
+
+
+

Loading database...

+
+
+ ) + } + + if (status === 'error') { + return ( +
+
+ ⚠️ +

Database Error

+

{error}

+
+
+ ) + } + + const tables = manifest?.tables ? manifest.tables.map((t) => [t, 0] as const) : [] + const columns = + queryResult?.fields.map((field, index) => { + const columnKey = getColumnKey(field.name, index) + return { + field, + columnKey, + width: columnWidths[columnKey] ?? getDefaultColumnWidth(field.name), + } + }) ?? [] + const totalColumnWidth = columns.reduce((sum, column) => sum + column.width, 0) + + return ( +
+ + +
+
+
+
+
+

+ Query +

+

SQL Editor

+
+
+ +
+
+ +
+
+
+
+ +
+
+
+ + + +
+
+ +
+
+
+

+ Results +

+

+ {isTableMode && tableName ? `stripe.${tableName}` : 'Query Output'} +

+
+ {(isTableMode || queryResult) && ( +
+ {isTableMode ? ( + <> + + + + Page {currentPage} / {pageCount} + + + + + + + + {totalRecords.toLocaleString()} {totalRecords === 1 ? 'record' : 'records'} + + + ) : ( + + {totalRecords.toLocaleString()} {totalRecords === 1 ? 'record' : 'records'} + + )} +
+ )} +
+
+ {isExecuting && ( +
+
+

Executing query…

+
+ )} + + {queryError && ( +
+ ⚠️ + {queryError} +
+ )} + + {queryResult && !isExecuting && ( +
+ 0 ? `${totalColumnWidth}px` : '100%' }} + > + + {columns.map((column) => ( + + ))} + + + + {columns.map((column) => ( + + ))} + + + + {displayedRows.map((row, rowIndex) => ( + + {columns.map((column) => { + const cellValue = formatCellValue(row[column.field.name]) + const previewValue = getCellPreview(cellValue) + return ( + + ) + })} + + ))} + +
+
+ {column.field.name} +
+
+ handleColumnResizeStart(event, column.columnKey, column.width) + } + className="absolute inset-y-0 -right-2 z-20 flex w-5 cursor-col-resize touch-none items-center justify-center rounded transition-colors duration-150 ease-out hover:bg-indigo-50" + > +
+
+
+
+ {previewValue} +
+
+
+ )} + + {!isExecuting && !queryError && !queryResult && ( +
+
+

+ Choose a table or run an ad-hoc query +

+

+ The editor and result grid are both draggable so you can tune the workspace as + you explore. +

+
+
+ )} +
+
+
+
+
+ ) +} + +function clamp(value: number, min: number, max: number): number { + return Math.min(max, Math.max(min, value)) +} + +function quoteIdentifier(identifier: string): string { + if (/^[A-Za-z_][A-Za-z0-9_]*$/.test(identifier)) { + return identifier + } + + return `"${identifier.replace(/"/g, '""')}"` +} + +function getColumnKey(fieldName: string, index: number): string { + return `${index}:${fieldName}` +} + +function getDefaultColumnWidth(fieldName: string): number { + if (fieldName === '_raw_data' || fieldName.includes('metadata')) { + return 220 + } + + if ( + fieldName === 'id' || + fieldName.endsWith('_id') || + fieldName.includes('cursor') || + fieldName.includes('account') + ) { + return 180 + } + + if (fieldName.endsWith('_at') || fieldName.includes('time') || fieldName.includes('date')) { + return 190 + } + + if (fieldName.includes('status') || fieldName.includes('type')) { + return 150 + } + + return clamp(fieldName.length * 10 + 56, MIN_COLUMN_WIDTH, 220) +} + +function formatCellValue(value: unknown): string { + if (value === null) return 'NULL' + if (value === undefined) return '' + if (typeof value === 'object') return JSON.stringify(value) + if (typeof value === 'boolean') return value ? 'true' : 'false' + return String(value) +} + +function getCellPreview(value: string): string { + if (value.length <= DEFAULT_CELL_PREVIEW_LENGTH) { + return value + } + + return `${value.slice(0, DEFAULT_CELL_PREVIEW_LENGTH - 1)}…` +} diff --git a/apps/visualizer/src/app/globals.css b/apps/visualizer/src/app/globals.css new file mode 100644 index 000000000..d4b507858 --- /dev/null +++ b/apps/visualizer/src/app/globals.css @@ -0,0 +1 @@ +@import 'tailwindcss'; diff --git a/apps/visualizer/src/app/layout.tsx b/apps/visualizer/src/app/layout.tsx new file mode 100644 index 000000000..d9ea67c65 --- /dev/null +++ b/apps/visualizer/src/app/layout.tsx @@ -0,0 +1,15 @@ +import type { Metadata } from 'next' +import './globals.css' + +export const metadata: Metadata = { + title: 'Stripe Schema Visualizer', + description: 'Explore generated Stripe schema data with a browser-based SQL visualizer', +} + +export default function RootLayout({ children }: { children: React.ReactNode }) { + return ( + + {children} + + ) +} diff --git a/apps/visualizer/src/app/page.tsx b/apps/visualizer/src/app/page.tsx new file mode 100644 index 000000000..e154c5591 --- /dev/null +++ b/apps/visualizer/src/app/page.tsx @@ -0,0 +1,76 @@ +'use client' + +import dynamic from 'next/dynamic' + +const ExplorerClient = dynamic(() => import('./ExplorerClient'), { + ssr: false, + loading: () => , +}) + +export default function VisualizerPage() { + return +} + +function ExplorerLoadingSkeleton() { + return ( +
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+ + + +
+
+ +
+
+
+
+
+
+
+
+
+
+
+

Loading visualizer...

+
+
+
+
+
+
+ ) +} diff --git a/apps/visualizer/src/lib/pglite.ts b/apps/visualizer/src/lib/pglite.ts new file mode 100644 index 000000000..706939a65 --- /dev/null +++ b/apps/visualizer/src/lib/pglite.ts @@ -0,0 +1,232 @@ +'use client' + +/** + * PGlite Database Hydration Hook + * + * Fetches the Stripe OpenAPI spec from GitHub, generates CREATE TABLE DDL + * in-browser using SpecParser, and loads it into a PGlite (WASM Postgres) + * instance. No static files, no build step. + * + * The spec (~3 MB) is cached in sessionStorage after the first fetch. + */ + +import { PGlite } from '@electric-sql/pglite' +import { useEffect, useState, useCallback, useRef } from 'react' +import { + SpecParser, + OPENAPI_RESOURCE_TABLE_ALIASES, + type ParsedResourceTable, +} from '@stripe/sync-source-stripe/browser' + +type PGliteInstance = InstanceType +type QueryResult = Awaited> + +const STRIPE_OPENAPI_URL = + 'https://raw.githubusercontent.com/stripe/openapi/master/openapi/spec3.json' +const SESSION_CACHE_KEY = 'stripe-explorer-schema-v1' + +export interface ExplorerManifest { + apiVersion: string + totalTables: number + tables: string[] +} + +type DatabaseStatus = 'idle' | 'loading' | 'ready' | 'error' +type InitializedDatabase = { db: PGliteInstance; manifest: ExplorerManifest } + +let sharedDatabasePromise: Promise | null = null + +interface UsePGliteResult { + db: PGliteInstance | null + status: DatabaseStatus + error: string | null + query: (sql: string, params?: unknown[]) => Promise + exec: (sql: string) => Promise + manifest: ExplorerManifest | null +} + +export function usePGlite(): UsePGliteResult { + const [db, setDb] = useState(null) + const [status, setStatus] = useState('idle') + const [error, setError] = useState(null) + const [manifest, setManifest] = useState(null) + const currentPromiseRef = useRef | null>(null) + + useEffect(() => { + let cancelled = false + setStatus('loading') + setError(null) + + currentPromiseRef.current ??= getOrCreateDatabase() + currentPromiseRef.current + .then(({ db: initializedDb, manifest: initializedManifest }) => { + if (cancelled) return + setDb(initializedDb) + setManifest(initializedManifest) + setStatus('ready') + }) + .catch((err) => { + console.error('[PGlite] Initialization error:', err) + if (cancelled) return + setError(err instanceof Error ? err.message : 'Unknown initialization error') + setStatus('error') + }) + + return () => { + cancelled = true + } + }, []) + + const query = useCallback( + async (sql: string, params?: unknown[]): Promise => { + if (status !== 'ready' || !db) throw new Error('Database not ready: ' + status) + return db.query(sql, params) + }, + [db, status] + ) + + const exec = useCallback( + async (sql: string): Promise => { + if (status !== 'ready' || !db) throw new Error('Database not ready: ' + status) + await db.exec(sql) + }, + [db, status] + ) + + return { db, status, error, query, exec, manifest } +} + +async function getOrCreateDatabase(): Promise { + if (!sharedDatabasePromise) { + sharedDatabasePromise = buildDatabase().catch((err) => { + sharedDatabasePromise = null + throw err + }) + } + return sharedDatabasePromise +} + +async function buildDatabase(): Promise { + // Try sessionStorage cache first (avoids re-fetching the 3 MB spec on reload) + let sql: string + let manifest: ExplorerManifest + const cached = + typeof sessionStorage !== 'undefined' ? sessionStorage.getItem(SESSION_CACHE_KEY) : null + + if (cached) { + console.log('[PGlite] Using cached schema from sessionStorage') + ;({ sql, manifest } = JSON.parse(cached) as { sql: string; manifest: ExplorerManifest }) + } else { + console.log('[PGlite] Fetching Stripe OpenAPI spec...') + const response = await fetch(STRIPE_OPENAPI_URL) + if (!response.ok) throw new Error(`Failed to fetch OpenAPI spec: ${response.status}`) + const spec = await response.json() + console.log('[PGlite] Parsing schema...') + ;({ sql, manifest } = generateSchema(spec)) + try { + sessionStorage.setItem(SESSION_CACHE_KEY, JSON.stringify({ sql, manifest })) + } catch { + // sessionStorage full — continue without caching + } + } + + console.log(`[PGlite] Creating database (${manifest.totalTables} tables)...`) + const db = await PGlite.create() + await db.exec(sql) + console.log('[PGlite] Ready') + return { db, manifest } +} + +// --------------------------------------------------------------------------- +// Schema generation — runs in the browser, no Node.js deps +// --------------------------------------------------------------------------- + +function generateSchema(spec: Record): { + sql: string + manifest: ExplorerManifest +} { + const schemas = + (spec as { components?: { schemas?: Record } }).components?.schemas ?? {} + + // Discover all table names from x-resourceId fields + const allTableNames = new Set() + for (const schemaDef of Object.values(schemas)) { + const resourceId = (schemaDef as Record)['x-resourceId'] + if (!resourceId || typeof resourceId !== 'string') continue + const alias = OPENAPI_RESOURCE_TABLE_ALIASES[resourceId] + if (alias) { + allTableNames.add(alias) + } else { + const normalized = resourceId.toLowerCase().replace(/\./g, '_') + allTableNames.add(normalized.endsWith('s') ? normalized : `${normalized}s`) + } + } + + const parser = new SpecParser() + const parsed = parser.parse(spec as Parameters[0], { + allowedTables: Array.from(allTableNames), + }) + + const lines: string[] = [`CREATE SCHEMA IF NOT EXISTS "stripe";`, ''] + for (const table of parsed.tables) { + lines.push(buildTableSql('stripe', table)) + lines.push('') + } + + const manifest: ExplorerManifest = { + apiVersion: parsed.apiVersion, + totalTables: parsed.tables.length, + tables: parsed.tables.map((t) => t.tableName), + } + + return { sql: lines.join('\n'), manifest } +} + +function buildTableSql(schema: string, table: ParsedResourceTable): string { + const qt = (s: string) => `"${s.replaceAll('"', '""')}"` + + const cols: string[] = [ + '"_raw_data" jsonb NOT NULL', + '"_last_synced_at" timestamptz', + '"_updated_at" timestamptz NOT NULL DEFAULT now()', + '"_account_id" text NOT NULL', + `"id" text GENERATED ALWAYS AS ((_raw_data->>'id')::text) STORED`, + ] + + for (const col of table.columns) { + const p = col.name.replace(/'/g, "''") + const pg = scalartypeToPg(col.type) + let expr: string + if (col.expandableReference) { + expr = `CASE WHEN jsonb_typeof(_raw_data->'${p}') = 'object' AND _raw_data->'${p}' ? 'id' THEN (_raw_data->'${p}'->>'id') ELSE (_raw_data->>'${p}') END` + } else if (pg === 'jsonb') { + expr = `(_raw_data->'${p}')::jsonb` + } else if (pg === 'text') { + expr = `(_raw_data->>'${p}')::text` + } else { + expr = `(NULLIF(_raw_data->>'${p}', ''))::${pg}` + } + cols.push(`${qt(col.name)} ${pg} GENERATED ALWAYS AS (${expr}) STORED`) + } + + cols.push('PRIMARY KEY ("id")') + + return `CREATE TABLE IF NOT EXISTS ${qt(schema)}.${qt(table.tableName)} (\n ${cols.join(',\n ')}\n);` +} + +function scalartypeToPg(type: string): string { + switch (type) { + case 'bigint': + return 'bigint' + case 'numeric': + return 'numeric' + case 'boolean': + return 'boolean' + case 'json': + return 'jsonb' + case 'timestamptz': + return 'timestamptz' + default: + return 'text' + } +} diff --git a/apps/visualizer/tsconfig.json b/apps/visualizer/tsconfig.json new file mode 100644 index 000000000..c1334095f --- /dev/null +++ b/apps/visualizer/tsconfig.json @@ -0,0 +1,27 @@ +{ + "compilerOptions": { + "target": "ES2017", + "lib": ["dom", "dom.iterable", "esnext"], + "allowJs": true, + "skipLibCheck": true, + "strict": true, + "noEmit": true, + "esModuleInterop": true, + "module": "esnext", + "moduleResolution": "bundler", + "resolveJsonModule": true, + "isolatedModules": true, + "jsx": "preserve", + "incremental": true, + "plugins": [ + { + "name": "next" + } + ], + "paths": { + "@/*": ["./src/*"] + } + }, + "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], + "exclude": ["node_modules"] +} diff --git a/package.json b/package.json index ab9019047..72dba6871 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,8 @@ "typecheck": "pnpm -r run typecheck", "lint": "pnpm -r run lint", "format": "prettier --write .", - "format:check": "prettier --check ." + "format:check": "prettier --check .", + "visualizer": "pnpm --filter @stripe/sync-visualizer dev" }, "dependencies": { "pino": "^10.0.0" diff --git a/packages/source-stripe/package.json b/packages/source-stripe/package.json index 1298a7e3c..25dd61ea8 100644 --- a/packages/source-stripe/package.json +++ b/packages/source-stripe/package.json @@ -8,6 +8,11 @@ "bun": "./src/index.ts", "types": "./dist/index.d.ts", "import": "./dist/index.js" + }, + "./browser": { + "bun": "./src/openapi/browser.ts", + "types": "./dist/openapi/browser.d.ts", + "import": "./dist/openapi/browser.js" } }, "bin": { diff --git a/packages/source-stripe/src/index.ts b/packages/source-stripe/src/index.ts index 7c90116fa..065e3fb6e 100644 --- a/packages/source-stripe/src/index.ts +++ b/packages/source-stripe/src/index.ts @@ -285,3 +285,5 @@ export default source export { buildResourceRegistry } from './resourceRegistry.js' export { catalogFromRegistry } from './catalog.js' +export { SpecParser, OPENAPI_RESOURCE_TABLE_ALIASES } from './openapi/specParser.js' +export type { ParsedResourceTable, ParsedOpenApiSpec } from './openapi/types.js' diff --git a/packages/source-stripe/src/openapi/browser.ts b/packages/source-stripe/src/openapi/browser.ts new file mode 100644 index 000000000..76aba7923 --- /dev/null +++ b/packages/source-stripe/src/openapi/browser.ts @@ -0,0 +1,2 @@ +export { SpecParser, OPENAPI_RESOURCE_TABLE_ALIASES } from './specParser.js' +export type { ParsedResourceTable, ParsedOpenApiSpec } from './types.js' diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index df70078f2..2005f2925 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -24,19 +24,19 @@ importers: version: 0.1.33 '@typescript-eslint/eslint-plugin': specifier: ^8.44.0 - version: 8.46.3(@typescript-eslint/parser@8.46.3(eslint@9.39.1)(typescript@5.9.3))(eslint@9.39.1)(typescript@5.9.3) + version: 8.46.3(@typescript-eslint/parser@8.46.3(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3) '@typescript-eslint/parser': specifier: ^8.44.0 - version: 8.46.3(eslint@9.39.1)(typescript@5.9.3) + version: 8.46.3(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3) eslint: specifier: ^9.35.0 - version: 9.39.1 + version: 9.39.1(jiti@2.6.1) eslint-config-prettier: specifier: ^10.1.8 - version: 10.1.8(eslint@9.39.1) + version: 10.1.8(eslint@9.39.1(jiti@2.6.1)) eslint-plugin-prettier: specifier: ^5.5.4 - version: 5.5.4(@types/eslint@9.6.1)(eslint-config-prettier@10.1.8(eslint@9.39.1))(eslint@9.39.1)(prettier@3.6.2) + version: 5.5.4(@types/eslint@9.6.1)(eslint-config-prettier@10.1.8(eslint@9.39.1(jiti@2.6.1)))(eslint@9.39.1(jiti@2.6.1))(prettier@3.6.2) prettier: specifier: ^3.6.2 version: 3.6.2 @@ -51,7 +51,7 @@ importers: version: 5.9.3 vite: specifier: ^7.1.11 - version: 7.2.2(@types/node@25.5.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.1) + version: 7.2.2(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.1) apps/engine: dependencies: @@ -115,7 +115,7 @@ importers: version: 8.15.6 vitest: specifier: ^3.2.4 - version: 3.2.4(@types/node@24.10.1)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.1) + version: 3.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.1) apps/service: dependencies: @@ -155,7 +155,7 @@ importers: version: 24.10.1 vitest: specifier: ^3.2.4 - version: 3.2.4(@types/node@24.10.1)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.1) + version: 3.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.1) optionalDependencies: '@temporalio/activity': specifier: ^1 @@ -199,7 +199,62 @@ importers: version: 0.27.3 vitest: specifier: ^3.2.4 - version: 3.2.4(@types/node@24.10.1)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.1) + version: 3.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.1) + + apps/visualizer: + dependencies: + '@codemirror/lang-sql': + specifier: ^6.7.0 + version: 6.10.0 + '@codemirror/state': + specifier: ^6.4.0 + version: 6.6.0 + '@codemirror/view': + specifier: ^6.26.0 + version: 6.40.0 + '@electric-sql/pglite': + specifier: ^0.2.0 + version: 0.2.17 + '@stripe/sync-source-stripe': + specifier: workspace:* + version: link:../../packages/source-stripe + codemirror: + specifier: ^6.0.1 + version: 6.0.2 + next: + specifier: ^15 + version: 15.5.14(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + react: + specifier: ^19 + version: 19.2.4 + react-dom: + specifier: ^19 + version: 19.2.4(react@19.2.4) + devDependencies: + '@tailwindcss/postcss': + specifier: ^4.2.1 + version: 4.2.2 + '@types/node': + specifier: ^22 + version: 22.19.15 + '@types/react': + specifier: ^19 + version: 19.2.14 + '@types/react-dom': + specifier: ^19 + version: 19.2.3(@types/react@19.2.14) + autoprefixer: + specifier: ^10.4.27 + version: 10.4.27(postcss@8.5.8) + postcss: + specifier: ^8.5.8 + version: 8.5.8 + tailwindcss: + specifier: ^4.2.1 + version: 4.2.2 + typescript: + specifier: ^5 + version: 5.9.3 e2e: devDependencies: @@ -241,7 +296,7 @@ importers: version: 17.7.0 vitest: specifier: ^3.2.1 - version: 3.2.4(@types/node@25.5.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.1) + version: 3.2.4(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.1) packages/destination-google-sheets: dependencies: @@ -257,7 +312,7 @@ importers: devDependencies: vitest: specifier: ^3.2.4 - version: 3.2.4(@types/node@25.5.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.1) + version: 3.2.4(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.1) packages/destination-postgres: dependencies: @@ -285,7 +340,7 @@ importers: version: 8.15.6 vitest: specifier: ^3.2.4 - version: 3.2.4(@types/node@25.5.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.1) + version: 3.2.4(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.1) packages/protocol: dependencies: @@ -301,7 +356,7 @@ importers: version: 24.10.1 vitest: specifier: ^3.2.1 - version: 3.2.4(@types/node@24.10.1)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.1) + version: 3.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.1) packages/source-stripe: dependencies: @@ -326,7 +381,7 @@ importers: version: 8.18.1 vitest: specifier: ^3.2.4 - version: 3.2.4(@types/node@24.10.1)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.1) + version: 3.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.1) packages/state-postgres: dependencies: @@ -348,7 +403,7 @@ importers: version: 5.9.3 vitest: specifier: ^3.2.4 - version: 3.2.4(@types/node@24.10.1)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.1) + version: 3.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.1) packages/ts-cli: dependencies: @@ -361,7 +416,7 @@ importers: version: 24.10.1 vitest: specifier: ^3.2 - version: 3.2.4(@types/node@24.10.1)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.1) + version: 3.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.1) packages/util-postgres: dependencies: @@ -374,10 +429,14 @@ importers: version: 8.15.6 vitest: specifier: ^3.2.1 - version: 3.2.4(@types/node@25.5.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.1) + version: 3.2.4(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.1) packages: + '@alloc/quick-lru@5.2.0': + resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==} + engines: {node: '>=10'} + '@asteasolutions/zod-to-openapi@8.4.3': resolution: {integrity: sha512-lwfMTN7kDbFDwMniYZUebiGGHxVGBw9ZSI4IBYjm6Ey22Kd5z/fsQb2k+Okr8WMbCCC553vi/ZM9utl5/XcvuQ==} peerDependencies: @@ -516,6 +575,36 @@ packages: resolution: {integrity: sha512-iY8yvjE0y651BixKNPgmv1WrQc+GZ142sb0z4gYnChDDY2YqI4P/jsSopBWrKfAt7LOJAkOXt7rC/hms+WclQQ==} engines: {node: '>=18.0.0'} + '@codemirror/autocomplete@6.20.1': + resolution: {integrity: sha512-1cvg3Vz1dSSToCNlJfRA2WSI4ht3K+WplO0UMOgmUYPivCyy2oueZY6Lx7M9wThm7SDUBViRmuT+OG/i8+ON9A==} + + '@codemirror/commands@6.10.3': + resolution: {integrity: sha512-JFRiqhKu+bvSkDLI+rUhJwSxQxYb759W5GBezE8Uc8mHLqC9aV/9aTC7yJSqCtB3F00pylrLCwnyS91Ap5ej4Q==} + + '@codemirror/lang-sql@6.10.0': + resolution: {integrity: sha512-6ayPkEd/yRw0XKBx5uAiToSgGECo/GY2NoJIHXIIQh1EVwLuKoU8BP/qK0qH5NLXAbtJRLuT73hx7P9X34iO4w==} + + '@codemirror/language@6.12.3': + resolution: {integrity: sha512-QwCZW6Tt1siP37Jet9Tb02Zs81TQt6qQrZR2H+eGMcFsL1zMrk2/b9CLC7/9ieP1fjIUMgviLWMmgiHoJrj+ZA==} + + '@codemirror/lint@6.9.5': + resolution: {integrity: sha512-GElsbU9G7QT9xXhpUg1zWGmftA/7jamh+7+ydKRuT0ORpWS3wOSP0yT1FOlIZa7mIJjpVPipErsyvVqB9cfTFA==} + + '@codemirror/search@6.6.0': + resolution: {integrity: sha512-koFuNXcDvyyotWcgOnZGmY7LZqEOXZaaxD/j6n18TCLx2/9HieZJ5H6hs1g8FiRxBD0DNfs0nXn17g872RmYdw==} + + '@codemirror/state@6.6.0': + resolution: {integrity: sha512-4nbvra5R5EtiCzr9BTHiTLc+MLXK2QGiAVYMyi8PkQd3SR+6ixar/Q/01Fa21TBIDOZXgeWV4WppsQolSreAPQ==} + + '@codemirror/view@6.40.0': + resolution: {integrity: sha512-WA0zdU7xfF10+5I3HhUUq3kqOx3KjqmtQ9lqZjfK7jtYk4G72YW9rezcSywpaUMCWOMlq+6E0pO1IWg1TNIhtg==} + + '@electric-sql/pglite@0.2.17': + resolution: {integrity: sha512-qEpKRT2oUaWDH6tjRxLHjdzMqRUGYDnGZlKrnL4dJ77JVMcP2Hpo3NYnOSPKdZdeec57B6QPprCUFg0picx5Pw==} + + '@emnapi/runtime@1.9.1': + resolution: {integrity: sha512-VYi5+ZVLhpgK4hQ0TAjiQiZ6ol0oe4mBx7mVv7IflsiEp0OWoVsp/+f9Vc1hOhE0TtkORVrI1GvzyreqpgWtkA==} + '@esbuild/aix-ppc64@0.25.12': resolution: {integrity: sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==} engines: {node: '>=18'} @@ -1066,6 +1155,143 @@ packages: resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==} engines: {node: '>=18.18'} + '@img/colour@1.1.0': + resolution: {integrity: sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==} + engines: {node: '>=18'} + + '@img/sharp-darwin-arm64@0.34.5': + resolution: {integrity: sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm64] + os: [darwin] + + '@img/sharp-darwin-x64@0.34.5': + resolution: {integrity: sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [darwin] + + '@img/sharp-libvips-darwin-arm64@1.2.4': + resolution: {integrity: sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==} + cpu: [arm64] + os: [darwin] + + '@img/sharp-libvips-darwin-x64@1.2.4': + resolution: {integrity: sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==} + cpu: [x64] + os: [darwin] + + '@img/sharp-libvips-linux-arm64@1.2.4': + resolution: {integrity: sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==} + cpu: [arm64] + os: [linux] + + '@img/sharp-libvips-linux-arm@1.2.4': + resolution: {integrity: sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==} + cpu: [arm] + os: [linux] + + '@img/sharp-libvips-linux-ppc64@1.2.4': + resolution: {integrity: sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==} + cpu: [ppc64] + os: [linux] + + '@img/sharp-libvips-linux-riscv64@1.2.4': + resolution: {integrity: sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==} + cpu: [riscv64] + os: [linux] + + '@img/sharp-libvips-linux-s390x@1.2.4': + resolution: {integrity: sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==} + cpu: [s390x] + os: [linux] + + '@img/sharp-libvips-linux-x64@1.2.4': + resolution: {integrity: sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==} + cpu: [x64] + os: [linux] + + '@img/sharp-libvips-linuxmusl-arm64@1.2.4': + resolution: {integrity: sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==} + cpu: [arm64] + os: [linux] + + '@img/sharp-libvips-linuxmusl-x64@1.2.4': + resolution: {integrity: sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==} + cpu: [x64] + os: [linux] + + '@img/sharp-linux-arm64@0.34.5': + resolution: {integrity: sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm64] + os: [linux] + + '@img/sharp-linux-arm@0.34.5': + resolution: {integrity: sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm] + os: [linux] + + '@img/sharp-linux-ppc64@0.34.5': + resolution: {integrity: sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [ppc64] + os: [linux] + + '@img/sharp-linux-riscv64@0.34.5': + resolution: {integrity: sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [riscv64] + os: [linux] + + '@img/sharp-linux-s390x@0.34.5': + resolution: {integrity: sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [s390x] + os: [linux] + + '@img/sharp-linux-x64@0.34.5': + resolution: {integrity: sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [linux] + + '@img/sharp-linuxmusl-arm64@0.34.5': + resolution: {integrity: sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm64] + os: [linux] + + '@img/sharp-linuxmusl-x64@0.34.5': + resolution: {integrity: sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [linux] + + '@img/sharp-wasm32@0.34.5': + resolution: {integrity: sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [wasm32] + + '@img/sharp-win32-arm64@0.34.5': + resolution: {integrity: sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm64] + os: [win32] + + '@img/sharp-win32-ia32@0.34.5': + resolution: {integrity: sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [ia32] + os: [win32] + + '@img/sharp-win32-x64@0.34.5': + resolution: {integrity: sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [win32] + '@isaacs/balanced-match@4.0.1': resolution: {integrity: sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==} engines: {node: 20 || >=22} @@ -1081,6 +1307,9 @@ packages: '@jridgewell/gen-mapping@0.3.13': resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} + '@jridgewell/remapping@2.3.5': + resolution: {integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==} + '@jridgewell/resolve-uri@3.1.2': resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} engines: {node: '>=6.0.0'} @@ -1217,6 +1446,69 @@ packages: peerDependencies: tslib: '2' + '@lezer/common@1.5.1': + resolution: {integrity: sha512-6YRVG9vBkaY7p1IVxL4s44n5nUnaNnGM2/AckNgYOnxTG2kWh1vR8BMxPseWPjRNpb5VtXnMpeYAEAADoRV1Iw==} + + '@lezer/highlight@1.2.3': + resolution: {integrity: sha512-qXdH7UqTvGfdVBINrgKhDsVTJTxactNNxLk7+UMwZhU13lMHaOBlJe9Vqp907ya56Y3+ed2tlqzys7jDkTmW0g==} + + '@lezer/lr@1.4.8': + resolution: {integrity: sha512-bPWa0Pgx69ylNlMlPvBPryqeLYQjyJjqPx+Aupm5zydLIF3NE+6MMLT8Yi23Bd9cif9VS00aUebn+6fDIGBcDA==} + + '@marijn/find-cluster-break@1.0.2': + resolution: {integrity: sha512-l0h88YhZFyKdXIFNfSWpyjStDjGHwZ/U7iobcK1cQQD8sejsONdQtTVU+1wVN1PBw40PiiHB1vA5S7VTfQiP9g==} + + '@next/env@15.5.14': + resolution: {integrity: sha512-aXeirLYuASxEgi4X4WhfXsShCFxWDfNn/8ZeC5YXAS2BB4A8FJi1kwwGL6nvMVboE7fZCzmJPNdMvVHc8JpaiA==} + + '@next/swc-darwin-arm64@15.5.14': + resolution: {integrity: sha512-Y9K6SPzobnZvrRDPO2s0grgzC+Egf0CqfbdvYmQVaztV890zicw8Z8+4Vqw8oPck8r1TjUHxVh8299Cg4TrxXg==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [darwin] + + '@next/swc-darwin-x64@15.5.14': + resolution: {integrity: sha512-aNnkSMjSFRTOmkd7qoNI2/rETQm/vKD6c/Ac9BZGa9CtoOzy3c2njgz7LvebQJ8iPxdeTuGnAjagyis8a9ifBw==} + engines: {node: '>= 10'} + cpu: [x64] + os: [darwin] + + '@next/swc-linux-arm64-gnu@15.5.14': + resolution: {integrity: sha512-tjlpia+yStPRS//6sdmlVwuO1Rioern4u2onafa5n+h2hCS9MAvMXqpVbSrjgiEOoCs0nJy7oPOmWgtRRNSM5Q==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + + '@next/swc-linux-arm64-musl@15.5.14': + resolution: {integrity: sha512-8B8cngBaLadl5lbDRdxGCP1Lef8ipD6KlxS3v0ElDAGil6lafrAM3B258p1KJOglInCVFUjk751IXMr2ixeQOQ==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + + '@next/swc-linux-x64-gnu@15.5.14': + resolution: {integrity: sha512-bAS6tIAg8u4Gn3Nz7fCPpSoKAexEt2d5vn1mzokcqdqyov6ZJ6gu6GdF9l8ORFrBuRHgv3go/RfzYz5BkZ6YSQ==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + + '@next/swc-linux-x64-musl@15.5.14': + resolution: {integrity: sha512-mMxv/FcrT7Gfaq4tsR22l17oKWXZmH/lVqcvjX0kfp5I0lKodHYLICKPoX1KRnnE+ci6oIUdriUhuA3rBCDiSw==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + + '@next/swc-win32-arm64-msvc@15.5.14': + resolution: {integrity: sha512-OTmiBlYThppnvnsqx0rBqjDRemlmIeZ8/o4zI7veaXoeO1PVHoyj2lfTfXTiiGjCyRDhA10y4h6ZvZvBiynr2g==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [win32] + + '@next/swc-win32-x64-msvc@15.5.14': + resolution: {integrity: sha512-+W7eFf3RS7m4G6tppVTOSyP9Y6FsJXfOuKzav1qKniiFm3KFByQfPEcouHdjlZmysl4zJGuGLQ/M9XyVeyeNEg==} + engines: {node: '>= 10'} + cpu: [x64] + os: [win32] + '@nodelib/fs.scandir@2.1.5': resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} engines: {node: '>= 8'} @@ -1650,9 +1942,100 @@ packages: '@swc/counter@0.1.3': resolution: {integrity: sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==} + '@swc/helpers@0.5.15': + resolution: {integrity: sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==} + '@swc/types@0.1.26': resolution: {integrity: sha512-lyMwd7WGgG79RS7EERZV3T8wMdmPq3xwyg+1nmAM64kIhx5yl+juO2PYIHb7vTiPgPCj8LYjsNV2T5wiQHUEaw==} + '@tailwindcss/node@4.2.2': + resolution: {integrity: sha512-pXS+wJ2gZpVXqFaUEjojq7jzMpTGf8rU6ipJz5ovJV6PUGmlJ+jvIwGrzdHdQ80Sg+wmQxUFuoW1UAAwHNEdFA==} + + '@tailwindcss/oxide-android-arm64@4.2.2': + resolution: {integrity: sha512-dXGR1n+P3B6748jZO/SvHZq7qBOqqzQ+yFrXpoOWWALWndF9MoSKAT3Q0fYgAzYzGhxNYOoysRvYlpixRBBoDg==} + engines: {node: '>= 20'} + cpu: [arm64] + os: [android] + + '@tailwindcss/oxide-darwin-arm64@4.2.2': + resolution: {integrity: sha512-iq9Qjr6knfMpZHj55/37ouZeykwbDqF21gPFtfnhCCKGDcPI/21FKC9XdMO/XyBM7qKORx6UIhGgg6jLl7BZlg==} + engines: {node: '>= 20'} + cpu: [arm64] + os: [darwin] + + '@tailwindcss/oxide-darwin-x64@4.2.2': + resolution: {integrity: sha512-BlR+2c3nzc8f2G639LpL89YY4bdcIdUmiOOkv2GQv4/4M0vJlpXEa0JXNHhCHU7VWOKWT/CjqHdTP8aUuDJkuw==} + engines: {node: '>= 20'} + cpu: [x64] + os: [darwin] + + '@tailwindcss/oxide-freebsd-x64@4.2.2': + resolution: {integrity: sha512-YUqUgrGMSu2CDO82hzlQ5qSb5xmx3RUrke/QgnoEx7KvmRJHQuZHZmZTLSuuHwFf0DJPybFMXMYf+WJdxHy/nQ==} + engines: {node: '>= 20'} + cpu: [x64] + os: [freebsd] + + '@tailwindcss/oxide-linux-arm-gnueabihf@4.2.2': + resolution: {integrity: sha512-FPdhvsW6g06T9BWT0qTwiVZYE2WIFo2dY5aCSpjG/S/u1tby+wXoslXS0kl3/KXnULlLr1E3NPRRw0g7t2kgaQ==} + engines: {node: '>= 20'} + cpu: [arm] + os: [linux] + + '@tailwindcss/oxide-linux-arm64-gnu@4.2.2': + resolution: {integrity: sha512-4og1V+ftEPXGttOO7eCmW7VICmzzJWgMx+QXAJRAhjrSjumCwWqMfkDrNu1LXEQzNAwz28NCUpucgQPrR4S2yw==} + engines: {node: '>= 20'} + cpu: [arm64] + os: [linux] + + '@tailwindcss/oxide-linux-arm64-musl@4.2.2': + resolution: {integrity: sha512-oCfG/mS+/+XRlwNjnsNLVwnMWYH7tn/kYPsNPh+JSOMlnt93mYNCKHYzylRhI51X+TbR+ufNhhKKzm6QkqX8ag==} + engines: {node: '>= 20'} + cpu: [arm64] + os: [linux] + + '@tailwindcss/oxide-linux-x64-gnu@4.2.2': + resolution: {integrity: sha512-rTAGAkDgqbXHNp/xW0iugLVmX62wOp2PoE39BTCGKjv3Iocf6AFbRP/wZT/kuCxC9QBh9Pu8XPkv/zCZB2mcMg==} + engines: {node: '>= 20'} + cpu: [x64] + os: [linux] + + '@tailwindcss/oxide-linux-x64-musl@4.2.2': + resolution: {integrity: sha512-XW3t3qwbIwiSyRCggeO2zxe3KWaEbM0/kW9e8+0XpBgyKU4ATYzcVSMKteZJ1iukJ3HgHBjbg9P5YPRCVUxlnQ==} + engines: {node: '>= 20'} + cpu: [x64] + os: [linux] + + '@tailwindcss/oxide-wasm32-wasi@4.2.2': + resolution: {integrity: sha512-eKSztKsmEsn1O5lJ4ZAfyn41NfG7vzCg496YiGtMDV86jz1q/irhms5O0VrY6ZwTUkFy/EKG3RfWgxSI3VbZ8Q==} + engines: {node: '>=14.0.0'} + cpu: [wasm32] + bundledDependencies: + - '@napi-rs/wasm-runtime' + - '@emnapi/core' + - '@emnapi/runtime' + - '@tybys/wasm-util' + - '@emnapi/wasi-threads' + - tslib + + '@tailwindcss/oxide-win32-arm64-msvc@4.2.2': + resolution: {integrity: sha512-qPmaQM4iKu5mxpsrWZMOZRgZv1tOZpUm+zdhhQP0VhJfyGGO3aUKdbh3gDZc/dPLQwW4eSqWGrrcWNBZWUWaXQ==} + engines: {node: '>= 20'} + cpu: [arm64] + os: [win32] + + '@tailwindcss/oxide-win32-x64-msvc@4.2.2': + resolution: {integrity: sha512-1T/37VvI7WyH66b+vqHj/cLwnCxt7Qt3WFu5Q8hk65aOvlwAhs7rAp1VkulBJw/N4tMirXjVnylTR72uI0HGcA==} + engines: {node: '>= 20'} + cpu: [x64] + os: [win32] + + '@tailwindcss/oxide@4.2.2': + resolution: {integrity: sha512-qEUA07+E5kehxYp9BVMpq9E8vnJuBHfJEC0vPC5e7iL/hw7HR61aDKoVoKzrG+QKp56vhNZe4qwkRmMC0zDLvg==} + engines: {node: '>= 20'} + + '@tailwindcss/postcss@4.2.2': + resolution: {integrity: sha512-n4goKQbW8RVXIbNKRB/45LzyUqN451deQK0nzIeauVEqjlI49slUlgKYJM2QyUzap/PcpnS7kzSUmPb1sCRvYQ==} + '@temporalio/activity@1.15.0': resolution: {integrity: sha512-kKEIrHMTsANiEpDVZd+v3OT6kU20UtcvAK7iibJNzQnoZUGC7XnqdKQlBuGYBxgpJzD9ppGgskXRczW+XU5Kng==} engines: {node: '>= 20.0.0'} @@ -1710,6 +2093,9 @@ packages: '@types/json-schema@7.0.15': resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} + '@types/node@22.19.15': + resolution: {integrity: sha512-F0R/h2+dsy5wJAUe3tAU6oqa2qbWY5TpNfL/RGmo1y38hiyO1w3x2jPtt76wmuaJI4DQnOBu21cNXQ2STIUUWg==} + '@types/node@24.10.1': resolution: {integrity: sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ==} @@ -1719,6 +2105,14 @@ packages: '@types/pg@8.15.6': resolution: {integrity: sha512-NoaMtzhxOrubeL/7UZuNTrejB4MPAJ0RpxZqXQf2qXuVlTPuG6Y8p4u9dKRaue4yjmC7ZhzVO2/Yyyn25znrPQ==} + '@types/react-dom@19.2.3': + resolution: {integrity: sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==} + peerDependencies: + '@types/react': ^19.2.0 + + '@types/react@19.2.14': + resolution: {integrity: sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==} + '@types/ws@8.18.1': resolution: {integrity: sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==} @@ -1942,6 +2336,13 @@ packages: resolution: {integrity: sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==} engines: {node: '>=8.0.0'} + autoprefixer@10.4.27: + resolution: {integrity: sha512-NP9APE+tO+LuJGn7/9+cohklunJsXWiaWEfV3si4Gi/XHDwVNgkwr1J3RQYFIvPy76GmJ9/bW8vyoU1LcxwKHA==} + engines: {node: ^10 || ^12 || >=14} + hasBin: true + peerDependencies: + postcss: ^8.1.0 + axios@1.13.5: resolution: {integrity: sha512-cz4ur7Vb0xS4/KUN0tPWe44eqxrIu31me+fbang3ijiNscE129POzipJJA6zniq2C/Z6sJCjMimjS8Lc/GAs8Q==} @@ -2021,10 +2422,16 @@ packages: citty@0.1.6: resolution: {integrity: sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ==} + 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'} + codemirror@6.0.2: + resolution: {integrity: sha512-VhydHotNW5w1UGK0Qj96BwSk/Zqbp9WbnyK2W/eVMv4QyF41INRGpjUhFJY7/uDNuudSc33a/PKr4iDqRduvHw==} + color-convert@2.0.1: resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} engines: {node: '>=7.0.0'} @@ -2046,10 +2453,16 @@ packages: resolution: {integrity: sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==} engines: {node: ^14.18.0 || >=16.10.0} + crelt@1.0.6: + resolution: {integrity: sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==} + cross-spawn@7.0.6: resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} engines: {node: '>= 8'} + csstype@3.2.3: + resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==} + debug@4.4.1: resolution: {integrity: sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==} engines: {node: '>=6.0'} @@ -2079,6 +2492,10 @@ packages: resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} engines: {node: '>=0.4.0'} + detect-libc@2.1.2: + resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} + engines: {node: '>=8'} + dotenv@16.6.1: resolution: {integrity: sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==} engines: {node: '>=12'} @@ -2313,6 +2730,9 @@ packages: resolution: {integrity: sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==} engines: {node: '>= 6'} + fraction.js@5.3.4: + resolution: {integrity: sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ==} + fs-monkey@1.1.0: resolution: {integrity: sha512-QMUezzXWII9EV5aTFXW1UBVUO77wYPpjqIF8/AviUCThNeSYZykpoTixUeaNNBwmCev0AMDWMAni+f8Hxb1IFw==} @@ -2494,6 +2914,10 @@ packages: resolution: {integrity: sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==} engines: {node: '>= 10.13.0'} + jiti@2.6.1: + resolution: {integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==} + hasBin: true + js-tokens@9.0.1: resolution: {integrity: sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==} @@ -2532,6 +2956,76 @@ packages: resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} engines: {node: '>= 0.8.0'} + lightningcss-android-arm64@1.32.0: + resolution: {integrity: sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [android] + + lightningcss-darwin-arm64@1.32.0: + resolution: {integrity: sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [darwin] + + lightningcss-darwin-x64@1.32.0: + resolution: {integrity: sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [darwin] + + lightningcss-freebsd-x64@1.32.0: + resolution: {integrity: sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [freebsd] + + lightningcss-linux-arm-gnueabihf@1.32.0: + resolution: {integrity: sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==} + engines: {node: '>= 12.0.0'} + cpu: [arm] + os: [linux] + + lightningcss-linux-arm64-gnu@1.32.0: + resolution: {integrity: sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + + lightningcss-linux-arm64-musl@1.32.0: + resolution: {integrity: sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + + lightningcss-linux-x64-gnu@1.32.0: + resolution: {integrity: sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + + lightningcss-linux-x64-musl@1.32.0: + resolution: {integrity: sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + + lightningcss-win32-arm64-msvc@1.32.0: + resolution: {integrity: sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [win32] + + lightningcss-win32-x64-msvc@1.32.0: + resolution: {integrity: sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [win32] + + lightningcss@1.32.0: + resolution: {integrity: sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==} + engines: {node: '>= 12.0.0'} + loader-runner@4.3.1: resolution: {integrity: sha512-IWqP2SCPhyVFTBtRcgMHdzlf9ul25NwaFx4wCEH/KjAXuuHY4yNjvPXsBokp8jCB936PyWRaPKUNh8NvylLp2Q==} engines: {node: '>=6.11.5'} @@ -2559,6 +3053,9 @@ packages: magic-string@0.30.19: resolution: {integrity: sha512-2N21sPY9Ws53PZvsEpVtNuSW+ScYbQdp4b9qUaL+9QkHUrGFKo56Lg9Emg5s9V/qrtNBmiR01sYhUOwu3H+VOw==} + magic-string@0.30.21: + resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} + math-intrinsics@1.1.0: resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} engines: {node: '>= 0.4'} @@ -2620,6 +3117,27 @@ packages: neo-async@2.6.2: resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} + next@15.5.14: + resolution: {integrity: sha512-M6S+4JyRjmKic2Ssm7jHUPkE6YUJ6lv4507jprsSZLulubz0ihO2E+S4zmQK3JZ2ov81JrugukKU4Tz0ivgqqQ==} + engines: {node: ^18.18.0 || ^19.8.0 || >= 20.0.0} + hasBin: true + peerDependencies: + '@opentelemetry/api': ^1.1.0 + '@playwright/test': ^1.51.1 + babel-plugin-react-compiler: '*' + react: ^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0 + react-dom: ^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0 + sass: ^1.3.0 + peerDependenciesMeta: + '@opentelemetry/api': + optional: true + '@playwright/test': + optional: true + babel-plugin-react-compiler: + optional: true + sass: + optional: true + nexus-rpc@0.0.1: resolution: {integrity: sha512-hAWn8Hh2eewpB5McXR5EW81R3pR/ziuGhKCF3wFyUVCklanPqrIgMNr7jKCbzXeNVad0nUDfWpFRqh2u+zxQtw==} engines: {node: '>= 18.0.0'} @@ -2744,8 +3262,15 @@ packages: resolution: {integrity: sha512-0zZC2ygfdqvqK8zJIr1e+wT1T/L+LF6qvqvbzEQ6tiMAoTqEVK9a1K3YRu8HEUvGEvNqZyPJTtb2sNIoTkB83w==} hasBin: true - postcss@8.5.6: - resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==} + postcss-value-parser@4.2.0: + resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} + + postcss@8.4.31: + resolution: {integrity: sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==} + engines: {node: ^10 || ^12 || >=14} + + postcss@8.5.8: + resolution: {integrity: sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg==} engines: {node: ^10 || ^12 || >=14} postgres-array@2.0.0: @@ -2805,6 +3330,15 @@ packages: quick-format-unescaped@4.0.4: resolution: {integrity: sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==} + react-dom@19.2.4: + resolution: {integrity: sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ==} + peerDependencies: + react: ^19.2.4 + + react@19.2.4: + resolution: {integrity: sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==} + engines: {node: '>=0.10.0'} + real-require@0.2.0: resolution: {integrity: sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==} engines: {node: '>= 12.13.0'} @@ -2854,6 +3388,9 @@ packages: safer-buffer@2.1.2: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + scheduler@0.27.0: + resolution: {integrity: sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==} + schema-utils@4.3.3: resolution: {integrity: sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA==} engines: {node: '>= 10.13.0'} @@ -2863,6 +3400,10 @@ packages: engines: {node: '>=10'} hasBin: true + sharp@0.34.5: + resolution: {integrity: sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + shebang-command@2.0.0: resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} engines: {node: '>=8'} @@ -2958,6 +3499,22 @@ packages: strnum@2.2.1: resolution: {integrity: sha512-BwRvNd5/QoAtyW1na1y1LsJGQNvRlkde6Q/ipqqEaivoMdV+B1OMOTVdwR+N/cwVUcIt9PYyHmV8HyexCZSupg==} + style-mod@4.1.3: + resolution: {integrity: sha512-i/n8VsZydrugj3Iuzll8+x/00GH2vnYsk1eomD8QiRrSAeW6ItbCQDtfXCeJHd0iwiNagqjQkvpvREEPtW3IoQ==} + + styled-jsx@5.1.6: + resolution: {integrity: sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA==} + engines: {node: '>= 12.0.0'} + peerDependencies: + '@babel/core': '*' + babel-plugin-macros: '*' + react: '>= 16.8.0 || 17.x.x || ^18.0.0-0 || ^19.0.0-0' + peerDependenciesMeta: + '@babel/core': + optional: true + babel-plugin-macros: + optional: true + supabase-management-js@2.0.2: resolution: {integrity: sha512-CWGAczaNXTUDExaxi+hUEPqlPtCiZ4r3a74NXOx7+Sf+P75foCuX/aXL9MztosWwRnZZAI8VGUXpdNe6K3xTtA==} engines: {node: '>=18.0.0'} @@ -2980,6 +3537,9 @@ packages: resolution: {integrity: sha512-MeQTA1r0litLUf0Rp/iisCaL8761lKAZHaimlbGK4j0HysC4PLfqygQj9srcs0m2RdtDYnF8UuYyKpbjHYp7Jw==} engines: {node: ^14.18.0 || >=16.0.0} + tailwindcss@4.2.2: + resolution: {integrity: sha512-KWBIxs1Xb6NoLdMVqhbhgwZf2PGBpPEiwOqgI4pFIYbNTfBXiKYyWoTsXgBQ9WFg/OlhnvHaY+AEpW7wSmFo2Q==} + tapable@2.3.2: resolution: {integrity: sha512-1MOpMXuhGzGL5TTCZFItxCc0AARf1EZFQkGqMm7ERKj8+Hgr5oLvJOVFcC+lRmR8hCe2S3jC4T5D7Vg/d7/fhA==} engines: {node: '>=6'} @@ -3072,6 +3632,9 @@ packages: engines: {node: '>=14.17'} hasBin: true + undici-types@6.21.0: + resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} + undici-types@7.16.0: resolution: {integrity: sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==} @@ -3174,6 +3737,9 @@ packages: jsdom: optional: true + w3c-keyname@2.2.8: + resolution: {integrity: sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==} + watchpack@2.5.1: resolution: {integrity: sha512-Zn5uXdcFNIA1+1Ei5McRd+iRzfhENPCe7LeABkJtNulSxjma+l7ltNx55BWZkRlwRnpOgHqxnjyaDgJnNXnqzg==} engines: {node: '>=10.13.0'} @@ -3268,6 +3834,8 @@ packages: snapshots: + '@alloc/quick-lru@5.2.0': {} + '@asteasolutions/zod-to-openapi@8.4.3(zod@4.3.6)': dependencies: openapi3-ts: 4.5.0 @@ -3702,6 +4270,68 @@ snapshots: '@aws/lambda-invoke-store@0.2.4': {} + '@codemirror/autocomplete@6.20.1': + dependencies: + '@codemirror/language': 6.12.3 + '@codemirror/state': 6.6.0 + '@codemirror/view': 6.40.0 + '@lezer/common': 1.5.1 + + '@codemirror/commands@6.10.3': + dependencies: + '@codemirror/language': 6.12.3 + '@codemirror/state': 6.6.0 + '@codemirror/view': 6.40.0 + '@lezer/common': 1.5.1 + + '@codemirror/lang-sql@6.10.0': + dependencies: + '@codemirror/autocomplete': 6.20.1 + '@codemirror/language': 6.12.3 + '@codemirror/state': 6.6.0 + '@lezer/common': 1.5.1 + '@lezer/highlight': 1.2.3 + '@lezer/lr': 1.4.8 + + '@codemirror/language@6.12.3': + dependencies: + '@codemirror/state': 6.6.0 + '@codemirror/view': 6.40.0 + '@lezer/common': 1.5.1 + '@lezer/highlight': 1.2.3 + '@lezer/lr': 1.4.8 + style-mod: 4.1.3 + + '@codemirror/lint@6.9.5': + dependencies: + '@codemirror/state': 6.6.0 + '@codemirror/view': 6.40.0 + crelt: 1.0.6 + + '@codemirror/search@6.6.0': + dependencies: + '@codemirror/state': 6.6.0 + '@codemirror/view': 6.40.0 + crelt: 1.0.6 + + '@codemirror/state@6.6.0': + dependencies: + '@marijn/find-cluster-break': 1.0.2 + + '@codemirror/view@6.40.0': + dependencies: + '@codemirror/state': 6.6.0 + crelt: 1.0.6 + style-mod: 4.1.3 + w3c-keyname: 2.2.8 + + '@electric-sql/pglite@0.2.17': {} + + '@emnapi/runtime@1.9.1': + dependencies: + tslib: 2.8.1 + optional: true + '@esbuild/aix-ppc64@0.25.12': optional: true @@ -3936,9 +4566,9 @@ snapshots: '@esbuild/win32-x64@0.27.3': optional: true - '@eslint-community/eslint-utils@4.9.0(eslint@9.39.1)': + '@eslint-community/eslint-utils@4.9.0(eslint@9.39.1(jiti@2.6.1))': dependencies: - eslint: 9.39.1 + eslint: 9.39.1(jiti@2.6.1) eslint-visitor-keys: 3.4.3 '@eslint-community/regexpp@4.12.2': {} @@ -4022,6 +4652,103 @@ snapshots: '@humanwhocodes/retry@0.4.3': {} + '@img/colour@1.1.0': + optional: true + + '@img/sharp-darwin-arm64@0.34.5': + optionalDependencies: + '@img/sharp-libvips-darwin-arm64': 1.2.4 + optional: true + + '@img/sharp-darwin-x64@0.34.5': + optionalDependencies: + '@img/sharp-libvips-darwin-x64': 1.2.4 + optional: true + + '@img/sharp-libvips-darwin-arm64@1.2.4': + optional: true + + '@img/sharp-libvips-darwin-x64@1.2.4': + optional: true + + '@img/sharp-libvips-linux-arm64@1.2.4': + optional: true + + '@img/sharp-libvips-linux-arm@1.2.4': + optional: true + + '@img/sharp-libvips-linux-ppc64@1.2.4': + optional: true + + '@img/sharp-libvips-linux-riscv64@1.2.4': + optional: true + + '@img/sharp-libvips-linux-s390x@1.2.4': + optional: true + + '@img/sharp-libvips-linux-x64@1.2.4': + optional: true + + '@img/sharp-libvips-linuxmusl-arm64@1.2.4': + optional: true + + '@img/sharp-libvips-linuxmusl-x64@1.2.4': + optional: true + + '@img/sharp-linux-arm64@0.34.5': + optionalDependencies: + '@img/sharp-libvips-linux-arm64': 1.2.4 + optional: true + + '@img/sharp-linux-arm@0.34.5': + optionalDependencies: + '@img/sharp-libvips-linux-arm': 1.2.4 + optional: true + + '@img/sharp-linux-ppc64@0.34.5': + optionalDependencies: + '@img/sharp-libvips-linux-ppc64': 1.2.4 + optional: true + + '@img/sharp-linux-riscv64@0.34.5': + optionalDependencies: + '@img/sharp-libvips-linux-riscv64': 1.2.4 + optional: true + + '@img/sharp-linux-s390x@0.34.5': + optionalDependencies: + '@img/sharp-libvips-linux-s390x': 1.2.4 + optional: true + + '@img/sharp-linux-x64@0.34.5': + optionalDependencies: + '@img/sharp-libvips-linux-x64': 1.2.4 + optional: true + + '@img/sharp-linuxmusl-arm64@0.34.5': + optionalDependencies: + '@img/sharp-libvips-linuxmusl-arm64': 1.2.4 + optional: true + + '@img/sharp-linuxmusl-x64@0.34.5': + optionalDependencies: + '@img/sharp-libvips-linuxmusl-x64': 1.2.4 + optional: true + + '@img/sharp-wasm32@0.34.5': + dependencies: + '@emnapi/runtime': 1.9.1 + optional: true + + '@img/sharp-win32-arm64@0.34.5': + optional: true + + '@img/sharp-win32-ia32@0.34.5': + optional: true + + '@img/sharp-win32-x64@0.34.5': + optional: true + '@isaacs/balanced-match@4.0.1': {} '@isaacs/brace-expansion@5.0.0': @@ -4042,6 +4769,11 @@ snapshots: '@jridgewell/sourcemap-codec': 1.5.5 '@jridgewell/trace-mapping': 0.3.31 + '@jridgewell/remapping@2.3.5': + dependencies: + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 + '@jridgewell/resolve-uri@3.1.2': {} '@jridgewell/source-map@0.3.11': @@ -4185,6 +4917,44 @@ snapshots: '@jsonjoy.com/codegen': 17.67.0(tslib@2.8.1) tslib: 2.8.1 + '@lezer/common@1.5.1': {} + + '@lezer/highlight@1.2.3': + dependencies: + '@lezer/common': 1.5.1 + + '@lezer/lr@1.4.8': + dependencies: + '@lezer/common': 1.5.1 + + '@marijn/find-cluster-break@1.0.2': {} + + '@next/env@15.5.14': {} + + '@next/swc-darwin-arm64@15.5.14': + optional: true + + '@next/swc-darwin-x64@15.5.14': + optional: true + + '@next/swc-linux-arm64-gnu@15.5.14': + optional: true + + '@next/swc-linux-arm64-musl@15.5.14': + optional: true + + '@next/swc-linux-x64-gnu@15.5.14': + optional: true + + '@next/swc-linux-x64-musl@15.5.14': + optional: true + + '@next/swc-win32-arm64-msvc@15.5.14': + optional: true + + '@next/swc-win32-x64-msvc@15.5.14': + optional: true + '@nodelib/fs.scandir@2.1.5': dependencies: '@nodelib/fs.stat': 2.0.5 @@ -4638,10 +5408,83 @@ snapshots: '@swc/counter@0.1.3': {} + '@swc/helpers@0.5.15': + dependencies: + tslib: 2.8.1 + '@swc/types@0.1.26': dependencies: '@swc/counter': 0.1.3 + '@tailwindcss/node@4.2.2': + dependencies: + '@jridgewell/remapping': 2.3.5 + enhanced-resolve: 5.20.1 + jiti: 2.6.1 + lightningcss: 1.32.0 + magic-string: 0.30.21 + source-map-js: 1.2.1 + tailwindcss: 4.2.2 + + '@tailwindcss/oxide-android-arm64@4.2.2': + optional: true + + '@tailwindcss/oxide-darwin-arm64@4.2.2': + optional: true + + '@tailwindcss/oxide-darwin-x64@4.2.2': + optional: true + + '@tailwindcss/oxide-freebsd-x64@4.2.2': + optional: true + + '@tailwindcss/oxide-linux-arm-gnueabihf@4.2.2': + optional: true + + '@tailwindcss/oxide-linux-arm64-gnu@4.2.2': + optional: true + + '@tailwindcss/oxide-linux-arm64-musl@4.2.2': + optional: true + + '@tailwindcss/oxide-linux-x64-gnu@4.2.2': + optional: true + + '@tailwindcss/oxide-linux-x64-musl@4.2.2': + optional: true + + '@tailwindcss/oxide-wasm32-wasi@4.2.2': + optional: true + + '@tailwindcss/oxide-win32-arm64-msvc@4.2.2': + optional: true + + '@tailwindcss/oxide-win32-x64-msvc@4.2.2': + optional: true + + '@tailwindcss/oxide@4.2.2': + optionalDependencies: + '@tailwindcss/oxide-android-arm64': 4.2.2 + '@tailwindcss/oxide-darwin-arm64': 4.2.2 + '@tailwindcss/oxide-darwin-x64': 4.2.2 + '@tailwindcss/oxide-freebsd-x64': 4.2.2 + '@tailwindcss/oxide-linux-arm-gnueabihf': 4.2.2 + '@tailwindcss/oxide-linux-arm64-gnu': 4.2.2 + '@tailwindcss/oxide-linux-arm64-musl': 4.2.2 + '@tailwindcss/oxide-linux-x64-gnu': 4.2.2 + '@tailwindcss/oxide-linux-x64-musl': 4.2.2 + '@tailwindcss/oxide-wasm32-wasi': 4.2.2 + '@tailwindcss/oxide-win32-arm64-msvc': 4.2.2 + '@tailwindcss/oxide-win32-x64-msvc': 4.2.2 + + '@tailwindcss/postcss@4.2.2': + dependencies: + '@alloc/quick-lru': 5.2.0 + '@tailwindcss/node': 4.2.2 + '@tailwindcss/oxide': 4.2.2 + postcss: 8.5.8 + tailwindcss: 4.2.2 + '@temporalio/activity@1.15.0': dependencies: '@temporalio/client': 1.15.0 @@ -4759,6 +5602,10 @@ snapshots: '@types/json-schema@7.0.15': {} + '@types/node@22.19.15': + dependencies: + undici-types: 6.21.0 + '@types/node@24.10.1': dependencies: undici-types: 7.16.0 @@ -4774,19 +5621,27 @@ snapshots: pg-protocol: 1.10.3 pg-types: 2.2.0 + '@types/react-dom@19.2.3(@types/react@19.2.14)': + dependencies: + '@types/react': 19.2.14 + + '@types/react@19.2.14': + dependencies: + csstype: 3.2.3 + '@types/ws@8.18.1': dependencies: '@types/node': 24.10.1 - '@typescript-eslint/eslint-plugin@8.46.3(@typescript-eslint/parser@8.46.3(eslint@9.39.1)(typescript@5.9.3))(eslint@9.39.1)(typescript@5.9.3)': + '@typescript-eslint/eslint-plugin@8.46.3(@typescript-eslint/parser@8.46.3(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3)': dependencies: '@eslint-community/regexpp': 4.12.2 - '@typescript-eslint/parser': 8.46.3(eslint@9.39.1)(typescript@5.9.3) + '@typescript-eslint/parser': 8.46.3(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3) '@typescript-eslint/scope-manager': 8.46.3 - '@typescript-eslint/type-utils': 8.46.3(eslint@9.39.1)(typescript@5.9.3) - '@typescript-eslint/utils': 8.46.3(eslint@9.39.1)(typescript@5.9.3) + '@typescript-eslint/type-utils': 8.46.3(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/utils': 8.46.3(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3) '@typescript-eslint/visitor-keys': 8.46.3 - eslint: 9.39.1 + eslint: 9.39.1(jiti@2.6.1) graphemer: 1.4.0 ignore: 7.0.5 natural-compare: 1.4.0 @@ -4795,14 +5650,14 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.46.3(eslint@9.39.1)(typescript@5.9.3)': + '@typescript-eslint/parser@8.46.3(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3)': dependencies: '@typescript-eslint/scope-manager': 8.46.3 '@typescript-eslint/types': 8.46.3 '@typescript-eslint/typescript-estree': 8.46.3(typescript@5.9.3) '@typescript-eslint/visitor-keys': 8.46.3 debug: 4.4.3 - eslint: 9.39.1 + eslint: 9.39.1(jiti@2.6.1) typescript: 5.9.3 transitivePeerDependencies: - supports-color @@ -4825,13 +5680,13 @@ snapshots: dependencies: typescript: 5.9.3 - '@typescript-eslint/type-utils@8.46.3(eslint@9.39.1)(typescript@5.9.3)': + '@typescript-eslint/type-utils@8.46.3(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3)': dependencies: '@typescript-eslint/types': 8.46.3 '@typescript-eslint/typescript-estree': 8.46.3(typescript@5.9.3) - '@typescript-eslint/utils': 8.46.3(eslint@9.39.1)(typescript@5.9.3) + '@typescript-eslint/utils': 8.46.3(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3) debug: 4.4.3 - eslint: 9.39.1 + eslint: 9.39.1(jiti@2.6.1) ts-api-utils: 2.1.0(typescript@5.9.3) typescript: 5.9.3 transitivePeerDependencies: @@ -4855,13 +5710,13 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.46.3(eslint@9.39.1)(typescript@5.9.3)': + '@typescript-eslint/utils@8.46.3(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3)': dependencies: - '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.1) + '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.1(jiti@2.6.1)) '@typescript-eslint/scope-manager': 8.46.3 '@typescript-eslint/types': 8.46.3 '@typescript-eslint/typescript-estree': 8.46.3(typescript@5.9.3) - eslint: 9.39.1 + eslint: 9.39.1(jiti@2.6.1) typescript: 5.9.3 transitivePeerDependencies: - supports-color @@ -4884,21 +5739,21 @@ snapshots: chai: 5.2.0 tinyrainbow: 2.0.0 - '@vitest/mocker@3.2.4(vite@7.2.2(@types/node@24.10.1)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.1))': + '@vitest/mocker@3.2.4(vite@7.2.2(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.1))': dependencies: '@vitest/spy': 3.2.4 estree-walker: 3.0.3 magic-string: 0.30.19 optionalDependencies: - vite: 7.2.2(@types/node@24.10.1)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.1) + vite: 7.2.2(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.1) - '@vitest/mocker@3.2.4(vite@7.2.2(@types/node@25.5.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.1))': + '@vitest/mocker@3.2.4(vite@7.2.2(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.1))': dependencies: '@vitest/spy': 3.2.4 estree-walker: 3.0.3 magic-string: 0.30.19 optionalDependencies: - vite: 7.2.2(@types/node@25.5.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.1) + vite: 7.2.2(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.1) '@vitest/pretty-format@3.2.4': dependencies: @@ -5065,6 +5920,15 @@ snapshots: atomic-sleep@1.0.0: {} + autoprefixer@10.4.27(postcss@8.5.8): + dependencies: + browserslist: 4.28.1 + caniuse-lite: 1.0.30001781 + fraction.js: 5.3.4 + picocolors: 1.1.1 + postcss: 8.5.8 + postcss-value-parser: 4.2.0 + axios@1.13.5: dependencies: follow-redirects: 1.15.11 @@ -5145,12 +6009,24 @@ snapshots: dependencies: consola: 3.4.2 + 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 + codemirror@6.0.2: + dependencies: + '@codemirror/autocomplete': 6.20.1 + '@codemirror/commands': 6.10.3 + '@codemirror/language': 6.12.3 + '@codemirror/lint': 6.9.5 + '@codemirror/search': 6.6.0 + '@codemirror/state': 6.6.0 + '@codemirror/view': 6.40.0 + color-convert@2.0.1: dependencies: color-name: 1.1.4 @@ -5167,12 +6043,16 @@ snapshots: consola@3.4.2: {} + crelt@1.0.6: {} + cross-spawn@7.0.6: dependencies: path-key: 3.1.1 shebang-command: 2.0.0 which: 2.0.2 + csstype@3.2.3: {} + debug@4.4.1: dependencies: ms: 2.1.3 @@ -5187,6 +6067,8 @@ snapshots: delayed-stream@1.0.0: {} + detect-libc@2.1.2: {} + dotenv@16.6.1: {} dunder-proto@1.0.1: @@ -5322,19 +6204,19 @@ snapshots: escape-string-regexp@4.0.0: {} - eslint-config-prettier@10.1.8(eslint@9.39.1): + eslint-config-prettier@10.1.8(eslint@9.39.1(jiti@2.6.1)): dependencies: - eslint: 9.39.1 + eslint: 9.39.1(jiti@2.6.1) - eslint-plugin-prettier@5.5.4(@types/eslint@9.6.1)(eslint-config-prettier@10.1.8(eslint@9.39.1))(eslint@9.39.1)(prettier@3.6.2): + eslint-plugin-prettier@5.5.4(@types/eslint@9.6.1)(eslint-config-prettier@10.1.8(eslint@9.39.1(jiti@2.6.1)))(eslint@9.39.1(jiti@2.6.1))(prettier@3.6.2): dependencies: - eslint: 9.39.1 + eslint: 9.39.1(jiti@2.6.1) prettier: 3.6.2 prettier-linter-helpers: 1.0.0 synckit: 0.11.11 optionalDependencies: '@types/eslint': 9.6.1 - eslint-config-prettier: 10.1.8(eslint@9.39.1) + eslint-config-prettier: 10.1.8(eslint@9.39.1(jiti@2.6.1)) eslint-scope@5.1.1: dependencies: @@ -5350,9 +6232,9 @@ snapshots: eslint-visitor-keys@4.2.1: {} - eslint@9.39.1: + eslint@9.39.1(jiti@2.6.1): dependencies: - '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.1) + '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.1(jiti@2.6.1)) '@eslint-community/regexpp': 4.12.2 '@eslint/config-array': 0.21.1 '@eslint/config-helpers': 0.4.2 @@ -5386,6 +6268,8 @@ snapshots: minimatch: 3.1.2 natural-compare: 1.4.0 optionator: 0.9.4 + optionalDependencies: + jiti: 2.6.1 transitivePeerDependencies: - supports-color @@ -5492,6 +6376,8 @@ snapshots: hasown: 2.0.2 mime-types: 2.1.35 + fraction.js@5.3.4: {} + fs-monkey@1.1.0: {} fsevents@2.3.3: @@ -5690,6 +6576,8 @@ snapshots: merge-stream: 2.0.0 supports-color: 8.1.1 + jiti@2.6.1: {} + js-tokens@9.0.1: {} js-yaml@4.1.0: @@ -5730,6 +6618,55 @@ snapshots: prelude-ls: 1.2.1 type-check: 0.4.0 + lightningcss-android-arm64@1.32.0: + optional: true + + lightningcss-darwin-arm64@1.32.0: + optional: true + + lightningcss-darwin-x64@1.32.0: + optional: true + + lightningcss-freebsd-x64@1.32.0: + optional: true + + lightningcss-linux-arm-gnueabihf@1.32.0: + optional: true + + lightningcss-linux-arm64-gnu@1.32.0: + optional: true + + lightningcss-linux-arm64-musl@1.32.0: + optional: true + + lightningcss-linux-x64-gnu@1.32.0: + optional: true + + lightningcss-linux-x64-musl@1.32.0: + optional: true + + lightningcss-win32-arm64-msvc@1.32.0: + optional: true + + lightningcss-win32-x64-msvc@1.32.0: + optional: true + + lightningcss@1.32.0: + dependencies: + detect-libc: 2.1.2 + optionalDependencies: + lightningcss-android-arm64: 1.32.0 + lightningcss-darwin-arm64: 1.32.0 + lightningcss-darwin-x64: 1.32.0 + lightningcss-freebsd-x64: 1.32.0 + lightningcss-linux-arm-gnueabihf: 1.32.0 + lightningcss-linux-arm64-gnu: 1.32.0 + lightningcss-linux-arm64-musl: 1.32.0 + lightningcss-linux-x64-gnu: 1.32.0 + lightningcss-linux-x64-musl: 1.32.0 + lightningcss-win32-arm64-msvc: 1.32.0 + lightningcss-win32-x64-msvc: 1.32.0 + loader-runner@4.3.1: {} locate-path@6.0.0: @@ -5750,6 +6687,10 @@ snapshots: dependencies: '@jridgewell/sourcemap-codec': 1.5.5 + magic-string@0.30.21: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + math-intrinsics@1.1.0: {} memfs@4.57.1(tslib@2.8.1): @@ -5808,6 +6749,29 @@ snapshots: neo-async@2.6.2: {} + next@15.5.14(react-dom@19.2.4(react@19.2.4))(react@19.2.4): + dependencies: + '@next/env': 15.5.14 + '@swc/helpers': 0.5.15 + caniuse-lite: 1.0.30001781 + postcss: 8.4.31 + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + styled-jsx: 5.1.6(react@19.2.4) + optionalDependencies: + '@next/swc-darwin-arm64': 15.5.14 + '@next/swc-darwin-x64': 15.5.14 + '@next/swc-linux-arm64-gnu': 15.5.14 + '@next/swc-linux-arm64-musl': 15.5.14 + '@next/swc-linux-x64-gnu': 15.5.14 + '@next/swc-linux-x64-musl': 15.5.14 + '@next/swc-win32-arm64-msvc': 15.5.14 + '@next/swc-win32-x64-msvc': 15.5.14 + sharp: 0.34.5 + transitivePeerDependencies: + - '@babel/core' + - babel-plugin-macros + nexus-rpc@0.0.1: {} node-fetch@2.7.0: @@ -5923,7 +6887,15 @@ snapshots: sonic-boom: 4.2.0 thread-stream: 3.1.0 - postcss@8.5.6: + postcss-value-parser@4.2.0: {} + + postcss@8.4.31: + dependencies: + nanoid: 3.3.11 + picocolors: 1.1.1 + source-map-js: 1.2.1 + + postcss@8.5.8: dependencies: nanoid: 3.3.11 picocolors: 1.1.1 @@ -5980,6 +6952,13 @@ snapshots: quick-format-unescaped@4.0.4: {} + react-dom@19.2.4(react@19.2.4): + dependencies: + react: 19.2.4 + scheduler: 0.27.0 + + react@19.2.4: {} + real-require@0.2.0: {} require-directory@2.1.1: {} @@ -6039,6 +7018,8 @@ snapshots: safer-buffer@2.1.2: {} + scheduler@0.27.0: {} + schema-utils@4.3.3: dependencies: '@types/json-schema': 7.0.15 @@ -6048,6 +7029,38 @@ snapshots: semver@7.7.3: {} + sharp@0.34.5: + dependencies: + '@img/colour': 1.1.0 + detect-libc: 2.1.2 + semver: 7.7.3 + optionalDependencies: + '@img/sharp-darwin-arm64': 0.34.5 + '@img/sharp-darwin-x64': 0.34.5 + '@img/sharp-libvips-darwin-arm64': 1.2.4 + '@img/sharp-libvips-darwin-x64': 1.2.4 + '@img/sharp-libvips-linux-arm': 1.2.4 + '@img/sharp-libvips-linux-arm64': 1.2.4 + '@img/sharp-libvips-linux-ppc64': 1.2.4 + '@img/sharp-libvips-linux-riscv64': 1.2.4 + '@img/sharp-libvips-linux-s390x': 1.2.4 + '@img/sharp-libvips-linux-x64': 1.2.4 + '@img/sharp-libvips-linuxmusl-arm64': 1.2.4 + '@img/sharp-libvips-linuxmusl-x64': 1.2.4 + '@img/sharp-linux-arm': 0.34.5 + '@img/sharp-linux-arm64': 0.34.5 + '@img/sharp-linux-ppc64': 0.34.5 + '@img/sharp-linux-riscv64': 0.34.5 + '@img/sharp-linux-s390x': 0.34.5 + '@img/sharp-linux-x64': 0.34.5 + '@img/sharp-linuxmusl-arm64': 0.34.5 + '@img/sharp-linuxmusl-x64': 0.34.5 + '@img/sharp-wasm32': 0.34.5 + '@img/sharp-win32-arm64': 0.34.5 + '@img/sharp-win32-ia32': 0.34.5 + '@img/sharp-win32-x64': 0.34.5 + optional: true + shebang-command@2.0.0: dependencies: shebang-regex: 3.0.0 @@ -6146,6 +7159,13 @@ snapshots: strnum@2.2.1: {} + style-mod@4.1.3: {} + + styled-jsx@5.1.6(react@19.2.4): + dependencies: + client-only: 0.0.1 + react: 19.2.4 + supabase-management-js@2.0.2: dependencies: axios: 1.13.5 @@ -6171,6 +7191,8 @@ snapshots: dependencies: '@pkgr/core': 0.2.9 + tailwindcss@4.2.2: {} + tapable@2.3.2: {} terser-webpack-plugin@5.4.0(@swc/core@1.15.21)(webpack@5.105.4(@swc/core@1.15.21)): @@ -6242,6 +7264,8 @@ snapshots: typescript@5.9.3: {} + undici-types@6.21.0: {} + undici-types@7.16.0: {} undici-types@7.18.2: @@ -6267,13 +7291,13 @@ snapshots: uuid@9.0.1: {} - vite-node@3.2.4(@types/node@24.10.1)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.1): + vite-node@3.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.1): dependencies: cac: 6.7.14 debug: 4.4.3 es-module-lexer: 1.7.0 pathe: 2.0.3 - vite: 7.2.2(@types/node@24.10.1)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.1) + vite: 7.2.2(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.1) transitivePeerDependencies: - '@types/node' - jiti @@ -6288,13 +7312,13 @@ snapshots: - tsx - yaml - vite-node@3.2.4(@types/node@25.5.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.1): + vite-node@3.2.4(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.1): dependencies: cac: 6.7.14 debug: 4.4.3 es-module-lexer: 1.7.0 pathe: 2.0.3 - vite: 7.2.2(@types/node@25.5.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.1) + vite: 7.2.2(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.1) transitivePeerDependencies: - '@types/node' - jiti @@ -6309,41 +7333,45 @@ snapshots: - tsx - yaml - vite@7.2.2(@types/node@24.10.1)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.1): + vite@7.2.2(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.1): dependencies: esbuild: 0.25.12 fdir: 6.5.0(picomatch@4.0.3) picomatch: 4.0.3 - postcss: 8.5.6 + postcss: 8.5.8 rollup: 4.53.1 tinyglobby: 0.2.15 optionalDependencies: '@types/node': 24.10.1 fsevents: 2.3.3 + jiti: 2.6.1 + lightningcss: 1.32.0 terser: 5.46.1 tsx: 4.21.0 yaml: 2.8.1 - vite@7.2.2(@types/node@25.5.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.1): + vite@7.2.2(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.1): dependencies: esbuild: 0.25.12 fdir: 6.5.0(picomatch@4.0.3) picomatch: 4.0.3 - postcss: 8.5.6 + postcss: 8.5.8 rollup: 4.53.1 tinyglobby: 0.2.15 optionalDependencies: '@types/node': 25.5.0 fsevents: 2.3.3 + jiti: 2.6.1 + lightningcss: 1.32.0 terser: 5.46.1 tsx: 4.21.0 yaml: 2.8.1 - vitest@3.2.4(@types/node@24.10.1)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.1): + vitest@3.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.1): dependencies: '@types/chai': 5.2.2 '@vitest/expect': 3.2.4 - '@vitest/mocker': 3.2.4(vite@7.2.2(@types/node@24.10.1)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.1)) + '@vitest/mocker': 3.2.4(vite@7.2.2(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.1)) '@vitest/pretty-format': 3.2.4 '@vitest/runner': 3.2.4 '@vitest/snapshot': 3.2.4 @@ -6361,8 +7389,8 @@ snapshots: tinyglobby: 0.2.15 tinypool: 1.1.1 tinyrainbow: 2.0.0 - vite: 7.2.2(@types/node@24.10.1)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.1) - vite-node: 3.2.4(@types/node@24.10.1)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.1) + vite: 7.2.2(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.1) + vite-node: 3.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.1) why-is-node-running: 2.3.0 optionalDependencies: '@types/node': 24.10.1 @@ -6380,11 +7408,11 @@ snapshots: - tsx - yaml - vitest@3.2.4(@types/node@25.5.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.1): + vitest@3.2.4(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.1): dependencies: '@types/chai': 5.2.2 '@vitest/expect': 3.2.4 - '@vitest/mocker': 3.2.4(vite@7.2.2(@types/node@25.5.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.1)) + '@vitest/mocker': 3.2.4(vite@7.2.2(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.1)) '@vitest/pretty-format': 3.2.4 '@vitest/runner': 3.2.4 '@vitest/snapshot': 3.2.4 @@ -6402,8 +7430,8 @@ snapshots: tinyglobby: 0.2.15 tinypool: 1.1.1 tinyrainbow: 2.0.0 - vite: 7.2.2(@types/node@25.5.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.1) - vite-node: 3.2.4(@types/node@25.5.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.1) + vite: 7.2.2(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.1) + vite-node: 3.2.4(@types/node@25.5.0)(jiti@2.6.1)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.1) why-is-node-running: 2.3.0 optionalDependencies: '@types/node': 25.5.0 @@ -6421,6 +7449,8 @@ snapshots: - tsx - yaml + w3c-keyname@2.2.8: {} + watchpack@2.5.1: dependencies: glob-to-regexp: 0.4.1