From 3fc3a7456a74fe9d3922f4d5804aa534c2238073 Mon Sep 17 00:00:00 2001 From: ordinarthur <@arthurbarre.js@gmail.com> Date: Fri, 15 May 2026 17:21:59 +0200 Subject: [PATCH] feat(web): instrumentation PostHog (analytics + nginx proxy) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Setup PostHog côté SPA — pageviews TanStack Router + 10 events business (signup, login SSO, upload facture, émission/brouillon facture native, marquer payée, lancer relance, plan créé, checkout Stripe). PostHogProvider dans __root.tsx, identify sur auth, proxy nginx /ingest/* → eu.i.posthog.com pour contourner les adblockers. Token bake via build-arg CI (POSTHOG_PROJECT_TOKEN, à ajouter côté Gitea Secrets). Co-Authored-By: Claude Opus 4.7 --- .gitea/workflows/deploy-web.yml | 2 + Dockerfile.web | 9 + apps/web/.env.development | 3 + apps/web/.env.example | 6 + apps/web/.gitignore | 1 + apps/web/nginx.conf | 41 +++ apps/web/package.json | 2 + apps/web/src/routes/__root.tsx | 32 +- apps/web/src/routes/_app/factures_.$id.tsx | 4 + apps/web/src/routes/_app/factures_.import.tsx | 3 + .../src/routes/_app/factures_.nouvelle.tsx | 7 + .../routes/_app/parametres_.abonnement.tsx | 3 + apps/web/src/routes/_app/plans_.nouveau.tsx | 7 + apps/web/src/routes/auth.sso.complete.tsx | 7 + apps/web/src/routes/login.tsx | 7 + apps/web/src/routes/signup.tsx | 7 + apps/web/vite.config.ts | 17 ++ packages/ui/src/components/Brand.tsx | 2 +- pnpm-lock.yaml | 282 ++++++++++++++++++ 19 files changed, 437 insertions(+), 5 deletions(-) diff --git a/.gitea/workflows/deploy-web.yml b/.gitea/workflows/deploy-web.yml index c664077..7b36733 100644 --- a/.gitea/workflows/deploy-web.yml +++ b/.gitea/workflows/deploy-web.yml @@ -63,6 +63,8 @@ jobs: VITE_APP_VERSION=${{ github.sha }} SENTRY_AUTH_TOKEN=${{ secrets.SENTRY_AUTH_TOKEN }} SENTRY_ORG=${{ secrets.SENTRY_ORG }} + VITE_PUBLIC_POSTHOG_PROJECT_TOKEN=${{ secrets.POSTHOG_PROJECT_TOKEN }} + VITE_PUBLIC_POSTHOG_HOST=https://eu.posthog.com - name: Install kubectl run: | diff --git a/Dockerfile.web b/Dockerfile.web index 1b42369..ba8f477 100644 --- a/Dockerfile.web +++ b/Dockerfile.web @@ -25,6 +25,11 @@ ARG VITE_APP_VERSION= # sourcemaps (cf. vite.config.ts). Ne fuit pas en runtime (consommé au build). ARG SENTRY_AUTH_TOKEN= ARG SENTRY_ORG=rubis +# PostHog — token public baked dans le bundle (phc_*). UI host = lien +# « voir dans PostHog » uniquement ; le data ingestion passe par /ingest +# proxifié vers eu.i.posthog.com par nginx (cf. apps/web/nginx.conf). +ARG VITE_PUBLIC_POSTHOG_PROJECT_TOKEN= +ARG VITE_PUBLIC_POSTHOG_HOST=https://eu.posthog.com # ----------------------------------------------------------------------------- # build — Vite produit dist/ @@ -61,6 +66,8 @@ ARG VITE_SENTRY_DSN_WEB ARG VITE_APP_VERSION ARG SENTRY_AUTH_TOKEN ARG SENTRY_ORG +ARG VITE_PUBLIC_POSTHOG_PROJECT_TOKEN +ARG VITE_PUBLIC_POSTHOG_HOST # vite build direct (le `tsc -b` du script build plante sans cache .tsbuildinfo # à cause de @tanstack/router-core ; le typecheck strict est en CI séparée). @@ -74,6 +81,8 @@ RUN VITE_API_URL=$VITE_API_URL \ APP_VERSION=$VITE_APP_VERSION \ SENTRY_AUTH_TOKEN=$SENTRY_AUTH_TOKEN \ SENTRY_ORG=$SENTRY_ORG \ + VITE_PUBLIC_POSTHOG_PROJECT_TOKEN=$VITE_PUBLIC_POSTHOG_PROJECT_TOKEN \ + VITE_PUBLIC_POSTHOG_HOST=$VITE_PUBLIC_POSTHOG_HOST \ pnpm --filter @rubis/web exec vite build # ----------------------------------------------------------------------------- diff --git a/apps/web/.env.development b/apps/web/.env.development index e35b502..d5dddac 100644 --- a/apps/web/.env.development +++ b/apps/web/.env.development @@ -1,6 +1,9 @@ VITE_API_URL=http://localhost:3333 VITE_PUBLIC_LANDING_URL=http://localhost:8080 VITE_USE_MOCKS=false +# PostHog — coller le token "phc_..." du projet (Project settings > Project API key). +VITE_PUBLIC_POSTHOG_PROJECT_TOKEN=phc_yPtTBc6cXyTS8mQVYbYze5fDoRWHD3Cy5iRdn9AR56x8 +VITE_PUBLIC_POSTHOG_HOST=https://eu.posthog.com # Sentry — DSN PUBLIC (peut être commit, c'est by-design dans @sentry/react) VITE_SENTRY_DSN_WEB=https://2e62d7ef1a5aad166d6e0ec9a6e31580@o4511353951354880.ingest.de.sentry.io/4511353959874640 # VITE_APP_VERSION : injecté par le CI (sha git court) ou via vite.config.ts diff --git a/apps/web/.env.example b/apps/web/.env.example index 857362f..6b98482 100644 --- a/apps/web/.env.example +++ b/apps/web/.env.example @@ -6,3 +6,9 @@ VITE_PUBLIC_LANDING_URL=https://rubis.pro # Active MSW pour mocker l'API. Laisser à "false" pour taper le vrai backend. VITE_USE_MOCKS=false + +# PostHog — récupérer dans Project settings > Project API key (commence par "phc_"). +# Le token est PUBLIC (envoyé au navigateur), pas besoin de le cacher. +# UI host : https://eu.posthog.com (EU) ou https://us.posthog.com (US). +VITE_PUBLIC_POSTHOG_PROJECT_TOKEN= +VITE_PUBLIC_POSTHOG_HOST=https://eu.posthog.com diff --git a/apps/web/.gitignore b/apps/web/.gitignore index a547bf3..7ceb59f 100644 --- a/apps/web/.gitignore +++ b/apps/web/.gitignore @@ -22,3 +22,4 @@ dist-ssr *.njsproj *.sln *.sw? +.env diff --git a/apps/web/nginx.conf b/apps/web/nginx.conf index 33d34b0..1efabee 100644 --- a/apps/web/nginx.conf +++ b/apps/web/nginx.conf @@ -3,6 +3,7 @@ # Sert : # - / → assets SPA + index.html avec fallback try_files (TanStack Router) # - /api/* → reverse proxy vers le service ClusterIP rubis-api:3333 +# - /ingest/* → reverse proxy vers PostHog EU (contourne les adblockers) # # Le service rubis-api est interne au cluster K3s (pas de NodePort). # Seul nginx (NodePort 30110 → Traefik) est exposé. @@ -12,6 +13,19 @@ upstream rubis_api { keepalive 32; } +# PostHog ingestion endpoint (EU) — proxifié pour passer les adblockers +# qui bloquent *.posthog.com directement. Le SDK est configuré avec +# api_host: "/ingest" (cf. src/routes/__root.tsx). +upstream posthog_ingest { + server eu.i.posthog.com:443; + keepalive 8; +} +# Assets PostHog (static.js, array.js, recorder) — domaine distinct chez PostHog. +upstream posthog_assets { + server eu-assets.i.posthog.com:443; + keepalive 8; +} + # Compression gzip — Vite produit déjà du JS minifié, mais HTML/CSS/SVG # bénéficient toujours du gzip on-the-fly. gzip on; @@ -63,6 +77,33 @@ server { proxy_read_timeout 60s; } + # PostHog assets (loader JS) — /ingest/static/* et /ingest/array/* vont + # vers eu-assets.i.posthog.com (CDN). Doit être déclaré AVANT /ingest/ + # car nginx matche par prefix le plus long. + location ~ ^/ingest/(static|array)/ { + rewrite ^/ingest/(.*)$ /$1 break; + proxy_pass https://posthog_assets; + proxy_http_version 1.1; + proxy_set_header Host eu-assets.i.posthog.com; + proxy_set_header Connection ""; + proxy_ssl_server_name on; + proxy_ssl_name eu-assets.i.posthog.com; + } + + # PostHog ingestion (events, sessions, exceptions) — /ingest/* → eu.i.posthog.com + location /ingest/ { + rewrite ^/ingest/(.*)$ /$1 break; + proxy_pass https://posthog_ingest; + proxy_http_version 1.1; + proxy_set_header Host eu.i.posthog.com; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto https; + proxy_set_header Connection ""; + proxy_ssl_server_name on; + proxy_ssl_name eu.i.posthog.com; + proxy_redirect off; + } + # SPA fallback : toute route non-asset, non-API → index.html # (TanStack Router gère côté client). location / { diff --git a/apps/web/package.json b/apps/web/package.json index dbdf456..94307c3 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -28,6 +28,7 @@ "@radix-ui/react-tooltip": "^1.1.8", "@rubis/shared": "workspace:*", "@rubis/ui": "workspace:*", + "@posthog/react": "^1.9.0", "@sentry/react": "^10.52.0", "@tanstack/react-form": "^1.0.0", "@tanstack/react-query": "^5.66.0", @@ -43,6 +44,7 @@ "react": "^19.2.5", "react-dom": "^19.2.5", "recharts": "^3.8.1", + "posthog-js": "^1.250.0", "sonner": "^1.7.4", "tailwind-merge": "^3.0.1", "zod": "^3.24.1" diff --git a/apps/web/src/routes/__root.tsx b/apps/web/src/routes/__root.tsx index d365711..095e83d 100644 --- a/apps/web/src/routes/__root.tsx +++ b/apps/web/src/routes/__root.tsx @@ -1,7 +1,8 @@ -import { Outlet, createRootRouteWithContext } from "@tanstack/react-router"; +import { Outlet, createRootRouteWithContext, useRouterState } from "@tanstack/react-router"; import type { QueryClient } from "@tanstack/react-query"; import { Toaster } from "sonner"; -import { lazy, Suspense } from "react"; +import { lazy, Suspense, useEffect } from "react"; +import { PostHogProvider, usePostHog } from "@posthog/react"; import { VersionToast } from "../components/version-toast"; @@ -34,9 +35,32 @@ export const Route = createRootRouteWithContext()({ notFoundComponent: NotFound, }); +function PostHogPageview() { + const posthog = usePostHog(); + const location = useRouterState({ select: (s) => s.location }); + + useEffect(() => { + posthog.capture("$pageview", { $current_url: window.location.href }); + }, [location.pathname, location.search, posthog]); + + return null; +} + function RootLayout() { return ( - <> + + )} - + ); } diff --git a/apps/web/src/routes/_app/factures_.$id.tsx b/apps/web/src/routes/_app/factures_.$id.tsx index d060af2..eba799e 100644 --- a/apps/web/src/routes/_app/factures_.$id.tsx +++ b/apps/web/src/routes/_app/factures_.$id.tsx @@ -4,6 +4,7 @@ import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; import { ArrowLeft, Check, Send } from "lucide-react"; import { toast } from "sonner"; import { z } from "zod"; +import { usePostHog } from "@posthog/react"; import type { Client, Invoice, Plan } from "@rubis/shared"; import { api } from "@/lib/api"; @@ -48,6 +49,7 @@ function InvoiceDetailPage() { const search = Route.useSearch(); const queryClient = useQueryClient(); const navigate = useNavigate(); + const posthog = usePostHog(); const { data: invoice, @@ -61,6 +63,7 @@ function InvoiceDetailPage() { const markPaidMutation = useMutation({ mutationFn: () => api.post(`/api/v1/invoices/${id}/mark-paid`), onSuccess: () => { + posthog.capture("invoice_marked_paid", { invoice_id: id }); void queryClient.invalidateQueries({ queryKey: queryKeys.invoices.all() }); void queryClient.invalidateQueries({ queryKey: queryKeys.dashboard.kpis() }); toast.success("Encaissée. + 1 rubis bien mérité."); @@ -184,6 +187,7 @@ function InvoiceDetailPage() { onClick={() => launchRelanceMutation.mutate(invoice.id, { onSuccess: () => { + posthog.capture("invoice_relance_launched", { invoice_id: invoice.id }); toast.success( `Relances activées pour ${invoice.numero}.`, ); diff --git a/apps/web/src/routes/_app/factures_.import.tsx b/apps/web/src/routes/_app/factures_.import.tsx index 44333dc..0ba4860 100644 --- a/apps/web/src/routes/_app/factures_.import.tsx +++ b/apps/web/src/routes/_app/factures_.import.tsx @@ -2,6 +2,7 @@ import { createFileRoute, Link, useNavigate } from "@tanstack/react-router"; import { useMutation } from "@tanstack/react-query"; import { ArrowLeft, FilePlus } from "lucide-react"; import { toast } from "sonner"; +import { usePostHog } from "@posthog/react"; import { Button } from "@rubis/ui"; import { Eyebrow } from "@rubis/ui"; @@ -16,10 +17,12 @@ export const Route = createFileRoute("/_app/factures_/import")({ function ImportLandingPage() { const navigate = useNavigate(); const manual = useManualInvoice(); + const posthog = usePostHog(); const upload = useMutation({ mutationFn: uploadInvoiceFiles, onSuccess: (batch) => { + posthog.capture("invoice_uploaded", { count: batch.drafts.length }); toast.success( `${batch.drafts.length} facture${batch.drafts.length > 1 ? "s" : ""} extraite${ batch.drafts.length > 1 ? "s" : "" diff --git a/apps/web/src/routes/_app/factures_.nouvelle.tsx b/apps/web/src/routes/_app/factures_.nouvelle.tsx index a78e50c..004517f 100644 --- a/apps/web/src/routes/_app/factures_.nouvelle.tsx +++ b/apps/web/src/routes/_app/factures_.nouvelle.tsx @@ -1,6 +1,7 @@ import { useEffect, useMemo, useRef, useState } from "react"; import { createFileRoute, Link, useNavigate } from "@tanstack/react-router"; import { useQuery } from "@tanstack/react-query"; +import { usePostHog } from "@posthog/react"; import { addDays } from "date-fns"; import { ArrowLeft, @@ -45,6 +46,7 @@ const newLine = (): InvoiceLineInput => ({ function FacturesNouvellePage() { const navigate = useNavigate(); + const posthog = usePostHog(); const { data: settings } = useInvoiceSettings(); const { data: themes } = useInvoiceThemes(); const { data: plans } = useQuery({ @@ -121,6 +123,11 @@ function FacturesNouvellePage() { }; try { const invoice = await create.mutateAsync(payload); + posthog.capture(draft ? "invoice_draft_saved" : "invoice_emitted", { + plan_id: planId ?? undefined, + theme_slug: themeSlug, + line_count: lines.length, + }); navigate({ to: "/factures/$id", params: { id: invoice.id } }); } catch (err) { setSubmitError(err instanceof Error ? err.message : "Erreur inconnue"); diff --git a/apps/web/src/routes/_app/parametres_.abonnement.tsx b/apps/web/src/routes/_app/parametres_.abonnement.tsx index d51973e..25e91f6 100644 --- a/apps/web/src/routes/_app/parametres_.abonnement.tsx +++ b/apps/web/src/routes/_app/parametres_.abonnement.tsx @@ -3,6 +3,7 @@ import { createFileRoute, Link } from "@tanstack/react-router"; import { ArrowLeft, ArrowRight, CreditCard, RotateCcw, Clock } from "lucide-react"; import { toast } from "sonner"; import { z } from "zod"; +import { usePostHog } from "@posthog/react"; import { useOpenPortal, @@ -35,6 +36,7 @@ function AbonnementPage() { const checkout = useStartCheckout(); const portal = useOpenPortal(); const reactivate = useReactivateSubscription(); + const posthog = usePostHog(); const [cycle, setCycle] = useState("monthly"); useEffect(() => { @@ -46,6 +48,7 @@ function AbonnementPage() { }, [search.checkout]); const onUpgrade = (plan: "pro" | "business") => { + posthog.capture("checkout_started", { plan, cycle }); checkout.mutate( { plan, cycle }, { diff --git a/apps/web/src/routes/_app/plans_.nouveau.tsx b/apps/web/src/routes/_app/plans_.nouveau.tsx index 708881f..442c459 100644 --- a/apps/web/src/routes/_app/plans_.nouveau.tsx +++ b/apps/web/src/routes/_app/plans_.nouveau.tsx @@ -1,6 +1,7 @@ import { useEffect, useMemo, useRef, useState } from "react"; import { createFileRoute, useNavigate, Link } from "@tanstack/react-router"; import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; +import { usePostHog } from "@posthog/react"; import { z } from "zod"; import { ArrowLeft, @@ -125,6 +126,7 @@ function PlanCreateWizard() { const navigate = useNavigate(); const { from } = Route.useSearch(); const queryClient = useQueryClient(); + const posthog = usePostHog(); const [step, setStep] = useState(1); // Si on duplique, on charge le plan source pour pré-remplir le draft. @@ -184,6 +186,11 @@ function PlanCreateWizard() { })), }), onSuccess: (created) => { + posthog.capture("plan_created", { + plan_name: created.name, + step_count: draft.steps.length, + global_tone: draft.globalTone, + }); void queryClient.invalidateQueries({ queryKey: queryKeys.plans.all() }); toast.success(`Plan « ${created.name} » créé.`); void navigate({ diff --git a/apps/web/src/routes/auth.sso.complete.tsx b/apps/web/src/routes/auth.sso.complete.tsx index 9830b45..e6ac8e9 100644 --- a/apps/web/src/routes/auth.sso.complete.tsx +++ b/apps/web/src/routes/auth.sso.complete.tsx @@ -2,6 +2,7 @@ import { useEffect, useRef } from "react"; import { createFileRoute, useNavigate } from "@tanstack/react-router"; import { z } from "zod"; import { toast } from "sonner"; +import { usePostHog } from "@posthog/react"; import type { AuthSession } from "@rubis/shared"; import { api } from "@/lib/api"; @@ -31,6 +32,7 @@ export const Route = createFileRoute("/auth/sso/complete")({ function SsoCompletePage() { const { next } = Route.useSearch(); const navigate = useNavigate(); + const posthog = usePostHog(); // Strict-mode protect : avoid double-firing the refresh in dev. const triggered = useRef(false); @@ -44,6 +46,11 @@ function SsoCompletePage() { undefined, { anonymous: true }, ); + posthog.identify(session.user.id, { + email: session.user.email, + name: session.user.fullName, + }); + posthog.capture("user_logged_in_sso"); authStore.setSession(session.accessToken, session.user); const firstName = session.user.fullName?.split(" ")[0]; toast.success(firstName ? `Bonjour ${firstName}.` : "Connecté."); diff --git a/apps/web/src/routes/login.tsx b/apps/web/src/routes/login.tsx index a2aea33..534e03d 100644 --- a/apps/web/src/routes/login.tsx +++ b/apps/web/src/routes/login.tsx @@ -5,6 +5,7 @@ import { useMutation } from "@tanstack/react-query"; import { toast } from "sonner"; import { ArrowRight } from "lucide-react"; import { z } from "zod"; +import { usePostHog } from "@posthog/react"; import { loginSchema, type AuthSession, type LoginInput } from "@rubis/shared"; @@ -51,6 +52,7 @@ export const Route = createFileRoute("/login")({ function LoginPage() { const navigate = useNavigate(); const search = Route.useSearch(); + const posthog = usePostHog(); // Toast d'erreur si on revient d'un échec SSO (?google=denied, ?microsoft=…). useEffect(() => { @@ -66,6 +68,11 @@ function LoginPage() { mutationFn: async (input: LoginInput) => api.post("/api/v1/auth/login", input, { anonymous: true }), onSuccess: (session) => { + posthog.identify(session.user.id, { + email: session.user.email, + name: session.user.fullName, + }); + posthog.capture("user_logged_in", { provider: "email" }); authStore.setSession(session.accessToken, session.user); toast.success(`Bonjour ${session.user.fullName.split(" ")[0]}.`); // Si on a une URL de redirection (depuis le guard d'auth), on la suit ; diff --git a/apps/web/src/routes/signup.tsx b/apps/web/src/routes/signup.tsx index 0e5fda4..70966a0 100644 --- a/apps/web/src/routes/signup.tsx +++ b/apps/web/src/routes/signup.tsx @@ -3,6 +3,7 @@ import { useForm } from "@tanstack/react-form"; import { useMutation } from "@tanstack/react-query"; import { toast } from "sonner"; import { ArrowRight } from "lucide-react"; +import { usePostHog } from "@posthog/react"; import { registerSchema, @@ -27,11 +28,17 @@ export const Route = createFileRoute("/signup")({ function SignupPage() { const navigate = useNavigate(); + const posthog = usePostHog(); const signupMutation = useMutation({ mutationFn: async (input: RegisterInput) => api.post("/api/v1/auth/signup", input, { anonymous: true }), onSuccess: (session) => { + posthog.identify(session.user.id, { + email: session.user.email, + name: session.user.fullName, + }); + posthog.capture("user_signed_up", { email: session.user.email }); authStore.setSession(session.accessToken, session.user); toast.success("Compte créé. On finalise votre installation."); void navigate({ to: "/onboarding/compte" }); diff --git a/apps/web/vite.config.ts b/apps/web/vite.config.ts index 131a7db..4b964dd 100644 --- a/apps/web/vite.config.ts +++ b/apps/web/vite.config.ts @@ -68,6 +68,23 @@ export default defineConfig({ server: { port: 5173, strictPort: true, + proxy: { + "/ingest/static": { + target: "https://eu-assets.i.posthog.com", + changeOrigin: true, + rewrite: (path) => path.replace(/^\/ingest/, ""), + }, + "/ingest/array": { + target: "https://eu-assets.i.posthog.com", + changeOrigin: true, + rewrite: (path) => path.replace(/^\/ingest/, ""), + }, + "/ingest": { + target: "https://eu.i.posthog.com", + changeOrigin: true, + rewrite: (path) => path.replace(/^\/ingest/, ""), + }, + }, }, build: { // Source maps requises pour que Sentry désobfusque les stack traces. diff --git a/packages/ui/src/components/Brand.tsx b/packages/ui/src/components/Brand.tsx index 574a179..0157e2f 100644 --- a/packages/ui/src/components/Brand.tsx +++ b/packages/ui/src/components/Brand.tsx @@ -57,7 +57,7 @@ export function Brand({ Rubis - {withSuffix && .pro} + {/* {withSuffix && sur l'ongle} */} ); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index dfb8816..0a4cb53 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -244,6 +244,9 @@ importers: '@fontsource-variable/inter': specifier: ^5.2.5 version: 5.2.8 + '@posthog/react': + specifier: ^1.9.0 + version: 1.9.0(@types/react@19.2.14)(posthog-js@1.373.5)(react@19.2.5) '@radix-ui/react-dialog': specifier: ^1.1.6 version: 1.1.15(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) @@ -304,6 +307,9 @@ importers: lucide-react: specifier: ^0.475.0 version: 0.475.0(react@19.2.5) + posthog-js: + specifier: ^1.250.0 + version: 1.373.5 react: specifier: ^19.2.5 version: 19.2.5 @@ -1898,6 +1904,10 @@ packages: resolution: {integrity: sha512-lAb0jQRVyleQQGiuuvCOTDVspc14nx6XJjP4FspJ1sNARo3Regq4ZZbrc3rN4b1TYSuUCvgH+UXUPug4SLOqEQ==} engines: {node: '>=8.0.0'} + '@opentelemetry/api-logs@0.208.0': + resolution: {integrity: sha512-CjruKY9V6NMssL/T1kAFgzosF1v9o6oeN+aX5JB/C/xPNtmgIJqcXHG7fA82Ou1zCpWGl4lROQUKwUNE1pMCyg==} + engines: {node: '>=8.0.0'} + '@opentelemetry/api-logs@0.212.0': resolution: {integrity: sha512-TEEVrLbNROUkYY51sBJGk7lO/OLjuepch8+hmpM6ffMJQ2z/KVCjdHuCFX6fJj8OkJP2zckPjrJzQtXU3IAsFg==} engines: {node: '>=8.0.0'} @@ -1910,6 +1920,12 @@ packages: resolution: {integrity: sha512-gLyJlPHPZYdAk1JENA9LeHejZe1Ti77/pTeFm/nMXmQH/HFZlcS/O2XJB+L8fkbrNSqhdtlvjBVjxwUYanNH5Q==} engines: {node: '>=8.0.0'} + '@opentelemetry/core@2.2.0': + resolution: {integrity: sha512-FuabnnUm8LflnieVxs6eP7Z383hgQU4W1e3KJS6aOG3RxWxcHyBxH8fDMHNgu/gFx/M2jvTOW/4/PHhLz6bjWw==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': '>=1.0.0 <1.10.0' + '@opentelemetry/core@2.6.1': resolution: {integrity: sha512-8xHSGWpJP9wBxgBpnqGL0R3PbdWQndL1Qp50qrg71+B28zK5OQmUgcDKLJgzyAAV38t4tOyLMGDD60LneR5W8g==} engines: {node: ^18.19.0 || >=20.6.0} @@ -1922,6 +1938,12 @@ packages: peerDependencies: '@opentelemetry/api': '>=1.0.0 <1.10.0' + '@opentelemetry/exporter-logs-otlp-http@0.208.0': + resolution: {integrity: sha512-jOv40Bs9jy9bZVLo/i8FwUiuCvbjWDI+ZW13wimJm4LjnlwJxGgB+N/VWOZUTpM+ah/awXeQqKdNlpLf2EjvYg==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + '@opentelemetry/instrumentation-amqplib@0.61.0': resolution: {integrity: sha512-mCKoyTGfRNisge4br0NpOFSy2Z1NnEW8hbCJdUDdJFHrPqVzc4IIBPA/vX0U+LUcQqrQvJX+HMIU0dbDRe0i0Q==} engines: {node: ^18.19.0 || >=20.6.0} @@ -2048,12 +2070,48 @@ packages: peerDependencies: '@opentelemetry/api': ^1.3.0 + '@opentelemetry/otlp-exporter-base@0.208.0': + resolution: {integrity: sha512-gMd39gIfVb2OgxldxUtOwGJYSH8P1kVFFlJLuut32L6KgUC4gl1dMhn+YC2mGn0bDOiQYSk/uHOdSjuKp58vvA==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/otlp-transformer@0.208.0': + resolution: {integrity: sha512-DCFPY8C6lAQHUNkzcNT9R+qYExvsk6C5Bto2pbNxgicpcSWbe2WHShLxkOxIdNcBiYPdVHv/e7vH7K6TI+C+fQ==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/resources@2.2.0': + resolution: {integrity: sha512-1pNQf/JazQTMA0BiO5NINUzH0cbLbbl7mntLa4aJNmCCXSj0q03T5ZXXL0zw4G55TjdL9Tz32cznGClf+8zr5A==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': '>=1.3.0 <1.10.0' + '@opentelemetry/resources@2.7.1': resolution: {integrity: sha512-DeT6KKolmC4e/dRQvMQ/RwlnzhaqeiFOXY5ngoOPJ07GgVVKxZOg9EcrNZb5aTzUn+iCrJldAgOfQm1O/QfPAQ==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': '>=1.3.0 <1.10.0' + '@opentelemetry/sdk-logs@0.208.0': + resolution: {integrity: sha512-QlAyL1jRpOeaqx7/leG1vJMp84g0xKP6gJmfELBpnI4O/9xPX+Hu5m1POk9Kl+veNkyth5t19hRlN6tNY1sjbA==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': '>=1.4.0 <1.10.0' + + '@opentelemetry/sdk-metrics@2.2.0': + resolution: {integrity: sha512-G5KYP6+VJMZzpGipQw7Giif48h6SGQ2PFKEYCybeXJsOCB4fp8azqMAAzE5lnnHK3ZVwYQrgmFbsUJO/zOnwGw==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': '>=1.9.0 <1.10.0' + + '@opentelemetry/sdk-trace-base@2.2.0': + resolution: {integrity: sha512-xWQgL0Bmctsalg6PaXExmzdedSp3gyKV8mQBwK/j9VGdCDu2fmXIb2gAehBKbkXCpJ4HPkgv3QfoJWRT4dHWbw==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': '>=1.3.0 <1.10.0' + '@opentelemetry/sdk-trace-base@2.7.1': resolution: {integrity: sha512-NAYIlsF8MPUsKqJMiDQJTMPOmlbawC1Iz/omMLygZ1C9am8fTKYjTaI+OZM+WTY3t3Glo0wnOg/6/pac6RGPPw==} engines: {node: ^18.19.0 || >=20.6.0} @@ -2148,11 +2206,57 @@ packages: '@poppinss/validator-lite@2.1.2': resolution: {integrity: sha512-UhSG1ouT6r67VbEFHK/8ax3EMZYHioew9PqGmEZjV41G15aPZi6cyhXtBVvF9xqkHMflA5V680k7bQzV0kfD5w==} + '@posthog/core@1.29.2': + resolution: {integrity: sha512-DYhR0Sl7pVdUXa+C9poCVjTj3D6SI9P7RLhIhr74YyHeHuCGL/MZsDEWcz3ul3qHDIhZU9myIUjID890QiQw+g==} + + '@posthog/react@1.9.0': + resolution: {integrity: sha512-lVdTsWT5+PtHBu44gSQ7QohbLjAYqHkFAIGAQ+HV8Eh9yj+OcnQ7mXCmyhaMlTBD3z7D0H1eWMp4vQaFnsIyWQ==} + peerDependencies: + '@types/react': '>=16.8.0' + posthog-js: '>=1.257.2' + react: '>=16.8.0' + peerDependenciesMeta: + '@types/react': + optional: true + + '@posthog/types@1.373.5': + resolution: {integrity: sha512-K7STCnRG/WBE1q0BwEkIcrJB5OqECaymsQj6Hp4Ntvaek4dqHkZGfp6hxwIPqQPjlOXwidwPLo+XGsn+CoZUyw==} + '@prisma/instrumentation@7.6.0': resolution: {integrity: sha512-ZPW2gRiwpPzEfgeZgaekhqXrbW+Y2RJKHVqUmlhZhKzRNCcvR6DykzylDrynpArKKRQtLxoZy36fK7U0p3pdgQ==} peerDependencies: '@opentelemetry/api': ^1.8 + '@protobufjs/aspromise@1.1.2': + resolution: {integrity: sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==} + + '@protobufjs/base64@1.1.2': + resolution: {integrity: sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==} + + '@protobufjs/codegen@2.0.5': + resolution: {integrity: sha512-zgXFLzW3Ap33e6d0Wlj4MGIm6Ce8O89n/apUaGNB/jx+hw+ruWEp7EwGUshdLKVRCxZW12fp9r40E1mQrf/34g==} + + '@protobufjs/eventemitter@1.1.0': + resolution: {integrity: sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==} + + '@protobufjs/fetch@1.1.0': + resolution: {integrity: sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==} + + '@protobufjs/float@1.0.2': + resolution: {integrity: sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==} + + '@protobufjs/inquire@1.1.1': + resolution: {integrity: sha512-mnzgDV26ueAvk7rsbt9L7bE0SuAoqyuys/sMMrmVcN5x9VsxpcG3rqAUSgDyLp0UZlmNfIbQ4fHfCtreVBk8Ew==} + + '@protobufjs/path@1.1.2': + resolution: {integrity: sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==} + + '@protobufjs/pool@1.1.0': + resolution: {integrity: sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==} + + '@protobufjs/utf8@1.1.1': + resolution: {integrity: sha512-oOAWABowe8EAbMyWKM0tYDKi8Yaox52D+HWZhAIJqQXbqe0xI/GV7FhLWqlEKreMkfDjshR5FKgi3mnle0h6Eg==} + '@radix-ui/number@1.1.1': resolution: {integrity: sha512-MkKCwxlXTgz6CFoJx3pCwn07GKp36+aZyu/u2Ln2VrA5DcdyCZkASEDBTd8x5whTQQL5CiYf4prXKLcgQdv29g==} @@ -3998,6 +4102,9 @@ packages: '@types/tedious@4.0.14': resolution: {integrity: sha512-KHPsfX/FoVbUGbyYvk1q9MMQHLPeRZhRJZdO45Q4YjvFkv4hMNghCWTvy7rdKessBsmtz4euWCWAB6/tVpI1Iw==} + '@types/trusted-types@2.0.7': + resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==} + '@types/unist@2.0.11': resolution: {integrity: sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==} @@ -4614,6 +4721,9 @@ packages: core-js-compat@3.49.0: resolution: {integrity: sha512-VQXt1jr9cBz03b331DFDCCP90b3fanciLkgiOoy8SBHy06gNf+vQ1A3WFLqG7I8TipYIKeYK9wxd0tUrvHcOZA==} + core-js@3.49.0: + resolution: {integrity: sha512-es1U2+YTtzpwkxVLwAFdSpaIMyQaq0PBgm3YD1W3Qpsn1NAmO3KSgZfu+oGSWVu6NvLHoHCV/aYcsE5wiB7ALg==} + cron-parser@4.9.0: resolution: {integrity: sha512-p0SaNjrHOnQeR8/VnfGbmg9te2kfyYSQ7Sc/j/6DtPL3JQvKxmjO9TSjNFpujqV3vEYYBvNNvXSxzyksBWAx1Q==} engines: {node: '>=12.0.0'} @@ -4856,6 +4966,9 @@ packages: resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==} engines: {node: '>= 4'} + dompurify@3.4.3: + resolution: {integrity: sha512-VVwJidIJcp1hpg2OMXML3ZVRPYSZiq4aX7qBh83BSIpOaRDqI+qxhXjjIWnpzkOXhmp0L81lnoME1mnCc9H48A==} + domutils@3.2.2: resolution: {integrity: sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==} @@ -5176,6 +5289,9 @@ packages: picomatch: optional: true + fflate@0.4.8: + resolution: {integrity: sha512-FJqqoDBR00Mdj9ppamLa/Y7vxm+PRmNWA67N846RvsoYVMKB4q3y/de5PA7gUmRMYK/8CMz2GDZQmCRN1wBcWA==} + fflate@0.8.2: resolution: {integrity: sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==} @@ -6020,6 +6136,9 @@ packages: resolution: {integrity: sha512-iLs7dGSyjZiUgvrUvuD3FndAxVJk+TywBkkkwUSm9HdYoskJalWg5qVsEiXeufPvRVPbCUmNQewg798rx+sPXg==} engines: {node: '>=20'} + long@5.3.2: + resolution: {integrity: sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==} + longest-streak@3.1.0: resolution: {integrity: sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==} @@ -6668,10 +6787,16 @@ packages: resolution: {integrity: sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==} engines: {node: '>=0.10.0'} + posthog-js@1.373.5: + resolution: {integrity: sha512-VjeSKiAtbRxcKXr+lFWlHNd9GGxA3A1gZ87EsIZmEV3N8SwO11uAf6JDTEuymdUNGn99XTvWcPrBCxkSBgVAEg==} + powershell-utils@0.1.0: resolution: {integrity: sha512-dM0jVuXJPsDN6DvRpea484tCUaMiXWjuCn++HGTqUWzGDjv5tZkEZldAJ/UMlqRYGFrD/etByo4/xOuC/snX2A==} engines: {node: '>=20'} + preact@10.29.1: + resolution: {integrity: sha512-gQCLc/vWroE8lIpleXtdJhTFDogTdZG9AjMUpVkDf2iTCNwYNWA+u16dL41TqUDJO4gm2IgrcMv3uTpjd4Pwmg==} + prebuild-install@7.1.3: resolution: {integrity: sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==} engines: {node: '>=10'} @@ -6727,6 +6852,10 @@ packages: property-information@7.1.0: resolution: {integrity: sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==} + protobufjs@7.5.8: + resolution: {integrity: sha512-dvpCIeLPbXZS/Ete7yLaO7RenOdken2NHKykBXbsaGxZT0UTltcarBciw+A78SRQs9iMAAVpsYA+l8b1hTePIA==} + engines: {node: '>=12.0.0'} + proxy-addr@2.0.7: resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} engines: {node: '>= 0.10'} @@ -6745,6 +6874,9 @@ packages: resolution: {integrity: sha512-6YHEFRL9mfgcAvql/XhwTvf5jKcOiiupt2FiJxHkiX1z4j7WL8J/jRHYLluORvc1XxB5rV20KoeK00gVJamspg==} engines: {node: '>=0.6'} + query-selector-shadow-dom@1.0.1: + resolution: {integrity: sha512-lT5yCqEBgfoMYpf3F2xQRK7zEr1rhIIZuceDK6+xRkJQ4NMbHTwXqk4NkwDwQMNqXgG9r9fyHnzwNVs6zV5KRw==} + queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} @@ -8030,6 +8162,9 @@ packages: web-namespaces@2.0.1: resolution: {integrity: sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==} + web-vitals@5.2.0: + resolution: {integrity: sha512-i2z98bEmaCqSDiHEDu+gHl/dmR4Q+TxFmG3/13KkMO+o8UxQzCqWaDRCiLgEa41nlO4VpXSI0ASa1xWmO9sBlA==} + webidl-conversions@3.0.1: resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} @@ -9895,6 +10030,10 @@ snapshots: dependencies: '@opentelemetry/api': 1.9.1 + '@opentelemetry/api-logs@0.208.0': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/api-logs@0.212.0': dependencies: '@opentelemetry/api': 1.9.1 @@ -9905,6 +10044,11 @@ snapshots: '@opentelemetry/api@1.9.1': {} + '@opentelemetry/core@2.2.0(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/semantic-conventions': 1.40.0 + '@opentelemetry/core@2.6.1(@opentelemetry/api@1.9.1)': dependencies: '@opentelemetry/api': 1.9.1 @@ -9915,6 +10059,15 @@ snapshots: '@opentelemetry/api': 1.9.1 '@opentelemetry/semantic-conventions': 1.40.0 + '@opentelemetry/exporter-logs-otlp-http@0.208.0(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/api-logs': 0.208.0 + '@opentelemetry/core': 2.2.0(@opentelemetry/api@1.9.1) + '@opentelemetry/otlp-exporter-base': 0.208.0(@opentelemetry/api@1.9.1) + '@opentelemetry/otlp-transformer': 0.208.0(@opentelemetry/api@1.9.1) + '@opentelemetry/sdk-logs': 0.208.0(@opentelemetry/api@1.9.1) + '@opentelemetry/instrumentation-amqplib@0.61.0(@opentelemetry/api@1.9.1)': dependencies: '@opentelemetry/api': 1.9.1 @@ -10097,12 +10250,55 @@ snapshots: transitivePeerDependencies: - supports-color + '@opentelemetry/otlp-exporter-base@0.208.0(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 2.2.0(@opentelemetry/api@1.9.1) + '@opentelemetry/otlp-transformer': 0.208.0(@opentelemetry/api@1.9.1) + + '@opentelemetry/otlp-transformer@0.208.0(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/api-logs': 0.208.0 + '@opentelemetry/core': 2.2.0(@opentelemetry/api@1.9.1) + '@opentelemetry/resources': 2.2.0(@opentelemetry/api@1.9.1) + '@opentelemetry/sdk-logs': 0.208.0(@opentelemetry/api@1.9.1) + '@opentelemetry/sdk-metrics': 2.2.0(@opentelemetry/api@1.9.1) + '@opentelemetry/sdk-trace-base': 2.2.0(@opentelemetry/api@1.9.1) + protobufjs: 7.5.8 + + '@opentelemetry/resources@2.2.0(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 2.2.0(@opentelemetry/api@1.9.1) + '@opentelemetry/semantic-conventions': 1.40.0 + '@opentelemetry/resources@2.7.1(@opentelemetry/api@1.9.1)': dependencies: '@opentelemetry/api': 1.9.1 '@opentelemetry/core': 2.7.1(@opentelemetry/api@1.9.1) '@opentelemetry/semantic-conventions': 1.40.0 + '@opentelemetry/sdk-logs@0.208.0(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/api-logs': 0.208.0 + '@opentelemetry/core': 2.2.0(@opentelemetry/api@1.9.1) + '@opentelemetry/resources': 2.2.0(@opentelemetry/api@1.9.1) + + '@opentelemetry/sdk-metrics@2.2.0(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 2.2.0(@opentelemetry/api@1.9.1) + '@opentelemetry/resources': 2.2.0(@opentelemetry/api@1.9.1) + + '@opentelemetry/sdk-trace-base@2.2.0(@opentelemetry/api@1.9.1)': + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 2.2.0(@opentelemetry/api@1.9.1) + '@opentelemetry/resources': 2.2.0(@opentelemetry/api@1.9.1) + '@opentelemetry/semantic-conventions': 1.40.0 + '@opentelemetry/sdk-trace-base@2.7.1(@opentelemetry/api@1.9.1)': dependencies: '@opentelemetry/api': 1.9.1 @@ -10211,6 +10407,19 @@ snapshots: '@poppinss/validator-lite@2.1.2': {} + '@posthog/core@1.29.2': + dependencies: + '@posthog/types': 1.373.5 + + '@posthog/react@1.9.0(@types/react@19.2.14)(posthog-js@1.373.5)(react@19.2.5)': + dependencies: + posthog-js: 1.373.5 + react: 19.2.5 + optionalDependencies: + '@types/react': 19.2.14 + + '@posthog/types@1.373.5': {} + '@prisma/instrumentation@7.6.0(@opentelemetry/api@1.9.1)': dependencies: '@opentelemetry/api': 1.9.1 @@ -10218,6 +10427,29 @@ snapshots: transitivePeerDependencies: - supports-color + '@protobufjs/aspromise@1.1.2': {} + + '@protobufjs/base64@1.1.2': {} + + '@protobufjs/codegen@2.0.5': {} + + '@protobufjs/eventemitter@1.1.0': {} + + '@protobufjs/fetch@1.1.0': + dependencies: + '@protobufjs/aspromise': 1.1.2 + '@protobufjs/inquire': 1.1.1 + + '@protobufjs/float@1.0.2': {} + + '@protobufjs/inquire@1.1.1': {} + + '@protobufjs/path@1.1.2': {} + + '@protobufjs/pool@1.1.0': {} + + '@protobufjs/utf8@1.1.1': {} + '@radix-ui/number@1.1.1': {} '@radix-ui/primitive@1.1.3': {} @@ -12079,6 +12311,9 @@ snapshots: dependencies: '@types/node': 25.6.0 + '@types/trusted-types@2.0.7': + optional: true + '@types/unist@2.0.11': {} '@types/unist@3.0.3': {} @@ -12821,6 +13056,8 @@ snapshots: dependencies: browserslist: 4.28.2 + core-js@3.49.0: {} + cron-parser@4.9.0: dependencies: luxon: 3.7.2 @@ -13017,6 +13254,10 @@ snapshots: dependencies: domelementtype: 2.3.0 + dompurify@3.4.3: + optionalDependencies: + '@types/trusted-types': 2.0.7 + domutils@3.2.2: dependencies: dom-serializer: 2.0.0 @@ -13408,6 +13649,8 @@ snapshots: optionalDependencies: picomatch: 4.0.4 + fflate@0.4.8: {} + fflate@0.8.2: {} figures@6.1.0: @@ -14265,6 +14508,8 @@ snapshots: strip-ansi: 7.2.0 wrap-ansi: 10.0.0 + long@5.3.2: {} + longest-streak@3.1.0: {} loose-envify@1.4.0: @@ -15101,8 +15346,26 @@ snapshots: dependencies: xtend: 4.0.2 + posthog-js@1.373.5: + dependencies: + '@opentelemetry/api': 1.9.1 + '@opentelemetry/api-logs': 0.208.0 + '@opentelemetry/exporter-logs-otlp-http': 0.208.0(@opentelemetry/api@1.9.1) + '@opentelemetry/resources': 2.7.1(@opentelemetry/api@1.9.1) + '@opentelemetry/sdk-logs': 0.208.0(@opentelemetry/api@1.9.1) + '@posthog/core': 1.29.2 + '@posthog/types': 1.373.5 + core-js: 3.49.0 + dompurify: 3.4.3 + fflate: 0.4.8 + preact: 10.29.1 + query-selector-shadow-dom: 1.0.1 + web-vitals: 5.2.0 + powershell-utils@0.1.0: {} + preact@10.29.1: {} + prebuild-install@7.1.3: dependencies: detect-libc: 2.1.2 @@ -15165,6 +15428,21 @@ snapshots: property-information@7.1.0: {} + protobufjs@7.5.8: + dependencies: + '@protobufjs/aspromise': 1.1.2 + '@protobufjs/base64': 1.1.2 + '@protobufjs/codegen': 2.0.5 + '@protobufjs/eventemitter': 1.1.0 + '@protobufjs/fetch': 1.1.0 + '@protobufjs/float': 1.0.2 + '@protobufjs/inquire': 1.1.1 + '@protobufjs/path': 1.1.2 + '@protobufjs/pool': 1.1.0 + '@protobufjs/utf8': 1.1.1 + '@types/node': 25.6.0 + long: 5.3.2 + proxy-addr@2.0.7: dependencies: forwarded: 0.2.0 @@ -15183,6 +15461,8 @@ snapshots: dependencies: side-channel: 1.1.0 + query-selector-shadow-dom@1.0.1: {} + queue-microtask@1.2.3: {} queue@6.0.2: @@ -16556,6 +16836,8 @@ snapshots: web-namespaces@2.0.1: {} + web-vitals@5.2.0: {} + webidl-conversions@3.0.1: {} webidl-conversions@7.0.0: {}