From 13f120086efcdc8136145daac0bd4e17e97392a0 Mon Sep 17 00:00:00 2001 From: Clement Denis Date: Fri, 3 Apr 2026 17:42:47 +0200 Subject: [PATCH 1/7] WIP --- Dockerfile | 1 + README.md | 21 ++ api/clickhouse-client.ts | 50 +++- api/lib/env.ts | 8 +- api/routes.ts | 29 +- api/server.ts | 2 + compose.yaml | 57 ++++ deno.json | 2 - deno.lock | 546 +++++++++++++--------------------- tasks/clickhouse.ts | 46 --- tasks/vite.ts | 30 +- web/components/BrandIcons.tsx | 20 -- web/components/SideBar.tsx | 8 +- web/layout.tsx | 14 +- web/lib/session.ts | 13 + web/pages/DeploymentPage.tsx | 16 +- web/pages/ProjectPage.tsx | 20 +- 17 files changed, 406 insertions(+), 477 deletions(-) create mode 100644 compose.yaml delete mode 100644 tasks/clickhouse.ts delete mode 100644 web/components/BrandIcons.tsx diff --git a/Dockerfile b/Dockerfile index 75a0708..da31208 100644 --- a/Dockerfile +++ b/Dockerfile @@ -13,6 +13,7 @@ COPY ./web /app/web RUN deno cache --allow-scripts --lock=deno.lock api/server.ts tasks/vite.ts # Build frontend (dist/web) and compile backend with static files +ENV BASE_URL="/" RUN deno task prod # Stage 2: Final image diff --git a/README.md b/README.md index 0b30a8e..9ac154f 100644 --- a/README.md +++ b/README.md @@ -94,6 +94,27 @@ deno task docker:prod deno task docker:logs ``` +### Docker Compose + +Use the compose stack when you want ClickHouse and the app started together. +It has inline defaults, so no env file is required. + +```bash +docker compose up --build +``` + +Override any value from your shell or a local `.env` file. Example: + +```bash +PORT=8877 CLICKHOUSE_PASSWORD=strong-password docker compose up --build +``` + +The stack starts: + +- `clickhouse`: database server on ports `8123` and `9000` +- `clickhouse-init`: one-shot schema creation for the `logs` table +- `app`: compiled application on port `3021` + ### Available Tasks ```bash diff --git a/api/clickhouse-client.ts b/api/clickhouse-client.ts index 0a70e4f..a6e7094 100644 --- a/api/clickhouse-client.ts +++ b/api/clickhouse-client.ts @@ -15,7 +15,7 @@ import { UNION, } from '@01edu/api/validator' -const LogSchema = OBJ({ +export const LogSchema = OBJ({ timestamp: NUM('The timestamp of the log event'), trace_id: NUM('A float64 representation of the trace ID'), span_id: optional(NUM('A float64 representation of the span ID')), @@ -41,7 +41,7 @@ export const LogSchemaOutput = OBJ({ service_instance_id: optional(STR('Service instance ID')), }, 'A log event') -const LogsInputSchema = UNION( +export const LogsInputSchema = UNION( LogSchema, ARR(LogSchema, 'An array of log events'), ) @@ -49,7 +49,7 @@ const LogsInputSchema = UNION( type Log = Asserted type LogsInput = Asserted -const client = createClient({ +export const client = createClient({ url: CLICKHOUSE_HOST, username: CLICKHOUSE_USER, password: CLICKHOUSE_PASSWORD, @@ -79,10 +79,7 @@ const numberToHex128 = (() => { } })() -async function insertLogs( - service_name: string, - data: LogsInput, -) { +export async function insertLogs(service_name: string,data: LogsInput) { const logsToInsert = Array.isArray(data) ? data : [data] if (logsToInsert.length === 0) return respond.NoContent() @@ -204,7 +201,7 @@ function inferParamType(key: string, value: string): string { return 'String' } -async function getLogs(dep: string, data: FetchTablesParams) { +export async function getLogs(dep: string, data: FetchTablesParams) { const { query, params } = buildLogsQuery(dep, data) try { const rs = await client.query({ @@ -244,4 +241,39 @@ async function getLogs(dep: string, data: FetchTablesParams) { // } // } -export { client, getLogs, insertLogs, LogSchema, LogsInputSchema } +export const initLogTable = async () => { + await client.ping() + await client.command({ + query: ` + CREATE TABLE IF NOT EXISTS logs ( + id UUID DEFAULT generateUUIDv4(), + -- Flattened resource fields + service_name LowCardinality(String), + service_version LowCardinality(String), + service_instance_id String, + + timestamp DateTime64(3, 'UTC') DEFAULT now64(3, 'UTC'), + observed_timestamp DateTime64(3, 'UTC') DEFAULT now64(3, 'UTC'), + trace_id FixedString(16), + span_id FixedString(16), + severity_number UInt8, + -- derived column, computed by DB from severity_number + severity_text LowCardinality(String) MATERIALIZED CASE + WHEN severity_number > 4 AND severity_number <= 8 THEN 'DEBUG' + WHEN severity_number > 8 AND severity_number <= 12 THEN 'INFO' + WHEN severity_number > 12 AND severity_number <= 16 THEN 'WARN' + WHEN severity_number > 20 AND severity_number <= 24 THEN 'FATAL' + ELSE 'ERROR' + END, + -- Often empty, but kept for OTEL spec compliance + body Nullable(String), + attributes JSON, + event_name LowCardinality(String) + ) + ENGINE = MergeTree + PARTITION BY toYYYYMMDD(timestamp) + ORDER BY (service_name, timestamp, trace_id) + SETTINGS index_granularity = 8192, min_bytes_for_wide_part = 0; + `, + }) +} diff --git a/api/lib/env.ts b/api/lib/env.ts index 12eff48..85ebdc1 100644 --- a/api/lib/env.ts +++ b/api/lib/env.ts @@ -2,9 +2,9 @@ import { ENV } from '@01edu/api/env' export const PORT = Number(ENV('PORT', '2119')) export const PICTURE_DIR = ENV('PICTURE_DIR', './.picture') -export const GOOGLE_CLIENT_ID = ENV('GOOGLE_CLIENT_ID') -export const CLIENT_SECRET = ENV('CLIENT_SECRET') -export const REDIRECT_URI = ENV('REDIRECT_URI') +export const GOOGLE_CLIENT_ID = ENV('GOOGLE_CLIENT_ID', '') +export const CLIENT_SECRET = ENV('CLIENT_SECRET', '') +export const REDIRECT_URI = ENV('REDIRECT_URI', `http://localhost:${PORT}`) export const ORIGIN = new URL(REDIRECT_URI).origin export const SECRET = ENV( 'SECRET', @@ -23,6 +23,8 @@ export const DB_SCHEMA_REFRESH_MS = Number( export const STORE_URL = ENV('STORE_URL') export const STORE_SECRET = ENV('STORE_SECRET') +const LOCAL_ENV = ENV('LOCAL_ENV', '') +export const isLocal = LOCAL_ENV === 'yes' || LOCAL_ENV == '1' || LOCAL_ENV === 'true' export const GEMINI_API_KEY = ENV('GEMINI_API_KEY') diff --git a/api/routes.ts b/api/routes.ts index 16328c2..d62742d 100644 --- a/api/routes.ts +++ b/api/routes.ts @@ -12,7 +12,7 @@ import { TeamDetailDef, User, UserDef, -} from './schema.ts' +} from '/api/schema.ts' import { ARR, BOOL, @@ -40,6 +40,7 @@ import { SQLQueryError, updateTableData, } from '/api/sql.ts' +import { isLocal } from '/api/lib/env.ts' import { get, getOne } from './lmdb-store.ts' import { log } from '/api/lib/logger.ts' import { analyzeQueryWithAI } from '/api/fix-query.ts' @@ -70,15 +71,25 @@ const MetricSchema = OBJ({ }, 'SQLite sqlite3_stmt_status counters'), }) -const withUserSession = async ({ cookies }: RequestContext) => { - const session = await decodeSession(cookies.session) - if (!session) { - log.warn('auth-missing-session') - throw new respond.UnauthorizedError({ message: 'Missing user session' }) +const localUser = { + id: 'local', // this id is for local env, it will ignore permissions + email: 'local@admin.dev', + fullName: 'Local Dev', + picture: 'https://www.npmjs.com/npm-avatar/eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdmF0YXJVUkwiOiJodHRwczovL3MuZ3JhdmF0YXIuY29tL2F2YXRhci9jMzQ1YzkyNTExNjZjNDVlYmViOWFjZTRiYmY5MjFiOT9zaXplPTQ5NiZkZWZhdWx0PXJldHJvIn0.7mU8AfQy7sYbuGZLwK5ZxkfwxfZnxaLOjDqoh5g4H5g', + isAdmin: true, +} as const + +const withUserSession = isLocal + ? () => localUser + : async ({ cookies }: RequestContext) => { + const session = await decodeSession(cookies.session) + if (!session) { + log.warn('auth-missing-session') + throw new respond.UnauthorizedError({ message: 'Missing user session' }) + } + const admin = AdminsCollection.get(session.id) + return { ...session, isAdmin: !!admin } } - const admin = AdminsCollection.get(session.id) - return { ...session, isAdmin: !!admin } -} const withAdminSession = async (ctx: RequestContext) => { const session = await withUserSession(ctx) diff --git a/api/server.ts b/api/server.ts index 596cef5..50e1413 100644 --- a/api/server.ts +++ b/api/server.ts @@ -4,9 +4,11 @@ import { server } from '@01edu/api/server' import { routeHandler } from '/api/routes.ts' import { PORT } from './lib/env.ts' import { init } from '/api/lib/functions.ts' +import { initLogTable } from '/api/clickhouse-client.ts' import { startSchemaRefreshLoop } from './sql.ts' import { log } from '/api/lib/logger.ts' +await initLogTable() await init() startSchemaRefreshLoop() diff --git a/compose.yaml b/compose.yaml new file mode 100644 index 0000000..b8b6323 --- /dev/null +++ b/compose.yaml @@ -0,0 +1,57 @@ +services: + clickhouse: + image: clickhouse/clickhouse-server:latest + restart: unless-stopped + environment: + CLICKHOUSE_USER: ${CLICKHOUSE_USER:-devtools} + CLICKHOUSE_PASSWORD: ${CLICKHOUSE_PASSWORD:-devtools-password} + CLICKHOUSE_DEFAULT_ACCESS_MANAGEMENT: ${CLICKHOUSE_DEFAULT_ACCESS_MANAGEMENT:-1} + ports: + - "8123:8123" + - "9000:9000" + ulimits: + nofile: + soft: 262144 + hard: 262144 + volumes: + - clickhouse-data:/var/lib/clickhouse + healthcheck: + test: + [ + "CMD-SHELL", + "clickhouse-client --host 127.0.0.1 --user \"$${CLICKHOUSE_USER}\" --password \"$${CLICKHOUSE_PASSWORD}\" --query 'SELECT 1' >/dev/null 2>&1", + ] + interval: 5s + timeout: 5s + retries: 20 + start_period: 10s + + app: + build: + context: . + restart: unless-stopped + environment: + APP_ENV: ${APP_ENV:-prod} + PORT: ${PORT:-3021} + PICTURE_DIR: ${PICTURE_DIR:-/app/.picture} + GOOGLE_CLIENT_ID: ${GOOGLE_CLIENT_ID:-} + CLIENT_SECRET: ${CLIENT_SECRET:-} + REDIRECT_URI: ${REDIRECT_URI:-http://localhost:3021/auth/callback} + SECRET: ${SECRET:-replace-with-a-real-secret} + STORE_URL: ${STORE_URL:-} + STORE_SECRET: ${STORE_SECRET:-} + CLICKHOUSE_HOST: ${CLICKHOUSE_HOST:-http://clickhouse:8123} + CLICKHOUSE_USER: ${CLICKHOUSE_USER:-devtools} + CLICKHOUSE_PASSWORD: ${CLICKHOUSE_PASSWORD:-devtools-password} + depends_on: + clickhouse: + condition: service_healthy + ports: + - "${PORT:-3021}:3021" + volumes: + - ./db:/app/db + - app-pictures:/app/.picture + +volumes: + clickhouse-data: + app-pictures: diff --git a/deno.json b/deno.json index 09b72af..6217ef1 100644 --- a/deno.json +++ b/deno.json @@ -5,7 +5,6 @@ "check": "deno check", "dev": { "dependencies": ["dev:clickhouse", "dev:api", "dev:vite"] }, "dev:api": "deno serve --port 3021 -A --env-file=.env.dev api/server.ts", - "dev:clickhouse": "deno run -A --env-file=.env.dev tasks/clickhouse.ts", "dev:env": "deno run -A tasks/env.ts", "dev:vite": "deno run -A --env-file=.env.dev tasks/vite.ts", "dev:with-seed": "deno task seed && deno task dev", @@ -22,7 +21,6 @@ "lint": "deno lint", "prod": "deno task prod:vite && deno task prod:api", "prod:api": "deno compile -A --no-check --output dist/api --target x86_64-unknown-linux-gnu --include dist/web api/server.ts --env=prod", - "prod:clickhouse": "APP_ENV=prod deno run -A --env-file tasks/clickhouse.ts", "prod:start": "deno task clickhouse:prod && dist/api", "prod:vite": "BASE_URL=/ APP_ENV=prod deno run -A tasks/vite.ts", "review": "deno run -A https://gistcdn.githack.com/kigiri/7658b4af30bb5eaca3e4cad1fcac7b0c/raw/review.js", diff --git a/deno.lock b/deno.lock index 3d15a9b..44a510f 100644 --- a/deno.lock +++ b/deno.lock @@ -1,72 +1,60 @@ { "version": "5", "specifiers": { - "jsr:@01edu/api-client@~0.2.6": "0.2.6", + "jsr:@01edu/api-client@~0.2.3": "0.2.3", "jsr:@01edu/api-proxy@~0.2.1": "0.2.1", - "jsr:@01edu/api@~0.2.7": "0.2.7", + "jsr:@01edu/api@~0.2.3": "0.2.3", + "jsr:@01edu/signal-router@~0.2.1": "0.2.1", "jsr:@01edu/time@0.1": "0.1.0", - "jsr:@01edu/types@~0.2.6": "0.2.6", + "jsr:@01edu/types@~0.2.3": "0.2.3", "jsr:@cd/sqlite@~0.13.1": "0.13.1", - "jsr:@deno/gfm@0.12.0": "0.12.0", - "jsr:@denosaurs/emoji@~0.3.1": "0.3.1", "jsr:@denosaurs/plug@1": "1.1.0", + "jsr:@std/assert@^1.0.17": "1.0.19", "jsr:@std/assert@^1.0.19": "1.0.19", - "jsr:@std/cli@^1.0.29": "1.0.29", - "jsr:@std/crypto@^1.1.0": "1.1.0", - "jsr:@std/data-structures@^1.0.11": "1.0.11", + "jsr:@std/async@^1.1.0": "1.2.0", + "jsr:@std/cli@^1.0.28": "1.0.28", + "jsr:@std/crypto@^1.0.5": "1.0.5", + "jsr:@std/data-structures@^1.0.10": "1.0.10", "jsr:@std/encoding@1": "1.0.10", "jsr:@std/encoding@^1.0.10": "1.0.10", - "jsr:@std/fmt@1": "1.0.10", - "jsr:@std/fmt@^1.0.10": "1.0.10", - "jsr:@std/fmt@^1.0.9": "1.0.10", + "jsr:@std/fmt@1": "1.0.9", + "jsr:@std/fmt@^1.0.9": "1.0.9", "jsr:@std/fs@1": "1.0.23", + "jsr:@std/fs@^1.0.22": "1.0.23", "jsr:@std/fs@^1.0.23": "1.0.23", - "jsr:@std/html@^1.0.6": "1.0.6", - "jsr:@std/http@^1.0.25": "1.1.0", - "jsr:@std/http@^1.1.0": "1.1.0", - "jsr:@std/internal@^1.0.12": "1.0.13", - "jsr:@std/internal@^1.0.13": "1.0.13", + "jsr:@std/html@^1.0.5": "1.0.5", + "jsr:@std/http@^1.0.25": "1.0.25", + "jsr:@std/internal@^1.0.12": "1.0.12", "jsr:@std/media-types@^1.1.0": "1.1.0", "jsr:@std/net@^1.0.6": "1.0.6", "jsr:@std/path@1": "1.1.4", "jsr:@std/path@1.0": "1.0.9", "jsr:@std/path@^1.1.4": "1.1.4", - "jsr:@std/streams@^1.1.0": "1.1.0", - "jsr:@std/testing@^1.0.18": "1.0.18", - "npm:@01edu/signal-router@~0.2.3": "0.2.3_@preact+signals@2.9.0__preact@10.29.2_preact@10.29.2", - "npm:@clickhouse/client@^1.18.5": "1.18.5", - "npm:@deno/vite-plugin@^2.0.2": "2.0.2_vite@8.0.13", - "npm:@preact/preset-vite@^2.10.5": "2.10.5_vite@8.0.13_preact@10.29.2", - "npm:@preact/signals@^2.9.0": "2.9.0_preact@10.29.2", - "npm:@tailwindcss/vite@^4.3.0": "4.3.0_vite@8.0.13", + "jsr:@std/streams@^1.0.17": "1.0.17", + "jsr:@std/testing@^1.0.17": "1.0.17", + "npm:@clickhouse/client@^1.18.2": "1.18.2", + "npm:@deno/vite-plugin@^2.0.2": "2.0.2_vite@8.0.3__@emnapi+core@1.9.1__@emnapi+runtime@1.9.1_@emnapi+core@1.9.1_@emnapi+runtime@1.9.1", + "npm:@preact/preset-vite@^2.10.5": "2.10.5_@babel+core@7.29.0_vite@8.0.3__@emnapi+core@1.9.1__@emnapi+runtime@1.9.1_@emnapi+core@1.9.1_@emnapi+runtime@1.9.1_preact@10.29.0", + "npm:@preact/signals@^2.9.0": "2.9.0_preact@10.29.0", + "npm:@tailwindcss/vite@^4.2.2": "4.2.2_vite@8.0.3__@emnapi+core@1.9.1__@emnapi+runtime@1.9.1_@emnapi+core@1.9.1_@emnapi+runtime@1.9.1", "npm:daisyui@^5.5.19": "5.5.19", - "npm:github-slugger@2": "2.0.0", - "npm:he@^1.2.0": "1.2.0", - "npm:katex@0.16": "0.16.46", - "npm:lucide-preact@^1.16.0": "1.16.0_preact@10.29.2", - "npm:marked-alert@^2.1.2": "2.1.2_marked@17.0.6", - "npm:marked-footnote@^1.4.0": "1.4.0_marked@17.0.6", - "npm:marked-gfm-heading-id@^4.1.3": "4.1.4_marked@17.0.6", - "npm:marked@^17.0.1": "17.0.6", - "npm:preact@^10.29.2": "10.29.2", - "npm:prismjs@^1.30.0": "1.30.0", - "npm:sanitize-html@^2.17.0": "2.17.4", - "npm:tailwindcss@^4.3.0": "4.3.0", - "npm:vite@^8.0.13": "8.0.13", - "npm:vite@^8.0.3": "8.0.13" + "npm:lucide-preact@^1.7.0": "1.7.0_preact@10.29.0", + "npm:preact@^10.29.0": "10.29.0", + "npm:tailwindcss@^4.2.2": "4.2.2", + "npm:vite@^8.0.3": "8.0.3_@emnapi+core@1.9.1_@emnapi+runtime@1.9.1" }, "jsr": { - "@01edu/api@0.2.7": { - "integrity": "17198ab087829f38dafc17e08cd7fd72ce04118a0058019d6af055f5ab3ea244", + "@01edu/api@0.2.3": { + "integrity": "bdd84e35381886c1a001c1d1cc7148e133ca52f8238de07801e47d7eabfdd8a7", "dependencies": [ "jsr:@01edu/time", "jsr:@01edu/types", "jsr:@std/fmt@^1.0.9", - "jsr:@std/http@^1.0.25" + "jsr:@std/http" ] }, - "@01edu/api-client@0.2.6": { - "integrity": "b5cd8e30259735734c2345312f335ada0ba4dfe28fc03e33f3ae478b7c810173", + "@01edu/api-client@0.2.3": { + "integrity": "6a561be260a6babd5c689c2a1ae62eaa9c407009cbebe73482ba92b1ce44cef5", "dependencies": [ "jsr:@01edu/types", "npm:@preact/signals" @@ -75,14 +63,21 @@ "@01edu/api-proxy@0.2.1": { "integrity": "ea188b029a324c920c22dfe52f6cd389fcd3764124dc405874cdfc9f4d78f271", "dependencies": [ - "npm:vite@^8.0.3" + "npm:vite" + ] + }, + "@01edu/signal-router@0.2.1": { + "integrity": "ee444d4f4672ba9ec6b67f827da60b092746053bebf6b43f2dee08bce1f0dde4", + "dependencies": [ + "npm:@preact/signals", + "npm:preact" ] }, "@01edu/time@0.1.0": { "integrity": "638ea7d2d00bfbf487e5262b4d6207de7f2101793d0d27a63d492e113a07dcb2" }, - "@01edu/types@0.2.6": { - "integrity": "a4ef7157a43b1fce692687c131a456957395a2ab94ff2d0c593ad0e8d805232f", + "@01edu/types@0.2.3": { + "integrity": "49880a688add4d786cb90a41822066ab8c41499ba746cb80356c61a3e485dac6", "dependencies": [ "jsr:@cd/sqlite" ] @@ -94,24 +89,6 @@ "jsr:@std/path@1.0" ] }, - "@deno/gfm@0.12.0": { - "integrity": "9b2d8f3e3d5673da5b2e8613d36cf38619ac5e3bdeb895d35472a16870fb147a", - "dependencies": [ - "jsr:@denosaurs/emoji", - "npm:github-slugger", - "npm:he", - "npm:katex", - "npm:marked", - "npm:marked-alert", - "npm:marked-footnote", - "npm:marked-gfm-heading-id", - "npm:prismjs", - "npm:sanitize-html" - ] - }, - "@denosaurs/emoji@0.3.1": { - "integrity": "b0aed5f55dec99e83da7c9637fe0a36d1d6252b7c99deaaa3fc5dea3fcf3da8b" - }, "@denosaurs/plug@1.1.0": { "integrity": "eb2f0b7546c7bca2000d8b0282c54d50d91cf6d75cb26a80df25a6de8c4bc044", "dependencies": [ @@ -124,40 +101,43 @@ "@std/assert@1.0.19": { "integrity": "eaada96ee120cb980bc47e040f82814d786fe8162ecc53c91d8df60b8755991e", "dependencies": [ - "jsr:@std/internal@^1.0.12" + "jsr:@std/internal" ] }, - "@std/cli@1.0.29": { - "integrity": "fa4ef29130baa834d8a13b7d138240c3a2fcfba740bfb7afa646a360a15ec84f" + "@std/async@1.2.0": { + "integrity": "c059c6f6d95ca7cc012ae8e8d7164d1697113d54b0b679e4372b354b11c2dee5" + }, + "@std/cli@1.0.28": { + "integrity": "74ef9b976db59ca6b23a5283469c9072be6276853807a83ec6c7ce412135c70a" }, - "@std/crypto@1.1.0": { - "integrity": "b8d6d0a6377a32b213af2661ed7bf1062d94feac0c57def5526a8e74a95c3ec8" + "@std/crypto@1.0.5": { + "integrity": "0dcfbb319fe0bba1bd3af904ceb4f948cde1b92979ec1614528380ed308a3b40" }, - "@std/data-structures@1.0.11": { - "integrity": "53b98ed7efa61f107dfc14244bd2ec5557f7f7ee0bbaef6d449d7937facacb89" + "@std/data-structures@1.0.10": { + "integrity": "f574f86b0e07c69b9edc555fcc814b57d29258bad39fd5a34ba8a80ecf033cfe" }, "@std/encoding@1.0.10": { "integrity": "8783c6384a2d13abd5e9e87a7ae0520a30e9f56aeeaa3bdf910a3eaaf5c811a1" }, - "@std/fmt@1.0.10": { - "integrity": "90dfba288802ac6de82fb31d0917eb9e4450b9925b954d5e51fc29ac07419db5" + "@std/fmt@1.0.9": { + "integrity": "2487343e8899fb2be5d0e3d35013e54477ada198854e52dd05ed0422eddcabe0" }, "@std/fs@1.0.23": { "integrity": "3ecbae4ce4fee03b180fa710caff36bb5adb66631c46a6460aaad49515565a37", "dependencies": [ - "jsr:@std/internal@^1.0.12", + "jsr:@std/internal", "jsr:@std/path@^1.1.4" ] }, - "@std/html@1.0.6": { - "integrity": "eaf759c8141e0733ca30eb49e4c08d8e6ca442b85c4d51f9894a56f502993e08" + "@std/html@1.0.5": { + "integrity": "4e2d693f474cae8c16a920fa5e15a3b72267b94b84667f11a50c6dd1cb18d35e" }, - "@std/http@1.1.0": { - "integrity": "265cd9a589fea924c5bb0bbed8bebb4bb2fa19129f760bd014e78dbd7a365a51", + "@std/http@1.0.25": { + "integrity": "577b4252290af1097132812b339fffdd55fb0f4aeb98ff11bdbf67998aa17193", "dependencies": [ "jsr:@std/cli", "jsr:@std/encoding@^1.0.10", - "jsr:@std/fmt@^1.0.10", + "jsr:@std/fmt@^1.0.9", "jsr:@std/fs@^1.0.23", "jsr:@std/html", "jsr:@std/media-types", @@ -166,8 +146,8 @@ "jsr:@std/streams" ] }, - "@std/internal@1.0.13": { - "integrity": "2f9546691d4ac2d32859c82dff284aaeac980ddeca38430d07941e7e288725c0" + "@std/internal@1.0.12": { + "integrity": "972a634fd5bc34b242024402972cd5143eac68d8dffaca5eaa4dba30ce17b027" }, "@std/media-types@1.1.0": { "integrity": "c9d093f0c05c3512932b330e3cc1fe1d627b301db33a4c2c2185c02471d6eaa4" @@ -181,31 +161,25 @@ "@std/path@1.1.4": { "integrity": "1d2d43f39efb1b42f0b1882a25486647cb851481862dc7313390b2bb044314b5", "dependencies": [ - "jsr:@std/internal@^1.0.12" + "jsr:@std/internal" ] }, - "@std/streams@1.1.0": { - "integrity": "2f7024d841f343fd478afe0c958a3f0f068ef2a0d2bcc954f550f97ac1fa22e3" + "@std/streams@1.0.17": { + "integrity": "7859f3d9deed83cf4b41f19223d4a67661b3d3819e9fc117698f493bf5992140" }, - "@std/testing@1.0.18": { - "integrity": "d3152f57b11666bf6358d0e127c7e3488e91178b0c2d8fbf0793e1c53cd13cb1", + "@std/testing@1.0.17": { + "integrity": "87bdc2700fa98249d48a17cd72413352d3d3680dcfbdb64947fd0982d6bbf681", "dependencies": [ - "jsr:@std/assert", + "jsr:@std/assert@^1.0.17", + "jsr:@std/async", "jsr:@std/data-structures", - "jsr:@std/fs@^1.0.23", - "jsr:@std/internal@^1.0.13", + "jsr:@std/fs@^1.0.22", + "jsr:@std/internal", "jsr:@std/path@^1.1.4" ] } }, "npm": { - "@01edu/signal-router@0.2.3_@preact+signals@2.9.0__preact@10.29.2_preact@10.29.2": { - "integrity": "sha512-Eg2ORuigaA8i3vM+Lr4k0P7+A53vZ3mKb2wsVnbBslkItaebEFwPUDxXiz2zDCJYHd06wLdvd64r/VRQQw6XFw==", - "dependencies": [ - "@preact/signals", - "preact" - ] - }, "@babel/code-frame@7.29.0": { "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==", "dependencies": [ @@ -214,8 +188,8 @@ "picocolors" ] }, - "@babel/compat-data@7.29.3": { - "integrity": "sha512-LIVqM46zQWZhj17qA8wb4nW/ixr2y1Nw+r1etiAWgRM6U1IqP+LNhL1yg440jYZR72jCWcWbLWzIosH+uP1fqg==" + "@babel/compat-data@7.29.0": { + "integrity": "sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==" }, "@babel/core@7.29.0": { "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==", @@ -301,8 +275,8 @@ "@babel/types" ] }, - "@babel/parser@7.29.3": { - "integrity": "sha512-b3ctpQwp+PROvU/cttc4OYl4MzfJUWy6FZg+PMXfzmt/+39iHVF0sDfqay8TQM3JA2EUOyKcFZt75jWriQijsA==", + "@babel/parser@7.29.2": { + "integrity": "sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA==", "dependencies": [ "@babel/types" ], @@ -360,16 +334,16 @@ "@babel/helper-validator-identifier" ] }, - "@clickhouse/client-common@1.18.5": { - "integrity": "sha512-g9LwcS1dvkatKDsIjT1PwUHldsiYzwdKAB0nXfd9APLd+t4PrNJa+my+dXcqJdmcWyhWjKLP/2/ztBwgxp+sbQ==" + "@clickhouse/client-common@1.18.2": { + "integrity": "sha512-J0SG6q9V31ydxonglpj9xhNRsUxCsF71iEZ784yldqMYwsHixj/9xHFDgBDX3DuMiDx/kPDfXnf+pimp08wIBA==" }, - "@clickhouse/client@1.18.5": { - "integrity": "sha512-4FfoyMkFWhsdNMuXsoEL6l3c12svA63BBJBtDo9SrxRZ14RdmN6jLr/rF3f84BK8cFoxETZCSeKlsbk6NNYebw==", + "@clickhouse/client@1.18.2": { + "integrity": "sha512-fuquQswRSHWM6D079ZeuGqkMOsqtcUPL06UdTnowmoeeYjVrqisfVmvnw8pc3OeKS4kVb91oygb/MfLDiMs0TQ==", "dependencies": [ "@clickhouse/client-common" ] }, - "@deno/vite-plugin@2.0.2_vite@8.0.13": { + "@deno/vite-plugin@2.0.2_vite@8.0.3__@emnapi+core@1.9.1__@emnapi+runtime@1.9.1_@emnapi+core@1.9.1_@emnapi+runtime@1.9.1": { "integrity": "sha512-bzuKApn9Jr2x1jSrbuJEJzy++8LUwjFVOAopAbepcE3RgYzdcPEWd36PSp7P5dNMQlNnQlgtm3MeNbcKZ/Eh/Q==", "dependencies": [ "@deno/loader@npm:@jsr/deno__loader@0.5.0", @@ -377,21 +351,21 @@ "vite" ] }, - "@emnapi/core@1.10.0": { - "integrity": "sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==", + "@emnapi/core@1.9.1": { + "integrity": "sha512-mukuNALVsoix/w1BJwFzwXBN/dHeejQtuVzcDsfOEsdpCumXb/E9j8w11h5S54tT1xhifGfbbSm/ICrObRb3KA==", "dependencies": [ "@emnapi/wasi-threads", "tslib" ] }, - "@emnapi/runtime@1.10.0": { - "integrity": "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==", + "@emnapi/runtime@1.9.1": { + "integrity": "sha512-VYi5+ZVLhpgK4hQ0TAjiQiZ6ol0oe4mBx7mVv7IflsiEp0OWoVsp/+f9Vc1hOhE0TtkORVrI1GvzyreqpgWtkA==", "dependencies": [ "tslib" ] }, - "@emnapi/wasi-threads@1.2.1": { - "integrity": "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==", + "@emnapi/wasi-threads@1.2.0": { + "integrity": "sha512-N10dEJNSsUx41Z6pZsXU8FjPjpBEplgH24sfkmITrBED1/U2Esum9F3lfLrMjKHHjmi557zQn7kR9R+XWXu5Rg==", "dependencies": [ "tslib" ] @@ -431,12 +405,12 @@ "integrity": "sha512-St6yKggjFGhxS52IFLJWvkchRFbAKg2Xh8UxA4S1EGz7GJ2Ui+ssDDldj/w2c8vCxvl6qgR0HaYbKeFJNqujmA==", "tarball": "https://npm.jsr.io/~/11/@jsr/std__bytes/1.0.6.tgz" }, - "@jsr/std__json@1.1.0": { - "integrity": "sha512-a9Eylh7ox33tFn5RxhESnvI4akpefQP5Qn+ePz3Ih4IJ/EPA8p0SKq0aztRfN1sGDhfyWMPWwlUcwNxONt+Ncg==", + "@jsr/std__json@1.0.3": { + "integrity": "sha512-hxHx1j4Wd4une+SHlpsSchKIPwtmP4naETNaQYqqY2iBawZPkcR7oiZBFwKcdhzjUWqMw5wV6ryZSI4d4YNzbQ==", "dependencies": [ "@jsr/std__streams" ], - "tarball": "https://npm.jsr.io/~/11/@jsr/std__json/1.1.0.tgz" + "tarball": "https://npm.jsr.io/~/11/@jsr/std__json/1.0.3.tgz" }, "@jsr/std__jsonc@1.0.2": { "integrity": "sha512-Lva9lY0UPvvgmS8INUHU8Tqijq2SPfdlnSAvofOYUBiB6ALPxo0rTMznRlY5Wt30nMW+rhMTha1x5RGpMBKUoQ==", @@ -445,25 +419,25 @@ ], "tarball": "https://npm.jsr.io/~/11/@jsr/std__jsonc/1.0.2.tgz" }, - "@jsr/std__streams@1.1.0": { - "integrity": "sha512-0yP/bIRAgcpdIg1o/XSYnVmCs3a7rtfKfhPPiKo7GFEtvF2qngWKJ80u8xN+D8o3otsrf/Ta90XiNj5WZJfFgg==", + "@jsr/std__streams@1.0.17": { + "integrity": "sha512-LnPlWk20mDIV5/nqoUomAB8umOimfGEyWRApxLgekXFuqKGDsGpUAi58amieVU2XAGNclmUOtQOcQ/qOl3PNFg==", "dependencies": [ "@jsr/std__bytes" ], - "tarball": "https://npm.jsr.io/~/11/@jsr/std__streams/1.1.0.tgz" + "tarball": "https://npm.jsr.io/~/11/@jsr/std__streams/1.0.17.tgz" }, - "@napi-rs/wasm-runtime@1.1.4_@emnapi+core@1.10.0_@emnapi+runtime@1.10.0": { - "integrity": "sha512-3NQNNgA1YSlJb/kMH1ildASP9HW7/7kYnRI2szWJaofaS1hWmbGI4H+d3+22aGzXXN9IJ+n+GiFVcGipJP18ow==", + "@napi-rs/wasm-runtime@1.1.2_@emnapi+core@1.9.1_@emnapi+runtime@1.9.1": { + "integrity": "sha512-sNXv5oLJ7ob93xkZ1XnxisYhGYXfaG9f65/ZgYuAu3qt7b3NadcOEhLvx28hv31PgX8SZJRYrAIPQilQmFpLVw==", "dependencies": [ "@emnapi/core", "@emnapi/runtime", "@tybys/wasm-util" ] }, - "@oxc-project/types@0.130.0": { - "integrity": "sha512-ibD2usx9JRu7f5pu2tMKMI4cpA4NgXJQoYRP4pQ7Pxmn1l6k/53qWtQWZayhYy3X4QZkt90Ot+mJEaeXouio6Q==" + "@oxc-project/types@0.122.0": { + "integrity": "sha512-oLAl5kBpV4w69UtFZ9xqcmTi+GENWOcPF7FCrczTiBbmC0ibXxCwyvZGbO39rCVEuLGAZM84DH0pUIyyv/YJzA==" }, - "@preact/preset-vite@2.10.5_vite@8.0.13_preact@10.29.2": { + "@preact/preset-vite@2.10.5_@babel+core@7.29.0_vite@8.0.3__@emnapi+core@1.9.1__@emnapi+runtime@1.9.1_@emnapi+core@1.9.1_@emnapi+runtime@1.9.1_preact@10.29.0": { "integrity": "sha512-p0vJpxiVO7KWWazWny3LUZ+saXyZKWv6Ju0bYMWNJRp2YveufRPgSUB1C4MTqGJfz07EehMgfN+AJNwQy+w6Iw==", "dependencies": [ "@babel/core", @@ -480,10 +454,10 @@ "zimmerframe" ] }, - "@preact/signals-core@1.14.2": { - "integrity": "sha512-RZHdBj9ZF4n40Rp4jS052EHHjBWf96P9oNdXPfhQTovCuWY9iQn3Gq+gOTJSgBO9A/JBuPfMOWsSX/lIU9Pc/A==" + "@preact/signals-core@1.14.1": { + "integrity": "sha512-vxPpfXqrwUe9lpjqfYNjAF/0RF/eFGeLgdJzdmIIZjpOnTmGmAB4BjWone562mJGMRP4frU6iZ6ei3PDsu52Ng==" }, - "@preact/signals@2.9.0_preact@10.29.2": { + "@preact/signals@2.9.0_preact@10.29.0": { "integrity": "sha512-hYrY0KyUqkDgOl1qba/JGn6y81pXnurn21PMaxfcMwdncdZ3M/oVdmpTvEnsGjh48dIwDVc7bjWHqIsngSjYug==", "dependencies": [ "@preact/signals-core", @@ -493,8 +467,8 @@ "@prefresh/babel-plugin@0.5.3": { "integrity": "sha512-57LX2SHs4BX2s1IwCjNzTE2OJeEepRCNf1VTEpbNcUyHfMO68eeOWGDIt4ob9aYlW6PEWZ1SuwNikuoIXANDtQ==" }, - "@prefresh/core@1.5.10_preact@10.29.2": { - "integrity": "sha512-7yPTFbG56sutaFu8krp3B4a200KOFUvrtlllKWRuLjsYXo9UUucHOZRcer+gtgMkFTpv6ob8TGcTwA32bSwa1w==", + "@prefresh/core@1.5.9_preact@10.29.0": { + "integrity": "sha512-IKBKCPaz34OFVC+adiQ2qaTF5qdztO2/4ZPf4KsRTgjKosWqxVXmEbxCiUydYZRY8GVie+DQlKzQr9gt6HQ+EQ==", "dependencies": [ "preact" ] @@ -502,7 +476,7 @@ "@prefresh/utils@1.2.1": { "integrity": "sha512-vq/sIuN5nYfYzvyayXI4C2QkprfNaHUQ9ZX+3xLD8nL3rWyzpxOm1+K7RtMbhd+66QcaISViK7amjnheQ/4WZw==" }, - "@prefresh/vite@2.4.12_preact@10.29.2_vite@8.0.13": { + "@prefresh/vite@2.4.12_preact@10.29.0_vite@8.0.3__@emnapi+core@1.9.1__@emnapi+runtime@1.9.1_@emnapi+core@1.9.1_@emnapi+runtime@1.9.1": { "integrity": "sha512-FY1fzXpUjiuosznMV0YM7XAOPZjB5FIdWS0W24+XnlxYkt9hNAwwsiKYn+cuTEoMtD/ZVazS5QVssBr9YhpCQA==", "dependencies": [ "@babel/core", @@ -514,87 +488,85 @@ "vite" ] }, - "@rolldown/binding-android-arm64@1.0.1": { - "integrity": "sha512-fJI3I0r3C3Oj/zdBCpaCmBRZYf07xpaq4yCfDDoSFm+beWNzbIl26puW8RraUdugoJw/95zerNOn6jasAhzSmg==", + "@rolldown/binding-android-arm64@1.0.0-rc.12": { + "integrity": "sha512-pv1y2Fv0JybcykuiiD3qBOBdz6RteYojRFY1d+b95WVuzx211CRh+ytI/+9iVyWQ6koTh5dawe4S/yRfOFjgaA==", "os": ["android"], "cpu": ["arm64"] }, - "@rolldown/binding-darwin-arm64@1.0.1": { - "integrity": "sha512-cKnAhWEsV7TPcA/5EAteDp6KcJZBQ2G+BqE7zayMMi7kMvwRsbv7WT9aOnn0WNl4SKEIf43vjS31iUPu80nzXg==", + "@rolldown/binding-darwin-arm64@1.0.0-rc.12": { + "integrity": "sha512-cFYr6zTG/3PXXF3pUO+umXxt1wkRK/0AYT8lDwuqvRC+LuKYWSAQAQZjCWDQpAH172ZV6ieYrNnFzVVcnSflAg==", "os": ["darwin"], "cpu": ["arm64"] }, - "@rolldown/binding-darwin-x64@1.0.1": { - "integrity": "sha512-YKrVwQjIRBPo+5G/u03wGjbdy4q7pyzCe93DK9VJ7zkVmeg8LJ7GbgsiHWdR4xSoe4CAXRD7Bcjgbtr64bkXNg==", + "@rolldown/binding-darwin-x64@1.0.0-rc.12": { + "integrity": "sha512-ZCsYknnHzeXYps0lGBz8JrF37GpE9bFVefrlmDrAQhOEi4IOIlcoU1+FwHEtyXGx2VkYAvhu7dyBf75EJQffBw==", "os": ["darwin"], "cpu": ["x64"] }, - "@rolldown/binding-freebsd-x64@1.0.1": { - "integrity": "sha512-z/oBsREo46SsFqBwYtFe0kpJeBijAT48O/WXLI4suiCLBkr03RTtTJMCzSdDd2znlh8VJizL09XVkQgk8IZonw==", + "@rolldown/binding-freebsd-x64@1.0.0-rc.12": { + "integrity": "sha512-dMLeprcVsyJsKolRXyoTH3NL6qtsT0Y2xeuEA8WQJquWFXkEC4bcu1rLZZSnZRMtAqwtrF/Ib9Ddtpa/Gkge9Q==", "os": ["freebsd"], "cpu": ["x64"] }, - "@rolldown/binding-linux-arm-gnueabihf@1.0.1": { - "integrity": "sha512-ik8q7GM11zxvYxFc2PeDcT6TBvhCQMaUxfph/M5l9sKuTs/Sjg3L+Byw0F7w0ZVLBZmx30P+gG0ECzzN+MFcmQ==", + "@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.12": { + "integrity": "sha512-YqWjAgGC/9M1lz3GR1r1rP79nMgo3mQiiA+Hfo+pvKFK1fAJ1bCi0ZQVh8noOqNacuY1qIcfyVfP6HoyBRZ85Q==", "os": ["linux"], "cpu": ["arm"] }, - "@rolldown/binding-linux-arm64-gnu@1.0.1": { - "integrity": "sha512-QoSx2EkyrrdZ6kcyE8stqZ62t0Yra8Fs5ia9lOxJrh6TMQJK7gQKmscdTHf7pOXKREKrVwOtJcQG3qVSfc866A==", + "@rolldown/binding-linux-arm64-gnu@1.0.0-rc.12": { + "integrity": "sha512-/I5AS4cIroLpslsmzXfwbe5OmWvSsrFuEw3mwvbQ1kDxJ822hFHIx+vsN/TAzNVyepI/j/GSzrtCIwQPeKCLIg==", "os": ["linux"], "cpu": ["arm64"] }, - "@rolldown/binding-linux-arm64-musl@1.0.1": { - "integrity": "sha512-uwNwFpwKeNiZawfAWBgg0VIztPTV3ihhh1vV334h9ivnNLorxnQMU6Fz8wG1Zb4Qh9LC1/MkcyT3YlDXG3Rsgg==", + "@rolldown/binding-linux-arm64-musl@1.0.0-rc.12": { + "integrity": "sha512-V6/wZztnBqlx5hJQqNWwFdxIKN0m38p8Jas+VoSfgH54HSj9tKTt1dZvG6JRHcjh6D7TvrJPWFGaY9UBVOaWPw==", "os": ["linux"], "cpu": ["arm64"] }, - "@rolldown/binding-linux-ppc64-gnu@1.0.1": { - "integrity": "sha512-zY1bul7OWr7DFBiJ++wofXvnr8B45ce3QsQUhKrIhXsygAh7bTkwyeM1bi1a2g5C/yC/N8TZyGDEoMfm/l9mpg==", + "@rolldown/binding-linux-ppc64-gnu@1.0.0-rc.12": { + "integrity": "sha512-AP3E9BpcUYliZCxa3w5Kwj9OtEVDYK6sVoUzy4vTOJsjPOgdaJZKFmN4oOlX0Wp0RPV2ETfmIra9x1xuayFB7g==", "os": ["linux"], "cpu": ["ppc64"] }, - "@rolldown/binding-linux-s390x-gnu@1.0.1": { - "integrity": "sha512-0frlsT/f4Ft6I7SMESTKnF3cZsdicQn1dCMkF/jT9wDLE+gGoiQfv1nmT9e+s7s/fekvvy6tZM2jHvI2tkbJDQ==", + "@rolldown/binding-linux-s390x-gnu@1.0.0-rc.12": { + "integrity": "sha512-nWwpvUSPkoFmZo0kQazZYOrT7J5DGOJ/+QHHzjvNlooDZED8oH82Yg67HvehPPLAg5fUff7TfWFHQS8IV1n3og==", "os": ["linux"], "cpu": ["s390x"] }, - "@rolldown/binding-linux-x64-gnu@1.0.1": { - "integrity": "sha512-XABVmGp9Tg0WspTVvwduTc4fpqy6JnAUrSQe6OuyqD/03nI7r0O9OWUkMIwFrjKAIqolvqoA4ZrJppgwE0Gxmw==", + "@rolldown/binding-linux-x64-gnu@1.0.0-rc.12": { + "integrity": "sha512-RNrafz5bcwRy+O9e6P8Z/OCAJW/A+qtBczIqVYwTs14pf4iV1/+eKEjdOUta93q2TsT/FI0XYDP3TCky38LMAg==", "os": ["linux"], "cpu": ["x64"] }, - "@rolldown/binding-linux-x64-musl@1.0.1": { - "integrity": "sha512-bV4fzswuzVcKD90o/VM6QqKxnxlDq0g2BISDLNVmxrnhpv1DDbyPhCIjYfvzYLV+MvkKKnQt2Q6AO86SEBULUQ==", + "@rolldown/binding-linux-x64-musl@1.0.0-rc.12": { + "integrity": "sha512-Jpw/0iwoKWx3LJ2rc1yjFrj+T7iHZn2JDg1Yny1ma0luviFS4mhAIcd1LFNxK3EYu3DHWCps0ydXQ5i/rrJ2ig==", "os": ["linux"], "cpu": ["x64"] }, - "@rolldown/binding-openharmony-arm64@1.0.1": { - "integrity": "sha512-/Mh0Zhq3OP7fVs0kcQHZP6lZEthMGTaSf8UBQYSFEZDWGXXlEC+nJ6EqenaK2t4LBXMe3A+K/G2BVXXdtOr4PQ==", + "@rolldown/binding-openharmony-arm64@1.0.0-rc.12": { + "integrity": "sha512-vRugONE4yMfVn0+7lUKdKvN4D5YusEiPilaoO2sgUWpCvrncvWgPMzK00ZFFJuiPgLwgFNP5eSiUlv2tfc+lpA==", "os": ["openharmony"], "cpu": ["arm64"] }, - "@rolldown/binding-wasm32-wasi@1.0.1": { - "integrity": "sha512-+1xc9X45l8ufsBAm6Gjvx2qDRIY9lTVt0cgWNcJ+1gdhXvkbxePA60yRTwSTuXL09CMhyJmjpV7E3NoyxbqFQQ==", + "@rolldown/binding-wasm32-wasi@1.0.0-rc.12_@emnapi+core@1.9.1_@emnapi+runtime@1.9.1": { + "integrity": "sha512-ykGiLr/6kkiHc0XnBfmFJuCjr5ZYKKofkx+chJWDjitX+KsJuAmrzWhwyOMSHzPhzOHOy7u9HlFoa5MoAOJ/Zg==", "dependencies": [ - "@emnapi/core", - "@emnapi/runtime", "@napi-rs/wasm-runtime" ], "cpu": ["wasm32"] }, - "@rolldown/binding-win32-arm64-msvc@1.0.1": { - "integrity": "sha512-1D+UqZdfnuR+Jy1GgMJwi85bD40H21uNmOPRWQhw4oRSuolZ/B5rixZ45DK2KXOTCvmVCecauWgEhbw8bI7tOw==", + "@rolldown/binding-win32-arm64-msvc@1.0.0-rc.12": { + "integrity": "sha512-5eOND4duWkwx1AzCxadcOrNeighiLwMInEADT0YM7xeEOOFcovWZCq8dadXgcRHSf3Ulh1kFo/qvzoFiCLOL1Q==", "os": ["win32"], "cpu": ["arm64"] }, - "@rolldown/binding-win32-x64-msvc@1.0.1": { - "integrity": "sha512-INAycaWuhlOK3wk4mRHGsdgwYWmd9cChdPdE9bwWmy6rn9VqVNYNFGhOdXrofXUxwHIncSiPNb8tNm8knDVIeQ==", + "@rolldown/binding-win32-x64-msvc@1.0.0-rc.12": { + "integrity": "sha512-PyqoipaswDLAZtot351MLhrlrh6lcZPo2LSYE+VDxbVk24LVKAGOuE4hb8xZQmrPAuEtTZW8E6D2zc5EUZX4Lw==", "os": ["win32"], "cpu": ["x64"] }, - "@rolldown/pluginutils@1.0.1": { - "integrity": "sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==" + "@rolldown/pluginutils@1.0.0-rc.12": { + "integrity": "sha512-HHMwmarRKvoFsJorqYlFeFRzXZqCt2ETQlEDOb9aqssrnVBB1/+xgTGtuTrIk5vzLNX1MjMtTf7W9z3tsSbrxw==" }, "@rollup/pluginutils@4.2.1": { "integrity": "sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ==", @@ -611,8 +583,8 @@ "picomatch@4.0.4" ] }, - "@tailwindcss/node@4.3.0": { - "integrity": "sha512-aFb4gUhFOgdh9AXo4IzBEOzBkkAxm9VigwDJnMIYv3lcfXCJVesNfbEaBl4BNgVRyid92AmdviqwBUBRKSeY3g==", + "@tailwindcss/node@4.2.2": { + "integrity": "sha512-pXS+wJ2gZpVXqFaUEjojq7jzMpTGf8rU6ipJz5ovJV6PUGmlJ+jvIwGrzdHdQ80Sg+wmQxUFuoW1UAAwHNEdFA==", "dependencies": [ "@jridgewell/remapping", "enhanced-resolve", @@ -623,67 +595,67 @@ "tailwindcss" ] }, - "@tailwindcss/oxide-android-arm64@4.3.0": { - "integrity": "sha512-TJPiq67tKlLuObP6RkwvVGDoxCMBVtDgKkLfa/uyj7/FyxvQwHS+UOnVrXXgbEsfUaMgiVvC4KbJnRr26ho4Ng==", + "@tailwindcss/oxide-android-arm64@4.2.2": { + "integrity": "sha512-dXGR1n+P3B6748jZO/SvHZq7qBOqqzQ+yFrXpoOWWALWndF9MoSKAT3Q0fYgAzYzGhxNYOoysRvYlpixRBBoDg==", "os": ["android"], "cpu": ["arm64"] }, - "@tailwindcss/oxide-darwin-arm64@4.3.0": { - "integrity": "sha512-oMN/WZRb+SO37BmUElEgeEWuU8E/HXRkiODxJxLe1UTHVXLrdVSgfaJV7pSlhRGMSOiXLuxTIjfsF3wYvz8cgQ==", + "@tailwindcss/oxide-darwin-arm64@4.2.2": { + "integrity": "sha512-iq9Qjr6knfMpZHj55/37ouZeykwbDqF21gPFtfnhCCKGDcPI/21FKC9XdMO/XyBM7qKORx6UIhGgg6jLl7BZlg==", "os": ["darwin"], "cpu": ["arm64"] }, - "@tailwindcss/oxide-darwin-x64@4.3.0": { - "integrity": "sha512-N6CUmu4a6bKVADfw77p+iw6Yd9Q3OBhe0veaDX+QazfuVYlQsHfDgxBrsjQ/IW+zywL8mTrNd0SdJT/zgtvMdA==", + "@tailwindcss/oxide-darwin-x64@4.2.2": { + "integrity": "sha512-BlR+2c3nzc8f2G639LpL89YY4bdcIdUmiOOkv2GQv4/4M0vJlpXEa0JXNHhCHU7VWOKWT/CjqHdTP8aUuDJkuw==", "os": ["darwin"], "cpu": ["x64"] }, - "@tailwindcss/oxide-freebsd-x64@4.3.0": { - "integrity": "sha512-zDL5hBkQdH5C6MpqbK3gQAgP80tsMwSI26vjOzjJtNCMUo0lFgOItzHKBIupOZNQxt3ouPH7RPhvNhiTfCe5CQ==", + "@tailwindcss/oxide-freebsd-x64@4.2.2": { + "integrity": "sha512-YUqUgrGMSu2CDO82hzlQ5qSb5xmx3RUrke/QgnoEx7KvmRJHQuZHZmZTLSuuHwFf0DJPybFMXMYf+WJdxHy/nQ==", "os": ["freebsd"], "cpu": ["x64"] }, - "@tailwindcss/oxide-linux-arm-gnueabihf@4.3.0": { - "integrity": "sha512-R06HdNi7A7OEoMsf6d4tjZ71RCWnZQPHj2mnotSFURjNLdBC+cIgXQ7l81CqeoiQftjf6OOblxXMInMgN2VzMA==", + "@tailwindcss/oxide-linux-arm-gnueabihf@4.2.2": { + "integrity": "sha512-FPdhvsW6g06T9BWT0qTwiVZYE2WIFo2dY5aCSpjG/S/u1tby+wXoslXS0kl3/KXnULlLr1E3NPRRw0g7t2kgaQ==", "os": ["linux"], "cpu": ["arm"] }, - "@tailwindcss/oxide-linux-arm64-gnu@4.3.0": { - "integrity": "sha512-qTJHELX8jetjhRQHCLilkVLmybpzNQAtaI/gaoVoidn/ufbNDbAo8KlK2J+yPoc8wQxvDxCmh/5lr8nC1+lTbg==", + "@tailwindcss/oxide-linux-arm64-gnu@4.2.2": { + "integrity": "sha512-4og1V+ftEPXGttOO7eCmW7VICmzzJWgMx+QXAJRAhjrSjumCwWqMfkDrNu1LXEQzNAwz28NCUpucgQPrR4S2yw==", "os": ["linux"], "cpu": ["arm64"] }, - "@tailwindcss/oxide-linux-arm64-musl@4.3.0": { - "integrity": "sha512-Z6sukiQsngnWO+l39X4pPbiWT81IC+PLKF+PHxIlyZbGNb9MODfYlXEVlFvej5BOZInWX01kVyzeLvHsXhfczQ==", + "@tailwindcss/oxide-linux-arm64-musl@4.2.2": { + "integrity": "sha512-oCfG/mS+/+XRlwNjnsNLVwnMWYH7tn/kYPsNPh+JSOMlnt93mYNCKHYzylRhI51X+TbR+ufNhhKKzm6QkqX8ag==", "os": ["linux"], "cpu": ["arm64"] }, - "@tailwindcss/oxide-linux-x64-gnu@4.3.0": { - "integrity": "sha512-DRNdQRpSGzRGfARVuVkxvM8Q12nh19l4BF/G7zGA1oe+9wcC6saFBHTISrpIcKzhiXtSrlSrluCfvMuledoCTQ==", + "@tailwindcss/oxide-linux-x64-gnu@4.2.2": { + "integrity": "sha512-rTAGAkDgqbXHNp/xW0iugLVmX62wOp2PoE39BTCGKjv3Iocf6AFbRP/wZT/kuCxC9QBh9Pu8XPkv/zCZB2mcMg==", "os": ["linux"], "cpu": ["x64"] }, - "@tailwindcss/oxide-linux-x64-musl@4.3.0": { - "integrity": "sha512-Z0IADbDo8bh6I7h2IQMx601AdXBLfFpEdUotft86evd/8ZPflZe9COPO8Q1vw+pfLWIUo9zN/JGZvwuAJqduqg==", + "@tailwindcss/oxide-linux-x64-musl@4.2.2": { + "integrity": "sha512-XW3t3qwbIwiSyRCggeO2zxe3KWaEbM0/kW9e8+0XpBgyKU4ATYzcVSMKteZJ1iukJ3HgHBjbg9P5YPRCVUxlnQ==", "os": ["linux"], "cpu": ["x64"] }, - "@tailwindcss/oxide-wasm32-wasi@4.3.0": { - "integrity": "sha512-HNZGOUxEmElksYR7S6sC5jTeNGpobAsy9u7Gu0AskJ8/20FR9GqebUyB+HBcU/ax6BHuiuJi+Oda4B+YX6H1yA==", + "@tailwindcss/oxide-wasm32-wasi@4.2.2": { + "integrity": "sha512-eKSztKsmEsn1O5lJ4ZAfyn41NfG7vzCg496YiGtMDV86jz1q/irhms5O0VrY6ZwTUkFy/EKG3RfWgxSI3VbZ8Q==", "cpu": ["wasm32"] }, - "@tailwindcss/oxide-win32-arm64-msvc@4.3.0": { - "integrity": "sha512-Pe+RPVTi1T+qymuuRpcdvwSVZjnll/f7n8gBxMMh3xLTctMDKqpdfGimbMyioqtLhUYZxdJ9wGNhV7MKHvgZsQ==", + "@tailwindcss/oxide-win32-arm64-msvc@4.2.2": { + "integrity": "sha512-qPmaQM4iKu5mxpsrWZMOZRgZv1tOZpUm+zdhhQP0VhJfyGGO3aUKdbh3gDZc/dPLQwW4eSqWGrrcWNBZWUWaXQ==", "os": ["win32"], "cpu": ["arm64"] }, - "@tailwindcss/oxide-win32-x64-msvc@4.3.0": { - "integrity": "sha512-Mvrf2kXW/yeW/OTezZlCGOirXRcUuLIBx/5Y12BaPM7wJoryG6dfS/NJL8aBPqtTEx/Vm4T4vKzFUcKDT+TKUA==", + "@tailwindcss/oxide-win32-x64-msvc@4.2.2": { + "integrity": "sha512-1T/37VvI7WyH66b+vqHj/cLwnCxt7Qt3WFu5Q8hk65aOvlwAhs7rAp1VkulBJw/N4tMirXjVnylTR72uI0HGcA==", "os": ["win32"], "cpu": ["x64"] }, - "@tailwindcss/oxide@4.3.0": { - "integrity": "sha512-F7HZGBeN9I0/AuuJS5PwcD8xayx5ri5GhjYUDBEVYUkexyA/giwbDNjRVrxSezE3T250OU2K/wp/ltWx3UOefg==", + "@tailwindcss/oxide@4.2.2": { + "integrity": "sha512-qEUA07+E5kehxYp9BVMpq9E8vnJuBHfJEC0vPC5e7iL/hw7HR61aDKoVoKzrG+QKp56vhNZe4qwkRmMC0zDLvg==", "optionalDependencies": [ "@tailwindcss/oxide-android-arm64", "@tailwindcss/oxide-darwin-arm64", @@ -699,8 +671,8 @@ "@tailwindcss/oxide-win32-x64-msvc" ] }, - "@tailwindcss/vite@4.3.0_vite@8.0.13": { - "integrity": "sha512-t6J3OrB5Fc0ExuhohouH0fWUGMYL6PTLhW+E7zIk/pdbnJARZDCwjBznFnkh5ynRnIRSI4YjtTH0t6USjJISrw==", + "@tailwindcss/vite@4.2.2_vite@8.0.3__@emnapi+core@1.9.1__@emnapi+runtime@1.9.1_@emnapi+core@1.9.1_@emnapi+runtime@1.9.1": { + "integrity": "sha512-mEiF5HO1QqCLXoNEfXVA1Tzo+cYsrqV7w9Juj2wdUFyW07JRenqMG225MvPwr3ZD9N1bFQj46X7r33iHxLUW0w==", "dependencies": [ "@tailwindcss/node", "@tailwindcss/oxide", @@ -708,14 +680,14 @@ "vite" ] }, - "@tybys/wasm-util@0.10.2": { - "integrity": "sha512-RoBvJ2X0wuKlWFIjrwffGw1IqZHKQqzIchKaadZZfnNpsAYp2mM0h36JtPCjNDAHGgYez/15uMBpfGwchhiMgg==", + "@tybys/wasm-util@0.10.1": { + "integrity": "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==", "dependencies": [ "tslib" ] }, - "@types/estree@1.0.9": { - "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==" + "@types/estree@1.0.8": { + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==" }, "babel-plugin-transform-hook-names@1.0.2_@babel+core@7.29.0": { "integrity": "sha512-5gafyjyyBTTdX/tQQ0hRgu4AhNHG/hqWi0ZZmg2xvs2FgRkJXzDNKBZCyoYqgFkovfDrgM8OoKg8karoUvWeCw==", @@ -723,8 +695,8 @@ "@babel/core" ] }, - "baseline-browser-mapping@2.10.29": { - "integrity": "sha512-Asa2krT+XTPZINCS+2QcyS8WTkObE77RwkydwF7h6DmnKqbvlalz93m/dnphUyCa6SWSP51VgtEUf2FN+gelFQ==", + "baseline-browser-mapping@2.10.13": { + "integrity": "sha512-BL2sTuHOdy0YT1lYieUxTw/QMtPBC3pmlJC6xk8BBYVv6vcw3SGdKemQ+Xsx9ik2F/lYDO9tqsFQH1r9PFuHKw==", "bin": true }, "boolbase@1.0.0": { @@ -741,11 +713,8 @@ ], "bin": true }, - "caniuse-lite@1.0.30001792": { - "integrity": "sha512-hVLMUZFgR4JJ6ACt1uEESvQN1/dBVqPAKY0hgrV70eN3391K6juAfTjKZLKvOMsx8PxA7gsY1/tLMMTcfFLLpw==" - }, - "commander@8.3.0": { - "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==" + "caniuse-lite@1.0.30001784": { + "integrity": "sha512-WU346nBTklUV9YfUl60fqRbU5ZqyXlqvo1SgigE1OAXK5bFL8LL9q1K7aap3N739l4BvNqnkm3YrGHiY9sfUQw==" }, "convert-source-map@2.0.0": { "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==" @@ -766,18 +735,12 @@ "daisyui@5.5.19": { "integrity": "sha512-pbFAkl1VCEh/MPCeclKL61I/MqRIFFhNU7yiXoDDRapXN4/qNCoMxeCCswyxEEhqL5eiTTfwHvucFtOE71C9sA==" }, - "dayjs@1.11.20": { - "integrity": "sha512-YbwwqR/uYpeoP4pu043q+LTDLFBLApUP6VxRihdfNTqu4ubqMlGDLd6ErXhEgsyvY0K6nCs7nggYumAN+9uEuQ==" - }, "debug@4.4.3": { "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "dependencies": [ "ms" ] }, - "deepmerge@4.3.1": { - "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==" - }, "detect-libc@2.1.2": { "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==" }, @@ -786,7 +749,7 @@ "dependencies": [ "domelementtype", "domhandler", - "entities@4.5.0" + "entities" ] }, "domelementtype@2.3.0": { @@ -806,11 +769,11 @@ "domhandler" ] }, - "electron-to-chromium@1.5.355": { - "integrity": "sha512-LUPZhKzZPYSPme1jEYohpkA+ybYCJztr1quAdBd7E7h3+VOBVcKkwwtBJu41nrjawrRzfb8mtMfzWozoaK0ZIQ==" + "electron-to-chromium@1.5.330": { + "integrity": "sha512-jFNydB5kFtYUobh4IkWUnXeyDbjf/r9gcUEXe1xcrcUxIGfTdzPXA+ld6zBRbwvgIGVzDll/LTIiDztEtckSnA==" }, - "enhanced-resolve@5.21.3": { - "integrity": "sha512-QyL119InA+XXEkNLNTPCXPugSvOfhwv0JOlGNzvxs0hZaiHLNvXSpudUWsOlsXGWJh8G6ckCScEkVHfX3kw/2Q==", + "enhanced-resolve@5.20.1": { + "integrity": "sha512-Qohcme7V1inbAfvjItgw0EaxVX5q2rdVEZHRBrEQdRZTssLDGsL8Lwrznl8oQ/6kuTJONLaDcGjkNP247XEhcA==", "dependencies": [ "graceful-fs", "tapable" @@ -819,15 +782,9 @@ "entities@4.5.0": { "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==" }, - "entities@7.0.1": { - "integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==" - }, "escalade@3.2.0": { "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==" }, - "escape-string-regexp@4.0.0": { - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==" - }, "estree-walker@2.0.2": { "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==" }, @@ -848,9 +805,6 @@ "gensync@1.0.0-beta.2": { "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==" }, - "github-slugger@2.0.0": { - "integrity": "sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw==" - }, "graceful-fs@4.2.11": { "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" }, @@ -858,20 +812,8 @@ "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", "bin": true }, - "htmlparser2@10.1.0": { - "integrity": "sha512-VTZkM9GWRAtEpveh7MSF6SjjrpNVNNVJfFup7xTY3UpFtm67foy9HDVXneLtFVt4pMz5kZtgNcvCniNFb1hlEQ==", - "dependencies": [ - "domelementtype", - "domhandler", - "domutils", - "entities@7.0.1" - ] - }, - "is-plain-object@5.0.0": { - "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==" - }, - "jiti@2.7.0": { - "integrity": "sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==", + "jiti@2.6.1": { + "integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==", "bin": true }, "js-tokens@4.0.0": { @@ -885,22 +827,9 @@ "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", "bin": true }, - "katex@0.16.46": { - "integrity": "sha512-WHy4Coo+bGZyH7NwJKHkS04YFsFcarWbAEOAC3EMndzdN6VSZqklLLIgfxzyaW9jDoeGYJX9SWbJPKpecox0Uw==", - "dependencies": [ - "commander" - ], - "bin": true - }, "kolorist@1.8.0": { "integrity": "sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==" }, - "launder@1.7.1": { - "integrity": "sha512-mU6WRz5EusL9ZZuiZ5SO4Y6C0P9PAUR9iwdb6bzj4KDihm28DiHFw+/yk9DBH4f+Pv1wuzQ4e2jV3oQ7mkIqvw==", - "dependencies": [ - "dayjs" - ] - }, "lightningcss-android-arm64@1.32.0": { "integrity": "sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==", "os": ["android"], @@ -981,8 +910,8 @@ "yallist" ] }, - "lucide-preact@1.16.0_preact@10.29.2": { - "integrity": "sha512-Sa1XSig6iWCFhdrqS+vT1EFJH4Yos2Q7H/EMawql1K+D9qjNRzjMutPySak0iMYto6PneHYAWoxnDBBlryjngw==", + "lucide-preact@1.7.0_preact@10.29.0": { + "integrity": "sha512-gv743hfkCH2MeUmZQ9g4+Yd+/zZyAOLuXvxWo6CUY6kMrnnoDZnnwpSZqWsEveCC9LNp+NgHkeTfztObIue+SA==", "dependencies": [ "preact" ] @@ -993,34 +922,11 @@ "@jridgewell/sourcemap-codec" ] }, - "marked-alert@2.1.2_marked@17.0.6": { - "integrity": "sha512-EFNRZ08d8L/iEIPLTlQMDjvwIsj03gxWCczYTht6DCiHJIZhMk4NK5gtPY9UqAYb09eV5VGT+jD4lp396E0I+w==", - "dependencies": [ - "marked" - ] - }, - "marked-footnote@1.4.0_marked@17.0.6": { - "integrity": "sha512-fZTxAhI1TcLEs5UOjCfYfTHpyKGaWQevbxaGTEA68B51l7i87SctPFtHETYqPkEN0ka5opvy4Dy1l/yXVC+hmg==", - "dependencies": [ - "marked" - ] - }, - "marked-gfm-heading-id@4.1.4_marked@17.0.6": { - "integrity": "sha512-CspnvVfHSkb/znqdPS4jUR8HtCjq3M/DnrsJCrfLBLvdrgbemmoINKpeWKQYkBiXAoBGejw0cV7xzqrPdup3WA==", - "dependencies": [ - "github-slugger", - "marked" - ] - }, - "marked@17.0.6": { - "integrity": "sha512-gB0gkNafnonOw0obSTEGZTT86IuhILt2Wfx0mWH/1Au83kybTayroZ/V6nS25mN7u8ASy+5fMhgB3XPNrOZdmA==", - "bin": true - }, "ms@2.1.3": { "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, - "nanoid@3.3.12": { - "integrity": "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==", + "nanoid@3.3.11": { + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", "bin": true }, "node-html-parser@6.1.13": { @@ -1030,8 +936,8 @@ "he" ] }, - "node-releases@2.0.44": { - "integrity": "sha512-5WUyunoPMsvvEhS8AxHtRzP+oA8UCkJ7YRxatWKjngndhDGLiqEVAQKWjFAiAiuL8zMRGzGSJxFnLetoa43qGQ==" + "node-releases@2.0.36": { + "integrity": "sha512-TdC8FSgHz8Mwtw9g5L4gR/Sh9XhSP/0DEkQxfEFXOpiul5IiHgHan2VhYYb6agDSfp4KuvltmGApc8HMgUrIkA==" }, "nth-check@2.1.1": { "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", @@ -1039,9 +945,6 @@ "boolbase" ] }, - "parse-srcset@1.0.2": { - "integrity": "sha512-/2qh0lav6CmI15FzA3i/2Bzk2zCgQhGMkvhOhKNcBVQ1ldgpbfiNTVslmooUmWJcADi1f1kIeynbDRVzNlfR6Q==" - }, "picocolors@1.1.1": { "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==" }, @@ -1051,22 +954,19 @@ "picomatch@4.0.4": { "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==" }, - "postcss@8.5.14": { - "integrity": "sha512-SoSL4+OSEtR99LHFZQiJLkT59C5B1amGO1NzTwj7TT1qCUgUO6hxOvzkOYxD+vMrXBM3XJIKzokoERdqQq/Zmg==", + "postcss@8.5.8": { + "integrity": "sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg==", "dependencies": [ "nanoid", "picocolors", "source-map-js" ] }, - "preact@10.29.2": { - "integrity": "sha512-7tNmwg/7mzzAoB/8kSg6Hl37JraAZw3Z3A0JSY7VXlZwo82Xn0G7wKbNNs2qoF4ZEEsQGTwDAroNdqKs1ofJxQ==" - }, - "prismjs@1.30.0": { - "integrity": "sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw==" + "preact@10.29.0": { + "integrity": "sha512-wSAGyk2bYR1c7t3SZ3jHcM6xy0lcBcDel6lODcs9ME6Th++Dx2KU+6D3HD8wMMKGA8Wpw7OMd3/4RGzYRpzwRg==" }, - "rolldown@1.0.1": { - "integrity": "sha512-X0KQHljNnEkWNqqiz9zJrGunh1B0HgOxLXvnFpCOcadzcy5qohZ3tqMEUg00vncoRovXuK3ZqCT9KnnKzoInFQ==", + "rolldown@1.0.0-rc.12_@emnapi+core@1.9.1_@emnapi+runtime@1.9.1": { + "integrity": "sha512-yP4USLIMYrwpPHEFB5JGH1uxhcslv6/hL0OyvTuY+3qlOSJvZ7ntYnoWpehBxufkgN0cvXxppuTu5hHa/zPh+A==", "dependencies": [ "@oxc-project/types", "@rolldown/pluginutils" @@ -1090,18 +990,6 @@ ], "bin": true }, - "sanitize-html@2.17.4": { - "integrity": "sha512-2HW7v2ol/uAM7sX4hbD8Z59OGWmAPrvjL8E71UWlBcj6m+kcF6ilQBLny+cIgY214QJeJT5tQuxKKqX0SQqjGQ==", - "dependencies": [ - "deepmerge", - "escape-string-regexp", - "htmlparser2", - "is-plain-object", - "launder", - "parse-srcset", - "postcss" - ] - }, "semver@6.3.1": { "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "bin": true @@ -1118,17 +1006,17 @@ "source-map@0.7.6": { "integrity": "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==" }, - "stack-trace@1.0.0": { - "integrity": "sha512-H6D7134xi6qONvh7ZHKgviXf+rd3vhGBSvebPZCaUkd8zvQ+7PtDw6CljPTe4cXWNf2IKZGNqw6VJXSb9IgBpA==" + "stack-trace@1.0.0-pre2": { + "integrity": "sha512-2ztBJRek8IVofG9DBJqdy2N5kulaacX30Nz7xmkYF6ale9WBVmIy6mFBchvGX7Vx/MyjBhx+Rcxqrj+dbOnQ6A==" }, - "tailwindcss@4.3.0": { - "integrity": "sha512-y6nxMGB1nMW9R6k96e5gdIFzcfL/gTJRNaqGes1YvkLnPVXzWgbqFF2yLC0T8G774n24cx3Pe8XrKoniCOAH+Q==" + "tailwindcss@4.2.2": { + "integrity": "sha512-KWBIxs1Xb6NoLdMVqhbhgwZf2PGBpPEiwOqgI4pFIYbNTfBXiKYyWoTsXgBQ9WFg/OlhnvHaY+AEpW7wSmFo2Q==" }, - "tapable@2.3.3": { - "integrity": "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==" + "tapable@2.3.2": { + "integrity": "sha512-1MOpMXuhGzGL5TTCZFItxCc0AARf1EZFQkGqMm7ERKj8+Hgr5oLvJOVFcC+lRmR8hCe2S3jC4T5D7Vg/d7/fhA==" }, - "tinyglobby@0.2.16": { - "integrity": "sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==", + "tinyglobby@0.2.15": { + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", "dependencies": [ "fdir", "picomatch@4.0.4" @@ -1146,7 +1034,7 @@ ], "bin": true }, - "vite-prerender-plugin@0.5.13_vite@8.0.13": { + "vite-prerender-plugin@0.5.13_vite@8.0.3__@emnapi+core@1.9.1__@emnapi+runtime@1.9.1_@emnapi+core@1.9.1_@emnapi+runtime@1.9.1": { "integrity": "sha512-IKSpYkzDBsKAxa05naRbj7GvNVMSdww/Z/E89oO3xndz+gWnOBOKOAbEXv7qDhktY/j3vHgJmoV1pPzqU2tx9g==", "dependencies": [ "kolorist", @@ -1158,8 +1046,8 @@ "vite" ] }, - "vite@8.0.13": { - "integrity": "sha512-MFtjBYgzmSxmgA4RAfjIyXWpGe1oALnjgUTzzV7QLx/TKxCzjtMH6Fd9/eVK+5Fg1qNoz5VAwsmMs/NofrmJvw==", + "vite@8.0.3_@emnapi+core@1.9.1_@emnapi+runtime@1.9.1": { + "integrity": "sha512-B9ifbFudT1TFhfltfaIPgjo9Z3mDynBTJSUYxTjOQruf/zHH+ezCQKcoqO+h7a9Pw9Nm/OtlXAiGT1axBgwqrQ==", "dependencies": [ "lightningcss", "picomatch@4.0.4", @@ -1179,35 +1067,31 @@ "integrity": "sha512-B58NGBEoc8Y9MWWCQGl/gq9xBCe4IiKM0a2x7GZdQKOW5Exr8S1W24J6OgM1njK8xCRGvAJIL/MxXHf6SkmQKQ==" } }, - "remote": { - "https://gistcdn.githack.com/kigiri/21df06d173fcdced5281b86ba6ac1382/raw/crypto.js": "e85976e655898538dbade9d87b05ca0a6bb167b3128cd4098622000a582f5f6d" - }, "workspace": { "dependencies": [ - "jsr:@01edu/api-client@~0.2.6", + "jsr:@01edu/api-client@~0.2.3", "jsr:@01edu/api-proxy@~0.2.1", - "jsr:@01edu/api@~0.2.7", + "jsr:@01edu/api@~0.2.3", + "jsr:@01edu/signal-router@~0.2.1", "jsr:@01edu/time@0.1", - "jsr:@deno/gfm@0.12.0", "jsr:@std/assert@^1.0.19", - "jsr:@std/crypto@^1.1.0", + "jsr:@std/crypto@^1.0.5", "jsr:@std/encoding@^1.0.10", - "jsr:@std/fmt@^1.0.10", + "jsr:@std/fmt@^1.0.9", "jsr:@std/fs@^1.0.23", - "jsr:@std/http@^1.1.0", + "jsr:@std/http@^1.0.25", "jsr:@std/path@^1.1.4", - "jsr:@std/testing@^1.0.18", - "npm:@01edu/signal-router@~0.2.3", - "npm:@clickhouse/client@^1.18.5", + "jsr:@std/testing@^1.0.17", + "npm:@clickhouse/client@^1.18.2", "npm:@deno/vite-plugin@^2.0.2", "npm:@preact/preset-vite@^2.10.5", "npm:@preact/signals@^2.9.0", - "npm:@tailwindcss/vite@^4.3.0", + "npm:@tailwindcss/vite@^4.2.2", "npm:daisyui@^5.5.19", - "npm:lucide-preact@^1.16.0", - "npm:preact@^10.29.2", - "npm:tailwindcss@^4.3.0", - "npm:vite@^8.0.13" + "npm:lucide-preact@^1.7.0", + "npm:preact@^10.29.0", + "npm:tailwindcss@^4.2.2", + "npm:vite@^8.0.3" ] } } diff --git a/tasks/clickhouse.ts b/tasks/clickhouse.ts deleted file mode 100644 index d147dde..0000000 --- a/tasks/clickhouse.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { client } from '/api/clickhouse-client.ts' - -if (import.meta.main) { - try { - await client.ping() - - await client.command({ - query: ` - CREATE TABLE IF NOT EXISTS logs ( - id UUID DEFAULT generateUUIDv4(), - -- Flattened resource fields - service_name LowCardinality(String), - service_version LowCardinality(String), - service_instance_id String, - - timestamp DateTime64(3, 'UTC') DEFAULT now64(3, 'UTC'), - observed_timestamp DateTime64(3, 'UTC') DEFAULT now64(3, 'UTC'), - trace_id FixedString(16), - span_id FixedString(16), - severity_number UInt8, - -- derived column, computed by DB from severity_number - severity_text LowCardinality(String) MATERIALIZED CASE - WHEN severity_number > 4 AND severity_number <= 8 THEN 'DEBUG' - WHEN severity_number > 8 AND severity_number <= 12 THEN 'INFO' - WHEN severity_number > 12 AND severity_number <= 16 THEN 'WARN' - WHEN severity_number > 20 AND severity_number <= 24 THEN 'FATAL' - ELSE 'ERROR' - END, - -- Often empty, but kept for OTEL spec compliance - body Nullable(String), - attributes JSON, - event_name LowCardinality(String) - ) - ENGINE = MergeTree - PARTITION BY toYYYYMMDD(timestamp) - ORDER BY (service_name, timestamp, trace_id) - SETTINGS index_granularity = 8192, min_bytes_for_wide_part = 0; - `, - }) - - console.log('logs table is ready') - } catch (error) { - console.error('Error creating ClickHouse table:', { error }) - Deno.exit(1) - } -} diff --git a/tasks/vite.ts b/tasks/vite.ts index 0fb51f7..1f6786d 100644 --- a/tasks/vite.ts +++ b/tasks/vite.ts @@ -1,6 +1,6 @@ // tasks/vite.js import { join } from 'node:path' -import { AliasOptions, build, createServer } from 'vite' +import { build, createServer } from 'vite' import { apiProxy } from '@01edu/api-proxy' import deno from '@deno/vite-plugin' import preact from '@preact/preset-vite' @@ -13,27 +13,27 @@ const plugins = [ deno(), ] -const alias: AliasOptions = [ +const BASE_URL = Deno.env.get('BASE_URL') || '/' +const preactRuntimeAlias = [ { - find: 'npm:@preact/signals@^2.5.1', - replacement: '@preact/signals', + find: /^npm:preact(?:@[^/]+)?\/jsx-runtime$/, + replacement: 'preact/jsx-runtime', }, { - find: 'npm:preact@^10.27.2', - replacement: 'preact', + find: /^npm:preact(?:@[^/]+)?\/jsx-dev-runtime$/, + replacement: 'preact/jsx-dev-runtime', }, ] + // Production build if (APP_ENV === 'prod') { await build({ configFile: false, root: join(import.meta.dirname!, '../web'), plugins, - resolve: { alias }, - build: { - outDir: '../dist/web', - emptyOutDir: true, - }, + base: BASE_URL, + resolve: { alias: preactRuntimeAlias }, + build: { outDir: '../dist/web', emptyOutDir: true }, }) Deno.exit(0) } @@ -43,12 +43,10 @@ const PORT = Number(Deno.env.get('PORT')) || 2119 const server = await createServer({ configFile: false, root: join(import.meta.dirname!, '../web'), + base: BASE_URL, plugins: [...plugins, apiProxy({ port: PORT, prefix: '/api/' })], - resolve: { alias }, - server: { - port: 7737, - host: true, - }, + resolve: { alias: preactRuntimeAlias }, + server: { port: 7737, host: true }, }) await server.listen() server.printUrls() diff --git a/web/components/BrandIcons.tsx b/web/components/BrandIcons.tsx deleted file mode 100644 index f8c410b..0000000 --- a/web/components/BrandIcons.tsx +++ /dev/null @@ -1,20 +0,0 @@ -import type { SVGAttributes } from 'preact' -// Copy path / name from: https://simpleicons.org/ - -type SVGProps = SVGAttributes -const Icon = (title: string, path: string) => (props: SVGProps) => ( - - {title} - - -) - -export const GitHub = Icon( - 'GibHub', - 'M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12', -) diff --git a/web/components/SideBar.tsx b/web/components/SideBar.tsx index ba853c7..2e85035 100644 --- a/web/components/SideBar.tsx +++ b/web/components/SideBar.tsx @@ -5,8 +5,8 @@ import { LucideIcon, Settings, } from 'lucide-preact' -import { user } from '../lib/session.ts' import { A, url } from '@01edu/signal-router' +import { sidebarItems } from '../lib/shared.tsx' export type SidebarItem = { label: string @@ -15,10 +15,10 @@ export type SidebarItem = { } export function Sidebar( - { sidebarItems, sbi, title }: { - sidebarItems: Record + { sbi, title, isAdmin }: { sbi?: string title?: string + isAdmin?: boolean }, ) { const sb = url.params.sb @@ -70,7 +70,7 @@ export function Sidebar( params={{ sbi: 'settings' }} replace class={`rounded p-2 w-full flex items-center gap-2 ${ - user.data?.isAdmin + isAdmin ? 'settings' === sbi ? 'bg-primary text-primary-content' : '' : 'opacity-50 pointer-events-none' }`} diff --git a/web/layout.tsx b/web/layout.tsx index 741a20c..33657c9 100644 --- a/web/layout.tsx +++ b/web/layout.tsx @@ -1,7 +1,6 @@ import { effect, signal } from '@preact/signals' import { A, url } from '@01edu/signal-router' import { Code, LogOut, Moon, Sun } from 'lucide-preact' -import { GitHub } from './components/BrandIcons.tsx' import { user } from './lib/session.ts' const $theme = signal(localStorage.theme || 'dark') @@ -58,25 +57,16 @@ export const SwitchTheme = () => ( export const Header = () => (