{"version":3,"file":"index.mjs","names":[],"sources":["../../src/endpoint.ts","../../src/gating.ts","../../src/sanitize.ts","../../src/user-config.ts","../../src/spawn.ts"],"sourcesContent":["/**\n * Production endpoint pinned to the deployed Prisma Compute backend.\n * Compiled as a build-time constant; not user-configurable.\n */\nexport const TELEMETRY_BACKEND_URL = 'https://cmpbfbsdp09hr3jf7pojjs5qs.ewr.prisma.build';\n\n/**\n * Path within the backend that accepts telemetry POSTs.\n */\nexport const TELEMETRY_ENDPOINT_PATH = '/events';\n\n/**\n * Resolve the full POST URL the sender targets. The\n * `PRISMA_NEXT_TELEMETRY_ENDPOINT` env var is an integration-testing\n * affordance only — it lets the test suite spin up a mock HTTP server\n * on an ephemeral port and point the spawned sender at it. The override\n * is intentionally undocumented in user-facing material.\n *\n * Fail-open: a malformed override (typo in a dev shell, bad CI config)\n * silently falls back to the production backend rather than throwing,\n * matching the telemetry layer's broader silent-on-failure contract.\n */\nexport function resolveTelemetryEndpoint(\n  env: Readonly<Record<string, string | undefined>> = process.env,\n): string {\n  const override = env['PRISMA_NEXT_TELEMETRY_ENDPOINT'];\n  const base = override !== undefined && override.length > 0 ? override : TELEMETRY_BACKEND_URL;\n  try {\n    return new URL(TELEMETRY_ENDPOINT_PATH, base).toString();\n  } catch {\n    return new URL(TELEMETRY_ENDPOINT_PATH, TELEMETRY_BACKEND_URL).toString();\n  }\n}\n","import type { UserConfig } from './user-config';\n\n/**\n * Why telemetry was disabled. Useful for debug-mode logging in the\n * parent; never surfaces to users.\n */\nexport type GatingDisabledReason = 'env-override' | 'stored-opt-out';\n\nexport type GatingResolution =\n  | { readonly enabled: true }\n  | { readonly enabled: false; readonly reason: GatingDisabledReason };\n\nexport interface GatingInputs {\n  /**\n   * Environment-variable lookups the resolver consults. Tests pass a\n   * literal record; production passes `process.env`. The two opt-out\n   * signals are `PRISMA_NEXT_DISABLE_TELEMETRY` (Prisma-specific) and\n   * `DO_NOT_TRACK` (community convention).\n   */\n  readonly env: Readonly<Record<string, string | undefined>>;\n  /** Result of `readUserConfig()` — file-missing tolerated as `{}`. */\n  readonly config: UserConfig;\n}\n\n/**\n * A `PRISMA_NEXT_DISABLE_TELEMETRY` value counts as an opt-out only if\n * it parses as a truthy string. The set-but-falsy spellings (`''`,\n * `'0'`, `'false'`) are intentionally treated as not-set so a parent\n * shell that exports the variable to a benign value doesn't accidentally\n * disable telemetry for child processes.\n */\nfunction isTruthyOptOut(raw: string | undefined): boolean {\n  if (raw === undefined) return false;\n  const normalised = raw.trim().toLowerCase();\n  if (normalised === '') return false;\n  if (normalised === '0') return false;\n  if (normalised === 'false') return false;\n  return true;\n}\n\n/**\n * Pure-function resolution of the gating decision. Same input → same\n * output; no I/O. The caller is responsible for reading the env and the\n * user config.\n *\n * Decision order:\n *   1. Env-var override (`PRISMA_NEXT_DISABLE_TELEMETRY` truthy, or\n *      `DO_NOT_TRACK=1`) → disabled. The env check runs first, so an\n *      opt-out env var wins over any stored or unset preference.\n *   2. Stored `enableTelemetry === false` → disabled (`stored-opt-out`).\n *   3. Stored `enableTelemetry === true` → enabled.\n *   4. Stored `enableTelemetry === undefined` (file missing, or field\n *      not set) → ENABLED. This is the opt-out default: absence of an\n *      explicit choice means telemetry is on. This is the load-bearing,\n *      counter-intuitive branch — do not \"fix\" it to default-off.\n *\n * Telemetry is disabled only when an env override is active or\n * `enableTelemetry` is explicitly `false`.\n */\nexport function resolveGating(inputs: GatingInputs): GatingResolution {\n  if (\n    isTruthyOptOut(inputs.env['PRISMA_NEXT_DISABLE_TELEMETRY']) ||\n    inputs.env['DO_NOT_TRACK'] === '1'\n  ) {\n    return { enabled: false, reason: 'env-override' };\n  }\n  if (inputs.config.enableTelemetry === false) {\n    return { enabled: false, reason: 'stored-opt-out' };\n  }\n  return { enabled: true };\n}\n","export interface CommanderOptionShape {\n  /** Commander's option attribute name, e.g. `dryRun` for `--dry-run`. */\n  readonly attributeName: string;\n  /** Commander's long, user-facing flag spelling, e.g. `--dry-run` or `--no-install`. */\n  readonly longName: string | null;\n  /** Commander's value source for this option. Only `cli` is user-supplied. */\n  readonly source: string | null;\n}\n\n/**\n * Input shape: a thin projection of commander's parsed-result surface.\n * The parent extracts the command path, positional args, and per-option\n * metadata from the leaf command. The sanitiser never consumes raw\n * argv, never reads `process.argv`, and never sees flag values.\n */\nexport interface CommanderResultShape {\n  /**\n   * The full command path from the root program to the leaf, including\n   * the root program name as the first element (the sanitiser drops it).\n   * Example: `['prisma-next', 'migration', 'new']`.\n   */\n  readonly commandPath: readonly string[];\n  /**\n   * Positional arguments commander parsed for the leaf command.\n   * **Intentionally never read.** Accepted so the call site doesn't have\n   * to think about whether to pass it; the sanitiser's contract is that\n   * positionals never leave the parent process.\n   */\n  readonly positionalArgs: readonly string[];\n  /**\n   * Per-option Commander metadata. The sanitiser emits only options whose\n   * source is `cli`, and uses `longName` so telemetry sees user-facing\n   * names (`dry-run`, `connection-string`, `no-install`) rather than\n   * Commander's internal camelCase attribute names or defaulted options.\n   */\n  readonly options: readonly CommanderOptionShape[];\n}\n\n/**\n * Output shape: the sanitised projection that flows into the telemetry\n * payload. Two fields only — command name (space-delimited subcommand\n * path) and flag names (in commander's option declaration order).\n */\nexport interface SanitisedCommand {\n  readonly command: string;\n  readonly flags: readonly string[];\n}\n\nfunction flagNameFromLongName(longName: string | null): string | null {\n  if (longName === null || !longName.startsWith('--')) return null;\n  const withoutPrefix = longName.slice(2);\n  return withoutPrefix.length > 0 ? withoutPrefix : null;\n}\n\n/**\n * Project commander's parsed result into the wire-shape command and\n * flag-name list. Pure; the only allowed inputs are the fields of\n * `CommanderResultShape`.\n *\n * Sanitiser contract — no flag values, no positionals, no raw argv:\n *   - Drop the root program name (`commandPath[0]`); the wire ships\n *     `migration new`, not `prisma-next migration new`.\n *   - Emit only options whose Commander source is `cli`.\n *   - Emit the long user-facing flag spelling without the `--` prefix;\n *     never emit Commander's camelCase attribute names.\n *   - `positionalArgs` is accepted but never consumed; the field exists\n *     in the input type to make it obvious at the call site that\n *     positionals were deliberately excluded.\n */\nexport function sanitizeCommanderResult(input: CommanderResultShape): SanitisedCommand {\n  const command = input.commandPath.slice(1).join(' ');\n  const flags = input.options.flatMap((option) => {\n    if (option.source !== 'cli') return [];\n    const flagName = flagNameFromLongName(option.longName);\n    return flagName === null ? [] : [flagName];\n  });\n  return { command, flags };\n}\n","import { randomUUID } from 'node:crypto';\nimport { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from 'node:fs';\nimport { homedir } from 'node:os';\nimport { dirname, join } from 'pathe';\n\n/**\n * The user-level config file. Persists the telemetry flag and the\n * installation UUID. Under the opt-out model the flag stays `undefined`\n * until the user makes an explicit choice (default-on first run mints\n * only the id via {@link ensureInstallationId}), and an env-var opt-out\n * never mutates disk. Once the id exists it survives any\n * on → off → on cycle, keeping the same UUID (correct for MAU continuity).\n *\n * Readers tolerate unknown fields for forward compat; writers merge\n * partials into the existing object so unknown fields are preserved.\n */\nexport interface UserConfig {\n  readonly enableTelemetry?: boolean;\n  readonly installationId?: string;\n  readonly [key: string]: unknown;\n}\n\nconst APP_DIR = 'prisma-next';\nconst FILE_NAME = 'config.json';\n\n/**\n * Resolves the user-level config directory:\n *   - Windows: `%APPDATA%\\prisma-next\\` (fallback: `%USERPROFILE%\\AppData\\Roaming\\prisma-next\\`).\n *   - Unix (incl. macOS): `$XDG_CONFIG_HOME/prisma-next/` if set, else\n *     `$HOME/.config/prisma-next/` per the XDG Base Directory Specification.\n *\n * The spec deliberately picks XDG over the macOS-native\n * `~/Library/Preferences/` convention so the path resolution is\n * test-overridable via `XDG_CONFIG_HOME` and matches the documented\n * behaviour on all *nix platforms. We intentionally do not use\n * `env-paths`: its macOS choice of `~/Library/Preferences` is for\n * OS-managed plist preferences, not arbitrary JSON files. Apple documents\n * that apps access that directory through system APIs such as\n * `NSUserDefaults`, while cross-platform CLI and developer tools conventionally\n * use `~/.config` on macOS too:\n * https://developer.apple.com/library/archive/documentation/FileManagement/Conceptual/FileSystemProgrammingGuide/MacOSXDirectories/MacOSXDirectories.html\n */\nfunction configDir(): string {\n  if (process.platform === 'win32') {\n    const appData = process.env['APPDATA'];\n    if (appData !== undefined && appData.length > 0) {\n      return join(appData, APP_DIR);\n    }\n    return join(homedir(), 'AppData', 'Roaming', APP_DIR);\n  }\n  const xdg = process.env['XDG_CONFIG_HOME'];\n  if (xdg !== undefined && xdg.length > 0) {\n    return join(xdg, APP_DIR);\n  }\n  return join(homedir(), '.config', APP_DIR);\n}\n\n/**\n * Path to the user-level config file. Resolved per call so test\n * harnesses can mutate `$XDG_CONFIG_HOME` between cases.\n */\nexport function userConfigPath(): string {\n  return join(configDir(), FILE_NAME);\n}\n\n/**\n * Reads the user-level config. File-missing, unreadable, or malformed →\n * `{}` (the absence of consent is the same answer in every error mode).\n * Unknown fields from a future client are passed through verbatim.\n */\nexport function readUserConfig(): UserConfig {\n  const path = userConfigPath();\n  if (!existsSync(path)) return {};\n  try {\n    const raw = readFileSync(path, 'utf-8');\n    const parsed: unknown = JSON.parse(raw);\n    if (parsed !== null && typeof parsed === 'object' && !Array.isArray(parsed)) {\n      return parsed as UserConfig;\n    }\n    return {};\n  } catch {\n    return {};\n  }\n}\n\n/**\n * Merges `partial` into the current config and writes the result\n * atomically (temp file + rename) so a crash mid-write never leaves a\n * half-baked file readable on disk. Unknown fields already on disk are\n * preserved.\n *\n * When `partial.enableTelemetry === true` and no `installationId` is\n * stored yet, generates a v4 random UUID and persists both fields in\n * the same write. An existing `installationId` is never rotated. This is\n * the *explicit-consent* mint path: a `false` answer\n * (`writeUserConfig({ enableTelemetry: false })`) writes no id, and a bare\n * `writeUserConfig({ installationId })` mints nothing extra. The default-on\n * first-send path mints its id separately via {@link ensureInstallationId},\n * which records no consent answer.\n */\nexport function writeUserConfig(partial: Partial<UserConfig>): void {\n  const current = readUserConfig();\n  const merged: Record<string, unknown> = { ...current, ...partial };\n  if (partial.enableTelemetry === true && merged['installationId'] === undefined) {\n    merged['installationId'] = randomUUID();\n  }\n  const path = userConfigPath();\n  const dir = dirname(path);\n  if (!existsSync(dir)) {\n    mkdirSync(dir, { recursive: true });\n  }\n  const tmpPath = `${path}.${process.pid}.tmp`;\n  writeFileSync(tmpPath, `${JSON.stringify(merged, null, 2)}\\n`, 'utf-8');\n  renameSync(tmpPath, path);\n}\n\n/**\n * Returns the stored `installationId`, minting and persisting a fresh v4\n * UUID when none exists yet. Crucially, this persists *only* the id —\n * `enableTelemetry` is left untouched (stays `undefined` on a default-on\n * first run), so the interactive `init` consent prompt is not wrongly\n * suppressed and no explicit consent the user never gave is recorded.\n *\n * Used by the default-on first-run fire path: the gate has already\n * resolved enabled, so this only ever runs when telemetry is on.\n */\nexport function ensureInstallationId(): string {\n  const existing = readUserConfig().installationId;\n  if (typeof existing === 'string' && existing.length > 0) {\n    return existing;\n  }\n  const installationId = randomUUID();\n  writeUserConfig({ installationId });\n  return installationId;\n}\n","import { fork } from 'node:child_process';\nimport { fileURLToPath } from 'node:url';\nimport { ifDefined } from '@prisma-next/utils/defined';\nimport { resolveTelemetryEndpoint } from './endpoint';\nimport { resolveGating } from './gating';\nimport type { ParentToSenderPayload } from './payload';\nimport { type CommanderResultShape, sanitizeCommanderResult } from './sanitize';\nimport { readUserConfig, type UserConfig } from './user-config';\n\n/**\n * Inputs the CLI entry point hands the telemetry layer at command\n * start. The CLI is responsible for stitching commander's result and\n * the project root together; the telemetry module does no I/O of its\n * own except for the user-config read (skipped when `userConfig` is\n * provided). `extensions` is deliberately absent: the detached child\n * loads `prisma-next.config.*` via c12 itself and derives the\n * extension-pack ids from the validated config — see the rationale\n * on `ParentToSenderPayload` for why c12 lives in the child rather\n * than on the parent's hot path.\n *\n * `databaseTarget` is an optional parent-side override forwarded to\n * the child. Set by `fireTelemetryAfterInitConsent` (where the\n * config file does not yet exist on disk); left unset by the\n * preAction-hook path so the child's c12 load supplies the value.\n */\nexport interface RunTelemetryInputs {\n  /** Sanitised commander snapshot — see `CommanderResultShape`. */\n  readonly command: CommanderResultShape;\n  /** This CLI's own version (from its `package.json`). */\n  readonly version: string;\n  /** Absolute path of the project root (typically `process.cwd()`). */\n  readonly projectRoot: string;\n  /**\n   * Optional parent-side override for the c12-derived database target,\n   * forwarded verbatim to the child sender. Wins over the child's\n   * c12-derived value when present; `undefined` means \"no override\".\n   */\n  readonly databaseTarget?: string;\n  /**\n   * Path to the sender entry compiled into this package's `dist/`.\n   * Resolved by the caller because the compiled sender lives at\n   * `<package>/dist/sender.mjs` and only the consumer knows its own\n   * `import.meta.url`.\n   */\n  readonly senderPath: string;\n  /**\n   * `isCI()` result from the consumer. Telemetry is suppressed when\n   * `true` regardless of the stored consent answer — CI environments\n   * never emit (matches the colour-output convention's CI suppression).\n   */\n  readonly isCI: boolean;\n  /** Process env to read for opt-out signals. Defaults to `process.env`. */\n  readonly env?: Readonly<Record<string, string | undefined>>;\n  /** Cached user config when the caller already read it to resolve gates before other work. */\n  readonly userConfig?: UserConfig;\n}\n\n/**\n * Best-effort telemetry spawn at command start. Returns synchronously —\n * the fork runs in the background and never blocks the parent. Every\n * failure mode is swallowed; the parent's stdout/stderr is untouched in\n * normal operation, the only escape valve being\n * `PRISMA_NEXT_DEBUG=1` which routes diagnostics to stderr.\n *\n * Returns the spawn outcome so debug-mode logging and the test-harness\n * probe (which verifies test runs short-circuit the fork) can inspect\n * the decision without scraping stderr.\n */\nexport type TelemetryRunOutcome =\n  | { readonly spawned: true }\n  | { readonly spawned: false; readonly reason: 'gated-off' | 'ci' | 'fork-failed' };\n\nexport function runTelemetry(inputs: RunTelemetryInputs): TelemetryRunOutcome {\n  const env = inputs.env ?? process.env;\n\n  if (inputs.isCI) {\n    return { spawned: false, reason: 'ci' };\n  }\n\n  const config = inputs.userConfig ?? readUserConfig();\n  const gating = resolveGating({ env, config });\n  if (!gating.enabled) {\n    return { spawned: false, reason: 'gated-off' };\n  }\n\n  const sanitised = sanitizeCommanderResult(inputs.command);\n  // Gating resolved enabled, so installationId should be set: the parent\n  // fire path mints it before calling runTelemetry on the default-on\n  // first run, and the init consent flow mints it on explicit opt-in.\n  // Defence-in-depth: a missing id here means a stale/corrupt config, so\n  // skip rather than send a junk event.\n  if (typeof config.installationId !== 'string' || config.installationId.length === 0) {\n    return { spawned: false, reason: 'gated-off' };\n  }\n\n  const payload: ParentToSenderPayload = {\n    installationId: config.installationId,\n    version: inputs.version,\n    command: sanitised.command,\n    flags: sanitised.flags,\n    projectRoot: inputs.projectRoot,\n    endpoint: resolveTelemetryEndpoint(env),\n    ...ifDefined('databaseTarget', inputs.databaseTarget),\n  };\n\n  try {\n    const child = fork(inputs.senderPath, [], {\n      detached: true,\n      stdio: ['pipe', 'ignore', 'ignore', 'ipc'],\n    });\n    child.send(payload, (err) => {\n      if (err !== null && process.env['PRISMA_NEXT_DEBUG'] === '1') {\n        process.stderr.write(`[cli-telemetry] parent send error: ${String(err)}\\n`);\n      }\n    });\n    child.disconnect();\n    child.unref();\n    return { spawned: true };\n  } catch (err) {\n    if (process.env['PRISMA_NEXT_DEBUG'] === '1') {\n      process.stderr.write(`[cli-telemetry] parent fork failed: ${String(err)}\\n`);\n    }\n    return { spawned: false, reason: 'fork-failed' };\n  }\n}\n\n/**\n * Resolve the path to the compiled sender entry relative to a consumer\n * that has captured its own `import.meta.url`. The CLI's\n * `tsdown`-emitted entry sits at `<package>/dist/sender.mjs`; the\n * consumer asks `senderModuleUrl()` and forwards the result to\n * `runTelemetry({ senderPath })`.\n */\nexport function senderModuleUrl(importMetaUrl: string): string {\n  return fileURLToPath(new URL('./sender.mjs', importMetaUrl));\n}\n"],"mappings":";;;;;;;;;;;;;AAIA,MAAa,wBAAwB;;;;AAKrC,MAAa,0BAA0B;;;;;;;;;;;;AAavC,SAAgB,yBACd,MAAoD,QAAQ,KACpD;CACR,MAAM,WAAW,IAAI;CACrB,MAAM,OAAO,aAAa,KAAA,KAAa,SAAS,SAAS,IAAI,WAAW;CACxE,IAAI;EACF,OAAO,IAAI,IAAI,yBAAyB,IAAI,CAAC,CAAC,SAAS;CACzD,QAAQ;EACN,OAAO,IAAI,IAAI,yBAAyB,qBAAqB,CAAC,CAAC,SAAS;CAC1E;AACF;;;;;;;;;;ACDA,SAAS,eAAe,KAAkC;CACxD,IAAI,QAAQ,KAAA,GAAW,OAAO;CAC9B,MAAM,aAAa,IAAI,KAAK,CAAC,CAAC,YAAY;CAC1C,IAAI,eAAe,IAAI,OAAO;CAC9B,IAAI,eAAe,KAAK,OAAO;CAC/B,IAAI,eAAe,SAAS,OAAO;CACnC,OAAO;AACT;;;;;;;;;;;;;;;;;;;;AAqBA,SAAgB,cAAc,QAAwC;CACpE,IACE,eAAe,OAAO,IAAI,gCAAgC,KAC1D,OAAO,IAAI,oBAAoB,KAE/B,OAAO;EAAE,SAAS;EAAO,QAAQ;CAAe;CAElD,IAAI,OAAO,OAAO,oBAAoB,OACpC,OAAO;EAAE,SAAS;EAAO,QAAQ;CAAiB;CAEpD,OAAO,EAAE,SAAS,KAAK;AACzB;;;ACtBA,SAAS,qBAAqB,UAAwC;CACpE,IAAI,aAAa,QAAQ,CAAC,SAAS,WAAW,IAAI,GAAG,OAAO;CAC5D,MAAM,gBAAgB,SAAS,MAAM,CAAC;CACtC,OAAO,cAAc,SAAS,IAAI,gBAAgB;AACpD;;;;;;;;;;;;;;;;AAiBA,SAAgB,wBAAwB,OAA+C;CAOrF,OAAO;EAAE,SANO,MAAM,YAAY,MAAM,CAAC,CAAC,CAAC,KAAK,GAMjC;EAAG,OALJ,MAAM,QAAQ,SAAS,WAAW;GAC9C,IAAI,OAAO,WAAW,OAAO,OAAO,CAAC;GACrC,MAAM,WAAW,qBAAqB,OAAO,QAAQ;GACrD,OAAO,aAAa,OAAO,CAAC,IAAI,CAAC,QAAQ;EAC3C,CACsB;CAAE;AAC1B;;;ACvDA,MAAM,UAAU;AAChB,MAAM,YAAY;;;;;;;;;;;;;;;;;;AAmBlB,SAAS,YAAoB;CAC3B,IAAI,QAAQ,aAAa,SAAS;EAChC,MAAM,UAAU,QAAQ,IAAI;EAC5B,IAAI,YAAY,KAAA,KAAa,QAAQ,SAAS,GAC5C,OAAO,KAAK,SAAS,OAAO;EAE9B,OAAO,KAAK,QAAQ,GAAG,WAAW,WAAW,OAAO;CACtD;CACA,MAAM,MAAM,QAAQ,IAAI;CACxB,IAAI,QAAQ,KAAA,KAAa,IAAI,SAAS,GACpC,OAAO,KAAK,KAAK,OAAO;CAE1B,OAAO,KAAK,QAAQ,GAAG,WAAW,OAAO;AAC3C;;;;;AAMA,SAAgB,iBAAyB;CACvC,OAAO,KAAK,UAAU,GAAG,SAAS;AACpC;;;;;;AAOA,SAAgB,iBAA6B;CAC3C,MAAM,OAAO,eAAe;CAC5B,IAAI,CAAC,WAAW,IAAI,GAAG,OAAO,CAAC;CAC/B,IAAI;EACF,MAAM,MAAM,aAAa,MAAM,OAAO;EACtC,MAAM,SAAkB,KAAK,MAAM,GAAG;EACtC,IAAI,WAAW,QAAQ,OAAO,WAAW,YAAY,CAAC,MAAM,QAAQ,MAAM,GACxE,OAAO;EAET,OAAO,CAAC;CACV,QAAQ;EACN,OAAO,CAAC;CACV;AACF;;;;;;;;;;;;;;;;AAiBA,SAAgB,gBAAgB,SAAoC;CAElE,MAAM,SAAkC;EAAE,GAD1B,eACmC;EAAG,GAAG;CAAQ;CACjE,IAAI,QAAQ,oBAAoB,QAAQ,OAAO,sBAAsB,KAAA,GACnE,OAAO,oBAAoB,WAAW;CAExC,MAAM,OAAO,eAAe;CAC5B,MAAM,MAAM,QAAQ,IAAI;CACxB,IAAI,CAAC,WAAW,GAAG,GACjB,UAAU,KAAK,EAAE,WAAW,KAAK,CAAC;CAEpC,MAAM,UAAU,GAAG,KAAK,GAAG,QAAQ,IAAI;CACvC,cAAc,SAAS,GAAG,KAAK,UAAU,QAAQ,MAAM,CAAC,EAAE,KAAK,OAAO;CACtE,WAAW,SAAS,IAAI;AAC1B;;;;;;;;;;;AAYA,SAAgB,uBAA+B;CAC7C,MAAM,WAAW,eAAe,CAAC,CAAC;CAClC,IAAI,OAAO,aAAa,YAAY,SAAS,SAAS,GACpD,OAAO;CAET,MAAM,iBAAiB,WAAW;CAClC,gBAAgB,EAAE,eAAe,CAAC;CAClC,OAAO;AACT;;;AC9DA,SAAgB,aAAa,QAAiD;CAC5E,MAAM,MAAM,OAAO,OAAO,QAAQ;CAElC,IAAI,OAAO,MACT,OAAO;EAAE,SAAS;EAAO,QAAQ;CAAK;CAGxC,MAAM,SAAS,OAAO,cAAc,eAAe;CAEnD,IAAI,CADW,cAAc;EAAE;EAAK;CAAO,CACjC,CAAC,CAAC,SACV,OAAO;EAAE,SAAS;EAAO,QAAQ;CAAY;CAG/C,MAAM,YAAY,wBAAwB,OAAO,OAAO;CAMxD,IAAI,OAAO,OAAO,mBAAmB,YAAY,OAAO,eAAe,WAAW,GAChF,OAAO;EAAE,SAAS;EAAO,QAAQ;CAAY;CAG/C,MAAM,UAAiC;EACrC,gBAAgB,OAAO;EACvB,SAAS,OAAO;EAChB,SAAS,UAAU;EACnB,OAAO,UAAU;EACjB,aAAa,OAAO;EACpB,UAAU,yBAAyB,GAAG;EACtC,GAAG,UAAU,kBAAkB,OAAO,cAAc;CACtD;CAEA,IAAI;EACF,MAAM,QAAQ,KAAK,OAAO,YAAY,CAAC,GAAG;GACxC,UAAU;GACV,OAAO;IAAC;IAAQ;IAAU;IAAU;GAAK;EAC3C,CAAC;EACD,MAAM,KAAK,UAAU,QAAQ;GAC3B,IAAI,QAAQ,QAAQ,QAAQ,IAAI,yBAAyB,KACvD,QAAQ,OAAO,MAAM,sCAAsC,OAAO,GAAG,EAAE,GAAG;EAE9E,CAAC;EACD,MAAM,WAAW;EACjB,MAAM,MAAM;EACZ,OAAO,EAAE,SAAS,KAAK;CACzB,SAAS,KAAK;EACZ,IAAI,QAAQ,IAAI,yBAAyB,KACvC,QAAQ,OAAO,MAAM,uCAAuC,OAAO,GAAG,EAAE,GAAG;EAE7E,OAAO;GAAE,SAAS;GAAO,QAAQ;EAAc;CACjD;AACF;;;;;;;;AASA,SAAgB,gBAAgB,eAA+B;CAC7D,OAAO,cAAc,IAAI,IAAI,gBAAgB,aAAa,CAAC;AAC7D"}