diff --git a/.claude/rules/consent.md b/.claude/rules/consent.md new file mode 100644 index 0000000..f71847f --- /dev/null +++ b/.claude/rules/consent.md @@ -0,0 +1,102 @@ +--- +paths: + - "packages/core/**" +--- + +# Consent Standards + +## State Machine + +Consent is a reactive state machine with event queuing, not a boolean gate. + +- **Merge, not replace:** `setState({ analytics: true })` merges with existing state +- **AND logic:** Destination requiring `["analytics", "marketing"]` needs BOTH granted +- **"necessary" and "exempt" always allowed:** Never blocked by consent +- **Pending = undefined:** Categories not yet set are pending, not denied +- **Lenient by default:** Events pass through; strict mode is opt-in + +### Event Queuing + +Events arriving before consent resolves are queued and replayed when consent changes. + +- Deduplicated by event ID +- `sentTo` Set tracks which destinations already received each event +- Queue expires based on `queueTimeout` (default 30s) +- In strict mode, queuing is disabled — pending = denied, events drop + +### CMP Fallback + +~15-20% of privacy-conscious users block CMP scripts. Use `consentFallback`: + +```typescript +consent: { + consentFallback: { + timeout: 3000, + state: { analytics: false, marketing: false } + } +} +``` + +### DNT & GPC + +When `respectDNT` or `respectGPC` is enabled: +- DNT disables `analytics` and `marketing` +- GPC additionally disables `personalization` + +### ConsentSignals (Separate from Destinations) + +Vendor consent protocols (e.g. Google Consent Mode) are modeled as ConsentSignals, not part of destinations: + +```typescript +consentSignals: [ + googleConsentMode({ waitForUpdate: 500 }) +] +``` + +## Timing Heuristics + +Not all "pending" consent is equal. Junction distinguishes the signal behind why consent hasn't resolved. + +| Signal | Meaning | Action | +|--------|---------|--------| +| CMP blocked | Script never loads | `consentFallback` (3s) | +| CMP loaded, no interaction | Banner visible | Queue, `queueTimeout` (30s) | +| CMP loaded, dismissed | Closed without choosing | Conservative defaults | + +**Future direction:** Accept a `consentSignalHint` from CMP integrations: +- `"blocked"` → fast fallback (seconds) +- `"visible"` → patient queue (30s+) +- `"dismissed"` → conservative defaults immediately + +### SPA vs MPA + +- **MPA:** Navigation = unload = queue loss. First pageview uniquely fragile. +- **SPA:** User stays on page, consent resolves naturally. +- May be best addressed at integration layer (e.g. `@junctionjs/next` defaults) rather than core. + +## Necessary vs. Exempt + +Two always-allowed consent categories serving different layers of the privacy stack. + +- **necessary**: CMP/storage layer. Cookies and web storage required for site functionality. Pinned to `true` in state. Legal basis: ePrivacy Art 5(3). +- **exempt**: Data/dispatch layer. Destinations that receive events regardless of consent state. Used for first-party observability. Legal basis: GDPR Art 6(1)(f) legitimate interest. + +### Why Two Categories + +They operate at different enforcement layers: +- CMPs enforce **storage** (cookies, localStorage) +- Junction enforces **dispatch** (network requests to destinations) + +### Guardrails (required) + +- **First-party only**: Exempt destinations must be first-party or contractually bound processors +- **Legal basis declaration**: Each exempt destination should declare its basis +- **Audit trail**: Events dispatched to exempt destinations carry `is_exempt: true` metadata +- **Transparency**: Emit `destination:exempt` events for debug panels and audit logs + +| Aspect | necessary | exempt | +|--------|-----------|--------| +| Consent UI | Visible | Hidden | +| Consent queue | Participates | Bypasses | +| Legal basis | ePrivacy strictly necessary | GDPR legitimate interest | +| User can disable | No (always on) | No (operational) | diff --git a/.claude/rules/destinations.md b/.claude/rules/destinations.md new file mode 100644 index 0000000..4d24e85 --- /dev/null +++ b/.claude/rules/destinations.md @@ -0,0 +1,96 @@ +--- +paths: + - "packages/destination-*/**" +--- + +# Destination Standards + +## Interface + +Destinations are plain objects with async functions, not classes. + +- Tree-shakeable (classes aren't), composable, easy to test +- Use factory functions (`createGA4()`, `http(config)`), not `new` + +```typescript +interface Destination { + name: string; + version: string; + consent: ConsentCategory[]; // AND logic + runtime: "client" | "server" | "both"; + + init: (config: TConfig) => Promise | void; + transform: (event: JctEvent, config: TConfig) => unknown | null; + send: (payload: unknown, config: TConfig) => Promise; + onConsent?: (state: ConsentState) => void; + teardown?: () => Promise | void; +} +``` + +- `transform` returns `null` to skip an event for this destination +- `transform` is a pure function — no side effects, no network calls +- `send` handles all network I/O +- Config is type-generic: `Destination` + +## Event Name Mapping + +All destinations use a 3-tier fallback: + +1. **Config override** — `config.eventNameMap["product:viewed"]` +2. **Default map** — Built-in mapping per destination +3. **Generated name** — `entity_action` (or destination-specific format) + +```typescript +function getEventName(event: JctEvent, config: Config): string { + const key = `${event.entity}:${event.action}`; + return config.eventNameMap?.[key] + ?? DEFAULT_MAP[key] + ?? `${event.entity}_${event.action}`; +} +``` + +### Per-Destination Defaults + +| entity:action | GA4 | Amplitude | Meta | +|---|---|---|---| +| page:viewed | page_view | Page Viewed | PageView | +| product:viewed | view_item | Product Viewed | ViewContent | +| product:added | add_to_cart | Product Added | AddToCart | +| order:completed | purchase | Order Completed | Purchase | + +## Script Loading + +Client-side destinations that load vendor scripts use a queue-before-load pattern: + +- Always check `typeof window === "undefined"` first (SSR safety) +- Always check if already loaded (idempotent) +- Create queuing stub before loading script +- Use `script.async = true` +- Support custom script URLs via config +- Gate loading with `loadScript?: boolean` config (default: true) + +## System Events + +The `_system` entity is reserved for internal lifecycle events. All destinations must filter them: + +```typescript +transform(event: JctEvent, config: Config) { + if (event.entity === "_system") return null; + // ... normal transformation +} +``` + +## Error Isolation + +The collector must never crash. Every external boundary is wrapped in try/catch. + +| Boundary | Failure behavior | +|---|---| +| `destination.init()` | Logged, destination skipped, collector continues | +| `destination.transform()` | Logged, event skipped for that destination, others still receive it | +| `destination.send()` | `.catch()` logs error, no await blocking | +| Consent listeners | Caught per-listener, other listeners still fire | + +- Use `emit("destination:error", ...)` so consumers can observe failures +- Never let one destination's failure affect another +- Prefix all console output with `[Junction]` diff --git a/.claude/rules/events.md b/.claude/rules/events.md new file mode 100644 index 0000000..7036a84 --- /dev/null +++ b/.claude/rules/events.md @@ -0,0 +1,41 @@ +--- +paths: + - "packages/core/**" + - "packages/client/**" +--- + +# Event Standards + +## Entity:Action Pairs + +All events use `entity:action` pairs, not flat strings. + +```typescript +// Good +track("product", "viewed", { product_id: "123" }) +track("order", "completed", { order_id: "456" }) + +// Bad +track("Product Viewed", { product_id: "123" }) +``` + +## Naming Rules + +- **Entities:** lowercase, singular or plural (`product`, `page`, `order`, `user`) +- **Actions:** lowercase, past tense preferred (`viewed`, `added`, `completed`, `signed_up`) +- **Combined key:** `entity:action` used for contract lookup and destination mapping +- Wildcard contracts (`entity:*`) match all actions for an entity +- If no contract exists, events pass through unvalidated + +## Destination Mapping + +Destinations map entity:action to vendor event names: + +```typescript +const GA4_EVENT_MAP: Record = { + "page:viewed": "page_view", + "product:viewed": "view_item", + "product:added": "add_to_cart", + "order:completed": "purchase", +}; +``` diff --git a/.claude/rules/gateway.md b/.claude/rules/gateway.md new file mode 100644 index 0000000..4ed0c10 --- /dev/null +++ b/.claude/rules/gateway.md @@ -0,0 +1,35 @@ +--- +paths: + - "packages/gateway/**" +--- + +# Gateway Standards + +## Request Flow + +``` +POST /collect + → CORS preflight (OPTIONS) + → Auth check (bearer token or x-api-key) + → Parse JSON body: { events: JctEvent[], consent?: ConsentState } + → Apply client-reported consent + → Per event: set context, identify if userId, track(entity, action, props) + → Flush immediately + → Return { ok: true, received: count } +``` + +## Edge-First Design + +- **Flush immediately** after processing — edge functions are short-lived +- No batching or queueing at gateway level (client SDK handles that) +- Uses only Web Standard APIs: Request, Response, URL, fetch, JSON +- Zero platform-specific imports + +## Server Context Enrichment + +Gateway extracts server-side context per request: +- IP: `cf-connecting-ip` → `x-forwarded-for` → `x-real-ip` +- Geo: `cf-ipcountry`, `cf-ipregion`, `cf-ipcity` +- User-Agent, Referer + +Merged with client context via `resolveContext` closure. diff --git a/.claude/rules/packages.md b/.claude/rules/packages.md new file mode 100644 index 0000000..f536068 --- /dev/null +++ b/.claude/rules/packages.md @@ -0,0 +1,72 @@ +--- +paths: + - "packages/**" +--- + +# Package Standards + +## Dependency Layering + +Packages form a strict hierarchy. No circular deps. + +``` +@junctionjs/{astro,next} <- Framework integrations +@junctionjs/destination-* <- Destinations +@junctionjs/{client,gateway} <- Runtime wrappers +@junctionjs/core <- Foundation +``` + +| Package type | How it depends on core | +|---|---| +| `client`, `gateway` | `dependencies` | +| `destination-*` | `peerDependencies` | +| Framework integrations | `peerDependencies` on core + client | + +- Destinations must never import from `client` or `gateway` +- Core has no workspace dependencies (only Zod) +- No package may depend on a package in a higher layer + +## ESM-Only Build + +All packages output ESM only. No CJS. + +```bash +tsup src/index.ts --format esm --dts --sourcemap --target es2022 --no-config +``` + +- Always: `--format esm --dts --sourcemap --target es2022 --no-config` +- Mark workspace dependencies as `--external` +- Mark framework dependencies as `--external` +- No tsup config files — CLI flags only +- Output to `dist/` + +## Package Exports + +All packages use `@junctionjs/*` scope. + +- Destinations: `@junctionjs/destination-{provider}` +- Framework integrations: `@junctionjs/{framework}` + +```json +"exports": { + ".": { + "import": "./dist/index.js", + "types": "./dist/index.d.ts" + } +} +``` + +- ESM only — no `require` condition +- Every export needs both `.js` and `.d.ts` +- `files` field: `["dist", "README.md"]` +- `publishConfig`: `{ "access": "public", "provenance": true }` + +## Code Style (Biome) + +- Double quotes, always semicolons, trailing commas everywhere +- 2-space indent, 120 char line width +- Unused variables/imports: warn (not error) +- `noExplicitAny`: off, `noNonNullAssertion`: off +- Import organization enabled (Biome sorts imports) +- Never add ESLint or Prettier configs +- Don't disable Biome rules without good reason diff --git a/.claude/rules/testing.md b/.claude/rules/testing.md new file mode 100644 index 0000000..1cf8ce5 --- /dev/null +++ b/.claude/rules/testing.md @@ -0,0 +1,103 @@ +--- +paths: + - "**/*.test.ts" +--- + +# Testing Standards + +## Vitest Setup + +- Centralized config at root `vitest.config.ts` +- Node environment by default; `@vitest-environment happy-dom` for DOM tests +- Globals enabled (`describe`, `it`, `expect`, `vi` available without import) +- Tests co-located: `packages/*/src/**/*.test.ts` + +## Structure + +```typescript +describe("ConsentManager", () => { // Module/class + describe("initialization", () => { // Feature group + it("starts with the default state", () => { // Behavior + }); + }); +}); +``` + +- 2-3 levels of `describe` nesting +- `it` statements describe behavior, not functions +- Use `// ─── section name ───` dividers for major sections + +## Fake Timers + +```typescript +beforeEach(() => { vi.useFakeTimers(); }); +afterEach(() => { vi.useRealTimers(); }); +``` + +- Use `vi.advanceTimersByTime(ms)` for sync advancement +- Use `await vi.advanceTimersByTimeAsync(ms)` when microtasks need to resolve + +## Mock Patterns + +```typescript +// vi.fn() — new functions +onConsent: vi.fn() +init: vi.fn().mockResolvedValue(undefined) +send: vi.fn().mockRejectedValue(new Error("Network error")) +transform: vi.fn((event) => ({ transformed: true, event })) + +// vi.spyOn() — existing objects (always suppress output) +vi.spyOn(console, "error").mockImplementation(() => {}) + +// vi.stubGlobal() — browser globals in Node tests +vi.stubGlobal("navigator", { sendBeacon: vi.fn() }) +``` + +- `vi.fn()` for mock objects in factories +- `vi.spyOn()` only for existing objects (console, timers) +- Always `.mockImplementation(() => {})` on console spies +- Reset with `.mockClear()` in `beforeEach` if reusing across tests + +## Test Factories + +```typescript +function makeEvent(overrides?: Partial): JctEvent { + return { + entity: "test", + action: "tracked", + properties: {}, + context: {}, + user: { anonymousId: "anon-123" }, + timestamp: new Date().toISOString(), + id: "evt-001", + version: "1.0.0", + source: { type: "client", name: "test", version: "0.0.0" }, + ...overrides, + }; +} + +function mockDestination(overrides?: Partial): Destination { + return { + name: "test-destination", + version: "0.1.0", + consent: ["analytics"], + runtime: "both", + init: vi.fn().mockResolvedValue(undefined), + transform: vi.fn((event) => ({ transformed: true, event })), + send: vi.fn().mockResolvedValue(undefined), + ...overrides, + }; +} +``` + +- `make*` for data objects, `mock*` for objects with spied methods +- Accept `Partial` and spread overrides last +- Provide complete, sensible defaults +- Co-locate factories in each test file (no shared test utils) + +## Rules + +- Every test file is self-contained (own factories, own setup) +- Clean up in `afterEach`: restore timers, clear mocks +- No shared mutable state between tests +- Behavior-focused test names: "notifies listeners on change", not "test notify" diff --git a/.claude/settings.local.json b/.claude/settings.local.json new file mode 100644 index 0000000..827c0aa --- /dev/null +++ b/.claude/settings.local.json @@ -0,0 +1,27 @@ +{ + "hooks": { + "Notification": [ + { + "hooks": [ + { + "type": "command", + "command": "curl -sf -X POST -H \"Content-Type: application/json\" -H \"X-Emdash-Token: $EMDASH_HOOK_TOKEN\" -H \"X-Emdash-Pty-Id: $EMDASH_PTY_ID\" -H \"X-Emdash-Event-Type: notification\" -d @- \"http://127.0.0.1:$EMDASH_HOOK_PORT/hook\" || true" + } + ] + } + ], + "Stop": [ + { + "hooks": [ + { + "type": "command", + "command": "curl -sf -X POST -H \"Content-Type: application/json\" -H \"X-Emdash-Token: $EMDASH_HOOK_TOKEN\" -H \"X-Emdash-Pty-Id: $EMDASH_PTY_ID\" -H \"X-Emdash-Event-Type: stop\" -d @- \"http://127.0.0.1:$EMDASH_HOOK_PORT/hook\" || true" + } + ] + } + ] + }, + "permissions": { + "allow": ["Bash(git add:*)", "Bash(git commit:*)"] + } +} diff --git a/.github/workflows/deploy-docs.yml b/.github/workflows/deploy-docs.yml new file mode 100644 index 0000000..e790a18 --- /dev/null +++ b/.github/workflows/deploy-docs.yml @@ -0,0 +1,38 @@ +name: Deploy Docs + +on: + push: + branches: [main] + paths: + - "apps/docs/**" + - ".github/workflows/deploy-docs.yml" + +jobs: + deploy: + runs-on: ubuntu-latest + permissions: + contents: read + deployments: write + + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-node@v4 + with: + node-version: 22 + cache: "npm" + + - name: Install dependencies + run: npm ci + + - name: Build docs + run: npm run build --workspace=apps/docs + env: + ASTRO_TELEMETRY_DISABLED: 1 + + - name: Deploy to Cloudflare Pages + uses: cloudflare/wrangler-action@v3 + with: + apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }} + accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} + command: pages deploy apps/docs/dist --project-name=junction-docs diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..0e8bf78 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,89 @@ +# Junction + +Junction is a TypeScript event collection layer for scaling technical teams. Config-as-code, consent-first, isomorphic (browser/Node/edge), destination-agnostic. Think "tag manager for engineers" — more control than GTM, less overhead than a CDP. + +## Quick Start + +```bash +npm install +npm run build # Build all packages (Turborepo) +npm test # Vitest (all packages) +npm run typecheck # TypeScript strict mode +npm run lint # Biome check +npm run format # Biome format --write +``` + +## Monorepo Structure + +``` +packages/ +├── core/ # Isomorphic collector, consent state machine, validation +├── client/ # Browser runtime (sessions, anon IDs, page views) +├── gateway/ # WinterCG edge gateway (Cloudflare Workers, Deno, Bun) +├── debug/ # In-page debug panel +├── auto-collect/ # Automatic event collection +├── astro/ # Astro v5+ integration +├── next/ # Next.js integration +├── cmp-onetrust/ # OneTrust CMP adapter +├── destination-amplitude/ # Amplitude destination +├── destination-ga4/ # GA4 destination +├── destination-meta/ # Meta Pixel + CAPI destination +├── destination-http/ # Generic HTTP destination +├── destination-plausible/ # Plausible destination +apps/ +└── demo/ # Demo application +``` + +## Key Architecture Decisions + +- **Entity:action events** — all events use `track("product", "viewed", props)`, not flat strings +- **Consent state machine** — reactive with queuing, AND logic, strict/lenient modes. See `.claude/rules/consent.md` +- **Plain-object destinations** — factory functions, not classes. See `.claude/rules/destinations.md` +- **ESM only** — no CJS builds. tsup with `--format esm --dts --sourcemap --target es2022 --no-config` +- **Zod schemas** — runtime event validation with strict and lenient modes + +## Gotchas + +- **gtag.js requires Arguments objects** — `window.dataLayer.push()` silently ignores plain Arrays. Always use `function() { dataLayer.push(arguments); }` pattern. See the GA4 destination for reference. +- **Consent queue deduplication** — events are deduped by ID in the consent queue. Always ensure events have unique IDs. +- **System events** — the `_system` entity is reserved. All destinations must return `null` from `transform()` for system events. +- **Dependency layers** — destinations must never import from `client` or `gateway`. Core has no workspace deps. See `.claude/rules/packages.md`. + +## Testing + +```bash +npm test # All tests +npx vitest run packages/core # Single package +npx vitest --watch # Watch mode +npx playwright test --config e2e/playwright.config.ts # E2E +``` + +- Tests co-located with source: `packages/*/src/**/*.test.ts` +- Use `make*` factories for data, `mock*` for spied objects +- See `.claude/rules/testing.md` for full conventions + +## Writing a New Destination + +See `CONTRIBUTING.md` for the full guide. The short version: + +1. Create `packages/destination-/` +2. Implement `Destination` interface (init, transform, send) +3. Use 3-tier event name mapping (config override → default map → generated) +4. Filter `_system` events in `transform()` +5. Add tests + +## Claude Code Setup + +This project uses [superpowers](https://github.com/anthropics/claude-plugins-official/tree/main/superpowers) for development workflow skills (planning, TDD, debugging, code review). + +```bash +claude plugins install superpowers@claude-plugins-official +``` + +Path-scoped rules in `.claude/rules/` load contextually — consent rules when editing core, destination rules when editing destinations, etc. + +## Links + +- Product context: `docs/product/` (mission, roadmap, tech stack) +- Contributing guide: `CONTRIBUTING.md` +- Release process: `RELEASING.md` diff --git a/apps/docs/astro.config.mjs b/apps/docs/astro.config.mjs new file mode 100644 index 0000000..bb34062 --- /dev/null +++ b/apps/docs/astro.config.mjs @@ -0,0 +1,63 @@ +import starlight from "@astrojs/starlight"; +import { defineConfig } from "astro/config"; + +export default defineConfig({ + integrations: [ + starlight({ + title: "Junction", + description: "Developer-native event collection and routing for scaling teams.", + social: [ + { + icon: "github", + label: "GitHub", + href: "https://github.com/tyssejc/junction", + }, + ], + editLink: { + baseUrl: "https://github.com/tyssejc/junction/edit/main/apps/docs/", + }, + sidebar: [ + { label: "What is Junction?", link: "/" }, + { + label: "Getting Started", + items: [{ label: "Quickstart", link: "/getting-started/quickstart/" }], + }, + { + label: "Concepts", + items: [ + { label: "Philosophy", link: "/concepts/philosophy/" }, + { label: "Events", link: "/concepts/events/" }, + { label: "Consent", link: "/concepts/consent/" }, + { label: "Validation", link: "/concepts/validation/" }, + { label: "Architecture", link: "/concepts/architecture/" }, + ], + }, + { + label: "Destinations", + items: [ + { label: "Overview", link: "/destinations/overview/" }, + { label: "GA4", link: "/destinations/ga4/" }, + { label: "Amplitude", link: "/destinations/amplitude/" }, + { label: "Meta", link: "/destinations/meta/" }, + { label: "Plausible", link: "/destinations/plausible/" }, + { label: "HTTP", link: "/destinations/http/" }, + ], + }, + { + label: "Integrations", + items: [ + { label: "Next.js", link: "/integrations/nextjs/" }, + { label: "Astro", link: "/integrations/astro/" }, + ], + }, + { + label: "Product", + items: [ + { label: "Mission", link: "/product/mission/" }, + { label: "Roadmap", link: "/product/roadmap/" }, + ], + }, + ], + }), + ], +}); diff --git a/apps/docs/package.json b/apps/docs/package.json new file mode 100644 index 0000000..ecd1870 --- /dev/null +++ b/apps/docs/package.json @@ -0,0 +1,16 @@ +{ + "name": "@junctionjs/docs", + "version": "0.0.1", + "private": true, + "type": "module", + "scripts": { + "dev": "astro dev", + "build": "astro build", + "preview": "astro preview" + }, + "dependencies": { + "astro": "^5.0.0", + "@astrojs/starlight": "^0.34.0", + "sharp": "^0.33.0" + } +} diff --git a/apps/docs/src/content.config.ts b/apps/docs/src/content.config.ts new file mode 100644 index 0000000..7fbcf2c --- /dev/null +++ b/apps/docs/src/content.config.ts @@ -0,0 +1,7 @@ +import { defineCollection } from "astro:content"; +import { docsLoader } from "@astrojs/starlight/loaders"; +import { docsSchema } from "@astrojs/starlight/schema"; + +export const collections = { + docs: defineCollection({ loader: docsLoader(), schema: docsSchema() }), +}; diff --git a/apps/docs/src/content/docs/concepts/architecture.mdx b/apps/docs/src/content/docs/concepts/architecture.mdx new file mode 100644 index 0000000..c195968 --- /dev/null +++ b/apps/docs/src/content/docs/concepts/architecture.mdx @@ -0,0 +1,365 @@ +--- +title: Architecture +description: Junction's system design, data flow, and package structure. +--- + +Built for teams migrating away from proprietary tag managers (Adobe Launch, Google Tag Manager) toward a developer-owned, code-first analytics infrastructure. + +--- + +## Design Principles + +**Events are the primitive, not tags.** Traditional TMS thinking says "fire a tag when a condition is met." Junction inverts this: you emit typed events, and destinations decide what to do with them. This decouples instrumentation from vendor-specific concerns and makes consent gating, schema validation, and destination hot-swapping possible. + +**One global, not two.** walkerOS puts both `window.elb` and `window.walker` on the page. Junction exposes a single `window.jct` (configurable) that IS the collector. Track events, manage consent, identify users — all from one object. + +**Config-as-code, not config-as-UI-state.** Your entire analytics configuration lives in TypeScript files under version control. Environment-specific settings use standard patterns (env vars, conditional logic). Changes go through PRs, get reviewed, and deploy via CI/CD. This solves the Adobe Launch "Latest" problem and GTM's opaque workspace model. + +**Consent is a first-class state machine.** Not an afterthought bolted on via GTM Consent Mode or fragmented Launch point-solutions. Events queue while consent is pending, then flush with updated user properties when consent resolves. Every destination declares its consent requirements. DNT and GPC are respected by default. + +**Schema validation catches errors before they reach destinations.** Define contracts per entity+action pair using Zod. Invalid events are caught at the source, not discovered weeks later when a funnel breaks. This is the single biggest gap in every existing TMS. + +**Runtime-agnostic.** The core runs anywhere JavaScript runs. The client package adds browser specifics. The gateway package runs on any WinterCG-compatible edge runtime (Cloudflare Workers, Deno Deploy, Vercel Edge, Bun). + +--- + +## Package Architecture + +``` +@junctionjs/ +├── core/ # Isomorphic core (types, collector, consent, validation) +│ └── src/ +│ ├── types.ts # The entire type system +│ ├── collector.ts # Event collector (the runtime engine) +│ ├── consent.ts # Consent state machine + event queue +│ ├── validation.ts # Zod-based schema validation +│ └── index.ts # Public exports +│ +├── client/ # Browser-specific wrapper +│ └── src/ +│ └── index.ts # DOM context, session, anon ID, auto page views +│ +├── astro/ # Astro v5+ integration +│ └── src/ +│ ├── index.ts # Astro integration (injectScript, addMiddleware) +│ ├── middleware.ts # SSR middleware (session, geo, IP enrichment) +│ └── collect-endpoint.ts # Server-side /api/collect route +│ +├── gateway/ # Edge runtime forward proxy +│ └── src/ +│ └── index.ts # WinterCG-compatible request handler +│ +├── destination-amplitude/ # Amplitude (Browser SDK + HTTP API) +├── destination-ga4/ # Google Analytics 4 (gtag + Measurement Protocol) +└── destination-meta/ # Meta Pixel + Conversions API +``` + +--- + +## Data Flow + +### Client-Side Flow + +``` +Developer calls Event is Consent Destinations +jct.track("product","added") validated via gate checks transform and + │ Zod contract consent state send to vendor + │ │ │ │ + ▼ ▼ ▼ ▼ +┌─────────────┐ ┌───────────┐ ┌──────────┐ ┌──────────────┐ ┌──────────┐ +│ track() │→ │ Validator │→ │ Consent │→ │ Buffer │→ │ Send │ +│ identify() │ │ (Zod) │ │ Manager │ │ (batch) │ │ (async) │ +│ consent() │ │ │ │ │ │ │ │ │ +└─────────────┘ └───────────┘ └──────────┘ └──────────────┘ └──────────┘ + │ │ │ + invalid events pending events sends to: + are dropped are queued - Amplitude + (strict) or until consent - GA4 (gtag) + warned (lenient) resolves - Meta Pixel +``` + +### Server-Side Flow (Gateway) + +``` +Client POSTs to Gateway enriches Server-side destinations +/api/collect with IP, geo, UA (no client-side secrets) + │ │ │ + ▼ ▼ ▼ +┌───────────┐ ┌────────────────┐ ┌────────────────────────────┐ +│ Client │→ │ Gateway │→ │ Server Destinations │ +│ Browser │ │ (Edge Worker) │ │ - Amplitude HTTP API │ +│ │ │ + IP/Geo │ │ - Meta Conversions API │ +│ │ │ + Session │ │ - BigQuery / Warehouse │ +└───────────┘ └────────────────┘ └────────────────────────────┘ +``` + +### Astro-Specific Flow + +``` +1. Build time: + astro.config.mjs → junction() integration → injects scripts + middleware + +2. SSR request: + Request → Middleware (session, geo) → Page render → Response + +3. Client hydration: + before-hydration script → createClient() → window.jct ready + +4. View Transitions: + astro:page-load event → jct.track("page","viewed") → destinations +``` + +--- + +## Consent Architecture + +### State Machine + +``` + ┌─────────┐ + Initial → │ PENDING │ ← No explicit choice yet + └────┬────┘ + │ + ┌──────────┴──────────┐ + ▼ ▼ + ┌───────────┐ ┌───────────┐ + │ GRANTED │ │ DENIED │ + └───────────┘ └───────────┘ + │ │ + └──────────┬──────────┘ + ▼ + Can change at any time + (user updates preferences) +``` + +### Event Queuing + +When consent is pending (user hasn't interacted with the CMP yet), events are queued in memory. When consent state changes: + +1. Queued events are replayed to newly-permitted destinations +2. User properties on queued events are updated (identity may have changed) +3. Destinations receive an `onConsent()` callback to sync their own consent state (e.g., Google Consent Mode v2) + +### Consent Categories + +| Category | Description | Example Destinations | +|-------------------|-------------------------------------|-----------------------| +| `necessary` | Always allowed | Error tracking | +| `analytics` | Site usage analytics | Amplitude, GA4 | +| `marketing` | Advertising and retargeting | Meta Pixel, Google Ads| +| `personalization` | Content personalization | Optimizely, LaunchDarkly | +| `social` | Social media features | Share widgets | + +--- + +## Schema Validation + +### Contract Definition + +```typescript +import { z } from "zod"; +import { schemas } from "@junctionjs/core"; + +// This contract says: "product:added events MUST have these fields, +// with these types, or they get dropped before reaching any destination." +const productAddedContract = { + entity: "product", + action: "added", + version: "1.0.0", + mode: "strict", // "strict" = drop invalid, "lenient" = warn + pass + schema: z.object({ + product_id: z.string().min(1), + name: z.string().min(1), + price: z.number().nonnegative(), + currency: z.string().length(3), + quantity: z.number().int().positive(), + }), +}; +``` + +### What This Prevents + +| Scenario | Without Validation | With Junction | +|---|---|---| +| Dev pushes `addToCart` instead of `product:added` | Amplitude funnel breaks silently | Build-time type error + runtime validation | +| Price sent as string `"19.99"` | Amplitude coerces unpredictably | Zod catches it, event dropped or coerced | +| Missing `product_id` | GA4 event fires without item_id | Contract rejects, logged as validation error | +| New dev forgets `currency` field | Revenue reports show $0 | Strict mode blocks the event | + +--- + +## Destination Plugin Interface + +Writing a custom destination requires implementing ONE interface with THREE required fields: + +```typescript +const myDestination: Destination = { + name: "my-service", + version: "1.0.0", + consent: ["analytics"], // required consent categories + runtime: "client", // "client" | "server" | "both" + + init(config) { }, // setup (load SDKs, etc.) + transform(event) { }, // convert JctEvent → vendor format + send(payload, config) { }, // deliver to vendor API + + // Optional: + onConsent(state) { }, // react to consent changes + teardown() { }, // cleanup on shutdown +}; +``` + +The `transform` function replaces walkerOS's "mapping" DSL. It's just TypeScript — you can use whatever logic you want, including conditional mapping, default values, property renaming, or filtering events entirely (return `null` to skip). + +--- + +## Git-Based Workflow + +### Branch Strategy (Maps to Your Original Vision) + +``` +main (production) +├── staging ← PR from feature branches +│ ├── feature/add-amplitude +│ ├── feature/update-consent-categories +│ └── fix/ga4-purchase-event-mapping +└── dev ← experimental / local testing +``` + +### CI/CD Pipeline + +```yaml +# .github/workflows/junction.yml +name: Junction Deploy + +on: + push: + branches: [main, staging] + paths: ['config/**', 'packages/**'] + +jobs: + validate: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - run: npm ci + - run: npm run typecheck # TypeScript catches config errors + - run: npm run test:contracts # Validate all event contracts + - run: npm run test:destinations # Test destination transforms + + deploy-gateway: + needs: validate + runs-on: ubuntu-latest + if: github.ref == 'refs/heads/main' + steps: + - run: npx wrangler deploy # Deploy gateway to Cloudflare Workers + env: + CLOUDFLARE_API_TOKEN: ${{ secrets.CF_TOKEN }} + + deploy-site: + needs: validate + runs-on: ubuntu-latest + steps: + - run: npm run build # Astro build (includes Junction client) + - run: npx wrangler pages deploy # Deploy to Cloudflare Pages (or Vercel, Netlify) +``` + +### What This Solves + +| Problem (from your doc) | Junction Solution | +|---|---| +| Launch saves to "Latest", breaking prod | Changes require PR + review + merge to main | +| GTM workspace model is unintuitive | Standard Git branches, standard PR workflow | +| No validation in Launch | Zod contracts + CI/CD type checking | +| Consent is "figure it out" | First-class consent state machine, per-destination gating | +| Closed source, can't debug | Everything is TypeScript you own | +| Team collaboration is hard | Git — the collaboration tool developers already know | + +--- + +## Astro v5+ Integration Details + +### View Transitions + +The biggest gotcha with Astro analytics: View Transitions don't fire `DOMContentLoaded` on navigation. Junction handles this by: + +1. Injecting at `before-hydration` (runs before islands activate) +2. Listening to `astro:page-load` (fires on initial load AND every View Transition) +3. Deduplicating the initial page view (client tracks it; View Transition listener skips first fire) + +### Middleware (Server-Side Enrichment) + +The Astro middleware runs on every SSR request and extracts: +- Client IP (from `cf-connecting-ip`, `x-forwarded-for`, etc.) +- Geo data (from Cloudflare/Vercel headers) +- User agent, referrer, accept-language +- Session ID (managed via HttpOnly cookie) + +This data is available in `Astro.locals.junction` and forwarded to the gateway. + +### Experimental CSP Support + +Astro 5.9+ supports automatic CSP hash generation for inline scripts. Junction's injected scripts are compatible — no `unsafe-inline` needed. + +--- + +## Comparison to Existing Solutions + +| Feature | Junction | walkerOS | RudderStack | GTM | Adobe Launch | +|---|---|---|---|---|---| +| **Config model** | TypeScript in Git | JSON/TS in code | TOML config | GUI + JSON export | GUI + "Library" | +| **Version control** | Native Git | Manual | Manual | Workspaces | "Latest" lol | +| **CI/CD** | GitHub Actions | None | Docker/K8s | None | None | +| **Consent** | State machine + queue | State machine + queue | Transformations | Consent Mode (opaque) | "Figure it out" | +| **Schema validation** | Zod contracts | Basic event validation | Via transformations | None | None | +| **Window globals** | 1 (`jct`) | 2 (`elb`, `walker`) | 1 (`rudderanalytics`) | 2+ (`dataLayer`, `gtag`) | 1 (`_satellite`) | +| **Edge gateway** | WinterCG (any runtime) | Node.js | Go server (heavy) | Java container (heavy) | Proprietary | +| **Astro support** | First-class integration | None | JS SDK (manual) | Script tag | Script tag | +| **Team model** | Git PRs | N/A | N/A | Workspaces | "Latest" | +| **License** | MIT | MIT | Apache 2.0 | Proprietary | Proprietary | +| **Operational cost** | Edge function (~$0) | Self-managed | K8s cluster ($$$) | Free (Google-owned) | $$$$ | + +--- + +## Migration Path: Adobe Analytics → Amplitude + +For your specific client engagement: + +### Phase 1: Parallel Tracking (Weeks 1-2) +- Deploy Junction alongside existing Adobe Launch +- Configure Amplitude destination (client-side) +- Map existing Adobe events to Junction event taxonomy +- Validate with contracts that data quality matches Adobe + +### Phase 2: Add Destinations (Weeks 3-4) +- Add GA4 destination (replacing any existing GA setup) +- Add Meta Pixel + CAPI destination +- Deploy gateway for server-side event forwarding +- Set up consent management with existing CMP + +### Phase 3: Cut Over (Week 5) +- Remove Adobe Launch container script +- Junction becomes the sole event collection layer +- Adobe contract ends, no dependency remains + +### Phase 4: Optimize (Ongoing) +- Add schema contracts for all critical events +- Set up CI/CD validation pipeline +- Add monitoring/alerting for destination errors +- Iterate on event taxonomy + +--- + +## What's Not Built Yet (Roadmap) + +1. **Rules Engine** — Auto-emit events based on URL/DOM/cookie conditions (your original doc's concept). Currently events are emitted manually via `jct.track()`. The rules engine would add declarative auto-tracking. + +2. **CMP Integrations** — Pre-built adapters for OneTrust, Cookiebot, Usercentrics that automatically sync consent state to Junction. + +3. **Debug Panel** — Browser devtools panel showing real-time event flow, consent state, destination status. Replaces GTM Preview Mode and the AEP Debugger. + +4. **Event Replay** — Record events in staging, replay against production destination configs to test changes without live traffic. + +5. **Monitoring Dashboard** — Production health monitoring: destination error rates, event volumes, validation failures. Optional — could be a simple Grafana/Datadog integration. + +6. **More Destinations** — Google Ads, LinkedIn Insight, TikTok Pixel, Pinterest Tag, Snowflake, BigQuery, S3/R2, Webhook (generic HTTP). diff --git a/apps/docs/src/content/docs/concepts/consent.mdx b/apps/docs/src/content/docs/concepts/consent.mdx new file mode 100644 index 0000000..0f4728f --- /dev/null +++ b/apps/docs/src/content/docs/concepts/consent.mdx @@ -0,0 +1,77 @@ +--- +title: Consent +description: Junction's consent state machine and event queuing. +--- + +## Consent-First Design + +Consent in Junction is not an afterthought bolted onto an existing system. It's a first-class state machine that controls event flow from the moment the collector initializes. + +## State Machine + +``` + ┌─────────┐ + Initial → │ PENDING │ ← No explicit choice yet + └────┬────┘ + │ + ┌──────────┴──────────┐ + ▼ ▼ + ┌───────────┐ ┌───────────┐ + │ GRANTED │ │ DENIED │ + └───────────┘ └───────────┘ + │ │ + └──────────┬──────────┘ + ▼ + Can change at any time + (user updates preferences) +``` + +Every consent category starts in a configurable default state (typically `pending`). Events are queued until consent resolves. + +## Consent Categories + +| Category | Description | Example Destinations | +|----------|-------------|---------------------| +| `necessary` | Always allowed | Error tracking | +| `analytics` | Site usage analytics | Amplitude, GA4 | +| `marketing` | Advertising and retargeting | Meta Pixel, Google Ads | +| `personalization` | Content personalization | Optimizely, LaunchDarkly | +| `social` | Social media features | Share widgets | + +## Event Queuing + +When consent is pending: + +1. Events are queued in memory (with configurable size limits) +2. When consent resolves, queued events are replayed to permitted destinations +3. User properties on queued events are updated (identity may have changed since queuing) +4. Destinations receive an `onConsent()` callback to sync their own consent state + +## Setting Consent + +```typescript +// From your CMP callback or consent banner +jct.consent({ + analytics: "granted", + marketing: "denied", + personalization: "granted", +}); +``` + +## Per-Destination Consent + +Each destination declares which consent categories it requires: + +```typescript +{ + destination: ga4, + config: { measurementId: "G-XXXXXXXXXX" }, + consent: ["analytics"], // requires analytics consent +} +``` + +A destination only receives events when **all** its required categories are granted (AND logic). + +## DNT and GPC + +Junction respects `Do Not Track` and `Global Privacy Control` signals by default. When these signals are detected, marketing and analytics consent categories are automatically denied. diff --git a/apps/docs/src/content/docs/concepts/events.mdx b/apps/docs/src/content/docs/concepts/events.mdx new file mode 100644 index 0000000..0f7bece --- /dev/null +++ b/apps/docs/src/content/docs/concepts/events.mdx @@ -0,0 +1,62 @@ +--- +title: Events +description: Junction's entity:action event model. +--- + +## Entity:Action Model + +Junction uses a structured event model where every event has an **entity** and an **action**: + +```typescript +jct.track("product", "viewed", { product_id: "SKU-123" }); +// ^^^^^^ ^^^^^^ +// entity action +``` + +This is different from flat event strings like `view_item` or `addToCart`. The entity:action model gives you: + +- **Consistent naming** — events are always `entity:action`, never ambiguous +- **Schema validation** — define contracts per entity+action pair +- **Destination mapping** — each destination translates to its own naming convention + +## Common Events + +| Entity | Action | Description | +|--------|--------|-------------| +| `page` | `viewed` | Page view | +| `product` | `viewed` | Product detail view | +| `product` | `added` | Added to cart | +| `order` | `completed` | Purchase completed | +| `form` | `submitted` | Form submission | +| `cta` | `clicked` | Call-to-action click | + +## Properties + +The third argument to `track()` is a properties object. Properties are passed to destinations after transformation: + +```typescript +jct.track("product", "viewed", { + product_id: "SKU-123", + name: "Junction T-Shirt", + price: 29.99, + currency: "USD", + category: "Apparel", +}); +``` + +## System Events + +The `_system` entity is reserved for internal lifecycle events (initialization, consent changes, errors). Destinations automatically filter system events — you don't need to handle them. + +## Identity + +Use `identify()` to associate events with a user: + +```typescript +jct.identify("user-123", { + email: "user@example.com", + plan: "pro", +}); +``` + +Anonymous IDs are generated automatically and persist across sessions via localStorage. diff --git a/apps/docs/src/content/docs/concepts/philosophy.mdx b/apps/docs/src/content/docs/concepts/philosophy.mdx new file mode 100644 index 0000000..1c12c0c --- /dev/null +++ b/apps/docs/src/content/docs/concepts/philosophy.mdx @@ -0,0 +1,80 @@ +--- +title: Philosophy +description: The design principles, trade-offs, and opinionated defaults behind Junction. +--- + +## Why Junction exists + +Analytics implementation infrastructure is broken for scaling technical teams. Legacy tag managers were built for marketers adding snippets to websites — they rely on opaque UIs, brittle rule-based logic, and workflows that don't fit into modern engineering practices. Full CDPs solve some of these problems but introduce more scope, cost, and organizational overhead than most scaling companies need. + +Junction occupies the gap: more control than a tag manager, less overhead than a CDP. + +## Design principles + +**Events are the primitive, not tags.** Traditional tag management says "fire a tag when a condition is met." Junction inverts this: you emit typed events, and destinations decide what to do with them. This decouples instrumentation from vendor-specific concerns and makes consent gating, schema validation, and destination hot-swapping possible. + +**Config as code, not config as UI state.** Your entire analytics configuration lives in TypeScript files under version control. Changes go through PRs, get reviewed, and deploy via CI/CD. This solves the Adobe Launch "Latest" problem and GTM's opaque workspace model. If you can't `git diff` it, you can't trust it. + +**Consent is a state machine, not a flag.** Consent isn't a boolean you check once. It's a reactive system where state changes over time, events queue while decisions are pending, and destinations independently gate on the categories they require. Junction treats this as a first-class runtime concern, not an afterthought bolted on after the fact. + +**Schema validation catches errors at the source.** Define contracts per event using Zod. Invalid events are caught before they reach any destination — not discovered weeks later when a funnel breaks or a revenue report shows $0. This is the single biggest gap in every existing tag management system. + +**Plain objects, not classes.** Destinations are factory functions that return plain objects. This makes them tree-shakeable, composable, and easy to test. No inheritance hierarchies, no `this` binding surprises, no framework lock-in. + +**One global, not two.** Some libraries put multiple objects on the window (`dataLayer` + `gtag`, `elb` + `walker`). Junction exposes a single `window.jct` that is the collector. Track events, manage consent, identify users — all from one object. + +## Opinionated defaults + +Junction ships with strong defaults that prioritize correctness and user privacy. You can opt out of any of them, but the defaults are intentional. + +| Default | Why | Override | +|---------|-----|----------| +| Consent starts as `pending` | Events should queue until the user makes a choice, not fire optimistically | Set `consent.default` to `granted` per category | +| DNT/GPC respected | Browser privacy signals should mean something | Disable in consent config | +| Strict validation drops invalid events | Bad data shouldn't silently corrupt your analytics | Use `lenient` mode to warn instead | +| System events filtered from destinations | Internal lifecycle events are not vendor analytics | Return `null` from `transform()` (already the convention) | +| ESM only | Tree-shaking, modern bundlers, no dual-package hazard | None — this is non-negotiable | + +These defaults exist because the cost of getting them wrong is high and silent. A dropped event is visible. A corrupted event is not. + +## Trade-offs we accept + +Every design choice has a cost. Here's where Junction intentionally trades one thing for another. + +**Code-first means no GUI.** There is no drag-and-drop interface for configuring destinations or building event rules. If your team needs a marketer-operated UI to manage tags, Junction is not the right tool. We believe the teams who benefit most from Junction are already comfortable with TypeScript and pull requests. + +**Typed events mean more upfront work.** Defining entity:action pairs and Zod schemas takes more effort than pushing an object into a `dataLayer`. The payoff is that your analytics implementation is self-documenting, self-validating, and refactorable. The work shifts from "debug broken funnels" to "define contracts once." + +**Consent-first means some events may never fire.** If a user denies consent, marketing destinations get nothing. Junction won't help you work around that. The queue exists to defer events while consent is pending, not to circumvent user choices. + +**Destination-agnostic means no deep vendor integrations.** Junction's destination interface is intentionally simple: `init`, `transform`, `send`. It won't configure your GA4 custom dimensions or manage your Amplitude taxonomies. It handles collection, validation, consent, and delivery — what happens inside the vendor is the vendor's domain. + +## What Junction is not + +Clarity about scope is as important as the feature list. + +- **Not a CDP.** No identity resolution, no customer profiles, no audience building, no activation workflows. Junction is CDP-compatible — it can feed data into one — but it doesn't try to become one. +- **Not a customer 360.** Junction doesn't unify user identities across devices or channels. It passes identity information (anonymous IDs, user IDs) to destinations, which handle resolution in their own systems. +- **Not a tag manager replacement for non-technical teams.** If your analytics workflow depends on a UI that marketers operate directly, Junction adds friction rather than removing it. +- **Not trying to out-Segment Segment.** The goal is not to build the broadest platform. It's to be the best implementation layer for teams that want speed, control, and correctness. + +## What Junction will become + +Junction should own: implementation, collection, validation, consent-aware routing, observability, and developer workflow. + +Junction should remain: CDP-compatible, warehouse-friendly, and identity-ready at the event level. + +Junction should not become responsible for: profiles, audiences, customer unification, or activation. At least not in the near term. These are important capabilities, but they belong in the tools that specialize in them. + +## The agent-native thesis + +AI agents are rapidly becoming how scaling companies build and ship software. No existing event collection layer is designed for agent-driven implementation. + +Tag managers require point-and-click UIs that agents can't operate. CDPs require complex configuration flows optimized for humans navigating dashboards. Junction is different: + +- **TypeScript config** — agents read and write code natively +- **Typed interfaces** — agents can discover and use the API without documentation +- **Schema contracts** — agents can validate their own instrumentation +- **Deterministic behavior** — no hidden state, no UI-dependent side effects + +The companies most likely to adopt Junction are also the fastest adopters of AI-assisted development. Junction is built to meet them where they are. diff --git a/apps/docs/src/content/docs/concepts/validation.mdx b/apps/docs/src/content/docs/concepts/validation.mdx new file mode 100644 index 0000000..81370ab --- /dev/null +++ b/apps/docs/src/content/docs/concepts/validation.mdx @@ -0,0 +1,61 @@ +--- +title: Validation +description: Zod-based schema contracts for event data quality. +--- + +## Why Validate? + +Without validation, data quality issues are discovered weeks later when a funnel breaks, a report shows $0 revenue, or a destination silently drops malformed events. Junction catches these at the source. + +## Schema Contracts + +Define contracts per entity+action pair using Zod: + +```typescript +import { z } from "zod"; + +const schemas = { + "product:added": { + version: "1.0.0", + mode: "strict", + schema: z.object({ + product_id: z.string().min(1), + name: z.string().min(1), + price: z.number().nonnegative(), + currency: z.string().length(3), + quantity: z.number().int().positive(), + }), + }, +}; +``` + +## Validation Modes + +| Mode | Invalid Event Behavior | +|------|----------------------| +| `strict` | Event is dropped, error logged | +| `lenient` | Warning logged, event passes through | + +Use `strict` for critical events (purchases, sign-ups) and `lenient` during development or for non-critical events. + +## What This Prevents + +| Scenario | Without Validation | With Junction | +|----------|-------------------|---------------| +| `addToCart` instead of `product:added` | Funnel breaks silently | Type error + runtime validation | +| Price sent as string `"19.99"` | Destination coerces unpredictably | Zod catches it | +| Missing `product_id` | GA4 event fires without item_id | Contract rejects, logged | +| New dev forgets `currency` field | Revenue reports show $0 | Strict mode blocks the event | + +## Adding Contracts to Your Config + +```typescript +import { createClient } from "@junctionjs/client"; + +const jct = createClient({ + schemas, + destinations: [/* ... */], +}); +``` + +Events without a matching contract pass through unvalidated. Add contracts incrementally — start with your most critical events. diff --git a/apps/docs/src/content/docs/destinations/amplitude.mdx b/apps/docs/src/content/docs/destinations/amplitude.mdx new file mode 100644 index 0000000..13c6055 --- /dev/null +++ b/apps/docs/src/content/docs/destinations/amplitude.mdx @@ -0,0 +1,66 @@ +--- +title: Amplitude +description: Send events to Amplitude via the Browser SDK (client) or HTTP V2 API (server). +--- + +import { Tabs, TabItem } from '@astrojs/starlight/components'; + +:::note +Full documentation coming soon. +::: + +## Install + + + + ```bash + npm install @junctionjs/destination-amplitude + ``` + + + ```bash + pnpm add @junctionjs/destination-amplitude + ``` + + + ```bash + yarn add @junctionjs/destination-amplitude + ``` + + + +## Usage + +```typescript +import { createCollector } from "@junctionjs/core"; +import { amplitude } from "@junctionjs/destination-amplitude"; + +const collector = createCollector({ + destinations: [ + { + destination: amplitude, + config: { + apiKey: "YOUR_AMPLITUDE_API_KEY", + mode: "client", + }, + }, + ], +}); +``` + +## Features + +- **Browser SDK** — client-side via Amplitude's official `@amplitude/analytics-browser` +- **HTTP V2 API** — server-side sending with no SDK dependency +- **User and session mapping** — forwards Junction identity and session data to Amplitude +- **Event name format** — configurable: `snake_case`, `Title Case`, `entity:action`, or custom function +- **Event name overrides** — customize any mapping via config + +## Default Event Mapping + +| Junction Event | Amplitude Event | +|---|---| +| `page:viewed` | `Page Viewed` | +| `product:viewed` | `Product Viewed` | +| `product:added` | `Product Added` | +| `order:completed` | `Order Completed` | diff --git a/apps/docs/src/content/docs/destinations/ga4.mdx b/apps/docs/src/content/docs/destinations/ga4.mdx new file mode 100644 index 0000000..2738e86 --- /dev/null +++ b/apps/docs/src/content/docs/destinations/ga4.mdx @@ -0,0 +1,67 @@ +--- +title: Google Analytics 4 +description: Send events to GA4 via gtag.js (client) or Measurement Protocol (server). +--- + +import { Tabs, TabItem } from '@astrojs/starlight/components'; + +:::note +Full documentation coming soon. +::: + +## Install + + + + ```bash + npm install @junctionjs/destination-ga4 + ``` + + + ```bash + pnpm add @junctionjs/destination-ga4 + ``` + + + ```bash + yarn add @junctionjs/destination-ga4 + ``` + + + +## Usage + +```typescript +import { createCollector } from "@junctionjs/core"; +import { ga4 } from "@junctionjs/destination-ga4"; + +const collector = createCollector({ + destinations: [ + { + destination: ga4, + config: { + measurementId: "G-XXXXXXXXXX", + consentMode: true, + }, + }, + ], +}); +``` + +## Features + +- **gtag.js** — automatically loads the gtag snippet on the client (configurable) +- **Measurement Protocol** — server-side sending via GA4's HTTP API +- **Consent Mode v2** — native integration with Google's consent signals +- **Recommended events** — default mapping for GA4's recommended event names +- **Event name overrides** — customize any mapping via `eventNameMap` +- **Custom script URL** — self-host or proxy the gtag.js script + +## Default Event Mapping + +| Junction Event | GA4 Event | +|---|---| +| `page:viewed` | `page_view` | +| `product:viewed` | `view_item` | +| `product:added` | `add_to_cart` | +| `order:completed` | `purchase` | diff --git a/apps/docs/src/content/docs/destinations/http.mdx b/apps/docs/src/content/docs/destinations/http.mdx new file mode 100644 index 0000000..fd19b4e --- /dev/null +++ b/apps/docs/src/content/docs/destinations/http.mdx @@ -0,0 +1,60 @@ +--- +title: HTTP (Generic) +description: Send events to any HTTP endpoint — webhooks, custom APIs, or self-hosted analytics. +--- + +import { Tabs, TabItem } from '@astrojs/starlight/components'; + +:::note +Full documentation coming soon. +::: + +## Install + + + + ```bash + npm install @junctionjs/destination-http + ``` + + + ```bash + pnpm add @junctionjs/destination-http + ``` + + + ```bash + yarn add @junctionjs/destination-http + ``` + + + +## Usage + +```typescript +import { createCollector } from "@junctionjs/core"; +import { http } from "@junctionjs/destination-http"; + +const collector = createCollector({ + destinations: [ + { + destination: http({ + url: "https://your-api.example.com/events", + headers: { + Authorization: "Bearer YOUR_TOKEN", + }, + }), + }, + ], +}); +``` + +## Features + +- **Any HTTP endpoint** — POST events to webhooks, custom APIs, or third-party services +- **Configurable headers** — static headers or dynamic per-event headers via `headersFn` +- **Configurable method** — POST, PUT, or PATCH +- **Custom body transform** — reshape event payloads before sending +- **Custom serializer** — swap out `JSON.stringify` for any format +- **Webhooks** — ideal for Slack, Discord, or any webhook-based integration +- **Error handling** — `onError` callback for non-2xx responses diff --git a/apps/docs/src/content/docs/destinations/meta.mdx b/apps/docs/src/content/docs/destinations/meta.mdx new file mode 100644 index 0000000..ab6c947 --- /dev/null +++ b/apps/docs/src/content/docs/destinations/meta.mdx @@ -0,0 +1,67 @@ +--- +title: Meta Pixel + CAPI +description: Send events to Meta via the Pixel (client) and Conversions API (server). +--- + +import { Tabs, TabItem } from '@astrojs/starlight/components'; + +:::note +Full documentation coming soon. +::: + +## Install + + + + ```bash + npm install @junctionjs/destination-meta + ``` + + + ```bash + pnpm add @junctionjs/destination-meta + ``` + + + ```bash + yarn add @junctionjs/destination-meta + ``` + + + +## Usage + +```typescript +import { createCollector } from "@junctionjs/core"; +import { meta } from "@junctionjs/destination-meta"; + +const collector = createCollector({ + destinations: [ + { + destination: meta, + config: { + pixelId: "YOUR_PIXEL_ID", + accessToken: "YOUR_CAPI_ACCESS_TOKEN", + }, + }, + ], +}); +``` + +## Features + +- **Meta Pixel** — client-side event tracking via `fbq()` +- **Conversions API (CAPI)** — server-side event delivery for improved signal quality +- **Event deduplication** — shared `event_id` between Pixel and CAPI prevents double-counting +- **Standard events** — default mapping to Meta's standard event names +- **Advanced matching** — optional hashed PII (email, phone) for better attribution +- **Consent: marketing** — requires marketing consent before sending + +## Default Event Mapping + +| Junction Event | Meta Event | +|---|---| +| `page:viewed` | `PageView` | +| `product:viewed` | `ViewContent` | +| `product:added` | `AddToCart` | +| `order:completed` | `Purchase` | diff --git a/apps/docs/src/content/docs/destinations/overview.mdx b/apps/docs/src/content/docs/destinations/overview.mdx new file mode 100644 index 0000000..741b73c --- /dev/null +++ b/apps/docs/src/content/docs/destinations/overview.mdx @@ -0,0 +1,93 @@ +--- +title: Destinations +description: How Junction routes events to analytics providers and APIs. +--- + +Destinations are where Junction sends your events. Each destination is a plain object with three async functions — `init`, `transform`, and `send` — wired together by the collector at runtime. + +## Available Destinations + +| Destination | Package | Runtime | +|-------------|---------|---------| +| Google Analytics 4 | `@junctionjs/destination-ga4` | Client + Server | +| Amplitude | `@junctionjs/destination-amplitude` | Client + Server | +| Meta Pixel + CAPI | `@junctionjs/destination-meta` | Client + Server | +| Plausible | `@junctionjs/destination-plausible` | Client | +| HTTP (Generic) | `@junctionjs/destination-http` | Server | + +## Configuration Pattern + +Every destination is registered on the collector via its config: + +```typescript +import { createCollector } from "@junctionjs/core"; +import { ga4 } from "@junctionjs/destination-ga4"; + +const collector = createCollector({ + destinations: [ + { + destination: ga4, + config: { + measurementId: "G-XXXXXXXXXX", + }, + }, + ], +}); +``` + +Destinations are factory functions or pre-built objects — never classes. This keeps them tree-shakeable and easy to test. + +## Event Name Mapping + +All destinations use a **3-tier fallback** to resolve event names: + +1. **Config override** — `config.eventNameMap["product:viewed"]` takes priority +2. **Default map** — each destination ships with sensible defaults for common events +3. **Generated name** — if no mapping exists, the name is derived from `entity_action` (or a destination-specific format) + +```typescript +// Example: override a single event name for GA4 +{ + destination: ga4, + config: { + measurementId: "G-XXXXXXXXXX", + eventNameMap: { + "product:viewed": "my_custom_view_item", + }, + }, +} +``` + +### Default Event Mapping + +| Junction Event | GA4 | Amplitude | Meta | +|---|---|---|---| +| `page:viewed` | `page_view` | `Page Viewed` | `PageView` | +| `product:viewed` | `view_item` | `Product Viewed` | `ViewContent` | +| `product:added` | `add_to_cart` | `Product Added` | `AddToCart` | +| `order:completed` | `purchase` | `Order Completed` | `Purchase` | + +## System Events + +The `_system` entity is reserved for Junction's internal lifecycle events (e.g., `_system:initialized`). All destinations must return `null` from `transform()` for system events — they are never forwarded to external providers. + +## Writing a Custom Destination + +Junction destinations implement the `Destination` interface: + +```typescript +interface Destination { + name: string; + version: string; + consent: ConsentCategory[]; + runtime: "client" | "server" | "both"; + + init: (config: TConfig) => Promise | void; + transform: (event: JctEvent, config: TConfig) => unknown | null; + send: (payload: unknown, config: TConfig) => Promise; + onConsent?: (state: ConsentState) => void; + teardown?: () => Promise | void; +} +``` + +See the [Contributing Guide](https://github.com/tyssejc/junction/blob/main/CONTRIBUTING.md) for the full walkthrough on building a new destination. diff --git a/apps/docs/src/content/docs/destinations/plausible.mdx b/apps/docs/src/content/docs/destinations/plausible.mdx new file mode 100644 index 0000000..e7488fb --- /dev/null +++ b/apps/docs/src/content/docs/destinations/plausible.mdx @@ -0,0 +1,57 @@ +--- +title: Plausible +description: Privacy-first analytics with Plausible — no cookies, no consent banner required. +--- + +import { Tabs, TabItem } from '@astrojs/starlight/components'; + +:::note +Full documentation coming soon. +::: + +## Install + + + + ```bash + npm install @junctionjs/destination-plausible + ``` + + + ```bash + pnpm add @junctionjs/destination-plausible + ``` + + + ```bash + yarn add @junctionjs/destination-plausible + ``` + + + +## Usage + +```typescript +import { createCollector } from "@junctionjs/core"; +import { plausible } from "@junctionjs/destination-plausible"; + +const collector = createCollector({ + destinations: [ + { + destination: plausible({ + domain: "example.com", + }), + }, + ], +}); +``` + +## Features + +- **Plausible Events API** — sends events via Plausible's server-side API +- **Privacy-focused** — no cookies, no PII, GDPR-friendly by design +- **Custom events** — map Junction events to Plausible custom event names +- **Custom properties** — forward up to 30 custom props per event +- **Revenue tracking** — attach currency and amount to conversion events +- **Self-hosted support** — configurable API host for self-hosted Plausible instances +- **Consent: analytics** — gated behind analytics consent category diff --git a/apps/docs/src/content/docs/getting-started/quickstart.mdx b/apps/docs/src/content/docs/getting-started/quickstart.mdx new file mode 100644 index 0000000..cb9fdf3 --- /dev/null +++ b/apps/docs/src/content/docs/getting-started/quickstart.mdx @@ -0,0 +1,98 @@ +--- +title: Quickstart +description: Install Junction and fire your first event in under 5 minutes. +--- + +## Install + +```bash +npm install @junctionjs/client @junctionjs/core +``` + +Add a destination — for example, GA4: + +```bash +npm install @junctionjs/destination-ga4 +``` + +## Configure + +Create a Junction configuration file: + +```typescript +// lib/junction.ts +import { createClient } from "@junctionjs/client"; +import { ga4 } from "@junctionjs/destination-ga4"; + +export const jct = createClient({ + destinations: [ + { + destination: ga4, + config: { + measurementId: "G-XXXXXXXXXX", + sendPageView: false, + }, + consent: ["analytics"], + }, + ], + consent: { + default: "pending", + }, +}); +``` + +## Track events + +Use the entity:action model to track events: + +```typescript +import { jct } from "./lib/junction"; + +// Page view +jct.track("page", "viewed"); + +// User action +jct.track("product", "added", { + product_id: "SKU-123", + name: "Junction T-Shirt", + price: 29.99, + currency: "USD", +}); +``` + +## Manage consent + +Update consent state when a user interacts with your consent banner: + +```typescript +jct.consent({ + analytics: "granted", + marketing: "denied", +}); +``` + +Events queued while consent was pending are automatically flushed to permitted destinations. + +## Add the debug panel + +```bash +npm install @junctionjs/debug +``` + +Enable it in your config: + +```typescript +const jct = createClient({ + debug: true, // shows the in-page debug panel + // ... rest of config +}); +``` + +Press `Ctrl+Shift+J` to toggle the debug panel and inspect events in real time. + +## Next steps + +- [Events](/concepts/events/) — understand the entity:action model +- [Consent](/concepts/consent/) — how the consent state machine works +- [Validation](/concepts/validation/) — add schema contracts +- [Destinations](/destinations/overview/) — see all available destinations diff --git a/apps/docs/src/content/docs/index.mdx b/apps/docs/src/content/docs/index.mdx new file mode 100644 index 0000000..61d2e4b --- /dev/null +++ b/apps/docs/src/content/docs/index.mdx @@ -0,0 +1,73 @@ +--- +title: What is Junction? +description: Developer-native event collection and routing for scaling teams. +template: splash +hero: + tagline: More control than a tag manager. Less overhead than a CDP. + actions: + - text: Get Started + link: /getting-started/quickstart/ + icon: right-arrow + variant: primary + - text: View on GitHub + link: https://github.com/tyssejc/junction + icon: external + variant: minimal +--- + +import { Card, CardGrid } from "@astrojs/starlight/components"; + +## Why Junction? + +Junction is a TypeScript event collection layer for scaling technical teams. Config-as-code, consent-first, isomorphic, destination-agnostic. + + + + Tracking configuration lives in TypeScript, reviewed in PRs, deployed + through CI/CD. No opaque UIs or workspace mysteries. + + + Zod schema contracts enforce event shapes at runtime, catching data quality + issues at the source — not weeks later when a funnel breaks. + + + A first-class consent state machine queues events until consent resolves, + with per-destination gating and DNT/GPC respected by default. + + + The same collector runs in browsers, Node.js, Deno, Cloudflare Workers, and + Bun. One implementation, every runtime. + + + +## Who is it for? + +Technical growth-stage startups and scaling companies that are: + +- Engineering-led or product-led +- Beyond "just install GA4" but not ready for full CDP complexity +- Running multiple analytics and marketing destinations +- Interested in code-first, AI-friendly development workflows + +## How it works + +All events use a typed entity:action model: + +```typescript +import { createClient } from "@junctionjs/client"; + +const jct = createClient({ + destinations: [ga4, amplitude, meta], + consent: { default: "pending" }, +}); + +// Entity:action — not flat strings +jct.track("product", "viewed", { + product_id: "SKU-123", + name: "Junction T-Shirt", + price: 29.99, + currency: "USD", +}); +``` + +Destinations transform and deliver events independently. Consent gates control which destinations receive data. Schema contracts validate every event before it leaves the client. diff --git a/apps/docs/src/content/docs/integrations/astro.mdx b/apps/docs/src/content/docs/integrations/astro.mdx new file mode 100644 index 0000000..7bd4a86 --- /dev/null +++ b/apps/docs/src/content/docs/integrations/astro.mdx @@ -0,0 +1,46 @@ +--- +title: Astro +description: Junction integration for Astro v5+ with View Transitions support. +--- + +## Install + +```bash +npm install @junctionjs/astro @junctionjs/client @junctionjs/core +``` + +## Setup + +Add the Junction integration to your Astro config: + +```javascript +// astro.config.mjs +import { defineConfig } from "astro/config"; +import junction from "@junctionjs/astro"; + +export default defineConfig({ + integrations: [ + junction({ + debug: true, + }), + ], +}); +``` + +## Features + +- Automatic script injection at `before-hydration` +- SSR middleware for session, geo, and IP enrichment +- View Transitions support — page views tracked on every navigation +- Server-side `/api/collect` endpoint +- CSP-compatible (no `unsafe-inline` needed) + +## Exports + +| Export | Description | +|--------|-------------| +| `@junctionjs/astro` | Astro integration (script injection, middleware) | +| `@junctionjs/astro/middleware` | SSR middleware for server-side enrichment | +| `@junctionjs/astro/collect-endpoint` | Server-side collect API route | + +Full documentation coming soon. diff --git a/apps/docs/src/content/docs/integrations/nextjs.mdx b/apps/docs/src/content/docs/integrations/nextjs.mdx new file mode 100644 index 0000000..9bf00f9 --- /dev/null +++ b/apps/docs/src/content/docs/integrations/nextjs.mdx @@ -0,0 +1,31 @@ +--- +title: Next.js +description: Junction integration for Next.js applications. +--- + +## Install + +```bash +npm install @junctionjs/next @junctionjs/client @junctionjs/core +``` + +## Usage + +```typescript +import { createClient } from "@junctionjs/client"; +import { ga4 } from "@junctionjs/destination-ga4"; + +const jct = createClient({ + destinations: [ + { + destination: ga4, + config: { measurementId: "G-XXXXXXXXXX" }, + consent: ["analytics"], + }, + ], +}); +``` + +See the [demo app](https://github.com/tyssejc/junction/tree/main/apps/demo) for a full Next.js reference implementation. + +Full documentation coming soon. diff --git a/apps/docs/src/content/docs/product/mission.mdx b/apps/docs/src/content/docs/product/mission.mdx new file mode 100644 index 0000000..91c5449 --- /dev/null +++ b/apps/docs/src/content/docs/product/mission.mdx @@ -0,0 +1,43 @@ +--- +title: Mission +description: The problem Junction solves and who it's for. +--- + +## Problem + +Analytics implementation infrastructure is broken for scaling technical teams. Legacy tag managers (GTM, Adobe Launch) were built for marketers adding snippets to websites — they rely on opaque UIs, brittle rule-based logic, and workflows that don't fit into modern engineering practices. As companies grow, this creates: + +- **No version control** — GTM workspaces and Adobe's "Latest" model make it impossible to know who changed what, when, or why +- **No validation** — typos, missing fields, and type mismatches silently corrupt analytics data, discovered weeks later when funnels break +- **Consent as afterthought** — bolted-on consent modes that fragment implementation and create compliance risk +- **Vendor lock-in** — proprietary systems where configuration can't be reviewed in PRs, tested in CI, or deployed through standard pipelines + +At the other end, full CDPs (Segment, RudderStack, Tealium) solve some of these problems but introduce more scope, cost, and organizational overhead than most scaling companies need. + +Meanwhile, AI agents are rapidly becoming how scaling companies build and ship software. No existing event collection layer is designed for agent-driven implementation. Tag managers require point-and-click UIs that agents can't operate. CDPs require complex configuration flows optimized for humans navigating dashboards. The companies most likely to adopt Junction — technical, growth-stage startups — are also the fastest adopters of AI-assisted development. There's a first-mover opportunity to build the event layer that agents can instrument natively. + +## Target Users + +Technical growth-stage startups and scaling companies that are: + +- Engineering-led or product-led +- Beyond "just install GA4" but not ready for full CDP complexity +- Running multiple analytics and marketing destinations +- Uncomfortable with brittle tag-manager sprawl or ad hoc tracking +- Interested in code-first, AI-friendly development workflows + +Primary champions: founders, engineering leads, growth engineers, analytics owners, and heads of data at smaller companies. + +Best-fit segments: B2B SaaS, PLG startups, headless/technical ecommerce, companies with both product analytics and marketing destinations. + +## Solution + +Junction is the first event collection layer designed from the ground up to be implemented by both developers and AI agents. It gives scaling companies more control than legacy tag managers and less overhead than a full CDP. + +- **Agent-native** — TypeScript config, typed interfaces, schema contracts, and deterministic behavior make Junction trivial for AI agents to instrument, wire up destinations, and validate correctness. No UIs to click through, no ambiguous config formats to interpret. +- **Config as code** — tracking configuration lives in TypeScript files, reviewed in PRs, deployed through CI/CD +- **Typed events** — Zod schema contracts enforce event shapes at runtime, catching data quality issues at the source +- **Consent-first** — a first-class consent state machine that queues events until consent resolves, with per-destination gating and DNT/GPC respected by default +- **Isomorphic** — the same collector runs in browsers, Node.js, Deno, Cloudflare Workers, and Bun +- **Destination-agnostic** — simple plugin interface lets teams add, swap, or remove analytics and marketing destinations without re-instrumenting +- **CDP-compatible, not CDP-scoped** — integrates with warehouses, profile systems, and downstream tools without trying to become the whole stack diff --git a/apps/docs/src/content/docs/product/roadmap.mdx b/apps/docs/src/content/docs/product/roadmap.mdx new file mode 100644 index 0000000..8ac8beb --- /dev/null +++ b/apps/docs/src/content/docs/product/roadmap.mdx @@ -0,0 +1,69 @@ +--- +title: Roadmap +description: Junction's product roadmap and development phases. +--- + +## Phase 1: MVP (Shipped) + +The core open-source product is built and functional: + +- Isomorphic event collector with typed event model (entity + action) +- Consent state machine with event queuing, per-destination gating, DNT/GPC support +- Zod-based schema validation (strict and lenient modes) +- Browser client with anonymous IDs, sessions, auto page views +- Astro v5+ integration (script injection, SSR middleware, View Transitions) +- WinterCG edge gateway (Cloudflare Workers, Deno, Bun, Vercel Edge) +- Next.js integration +- Destinations: Amplitude, GA4, Meta Pixel + CAPI, HTTP (generic), Plausible +- In-page debug panel for real-time event flow visibility +- OneTrust CMP adapter +- Auto-collect module +- Monorepo with CI/CD, Changesets for versioning, npm publishing + +## Phase 2: Validation Sprint (Current — 90-Day Plan, Mar 30 – Jun 27 2026) + +Goal: make Junction production-ready for design partner adoption. A design partner can deploy and operate Junction; a prospect can evaluate it end-to-end in under 10 minutes. + +### Phase 2.1: PostHog Destination (Days 1–20, Mar 30 – Apr 18) + +- `@junctionjs/destination-posthog` — client-side (posthog-js) and server-side (API) event capture +- Standard destination interface, entity:action mapping, consent configuration +- Demo app updated, docs page, published to npm + +### Phase 2.2: Hosted Gateway + Observability (Days 21–60, Apr 19 – May 28) + +- Cloudflare Workers deployment with Hono, credential management, API key auth +- Durable event log, retry logic for failed deliveries +- Observability API: recent events, delivery status, validation errors, consent-blocked events +- Lightweight dashboard UI with human-readable error explanations +- Health endpoint, rate limiting, CORS, deployment playbook + +### Phase 2.3: Adoption Surface (Days 61–90, May 29 – Jun 27) + +- **Reference implementation** — Next.js SaaS example showing full loop: client SDK → hosted gateway → PostHog + GA4, with consent flow and debug panel +- **Docs** — reworked quickstart, GTM-to-Junction migration guide, gateway deployment guide +- **Agentic instrumentation spike** — `CLAUDE.md` template for Junction users so AI assistants know how to instrument events correctly + +### Deferred to post-Phase 2 + +- Additional destinations based on design partner signal (Mixpanel, HubSpot, LinkedIn Ads, Segment-as-destination) +- Schema/contract ergonomics — easier authoring, reusable patterns, starter templates +- Consent implementation cookbook +- AI CLI tooling beyond the CLAUDE.md template +- Team workflows / environments / audit trail + +## Phase 3: Post-Launch Product Expansion + +- **Rules engine** — declarative auto-tracking based on URL/DOM/cookie conditions +- **CMP integrations** — pre-built adapters for Cookiebot, Usercentrics, and others +- **Event replay** — record events in staging, replay against production configs +- **Monitoring dashboard** — destination error rates, event volumes, validation failures +- **Team workflows** — environments, approvals, audit trail, access controls +- **More destinations** — Google Ads, LinkedIn Insight, TikTok Pixel, Pinterest Tag, Snowflake, BigQuery, S3/R2 + +## Monetization Sequence + +1. **Productized implementation services** (via Stacked Analytics) — migration, modernization, architecture, launch support +2. **Hosted gateway / runtime** — managed infrastructure as recurring revenue +3. **Observability / debugging / event QA** — premium software surface +4. **Team workflows / audit trail** — expansion into agencies and larger teams diff --git a/apps/docs/tsconfig.json b/apps/docs/tsconfig.json new file mode 100644 index 0000000..bcbf8b5 --- /dev/null +++ b/apps/docs/tsconfig.json @@ -0,0 +1,3 @@ +{ + "extends": "astro/tsconfigs/strict" +} diff --git a/docs/90-day-action-memo.md b/docs/90-day-action-memo.md new file mode 100644 index 0000000..5c25d69 --- /dev/null +++ b/docs/90-day-action-memo.md @@ -0,0 +1,580 @@ +# **90-Day Action Memo** + +**Junction: Product, GTM, and Design Partner Validation Plan** + +## **Purpose** + +Over the next 90 days, the goal is to determine whether Junction can become a venture-scale company by validating: + +* a clear initial ICP + +* a compelling problem/solution fit + +* a credible product for technical growth-stage teams + +* an early monetization path through services and hosted software + +This phase is not about broad launch. It is about focused validation, disciplined learning, and building enough product and market traction to support the next strategic decision. + +## **Core thesis** + +Junction should be explored as: + +**The developer-native event implementation layer for scaling companies that need more control than legacy tag managers and less overhead than a full CDP.** + +The near-term GTM motion should focus on technical startups and scaling companies where analytics and martech implementation complexity is starting to break existing approaches. + +## **Success criteria by day 90** + +By the end of this phase, Junction should have: + +* a sharper ICP and messaging direction + +* 10–15 meaningful market discovery conversations completed + +* 2–3 active design partners or late-stage design partner candidates + +* PostHog added as a destination + +* a stronger debugging/observability experience + +* a lightweight hosted gateway/runtime MVP defined or in use + +* a clear services \+ product commercialization model + +* a tighter narrative for investors and early supporters + +--- + +# **Swim lane 1: Technical / Product** + +## **Strategic objective** + +Make Junction credible, adoptable, and operable for technical growth-stage teams evaluating it as a real implementation layer. + +## **Days 1–30** + +### **1\. Ship planning and architecture for near-term roadmap** + +Define scope, ownership, and success criteria for: + +* PostHog destination + +* observability/debugging MVP + +* hosted gateway/runtime MVP + +* one startup-focused reference implementation + +### **2\. Build PostHog destination** + +PostHog is the highest-priority destination addition because it strengthens the story that Junction supports both product analytics and growth use cases. + +Desired outcome: + +* product teams can see Junction as relevant + +* Junction no longer reads as martech-only infrastructure + +### **3\. Define observability MVP** + +Identify the minimum useful debugging surface: + +* live event visibility + +* payload inspection + +* validation status + +* consent blocking/queueing state + +* destination delivery outcome + +* dropped/replayed event state + +Desired outcome: + +* a prospect can understand what Junction is doing and why + +### **4\. Define hosted gateway/runtime MVP** + +Specify the minimum hosted path for design partners: + +* managed ingestion endpoint + +* secrets/credential management + +* event logs + +* retry handling + +* basic health visibility + +Desired outcome: + +* design partners can adopt without full self-hosting burden + +### **5\. Improve quickstart and docs structure** + +Rework docs to better support evaluation: + +* what Junction is + +* how it differs from GTM/Segment/RudderStack + +* how schemas work + +* how consent works + +* how routing works + +* how to get running quickly + +Desired outcome: + +* a technical buyer can understand the product in one short session + +## **Days 31–60** + +### **6\. Release PostHog destination** + +Complete implementation, test coverage, docs, and example usage. + +### **7\. Implement observability/debugging v1** + +Focus on practical usability, not polish: + +* event stream + +* validation visibility + +* consent state explanation + +* destination delivery feedback + +* error messaging + +Desired outcome: + +* early users trust the product more quickly + +* debugging becomes a differentiator + +### **8\. Publish one excellent reference implementation** + +Priority order: + +* Next.js SaaS example + +* Astro example + +* ecommerce/headless example + +Each should demonstrate: + +* event contracts + +* multiple destinations + +* consent flow + +* validation/debug workflow + +Desired outcome: + +* reduce adoption friction + +* support founder and design partner outreach + +### **9\. Improve schema ergonomics** + +Focus on: + +* clearer validation messages + +* starter patterns/templates + +* reusable event structures + +* lower friction in contract authoring + +Desired outcome: + +* schema validation feels like leverage, not overhead + +## **Days 61–90** + +### **10\. Deliver hosted gateway/runtime MVP** + +Have a workable managed path for design partners or internal pilot usage. + +### **11\. Add next destination based on interview signal** + +Candidates: + +* Mixpanel + +* HubSpot + +* LinkedIn Ads + +* Segment as destination + +* RudderStack as destination + +Choose based on real demand from discovery conversations. + +### **12\. Publish migration guidance** + +At minimum: + +* GTM to Junction migration guide + +* Launch to Junction migration guide + +* event inventory template + +* implementation planning checklist + +Desired outcome: + +* reduce switching fear + +* support services work through Stacked + +### **13\. Evaluate AI-assisted implementation helpers** + +Do lightweight exploration of: + +* CLI scaffolding + +* schema generation support + +* config generation from prompts + +* error explanation helpers + +This is exploratory, not a primary build track. + +Desired outcome: + +* support future AI-native positioning without distracting from core roadmap + +--- + +# **Swim lane 2: Functional / GTM** + +## **Strategic objective** + +Identify the right early customer, validate the strongest pain narrative, and convert a small number of qualified companies into paid design partner relationships. + +## **Days 1–30** + +### **1\. Define design partner profile** + +Create a clear qualification profile for target companies: + +* technical startup or scaling company + +* real analytics implementation pain + +* multiple destinations now or soon + +* discomfort with brittle GTM/ad hoc tracking + +* collaborative enough to work with an early product + +* likely to resemble future target customers + +### **2\. Build target list** + +Create a list of founders and operators for outreach, ideally segmented by: + +* B2B SaaS + +* PLG startups + +* technical ecommerce + +* product/growth-heavy startups + +Target initial list: + +* 20–30 names + +* prioritize warm network paths first + +### **3\. Create structured discovery interview framework** + +Standardize how conversations are run and captured. + +Topics to probe: + +* current stack + +* where the current model breaks + +* who owns analytics implementation + +* pain around tool additions, debugging, engineering burden, consent, flexibility + +* willingness to adopt a code-first alternative + +* appetite for software vs services vs both + +### **4\. Test initial message directions** + +Test 2–3 positioning variants: + +* faster analytics implementation for scaling teams + +* code-first replacement for brittle tag sprawl + +* one event layer for product and marketing data + +* more control than GTM, less overhead than a full CDP + +Desired outcome: + +* hear buyer language + +* identify which framing earns interest + +### **5\. Define external Junction / Stacked narrative** + +Create a simple, consistent explanation: + +* Junction \= product/platform + +* Stacked \= services/implementation partner + +* design partners help shape Junction while engagements can run through Stacked + +Desired outcome: + +* reduce brand confusion + +* create confidence in conversations + +## **Days 31–60** + +### **6\. Complete 10–15 discovery conversations** + +Use structured notes and compare responses across interviews. + +Desired outcome: + +* identify repeated pain patterns + +* determine whether speed, flexibility, reliability, or simplification is the strongest wedge + +### **7\. Draft design partner offer** + +Frame it as a high-touch early program, not loose consulting. + +Likely offer: + +* implementation modernization package + +* event architecture design + +* Junction implementation + +* destination setup + +* consent-aware planning + +* QA and launch support + +* direct product access and roadmap input + +Commercial posture: + +* paid, but advantaged + +* likely sold through Stacked + +### **8\. Convert top prospects into design partner discussions** + +Move from exploratory discovery into specific conversations with best-fit prospects. + +Desired outcome: + +* 3–5 serious design partner candidates + +* 2–3 likely near-term partners + +### **9\. Refine company narrative** + +Update the strategic narrative based on actual market responses: + +* what buyers think Junction is + +* what they actually value + +* what objections recur + +* what language is working + +## **Days 61–90** + +### **10\. Close 2–3 design partners** + +Structure them with: + +* clear scope + +* clear expectations + +* active feedback cadence + +* commercial commitment + +* product-learning objectives + +### **11\. Begin implementation engagements** + +Run at least the initial phase of partner work: + +* current-state review + +* architecture design + +* setup/migration plan + +* product feedback loop + +### **12\. Capture repeatable learning** + +After each conversation and each partner milestone, document: + +* what pain triggered interest + +* what value showed up first + +* what created friction + +* what product requests generalized + +* what should remain services-led + +### **13\. Prepare investor/strategic update** + +By the end of day 90, summarize: + +* ICP signal + +* design partner traction + +* product progress + +* monetization signal + +* roadmap implications + +* evidence for market gap and Junction’s right to win + +--- + +# **Weekly operating cadence** + +To make this plan work, both swim lanes should run on a simple weekly rhythm. + +## **Technical weekly rhythm** + +* roadmap review + +* shipped progress review + +* design partner product blockers + +* docs/example review + +* decision log for what is product vs service vs later + +## **Functional/GTM weekly rhythm** + +* outreach review + +* interview debriefs + +* message testing takeaways + +* design partner pipeline review + +* learning summary and implications for roadmap + +## **Shared weekly checkpoint** + +Once per week, review: + +* what we learned from the market + +* what we learned from the product + +* what changed in our conviction + +* what should be reprioritized immediately + +--- + +# **Key decisions to force by the end of 90 days** + +By the end of this period, Junction should be able to answer: + +1. Which ICP is strongest for initial traction? + +2. What pain gets attention fastest? + +3. What is the best front-door offer? + +4. What product capabilities are essential for adoption? + +5. What belongs in OSS, hosted product, and services? + +6. Is the Stacked \+ Junction model helping or confusing? + +7. Is there enough real pull to justify continued company formation effort? + +--- + +# **Immediate priorities summary** + +## **Technical** + +* PostHog destination + +* observability/debugging MVP + +* hosted gateway/runtime MVP + +* reference implementation + +* docs and migration guidance + +## **Functional / GTM** + +* structured discovery interviews + +* target account/founder list + +* design partner qualification + +* Junction/Stacked narrative + +* paid design partner offer + +* close 2–3 real partners + +--- + +# **Bottom line** + +The next 90 days should be run as a focused validation sprint. + +The technical lane should make Junction feel real and credible. + +The GTM lane should determine whether there is a repeatable market wedge strong enough to support a company. + +Success is not measured by feature count. It is measured by whether a small number of the right companies engage deeply enough to prove that Junction solves an urgent problem in a way they will pay for. + diff --git a/docs/next-step-plan.md b/docs/next-step-plan.md new file mode 100644 index 0000000..6f969de --- /dev/null +++ b/docs/next-step-plan.md @@ -0,0 +1,840 @@ +# **Junction immediate next-step plan** + +## **Objective** + +Validate whether Junction can become a real company by proving three things in parallel: + +1. **Product credibility** — technical teams can understand, trial, and trust it + +2. **Market pull** — a specific ICP feels enough pain to engage and pay + +3. **Commercial shape** — there is a repeatable path from OSS interest to services and then software revenue + +--- + +# **1\. Core goal for this phase** + +The goal is **not** broad launch. + +The goal is to answer: + +**For which specific type of scaling company does Junction solve a painful enough implementation problem that they will engage deeply, trial it, and pay for some combination of services, hosting, or software?** + +This phase should be treated as: + +* PMF exploration + +* design partner recruitment + +* product hardening + +* narrative sharpening + +--- + +# **2\. Primary ICP for exploration** + +## **Primary target** + +**Technical growth-stage startups and scaling companies** that are: + +* engineering-led or product-led + +* increasingly complex in analytics / martech needs + +* beyond “just install GA4” + +* uncomfortable with brittle GTM sprawl or ad hoc tracking + +* interested in speed, flexibility, and future scalability + +## **Best-fit examples** + +* B2B SaaS + +* PLG startups + +* headless / technical ecommerce teams + +* companies with both product analytics and marketing destinations + +* teams using AI-assisted development workflows + +## **Buyer / champion candidates** + +* founder + +* engineering lead + +* product lead + +* growth engineering lead + +* analytics owner + +* head of data at smaller companies + +## **Positioning for this ICP** + +Junction is: + **the developer-native event implementation layer for scaling companies that need more control than legacy tag managers and less overhead than a full CDP.** + +--- + +# **3\. Strategic posture** + +## **What Junction is** + +* code-first event collection and routing + +* schema-validated implementation layer + +* consent-aware data collection foundation + +* product \+ marketing destination bridge + +* modern replacement for brittle tag-manager sprawl + +## **What Junction is not** + +* not a CDP + +* not a customer-360 platform + +* not an audience builder + +* not an identity graph company + +* not trying to out-Segment Segment + +## **Why this matters** + +The company should own: + +* implementation + +* collection + +* validation + +* consent-aware routing + +* observability + +* developer workflow + +It should remain: + +* CDP-compatible + +* warehouse-friendly + +* identity-ready at the event level + +But not become responsible for profiles, audiences, and customer unification in the near term. + +--- + +# **4\. Near-term product roadmap** + +## **Tier 1: must-do now** + +### **A. Add PostHog destination** + +Why: + +* supports startup / technical ICP + +* broadens story beyond martech + +* strengthens “one event layer for product \+ growth” + +* fits AI-native builder audiences + +Success outcome: + +* Junction can credibly support both product and marketing use cases in the same implementation story + +### **B. Improve debugging / observability** + +This is likely the most important product improvement after core destination support. + +Must-have capabilities: + +* live event stream + +* payload inspection + +* validation error visibility + +* queued / dropped / replayed event visibility + +* destination delivery status + +* human-readable explanation of failures + +* clear consent-blocking visibility + +Success outcome: + +* a prospect can understand what happened, why it happened, and whether Junction is trustworthy + +### **C. Create a lightweight hosted gateway / runtime MVP** + +Must-have capabilities: + +* managed ingestion endpoint + +* credential/secret handling + +* delivery logs + +* retries + +* basic health status + +* simple managed deployment story + +Success outcome: + +* a design partner can adopt Junction without needing to self-host everything or worry about runtime ops + +### **D. Build excellent reference implementations** + +Prioritize: + +* Next.js SaaS example + +* Astro example + +* one ecommerce/headless example + +Each should show: + +* event schemas + +* consent flow + +* multiple destinations + +* validation behavior + +* debug workflow + +Success outcome: + +* a technical buyer can imagine adopting Junction in under 10 minutes + +--- + +## **Tier 2: build next** + +### **A. Add one or two more high-value destinations** + +Best candidates: + +* Mixpanel + +* HubSpot + +* LinkedIn Ads + +* Segment as a destination + +* RudderStack as a destination + +Why: + +* supports startup growth stacks + +* reduces adoption friction + +* lets Junction sit upstream even when customers keep existing tools + +### **B. Improve schema / contract ergonomics** + +Focus on: + +* easier schema authoring + +* reusable patterns + +* standard event templates + +* better validation messages + +* starter event libraries + +### **C. Improve consent implementation experience** + +Focus on: + +* cookbook examples + +* common consent modes + +* better destination-level mapping + +* visibility into why events are blocked/queued + +* practical examples of GPC/DNT handling + +### **D. Build migration helpers** + +Focus on: + +* GTM-to-Junction guidance + +* Launch-to-Junction guidance + +* event inventory templates + +* data layer mapping patterns + +* switch-over playbooks + +--- + +## **Tier 3: differentiators to layer in** + +* AI CLI helpers + +* config scaffolding from prompts + +* schema generation assistance + +* destination mapping suggestions + +* implementation explainers + +* more vertical templates + +These matter, but should not outrun core operability. + +--- + +# **5\. Design partner program** + +## **Purpose** + +Use design partners to validate: + +* who cares most + +* what pain is strongest + +* which capabilities drive adoption + +* what buyers will pay for + +* what should become product vs. service + +## **What a design partner is** + +A real early customer who: + +* has a real problem + +* collaborates closely + +* accepts some product immaturity + +* gives structured feedback + +* helps shape the product + +## **Design partner selection criteria** + +Prioritize companies that: + +* have current implementation pain + +* are collaborative + +* are technical enough for code-first adoption + +* resemble future customers you want more of + +* can assign a real internal owner + +Avoid companies that are: + +* just curious + +* too custom + +* too early to feel real pain + +* too enterprise-heavy for an evolving product + +* unwilling to commit time or money + +## **Design partner commercial model** + +Default model should be: + **paid, but advantaged** + +Likely structure: + +* discounted implementation/design-partner engagement + +* possible hosted/runtime access included + +* direct access to founders + +* input into roadmap + +* expectation of active collaboration + +Do not default to free. + +--- + +# **6\. GTM learning plan** + +## **Phase 1: interview and pattern-find** + +Build a target list of founders and operators and run structured conversations. + +Target: + +* 10–15 discovery interviews + +Goals: + +* understand current stack + +* identify breaking points + +* hear buyer language + +* validate who owns the problem + +* test whether the pain is speed, complexity, reliability, trust, or flexibility + +Questions to probe: + +* what broke first in your current setup? + +* where does implementation slow you down? + +* how do new tools get added today? + +* who owns tracking? + +* how much engineering work does analytics create? + +* how do you debug broken or missing events? + +* what happens when consent requirements complicate tracking? + +* what would have to be true for you to switch approaches? + +## **Phase 2: convert 2–3 design partners** + +The initial commercial offer should be framed as: + **Analytics Implementation Modernization** + +Package includes: + +* audit/current-state review + +* event architecture design + +* Junction implementation + +* destination setup + +* consent-aware modeling + +* QA and launch support + +## **Phase 3: extract repeatable pain** + +After each engagement, document: + +* what they thought they were buying + +* what value showed up fastest + +* what blocked adoption + +* which capabilities mattered most + +* which asks are productizable + +* what they would actually pay for + +--- + +# **7\. Monetization plan** + +## **Near-term revenue** + +### **A. Productized implementation services** + +Sell through Stacked Analytics initially. + +Examples: + +* migration package + +* modernization package + +* instrumentation architecture package + +* launch support package + +Why: + +* fastest path to revenue + +* easiest entry into consideration set + +* creates product learning + +* design-partner friendly + +### **B. Hosted gateway / runtime** + +As product matures, offer managed runtime as recurring revenue. + +What customers are buying: + +* convenience + +* reliability + +* lower operational burden + +## **Medium-term software monetization** + +### **A. Observability / debugging / event QA** + +This is likely the strongest premium software surface. + +Customers buy: + +* confidence + +* faster troubleshooting + +* clearer delivery visibility + +* less time lost to broken implementations + +### **B. Team workflows / environments / audit trail** + +Add later for: + +* larger teams + +* agencies + +* mid-market accounts + +* enterprise readiness + +Customers buy: + +* coordination + +* control + +* rollback + +* traceability + +## **Monetization sequence** + +1. services + +2. hosted runtime + +3. observability / QA + +4. team workflows / audit trail + +--- + +# **8\. Role of Stacked Analytics** + +## **Recommended model** + +Use Stacked as: + +* implementation/services partner + +* design partner delivery layer + +* migration and architecture partner + +Use Junction as: + +* product/platform + +* OSS project + +* hosted offering + +* core company narrative + +## **Why this works** + +* Stacked can absorb high-touch work + +* Junction stays product-disciplined + +* early revenue does not force Junction into consultancy identity + +* customer learning still flows into roadmap + +## **Guardrails** + +Be explicit that: + +* Stacked sells services + +* Junction is the product + +* design partners are helping shape Junction + +* not every services request becomes a product feature + +Avoid Junction becoming perceived as just “Stacked’s internal framework.” + +--- + +# **9\. Competitive differentiation** + +## **Primary competitors** + +* GTM + +* Adobe Launch / Tags + +* Segment + +* RudderStack + +* Tealium + +## **Secondary / adjacent** + +* Snowplow + +* mParticle + +* Piwik PRO + +* JENTIS + +* Commanders Act + +## **Vertical / ecosystem-specific** + +* Stape + +* Elevar + +## **Junction’s differentiation** + +Junction should win by being: + +* more code-first than GTM / Adobe + +* lighter and more controllable than a full CDP + +* more implementation-focused than broader customer-data platforms + +* more developer-native than marketer-first tools + +* better at typed, consent-aware event implementation than tag-sprawl approaches + +Key line: + **more control than legacy tag managers, less overhead than a full CDP** + +--- + +# **10\. Messaging to test** + +## **Primary message direction** + +Sell Junction as growth infrastructure, not governance infrastructure. + +Test messages like: + +* ship analytics and downstream integrations faster + +* replace brittle tag-manager sprawl with typed event infrastructure + +* one implementation layer for product and marketing data + +* scale your analytics implementation without inheriting CDP complexity + +* a code-first foundation for reliable growth and product data + +## **What not to lead with** + +* governance + +* compliance + +* customer 360 + +* “GTM killer” + +* “open-source CDP” + +Governance should be supporting proof, not the front-door pitch. + +--- + +# **11\. Immediate 90-day execution plan** + +## **Days 1–30** + +### **Product** + +* scope and build PostHog destination + +* define observability MVP + +* define hosted gateway MVP + +* improve docs and quickstart narrative + +### **Market** + +* build founder/operator target list + +* run first 5–7 discovery conversations + +* test positioning language + +* draft design partner offer + +### **Internal** + +* define Stacked vs Junction relationship language + +* define design partner qualification criteria + +* create interview note template and product-learning template + +## **Days 31–60** + +### **Product** + +* ship PostHog + +* ship first observability improvements + +* publish one great startup-focused example implementation + +* tighten consent and validation docs + +### **Market** + +* complete 10–15 discovery interviews + +* identify strongest ICP signals + +* move best-fit prospects into design-partner conversations + +* refine offer based on objections and feedback + +### **Commercial** + +* package paid design-partner engagement + +* define what is OSS vs hosted vs services + +* create a simple one-page design partner brief + +## **Days 61–90** + +### **Product** + +* deliver hosted gateway/runtime MVP + +* improve debug/event inspection further + +* start next destination based on interview signal + +* publish migration guide(s) + +### **Market** + +* close 2–3 design partners + +* begin real implementations + +* gather case-study material + +* document repeated pain themes + +### **Strategy** + +* review what customers actually valued + +* update roadmap based on repeated patterns + +* refine investor/company narrative with evidence from real partner work + +--- + +# **12\. Success criteria for this phase** + +At the end of this phase, you want evidence that: + +## **Product** + +* Junction feels credible and understandable + +* technical teams can adopt it without huge friction + +* debugging/operability is strong enough to build trust + +## **Market** + +* a clear ICP emerges + +* a repeatable pain narrative shows up + +* design partners engage for real reasons, not curiosity + +## **Commercial** + +* at least some buyers will pay + +* services-led motion works + +* hosted/runtime interest exists + +* you can see the path to recurring software revenue + +--- + +# **13\. Bottom-line recommendation** + +The next step is not just “build more features.” + +It is to run a coordinated exploration with four priorities: + +1. **Add PostHog and strengthen product credibility** + +2. **Improve observability and create a lightweight hosted path** + +3. **Run disciplined founder/design-partner discovery** + +4. **Use Stacked for paid early services while keeping Junction clearly standalone** + +That is the best path to figuring out whether Junction is: + +* an interesting OSS tool + +* a services-enabled product + +* or the foundation of a real company + diff --git a/docs/product/mission.md b/docs/product/mission.md new file mode 100644 index 0000000..269cebf --- /dev/null +++ b/docs/product/mission.md @@ -0,0 +1,40 @@ +# Product Mission + +## Problem + +Analytics implementation infrastructure is broken for scaling technical teams. Legacy tag managers (GTM, Adobe Launch) were built for marketers adding snippets to websites — they rely on opaque UIs, brittle rule-based logic, and workflows that don't fit into modern engineering practices. As companies grow, this creates: + +- **No version control** — GTM workspaces and Adobe's "Latest" model make it impossible to know who changed what, when, or why +- **No validation** — typos, missing fields, and type mismatches silently corrupt analytics data, discovered weeks later when funnels break +- **Consent as afterthought** — bolted-on consent modes that fragment implementation and create compliance risk +- **Vendor lock-in** — proprietary systems where configuration can't be reviewed in PRs, tested in CI, or deployed through standard pipelines + +At the other end, full CDPs (Segment, RudderStack, Tealium) solve some of these problems but introduce more scope, cost, and organizational overhead than most scaling companies need. + +Meanwhile, AI agents are rapidly becoming how scaling companies build and ship software. No existing event collection layer is designed for agent-driven implementation. Tag managers require point-and-click UIs that agents can't operate. CDPs require complex configuration flows optimized for humans navigating dashboards. The companies most likely to adopt Junction — technical, growth-stage startups — are also the fastest adopters of AI-assisted development. There's a first-mover opportunity to build the event layer that agents can instrument natively. + +## Target Users + +Technical growth-stage startups and scaling companies that are: + +- Engineering-led or product-led +- Beyond "just install GA4" but not ready for full CDP complexity +- Running multiple analytics and marketing destinations +- Uncomfortable with brittle tag-manager sprawl or ad hoc tracking +- Interested in code-first, AI-friendly development workflows + +Primary champions: founders, engineering leads, growth engineers, analytics owners, and heads of data at smaller companies. + +Best-fit segments: B2B SaaS, PLG startups, headless/technical ecommerce, companies with both product analytics and marketing destinations. + +## Solution + +Junction is the first event collection layer designed from the ground up to be implemented by both developers and AI agents. It gives scaling companies more control than legacy tag managers and less overhead than a full CDP. + +- **Agent-native** — TypeScript config, typed interfaces, schema contracts, and deterministic behavior make Junction trivial for AI agents to instrument, wire up destinations, and validate correctness. No UIs to click through, no ambiguous config formats to interpret. +- **Config as code** — tracking configuration lives in TypeScript files, reviewed in PRs, deployed through CI/CD +- **Typed events** — Zod schema contracts enforce event shapes at runtime, catching data quality issues at the source +- **Consent-first** — a first-class consent state machine that queues events until consent resolves, with per-destination gating and DNT/GPC respected by default +- **Isomorphic** — the same collector runs in browsers, Node.js, Deno, Cloudflare Workers, and Bun +- **Destination-agnostic** — simple plugin interface lets teams add, swap, or remove analytics and marketing destinations without re-instrumenting +- **CDP-compatible, not CDP-scoped** — integrates with warehouses, profile systems, and downstream tools without trying to become the whole stack diff --git a/docs/product/roadmap.md b/docs/product/roadmap.md new file mode 100644 index 0000000..2c168cb --- /dev/null +++ b/docs/product/roadmap.md @@ -0,0 +1,57 @@ +# Product Roadmap + +## Phase 1: MVP (Shipped) + +The core open-source product is built and functional: + +- Isomorphic event collector with typed event model (entity + action) +- Consent state machine with event queuing, per-destination gating, DNT/GPC support +- Zod-based schema validation (strict and lenient modes) +- Browser client with anonymous IDs, sessions, auto page views +- Astro v5+ integration (script injection, SSR middleware, View Transitions) +- WinterCG edge gateway (Cloudflare Workers, Deno, Bun, Vercel Edge) +- Next.js integration +- Destinations: Amplitude, GA4, Meta Pixel + CAPI, HTTP (generic), Plausible +- In-page debug panel for real-time event flow visibility +- OneTrust CMP adapter +- Auto-collect module +- Monorepo with CI/CD, Changesets for versioning, npm publishing + +## Phase 2: Validation Sprint (Current — 90-Day Plan) + +### Tier 1: Must-do now + +- **PostHog destination** — broadens story beyond martech into product analytics; strengthens "one event layer for product + growth" +- **Observability / debugging MVP** — live event stream, payload inspection, validation errors, consent-blocking visibility, destination delivery status, human-readable failure explanations +- **Hosted gateway / runtime MVP** — managed ingestion endpoint, credential handling, delivery logs, retries, basic health status +- **Reference implementations** — Next.js SaaS example, Astro example, ecommerce/headless example (each showing schemas, consent, multi-destination, debug workflow) +- **Docs and quickstart improvements** — make the product understandable in one short session + +### Tier 2: Build next + +- Additional destinations based on design partner signal (candidates: Mixpanel, HubSpot, LinkedIn Ads, Segment-as-destination, RudderStack-as-destination) +- Schema/contract ergonomics — easier authoring, reusable patterns, starter templates, better validation messages +- Consent implementation experience — cookbooks, common consent modes, GPC/DNT examples +- Migration helpers — GTM-to-Junction guide, Adobe Launch-to-Junction guide, event inventory templates + +### Tier 3: Differentiators to layer in + +- AI CLI helpers — config scaffolding from prompts, schema generation, error explanation +- Destination mapping suggestions +- Vertical templates (ecommerce, SaaS, PLG) + +## Phase 3: Post-Launch Product Expansion + +- **Rules engine** — declarative auto-tracking based on URL/DOM/cookie conditions +- **CMP integrations** — pre-built adapters for Cookiebot, Usercentrics, and others +- **Event replay** — record events in staging, replay against production configs +- **Monitoring dashboard** — destination error rates, event volumes, validation failures +- **Team workflows** — environments, approvals, audit trail, access controls +- **More destinations** — Google Ads, LinkedIn Insight, TikTok Pixel, Pinterest Tag, Snowflake, BigQuery, S3/R2 + +## Monetization Sequence + +1. **Productized implementation services** (via Stacked Analytics) — migration, modernization, architecture, launch support +2. **Hosted gateway / runtime** — managed infrastructure as recurring revenue +3. **Observability / debugging / event QA** — premium software surface +4. **Team workflows / audit trail** — expansion into agencies and larger teams diff --git a/docs/product/tech-stack.md b/docs/product/tech-stack.md new file mode 100644 index 0000000..692c31a --- /dev/null +++ b/docs/product/tech-stack.md @@ -0,0 +1,45 @@ +# Tech Stack + +## Language + +- **TypeScript** — all packages, strict mode +- Targets Node.js >= 18, browser, and WinterCG edge runtimes + +## Monorepo + +- **npm workspaces** (migrating to **bun** as primary package manager going forward) +- **Turborepo** — build orchestration across packages +- **Changesets** — versioning and npm publishing + +## Runtime + +- **Isomorphic core** — runs in browser, Node.js, Deno, Cloudflare Workers, Bun +- **WinterCG-compatible** edge gateway +- **Zod** — schema validation for event contracts + +## Framework Integrations + +- **Astro v5+** — first-class integration (script injection, SSR middleware, View Transitions) +- **Next.js** — dedicated package + +## Testing + +- **Vitest** — unit and integration tests (v8 coverage provider, happy-dom for browser env) +- **Playwright** — end-to-end tests + +## Linting & Formatting + +- **Biome** — linting and formatting (replaces ESLint + Prettier) +- **lint-staged** + **Husky** — pre-commit hooks + +## CI/CD + +- **GitHub Actions** — CI on push/PR to main, matrix testing across Node 18/20/22 +- **Changesets** — automated release workflow +- **Cloudflare Workers / Wrangler** — gateway deployment target + +## Hosting + +- **Cloudflare Workers** — primary edge runtime target for gateway +- **Cloudflare Pages** — site/demo deployment +- Designed to run on any WinterCG-compatible platform (Vercel Edge, Deno Deploy, Bun) diff --git a/docs/status-reports/2026-03-27.md b/docs/status-reports/2026-03-27.md new file mode 100644 index 0000000..263b32d --- /dev/null +++ b/docs/status-reports/2026-03-27.md @@ -0,0 +1,60 @@ +# Junction — Weekly Status Report (Mar 21–27, 2026) + +## Releases + +Two npm releases published via Changesets: + +| Package | Version | Type | +|---------|---------|------| +| `@junctionjs/core` | 0.3.0 | minor | +| `@junctionjs/next` | 2.0.0 | major | +| `@junctionjs/destination-ga4` | 2.0.0 | major | +| `@junctionjs/destination-http` | 2.0.0 | major | +| `@junctionjs/client` | 0.1.3 | patch | + +## PRs Merged (6) + +| PR | Title | Area | +|----|-------|------| +| #9 | fix(core,next): flush buffer on consent change, fix double pageview | core, next | +| #10 | fix(core): pin necessary consent to always-granted in state | core | +| #11 | fix(ga4): fix gtag.js dataLayer integration and consent defaults | ga4 | +| #12 | feat(core): consent queue guardrails — size limits, drop telemetry, flush drain | core | +| #8 | chore: version packages (first release) | release | +| #13 | chore: version packages (second release) | release | + +## What Shipped + +### Bug fixes + +- **Consent queue flush race condition** — events sitting in the 2s buffer timer were missed by `consent.drain()` on consent change. Non-exempt destinations never received the initial pageview after consent was granted. Fixed by flushing the buffer inside the consent `onChange` handler. +- **Double pageview on navigation** — Next.js `usePathname()` and `useSearchParams()` updating in separate render passes caused `PageTracker` effect to fire twice. Fixed by deriving a single URL string dependency. +- **Necessary consent always granted** — `necessary: true` is now pinned in consent state at init, `setState`, and `reset`. Debug panel shows it correctly. +- **GA4 dataLayer integration** — `gtag()` silently ignores Arrays; must use `function() { dataLayer.push(arguments); }` pattern. + +### New features + +- `maxQueueSize` option on `ConsentConfig` — drops oldest events when exceeded (ring buffer semantics) +- `queue:drop` telemetry event — emitted with `{ count, reason: "timeout" | "overflow" }` when events are lost +- `flush()` now drains the consent queue for permitted events — critical for page unload scenarios + +## Issues Opened (3) + +All from research into the necessary vs. exempt consent distinction: + +| Issue | Title | +|-------|-------| +| #14 | [Exempt destination guardrails](https://github.com/tyssejc/junction/issues/14) — first-party restriction, legal basis declaration, audit trail | +| #15 | [Exempt bypass queue/buffer](https://github.com/tyssejc/junction/issues/15) — behavioral divergence for immediate dispatch | +| #16 | [Unconditional pagehide flush](https://github.com/tyssejc/junction/issues/16) — client should always flush on unload | + +## Standards Documented (2) + +New design standards added to `agent-os/standards/core/`: + +- **consent-timing-heuristics.md** — When to assume consent won't arrive (CMP blocked vs. banner ignored vs. dismissed). SPA vs. MPA timing tradeoffs documented as open question. +- **necessary-vs-exempt.md** — Two always-allowed categories serving different privacy stack layers. Legal reality (ePrivacy Art 5(3) covers network requests), required guardrails, behavioral divergence table, open questions. + +## Research Conducted + +Three-agent research team (privacy counsel, technical architect, devil's advocate) analyzed the necessary/exempt distinction. Key finding: **ePrivacy Article 5(3) covers all client-initiated network requests, not just cookies** (EDPB Guidelines 2/2023, settled law). "Exempt" requires legitimate interest as its legal basis, with disclosure, balancing test, and user opt-out — none of which exist today. Issues #14-16 capture the remediation work. diff --git a/docs/strategy-synthesis.md b/docs/strategy-synthesis.md new file mode 100644 index 0000000..e0f2209 --- /dev/null +++ b/docs/strategy-synthesis.md @@ -0,0 +1,198 @@ +**Junction: Company Strategy and Market Position** + +Positioning, go-to-market, monetization, and competitive differentiation for an investor and operator audience + +Prepared as a strategic synthesis +March 2026 + +| What Junction is: a developer-native implementation and event-routing foundation for modern analytics and marketing data collection. | +| :---- | +| Who it is for first: technical, scaling companies that have outgrown ad hoc analytics but do not want full CDP complexity. | +| How it wins: more control than GTM/Adobe, less overhead than Segment/RudderStack, stronger typed validation and consent as a first-class runtime concern. | +| How it monetizes: productized services first, then hosted runtime, then observability and team workflow software. | + +# **Executive Summary** + +Junction should be built as a focused company around a clear gap in the market: scaling companies need a more modern foundation for analytics and marketing data collection, routing, consent handling, and implementation quality than traditional tag managers provide, but many are not ready for the cost, scope, and complexity of a full CDP. + +The strongest early company shape is open source core plus hosted product plus high-value implementation services. Open source drives trust, adoption, and ecosystem credibility. The hosted product monetizes convenience, reliability, observability, and team workflows. Services accelerate revenue, design-partner learning, migrations, and market entry without forcing the product to solve every bespoke customer edge case. + +Junction should not initially position itself as a CDP, nor should it try to out-Segment Segment or out-RudderStack RudderStack. Its most defensible position is the implementation and event-pipeline layer: code-first, AI-friendly, consent-aware, schema-validated, portable, and built for technical teams that want speed and control. + +The initial go-to-market should target technical growth-stage companies, especially startups and scaling businesses that are beginning to feel friction from fragmented instrumentation, rapidly expanding martech stacks, brittle pixels, and implementation rework. The primary story should be growth and execution, not governance. Governance, auditability, and compliance matter, but they should support the growth story rather than lead it. + +## **Core Investment Thesis** + +* There is a meaningful wedge between legacy tag management and full customer data platforms. +* Technical, AI-enabled teams are increasingly comfortable with code-first infrastructure when it improves speed and portability. +* Analytics implementations break down as businesses scale, creating demand for a modern collection and routing layer. +* Consent, event quality, and destination sprawl are now operational issues, not edge concerns. +* A services-assisted open-source model can create early revenue while preserving product discipline. + +# **Market Gap and Problem Statement** + +Traditional tag managers were designed for a world where browser-side deployment, UI-driven rules, and marketer-operated configuration were the norm. That model still works for many organizations, but it becomes brittle as products grow, stacks diversify, consent rules get stricter, and engineering teams demand more reliable implementation practices. + +At the other end of the market, customer data platforms and event infrastructure products offer broad collection, transformation, profile, and activation capabilities. Those platforms can be powerful, but they often introduce more scope, cost, and organizational overhead than a scaling company wants to take on early. + +This creates a clear gap: many companies need a modern implementation foundation before they need a full CDP. They need cleaner collection, better routing, stronger validation, and more dependable consent behavior. They need less mystery, less UI sprawl, and less rework. They do not necessarily need identity resolution, customer 360, or audience orchestration to solve their current problem. + +## **Where Junction Sits in the Stack** + +| Layer | What teams need | Typical incumbent | Junction opportunity | +| ----- | ----- | ----- | ----- | +| Legacy TMS | Deploy tags and rules quickly | GTM, Adobe Tags | Offer a code-first, typed, developer-native alternative | +| Event pipeline | Validate, route, enrich, govern events | Partial overlap across Segment/RudderStack | Become the implementation and routing layer for modern teams | +| CDP / identity | Profiles, audiences, identity resolution | Segment, RudderStack, Tealium | Integrate with this layer rather than become it early | + +# **Company Vision and Strategic Position** + +Junction should be defined as a developer-native analytics implementation company. The company is not primarily selling a prettier tag manager interface and is not primarily selling a customer data platform. It is selling the core operational layer that helps technical teams collect, validate, route, and evolve their marketing and product data infrastructure with more speed and control. + +The simplest way to describe the company is: Junction gives scaling teams more control than a legacy tag manager and less overhead than a full CDP. + +That position matters because it creates room to compete without pretending to be everything. Junction can be credibly compared to GTM, Adobe, Segment, and RudderStack, but it should remain disciplined about what it owns. It should own implementation, collection, routing, validation, consent-aware behavior, and developer workflow. It should integrate with the rest of the stack rather than trying to become the whole stack on day one. + +### **Recommended positioning statement** + +**Junction is the developer-native marketing and product data layer for scaling companies that need more control than GTM and less overhead than a full CDP.** + +# **Ideal Customer Profile and Go-to-Market Approach** + +## **Initial customer profile** + +* Technical growth-stage startups and scaling companies, typically beyond the earliest phase but not yet eager to buy enterprise data bureaucracy and vendor lock-in. +* Teams with real product or web complexity, multiple data destinations, and rising implementation pain. +* Organizations where engineering, product, growth, and data all rely on event collection but no single function wants to own an increasingly messy analytics stack. +* Companies that are already using AI-assisted development or are receptive to code-first workflows because those workflows improve speed and maintainability. + +## **Why startup and growth-stage companies first** + +For technical startups, code-first is often a feature rather than a drawback. These buyers are more comfortable with configuration in code, more willing to use AI-assisted implementation workflows, and less attached to legacy martech operating models. They are also easier to recruit as design partners because they move faster and have fewer internal blockers. + +Critically, the first commercial story should be about growth and execution. Fast-growing companies rarely buy first on governance rhetoric. They buy because they need to launch faster, add new tools with less rework, reduce implementation friction, and keep their stack from collapsing as complexity grows. Junction should be framed as growth infrastructure, with governance, validation, and consent functioning as the enabling foundation behind that promise. + +## **Go-to-market motion** + +| Phase | Primary motion | What is sold | Why it matters | +| ----- | ----- | ----- | ----- | +| Phase 1 | Design partners \+ services-led adoption | Migration, implementation, architecture, launch support | Creates revenue, trust, and real-world learning | +| Phase 2 | Hosted product upsell | Managed gateway, cloud runtime, logs, delivery reliability | Turns implementation into recurring revenue | +| Phase 3 | Product expansion | Observability, QA, debugging, workflow controls | Builds sticky software value and higher ACV | + +## **AI-native distribution advantage** + +Junction has a potential advantage that many incumbents do not: it can be designed explicitly for AI-assisted implementation. That means scaffolding configuration from prompts, generating event plans from plain English, explaining failed validation, helping teams migrate legacy tag logic into typed contracts, and offering CLI or agent experiences that make code-first adoption much easier. + +This does not replace the product strategy, but it can materially improve distribution and usability. For a startup audience, AI-native implementation may turn a perceived barrier into a differentiator. + +# **Competitive Differentiation** + +## **Competitive frame** + +Junction should not try to win simply by being cheaper. Lower price may help it get considered, but it will not define the company. The stronger answer to why Junction belongs in the consideration set is that it occupies a distinct position in the stack: a modern implementation and event-pipeline layer for code-first teams. + +Relative to GTM and Adobe, Junction offers a stronger code-native operating model, typed events, schema validation, and first-class consent behavior. Relative to Segment and RudderStack, Junction offers a lighter-weight, more controllable path for teams that want collection and routing without buying into a broad CDP footprint too early. Relative to specialists like Stape and Elevar, Junction can compete through developer experience, portability, and broader cross-stack applicability, while still leaving room for e-commerce-specific packaging later if desired. Tealium and Snowplow should also be treated as important reference points because they validate adjacent parts of the market: Tealium shows that collection, routing, and governance can form a real category, while Snowplow shows that developer-first event infrastructure is strategically credible. + +## **Competitive landscape tiers** + +Primary competitive set: Google Tag Manager, Adobe Launch/Tags, Segment, RudderStack, and Tealium. These are the companies most likely to appear in an active buying conversation because they already occupy the budget line for collection, routing, tag management, or customer data infrastructure. + +Adjacent competitive set: Snowplow, mParticle, Piwik PRO, JENTIS, and Commanders Act. These are not always direct substitutes, but they matter because they compete for the same strategic narrative: privacy-aware collection, governed event pipelines, or developer-owned data infrastructure. + +Vertical and ecosystem alternatives: Stape and Elevar should be monitored closely, especially if Junction leans further into server-side tracking operations or e-commerce. These tools prove that buyers will pay for improved delivery, attribution support, and operational simplicity in narrower but commercially important contexts. + +## **How Junction should frame itself against each class** + +Against GTM and Adobe, Junction should present itself as the modern implementation model: versioned, typed, consent-aware, and built for AI-assisted engineering teams rather than UI-centric tag administration. + +Against Segment, RudderStack, and Tealium, Junction should emphasize focus. The company is not trying to replace the entire CDP or customer-360 stack. It offers a simpler, more affordable, and more controllable implementation layer for companies that want strong collection and routing before they need full identity, audience, and activation products. + +Against Snowplow, Junction should stress the operational side of analytics implementation: easier adoption for web and growth teams, consent-native routing, destination portability, and a shorter path from implementation to business value. Snowplow validates the developer-first thesis, but Junction can win by being more implementation- centric and easier to operationalize for scaling companies. + +Against specialists such as Stape and Elevar, Junction should compete on breadth of applicability. Those companies solve important but narrower problems. Junction can become the foundational layer that supports e-commerce, SaaS, and broader growth use cases without being locked to a single delivery model or platform ecosystem. + +## **Competitive positioning summary** + +The strategic takeaway is that Junction does not need to be the broadest platform in the market to be compelling. It needs to be the best product in a specific gap: the developer-native collection, validation, consent, and routing layer for scaling companies that have outgrown legacy tag management but do not want the cost, complexity, or scope creep of a full CDP too early. + +| Competitor set | What they are strong at | Where they create friction | Junction advantage | Implication | +| ----- | ----- | ----- | ----- | ----- | +| GTM / Adobe | Fast tag deployment, familiar workflows | UI sprawl, brittle logic, weak code-native governance | Typed, versioned, code-first implementation | Strong replacement narrative for technical teams | +| Segment | Broad CDP capabilities, strong brand | Cost, complexity, broader scope than many teams need | Simpler, cheaper, narrower, more controllable | Position as collection/routing layer without CDP baggage | +| RudderStack | Technical story, event pipeline breadth | Can still widen into platform complexity | Sharper implementation focus and better AI-native workflow potential | Compete through focus, UX, and scope discipline | +| Stape / Elevar | Operational specialization, especially server-side and e-commerce | Narrower use-case coverage | More portable foundation across stacks and teams | Could be complemented or competed with depending on vertical strategy | + +# **Monetization Plan** + +The monetization model should be layered. Open source remains the trust and adoption engine, but the paid offering must map to operational pain points that customers value enough to pay for. The strongest model is not one revenue stream; it is a progression from services into recurring infrastructure and then into higher-value operating software. + +## **Revenue pillars** + +| Revenue pillar | Customer value | Early importance | Long-term value | Notes | +| ----- | ----- | ----- | ----- | ----- | +| Implementation services | Time-to-value and expertise | Very high | Moderate | Best early revenue source if tightly productized | +| Hosted gateway / cloud runtime | Convenience and reliability | High | High | Recurring revenue foundation; avoid becoming commodity hosting | +| Observability / debugging / event QA | Confidence and troubleshooting speed | Medium | Very high | Likely the strongest premium software surface | +| Team workflows / environments / audit trail | Coordination and control | Low to medium | High | Important for expansion into larger teams and agencies | + +## **Recommended commercialization sequence** + +* Start with productized implementation and migration services to secure design partners, prove outcomes, and learn where the product must mature. +* Add hosted gateway and managed runtime offerings to turn deployments into recurring infrastructure revenue. +* Expand into observability, debugging, validation dashboards, and event QA to create sticky premium software value. +* Layer in environments, approvals, audit trail, and access controls as the customer base broadens into agencies and larger teams. + +## **What should remain open source** + +To preserve trust and adoption, the open-source core should continue to cover the fundamentals: event collection, routing, consent behavior, and core validation. Paid product surfaces should concentrate on convenience, cloud operations, visibility, collaboration, support, and team workflow rather than crippling the underlying runtime. + +# **Company Structure and the Role of Services** + +A particularly attractive early structure is to let Stacked Analytics operate alongside Junction as a services and implementation partner. This mirrors the pattern used successfully in other data companies where services created both early revenue and product insight without forcing the software roadmap to absorb every custom engagement. + +The strategic benefit is simple: Stacked can absorb high-touch migration, implementation, architecture, and support work while Junction stays disciplined as a product. This creates a useful separation between custom execution and reusable software. + +The model works best if the line between the two remains explicit. Stacked should own implementation, migration, architecture design, consent strategy, QA, and launch support. Junction should own the runtime, routing, validation, consent-aware collection, hosted product, observability, and workflow software. Services should inform the product, not trap it. + +## **Operating principles for a services-assisted product company** + +* Use services to discover repeatable needs that deserve productization. +* Avoid one-off product work that is unlikely to generalize across customers. +* Package services into clear offers instead of allowing endless custom sprawl. +* Keep Junction branded and legible as a standalone product and company. + +# **Strategic Boundary: Why Junction Should Not Start as a CDP** + +Many collection and routing companies eventually widen into customer data platform territory. That pattern is understandable because profiles, audiences, and activation create larger budgets and broader platform ambitions. However, trying to become a CDP too early would dilute Junction’s most defensible position and pull it into a much more crowded, scope-heavy fight. + +Junction does not need to become a CDP to be strategically important. It needs to be CDP-compatible. In practice, that means being easy to connect to warehouses, profile systems, and downstream tools while remaining focused on implementation, collection, routing, validation, and consent-aware behavior. + +This focus is a strength. It allows Junction to own a clear layer in the stack and become the preferred foundation for companies that are too sophisticated for legacy TMS workflows but too early or too focused to adopt a broad CDP platform. + +# **Key Risks and Strategic Questions** + +| Risk or question | Why it matters | Mitigation | +| ----- | ----- | ----- | +| Getting into the consideration set | The product will lose if it is never evaluated | Use open source, sharp category language, design partners, and services-led distribution | +| Over-expanding into CDP scope | Could dilute focus and drag Junction into broader platform battles | Maintain a clear implementation-layer identity and integrate outward | +| Services overwhelming product focus | Custom work can distort roadmap and margins | Package services and require productization discipline | +| Competing against modern data tools on price alone | Cheap is not durable differentiation | Anchor on focus, control, implementation quality, and AI-native workflow | + +# **12–18 Month Strategic Priorities** + +* Secure a small number of design partners and use them to validate both product-market fit and packaging. +* Productize a migration and implementation offer that Stacked Analytics can deliver repeatedly. +* Ship a managed gateway/runtime that removes hosting and reliability friction for early adopters. +* Prioritize observability, delivery visibility, validation diagnostics, and event QA as the first premium software surfaces. +* Develop AI-assisted tooling and CLI workflows that materially lower implementation friction for code-first teams. +* Build proof points in one or two early segments rather than marketing to every possible analytics buyer. + +# **Conclusion** + +Junction has the ingredients for a real company because it addresses a meaningful and increasingly visible gap in the data stack. Companies need a better foundation for implementation, collection, and routing as analytics and martech complexity increases, but they do not all want or need a full CDP to solve that problem. + +The opportunity is strongest if Junction remains disciplined about what it is: a developer-native implementation and event pipeline layer for modern teams. The company should lead with growth and execution outcomes, enter the market through technical scaling companies, monetize first through services and hosted runtime, and build toward observability and team workflow software as the durable recurring engine. + +In that shape, Junction can become a credible new category entrant: not simply an open-source tag manager and not another full-suite CDP, but the modern implementation foundation between those worlds. + diff --git a/docs/superpowers/plans/2026-03-23-ga4-demo-integration.md b/docs/superpowers/plans/2026-03-23-ga4-demo-integration.md new file mode 100644 index 0000000..9facf28 --- /dev/null +++ b/docs/superpowers/plans/2026-03-23-ga4-demo-integration.md @@ -0,0 +1,170 @@ +# GA4 Demo Integration — Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** Wire up the real GA4 destination in the demo app to validate end-to-end functionality. + +**Architecture:** Swap the simulated GA4 no-op destination for the real `@junctionjs/destination-ga4` package in the demo's Junction config. The Measurement ID comes from an env var so it's not committed. The demo sink continues to show GA4 transforms for visualization. + +**Tech Stack:** Next.js 15, @junctionjs/destination-ga4, Google Analytics 4, gtag.js + +--- + +### Task 1: Remove simulatedGA4 from demo-sink.ts + +**Files:** +- Modify: `apps/demo/lib/demo-sink.ts:81` + +- [ ] **Step 1: Remove simulatedGA4 export** + +In `apps/demo/lib/demo-sink.ts`, remove line 81: + +```ts +// DELETE this line: +export const simulatedGA4 = noopDestination("ga4", ["analytics"]); +``` + +- [ ] **Step 2: Verify demo-sink.ts still exports the other simulated destinations and demoSink** + +The file should still export: `simulatedAmplitude`, `simulatedMeta`, `demoSink`, `getEvents`, `onEvent`, `clearEvents`, and `CapturedEvent`. + +- [ ] **Step 3: Commit** + +```bash +git add apps/demo/lib/demo-sink.ts +git commit -m "refactor(demo): remove simulatedGA4 no-op destination" +``` + +--- + +### Task 2: Wire up real GA4 destination in junction-config.ts + +**Files:** +- Modify: `apps/demo/lib/junction-config.ts` + +- [ ] **Step 1: Update imports** + +Replace: +```ts +import { demoSink, simulatedAmplitude, simulatedGA4, simulatedMeta } from "./demo-sink"; +``` + +With: +```ts +import { ga4 } from "@junctionjs/destination-ga4"; +import { demoSink, simulatedAmplitude, simulatedMeta } from "./demo-sink"; +``` + +- [ ] **Step 2: Replace simulatedGA4 destination entry with real ga4** + +Replace: +```ts + { destination: simulatedGA4, config: {}, enabled: true }, +``` + +With: +```ts + // Real GA4 — gated on env var. When disabled, the collector skips it + // entirely (no init call), so the empty measurementId fallback is safe. + // See: packages/core/src/collector.ts:97 — `if (entry.enabled === false) continue;` + ...(process.env.NEXT_PUBLIC_GA4_MEASUREMENT_ID + ? [ + { + destination: ga4, + config: { + measurementId: process.env.NEXT_PUBLIC_GA4_MEASUREMENT_ID, + sendPageView: false, + consentMode: true, + }, + consent: ["analytics"], + enabled: true, + }, + ] + : []), +``` + +> **Note:** Using spread-conditional instead of `enabled: false` with an empty string. This avoids the destination entry entirely when the env var is absent — cleaner and doesn't rely on the collector's `enabled` guard. + +- [ ] **Step 3: Update the file's doc comment** + +Replace the comment block above `destinations:` to reflect that GA4 is now real: + +```ts +/** + * Junction collector configuration for the Orbit Supply demo. + * + * The demo-sink (exempt) always receives events for visualization. + * GA4 is a real destination gated on NEXT_PUBLIC_GA4_MEASUREMENT_ID env var. + * Simulated Amplitude/Meta destinations are consent-gated so the + * consent queue actually works: events queue while pending, flush on + * grant, and drop on deny. + */ +``` + +- [ ] **Step 4: Verify TypeScript compiles** + +Run: `cd apps/demo && npx tsc --noEmit` +Expected: No errors + +- [ ] **Step 5: Commit** + +```bash +git add apps/demo/lib/junction-config.ts +git commit -m "feat(demo): wire up real GA4 destination with consent mode" +``` + +--- + +### Task 3: Create .env.local with placeholder + +**Files:** +- Create: `apps/demo/.env.local` + +- [ ] **Step 1: Create .env.local** + +``` +NEXT_PUBLIC_GA4_MEASUREMENT_ID=G-XXXXXXXXXX +``` + +(User will replace `G-XXXXXXXXXX` with their real Measurement ID) + +- [ ] **Step 2: Verify .env.local is gitignored** + +Run: `git check-ignore apps/demo/.env.local` +Expected: `apps/demo/.env.local` (confirms it's ignored by root `.gitignore` pattern `.env*.local`) + +- [ ] **Step 3: No commit needed** — file is gitignored + +--- + +### Task 4: Manual smoke test + +- [ ] **Step 1: Start dev server** + +Run: `cd apps/demo && npm run dev` + +- [ ] **Step 2: Open browser and check gtag.js loads** + +Open http://localhost:3000. In DevTools Network tab, filter for `gtag`. Verify: +- `gtag/js?id=G-XXXXXXXXXX` script loads +- No console errors from Junction or GA4 + +- [ ] **Step 3: Check events fire on interaction** + +Navigate to Store page, click a product. In Network tab, filter for `google-analytics.com/g/collect`. Verify: +- Requests are being sent to GA4 +- Event names match expected GA4 events (e.g., `page_view`, `view_item`) + +- [ ] **Step 4: Check consent gating** + +Clear cookies/localStorage, reload. Before accepting consent: +- Events should queue (visible in demo's event viewer) +- No GA4 network requests should fire + +After granting analytics consent: +- Queued events should flush +- GA4 network requests should appear + +- [ ] **Step 5: Check GA4 Realtime dashboard** + +Open GA4 property > Reports > Realtime. Verify events appear with correct names and parameters. diff --git a/docs/superpowers/plans/2026-03-28-context-management-migration.md b/docs/superpowers/plans/2026-03-28-context-management-migration.md new file mode 100644 index 0000000..e8252e2 --- /dev/null +++ b/docs/superpowers/plans/2026-03-28-context-management-migration.md @@ -0,0 +1,802 @@ +# Context Management Migration Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** Migrate project context from agent-os into native Claude Code conventions (CLAUDE.md + path-scoped rules) so any contributor can clone the repo and be productive with Claude Code immediately. + +**Architecture:** Move agent-os product docs to `docs/product/`, consolidate 17 agent-os standards into 6 path-scoped `.claude/rules/` files, create a lean CLAUDE.md (<200 lines), add superpowers install instructions, and clean up agent-os artifacts. + +**Tech Stack:** Claude Code (.claude/ conventions), Markdown + +--- + +### Task 1: Create `docs/product/` from agent-os product docs + +**Files:** +- Create: `docs/product/mission.md` (copy from `agent-os/product/mission.md`) +- Create: `docs/product/roadmap.md` (copy from `agent-os/product/roadmap.md`) +- Create: `docs/product/tech-stack.md` (copy from `agent-os/product/tech-stack.md`) + +- [ ] **Step 1: Create `docs/product/` directory and copy files** + +```bash +mkdir -p docs/product +cp agent-os/product/mission.md docs/product/mission.md +cp agent-os/product/roadmap.md docs/product/roadmap.md +cp agent-os/product/tech-stack.md docs/product/tech-stack.md +``` + +- [ ] **Step 2: Verify files copied correctly** + +```bash +ls docs/product/ +``` + +Expected: `mission.md roadmap.md tech-stack.md` + +- [ ] **Step 3: Commit** + +```bash +git add docs/product/ +git commit -m "docs: move product context from agent-os to docs/product" +``` + +--- + +### Task 2: Create `.claude/rules/consent.md` + +Merges three related agent-os standards: consent-state-machine, consent-timing-heuristics, necessary-vs-exempt. Scoped to `packages/core/**`. + +**Files:** +- Create: `.claude/rules/consent.md` + +- [ ] **Step 1: Create the rule file** + +```markdown +--- +paths: + - "packages/core/**" +--- + +# Consent Standards + +## State Machine + +Consent is a reactive state machine with event queuing, not a boolean gate. + +- **Merge, not replace:** `setState({ analytics: true })` merges with existing state +- **AND logic:** Destination requiring `["analytics", "marketing"]` needs BOTH granted +- **"necessary" and "exempt" always allowed:** Never blocked by consent +- **Pending = undefined:** Categories not yet set are pending, not denied +- **Lenient by default:** Events pass through; strict mode is opt-in + +### Event Queuing + +Events arriving before consent resolves are queued and replayed when consent changes. + +- Deduplicated by event ID +- `sentTo` Set tracks which destinations already received each event +- Queue expires based on `queueTimeout` (default 30s) +- In strict mode, queuing is disabled — pending = denied, events drop + +### CMP Fallback + +~15-20% of privacy-conscious users block CMP scripts. Use `consentFallback`: + +```typescript +consent: { + consentFallback: { + timeout: 3000, + state: { analytics: false, marketing: false } + } +} +``` + +### DNT & GPC + +When `respectDNT` or `respectGPC` is enabled: +- DNT disables `analytics` and `marketing` +- GPC additionally disables `personalization` + +### ConsentSignals (Separate from Destinations) + +Vendor consent protocols (e.g. Google Consent Mode) are modeled as ConsentSignals, not part of destinations: + +```typescript +consentSignals: [ + googleConsentMode({ waitForUpdate: 500 }) +] +``` + +## Timing Heuristics + +Not all "pending" consent is equal. Junction distinguishes the signal behind why consent hasn't resolved. + +| Signal | Meaning | Action | +|--------|---------|--------| +| CMP blocked | Script never loads | `consentFallback` (3s) | +| CMP loaded, no interaction | Banner visible | Queue, `queueTimeout` (30s) | +| CMP loaded, dismissed | Closed without choosing | Conservative defaults | + +**Future direction:** Accept a `consentSignalHint` from CMP integrations: +- `"blocked"` → fast fallback (seconds) +- `"visible"` → patient queue (30s+) +- `"dismissed"` → conservative defaults immediately + +### SPA vs MPA + +- **MPA:** Navigation = unload = queue loss. First pageview uniquely fragile. +- **SPA:** User stays on page, consent resolves naturally. +- May be best addressed at integration layer (e.g. `@junctionjs/next` defaults) rather than core. + +## Necessary vs. Exempt + +Two always-allowed consent categories serving different layers of the privacy stack. + +- **necessary**: CMP/storage layer. Cookies and web storage required for site functionality. Pinned to `true` in state. Legal basis: ePrivacy Art 5(3). +- **exempt**: Data/dispatch layer. Destinations that receive events regardless of consent state. Used for first-party observability. Legal basis: GDPR Art 6(1)(f) legitimate interest. + +### Why Two Categories + +They operate at different enforcement layers: +- CMPs enforce **storage** (cookies, localStorage) +- Junction enforces **dispatch** (network requests to destinations) + +### Guardrails (required) + +- **First-party only**: Exempt destinations must be first-party or contractually bound processors +- **Legal basis declaration**: Each exempt destination should declare its basis +- **Audit trail**: Events dispatched to exempt destinations carry `is_exempt: true` metadata +- **Transparency**: Emit `destination:exempt` events for debug panels and audit logs + +| Aspect | necessary | exempt | +|--------|-----------|--------| +| Consent UI | Visible | Hidden | +| Consent queue | Participates | Bypasses | +| Legal basis | ePrivacy strictly necessary | GDPR legitimate interest | +| User can disable | No (always on) | No (operational) | +``` + +- [ ] **Step 2: Verify frontmatter is valid** + +Open the file and confirm the `paths` frontmatter is correct YAML. + +- [ ] **Step 3: Commit** + +```bash +git add .claude/rules/consent.md +git commit -m "docs: add path-scoped consent rules for packages/core" +``` + +--- + +### Task 3: Create `.claude/rules/destinations.md` + +Merges: destination-interface, event-name-mapping, script-loading, system-events, error-isolation. Scoped to `packages/destination-*/**`. + +**Files:** +- Create: `.claude/rules/destinations.md` + +- [ ] **Step 1: Create the rule file** + +```markdown +--- +paths: + - "packages/destination-*/**" +--- + +# Destination Standards + +## Interface + +Destinations are plain objects with async functions, not classes. + +- Tree-shakeable (classes aren't), composable, easy to test +- Use factory functions (`createGA4()`, `http(config)`), not `new` + +```typescript +interface Destination { + name: string; + version: string; + consent: ConsentCategory[]; // AND logic + runtime: "client" | "server" | "both"; + + init: (config: TConfig) => Promise | void; + transform: (event: JctEvent, config: TConfig) => unknown | null; + send: (payload: unknown, config: TConfig) => Promise; + onConsent?: (state: ConsentState) => void; + teardown?: () => Promise | void; +} +``` + +- `transform` returns `null` to skip an event for this destination +- `transform` is a pure function — no side effects, no network calls +- `send` handles all network I/O +- Config is type-generic: `Destination` + +## Event Name Mapping + +All destinations use a 3-tier fallback: + +1. **Config override** — `config.eventNameMap["product:viewed"]` +2. **Default map** — Built-in mapping per destination +3. **Generated name** — `entity_action` (or destination-specific format) + +```typescript +function getEventName(event: JctEvent, config: Config): string { + const key = `${event.entity}:${event.action}`; + return config.eventNameMap?.[key] + ?? DEFAULT_MAP[key] + ?? `${event.entity}_${event.action}`; +} +``` + +### Per-Destination Defaults + +| entity:action | GA4 | Amplitude | Meta | +|---|---|---|---| +| page:viewed | page_view | Page Viewed | PageView | +| product:viewed | view_item | Product Viewed | ViewContent | +| product:added | add_to_cart | Product Added | AddToCart | +| order:completed | purchase | Order Completed | Purchase | + +## Script Loading + +Client-side destinations that load vendor scripts use a queue-before-load pattern: + +- Always check `typeof window === "undefined"` first (SSR safety) +- Always check if already loaded (idempotent) +- Create queuing stub before loading script +- Use `script.async = true` +- Support custom script URLs via config +- Gate loading with `loadScript?: boolean` config (default: true) + +## System Events + +The `_system` entity is reserved for internal lifecycle events. All destinations must filter them: + +```typescript +transform(event: JctEvent, config: Config) { + if (event.entity === "_system") return null; + // ... normal transformation +} +``` + +## Error Isolation + +The collector must never crash. Every external boundary is wrapped in try/catch. + +| Boundary | Failure behavior | +|---|---| +| `destination.init()` | Logged, destination skipped, collector continues | +| `destination.transform()` | Logged, event skipped for that destination, others still receive it | +| `destination.send()` | `.catch()` logs error, no await blocking | +| Consent listeners | Caught per-listener, other listeners still fire | + +- Use `emit("destination:error", ...)` so consumers can observe failures +- Never let one destination's failure affect another +- Prefix all console output with `[Junction]` +``` + +- [ ] **Step 2: Commit** + +```bash +git add .claude/rules/destinations.md +git commit -m "docs: add path-scoped destination rules for destination packages" +``` + +--- + +### Task 4: Create `.claude/rules/gateway.md` + +From: gateway-request-flow. Scoped to `packages/gateway/**`. + +**Files:** +- Create: `.claude/rules/gateway.md` + +- [ ] **Step 1: Create the rule file** + +```markdown +--- +paths: + - "packages/gateway/**" +--- + +# Gateway Standards + +## Request Flow + +``` +POST /collect + → CORS preflight (OPTIONS) + → Auth check (bearer token or x-api-key) + → Parse JSON body: { events: JctEvent[], consent?: ConsentState } + → Apply client-reported consent + → Per event: set context, identify if userId, track(entity, action, props) + → Flush immediately + → Return { ok: true, received: count } +``` + +## Edge-First Design + +- **Flush immediately** after processing — edge functions are short-lived +- No batching or queueing at gateway level (client SDK handles that) +- Uses only Web Standard APIs: Request, Response, URL, fetch, JSON +- Zero platform-specific imports + +## Server Context Enrichment + +Gateway extracts server-side context per request: +- IP: `cf-connecting-ip` → `x-forwarded-for` → `x-real-ip` +- Geo: `cf-ipcountry`, `cf-ipregion`, `cf-ipcity` +- User-Agent, Referer + +Merged with client context via `resolveContext` closure. +``` + +- [ ] **Step 2: Commit** + +```bash +git add .claude/rules/gateway.md +git commit -m "docs: add path-scoped gateway rules" +``` + +--- + +### Task 5: Create `.claude/rules/events.md` + +From: entity-action-events. Scoped to core and client packages. + +**Files:** +- Create: `.claude/rules/events.md` + +- [ ] **Step 1: Create the rule file** + +```markdown +--- +paths: + - "packages/core/**" + - "packages/client/**" +--- + +# Event Standards + +## Entity:Action Pairs + +All events use `entity:action` pairs, not flat strings. + +```typescript +// Good +track("product", "viewed", { product_id: "123" }) +track("order", "completed", { order_id: "456" }) + +// Bad +track("Product Viewed", { product_id: "123" }) +``` + +## Naming Rules + +- **Entities:** lowercase, singular or plural (`product`, `page`, `order`, `user`) +- **Actions:** lowercase, past tense preferred (`viewed`, `added`, `completed`, `signed_up`) +- **Combined key:** `entity:action` used for contract lookup and destination mapping +- Wildcard contracts (`entity:*`) match all actions for an entity +- If no contract exists, events pass through unvalidated + +## Destination Mapping + +Destinations map entity:action to vendor event names: + +```typescript +const GA4_EVENT_MAP: Record = { + "page:viewed": "page_view", + "product:viewed": "view_item", + "product:added": "add_to_cart", + "order:completed": "purchase", +}; +``` +``` + +- [ ] **Step 2: Commit** + +```bash +git add .claude/rules/events.md +git commit -m "docs: add path-scoped event naming rules for core/client" +``` + +--- + +### Task 6: Create `.claude/rules/testing.md` + +Merges: vitest-conventions, mock-patterns, test-factories. Scoped to test files. + +**Files:** +- Create: `.claude/rules/testing.md` + +- [ ] **Step 1: Create the rule file** + +```markdown +--- +paths: + - "**/*.test.ts" +--- + +# Testing Standards + +## Vitest Setup + +- Centralized config at root `vitest.config.ts` +- Node environment by default; `@vitest-environment happy-dom` for DOM tests +- Globals enabled (`describe`, `it`, `expect`, `vi` available without import) +- Tests co-located: `packages/*/src/**/*.test.ts` + +## Structure + +```typescript +describe("ConsentManager", () => { // Module/class + describe("initialization", () => { // Feature group + it("starts with the default state", () => { // Behavior + }); + }); +}); +``` + +- 2-3 levels of `describe` nesting +- `it` statements describe behavior, not functions +- Use `// ─── section name ───` dividers for major sections + +## Fake Timers + +```typescript +beforeEach(() => { vi.useFakeTimers(); }); +afterEach(() => { vi.useRealTimers(); }); +``` + +- Use `vi.advanceTimersByTime(ms)` for sync advancement +- Use `await vi.advanceTimersByTimeAsync(ms)` when microtasks need to resolve + +## Mock Patterns + +```typescript +// vi.fn() — new functions +onConsent: vi.fn() +init: vi.fn().mockResolvedValue(undefined) +send: vi.fn().mockRejectedValue(new Error("Network error")) +transform: vi.fn((event) => ({ transformed: true, event })) + +// vi.spyOn() — existing objects (always suppress output) +vi.spyOn(console, "error").mockImplementation(() => {}) + +// vi.stubGlobal() — browser globals in Node tests +vi.stubGlobal("navigator", { sendBeacon: vi.fn() }) +``` + +- `vi.fn()` for mock objects in factories +- `vi.spyOn()` only for existing objects (console, timers) +- Always `.mockImplementation(() => {})` on console spies +- Reset with `.mockClear()` in `beforeEach` if reusing across tests + +## Test Factories + +```typescript +function makeEvent(overrides?: Partial): JctEvent { + return { + entity: "test", + action: "tracked", + properties: {}, + context: {}, + user: { anonymousId: "anon-123" }, + timestamp: new Date().toISOString(), + id: "evt-001", + version: "1.0.0", + source: { type: "client", name: "test", version: "0.0.0" }, + ...overrides, + }; +} + +function mockDestination(overrides?: Partial): Destination { + return { + name: "test-destination", + version: "0.1.0", + consent: ["analytics"], + runtime: "both", + init: vi.fn().mockResolvedValue(undefined), + transform: vi.fn((event) => ({ transformed: true, event })), + send: vi.fn().mockResolvedValue(undefined), + ...overrides, + }; +} +``` + +- `make*` for data objects, `mock*` for objects with spied methods +- Accept `Partial` and spread overrides last +- Provide complete, sensible defaults +- Co-locate factories in each test file (no shared test utils) + +## Rules + +- Every test file is self-contained (own factories, own setup) +- Clean up in `afterEach`: restore timers, clear mocks +- No shared mutable state between tests +- Behavior-focused test names: "notifies listeners on change", not "test notify" +``` + +- [ ] **Step 2: Commit** + +```bash +git add .claude/rules/testing.md +git commit -m "docs: add path-scoped testing rules for test files" +``` + +--- + +### Task 7: Create `.claude/rules/packages.md` + +Merges: dependency-layering, esm-only-build, package-exports, biome-code-style. Scoped to all packages. + +**Files:** +- Create: `.claude/rules/packages.md` + +- [ ] **Step 1: Create the rule file** + +```markdown +--- +paths: + - "packages/**" +--- + +# Package Standards + +## Dependency Layering + +Packages form a strict hierarchy. No circular deps. + +``` +@junctionjs/{astro,next} <- Framework integrations +@junctionjs/destination-* <- Destinations +@junctionjs/{client,gateway} <- Runtime wrappers +@junctionjs/core <- Foundation +``` + +| Package type | How it depends on core | +|---|---| +| `client`, `gateway` | `dependencies` | +| `destination-*` | `peerDependencies` | +| Framework integrations | `peerDependencies` on core + client | + +- Destinations must never import from `client` or `gateway` +- Core has no workspace dependencies (only Zod) +- No package may depend on a package in a higher layer + +## ESM-Only Build + +All packages output ESM only. No CJS. + +```bash +tsup src/index.ts --format esm --dts --sourcemap --target es2022 --no-config +``` + +- Always: `--format esm --dts --sourcemap --target es2022 --no-config` +- Mark workspace dependencies as `--external` +- Mark framework dependencies as `--external` +- No tsup config files — CLI flags only +- Output to `dist/` + +## Package Exports + +All packages use `@junctionjs/*` scope. + +- Destinations: `@junctionjs/destination-{provider}` +- Framework integrations: `@junctionjs/{framework}` + +```json +"exports": { + ".": { + "import": "./dist/index.js", + "types": "./dist/index.d.ts" + } +} +``` + +- ESM only — no `require` condition +- Every export needs both `.js` and `.d.ts` +- `files` field: `["dist", "README.md"]` +- `publishConfig`: `{ "access": "public", "provenance": true }` + +## Code Style (Biome) + +- Double quotes, always semicolons, trailing commas everywhere +- 2-space indent, 120 char line width +- Unused variables/imports: warn (not error) +- `noExplicitAny`: off, `noNonNullAssertion`: off +- Import organization enabled (Biome sorts imports) +- Never add ESLint or Prettier configs +- Don't disable Biome rules without good reason +``` + +- [ ] **Step 2: Commit** + +```bash +git add .claude/rules/packages.md +git commit -m "docs: add path-scoped package rules" +``` + +--- + +### Task 8: Create CLAUDE.md + +**Files:** +- Create: `CLAUDE.md` + +- [ ] **Step 1: Create the CLAUDE.md file** + +```markdown +# Junction + +Junction is a TypeScript event collection layer for scaling technical teams. Config-as-code, consent-first, isomorphic (browser/Node/edge), destination-agnostic. Think "tag manager for engineers" — more control than GTM, less overhead than a CDP. + +## Quick Start + +```bash +npm install +npm run build # Build all packages (Turborepo) +npm test # Vitest (all packages) +npm run typecheck # TypeScript strict mode +npm run lint # Biome check +npm run format # Biome format --write +``` + +## Monorepo Structure + +``` +packages/ +├── core/ # Isomorphic collector, consent state machine, validation +├── client/ # Browser runtime (sessions, anon IDs, page views) +├── gateway/ # WinterCG edge gateway (Cloudflare Workers, Deno, Bun) +├── debug/ # In-page debug panel +├── auto-collect/ # Automatic event collection +├── astro/ # Astro v5+ integration +├── next/ # Next.js integration +├── cmp-onetrust/ # OneTrust CMP adapter +├── destination-amplitude/ # Amplitude destination +├── destination-ga4/ # GA4 destination +├── destination-meta/ # Meta Pixel + CAPI destination +├── destination-http/ # Generic HTTP destination +├── destination-plausible/ # Plausible destination +apps/ +└── demo/ # Demo application +``` + +## Key Architecture Decisions + +- **Entity:action events** — all events use `track("product", "viewed", props)`, not flat strings +- **Consent state machine** — reactive with queuing, AND logic, strict/lenient modes. See `.claude/rules/consent.md` +- **Plain-object destinations** — factory functions, not classes. See `.claude/rules/destinations.md` +- **ESM only** — no CJS builds. tsup with `--format esm --dts --sourcemap --target es2022 --no-config` +- **Zod schemas** — runtime event validation with strict and lenient modes + +## Gotchas + +- **gtag.js requires Arguments objects** — `window.dataLayer.push()` silently ignores plain Arrays. Always use `function() { dataLayer.push(arguments); }` pattern. See the GA4 destination for reference. +- **Consent queue deduplication** — events are deduped by ID in the consent queue. Always ensure events have unique IDs. +- **System events** — the `_system` entity is reserved. All destinations must return `null` from `transform()` for system events. +- **Dependency layers** — destinations must never import from `client` or `gateway`. Core has no workspace deps. See `.claude/rules/packages.md`. + +## Testing + +```bash +npm test # All tests +npx vitest run packages/core # Single package +npx vitest --watch # Watch mode +npx playwright test --config e2e/playwright.config.ts # E2E +``` + +- Tests co-located with source: `packages/*/src/**/*.test.ts` +- Use `make*` factories for data, `mock*` for spied objects +- See `.claude/rules/testing.md` for full conventions + +## Writing a New Destination + +See `CONTRIBUTING.md` for the full guide. The short version: + +1. Create `packages/destination-/` +2. Implement `Destination` interface (init, transform, send) +3. Use 3-tier event name mapping (config override → default map → generated) +4. Filter `_system` events in `transform()` +5. Add tests + +## Claude Code Setup + +This project uses [superpowers](https://github.com/anthropics/claude-plugins-official/tree/main/superpowers) for development workflow skills (planning, TDD, debugging, code review). + +```bash +claude plugins install superpowers@claude-plugins-official +``` + +Path-scoped rules in `.claude/rules/` load contextually — consent rules when editing core, destination rules when editing destinations, etc. + +## Links + +- Product context: `docs/product/` (mission, roadmap, tech stack) +- Contributing guide: `CONTRIBUTING.md` +- Release process: `RELEASING.md` +``` + +- [ ] **Step 2: Commit** + +```bash +git add CLAUDE.md +git commit -m "docs: add CLAUDE.md for Claude Code contributor experience" +``` + +--- + +### Task 9: Clean up agent-os artifacts + +**Files:** +- Delete: `agent-os/` (entire directory) +- Delete: `.claude/commands/agent-os/` (slash commands that depend on agent-os) + +- [ ] **Step 1: Remove agent-os directory** + +```bash +rm -rf agent-os/ +``` + +- [ ] **Step 2: Remove agent-os slash commands** + +```bash +rm -rf .claude/commands/agent-os/ +``` + +- [ ] **Step 3: Check if .claude/commands/ is now empty and clean up if so** + +```bash +ls .claude/commands/ +``` + +If empty, remove the directory: + +```bash +rmdir .claude/commands/ +``` + +- [ ] **Step 4: Commit** + +```bash +git add -A +git commit -m "chore: remove agent-os directory and commands (migrated to .claude/rules and docs/product)" +``` + +--- + +### Task 10: Final verification + +- [ ] **Step 1: Verify the new structure** + +```bash +ls CLAUDE.md +ls docs/product/ +ls .claude/rules/ +``` + +Expected: +- `CLAUDE.md` exists at root +- `docs/product/`: `mission.md`, `roadmap.md`, `tech-stack.md` +- `.claude/rules/`: `consent.md`, `destinations.md`, `events.md`, `gateway.md`, `packages.md`, `testing.md` + +- [ ] **Step 2: Verify agent-os is gone** + +```bash +ls agent-os/ 2>&1 +ls .claude/commands/agent-os/ 2>&1 +``` + +Expected: both return "No such file or directory" + +- [ ] **Step 3: Run build and tests to confirm nothing broke** + +```bash +npm run build && npm test +``` + +Expected: all pass (this migration is docs-only, no code changes) diff --git a/docs/superpowers/specs/2026-03-23-ga4-demo-integration-design.md b/docs/superpowers/specs/2026-03-23-ga4-demo-integration-design.md new file mode 100644 index 0000000..dfa47ed --- /dev/null +++ b/docs/superpowers/specs/2026-03-23-ga4-demo-integration-design.md @@ -0,0 +1,59 @@ +# GA4 Demo Integration — Design Spec + +## Goal + +Replace the simulated GA4 destination in the demo app with the real `@junctionjs/destination-ga4` package, configured the way a customer would, to validate end-to-end functionality. + +## Changes + +### 1. `apps/demo/lib/junction-config.ts` + +Import the real `ga4` destination from `@junctionjs/destination-ga4` and add it to the destinations array with real config. Remove the `simulatedGA4` import and destination entry. + +```ts +import { ga4 } from "@junctionjs/destination-ga4"; + +// In destinations array: +{ + destination: ga4, + config: { + measurementId: process.env.NEXT_PUBLIC_GA4_MEASUREMENT_ID!, + sendPageView: false, + consentMode: true, + }, + consent: ["analytics"], + enabled: !!process.env.NEXT_PUBLIC_GA4_MEASUREMENT_ID, +} +``` + +Key decisions: +- `sendPageView: false` — Junction's `PageTracker` handles page views +- `consentMode: true` — enables Google Consent Mode v2 integration +- `consent: ["analytics"]` — overrides the destination's default `["analytics", "marketing"]` to match what the demo expects +- `enabled` gated on env var — demo still works without it (falls back to demo sink only) + +### 2. `apps/demo/lib/demo-sink.ts` + +Remove `simulatedGA4` export. The demo sink's `send()` method already imports `ga4` for transform visualization — that stays unchanged. + +### 3. `apps/demo/.env.local` (gitignored) + +``` +NEXT_PUBLIC_GA4_MEASUREMENT_ID=G-XXXXXXXXXX +``` + +### 4. What stays the same + +- Demo sink (event viewer UI) — still captures all events with vendor transforms +- Simulated Amplitude and Meta destinations +- All existing demo pages, contracts, and consent flow +- The GA4 destination package source code (bugs fixed separately if found) + +## Testing + +Manual verification in browser: +1. gtag.js loads in `` (Network tab) +2. Events fire to GA4 on user actions (Network tab: `collect?` requests) +3. Events appear in GA4 Realtime / DebugView +4. Consent gating works: events queue before grant, fire after +5. Demo sink event viewer still shows GA4 transforms diff --git a/package-lock.json b/package-lock.json index b0a1bc4..3183e0a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -59,14 +59,450 @@ "typescript": "^5.5.0" } }, - "node_modules/@acemir/cssom": { - "version": "0.9.31", - "resolved": "https://registry.npmjs.org/@acemir/cssom/-/cssom-0.9.31.tgz", - "integrity": "sha512-ZnR3GSaH+/vJ0YlHau21FjfLYjMpYVIzTD8M8vIEQvIGxeOXyXdzCI140rrCY862p/C/BbzWsjc1dgnM9mkoTA==", - "dev": true, - "license": "MIT", + "apps/docs": { + "name": "@junctionjs/docs", + "version": "0.0.1", + "dependencies": { + "@astrojs/starlight": "^0.34.0", + "astro": "^5.0.0", + "sharp": "^0.33.0" + } + }, + "apps/docs/node_modules/@img/sharp-darwin-arm64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.33.5.tgz", + "integrity": "sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-arm64": "1.0.4" + } + }, + "apps/docs/node_modules/@img/sharp-darwin-x64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.33.5.tgz", + "integrity": "sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-x64": "1.0.4" + } + }, + "apps/docs/node_modules/@img/sharp-libvips-darwin-arm64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.0.4.tgz", + "integrity": "sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg==", + "cpu": [ + "arm64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "apps/docs/node_modules/@img/sharp-libvips-darwin-x64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.0.4.tgz", + "integrity": "sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ==", + "cpu": [ + "x64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "apps/docs/node_modules/@img/sharp-libvips-linux-arm": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.0.5.tgz", + "integrity": "sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g==", + "cpu": [ + "arm" + ], + "libc": [ + "glibc" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "apps/docs/node_modules/@img/sharp-libvips-linux-arm64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.0.4.tgz", + "integrity": "sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA==", + "cpu": [ + "arm64" + ], + "libc": [ + "glibc" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "apps/docs/node_modules/@img/sharp-libvips-linux-s390x": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.0.4.tgz", + "integrity": "sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA==", + "cpu": [ + "s390x" + ], + "libc": [ + "glibc" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "apps/docs/node_modules/@img/sharp-libvips-linux-x64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.0.4.tgz", + "integrity": "sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw==", + "cpu": [ + "x64" + ], + "libc": [ + "glibc" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "apps/docs/node_modules/@img/sharp-libvips-linuxmusl-arm64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.0.4.tgz", + "integrity": "sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA==", + "cpu": [ + "arm64" + ], + "libc": [ + "musl" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "apps/docs/node_modules/@img/sharp-libvips-linuxmusl-x64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.0.4.tgz", + "integrity": "sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw==", + "cpu": [ + "x64" + ], + "libc": [ + "musl" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "apps/docs/node_modules/@img/sharp-linux-arm": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.33.5.tgz", + "integrity": "sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ==", + "cpu": [ + "arm" + ], + "libc": [ + "glibc" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm": "1.0.5" + } + }, + "apps/docs/node_modules/@img/sharp-linux-arm64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.33.5.tgz", + "integrity": "sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA==", + "cpu": [ + "arm64" + ], + "libc": [ + "glibc" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm64": "1.0.4" + } + }, + "apps/docs/node_modules/@img/sharp-linux-s390x": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.33.5.tgz", + "integrity": "sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q==", + "cpu": [ + "s390x" + ], + "libc": [ + "glibc" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-s390x": "1.0.4" + } + }, + "apps/docs/node_modules/@img/sharp-linux-x64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.33.5.tgz", + "integrity": "sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA==", + "cpu": [ + "x64" + ], + "libc": [ + "glibc" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-x64": "1.0.4" + } + }, + "apps/docs/node_modules/@img/sharp-linuxmusl-arm64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.33.5.tgz", + "integrity": "sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g==", + "cpu": [ + "arm64" + ], + "libc": [ + "musl" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-arm64": "1.0.4" + } + }, + "apps/docs/node_modules/@img/sharp-linuxmusl-x64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.33.5.tgz", + "integrity": "sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw==", + "cpu": [ + "x64" + ], + "libc": [ + "musl" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-x64": "1.0.4" + } + }, + "apps/docs/node_modules/@img/sharp-wasm32": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.33.5.tgz", + "integrity": "sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg==", + "cpu": [ + "wasm32" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", + "optional": true, + "dependencies": { + "@emnapi/runtime": "^1.2.0" + }, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "apps/docs/node_modules/@img/sharp-win32-ia32": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.33.5.tgz", + "integrity": "sha512-T36PblLaTwuVJ/zw/LaH0PdZkRz5rd3SmMHX8GSmR7vtNSP5Z6bQkExdSK7xGWyxLw4sUknBuugTelgw2faBbQ==", + "cpu": [ + "ia32" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "apps/docs/node_modules/@img/sharp-win32-x64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.33.5.tgz", + "integrity": "sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", "optional": true, - "peer": true + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "apps/docs/node_modules/sharp": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.33.5.tgz", + "integrity": "sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw==", + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "color": "^4.2.3", + "detect-libc": "^2.0.3", + "semver": "^7.6.3" + }, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-darwin-arm64": "0.33.5", + "@img/sharp-darwin-x64": "0.33.5", + "@img/sharp-libvips-darwin-arm64": "1.0.4", + "@img/sharp-libvips-darwin-x64": "1.0.4", + "@img/sharp-libvips-linux-arm": "1.0.5", + "@img/sharp-libvips-linux-arm64": "1.0.4", + "@img/sharp-libvips-linux-s390x": "1.0.4", + "@img/sharp-libvips-linux-x64": "1.0.4", + "@img/sharp-libvips-linuxmusl-arm64": "1.0.4", + "@img/sharp-libvips-linuxmusl-x64": "1.0.4", + "@img/sharp-linux-arm": "0.33.5", + "@img/sharp-linux-arm64": "0.33.5", + "@img/sharp-linux-s390x": "0.33.5", + "@img/sharp-linux-x64": "0.33.5", + "@img/sharp-linuxmusl-arm64": "0.33.5", + "@img/sharp-linuxmusl-x64": "0.33.5", + "@img/sharp-wasm32": "0.33.5", + "@img/sharp-win32-ia32": "0.33.5", + "@img/sharp-win32-x64": "0.33.5" + } }, "node_modules/@alloc/quick-lru": { "version": "5.2.0", @@ -81,66 +517,22 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@asamuzakjp/css-color": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-4.1.2.tgz", - "integrity": "sha512-NfBUvBaYgKIuq6E/RBLY1m0IohzNHAYyaJGuTK79Z23uNwmz2jl1mPsC5ZxCCxylinKhT1Amn5oNTlx1wN8cQg==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "@csstools/css-calc": "^3.0.0", - "@csstools/css-color-parser": "^4.0.1", - "@csstools/css-parser-algorithms": "^4.0.0", - "@csstools/css-tokenizer": "^4.0.0", - "lru-cache": "^11.2.5" - } - }, - "node_modules/@asamuzakjp/dom-selector": { - "version": "6.8.1", - "resolved": "https://registry.npmjs.org/@asamuzakjp/dom-selector/-/dom-selector-6.8.1.tgz", - "integrity": "sha512-MvRz1nCqW0fsy8Qz4dnLIvhOlMzqDVBabZx6lH+YywFDdjXhMY37SmpV1XFX3JzG5GWHn63j6HX6QPr3lZXHvQ==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "@asamuzakjp/nwsapi": "^2.3.9", - "bidi-js": "^1.0.3", - "css-tree": "^3.1.0", - "is-potential-custom-element-name": "^1.0.1", - "lru-cache": "^11.2.6" - } - }, - "node_modules/@asamuzakjp/nwsapi": { - "version": "2.3.9", - "resolved": "https://registry.npmjs.org/@asamuzakjp/nwsapi/-/nwsapi-2.3.9.tgz", - "integrity": "sha512-n8GuYSrI9bF7FFZ/SjhwevlHc8xaVlb/7HmHelnc/PZXBD2ZR49NnN9sMMuDdEGPeeRQ5d0hqlSlEpgCX3Wl0Q==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true - }, "node_modules/@astrojs/compiler": { "version": "2.13.1", "resolved": "https://registry.npmjs.org/@astrojs/compiler/-/compiler-2.13.1.tgz", "integrity": "sha512-f3FN83d2G/v32ipNClRKgYv30onQlMZX1vCeZMjPsMMPl1mDpmbl0+N5BYo4S/ofzqJyS5hvwacEo0CCVDn/Qg==", - "dev": true, "license": "MIT" }, "node_modules/@astrojs/internal-helpers": { "version": "0.7.5", "resolved": "https://registry.npmjs.org/@astrojs/internal-helpers/-/internal-helpers-0.7.5.tgz", "integrity": "sha512-vreGnYSSKhAjFJCWAwe/CNhONvoc5lokxtRoZims+0wa3KbHBdPHSSthJsKxPd8d/aic6lWKpRTYGY/hsgK6EA==", - "dev": true, "license": "MIT" }, "node_modules/@astrojs/markdown-remark": { "version": "6.3.10", "resolved": "https://registry.npmjs.org/@astrojs/markdown-remark/-/markdown-remark-6.3.10.tgz", "integrity": "sha512-kk4HeYR6AcnzC4QV8iSlOfh+N8TZ3MEStxPyenyCtemqn8IpEATBFMTJcfrNW32dgpt6MY3oCkMM/Tv3/I4G3A==", - "dev": true, "license": "MIT", "dependencies": { "@astrojs/internal-helpers": "0.7.5", @@ -166,11 +558,72 @@ "vfile": "^6.0.3" } }, + "node_modules/@astrojs/mdx": { + "version": "4.3.14", + "resolved": "https://registry.npmjs.org/@astrojs/mdx/-/mdx-4.3.14.tgz", + "integrity": "sha512-FBrqJQORVm+rkRa2TS5CjU9PBA6hkhrwLVBSS9A77gN2+iehvjq1w6yya/d0YKC7osiVorKkr3Qd9wNbl0ZkGA==", + "license": "MIT", + "dependencies": { + "@astrojs/markdown-remark": "6.3.11", + "@mdx-js/mdx": "^3.1.1", + "acorn": "^8.15.0", + "es-module-lexer": "^1.7.0", + "estree-util-visit": "^2.0.0", + "hast-util-to-html": "^9.0.5", + "piccolore": "^0.1.3", + "rehype-raw": "^7.0.0", + "remark-gfm": "^4.0.1", + "remark-smartypants": "^3.0.2", + "source-map": "^0.7.6", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.3" + }, + "engines": { + "node": "18.20.8 || ^20.3.0 || >=22.0.0" + }, + "peerDependencies": { + "astro": "^5.0.0" + } + }, + "node_modules/@astrojs/mdx/node_modules/@astrojs/internal-helpers": { + "version": "0.7.6", + "resolved": "https://registry.npmjs.org/@astrojs/internal-helpers/-/internal-helpers-0.7.6.tgz", + "integrity": "sha512-GOle7smBWKfMSP8osUIGOlB5kaHdQLV3foCsf+5Q9Wsuu+C6Fs3Ez/ttXmhjZ1HkSgsogcM1RXSjjOVieHq16Q==", + "license": "MIT" + }, + "node_modules/@astrojs/mdx/node_modules/@astrojs/markdown-remark": { + "version": "6.3.11", + "resolved": "https://registry.npmjs.org/@astrojs/markdown-remark/-/markdown-remark-6.3.11.tgz", + "integrity": "sha512-hcaxX/5aC6lQgHeGh1i+aauvSwIT6cfyFjKWvExYSxUhZZBBdvCliOtu06gbQyhbe0pGJNoNmqNlQZ5zYUuIyQ==", + "license": "MIT", + "dependencies": { + "@astrojs/internal-helpers": "0.7.6", + "@astrojs/prism": "3.3.0", + "github-slugger": "^2.0.0", + "hast-util-from-html": "^2.0.3", + "hast-util-to-text": "^4.0.2", + "import-meta-resolve": "^4.2.0", + "js-yaml": "^4.1.1", + "mdast-util-definitions": "^6.0.0", + "rehype-raw": "^7.0.0", + "rehype-stringify": "^10.0.1", + "remark-gfm": "^4.0.1", + "remark-parse": "^11.0.0", + "remark-rehype": "^11.1.2", + "remark-smartypants": "^3.0.2", + "shiki": "^3.21.0", + "smol-toml": "^1.6.0", + "unified": "^11.0.5", + "unist-util-remove-position": "^5.0.0", + "unist-util-visit": "^5.0.0", + "unist-util-visit-parents": "^6.0.2", + "vfile": "^6.0.3" + } + }, "node_modules/@astrojs/prism": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/@astrojs/prism/-/prism-3.3.0.tgz", "integrity": "sha512-q8VwfU/fDZNoDOf+r7jUnMC2//H2l0TuQ6FkGJL8vD8nw/q5KiL3DS1KKBI3QhI9UQhpJ5dc7AtqfbXWuOgLCQ==", - "dev": true, "license": "MIT", "dependencies": { "prismjs": "^1.30.0" @@ -179,11 +632,68 @@ "node": "18.20.8 || ^20.3.0 || >=22.0.0" } }, + "node_modules/@astrojs/sitemap": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/@astrojs/sitemap/-/sitemap-3.7.2.tgz", + "integrity": "sha512-PqkzkcZTb5ICiyIR8VoKbIAP/laNRXi5tw616N1Ckk+40oNB8Can1AzVV56lrbC5GKSZFCyJYUVYqVivMisvpA==", + "license": "MIT", + "dependencies": { + "sitemap": "^9.0.0", + "stream-replace-string": "^2.0.0", + "zod": "^4.3.6" + } + }, + "node_modules/@astrojs/sitemap/node_modules/zod": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.3.6.tgz", + "integrity": "sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/@astrojs/starlight": { + "version": "0.34.8", + "resolved": "https://registry.npmjs.org/@astrojs/starlight/-/starlight-0.34.8.tgz", + "integrity": "sha512-XuYz0TfCZhje2u1Q9FNtmTdm7/B9QP91RDI1VkPgYvDhSYlME3k8gwgcBMHnR9ASDo2p9gskrqe7t1Pub/qryg==", + "license": "MIT", + "dependencies": { + "@astrojs/markdown-remark": "^6.3.1", + "@astrojs/mdx": "^4.2.3", + "@astrojs/sitemap": "^3.3.0", + "@pagefind/default-ui": "^1.3.0", + "@types/hast": "^3.0.4", + "@types/js-yaml": "^4.0.9", + "@types/mdast": "^4.0.4", + "astro-expressive-code": "^0.41.1", + "bcp-47": "^2.1.0", + "hast-util-from-html": "^2.0.1", + "hast-util-select": "^6.0.2", + "hast-util-to-string": "^3.0.0", + "hastscript": "^9.0.0", + "i18next": "^23.11.5", + "js-yaml": "^4.1.0", + "klona": "^2.0.6", + "mdast-util-directive": "^3.0.0", + "mdast-util-to-markdown": "^2.1.0", + "mdast-util-to-string": "^4.0.0", + "pagefind": "^1.3.0", + "rehype": "^13.0.1", + "rehype-format": "^5.0.0", + "remark-directive": "^3.0.0", + "ultrahtml": "^1.6.0", + "unified": "^11.0.5", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.2" + }, + "peerDependencies": { + "astro": "^5.5.0" + } + }, "node_modules/@astrojs/telemetry": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/@astrojs/telemetry/-/telemetry-3.3.0.tgz", "integrity": "sha512-UFBgfeldP06qu6khs/yY+q1cDAaArM2/7AEIqQ9Cuvf7B1hNLq0xDrZkct+QoIGyjq56y8IaE2I3CTvG99mlhQ==", - "dev": true, "license": "MIT", "dependencies": { "ci-info": "^4.2.0", @@ -202,7 +712,6 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", - "dev": true, "license": "MIT", "engines": { "node": ">=6.9.0" @@ -212,7 +721,6 @@ "version": "7.28.5", "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", - "dev": true, "license": "MIT", "engines": { "node": ">=6.9.0" @@ -222,7 +730,6 @@ "version": "7.29.0", "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.0.tgz", "integrity": "sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww==", - "dev": true, "license": "MIT", "dependencies": { "@babel/types": "^7.29.0" @@ -238,7 +745,6 @@ "version": "7.28.6", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.6.tgz", "integrity": "sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==", - "dev": true, "license": "MIT", "engines": { "node": ">=6.9.0" @@ -248,7 +754,6 @@ "version": "7.29.0", "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz", "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", - "dev": true, "license": "MIT", "dependencies": { "@babel/helper-string-parser": "^7.27.1", @@ -422,26 +927,10 @@ "node": ">=14.21.3" } }, - "node_modules/@bramus/specificity": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/@bramus/specificity/-/specificity-2.4.2.tgz", - "integrity": "sha512-ctxtJ/eA+t+6q2++vj5j7FYX3nRu311q1wfYH3xjlLOsczhlhxAg2FWNUXhpGvAw3BWo1xBcvOV6/YLc2r5FJw==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "css-tree": "^3.0.0" - }, - "bin": { - "specificity": "bin/cli.js" - } - }, "node_modules/@capsizecss/unpack": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/@capsizecss/unpack/-/unpack-4.0.0.tgz", "integrity": "sha512-VERIM64vtTP1C4mxQ5thVT9fK0apjPFobqybMtA1UdUujWka24ERHbRHFGmpbbhp73MhV+KSsHQH9C6uOTdEQA==", - "dev": true, "license": "MIT", "dependencies": { "fontkitten": "^1.0.0" @@ -725,148 +1214,13 @@ "prettier": "^2.7.1" } }, - "node_modules/@csstools/color-helpers": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-6.0.1.tgz", - "integrity": "sha512-NmXRccUJMk2AWA5A7e5a//3bCIMyOu2hAtdRYrhPPHjDxINuCwX1w6rnIZ4xjLcp0ayv6h8Pc3X0eJUGiAAXHQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], - "license": "MIT-0", - "optional": true, - "peer": true, - "engines": { - "node": ">=20.19.0" - } - }, - "node_modules/@csstools/css-calc": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@csstools/css-calc/-/css-calc-3.1.1.tgz", - "integrity": "sha512-HJ26Z/vmsZQqs/o3a6bgKslXGFAungXGbinULZO3eMsOyNJHeBBZfup5FiZInOghgoM4Hwnmw+OgbJCNg1wwUQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], - "license": "MIT", - "optional": true, - "peer": true, - "engines": { - "node": ">=20.19.0" - }, - "peerDependencies": { - "@csstools/css-parser-algorithms": "^4.0.0", - "@csstools/css-tokenizer": "^4.0.0" - } - }, - "node_modules/@csstools/css-color-parser": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@csstools/css-color-parser/-/css-color-parser-4.0.1.tgz", - "integrity": "sha512-vYwO15eRBEkeF6xjAno/KQ61HacNhfQuuU/eGwH67DplL0zD5ZixUa563phQvUelA07yDczIXdtmYojCphKJcw==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "@csstools/color-helpers": "^6.0.1", - "@csstools/css-calc": "^3.0.0" - }, - "engines": { - "node": ">=20.19.0" - }, - "peerDependencies": { - "@csstools/css-parser-algorithms": "^4.0.0", - "@csstools/css-tokenizer": "^4.0.0" - } - }, - "node_modules/@csstools/css-parser-algorithms": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-4.0.0.tgz", - "integrity": "sha512-+B87qS7fIG3L5h3qwJ/IFbjoVoOe/bpOdh9hAjXbvx0o8ImEmUsGXN0inFOnk2ChCFgqkkGFQ+TpM5rbhkKe4w==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], - "license": "MIT", - "optional": true, - "peer": true, - "engines": { - "node": ">=20.19.0" - }, - "peerDependencies": { - "@csstools/css-tokenizer": "^4.0.0" - } - }, - "node_modules/@csstools/css-syntax-patches-for-csstree": { - "version": "1.0.27", - "resolved": "https://registry.npmjs.org/@csstools/css-syntax-patches-for-csstree/-/css-syntax-patches-for-csstree-1.0.27.tgz", - "integrity": "sha512-sxP33Jwg1bviSUXAV43cVYdmjt2TLnLXNqCWl9xmxHawWVjGz/kEbdkr7F9pxJNBN2Mh+dq0crgItbW6tQvyow==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], - "license": "MIT-0", - "optional": true, - "peer": true - }, - "node_modules/@csstools/css-tokenizer": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-4.0.0.tgz", - "integrity": "sha512-QxULHAm7cNu72w97JUNCBFODFaXpbDg+dP8b/oWFAZ2MTRppA3U00Y2L1HqaS4J6yBqxwa/Y3nMBaxVKbB/NsA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], + "node_modules/@ctrl/tinycolor": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@ctrl/tinycolor/-/tinycolor-4.2.0.tgz", + "integrity": "sha512-kzyuwOAQnXJNLS9PSyrk0CWk35nWJW/zl/6KvnTBMFK65gm7U1/Z5BqjxeapjZCIhQcM/DsrEmcbRwDyXyXK4A==", "license": "MIT", - "optional": true, - "peer": true, "engines": { - "node": ">=20.19.0" + "node": ">=14" } }, "node_modules/@emnapi/runtime": { @@ -886,7 +1240,6 @@ "cpu": [ "ppc64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -903,7 +1256,6 @@ "cpu": [ "arm" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -920,7 +1272,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -937,7 +1288,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -954,7 +1304,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -971,7 +1320,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -988,7 +1336,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1005,7 +1352,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1022,7 +1368,6 @@ "cpu": [ "arm" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1039,7 +1384,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1056,7 +1400,6 @@ "cpu": [ "ia32" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1073,7 +1416,6 @@ "cpu": [ "loong64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1090,7 +1432,6 @@ "cpu": [ "mips64el" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1107,7 +1448,6 @@ "cpu": [ "ppc64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1124,7 +1464,6 @@ "cpu": [ "riscv64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1141,7 +1480,6 @@ "cpu": [ "s390x" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1158,7 +1496,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1175,7 +1512,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1192,7 +1528,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1209,7 +1544,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1226,7 +1560,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1243,7 +1576,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1260,7 +1592,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1277,7 +1608,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1294,7 +1624,6 @@ "cpu": [ "ia32" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1311,7 +1640,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1321,24 +1649,49 @@ "node": ">=12" } }, - "node_modules/@exodus/bytes": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@exodus/bytes/-/bytes-1.14.1.tgz", - "integrity": "sha512-OhkBFWI6GcRMUroChZiopRiSp2iAMvEBK47NhJooDqz1RERO4QuZIZnjP63TXX8GAiLABkYmX+fuQsdJ1dd2QQ==", - "dev": true, + "node_modules/@expressive-code/core": { + "version": "0.41.7", + "resolved": "https://registry.npmjs.org/@expressive-code/core/-/core-0.41.7.tgz", + "integrity": "sha512-ck92uZYZ9Wba2zxkiZLsZGi9N54pMSAVdrI9uW3Oo9AtLglD5RmrdTwbYPCT2S/jC36JGB2i+pnQtBm/Ib2+dg==", + "license": "MIT", + "dependencies": { + "@ctrl/tinycolor": "^4.0.4", + "hast-util-select": "^6.0.2", + "hast-util-to-html": "^9.0.1", + "hast-util-to-text": "^4.0.1", + "hastscript": "^9.0.0", + "postcss": "^8.4.38", + "postcss-nested": "^6.0.1", + "unist-util-visit": "^5.0.0", + "unist-util-visit-parents": "^6.0.1" + } + }, + "node_modules/@expressive-code/plugin-frames": { + "version": "0.41.7", + "resolved": "https://registry.npmjs.org/@expressive-code/plugin-frames/-/plugin-frames-0.41.7.tgz", + "integrity": "sha512-diKtxjQw/979cTglRFaMCY/sR6hWF0kSMg8jsKLXaZBSfGS0I/Hoe7Qds3vVEgeoW+GHHQzMcwvgx/MOIXhrTA==", + "license": "MIT", + "dependencies": { + "@expressive-code/core": "^0.41.7" + } + }, + "node_modules/@expressive-code/plugin-shiki": { + "version": "0.41.7", + "resolved": "https://registry.npmjs.org/@expressive-code/plugin-shiki/-/plugin-shiki-0.41.7.tgz", + "integrity": "sha512-DL605bLrUOgqTdZ0Ot5MlTaWzppRkzzqzeGEu7ODnHF39IkEBbFdsC7pbl3LbUQ1DFtnfx6rD54k/cdofbW6KQ==", + "license": "MIT", + "dependencies": { + "@expressive-code/core": "^0.41.7", + "shiki": "^3.2.2" + } + }, + "node_modules/@expressive-code/plugin-text-markers": { + "version": "0.41.7", + "resolved": "https://registry.npmjs.org/@expressive-code/plugin-text-markers/-/plugin-text-markers-0.41.7.tgz", + "integrity": "sha512-Ewpwuc5t6eFdZmWlFyeuy3e1PTQC0jFvw2Q+2bpcWXbOZhPLsT7+h8lsSIJxb5mS7wZko7cKyQ2RLYDyK6Fpmw==", "license": "MIT", - "optional": true, - "peer": true, - "engines": { - "node": "^20.19.0 || ^22.12.0 || >=24.0.0" - }, - "peerDependencies": { - "@noble/hashes": "^1.8.0 || ^2.0.0" - }, - "peerDependenciesMeta": { - "@noble/hashes": { - "optional": true - } + "dependencies": { + "@expressive-code/core": "^0.41.7" } }, "node_modules/@img/colour": { @@ -1865,7 +2218,6 @@ "version": "1.5.5", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", - "dev": true, "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { @@ -1927,6 +2279,10 @@ "resolved": "packages/destination-plausible", "link": true }, + "node_modules/@junctionjs/docs": { + "resolved": "apps/docs", + "link": true + }, "node_modules/@junctionjs/gateway": { "resolved": "packages/gateway", "link": true @@ -2007,6 +2363,43 @@ "node": ">=6 <7 || >=8" } }, + "node_modules/@mdx-js/mdx": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@mdx-js/mdx/-/mdx-3.1.1.tgz", + "integrity": "sha512-f6ZO2ifpwAQIpzGWaBQT2TXxPv6z3RBzQKpVftEWN78Vl/YweF1uwussDx8ECAXVtr3Rs89fKyG9YlzUs9DyGQ==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdx": "^2.0.0", + "acorn": "^8.0.0", + "collapse-white-space": "^2.0.0", + "devlop": "^1.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "estree-util-scope": "^1.0.0", + "estree-walker": "^3.0.0", + "hast-util-to-jsx-runtime": "^2.0.0", + "markdown-extensions": "^2.0.0", + "recma-build-jsx": "^1.0.0", + "recma-jsx": "^1.0.0", + "recma-stringify": "^1.0.0", + "rehype-recma": "^1.0.0", + "remark-mdx": "^3.0.0", + "remark-parse": "^11.0.0", + "remark-rehype": "^11.0.0", + "source-map": "^0.7.0", + "unified": "^11.0.0", + "unist-util-position-from-estree": "^2.0.0", + "unist-util-stringify-position": "^4.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/@next/env": { "version": "15.5.12", "resolved": "https://registry.npmjs.org/@next/env/-/env-15.5.12.tgz", @@ -2183,9 +2576,92 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/@oslojs/encoding/-/encoding-1.1.0.tgz", "integrity": "sha512-70wQhgYmndg4GCPxPPxPGevRKqTIJ2Nh4OkiMWmDAVYsTQ+Ta7Sq+rPevXyXGdzr30/qZBnyOalCszoMxlyldQ==", - "dev": true, "license": "MIT" }, + "node_modules/@pagefind/darwin-arm64": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@pagefind/darwin-arm64/-/darwin-arm64-1.4.0.tgz", + "integrity": "sha512-2vMqkbv3lbx1Awea90gTaBsvpzgRs7MuSgKDxW0m9oV1GPZCZbZBJg/qL83GIUEN2BFlY46dtUZi54pwH+/pTQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@pagefind/darwin-x64": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@pagefind/darwin-x64/-/darwin-x64-1.4.0.tgz", + "integrity": "sha512-e7JPIS6L9/cJfow+/IAqknsGqEPjJnVXGjpGm25bnq+NPdoD3c/7fAwr1OXkG4Ocjx6ZGSCijXEV4ryMcH2E3A==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@pagefind/default-ui": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@pagefind/default-ui/-/default-ui-1.4.0.tgz", + "integrity": "sha512-wie82VWn3cnGEdIjh4YwNESyS1G6vRHwL6cNjy9CFgNnWW/PGRjsLq300xjVH5sfPFK3iK36UxvIBymtQIEiSQ==", + "license": "MIT" + }, + "node_modules/@pagefind/freebsd-x64": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@pagefind/freebsd-x64/-/freebsd-x64-1.4.0.tgz", + "integrity": "sha512-WcJVypXSZ+9HpiqZjFXMUobfFfZZ6NzIYtkhQ9eOhZrQpeY5uQFqNWLCk7w9RkMUwBv1HAMDW3YJQl/8OqsV0Q==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@pagefind/linux-arm64": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@pagefind/linux-arm64/-/linux-arm64-1.4.0.tgz", + "integrity": "sha512-PIt8dkqt4W06KGmQjONw7EZbhDF+uXI7i0XtRLN1vjCUxM9vGPdtJc2mUyVPevjomrGz5M86M8bqTr6cgDp1Uw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@pagefind/linux-x64": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@pagefind/linux-x64/-/linux-x64-1.4.0.tgz", + "integrity": "sha512-z4oddcWwQ0UHrTHR8psLnVlz6USGJ/eOlDPTDYZ4cI8TK8PgwRUPQZp9D2iJPNIPcS6Qx/E4TebjuGJOyK8Mmg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@pagefind/windows-x64": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@pagefind/windows-x64/-/windows-x64-1.4.0.tgz", + "integrity": "sha512-NkT+YAdgS2FPCn8mIA9bQhiBs+xmniMGq1LFPDhcFn0+2yIUEiIG06t7bsZlhdjknEQRTSdT7YitP6fC5qwP0g==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, "node_modules/@playwright/test": { "version": "1.58.2", "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.58.2.tgz", @@ -2206,7 +2682,6 @@ "version": "5.3.0", "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.3.0.tgz", "integrity": "sha512-5EdhGZtnu3V88ces7s53hhfK5KSASnJZv8Lulpc04cWO3REESroJXg73DFsOmgbU2BhwV0E20bu2IDZb3VKW4Q==", - "dev": true, "license": "MIT", "dependencies": { "@types/estree": "^1.0.0", @@ -2229,7 +2704,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", - "dev": true, "license": "MIT" }, "node_modules/@rollup/rollup-android-arm-eabi": { @@ -2239,7 +2713,6 @@ "cpu": [ "arm" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2253,7 +2726,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2267,7 +2739,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2281,7 +2752,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2295,7 +2765,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2309,7 +2778,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2323,7 +2791,6 @@ "cpu": [ "arm" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2337,7 +2804,6 @@ "cpu": [ "arm" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2351,7 +2817,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2365,7 +2830,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2379,7 +2843,6 @@ "cpu": [ "loong64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2393,7 +2856,6 @@ "cpu": [ "loong64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2407,7 +2869,6 @@ "cpu": [ "ppc64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2421,7 +2882,6 @@ "cpu": [ "ppc64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2435,7 +2895,6 @@ "cpu": [ "riscv64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2449,7 +2908,6 @@ "cpu": [ "riscv64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2463,7 +2921,6 @@ "cpu": [ "s390x" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2477,7 +2934,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2491,7 +2947,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2505,7 +2960,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2519,7 +2973,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2533,7 +2986,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2547,7 +2999,6 @@ "cpu": [ "ia32" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2561,7 +3012,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2575,7 +3025,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2586,7 +3035,6 @@ "version": "3.22.0", "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-3.22.0.tgz", "integrity": "sha512-iAlTtSDDbJiRpvgL5ugKEATDtHdUVkqgHDm/gbD2ZS9c88mx7G1zSYjjOxp5Qa0eaW0MAQosFRmJSk354PRoQA==", - "dev": true, "license": "MIT", "dependencies": { "@shikijs/types": "3.22.0", @@ -2599,7 +3047,6 @@ "version": "3.22.0", "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-3.22.0.tgz", "integrity": "sha512-jdKhfgW9CRtj3Tor0L7+yPwdG3CgP7W+ZEqSsojrMzCjD1e0IxIbwUMDDpYlVBlC08TACg4puwFGkZfLS+56Tw==", - "dev": true, "license": "MIT", "dependencies": { "@shikijs/types": "3.22.0", @@ -2611,7 +3058,6 @@ "version": "3.22.0", "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-3.22.0.tgz", "integrity": "sha512-DyXsOG0vGtNtl7ygvabHd7Mt5EY8gCNqR9Y7Lpbbd/PbJvgWrqaKzH1JW6H6qFkuUa8aCxoiYVv8/YfFljiQxA==", - "dev": true, "license": "MIT", "dependencies": { "@shikijs/types": "3.22.0", @@ -2622,7 +3068,6 @@ "version": "3.22.0", "resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-3.22.0.tgz", "integrity": "sha512-x/42TfhWmp6H00T6uwVrdTJGKgNdFbrEdhaDwSR5fd5zhQ1Q46bHq9EO61SCEWJR0HY7z2HNDMaBZp8JRmKiIA==", - "dev": true, "license": "MIT", "dependencies": { "@shikijs/types": "3.22.0" @@ -2632,7 +3077,6 @@ "version": "3.22.0", "resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-3.22.0.tgz", "integrity": "sha512-o+tlOKqsr6FE4+mYJG08tfCFDS+3CG20HbldXeVoyP+cYSUxDhrFf3GPjE60U55iOkkjbpY2uC3It/eeja35/g==", - "dev": true, "license": "MIT", "dependencies": { "@shikijs/types": "3.22.0" @@ -2642,7 +3086,6 @@ "version": "3.22.0", "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-3.22.0.tgz", "integrity": "sha512-491iAekgKDBFE67z70Ok5a8KBMsQ2IJwOWw3us/7ffQkIBCyOQfm/aNwVMBUriP02QshIfgHCBSIYAl3u2eWjg==", - "dev": true, "license": "MIT", "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", @@ -2653,7 +3096,6 @@ "version": "10.0.2", "resolved": "https://registry.npmjs.org/@shikijs/vscode-textmate/-/vscode-textmate-10.0.2.tgz", "integrity": "sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==", - "dev": true, "license": "MIT" }, "node_modules/@swc/helpers": { @@ -2940,7 +3382,6 @@ "version": "4.1.12", "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", - "dev": true, "license": "MIT", "dependencies": { "@types/ms": "*" @@ -2950,41 +3391,57 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", - "dev": true, "license": "MIT" }, + "node_modules/@types/estree-jsx": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree-jsx/-/estree-jsx-1.0.5.tgz", + "integrity": "sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==", + "license": "MIT", + "dependencies": { + "@types/estree": "*" + } + }, "node_modules/@types/hast": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", - "dev": true, "license": "MIT", "dependencies": { "@types/unist": "*" } }, + "node_modules/@types/js-yaml": { + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/@types/js-yaml/-/js-yaml-4.0.9.tgz", + "integrity": "sha512-k4MGaQl5TGo/iipqb2UDG2UwjXziSWkh0uysQelTlJpX1qGlpUZYm8PnO4DxG1qBomtJUdYJ6qR6xdIah10JLg==", + "license": "MIT" + }, "node_modules/@types/mdast": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz", "integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==", - "dev": true, "license": "MIT", "dependencies": { "@types/unist": "*" } }, + "node_modules/@types/mdx": { + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/@types/mdx/-/mdx-2.0.13.tgz", + "integrity": "sha512-+OWZQfAYyio6YkJb3HLxDrvnx6SWWDbC0zVPfBRzUk0/nqoDyf6dNxQi3eArPe8rJ473nobTMQ/8Zk+LxJ+Yuw==", + "license": "MIT" + }, "node_modules/@types/ms": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==", - "dev": true, "license": "MIT" }, "node_modules/@types/nlcst": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/@types/nlcst/-/nlcst-2.0.3.tgz", "integrity": "sha512-vSYNSDe6Ix3q+6Z7ri9lyWqgGhJTmzRjZRqyq15N0Z/1/UnVsno9G/N40NBijoYx2seFDIl0+B2mgAb9mezUCA==", - "dev": true, "license": "MIT", "dependencies": { "@types/unist": "*" @@ -2994,7 +3451,6 @@ "version": "25.2.3", "resolved": "https://registry.npmjs.org/@types/node/-/node-25.2.3.tgz", "integrity": "sha512-m0jEgYlYz+mDJZ2+F4v8D1AyQb+QzsNqRuI7xg1VQX/KlKS0qT9r1Mo16yo5F/MtifXFgaofIFsdFMox2SxIbQ==", - "dev": true, "license": "MIT", "dependencies": { "undici-types": "~7.16.0" @@ -3020,11 +3476,19 @@ "@types/react": "^19.2.0" } }, + "node_modules/@types/sax": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/sax/-/sax-1.2.7.tgz", + "integrity": "sha512-rO73L89PJxeYM3s3pPPjiPgVVcymqU490g0YO5n5By0k2Erzj6tay/4lr1CHAAU4JyOWd1rpQ8bCf6cZfHU96A==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/unist": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", - "dev": true, "license": "MIT" }, "node_modules/@types/whatwg-mimetype": { @@ -3048,7 +3512,6 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", - "dev": true, "license": "ISC" }, "node_modules/@vitest/expect": { @@ -3168,7 +3631,6 @@ "version": "8.15.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", - "dev": true, "license": "MIT", "bin": { "acorn": "bin/acorn" @@ -3177,23 +3639,19 @@ "node": ">=0.4.0" } }, - "node_modules/agent-base": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", - "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", - "dev": true, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", "license": "MIT", - "optional": true, - "peer": true, - "engines": { - "node": ">= 14" + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, "node_modules/ansi-align": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", - "dev": true, "license": "ISC", "dependencies": { "string-width": "^4.1.0" @@ -3203,7 +3661,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -3213,14 +3670,12 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, "license": "MIT" }, "node_modules/ansi-align/node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", @@ -3235,7 +3690,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" @@ -3274,7 +3728,6 @@ "version": "6.2.2", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", - "dev": true, "license": "MIT", "engines": { "node": ">=12" @@ -3287,7 +3740,6 @@ "version": "6.2.3", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", - "dev": true, "license": "MIT", "engines": { "node": ">=12" @@ -3307,7 +3759,6 @@ "version": "3.1.3", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dev": true, "license": "ISC", "dependencies": { "normalize-path": "^3.0.0", @@ -3321,7 +3772,6 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, "license": "MIT", "engines": { "node": ">=8.6" @@ -3330,18 +3780,22 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/arg": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", + "license": "MIT" + }, "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true, "license": "Python-2.0" }, "node_modules/aria-query": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz", "integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==", - "dev": true, "license": "Apache-2.0", "engines": { "node": ">= 0.4" @@ -3351,7 +3805,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/array-iterate/-/array-iterate-2.0.1.tgz", "integrity": "sha512-I1jXZMjAgCMmxT4qxXfPXa6SthSoE8h6gkSI9BGGNv8mP8G/v0blc+qFnZu6K42vTOiuME596QaLO0TP3Lk0xg==", - "dev": true, "license": "MIT", "funding": { "type": "github", @@ -3378,11 +3831,19 @@ "node": ">=12" } }, + "node_modules/astring": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/astring/-/astring-1.9.0.tgz", + "integrity": "sha512-LElXdjswlqjWrPpJFg1Fx4wpkOCxj1TDHlSV4PlaRxHGWko024xICaa97ZkMfs6DRKlCguiAI+rbXv5GWwXIkg==", + "license": "MIT", + "bin": { + "astring": "bin/astring" + } + }, "node_modules/astro": { "version": "5.17.2", "resolved": "https://registry.npmjs.org/astro/-/astro-5.17.2.tgz", "integrity": "sha512-7jnMqGo53hOQNwo1N/wqeOvUp8wwW/p+DeerSjSkHNx8L/1mhy6P7rVo7EhdmF8DpKqw0tl/B5Fx1WcIzg1ysA==", - "dev": true, "license": "MIT", "dependencies": { "@astrojs/compiler": "^2.13.0", @@ -3465,6 +3926,18 @@ "sharp": "^0.34.0" } }, + "node_modules/astro-expressive-code": { + "version": "0.41.7", + "resolved": "https://registry.npmjs.org/astro-expressive-code/-/astro-expressive-code-0.41.7.tgz", + "integrity": "sha512-hUpogGc6DdAd+I7pPXsctyYPRBJDK7Q7d06s4cyP0Vz3OcbziP3FNzN0jZci1BpCvLn9675DvS7B9ctKKX64JQ==", + "license": "MIT", + "dependencies": { + "rehype-expressive-code": "^0.41.7" + }, + "peerDependencies": { + "astro": "^4.0.0-beta || ^5.0.0-beta || ^3.3.0 || ^6.0.0-beta" + } + }, "node_modules/astro/node_modules/@esbuild/aix-ppc64": { "version": "0.27.3", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.3.tgz", @@ -3472,7 +3945,6 @@ "cpu": [ "ppc64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -3489,7 +3961,6 @@ "cpu": [ "arm" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -3506,7 +3977,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -3523,7 +3993,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -3540,7 +4009,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -3557,7 +4025,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -3574,7 +4041,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -3591,7 +4057,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -3608,7 +4073,6 @@ "cpu": [ "arm" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -3625,7 +4089,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -3642,7 +4105,6 @@ "cpu": [ "ia32" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -3659,7 +4121,6 @@ "cpu": [ "loong64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -3676,7 +4137,6 @@ "cpu": [ "mips64el" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -3693,7 +4153,6 @@ "cpu": [ "ppc64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -3710,7 +4169,6 @@ "cpu": [ "riscv64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -3727,7 +4185,6 @@ "cpu": [ "s390x" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -3744,7 +4201,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -3761,7 +4217,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -3778,7 +4233,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -3795,7 +4249,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -3812,7 +4265,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -3829,7 +4281,6 @@ "cpu": [ "ia32" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -3846,7 +4297,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -3860,7 +4310,6 @@ "version": "0.27.3", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.3.tgz", "integrity": "sha512-8VwMnyGCONIs6cWue2IdpHxHnAjzxnw2Zr7MkVxB2vjmQ2ivqGFb4LEG3SMnv0Gb2F/G/2yA8zUaiL1gywDCCg==", - "dev": true, "hasInstallScript": true, "license": "MIT", "bin": { @@ -3902,7 +4351,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.2.tgz", "integrity": "sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg==", - "dev": true, "license": "MIT", "engines": { "node": ">=18" @@ -3912,7 +4360,6 @@ "version": "6.4.1", "resolved": "https://registry.npmjs.org/vite/-/vite-6.4.1.tgz", "integrity": "sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==", - "dev": true, "license": "MIT", "dependencies": { "esbuild": "^0.25.0", @@ -3990,7 +4437,6 @@ "cpu": [ "ppc64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -4007,7 +4453,6 @@ "cpu": [ "arm" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -4024,7 +4469,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -4041,7 +4485,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -4058,7 +4501,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -4075,7 +4517,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -4092,7 +4533,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -4109,7 +4549,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -4126,7 +4565,6 @@ "cpu": [ "arm" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -4143,7 +4581,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -4160,7 +4597,6 @@ "cpu": [ "ia32" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -4177,7 +4613,6 @@ "cpu": [ "loong64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -4194,7 +4629,6 @@ "cpu": [ "mips64el" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -4211,7 +4645,6 @@ "cpu": [ "ppc64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -4228,7 +4661,6 @@ "cpu": [ "riscv64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -4245,7 +4677,6 @@ "cpu": [ "s390x" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -4262,7 +4693,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -4279,7 +4709,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -4296,7 +4725,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -4313,7 +4741,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -4330,7 +4757,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -4347,7 +4773,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -4364,7 +4789,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -4381,7 +4805,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -4398,7 +4821,6 @@ "cpu": [ "ia32" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -4415,7 +4837,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -4429,7 +4850,6 @@ "version": "0.25.12", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz", "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==", - "dev": true, "hasInstallScript": true, "license": "MIT", "bin": { @@ -4471,7 +4891,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz", "integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==", - "dev": true, "license": "Apache-2.0", "engines": { "node": ">= 0.4" @@ -4481,7 +4900,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/bail/-/bail-2.0.2.tgz", "integrity": "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==", - "dev": true, "license": "MIT", "funding": { "type": "github", @@ -4492,9 +4910,33 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/base-64/-/base-64-1.0.0.tgz", "integrity": "sha512-kwDPIFCGx0NZHog36dj+tHiwP4QMzsZ3AgMViUBKI0+V5n4U0ufTCUMhnQ04diaRI8EX/QcPfql7zlhZ7j4zgg==", - "dev": true, "license": "MIT" }, + "node_modules/bcp-47": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/bcp-47/-/bcp-47-2.1.0.tgz", + "integrity": "sha512-9IIS3UPrvIa1Ej+lVDdDwO7zLehjqsaByECw0bu2RRGP73jALm6FYbzI5gWbgHLvNdkvfXB5YrSbocZdOS0c0w==", + "license": "MIT", + "dependencies": { + "is-alphabetical": "^2.0.0", + "is-alphanumerical": "^2.0.0", + "is-decimal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/bcp-47-match": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/bcp-47-match/-/bcp-47-match-2.0.3.tgz", + "integrity": "sha512-JtTezzbAibu8G0R9op9zb3vcWZd9JF6M0xOYGPn0fNCd7wOpRB1mU2mH9T8gaBGbAAyIIVgB2G7xG0GP98zMAQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/better-path-resolve": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/better-path-resolve/-/better-path-resolve-1.0.0.tgz", @@ -4508,30 +4950,16 @@ "node": ">=4" } }, - "node_modules/bidi-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/bidi-js/-/bidi-js-1.0.3.tgz", - "integrity": "sha512-RKshQI1R3YQ+n9YJz2QQ147P66ELpa1FQEg20Dk8oW9t2KgLbpDLLp9aGZ7y8WHSshDknG0bknqGw5/tyCs5tw==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "require-from-string": "^2.0.2" - } - }, "node_modules/boolbase": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", - "dev": true, "license": "ISC" }, "node_modules/boxen": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/boxen/-/boxen-8.0.1.tgz", "integrity": "sha512-F3PH5k5juxom4xktynS7MoFY+NUWH5LC4CnH11YB8NPew+HLpmBLCybSAEyb2F+4pRXhuhWqFesoQd6DAyc2hw==", - "dev": true, "license": "MIT", "dependencies": { "ansi-align": "^3.0.1", @@ -4593,7 +5021,6 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-8.0.0.tgz", "integrity": "sha512-8WB3Jcas3swSvjIeA2yvCJ+Miyz5l1ZmB6HFb9R1317dt9LCQoswg/BGrmAmkWVEszSrrg4RwmO46qIm2OEnSA==", - "dev": true, "license": "MIT", "engines": { "node": ">=16" @@ -4626,7 +5053,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz", "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==", - "dev": true, "license": "MIT", "funding": { "type": "github", @@ -4654,7 +5080,6 @@ "version": "5.6.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", - "dev": true, "license": "MIT", "engines": { "node": "^12.17.0 || ^14.13 || >=16.0.0" @@ -4667,7 +5092,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-2.0.2.tgz", "integrity": "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==", - "dev": true, "license": "MIT", "funding": { "type": "github", @@ -4678,7 +5102,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-2.1.0.tgz", "integrity": "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==", - "dev": true, "license": "MIT", "funding": { "type": "github", @@ -4689,7 +5112,16 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz", "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==", - "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-reference-invalid": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-2.0.1.tgz", + "integrity": "sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==", "license": "MIT", "funding": { "type": "github", @@ -4733,7 +5165,6 @@ "version": "4.4.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.4.0.tgz", "integrity": "sha512-77PSwercCZU2Fc4sX94eF8k8Pxte6JAwL4/ICZLFjJLqegs7kCuAsqqj/70NQF6TvDpgFjkubQB2FW2ZZddvQg==", - "dev": true, "funding": [ { "type": "github", @@ -4761,7 +5192,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-3.0.0.tgz", "integrity": "sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==", - "dev": true, "license": "MIT", "engines": { "node": ">=10" @@ -4835,6 +5265,57 @@ "node": ">=6" } }, + "node_modules/collapse-white-space": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-2.1.0.tgz", + "integrity": "sha512-loKTxY1zCOuG4j9f6EPnuyyYkf58RnhhWTvRoZEokgB+WbdXehfjFviyOVYkqzEWz1Q5kRiZdBYS5SwxbQYwzw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/color": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz", + "integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1", + "color-string": "^1.9.0" + }, + "engines": { + "node": ">=12.5.0" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" + }, + "node_modules/color-string": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", + "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", + "license": "MIT", + "dependencies": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } + }, "node_modules/colorette": { "version": "2.0.20", "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", @@ -4846,7 +5327,6 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", "integrity": "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==", - "dev": true, "license": "MIT", "funding": { "type": "github", @@ -4857,7 +5337,6 @@ "version": "11.1.0", "resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz", "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=16" @@ -4867,7 +5346,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/common-ancestor-path/-/common-ancestor-path-1.0.1.tgz", "integrity": "sha512-L3sHRo1pXXEqX8VU28kfgUY+YGsk09hPqZiZmLacNib6XNTCM8ubYeT7ryXQw8asB1sKgcU5lkB7ONug08aB8w==", - "dev": true, "license": "ISC" }, "node_modules/confbox": { @@ -4891,7 +5369,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.1.1.tgz", "integrity": "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=18" @@ -4905,7 +5382,6 @@ "version": "1.2.2", "resolved": "https://registry.npmjs.org/cookie-es/-/cookie-es-1.2.2.tgz", "integrity": "sha512-+W7VmiVINB+ywl1HGXJXmrqkOhpKrIiVZV6tQuV54ZyQC7MMuBt81Vc336GMLoHBq5hV/F9eXgt5Mnx0Rha5Fg==", - "dev": true, "license": "MIT" }, "node_modules/cross-spawn": { @@ -4927,7 +5403,6 @@ "version": "0.3.5", "resolved": "https://registry.npmjs.org/crossws/-/crossws-0.3.5.tgz", "integrity": "sha512-ojKiDvcmByhwa8YYqbQI/hg7MEU0NC03+pSdEq4ZUnZR9xXpwk7E43SMNGkn+JxJGPFtNvQ48+vV2p+P1ml5PA==", - "dev": true, "license": "MIT", "dependencies": { "uncrypto": "^0.1.3" @@ -4937,7 +5412,6 @@ "version": "5.2.2", "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.2.2.tgz", "integrity": "sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==", - "dev": true, "license": "BSD-2-Clause", "dependencies": { "boolbase": "^1.0.0", @@ -4950,11 +5424,26 @@ "url": "https://github.com/sponsors/fb55" } }, + "node_modules/css-selector-parser": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/css-selector-parser/-/css-selector-parser-3.3.0.tgz", + "integrity": "sha512-Y2asgMGFqJKF4fq4xHDSlFYIkeVfRsm69lQC1q9kbEsH5XtnINTMrweLkjYMeaUgiXBy/uvKeO/a1JHTNnmB2g==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/mdevils" + }, + { + "type": "patreon", + "url": "https://patreon.com/mdevils" + } + ], + "license": "MIT" + }, "node_modules/css-tree": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-3.1.0.tgz", "integrity": "sha512-0eW44TGN5SQXU1mWSkKwFstI/22X2bG1nYzZTYMAWjylYURhse752YgbE4Cx46AC+bAvI+/dYTPRk1LqSUnu6w==", - "dev": true, "license": "MIT", "dependencies": { "mdn-data": "2.12.2", @@ -4968,7 +5457,6 @@ "version": "6.2.2", "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.2.2.tgz", "integrity": "sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==", - "dev": true, "license": "BSD-2-Clause", "engines": { "node": ">= 6" @@ -4981,7 +5469,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", - "dev": true, "license": "MIT", "bin": { "cssesc": "bin/cssesc" @@ -4994,7 +5481,6 @@ "version": "5.0.5", "resolved": "https://registry.npmjs.org/csso/-/csso-5.0.5.tgz", "integrity": "sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==", - "dev": true, "license": "MIT", "dependencies": { "css-tree": "~2.2.0" @@ -5008,7 +5494,6 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.2.1.tgz", "integrity": "sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==", - "dev": true, "license": "MIT", "dependencies": { "mdn-data": "2.0.28", @@ -5023,27 +5508,8 @@ "version": "2.0.28", "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.28.tgz", "integrity": "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==", - "dev": true, "license": "CC0-1.0" }, - "node_modules/cssstyle": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-6.0.1.tgz", - "integrity": "sha512-IoJs7La+oFp/AB033wBStxNOJt4+9hHMxsXUPANcoXL2b3W4DZKghlJ2cI/eyeRZIQ9ysvYEorVhjrcYctWbog==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "@asamuzakjp/css-color": "^4.1.2", - "@csstools/css-syntax-patches-for-csstree": "^1.0.26", - "css-tree": "^3.1.0", - "lru-cache": "^11.2.5" - }, - "engines": { - "node": ">=20" - } - }, "node_modules/csstype": { "version": "3.2.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", @@ -5051,22 +5517,6 @@ "dev": true, "license": "MIT" }, - "node_modules/data-urls": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-7.0.0.tgz", - "integrity": "sha512-23XHcCF+coGYevirZceTVD7NdJOqVn+49IHyxgszm+JIiHLoB2TkmPtsYkNWT1pvRSGkc35L6NHs0yHkN2SumA==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "whatwg-mimetype": "^5.0.0", - "whatwg-url": "^16.0.0" - }, - "engines": { - "node": "^20.19.0 || ^22.12.0 || >=24.0.0" - } - }, "node_modules/dataloader": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/dataloader/-/dataloader-1.4.0.tgz", @@ -5078,7 +5528,6 @@ "version": "4.4.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "dev": true, "license": "MIT", "dependencies": { "ms": "^2.1.3" @@ -5092,20 +5541,10 @@ } } }, - "node_modules/decimal.js": { - "version": "10.6.0", - "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.6.0.tgz", - "integrity": "sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true - }, "node_modules/decode-named-character-reference": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.3.0.tgz", "integrity": "sha512-GtpQYB283KrPp6nRw50q3U9/VfOutZOe103qlN7BPP6Ad27xYnOIWv4lPzo8HCAL+mMZofJ9KEy30fq6MfaK6Q==", - "dev": true, "license": "MIT", "dependencies": { "character-entities": "^2.0.0" @@ -5129,14 +5568,12 @@ "version": "6.1.4", "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.4.tgz", "integrity": "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==", - "dev": true, "license": "MIT" }, "node_modules/dequal": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", - "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -5146,7 +5583,6 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/destr/-/destr-2.0.5.tgz", "integrity": "sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA==", - "dev": true, "license": "MIT" }, "node_modules/detect-indent": { @@ -5163,7 +5599,6 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", - "devOptional": true, "license": "Apache-2.0", "engines": { "node": ">=8" @@ -5173,7 +5608,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/deterministic-object-hash/-/deterministic-object-hash-2.0.2.tgz", "integrity": "sha512-KxektNH63SrbfUyDiwXqRb1rLwKt33AmMv+5Nhsw1kqZ13SJBRTgZHtGbE+hH3a1mVW1cz+4pqSWVPAtLVXTzQ==", - "dev": true, "license": "MIT", "dependencies": { "base-64": "^1.0.0" @@ -5186,14 +5620,12 @@ "version": "5.6.2", "resolved": "https://registry.npmjs.org/devalue/-/devalue-5.6.2.tgz", "integrity": "sha512-nPRkjWzzDQlsejL1WVifk5rvcFi/y1onBRxjaFMjZeR9mFpqu2gmAZ9xUB9/IEanEP/vBtGeGganC/GO1fmufg==", - "dev": true, "license": "MIT" }, "node_modules/devlop": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz", "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==", - "dev": true, "license": "MIT", "dependencies": { "dequal": "^2.0.0" @@ -5207,7 +5639,6 @@ "version": "8.0.3", "resolved": "https://registry.npmjs.org/diff/-/diff-8.0.3.tgz", "integrity": "sha512-qejHi7bcSD4hQAZE0tNAawRK1ZtafHDmMTMkrrIGgSLl7hTnQHmKCeB45xAcbfTqK2zowkM3j3bHt/4b/ARbYQ==", - "dev": true, "license": "BSD-3-Clause", "engines": { "node": ">=0.3.1" @@ -5226,18 +5657,29 @@ "node": ">=8" } }, + "node_modules/direction": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/direction/-/direction-2.0.1.tgz", + "integrity": "sha512-9S6m9Sukh1cZNknO1CWAr2QAWsbKLafQiyM5gZ7VgXHeuaoUwffKN4q6NC4A/Mf9iiPlOXQEKW/Mv/mh9/3YFA==", + "license": "MIT", + "bin": { + "direction": "cli.js" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/dlv": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", - "dev": true, "license": "MIT" }, "node_modules/dom-serializer": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", - "dev": true, "license": "MIT", "dependencies": { "domelementtype": "^2.3.0", @@ -5252,7 +5694,6 @@ "version": "4.5.0", "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", - "dev": true, "license": "BSD-2-Clause", "engines": { "node": ">=0.12" @@ -5265,7 +5706,6 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", - "dev": true, "funding": [ { "type": "github", @@ -5278,7 +5718,6 @@ "version": "5.0.3", "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", - "dev": true, "license": "BSD-2-Clause", "dependencies": { "domelementtype": "^2.3.0" @@ -5294,7 +5733,6 @@ "version": "3.2.2", "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz", "integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==", - "dev": true, "license": "BSD-2-Clause", "dependencies": { "dom-serializer": "^2.0.0", @@ -5319,7 +5757,6 @@ "version": "3.1.4", "resolved": "https://registry.npmjs.org/dset/-/dset-3.1.4.tgz", "integrity": "sha512-2QF/g9/zTaPDc3BjNcVTGoBbXBgYfMTTceLaYcFJ/W9kggFUkhxD/hMEeuLKbugyef9SqAx8cpgwlIP/jinUTA==", - "dev": true, "license": "MIT", "engines": { "node": ">=4" @@ -5329,7 +5766,6 @@ "version": "10.6.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", - "dev": true, "license": "MIT" }, "node_modules/enhanced-resolve": { @@ -5387,7 +5823,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", - "dev": true, "license": "BSD-2-Clause", "engines": { "node": ">=0.12" @@ -5413,14 +5848,45 @@ "version": "1.7.0", "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz", "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==", - "dev": true, "license": "MIT" }, + "node_modules/esast-util-from-estree": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/esast-util-from-estree/-/esast-util-from-estree-2.0.0.tgz", + "integrity": "sha512-4CyanoAudUSBAn5K13H4JhsMH6L9ZP7XbLVe/dKybkxMO7eDyLsT8UHl9TRNrU2Gr9nz+FovfSIjuXWJ81uVwQ==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "devlop": "^1.0.0", + "estree-util-visit": "^2.0.0", + "unist-util-position-from-estree": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/esast-util-from-js": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/esast-util-from-js/-/esast-util-from-js-2.0.1.tgz", + "integrity": "sha512-8Ja+rNJ0Lt56Pcf3TAmpBZjmx8ZcK5Ts4cAzIOjsjevg9oSXJnl6SUQ2EevU8tv3h6ZLWmoKL5H4fgWvdvfETw==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "acorn": "^8.0.0", + "esast-util-from-estree": "^2.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/esbuild": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", - "dev": true, + "devOptional": true, "hasInstallScript": true, "license": "MIT", "bin": { @@ -5459,7 +5925,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", - "dev": true, "license": "MIT", "engines": { "node": ">=12" @@ -5482,11 +5947,92 @@ "node": ">=4" } }, + "node_modules/estree-util-attach-comments": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/estree-util-attach-comments/-/estree-util-attach-comments-3.0.0.tgz", + "integrity": "sha512-cKUwm/HUcTDsYh/9FgnuFqpfquUbwIqwKM26BVCGDPVgvaCl/nDCCjUfiLlx6lsEZ3Z4RFxNbOQ60pkaEwFxGw==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-util-build-jsx": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/estree-util-build-jsx/-/estree-util-build-jsx-3.0.1.tgz", + "integrity": "sha512-8U5eiL6BTrPxp/CHbs2yMgP8ftMhR5ww1eIKoWRMlqvltHF8fZn5LRDvTKuxD3DUn+shRbLGqXemcP51oFCsGQ==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "devlop": "^1.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "estree-walker": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-util-is-identifier-name": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/estree-util-is-identifier-name/-/estree-util-is-identifier-name-3.0.0.tgz", + "integrity": "sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-util-scope": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/estree-util-scope/-/estree-util-scope-1.0.0.tgz", + "integrity": "sha512-2CAASclonf+JFWBNJPndcOpA8EMJwa0Q8LUFJEKqXLW6+qBvbFZuF5gItbQOs/umBUkjviCSDCbBwU2cXbmrhQ==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "devlop": "^1.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-util-to-js": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/estree-util-to-js/-/estree-util-to-js-2.0.0.tgz", + "integrity": "sha512-WDF+xj5rRWmD5tj6bIqRi6CkLIXbbNQUcxQHzGysQzvHmdYG2G7p/Tf0J0gpxGgkeMZNTIjT/AoSvC9Xehcgdg==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "astring": "^1.8.0", + "source-map": "^0.7.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-util-visit": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/estree-util-visit/-/estree-util-visit-2.0.0.tgz", + "integrity": "sha512-m5KgiH85xAhhW8Wta0vShLcUvOsh3LLPI2YVwcbio1l7E09NTLL1EyMZFM1OyWowoH0skScNbhOPl4kcBgzTww==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/estree-walker": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", - "dev": true, "license": "MIT", "dependencies": { "@types/estree": "^1.0.0" @@ -5496,7 +6042,6 @@ "version": "5.0.4", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.4.tgz", "integrity": "sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==", - "dev": true, "license": "MIT" }, "node_modules/expect-type": { @@ -5509,11 +6054,22 @@ "node": ">=12.0.0" } }, + "node_modules/expressive-code": { + "version": "0.41.7", + "resolved": "https://registry.npmjs.org/expressive-code/-/expressive-code-0.41.7.tgz", + "integrity": "sha512-2wZjC8OQ3TaVEMcBtYY4Va3lo6J+Ai9jf3d4dbhURMJcU4Pbqe6EcHe424MIZI0VHUA1bR6xdpoHYi3yxokWqA==", + "license": "MIT", + "dependencies": { + "@expressive-code/core": "^0.41.7", + "@expressive-code/plugin-frames": "^0.41.7", + "@expressive-code/plugin-shiki": "^0.41.7", + "@expressive-code/plugin-text-markers": "^0.41.7" + } + }, "node_modules/extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "dev": true, "license": "MIT" }, "node_modules/extendable-error": { @@ -5554,7 +6110,6 @@ "version": "6.5.0", "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", - "dev": true, "license": "MIT", "engines": { "node": ">=12.0.0" @@ -5611,7 +6166,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/flattie/-/flattie-1.1.1.tgz", "integrity": "sha512-9UbaD6XdAL97+k/n+N7JwX46K/M6Zc6KcFYskrYL8wbBV/Uyk0CTAMY0VT+qiK5PM7AIc9aTWYtq65U7T+aCNQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -5621,7 +6175,6 @@ "version": "0.4.1", "resolved": "https://registry.npmjs.org/fontace/-/fontace-0.4.1.tgz", "integrity": "sha512-lDMvbAzSnHmbYMTEld5qdtvNH2/pWpICOqpean9IgC7vUbUJc3k+k5Dokp85CegamqQpFbXf0rAVkbzpyTA8aw==", - "dev": true, "license": "MIT", "dependencies": { "fontkitten": "^1.0.2" @@ -5631,7 +6184,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/fontkitten/-/fontkitten-1.0.2.tgz", "integrity": "sha512-piJxbLnkD9Xcyi7dWJRnqszEURixe7CrF/efBfbffe2DPyabmuIuqraruY8cXTs19QoM8VJzx47BDRVNXETM7Q==", - "dev": true, "license": "MIT", "dependencies": { "tiny-inflate": "^1.0.3" @@ -5659,7 +6211,6 @@ "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, "hasInstallScript": true, "license": "MIT", "optional": true, @@ -5674,7 +6225,6 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.4.0.tgz", "integrity": "sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q==", - "dev": true, "license": "MIT", "engines": { "node": ">=18" @@ -5687,7 +6237,7 @@ "version": "4.13.6", "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.13.6.tgz", "integrity": "sha512-shZT/QMiSHc/YBLxxOkMtgSid5HFoauqCE3/exfsEcwg1WkeqjG+V40yBbBrsD+jW2HDXcs28xOfcbm2jI8Ddw==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "resolve-pkg-maps": "^1.0.0" @@ -5700,7 +6250,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/github-slugger/-/github-slugger-2.0.0.tgz", "integrity": "sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw==", - "dev": true, "license": "ISC" }, "node_modules/glob-parent": { @@ -5748,7 +6297,6 @@ "version": "1.15.5", "resolved": "https://registry.npmjs.org/h3/-/h3-1.15.5.tgz", "integrity": "sha512-xEyq3rSl+dhGX2Lm0+eFQIAzlDN6Fs0EcC4f7BNUmzaRX/PTzeuM+Tr2lHB8FoXggsQIeXLj8EDVgs5ywxyxmg==", - "dev": true, "license": "MIT", "dependencies": { "cookie-es": "^1.2.2", @@ -5790,24 +6338,56 @@ "node": ">=0.12" }, "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/happy-dom/node_modules/whatwg-mimetype": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz", - "integrity": "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/happy-dom/node_modules/whatwg-mimetype": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz", + "integrity": "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + } + }, + "node_modules/hast-util-embedded": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-embedded/-/hast-util-embedded-3.0.0.tgz", + "integrity": "sha512-naH8sld4Pe2ep03qqULEtvYr7EjrLK2QHY8KJR6RJkTUjPGObe1vnx585uzem2hGra+s1q08DZZpfgDVYRbaXA==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "hast-util-is-element": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-format": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/hast-util-format/-/hast-util-format-1.1.0.tgz", + "integrity": "sha512-yY1UDz6bC9rDvCWHpx12aIBGRG7krurX0p0Fm6pT547LwDIZZiNr8a+IHDogorAdreULSEzP82Nlv5SZkHZcjA==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "hast-util-embedded": "^3.0.0", + "hast-util-minify-whitespace": "^1.0.0", + "hast-util-phrasing": "^3.0.0", + "hast-util-whitespace": "^3.0.0", + "html-whitespace-sensitive-tag-names": "^3.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, "node_modules/hast-util-from-html": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/hast-util-from-html/-/hast-util-from-html-2.0.3.tgz", "integrity": "sha512-CUSRHXyKjzHov8yKsQjGOElXy/3EKpyX56ELnkHH34vDVw1N1XSQ1ZcAvTyAPtGqLTuKP/uxM+aLkSPqF/EtMw==", - "dev": true, "license": "MIT", "dependencies": { "@types/hast": "^3.0.0", @@ -5826,7 +6406,6 @@ "version": "8.0.3", "resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-8.0.3.tgz", "integrity": "sha512-3kxEVkEKt0zvcZ3hCRYI8rqrgwtlIOFMWkbclACvjlDw8Li9S2hk/d51OI0nr/gIpdMHNepwgOKqZ/sy0Clpyg==", - "dev": true, "license": "MIT", "dependencies": { "@types/hast": "^3.0.0", @@ -5843,11 +6422,36 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/hast-util-has-property": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-has-property/-/hast-util-has-property-3.0.0.tgz", + "integrity": "sha512-MNilsvEKLFpV604hwfhVStK0usFY/QmM5zX16bo7EjnAEGofr5YyI37kzopBlZJkHD4t887i+q/C8/tr5Q94cA==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-is-body-ok-link": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/hast-util-is-body-ok-link/-/hast-util-is-body-ok-link-3.0.1.tgz", + "integrity": "sha512-0qpnzOBLztXHbHQenVB8uNuxTnm/QBFUOmdOSsEn7GnBtyY07+ENTWVFBAnXd/zEgd9/SUG3lRY7hSIBWRgGpQ==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/hast-util-is-element": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/hast-util-is-element/-/hast-util-is-element-3.0.0.tgz", "integrity": "sha512-Val9mnv2IWpLbNPqc/pUem+a7Ipj2aHacCwgNfTiK0vJKl0LF+4Ba4+v1oPHFpf3bLYmreq0/l3Gud9S5OH42g==", - "dev": true, "license": "MIT", "dependencies": { "@types/hast": "^3.0.0" @@ -5857,11 +6461,27 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/hast-util-minify-whitespace": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hast-util-minify-whitespace/-/hast-util-minify-whitespace-1.0.1.tgz", + "integrity": "sha512-L96fPOVpnclQE0xzdWb/D12VT5FabA7SnZOUMtL1DbXmYiHJMXZvFkIZfiMmTCNJHUeO2K9UYNXoVyfz+QHuOw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "hast-util-embedded": "^3.0.0", + "hast-util-is-element": "^3.0.0", + "hast-util-whitespace": "^3.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/hast-util-parse-selector": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-4.0.0.tgz", "integrity": "sha512-wkQCkSYoOGCRKERFWcxMVMOcYE2K1AaNLU8DXS9arxnLOUEWbOXKXiJUNzEpqZ3JOKpnha3jkFrumEjVliDe7A==", - "dev": true, "license": "MIT", "dependencies": { "@types/hast": "^3.0.0" @@ -5871,11 +6491,27 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/hast-util-phrasing": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/hast-util-phrasing/-/hast-util-phrasing-3.0.1.tgz", + "integrity": "sha512-6h60VfI3uBQUxHqTyMymMZnEbNl1XmEGtOxxKYL7stY2o601COo62AWAYBQR9lZbYXYSBoxag8UpPRXK+9fqSQ==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "hast-util-embedded": "^3.0.0", + "hast-util-has-property": "^3.0.0", + "hast-util-is-body-ok-link": "^3.0.0", + "hast-util-is-element": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/hast-util-raw": { "version": "9.1.0", "resolved": "https://registry.npmjs.org/hast-util-raw/-/hast-util-raw-9.1.0.tgz", "integrity": "sha512-Y8/SBAHkZGoNkpzqqfCldijcuUKh7/su31kEBp67cFY09Wy0mTRgtsLYsiIxMJxlu0f6AA5SUTbDR8K0rxnbUw==", - "dev": true, "license": "MIT", "dependencies": { "@types/hast": "^3.0.0", @@ -5897,11 +6533,65 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/hast-util-select": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/hast-util-select/-/hast-util-select-6.0.4.tgz", + "integrity": "sha512-RqGS1ZgI0MwxLaKLDxjprynNzINEkRHY2i8ln4DDjgv9ZhcYVIHN9rlpiYsqtFwrgpYU361SyWDQcGNIBVu3lw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "bcp-47-match": "^2.0.0", + "comma-separated-tokens": "^2.0.0", + "css-selector-parser": "^3.0.0", + "devlop": "^1.0.0", + "direction": "^2.0.0", + "hast-util-has-property": "^3.0.0", + "hast-util-to-string": "^3.0.0", + "hast-util-whitespace": "^3.0.0", + "nth-check": "^2.0.0", + "property-information": "^7.0.0", + "space-separated-tokens": "^2.0.0", + "unist-util-visit": "^5.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-to-estree": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/hast-util-to-estree/-/hast-util-to-estree-3.1.3.tgz", + "integrity": "sha512-48+B/rJWAp0jamNbAAf9M7Uf//UVqAoMmgXhBdxTDJLGKY+LRnZ99qcG+Qjl5HfMpYNzS5v4EAwVEF34LeAj7w==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "comma-separated-tokens": "^2.0.0", + "devlop": "^1.0.0", + "estree-util-attach-comments": "^3.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "hast-util-whitespace": "^3.0.0", + "mdast-util-mdx-expression": "^2.0.0", + "mdast-util-mdx-jsx": "^3.0.0", + "mdast-util-mdxjs-esm": "^2.0.0", + "property-information": "^7.0.0", + "space-separated-tokens": "^2.0.0", + "style-to-js": "^1.0.0", + "unist-util-position": "^5.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/hast-util-to-html": { "version": "9.0.5", "resolved": "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-9.0.5.tgz", "integrity": "sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw==", - "dev": true, "license": "MIT", "dependencies": { "@types/hast": "^3.0.0", @@ -5921,11 +6611,37 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/hast-util-to-jsx-runtime": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/hast-util-to-jsx-runtime/-/hast-util-to-jsx-runtime-2.3.6.tgz", + "integrity": "sha512-zl6s8LwNyo1P9uw+XJGvZtdFF1GdAkOg8ujOw+4Pyb76874fLps4ueHXDhXWdk6YHQ6OgUtinliG7RsYvCbbBg==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "comma-separated-tokens": "^2.0.0", + "devlop": "^1.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "hast-util-whitespace": "^3.0.0", + "mdast-util-mdx-expression": "^2.0.0", + "mdast-util-mdx-jsx": "^3.0.0", + "mdast-util-mdxjs-esm": "^2.0.0", + "property-information": "^7.0.0", + "space-separated-tokens": "^2.0.0", + "style-to-js": "^1.0.0", + "unist-util-position": "^5.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/hast-util-to-parse5": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/hast-util-to-parse5/-/hast-util-to-parse5-8.0.1.tgz", "integrity": "sha512-MlWT6Pjt4CG9lFCjiz4BH7l9wmrMkfkJYCxFwKQic8+RTZgWPuWxwAfjJElsXkex7DJjfSJsQIt931ilUgmwdA==", - "dev": true, "license": "MIT", "dependencies": { "@types/hast": "^3.0.0", @@ -5941,11 +6657,23 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/hast-util-to-string": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/hast-util-to-string/-/hast-util-to-string-3.0.1.tgz", + "integrity": "sha512-XelQVTDWvqcl3axRfI0xSeoVKzyIFPwsAGSLIsKdJKQMXDYJS4WYrBNF/8J7RdhIcFI2BOHgAifggsvsxp/3+A==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/hast-util-to-text": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/hast-util-to-text/-/hast-util-to-text-4.0.2.tgz", "integrity": "sha512-KK6y/BN8lbaq654j7JgBydev7wuNMcID54lkRav1P0CaE1e47P72AWWPiGKXTJU271ooYzcvTAn/Zt0REnvc7A==", - "dev": true, "license": "MIT", "dependencies": { "@types/hast": "^3.0.0", @@ -5962,7 +6690,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz", "integrity": "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==", - "dev": true, "license": "MIT", "dependencies": { "@types/hast": "^3.0.0" @@ -5976,7 +6703,6 @@ "version": "9.0.1", "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-9.0.1.tgz", "integrity": "sha512-g7df9rMFX/SPi34tyGCyUBREQoKkapwdY/T04Qn9TDWfHhAYt4/I0gMVirzK5wEzeUqIjEB+LXC/ypb7Aqno5w==", - "dev": true, "license": "MIT", "dependencies": { "@types/hast": "^3.0.0", @@ -5990,78 +6716,38 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/html-encoding-sniffer": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-6.0.0.tgz", - "integrity": "sha512-CV9TW3Y3f8/wT0BRFc1/KAVQ3TUHiXmaAb6VW9vtiMFf7SLoMd1PdAc4W3KFOFETBJUb90KatHqlsZMWV+R9Gg==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "@exodus/bytes": "^1.6.0" - }, - "engines": { - "node": "^20.19.0 || ^22.12.0 || >=24.0.0" - } - }, "node_modules/html-escaper": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-3.0.3.tgz", "integrity": "sha512-RuMffC89BOWQoY0WKGpIhn5gX3iI54O6nRA0yC124NYVtzjmFWBIiFd8M0x+ZdX0P9R4lADg1mgP8C7PxGOWuQ==", - "dev": true, "license": "MIT" }, "node_modules/html-void-elements": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-3.0.0.tgz", "integrity": "sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==", - "dev": true, "license": "MIT", "funding": { "type": "github", "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/html-whitespace-sensitive-tag-names": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/html-whitespace-sensitive-tag-names/-/html-whitespace-sensitive-tag-names-3.0.1.tgz", + "integrity": "sha512-q+310vW8zmymYHALr1da4HyXUQ0zgiIwIicEfotYPWGN0OJVEN/58IJ3A4GBYcEq3LGAZqKb+ugvP0GNB9CEAA==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/http-cache-semantics": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", "integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==", - "dev": true, "license": "BSD-2-Clause" }, - "node_modules/http-proxy-agent": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", - "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "agent-base": "^7.1.0", - "debug": "^4.3.4" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/https-proxy-agent": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", - "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "agent-base": "^7.1.2", - "debug": "4" - }, - "engines": { - "node": ">= 14" - } - }, "node_modules/human-id": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/human-id/-/human-id-4.1.3.tgz", @@ -6088,6 +6774,29 @@ "url": "https://github.com/sponsors/typicode" } }, + "node_modules/i18next": { + "version": "23.16.8", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-23.16.8.tgz", + "integrity": "sha512-06r/TitrM88Mg5FdUXAKL96dJMzgqLE5dv3ryBAra4KCwD9mJ4ndOTS95ZuymIGoE+2hzfdaMak2X11/es7ZWg==", + "funding": [ + { + "type": "individual", + "url": "https://locize.com" + }, + { + "type": "individual", + "url": "https://locize.com/i18next.html" + }, + { + "type": "individual", + "url": "https://www.i18next.com/how-to/faq#i18next-is-awesome.-how-can-i-support-the-project" + } + ], + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.23.2" + } + }, "node_modules/iconv-lite": { "version": "0.7.2", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.2.tgz", @@ -6119,28 +6828,71 @@ "version": "4.2.0", "resolved": "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-4.2.0.tgz", "integrity": "sha512-Iqv2fzaTQN28s/FwZAoFq0ZSs/7hMAHJVX+w8PZl3cY19Pxk6jFFalxQoIfW2826i/fDLXv8IiEZRIT0lDuWcg==", - "dev": true, "license": "MIT", "funding": { "type": "github", "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/inline-style-parser": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.2.7.tgz", + "integrity": "sha512-Nb2ctOyNR8DqQoR0OwRG95uNWIC0C1lCgf5Naz5H6Ji72KZ8OcFZLz2P5sNgwlyoJ8Yif11oMuYs5pBQa86csA==", + "license": "MIT" + }, "node_modules/iron-webcrypto": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/iron-webcrypto/-/iron-webcrypto-1.2.1.tgz", "integrity": "sha512-feOM6FaSr6rEABp/eDfVseKyTMDt+KGpeB35SkVn9Tyn0CqvVsY3EwI0v5i8nMHyJnzCIQf7nsy3p41TPkJZhg==", - "dev": true, "license": "MIT", "funding": { "url": "https://github.com/sponsors/brc-dd" } }, + "node_modules/is-alphabetical": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.1.tgz", + "integrity": "sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-alphanumerical": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-2.0.1.tgz", + "integrity": "sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==", + "license": "MIT", + "dependencies": { + "is-alphabetical": "^2.0.0", + "is-decimal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-arrayish": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.4.tgz", + "integrity": "sha512-m6UrgzFVUYawGBh1dUsWR5M2Clqic9RVXC/9f8ceNlv2IcO9j9J/z8UoCLPqtsPBFNzEpfR3xftohbfqDx8EQA==", + "license": "MIT" + }, + "node_modules/is-decimal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-2.0.1.tgz", + "integrity": "sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/is-docker": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", - "dev": true, "license": "MIT", "bin": { "is-docker": "cli.js" @@ -6166,7 +6918,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -6185,11 +6936,20 @@ "node": ">=0.10.0" } }, + "node_modules/is-hexadecimal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-2.0.1.tgz", + "integrity": "sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/is-inside-container": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", - "dev": true, "license": "MIT", "dependencies": { "is-docker": "^3.0.0" @@ -6218,7 +6978,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", - "dev": true, "license": "MIT", "engines": { "node": ">=12" @@ -6227,15 +6986,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-potential-custom-element-name": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", - "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true - }, "node_modules/is-subdir": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/is-subdir/-/is-subdir-1.2.0.tgz", @@ -6263,7 +7013,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.1.tgz", "integrity": "sha512-e6rvdUCiQCAuumZslxRJWR/Doq4VpPR82kqclvcS0efgt430SlGIk05vdCN58+VrzgtIcfNODjozVielycD4Sw==", - "dev": true, "license": "MIT", "dependencies": { "is-inside-container": "^1.0.0" @@ -6286,7 +7035,7 @@ "version": "2.6.1", "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz", "integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==", - "dev": true, + "devOptional": true, "license": "MIT", "bin": { "jiti": "lib/jiti-cli.mjs" @@ -6302,75 +7051,16 @@ "node": ">=10" } }, - "node_modules/js-yaml": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", - "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", - "dev": true, - "license": "MIT", - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/jsdom": { - "version": "28.1.0", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-28.1.0.tgz", - "integrity": "sha512-0+MoQNYyr2rBHqO1xilltfDjV9G7ymYGlAUazgcDLQaUf8JDHbuGwsxN6U9qWaElZ4w1B2r7yEGIL3GdeW3Rug==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "@acemir/cssom": "^0.9.31", - "@asamuzakjp/dom-selector": "^6.8.1", - "@bramus/specificity": "^2.4.2", - "@exodus/bytes": "^1.11.0", - "cssstyle": "^6.0.1", - "data-urls": "^7.0.0", - "decimal.js": "^10.6.0", - "html-encoding-sniffer": "^6.0.0", - "http-proxy-agent": "^7.0.2", - "https-proxy-agent": "^7.0.6", - "is-potential-custom-element-name": "^1.0.1", - "parse5": "^8.0.0", - "saxes": "^6.0.0", - "symbol-tree": "^3.2.4", - "tough-cookie": "^6.0.0", - "undici": "^7.21.0", - "w3c-xmlserializer": "^5.0.0", - "webidl-conversions": "^8.0.1", - "whatwg-mimetype": "^5.0.0", - "whatwg-url": "^16.0.0", - "xml-name-validator": "^5.0.0" - }, - "engines": { - "node": "^20.19.0 || ^22.12.0 || >=24.0.0" - }, - "peerDependencies": { - "canvas": "^3.0.0" - }, - "peerDependenciesMeta": { - "canvas": { - "optional": true - } - } - }, - "node_modules/jsdom/node_modules/parse5": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-8.0.0.tgz", - "integrity": "sha512-9m4m5GSgXjL4AjumKzq1Fgfp3Z8rsvjRNbnkVwfu2ImRqE5D0LnY2QfDen18FSY9C573YU5XxSapdHZTZ2WolA==", - "dev": true, + "node_modules/js-yaml": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", "license": "MIT", - "optional": true, - "peer": true, "dependencies": { - "entities": "^6.0.0" + "argparse": "^2.0.1" }, - "funding": { - "url": "https://github.com/inikulin/parse5?sponsor=1" + "bin": { + "js-yaml": "bin/js-yaml.js" } }, "node_modules/jsonfile": { @@ -6387,17 +7077,25 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", - "dev": true, "license": "MIT", "engines": { "node": ">=6" } }, + "node_modules/klona": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/klona/-/klona-2.0.6.tgz", + "integrity": "sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA==", + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, "node_modules/lightningcss": { "version": "1.31.1", "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.31.1.tgz", "integrity": "sha512-l51N2r93WmGUye3WuFoN5k10zyvrVs0qfKBhyC5ogUQ6Ew6JUSswh78mbSO+IU3nTWsyOArqPCcShdQSadghBQ==", - "dev": true, + "devOptional": true, "license": "MPL-2.0", "dependencies": { "detect-libc": "^2.0.3" @@ -6430,13 +7128,11 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MPL-2.0", "optional": true, "os": [ "android" ], - "peer": true, "engines": { "node": ">= 12.0.0" }, @@ -6452,13 +7148,11 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MPL-2.0", "optional": true, "os": [ "darwin" ], - "peer": true, "engines": { "node": ">= 12.0.0" }, @@ -6474,13 +7168,11 @@ "cpu": [ "x64" ], - "dev": true, "license": "MPL-2.0", "optional": true, "os": [ "darwin" ], - "peer": true, "engines": { "node": ">= 12.0.0" }, @@ -6496,13 +7188,11 @@ "cpu": [ "x64" ], - "dev": true, "license": "MPL-2.0", "optional": true, "os": [ "freebsd" ], - "peer": true, "engines": { "node": ">= 12.0.0" }, @@ -6518,13 +7208,11 @@ "cpu": [ "arm" ], - "dev": true, "license": "MPL-2.0", "optional": true, "os": [ "linux" ], - "peer": true, "engines": { "node": ">= 12.0.0" }, @@ -6540,13 +7228,11 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MPL-2.0", "optional": true, "os": [ "linux" ], - "peer": true, "engines": { "node": ">= 12.0.0" }, @@ -6562,13 +7248,11 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MPL-2.0", "optional": true, "os": [ "linux" ], - "peer": true, "engines": { "node": ">= 12.0.0" }, @@ -6584,13 +7268,11 @@ "cpu": [ "x64" ], - "dev": true, "license": "MPL-2.0", "optional": true, "os": [ "linux" ], - "peer": true, "engines": { "node": ">= 12.0.0" }, @@ -6606,13 +7288,11 @@ "cpu": [ "x64" ], - "dev": true, "license": "MPL-2.0", "optional": true, "os": [ "linux" ], - "peer": true, "engines": { "node": ">= 12.0.0" }, @@ -6628,13 +7308,11 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MPL-2.0", "optional": true, "os": [ "win32" ], - "peer": true, "engines": { "node": ">= 12.0.0" }, @@ -6650,13 +7328,11 @@ "cpu": [ "x64" ], - "dev": true, "license": "MPL-2.0", "optional": true, "os": [ "win32" ], - "peer": true, "engines": { "node": ">= 12.0.0" }, @@ -6792,7 +7468,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz", "integrity": "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==", - "dev": true, "license": "MIT", "funding": { "type": "github", @@ -6810,7 +7485,6 @@ "version": "11.2.6", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.6.tgz", "integrity": "sha512-ESL2CrkS/2wTPfuend7Zhkzo2u0daGJ/A2VucJOgQ/C48S/zB8MMeMHSGKYpXhIjbPxfuezITkaBH1wqv00DDQ==", - "dev": true, "license": "BlueOak-1.0.0", "engines": { "node": "20 || >=22" @@ -6829,7 +7503,6 @@ "version": "0.30.21", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", - "dev": true, "license": "MIT", "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" @@ -6839,7 +7512,6 @@ "version": "0.5.2", "resolved": "https://registry.npmjs.org/magicast/-/magicast-0.5.2.tgz", "integrity": "sha512-E3ZJh4J3S9KfwdjZhe2afj6R9lGIN5Pher1pF39UGrXRqq/VDaGVIGN13BjHd2u8B61hArAGOnso7nBOouW3TQ==", - "dev": true, "license": "MIT", "dependencies": { "@babel/parser": "^7.29.0", @@ -6847,11 +7519,22 @@ "source-map-js": "^1.2.1" } }, + "node_modules/markdown-extensions": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/markdown-extensions/-/markdown-extensions-2.0.0.tgz", + "integrity": "sha512-o5vL7aDWatOTX8LzaS1WMoaoxIiLRQJuIKKe2wAw6IeULDHaqbiqiggmx+pKvZDb1Sj+pE46Sn1T7lCqfFtg1Q==", + "license": "MIT", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/markdown-table": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.4.tgz", "integrity": "sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw==", - "dev": true, "license": "MIT", "funding": { "type": "github", @@ -6862,7 +7545,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/mdast-util-definitions/-/mdast-util-definitions-6.0.0.tgz", "integrity": "sha512-scTllyX6pnYNZH/AIp/0ePz6s4cZtARxImwoPJ7kS42n+MnVsI4XbnG6d4ibehRIldYMWM2LD7ImQblVhUejVQ==", - "dev": true, "license": "MIT", "dependencies": { "@types/mdast": "^4.0.0", @@ -6874,11 +7556,31 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/mdast-util-directive": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-directive/-/mdast-util-directive-3.1.0.tgz", + "integrity": "sha512-I3fNFt+DHmpWCYAT7quoM6lHf9wuqtI+oCOfvILnoicNIqjh5E3dEJWiXuYME2gNe8vl1iMQwyUHa7bgFmak6Q==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "ccount": "^2.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0", + "parse-entities": "^4.0.0", + "stringify-entities": "^4.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/mdast-util-find-and-replace": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/mdast-util-find-and-replace/-/mdast-util-find-and-replace-3.0.2.tgz", "integrity": "sha512-Tmd1Vg/m3Xz43afeNxDIhWRtFZgM2VLyaf4vSTYwudTyeuTneoL3qtWMA5jeLyz/O1vDJmmV4QuScFCA2tBPwg==", - "dev": true, "license": "MIT", "dependencies": { "@types/mdast": "^4.0.0", @@ -6895,7 +7597,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.2.tgz", "integrity": "sha512-uZhTV/8NBuw0WHkPTrCqDOl0zVe1BIng5ZtHoDk49ME1qqcjYmmLmOf0gELgcRMxN4w2iuIeVso5/6QymSrgmA==", - "dev": true, "license": "MIT", "dependencies": { "@types/mdast": "^4.0.0", @@ -6920,7 +7621,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/mdast-util-gfm/-/mdast-util-gfm-3.1.0.tgz", "integrity": "sha512-0ulfdQOM3ysHhCJ1p06l0b0VKlhU0wuQs3thxZQagjcjPrlFRqY215uZGHHJan9GEAXd9MbfPjFJz+qMkVR6zQ==", - "dev": true, "license": "MIT", "dependencies": { "mdast-util-from-markdown": "^2.0.0", @@ -6940,7 +7640,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/mdast-util-gfm-autolink-literal/-/mdast-util-gfm-autolink-literal-2.0.1.tgz", "integrity": "sha512-5HVP2MKaP6L+G6YaxPNjuL0BPrq9orG3TsrZ9YXbA3vDw/ACI4MEsnoDpn6ZNm7GnZgtAcONJyPhOP8tNJQavQ==", - "dev": true, "license": "MIT", "dependencies": { "@types/mdast": "^4.0.0", @@ -6958,7 +7657,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/mdast-util-gfm-footnote/-/mdast-util-gfm-footnote-2.1.0.tgz", "integrity": "sha512-sqpDWlsHn7Ac9GNZQMeUzPQSMzR6Wv0WKRNvQRg0KqHh02fpTz69Qc1QSseNX29bhz1ROIyNyxExfawVKTm1GQ==", - "dev": true, "license": "MIT", "dependencies": { "@types/mdast": "^4.0.0", @@ -6976,7 +7674,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/mdast-util-gfm-strikethrough/-/mdast-util-gfm-strikethrough-2.0.0.tgz", "integrity": "sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg==", - "dev": true, "license": "MIT", "dependencies": { "@types/mdast": "^4.0.0", @@ -6992,7 +7689,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/mdast-util-gfm-table/-/mdast-util-gfm-table-2.0.0.tgz", "integrity": "sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg==", - "dev": true, "license": "MIT", "dependencies": { "@types/mdast": "^4.0.0", @@ -7010,7 +7706,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/mdast-util-gfm-task-list-item/-/mdast-util-gfm-task-list-item-2.0.0.tgz", "integrity": "sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ==", - "dev": true, "license": "MIT", "dependencies": { "@types/mdast": "^4.0.0", @@ -7023,11 +7718,87 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/mdast-util-mdx": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-mdx/-/mdast-util-mdx-3.0.0.tgz", + "integrity": "sha512-JfbYLAW7XnYTTbUsmpu0kdBUVe+yKVJZBItEjwyYJiDJuZ9w4eeaqks4HQO+R7objWgS2ymV60GYpI14Ug554w==", + "license": "MIT", + "dependencies": { + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-mdx-expression": "^2.0.0", + "mdast-util-mdx-jsx": "^3.0.0", + "mdast-util-mdxjs-esm": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdx-expression": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-mdx-expression/-/mdast-util-mdx-expression-2.0.1.tgz", + "integrity": "sha512-J6f+9hUp+ldTZqKRSg7Vw5V6MqjATc+3E4gf3CFNcuZNWD8XdyI6zQ8GqH7f8169MM6P7hMBRDVGnn7oHB9kXQ==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdx-jsx": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/mdast-util-mdx-jsx/-/mdast-util-mdx-jsx-3.2.0.tgz", + "integrity": "sha512-lj/z8v0r6ZtsN/cGNNtemmmfoLAFZnjMbNyLzBafjzikOM+glrjNHPlf6lQDOTccj9n5b0PPihEBbhneMyGs1Q==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "ccount": "^2.0.0", + "devlop": "^1.1.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0", + "parse-entities": "^4.0.0", + "stringify-entities": "^4.0.0", + "unist-util-stringify-position": "^4.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdxjs-esm": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-mdxjs-esm/-/mdast-util-mdxjs-esm-2.0.1.tgz", + "integrity": "sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/mdast-util-phrasing": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/mdast-util-phrasing/-/mdast-util-phrasing-4.1.0.tgz", "integrity": "sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==", - "dev": true, "license": "MIT", "dependencies": { "@types/mdast": "^4.0.0", @@ -7042,7 +7813,6 @@ "version": "13.2.1", "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.1.tgz", "integrity": "sha512-cctsq2wp5vTsLIcaymblUriiTcZd0CwWtCbLvrOzYCDZoWyMNV8sZ7krj09FSnsiJi3WVsHLM4k6Dq/yaPyCXA==", - "dev": true, "license": "MIT", "dependencies": { "@types/hast": "^3.0.0", @@ -7064,7 +7834,6 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.2.tgz", "integrity": "sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA==", - "dev": true, "license": "MIT", "dependencies": { "@types/mdast": "^4.0.0", @@ -7086,7 +7855,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-4.0.0.tgz", "integrity": "sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==", - "dev": true, "license": "MIT", "dependencies": { "@types/mdast": "^4.0.0" @@ -7100,7 +7868,6 @@ "version": "2.12.2", "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.12.2.tgz", "integrity": "sha512-IEn+pegP1aManZuckezWCO+XZQDplx1366JoVhTpMpBB1sPey/SbveZQUosKiKiGYjg1wH4pMlNgXbCiYgihQA==", - "dev": true, "license": "CC0-1.0" }, "node_modules/merge2": { @@ -7117,7 +7884,6 @@ "version": "4.0.2", "resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.2.tgz", "integrity": "sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA==", - "dev": true, "funding": [ { "type": "GitHub Sponsors", @@ -7153,7 +7919,6 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-2.0.3.tgz", "integrity": "sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==", - "dev": true, "funding": [ { "type": "GitHub Sponsors", @@ -7184,11 +7949,29 @@ "micromark-util-types": "^2.0.0" } }, + "node_modules/micromark-extension-directive": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/micromark-extension-directive/-/micromark-extension-directive-3.0.2.tgz", + "integrity": "sha512-wjcXHgk+PPdmvR58Le9d7zQYWy+vKEU9Se44p2CrCDPiLr2FMyiT4Fyb5UFKFC66wGB3kPlgD7q3TnoqPS7SZA==", + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-factory-whitespace": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "parse-entities": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/micromark-extension-gfm": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/micromark-extension-gfm/-/micromark-extension-gfm-3.0.0.tgz", "integrity": "sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w==", - "dev": true, "license": "MIT", "dependencies": { "micromark-extension-gfm-autolink-literal": "^2.0.0", @@ -7209,7 +7992,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-2.1.0.tgz", "integrity": "sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw==", - "dev": true, "license": "MIT", "dependencies": { "micromark-util-character": "^2.0.0", @@ -7226,7 +8008,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/micromark-extension-gfm-footnote/-/micromark-extension-gfm-footnote-2.1.0.tgz", "integrity": "sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw==", - "dev": true, "license": "MIT", "dependencies": { "devlop": "^1.0.0", @@ -7247,7 +8028,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/micromark-extension-gfm-strikethrough/-/micromark-extension-gfm-strikethrough-2.1.0.tgz", "integrity": "sha512-ADVjpOOkjz1hhkZLlBiYA9cR2Anf8F4HqZUO6e5eDcPQd0Txw5fxLzzxnEkSkfnD0wziSGiv7sYhk/ktvbf1uw==", - "dev": true, "license": "MIT", "dependencies": { "devlop": "^1.0.0", @@ -7266,7 +8046,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/micromark-extension-gfm-table/-/micromark-extension-gfm-table-2.1.1.tgz", "integrity": "sha512-t2OU/dXXioARrC6yWfJ4hqB7rct14e8f7m0cbI5hUmDyyIlwv5vEtooptH8INkbLzOatzKuVbQmAYcbWoyz6Dg==", - "dev": true, "license": "MIT", "dependencies": { "devlop": "^1.0.0", @@ -7284,7 +8063,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/micromark-extension-gfm-tagfilter/-/micromark-extension-gfm-tagfilter-2.0.0.tgz", "integrity": "sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg==", - "dev": true, "license": "MIT", "dependencies": { "micromark-util-types": "^2.0.0" @@ -7298,7 +8076,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/micromark-extension-gfm-task-list-item/-/micromark-extension-gfm-task-list-item-2.1.0.tgz", "integrity": "sha512-qIBZhqxqI6fjLDYFTBIa4eivDMnP+OZqsNwmQ3xNLE4Cxwc+zfQEfbs6tzAo2Hjq+bh6q5F+Z8/cksrLFYWQQw==", - "dev": true, "license": "MIT", "dependencies": { "devlop": "^1.0.0", @@ -7306,17 +8083,139 @@ "micromark-util-character": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-mdx-expression": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/micromark-extension-mdx-expression/-/micromark-extension-mdx-expression-3.0.1.tgz", + "integrity": "sha512-dD/ADLJ1AeMvSAKBwO22zG22N4ybhe7kFIZ3LsDI0GlsNr2A3KYxb0LdC1u5rj4Nw+CHKY0RVdnHX8vj8ejm4Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "devlop": "^1.0.0", + "micromark-factory-mdx-expression": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-events-to-acorn": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-mdx-jsx": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/micromark-extension-mdx-jsx/-/micromark-extension-mdx-jsx-3.0.2.tgz", + "integrity": "sha512-e5+q1DjMh62LZAJOnDraSSbDMvGJ8x3cbjygy2qFEi7HCeUT4BDKCvMozPozcD6WmOt6sVvYDNBKhFSz3kjOVQ==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "devlop": "^1.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "micromark-factory-mdx-expression": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-events-to-acorn": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-mdx-md": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-mdx-md/-/micromark-extension-mdx-md-2.0.0.tgz", + "integrity": "sha512-EpAiszsB3blw4Rpba7xTOUptcFeBFi+6PY8VnJ2hhimH+vCQDirWgsMpz7w1XcZE7LVrSAUGb9VJpG9ghlYvYQ==", + "license": "MIT", + "dependencies": { + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-mdxjs": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-mdxjs/-/micromark-extension-mdxjs-3.0.0.tgz", + "integrity": "sha512-A873fJfhnJ2siZyUrJ31l34Uqwy4xIFmvPY1oj+Ean5PHcPBYzEsvqvWGaWcfEIr11O5Dlw3p2y0tZWpKHDejQ==", + "license": "MIT", + "dependencies": { + "acorn": "^8.0.0", + "acorn-jsx": "^5.0.0", + "micromark-extension-mdx-expression": "^3.0.0", + "micromark-extension-mdx-jsx": "^3.0.0", + "micromark-extension-mdx-md": "^2.0.0", + "micromark-extension-mdxjs-esm": "^3.0.0", + "micromark-util-combine-extensions": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-mdxjs-esm": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-mdxjs-esm/-/micromark-extension-mdxjs-esm-3.0.0.tgz", + "integrity": "sha512-DJFl4ZqkErRpq/dAPyeWp15tGrcrrJho1hKK5uBS70BCtfrIFg81sqcTVu3Ta+KD1Tk5vAtBNElWxtAa+m8K9A==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "devlop": "^1.0.0", + "micromark-core-commonmark": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-events-to-acorn": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unist-util-position-from-estree": "^2.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-factory-destination": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-2.0.1.tgz", + "integrity": "sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" } }, - "node_modules/micromark-factory-destination": { + "node_modules/micromark-factory-label": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-2.0.1.tgz", - "integrity": "sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA==", - "dev": true, + "resolved": "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-2.0.1.tgz", + "integrity": "sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg==", "funding": [ { "type": "GitHub Sponsors", @@ -7329,16 +8228,16 @@ ], "license": "MIT", "dependencies": { + "devlop": "^1.0.0", "micromark-util-character": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, - "node_modules/micromark-factory-label": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-2.0.1.tgz", - "integrity": "sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg==", - "dev": true, + "node_modules/micromark-factory-mdx-expression": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/micromark-factory-mdx-expression/-/micromark-factory-mdx-expression-2.0.3.tgz", + "integrity": "sha512-kQnEtA3vzucU2BkrIa8/VaSAsP+EJ3CKOvhMuJgOEGg9KDC6OAY6nSnNDVRiVNRqj7Y4SlSzcStaH/5jge8JdQ==", "funding": [ { "type": "GitHub Sponsors", @@ -7351,17 +8250,21 @@ ], "license": "MIT", "dependencies": { + "@types/estree": "^1.0.0", "devlop": "^1.0.0", + "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", + "micromark-util-events-to-acorn": "^2.0.0", "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" + "micromark-util-types": "^2.0.0", + "unist-util-position-from-estree": "^2.0.0", + "vfile-message": "^4.0.0" } }, "node_modules/micromark-factory-space": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz", "integrity": "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==", - "dev": true, "funding": [ { "type": "GitHub Sponsors", @@ -7382,7 +8285,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/micromark-factory-title/-/micromark-factory-title-2.0.1.tgz", "integrity": "sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw==", - "dev": true, "funding": [ { "type": "GitHub Sponsors", @@ -7405,7 +8307,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/micromark-factory-whitespace/-/micromark-factory-whitespace-2.0.1.tgz", "integrity": "sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ==", - "dev": true, "funding": [ { "type": "GitHub Sponsors", @@ -7428,7 +8329,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", - "dev": true, "funding": [ { "type": "GitHub Sponsors", @@ -7449,7 +8349,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-2.0.1.tgz", "integrity": "sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA==", - "dev": true, "funding": [ { "type": "GitHub Sponsors", @@ -7469,7 +8368,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-2.0.1.tgz", "integrity": "sha512-K0kHzM6afW/MbeWYWLjoHQv1sgg2Q9EccHEDzSkxiP/EaagNzCm7T/WMKZ3rjMbvIpvBiZgwR3dKMygtA4mG1Q==", - "dev": true, "funding": [ { "type": "GitHub Sponsors", @@ -7491,7 +8389,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/micromark-util-combine-extensions/-/micromark-util-combine-extensions-2.0.1.tgz", "integrity": "sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg==", - "dev": true, "funding": [ { "type": "GitHub Sponsors", @@ -7512,7 +8409,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-2.0.2.tgz", "integrity": "sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw==", - "dev": true, "funding": [ { "type": "GitHub Sponsors", @@ -7532,7 +8428,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/micromark-util-decode-string/-/micromark-util-decode-string-2.0.1.tgz", "integrity": "sha512-nDV/77Fj6eH1ynwscYTOsbK7rR//Uj0bZXBwJZRfaLEJ1iGBR6kIfNmlNqaqJf649EP0F3NWNdeJi03elllNUQ==", - "dev": true, "funding": [ { "type": "GitHub Sponsors", @@ -7555,7 +8450,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.1.tgz", "integrity": "sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==", - "dev": true, "funding": [ { "type": "GitHub Sponsors", @@ -7568,11 +8462,35 @@ ], "license": "MIT" }, + "node_modules/micromark-util-events-to-acorn": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/micromark-util-events-to-acorn/-/micromark-util-events-to-acorn-2.0.3.tgz", + "integrity": "sha512-jmsiEIiZ1n7X1Rr5k8wVExBQCg5jy4UXVADItHmNk1zkwEVhBuIUKRu3fqv+hs4nxLISi2DQGlqIOGiFxgbfHg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "@types/unist": "^3.0.0", + "devlop": "^1.0.0", + "estree-util-visit": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "vfile-message": "^4.0.0" + } + }, "node_modules/micromark-util-html-tag-name": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-2.0.1.tgz", "integrity": "sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA==", - "dev": true, "funding": [ { "type": "GitHub Sponsors", @@ -7589,7 +8507,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-2.0.1.tgz", "integrity": "sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q==", - "dev": true, "funding": [ { "type": "GitHub Sponsors", @@ -7609,7 +8526,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/micromark-util-resolve-all/-/micromark-util-resolve-all-2.0.1.tgz", "integrity": "sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg==", - "dev": true, "funding": [ { "type": "GitHub Sponsors", @@ -7629,7 +8545,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.1.tgz", "integrity": "sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==", - "dev": true, "funding": [ { "type": "GitHub Sponsors", @@ -7651,7 +8566,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-2.1.0.tgz", "integrity": "sha512-XQLu552iSctvnEcgXw6+Sx75GflAPNED1qx7eBJ+wydBb2KCbRZe+NwvIEEMM83uml1+2WSXpBAcp9IUCgCYWA==", - "dev": true, "funding": [ { "type": "GitHub Sponsors", @@ -7674,7 +8588,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", - "dev": true, "funding": [ { "type": "GitHub Sponsors", @@ -7691,7 +8604,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.2.tgz", "integrity": "sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==", - "dev": true, "funding": [ { "type": "GitHub Sponsors", @@ -7778,7 +8690,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.1.tgz", "integrity": "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=10" @@ -7788,7 +8699,6 @@ "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true, "license": "MIT" }, "node_modules/mz": { @@ -7838,7 +8748,6 @@ "version": "0.6.18", "resolved": "https://registry.npmjs.org/neotraverse/-/neotraverse-0.6.18.tgz", "integrity": "sha512-Z4SmBUweYa09+o6pG+eASabEpP6QkQ70yHj351pQoEXIs8uHbaU2DWVmzBANKgflPa47A50PtB2+NgRpQvr7vA==", - "dev": true, "license": "MIT", "engines": { "node": ">= 10" @@ -7928,7 +8837,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/nlcst-to-string/-/nlcst-to-string-4.0.0.tgz", "integrity": "sha512-YKLBCcUYKAg0FNlOBT6aI91qFmSiFKiluk655WzPF+DDMA02qIyy8uiRqI8QXtcFpEvll12LpL5MXqEmAZ+dcA==", - "dev": true, "license": "MIT", "dependencies": { "@types/nlcst": "^2.0.0" @@ -7963,7 +8871,6 @@ "version": "1.6.7", "resolved": "https://registry.npmjs.org/node-fetch-native/-/node-fetch-native-1.6.7.tgz", "integrity": "sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q==", - "dev": true, "license": "MIT" }, "node_modules/node-fetch/node_modules/tr46": { @@ -7995,14 +8902,12 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/node-mock-http/-/node-mock-http-1.0.4.tgz", "integrity": "sha512-8DY+kFsDkNXy1sJglUfuODx1/opAGJGyrTuFqEoN90oRc2Vk0ZbD4K2qmKXBBEhZQzdKHIVfEJpDU8Ak2NJEvQ==", - "dev": true, "license": "MIT" }, "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -8012,7 +8917,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", - "dev": true, "license": "BSD-2-Clause", "dependencies": { "boolbase": "^1.0.0" @@ -8035,7 +8939,6 @@ "version": "1.5.1", "resolved": "https://registry.npmjs.org/ofetch/-/ofetch-1.5.1.tgz", "integrity": "sha512-2W4oUZlVaqAPAil6FUg/difl6YhqhUR7x2eZY4bQCko22UXg3hptq9KLQdqFClV+Wu85UX7hNtdGTngi/1BxcA==", - "dev": true, "license": "MIT", "dependencies": { "destr": "^2.0.5", @@ -8047,7 +8950,6 @@ "version": "2.0.11", "resolved": "https://registry.npmjs.org/ohash/-/ohash-2.0.11.tgz", "integrity": "sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==", - "dev": true, "license": "MIT" }, "node_modules/onetime": { @@ -8070,14 +8972,12 @@ "version": "0.12.1", "resolved": "https://registry.npmjs.org/oniguruma-parser/-/oniguruma-parser-0.12.1.tgz", "integrity": "sha512-8Unqkvk1RYc6yq2WBYRj4hdnsAxVze8i7iPfQr8e4uSP3tRv0rpZcbGUDvxfQQcdwHt/e9PrMvGCsa8OqG9X3w==", - "dev": true, "license": "MIT" }, "node_modules/oniguruma-to-es": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/oniguruma-to-es/-/oniguruma-to-es-4.3.4.tgz", "integrity": "sha512-3VhUGN3w2eYxnTzHn+ikMI+fp/96KoRSVK9/kMTcFqj1NRDh2IhQCKvYxDnWePKRXY/AqH+Fuiyb7VHSzBjHfA==", - "dev": true, "license": "MIT", "dependencies": { "oniguruma-parser": "^0.12.1", @@ -8109,7 +9009,6 @@ "version": "6.2.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-6.2.0.tgz", "integrity": "sha512-kuUqqHNUqoIWp/c467RI4X6mmyuojY5jGutNU0wVTmEOOfcuwLqyMVoAi9MKi2Ak+5i9+nhmrK4ufZE8069kHA==", - "dev": true, "license": "MIT", "dependencies": { "yocto-queue": "^1.1.1" @@ -8164,7 +9063,6 @@ "version": "8.1.1", "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-8.1.1.tgz", "integrity": "sha512-aNZ+VfjobsWryoiPnEApGGmf5WmNsCo9xu8dfaYamG5qaLP7ClhLN6NgsFe6SwJ2UbLEBK5dv9x8Mn5+RVhMWQ==", - "dev": true, "license": "MIT", "dependencies": { "eventemitter3": "^5.0.1", @@ -8181,7 +9079,6 @@ "version": "6.1.4", "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-6.1.4.tgz", "integrity": "sha512-MyIV3ZA/PmyBN/ud8vV9XzwTrNtR4jFrObymZYnZqMmW0zA8Z17vnT0rBgFE/TlohB+YCHqXMgZzb3Csp49vqg==", - "dev": true, "license": "MIT", "engines": { "node": ">=14.16" @@ -8204,14 +9101,54 @@ "version": "1.6.0", "resolved": "https://registry.npmjs.org/package-manager-detector/-/package-manager-detector-1.6.0.tgz", "integrity": "sha512-61A5ThoTiDG/C8s8UMZwSorAGwMJ0ERVGj2OjoW5pAalsNOg15+iQiPzrLJ4jhZ1HJzmC2PIHT2oEiH3R5fzNA==", - "dev": true, + "license": "MIT" + }, + "node_modules/pagefind": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/pagefind/-/pagefind-1.4.0.tgz", + "integrity": "sha512-z2kY1mQlL4J8q5EIsQkLzQjilovKzfNVhX8De6oyE6uHpfFtyBaqUpcl/XzJC/4fjD8vBDyh1zolimIcVrCn9g==", + "license": "MIT", + "bin": { + "pagefind": "lib/runner/bin.cjs" + }, + "optionalDependencies": { + "@pagefind/darwin-arm64": "1.4.0", + "@pagefind/darwin-x64": "1.4.0", + "@pagefind/freebsd-x64": "1.4.0", + "@pagefind/linux-arm64": "1.4.0", + "@pagefind/linux-x64": "1.4.0", + "@pagefind/windows-x64": "1.4.0" + } + }, + "node_modules/parse-entities": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-4.0.2.tgz", + "integrity": "sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw==", + "license": "MIT", + "dependencies": { + "@types/unist": "^2.0.0", + "character-entities-legacy": "^3.0.0", + "character-reference-invalid": "^2.0.0", + "decode-named-character-reference": "^1.0.0", + "is-alphanumerical": "^2.0.0", + "is-decimal": "^2.0.0", + "is-hexadecimal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/parse-entities/node_modules/@types/unist": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz", + "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==", "license": "MIT" }, "node_modules/parse-latin": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/parse-latin/-/parse-latin-7.0.0.tgz", "integrity": "sha512-mhHgobPPua5kZ98EF4HWiH167JWBfl4pvAIXXdbaVohtK7a6YBOy56kvhCqduqyo/f3yrHFWmqmiMg/BkBkYYQ==", - "dev": true, "license": "MIT", "dependencies": { "@types/nlcst": "^2.0.0", @@ -8230,7 +9167,6 @@ "version": "7.3.0", "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz", "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==", - "dev": true, "license": "MIT", "dependencies": { "entities": "^6.0.0" @@ -8290,7 +9226,6 @@ "version": "0.1.3", "resolved": "https://registry.npmjs.org/piccolore/-/piccolore-0.1.3.tgz", "integrity": "sha512-o8bTeDWjE086iwKrROaDf31K0qC/BENdm15/uH9usSC/uZjJOKb2YGiVHfLY4GhwsERiPI1jmwI2XrA7ACOxVw==", - "dev": true, "license": "ISC" }, "node_modules/picocolors": { @@ -8303,7 +9238,6 @@ "version": "4.0.3", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", - "dev": true, "license": "MIT", "engines": { "node": ">=12" @@ -8400,7 +9334,6 @@ "version": "2.3.2", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, "hasInstallScript": true, "license": "MIT", "optional": true, @@ -8415,7 +9348,6 @@ "version": "8.5.6", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", - "dev": true, "funding": [ { "type": "opencollective", @@ -8483,6 +9415,44 @@ } } }, + "node_modules/postcss-nested": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz", + "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "postcss-selector-parser": "^6.1.1" + }, + "engines": { + "node": ">=12.0" + }, + "peerDependencies": { + "postcss": "^8.2.14" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", + "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/prettier": { "version": "2.8.8", "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", @@ -8503,7 +9473,6 @@ "version": "1.30.0", "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.30.0.tgz", "integrity": "sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw==", - "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -8513,7 +9482,6 @@ "version": "2.4.2", "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", - "dev": true, "license": "MIT", "dependencies": { "kleur": "^3.0.3", @@ -8527,25 +9495,12 @@ "version": "7.1.0", "resolved": "https://registry.npmjs.org/property-information/-/property-information-7.1.0.tgz", "integrity": "sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==", - "dev": true, "license": "MIT", "funding": { "type": "github", "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "engines": { - "node": ">=6" - } - }, "node_modules/quansync": { "version": "0.2.11", "resolved": "https://registry.npmjs.org/quansync/-/quansync-0.2.11.tgz", @@ -8588,7 +9543,6 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/radix3/-/radix3-1.1.2.tgz", "integrity": "sha512-b484I/7b8rDEdSDKckSSBA8knMpcdsXudlE/LNL639wFoHKwLbEkQFZHWEYwDC0wa0FKUcCY+GAF73Z7wxNVFA==", - "dev": true, "license": "MIT" }, "node_modules/react": { @@ -8666,11 +9620,77 @@ "url": "https://paulmillr.com/funding/" } }, + "node_modules/recma-build-jsx": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/recma-build-jsx/-/recma-build-jsx-1.0.0.tgz", + "integrity": "sha512-8GtdyqaBcDfva+GUKDr3nev3VpKAhup1+RvkMvUxURHpW7QyIvk9F5wz7Vzo06CEMSilw6uArgRqhpiUcWp8ew==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "estree-util-build-jsx": "^3.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/recma-jsx": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/recma-jsx/-/recma-jsx-1.0.1.tgz", + "integrity": "sha512-huSIy7VU2Z5OLv6oFLosQGGDqPqdO1iq6bWNAdhzMxSJP7RAso4fCZ1cKu8j9YHCZf3TPrq4dw3okhrylgcd7w==", + "license": "MIT", + "dependencies": { + "acorn-jsx": "^5.0.0", + "estree-util-to-js": "^2.0.0", + "recma-parse": "^1.0.0", + "recma-stringify": "^1.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + }, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/recma-parse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/recma-parse/-/recma-parse-1.0.0.tgz", + "integrity": "sha512-OYLsIGBB5Y5wjnSnQW6t3Xg7q3fQ7FWbw/vcXtORTnyaSFscOtABg+7Pnz6YZ6c27fG1/aN8CjfwoUEUIdwqWQ==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "esast-util-from-js": "^2.0.0", + "unified": "^11.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/recma-stringify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/recma-stringify/-/recma-stringify-1.0.0.tgz", + "integrity": "sha512-cjwII1MdIIVloKvC9ErQ+OgAtwHBmcZ0Bg4ciz78FtbT8In39aAYbaA7zvxQ61xVMSPE8WxhLwLbhif4Js2C+g==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "estree-util-to-js": "^2.0.0", + "unified": "^11.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/regex": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/regex/-/regex-6.1.0.tgz", "integrity": "sha512-6VwtthbV4o/7+OaAF9I5L5V3llLEsoPyq9P1JVXkedTP33c7MfCG0/5NOPcSJn0TzXcG9YUrR0gQSWioew3LDg==", - "dev": true, "license": "MIT", "dependencies": { "regex-utilities": "^2.3.0" @@ -8680,7 +9700,6 @@ "version": "6.0.2", "resolved": "https://registry.npmjs.org/regex-recursion/-/regex-recursion-6.0.2.tgz", "integrity": "sha512-0YCaSCq2VRIebiaUviZNs0cBz1kg5kVS2UKUfNIx8YVs1cN3AV7NTctO5FOKBA+UT2BPJIWZauYHPqJODG50cg==", - "dev": true, "license": "MIT", "dependencies": { "regex-utilities": "^2.3.0" @@ -8690,14 +9709,12 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/regex-utilities/-/regex-utilities-2.3.0.tgz", "integrity": "sha512-8VhliFJAWRaUiVvREIiW2NXXTmHs4vMNnSzuJVhscgmGav3g9VDxLrQndI3dZZVVdp0ZO/5v0xmX516/7M9cng==", - "dev": true, "license": "MIT" }, "node_modules/rehype": { "version": "13.0.2", "resolved": "https://registry.npmjs.org/rehype/-/rehype-13.0.2.tgz", "integrity": "sha512-j31mdaRFrwFRUIlxGeuPXXKWQxet52RBQRvCmzl5eCefn/KGbomK5GMHNMsOJf55fgo3qw5tST5neDuarDYR2A==", - "dev": true, "license": "MIT", "dependencies": { "@types/hast": "^3.0.0", @@ -8710,11 +9727,33 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/rehype-expressive-code": { + "version": "0.41.7", + "resolved": "https://registry.npmjs.org/rehype-expressive-code/-/rehype-expressive-code-0.41.7.tgz", + "integrity": "sha512-25f8ZMSF1d9CMscX7Cft0TSQIqdwjce2gDOvQ+d/w0FovsMwrSt3ODP4P3Z7wO1jsIJ4eYyaDRnIR/27bd/EMQ==", + "license": "MIT", + "dependencies": { + "expressive-code": "^0.41.7" + } + }, + "node_modules/rehype-format": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/rehype-format/-/rehype-format-5.0.1.tgz", + "integrity": "sha512-zvmVru9uB0josBVpr946OR8ui7nJEdzZobwLOOqHb/OOD88W0Vk2SqLwoVOj0fM6IPCCO6TaV9CvQvJMWwukFQ==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "hast-util-format": "^1.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/rehype-parse": { "version": "9.0.1", "resolved": "https://registry.npmjs.org/rehype-parse/-/rehype-parse-9.0.1.tgz", "integrity": "sha512-ksCzCD0Fgfh7trPDxr2rSylbwq9iYDkSn8TCDmEJ49ljEUBxDVCzCHv7QNzZOfODanX4+bWQ4WZqLCRWYLfhag==", - "dev": true, "license": "MIT", "dependencies": { "@types/hast": "^3.0.0", @@ -8730,7 +9769,6 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/rehype-raw/-/rehype-raw-7.0.0.tgz", "integrity": "sha512-/aE8hCfKlQeA8LmyeyQvQF3eBiLRGNlfBJEvWH7ivp9sBqs7TNqBL5X3v157rM4IFETqDnIOO+z5M/biZbo9Ww==", - "dev": true, "license": "MIT", "dependencies": { "@types/hast": "^3.0.0", @@ -8742,11 +9780,25 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/rehype-recma": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/rehype-recma/-/rehype-recma-1.0.0.tgz", + "integrity": "sha512-lqA4rGUf1JmacCNWWZx0Wv1dHqMwxzsDWYMTowuplHF3xH0N/MmrZ/G3BDZnzAkRmxDadujCjaKM2hqYdCBOGw==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "@types/hast": "^3.0.0", + "hast-util-to-estree": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/rehype-stringify": { "version": "10.0.1", "resolved": "https://registry.npmjs.org/rehype-stringify/-/rehype-stringify-10.0.1.tgz", "integrity": "sha512-k9ecfXHmIPuFVI61B9DeLPN0qFHfawM6RsuX48hoqlaKSF61RskNjSm1lI8PhBEM0MRdLxVVm4WmTqJQccH9mA==", - "dev": true, "license": "MIT", "dependencies": { "@types/hast": "^3.0.0", @@ -8758,11 +9810,26 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/remark-directive": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/remark-directive/-/remark-directive-3.0.1.tgz", + "integrity": "sha512-gwglrEQEZcZYgVyG1tQuA+h58EZfq5CSULw7J90AFuCTyib1thgHPoqQ+h9iFvU6R+vnZ5oNFQR5QKgGpk741A==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-directive": "^3.0.0", + "micromark-extension-directive": "^3.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/remark-gfm": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/remark-gfm/-/remark-gfm-4.0.1.tgz", "integrity": "sha512-1quofZ2RQ9EWdeN34S79+KExV1764+wCUGop5CPL1WGdD0ocPpu91lzPGbwWMECpEpd42kJGQwzRfyov9j4yNg==", - "dev": true, "license": "MIT", "dependencies": { "@types/mdast": "^4.0.0", @@ -8777,11 +9844,24 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/remark-mdx": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/remark-mdx/-/remark-mdx-3.1.1.tgz", + "integrity": "sha512-Pjj2IYlUY3+D8x00UJsIOg5BEvfMyeI+2uLPn9VO9Wg4MEtN/VTIq2NEJQfde9PnX15KgtHyl9S0BcTnWrIuWg==", + "license": "MIT", + "dependencies": { + "mdast-util-mdx": "^3.0.0", + "micromark-extension-mdxjs": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/remark-parse": { "version": "11.0.0", "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-11.0.0.tgz", "integrity": "sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==", - "dev": true, "license": "MIT", "dependencies": { "@types/mdast": "^4.0.0", @@ -8798,7 +9878,6 @@ "version": "11.1.2", "resolved": "https://registry.npmjs.org/remark-rehype/-/remark-rehype-11.1.2.tgz", "integrity": "sha512-Dh7l57ianaEoIpzbp0PC9UKAdCSVklD8E5Rpw7ETfbTl3FqcOOgq5q2LVDhgGCkaBv7p24JXikPdvhhmHvKMsw==", - "dev": true, "license": "MIT", "dependencies": { "@types/hast": "^3.0.0", @@ -8816,7 +9895,6 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/remark-smartypants/-/remark-smartypants-3.0.2.tgz", "integrity": "sha512-ILTWeOriIluwEvPjv67v7Blgrcx+LZOkAUVtKI3putuhlZm84FnqDORNXPPm+HY3NdZOMhyDwZ1E+eZB/Df5dA==", - "dev": true, "license": "MIT", "dependencies": { "retext": "^9.0.0", @@ -8832,7 +9910,6 @@ "version": "11.0.0", "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-11.0.0.tgz", "integrity": "sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==", - "dev": true, "license": "MIT", "dependencies": { "@types/mdast": "^4.0.0", @@ -8844,18 +9921,6 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/resolve-from": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", @@ -8870,7 +9935,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", - "dev": true, + "devOptional": true, "license": "MIT", "funding": { "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" @@ -8897,7 +9962,6 @@ "version": "9.0.0", "resolved": "https://registry.npmjs.org/retext/-/retext-9.0.0.tgz", "integrity": "sha512-sbMDcpHCNjvlheSgMfEcVrZko3cDzdbe1x/e7G66dFp0Ff7Mldvi2uv6JkJQzdRcvLYE8CA8Oe8siQx8ZOgTcA==", - "dev": true, "license": "MIT", "dependencies": { "@types/nlcst": "^2.0.0", @@ -8914,7 +9978,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/retext-latin/-/retext-latin-4.0.0.tgz", "integrity": "sha512-hv9woG7Fy0M9IlRQloq/N6atV82NxLGveq+3H2WOi79dtIYWN8OaxogDm77f8YnVXJL2VD3bbqowu5E3EMhBYA==", - "dev": true, "license": "MIT", "dependencies": { "@types/nlcst": "^2.0.0", @@ -8930,7 +9993,6 @@ "version": "6.2.0", "resolved": "https://registry.npmjs.org/retext-smartypants/-/retext-smartypants-6.2.0.tgz", "integrity": "sha512-kk0jOU7+zGv//kfjXEBjdIryL1Acl4i9XNkHxtM7Tm5lFiCog576fjNC9hjoR7LTKQ0DsPWy09JummSsH1uqfQ==", - "dev": true, "license": "MIT", "dependencies": { "@types/nlcst": "^2.0.0", @@ -8946,7 +10008,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/retext-stringify/-/retext-stringify-4.0.0.tgz", "integrity": "sha512-rtfN/0o8kL1e+78+uxPTqu1Klt0yPzKuQ2BfWwwfgIUSayyzxpM1PJzkKt4V8803uB9qSy32MvI7Xep9khTpiA==", - "dev": true, "license": "MIT", "dependencies": { "@types/nlcst": "^2.0.0", @@ -8980,7 +10041,6 @@ "version": "4.57.1", "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.57.1.tgz", "integrity": "sha512-oQL6lgK3e2QZeQ7gcgIkS2YZPg5slw37hYufJ3edKlfQSGGm8ICoxswK15ntSzF/a8+h7ekRy7k7oWc3BQ7y8A==", - "dev": true, "license": "MIT", "dependencies": { "@types/estree": "1.0.8" @@ -9056,27 +10116,11 @@ "version": "1.4.4", "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.4.tgz", "integrity": "sha512-1n3r/tGXO6b6VXMdFT54SHzT9ytu9yr7TaELowdYpMqY/Ao7EnlQGmAQ1+RatX7Tkkdm6hONI2owqNx2aZj5Sw==", - "dev": true, "license": "BlueOak-1.0.0", "engines": { "node": ">=11.0.0" } }, - "node_modules/saxes": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", - "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==", - "dev": true, - "license": "ISC", - "optional": true, - "peer": true, - "dependencies": { - "xmlchars": "^2.2.0" - }, - "engines": { - "node": ">=v12.22.7" - } - }, "node_modules/scheduler": { "version": "0.27.0", "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz", @@ -9087,7 +10131,6 @@ "version": "7.7.4", "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", - "devOptional": true, "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -9168,7 +10211,6 @@ "version": "3.22.0", "resolved": "https://registry.npmjs.org/shiki/-/shiki-3.22.0.tgz", "integrity": "sha512-LBnhsoYEe0Eou4e1VgJACes+O6S6QC0w71fCSp5Oya79inkwkm15gQ1UF6VtQ8j/taMDh79hAB49WUk8ALQW3g==", - "dev": true, "license": "MIT", "dependencies": { "@shikijs/core": "3.22.0", @@ -9201,13 +10243,49 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/simple-swizzle": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.4.tgz", + "integrity": "sha512-nAu1WFPQSMNr2Zn9PGSZK9AGn4t/y97lEm+MXTtUDwfP0ksAIX4nO+6ruD9Jwut4C49SB1Ws+fbXsm/yScWOHw==", + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.3.1" + } + }, "node_modules/sisteransi": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", - "dev": true, "license": "MIT" }, + "node_modules/sitemap": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/sitemap/-/sitemap-9.0.1.tgz", + "integrity": "sha512-S6hzjGJSG3d6if0YoF5kTyeRJvia6FSTBroE5fQ0bu1QNxyJqhhinfUsXi9fH3MgtXODWvwo2BDyQSnhPQ88uQ==", + "license": "MIT", + "dependencies": { + "@types/node": "^24.9.2", + "@types/sax": "^1.2.1", + "arg": "^5.0.0", + "sax": "^1.4.1" + }, + "bin": { + "sitemap": "dist/esm/cli.js" + }, + "engines": { + "node": ">=20.19.5", + "npm": ">=10.8.2" + } + }, + "node_modules/sitemap/node_modules/@types/node": { + "version": "24.12.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.12.0.tgz", + "integrity": "sha512-GYDxsZi3ChgmckRT9HPU0WEhKLP08ev/Yfcq2AstjrDASOYCSXeyjDsHg4v5t4jOj7cyDX3vmprafKlWIG9MXQ==", + "license": "MIT", + "dependencies": { + "undici-types": "~7.16.0" + } + }, "node_modules/slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", @@ -9255,7 +10333,6 @@ "version": "1.6.0", "resolved": "https://registry.npmjs.org/smol-toml/-/smol-toml-1.6.0.tgz", "integrity": "sha512-4zemZi0HvTnYwLfrpk/CF9LOd9Lt87kAt50GnqhMpyF9U3poDAP2+iukq2bZsO/ufegbYehBkqINbsWxj4l4cw==", - "dev": true, "license": "BSD-3-Clause", "engines": { "node": ">= 18" @@ -9268,7 +10345,6 @@ "version": "0.7.6", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.6.tgz", "integrity": "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==", - "dev": true, "license": "BSD-3-Clause", "engines": { "node": ">= 12" @@ -9287,7 +10363,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==", - "dev": true, "license": "MIT", "funding": { "type": "github", @@ -9326,6 +10401,12 @@ "dev": true, "license": "MIT" }, + "node_modules/stream-replace-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/stream-replace-string/-/stream-replace-string-2.0.0.tgz", + "integrity": "sha512-TlnjJ1C0QrmxRNrON00JvaFFlNh5TTG00APw23j74ET7gkQpTASi6/L2fuiav8pzK715HXtUeClpBTw2NPSn6w==", + "license": "MIT" + }, "node_modules/string-argv": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz", @@ -9340,7 +10421,6 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", - "dev": true, "license": "MIT", "dependencies": { "emoji-regex": "^10.3.0", @@ -9358,7 +10438,6 @@ "version": "4.0.4", "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.4.tgz", "integrity": "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==", - "dev": true, "license": "MIT", "dependencies": { "character-entities-html4": "^2.0.0", @@ -9373,7 +10452,6 @@ "version": "7.1.2", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", - "dev": true, "license": "MIT", "dependencies": { "ansi-regex": "^6.0.1" @@ -9395,6 +10473,24 @@ "node": ">=4" } }, + "node_modules/style-to-js": { + "version": "1.1.21", + "resolved": "https://registry.npmjs.org/style-to-js/-/style-to-js-1.1.21.tgz", + "integrity": "sha512-RjQetxJrrUJLQPHbLku6U/ocGtzyjbJMP9lCNK7Ag0CNh690nSH8woqWH9u16nMjYBAok+i7JO1NP2pOy8IsPQ==", + "license": "MIT", + "dependencies": { + "style-to-object": "1.0.14" + } + }, + "node_modules/style-to-object": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-1.0.14.tgz", + "integrity": "sha512-LIN7rULI0jBscWQYaSswptyderlarFkjQ+t79nzty8tcIAceVomEVlLzH5VP4Cmsv6MtKhs7qaAiwlcp+Mgaxw==", + "license": "MIT", + "dependencies": { + "inline-style-parser": "0.2.7" + } + }, "node_modules/styled-jsx": { "version": "5.1.6", "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.6.tgz", @@ -9455,7 +10551,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/svgo/-/svgo-4.0.0.tgz", "integrity": "sha512-VvrHQ+9uniE+Mvx3+C9IEe/lWasXCU0nXMY2kZeLrHNICuRiC8uMPyM14UEaMOFA5mhyQqEkB02VoQ16n3DLaw==", - "dev": true, "license": "MIT", "dependencies": { "commander": "^11.1.0", @@ -9477,15 +10572,6 @@ "url": "https://opencollective.com/svgo" } }, - "node_modules/symbol-tree": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", - "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true - }, "node_modules/tailwind-merge": { "version": "2.6.1", "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-2.6.1.tgz", @@ -9557,7 +10643,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/tiny-inflate/-/tiny-inflate-1.0.3.tgz", "integrity": "sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==", - "dev": true, "license": "MIT" }, "node_modules/tinybench": { @@ -9578,7 +10663,6 @@ "version": "0.2.15", "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", - "dev": true, "license": "MIT", "dependencies": { "fdir": "^6.5.0", @@ -9621,30 +10705,6 @@ "node": ">=14.0.0" } }, - "node_modules/tldts": { - "version": "7.0.23", - "resolved": "https://registry.npmjs.org/tldts/-/tldts-7.0.23.tgz", - "integrity": "sha512-ASdhgQIBSay0R/eXggAkQ53G4nTJqTXqC2kbaBbdDwM7SkjyZyO0OaaN1/FH7U/yCeqOHDwFO5j8+Os/IS1dXw==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "tldts-core": "^7.0.23" - }, - "bin": { - "tldts": "bin/cli.js" - } - }, - "node_modules/tldts-core": { - "version": "7.0.23", - "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-7.0.23.tgz", - "integrity": "sha512-0g9vrtDQLrNIiCj22HSe9d4mLVG3g5ph5DZ8zCKBr4OtrspmNB6ss7hVyzArAeE88ceZocIEGkyW1Ime7fxPtQ==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true - }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -9658,36 +10718,6 @@ "node": ">=8.0" } }, - "node_modules/tough-cookie": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-6.0.0.tgz", - "integrity": "sha512-kXuRi1mtaKMrsLUxz3sQYvVl37B0Ns6MzfrtV5DvJceE9bPyspOqk9xxv7XbZWcfLWbFmm997vl83qUWVJA64w==", - "dev": true, - "license": "BSD-3-Clause", - "optional": true, - "peer": true, - "dependencies": { - "tldts": "^7.0.5" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/tr46": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-6.0.0.tgz", - "integrity": "sha512-bLVMLPtstlZ4iMQHpFHTR7GAGj2jxi8Dg0s2h2MafAE4uSWF98FC/3MomU51iQAMf8/qDUbKWf5GxuvvVcXEhw==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "punycode": "^2.3.1" - }, - "engines": { - "node": ">=20" - } - }, "node_modules/tree-kill": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", @@ -9702,7 +10732,6 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz", "integrity": "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==", - "dev": true, "license": "MIT", "funding": { "type": "github", @@ -9713,7 +10742,6 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/trough/-/trough-2.2.0.tgz", "integrity": "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==", - "dev": true, "license": "MIT", "funding": { "type": "github", @@ -9731,7 +10759,6 @@ "version": "3.1.6", "resolved": "https://registry.npmjs.org/tsconfck/-/tsconfck-3.1.6.tgz", "integrity": "sha512-ks6Vjr/jEw0P1gmOVwutM3B7fWxoWBL2KRDb1JfqGVawBmO5UsvmWOQFGHBPl5yxYz4eERr19E6L7NMv+Fej4w==", - "dev": true, "license": "MIT", "bin": { "tsconfck": "bin/tsconfck.js" @@ -10244,7 +11271,7 @@ "version": "4.21.0", "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.21.0.tgz", "integrity": "sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "esbuild": "~0.27.0", @@ -10267,7 +11294,6 @@ "cpu": [ "ppc64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -10284,7 +11310,6 @@ "cpu": [ "arm" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -10301,7 +11326,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -10318,7 +11342,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -10335,7 +11358,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -10352,7 +11374,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -10369,7 +11390,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -10386,7 +11406,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -10403,7 +11422,6 @@ "cpu": [ "arm" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -10420,7 +11438,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -10437,7 +11454,6 @@ "cpu": [ "ia32" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -10454,7 +11470,6 @@ "cpu": [ "loong64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -10471,7 +11486,6 @@ "cpu": [ "mips64el" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -10488,7 +11502,6 @@ "cpu": [ "ppc64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -10505,7 +11518,6 @@ "cpu": [ "riscv64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -10522,7 +11534,6 @@ "cpu": [ "s390x" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -10539,7 +11550,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -10556,7 +11566,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -10573,7 +11582,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -10590,7 +11598,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -10607,7 +11614,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -10624,7 +11630,6 @@ "cpu": [ "ia32" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -10641,7 +11646,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -10655,7 +11659,7 @@ "version": "0.27.3", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.3.tgz", "integrity": "sha512-8VwMnyGCONIs6cWue2IdpHxHnAjzxnw2Zr7MkVxB2vjmQ2ivqGFb4LEG3SMnv0Gb2F/G/2yA8zUaiL1gywDCCg==", - "dev": true, + "devOptional": true, "hasInstallScript": true, "license": "MIT", "bin": { @@ -10799,7 +11803,6 @@ "version": "4.41.0", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", - "dev": true, "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=16" @@ -10812,7 +11815,6 @@ "version": "5.9.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", - "dev": true, "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", @@ -10826,47 +11828,30 @@ "version": "1.6.3", "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.6.3.tgz", "integrity": "sha512-yDJTmhydvl5lJzBmy/hyOAA0d+aqCBuwl818haVdYCRrWV84o7YyeVm4QlVHStqNrrJSTb6jKuFAVqAFsr+K3Q==", - "dev": true, "license": "MIT" }, "node_modules/ultrahtml": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/ultrahtml/-/ultrahtml-1.6.0.tgz", "integrity": "sha512-R9fBn90VTJrqqLDwyMph+HGne8eqY1iPfYhPzZrvKpIfwkWZbcYlfpsb8B9dTvBfpy1/hqAD7Wi8EKfP9e8zdw==", - "dev": true, "license": "MIT" }, "node_modules/uncrypto": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/uncrypto/-/uncrypto-0.1.3.tgz", "integrity": "sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q==", - "dev": true, "license": "MIT" }, - "node_modules/undici": { - "version": "7.22.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-7.22.0.tgz", - "integrity": "sha512-RqslV2Us5BrllB+JeiZnK4peryVTndy9Dnqq62S3yYRRTj0tFQCwEniUy2167skdGOy3vqRzEvl1Dm4sV2ReDg==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "engines": { - "node": ">=20.18.1" - } - }, "node_modules/undici-types": { "version": "7.16.0", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", - "dev": true, "license": "MIT" }, "node_modules/unified": { "version": "11.0.5", "resolved": "https://registry.npmjs.org/unified/-/unified-11.0.5.tgz", "integrity": "sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==", - "dev": true, "license": "MIT", "dependencies": { "@types/unist": "^3.0.0", @@ -10886,7 +11871,6 @@ "version": "0.7.4", "resolved": "https://registry.npmjs.org/unifont/-/unifont-0.7.4.tgz", "integrity": "sha512-oHeis4/xl42HUIeHuNZRGEvxj5AaIKR+bHPNegRq5LV1gdc3jundpONbjglKpihmJf+dswygdMJn3eftGIMemg==", - "dev": true, "license": "MIT", "dependencies": { "css-tree": "^3.1.0", @@ -10898,7 +11882,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/unist-util-find-after/-/unist-util-find-after-5.0.0.tgz", "integrity": "sha512-amQa0Ep2m6hE2g72AugUItjbuM8X8cGQnFoHk0pGfrFeT9GZhzN5SW8nRsiGKK7Aif4CrACPENkA6P/Lw6fHGQ==", - "dev": true, "license": "MIT", "dependencies": { "@types/unist": "^3.0.0", @@ -10913,7 +11896,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.1.tgz", "integrity": "sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==", - "dev": true, "license": "MIT", "dependencies": { "@types/unist": "^3.0.0" @@ -10927,7 +11909,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/unist-util-modify-children/-/unist-util-modify-children-4.0.0.tgz", "integrity": "sha512-+tdN5fGNddvsQdIzUF3Xx82CU9sMM+fA0dLgR9vOmT0oPT2jH+P1nd5lSqfCfXAw+93NhcXNY2qqvTUtE4cQkw==", - "dev": true, "license": "MIT", "dependencies": { "@types/unist": "^3.0.0", @@ -10942,7 +11923,19 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-5.0.0.tgz", "integrity": "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==", - "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-position-from-estree": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unist-util-position-from-estree/-/unist-util-position-from-estree-2.0.0.tgz", + "integrity": "sha512-KaFVRjoqLyF6YXCbVLNad/eS4+OfPQQn2yOd7zF/h5T/CSL2v8NpN6a5TPvtbXthAGw5nG+PuTtq+DdIZr+cRQ==", "license": "MIT", "dependencies": { "@types/unist": "^3.0.0" @@ -10956,7 +11949,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-5.0.0.tgz", "integrity": "sha512-Hp5Kh3wLxv0PHj9m2yZhhLt58KzPtEYKQQ4yxfYFEO7EvHwzyDYnduhHnY1mDxoqr7VUwVuHXk9RXKIiYS1N8Q==", - "dev": true, "license": "MIT", "dependencies": { "@types/unist": "^3.0.0", @@ -10971,7 +11963,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", - "dev": true, "license": "MIT", "dependencies": { "@types/unist": "^3.0.0" @@ -10985,7 +11976,6 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.1.0.tgz", "integrity": "sha512-m+vIdyeCOpdr/QeQCu2EzxX/ohgS8KbnPDgFni4dQsfSCtpz8UqDyY5GjRru8PDKuYn7Fq19j1CQ+nJSsGKOzg==", - "dev": true, "license": "MIT", "dependencies": { "@types/unist": "^3.0.0", @@ -11001,7 +11991,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/unist-util-visit-children/-/unist-util-visit-children-3.0.0.tgz", "integrity": "sha512-RgmdTfSBOg04sdPcpTSD1jzoNBjt9a80/ZCzp5cI9n1qPzLZWF9YdvWGN2zmTumP1HWhXKdUWexjy/Wy/lJ7tA==", - "dev": true, "license": "MIT", "dependencies": { "@types/unist": "^3.0.0" @@ -11015,7 +12004,6 @@ "version": "6.0.2", "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.2.tgz", "integrity": "sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==", - "dev": true, "license": "MIT", "dependencies": { "@types/unist": "^3.0.0", @@ -11040,7 +12028,6 @@ "version": "1.17.4", "resolved": "https://registry.npmjs.org/unstorage/-/unstorage-1.17.4.tgz", "integrity": "sha512-fHK0yNg38tBiJKp/Vgsq4j0JEsCmgqH58HAn707S7zGkArbZsVr/CwINoi+nh3h98BRCwKvx1K3Xg9u3VV83sw==", - "dev": true, "license": "MIT", "dependencies": { "anymatch": "^3.1.3", @@ -11137,7 +12124,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-5.0.0.tgz", "integrity": "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==", - "dev": true, "license": "MIT", "dependencies": { "readdirp": "^5.0.0" @@ -11153,7 +12139,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-5.0.0.tgz", "integrity": "sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==", - "dev": true, "license": "MIT", "engines": { "node": ">= 20.19.0" @@ -11163,11 +12148,16 @@ "url": "https://paulmillr.com/funding/" } }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "license": "MIT" + }, "node_modules/vfile": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz", "integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==", - "dev": true, "license": "MIT", "dependencies": { "@types/unist": "^3.0.0", @@ -11182,7 +12172,6 @@ "version": "5.0.3", "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-5.0.3.tgz", "integrity": "sha512-5yXvWDEgqeiYiBe1lbxYF7UMAIm/IcopxMHrMQDq3nvKcjPKIhZklUKL+AE7J7uApI4kwe2snsK+eI6UTj9EHg==", - "dev": true, "license": "MIT", "dependencies": { "@types/unist": "^3.0.0", @@ -11197,7 +12186,6 @@ "version": "4.0.3", "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.3.tgz", "integrity": "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==", - "dev": true, "license": "MIT", "dependencies": { "@types/unist": "^3.0.0", @@ -11212,7 +12200,7 @@ "version": "5.4.21", "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.21.tgz", "integrity": "sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "esbuild": "^0.21.3", @@ -11295,7 +12283,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/vitefu/-/vitefu-1.1.1.tgz", "integrity": "sha512-B/Fegf3i8zh0yFbpzZ21amWzHmuNlLlmJT6n7bu5e+pCHUKQIfXSYokrqOBGEMMe9UG2sostKQF9mml/vYaWJQ==", - "dev": true, "license": "MIT", "workspaces": [ "tests/deps/*", @@ -11377,73 +12364,16 @@ } } }, - "node_modules/w3c-xmlserializer": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz", - "integrity": "sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "xml-name-validator": "^5.0.0" - }, - "engines": { - "node": ">=18" - } - }, "node_modules/web-namespaces": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/web-namespaces/-/web-namespaces-2.0.1.tgz", "integrity": "sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==", - "dev": true, "license": "MIT", "funding": { "type": "github", "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/webidl-conversions": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-8.0.1.tgz", - "integrity": "sha512-BMhLD/Sw+GbJC21C/UgyaZX41nPt8bUTg+jWyDeg7e7YN4xOM05YPSIXceACnXVtqyEw/LMClUQMtMZ+PGGpqQ==", - "dev": true, - "license": "BSD-2-Clause", - "optional": true, - "peer": true, - "engines": { - "node": ">=20" - } - }, - "node_modules/whatwg-mimetype": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-5.0.0.tgz", - "integrity": "sha512-sXcNcHOC51uPGF0P/D4NVtrkjSU2fNsm9iog4ZvZJsL3rjoDAzXZhkm2MWt1y+PUdggKAYVoMAIYcs78wJ51Cw==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "engines": { - "node": ">=20" - } - }, - "node_modules/whatwg-url": { - "version": "16.0.1", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-16.0.1.tgz", - "integrity": "sha512-1to4zXBxmXHV3IiSSEInrreIlu02vUOvrhxJJH5vcxYTBDAx51cqZiKdyTxlecdKNSjj8EcxGBxNf6Vg+945gw==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "@exodus/bytes": "^1.11.0", - "tr46": "^6.0.0", - "webidl-conversions": "^8.0.1" - }, - "engines": { - "node": "^20.19.0 || ^22.12.0 || >=24.0.0" - } - }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -11464,7 +12394,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/which-pm-runs/-/which-pm-runs-1.1.0.tgz", "integrity": "sha512-n1brCuqClxfFfq/Rb0ICg9giSZqCS+pLtccdag6C2HyufBrh3fBOiy9nb6ggRMvWOVH5GrdJskj5iGTZNxd7SA==", - "dev": true, "license": "MIT", "engines": { "node": ">=4" @@ -11491,7 +12420,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-5.0.0.tgz", "integrity": "sha512-c9bZp7b5YtRj2wOe6dlj32MK+Bx/M/d+9VB2SHM1OtsUHR0aV0tdP6DWh/iMt0kWi1t5g1Iudu6hQRNd1A4PVA==", - "dev": true, "license": "MIT", "dependencies": { "string-width": "^7.0.0" @@ -11507,7 +12435,6 @@ "version": "9.0.2", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz", "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==", - "dev": true, "license": "MIT", "dependencies": { "ansi-styles": "^6.2.1", @@ -11543,39 +12470,17 @@ } } }, - "node_modules/xml-name-validator": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-5.0.0.tgz", - "integrity": "sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==", - "dev": true, - "license": "Apache-2.0", - "optional": true, - "peer": true, - "engines": { - "node": ">=18" - } - }, - "node_modules/xmlchars": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", - "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true - }, "node_modules/xxhash-wasm": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/xxhash-wasm/-/xxhash-wasm-1.1.0.tgz", "integrity": "sha512-147y/6YNh+tlp6nd/2pWq38i9h6mz/EuQ6njIrmW8D1BS5nCqs0P6DG+m6zTGnNz5I+uhZ0SHxBs9BsPrwcKDA==", - "dev": true, "license": "MIT" }, "node_modules/yaml": { "version": "2.8.2", "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.2.tgz", "integrity": "sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==", - "dev": true, + "devOptional": true, "license": "ISC", "bin": { "yaml": "bin.mjs" @@ -11591,7 +12496,6 @@ "version": "21.1.1", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "dev": true, "license": "ISC", "engines": { "node": ">=12" @@ -11601,7 +12505,6 @@ "version": "1.2.2", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.2.2.tgz", "integrity": "sha512-4LCcse/U2MHZ63HAJVE+v71o7yOdIe4cZ70Wpf8D/IyjDKYQLV5GD46B+hSTjJsvV5PztjvHoU580EftxjDZFQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=12.20" @@ -11614,7 +12517,6 @@ "version": "0.2.3", "resolved": "https://registry.npmjs.org/yocto-spinner/-/yocto-spinner-0.2.3.tgz", "integrity": "sha512-sqBChb33loEnkoXte1bLg45bEBsOP9N1kzQh5JZNKj/0rik4zAPTNSAVPj3uQAdc6slYJ0Ksc403G2XgxsJQFQ==", - "dev": true, "license": "MIT", "dependencies": { "yoctocolors": "^2.1.1" @@ -11630,7 +12532,6 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/yoctocolors/-/yoctocolors-2.1.2.tgz", "integrity": "sha512-CzhO+pFNo8ajLM2d2IW/R93ipy99LWjtwblvC1RsoSUMZgyLbYFr221TnSNT7GjGdYui6P459mw9JH/g/zW2ug==", - "dev": true, "license": "MIT", "engines": { "node": ">=18" @@ -11652,7 +12553,6 @@ "version": "3.25.1", "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.25.1.tgz", "integrity": "sha512-pM/SU9d3YAggzi6MtR4h7ruuQlqKtad8e9S0fmxcMi+ueAK5Korys/aWcV9LIIHTVbj01NdzxcnXSN+O74ZIVA==", - "dev": true, "license": "ISC", "peerDependencies": { "zod": "^3.25 || ^4" @@ -11662,7 +12562,6 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/zod-to-ts/-/zod-to-ts-1.2.0.tgz", "integrity": "sha512-x30XE43V+InwGpvTySRNz9kB7qFU8DlyEy7BsSTCHPH1R0QasMmHWZDCzYm6bVXtj/9NNJAZF3jW8rzFvH5OFA==", - "dev": true, "peerDependencies": { "typescript": "^4.9.4 || ^5.0.2", "zod": "^3" @@ -11672,7 +12571,6 @@ "version": "2.0.4", "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==", - "dev": true, "license": "MIT", "funding": { "type": "github", @@ -11681,10 +12579,10 @@ }, "packages/astro": { "name": "@junctionjs/astro", - "version": "0.1.5", + "version": "2.0.0", "license": "MIT", "dependencies": { - "@junctionjs/core": "^0.1.2" + "@junctionjs/core": "^0.3.0" }, "devDependencies": { "@junctionjs/debug": "*", @@ -11696,7 +12594,7 @@ "node": ">=18.0.0" }, "peerDependencies": { - "@junctionjs/debug": "^0.1.0", + "@junctionjs/debug": "^2.0.0", "astro": "^5.0.0" }, "peerDependenciesMeta": { @@ -11707,10 +12605,10 @@ }, "packages/auto-collect": { "name": "@junctionjs/auto-collect", - "version": "0.1.1", + "version": "0.1.3", "license": "MIT", "dependencies": { - "@junctionjs/core": "^0.1.2" + "@junctionjs/core": "^0.3.0" }, "devDependencies": { "tsup": "^8.0.0", @@ -11722,10 +12620,10 @@ }, "packages/client": { "name": "@junctionjs/client", - "version": "0.1.1", + "version": "0.1.3", "license": "MIT", "dependencies": { - "@junctionjs/core": "^0.1.2" + "@junctionjs/core": "^0.3.0" }, "devDependencies": { "tsup": "^8.0.0", @@ -11737,7 +12635,7 @@ }, "packages/cmp-onetrust": { "name": "@junctionjs/cmp-onetrust", - "version": "0.1.0", + "version": "2.0.0", "license": "MIT", "devDependencies": { "@junctionjs/core": "*", @@ -11748,12 +12646,12 @@ "node": ">=18.0.0" }, "peerDependencies": { - "@junctionjs/core": "^0.1.0" + "@junctionjs/core": "^0.3.0" } }, "packages/core": { "name": "@junctionjs/core", - "version": "0.1.2", + "version": "0.3.0", "license": "MIT", "dependencies": { "zod": "^3.23.0" @@ -11768,7 +12666,7 @@ }, "packages/debug": { "name": "@junctionjs/debug", - "version": "0.1.2", + "version": "2.0.0", "license": "MIT", "devDependencies": { "@junctionjs/core": "*", @@ -11779,12 +12677,12 @@ "node": ">=18.0.0" }, "peerDependencies": { - "@junctionjs/core": "^0.1.0" + "@junctionjs/core": "^0.3.0" } }, "packages/destination-amplitude": { "name": "@junctionjs/destination-amplitude", - "version": "0.1.1", + "version": "2.0.0", "license": "MIT", "devDependencies": { "@junctionjs/core": "*", @@ -11795,12 +12693,12 @@ "node": ">=18.0.0" }, "peerDependencies": { - "@junctionjs/core": "^0.1.0" + "@junctionjs/core": "^0.3.0" } }, "packages/destination-ga4": { "name": "@junctionjs/destination-ga4", - "version": "0.1.1", + "version": "2.0.0", "license": "MIT", "devDependencies": { "@junctionjs/core": "*", @@ -11811,12 +12709,12 @@ "node": ">=18.0.0" }, "peerDependencies": { - "@junctionjs/core": "^0.1.0" + "@junctionjs/core": "^0.3.0" } }, "packages/destination-http": { "name": "@junctionjs/destination-http", - "version": "0.1.1", + "version": "2.0.0", "license": "MIT", "devDependencies": { "@junctionjs/core": "*", @@ -11827,12 +12725,12 @@ "node": ">=18.0.0" }, "peerDependencies": { - "@junctionjs/core": "^0.1.0" + "@junctionjs/core": "^0.3.0" } }, "packages/destination-meta": { "name": "@junctionjs/destination-meta", - "version": "0.1.1", + "version": "2.0.0", "license": "MIT", "devDependencies": { "@junctionjs/core": "*", @@ -11843,12 +12741,12 @@ "node": ">=18.0.0" }, "peerDependencies": { - "@junctionjs/core": "^0.1.0" + "@junctionjs/core": "^0.3.0" } }, "packages/destination-plausible": { "name": "@junctionjs/destination-plausible", - "version": "0.1.1", + "version": "2.0.0", "license": "MIT", "devDependencies": { "@junctionjs/core": "*", @@ -11859,15 +12757,15 @@ "node": ">=18.0.0" }, "peerDependencies": { - "@junctionjs/core": "^0.1.0" + "@junctionjs/core": "^0.3.0" } }, "packages/gateway": { "name": "@junctionjs/gateway", - "version": "0.1.1", + "version": "0.1.3", "license": "MIT", "dependencies": { - "@junctionjs/core": "^0.1.2" + "@junctionjs/core": "^0.3.0" }, "devDependencies": { "tsup": "^8.0.0", @@ -11879,9 +12777,12 @@ }, "packages/next": { "name": "@junctionjs/next", - "version": "0.1.1", + "version": "2.0.0", "license": "MIT", "devDependencies": { + "@junctionjs/client": "*", + "@junctionjs/core": "*", + "@junctionjs/debug": "*", "@types/react": "^19.0.0", "next": "^15.1.0", "react": "^19.0.0", @@ -11889,9 +12790,9 @@ "typescript": "^5.5.0" }, "peerDependencies": { - "@junctionjs/client": "^0.1.0", - "@junctionjs/core": "^0.1.0", - "@junctionjs/debug": "^0.1.0", + "@junctionjs/client": "^0.1.3", + "@junctionjs/core": "^0.3.0", + "@junctionjs/debug": "^2.0.0", "next": ">=14.0.0", "react": ">=18.0.0" },