@emailcheck/email-validator-js 5.0.0-beta.2 → 5.1.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +40 -4
- package/dist/cli/index.js +34 -2
- package/dist/cli/index.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.esm.js +36 -3
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +36 -2
- package/dist/index.js.map +1 -1
- package/dist/sender-strategy.d.ts +26 -0
- package/dist/serverless/adapters/aws-lambda.cjs.js +5 -5
- package/dist/serverless/adapters/aws-lambda.cjs.js.map +1 -1
- package/dist/serverless/adapters/aws-lambda.esm.js +5 -5
- package/dist/serverless/adapters/aws-lambda.esm.js.map +1 -1
- package/dist/serverless/adapters/azure.cjs.js +5 -5
- package/dist/serverless/adapters/azure.cjs.js.map +1 -1
- package/dist/serverless/adapters/azure.esm.js +5 -5
- package/dist/serverless/adapters/azure.esm.js.map +1 -1
- package/dist/serverless/adapters/cloudflare.cjs.js +5 -5
- package/dist/serverless/adapters/cloudflare.cjs.js.map +1 -1
- package/dist/serverless/adapters/cloudflare.esm.js +5 -5
- package/dist/serverless/adapters/cloudflare.esm.js.map +1 -1
- package/dist/serverless/adapters/gcp.cjs.js +5 -5
- package/dist/serverless/adapters/gcp.cjs.js.map +1 -1
- package/dist/serverless/adapters/gcp.esm.js +5 -5
- package/dist/serverless/adapters/gcp.esm.js.map +1 -1
- package/dist/serverless/adapters/netlify.cjs.js +5 -5
- package/dist/serverless/adapters/netlify.cjs.js.map +1 -1
- package/dist/serverless/adapters/netlify.esm.js +5 -5
- package/dist/serverless/adapters/netlify.esm.js.map +1 -1
- package/dist/serverless/adapters/vercel.cjs.js +5 -5
- package/dist/serverless/adapters/vercel.cjs.js.map +1 -1
- package/dist/serverless/adapters/vercel.esm.js +5 -5
- package/dist/serverless/adapters/vercel.esm.js.map +1 -1
- package/dist/serverless/index.cjs.js +5 -5
- package/dist/serverless/index.cjs.js.map +1 -1
- package/dist/serverless/index.esm.js +5 -5
- package/dist/serverless/index.esm.js.map +1 -1
- package/dist/serverless/verifier.cjs.js +5 -5
- package/dist/serverless/verifier.cjs.js.map +1 -1
- package/dist/serverless/verifier.esm.js +5 -5
- package/dist/serverless/verifier.esm.js.map +1 -1
- package/dist/serverless/verifier.min.js +1 -1
- package/dist/types.d.ts +72 -0
- package/package.json +3 -3
package/dist/cli/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../src/cli/parse-args.ts","../../src/adapters/lru-adapter.ts","../../src/types.ts","../../src/cache.ts","../../src/domain-suggester.ts","../../src/email-validator.ts","../../src/is-disposable-email.ts","../../src/is-free-email.ts","../../src/mx-resolver.ts","../../src/name-detector.ts","../../src/smtp-verifier.ts","../../src/transcript.ts","../../src/whois-parser.ts","../../src/whois.ts","../../src/verify-email.ts","../../src/cli/format.ts","../../src/cli/run.ts","../../src/cli/index.ts"],"sourcesContent":["/**\n * Minimal flag parser for the `email-validate` CLI.\n *\n * Accepts `argv` (everything after `node bin / email-validate`) and produces a\n * `ParsedArgs` shape, or throws a `CliArgError` with `messages[]` and an\n * `exitCode` for the caller to propagate.\n *\n * Why hand-rolled: the CLI surface is small (~15 flags), and pulling in\n * `commander` / `yargs` would balloon the published bundle for every consumer\n * regardless of whether they ever run the CLI. The trade-off is no\n * sub-command tree — just one flat command — which fits the tool fine.\n */\n\nexport interface ParsedArgs {\n /** Email address to validate (positional). */\n email: string;\n // SMTP / MX flags\n verifyMx: boolean;\n verifySmtp: boolean;\n ports?: number[];\n smtpPort?: number;\n hostname?: string;\n timeoutMs?: number;\n // Disposable / free / suggestion flags\n checkDisposable: boolean;\n checkFree: boolean;\n suggestDomain: boolean;\n detectName: boolean;\n // WHOIS flags\n checkDomainAge: boolean;\n checkDomainRegistration: boolean;\n whoisTimeoutMs?: number;\n // Output flags\n format: 'text' | 'json' | 'pretty';\n quiet: boolean;\n debug: boolean;\n captureTranscript: boolean;\n logDir: string | null; // null => no file, default './logs'\n}\n\nexport interface ParsedHelp {\n kind: 'help';\n}\n\nexport interface ParsedVersion {\n kind: 'version';\n}\n\nexport interface CliArgError {\n kind: 'error';\n messages: string[];\n exitCode: number;\n}\n\nexport type ParseResult = ({ kind: 'args' } & ParsedArgs) | ParsedHelp | ParsedVersion | CliArgError;\n\nconst HELP_TEXT = `email-validate <email> [options]\n\nRun the full email-validator-js pipeline against one address. By default,\nruns format / MX / SMTP probe / disposable / free-provider / typo-suggest /\nname-detection, captures a structured transcript, prints it to stdout, and\nwrites the JSON result to ./logs/.\n\nWHOIS lookups are off by default (they're slow); enable with --whois-age or\n--whois-registration.\n\nOptions:\n --mx, --no-mx Resolve MX records (default: on)\n --smtp, --no-smtp Run live SMTP probe (default: on)\n --disposable, --no-disposable Check disposable-email list (default: on)\n --free, --no-free Check free-provider list (default: on)\n --suggest-domain, --no-suggest-domain\n Suggest a corrected domain on typos (default: on)\n --detect-name, --no-detect-name\n Extract first/last name from local (default: on)\n --whois-age Look up domain creation date (default: off)\n --whois-registration Look up domain registration status (default: off)\n\n --port <n> Force a single SMTP port (e.g. 587)\n --ports <n,n,...> Comma-separated SMTP port walk (default: 25,587,465)\n --hostname <name> EHLO/HELO identity (default: localhost)\n --timeout <ms> SMTP timeout per port (default: 5000)\n --whois-timeout <ms> WHOIS query timeout (default: 5000)\n\n --format <text|json|pretty> Stdout format (default: pretty)\n --no-transcript Skip the per-step transcript capture\n --log-dir <path> Directory to write the JSON result (default: ./logs)\n --no-log-file Skip writing the result file\n --quiet Print only the final verdict to stdout\n --debug Verbose console logging during the run\n\n -h, --help Show this help\n -v, --version Print version\n\nExamples:\n # Quick interactive check — full pipeline, pretty output, log saved to ./logs\n email-validate alice@example.com\n\n # Skip the SMTP probe (fast, just format / MX / lists / typos)\n email-validate alice@example.com --no-smtp\n\n # Add WHOIS age + registration for full domain reputation picture\n email-validate alice@example.com --whois-age --whois-registration\n\n # Pipe JSON to jq for tooling\n email-validate alice@example.com --format json --quiet --no-log-file | jq\n\n # Silent verdict for shell scripting (exit code 0=ok, 1=undeliverable/invalid)\n email-validate alice@example.com --quiet --no-log-file\n if email-validate \"$EMAIL\" --quiet --no-log-file > /dev/null; then …\n\n # Pin the SMTP probe to one port + custom HELO + custom log path\n email-validate alice@example.com --port 587 --hostname mta.acme.com --log-dir /var/log/email\n\n # Debug a specific delivery quirk (full transcript + console logs)\n email-validate alice@example.com --debug --format pretty\n`;\n\nconst TRUE_FLAGS = new Set([\n 'mx',\n 'smtp',\n 'disposable',\n 'free',\n 'suggest-domain',\n 'detect-name',\n 'whois-age',\n 'whois-registration',\n 'transcript',\n 'log-file',\n 'quiet',\n 'debug',\n]);\n\nconst VALUE_FLAGS = new Set(['port', 'ports', 'hostname', 'timeout', 'whois-timeout', 'format', 'log-dir']);\n\n/** Strip a leading `no-` prefix from a flag name; return the stripped name + the polarity. */\nfunction splitNo(flag: string): { name: string; positive: boolean } {\n if (flag.startsWith('no-')) return { name: flag.slice(3), positive: false };\n return { name: flag, positive: true };\n}\n\nfunction parseIntOr(value: string, what: string, errors: string[]): number | undefined {\n const n = Number(value);\n if (!Number.isFinite(n) || !Number.isInteger(n) || n <= 0) {\n errors.push(`Invalid ${what}: \"${value}\" (expected a positive integer)`);\n return undefined;\n }\n return n;\n}\n\nfunction parsePortsCsv(value: string, errors: string[]): number[] | undefined {\n const ports = value\n .split(',')\n .map((p) => p.trim())\n .filter((p) => p.length > 0)\n .map((p) => parseIntOr(p, 'port', errors))\n .filter((n): n is number => n !== undefined);\n if (ports.length === 0) {\n errors.push(`--ports requires at least one valid port (got \"${value}\")`);\n return undefined;\n }\n return ports;\n}\n\nexport function parseArgs(argv: readonly string[]): ParseResult {\n const errors: string[] = [];\n const positional: string[] = [];\n\n // CLI-friendly defaults — different from the library defaults because the\n // CLI is for interactive checks, where users want the full pipeline by\n // default. WHOIS is still opt-in (it's slow + adds an external dependency).\n const result: ParsedArgs = {\n email: '',\n verifyMx: true,\n verifySmtp: true,\n checkDisposable: true,\n checkFree: true,\n suggestDomain: true,\n detectName: true,\n checkDomainAge: false,\n checkDomainRegistration: false,\n format: 'pretty',\n quiet: false,\n debug: false,\n captureTranscript: true,\n logDir: './logs',\n };\n let logFile = true;\n\n for (let i = 0; i < argv.length; i++) {\n const token = argv[i];\n if (token === undefined) continue;\n\n // Positional (the email)\n if (!token.startsWith('-')) {\n positional.push(token);\n continue;\n }\n\n if (token === '-h' || token === '--help') return { kind: 'help' };\n if (token === '-v' || token === '--version') return { kind: 'version' };\n\n if (!token.startsWith('--')) {\n errors.push(`Unknown short flag: \"${token}\"`);\n continue;\n }\n\n // Allow `--flag=value` form.\n const eqIdx = token.indexOf('=');\n const rawName = eqIdx === -1 ? token.slice(2) : token.slice(2, eqIdx);\n const inlineValue = eqIdx === -1 ? undefined : token.slice(eqIdx + 1);\n\n if (TRUE_FLAGS.has(rawName) || (rawName.startsWith('no-') && TRUE_FLAGS.has(rawName.slice(3)))) {\n const { name, positive } = splitNo(rawName);\n switch (name) {\n case 'mx':\n result.verifyMx = positive;\n break;\n case 'smtp':\n result.verifySmtp = positive;\n break;\n case 'disposable':\n result.checkDisposable = positive;\n break;\n case 'free':\n result.checkFree = positive;\n break;\n case 'suggest-domain':\n result.suggestDomain = positive;\n break;\n case 'detect-name':\n result.detectName = positive;\n break;\n case 'whois-age':\n result.checkDomainAge = positive;\n break;\n case 'whois-registration':\n result.checkDomainRegistration = positive;\n break;\n case 'transcript':\n result.captureTranscript = positive;\n break;\n case 'log-file':\n logFile = positive;\n break;\n case 'quiet':\n result.quiet = positive;\n break;\n case 'debug':\n result.debug = positive;\n break;\n }\n continue;\n }\n\n if (VALUE_FLAGS.has(rawName)) {\n const value = inlineValue ?? argv[++i];\n if (value === undefined) {\n errors.push(`Flag --${rawName} requires a value`);\n continue;\n }\n switch (rawName) {\n case 'port': {\n const port = parseIntOr(value, 'port', errors);\n if (port !== undefined) result.smtpPort = port;\n break;\n }\n case 'ports': {\n const ports = parsePortsCsv(value, errors);\n if (ports) result.ports = ports;\n break;\n }\n case 'hostname':\n result.hostname = value;\n break;\n case 'timeout': {\n const ms = parseIntOr(value, '--timeout', errors);\n if (ms !== undefined) result.timeoutMs = ms;\n break;\n }\n case 'whois-timeout': {\n const ms = parseIntOr(value, '--whois-timeout', errors);\n if (ms !== undefined) result.whoisTimeoutMs = ms;\n break;\n }\n case 'format':\n if (value !== 'text' && value !== 'json' && value !== 'pretty') {\n errors.push(`--format must be one of text|json|pretty (got \"${value}\")`);\n } else {\n result.format = value;\n }\n break;\n case 'log-dir':\n result.logDir = value;\n break;\n }\n continue;\n }\n\n errors.push(`Unknown flag: \"${token}\"`);\n }\n\n if (!logFile) result.logDir = null;\n\n if (positional.length === 0) errors.push('Missing required argument: <email>');\n if (positional.length > 1) errors.push(`Expected one email, got ${positional.length}: ${positional.join(', ')}`);\n\n if (errors.length > 0) {\n return { kind: 'error', messages: errors, exitCode: 2 };\n }\n\n const [email] = positional;\n if (!email) return { kind: 'error', messages: ['Missing required argument: <email>'], exitCode: 2 };\n result.email = email;\n return { kind: 'args', ...result };\n}\n\nexport function helpText(): string {\n return HELP_TEXT;\n}\n","import { type LRU, lru } from 'tiny-lru';\nimport type { CacheStore } from '../cache-interface';\n\n/**\n * Adapter to make tiny-lru compatible with our cache interface\n */\nexport class LRUAdapter<T> implements CacheStore<T> {\n private lru: LRU<T>;\n\n constructor(maxSize: number = 1000, ttlMs: number = 3600000) {\n this.lru = lru<T>(maxSize, ttlMs);\n }\n\n get(key: string): T | null | undefined {\n const value = this.lru.get(key);\n // tiny-lru returns undefined for not found\n return value === undefined ? null : value;\n }\n\n // Per-entry ttlMs is intentionally ignored: tiny-lru only supports a single\n // TTL set at construction. Callers that need per-entry expiry should pick a\n // backend that honours it (e.g. RedisAdapter).\n async set(key: string, value: T, _ttlMs?: number): Promise<void> {\n this.lru.set(key, value);\n }\n\n async delete(key: string): Promise<boolean> {\n this.lru.delete(key);\n return true;\n }\n\n async has(key: string): Promise<boolean> {\n return this.lru.has(key);\n }\n\n async clear(): Promise<void> {\n this.lru.clear();\n }\n\n size(): number {\n return this.lru.size;\n }\n\n /**\n * Get the underlying LRU instance for advanced operations\n */\n getLRU(): LRU<T> {\n return this.lru;\n }\n}\n","import type { Cache } from './cache-interface';\n\n/** Error codes set on `VerificationResult.metadata.error` when `verifyEmail` cannot deliver a definitive verdict. */\nexport enum VerificationErrorCode {\n invalidFormat = 'INVALID_FORMAT',\n invalidDomain = 'INVALID_DOMAIN',\n noMxRecords = 'NO_MX_RECORDS',\n smtpConnectionFailed = 'SMTP_CONNECTION_FAILED',\n smtpTimeout = 'SMTP_TIMEOUT',\n mailboxNotFound = 'MAILBOX_NOT_FOUND',\n networkError = 'NETWORK_ERROR',\n disposableEmail = 'DISPOSABLE_EMAIL',\n}\n\n/** Discriminator for `VerificationStep.kind`. */\nexport type VerificationStepKind =\n | 'syntax'\n | 'domain-validation'\n | 'name-detection'\n | 'domain-suggestion'\n | 'disposable'\n | 'free'\n | 'mx-lookup'\n | 'smtp-probe'\n | 'whois-age'\n | 'whois-registration';\n\n/**\n * One unit of work in the verification pipeline. Produced when\n * `VerifyEmailParams.captureTranscript === true`. The `details` shape varies\n * per step — see the inline interfaces under each kind.\n */\nexport interface VerificationStep {\n kind: VerificationStepKind;\n startedAt: number;\n durationMs: number;\n /** Whether the step completed without throwing. Step-level result lives in `details`. */\n ok: boolean;\n details: Record<string, unknown>;\n}\n\nexport interface VerificationResult {\n email: string;\n validFormat: boolean;\n validMx: boolean | null;\n validSmtp: boolean | null;\n isDisposable: boolean;\n isFree: boolean;\n detectedName?: DetectedName | null;\n domainAge?: DomainAgeInfo | null;\n domainRegistration?: DomainRegistrationInfo | null;\n domainSuggestion?: DomainSuggestion | null;\n /** MX records found for the domain (if MX verification was performed) */\n mxRecords?: string[] | null;\n\n // SMTP verification fields (flattened from SmtpVerificationResult)\n /** Whether SMTP connection was successful */\n canConnectSmtp?: boolean;\n /** Whether the mailbox is full */\n hasFullInbox?: boolean;\n /** Whether the domain has catch-all enabled */\n isCatchAll?: boolean;\n /** Whether the email is deliverable */\n isDeliverable?: boolean;\n /** Whether the email/account is disabled */\n isDisabled?: boolean;\n\n /** Always populated by `verifyEmail` — read directly without optional chaining. */\n metadata: {\n verificationTime: number;\n cached: boolean;\n error?: VerificationErrorCode;\n };\n /**\n * Per-step trace of what `verifyEmail` did. Present only when\n * `VerifyEmailParams.captureTranscript === true`. Each entry records timing\n * and step-specific details (raw WHOIS data, SMTP transcript, MX records,\n * cache hit/miss, etc.) for debugging and diagnostics.\n */\n transcript?: VerificationStep[];\n}\n\n/**\n * Parameters for `verifyEmail` — the high-level orchestrator that runs the\n * full pipeline (syntax → typo / name / domain → disposable / free → WHOIS\n * → MX → SMTP).\n */\nexport interface VerifyEmailParams {\n /** The full email address to verify (`local@domain`). */\n emailAddress: string;\n // ── Step toggles (each defaults are listed inline) ────────────────────────\n /** Resolve MX records via DNS to confirm the domain accepts mail. Default: `true`. */\n verifyMx?: boolean;\n /** Open an SMTP connection to the highest-priority MX and probe `RCPT TO`. Default: `false`. */\n verifySmtp?: boolean;\n /** Check the address against the bundled disposable-provider list. Default: `true`. */\n checkDisposable?: boolean;\n /** Check the address against the bundled free-provider list. Default: `true`. */\n checkFree?: boolean;\n /** Extract first/last name from the local-part. Default: `false` (cheap, but not free). */\n detectName?: boolean;\n /** Suggest a corrected domain on typos (e.g. `gnail.com` → `gmail.com`). Default: `true`. */\n suggestDomain?: boolean;\n /** Look up the domain creation date via WHOIS. Slow + external dep. Default: `false`. */\n checkDomainAge?: boolean;\n /** Look up domain registration status (registered / expired / locked). Default: `false`. */\n checkDomainRegistration?: boolean;\n // ── Skip-on-disposable shortcuts ────────────────────────────────────────\n /**\n * When the address is identified as disposable, skip the (expensive) MX +\n * SMTP probe and accept the disposable verdict as the final answer.\n * Default: `false`.\n */\n skipMxForDisposable?: boolean;\n /**\n * When the address is identified as disposable, skip the WHOIS checks too.\n * Default: `false`.\n */\n skipDomainWhoisForDisposable?: boolean;\n // ── Custom strategies (extension points for callers) ──────────────────────\n /** Override the default name-detection heuristic. Receives the email; returns `DetectedName | null`. */\n nameDetectionMethod?: NameDetectionMethod;\n /** Override the default domain-suggestion heuristic. Receives the domain; returns `DomainSuggestion | null`. */\n domainSuggestionMethod?: DomainSuggestionMethod;\n /** Custom domain list for the typo suggester. Defaults to the bundled common-domain set. */\n commonDomains?: string[];\n // ── SMTP probe wiring ─────────────────────────────────────────────────────\n /**\n * Per-attempt timeout for the SMTP probe, in milliseconds. Bounds both the\n * TCP/TLS connection setup AND the inactivity gap between SMTP commands\n * within an attempt. Default: `4000` ms.\n *\n * To bound the total wall-clock across all MX × port attempts, use\n * `smtpTotalDeadlineMs` instead. To control retries on connection-class\n * failures, use `smtpRetry`.\n */\n smtpPerAttemptTimeoutMs?: number;\n /**\n * Hard cap on total wall-clock time for the SMTP probe across all MX × port\n * × retry attempts. Reasonable when calling from a request handler with a\n * tight latency budget. Default: unbounded.\n */\n smtpTotalDeadlineMs?: number;\n /**\n * Stop the SMTP probe after this many connection-class failures in a row\n * (counting `connection_error` / `connection_timeout` / `connection_closed`\n * across MX × port attempts). Resets on any non-connection-class outcome.\n * Default: unbounded.\n */\n smtpMaxConsecutiveFailures?: number;\n /**\n * Hard cap on how many MX hostnames the SMTP probe will try, regardless of\n * how many DNS returned. Default: unbounded — try them all.\n */\n smtpMaxMxHosts?: number;\n /** Optional retry policy for connection-class failures on a single MX × port. Default: no retries. */\n smtpRetry?: RetryPolicy;\n /**\n * Force a specific port for the SMTP probe (e.g. `587`). When set, this\n * port is the only one tried — overrides the default `[25, 587, 465]` walk\n * and any per-MX hint cached from a previous probe.\n */\n smtpPort?: number;\n // ── WHOIS probe wiring ────────────────────────────────────────────────────\n /** Per-WHOIS-query timeout in milliseconds. Default: `5000`. */\n whoisTimeoutMs?: number;\n // ── Caching + diagnostics ────────────────────────────────────────────────\n /** Optional shared cache for MX, WHOIS, disposable / free, SMTP, and domain results. */\n cache?: Cache;\n /** When true, the pipeline writes a per-line trace to `console.debug`. Default: `false`. */\n debug?: boolean;\n /**\n * When true, populates `result.transcript` with a per-step structured trace\n * covering every subsystem (syntax / disposable / free / MX / SMTP / WHOIS /\n * name detection / domain suggestion). Each step records timing +\n * step-specific details (raw WHOIS data, SMTP transcript, MX records, cache\n * hit/miss, etc.). Safe to leave off for production; turn on for diagnostics\n * or debug UIs. Default: `false`.\n */\n captureTranscript?: boolean;\n}\n\n/**\n * Parameters for `verifyEmailBatch` — fan-out wrapper around `verifyEmail`\n * that runs many addresses through the same pipeline with a concurrency cap.\n */\nexport interface BatchVerifyParams {\n /** Email addresses to verify, in order. */\n emailAddresses: string[];\n /** Maximum number of in-flight `verifyEmail` calls. Default: `5`. */\n concurrency?: number;\n /** Per-attempt SMTP timeout in milliseconds (forwarded to each `verifyEmail` call). Default: `4000`. */\n smtpPerAttemptTimeoutMs?: number;\n /** Hard cap on total wall-clock for each individual SMTP probe. Forwarded to `verifyEmail`. */\n smtpTotalDeadlineMs?: number;\n /** Stop each individual SMTP probe after this many connection-class failures in a row. */\n smtpMaxConsecutiveFailures?: number;\n /** Hard cap on MX hostnames per individual SMTP probe. */\n smtpMaxMxHosts?: number;\n /** Optional retry policy per MX×port for each individual SMTP probe. */\n smtpRetry?: RetryPolicy;\n /** Resolve MX records per address. Default: `true`. */\n verifyMx?: boolean;\n /** Run the SMTP probe per address. Default: `false`. */\n verifySmtp?: boolean;\n /** Check disposable list per address. Default: `true`. */\n checkDisposable?: boolean;\n /** Check free-provider list per address. Default: `true`. */\n checkFree?: boolean;\n /** Extract first/last name from each local-part. Default: `false`. */\n detectName?: boolean;\n /** Override the name-detection heuristic. */\n nameDetectionMethod?: NameDetectionMethod;\n /** Suggest a corrected domain on typos. Default: `false` for batches (it's per-call cost). */\n suggestDomain?: boolean;\n /** Override the domain-suggestion heuristic. */\n domainSuggestionMethod?: DomainSuggestionMethod;\n /** Custom canonical-domain list for the typo suggester. */\n commonDomains?: string[];\n /** Skip MX/SMTP probe for disposable addresses. Default: `false`. */\n skipMxForDisposable?: boolean;\n /** Skip WHOIS lookups for disposable addresses. Default: `false`. */\n skipDomainWhoisForDisposable?: boolean;\n /** Optional shared cache (re-used across all addresses in the batch). */\n cache?: Cache;\n}\n\n/**\n * Rich cache result types for storing detailed verification results\n */\n\n/**\n * Result for disposable email detection with metadata\n */\nexport interface DisposableEmailResult {\n /** Whether the email/domain is disposable */\n isDisposable: boolean;\n /** Source that identified this as disposable (e.g., list name, service) */\n source?: string;\n /** Category of disposable email (e.g., 'temp', 'alias', 'forwarding') */\n category?: string;\n /** Timestamp when this was checked */\n checkedAt: number;\n}\n\n/**\n * Result for free email provider detection with metadata\n */\nexport interface FreeEmailResult {\n /** Whether the email/domain is from a free provider */\n isFree: boolean;\n /** Name of the free provider (e.g., 'gmail', 'yahoo', 'outlook') */\n provider?: string;\n /** Timestamp when this was checked */\n checkedAt: number;\n}\n\n/**\n * Result for domain validation with metadata\n */\nexport interface DomainValidResult {\n /** Whether the domain is valid */\n isValid: boolean;\n /** Whether MX records were found */\n hasMX: boolean;\n /** The MX records that were found */\n mxRecords?: string[];\n /** Timestamp when this was checked */\n checkedAt: number;\n}\n\n/**\n * Email providers enum\n */\nexport enum EmailProvider {\n gmail = 'gmail',\n hotmailB2b = 'hotmail_b2b',\n hotmailB2c = 'hotmail_b2c',\n proofpoint = 'proofpoint',\n mimecast = 'mimecast',\n yahoo = 'yahoo',\n everythingElse = 'everything_else',\n}\n\n/**\n * Verdict from one `verifyMailboxSMTP` call. Flat by design — every field is\n * one boolean / scalar so callers can switch on a few keys instead of walking\n * a tree.\n */\nexport interface SmtpVerificationResult {\n /** True when at least one MX×port responded with an SMTP greeting. */\n canConnectSmtp: boolean;\n /** True when the MX returned `552` / `452` (over-quota / mailbox full). */\n hasFullInbox: boolean;\n /**\n * True when both the real RCPT TO and the random-local probe RCPT TO\n * returned `250` — the MX accepts every recipient and the deliverability\n * signal for the real address is unreliable.\n */\n isCatchAll: boolean;\n /** True when the real RCPT TO returned `250` / `251`. */\n isDeliverable: boolean;\n /** True when the real RCPT TO was definitively rejected. */\n isDisabled: boolean;\n /**\n * Short reason key when `isDeliverable === false`. Vocabulary:\n * `not_found` | `over_quota` | `temporary_failure` | `ambiguous` |\n * `connection_error` | `connection_timeout` | `connection_closed` |\n * `tls_upgrade_failed` | `tls_handshake_failed` |\n * `ehlo_failed` | `helo_failed` | `mail_from_rejected` |\n * `no_greeting` | `no_mx_records` | `unrecognized_response` |\n * `step_timeout` | `socket_timeout`\n *\n * Pass to `refineReasonByEnhancedStatus(error, enhancedStatus)` for a\n * richer (mailbox-status-aware) reason when the MX returned a DSN.\n */\n error?: string;\n /** Most recent 3-digit SMTP code observed during the probe. */\n responseCode?: number;\n /**\n * RFC 3463 enhanced status code from the most recent SMTP reply that\n * carried one — e.g. `\"5.1.1\"` (mailbox unknown), `\"5.7.1\"` (policy\n * block), `\"4.7.0\"` (transient policy). Undefined when no MX reply\n * included an enhanced status.\n */\n enhancedStatus?: string;\n /** Operational counters — always populated. See `SmtpProbeMetrics`. */\n metrics?: SmtpProbeMetrics;\n /** Wall-clock timestamp this verdict was produced (set on every result). */\n checkedAt?: number;\n /**\n * Server reply lines, in arrival order, prefixed `<host>:<port>|s| <line>`\n * so multi-MX dialogues stay readable. Present only when\n * `captureTranscript: true` was passed.\n */\n transcript?: string[];\n /**\n * Client commands sent, in send order, prefixed `<host>:<port>|c| <cmd>`.\n * Present only when `captureTranscript: true` was passed.\n */\n commands?: string[];\n}\n\n/**\n * Operational counters for one `verifyMailboxSMTP` call. The cost of\n * collecting these is trivial — pure bookkeeping during the existing flow.\n */\nexport interface SmtpProbeMetrics {\n /** How many MX hostnames the outer loop attempted before stopping. */\n mxAttempts: number;\n /** Total connection attempts across the whole call (sum across MX×port). */\n portAttempts: number;\n /** MX hostnames attempted in priority order (matches `mxRecords` slice). */\n mxHostsTried: string[];\n /**\n * MX hostname that produced the final answer. Undefined when every MX\n * failed (in which case `result.isDeliverable === false` and the SMTP\n * reason is whatever the last attempted MX returned).\n */\n mxHostUsed?: string;\n /** Total wall-clock time the probe spent, in milliseconds. */\n totalDurationMs: number;\n}\n\n/**\n * Result for batch verification\n */\nexport interface BatchVerificationResult {\n results: Map<string, VerificationResult>;\n summary: {\n total: number;\n valid: number;\n invalid: number;\n errors: number;\n processingTime: number;\n };\n}\n\n/** TLS configuration options for the SMTP probe. */\nexport interface SMTPTLSConfig {\n rejectUnauthorized?: boolean;\n minVersion?: 'TLSv1.2' | 'TLSv1.3';\n}\n\n/**\n * SMTP protocol steps walked by the verifier in order. `startTls` is a\n * conditional step — it sends the STARTTLS command and upgrades the socket\n * to TLS when the MX advertised support (controlled by\n * `SMTPVerifyOptions.startTls`). On implicit-TLS ports (465) it's a no-op.\n */\nexport enum SMTPStep {\n greeting = 'GREETING',\n ehlo = 'EHLO',\n helo = 'HELO',\n startTls = 'STARTTLS',\n mailFrom = 'MAIL_FROM',\n rcptTo = 'RCPT_TO',\n}\n\n/** Custom SMTP step sequence for advanced callers. */\nexport interface SMTPSequence {\n steps: SMTPStep[];\n /** Override MAIL FROM payload — supply with angle brackets or `<>` for null sender. */\n from?: string;\n}\n\n/**\n * Optional retry policy for connection-class failures (timeout / connection\n * error / connection closed) on a single MX × port. Definitive answers\n * (250 / 550 / 552 / etc.) are never retried — they're stable verdicts.\n */\nexport interface RetryPolicy {\n /**\n * How many extra attempts to make on the same MX × port after a\n * connection-class failure. `0` means no retry (the default).\n */\n attempts: number;\n /**\n * Delay between retries, in milliseconds. With `backoff: 'exponential'`\n * (the default), the actual delay is `delayMs * 2^(attemptIndex - 1)`.\n * Default: `200` ms.\n */\n delayMs?: number;\n /**\n * Backoff strategy between retries.\n * - `'exponential'` (default): `delayMs * 2^(attemptIndex - 1)`.\n * - `'fixed'`: every retry waits `delayMs` exactly.\n */\n backoff?: 'exponential' | 'fixed';\n}\n\n/**\n * Options for `verifyMailboxSMTP` and `verifyEmail`'s SMTP probe.\n *\n * Time-budget defaults are tuned for a 4-MX × 3-port worst case. If you\n * call this from a request handler with a tight latency budget, set\n * `totalDeadlineMs` so the probe gives up before your handler does.\n */\nexport interface SMTPVerifyOptions {\n // ── Connection envelope ───────────────────────────────────────────────────\n /**\n * Ports to walk per MX, in priority order. The probe stops on the first\n * port that yields a definitive answer; indeterminate outcomes (timeout /\n * connection error / etc.) fall through to the next port.\n *\n * Default: `[25, 587, 465]` — plain → STARTTLS-able → implicit-TLS.\n */\n ports?: number[];\n /**\n * Per-attempt timeout in milliseconds. Bounds both the TCP/TLS connection\n * setup AND the inactivity gap between SMTP commands within an attempt.\n * Each MX × port pair gets its own budget — to bound the total wall-clock,\n * use `totalDeadlineMs` instead.\n *\n * Default: `3000` ms.\n */\n perAttemptTimeoutMs?: number;\n /**\n * TLS configuration applied to implicit-TLS ports (465) and to STARTTLS\n * upgrades on plaintext ports.\n *\n * - `true` (default): use sensible TLS defaults (`rejectUnauthorized: false`,\n * `minVersion: 'TLSv1.2'`) — picks up CA quirks of long-tail MXes.\n * - `false`: disable TLS entirely (port 465 will fail to handshake; STARTTLS\n * step is skipped).\n * - `SMTPTLSConfig` object: override individual fields. Merged onto the defaults.\n */\n tlsConfig?: boolean | SMTPTLSConfig;\n /**\n * Hostname this client identifies itself as in the `EHLO` / `HELO` argument.\n * Should be a real FQDN — `localhost` from a public IP is a textbook spam-bot\n * signature and gets rejected by careful MXes.\n *\n * Default: `'localhost'`. Override with your delivery domain in production.\n */\n heloHostname?: string;\n // ── Caching ──────────────────────────────────────────────────────────────\n /**\n * Optional cache instance. When provided, the probe reuses prior verdicts\n * keyed on `<primary mx>:<local>@<domain>` and remembers the last\n * successful port per primary MX (so a re-probe skips the failed-port\n * walk).\n *\n * Pass `null` or omit to skip caching entirely.\n */\n cache?: Cache | null;\n /**\n * When true, a per-line `[SMTP] …` trace is written to `console.log`.\n * Useful for diagnosing real-MX behavior; off by default for production.\n */\n debug?: boolean;\n /**\n * When true, the returned `SmtpVerificationResult` carries `transcript`\n * and `commands` arrays prefixed with `<host>:<port>|s| …` /\n * `<host>:<port>|c| …`. Aggregated across every MX × port attempted.\n *\n * Default: `false`. The strings are O(N × wire-bytes); skip when you\n * don't need the trace.\n */\n captureTranscript?: boolean;\n // ── Time budget + early-stop policy ───────────────────────────────────────\n /**\n * Hard cap on total wall-clock time for the entire probe (across all\n * MX × port × retry attempts). When the deadline passes, the in-flight\n * attempt is allowed to finish (it has its own per-attempt budget) and\n * no new attempts are started.\n *\n * Use this to bound latency from a request-handler caller. A reasonable\n * value matches your handler's deadline minus headroom for everything\n * else it does.\n *\n * Default: unbounded — only `perAttemptTimeoutMs × ports.length × mxRecords.length`\n * limits the worst case (e.g. `3000 × 3 × 4 = 36s`).\n */\n totalDeadlineMs?: number;\n /**\n * Stop probing after this many connection-class failures in a row.\n * Counts consecutive `connection_error` / `connection_timeout` /\n * `connection_closed` outcomes across MX × port attempts; resets on any\n * non-connection-class outcome. Useful for cutting off probes when the\n * network path to the MX is wholly unreachable instead of waiting for\n * every port × MX combination to time out.\n *\n * Default: unbounded.\n */\n maxConsecutiveFailures?: number;\n /**\n * Hard cap on how many MX hostnames to try, regardless of how many were\n * supplied in `mxRecords`. The probe walks them in priority order\n * (`mxRecords[0]` first) and stops after this many.\n *\n * Default: unbounded.\n */\n maxMxHosts?: number;\n /**\n * Optional retry policy for connection-class failures on a single MX × port.\n * Definitive answers (250 / 550 / 552 / 421 / etc.) are never retried —\n * they're stable verdicts.\n *\n * Default: no retries.\n */\n retry?: RetryPolicy;\n // ── Dialogue customization ───────────────────────────────────────────────\n /**\n * Override the per-attempt SMTP step list. Defaults to\n * `[greeting, ehlo, startTls, mailFrom, rcptTo]` — covering the entire\n * RFC 5321 envelope plus optional TLS upgrade. Most callers never need\n * to override this; useful for advanced testing scenarios (e.g. probe\n * RFC compliance with `[greeting, helo, mailFrom, rcptTo]`).\n */\n sequence?: SMTPSequence;\n /**\n * Override the random local-part generator used by the catch-all dual\n * probe. Useful for deterministic tests; receives the real local-part\n * and domain so callers can derive a probe-local that matches the MX's\n * syntax rules.\n *\n * Default: `<16 hex chars>-noexist` — long enough to never collide,\n * structured so it's clearly synthetic, and passes common syntax filters.\n */\n catchAllProbeLocal?: (realLocal: string, domain: string) => string;\n /**\n * SMTP PIPELINING (RFC 2920) — batch the envelope phase\n * (RCPT TO real + RCPT TO probe + RSET) into one `socket.write()` when\n * the MX advertises support.\n *\n * - `'auto'` (default): pipeline when EHLO multi-line includes `PIPELINING`,\n * sequential otherwise.\n * - `'never'`: always sequential — useful for deterministic wire-level\n * assertions in tests or when investigating a pipeline-buggy MX.\n * - `'force'`: pipeline without checking — testing escape hatch.\n */\n pipelining?: 'auto' | 'never' | 'force';\n /**\n * STARTTLS upgrade on plaintext ports (25, 587). Implicit-TLS ports (465)\n * ignore this option — they're already TLS from the start.\n *\n * - `'auto'` (default): upgrade if the MX advertises STARTTLS in EHLO.\n * Submission-port (587) MXes typically require this — without it,\n * `MAIL FROM` is rejected with `530 Must issue STARTTLS first`.\n * - `'never'`: never upgrade — send `MAIL FROM` / `RCPT TO` in plaintext.\n * - `'force'`: send `STARTTLS` unconditionally. Fails with\n * `tls_upgrade_failed` when the MX doesn't support it. Testing only.\n */\n startTls?: 'auto' | 'never' | 'force';\n}\n\nexport interface VerifyMailboxSMTPParams {\n local: string;\n domain: string;\n mxRecords: string[];\n options?: SMTPVerifyOptions;\n}\n\n/**\n * Domain suggestion for typo correction\n */\nexport interface DomainSuggestion {\n original: string;\n suggested: string;\n confidence: number;\n}\n\n/**\n * Custom domain suggestion function type\n */\nexport type DomainSuggestionMethod = (domain: string) => DomainSuggestion | null;\n\n/**\n * Parameters for domain suggestion\n */\nexport interface DomainSuggestionParams {\n domain: string;\n customMethod?: DomainSuggestionMethod;\n commonDomains?: string[];\n cache?: Cache;\n}\n\n/**\n * Result of name detection from email\n */\nexport interface DetectedName {\n firstName?: string;\n lastName?: string;\n confidence: number;\n}\n\n/**\n * Custom name detection function type\n */\nexport type NameDetectionMethod = (email: string) => DetectedName | null;\n\n/**\n * Parameters for name detection\n */\nexport interface NameDetectionParams {\n email: string;\n customMethod?: NameDetectionMethod;\n}\n\n/**\n * Domain age information\n */\nexport interface DomainAgeInfo {\n domain: string;\n creationDate: Date;\n ageInDays: number;\n ageInYears: number;\n expirationDate: Date | null;\n updatedDate: Date | null;\n}\n\n/**\n * Domain registration status information\n */\nexport interface DomainRegistrationInfo {\n domain: string;\n isRegistered: boolean;\n isAvailable: boolean;\n status: string[];\n registrar: string | null;\n nameServers: string[];\n expirationDate: Date | null;\n isExpired: boolean;\n daysUntilExpiration: number | null;\n isPendingDelete?: boolean;\n isLocked?: boolean;\n}\n\n/**\n * Options for domain suggester\n */\nexport interface DomainSuggesterOptions {\n threshold?: number;\n customDomains?: string[];\n}\n\n/**\n * Parameters for isDisposableEmail function\n */\nexport interface DisposableEmailCheckParams {\n emailOrDomain: string;\n cache?: Cache | null;\n logger?: (...args: unknown[]) => void;\n}\n\n/**\n * Parameters for isFreeEmail function\n */\nexport interface FreeEmailCheckParams {\n emailOrDomain: string;\n cache?: Cache | null;\n logger?: (...args: unknown[]) => void;\n}\n\n/**\n * Parameters for resolveMxRecords function\n */\nexport interface ResolveMxParams {\n domain: string;\n cache?: Cache | null;\n logger?: (...args: unknown[]) => void;\n}\n\n/**\n * Options for email validation (serverless compatible)\n */\nexport interface ValidateEmailOptions {\n validateSyntax?: boolean;\n validateTypo?: boolean;\n validateDisposable?: boolean;\n validateFree?: boolean;\n validateMx?: boolean;\n validateSMTP?: boolean;\n skipCache?: boolean;\n batchSize?: number;\n domainSuggesterOptions?: DomainSuggesterOptions;\n}\n\n/**\n * Result of email validation (serverless compatible)\n */\nexport interface EmailValidationResult {\n valid: boolean;\n email: string;\n local?: string;\n domain?: string;\n validators: {\n syntax?: ValidatorResult;\n typo?: ValidatorResult & { suggestion?: string };\n disposable?: ValidatorResult;\n free?: ValidatorResult;\n mx?: ValidatorResult & { records?: string[]; error?: string };\n smtp?: ValidatorResult & { error?: string };\n };\n}\n\n/**\n * Individual validator result\n */\nexport interface ValidatorResult {\n valid: boolean;\n}\n\n// Re-export cache interfaces\nexport type { Cache, CacheStore } from './cache-interface';\n","import { LRUAdapter } from './adapters/lru-adapter';\nimport type { Cache, CacheStore } from './cache-interface';\nimport type { DisposableEmailResult, DomainValidResult, FreeEmailResult, SmtpVerificationResult } from './types';\nimport type { ParsedWhoisResult } from './whois-parser';\n\n/**\n * Default cache options\n */\nexport const DEFAULT_CACHE_OPTIONS = {\n ttl: {\n mx: 3600000,\n disposable: 86400000,\n free: 86400000,\n domainValid: 86400000,\n smtp: 1800000,\n smtpPort: 86400000,\n domainSuggestion: 86400000,\n whois: 3600000,\n },\n maxSize: {\n mx: 10000,\n disposable: 10000,\n free: 10000,\n domainValid: 10000,\n smtp: 10000,\n smtpPort: 10000,\n domainSuggestion: 10000,\n whois: 10000,\n },\n};\n\n/**\n * Lazy-loaded default cache instance\n */\nlet defaultCacheInstance: Cache | null = null;\n\n/**\n * Get the default in-memory cache singleton using LRU\n * This is created on first access and reused for all subsequent calls\n */\nexport function getDefaultCache(): Cache {\n if (!defaultCacheInstance) {\n defaultCacheInstance = {\n mx: new LRUAdapter<string[]>(DEFAULT_CACHE_OPTIONS.maxSize.mx, DEFAULT_CACHE_OPTIONS.ttl.mx),\n disposable: new LRUAdapter<DisposableEmailResult>(\n DEFAULT_CACHE_OPTIONS.maxSize.disposable,\n DEFAULT_CACHE_OPTIONS.ttl.disposable\n ),\n free: new LRUAdapter<FreeEmailResult>(DEFAULT_CACHE_OPTIONS.maxSize.free, DEFAULT_CACHE_OPTIONS.ttl.free),\n domainValid: new LRUAdapter<DomainValidResult>(\n DEFAULT_CACHE_OPTIONS.maxSize.domainValid,\n DEFAULT_CACHE_OPTIONS.ttl.domainValid\n ),\n smtp: new LRUAdapter<SmtpVerificationResult>(DEFAULT_CACHE_OPTIONS.maxSize.smtp, DEFAULT_CACHE_OPTIONS.ttl.smtp),\n smtpPort: new LRUAdapter<number>(DEFAULT_CACHE_OPTIONS.maxSize.smtpPort, DEFAULT_CACHE_OPTIONS.ttl.smtpPort),\n domainSuggestion: new LRUAdapter<{ suggested: string; confidence: number } | null>(\n DEFAULT_CACHE_OPTIONS.maxSize.domainSuggestion,\n DEFAULT_CACHE_OPTIONS.ttl.domainSuggestion\n ),\n whois: new LRUAdapter<ParsedWhoisResult>(DEFAULT_CACHE_OPTIONS.maxSize.whois, DEFAULT_CACHE_OPTIONS.ttl.whois),\n };\n }\n return defaultCacheInstance;\n}\n\n/**\n * Helper function to get cache store from cache parameter\n * Follows same pattern as logging - use passed cache or default\n */\nexport function getCacheStore<T>(cache: Cache | null | undefined, key: keyof Cache): CacheStore<T> {\n return (cache?.[key] || getDefaultCache()[key]) as CacheStore<T>;\n}\n\n/**\n * Clear all entries from every store in the default cache instance.\n * No-op if the cache hasn't been lazily constructed yet.\n */\nexport function clearDefaultCache(): void {\n if (!defaultCacheInstance) return;\n for (const store of Object.values(defaultCacheInstance)) {\n store.clear();\n }\n}\n\nexport type { Cache, CacheStore } from './cache-interface';\n","import { stringSimilarity } from 'string-similarity-js';\nimport { getCacheStore } from './cache';\nimport type { Cache } from './cache-interface';\nimport commonEmailDomainsJson from './data/common-email-domains.json';\nimport typoPatternsJson from './data/typo-patterns.json';\nimport type { DomainSuggestion, DomainSuggestionParams } from './types';\n\n/**\n * List of common email domains for typo detection — popular free providers,\n * business providers, and hosting services. Source data lives in\n * src/data/common-email-domains.json.\n */\nexport const commonEmailDomains: readonly string[] = commonEmailDomainsJson as string[];\n\n/**\n * Hand-curated typo → canonical map. Faster + more accurate than the\n * similarity heuristic for common misspellings of the top providers.\n */\nconst TYPO_PATTERNS = typoPatternsJson as Record<string, string[]>;\n\n/**\n * Calculate similarity threshold based on domain length\n * Shorter domains need higher similarity to avoid false positives\n */\nfunction getSimilarityThreshold(domain: string) {\n const length = domain.length;\n if (length <= 6) return 0.85; // Short domains need high similarity\n if (length <= 10) return 0.8; // Medium domains\n return 0.75; // Longer domains can have lower threshold\n}\n\n/**\n * Pure matching logic — no caching, no I/O. Returns the best suggestion for\n * `domain` against `candidates` or null. Both the sync and the async\n * (cache-aware) public entry points share this single implementation.\n */\nfunction findSuggestion(domain: string, candidates: readonly string[]): DomainSuggestion | null {\n const lower = domain.toLowerCase();\n\n // Already a known good domain → no suggestion.\n if (candidates.includes(lower)) return null;\n\n // Hand-crafted typo table beats the similarity heuristic for common cases.\n for (const [correct, typos] of Object.entries(TYPO_PATTERNS)) {\n if (typos.includes(lower)) {\n return { original: domain, suggested: correct, confidence: 0.95 };\n }\n }\n\n const threshold = getSimilarityThreshold(lower);\n let best: { domain: string; similarity: number } | null = null;\n\n for (const candidate of candidates) {\n const similarity = stringSimilarity(lower, candidate.toLowerCase());\n if (similarity >= threshold && (!best || similarity > best.similarity)) {\n best = { domain: candidate, similarity };\n }\n }\n\n // Second pass with a relaxed threshold for length-similar domains.\n if (!best) {\n for (const candidate of candidates) {\n if (Math.abs(lower.length - candidate.length) > 2) continue;\n const similarity = stringSimilarity(lower, candidate.toLowerCase());\n if (similarity >= 0.7 && (!best || similarity > best.similarity)) {\n best = { domain: candidate, similarity };\n }\n }\n }\n\n if (!best) return null;\n // Reject suggestions whose first letter differs unless similarity is very high\n // — this avoids \"amazon.com\" being suggested for \"yahoo.com\" type junk.\n if (best.domain.charAt(0) !== lower.charAt(0) && best.similarity < 0.9) return null;\n\n return { original: domain, suggested: best.domain, confidence: best.similarity };\n}\n\n/** Sync default — no cache. Public for callers that need a synchronous answer. */\nexport function defaultDomainSuggestionMethod(domain: string, commonDomains?: string[]): DomainSuggestion | null {\n if (!domain || domain.length < 3) return null;\n return findSuggestion(domain, commonDomains ?? commonEmailDomains);\n}\n\n/** Async default — wraps the sync match with a per-domain cache layer. */\nexport async function defaultDomainSuggestionMethodAsync(\n domain: string,\n commonDomains?: string[],\n cache?: Cache\n): Promise<DomainSuggestion | null> {\n if (!domain || domain.length < 3) return null;\n const candidates = commonDomains ?? commonEmailDomains;\n const cacheKey = `${domain.toLowerCase()}:${candidates.length}`;\n const cacheStore = getCacheStore<DomainSuggestion | null>(cache, 'domainSuggestion');\n\n const cached = await cacheStore.get(cacheKey);\n if (cached !== null && cached !== undefined) return cached as DomainSuggestion | null;\n\n const result = findSuggestion(domain, candidates);\n await cacheStore.set(cacheKey, result);\n return result;\n}\n\n/** Sync entry: pass a domain (or email-shaped string), get a suggestion or null. */\nexport function suggestDomain(params: DomainSuggestionParams): DomainSuggestion | null {\n const { domain, customMethod, commonDomains } = params;\n if (!domain || domain.length < 3) return null;\n\n if (customMethod) {\n try {\n return customMethod(domain);\n } catch (error) {\n // Fall back to the default if the user's method throws.\n console.warn('Custom domain suggestion method failed, falling back to default:', error);\n }\n }\n return defaultDomainSuggestionMethod(domain, commonDomains);\n}\n\n/** Async entry: takes a full email, returns a suggestion that rewrites the local-part too. */\nexport async function suggestEmailDomain(\n email: string,\n commonDomains?: string[],\n cache?: Cache\n): Promise<DomainSuggestion | null> {\n if (!email?.includes('@')) return null;\n const [localPart, domain] = email.split('@');\n if (!domain || !localPart) return null;\n\n const suggestion = await defaultDomainSuggestionMethodAsync(domain, commonDomains, cache);\n if (!suggestion) return null;\n\n return {\n original: email,\n suggested: `${localPart}@${suggestion.suggested}`,\n confidence: suggestion.confidence,\n };\n}\n\nexport function isCommonDomain(domain: string, commonDomains?: string[]): boolean {\n return (commonDomains ?? commonEmailDomains).includes(domain.toLowerCase());\n}\n\nexport function getDomainSimilarity(domain1: string, domain2: string): number {\n return stringSimilarity(domain1.toLowerCase(), domain2.toLowerCase());\n}\n","import { isValid } from 'psl';\nimport { getCacheStore } from './cache';\nimport type { Cache } from './cache-interface';\nimport type { DomainValidResult } from './types';\n\n/**\n * Validates if email domain is valid TLD\n */\nexport async function isValidEmailDomain(emailOrDomain: string, cache?: Cache | null): Promise<boolean> {\n let [localPart, emailDomain] = emailOrDomain?.split('@') || [];\n if (!emailDomain) {\n emailDomain = localPart;\n }\n if (!emailDomain) {\n return false;\n }\n\n // Check cache first - now uses rich DomainValidResult\n const cacheStore = getCacheStore<DomainValidResult>(cache, 'domainValid');\n const cached = await cacheStore.get(emailDomain);\n if (cached !== null && cached !== undefined) {\n return cached.isValid;\n }\n\n try {\n const isValidResult = isValid(emailDomain) || false;\n\n // Store rich result in cache\n const richResult: DomainValidResult = {\n isValid: isValidResult,\n hasMX: false, // MX not checked in this function\n checkedAt: Date.now(),\n };\n\n await cacheStore.set(emailDomain, richResult);\n return isValidResult;\n } catch (validationError) {\n const errorResult: DomainValidResult = {\n isValid: false,\n hasMX: false,\n checkedAt: Date.now(),\n };\n await cacheStore.set(emailDomain, errorResult);\n return false;\n }\n}\n\n/**\n * Validates email-address format with a pragmatic (not strictly RFC-5322) regex.\n *\n * The local-part allow-list is `[a-zA-Z0-9._+'-]` — letters, digits, dot,\n * underscore, plus, apostrophe, hyphen. Characters that are technically valid\n * in RFC atext but virtually never appear in real mailboxes (`= ? ^ ~ { } | *\n * & % $ # ! / `` `) are rejected. Quoted local-parts (`\"...\"@example.com`) are\n * accepted as-is — they're rare but legal — but their interior is not parsed.\n */\nexport function isValidEmail(emailAddress: string) {\n if (!emailAddress || typeof emailAddress !== 'string') {\n return false;\n }\n\n // Local-part: dot-atom-text with the pragmatic character set, OR a\n // quoted-string. Domain: IPv4 literal in brackets, OR labels-and-TLD.\n const re =\n /^(([a-zA-Z0-9_+'-]+(\\.[a-zA-Z0-9_+'-]+)*)|(\".+\"))@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}])|(([a-zA-Z0-9-]+\\.)+[a-zA-Z]{2,}))$/;\n\n const emailLower = emailAddress.toLowerCase();\n\n // Heuristic guards on top of the regex — these are subtle invalid patterns\n // that the regex's dot-atom structure can still permit at the seams.\n if (emailLower.indexOf('.+') !== -1) return false;\n if (emailLower.indexOf('..') !== -1) return false;\n if (emailLower.startsWith('.') || emailLower.endsWith('.')) return false;\n\n const parts = emailAddress.split('@');\n if (parts.length !== 2) return false;\n\n const [localPart, domain] = parts;\n if (!localPart || !domain) return false;\n if (localPart.length > 64) return false; // RFC 5321\n if (domain.length > 253) return false; // RFC 5321\n\n return re.test(emailLower);\n}\n","import { getCacheStore } from './cache';\nimport disposableProviders from './disposable-email-providers.json';\nimport type { DisposableEmailCheckParams, DisposableEmailResult } from './types';\n\nconst disposableEmailProviders: Set<string> = new Set(disposableProviders as string[]);\n\n/**\n * Check whether the email's domain is on the bundled disposable-provider list.\n * Result is rich-cached (`DisposableEmailResult`) so repeated calls hit a Set\n * lookup behind a CacheStore<T>.\n */\nexport async function isDisposableEmail(params: DisposableEmailCheckParams): Promise<boolean> {\n const { emailOrDomain, cache, logger } = params;\n const log = logger || (() => {});\n\n const parts = emailOrDomain.split('@');\n const emailDomain = parts.length > 1 ? parts[1] : parts[0];\n if (!emailDomain) return false;\n\n const cacheStore = getCacheStore<DisposableEmailResult>(cache, 'disposable');\n let cached: DisposableEmailResult | null | undefined;\n try {\n cached = await cacheStore.get(emailDomain);\n } catch {\n cached = null;\n }\n if (cached !== null && cached !== undefined) {\n log(`[isDisposableEmail] Cache hit for ${emailDomain}: ${cached.isDisposable}`);\n return cached.isDisposable;\n }\n\n const isDisposable = disposableEmailProviders.has(emailDomain);\n const richResult: DisposableEmailResult = {\n isDisposable,\n source: 'disposable-email-providers.json',\n category: isDisposable ? 'disposable' : undefined,\n checkedAt: Date.now(),\n };\n\n try {\n await cacheStore.set(emailDomain, richResult);\n log(`[isDisposableEmail] Cached result for ${emailDomain}: ${isDisposable}`);\n } catch {\n log(`[isDisposableEmail] Cache write error for ${emailDomain}`);\n }\n log(`[isDisposableEmail] Check result for ${emailDomain}: ${isDisposable}`);\n return isDisposable;\n}\n","import { getCacheStore } from './cache';\nimport freeProviders from './free-email-providers.json';\nimport type { FreeEmailCheckParams, FreeEmailResult } from './types';\n\nconst freeEmailProviders: Set<string> = new Set(freeProviders as string[]);\n\n/**\n * Check whether the email's domain is on the bundled free-provider list.\n * Result is rich-cached (`FreeEmailResult`) so repeated calls hit a Set\n * lookup behind a CacheStore<T>.\n */\nexport async function isFreeEmail(params: FreeEmailCheckParams): Promise<boolean> {\n const { emailOrDomain, cache, logger } = params;\n const log = logger || (() => {});\n\n const parts = emailOrDomain.split('@');\n const emailDomain = parts.length > 1 ? parts[1] : parts[0];\n if (!emailDomain) return false;\n\n const cacheStore = getCacheStore<FreeEmailResult>(cache, 'free');\n let cached: FreeEmailResult | null | undefined;\n try {\n cached = await cacheStore.get(emailDomain);\n } catch {\n cached = null;\n }\n if (cached !== null && cached !== undefined) {\n log(`[isFreeEmail] Cache hit for ${emailDomain}: ${cached.isFree}`);\n return cached.isFree;\n }\n\n const isFree = freeEmailProviders.has(emailDomain);\n const richResult: FreeEmailResult = {\n isFree,\n provider: isFree ? emailDomain : undefined,\n checkedAt: Date.now(),\n };\n\n try {\n await cacheStore.set(emailDomain, richResult);\n log(`[isFreeEmail] Cached result for ${emailDomain}: ${isFree}`);\n } catch {\n log(`[isFreeEmail] Cache write error for ${emailDomain}`);\n }\n log(`[isFreeEmail] Check result for ${emailDomain}: ${isFree}`);\n return isFree;\n}\n","import { promises as dnsPromises } from 'node:dns';\nimport { getCacheStore } from './cache';\nimport type { ResolveMxParams } from './types';\n\nexport async function resolveMxRecords(params: ResolveMxParams): Promise<string[]> {\n const { domain, cache, logger } = params;\n const log = logger || (() => {});\n\n // Check cache first\n const cacheStore = getCacheStore<string[]>(cache, 'mx');\n const cached = await cacheStore.get(domain);\n if (cached !== null && cached !== undefined) {\n log(`[resolveMxRecords] Cache hit for ${domain}: ${cached?.length} MX records`);\n return cached;\n }\n\n log(`[resolveMxRecords] Performing DNS MX lookup for ${domain}`);\n try {\n const records: { exchange: string; priority: number }[] = await dnsPromises.resolveMx(domain);\n records?.sort((a, b) => {\n if (a.priority < b.priority) {\n return -1;\n }\n if (a.priority > b.priority) {\n return 1;\n }\n return 0;\n });\n\n const exchanges = records?.map((record) => record.exchange);\n log(`[resolveMxRecords] Found ${exchanges?.length} MX records for ${domain}: [${exchanges?.join(', ')}]`);\n\n // Cache the result\n await cacheStore.set(domain, exchanges);\n log(`[resolveMxRecords] Cached ${exchanges?.length} MX records for ${domain}`);\n\n return exchanges;\n } catch (error) {\n log(`[resolveMxRecords] MX lookup failed for ${domain}, caching empty result`);\n // Cache negative results for shorter time\n await cacheStore.set(domain, []);\n throw error;\n }\n}\n","import commonFirstNameJson from './data/common-first-names.json';\nimport commonLastNameJson from './data/common-last-names.json';\nimport type { DetectedName, NameDetectionParams } from './types';\n\n/**\n * Common name separators and patterns\n */\nconst nameSeparator = ['.', '_', '-'];\nconst commonNameSuffixes = [\n 'mail',\n 'email',\n 'contact',\n 'info',\n 'admin',\n 'support',\n 'sales',\n 'help',\n 'noreply',\n 'no-reply',\n 'donotreply',\n 'notifications',\n 'alerts',\n];\n\n// Additional suffixes that might appear in email addresses\nconst contextualSuffixes = [\n 'dev',\n 'company',\n 'team',\n 'group',\n 'office',\n 'work',\n 'personal',\n 'home',\n 'private',\n 'business',\n 'corp',\n 'inc',\n 'ltd',\n 'llc',\n 'org',\n];\n\n// Common titles and honorifics\nconst COMMON_TITLES = [\n 'mr',\n 'mrs',\n 'ms',\n 'miss',\n 'dr',\n 'prof',\n 'sir',\n 'lord',\n 'lady',\n 'captain',\n 'rev',\n 'father',\n 'sister',\n];\n\n// Common first names across English, Latin, Arabic, Asian, European, African cultures.\n// Source data lives in src/data/common-first-names.json — JSON keeps the source\n// file readable instead of buried under hundreds of string literals.\nconst commonFirstName: Set<string> = new Set(commonFirstNameJson as string[]);\n\n// Common surnames; same rationale as commonFirstName above.\nconst commonLastName: Set<string> = new Set(commonLastNameJson as string[]);\n\n// Check if a string looks like a year\nfunction isYearLike(str: string) {\n return /^(19|20)\\d{2}$/.test(str);\n}\n\n// Check if a string is a known first name\nfunction isKnownFirstName(str: string) {\n return commonFirstName.has(str.toLowerCase());\n}\n\n// Check if a string is a known last name\nfunction isKnownLastName(str: string) {\n return commonLastName.has(str.toLowerCase());\n}\n\n// Check if a string is a title/honorific\nfunction isTitle(str: string) {\n return COMMON_TITLES.includes(str.toLowerCase().replace('.', ''));\n}\n\n// Check if a string is a middle name indicator\n// Score how likely a string is to be a first name\nfunction getFirstNameScore(str: string) {\n const lower = str.toLowerCase();\n if (commonFirstName.has(lower)) return 1.0;\n if (commonLastName.has(lower)) return 0.3; // Some overlap\n if (str.length >= 2 && str.length <= 15 && /^[a-zA-Z]+$/.test(str)) return 0.5;\n return 0;\n}\n\n// Score how likely a string is to be a last name\nfunction getLastNameScore(str: string) {\n const lower = str.toLowerCase();\n if (commonLastName.has(lower)) return 1.0;\n if (commonFirstName.has(lower)) return 0.3; // Some overlap\n if (str.length >= 2 && str.length <= 20 && /^[a-zA-Z]+$/.test(str)) return 0.5;\n return 0;\n}\n\n/**\n * Intelligently capitalize names, handling special cases\n */\nfunction capitalizeName(str: string) {\n if (!str) return '';\n\n // Handle special name patterns\n const specialPatterns = [\n {\n pattern: /^(o')([a-z]+)/i,\n format: (m: RegExpMatchArray) => `O'${m[2].charAt(0).toUpperCase()}${m[2].slice(1).toLowerCase()}`,\n },\n {\n pattern: /^(mac)([a-z]+)/i,\n format: (m: RegExpMatchArray) => `Mac${m[2].charAt(0).toUpperCase()}${m[2].slice(1).toLowerCase()}`,\n },\n {\n pattern: /^(mc)([a-z]+)/i,\n format: (m: RegExpMatchArray) => `Mc${m[2].charAt(0).toUpperCase()}${m[2].slice(1).toLowerCase()}`,\n },\n {\n pattern: /^(van|von|de|del|dela|da|di|le|la|du|den|der|ter|ten)(\\s+)([a-z]+)/i,\n format: (m: RegExpMatchArray) =>\n m[1].toLowerCase() + m[2] + m[3].charAt(0).toUpperCase() + m[3].slice(1).toLowerCase(),\n },\n ];\n\n for (const { pattern, format } of specialPatterns) {\n const match = str.match(pattern);\n if (match) {\n return format(match);\n }\n }\n\n // Handle hyphenated names\n if (str.includes('-')) {\n return str\n .split('-')\n .map((part) => part.charAt(0).toUpperCase() + part.slice(1).toLowerCase())\n .join('-');\n }\n\n // Handle apostrophes in names like D'Angelo\n if (str.includes(\"'\") && str.indexOf(\"'\") > 0) {\n const parts = str.split(\"'\");\n return parts\n .map((part, i) =>\n i === 0\n ? part.charAt(0).toUpperCase() + part.slice(1).toLowerCase()\n : part.charAt(0).toUpperCase() + part.slice(1).toLowerCase()\n )\n .join(\"'\");\n }\n\n // Standard capitalization\n if (/^[a-zA-Z]/.test(str)) {\n return str.charAt(0).toUpperCase() + str.slice(1).toLowerCase();\n }\n\n return str;\n}\n\n/**\n * Parse composite name parts that may contain numbers and special patterns\n * Intelligently strips numbers and special characters that are likely not part of the actual name\n * e.g., \"john1\" -> \"john\", \"due2\" -> \"due\", \"test123\" -> \"test\"\n */\nfunction parseCompositeNamePart(part: string): {\n hasNumbers: boolean;\n cleaned: string;\n confidence: number;\n} {\n const hasNumbers = /\\d/.test(part);\n let confidence = 1.0;\n\n // Multiple strategies for cleaning names:\n // 1. Remove trailing numbers (john123 -> john)\n // 2. Remove interspersed numbers if they seem unnatural (jo1hn -> john)\n // 3. Remove leading numbers if followed by a valid name (1john -> john)\n // 4. Handle year patterns (john2023 -> john)\n // 5. Handle common number substitutions (j0hn -> john, 3ric -> eric)\n\n let cleaned = part;\n\n // Handle common leetspeak/number substitutions\n const leetSpeakMap: { [key: string]: string } = {\n '0': 'o',\n '1': 'i',\n '3': 'e',\n '4': 'a',\n '5': 's',\n '7': 't',\n '8': 'b',\n };\n\n // First check if it might be leetspeak\n if (hasNumbers && part.length >= 3) {\n let leetCleaned = part.toLowerCase();\n for (const [num, letter] of Object.entries(leetSpeakMap)) {\n leetCleaned = leetCleaned.replace(new RegExp(num, 'g'), letter);\n }\n\n // Check if the cleaned version is a known name\n if (isKnownFirstName(leetCleaned) || isKnownLastName(leetCleaned)) {\n cleaned = leetCleaned;\n confidence = 0.7; // Lower confidence for leetspeak conversions\n }\n }\n\n // If not leetspeak, try standard cleaning\n if (cleaned === part) {\n // Remove year-like suffixes\n const withoutYear = part.replace(/(19|20)\\d{2}$/, '');\n if (withoutYear !== part && withoutYear.length >= 2) {\n cleaned = withoutYear;\n confidence = 0.8;\n } else {\n // Try to extract alphabetic base by removing all numbers\n const pureAlpha = part.replace(/\\d+/g, '');\n\n // If we have a reasonable alphabetic base (at least 2 chars), use it\n // Also accept single letter if it's part of a pattern like j7.d2\n if (pureAlpha.length >= 2) {\n cleaned = pureAlpha;\n confidence = hasNumbers ? 0.85 : 1.0;\n } else if (pureAlpha.length === 1 && /^[a-zA-Z]$/.test(pureAlpha)) {\n // For single letters (like 'j' from 'j7'), accept them as valid initials\n cleaned = pureAlpha;\n confidence = 0.6; // Lower confidence for single letters\n } else {\n // Otherwise, try to extract base name without trailing numbers\n const baseMatch = part.match(/^([a-zA-Z]+)\\d*$/);\n if (baseMatch) {\n cleaned = baseMatch[1];\n confidence = 0.75;\n } else {\n // Handle mixed alphanumeric that doesn't match patterns\n cleaned = part;\n confidence = 0.4;\n }\n }\n }\n }\n\n // Boost confidence if the cleaned result is a known name\n if (cleaned !== part) {\n if (isKnownFirstName(cleaned) || isKnownLastName(cleaned)) {\n confidence = Math.min(1.0, confidence + 0.2);\n }\n }\n\n return { hasNumbers, cleaned, confidence };\n}\n\n/**\n * Check if string is likely a name (not containing invalid patterns)\n */\nfunction isLikelyName(str: string, allowNumbers = false, allowSingleLetter = false) {\n if (!str) return false;\n\n // Allow single letters if explicitly permitted (for patterns like j7.d2)\n if (str.length < 2 && !allowSingleLetter) return false;\n if (str.length === 1 && allowSingleLetter && /^[a-zA-Z]$/.test(str)) return true;\n\n // Check if it's a common email prefix that's not a name\n if (commonNameSuffixes.includes(str.toLowerCase())) return false;\n\n // If allowing numbers (for composite names), be more lenient\n if (allowNumbers) {\n // Still reject if it's ALL numbers\n if (/^\\d+$/.test(str)) return false;\n // Accept mixed alphanumeric patterns\n return true;\n }\n\n // Check if it contains too many numbers (likely not a name)\n const digitCount = (str.match(/\\d/g) || []).length;\n if (digitCount > str.length * 0.3) return false;\n\n // Check if it's all uppercase or all lowercase (less likely to be a properly formatted name)\n // But still allow it with lower confidence\n\n return true;\n}\n\n/**\n * Default name detection method\n * Attempts to extract first and last name from email local part\n */\nexport function defaultNameDetectionMethod(email: string): DetectedName | null {\n if (!email?.includes('@')) {\n return null;\n }\n\n const [localPart] = email.split('@');\n if (!localPart) {\n return null;\n }\n\n // Remove plus sign and anything after it (email aliases)\n const localWithoutAlias = localPart.split('+')[0];\n\n // For initial processing, keep the original (don't remove trailing numbers yet)\n // We'll handle numbers more intelligently based on context\n const cleanedLocal = localWithoutAlias;\n\n // Special handling for no-reply variants\n if (cleanedLocal.toLowerCase() === 'no-reply' || cleanedLocal.toLowerCase() === 'noreply') {\n return null;\n }\n\n let firstName: string | undefined;\n let lastName: string | undefined;\n let confidence = 0;\n\n // Check for CamelCase pattern first (like johnDoe or JohnSmith)\n const camelCasePatterns = [\n /^([a-z]+)([A-Z][a-z]+)$/, // johnDoe\n /^([A-Z][a-z]+)([A-Z][a-z]+)$/, // JohnSmith\n /^([a-z]+)([A-Z][a-z]+)([A-Z][a-z]+)$/, // johnMcDonald\n ];\n\n for (const pattern of camelCasePatterns) {\n const match = cleanedLocal.match(pattern);\n if (match) {\n if (match.length === 3) {\n // Two parts\n const [, first, last] = match;\n if (isLikelyName(first) && isLikelyName(last)) {\n const firstScore = getFirstNameScore(first);\n const lastScore = getLastNameScore(last);\n\n firstName = capitalizeName(first);\n lastName = capitalizeName(last);\n confidence = 0.7 + (firstScore + lastScore) * 0.15; // 0.7-1.0 based on name recognition\n break;\n }\n } else if (match.length === 4) {\n // Three parts (like johnMcDonald)\n const [, first, middle, last] = match;\n const combined = middle + last; // Combine for names like McDonald\n\n if (isLikelyName(first)) {\n firstName = capitalizeName(first);\n lastName = capitalizeName(combined);\n confidence = 0.75;\n break;\n }\n }\n }\n }\n\n // If no CamelCase match, try different separator patterns\n if (!firstName && !lastName) {\n for (const separator of nameSeparator) {\n if (cleanedLocal.includes(separator)) {\n const parts = cleanedLocal.split(separator).filter((p) => p.length > 0);\n\n if (parts.length === 2) {\n const [first, last] = parts;\n\n // Check for title at the beginning\n if (isTitle(first)) {\n // Skip title and use second part as first name if there's a third part\n continue;\n }\n\n // Parse composite parts (may contain numbers)\n const firstParsed = parseCompositeNamePart(first);\n const lastParsed = parseCompositeNamePart(last);\n\n // Calculate name likelihood scores\n const firstNameScore = getFirstNameScore(firstParsed.cleaned);\n const lastNameScore = getLastNameScore(lastParsed.cleaned);\n\n // Determine if order should be reversed (last.first pattern)\n const reverseScore = getLastNameScore(firstParsed.cleaned) + getFirstNameScore(lastParsed.cleaned);\n const normalScore = firstNameScore + lastNameScore;\n\n // Check if both parts could be names (more lenient with numbers and single letters)\n // But be more restrictive: only allow single letters if the other part is longer\n const firstLikely = isLikelyName(first, true, true);\n const lastLikely = isLikelyName(last, true, true);\n\n // Additional check: if one part is a single letter, the other should be at least 2 characters\n const oneIsSingleLetter = first.length === 1 || last.length === 1;\n const otherIsLongEnough = oneIsSingleLetter\n ? first.length === 1\n ? last.length >= 2\n : first.length >= 2\n : true;\n\n const bothPartsValid = firstLikely && lastLikely && otherIsLongEnough;\n\n if (bothPartsValid) {\n // Smart handling: Always try to extract clean names when possible\n // For patterns like john1.due2, we want \"John\" and \"Due\"\n\n // Determine name order based on scores\n const useReversed = reverseScore > normalScore * 1.2; // Bias toward normal order\n\n if (firstParsed.hasNumbers || lastParsed.hasNumbers) {\n // At least one part has numbers - intelligently clean them\n const cleanedFirst = firstParsed.cleaned;\n const cleanedLast = lastParsed.cleaned;\n\n // Check if the cleaned versions are valid names (allow single letters for patterns like j7.d2)\n if (isLikelyName(cleanedFirst, false, true) && isLikelyName(cleanedLast, false, true)) {\n // Successfully cleaned to valid names\n if (useReversed) {\n firstName = capitalizeName(cleanedLast);\n lastName = capitalizeName(cleanedFirst);\n } else {\n firstName = capitalizeName(cleanedFirst);\n lastName = capitalizeName(cleanedLast);\n }\n\n // Calculate confidence based on multiple factors\n const baseConfidence = 0.7;\n const separatorBonus = separator === '.' ? 0.15 : separator === '_' ? 0.05 : 0;\n const nameRecognitionBonus = normalScore > 0.5 ? 0.1 : 0;\n const cleaningPenalty = (firstParsed.confidence + lastParsed.confidence) / 2 - 1; // -1 to 0\n\n confidence = Math.min(0.95, baseConfidence + separatorBonus + nameRecognitionBonus + cleaningPenalty);\n } else {\n // Fallback to keeping numbers if cleaning doesn't produce valid names\n // This handles cases like \"a1.b2\" where removing numbers leaves too little\n firstName = capitalizeName(first);\n lastName = capitalizeName(last);\n confidence = 0.5; // Lower confidence for alphanumeric patterns\n }\n } else {\n // Neither has numbers - regular name\n if (useReversed) {\n firstName = capitalizeName(last);\n lastName = capitalizeName(first);\n } else {\n firstName = capitalizeName(first);\n lastName = capitalizeName(last);\n }\n\n // Calculate confidence\n const baseConfidence = 0.75;\n const separatorBonus = separator === '.' ? 0.15 : separator === '_' ? 0.05 : 0;\n const nameRecognitionBonus = Math.min(0.15, normalScore * 0.15);\n\n confidence = Math.min(0.95, baseConfidence + separatorBonus + nameRecognitionBonus);\n }\n\n break;\n }\n } else if (parts.length === 3) {\n // Handle cases like first.middle.last or first.last.suffix\n const [first, middle, last] = parts;\n\n // Parse composite parts\n const firstParsed = parseCompositeNamePart(first);\n const middleParsed = parseCompositeNamePart(middle);\n const lastParsed = parseCompositeNamePart(last);\n\n // Check if last part is likely a suffix (mail, email, etc.)\n const isLastSuffix =\n commonNameSuffixes.includes(last.toLowerCase()) ||\n contextualSuffixes.includes(last.toLowerCase()) ||\n isYearLike(last);\n\n if (isLastSuffix) {\n if (isLikelyName(first, true, true) && isLikelyName(middle, true, true)) {\n // Clean numbers from names if present\n const cleanedFirst = firstParsed.hasNumbers ? firstParsed.cleaned : first;\n const cleanedMiddle = middleParsed.hasNumbers ? middleParsed.cleaned : middle;\n\n if (isLikelyName(cleanedFirst, false, true) && isLikelyName(cleanedMiddle, false, true)) {\n firstName = capitalizeName(cleanedFirst);\n lastName = capitalizeName(cleanedMiddle);\n confidence = 0.7;\n } else {\n firstName = capitalizeName(first);\n lastName = capitalizeName(middle);\n confidence = 0.65;\n }\n break;\n }\n } else if (isLikelyName(first, true, true) && isLikelyName(last, true, true)) {\n // Intelligently handle three-part names\n const cleanedFirst = firstParsed.hasNumbers ? firstParsed.cleaned : first;\n const cleanedLast = lastParsed.hasNumbers ? lastParsed.cleaned : last;\n\n if (isLikelyName(cleanedFirst, false, true) && isLikelyName(cleanedLast, false, true)) {\n firstName = capitalizeName(cleanedFirst);\n lastName = capitalizeName(cleanedLast);\n confidence = 0.75;\n } else {\n // Fallback if cleaning doesn't produce valid names\n firstName = capitalizeName(first);\n lastName = capitalizeName(last);\n confidence = 0.55;\n }\n break;\n }\n } else if (parts.length > 3) {\n // Handle complex composite names with multiple parts\n // Take first and last meaningful parts\n const firstPart = parts[0];\n\n // Check if last part is a suffix to ignore\n const lastPartLower = parts[parts.length - 1].toLowerCase();\n const isLastPartSuffix =\n commonNameSuffixes.includes(lastPartLower) ||\n contextualSuffixes.includes(lastPartLower) ||\n isYearLike(parts[parts.length - 1]);\n const effectiveLastIndex = isLastPartSuffix ? parts.length - 2 : parts.length - 1;\n const lastToUse = effectiveLastIndex >= 0 ? parts[effectiveLastIndex] : null;\n\n if (lastToUse && isLikelyName(firstPart, true, true) && isLikelyName(lastToUse, true, true)) {\n const firstParsed = parseCompositeNamePart(firstPart);\n const lastParsed = parseCompositeNamePart(lastToUse);\n\n // Try to clean names intelligently\n const cleanedFirst = firstParsed.hasNumbers ? firstParsed.cleaned : firstPart;\n const cleanedLast = lastParsed.hasNumbers ? lastParsed.cleaned : lastToUse;\n\n if (isLikelyName(cleanedFirst, false, true) && isLikelyName(cleanedLast, false, true)) {\n firstName = capitalizeName(cleanedFirst);\n lastName = capitalizeName(cleanedLast);\n confidence = 0.6;\n } else {\n firstName = capitalizeName(firstPart);\n lastName = capitalizeName(lastToUse);\n confidence = 0.5;\n }\n break;\n }\n }\n }\n }\n }\n\n // Additional pattern: underscore_case or CONSTANT_CASE\n if (!firstName && !lastName) {\n const underscoreMatch = cleanedLocal.match(/^([A-Z_]+)$/);\n if (underscoreMatch) {\n const parts = cleanedLocal\n .toLowerCase()\n .split('_')\n .filter((p) => p.length > 0);\n if (parts.length === 2) {\n const [first, last] = parts;\n if (isLikelyName(first) && isLikelyName(last)) {\n firstName = capitalizeName(first);\n lastName = capitalizeName(last);\n confidence = 0.65;\n }\n }\n }\n }\n\n // If still no match, check if the whole local part could be a single name\n if (!firstName && !lastName) {\n const parsed = parseCompositeNamePart(cleanedLocal);\n\n // Check if it could be a single name (allow alphanumeric but NOT single letters)\n if (isLikelyName(cleanedLocal, true, false)) {\n if (/^[a-zA-Z]+$/.test(cleanedLocal)) {\n // Pure alphabetic - likely a single name\n const nameScore = Math.max(getFirstNameScore(cleanedLocal), getLastNameScore(cleanedLocal));\n\n // Determine if it's more likely a first or last name\n if (getFirstNameScore(cleanedLocal) >= getLastNameScore(cleanedLocal)) {\n firstName = capitalizeName(cleanedLocal);\n } else {\n lastName = capitalizeName(cleanedLocal);\n }\n\n confidence = 0.4 + nameScore * 0.3; // 0.4-0.7 based on name recognition\n } else if (parsed.hasNumbers && parsed.cleaned.length >= 2) {\n // Has numbers but we can extract a clean name\n const cleanedScore = Math.max(getFirstNameScore(parsed.cleaned), getLastNameScore(parsed.cleaned));\n\n if (getFirstNameScore(parsed.cleaned) >= getLastNameScore(parsed.cleaned)) {\n firstName = capitalizeName(parsed.cleaned);\n } else {\n lastName = capitalizeName(parsed.cleaned);\n }\n\n confidence = 0.3 + cleanedScore * 0.2 + parsed.confidence * 0.2; // 0.3-0.7 based on multiple factors\n }\n }\n }\n\n if (!firstName && !lastName) {\n return null;\n }\n\n return {\n firstName,\n lastName,\n confidence: Math.max(0, Math.min(1, confidence)), // Ensure confidence is between 0 and 1\n };\n}\n\n/**\n * Detect name from email address\n * @param params - Detection parameters including email and optional custom method\n * @returns Detected name with confidence score, or null if no name detected\n */\nexport function detectNameFromEmail(params: NameDetectionParams): DetectedName | null {\n const { email, customMethod } = params;\n\n if (!email?.includes('@')) {\n return null;\n }\n\n // Use custom method if provided\n if (customMethod) {\n try {\n return customMethod(email);\n } catch (error) {\n // Fall back to default method if custom method fails\n console.warn('Custom name detection method failed, falling back to default:', error);\n }\n }\n\n // Use default method\n return defaultNameDetectionMethod(email);\n}\n\n/**\n * Clean name by removing special characters (dots, underscores, asterisks)\n * Specifically designed for Algorithm name processing\n *\n * @param name - The name to clean\n * @returns The cleaned name with special characters removed\n */\nexport function cleanNameForAlgorithm(name: string): string {\n if (!name) return '';\n\n // Remove dots, underscores, and asterisks\n let cleaned = name.replace(/[._*]/g, '');\n\n // Normalize multiple spaces to single space\n cleaned = cleaned.replace(/\\s+/g, ' ').trim();\n\n // If the name is now empty after cleaning, return the original\n if (!cleaned) {\n return name;\n }\n\n return cleaned;\n}\n\n/**\n * Enhanced name detection for Algorithm with aggressive cleaning\n * Removes dots, underscores, and asterisks from detected names\n *\n * @param email - Email address to extract name from\n * @returns Detected name with cleaned special characters, or null if no name detected\n */\nexport function detectNameForAlgorithm(email: string): DetectedName | null {\n const detectedName = detectName(email);\n\n if (!detectedName) {\n return null;\n }\n\n // Clean first name and last name by removing special characters\n const cleanedFirstName = detectedName.firstName ? cleanNameForAlgorithm(detectedName.firstName) : undefined;\n const cleanedLastName = detectedName.lastName ? cleanNameForAlgorithm(detectedName.lastName) : undefined;\n\n // If both names are empty after cleaning, return null\n if (!cleanedFirstName && !cleanedLastName) {\n return null;\n }\n\n return {\n firstName: cleanedFirstName,\n lastName: cleanedLastName,\n confidence: detectedName.confidence * 0.95, // Slightly reduce confidence due to cleaning\n };\n}\n\n/**\n * Convenience function to detect name from email string\n * @param email - Email address to extract name from\n * @returns Detected name with confidence score, or null if no name detected\n */\nexport function detectName(email: string): DetectedName | null {\n return detectNameFromEmail({ email });\n}\n","/**\n * SMTP mailbox probe.\n *\n * Walks `mxRecords` in priority order, then `ports` in the configured order.\n * Returns the first attempt that yields a definitive answer (250 / 550 / 552 /\n * 452); on indeterminate outcomes (timeouts, connection resets, EHLO failures,\n * unrecognized responses), falls through to the next MX×port pair.\n *\n * Per-attempt dialogue:\n * greeting → EHLO → MAIL FROM → RCPT TO real → RCPT TO probe → RSET\n *\n * The probe RCPT uses a guaranteed-nonexistent random local-part so we can\n * detect catch-all MXes (Outlook / Yahoo / Office 365 / ProtonMail / many\n * corporates accept every recipient at the MX layer and bounce later).\n * When both real + probe return 250, `result.isCatchAll = true` and callers\n * know the deliverability signal is unreliable but that the address syntax\n * was at least accepted.\n *\n * The envelope (real RCPT + probe RCPT + RSET) is batched via PIPELINING\n * (RFC 2920) when the MX advertises support — roughly halves wire-level\n * latency. Tests can disable with `pipelining: 'never'` for deterministic\n * `socket.write()` call counts.\n *\n * Every result carries a `metrics` block with `mxAttempts`, `portAttempts`,\n * `mxHostsTried`, `mxHostUsed?`, `totalDurationMs` — useful for region-health\n * dashboards and root-cause-analysis when probes go wrong.\n */\n\nimport { randomBytes } from 'node:crypto';\nimport * as net from 'node:net';\nimport * as tls from 'node:tls';\nimport { getCacheStore } from './cache';\nimport type {\n SMTPSequence,\n SMTPTLSConfig,\n SMTPVerifyOptions,\n SmtpProbeMetrics,\n SmtpVerificationResult,\n VerifyMailboxSMTPParams,\n} from './types';\nimport { SMTPStep } from './types';\n\nconst DEFAULT_PORTS = [25, 587, 465]; // plain → STARTTLS-able → implicit-TLS\nconst DEFAULT_TIMEOUT_MS = 3000;\n/** ms to wait for QUIT to drain before forcibly destroying the socket. */\nconst QUIT_DRAIN_MS = 100;\n\n/** Implicit-TLS map. Plain ports advertise STARTTLS via EHLO; we do not auto-upgrade. */\nconst PORT_TLS: Record<number, boolean> = { 25: false, 587: false, 465: true };\n\n/** True for IPv4 / IPv6 in any form (compressed, mapped, mixed). */\nconst isIPAddress = (host: string): boolean => net.isIP(host) !== 0;\n\nexport interface ParsedDsn {\n /** 2 = success, 4 = transient, 5 = permanent */\n class: number;\n /** 1 addressing, 2 mailbox, 3 mail-system, 4 network, 5 protocol, 6 message, 7 security/policy */\n subject: number;\n detail: number;\n}\n\n/**\n * Parse an RFC 3463 enhanced status code at the start of an SMTP reply.\n * Examples: \"550 5.1.1 user unknown\" → {5,1,1}; \"421 4.7.0 try later\" → {4,7,0}.\n */\nexport function parseDsn(reply: string): ParsedDsn | null {\n const match = reply.match(/^\\d{3}[ -](\\d)\\.(\\d{1,3})\\.(\\d{1,3})\\b/);\n if (!match) return null;\n return { class: Number(match[1]), subject: Number(match[2]), detail: Number(match[3]) };\n}\n\nfunction dsnToString(dsn: ParsedDsn): string {\n return `${dsn.class}.${dsn.subject}.${dsn.detail}`;\n}\n\nfunction isPolicyBlock(reply: string): boolean {\n const dsn = parseDsn(reply);\n return dsn?.class === 5 && dsn?.subject === 7;\n}\n\nconst HIGH_VOLUME_RE =\n /(high number of|our system has detected unusual activity|contact your service provider for support|\\[irr\\])/i;\nconst OVER_QUOTA_RE = /(over quota)/i;\nconst INVALID_MAILBOX_PREFIX_RE = /^(510|511|513|550|551|553)/;\nconst INVALID_MAILBOX_FALSE_POSITIVE_RE = /(junk|spam|openspf|spoofing|host|rbl.+blocked)/i;\nconst MULTILINE_RE = /^\\d{3}-/;\n\nconst isHighVolume = (reply: string): boolean => HIGH_VOLUME_RE.test(reply);\nconst isOverQuota = (reply: string): boolean => OVER_QUOTA_RE.test(reply);\n\nfunction isInvalidMailboxError(reply: string): boolean {\n if (!INVALID_MAILBOX_PREFIX_RE.test(reply)) return false;\n if (INVALID_MAILBOX_FALSE_POSITIVE_RE.test(reply)) return false;\n if (isPolicyBlock(reply)) return false;\n return true;\n}\n\n/**\n * 16 hex characters + suffix — long enough to never collide with any real\n * mailbox, structured so it's clearly synthetic and passes the local-part\n * syntax checks of every common MX.\n */\nfunction defaultProbeLocal(): string {\n return `${randomBytes(8).toString('hex')}-noexist`;\n}\n\n/**\n * Public entry point. Walks `mxRecords × ports` and returns the first\n * definitive answer. Always:\n * - iterates MX records on indeterminate outcomes (no flag)\n * - runs the catch-all dual-probe (no flag)\n * - populates `result.metrics` and `result.enhancedStatus`\n *\n * Opt-in only:\n * - `captureTranscript: true` returns the wire transcript on the result\n * - `pipelining: 'never'` disables PIPELINING for deterministic tests\n * - `catchAllProbeLocal` overrides the random-local generator\n */\nexport async function verifyMailboxSMTP(\n params: VerifyMailboxSMTPParams\n): Promise<{ smtpResult: SmtpVerificationResult; cached: boolean; port: number; portCached: boolean }> {\n const { local, domain, options = {} } = params;\n // Coerce null → empty array (destructuring default only fires on undefined).\n const mxRecords = params.mxRecords ?? [];\n // Filter out non-integer / out-of-range ports — net.connect throws RangeError\n // synchronously for those, which would crash the promise executor.\n const ports = (options.ports ?? DEFAULT_PORTS).filter((port) => Number.isInteger(port) && port > 0 && port < 65536);\n const perAttemptTimeoutMs = options.perAttemptTimeoutMs ?? DEFAULT_TIMEOUT_MS;\n const tlsConfig = options.tlsConfig ?? true;\n const heloHostname = options.heloHostname ?? 'localhost';\n const debug = options.debug ?? false;\n const captureTranscript = options.captureTranscript ?? false;\n const sequence = options.sequence;\n const cache = options.cache;\n const log = debug ? (...args: unknown[]) => console.log('[SMTP]', ...args) : () => {};\n\n // Early-stop policy.\n const totalDeadlineMs = options.totalDeadlineMs;\n const maxConsecutiveFailures = options.maxConsecutiveFailures;\n const maxMxHosts = options.maxMxHosts;\n const retryAttempts = options.retry?.attempts ?? 0;\n const retryDelayMs = options.retry?.delayMs ?? 200;\n const retryBackoff = options.retry?.backoff ?? 'exponential';\n\n const startedAtMs = Date.now();\n\n const primaryMx = mxRecords[0];\n if (!primaryMx) {\n log('No MX records found');\n const metrics = makeMetrics([], 0, 0, undefined, startedAtMs);\n return { smtpResult: failureResult('no_mx_records', metrics), cached: false, port: 0, portCached: false };\n }\n log(`Verifying ${local}@${domain} via ${primaryMx} (mx count=${mxRecords.length})`);\n\n const transcript: string[] = [];\n const commands: string[] = [];\n\n const probeOptions: ProbeOptions = {\n local,\n domain,\n perAttemptTimeoutMs,\n tlsConfig,\n heloHostname,\n sequence,\n log,\n catchAllProbeLocal: options.catchAllProbeLocal,\n pipelining: options.pipelining ?? 'auto',\n startTls: options.startTls ?? 'auto',\n };\n\n // Cache short-circuits — keyed on the primary MX so the cache key matches\n // what callers compute from `mxRecords[0]`.\n const verdictCache = cache ? getCacheStore<SmtpVerificationResult>(cache, 'smtp') : null;\n const verdictKey = `${primaryMx}:${local}@${domain}`;\n if (verdictCache) {\n const cachedResult = await safeCacheGet(verdictCache, verdictKey);\n if (cachedResult) {\n log(`Using cached SMTP result: ${cachedResult.isDeliverable}`);\n return { smtpResult: cachedResult, cached: true, port: 0, portCached: false };\n }\n }\n\n const portCache = cache ? getCacheStore<number>(cache, 'smtpPort') : null;\n const cachedPort = portCache ? await safeCacheGet(portCache, primaryMx) : null;\n\n const mxHostsTried: string[] = [];\n let mxAttempts = 0;\n let portAttempts = 0;\n let consecutiveFailures = 0;\n let lastReason = 'all_attempts_failed';\n let lastEnhancedStatus: string | undefined;\n let lastResponseCode: number | undefined;\n let stoppedEarly: 'deadline' | 'consecutive_failures' | 'max_mx_hosts' | null = null;\n\n /** Connection-class outcomes count toward `maxConsecutiveFailures`; everything else resets it. */\n const isConnectionFailure = (reason: string): boolean =>\n reason === 'connection_error' ||\n reason === 'connection_timeout' ||\n reason === 'connection_closed' ||\n reason === 'socket_timeout';\n\n /** Compute backoff delay for the Nth retry (1-indexed). */\n const retryDelayFor = (attemptIndex: number): number =>\n retryBackoff === 'exponential' ? retryDelayMs * 2 ** (attemptIndex - 1) : retryDelayMs;\n\n /** Run one probe attempt with optional retries on connection-class failures. */\n const probeWithRetry = async (mxHost: string, port: number): Promise<ProbeResult> => {\n let lastProbe = await runProbe({ ...probeOptions, mxHost, port });\n for (let i = 1; i <= retryAttempts; i++) {\n if (lastProbe.result !== null || !isConnectionFailure(lastProbe.reason)) break;\n const delay = retryDelayFor(i);\n log(`retry ${i}/${retryAttempts} on ${mxHost}:${port} after ${delay}ms (last: ${lastProbe.reason})`);\n await new Promise((r) => setTimeout(r, delay));\n portAttempts++;\n lastProbe = await runProbe({ ...probeOptions, mxHost, port });\n }\n return lastProbe;\n };\n\n outer: for (const mxHost of mxRecords) {\n if (maxMxHosts !== undefined && mxAttempts >= maxMxHosts) {\n stoppedEarly = 'max_mx_hosts';\n break;\n }\n mxHostsTried.push(mxHost);\n mxAttempts++;\n\n // Cached-port fast path: only valid for the primary MX.\n const portsForThisMx =\n mxHost === primaryMx && cachedPort ? [cachedPort, ...ports.filter((p) => p !== cachedPort)] : ports;\n\n for (const port of portsForThisMx) {\n if (totalDeadlineMs !== undefined && Date.now() - startedAtMs >= totalDeadlineMs) {\n stoppedEarly = 'deadline';\n break outer;\n }\n portAttempts++;\n log(`Testing ${mxHost}:${port}`);\n const probe = await probeWithRetry(mxHost, port);\n collectTranscript(transcript, commands, probe, mxHost, port);\n lastReason = probe.reason;\n if (probe.enhancedStatus !== undefined) lastEnhancedStatus = probe.enhancedStatus;\n if (probe.responseCode !== undefined) lastResponseCode = probe.responseCode;\n\n // Definitive answer (250/251 deliverable, 550/552/etc. rejected) ends\n // the search. Indeterminate (null) falls through to the next port/MX.\n if (probe.result !== null) {\n const metrics = makeMetrics(mxHostsTried, mxAttempts, portAttempts, mxHost, startedAtMs);\n const smtpResult = toSmtpVerificationResult(probe, {\n transcript: captureTranscript ? transcript : undefined,\n commands: captureTranscript ? commands : undefined,\n metrics,\n });\n await safeCacheSet(verdictCache, verdictKey, smtpResult);\n if (mxHost === primaryMx) await safeCacheSet(portCache, primaryMx, port);\n return { smtpResult, cached: false, port, portCached: cachedPort === port };\n }\n\n // Track consecutive connection-class failures for the early-stop policy.\n consecutiveFailures = isConnectionFailure(probe.reason) ? consecutiveFailures + 1 : 0;\n if (maxConsecutiveFailures !== undefined && consecutiveFailures >= maxConsecutiveFailures) {\n stoppedEarly = 'consecutive_failures';\n break outer;\n }\n }\n }\n if (stoppedEarly) log(`Stopped early: ${stoppedEarly}`);\n\n // Every MX×port returned indeterminate — surface the LAST attempt's reason\n // so callers can see the failure mode (e.g. tls_error tells a different\n // story than connection_timeout).\n log(`All MX×port attempts failed (mx=${mxAttempts}, port=${portAttempts})`);\n const metrics = makeMetrics(mxHostsTried, mxAttempts, portAttempts, undefined, startedAtMs);\n const smtpResult: SmtpVerificationResult = {\n ...failureResult(lastReason, metrics),\n ...(lastEnhancedStatus !== undefined ? { enhancedStatus: lastEnhancedStatus } : {}),\n ...(lastResponseCode !== undefined ? { responseCode: lastResponseCode } : {}),\n ...(captureTranscript ? { transcript: [...transcript], commands: [...commands] } : {}),\n };\n return { smtpResult, cached: false, port: 0, portCached: false };\n}\n\nfunction makeMetrics(\n mxHostsTried: string[],\n mxAttempts: number,\n portAttempts: number,\n mxHostUsed: string | undefined,\n startedAtMs: number\n): SmtpProbeMetrics {\n return {\n mxAttempts,\n portAttempts,\n mxHostsTried: [...mxHostsTried],\n ...(mxHostUsed !== undefined ? { mxHostUsed } : {}),\n totalDurationMs: Date.now() - startedAtMs,\n };\n}\n\nfunction collectTranscript(\n transcript: string[],\n commands: string[],\n probe: ProbeResult,\n mxHost: string,\n port: number\n): void {\n const prefix = `${mxHost}:${port}`;\n for (const line of probe.transcript) transcript.push(`${prefix}|s| ${line}`);\n for (const cmd of probe.commands) commands.push(`${prefix}|c| ${cmd}`);\n}\n\nfunction failureResult(reason: string, metrics: SmtpProbeMetrics): SmtpVerificationResult {\n return {\n canConnectSmtp: false,\n hasFullInbox: false,\n isCatchAll: false,\n isDeliverable: false,\n isDisabled: false,\n error: reason,\n checkedAt: Date.now(),\n metrics,\n };\n}\n\ninterface ToResultExtras {\n transcript?: string[];\n commands?: string[];\n metrics: SmtpProbeMetrics;\n}\n\nfunction toSmtpVerificationResult(probe: ProbeResult, extras: ToResultExtras): SmtpVerificationResult {\n const result = probe.result;\n const out: SmtpVerificationResult = {\n canConnectSmtp: result !== null,\n hasFullInbox: probe.reason === 'over_quota',\n isCatchAll: probe.isCatchAll ?? false,\n isDeliverable: result === true,\n isDisabled: result === false,\n error: result === true ? undefined : probe.reason,\n checkedAt: Date.now(),\n metrics: extras.metrics,\n ...(probe.enhancedStatus !== undefined ? { enhancedStatus: probe.enhancedStatus } : {}),\n ...(probe.responseCode !== undefined ? { responseCode: probe.responseCode } : {}),\n };\n if (extras.transcript) out.transcript = [...extras.transcript];\n if (extras.commands) out.commands = [...extras.commands];\n return out;\n}\n\nasync function safeCacheGet<T>(\n store: { get: (k: string) => Promise<T | null | undefined> | T | null | undefined } | null,\n key: string\n): Promise<T | null> {\n if (!store) return null;\n try {\n const v = await store.get(key);\n return v ?? null;\n } catch {\n return null;\n }\n}\n\nasync function safeCacheSet<T>(\n store: { set: (k: string, v: T) => Promise<void> | void } | null,\n key: string,\n value: T\n): Promise<void> {\n if (!store) return;\n try {\n await store.set(key, value);\n } catch {\n // Cache write errors are non-fatal — the next call just re-probes.\n }\n}\n\ninterface ProbeOptions {\n local: string;\n domain: string;\n perAttemptTimeoutMs: number;\n tlsConfig: boolean | SMTPTLSConfig;\n heloHostname: string;\n sequence?: SMTPSequence;\n log: (...args: unknown[]) => void;\n catchAllProbeLocal?: SMTPVerifyOptions['catchAllProbeLocal'];\n pipelining: 'auto' | 'never' | 'force';\n startTls: 'auto' | 'never' | 'force';\n}\n\ninterface ProbeParams extends ProbeOptions {\n mxHost: string;\n port: number;\n}\n\ninterface ProbeResult {\n /** true=deliverable, false=hard-rejected, null=indeterminate */\n result: boolean | null;\n /** Short reason vocabulary — propagated to `SmtpVerificationResult.error`. */\n reason: string;\n /** RFC 3463 enhanced status from the most recent reply that carried one. */\n enhancedStatus?: string;\n /** SMTP response code from the most recent reply (e.g. 250, 550). */\n responseCode?: number;\n /**\n * Catch-all flag from the dual-probe. `true` when both real + probe RCPT\n * returned 250; `false` otherwise; `undefined` only if the probe never\n * reached the envelope phase (indeterminate before MAIL FROM).\n */\n isCatchAll?: boolean;\n /** Server lines, in arrival order, no port prefix. */\n transcript: string[];\n /** Client commands sent, in send order, no port prefix. */\n commands: string[];\n}\n\nasync function runProbe(p: ProbeParams): Promise<ProbeResult> {\n return new SMTPProbeConnection(p).run();\n}\n\n/** Buckets a numeric SMTP RCPT-TO reply into the dual-probe state machine. */\ntype RcptOutcome = 'pending' | 'accept' | 'soft_reject' | 'hard_reject';\n\n/** Phase of the dual-probe envelope (after MAIL FROM is accepted). */\ntype DualPhase = 'idle' | 'rcpt_real' | 'rcpt_probe' | 'rset';\n\n/**\n * One SMTP connection attempt. Lives for one MX×port; resolves to:\n * true — RCPT TO real accepted (with `isCatchAll` set when probe also 250)\n * false — RCPT TO real definitively rejected / over-quota\n * null — indeterminate (timeout, hangup, unrecognized, ehlo failure, etc.)\n */\nclass SMTPProbeConnection {\n // ── Connection state ─────────────────────────────────────────────────────\n private socket?: net.Socket | tls.TLSSocket;\n private buffer = '';\n private resolved = false;\n private currentStepIndex = 0;\n /** True for implicit-TLS ports (465) from the start, or after STARTTLS upgrade. */\n private isTLS: boolean;\n /** True between sending STARTTLS and the TLS handshake completing. */\n private tlsUpgrading = false;\n /**\n * True when we sent the second EHLO after a successful STARTTLS upgrade.\n * The EHLO response arrives while `currentStepIndex` is still on `startTls`\n * — this flag tells the dispatcher to advance past startTls when the\n * post-upgrade EHLO returns 250, instead of treating it as a STARTTLS\n * acknowledgement.\n */\n private postUpgradeReEhlo = false;\n private connectionTimer?: NodeJS.Timeout;\n private stepTimer?: NodeJS.Timeout;\n private resolveFn!: (value: ProbeResult) => void;\n\n // ── Dialogue tracking ────────────────────────────────────────────────────\n private readonly steps: SMTPStep[];\n private readonly tlsOptions: tls.ConnectionOptions;\n private readonly transcript: string[] = [];\n private readonly commands: string[] = [];\n /** Last RFC 3463 enhanced status seen (last-write semantics — most recent wins). */\n private lastEnhancedStatus?: string;\n /** Last 3-digit SMTP response code seen (last-write semantics). */\n private lastResponseCode?: number;\n\n // ── EHLO capability advertisement ────────────────────────────────────────\n private supportsPipelining = false;\n private supportsStartTls = false;\n\n // ── Dual-probe (catch-all detection) ─────────────────────────────────────\n private readonly probeLocal: string;\n private dualPhase: DualPhase = 'idle';\n private realOutcome: RcptOutcome = 'pending';\n private probeOutcome: RcptOutcome = 'pending';\n private dualPipelined = false;\n /**\n * Pipelined-only escape hatch. When the real RCPT is rejected mid-batched-\n * envelope, the probe + RSET are already on the wire; we stash the verdict\n * and commit it after the response loop drains.\n */\n private pendingDecision: { result: boolean | null; reason: string } | null = null;\n private isCatchAllFlag?: boolean;\n\n constructor(private readonly p: ProbeParams) {\n // Default sequence — every modern MX speaks ESMTP, so EHLO works on port 25 too.\n // STARTTLS is conditional: the executeStep handler skips it when the port is\n // already TLS, when the MX didn't advertise STARTTLS in 'auto' mode, or when\n // `startTls === 'never'`. Without it in the sequence, port 587 submission\n // MXes reject `MAIL FROM` with `530 Must issue STARTTLS first`.\n const defaultSteps = [SMTPStep.greeting, SMTPStep.ehlo, SMTPStep.startTls, SMTPStep.mailFrom, SMTPStep.rcptTo];\n this.steps = [...(p.sequence?.steps ?? defaultSteps)];\n this.isTLS = PORT_TLS[p.port] === true;\n const servername = isIPAddress(p.mxHost) ? undefined : p.mxHost;\n this.tlsOptions = {\n host: p.mxHost,\n servername,\n rejectUnauthorized: false,\n minVersion: 'TLSv1.2',\n ...(typeof p.tlsConfig === 'object' ? p.tlsConfig : {}),\n };\n this.probeLocal = p.catchAllProbeLocal ? p.catchAllProbeLocal(p.local, p.domain) : defaultProbeLocal();\n }\n\n run(): Promise<ProbeResult> {\n return new Promise<ProbeResult>((resolve) => {\n this.resolveFn = resolve;\n try {\n this.connect();\n this.armConnectionTimer();\n } catch (error) {\n // Synchronous net/tls.connect throws (RangeError on bad port, etc.)\n // collapse to the same `connection_error` reason as async errors so\n // callers can branch on a single key. The diagnostic detail is logged.\n this.p.log(`connect threw: ${error instanceof Error ? error.message : 'unknown'}`);\n this.finish(null, 'connection_error');\n }\n });\n }\n\n private connect(): void {\n const onConnect = () => {\n this.p.log(`Connected to ${this.p.mxHost}:${this.p.port}${this.isTLS ? ' with TLS' : ''}`);\n this.socket?.on('data', this.onData);\n };\n if (this.isTLS) {\n this.socket = tls.connect({ ...this.tlsOptions, port: this.p.port }, onConnect);\n } else {\n this.socket = net.connect({ host: this.p.mxHost, port: this.p.port }, onConnect);\n }\n this.socket.setTimeout(this.p.perAttemptTimeoutMs, () => this.finish(null, 'socket_timeout'));\n this.socket.on('error', () => this.finish(null, 'connection_error'));\n this.socket.on('close', () => this.finish(null, 'connection_closed'));\n }\n\n private armConnectionTimer(): void {\n this.connectionTimer = setTimeout(() => this.finish(null, 'connection_timeout'), this.p.perAttemptTimeoutMs);\n }\n\n private resetStepTimer(): void {\n if (this.stepTimer) clearTimeout(this.stepTimer);\n this.stepTimer = setTimeout(() => this.finish(null, 'step_timeout'), this.p.perAttemptTimeoutMs);\n }\n\n private onData = (data: Buffer | string): void => {\n if (this.resolved) return;\n this.resetStepTimer();\n this.buffer += typeof data === 'string' ? data : data.toString();\n let pos: number;\n while ((pos = this.buffer.indexOf('\\r\\n')) !== -1) {\n const line = this.buffer.slice(0, pos).trim();\n this.buffer = this.buffer.slice(pos + 2);\n this.processLine(line);\n }\n };\n\n private send(cmd: string): void {\n if (this.resolved) return;\n this.commands.push(cmd);\n this.p.log(`→ ${cmd}`);\n this.socket?.write(`${cmd}\\r\\n`);\n }\n\n private nextStep(): void {\n this.currentStepIndex++;\n const step = this.steps[this.currentStepIndex];\n if (step === undefined) {\n this.finish(true, 'sequence_complete');\n return;\n }\n this.executeStep(step);\n }\n\n private executeStep(step: SMTPStep): void {\n if (this.resolved) return;\n switch (step) {\n case SMTPStep.greeting:\n return; // server-driven; nothing to send\n case SMTPStep.ehlo:\n this.send(`EHLO ${this.p.heloHostname}`);\n return;\n case SMTPStep.helo:\n this.send(`HELO ${this.p.heloHostname}`);\n return;\n case SMTPStep.startTls:\n this.executeStartTls();\n return;\n case SMTPStep.mailFrom: {\n const from = this.p.sequence?.from ?? `<${this.p.local}@${this.p.domain}>`;\n this.send(`MAIL FROM:${from}`);\n return;\n }\n case SMTPStep.rcptTo:\n this.executeEnvelope();\n return;\n }\n }\n\n /**\n * Conditional STARTTLS upgrade. Skipped (advances to next step) when:\n * - already TLS (implicit-TLS port like 465 or already-upgraded)\n * - `startTls === 'never'`\n * - `startTls === 'auto'` AND the MX didn't advertise STARTTLS in EHLO\n *\n * Sends `STARTTLS` and waits for 220 when:\n * - `startTls === 'force'` (regardless of advertisement)\n * - `startTls === 'auto'` AND the MX advertised it\n *\n * On 220, `tls.connect()` wraps the existing socket. After the handshake\n * we re-EHLO (mandatory per RFC 3207 §4.2 — pre-TLS state must be\n * discarded) before continuing to MAIL FROM.\n */\n private executeStartTls(): void {\n const mode = this.p.startTls;\n const wantsUpgrade =\n !this.isTLS && mode !== 'never' && (mode === 'force' || (mode === 'auto' && this.supportsStartTls));\n\n if (!wantsUpgrade) {\n this.nextStep(); // advance to mailFrom\n return;\n }\n this.send('STARTTLS');\n }\n\n /**\n * Wrap the plaintext socket with TLS in place. Called after the server\n * answers our STARTTLS with 220. Detaches the plaintext-socket listeners\n * (TLS owns the underlying transport now), re-installs them on the wrapped\n * socket, resets EHLO-derived capabilities, and re-issues EHLO once the\n * handshake completes (RFC 3207 §4.2 mandates re-EHLO after upgrade —\n * pre-TLS state must be discarded).\n */\n private upgradeToTls(): void {\n const plainSocket = this.socket;\n if (!plainSocket) {\n this.finish(null, 'tls_upgrade_failed');\n return;\n }\n\n // Detach OUR listeners so the plaintext socket's events (which TLS now\n // drives internally) don't reach our handlers and prematurely call\n // finish(). TLS will install its own listeners on the wrapped socket.\n // Guarded: test mocks may not implement EventEmitter fully.\n const detach = (plainSocket as { removeAllListeners?: (ev: string) => void }).removeAllListeners;\n if (typeof detach === 'function') {\n detach.call(plainSocket, 'data');\n detach.call(plainSocket, 'error');\n detach.call(plainSocket, 'close');\n detach.call(plainSocket, 'timeout');\n }\n try {\n plainSocket.setTimeout(0);\n } catch {\n // Fake / already-destroyed sockets may not accept setTimeout — fine.\n }\n\n this.tlsUpgrading = true;\n const servername = isIPAddress(this.p.mxHost) ? undefined : this.p.mxHost;\n\n const tlsSocket = tls.connect({ ...this.tlsOptions, socket: plainSocket, servername }, () => {\n this.tlsUpgrading = false;\n this.isTLS = true;\n // RFC 3207 §4.2 — discard any pre-TLS server state. Capabilities\n // re-read from the second EHLO; the first set may have been a\n // downgrade attack (or legitimately different).\n this.buffer = '';\n this.supportsStartTls = false;\n this.supportsPipelining = false;\n this.postUpgradeReEhlo = true;\n this.send(`EHLO ${this.p.heloHostname}`);\n });\n\n this.socket = tlsSocket;\n this.socket.on('data', this.onData);\n // Distinguish handshake errors (the wrapped TLS layer) from later\n // post-upgrade socket errors so callers can tell what failed.\n this.socket.on('error', () => {\n this.finish(null, this.tlsUpgrading ? 'tls_handshake_failed' : 'connection_error');\n });\n this.socket.on('close', () => this.finish(null, 'connection_closed'));\n this.socket.setTimeout(this.p.perAttemptTimeoutMs, () => this.finish(null, 'socket_timeout'));\n }\n\n /**\n * Send the dual-probe envelope (real RCPT + probe RCPT + RSET). Pipelined\n * when the MX advertised PIPELINING (or `pipelining: 'force'`); sequential\n * otherwise.\n */\n private executeEnvelope(): void {\n const wantsPipelining = this.p.pipelining === 'force' || (this.p.pipelining === 'auto' && this.supportsPipelining);\n\n const realCmd = `RCPT TO:<${this.p.local}@${this.p.domain}>`;\n\n if (wantsPipelining) {\n // Batch real + probe + RSET into one socket.write(). Response phases\n // (rcpt_real → rcpt_probe → rset) demux replies in order.\n this.dualPipelined = true;\n const probeCmd = `RCPT TO:<${this.probeLocal}@${this.p.domain}>`;\n const rsetCmd = 'RSET';\n this.commands.push(realCmd, probeCmd, rsetCmd);\n this.p.log(`→ ${realCmd}`);\n this.p.log(`→ ${probeCmd}`);\n this.p.log(`→ ${rsetCmd}`);\n this.socket?.write(`${realCmd}\\r\\n${probeCmd}\\r\\n${rsetCmd}\\r\\n`);\n this.dualPhase = 'rcpt_real';\n return;\n }\n\n // Sequential — send real RCPT first; rest follows in handleEnvelopeReply.\n this.dualPipelined = false;\n this.send(realCmd);\n this.dualPhase = 'rcpt_real';\n }\n\n private processLine(line: string): void {\n if (this.resolved) return;\n this.transcript.push(line);\n this.p.log(`← ${line}`);\n\n // Parse code + DSN up-front so the result carries them even when a\n // heuristic short-circuits before dispatch.\n const codeStr = line.slice(0, 3);\n const numericCode = /^\\d{3}$/.test(codeStr) ? parseInt(codeStr, 10) : null;\n if (numericCode !== null) this.lastResponseCode = numericCode;\n const dsn = parseDsn(line);\n if (dsn) this.lastEnhancedStatus = dsnToString(dsn);\n\n // Heuristic early-returns fire pre-envelope and on the real-RCPT response.\n // Inside the probe/rset phases we ignore them — a probe response shouldn't\n // be classified as \"high volume\" or \"not found\" (those signals refer to\n // the real recipient). Multi-line replies (e.g. `452-4.2.2 over quota...`)\n // trigger the heuristics here BEFORE the multiline check returns early.\n if (this.dualPhase === 'idle' || this.dualPhase === 'rcpt_real') {\n if (isHighVolume(line)) {\n this.finish(true, 'high_volume');\n return;\n }\n if (isOverQuota(line)) {\n this.isCatchAllFlag = false;\n this.finish(false, 'over_quota');\n return;\n }\n if (isInvalidMailboxError(line)) {\n this.isCatchAllFlag = false;\n this.finish(false, 'not_found');\n return;\n }\n }\n\n // Multi-line continuation. Capture EHLO advertisements so we know\n // whether to use PIPELINING when the envelope phase fires.\n if (MULTILINE_RE.test(line)) {\n const step = this.steps[this.currentStepIndex];\n // Capability detection on EHLO multi-line. Also fires on the\n // post-STARTTLS re-EHLO (currentStep is `startTls` until we receive\n // the 250 below) so capabilities are re-read after the upgrade —\n // some MXes advertise different capabilities pre/post-TLS.\n const isEhloLike =\n step === SMTPStep.ehlo || step === SMTPStep.helo || (step === SMTPStep.startTls && this.postUpgradeReEhlo);\n if (isEhloLike && line.startsWith('250-')) {\n const upper = line.toUpperCase();\n if (upper.includes('PIPELINING')) this.supportsPipelining = true;\n if (upper.includes('STARTTLS')) this.supportsStartTls = true;\n }\n return;\n }\n\n if (numericCode === null) {\n this.finish(null, 'unrecognized_response');\n return;\n }\n\n this.dispatch(numericCode, line);\n }\n\n private dispatch(code: number, line: string): void {\n const step = this.steps[this.currentStepIndex];\n\n // Inside the envelope, route by phase.\n if (this.dualPhase !== 'idle' && step === SMTPStep.rcptTo) {\n this.handleEnvelopeReply(code, line);\n return;\n }\n\n switch (step) {\n case SMTPStep.greeting:\n if (code === 220) this.nextStep();\n else this.finish(null, 'no_greeting');\n return;\n case SMTPStep.ehlo:\n if (code === 250) this.nextStep();\n else this.finish(null, 'ehlo_failed');\n return;\n case SMTPStep.helo:\n if (code === 250) this.nextStep();\n else this.finish(null, 'helo_failed');\n return;\n case SMTPStep.startTls:\n // Two replies map to this step:\n // 1. The server's 220 response to our `STARTTLS` command —\n // handshake the wrapper socket and re-EHLO.\n // 2. The 250 response to that post-upgrade re-EHLO — advance to\n // MAIL FROM (skip startTls now that we've done the dance).\n if (this.postUpgradeReEhlo) {\n this.postUpgradeReEhlo = false;\n if (code === 250) this.nextStep();\n else this.finish(null, 'ehlo_failed');\n return;\n }\n if (code === 220) {\n this.upgradeToTls();\n } else {\n this.finish(null, 'tls_upgrade_failed');\n }\n return;\n case SMTPStep.mailFrom:\n if (code === 250) this.nextStep();\n else this.finish(null, 'mail_from_rejected');\n return;\n case SMTPStep.rcptTo:\n // Only reachable if dualPhase is idle on rcptTo — should never happen\n // in practice (executeEnvelope sets it). Treat as fall-through.\n this.handleEnvelopeReply(code, line);\n return;\n }\n }\n\n /**\n * Dual-probe / pipelined-envelope reply router. Demuxes server replies for\n * the three queued commands (real RCPT, probe RCPT, RSET) and resolves\n * with the catch-all-aware verdict.\n */\n private handleEnvelopeReply(code: number, line: string): void {\n if (this.dualPhase === 'rcpt_real') {\n this.realOutcome = classifyRcpt(code);\n\n // Over-quota short-circuits — the catch-all probe gives no extra signal.\n if (code === 552 || code === 452 || isOverQuota(line)) {\n this.isCatchAllFlag = false;\n if (this.dualPipelined) {\n this.pendingDecision = { result: false, reason: 'over_quota' };\n this.dualPhase = 'rcpt_probe';\n return;\n }\n this.finish(false, 'over_quota');\n return;\n }\n\n // Soft reject — temporary; further probing would hit the same rate-limit.\n if (this.realOutcome === 'soft_reject') {\n if (this.dualPipelined) {\n this.pendingDecision = { result: null, reason: 'temporary_failure' };\n this.dualPhase = 'rcpt_probe';\n return;\n }\n this.finish(null, 'temporary_failure');\n return;\n }\n\n // Hard reject — distinguish \"user unknown\" (clean not_found) from policy /\n // spam-flagged 5xx (genuinely ambiguous).\n if (this.realOutcome === 'hard_reject') {\n const reason = isInvalidMailboxError(line) ? 'not_found' : 'ambiguous';\n const result = reason === 'not_found' ? false : null;\n this.isCatchAllFlag = false;\n if (this.dualPipelined) {\n this.pendingDecision = { result, reason };\n this.dualPhase = 'rcpt_probe';\n return;\n }\n this.finish(result, reason);\n return;\n }\n\n // Real RCPT accepted — advance to probe phase.\n if (this.dualPipelined) {\n this.dualPhase = 'rcpt_probe';\n } else {\n this.send(`RCPT TO:<${this.probeLocal}@${this.p.domain}>`);\n this.dualPhase = 'rcpt_probe';\n }\n return;\n }\n\n if (this.dualPhase === 'rcpt_probe') {\n this.probeOutcome = classifyRcpt(code);\n if (this.dualPipelined) {\n this.dualPhase = 'rset';\n } else {\n this.send('RSET');\n this.dualPhase = 'rset';\n }\n return;\n }\n\n if (this.dualPhase === 'rset') {\n // RSET response received. We don't care about its code — it's just the\n // demux marker that the envelope is fully drained.\n if (this.pendingDecision) {\n // Pre-decided verdict from a real-RCPT reject; commit it now.\n this.finish(this.pendingDecision.result, this.pendingDecision.reason);\n return;\n }\n this.decideDualProbe();\n return;\n }\n }\n\n /** Final decision after both RCPT outcomes are known. Catch-all only when both 250. */\n private decideDualProbe(): void {\n if (this.realOutcome === 'accept' && this.probeOutcome === 'accept') {\n this.isCatchAllFlag = true;\n this.finish(true, 'valid');\n } else if (this.realOutcome === 'accept') {\n this.isCatchAllFlag = false;\n this.finish(true, 'valid');\n } else if (this.realOutcome === 'hard_reject') {\n this.isCatchAllFlag = false;\n this.finish(false, 'not_found');\n } else if (this.realOutcome === 'soft_reject') {\n this.finish(null, 'temporary_failure');\n } else {\n this.finish(null, 'ambiguous');\n }\n }\n\n private finish(result: boolean | null, reason: string): void {\n if (this.resolved) return;\n this.resolved = true;\n this.p.log(`${this.p.port}: ${reason}`);\n\n if (this.connectionTimer) clearTimeout(this.connectionTimer);\n if (this.stepTimer) clearTimeout(this.stepTimer);\n\n try {\n this.socket?.setTimeout(0);\n } catch {\n // Already destroyed.\n }\n try {\n this.socket?.write('QUIT\\r\\n');\n } catch {\n // Already destroyed.\n }\n const drain = setTimeout(() => this.socket?.destroy(), QUIT_DRAIN_MS);\n drain.unref?.();\n\n this.resolveFn({\n result,\n reason,\n ...(this.lastEnhancedStatus !== undefined ? { enhancedStatus: this.lastEnhancedStatus } : {}),\n ...(this.lastResponseCode !== undefined ? { responseCode: this.lastResponseCode } : {}),\n ...(this.isCatchAllFlag !== undefined ? { isCatchAll: this.isCatchAllFlag } : {}),\n transcript: this.transcript,\n commands: this.commands,\n });\n }\n}\n\nfunction classifyRcpt(code: number): RcptOutcome {\n if (code === 250 || code === 251) return 'accept';\n if (code >= 400 && code < 500) return 'soft_reject';\n return 'hard_reject';\n}\n","/**\n * Lightweight transcript collector used by `verifyEmail` to capture a\n * structured trace of every subsystem call (syntax / disposable / free /\n * MX / SMTP / WHOIS / name detection / domain suggestion).\n *\n * Two collectors:\n * - `ArrayTranscriptCollector` — accumulates steps, exposed in result.\n * - `NULL_COLLECTOR` — no-op singleton used when capture is disabled, so\n * the call sites in `verifyEmail` never need an `if (transcript)` branch.\n */\nimport type { VerificationStep, VerificationStepKind } from './types';\n\nexport interface TranscriptCollector {\n /** Run `fn`, time it, push a step record. Re-throws on error after recording. */\n record<T>(\n kind: VerificationStepKind,\n fn: () => Promise<T> | T,\n detailsFor: (value: T) => Record<string, unknown>\n ): Promise<T>;\n /** Push a pre-built step. Useful when timing is owned by the callee. */\n push(step: VerificationStep): void;\n}\n\nexport class ArrayTranscriptCollector implements TranscriptCollector {\n readonly steps: VerificationStep[] = [];\n\n async record<T>(\n kind: VerificationStepKind,\n fn: () => Promise<T> | T,\n detailsFor: (value: T) => Record<string, unknown>\n ): Promise<T> {\n const startedAt = Date.now();\n try {\n const value = await fn();\n this.steps.push({\n kind,\n startedAt,\n durationMs: Date.now() - startedAt,\n ok: true,\n details: detailsFor(value),\n });\n return value;\n } catch (error) {\n this.steps.push({\n kind,\n startedAt,\n durationMs: Date.now() - startedAt,\n ok: false,\n details: { error: error instanceof Error ? error.message : String(error) },\n });\n throw error;\n }\n }\n\n push(step: VerificationStep): void {\n this.steps.push(step);\n }\n}\n\n/** No-op collector — every method is a no-op. Used when capture is disabled. */\nexport const NULL_COLLECTOR: TranscriptCollector = {\n async record(_kind, fn) {\n return fn();\n },\n push() {\n // no-op\n },\n};\n","const defaultRegex = {\n domainName: 'Domain Name: *([^\\\\s]+)',\n registrar: 'Registrar: *(.+)',\n updatedDate: 'Updated Date: *(.+)',\n creationDate: 'Creat(ed|ion) Date: *(.+)',\n expirationDate: 'Expir\\\\w+ Date: *(.+)',\n status: 'Status:\\\\s*(.+)\\\\s*\\\\n',\n dateFormat: \"yyyy-MM-dd'T'HH:mm:ss'Z'\",\n notFound: '(No match for |Domain not found|NOT FOUND\\\\s)',\n};\n\nconst comRegex = { ...defaultRegex, notFound: 'No match for ' };\n\nconst orgRegex = { ...defaultRegex, notFound: '^(NOT FOUND|Domain not found)' };\n\nconst auRegex = {\n ...defaultRegex,\n updatedDate: 'Last Modified: *(.+)',\n registrar: 'Registrar Name: *(.+)',\n rateLimited: 'WHOIS LIMIT EXCEEDED',\n notFound: '^NOT FOUND',\n};\n\nconst usRegex = {\n ...defaultRegex,\n status: 'Domain Status: *(.+)',\n expirationDate: 'Registrar Registration Expiration Date: *(.+)',\n notFound: '^No Data Found',\n};\n\nconst ruRegex = {\n ...defaultRegex,\n domainName: 'domain: *([^\\\\s]+)',\n registrar: 'registrar: *(.+)',\n expirationDate: 'paid-till: *(.+)',\n status: 'state: *(.+)',\n notFound: 'No entries found',\n};\n\nconst ukRegex = {\n ...defaultRegex,\n domainName: 'Domain name:\\\\s*([^\\\\s]+)',\n dateFormat: 'dd-MMM-yyyy',\n};\n\nconst frRegex = {\n ...defaultRegex,\n domainName: 'domain: *([^\\\\s]+)',\n expirationDate: 'Expir\\\\w+ Date:\\\\s?(.+)',\n updatedDate: 'last-update: *(.+)',\n notFound: '(No entries found in |%% NOT FOUND)',\n};\n\nconst nlRegex = {\n ...defaultRegex,\n notFound: '\\\\.nl is free',\n rateLimited: 'maximum number of requests per second exceeded',\n};\n\nconst fiRegex = {\n ...defaultRegex,\n domainName: 'domain\\\\.*: *([\\\\S]+)',\n registrar: 'registrar\\\\.*: *(.*)',\n status: 'status\\\\.*: *([\\\\S]+)',\n dateFormat: 'dd.MM.yyyy HH:mm:ss',\n};\n\nconst jpRegex = {\n ...defaultRegex,\n domainName: '\\\\[Domain Name\\\\]\\\\s*([^\\\\s]+)',\n dateFormat: 'yyyy/MM/dd',\n notFound: 'No match!!',\n};\n\nconst plRegex = {\n ...defaultRegex,\n domainName: 'DOMAIN NAME: *([^\\\\s]+)\\\\s+',\n status: 'Registration status:\\\\n\\\\s*(.+)',\n expirationDate: 'renewal date: *(.+)',\n dateFormat: 'yyyy.MM.dd HH:mm:ss',\n};\n\nconst brRegex = {\n ...defaultRegex,\n domainName: 'domain: *([^\\\\s]+)\\\\n',\n dateFormat: 'yyyyMMdd',\n};\n\nconst euRegex = {\n ...defaultRegex,\n domainName: 'Domain: *([^\\\\n\\\\r]+)',\n registrar: 'Registrar: *\\\\n *Name: *([^\\\\n\\\\r]+)',\n notFound: 'Status: AVAILABLE',\n};\n\nconst eeRegex = {\n ...defaultRegex,\n domainName: 'Domain: *[\\\\n\\\\r]+\\\\s*name: *([^\\\\n\\\\r]+)',\n status: 'Domain: *[\\\\n\\\\r]+\\\\s*name: *[^\\\\n\\\\r]+\\\\s*status: *([^\\\\n\\\\r]+)',\n};\n\nconst krRegex = {\n ...defaultRegex,\n domainName: 'Domain Name\\\\s*: *([^\\\\s]+)',\n dateFormat: 'yyyy. MM. dd.',\n notFound: 'The requested domain was not found ',\n};\n\nconst bgRegex = {\n ...defaultRegex,\n domainName: 'DOMAIN NAME: *([^\\\\s]+)',\n status: 'registration status:\\\\s*(.+)',\n notFound: 'registration status: available',\n rateLimited: 'Query limit exceeded',\n};\n\nconst deRegex = {\n ...defaultRegex,\n domainName: 'Domain: *([^\\\\s]+)',\n notFound: 'Status: *free',\n};\n\nconst atRegex = {\n ...defaultRegex,\n domainName: 'domain: *([^\\\\s]+)',\n notFound: ' nothing found',\n dateFormat: 'yyyyMMdd HH:mm:ss',\n rateLimited: 'Quota exceeded',\n};\n\nconst caRegex = {\n ...defaultRegex,\n domainName: 'Domain Name: *([^\\\\s]+)',\n notFound: 'Not found: ',\n};\n\nconst beRegex = {\n ...defaultRegex,\n domainName: 'Domain:\\\\s*([^\\\\s]+)',\n dateFormat: 'ddd MMM dd yyyy',\n notFound: 'Status:\\\\s*AVAILABLE',\n};\n\nconst infoRegex = {\n ...defaultRegex,\n notFound: '^(NOT FOUND|Domain not found)',\n};\n\nconst kgRegex = {\n ...defaultRegex,\n domainName: '^Domain\\\\s*([^\\\\s]+)',\n dateFormat: 'ddd MMM dd HH:mm:ss yyyy',\n notFound: 'domain is available for registration',\n};\n\nconst idRegex = {\n ...defaultRegex,\n domainName: 'Domain Name:([^\\\\s]+)',\n dateFormat: \"dd-MMM-yyyy HH:mm:ss 'UTC'\",\n notFound: 'DOMAIN NOT FOUND',\n};\n\nconst skRegex = {\n ...defaultRegex,\n domainName: 'Domain:\\\\s*([^\\\\s]+)',\n notFound: 'Domain not found',\n};\n\nconst seRegex = {\n ...defaultRegex,\n domainName: 'domain\\\\.*: *([^\\\\s]+)',\n notFound: '\\\\\" not found.',\n};\n\nconst isRegex = {\n ...defaultRegex,\n domainName: 'domain\\\\.*: *([^\\\\s]+)',\n dateFormat: 'MMM dd yyyy',\n notFound: 'No entries found for query',\n};\n\nconst coRegex = {\n ...defaultRegex,\n notFound: 'No Data Found',\n};\n\ntype Regex = {\n registrar?: string;\n domainName?: string;\n notFound?: string;\n updatedDate?: string;\n creationDate?: string;\n expirationDate?: string;\n status?: string;\n rateLimited?: string;\n dateFormat?: string;\n};\n\nexport type ParsedWhoisResult = {\n domainName: string;\n isAvailable?: boolean;\n registryDomainId?: string;\n registrarWhoisServer?: string;\n registrar?: string;\n registrarUrl?: string;\n registrarIanaId?: string;\n registrarAbuseContactEmail?: string;\n registrarAbuseContactPhone?: string;\n updatedDate?: string | null;\n creationDate?: string | null;\n expirationDate?: string | null;\n status?: string[];\n dnssec?: string;\n nameServers?: string[];\n rateLimited?: boolean;\n notFound?: boolean;\n dateFormat?: string;\n};\n\n// Helper function to parse dates based on format string\nfunction parseDate(dateStr: string, format: string): Date | null {\n try {\n // Clean up the date string\n dateStr = dateStr.trim();\n\n // Handle ISO format. Validate before returning — `new Date('garbage')`\n // returns an Invalid Date object that crashes `.toISOString()` callers.\n if (format === \"yyyy-MM-dd'T'HH:mm:ss'Z'\" || dateStr.match(/^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}/)) {\n const isoDate = new Date(dateStr);\n return Number.isNaN(isoDate.getTime()) ? null : isoDate;\n }\n\n // Handle various date formats\n let date: Date | null = null;\n\n switch (format) {\n case 'yyyy/MM/dd': {\n const parts = dateStr.split('/');\n if (parts.length === 3) {\n date = new Date(`${parts[0]}-${parts[1].padStart(2, '0')}-${parts[2].padStart(2, '0')}`);\n }\n break;\n }\n case 'dd-MMM-yyyy': {\n // e.g., \"14-Sep-2023\"\n date = new Date(dateStr.replace(/-/g, ' '));\n break;\n }\n case 'dd.MM.yyyy HH:mm:ss': {\n const [datePart, timePart] = dateStr.split(' ');\n if (datePart) {\n const parts = datePart.split('.');\n if (parts.length === 3) {\n const dateString = `${parts[2]}-${parts[1].padStart(2, '0')}-${parts[0].padStart(2, '0')}`;\n date = new Date(`${dateString}${timePart ? `T${timePart}` : ''}`);\n }\n }\n break;\n }\n case 'yyyy.MM.dd HH:mm:ss': {\n const [datePart, timePart] = dateStr.split(' ');\n if (datePart) {\n const parts = datePart.split('.');\n if (parts.length === 3) {\n const dateString = `${parts[0]}-${parts[1].padStart(2, '0')}-${parts[2].padStart(2, '0')}`;\n date = new Date(`${dateString}${timePart ? `T${timePart}` : ''}`);\n }\n }\n break;\n }\n case 'yyyyMMdd': {\n if (dateStr.length === 8) {\n const year = dateStr.substring(0, 4);\n const month = dateStr.substring(4, 6);\n const day = dateStr.substring(6, 8);\n date = new Date(`${year}-${month}-${day}`);\n }\n break;\n }\n case 'yyyy. MM. dd.': {\n const cleaned = dateStr.replace(/\\./g, '').trim();\n const parts = cleaned.split(/\\s+/);\n if (parts.length === 3) {\n date = new Date(`${parts[0]}-${parts[1].padStart(2, '0')}-${parts[2].padStart(2, '0')}`);\n }\n break;\n }\n case 'ddd MMM dd yyyy': {\n // e.g., \"Thu Sep 14 2023\"\n const parts = dateStr.split(/\\s+/);\n if (parts.length >= 4) {\n date = new Date(`${parts[1]} ${parts[2]} ${parts[3]}`);\n }\n break;\n }\n case 'ddd MMM dd HH:mm:ss yyyy': {\n // e.g., \"Thu Sep 14 10:30:00 2023\"\n const parts = dateStr.split(/\\s+/);\n if (parts.length >= 5) {\n date = new Date(`${parts[1]} ${parts[2]} ${parts[4]} ${parts[3]}`);\n }\n break;\n }\n case 'yyyyMMdd HH:mm:ss': {\n const [datePart, timePart] = dateStr.split(' ');\n if (datePart && datePart.length === 8) {\n const year = datePart.substring(0, 4);\n const month = datePart.substring(4, 6);\n const day = datePart.substring(6, 8);\n date = new Date(`${year}-${month}-${day}${timePart ? `T${timePart}` : ''}`);\n }\n break;\n }\n case \"dd-MMM-yyyy HH:mm:ss 'UTC'\": {\n // e.g., \"14-Sep-2023 10:30:00 UTC\"\n const cleaned = dateStr.replace(/\\s*UTC\\s*$/, '');\n date = new Date(cleaned.replace(/-/g, ' '));\n break;\n }\n case 'MMM dd yyyy': {\n // e.g., \"Sep 14 2023\"\n date = new Date(dateStr);\n break;\n }\n default: {\n // Try parsing as ISO or standard format\n date = new Date(dateStr);\n }\n }\n\n // Check if the date is valid\n if (date && !Number.isNaN(date.getTime())) {\n return date;\n }\n\n // Fallback: try direct parsing\n const fallback = new Date(dateStr);\n if (!Number.isNaN(fallback.getTime())) {\n return fallback;\n }\n\n return null;\n } catch {\n return null;\n }\n}\n\n/**\n * TLD → registry-specific regex set. Multiple TLDs share a regex when their\n * WHOIS servers use the same response shape (`.com` and `.net` are both\n * served by Verisign with identical formatting).\n */\nconst TLD_REGEX: Record<string, Regex> = {\n com: comRegex,\n net: comRegex,\n name: comRegex,\n org: orgRegex,\n me: orgRegex,\n mobi: orgRegex,\n au: auRegex,\n ru: ruRegex,\n рф: ruRegex,\n su: ruRegex,\n us: usRegex,\n biz: usRegex,\n uk: ukRegex,\n fr: frRegex,\n nl: nlRegex,\n fi: fiRegex,\n jp: jpRegex,\n pl: plRegex,\n br: brRegex,\n eu: euRegex,\n ee: eeRegex,\n kr: krRegex,\n bg: bgRegex,\n de: deRegex,\n at: atRegex,\n ca: caRegex,\n be: beRegex,\n kg: kgRegex,\n info: infoRegex,\n id: idRegex,\n sk: skRegex,\n se: seRegex,\n nu: seRegex,\n is: isRegex,\n co: coRegex,\n};\n\n/** Generic free-text WHOIS fields shared across registries. */\nconst COMMON_FIELD_PATTERNS: ReadonlyArray<{\n pattern: RegExp;\n property: keyof ParsedWhoisResult;\n multiple?: boolean;\n}> = [\n { pattern: /Name Server:\\s*(.*)/gi, property: 'nameServers', multiple: true },\n { pattern: /Registrar URL:\\s*(.*)/i, property: 'registrarUrl' },\n { pattern: /Registrar WHOIS Server:\\s*(.*)/i, property: 'registrarWhoisServer' },\n { pattern: /Registry Domain ID:\\s*(.*)/i, property: 'registryDomainId' },\n { pattern: /Registrar Abuse Contact Email:\\s*(.*)/i, property: 'registrarAbuseContactEmail' },\n { pattern: /Registrar Abuse Contact Phone:\\s*(.*)/i, property: 'registrarAbuseContactPhone' },\n { pattern: /DNSSEC:\\s*(.*)/i, property: 'dnssec' },\n { pattern: /Registrar IANA ID:\\s*(.*)/i, property: 'registrarIanaId' },\n];\n\nconst ISO_DATE_FORMAT = \"yyyy-MM-dd'T'HH:mm:ss'Z'\";\n\nfunction pickRegex(domain: string): Regex {\n const tld = domain.split('.').pop()?.toLowerCase();\n if (!tld) return defaultRegex;\n return TLD_REGEX[tld] ?? defaultRegex;\n}\n\nfunction collectStatuses(rawData: string, pattern: string): string[] {\n const out: string[] = [];\n const re = new RegExp(pattern, 'gi');\n for (const match of rawData.matchAll(re)) {\n if (match[1]) out.push(match[1].trim());\n }\n return out;\n}\n\nfunction extractDate(rawData: string, pattern: string, dateFormat: string): string | undefined {\n // The default `Creat(ed|ion) Date:` pattern wraps the keyword in a capture\n // group, so we use a non-capturing variant when reading the value.\n const dateRegex = pattern.includes('Creat(ed|ion)') ? /Creat(?:ed|ion) Date:\\s*(.+)/i : new RegExp(pattern, 'i');\n const dateStr = rawData.match(dateRegex)?.[1]?.trim();\n if (!dateStr) return undefined;\n return parseDate(dateStr, dateFormat)?.toISOString() ?? dateStr;\n}\n\nfunction applyCommonFieldPatterns(rawData: string, result: ParsedWhoisResult): void {\n for (const { pattern, property, multiple } of COMMON_FIELD_PATTERNS) {\n if (multiple) {\n const matches = Array.from(rawData.matchAll(pattern));\n if (matches.length > 0) (result[property] as string[]) = matches.map((m) => m[1].trim());\n continue;\n }\n const match = rawData.match(pattern);\n if (match?.[1]) (result[property] as string) = match[1].trim();\n }\n}\n\nexport function parseWhoisData({ rawData, domain }: { rawData: string; domain: string }): ParsedWhoisResult {\n if (!rawData) return { domainName: domain, isAvailable: true };\n\n const result: ParsedWhoisResult = { domainName: domain };\n const regexSet = pickRegex(domain);\n const dateFormat = regexSet.dateFormat ?? ISO_DATE_FORMAT;\n\n for (const [key, pattern] of Object.entries(regexSet)) {\n if (!pattern || key === 'dateFormat') continue;\n if (!new RegExp(pattern, 'i').test(rawData)) continue;\n\n switch (key as keyof Regex) {\n case 'rateLimited':\n result.rateLimited = true;\n throw new Error('Rate Limited');\n case 'notFound':\n result.isAvailable = true;\n break;\n case 'status':\n result.status = collectStatuses(rawData, pattern);\n break;\n case 'creationDate':\n case 'expirationDate':\n case 'updatedDate': {\n const value = extractDate(rawData, pattern, dateFormat);\n if (value) result[key as 'creationDate' | 'expirationDate' | 'updatedDate'] = value;\n break;\n }\n case 'domainName': {\n const m = rawData.match(new RegExp(pattern, 'i'));\n if (m?.[1]) result.domainName = m[1].toLowerCase().trim();\n break;\n }\n case 'registrar': {\n const m = rawData.match(new RegExp(pattern, 'i'));\n if (m?.[1]) result.registrar = m[1].trim();\n break;\n }\n }\n }\n\n result.isAvailable ??= false;\n applyCommonFieldPatterns(rawData, result);\n return result;\n}\n","/**\n * WHOIS lookup — TCP query against a TLD-specific WHOIS server, then parse.\n *\n * Two public surfaces:\n * - `getDomainAge`: extracts creation date and computes age.\n * - `getDomainRegistrationStatus`: extracts registrar / status / expiry.\n *\n * Both share the same `getWhoisData` retrieval pipeline:\n * 1. Strip URL/email noise from the domain (`cleanDomain`).\n * 2. Validate via `psl`.\n * 3. Look up the TLD-specific server (or fall back through IANA's referral).\n * 4. TCP-query port 43 (`queryWhoisServer`).\n * 5. Cache the parsed result.\n */\nimport * as net from 'node:net';\nimport { isValid } from 'psl';\nimport { getCacheStore } from './cache';\nimport type { Cache } from './cache-interface';\nimport whoisServersJson from './data/whois-servers.json';\nimport type { DomainAgeInfo, DomainRegistrationInfo } from './types';\nimport { type ParsedWhoisResult, parseWhoisData } from './whois-parser';\n\ntype Logger = (...args: unknown[]) => void;\nconst noopLog: Logger = () => {};\n\nconst WHOIS_PORT = 43;\nconst IANA_FALLBACK_SERVER = 'whois.iana.org';\nconst whoisServers = whoisServersJson as Record<string, string>;\n\n/** Strip protocol, path, and email-prefix noise — return just the host. */\nfunction cleanDomain(input: string): string | null {\n const stripped = input\n .replace(/^https?:\\/\\//, '')\n .split('/')[0]\n ?.split('@')\n .pop();\n return stripped || null;\n}\n\n/** TCP query the WHOIS server on port 43 with a timeout. */\nfunction queryWhoisServer(domain: string, server: string, timeout: number, log: Logger): Promise<string> {\n return new Promise((resolve, reject) => {\n const client = new net.Socket();\n let data = '';\n\n log(`[whois] querying ${server} for ${domain}`);\n\n const timer = setTimeout(() => {\n log(`[whois] timeout after ${timeout}ms — ${domain} @ ${server}`);\n client.destroy();\n reject(new Error('WHOIS query timeout'));\n }, timeout);\n\n client.connect(WHOIS_PORT, server, () => {\n log(`[whois] connected to ${server}, sending query`);\n client.write(`${domain}\\r\\n`);\n });\n\n client.on('data', (chunk) => {\n data += chunk.toString();\n });\n\n client.on('close', () => {\n clearTimeout(timer);\n log(`[whois] received ${data.length} bytes from ${server}`);\n resolve(data);\n });\n\n client.on('error', (err) => {\n clearTimeout(timer);\n log(`[whois] error from ${server}: ${err.message}`);\n reject(err);\n });\n });\n}\n\n/** Pick the TLD-specific server, or fall back through IANA's referral. */\nasync function fetchAndParse(domain: string, timeout: number, log: Logger): Promise<ParsedWhoisResult> {\n const tld = domain.split('.').pop()?.toLowerCase();\n if (!tld) throw new Error('Invalid domain');\n\n const direct = whoisServers[tld];\n if (direct) {\n log(`[whois] using ${direct} for .${tld}`);\n const raw = await queryWhoisServer(domain, direct, timeout, log);\n return parseWhoisData({ rawData: raw, domain });\n }\n\n log(`[whois] no server for .${tld}, asking IANA`);\n const ianaResponse = await queryWhoisServer(domain, IANA_FALLBACK_SERVER, timeout, log);\n const referredServer = ianaResponse.match(/refer:\\s+(\\S+)/i)?.[1];\n if (referredServer) {\n log(`[whois] IANA referred us to ${referredServer}`);\n const raw = await queryWhoisServer(domain, referredServer, timeout, log);\n return parseWhoisData({ rawData: raw, domain });\n }\n return parseWhoisData({ rawData: ianaResponse, domain });\n}\n\nasync function getWhoisData(\n domain: string,\n timeout: number,\n log: Logger,\n cache?: Cache\n): Promise<ParsedWhoisResult | null> {\n const cacheKey = `whois:${domain}`;\n const cacheStore = getCacheStore<ParsedWhoisResult>(cache, 'whois');\n\n const cached = await cacheStore.get(cacheKey);\n if (cached) {\n log(`[whois] cache hit for ${domain}`);\n return cached as ParsedWhoisResult;\n }\n\n try {\n const data = await fetchAndParse(domain, timeout, log);\n await cacheStore.set(cacheKey, data);\n return data;\n } catch (error) {\n log(`[whois] failed for ${domain}: ${error instanceof Error ? error.message : String(error)}`);\n return null;\n }\n}\n\n/** Validate domain shape + parse + cache. Returns null on any failure. */\nasync function loadWhoisFor(\n domain: string,\n timeout: number,\n log: Logger,\n cache?: Cache\n): Promise<{ host: string; data: ParsedWhoisResult } | null> {\n const host = cleanDomain(domain);\n if (!host) {\n log(`[whois] invalid domain shape: ${domain}`);\n return null;\n }\n if (!isValid(host)) {\n log(`[whois] psl rejected: ${host}`);\n return null;\n }\n const data = await getWhoisData(host, timeout, log, cache);\n return data ? { host, data } : null;\n}\n\nexport async function getDomainAge(\n domain: string,\n timeout = 5000,\n debug = false,\n cache?: Cache\n): Promise<DomainAgeInfo | null> {\n const log: Logger = debug ? console.debug : noopLog;\n const loaded = await loadWhoisFor(domain, timeout, log, cache);\n if (!loaded?.data.creationDate) return null;\n\n const { host, data } = loaded;\n // Type-narrowed by the guard above — destructuring widens it back, so re-check.\n const rawCreation = data.creationDate;\n if (!rawCreation) return null;\n const creationDate = new Date(rawCreation);\n const ageInDays = Math.floor((Date.now() - creationDate.getTime()) / 86_400_000);\n const ageInYears = parseFloat((ageInDays / 365.25).toFixed(2));\n log(`[whois] ${host} age: ${ageInDays} days (${ageInYears}y)`);\n\n return {\n domain: host,\n creationDate,\n ageInDays,\n ageInYears,\n expirationDate: data.expirationDate ? new Date(data.expirationDate) : null,\n updatedDate: data.updatedDate ? new Date(data.updatedDate) : null,\n };\n}\n\nexport async function getDomainRegistrationStatus(\n domain: string,\n timeout = 5000,\n debug = false,\n cache?: Cache\n): Promise<DomainRegistrationInfo | null> {\n const log: Logger = debug ? console.debug : noopLog;\n const loaded = await loadWhoisFor(domain, timeout, log, cache);\n if (!loaded) return null;\n\n const { host, data } = loaded;\n if (data.isAvailable) {\n log(`[whois] ${host} is available / not registered`);\n return availableResult(host);\n }\n\n const isRegistered = Boolean(data.domainName || data.creationDate || data.registrar);\n const expirationDate = data.expirationDate ? new Date(data.expirationDate) : null;\n const isExpired = expirationDate ? Date.now() > expirationDate.getTime() : false;\n const daysUntilExpiration =\n expirationDate && !isExpired ? Math.floor((expirationDate.getTime() - Date.now()) / 86_400_000) : null;\n\n // Status codes look like \"clientTransferProhibited https://...\" — keep just the code.\n const statusCodes = (data.status ?? []).map((s) => s.split(' ')[0] ?? '');\n const isPendingDelete = statusCodes.some((s) => /pendingdelete|redemption/i.test(s));\n const isLocked = statusCodes.some((s) => /(client|server)transferprohibited/i.test(s));\n\n log(\n `[whois] ${host} — registered=${isRegistered} expired=${isExpired} locked=${isLocked} pendingDelete=${isPendingDelete}`\n );\n\n return {\n domain: host,\n isRegistered,\n isAvailable: !isRegistered,\n status: statusCodes,\n registrar: data.registrar ?? null,\n nameServers: data.nameServers ?? [],\n expirationDate,\n isExpired,\n daysUntilExpiration,\n isPendingDelete,\n isLocked,\n };\n}\n\nfunction availableResult(domain: string): DomainRegistrationInfo {\n return {\n domain,\n isRegistered: false,\n isAvailable: true,\n status: [],\n registrar: null,\n nameServers: [],\n expirationDate: null,\n isExpired: false,\n daysUntilExpiration: null,\n isPendingDelete: false,\n isLocked: false,\n };\n}\n","/**\n * `verifyEmail` orchestrator + its private helpers.\n *\n * Lives in its own file so `batch-verifier.ts` can import `verifyEmail`\n * without going through `./index.ts` — that re-export was the source of the\n * `index.ts -> batch-verifier.ts -> index.ts` circular dependency Rollup\n * warned about.\n */\nimport { parse } from 'psl';\nimport { getCacheStore } from './cache';\nimport { suggestEmailDomain } from './domain-suggester';\nimport { isValidEmail, isValidEmailDomain } from './email-validator';\nimport { isDisposableEmail } from './is-disposable-email';\nimport { isFreeEmail } from './is-free-email';\nimport { resolveMxRecords } from './mx-resolver';\nimport { detectNameFromEmail } from './name-detector';\nimport { verifyMailboxSMTP } from './smtp-verifier';\nimport { ArrayTranscriptCollector, NULL_COLLECTOR, type TranscriptCollector } from './transcript';\nimport {\n type DomainSuggestion,\n type SmtpVerificationResult,\n VerificationErrorCode,\n type VerificationResult,\n type VerifyEmailParams,\n} from './types';\nimport { getDomainAge, getDomainRegistrationStatus } from './whois';\n\ntype Logger = (...args: unknown[]) => void;\n\n/** Per-MX-domain port overrides — picked when no explicit `smtpPort` was passed. */\nexport const domainPorts: Record<string, number> = {\n // 465 or 587\n // https://help.ovhcloud.com/csm/en-ca-web-paas-development-email?id=kb_article_view&sysparm_article=KB0053893\n 'ovh.net': 465,\n};\n\n/**\n * Copy SMTP verification fields onto the flat result + derive validSmtp.\n * `validSmtp` is null when we couldn't connect (so the caller knows verification\n * was inconclusive, not negative), otherwise tracks `isDeliverable`.\n */\nfunction applySmtpResult(result: VerificationResult, smtp: SmtpVerificationResult): void {\n result.canConnectSmtp = smtp.canConnectSmtp;\n result.hasFullInbox = smtp.hasFullInbox;\n result.isCatchAll = smtp.isCatchAll;\n result.isDeliverable = smtp.isDeliverable;\n result.isDisabled = smtp.isDisabled;\n result.validSmtp = smtp.canConnectSmtp ? smtp.isDeliverable : null;\n}\n\n/** Pick a port override from explicit param > known per-MX-domain map > library default. */\nfunction resolveSmtpPorts(explicitPort: number | undefined, primaryMx: string | undefined): number[] | undefined {\n if (explicitPort) return [explicitPort];\n if (!primaryMx) return undefined;\n const mxDomain = parse(primaryMx);\n if (!('domain' in mxDomain) || !mxDomain.domain) return undefined;\n const known = domainPorts[mxDomain.domain];\n return known ? [known] : undefined;\n}\n\n/**\n * Verify an email address — orchestrates format / disposable / free / MX / SMTP /\n * WHOIS / name-detection / domain-suggestion checks. Each helper below owns one\n * step and runs only when its flag is enabled. Early returns short-circuit on\n * format/domain failures.\n */\nexport async function verifyEmail(params: VerifyEmailParams): Promise<VerificationResult> {\n const startTime = Date.now();\n const debug = params.debug ?? false;\n const log: Logger = debug ? console.debug : () => {};\n const result = blankResult(params.emailAddress);\n\n // Capture collector — opt-in via `captureTranscript`. The NULL_COLLECTOR is\n // a no-op so call sites don't need to branch.\n const captureTranscript = params.captureTranscript ?? false;\n const collector: TranscriptCollector = captureTranscript ? new ArrayTranscriptCollector() : NULL_COLLECTOR;\n\n // 1. Format check — bail fast.\n const syntaxValid = await collector.record(\n 'syntax',\n () => isValidEmail(params.emailAddress),\n (ok) => ({ ok })\n );\n if (!syntaxValid) {\n return finalize(result, VerificationErrorCode.invalidFormat, startTime, collector);\n }\n result.validFormat = true;\n\n // 2. Name detection (cheap, runs on local part only).\n if (params.detectName) {\n result.detectedName = await collector.record(\n 'name-detection',\n () => detectNameFromEmail({ email: params.emailAddress, customMethod: params.nameDetectionMethod }),\n (detected) => ({ detected: detected ?? null })\n );\n }\n\n // 3. Domain suggestion (cheap, runs on domain only).\n if (params.suggestDomain ?? true) {\n result.domainSuggestion = await collector.record(\n 'domain-suggestion',\n () => runSuggestDomain(params),\n (suggestion) => ({ suggestion: suggestion ?? null })\n );\n }\n\n const [local, domain] = params.emailAddress.split('@');\n if (!domain || !local) {\n return finalize(result, VerificationErrorCode.invalidFormat, startTime, collector);\n }\n const domainValid = await collector.record(\n 'domain-validation',\n () => isValidEmailDomain(domain, params.cache),\n (valid) => ({ domain, valid })\n );\n if (!domainValid) {\n return finalize(result, VerificationErrorCode.invalidDomain, startTime, collector);\n }\n\n // 4. Disposable + free provider checks.\n if (params.checkDisposable ?? true) {\n result.isDisposable = await collector.record(\n 'disposable',\n () => isDisposableEmail({ emailOrDomain: params.emailAddress, cache: params.cache, logger: log }),\n (isDisposable) => ({ domain, isDisposable })\n );\n log(`[verifyEmail] disposable: ${result.isDisposable}`);\n if (result.isDisposable) result.metadata.error = VerificationErrorCode.disposableEmail;\n }\n if (params.checkFree ?? true) {\n result.isFree = await collector.record(\n 'free',\n () => isFreeEmail({ emailOrDomain: params.emailAddress, cache: params.cache, logger: log }),\n (isFree) => ({ domain, isFree })\n );\n log(`[verifyEmail] free: ${result.isFree}`);\n }\n\n const skipMx = (params.skipMxForDisposable ?? false) && result.isDisposable;\n const skipWhois = (params.skipDomainWhoisForDisposable ?? false) && result.isDisposable;\n\n // 5. WHOIS-driven domain age + registration (skipped for disposable when configured).\n await runWhoisChecks(domain, params, result, skipWhois, log, collector);\n\n // 6. MX + SMTP — runs when either flag is on, unless we're skipping\n // disposable addresses (the address is already known to be junk).\n const wantsMxOrSmtp = (params.verifyMx ?? true) || (params.verifySmtp ?? false);\n if (wantsMxOrSmtp && skipMx) {\n log(`[verifyEmail] skipping MX/SMTP for disposable: ${params.emailAddress}`);\n } else if (wantsMxOrSmtp) {\n await runMxAndSmtp(local, domain, params, result, log, collector);\n }\n\n result.metadata.verificationTime = Date.now() - startTime;\n if (captureTranscript) result.transcript = (collector as ArrayTranscriptCollector).steps;\n return result;\n}\n\nfunction blankResult(email: string): VerificationResult {\n return {\n email,\n validFormat: false,\n validMx: null,\n validSmtp: null,\n isDisposable: false,\n isFree: false,\n metadata: { verificationTime: 0, cached: false },\n };\n}\n\nfunction finalize(\n result: VerificationResult,\n error: VerificationErrorCode,\n startTime: number,\n collector: TranscriptCollector\n): VerificationResult {\n result.metadata.error = error;\n result.metadata.verificationTime = Date.now() - startTime;\n if (collector instanceof ArrayTranscriptCollector) {\n result.transcript = collector.steps;\n }\n return result;\n}\n\nasync function runSuggestDomain(params: VerifyEmailParams): Promise<DomainSuggestion | null> {\n const [, emailDomain] = params.emailAddress.split('@');\n if (!emailDomain) return null;\n if (params.domainSuggestionMethod) return params.domainSuggestionMethod(emailDomain);\n return suggestEmailDomain(params.emailAddress, params.commonDomains);\n}\n\nasync function runWhoisChecks(\n domain: string,\n params: VerifyEmailParams,\n result: VerificationResult,\n skipWhois: boolean,\n log: Logger,\n collector: TranscriptCollector\n): Promise<void> {\n if (!params.checkDomainAge && !params.checkDomainRegistration) return;\n if (skipWhois) {\n log(`[verifyEmail] WHOIS checks skipped for disposable: ${domain}`);\n return;\n }\n const whoisTimeoutMs = params.whoisTimeoutMs ?? 5000;\n const debug = params.debug ?? false;\n\n if (params.checkDomainAge) {\n try {\n result.domainAge = await collector.record(\n 'whois-age',\n () => getDomainAge(domain, whoisTimeoutMs, debug, params.cache),\n (info) => ({\n domain,\n found: info !== null,\n ageInDays: info?.ageInDays ?? null,\n ageInYears: info?.ageInYears ?? null,\n creationDate: info?.creationDate?.toISOString() ?? null,\n expirationDate: info?.expirationDate?.toISOString() ?? null,\n })\n );\n log(`[verifyEmail] domain age:`, result.domainAge ? `${result.domainAge.ageInDays} days` : 'null');\n } catch (error) {\n log('[verifyEmail] domain age lookup failed', error);\n result.domainAge = null;\n }\n }\n\n if (params.checkDomainRegistration) {\n try {\n result.domainRegistration = await collector.record(\n 'whois-registration',\n () => getDomainRegistrationStatus(domain, whoisTimeoutMs, debug, params.cache),\n (info) => ({\n domain,\n found: info !== null,\n isRegistered: info?.isRegistered ?? null,\n isExpired: info?.isExpired ?? null,\n isLocked: info?.isLocked ?? null,\n isPendingDelete: info?.isPendingDelete ?? null,\n daysUntilExpiration: info?.daysUntilExpiration ?? null,\n status: info?.status ?? [],\n })\n );\n log(`[verifyEmail] registered:`, result.domainRegistration?.isRegistered ?? false);\n } catch (error) {\n log('[verifyEmail] domain registration lookup failed', error);\n result.domainRegistration = null;\n }\n }\n}\n\nasync function runMxAndSmtp(\n local: string,\n domain: string,\n params: VerifyEmailParams,\n result: VerificationResult,\n log: Logger,\n collector: TranscriptCollector\n): Promise<void> {\n let mxRecords: string[];\n try {\n mxRecords = await collector.record(\n 'mx-lookup',\n () => resolveMxRecords({ domain, cache: params.cache, logger: log }),\n (records) => ({ domain, records, count: records.length })\n );\n } catch (error) {\n log('[verifyEmail] MX lookup failed', error);\n result.validMx = false;\n result.mxRecords = null;\n result.metadata.error = VerificationErrorCode.noMxRecords;\n return;\n }\n\n result.mxRecords = mxRecords;\n result.validMx = mxRecords.length > 0;\n if (!result.validMx) {\n result.metadata.error = VerificationErrorCode.noMxRecords;\n return;\n }\n\n if (!(params.verifySmtp ?? false)) return;\n\n await runSmtp(local, domain, mxRecords, params, result, log, collector);\n}\n\nasync function runSmtp(\n local: string,\n domain: string,\n mxRecords: string[],\n params: VerifyEmailParams,\n result: VerificationResult,\n log: Logger,\n collector: TranscriptCollector\n): Promise<void> {\n const cacheKey = `${params.emailAddress}:smtp`;\n const smtpCache = getCacheStore<SmtpVerificationResult>(params.cache, 'smtp');\n const cached = await smtpCache.get(cacheKey);\n\n if (cached) {\n applySmtpResult(result, cached);\n result.metadata.cached = true;\n log(`[verifyEmail] SMTP cache hit: ${result.validSmtp} for ${params.emailAddress}`);\n collector.push({\n kind: 'smtp-probe',\n startedAt: Date.now(),\n durationMs: 0,\n ok: true,\n details: {\n cacheHit: true,\n verdict: smtpVerdictFor(result.validSmtp),\n canConnectSmtp: cached.canConnectSmtp,\n },\n });\n } else {\n await collector.record(\n 'smtp-probe',\n async () => {\n const probe = await verifyMailboxSMTP({\n local,\n domain,\n mxRecords,\n options: {\n cache: params.cache,\n ports: resolveSmtpPorts(params.smtpPort, mxRecords[0]),\n perAttemptTimeoutMs: params.smtpPerAttemptTimeoutMs ?? 4000,\n totalDeadlineMs: params.smtpTotalDeadlineMs,\n maxConsecutiveFailures: params.smtpMaxConsecutiveFailures,\n maxMxHosts: params.smtpMaxMxHosts,\n retry: params.smtpRetry,\n debug: params.debug ?? false,\n // Forward transcript capture so the SMTP step's details include\n // the full per-port transcript when the caller asked for it.\n captureTranscript: params.captureTranscript ?? false,\n },\n });\n await smtpCache.set(cacheKey, probe.smtpResult);\n applySmtpResult(result, probe.smtpResult);\n result.metadata.cached = probe.cached;\n return probe;\n },\n ({ smtpResult, port, cached: probedFromCache }) => ({\n cacheHit: false,\n port,\n cached: probedFromCache,\n verdict: smtpVerdictFor(result.validSmtp),\n canConnectSmtp: smtpResult.canConnectSmtp,\n error: smtpResult.error ?? null,\n // Only present if captureTranscript was set on params.\n transcript: smtpResult.transcript ?? null,\n commands: smtpResult.commands ?? null,\n })\n );\n log(`[verifyEmail] SMTP probed: ${result.validSmtp} for ${params.emailAddress}`);\n }\n\n if (result.validSmtp === false) result.metadata.error = VerificationErrorCode.mailboxNotFound;\n else if (result.validSmtp === null) result.metadata.error = VerificationErrorCode.smtpConnectionFailed;\n}\n\nfunction smtpVerdictFor(validSmtp: boolean | null | undefined): 'deliverable' | 'undeliverable' | 'indeterminate' {\n if (validSmtp === true) return 'deliverable';\n if (validSmtp === false) return 'undeliverable';\n return 'indeterminate';\n}\n","/**\n * Output formatters for the CLI. The runner picks one based on `--format`.\n *\n * pretty — colored, human-friendly summary + transcript table (default)\n * text — plain ASCII single-line verdict + KV pairs (for piping)\n * json — full `VerificationResult` as a single JSON line (for tooling)\n */\nimport type { VerificationResult, VerificationStep } from '../types';\n\n/** Tiny ANSI color helpers — no chalk dependency. Disabled when stdout isn't a TTY. */\nfunction colorize(): {\n green: (s: string) => string;\n red: (s: string) => string;\n yellow: (s: string) => string;\n dim: (s: string) => string;\n bold: (s: string) => string;\n} {\n const enabled = process.stdout.isTTY && process.env.NO_COLOR !== '1';\n const wrap = (open: string, close: string) => (s: string) => (enabled ? `\\x1b[${open}m${s}\\x1b[${close}m` : s);\n return {\n green: wrap('32', '39'),\n red: wrap('31', '39'),\n yellow: wrap('33', '39'),\n dim: wrap('2', '22'),\n bold: wrap('1', '22'),\n };\n}\n\n/** Single-line verdict, colored if the terminal supports it. */\nexport function verdictLine(result: VerificationResult): string {\n const c = colorize();\n if (result.validFormat === false) return c.red(`✗ INVALID FORMAT ${result.email}`);\n if (result.validMx === false) return c.red(`✗ NO MX RECORDS ${result.email}`);\n if (result.validSmtp === true) return c.green(`✓ DELIVERABLE ${result.email}`);\n if (result.validSmtp === false) return c.red(`✗ UNDELIVERABLE ${result.email}`);\n // `canConnectSmtp` is the reliable signal for \"did we actually probe?\":\n // undefined → SMTP step skipped; false → probed and couldn't connect.\n const smtpProbed = result.canConnectSmtp !== undefined;\n if (smtpProbed && result.validSmtp === null) return c.yellow(`? INDETERMINATE ${result.email}`);\n return c.green(`✓ FORMAT/MX OK ${result.email} ${c.dim('(SMTP not probed)')}`);\n}\n\nexport function formatJson(result: VerificationResult): string {\n return JSON.stringify(result);\n}\n\nexport function formatText(result: VerificationResult): string {\n const lines: string[] = [];\n lines.push(verdictLine(result));\n lines.push(` format=${result.validFormat} mx=${result.validMx} smtp=${result.validSmtp}`);\n lines.push(` isDisposable=${result.isDisposable} isFree=${result.isFree}`);\n if (result.mxRecords?.length) lines.push(` mxRecords=${result.mxRecords.join(', ')}`);\n if (result.domainSuggestion) lines.push(` suggestion=${result.domainSuggestion.suggested}`);\n if (result.detectedName) {\n const { firstName, lastName, confidence } = result.detectedName;\n lines.push(` detectedName=${firstName ?? '_'} ${lastName ?? '_'} (conf=${confidence.toFixed(2)})`);\n }\n if (result.metadata.error) lines.push(` error=${result.metadata.error}`);\n lines.push(` time=${result.metadata.verificationTime}ms cached=${result.metadata.cached}`);\n return lines.join('\\n');\n}\n\nexport function formatPretty(result: VerificationResult): string {\n const c = colorize();\n const lines: string[] = [];\n lines.push(verdictLine(result));\n lines.push('');\n\n // Summary block.\n lines.push(c.bold('Summary'));\n lines.push(` ${c.dim('format:')} ${formatBool(result.validFormat)}`);\n if (result.validMx !== null)\n lines.push(\n ` ${c.dim('MX records:')} ${formatBool(result.validMx)}${result.mxRecords ? ` ${c.dim(result.mxRecords.join(', '))}` : ''}`\n );\n if (result.validSmtp !== null) lines.push(` ${c.dim('SMTP:')} ${formatBool(result.validSmtp)}`);\n lines.push(\n ` ${c.dim('disposable:')} ${formatBool(!result.isDisposable)} ${c.dim(result.isDisposable ? '(domain on disposable list)' : '')}`\n );\n lines.push(\n ` ${c.dim('free provider:')} ${formatBool(!result.isFree)} ${c.dim(result.isFree ? '(domain on free list)' : '')}`\n );\n if (result.domainSuggestion) {\n lines.push(\n ` ${c.dim('suggestion:')} ${c.yellow(result.domainSuggestion.suggested)} ${c.dim(`(conf=${result.domainSuggestion.confidence.toFixed(2)})`)}`\n );\n }\n if (result.detectedName) {\n const { firstName, lastName, confidence } = result.detectedName;\n lines.push(\n ` ${c.dim('detected name:')} ${[firstName, lastName].filter(Boolean).join(' ')} ${c.dim(`(conf=${confidence.toFixed(2)})`)}`\n );\n }\n if (result.domainAge) {\n lines.push(\n ` ${c.dim('domain age:')} ${result.domainAge.ageInDays} days ${c.dim(`(${result.domainAge.ageInYears.toFixed(1)} years)`)}`\n );\n }\n if (result.domainRegistration) {\n const r = result.domainRegistration;\n lines.push(\n ` ${c.dim('registration:')} ${r.isRegistered ? c.green('registered') : c.red('available')}${r.isExpired ? ` ${c.red('(expired)')}` : ''}${r.isLocked ? ` ${c.dim('(locked)')}` : ''}`\n );\n }\n if (result.metadata.error) lines.push(` ${c.dim('error:')} ${c.red(result.metadata.error)}`);\n lines.push(\n ` ${c.dim('elapsed:')} ${result.metadata.verificationTime} ms${result.metadata.cached ? ` ${c.dim('(cached)')}` : ''}`\n );\n\n // Transcript block (if captured).\n if (result.transcript && result.transcript.length > 0) {\n lines.push('');\n lines.push(c.bold('Transcript'));\n for (const step of result.transcript) {\n lines.push(` ${formatStep(step, c)}`);\n }\n }\n\n return lines.join('\\n');\n}\n\nfunction formatBool(value: boolean | null): string {\n const c = colorize();\n if (value === true) return c.green('✓');\n if (value === false) return c.red('✗');\n return c.dim('—');\n}\n\nfunction formatStep(step: VerificationStep, c: ReturnType<typeof colorize>): string {\n const okMark = step.ok ? c.green('✓') : c.red('✗');\n const time = `${step.durationMs}ms`.padStart(6);\n const detail = formatStepDetail(step);\n return `${okMark} ${c.dim(time)} ${c.bold(step.kind.padEnd(20))} ${detail}`;\n}\n\nfunction formatStepDetail(step: VerificationStep): string {\n const d = step.details;\n switch (step.kind) {\n case 'syntax':\n return `ok=${String(d.ok)}`;\n case 'domain-validation':\n return `domain=${String(d.domain)} valid=${String(d.valid)}`;\n case 'name-detection':\n return d.detected ? `detected ${JSON.stringify(d.detected)}` : 'no name detected';\n case 'domain-suggestion':\n return d.suggestion ? `→ ${JSON.stringify(d.suggestion)}` : 'no suggestion';\n case 'disposable':\n return `domain=${String(d.domain)} isDisposable=${String(d.isDisposable)}`;\n case 'free':\n return `domain=${String(d.domain)} isFree=${String(d.isFree)}`;\n case 'mx-lookup':\n return `domain=${String(d.domain)} count=${String(d.count)}`;\n case 'smtp-probe':\n return d.cacheHit\n ? `cache hit verdict=${String(d.verdict)}`\n : `port=${String(d.port)} verdict=${String(d.verdict)}${d.error ? ` error=${String(d.error)}` : ''}`;\n case 'whois-age':\n return d.found ? `found created=${String(d.creationDate)} ageDays=${String(d.ageInDays)}` : 'not found';\n case 'whois-registration':\n return d.found\n ? `registered=${String(d.isRegistered)} expired=${String(d.isExpired)} locked=${String(d.isLocked)}`\n : 'not found';\n }\n}\n","/**\n * CLI runner — turns ParsedArgs into a verifyEmail invocation, formats the\n * output, and optionally writes the structured result to a log file.\n *\n * Returns the process exit code:\n * 0 — deliverable / format-and-MX OK / no SMTP probe asked for\n * 1 — undeliverable / no MX records / invalid format / indeterminate\n * 2 — bad CLI arguments (handled in `index.ts` before reaching here)\n */\nimport { mkdirSync, writeFileSync } from 'node:fs';\nimport { resolve } from 'node:path';\nimport { verifyEmail } from '../index';\nimport type { VerificationResult } from '../types';\nimport { formatJson, formatPretty, formatText, verdictLine } from './format';\nimport type { ParsedArgs } from './parse-args';\n\nexport interface CliRunDeps {\n /** Allow tests to inject a custom verifier — defaults to the real one. */\n verify?: typeof verifyEmail;\n /** Write a string to the given path. Defaults to fs.writeFileSync. */\n writeFile?: (path: string, contents: string) => void;\n /** Ensure a directory exists. Defaults to fs.mkdirSync(recursive). */\n ensureDir?: (path: string) => void;\n /** stdout / stderr writers — tests inject in-memory buffers. */\n stdout?: (line: string) => void;\n stderr?: (line: string) => void;\n /** Used to build the log filename — tests pin it for determinism. */\n now?: () => Date;\n}\n\n/** Build the timestamped log filename for an email + run time. */\nexport function logFileNameFor(email: string, when: Date): string {\n const safeEmail = email.replace(/[^a-zA-Z0-9._-]+/g, '_');\n const stamp =\n `${when.getUTCFullYear()}-${pad(when.getUTCMonth() + 1)}-${pad(when.getUTCDate())}` +\n `T${pad(when.getUTCHours())}${pad(when.getUTCMinutes())}${pad(when.getUTCSeconds())}Z`;\n return `email-validate-${stamp}-${safeEmail}.json`;\n}\n\nfunction pad(n: number): string {\n return n < 10 ? `0${n}` : String(n);\n}\n\nexport async function run(args: ParsedArgs, deps: CliRunDeps = {}): Promise<number> {\n const verify = deps.verify ?? verifyEmail;\n const stdout = deps.stdout ?? ((line) => process.stdout.write(`${line}\\n`));\n const stderr = deps.stderr ?? ((line) => process.stderr.write(`${line}\\n`));\n const writeFile = deps.writeFile ?? ((path, contents) => writeFileSync(path, contents, 'utf8'));\n const ensureDir = deps.ensureDir ?? ((path) => mkdirSync(path, { recursive: true }));\n const now = deps.now ?? (() => new Date());\n\n const result = await verify({\n emailAddress: args.email,\n verifyMx: args.verifyMx,\n verifySmtp: args.verifySmtp,\n smtpPerAttemptTimeoutMs: args.timeoutMs ?? 5000,\n debug: args.debug,\n smtpPort: args.smtpPort,\n checkDisposable: args.checkDisposable,\n checkFree: args.checkFree,\n detectName: args.detectName,\n suggestDomain: args.suggestDomain,\n checkDomainAge: args.checkDomainAge,\n checkDomainRegistration: args.checkDomainRegistration,\n whoisTimeoutMs: args.whoisTimeoutMs ?? 5000,\n captureTranscript: args.captureTranscript,\n });\n\n // Stdout output.\n if (args.quiet) {\n stdout(verdictLine(result));\n } else {\n switch (args.format) {\n case 'json':\n stdout(formatJson(result));\n break;\n case 'text':\n stdout(formatText(result));\n break;\n case 'pretty':\n stdout(formatPretty(result));\n break;\n }\n }\n\n // Optional file log.\n if (args.logDir) {\n try {\n const dir = resolve(args.logDir);\n ensureDir(dir);\n const path = resolve(dir, logFileNameFor(args.email, now()));\n writeFile(path, JSON.stringify(result, null, 2));\n if (!args.quiet) stderr(`Log written: ${path}`);\n } catch (error) {\n stderr(`Warning: failed to write log file: ${error instanceof Error ? error.message : String(error)}`);\n }\n }\n\n return exitCodeFor(result);\n}\n\nexport function exitCodeFor(result: VerificationResult): number {\n if (!result.validFormat) return 1;\n if (result.validMx === false) return 1;\n if (result.validSmtp === false) return 1;\n // `canConnectSmtp` is the reliable \"did we actually probe?\" signal:\n // undefined → SMTP not requested → exit 0 if format/MX OK\n // false → probed but couldn't connect → exit 1 (indeterminate)\n // true → probed and connected → validSmtp drives the verdict above\n const smtpProbed = result.canConnectSmtp !== undefined;\n if (smtpProbed && result.validSmtp === null) return 1;\n return 0;\n}\n","/**\n * `email-validate` CLI entry point.\n *\n * Wired into `package.json#bin` so `bun add -g @emailcheck/email-validator-js`\n * (or the npm equivalent) installs an `email-validate` command.\n *\n * Programmatic users can also import these helpers directly:\n * import { parseArgs, run } from '@emailcheck/email-validator-js/cli';\n */\nimport { helpText, parseArgs } from './parse-args';\nimport { run } from './run';\n\nexport type { CliArgError, ParsedArgs, ParsedHelp, ParsedVersion, ParseResult } from './parse-args';\nexport { helpText, parseArgs } from './parse-args';\nexport type { CliRunDeps } from './run';\nexport { exitCodeFor, logFileNameFor, run } from './run';\n\nexport async function main(argv: readonly string[] = process.argv.slice(2)): Promise<number> {\n const parsed = parseArgs(argv);\n\n if (parsed.kind === 'help') {\n process.stdout.write(`${helpText()}\\n`);\n return 0;\n }\n if (parsed.kind === 'version') {\n // Read from the bundled package.json — the build copies it next to the bin.\n // For unbundled (Bun-direct) runs, fall back to a placeholder.\n try {\n const pkg = require('../../package.json') as { version: string };\n process.stdout.write(`${pkg.version}\\n`);\n } catch {\n process.stdout.write('unknown\\n');\n }\n return 0;\n }\n if (parsed.kind === 'error') {\n for (const msg of parsed.messages) process.stderr.write(`${msg}\\n`);\n process.stderr.write(`\\nRun with --help for usage.\\n`);\n return parsed.exitCode;\n }\n\n return run(parsed);\n}\n\n// When invoked directly (not imported), run main() and propagate the exit code.\n// `import.meta.main` works under Bun; for Node we check require.main.\nconst isDirectInvocation =\n // bun\n (typeof import.meta !== 'undefined' && (import.meta as { main?: boolean }).main === true) ||\n // node CommonJS bundle\n (typeof require !== 'undefined' && require.main === module);\n\nif (isDirectInvocation) {\n main()\n .then((code) => process.exit(code))\n .catch((error) => {\n process.stderr.write(\n `Unexpected error: ${error instanceof Error ? (error.stack ?? error.message) : String(error)}\\n`\n );\n process.exit(1);\n });\n}\n"],"names":["lru","VerificationErrorCode","SMTPStep","stringSimilarity","isValid","dnsPromises","net","randomBytes","metrics","smtpResult","tls","parse","writeFileSync","mkdirSync","resolve"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../src/cli/parse-args.ts","../../src/adapters/lru-adapter.ts","../../src/types.ts","../../src/cache.ts","../../src/domain-suggester.ts","../../src/email-validator.ts","../../src/is-disposable-email.ts","../../src/is-free-email.ts","../../src/mx-resolver.ts","../../src/name-detector.ts","../../src/sender-strategy.ts","../../src/smtp-verifier.ts","../../src/transcript.ts","../../src/whois-parser.ts","../../src/whois.ts","../../src/verify-email.ts","../../src/cli/format.ts","../../src/cli/run.ts","../../src/cli/index.ts"],"sourcesContent":["/**\n * Minimal flag parser for the `email-validate` CLI.\n *\n * Accepts `argv` (everything after `node bin / email-validate`) and produces a\n * `ParsedArgs` shape, or throws a `CliArgError` with `messages[]` and an\n * `exitCode` for the caller to propagate.\n *\n * Why hand-rolled: the CLI surface is small (~15 flags), and pulling in\n * `commander` / `yargs` would balloon the published bundle for every consumer\n * regardless of whether they ever run the CLI. The trade-off is no\n * sub-command tree — just one flat command — which fits the tool fine.\n */\n\nexport interface ParsedArgs {\n /** Email address to validate (positional). */\n email: string;\n // SMTP / MX flags\n verifyMx: boolean;\n verifySmtp: boolean;\n ports?: number[];\n smtpPort?: number;\n hostname?: string;\n timeoutMs?: number;\n // Disposable / free / suggestion flags\n checkDisposable: boolean;\n checkFree: boolean;\n suggestDomain: boolean;\n detectName: boolean;\n // WHOIS flags\n checkDomainAge: boolean;\n checkDomainRegistration: boolean;\n whoisTimeoutMs?: number;\n // Output flags\n format: 'text' | 'json' | 'pretty';\n quiet: boolean;\n debug: boolean;\n captureTranscript: boolean;\n logDir: string | null; // null => no file, default './logs'\n}\n\nexport interface ParsedHelp {\n kind: 'help';\n}\n\nexport interface ParsedVersion {\n kind: 'version';\n}\n\nexport interface CliArgError {\n kind: 'error';\n messages: string[];\n exitCode: number;\n}\n\nexport type ParseResult = ({ kind: 'args' } & ParsedArgs) | ParsedHelp | ParsedVersion | CliArgError;\n\nconst HELP_TEXT = `email-validate <email> [options]\n\nRun the full email-validator-js pipeline against one address. By default,\nruns format / MX / SMTP probe / disposable / free-provider / typo-suggest /\nname-detection, captures a structured transcript, prints it to stdout, and\nwrites the JSON result to ./logs/.\n\nWHOIS lookups are off by default (they're slow); enable with --whois-age or\n--whois-registration.\n\nOptions:\n --mx, --no-mx Resolve MX records (default: on)\n --smtp, --no-smtp Run live SMTP probe (default: on)\n --disposable, --no-disposable Check disposable-email list (default: on)\n --free, --no-free Check free-provider list (default: on)\n --suggest-domain, --no-suggest-domain\n Suggest a corrected domain on typos (default: on)\n --detect-name, --no-detect-name\n Extract first/last name from local (default: on)\n --whois-age Look up domain creation date (default: off)\n --whois-registration Look up domain registration status (default: off)\n\n --port <n> Force a single SMTP port (e.g. 587)\n --ports <n,n,...> Comma-separated SMTP port walk (default: 25,587,465)\n --hostname <name> EHLO/HELO identity (default: localhost)\n --timeout <ms> SMTP timeout per port (default: 5000)\n --whois-timeout <ms> WHOIS query timeout (default: 5000)\n\n --format <text|json|pretty> Stdout format (default: pretty)\n --no-transcript Skip the per-step transcript capture\n --log-dir <path> Directory to write the JSON result (default: ./logs)\n --no-log-file Skip writing the result file\n --quiet Print only the final verdict to stdout\n --debug Verbose console logging during the run\n\n -h, --help Show this help\n -v, --version Print version\n\nExamples:\n # Quick interactive check — full pipeline, pretty output, log saved to ./logs\n email-validate alice@example.com\n\n # Skip the SMTP probe (fast, just format / MX / lists / typos)\n email-validate alice@example.com --no-smtp\n\n # Add WHOIS age + registration for full domain reputation picture\n email-validate alice@example.com --whois-age --whois-registration\n\n # Pipe JSON to jq for tooling\n email-validate alice@example.com --format json --quiet --no-log-file | jq\n\n # Silent verdict for shell scripting (exit code 0=ok, 1=undeliverable/invalid)\n email-validate alice@example.com --quiet --no-log-file\n if email-validate \"$EMAIL\" --quiet --no-log-file > /dev/null; then …\n\n # Pin the SMTP probe to one port + custom HELO + custom log path\n email-validate alice@example.com --port 587 --hostname mta.acme.com --log-dir /var/log/email\n\n # Debug a specific delivery quirk (full transcript + console logs)\n email-validate alice@example.com --debug --format pretty\n`;\n\nconst TRUE_FLAGS = new Set([\n 'mx',\n 'smtp',\n 'disposable',\n 'free',\n 'suggest-domain',\n 'detect-name',\n 'whois-age',\n 'whois-registration',\n 'transcript',\n 'log-file',\n 'quiet',\n 'debug',\n]);\n\nconst VALUE_FLAGS = new Set(['port', 'ports', 'hostname', 'timeout', 'whois-timeout', 'format', 'log-dir']);\n\n/** Strip a leading `no-` prefix from a flag name; return the stripped name + the polarity. */\nfunction splitNo(flag: string): { name: string; positive: boolean } {\n if (flag.startsWith('no-')) return { name: flag.slice(3), positive: false };\n return { name: flag, positive: true };\n}\n\nfunction parseIntOr(value: string, what: string, errors: string[]): number | undefined {\n const n = Number(value);\n if (!Number.isFinite(n) || !Number.isInteger(n) || n <= 0) {\n errors.push(`Invalid ${what}: \"${value}\" (expected a positive integer)`);\n return undefined;\n }\n return n;\n}\n\nfunction parsePortsCsv(value: string, errors: string[]): number[] | undefined {\n const ports = value\n .split(',')\n .map((p) => p.trim())\n .filter((p) => p.length > 0)\n .map((p) => parseIntOr(p, 'port', errors))\n .filter((n): n is number => n !== undefined);\n if (ports.length === 0) {\n errors.push(`--ports requires at least one valid port (got \"${value}\")`);\n return undefined;\n }\n return ports;\n}\n\nexport function parseArgs(argv: readonly string[]): ParseResult {\n const errors: string[] = [];\n const positional: string[] = [];\n\n // CLI-friendly defaults — different from the library defaults because the\n // CLI is for interactive checks, where users want the full pipeline by\n // default. WHOIS is still opt-in (it's slow + adds an external dependency).\n const result: ParsedArgs = {\n email: '',\n verifyMx: true,\n verifySmtp: true,\n checkDisposable: true,\n checkFree: true,\n suggestDomain: true,\n detectName: true,\n checkDomainAge: false,\n checkDomainRegistration: false,\n format: 'pretty',\n quiet: false,\n debug: false,\n captureTranscript: true,\n logDir: './logs',\n };\n let logFile = true;\n\n for (let i = 0; i < argv.length; i++) {\n const token = argv[i];\n if (token === undefined) continue;\n\n // Positional (the email)\n if (!token.startsWith('-')) {\n positional.push(token);\n continue;\n }\n\n if (token === '-h' || token === '--help') return { kind: 'help' };\n if (token === '-v' || token === '--version') return { kind: 'version' };\n\n if (!token.startsWith('--')) {\n errors.push(`Unknown short flag: \"${token}\"`);\n continue;\n }\n\n // Allow `--flag=value` form.\n const eqIdx = token.indexOf('=');\n const rawName = eqIdx === -1 ? token.slice(2) : token.slice(2, eqIdx);\n const inlineValue = eqIdx === -1 ? undefined : token.slice(eqIdx + 1);\n\n if (TRUE_FLAGS.has(rawName) || (rawName.startsWith('no-') && TRUE_FLAGS.has(rawName.slice(3)))) {\n const { name, positive } = splitNo(rawName);\n switch (name) {\n case 'mx':\n result.verifyMx = positive;\n break;\n case 'smtp':\n result.verifySmtp = positive;\n break;\n case 'disposable':\n result.checkDisposable = positive;\n break;\n case 'free':\n result.checkFree = positive;\n break;\n case 'suggest-domain':\n result.suggestDomain = positive;\n break;\n case 'detect-name':\n result.detectName = positive;\n break;\n case 'whois-age':\n result.checkDomainAge = positive;\n break;\n case 'whois-registration':\n result.checkDomainRegistration = positive;\n break;\n case 'transcript':\n result.captureTranscript = positive;\n break;\n case 'log-file':\n logFile = positive;\n break;\n case 'quiet':\n result.quiet = positive;\n break;\n case 'debug':\n result.debug = positive;\n break;\n }\n continue;\n }\n\n if (VALUE_FLAGS.has(rawName)) {\n const value = inlineValue ?? argv[++i];\n if (value === undefined) {\n errors.push(`Flag --${rawName} requires a value`);\n continue;\n }\n switch (rawName) {\n case 'port': {\n const port = parseIntOr(value, 'port', errors);\n if (port !== undefined) result.smtpPort = port;\n break;\n }\n case 'ports': {\n const ports = parsePortsCsv(value, errors);\n if (ports) result.ports = ports;\n break;\n }\n case 'hostname':\n result.hostname = value;\n break;\n case 'timeout': {\n const ms = parseIntOr(value, '--timeout', errors);\n if (ms !== undefined) result.timeoutMs = ms;\n break;\n }\n case 'whois-timeout': {\n const ms = parseIntOr(value, '--whois-timeout', errors);\n if (ms !== undefined) result.whoisTimeoutMs = ms;\n break;\n }\n case 'format':\n if (value !== 'text' && value !== 'json' && value !== 'pretty') {\n errors.push(`--format must be one of text|json|pretty (got \"${value}\")`);\n } else {\n result.format = value;\n }\n break;\n case 'log-dir':\n result.logDir = value;\n break;\n }\n continue;\n }\n\n errors.push(`Unknown flag: \"${token}\"`);\n }\n\n if (!logFile) result.logDir = null;\n\n if (positional.length === 0) errors.push('Missing required argument: <email>');\n if (positional.length > 1) errors.push(`Expected one email, got ${positional.length}: ${positional.join(', ')}`);\n\n if (errors.length > 0) {\n return { kind: 'error', messages: errors, exitCode: 2 };\n }\n\n const [email] = positional;\n if (!email) return { kind: 'error', messages: ['Missing required argument: <email>'], exitCode: 2 };\n result.email = email;\n return { kind: 'args', ...result };\n}\n\nexport function helpText(): string {\n return HELP_TEXT;\n}\n","import { type LRU, lru } from 'tiny-lru';\nimport type { CacheStore } from '../cache-interface';\n\n/**\n * Adapter to make tiny-lru compatible with our cache interface\n */\nexport class LRUAdapter<T> implements CacheStore<T> {\n private lru: LRU<T>;\n\n constructor(maxSize: number = 1000, ttlMs: number = 3600000) {\n this.lru = lru<T>(maxSize, ttlMs);\n }\n\n get(key: string): T | null | undefined {\n const value = this.lru.get(key);\n // tiny-lru returns undefined for not found\n return value === undefined ? null : value;\n }\n\n // Per-entry ttlMs is intentionally ignored: tiny-lru only supports a single\n // TTL set at construction. Callers that need per-entry expiry should pick a\n // backend that honours it (e.g. RedisAdapter).\n async set(key: string, value: T, _ttlMs?: number): Promise<void> {\n this.lru.set(key, value);\n }\n\n async delete(key: string): Promise<boolean> {\n this.lru.delete(key);\n return true;\n }\n\n async has(key: string): Promise<boolean> {\n return this.lru.has(key);\n }\n\n async clear(): Promise<void> {\n this.lru.clear();\n }\n\n size(): number {\n return this.lru.size;\n }\n\n /**\n * Get the underlying LRU instance for advanced operations\n */\n getLRU(): LRU<T> {\n return this.lru;\n }\n}\n","import type { Cache } from './cache-interface';\n\n/** Error codes set on `VerificationResult.metadata.error` when `verifyEmail` cannot deliver a definitive verdict. */\nexport enum VerificationErrorCode {\n invalidFormat = 'INVALID_FORMAT',\n invalidDomain = 'INVALID_DOMAIN',\n noMxRecords = 'NO_MX_RECORDS',\n smtpConnectionFailed = 'SMTP_CONNECTION_FAILED',\n smtpTimeout = 'SMTP_TIMEOUT',\n mailboxNotFound = 'MAILBOX_NOT_FOUND',\n networkError = 'NETWORK_ERROR',\n disposableEmail = 'DISPOSABLE_EMAIL',\n}\n\n/** Discriminator for `VerificationStep.kind`. */\nexport type VerificationStepKind =\n | 'syntax'\n | 'domain-validation'\n | 'name-detection'\n | 'domain-suggestion'\n | 'disposable'\n | 'free'\n | 'mx-lookup'\n | 'smtp-probe'\n | 'whois-age'\n | 'whois-registration';\n\n/**\n * One unit of work in the verification pipeline. Produced when\n * `VerifyEmailParams.captureTranscript === true`. The `details` shape varies\n * per step — see the inline interfaces under each kind.\n */\nexport interface VerificationStep {\n kind: VerificationStepKind;\n startedAt: number;\n durationMs: number;\n /** Whether the step completed without throwing. Step-level result lives in `details`. */\n ok: boolean;\n details: Record<string, unknown>;\n}\n\nexport interface VerificationResult {\n email: string;\n validFormat: boolean;\n validMx: boolean | null;\n validSmtp: boolean | null;\n isDisposable: boolean;\n isFree: boolean;\n detectedName?: DetectedName | null;\n domainAge?: DomainAgeInfo | null;\n domainRegistration?: DomainRegistrationInfo | null;\n domainSuggestion?: DomainSuggestion | null;\n /** MX records found for the domain (if MX verification was performed) */\n mxRecords?: string[] | null;\n\n // SMTP verification fields (flattened from SmtpVerificationResult)\n /** Whether SMTP connection was successful */\n canConnectSmtp?: boolean;\n /** Whether the mailbox is full */\n hasFullInbox?: boolean;\n /** Whether the domain has catch-all enabled */\n isCatchAll?: boolean;\n /** Whether the email is deliverable */\n isDeliverable?: boolean;\n /** Whether the email/account is disabled */\n isDisabled?: boolean;\n\n /** Always populated by `verifyEmail` — read directly without optional chaining. */\n metadata: {\n verificationTime: number;\n cached: boolean;\n error?: VerificationErrorCode;\n };\n /**\n * Per-step trace of what `verifyEmail` did. Present only when\n * `VerifyEmailParams.captureTranscript === true`. Each entry records timing\n * and step-specific details (raw WHOIS data, SMTP transcript, MX records,\n * cache hit/miss, etc.) for debugging and diagnostics.\n */\n transcript?: VerificationStep[];\n}\n\n/**\n * Parameters for `verifyEmail` — the high-level orchestrator that runs the\n * full pipeline (syntax → typo / name / domain → disposable / free → WHOIS\n * → MX → SMTP).\n */\nexport interface VerifyEmailParams {\n /** The full email address to verify (`local@domain`). */\n emailAddress: string;\n // ── Step toggles (each defaults are listed inline) ────────────────────────\n /** Resolve MX records via DNS to confirm the domain accepts mail. Default: `true`. */\n verifyMx?: boolean;\n /** Open an SMTP connection to the highest-priority MX and probe `RCPT TO`. Default: `false`. */\n verifySmtp?: boolean;\n /** Check the address against the bundled disposable-provider list. Default: `true`. */\n checkDisposable?: boolean;\n /** Check the address against the bundled free-provider list. Default: `true`. */\n checkFree?: boolean;\n /** Extract first/last name from the local-part. Default: `false` (cheap, but not free). */\n detectName?: boolean;\n /** Suggest a corrected domain on typos (e.g. `gnail.com` → `gmail.com`). Default: `true`. */\n suggestDomain?: boolean;\n /** Look up the domain creation date via WHOIS. Slow + external dep. Default: `false`. */\n checkDomainAge?: boolean;\n /** Look up domain registration status (registered / expired / locked). Default: `false`. */\n checkDomainRegistration?: boolean;\n // ── Skip-on-disposable shortcuts ────────────────────────────────────────\n /**\n * When the address is identified as disposable, skip the (expensive) MX +\n * SMTP probe and accept the disposable verdict as the final answer.\n * Default: `false`.\n */\n skipMxForDisposable?: boolean;\n /**\n * When the address is identified as disposable, skip the WHOIS checks too.\n * Default: `false`.\n */\n skipDomainWhoisForDisposable?: boolean;\n // ── Custom strategies (extension points for callers) ──────────────────────\n /** Override the default name-detection heuristic. Receives the email; returns `DetectedName | null`. */\n nameDetectionMethod?: NameDetectionMethod;\n /** Override the default domain-suggestion heuristic. Receives the domain; returns `DomainSuggestion | null`. */\n domainSuggestionMethod?: DomainSuggestionMethod;\n /** Custom domain list for the typo suggester. Defaults to the bundled common-domain set. */\n commonDomains?: string[];\n // ── SMTP probe wiring ─────────────────────────────────────────────────────\n /**\n * Per-attempt timeout for the SMTP probe, in milliseconds. Bounds both the\n * TCP/TLS connection setup AND the inactivity gap between SMTP commands\n * within an attempt. Default: `4000` ms.\n *\n * To bound the total wall-clock across all MX × port attempts, use\n * `smtpTotalDeadlineMs` instead. To control retries on connection-class\n * failures, use `smtpRetry`.\n */\n smtpPerAttemptTimeoutMs?: number;\n /**\n * Hard cap on total wall-clock time for the SMTP probe across all MX × port\n * × retry attempts. Reasonable when calling from a request handler with a\n * tight latency budget. Default: unbounded.\n */\n smtpTotalDeadlineMs?: number;\n /**\n * Stop the SMTP probe after this many connection-class failures in a row\n * (counting `connection_error` / `connection_timeout` / `connection_closed`\n * across MX × port attempts). Resets on any non-connection-class outcome.\n * Default: unbounded.\n */\n smtpMaxConsecutiveFailures?: number;\n /**\n * Hard cap on how many MX hostnames the SMTP probe will try, regardless of\n * how many DNS returned. Default: unbounded — try them all.\n */\n smtpMaxMxHosts?: number;\n /** Optional retry policy for connection-class failures on a single MX × port. Default: no retries. */\n smtpRetry?: RetryPolicy;\n /**\n * Force a specific port for the SMTP probe (e.g. `587`). When set, this\n * port is the only one tried — overrides the default `[25, 587, 465]` walk\n * and any per-MX hint cached from a previous probe.\n */\n smtpPort?: number;\n /**\n * Strategy for the `MAIL FROM:` envelope sender during the SMTP probe.\n * See `SMTPSenderStrategy` for the menu. Picking a deliberate strategy\n * (e.g. `{ kind: 'null-sender' }`) reduces spam-flagging vs. the library\n * default of `<recipient@domain>`. Default: unset → uses recipient address\n * (preserved for backwards compatibility, but not recommended for\n * production probes).\n */\n smtpSender?: SMTPSenderStrategy;\n /**\n * EHLO/HELO hostname presented to the MX during the SMTP probe. Should be\n * a real FQDN — `'localhost'` from a public IP is a spam-bot signature\n * and gets rejected by careful MXes. Default: `'localhost'` (preserved for\n * backwards compatibility; override in production).\n */\n smtpHeloHostname?: string;\n // ── WHOIS probe wiring ────────────────────────────────────────────────────\n /** Per-WHOIS-query timeout in milliseconds. Default: `5000`. */\n whoisTimeoutMs?: number;\n // ── Caching + diagnostics ────────────────────────────────────────────────\n /** Optional shared cache for MX, WHOIS, disposable / free, SMTP, and domain results. */\n cache?: Cache;\n /** When true, the pipeline writes a per-line trace to `console.debug`. Default: `false`. */\n debug?: boolean;\n /**\n * When true, populates `result.transcript` with a per-step structured trace\n * covering every subsystem (syntax / disposable / free / MX / SMTP / WHOIS /\n * name detection / domain suggestion). Each step records timing +\n * step-specific details (raw WHOIS data, SMTP transcript, MX records, cache\n * hit/miss, etc.). Safe to leave off for production; turn on for diagnostics\n * or debug UIs. Default: `false`.\n */\n captureTranscript?: boolean;\n}\n\n/**\n * Parameters for `verifyEmailBatch` — fan-out wrapper around `verifyEmail`\n * that runs many addresses through the same pipeline with a concurrency cap.\n */\nexport interface BatchVerifyParams {\n /** Email addresses to verify, in order. */\n emailAddresses: string[];\n /** Maximum number of in-flight `verifyEmail` calls. Default: `5`. */\n concurrency?: number;\n /** Per-attempt SMTP timeout in milliseconds (forwarded to each `verifyEmail` call). Default: `4000`. */\n smtpPerAttemptTimeoutMs?: number;\n /** Hard cap on total wall-clock for each individual SMTP probe. Forwarded to `verifyEmail`. */\n smtpTotalDeadlineMs?: number;\n /** Stop each individual SMTP probe after this many connection-class failures in a row. */\n smtpMaxConsecutiveFailures?: number;\n /** Hard cap on MX hostnames per individual SMTP probe. */\n smtpMaxMxHosts?: number;\n /** Optional retry policy per MX×port for each individual SMTP probe. */\n smtpRetry?: RetryPolicy;\n /** Resolve MX records per address. Default: `true`. */\n verifyMx?: boolean;\n /** Run the SMTP probe per address. Default: `false`. */\n verifySmtp?: boolean;\n /** Check disposable list per address. Default: `true`. */\n checkDisposable?: boolean;\n /** Check free-provider list per address. Default: `true`. */\n checkFree?: boolean;\n /** Extract first/last name from each local-part. Default: `false`. */\n detectName?: boolean;\n /** Override the name-detection heuristic. */\n nameDetectionMethod?: NameDetectionMethod;\n /** Suggest a corrected domain on typos. Default: `false` for batches (it's per-call cost). */\n suggestDomain?: boolean;\n /** Override the domain-suggestion heuristic. */\n domainSuggestionMethod?: DomainSuggestionMethod;\n /** Custom canonical-domain list for the typo suggester. */\n commonDomains?: string[];\n /** Skip MX/SMTP probe for disposable addresses. Default: `false`. */\n skipMxForDisposable?: boolean;\n /** Skip WHOIS lookups for disposable addresses. Default: `false`. */\n skipDomainWhoisForDisposable?: boolean;\n /** Optional shared cache (re-used across all addresses in the batch). */\n cache?: Cache;\n}\n\n/**\n * Rich cache result types for storing detailed verification results\n */\n\n/**\n * Result for disposable email detection with metadata\n */\nexport interface DisposableEmailResult {\n /** Whether the email/domain is disposable */\n isDisposable: boolean;\n /** Source that identified this as disposable (e.g., list name, service) */\n source?: string;\n /** Category of disposable email (e.g., 'temp', 'alias', 'forwarding') */\n category?: string;\n /** Timestamp when this was checked */\n checkedAt: number;\n}\n\n/**\n * Result for free email provider detection with metadata\n */\nexport interface FreeEmailResult {\n /** Whether the email/domain is from a free provider */\n isFree: boolean;\n /** Name of the free provider (e.g., 'gmail', 'yahoo', 'outlook') */\n provider?: string;\n /** Timestamp when this was checked */\n checkedAt: number;\n}\n\n/**\n * Result for domain validation with metadata\n */\nexport interface DomainValidResult {\n /** Whether the domain is valid */\n isValid: boolean;\n /** Whether MX records were found */\n hasMX: boolean;\n /** The MX records that were found */\n mxRecords?: string[];\n /** Timestamp when this was checked */\n checkedAt: number;\n}\n\n/**\n * Email providers enum\n */\nexport enum EmailProvider {\n gmail = 'gmail',\n hotmailB2b = 'hotmail_b2b',\n hotmailB2c = 'hotmail_b2c',\n proofpoint = 'proofpoint',\n mimecast = 'mimecast',\n yahoo = 'yahoo',\n everythingElse = 'everything_else',\n}\n\n/**\n * Verdict from one `verifyMailboxSMTP` call. Flat by design — every field is\n * one boolean / scalar so callers can switch on a few keys instead of walking\n * a tree.\n */\nexport interface SmtpVerificationResult {\n /** True when at least one MX×port responded with an SMTP greeting. */\n canConnectSmtp: boolean;\n /** True when the MX returned `552` / `452` (over-quota / mailbox full). */\n hasFullInbox: boolean;\n /**\n * True when both the real RCPT TO and the random-local probe RCPT TO\n * returned `250` — the MX accepts every recipient and the deliverability\n * signal for the real address is unreliable.\n */\n isCatchAll: boolean;\n /** True when the real RCPT TO returned `250` / `251`. */\n isDeliverable: boolean;\n /** True when the real RCPT TO was definitively rejected. */\n isDisabled: boolean;\n /**\n * Short reason key when `isDeliverable === false`. Vocabulary:\n * `not_found` | `over_quota` | `temporary_failure` | `ambiguous` |\n * `connection_error` | `connection_timeout` | `connection_closed` |\n * `tls_upgrade_failed` | `tls_handshake_failed` |\n * `ehlo_failed` | `helo_failed` | `mail_from_rejected` |\n * `no_greeting` | `no_mx_records` | `unrecognized_response` |\n * `step_timeout` | `socket_timeout`\n *\n * Pass to `refineReasonByEnhancedStatus(error, enhancedStatus)` for a\n * richer (mailbox-status-aware) reason when the MX returned a DSN.\n */\n error?: string;\n /** Most recent 3-digit SMTP code observed during the probe. */\n responseCode?: number;\n /**\n * RFC 3463 enhanced status code from the most recent SMTP reply that\n * carried one — e.g. `\"5.1.1\"` (mailbox unknown), `\"5.7.1\"` (policy\n * block), `\"4.7.0\"` (transient policy). Undefined when no MX reply\n * included an enhanced status.\n */\n enhancedStatus?: string;\n /** Operational counters — always populated. See `SmtpProbeMetrics`. */\n metrics?: SmtpProbeMetrics;\n /** Wall-clock timestamp this verdict was produced (set on every result). */\n checkedAt?: number;\n /**\n * Server reply lines, in arrival order, prefixed `<host>:<port>|s| <line>`\n * so multi-MX dialogues stay readable. Present only when\n * `captureTranscript: true` was passed.\n */\n transcript?: string[];\n /**\n * Client commands sent, in send order, prefixed `<host>:<port>|c| <cmd>`.\n * Present only when `captureTranscript: true` was passed.\n */\n commands?: string[];\n}\n\n/**\n * Operational counters for one `verifyMailboxSMTP` call. The cost of\n * collecting these is trivial — pure bookkeeping during the existing flow.\n */\nexport interface SmtpProbeMetrics {\n /** How many MX hostnames the outer loop attempted before stopping. */\n mxAttempts: number;\n /** Total connection attempts across the whole call (sum across MX×port). */\n portAttempts: number;\n /** MX hostnames attempted in priority order (matches `mxRecords` slice). */\n mxHostsTried: string[];\n /**\n * MX hostname that produced the final answer. Undefined when every MX\n * failed (in which case `result.isDeliverable === false` and the SMTP\n * reason is whatever the last attempted MX returned).\n */\n mxHostUsed?: string;\n /** Total wall-clock time the probe spent, in milliseconds. */\n totalDurationMs: number;\n}\n\n/**\n * Result for batch verification\n */\nexport interface BatchVerificationResult {\n results: Map<string, VerificationResult>;\n summary: {\n total: number;\n valid: number;\n invalid: number;\n errors: number;\n processingTime: number;\n };\n}\n\n/** TLS configuration options for the SMTP probe. */\nexport interface SMTPTLSConfig {\n rejectUnauthorized?: boolean;\n minVersion?: 'TLSv1.2' | 'TLSv1.3';\n}\n\n/**\n * SMTP protocol steps walked by the verifier in order. `startTls` is a\n * conditional step — it sends the STARTTLS command and upgrades the socket\n * to TLS when the MX advertised support (controlled by\n * `SMTPVerifyOptions.startTls`). On implicit-TLS ports (465) it's a no-op.\n */\nexport enum SMTPStep {\n greeting = 'GREETING',\n ehlo = 'EHLO',\n helo = 'HELO',\n startTls = 'STARTTLS',\n mailFrom = 'MAIL_FROM',\n rcptTo = 'RCPT_TO',\n}\n\n/** Custom SMTP step sequence for advanced callers. */\nexport interface SMTPSequence {\n steps: SMTPStep[];\n /** Override MAIL FROM payload — supply with angle brackets or `<>` for null sender. */\n from?: string;\n}\n\n/**\n * High-level policy for picking the `MAIL FROM:` payload sent during SMTP\n * verification. Most callers should use this rather than `SMTPSequence.from`.\n *\n * Why this matters: `MAIL FROM:` is the single biggest spam-fingerprint on a\n * verification probe. The library's historical default (`<recipient@domain>`)\n * is exactly what blocklists key on — sender == recipient is the textbook\n * \"fake bounce probe\" pattern. Picking a deliberate strategy lets you choose\n * how the probe presents itself to the MX:\n *\n * - `'null-sender'`: RFC 5321 §4.5.5 null reverse-path `<>`. DSN/bounce-shaped.\n * Best deliverability vs spam-flagging on Gmail / Outlook (they whitelist\n * `<>` so they don't recursively bounce a bounce). Some strict gateways\n * (Yahoo / Proofpoint / Mimecast) reject `<>` from unknown IPs — those\n * rejections are clean `550`s, they don't burn IP reputation.\n * - `'fixed'`: a real address on a domain you own (with valid SPF / PTR /\n * DMARC). Best deliverability when properly authenticated; worst when not.\n * - `'random-at-recipient'`: random local-part on the recipient's own domain\n * (e.g. `<probe-a3x9…@gmail.com>` when probing `alice@gmail.com`). Looks\n * like internal-domain mail to MTAs that prefer same-envelope-domain.\n * - `'random-at-domain'`: random local-part on a fixed sender domain. Useful\n * when you control a domain but want unique probe envelopes per call.\n * - `'custom'`: full escape hatch — receives the recipient, returns the\n * literal `MAIL FROM:` payload (with angle brackets).\n */\nexport type SMTPSenderStrategy =\n | { kind: 'null-sender' }\n | { kind: 'fixed'; address: string }\n | { kind: 'random-at-recipient'; localPrefix?: string }\n | { kind: 'random-at-domain'; domain: string; localPrefix?: string }\n | { kind: 'custom'; build: (recipient: { local: string; domain: string }) => string };\n\n/**\n * Optional retry policy for connection-class failures (timeout / connection\n * error / connection closed) on a single MX × port. Definitive answers\n * (250 / 550 / 552 / etc.) are never retried — they're stable verdicts.\n */\nexport interface RetryPolicy {\n /**\n * How many extra attempts to make on the same MX × port after a\n * connection-class failure. `0` means no retry (the default).\n */\n attempts: number;\n /**\n * Delay between retries, in milliseconds. With `backoff: 'exponential'`\n * (the default), the actual delay is `delayMs * 2^(attemptIndex - 1)`.\n * Default: `200` ms.\n */\n delayMs?: number;\n /**\n * Backoff strategy between retries.\n * - `'exponential'` (default): `delayMs * 2^(attemptIndex - 1)`.\n * - `'fixed'`: every retry waits `delayMs` exactly.\n */\n backoff?: 'exponential' | 'fixed';\n}\n\n/**\n * Options for `verifyMailboxSMTP` and `verifyEmail`'s SMTP probe.\n *\n * Time-budget defaults are tuned for a 4-MX × 3-port worst case. If you\n * call this from a request handler with a tight latency budget, set\n * `totalDeadlineMs` so the probe gives up before your handler does.\n */\nexport interface SMTPVerifyOptions {\n // ── Connection envelope ───────────────────────────────────────────────────\n /**\n * Ports to walk per MX, in priority order. The probe stops on the first\n * port that yields a definitive answer; indeterminate outcomes (timeout /\n * connection error / etc.) fall through to the next port.\n *\n * Default: `[25, 587, 465]` — plain → STARTTLS-able → implicit-TLS.\n */\n ports?: number[];\n /**\n * Per-attempt timeout in milliseconds. Bounds both the TCP/TLS connection\n * setup AND the inactivity gap between SMTP commands within an attempt.\n * Each MX × port pair gets its own budget — to bound the total wall-clock,\n * use `totalDeadlineMs` instead.\n *\n * Default: `3000` ms.\n */\n perAttemptTimeoutMs?: number;\n /**\n * TLS configuration applied to implicit-TLS ports (465) and to STARTTLS\n * upgrades on plaintext ports.\n *\n * - `true` (default): use sensible TLS defaults (`rejectUnauthorized: false`,\n * `minVersion: 'TLSv1.2'`) — picks up CA quirks of long-tail MXes.\n * - `false`: disable TLS entirely (port 465 will fail to handshake; STARTTLS\n * step is skipped).\n * - `SMTPTLSConfig` object: override individual fields. Merged onto the defaults.\n */\n tlsConfig?: boolean | SMTPTLSConfig;\n /**\n * Hostname this client identifies itself as in the `EHLO` / `HELO` argument.\n * Should be a real FQDN — `localhost` from a public IP is a textbook spam-bot\n * signature and gets rejected by careful MXes.\n *\n * Default: `'localhost'`. Override with your delivery domain in production.\n */\n heloHostname?: string;\n // ── Caching ──────────────────────────────────────────────────────────────\n /**\n * Optional cache instance. When provided, the probe reuses prior verdicts\n * keyed on `<primary mx>:<local>@<domain>` and remembers the last\n * successful port per primary MX (so a re-probe skips the failed-port\n * walk).\n *\n * Pass `null` or omit to skip caching entirely.\n */\n cache?: Cache | null;\n /**\n * When true, a per-line `[SMTP] …` trace is written to `console.log`.\n * Useful for diagnosing real-MX behavior; off by default for production.\n */\n debug?: boolean;\n /**\n * When true, the returned `SmtpVerificationResult` carries `transcript`\n * and `commands` arrays prefixed with `<host>:<port>|s| …` /\n * `<host>:<port>|c| …`. Aggregated across every MX × port attempted.\n *\n * Default: `false`. The strings are O(N × wire-bytes); skip when you\n * don't need the trace.\n */\n captureTranscript?: boolean;\n // ── Time budget + early-stop policy ───────────────────────────────────────\n /**\n * Hard cap on total wall-clock time for the entire probe (across all\n * MX × port × retry attempts). When the deadline passes, the in-flight\n * attempt is allowed to finish (it has its own per-attempt budget) and\n * no new attempts are started.\n *\n * Use this to bound latency from a request-handler caller. A reasonable\n * value matches your handler's deadline minus headroom for everything\n * else it does.\n *\n * Default: unbounded — only `perAttemptTimeoutMs × ports.length × mxRecords.length`\n * limits the worst case (e.g. `3000 × 3 × 4 = 36s`).\n */\n totalDeadlineMs?: number;\n /**\n * Stop probing after this many connection-class failures in a row.\n * Counts consecutive `connection_error` / `connection_timeout` /\n * `connection_closed` outcomes across MX × port attempts; resets on any\n * non-connection-class outcome. Useful for cutting off probes when the\n * network path to the MX is wholly unreachable instead of waiting for\n * every port × MX combination to time out.\n *\n * Default: unbounded.\n */\n maxConsecutiveFailures?: number;\n /**\n * Hard cap on how many MX hostnames to try, regardless of how many were\n * supplied in `mxRecords`. The probe walks them in priority order\n * (`mxRecords[0]` first) and stops after this many.\n *\n * Default: unbounded.\n */\n maxMxHosts?: number;\n /**\n * Optional retry policy for connection-class failures on a single MX × port.\n * Definitive answers (250 / 550 / 552 / 421 / etc.) are never retried —\n * they're stable verdicts.\n *\n * Default: no retries.\n */\n retry?: RetryPolicy;\n // ── Dialogue customization ───────────────────────────────────────────────\n /**\n * Strategy for picking the `MAIL FROM:` envelope sender. See\n * `SMTPSenderStrategy` for the full menu (`null-sender` / `fixed` /\n * `random-at-recipient` / `random-at-domain` / `custom`).\n *\n * When set, this overrides any `sequence.from`. When unset, the probe falls\n * back to `sequence.from` (legacy low-level override) and finally to the\n * default `<local@domain>` (the recipient's own address — note that this\n * default is the textbook spam-probe fingerprint, so opting into a real\n * strategy is recommended for production use).\n */\n sender?: SMTPSenderStrategy;\n /**\n * Override the per-attempt SMTP step list. Defaults to\n * `[greeting, ehlo, startTls, mailFrom, rcptTo]` — covering the entire\n * RFC 5321 envelope plus optional TLS upgrade. Most callers never need\n * to override this; useful for advanced testing scenarios (e.g. probe\n * RFC compliance with `[greeting, helo, mailFrom, rcptTo]`).\n */\n sequence?: SMTPSequence;\n /**\n * Override the random local-part generator used by the catch-all dual\n * probe. Useful for deterministic tests; receives the real local-part\n * and domain so callers can derive a probe-local that matches the MX's\n * syntax rules.\n *\n * Default: `<16 hex chars>-noexist` — long enough to never collide,\n * structured so it's clearly synthetic, and passes common syntax filters.\n */\n catchAllProbeLocal?: (realLocal: string, domain: string) => string;\n /**\n * SMTP PIPELINING (RFC 2920) — batch the envelope phase\n * (RCPT TO real + RCPT TO probe + RSET) into one `socket.write()` when\n * the MX advertises support.\n *\n * - `'auto'` (default): pipeline when EHLO multi-line includes `PIPELINING`,\n * sequential otherwise.\n * - `'never'`: always sequential — useful for deterministic wire-level\n * assertions in tests or when investigating a pipeline-buggy MX.\n * - `'force'`: pipeline without checking — testing escape hatch.\n */\n pipelining?: 'auto' | 'never' | 'force';\n /**\n * STARTTLS upgrade on plaintext ports (25, 587). Implicit-TLS ports (465)\n * ignore this option — they're already TLS from the start.\n *\n * - `'auto'` (default): upgrade if the MX advertises STARTTLS in EHLO.\n * Submission-port (587) MXes typically require this — without it,\n * `MAIL FROM` is rejected with `530 Must issue STARTTLS first`.\n * - `'never'`: never upgrade — send `MAIL FROM` / `RCPT TO` in plaintext.\n * - `'force'`: send `STARTTLS` unconditionally. Fails with\n * `tls_upgrade_failed` when the MX doesn't support it. Testing only.\n */\n startTls?: 'auto' | 'never' | 'force';\n}\n\nexport interface VerifyMailboxSMTPParams {\n local: string;\n domain: string;\n mxRecords: string[];\n options?: SMTPVerifyOptions;\n}\n\n/**\n * Domain suggestion for typo correction\n */\nexport interface DomainSuggestion {\n original: string;\n suggested: string;\n confidence: number;\n}\n\n/**\n * Custom domain suggestion function type\n */\nexport type DomainSuggestionMethod = (domain: string) => DomainSuggestion | null;\n\n/**\n * Parameters for domain suggestion\n */\nexport interface DomainSuggestionParams {\n domain: string;\n customMethod?: DomainSuggestionMethod;\n commonDomains?: string[];\n cache?: Cache;\n}\n\n/**\n * Result of name detection from email\n */\nexport interface DetectedName {\n firstName?: string;\n lastName?: string;\n confidence: number;\n}\n\n/**\n * Custom name detection function type\n */\nexport type NameDetectionMethod = (email: string) => DetectedName | null;\n\n/**\n * Parameters for name detection\n */\nexport interface NameDetectionParams {\n email: string;\n customMethod?: NameDetectionMethod;\n}\n\n/**\n * Domain age information\n */\nexport interface DomainAgeInfo {\n domain: string;\n creationDate: Date;\n ageInDays: number;\n ageInYears: number;\n expirationDate: Date | null;\n updatedDate: Date | null;\n}\n\n/**\n * Domain registration status information\n */\nexport interface DomainRegistrationInfo {\n domain: string;\n isRegistered: boolean;\n isAvailable: boolean;\n status: string[];\n registrar: string | null;\n nameServers: string[];\n expirationDate: Date | null;\n isExpired: boolean;\n daysUntilExpiration: number | null;\n isPendingDelete?: boolean;\n isLocked?: boolean;\n}\n\n/**\n * Options for domain suggester\n */\nexport interface DomainSuggesterOptions {\n threshold?: number;\n customDomains?: string[];\n}\n\n/**\n * Parameters for isDisposableEmail function\n */\nexport interface DisposableEmailCheckParams {\n emailOrDomain: string;\n cache?: Cache | null;\n logger?: (...args: unknown[]) => void;\n}\n\n/**\n * Parameters for isFreeEmail function\n */\nexport interface FreeEmailCheckParams {\n emailOrDomain: string;\n cache?: Cache | null;\n logger?: (...args: unknown[]) => void;\n}\n\n/**\n * Parameters for resolveMxRecords function\n */\nexport interface ResolveMxParams {\n domain: string;\n cache?: Cache | null;\n logger?: (...args: unknown[]) => void;\n}\n\n/**\n * Options for email validation (serverless compatible)\n */\nexport interface ValidateEmailOptions {\n validateSyntax?: boolean;\n validateTypo?: boolean;\n validateDisposable?: boolean;\n validateFree?: boolean;\n validateMx?: boolean;\n validateSMTP?: boolean;\n skipCache?: boolean;\n batchSize?: number;\n domainSuggesterOptions?: DomainSuggesterOptions;\n}\n\n/**\n * Result of email validation (serverless compatible)\n */\nexport interface EmailValidationResult {\n valid: boolean;\n email: string;\n local?: string;\n domain?: string;\n validators: {\n syntax?: ValidatorResult;\n typo?: ValidatorResult & { suggestion?: string };\n disposable?: ValidatorResult;\n free?: ValidatorResult;\n mx?: ValidatorResult & { records?: string[]; error?: string };\n smtp?: ValidatorResult & { error?: string };\n };\n}\n\n/**\n * Individual validator result\n */\nexport interface ValidatorResult {\n valid: boolean;\n}\n\n// Re-export cache interfaces\nexport type { Cache, CacheStore } from './cache-interface';\n","import { LRUAdapter } from './adapters/lru-adapter';\nimport type { Cache, CacheStore } from './cache-interface';\nimport type { DisposableEmailResult, DomainValidResult, FreeEmailResult, SmtpVerificationResult } from './types';\nimport type { ParsedWhoisResult } from './whois-parser';\n\n/**\n * Default cache options\n */\nexport const DEFAULT_CACHE_OPTIONS = {\n ttl: {\n mx: 3600000,\n disposable: 86400000,\n free: 86400000,\n domainValid: 86400000,\n smtp: 1800000,\n smtpPort: 86400000,\n domainSuggestion: 86400000,\n whois: 3600000,\n },\n maxSize: {\n mx: 10000,\n disposable: 10000,\n free: 10000,\n domainValid: 10000,\n smtp: 10000,\n smtpPort: 10000,\n domainSuggestion: 10000,\n whois: 10000,\n },\n};\n\n/**\n * Lazy-loaded default cache instance\n */\nlet defaultCacheInstance: Cache | null = null;\n\n/**\n * Get the default in-memory cache singleton using LRU\n * This is created on first access and reused for all subsequent calls\n */\nexport function getDefaultCache(): Cache {\n if (!defaultCacheInstance) {\n defaultCacheInstance = {\n mx: new LRUAdapter<string[]>(DEFAULT_CACHE_OPTIONS.maxSize.mx, DEFAULT_CACHE_OPTIONS.ttl.mx),\n disposable: new LRUAdapter<DisposableEmailResult>(\n DEFAULT_CACHE_OPTIONS.maxSize.disposable,\n DEFAULT_CACHE_OPTIONS.ttl.disposable\n ),\n free: new LRUAdapter<FreeEmailResult>(DEFAULT_CACHE_OPTIONS.maxSize.free, DEFAULT_CACHE_OPTIONS.ttl.free),\n domainValid: new LRUAdapter<DomainValidResult>(\n DEFAULT_CACHE_OPTIONS.maxSize.domainValid,\n DEFAULT_CACHE_OPTIONS.ttl.domainValid\n ),\n smtp: new LRUAdapter<SmtpVerificationResult>(DEFAULT_CACHE_OPTIONS.maxSize.smtp, DEFAULT_CACHE_OPTIONS.ttl.smtp),\n smtpPort: new LRUAdapter<number>(DEFAULT_CACHE_OPTIONS.maxSize.smtpPort, DEFAULT_CACHE_OPTIONS.ttl.smtpPort),\n domainSuggestion: new LRUAdapter<{ suggested: string; confidence: number } | null>(\n DEFAULT_CACHE_OPTIONS.maxSize.domainSuggestion,\n DEFAULT_CACHE_OPTIONS.ttl.domainSuggestion\n ),\n whois: new LRUAdapter<ParsedWhoisResult>(DEFAULT_CACHE_OPTIONS.maxSize.whois, DEFAULT_CACHE_OPTIONS.ttl.whois),\n };\n }\n return defaultCacheInstance;\n}\n\n/**\n * Helper function to get cache store from cache parameter\n * Follows same pattern as logging - use passed cache or default\n */\nexport function getCacheStore<T>(cache: Cache | null | undefined, key: keyof Cache): CacheStore<T> {\n return (cache?.[key] || getDefaultCache()[key]) as CacheStore<T>;\n}\n\n/**\n * Clear all entries from every store in the default cache instance.\n * No-op if the cache hasn't been lazily constructed yet.\n */\nexport function clearDefaultCache(): void {\n if (!defaultCacheInstance) return;\n for (const store of Object.values(defaultCacheInstance)) {\n store.clear();\n }\n}\n\nexport type { Cache, CacheStore } from './cache-interface';\n","import { stringSimilarity } from 'string-similarity-js';\nimport { getCacheStore } from './cache';\nimport type { Cache } from './cache-interface';\nimport commonEmailDomainsJson from './data/common-email-domains.json';\nimport typoPatternsJson from './data/typo-patterns.json';\nimport type { DomainSuggestion, DomainSuggestionParams } from './types';\n\n/**\n * List of common email domains for typo detection — popular free providers,\n * business providers, and hosting services. Source data lives in\n * src/data/common-email-domains.json.\n */\nexport const commonEmailDomains: readonly string[] = commonEmailDomainsJson as string[];\n\n/**\n * Hand-curated typo → canonical map. Faster + more accurate than the\n * similarity heuristic for common misspellings of the top providers.\n */\nconst TYPO_PATTERNS = typoPatternsJson as Record<string, string[]>;\n\n/**\n * Calculate similarity threshold based on domain length\n * Shorter domains need higher similarity to avoid false positives\n */\nfunction getSimilarityThreshold(domain: string) {\n const length = domain.length;\n if (length <= 6) return 0.85; // Short domains need high similarity\n if (length <= 10) return 0.8; // Medium domains\n return 0.75; // Longer domains can have lower threshold\n}\n\n/**\n * Pure matching logic — no caching, no I/O. Returns the best suggestion for\n * `domain` against `candidates` or null. Both the sync and the async\n * (cache-aware) public entry points share this single implementation.\n */\nfunction findSuggestion(domain: string, candidates: readonly string[]): DomainSuggestion | null {\n const lower = domain.toLowerCase();\n\n // Already a known good domain → no suggestion.\n if (candidates.includes(lower)) return null;\n\n // Hand-crafted typo table beats the similarity heuristic for common cases.\n for (const [correct, typos] of Object.entries(TYPO_PATTERNS)) {\n if (typos.includes(lower)) {\n return { original: domain, suggested: correct, confidence: 0.95 };\n }\n }\n\n const threshold = getSimilarityThreshold(lower);\n let best: { domain: string; similarity: number } | null = null;\n\n for (const candidate of candidates) {\n const similarity = stringSimilarity(lower, candidate.toLowerCase());\n if (similarity >= threshold && (!best || similarity > best.similarity)) {\n best = { domain: candidate, similarity };\n }\n }\n\n // Second pass with a relaxed threshold for length-similar domains.\n if (!best) {\n for (const candidate of candidates) {\n if (Math.abs(lower.length - candidate.length) > 2) continue;\n const similarity = stringSimilarity(lower, candidate.toLowerCase());\n if (similarity >= 0.7 && (!best || similarity > best.similarity)) {\n best = { domain: candidate, similarity };\n }\n }\n }\n\n if (!best) return null;\n // Reject suggestions whose first letter differs unless similarity is very high\n // — this avoids \"amazon.com\" being suggested for \"yahoo.com\" type junk.\n if (best.domain.charAt(0) !== lower.charAt(0) && best.similarity < 0.9) return null;\n\n return { original: domain, suggested: best.domain, confidence: best.similarity };\n}\n\n/** Sync default — no cache. Public for callers that need a synchronous answer. */\nexport function defaultDomainSuggestionMethod(domain: string, commonDomains?: string[]): DomainSuggestion | null {\n if (!domain || domain.length < 3) return null;\n return findSuggestion(domain, commonDomains ?? commonEmailDomains);\n}\n\n/** Async default — wraps the sync match with a per-domain cache layer. */\nexport async function defaultDomainSuggestionMethodAsync(\n domain: string,\n commonDomains?: string[],\n cache?: Cache\n): Promise<DomainSuggestion | null> {\n if (!domain || domain.length < 3) return null;\n const candidates = commonDomains ?? commonEmailDomains;\n const cacheKey = `${domain.toLowerCase()}:${candidates.length}`;\n const cacheStore = getCacheStore<DomainSuggestion | null>(cache, 'domainSuggestion');\n\n const cached = await cacheStore.get(cacheKey);\n if (cached !== null && cached !== undefined) return cached as DomainSuggestion | null;\n\n const result = findSuggestion(domain, candidates);\n await cacheStore.set(cacheKey, result);\n return result;\n}\n\n/** Sync entry: pass a domain (or email-shaped string), get a suggestion or null. */\nexport function suggestDomain(params: DomainSuggestionParams): DomainSuggestion | null {\n const { domain, customMethod, commonDomains } = params;\n if (!domain || domain.length < 3) return null;\n\n if (customMethod) {\n try {\n return customMethod(domain);\n } catch (error) {\n // Fall back to the default if the user's method throws.\n console.warn('Custom domain suggestion method failed, falling back to default:', error);\n }\n }\n return defaultDomainSuggestionMethod(domain, commonDomains);\n}\n\n/** Async entry: takes a full email, returns a suggestion that rewrites the local-part too. */\nexport async function suggestEmailDomain(\n email: string,\n commonDomains?: string[],\n cache?: Cache\n): Promise<DomainSuggestion | null> {\n if (!email?.includes('@')) return null;\n const [localPart, domain] = email.split('@');\n if (!domain || !localPart) return null;\n\n const suggestion = await defaultDomainSuggestionMethodAsync(domain, commonDomains, cache);\n if (!suggestion) return null;\n\n return {\n original: email,\n suggested: `${localPart}@${suggestion.suggested}`,\n confidence: suggestion.confidence,\n };\n}\n\nexport function isCommonDomain(domain: string, commonDomains?: string[]): boolean {\n return (commonDomains ?? commonEmailDomains).includes(domain.toLowerCase());\n}\n\nexport function getDomainSimilarity(domain1: string, domain2: string): number {\n return stringSimilarity(domain1.toLowerCase(), domain2.toLowerCase());\n}\n","import { isValid } from 'psl';\nimport { getCacheStore } from './cache';\nimport type { Cache } from './cache-interface';\nimport type { DomainValidResult } from './types';\n\n/**\n * Validates if email domain is valid TLD\n */\nexport async function isValidEmailDomain(emailOrDomain: string, cache?: Cache | null): Promise<boolean> {\n let [localPart, emailDomain] = emailOrDomain?.split('@') || [];\n if (!emailDomain) {\n emailDomain = localPart;\n }\n if (!emailDomain) {\n return false;\n }\n\n // Check cache first - now uses rich DomainValidResult\n const cacheStore = getCacheStore<DomainValidResult>(cache, 'domainValid');\n const cached = await cacheStore.get(emailDomain);\n if (cached !== null && cached !== undefined) {\n return cached.isValid;\n }\n\n try {\n const isValidResult = isValid(emailDomain) || false;\n\n // Store rich result in cache\n const richResult: DomainValidResult = {\n isValid: isValidResult,\n hasMX: false, // MX not checked in this function\n checkedAt: Date.now(),\n };\n\n await cacheStore.set(emailDomain, richResult);\n return isValidResult;\n } catch (validationError) {\n const errorResult: DomainValidResult = {\n isValid: false,\n hasMX: false,\n checkedAt: Date.now(),\n };\n await cacheStore.set(emailDomain, errorResult);\n return false;\n }\n}\n\n/**\n * Validates email-address format with a pragmatic (not strictly RFC-5322) regex.\n *\n * The local-part allow-list is `[a-zA-Z0-9._+'-]` — letters, digits, dot,\n * underscore, plus, apostrophe, hyphen. Characters that are technically valid\n * in RFC atext but virtually never appear in real mailboxes (`= ? ^ ~ { } | *\n * & % $ # ! / `` `) are rejected. Quoted local-parts (`\"...\"@example.com`) are\n * accepted as-is — they're rare but legal — but their interior is not parsed.\n */\nexport function isValidEmail(emailAddress: string) {\n if (!emailAddress || typeof emailAddress !== 'string') {\n return false;\n }\n\n // Local-part: dot-atom-text with the pragmatic character set, OR a\n // quoted-string. Domain: IPv4 literal in brackets, OR labels-and-TLD.\n const re =\n /^(([a-zA-Z0-9_+'-]+(\\.[a-zA-Z0-9_+'-]+)*)|(\".+\"))@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}])|(([a-zA-Z0-9-]+\\.)+[a-zA-Z]{2,}))$/;\n\n const emailLower = emailAddress.toLowerCase();\n\n // Heuristic guards on top of the regex — these are subtle invalid patterns\n // that the regex's dot-atom structure can still permit at the seams.\n if (emailLower.indexOf('.+') !== -1) return false;\n if (emailLower.indexOf('..') !== -1) return false;\n if (emailLower.startsWith('.') || emailLower.endsWith('.')) return false;\n\n const parts = emailAddress.split('@');\n if (parts.length !== 2) return false;\n\n const [localPart, domain] = parts;\n if (!localPart || !domain) return false;\n if (localPart.length > 64) return false; // RFC 5321\n if (domain.length > 253) return false; // RFC 5321\n\n return re.test(emailLower);\n}\n","import { getCacheStore } from './cache';\nimport disposableProviders from './disposable-email-providers.json';\nimport type { DisposableEmailCheckParams, DisposableEmailResult } from './types';\n\nconst disposableEmailProviders: Set<string> = new Set(disposableProviders as string[]);\n\n/**\n * Check whether the email's domain is on the bundled disposable-provider list.\n * Result is rich-cached (`DisposableEmailResult`) so repeated calls hit a Set\n * lookup behind a CacheStore<T>.\n */\nexport async function isDisposableEmail(params: DisposableEmailCheckParams): Promise<boolean> {\n const { emailOrDomain, cache, logger } = params;\n const log = logger || (() => {});\n\n const parts = emailOrDomain.split('@');\n const emailDomain = parts.length > 1 ? parts[1] : parts[0];\n if (!emailDomain) return false;\n\n const cacheStore = getCacheStore<DisposableEmailResult>(cache, 'disposable');\n let cached: DisposableEmailResult | null | undefined;\n try {\n cached = await cacheStore.get(emailDomain);\n } catch {\n cached = null;\n }\n if (cached !== null && cached !== undefined) {\n log(`[isDisposableEmail] Cache hit for ${emailDomain}: ${cached.isDisposable}`);\n return cached.isDisposable;\n }\n\n const isDisposable = disposableEmailProviders.has(emailDomain);\n const richResult: DisposableEmailResult = {\n isDisposable,\n source: 'disposable-email-providers.json',\n category: isDisposable ? 'disposable' : undefined,\n checkedAt: Date.now(),\n };\n\n try {\n await cacheStore.set(emailDomain, richResult);\n log(`[isDisposableEmail] Cached result for ${emailDomain}: ${isDisposable}`);\n } catch {\n log(`[isDisposableEmail] Cache write error for ${emailDomain}`);\n }\n log(`[isDisposableEmail] Check result for ${emailDomain}: ${isDisposable}`);\n return isDisposable;\n}\n","import { getCacheStore } from './cache';\nimport freeProviders from './free-email-providers.json';\nimport type { FreeEmailCheckParams, FreeEmailResult } from './types';\n\nconst freeEmailProviders: Set<string> = new Set(freeProviders as string[]);\n\n/**\n * Check whether the email's domain is on the bundled free-provider list.\n * Result is rich-cached (`FreeEmailResult`) so repeated calls hit a Set\n * lookup behind a CacheStore<T>.\n */\nexport async function isFreeEmail(params: FreeEmailCheckParams): Promise<boolean> {\n const { emailOrDomain, cache, logger } = params;\n const log = logger || (() => {});\n\n const parts = emailOrDomain.split('@');\n const emailDomain = parts.length > 1 ? parts[1] : parts[0];\n if (!emailDomain) return false;\n\n const cacheStore = getCacheStore<FreeEmailResult>(cache, 'free');\n let cached: FreeEmailResult | null | undefined;\n try {\n cached = await cacheStore.get(emailDomain);\n } catch {\n cached = null;\n }\n if (cached !== null && cached !== undefined) {\n log(`[isFreeEmail] Cache hit for ${emailDomain}: ${cached.isFree}`);\n return cached.isFree;\n }\n\n const isFree = freeEmailProviders.has(emailDomain);\n const richResult: FreeEmailResult = {\n isFree,\n provider: isFree ? emailDomain : undefined,\n checkedAt: Date.now(),\n };\n\n try {\n await cacheStore.set(emailDomain, richResult);\n log(`[isFreeEmail] Cached result for ${emailDomain}: ${isFree}`);\n } catch {\n log(`[isFreeEmail] Cache write error for ${emailDomain}`);\n }\n log(`[isFreeEmail] Check result for ${emailDomain}: ${isFree}`);\n return isFree;\n}\n","import { promises as dnsPromises } from 'node:dns';\nimport { getCacheStore } from './cache';\nimport type { ResolveMxParams } from './types';\n\nexport async function resolveMxRecords(params: ResolveMxParams): Promise<string[]> {\n const { domain, cache, logger } = params;\n const log = logger || (() => {});\n\n // Check cache first\n const cacheStore = getCacheStore<string[]>(cache, 'mx');\n const cached = await cacheStore.get(domain);\n if (cached !== null && cached !== undefined) {\n log(`[resolveMxRecords] Cache hit for ${domain}: ${cached?.length} MX records`);\n return cached;\n }\n\n log(`[resolveMxRecords] Performing DNS MX lookup for ${domain}`);\n try {\n const records: { exchange: string; priority: number }[] = await dnsPromises.resolveMx(domain);\n records?.sort((a, b) => {\n if (a.priority < b.priority) {\n return -1;\n }\n if (a.priority > b.priority) {\n return 1;\n }\n return 0;\n });\n\n const exchanges = records?.map((record) => record.exchange);\n log(`[resolveMxRecords] Found ${exchanges?.length} MX records for ${domain}: [${exchanges?.join(', ')}]`);\n\n // Cache the result\n await cacheStore.set(domain, exchanges);\n log(`[resolveMxRecords] Cached ${exchanges?.length} MX records for ${domain}`);\n\n return exchanges;\n } catch (error) {\n log(`[resolveMxRecords] MX lookup failed for ${domain}, caching empty result`);\n // Cache negative results for shorter time\n await cacheStore.set(domain, []);\n throw error;\n }\n}\n","import commonFirstNameJson from './data/common-first-names.json';\nimport commonLastNameJson from './data/common-last-names.json';\nimport type { DetectedName, NameDetectionParams } from './types';\n\n/**\n * Common name separators and patterns\n */\nconst nameSeparator = ['.', '_', '-'];\nconst commonNameSuffixes = [\n 'mail',\n 'email',\n 'contact',\n 'info',\n 'admin',\n 'support',\n 'sales',\n 'help',\n 'noreply',\n 'no-reply',\n 'donotreply',\n 'notifications',\n 'alerts',\n];\n\n// Additional suffixes that might appear in email addresses\nconst contextualSuffixes = [\n 'dev',\n 'company',\n 'team',\n 'group',\n 'office',\n 'work',\n 'personal',\n 'home',\n 'private',\n 'business',\n 'corp',\n 'inc',\n 'ltd',\n 'llc',\n 'org',\n];\n\n// Common titles and honorifics\nconst COMMON_TITLES = [\n 'mr',\n 'mrs',\n 'ms',\n 'miss',\n 'dr',\n 'prof',\n 'sir',\n 'lord',\n 'lady',\n 'captain',\n 'rev',\n 'father',\n 'sister',\n];\n\n// Common first names across English, Latin, Arabic, Asian, European, African cultures.\n// Source data lives in src/data/common-first-names.json — JSON keeps the source\n// file readable instead of buried under hundreds of string literals.\nconst commonFirstName: Set<string> = new Set(commonFirstNameJson as string[]);\n\n// Common surnames; same rationale as commonFirstName above.\nconst commonLastName: Set<string> = new Set(commonLastNameJson as string[]);\n\n// Check if a string looks like a year\nfunction isYearLike(str: string) {\n return /^(19|20)\\d{2}$/.test(str);\n}\n\n// Check if a string is a known first name\nfunction isKnownFirstName(str: string) {\n return commonFirstName.has(str.toLowerCase());\n}\n\n// Check if a string is a known last name\nfunction isKnownLastName(str: string) {\n return commonLastName.has(str.toLowerCase());\n}\n\n// Check if a string is a title/honorific\nfunction isTitle(str: string) {\n return COMMON_TITLES.includes(str.toLowerCase().replace('.', ''));\n}\n\n// Check if a string is a middle name indicator\n// Score how likely a string is to be a first name\nfunction getFirstNameScore(str: string) {\n const lower = str.toLowerCase();\n if (commonFirstName.has(lower)) return 1.0;\n if (commonLastName.has(lower)) return 0.3; // Some overlap\n if (str.length >= 2 && str.length <= 15 && /^[a-zA-Z]+$/.test(str)) return 0.5;\n return 0;\n}\n\n// Score how likely a string is to be a last name\nfunction getLastNameScore(str: string) {\n const lower = str.toLowerCase();\n if (commonLastName.has(lower)) return 1.0;\n if (commonFirstName.has(lower)) return 0.3; // Some overlap\n if (str.length >= 2 && str.length <= 20 && /^[a-zA-Z]+$/.test(str)) return 0.5;\n return 0;\n}\n\n/**\n * Intelligently capitalize names, handling special cases\n */\nfunction capitalizeName(str: string) {\n if (!str) return '';\n\n // Handle special name patterns\n const specialPatterns = [\n {\n pattern: /^(o')([a-z]+)/i,\n format: (m: RegExpMatchArray) => `O'${m[2].charAt(0).toUpperCase()}${m[2].slice(1).toLowerCase()}`,\n },\n {\n pattern: /^(mac)([a-z]+)/i,\n format: (m: RegExpMatchArray) => `Mac${m[2].charAt(0).toUpperCase()}${m[2].slice(1).toLowerCase()}`,\n },\n {\n pattern: /^(mc)([a-z]+)/i,\n format: (m: RegExpMatchArray) => `Mc${m[2].charAt(0).toUpperCase()}${m[2].slice(1).toLowerCase()}`,\n },\n {\n pattern: /^(van|von|de|del|dela|da|di|le|la|du|den|der|ter|ten)(\\s+)([a-z]+)/i,\n format: (m: RegExpMatchArray) =>\n m[1].toLowerCase() + m[2] + m[3].charAt(0).toUpperCase() + m[3].slice(1).toLowerCase(),\n },\n ];\n\n for (const { pattern, format } of specialPatterns) {\n const match = str.match(pattern);\n if (match) {\n return format(match);\n }\n }\n\n // Handle hyphenated names\n if (str.includes('-')) {\n return str\n .split('-')\n .map((part) => part.charAt(0).toUpperCase() + part.slice(1).toLowerCase())\n .join('-');\n }\n\n // Handle apostrophes in names like D'Angelo\n if (str.includes(\"'\") && str.indexOf(\"'\") > 0) {\n const parts = str.split(\"'\");\n return parts\n .map((part, i) =>\n i === 0\n ? part.charAt(0).toUpperCase() + part.slice(1).toLowerCase()\n : part.charAt(0).toUpperCase() + part.slice(1).toLowerCase()\n )\n .join(\"'\");\n }\n\n // Standard capitalization\n if (/^[a-zA-Z]/.test(str)) {\n return str.charAt(0).toUpperCase() + str.slice(1).toLowerCase();\n }\n\n return str;\n}\n\n/**\n * Parse composite name parts that may contain numbers and special patterns\n * Intelligently strips numbers and special characters that are likely not part of the actual name\n * e.g., \"john1\" -> \"john\", \"due2\" -> \"due\", \"test123\" -> \"test\"\n */\nfunction parseCompositeNamePart(part: string): {\n hasNumbers: boolean;\n cleaned: string;\n confidence: number;\n} {\n const hasNumbers = /\\d/.test(part);\n let confidence = 1.0;\n\n // Multiple strategies for cleaning names:\n // 1. Remove trailing numbers (john123 -> john)\n // 2. Remove interspersed numbers if they seem unnatural (jo1hn -> john)\n // 3. Remove leading numbers if followed by a valid name (1john -> john)\n // 4. Handle year patterns (john2023 -> john)\n // 5. Handle common number substitutions (j0hn -> john, 3ric -> eric)\n\n let cleaned = part;\n\n // Handle common leetspeak/number substitutions\n const leetSpeakMap: { [key: string]: string } = {\n '0': 'o',\n '1': 'i',\n '3': 'e',\n '4': 'a',\n '5': 's',\n '7': 't',\n '8': 'b',\n };\n\n // First check if it might be leetspeak\n if (hasNumbers && part.length >= 3) {\n let leetCleaned = part.toLowerCase();\n for (const [num, letter] of Object.entries(leetSpeakMap)) {\n leetCleaned = leetCleaned.replace(new RegExp(num, 'g'), letter);\n }\n\n // Check if the cleaned version is a known name\n if (isKnownFirstName(leetCleaned) || isKnownLastName(leetCleaned)) {\n cleaned = leetCleaned;\n confidence = 0.7; // Lower confidence for leetspeak conversions\n }\n }\n\n // If not leetspeak, try standard cleaning\n if (cleaned === part) {\n // Remove year-like suffixes\n const withoutYear = part.replace(/(19|20)\\d{2}$/, '');\n if (withoutYear !== part && withoutYear.length >= 2) {\n cleaned = withoutYear;\n confidence = 0.8;\n } else {\n // Try to extract alphabetic base by removing all numbers\n const pureAlpha = part.replace(/\\d+/g, '');\n\n // If we have a reasonable alphabetic base (at least 2 chars), use it\n // Also accept single letter if it's part of a pattern like j7.d2\n if (pureAlpha.length >= 2) {\n cleaned = pureAlpha;\n confidence = hasNumbers ? 0.85 : 1.0;\n } else if (pureAlpha.length === 1 && /^[a-zA-Z]$/.test(pureAlpha)) {\n // For single letters (like 'j' from 'j7'), accept them as valid initials\n cleaned = pureAlpha;\n confidence = 0.6; // Lower confidence for single letters\n } else {\n // Otherwise, try to extract base name without trailing numbers\n const baseMatch = part.match(/^([a-zA-Z]+)\\d*$/);\n if (baseMatch) {\n cleaned = baseMatch[1];\n confidence = 0.75;\n } else {\n // Handle mixed alphanumeric that doesn't match patterns\n cleaned = part;\n confidence = 0.4;\n }\n }\n }\n }\n\n // Boost confidence if the cleaned result is a known name\n if (cleaned !== part) {\n if (isKnownFirstName(cleaned) || isKnownLastName(cleaned)) {\n confidence = Math.min(1.0, confidence + 0.2);\n }\n }\n\n return { hasNumbers, cleaned, confidence };\n}\n\n/**\n * Check if string is likely a name (not containing invalid patterns)\n */\nfunction isLikelyName(str: string, allowNumbers = false, allowSingleLetter = false) {\n if (!str) return false;\n\n // Allow single letters if explicitly permitted (for patterns like j7.d2)\n if (str.length < 2 && !allowSingleLetter) return false;\n if (str.length === 1 && allowSingleLetter && /^[a-zA-Z]$/.test(str)) return true;\n\n // Check if it's a common email prefix that's not a name\n if (commonNameSuffixes.includes(str.toLowerCase())) return false;\n\n // If allowing numbers (for composite names), be more lenient\n if (allowNumbers) {\n // Still reject if it's ALL numbers\n if (/^\\d+$/.test(str)) return false;\n // Accept mixed alphanumeric patterns\n return true;\n }\n\n // Check if it contains too many numbers (likely not a name)\n const digitCount = (str.match(/\\d/g) || []).length;\n if (digitCount > str.length * 0.3) return false;\n\n // Check if it's all uppercase or all lowercase (less likely to be a properly formatted name)\n // But still allow it with lower confidence\n\n return true;\n}\n\n/**\n * Default name detection method\n * Attempts to extract first and last name from email local part\n */\nexport function defaultNameDetectionMethod(email: string): DetectedName | null {\n if (!email?.includes('@')) {\n return null;\n }\n\n const [localPart] = email.split('@');\n if (!localPart) {\n return null;\n }\n\n // Remove plus sign and anything after it (email aliases)\n const localWithoutAlias = localPart.split('+')[0];\n\n // For initial processing, keep the original (don't remove trailing numbers yet)\n // We'll handle numbers more intelligently based on context\n const cleanedLocal = localWithoutAlias;\n\n // Special handling for no-reply variants\n if (cleanedLocal.toLowerCase() === 'no-reply' || cleanedLocal.toLowerCase() === 'noreply') {\n return null;\n }\n\n let firstName: string | undefined;\n let lastName: string | undefined;\n let confidence = 0;\n\n // Check for CamelCase pattern first (like johnDoe or JohnSmith)\n const camelCasePatterns = [\n /^([a-z]+)([A-Z][a-z]+)$/, // johnDoe\n /^([A-Z][a-z]+)([A-Z][a-z]+)$/, // JohnSmith\n /^([a-z]+)([A-Z][a-z]+)([A-Z][a-z]+)$/, // johnMcDonald\n ];\n\n for (const pattern of camelCasePatterns) {\n const match = cleanedLocal.match(pattern);\n if (match) {\n if (match.length === 3) {\n // Two parts\n const [, first, last] = match;\n if (isLikelyName(first) && isLikelyName(last)) {\n const firstScore = getFirstNameScore(first);\n const lastScore = getLastNameScore(last);\n\n firstName = capitalizeName(first);\n lastName = capitalizeName(last);\n confidence = 0.7 + (firstScore + lastScore) * 0.15; // 0.7-1.0 based on name recognition\n break;\n }\n } else if (match.length === 4) {\n // Three parts (like johnMcDonald)\n const [, first, middle, last] = match;\n const combined = middle + last; // Combine for names like McDonald\n\n if (isLikelyName(first)) {\n firstName = capitalizeName(first);\n lastName = capitalizeName(combined);\n confidence = 0.75;\n break;\n }\n }\n }\n }\n\n // If no CamelCase match, try different separator patterns\n if (!firstName && !lastName) {\n for (const separator of nameSeparator) {\n if (cleanedLocal.includes(separator)) {\n const parts = cleanedLocal.split(separator).filter((p) => p.length > 0);\n\n if (parts.length === 2) {\n const [first, last] = parts;\n\n // Check for title at the beginning\n if (isTitle(first)) {\n // Skip title and use second part as first name if there's a third part\n continue;\n }\n\n // Parse composite parts (may contain numbers)\n const firstParsed = parseCompositeNamePart(first);\n const lastParsed = parseCompositeNamePart(last);\n\n // Calculate name likelihood scores\n const firstNameScore = getFirstNameScore(firstParsed.cleaned);\n const lastNameScore = getLastNameScore(lastParsed.cleaned);\n\n // Determine if order should be reversed (last.first pattern)\n const reverseScore = getLastNameScore(firstParsed.cleaned) + getFirstNameScore(lastParsed.cleaned);\n const normalScore = firstNameScore + lastNameScore;\n\n // Check if both parts could be names (more lenient with numbers and single letters)\n // But be more restrictive: only allow single letters if the other part is longer\n const firstLikely = isLikelyName(first, true, true);\n const lastLikely = isLikelyName(last, true, true);\n\n // Additional check: if one part is a single letter, the other should be at least 2 characters\n const oneIsSingleLetter = first.length === 1 || last.length === 1;\n const otherIsLongEnough = oneIsSingleLetter\n ? first.length === 1\n ? last.length >= 2\n : first.length >= 2\n : true;\n\n const bothPartsValid = firstLikely && lastLikely && otherIsLongEnough;\n\n if (bothPartsValid) {\n // Smart handling: Always try to extract clean names when possible\n // For patterns like john1.due2, we want \"John\" and \"Due\"\n\n // Determine name order based on scores\n const useReversed = reverseScore > normalScore * 1.2; // Bias toward normal order\n\n if (firstParsed.hasNumbers || lastParsed.hasNumbers) {\n // At least one part has numbers - intelligently clean them\n const cleanedFirst = firstParsed.cleaned;\n const cleanedLast = lastParsed.cleaned;\n\n // Check if the cleaned versions are valid names (allow single letters for patterns like j7.d2)\n if (isLikelyName(cleanedFirst, false, true) && isLikelyName(cleanedLast, false, true)) {\n // Successfully cleaned to valid names\n if (useReversed) {\n firstName = capitalizeName(cleanedLast);\n lastName = capitalizeName(cleanedFirst);\n } else {\n firstName = capitalizeName(cleanedFirst);\n lastName = capitalizeName(cleanedLast);\n }\n\n // Calculate confidence based on multiple factors\n const baseConfidence = 0.7;\n const separatorBonus = separator === '.' ? 0.15 : separator === '_' ? 0.05 : 0;\n const nameRecognitionBonus = normalScore > 0.5 ? 0.1 : 0;\n const cleaningPenalty = (firstParsed.confidence + lastParsed.confidence) / 2 - 1; // -1 to 0\n\n confidence = Math.min(0.95, baseConfidence + separatorBonus + nameRecognitionBonus + cleaningPenalty);\n } else {\n // Fallback to keeping numbers if cleaning doesn't produce valid names\n // This handles cases like \"a1.b2\" where removing numbers leaves too little\n firstName = capitalizeName(first);\n lastName = capitalizeName(last);\n confidence = 0.5; // Lower confidence for alphanumeric patterns\n }\n } else {\n // Neither has numbers - regular name\n if (useReversed) {\n firstName = capitalizeName(last);\n lastName = capitalizeName(first);\n } else {\n firstName = capitalizeName(first);\n lastName = capitalizeName(last);\n }\n\n // Calculate confidence\n const baseConfidence = 0.75;\n const separatorBonus = separator === '.' ? 0.15 : separator === '_' ? 0.05 : 0;\n const nameRecognitionBonus = Math.min(0.15, normalScore * 0.15);\n\n confidence = Math.min(0.95, baseConfidence + separatorBonus + nameRecognitionBonus);\n }\n\n break;\n }\n } else if (parts.length === 3) {\n // Handle cases like first.middle.last or first.last.suffix\n const [first, middle, last] = parts;\n\n // Parse composite parts\n const firstParsed = parseCompositeNamePart(first);\n const middleParsed = parseCompositeNamePart(middle);\n const lastParsed = parseCompositeNamePart(last);\n\n // Check if last part is likely a suffix (mail, email, etc.)\n const isLastSuffix =\n commonNameSuffixes.includes(last.toLowerCase()) ||\n contextualSuffixes.includes(last.toLowerCase()) ||\n isYearLike(last);\n\n if (isLastSuffix) {\n if (isLikelyName(first, true, true) && isLikelyName(middle, true, true)) {\n // Clean numbers from names if present\n const cleanedFirst = firstParsed.hasNumbers ? firstParsed.cleaned : first;\n const cleanedMiddle = middleParsed.hasNumbers ? middleParsed.cleaned : middle;\n\n if (isLikelyName(cleanedFirst, false, true) && isLikelyName(cleanedMiddle, false, true)) {\n firstName = capitalizeName(cleanedFirst);\n lastName = capitalizeName(cleanedMiddle);\n confidence = 0.7;\n } else {\n firstName = capitalizeName(first);\n lastName = capitalizeName(middle);\n confidence = 0.65;\n }\n break;\n }\n } else if (isLikelyName(first, true, true) && isLikelyName(last, true, true)) {\n // Intelligently handle three-part names\n const cleanedFirst = firstParsed.hasNumbers ? firstParsed.cleaned : first;\n const cleanedLast = lastParsed.hasNumbers ? lastParsed.cleaned : last;\n\n if (isLikelyName(cleanedFirst, false, true) && isLikelyName(cleanedLast, false, true)) {\n firstName = capitalizeName(cleanedFirst);\n lastName = capitalizeName(cleanedLast);\n confidence = 0.75;\n } else {\n // Fallback if cleaning doesn't produce valid names\n firstName = capitalizeName(first);\n lastName = capitalizeName(last);\n confidence = 0.55;\n }\n break;\n }\n } else if (parts.length > 3) {\n // Handle complex composite names with multiple parts\n // Take first and last meaningful parts\n const firstPart = parts[0];\n\n // Check if last part is a suffix to ignore\n const lastPartLower = parts[parts.length - 1].toLowerCase();\n const isLastPartSuffix =\n commonNameSuffixes.includes(lastPartLower) ||\n contextualSuffixes.includes(lastPartLower) ||\n isYearLike(parts[parts.length - 1]);\n const effectiveLastIndex = isLastPartSuffix ? parts.length - 2 : parts.length - 1;\n const lastToUse = effectiveLastIndex >= 0 ? parts[effectiveLastIndex] : null;\n\n if (lastToUse && isLikelyName(firstPart, true, true) && isLikelyName(lastToUse, true, true)) {\n const firstParsed = parseCompositeNamePart(firstPart);\n const lastParsed = parseCompositeNamePart(lastToUse);\n\n // Try to clean names intelligently\n const cleanedFirst = firstParsed.hasNumbers ? firstParsed.cleaned : firstPart;\n const cleanedLast = lastParsed.hasNumbers ? lastParsed.cleaned : lastToUse;\n\n if (isLikelyName(cleanedFirst, false, true) && isLikelyName(cleanedLast, false, true)) {\n firstName = capitalizeName(cleanedFirst);\n lastName = capitalizeName(cleanedLast);\n confidence = 0.6;\n } else {\n firstName = capitalizeName(firstPart);\n lastName = capitalizeName(lastToUse);\n confidence = 0.5;\n }\n break;\n }\n }\n }\n }\n }\n\n // Additional pattern: underscore_case or CONSTANT_CASE\n if (!firstName && !lastName) {\n const underscoreMatch = cleanedLocal.match(/^([A-Z_]+)$/);\n if (underscoreMatch) {\n const parts = cleanedLocal\n .toLowerCase()\n .split('_')\n .filter((p) => p.length > 0);\n if (parts.length === 2) {\n const [first, last] = parts;\n if (isLikelyName(first) && isLikelyName(last)) {\n firstName = capitalizeName(first);\n lastName = capitalizeName(last);\n confidence = 0.65;\n }\n }\n }\n }\n\n // If still no match, check if the whole local part could be a single name\n if (!firstName && !lastName) {\n const parsed = parseCompositeNamePart(cleanedLocal);\n\n // Check if it could be a single name (allow alphanumeric but NOT single letters)\n if (isLikelyName(cleanedLocal, true, false)) {\n if (/^[a-zA-Z]+$/.test(cleanedLocal)) {\n // Pure alphabetic - likely a single name\n const nameScore = Math.max(getFirstNameScore(cleanedLocal), getLastNameScore(cleanedLocal));\n\n // Determine if it's more likely a first or last name\n if (getFirstNameScore(cleanedLocal) >= getLastNameScore(cleanedLocal)) {\n firstName = capitalizeName(cleanedLocal);\n } else {\n lastName = capitalizeName(cleanedLocal);\n }\n\n confidence = 0.4 + nameScore * 0.3; // 0.4-0.7 based on name recognition\n } else if (parsed.hasNumbers && parsed.cleaned.length >= 2) {\n // Has numbers but we can extract a clean name\n const cleanedScore = Math.max(getFirstNameScore(parsed.cleaned), getLastNameScore(parsed.cleaned));\n\n if (getFirstNameScore(parsed.cleaned) >= getLastNameScore(parsed.cleaned)) {\n firstName = capitalizeName(parsed.cleaned);\n } else {\n lastName = capitalizeName(parsed.cleaned);\n }\n\n confidence = 0.3 + cleanedScore * 0.2 + parsed.confidence * 0.2; // 0.3-0.7 based on multiple factors\n }\n }\n }\n\n if (!firstName && !lastName) {\n return null;\n }\n\n return {\n firstName,\n lastName,\n confidence: Math.max(0, Math.min(1, confidence)), // Ensure confidence is between 0 and 1\n };\n}\n\n/**\n * Detect name from email address\n * @param params - Detection parameters including email and optional custom method\n * @returns Detected name with confidence score, or null if no name detected\n */\nexport function detectNameFromEmail(params: NameDetectionParams): DetectedName | null {\n const { email, customMethod } = params;\n\n if (!email?.includes('@')) {\n return null;\n }\n\n // Use custom method if provided\n if (customMethod) {\n try {\n return customMethod(email);\n } catch (error) {\n // Fall back to default method if custom method fails\n console.warn('Custom name detection method failed, falling back to default:', error);\n }\n }\n\n // Use default method\n return defaultNameDetectionMethod(email);\n}\n\n/**\n * Clean name by removing special characters (dots, underscores, asterisks)\n * Specifically designed for Algorithm name processing\n *\n * @param name - The name to clean\n * @returns The cleaned name with special characters removed\n */\nexport function cleanNameForAlgorithm(name: string): string {\n if (!name) return '';\n\n // Remove dots, underscores, and asterisks\n let cleaned = name.replace(/[._*]/g, '');\n\n // Normalize multiple spaces to single space\n cleaned = cleaned.replace(/\\s+/g, ' ').trim();\n\n // If the name is now empty after cleaning, return the original\n if (!cleaned) {\n return name;\n }\n\n return cleaned;\n}\n\n/**\n * Enhanced name detection for Algorithm with aggressive cleaning\n * Removes dots, underscores, and asterisks from detected names\n *\n * @param email - Email address to extract name from\n * @returns Detected name with cleaned special characters, or null if no name detected\n */\nexport function detectNameForAlgorithm(email: string): DetectedName | null {\n const detectedName = detectName(email);\n\n if (!detectedName) {\n return null;\n }\n\n // Clean first name and last name by removing special characters\n const cleanedFirstName = detectedName.firstName ? cleanNameForAlgorithm(detectedName.firstName) : undefined;\n const cleanedLastName = detectedName.lastName ? cleanNameForAlgorithm(detectedName.lastName) : undefined;\n\n // If both names are empty after cleaning, return null\n if (!cleanedFirstName && !cleanedLastName) {\n return null;\n }\n\n return {\n firstName: cleanedFirstName,\n lastName: cleanedLastName,\n confidence: detectedName.confidence * 0.95, // Slightly reduce confidence due to cleaning\n };\n}\n\n/**\n * Convenience function to detect name from email string\n * @param email - Email address to extract name from\n * @returns Detected name with confidence score, or null if no name detected\n */\nexport function detectName(email: string): DetectedName | null {\n return detectNameFromEmail({ email });\n}\n","/**\n * `MAIL FROM:` payload resolution from a `SMTPSenderStrategy` policy.\n *\n * Pure functions — no I/O, no shared state. The randomness comes from\n * `crypto.randomBytes` (same primitive used by the catch-all probe local\n * generator in `smtp-verifier.ts`) so probes can't be fingerprinted by a\n * predictable PRNG.\n */\n\nimport { randomBytes } from 'node:crypto';\nimport type { SMTPSenderStrategy } from './types';\n\nconst DEFAULT_LOCAL_PREFIX = 'probe';\n\n/**\n * Resolve a sender strategy into the literal `MAIL FROM:` payload (including\n * angle brackets). Output is ready to drop into `MAIL FROM:${result}`.\n *\n * Examples (with random=`a3x9b7c2deadbeef`):\n * `{ kind: 'null-sender' }` → `<>`\n * `{ kind: 'fixed', address: 'verify@x.com' }` → `<verify@x.com>`\n * `{ kind: 'fixed', address: '<verify@x.com>' }` → `<verify@x.com>` (already wrapped)\n * `{ kind: 'random-at-recipient' }` → recipient `alice@gmail.com`\n * → `<probe-a3x9b7c2deadbeef@gmail.com>`\n * `{ kind: 'random-at-domain', domain: 'x.com' }` → `<probe-a3x9b7c2deadbeef@x.com>`\n * `{ kind: 'custom', build: r => `<x@${r.domain}>` }` → whatever `build` returns\n */\nexport function resolveSenderAddress(\n strategy: SMTPSenderStrategy,\n recipient: { local: string; domain: string }\n): string {\n switch (strategy.kind) {\n case 'null-sender':\n return '<>';\n case 'fixed':\n return wrap(strategy.address);\n case 'random-at-recipient':\n return wrap(`${randomLocal(strategy.localPrefix)}@${recipient.domain}`);\n case 'random-at-domain':\n return wrap(`${randomLocal(strategy.localPrefix)}@${strategy.domain}`);\n case 'custom':\n // Trust the caller — but pass a defensive copy so a buggy `build` can't\n // mutate our internal recipient object via an accidental shared reference.\n return strategy.build({ local: recipient.local, domain: recipient.domain });\n }\n}\n\n/** Wrap an address in `<>` unless the caller already did. Idempotent. */\nfunction wrap(address: string): string {\n if (address.startsWith('<') && address.endsWith('>')) return address;\n return `<${address}>`;\n}\n\n/** 16-hex-char random local-part with a recognizable prefix. */\nfunction randomLocal(prefix: string | undefined): string {\n // 8 bytes → 16 hex chars: long enough that birthday-collision probability is\n // negligible across realistic probe volumes, short enough to fit comfortably\n // inside the 64-char local-part limit even with the prefix attached.\n const random = randomBytes(8).toString('hex');\n const safePrefix = prefix ?? DEFAULT_LOCAL_PREFIX;\n return `${safePrefix}-${random}`;\n}\n","/**\n * SMTP mailbox probe.\n *\n * Walks `mxRecords` in priority order, then `ports` in the configured order.\n * Returns the first attempt that yields a definitive answer (250 / 550 / 552 /\n * 452); on indeterminate outcomes (timeouts, connection resets, EHLO failures,\n * unrecognized responses), falls through to the next MX×port pair.\n *\n * Per-attempt dialogue:\n * greeting → EHLO → MAIL FROM → RCPT TO real → RCPT TO probe → RSET\n *\n * The probe RCPT uses a guaranteed-nonexistent random local-part so we can\n * detect catch-all MXes (Outlook / Yahoo / Office 365 / ProtonMail / many\n * corporates accept every recipient at the MX layer and bounce later).\n * When both real + probe return 250, `result.isCatchAll = true` and callers\n * know the deliverability signal is unreliable but that the address syntax\n * was at least accepted.\n *\n * The envelope (real RCPT + probe RCPT + RSET) is batched via PIPELINING\n * (RFC 2920) when the MX advertises support — roughly halves wire-level\n * latency. Tests can disable with `pipelining: 'never'` for deterministic\n * `socket.write()` call counts.\n *\n * Every result carries a `metrics` block with `mxAttempts`, `portAttempts`,\n * `mxHostsTried`, `mxHostUsed?`, `totalDurationMs` — useful for region-health\n * dashboards and root-cause-analysis when probes go wrong.\n */\n\nimport { randomBytes } from 'node:crypto';\nimport * as net from 'node:net';\nimport * as tls from 'node:tls';\nimport { getCacheStore } from './cache';\nimport { resolveSenderAddress } from './sender-strategy';\nimport type {\n SMTPSenderStrategy,\n SMTPSequence,\n SMTPTLSConfig,\n SMTPVerifyOptions,\n SmtpProbeMetrics,\n SmtpVerificationResult,\n VerifyMailboxSMTPParams,\n} from './types';\nimport { SMTPStep } from './types';\n\nconst DEFAULT_PORTS = [25, 587, 465]; // plain → STARTTLS-able → implicit-TLS\nconst DEFAULT_TIMEOUT_MS = 3000;\n/** ms to wait for QUIT to drain before forcibly destroying the socket. */\nconst QUIT_DRAIN_MS = 100;\n\n/** Implicit-TLS map. Plain ports advertise STARTTLS via EHLO; we do not auto-upgrade. */\nconst PORT_TLS: Record<number, boolean> = { 25: false, 587: false, 465: true };\n\n/** True for IPv4 / IPv6 in any form (compressed, mapped, mixed). */\nconst isIPAddress = (host: string): boolean => net.isIP(host) !== 0;\n\nexport interface ParsedDsn {\n /** 2 = success, 4 = transient, 5 = permanent */\n class: number;\n /** 1 addressing, 2 mailbox, 3 mail-system, 4 network, 5 protocol, 6 message, 7 security/policy */\n subject: number;\n detail: number;\n}\n\n/**\n * Parse an RFC 3463 enhanced status code at the start of an SMTP reply.\n * Examples: \"550 5.1.1 user unknown\" → {5,1,1}; \"421 4.7.0 try later\" → {4,7,0}.\n */\nexport function parseDsn(reply: string): ParsedDsn | null {\n const match = reply.match(/^\\d{3}[ -](\\d)\\.(\\d{1,3})\\.(\\d{1,3})\\b/);\n if (!match) return null;\n return { class: Number(match[1]), subject: Number(match[2]), detail: Number(match[3]) };\n}\n\nfunction dsnToString(dsn: ParsedDsn): string {\n return `${dsn.class}.${dsn.subject}.${dsn.detail}`;\n}\n\nfunction isPolicyBlock(reply: string): boolean {\n const dsn = parseDsn(reply);\n return dsn?.class === 5 && dsn?.subject === 7;\n}\n\nconst HIGH_VOLUME_RE =\n /(high number of|our system has detected unusual activity|contact your service provider for support|\\[irr\\])/i;\nconst OVER_QUOTA_RE = /(over quota)/i;\nconst INVALID_MAILBOX_PREFIX_RE = /^(510|511|513|550|551|553)/;\nconst INVALID_MAILBOX_FALSE_POSITIVE_RE = /(junk|spam|openspf|spoofing|host|rbl.+blocked)/i;\nconst MULTILINE_RE = /^\\d{3}-/;\n\nconst isHighVolume = (reply: string): boolean => HIGH_VOLUME_RE.test(reply);\nconst isOverQuota = (reply: string): boolean => OVER_QUOTA_RE.test(reply);\n\nfunction isInvalidMailboxError(reply: string): boolean {\n if (!INVALID_MAILBOX_PREFIX_RE.test(reply)) return false;\n if (INVALID_MAILBOX_FALSE_POSITIVE_RE.test(reply)) return false;\n if (isPolicyBlock(reply)) return false;\n return true;\n}\n\n/**\n * 16 hex characters + suffix — long enough to never collide with any real\n * mailbox, structured so it's clearly synthetic and passes the local-part\n * syntax checks of every common MX.\n */\nfunction defaultProbeLocal(): string {\n return `${randomBytes(8).toString('hex')}-noexist`;\n}\n\n/**\n * Public entry point. Walks `mxRecords × ports` and returns the first\n * definitive answer. Always:\n * - iterates MX records on indeterminate outcomes (no flag)\n * - runs the catch-all dual-probe (no flag)\n * - populates `result.metrics` and `result.enhancedStatus`\n *\n * Opt-in only:\n * - `captureTranscript: true` returns the wire transcript on the result\n * - `pipelining: 'never'` disables PIPELINING for deterministic tests\n * - `catchAllProbeLocal` overrides the random-local generator\n */\nexport async function verifyMailboxSMTP(\n params: VerifyMailboxSMTPParams\n): Promise<{ smtpResult: SmtpVerificationResult; cached: boolean; port: number; portCached: boolean }> {\n const { local, domain, options = {} } = params;\n // Coerce null → empty array (destructuring default only fires on undefined).\n const mxRecords = params.mxRecords ?? [];\n // Filter out non-integer / out-of-range ports — net.connect throws RangeError\n // synchronously for those, which would crash the promise executor.\n const ports = (options.ports ?? DEFAULT_PORTS).filter((port) => Number.isInteger(port) && port > 0 && port < 65536);\n const perAttemptTimeoutMs = options.perAttemptTimeoutMs ?? DEFAULT_TIMEOUT_MS;\n const tlsConfig = options.tlsConfig ?? true;\n const heloHostname = options.heloHostname ?? 'localhost';\n const debug = options.debug ?? false;\n const captureTranscript = options.captureTranscript ?? false;\n const sequence = options.sequence;\n const sender = options.sender;\n const cache = options.cache;\n const log = debug ? (...args: unknown[]) => console.log('[SMTP]', ...args) : () => {};\n\n // Early-stop policy.\n const totalDeadlineMs = options.totalDeadlineMs;\n const maxConsecutiveFailures = options.maxConsecutiveFailures;\n const maxMxHosts = options.maxMxHosts;\n const retryAttempts = options.retry?.attempts ?? 0;\n const retryDelayMs = options.retry?.delayMs ?? 200;\n const retryBackoff = options.retry?.backoff ?? 'exponential';\n\n const startedAtMs = Date.now();\n\n const primaryMx = mxRecords[0];\n if (!primaryMx) {\n log('No MX records found');\n const metrics = makeMetrics([], 0, 0, undefined, startedAtMs);\n return { smtpResult: failureResult('no_mx_records', metrics), cached: false, port: 0, portCached: false };\n }\n log(`Verifying ${local}@${domain} via ${primaryMx} (mx count=${mxRecords.length})`);\n\n const transcript: string[] = [];\n const commands: string[] = [];\n\n const probeOptions: ProbeOptions = {\n local,\n domain,\n perAttemptTimeoutMs,\n tlsConfig,\n heloHostname,\n sequence,\n sender,\n log,\n catchAllProbeLocal: options.catchAllProbeLocal,\n pipelining: options.pipelining ?? 'auto',\n startTls: options.startTls ?? 'auto',\n };\n\n // Cache short-circuits — keyed on the primary MX so the cache key matches\n // what callers compute from `mxRecords[0]`.\n const verdictCache = cache ? getCacheStore<SmtpVerificationResult>(cache, 'smtp') : null;\n const verdictKey = `${primaryMx}:${local}@${domain}`;\n if (verdictCache) {\n const cachedResult = await safeCacheGet(verdictCache, verdictKey);\n if (cachedResult) {\n log(`Using cached SMTP result: ${cachedResult.isDeliverable}`);\n return { smtpResult: cachedResult, cached: true, port: 0, portCached: false };\n }\n }\n\n const portCache = cache ? getCacheStore<number>(cache, 'smtpPort') : null;\n const cachedPort = portCache ? await safeCacheGet(portCache, primaryMx) : null;\n\n const mxHostsTried: string[] = [];\n let mxAttempts = 0;\n let portAttempts = 0;\n let consecutiveFailures = 0;\n let lastReason = 'all_attempts_failed';\n let lastEnhancedStatus: string | undefined;\n let lastResponseCode: number | undefined;\n let stoppedEarly: 'deadline' | 'consecutive_failures' | 'max_mx_hosts' | null = null;\n\n /** Connection-class outcomes count toward `maxConsecutiveFailures`; everything else resets it. */\n const isConnectionFailure = (reason: string): boolean =>\n reason === 'connection_error' ||\n reason === 'connection_timeout' ||\n reason === 'connection_closed' ||\n reason === 'socket_timeout';\n\n /** Compute backoff delay for the Nth retry (1-indexed). */\n const retryDelayFor = (attemptIndex: number): number =>\n retryBackoff === 'exponential' ? retryDelayMs * 2 ** (attemptIndex - 1) : retryDelayMs;\n\n /** Run one probe attempt with optional retries on connection-class failures. */\n const probeWithRetry = async (mxHost: string, port: number): Promise<ProbeResult> => {\n let lastProbe = await runProbe({ ...probeOptions, mxHost, port });\n for (let i = 1; i <= retryAttempts; i++) {\n if (lastProbe.result !== null || !isConnectionFailure(lastProbe.reason)) break;\n const delay = retryDelayFor(i);\n log(`retry ${i}/${retryAttempts} on ${mxHost}:${port} after ${delay}ms (last: ${lastProbe.reason})`);\n await new Promise((r) => setTimeout(r, delay));\n portAttempts++;\n lastProbe = await runProbe({ ...probeOptions, mxHost, port });\n }\n return lastProbe;\n };\n\n outer: for (const mxHost of mxRecords) {\n if (maxMxHosts !== undefined && mxAttempts >= maxMxHosts) {\n stoppedEarly = 'max_mx_hosts';\n break;\n }\n mxHostsTried.push(mxHost);\n mxAttempts++;\n\n // Cached-port fast path: only valid for the primary MX.\n const portsForThisMx =\n mxHost === primaryMx && cachedPort ? [cachedPort, ...ports.filter((p) => p !== cachedPort)] : ports;\n\n for (const port of portsForThisMx) {\n if (totalDeadlineMs !== undefined && Date.now() - startedAtMs >= totalDeadlineMs) {\n stoppedEarly = 'deadline';\n break outer;\n }\n portAttempts++;\n log(`Testing ${mxHost}:${port}`);\n const probe = await probeWithRetry(mxHost, port);\n collectTranscript(transcript, commands, probe, mxHost, port);\n lastReason = probe.reason;\n if (probe.enhancedStatus !== undefined) lastEnhancedStatus = probe.enhancedStatus;\n if (probe.responseCode !== undefined) lastResponseCode = probe.responseCode;\n\n // Definitive answer (250/251 deliverable, 550/552/etc. rejected) ends\n // the search. Indeterminate (null) falls through to the next port/MX.\n if (probe.result !== null) {\n const metrics = makeMetrics(mxHostsTried, mxAttempts, portAttempts, mxHost, startedAtMs);\n const smtpResult = toSmtpVerificationResult(probe, {\n transcript: captureTranscript ? transcript : undefined,\n commands: captureTranscript ? commands : undefined,\n metrics,\n });\n await safeCacheSet(verdictCache, verdictKey, smtpResult);\n if (mxHost === primaryMx) await safeCacheSet(portCache, primaryMx, port);\n return { smtpResult, cached: false, port, portCached: cachedPort === port };\n }\n\n // Track consecutive connection-class failures for the early-stop policy.\n consecutiveFailures = isConnectionFailure(probe.reason) ? consecutiveFailures + 1 : 0;\n if (maxConsecutiveFailures !== undefined && consecutiveFailures >= maxConsecutiveFailures) {\n stoppedEarly = 'consecutive_failures';\n break outer;\n }\n }\n }\n if (stoppedEarly) log(`Stopped early: ${stoppedEarly}`);\n\n // Every MX×port returned indeterminate — surface the LAST attempt's reason\n // so callers can see the failure mode (e.g. tls_error tells a different\n // story than connection_timeout).\n log(`All MX×port attempts failed (mx=${mxAttempts}, port=${portAttempts})`);\n const metrics = makeMetrics(mxHostsTried, mxAttempts, portAttempts, undefined, startedAtMs);\n const smtpResult: SmtpVerificationResult = {\n ...failureResult(lastReason, metrics),\n ...(lastEnhancedStatus !== undefined ? { enhancedStatus: lastEnhancedStatus } : {}),\n ...(lastResponseCode !== undefined ? { responseCode: lastResponseCode } : {}),\n ...(captureTranscript ? { transcript: [...transcript], commands: [...commands] } : {}),\n };\n return { smtpResult, cached: false, port: 0, portCached: false };\n}\n\nfunction makeMetrics(\n mxHostsTried: string[],\n mxAttempts: number,\n portAttempts: number,\n mxHostUsed: string | undefined,\n startedAtMs: number\n): SmtpProbeMetrics {\n return {\n mxAttempts,\n portAttempts,\n mxHostsTried: [...mxHostsTried],\n ...(mxHostUsed !== undefined ? { mxHostUsed } : {}),\n totalDurationMs: Date.now() - startedAtMs,\n };\n}\n\nfunction collectTranscript(\n transcript: string[],\n commands: string[],\n probe: ProbeResult,\n mxHost: string,\n port: number\n): void {\n const prefix = `${mxHost}:${port}`;\n for (const line of probe.transcript) transcript.push(`${prefix}|s| ${line}`);\n for (const cmd of probe.commands) commands.push(`${prefix}|c| ${cmd}`);\n}\n\nfunction failureResult(reason: string, metrics: SmtpProbeMetrics): SmtpVerificationResult {\n return {\n canConnectSmtp: false,\n hasFullInbox: false,\n isCatchAll: false,\n isDeliverable: false,\n isDisabled: false,\n error: reason,\n checkedAt: Date.now(),\n metrics,\n };\n}\n\ninterface ToResultExtras {\n transcript?: string[];\n commands?: string[];\n metrics: SmtpProbeMetrics;\n}\n\nfunction toSmtpVerificationResult(probe: ProbeResult, extras: ToResultExtras): SmtpVerificationResult {\n const result = probe.result;\n const out: SmtpVerificationResult = {\n canConnectSmtp: result !== null,\n hasFullInbox: probe.reason === 'over_quota',\n isCatchAll: probe.isCatchAll ?? false,\n isDeliverable: result === true,\n isDisabled: result === false,\n error: result === true ? undefined : probe.reason,\n checkedAt: Date.now(),\n metrics: extras.metrics,\n ...(probe.enhancedStatus !== undefined ? { enhancedStatus: probe.enhancedStatus } : {}),\n ...(probe.responseCode !== undefined ? { responseCode: probe.responseCode } : {}),\n };\n if (extras.transcript) out.transcript = [...extras.transcript];\n if (extras.commands) out.commands = [...extras.commands];\n return out;\n}\n\nasync function safeCacheGet<T>(\n store: { get: (k: string) => Promise<T | null | undefined> | T | null | undefined } | null,\n key: string\n): Promise<T | null> {\n if (!store) return null;\n try {\n const v = await store.get(key);\n return v ?? null;\n } catch {\n return null;\n }\n}\n\nasync function safeCacheSet<T>(\n store: { set: (k: string, v: T) => Promise<void> | void } | null,\n key: string,\n value: T\n): Promise<void> {\n if (!store) return;\n try {\n await store.set(key, value);\n } catch {\n // Cache write errors are non-fatal — the next call just re-probes.\n }\n}\n\ninterface ProbeOptions {\n local: string;\n domain: string;\n perAttemptTimeoutMs: number;\n tlsConfig: boolean | SMTPTLSConfig;\n heloHostname: string;\n sequence?: SMTPSequence;\n sender?: SMTPSenderStrategy;\n log: (...args: unknown[]) => void;\n catchAllProbeLocal?: SMTPVerifyOptions['catchAllProbeLocal'];\n pipelining: 'auto' | 'never' | 'force';\n startTls: 'auto' | 'never' | 'force';\n}\n\ninterface ProbeParams extends ProbeOptions {\n mxHost: string;\n port: number;\n}\n\ninterface ProbeResult {\n /** true=deliverable, false=hard-rejected, null=indeterminate */\n result: boolean | null;\n /** Short reason vocabulary — propagated to `SmtpVerificationResult.error`. */\n reason: string;\n /** RFC 3463 enhanced status from the most recent reply that carried one. */\n enhancedStatus?: string;\n /** SMTP response code from the most recent reply (e.g. 250, 550). */\n responseCode?: number;\n /**\n * Catch-all flag from the dual-probe. `true` when both real + probe RCPT\n * returned 250; `false` otherwise; `undefined` only if the probe never\n * reached the envelope phase (indeterminate before MAIL FROM).\n */\n isCatchAll?: boolean;\n /** Server lines, in arrival order, no port prefix. */\n transcript: string[];\n /** Client commands sent, in send order, no port prefix. */\n commands: string[];\n}\n\nasync function runProbe(p: ProbeParams): Promise<ProbeResult> {\n return new SMTPProbeConnection(p).run();\n}\n\n/** Buckets a numeric SMTP RCPT-TO reply into the dual-probe state machine. */\ntype RcptOutcome = 'pending' | 'accept' | 'soft_reject' | 'hard_reject';\n\n/** Phase of the dual-probe envelope (after MAIL FROM is accepted). */\ntype DualPhase = 'idle' | 'rcpt_real' | 'rcpt_probe' | 'rset';\n\n/**\n * One SMTP connection attempt. Lives for one MX×port; resolves to:\n * true — RCPT TO real accepted (with `isCatchAll` set when probe also 250)\n * false — RCPT TO real definitively rejected / over-quota\n * null — indeterminate (timeout, hangup, unrecognized, ehlo failure, etc.)\n */\nclass SMTPProbeConnection {\n // ── Connection state ─────────────────────────────────────────────────────\n private socket?: net.Socket | tls.TLSSocket;\n private buffer = '';\n private resolved = false;\n private currentStepIndex = 0;\n /** True for implicit-TLS ports (465) from the start, or after STARTTLS upgrade. */\n private isTLS: boolean;\n /** True between sending STARTTLS and the TLS handshake completing. */\n private tlsUpgrading = false;\n /**\n * True when we sent the second EHLO after a successful STARTTLS upgrade.\n * The EHLO response arrives while `currentStepIndex` is still on `startTls`\n * — this flag tells the dispatcher to advance past startTls when the\n * post-upgrade EHLO returns 250, instead of treating it as a STARTTLS\n * acknowledgement.\n */\n private postUpgradeReEhlo = false;\n private connectionTimer?: NodeJS.Timeout;\n private stepTimer?: NodeJS.Timeout;\n private resolveFn!: (value: ProbeResult) => void;\n\n // ── Dialogue tracking ────────────────────────────────────────────────────\n private readonly steps: SMTPStep[];\n private readonly tlsOptions: tls.ConnectionOptions;\n private readonly transcript: string[] = [];\n private readonly commands: string[] = [];\n /** Last RFC 3463 enhanced status seen (last-write semantics — most recent wins). */\n private lastEnhancedStatus?: string;\n /** Last 3-digit SMTP response code seen (last-write semantics). */\n private lastResponseCode?: number;\n\n // ── EHLO capability advertisement ────────────────────────────────────────\n private supportsPipelining = false;\n private supportsStartTls = false;\n\n // ── Dual-probe (catch-all detection) ─────────────────────────────────────\n private readonly probeLocal: string;\n private dualPhase: DualPhase = 'idle';\n private realOutcome: RcptOutcome = 'pending';\n private probeOutcome: RcptOutcome = 'pending';\n private dualPipelined = false;\n /**\n * Pipelined-only escape hatch. When the real RCPT is rejected mid-batched-\n * envelope, the probe + RSET are already on the wire; we stash the verdict\n * and commit it after the response loop drains.\n */\n private pendingDecision: { result: boolean | null; reason: string } | null = null;\n private isCatchAllFlag?: boolean;\n\n constructor(private readonly p: ProbeParams) {\n // Default sequence — every modern MX speaks ESMTP, so EHLO works on port 25 too.\n // STARTTLS is conditional: the executeStep handler skips it when the port is\n // already TLS, when the MX didn't advertise STARTTLS in 'auto' mode, or when\n // `startTls === 'never'`. Without it in the sequence, port 587 submission\n // MXes reject `MAIL FROM` with `530 Must issue STARTTLS first`.\n const defaultSteps = [SMTPStep.greeting, SMTPStep.ehlo, SMTPStep.startTls, SMTPStep.mailFrom, SMTPStep.rcptTo];\n this.steps = [...(p.sequence?.steps ?? defaultSteps)];\n this.isTLS = PORT_TLS[p.port] === true;\n const servername = isIPAddress(p.mxHost) ? undefined : p.mxHost;\n this.tlsOptions = {\n host: p.mxHost,\n servername,\n rejectUnauthorized: false,\n minVersion: 'TLSv1.2',\n ...(typeof p.tlsConfig === 'object' ? p.tlsConfig : {}),\n };\n this.probeLocal = p.catchAllProbeLocal ? p.catchAllProbeLocal(p.local, p.domain) : defaultProbeLocal();\n }\n\n run(): Promise<ProbeResult> {\n return new Promise<ProbeResult>((resolve) => {\n this.resolveFn = resolve;\n try {\n this.connect();\n this.armConnectionTimer();\n } catch (error) {\n // Synchronous net/tls.connect throws (RangeError on bad port, etc.)\n // collapse to the same `connection_error` reason as async errors so\n // callers can branch on a single key. The diagnostic detail is logged.\n this.p.log(`connect threw: ${error instanceof Error ? error.message : 'unknown'}`);\n this.finish(null, 'connection_error');\n }\n });\n }\n\n private connect(): void {\n const onConnect = () => {\n this.p.log(`Connected to ${this.p.mxHost}:${this.p.port}${this.isTLS ? ' with TLS' : ''}`);\n this.socket?.on('data', this.onData);\n };\n if (this.isTLS) {\n this.socket = tls.connect({ ...this.tlsOptions, port: this.p.port }, onConnect);\n } else {\n this.socket = net.connect({ host: this.p.mxHost, port: this.p.port }, onConnect);\n }\n this.socket.setTimeout(this.p.perAttemptTimeoutMs, () => this.finish(null, 'socket_timeout'));\n this.socket.on('error', () => this.finish(null, 'connection_error'));\n this.socket.on('close', () => this.finish(null, 'connection_closed'));\n }\n\n private armConnectionTimer(): void {\n this.connectionTimer = setTimeout(() => this.finish(null, 'connection_timeout'), this.p.perAttemptTimeoutMs);\n }\n\n private resetStepTimer(): void {\n if (this.stepTimer) clearTimeout(this.stepTimer);\n this.stepTimer = setTimeout(() => this.finish(null, 'step_timeout'), this.p.perAttemptTimeoutMs);\n }\n\n private onData = (data: Buffer | string): void => {\n if (this.resolved) return;\n this.resetStepTimer();\n this.buffer += typeof data === 'string' ? data : data.toString();\n let pos: number;\n while ((pos = this.buffer.indexOf('\\r\\n')) !== -1) {\n const line = this.buffer.slice(0, pos).trim();\n this.buffer = this.buffer.slice(pos + 2);\n this.processLine(line);\n }\n };\n\n private send(cmd: string): void {\n if (this.resolved) return;\n this.commands.push(cmd);\n this.p.log(`→ ${cmd}`);\n this.socket?.write(`${cmd}\\r\\n`);\n }\n\n private nextStep(): void {\n this.currentStepIndex++;\n const step = this.steps[this.currentStepIndex];\n if (step === undefined) {\n this.finish(true, 'sequence_complete');\n return;\n }\n this.executeStep(step);\n }\n\n private executeStep(step: SMTPStep): void {\n if (this.resolved) return;\n switch (step) {\n case SMTPStep.greeting:\n return; // server-driven; nothing to send\n case SMTPStep.ehlo:\n this.send(`EHLO ${this.p.heloHostname}`);\n return;\n case SMTPStep.helo:\n this.send(`HELO ${this.p.heloHostname}`);\n return;\n case SMTPStep.startTls:\n this.executeStartTls();\n return;\n case SMTPStep.mailFrom: {\n // Precedence: high-level `sender` strategy → low-level `sequence.from`\n // literal → backwards-compat default of recipient address. The default\n // is preserved for compat but is the worst-case spam fingerprint —\n // callers should explicitly pick a `sender` strategy in production.\n const from = this.p.sender\n ? resolveSenderAddress(this.p.sender, { local: this.p.local, domain: this.p.domain })\n : (this.p.sequence?.from ?? `<${this.p.local}@${this.p.domain}>`);\n this.send(`MAIL FROM:${from}`);\n return;\n }\n case SMTPStep.rcptTo:\n this.executeEnvelope();\n return;\n }\n }\n\n /**\n * Conditional STARTTLS upgrade. Skipped (advances to next step) when:\n * - already TLS (implicit-TLS port like 465 or already-upgraded)\n * - `startTls === 'never'`\n * - `startTls === 'auto'` AND the MX didn't advertise STARTTLS in EHLO\n *\n * Sends `STARTTLS` and waits for 220 when:\n * - `startTls === 'force'` (regardless of advertisement)\n * - `startTls === 'auto'` AND the MX advertised it\n *\n * On 220, `tls.connect()` wraps the existing socket. After the handshake\n * we re-EHLO (mandatory per RFC 3207 §4.2 — pre-TLS state must be\n * discarded) before continuing to MAIL FROM.\n */\n private executeStartTls(): void {\n const mode = this.p.startTls;\n const wantsUpgrade =\n !this.isTLS && mode !== 'never' && (mode === 'force' || (mode === 'auto' && this.supportsStartTls));\n\n if (!wantsUpgrade) {\n this.nextStep(); // advance to mailFrom\n return;\n }\n this.send('STARTTLS');\n }\n\n /**\n * Wrap the plaintext socket with TLS in place. Called after the server\n * answers our STARTTLS with 220. Detaches the plaintext-socket listeners\n * (TLS owns the underlying transport now), re-installs them on the wrapped\n * socket, resets EHLO-derived capabilities, and re-issues EHLO once the\n * handshake completes (RFC 3207 §4.2 mandates re-EHLO after upgrade —\n * pre-TLS state must be discarded).\n */\n private upgradeToTls(): void {\n const plainSocket = this.socket;\n if (!plainSocket) {\n this.finish(null, 'tls_upgrade_failed');\n return;\n }\n\n // Detach OUR listeners so the plaintext socket's events (which TLS now\n // drives internally) don't reach our handlers and prematurely call\n // finish(). TLS will install its own listeners on the wrapped socket.\n // Guarded: test mocks may not implement EventEmitter fully.\n const detach = (plainSocket as { removeAllListeners?: (ev: string) => void }).removeAllListeners;\n if (typeof detach === 'function') {\n detach.call(plainSocket, 'data');\n detach.call(plainSocket, 'error');\n detach.call(plainSocket, 'close');\n detach.call(plainSocket, 'timeout');\n }\n try {\n plainSocket.setTimeout(0);\n } catch {\n // Fake / already-destroyed sockets may not accept setTimeout — fine.\n }\n\n this.tlsUpgrading = true;\n const servername = isIPAddress(this.p.mxHost) ? undefined : this.p.mxHost;\n\n const tlsSocket = tls.connect({ ...this.tlsOptions, socket: plainSocket, servername }, () => {\n this.tlsUpgrading = false;\n this.isTLS = true;\n // RFC 3207 §4.2 — discard any pre-TLS server state. Capabilities\n // re-read from the second EHLO; the first set may have been a\n // downgrade attack (or legitimately different).\n this.buffer = '';\n this.supportsStartTls = false;\n this.supportsPipelining = false;\n this.postUpgradeReEhlo = true;\n this.send(`EHLO ${this.p.heloHostname}`);\n });\n\n this.socket = tlsSocket;\n this.socket.on('data', this.onData);\n // Distinguish handshake errors (the wrapped TLS layer) from later\n // post-upgrade socket errors so callers can tell what failed.\n this.socket.on('error', () => {\n this.finish(null, this.tlsUpgrading ? 'tls_handshake_failed' : 'connection_error');\n });\n this.socket.on('close', () => this.finish(null, 'connection_closed'));\n this.socket.setTimeout(this.p.perAttemptTimeoutMs, () => this.finish(null, 'socket_timeout'));\n }\n\n /**\n * Send the dual-probe envelope (real RCPT + probe RCPT + RSET). Pipelined\n * when the MX advertised PIPELINING (or `pipelining: 'force'`); sequential\n * otherwise.\n */\n private executeEnvelope(): void {\n const wantsPipelining = this.p.pipelining === 'force' || (this.p.pipelining === 'auto' && this.supportsPipelining);\n\n const realCmd = `RCPT TO:<${this.p.local}@${this.p.domain}>`;\n\n if (wantsPipelining) {\n // Batch real + probe + RSET into one socket.write(). Response phases\n // (rcpt_real → rcpt_probe → rset) demux replies in order.\n this.dualPipelined = true;\n const probeCmd = `RCPT TO:<${this.probeLocal}@${this.p.domain}>`;\n const rsetCmd = 'RSET';\n this.commands.push(realCmd, probeCmd, rsetCmd);\n this.p.log(`→ ${realCmd}`);\n this.p.log(`→ ${probeCmd}`);\n this.p.log(`→ ${rsetCmd}`);\n this.socket?.write(`${realCmd}\\r\\n${probeCmd}\\r\\n${rsetCmd}\\r\\n`);\n this.dualPhase = 'rcpt_real';\n return;\n }\n\n // Sequential — send real RCPT first; rest follows in handleEnvelopeReply.\n this.dualPipelined = false;\n this.send(realCmd);\n this.dualPhase = 'rcpt_real';\n }\n\n private processLine(line: string): void {\n if (this.resolved) return;\n this.transcript.push(line);\n this.p.log(`← ${line}`);\n\n // Parse code + DSN up-front so the result carries them even when a\n // heuristic short-circuits before dispatch.\n const codeStr = line.slice(0, 3);\n const numericCode = /^\\d{3}$/.test(codeStr) ? parseInt(codeStr, 10) : null;\n if (numericCode !== null) this.lastResponseCode = numericCode;\n const dsn = parseDsn(line);\n if (dsn) this.lastEnhancedStatus = dsnToString(dsn);\n\n // Heuristic early-returns fire pre-envelope and on the real-RCPT response.\n // Inside the probe/rset phases we ignore them — a probe response shouldn't\n // be classified as \"high volume\" or \"not found\" (those signals refer to\n // the real recipient). Multi-line replies (e.g. `452-4.2.2 over quota...`)\n // trigger the heuristics here BEFORE the multiline check returns early.\n if (this.dualPhase === 'idle' || this.dualPhase === 'rcpt_real') {\n if (isHighVolume(line)) {\n this.finish(true, 'high_volume');\n return;\n }\n if (isOverQuota(line)) {\n this.isCatchAllFlag = false;\n this.finish(false, 'over_quota');\n return;\n }\n if (isInvalidMailboxError(line)) {\n this.isCatchAllFlag = false;\n this.finish(false, 'not_found');\n return;\n }\n }\n\n // Multi-line continuation. Capture EHLO advertisements so we know\n // whether to use PIPELINING when the envelope phase fires.\n if (MULTILINE_RE.test(line)) {\n const step = this.steps[this.currentStepIndex];\n // Capability detection on EHLO multi-line. Also fires on the\n // post-STARTTLS re-EHLO (currentStep is `startTls` until we receive\n // the 250 below) so capabilities are re-read after the upgrade —\n // some MXes advertise different capabilities pre/post-TLS.\n const isEhloLike =\n step === SMTPStep.ehlo || step === SMTPStep.helo || (step === SMTPStep.startTls && this.postUpgradeReEhlo);\n if (isEhloLike && line.startsWith('250-')) {\n const upper = line.toUpperCase();\n if (upper.includes('PIPELINING')) this.supportsPipelining = true;\n if (upper.includes('STARTTLS')) this.supportsStartTls = true;\n }\n return;\n }\n\n if (numericCode === null) {\n this.finish(null, 'unrecognized_response');\n return;\n }\n\n this.dispatch(numericCode, line);\n }\n\n private dispatch(code: number, line: string): void {\n const step = this.steps[this.currentStepIndex];\n\n // Inside the envelope, route by phase.\n if (this.dualPhase !== 'idle' && step === SMTPStep.rcptTo) {\n this.handleEnvelopeReply(code, line);\n return;\n }\n\n switch (step) {\n case SMTPStep.greeting:\n if (code === 220) this.nextStep();\n else this.finish(null, 'no_greeting');\n return;\n case SMTPStep.ehlo:\n if (code === 250) this.nextStep();\n else this.finish(null, 'ehlo_failed');\n return;\n case SMTPStep.helo:\n if (code === 250) this.nextStep();\n else this.finish(null, 'helo_failed');\n return;\n case SMTPStep.startTls:\n // Two replies map to this step:\n // 1. The server's 220 response to our `STARTTLS` command —\n // handshake the wrapper socket and re-EHLO.\n // 2. The 250 response to that post-upgrade re-EHLO — advance to\n // MAIL FROM (skip startTls now that we've done the dance).\n if (this.postUpgradeReEhlo) {\n this.postUpgradeReEhlo = false;\n if (code === 250) this.nextStep();\n else this.finish(null, 'ehlo_failed');\n return;\n }\n if (code === 220) {\n this.upgradeToTls();\n } else {\n this.finish(null, 'tls_upgrade_failed');\n }\n return;\n case SMTPStep.mailFrom:\n if (code === 250) this.nextStep();\n else this.finish(null, 'mail_from_rejected');\n return;\n case SMTPStep.rcptTo:\n // Only reachable if dualPhase is idle on rcptTo — should never happen\n // in practice (executeEnvelope sets it). Treat as fall-through.\n this.handleEnvelopeReply(code, line);\n return;\n }\n }\n\n /**\n * Dual-probe / pipelined-envelope reply router. Demuxes server replies for\n * the three queued commands (real RCPT, probe RCPT, RSET) and resolves\n * with the catch-all-aware verdict.\n */\n private handleEnvelopeReply(code: number, line: string): void {\n if (this.dualPhase === 'rcpt_real') {\n this.realOutcome = classifyRcpt(code);\n\n // Over-quota short-circuits — the catch-all probe gives no extra signal.\n if (code === 552 || code === 452 || isOverQuota(line)) {\n this.isCatchAllFlag = false;\n if (this.dualPipelined) {\n this.pendingDecision = { result: false, reason: 'over_quota' };\n this.dualPhase = 'rcpt_probe';\n return;\n }\n this.finish(false, 'over_quota');\n return;\n }\n\n // Soft reject — temporary; further probing would hit the same rate-limit.\n if (this.realOutcome === 'soft_reject') {\n if (this.dualPipelined) {\n this.pendingDecision = { result: null, reason: 'temporary_failure' };\n this.dualPhase = 'rcpt_probe';\n return;\n }\n this.finish(null, 'temporary_failure');\n return;\n }\n\n // Hard reject — distinguish \"user unknown\" (clean not_found) from policy /\n // spam-flagged 5xx (genuinely ambiguous).\n if (this.realOutcome === 'hard_reject') {\n const reason = isInvalidMailboxError(line) ? 'not_found' : 'ambiguous';\n const result = reason === 'not_found' ? false : null;\n this.isCatchAllFlag = false;\n if (this.dualPipelined) {\n this.pendingDecision = { result, reason };\n this.dualPhase = 'rcpt_probe';\n return;\n }\n this.finish(result, reason);\n return;\n }\n\n // Real RCPT accepted — advance to probe phase.\n if (this.dualPipelined) {\n this.dualPhase = 'rcpt_probe';\n } else {\n this.send(`RCPT TO:<${this.probeLocal}@${this.p.domain}>`);\n this.dualPhase = 'rcpt_probe';\n }\n return;\n }\n\n if (this.dualPhase === 'rcpt_probe') {\n this.probeOutcome = classifyRcpt(code);\n if (this.dualPipelined) {\n this.dualPhase = 'rset';\n } else {\n this.send('RSET');\n this.dualPhase = 'rset';\n }\n return;\n }\n\n if (this.dualPhase === 'rset') {\n // RSET response received. We don't care about its code — it's just the\n // demux marker that the envelope is fully drained.\n if (this.pendingDecision) {\n // Pre-decided verdict from a real-RCPT reject; commit it now.\n this.finish(this.pendingDecision.result, this.pendingDecision.reason);\n return;\n }\n this.decideDualProbe();\n return;\n }\n }\n\n /** Final decision after both RCPT outcomes are known. Catch-all only when both 250. */\n private decideDualProbe(): void {\n if (this.realOutcome === 'accept' && this.probeOutcome === 'accept') {\n this.isCatchAllFlag = true;\n this.finish(true, 'valid');\n } else if (this.realOutcome === 'accept') {\n this.isCatchAllFlag = false;\n this.finish(true, 'valid');\n } else if (this.realOutcome === 'hard_reject') {\n this.isCatchAllFlag = false;\n this.finish(false, 'not_found');\n } else if (this.realOutcome === 'soft_reject') {\n this.finish(null, 'temporary_failure');\n } else {\n this.finish(null, 'ambiguous');\n }\n }\n\n private finish(result: boolean | null, reason: string): void {\n if (this.resolved) return;\n this.resolved = true;\n this.p.log(`${this.p.port}: ${reason}`);\n\n if (this.connectionTimer) clearTimeout(this.connectionTimer);\n if (this.stepTimer) clearTimeout(this.stepTimer);\n\n try {\n this.socket?.setTimeout(0);\n } catch {\n // Already destroyed.\n }\n try {\n this.socket?.write('QUIT\\r\\n');\n } catch {\n // Already destroyed.\n }\n const drain = setTimeout(() => this.socket?.destroy(), QUIT_DRAIN_MS);\n drain.unref?.();\n\n this.resolveFn({\n result,\n reason,\n ...(this.lastEnhancedStatus !== undefined ? { enhancedStatus: this.lastEnhancedStatus } : {}),\n ...(this.lastResponseCode !== undefined ? { responseCode: this.lastResponseCode } : {}),\n ...(this.isCatchAllFlag !== undefined ? { isCatchAll: this.isCatchAllFlag } : {}),\n transcript: this.transcript,\n commands: this.commands,\n });\n }\n}\n\nfunction classifyRcpt(code: number): RcptOutcome {\n if (code === 250 || code === 251) return 'accept';\n if (code >= 400 && code < 500) return 'soft_reject';\n return 'hard_reject';\n}\n","/**\n * Lightweight transcript collector used by `verifyEmail` to capture a\n * structured trace of every subsystem call (syntax / disposable / free /\n * MX / SMTP / WHOIS / name detection / domain suggestion).\n *\n * Two collectors:\n * - `ArrayTranscriptCollector` — accumulates steps, exposed in result.\n * - `NULL_COLLECTOR` — no-op singleton used when capture is disabled, so\n * the call sites in `verifyEmail` never need an `if (transcript)` branch.\n */\nimport type { VerificationStep, VerificationStepKind } from './types';\n\nexport interface TranscriptCollector {\n /** Run `fn`, time it, push a step record. Re-throws on error after recording. */\n record<T>(\n kind: VerificationStepKind,\n fn: () => Promise<T> | T,\n detailsFor: (value: T) => Record<string, unknown>\n ): Promise<T>;\n /** Push a pre-built step. Useful when timing is owned by the callee. */\n push(step: VerificationStep): void;\n}\n\nexport class ArrayTranscriptCollector implements TranscriptCollector {\n readonly steps: VerificationStep[] = [];\n\n async record<T>(\n kind: VerificationStepKind,\n fn: () => Promise<T> | T,\n detailsFor: (value: T) => Record<string, unknown>\n ): Promise<T> {\n const startedAt = Date.now();\n try {\n const value = await fn();\n this.steps.push({\n kind,\n startedAt,\n durationMs: Date.now() - startedAt,\n ok: true,\n details: detailsFor(value),\n });\n return value;\n } catch (error) {\n this.steps.push({\n kind,\n startedAt,\n durationMs: Date.now() - startedAt,\n ok: false,\n details: { error: error instanceof Error ? error.message : String(error) },\n });\n throw error;\n }\n }\n\n push(step: VerificationStep): void {\n this.steps.push(step);\n }\n}\n\n/** No-op collector — every method is a no-op. Used when capture is disabled. */\nexport const NULL_COLLECTOR: TranscriptCollector = {\n async record(_kind, fn) {\n return fn();\n },\n push() {\n // no-op\n },\n};\n","const defaultRegex = {\n domainName: 'Domain Name: *([^\\\\s]+)',\n registrar: 'Registrar: *(.+)',\n updatedDate: 'Updated Date: *(.+)',\n creationDate: 'Creat(ed|ion) Date: *(.+)',\n expirationDate: 'Expir\\\\w+ Date: *(.+)',\n status: 'Status:\\\\s*(.+)\\\\s*\\\\n',\n dateFormat: \"yyyy-MM-dd'T'HH:mm:ss'Z'\",\n notFound: '(No match for |Domain not found|NOT FOUND\\\\s)',\n};\n\nconst comRegex = { ...defaultRegex, notFound: 'No match for ' };\n\nconst orgRegex = { ...defaultRegex, notFound: '^(NOT FOUND|Domain not found)' };\n\nconst auRegex = {\n ...defaultRegex,\n updatedDate: 'Last Modified: *(.+)',\n registrar: 'Registrar Name: *(.+)',\n rateLimited: 'WHOIS LIMIT EXCEEDED',\n notFound: '^NOT FOUND',\n};\n\nconst usRegex = {\n ...defaultRegex,\n status: 'Domain Status: *(.+)',\n expirationDate: 'Registrar Registration Expiration Date: *(.+)',\n notFound: '^No Data Found',\n};\n\nconst ruRegex = {\n ...defaultRegex,\n domainName: 'domain: *([^\\\\s]+)',\n registrar: 'registrar: *(.+)',\n expirationDate: 'paid-till: *(.+)',\n status: 'state: *(.+)',\n notFound: 'No entries found',\n};\n\nconst ukRegex = {\n ...defaultRegex,\n domainName: 'Domain name:\\\\s*([^\\\\s]+)',\n dateFormat: 'dd-MMM-yyyy',\n};\n\nconst frRegex = {\n ...defaultRegex,\n domainName: 'domain: *([^\\\\s]+)',\n expirationDate: 'Expir\\\\w+ Date:\\\\s?(.+)',\n updatedDate: 'last-update: *(.+)',\n notFound: '(No entries found in |%% NOT FOUND)',\n};\n\nconst nlRegex = {\n ...defaultRegex,\n notFound: '\\\\.nl is free',\n rateLimited: 'maximum number of requests per second exceeded',\n};\n\nconst fiRegex = {\n ...defaultRegex,\n domainName: 'domain\\\\.*: *([\\\\S]+)',\n registrar: 'registrar\\\\.*: *(.*)',\n status: 'status\\\\.*: *([\\\\S]+)',\n dateFormat: 'dd.MM.yyyy HH:mm:ss',\n};\n\nconst jpRegex = {\n ...defaultRegex,\n domainName: '\\\\[Domain Name\\\\]\\\\s*([^\\\\s]+)',\n dateFormat: 'yyyy/MM/dd',\n notFound: 'No match!!',\n};\n\nconst plRegex = {\n ...defaultRegex,\n domainName: 'DOMAIN NAME: *([^\\\\s]+)\\\\s+',\n status: 'Registration status:\\\\n\\\\s*(.+)',\n expirationDate: 'renewal date: *(.+)',\n dateFormat: 'yyyy.MM.dd HH:mm:ss',\n};\n\nconst brRegex = {\n ...defaultRegex,\n domainName: 'domain: *([^\\\\s]+)\\\\n',\n dateFormat: 'yyyyMMdd',\n};\n\nconst euRegex = {\n ...defaultRegex,\n domainName: 'Domain: *([^\\\\n\\\\r]+)',\n registrar: 'Registrar: *\\\\n *Name: *([^\\\\n\\\\r]+)',\n notFound: 'Status: AVAILABLE',\n};\n\nconst eeRegex = {\n ...defaultRegex,\n domainName: 'Domain: *[\\\\n\\\\r]+\\\\s*name: *([^\\\\n\\\\r]+)',\n status: 'Domain: *[\\\\n\\\\r]+\\\\s*name: *[^\\\\n\\\\r]+\\\\s*status: *([^\\\\n\\\\r]+)',\n};\n\nconst krRegex = {\n ...defaultRegex,\n domainName: 'Domain Name\\\\s*: *([^\\\\s]+)',\n dateFormat: 'yyyy. MM. dd.',\n notFound: 'The requested domain was not found ',\n};\n\nconst bgRegex = {\n ...defaultRegex,\n domainName: 'DOMAIN NAME: *([^\\\\s]+)',\n status: 'registration status:\\\\s*(.+)',\n notFound: 'registration status: available',\n rateLimited: 'Query limit exceeded',\n};\n\nconst deRegex = {\n ...defaultRegex,\n domainName: 'Domain: *([^\\\\s]+)',\n notFound: 'Status: *free',\n};\n\nconst atRegex = {\n ...defaultRegex,\n domainName: 'domain: *([^\\\\s]+)',\n notFound: ' nothing found',\n dateFormat: 'yyyyMMdd HH:mm:ss',\n rateLimited: 'Quota exceeded',\n};\n\nconst caRegex = {\n ...defaultRegex,\n domainName: 'Domain Name: *([^\\\\s]+)',\n notFound: 'Not found: ',\n};\n\nconst beRegex = {\n ...defaultRegex,\n domainName: 'Domain:\\\\s*([^\\\\s]+)',\n dateFormat: 'ddd MMM dd yyyy',\n notFound: 'Status:\\\\s*AVAILABLE',\n};\n\nconst infoRegex = {\n ...defaultRegex,\n notFound: '^(NOT FOUND|Domain not found)',\n};\n\nconst kgRegex = {\n ...defaultRegex,\n domainName: '^Domain\\\\s*([^\\\\s]+)',\n dateFormat: 'ddd MMM dd HH:mm:ss yyyy',\n notFound: 'domain is available for registration',\n};\n\nconst idRegex = {\n ...defaultRegex,\n domainName: 'Domain Name:([^\\\\s]+)',\n dateFormat: \"dd-MMM-yyyy HH:mm:ss 'UTC'\",\n notFound: 'DOMAIN NOT FOUND',\n};\n\nconst skRegex = {\n ...defaultRegex,\n domainName: 'Domain:\\\\s*([^\\\\s]+)',\n notFound: 'Domain not found',\n};\n\nconst seRegex = {\n ...defaultRegex,\n domainName: 'domain\\\\.*: *([^\\\\s]+)',\n notFound: '\\\\\" not found.',\n};\n\nconst isRegex = {\n ...defaultRegex,\n domainName: 'domain\\\\.*: *([^\\\\s]+)',\n dateFormat: 'MMM dd yyyy',\n notFound: 'No entries found for query',\n};\n\nconst coRegex = {\n ...defaultRegex,\n notFound: 'No Data Found',\n};\n\ntype Regex = {\n registrar?: string;\n domainName?: string;\n notFound?: string;\n updatedDate?: string;\n creationDate?: string;\n expirationDate?: string;\n status?: string;\n rateLimited?: string;\n dateFormat?: string;\n};\n\nexport type ParsedWhoisResult = {\n domainName: string;\n isAvailable?: boolean;\n registryDomainId?: string;\n registrarWhoisServer?: string;\n registrar?: string;\n registrarUrl?: string;\n registrarIanaId?: string;\n registrarAbuseContactEmail?: string;\n registrarAbuseContactPhone?: string;\n updatedDate?: string | null;\n creationDate?: string | null;\n expirationDate?: string | null;\n status?: string[];\n dnssec?: string;\n nameServers?: string[];\n rateLimited?: boolean;\n notFound?: boolean;\n dateFormat?: string;\n};\n\n// Helper function to parse dates based on format string\nfunction parseDate(dateStr: string, format: string): Date | null {\n try {\n // Clean up the date string\n dateStr = dateStr.trim();\n\n // Handle ISO format. Validate before returning — `new Date('garbage')`\n // returns an Invalid Date object that crashes `.toISOString()` callers.\n if (format === \"yyyy-MM-dd'T'HH:mm:ss'Z'\" || dateStr.match(/^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}/)) {\n const isoDate = new Date(dateStr);\n return Number.isNaN(isoDate.getTime()) ? null : isoDate;\n }\n\n // Handle various date formats\n let date: Date | null = null;\n\n switch (format) {\n case 'yyyy/MM/dd': {\n const parts = dateStr.split('/');\n if (parts.length === 3) {\n date = new Date(`${parts[0]}-${parts[1].padStart(2, '0')}-${parts[2].padStart(2, '0')}`);\n }\n break;\n }\n case 'dd-MMM-yyyy': {\n // e.g., \"14-Sep-2023\"\n date = new Date(dateStr.replace(/-/g, ' '));\n break;\n }\n case 'dd.MM.yyyy HH:mm:ss': {\n const [datePart, timePart] = dateStr.split(' ');\n if (datePart) {\n const parts = datePart.split('.');\n if (parts.length === 3) {\n const dateString = `${parts[2]}-${parts[1].padStart(2, '0')}-${parts[0].padStart(2, '0')}`;\n date = new Date(`${dateString}${timePart ? `T${timePart}` : ''}`);\n }\n }\n break;\n }\n case 'yyyy.MM.dd HH:mm:ss': {\n const [datePart, timePart] = dateStr.split(' ');\n if (datePart) {\n const parts = datePart.split('.');\n if (parts.length === 3) {\n const dateString = `${parts[0]}-${parts[1].padStart(2, '0')}-${parts[2].padStart(2, '0')}`;\n date = new Date(`${dateString}${timePart ? `T${timePart}` : ''}`);\n }\n }\n break;\n }\n case 'yyyyMMdd': {\n if (dateStr.length === 8) {\n const year = dateStr.substring(0, 4);\n const month = dateStr.substring(4, 6);\n const day = dateStr.substring(6, 8);\n date = new Date(`${year}-${month}-${day}`);\n }\n break;\n }\n case 'yyyy. MM. dd.': {\n const cleaned = dateStr.replace(/\\./g, '').trim();\n const parts = cleaned.split(/\\s+/);\n if (parts.length === 3) {\n date = new Date(`${parts[0]}-${parts[1].padStart(2, '0')}-${parts[2].padStart(2, '0')}`);\n }\n break;\n }\n case 'ddd MMM dd yyyy': {\n // e.g., \"Thu Sep 14 2023\"\n const parts = dateStr.split(/\\s+/);\n if (parts.length >= 4) {\n date = new Date(`${parts[1]} ${parts[2]} ${parts[3]}`);\n }\n break;\n }\n case 'ddd MMM dd HH:mm:ss yyyy': {\n // e.g., \"Thu Sep 14 10:30:00 2023\"\n const parts = dateStr.split(/\\s+/);\n if (parts.length >= 5) {\n date = new Date(`${parts[1]} ${parts[2]} ${parts[4]} ${parts[3]}`);\n }\n break;\n }\n case 'yyyyMMdd HH:mm:ss': {\n const [datePart, timePart] = dateStr.split(' ');\n if (datePart && datePart.length === 8) {\n const year = datePart.substring(0, 4);\n const month = datePart.substring(4, 6);\n const day = datePart.substring(6, 8);\n date = new Date(`${year}-${month}-${day}${timePart ? `T${timePart}` : ''}`);\n }\n break;\n }\n case \"dd-MMM-yyyy HH:mm:ss 'UTC'\": {\n // e.g., \"14-Sep-2023 10:30:00 UTC\"\n const cleaned = dateStr.replace(/\\s*UTC\\s*$/, '');\n date = new Date(cleaned.replace(/-/g, ' '));\n break;\n }\n case 'MMM dd yyyy': {\n // e.g., \"Sep 14 2023\"\n date = new Date(dateStr);\n break;\n }\n default: {\n // Try parsing as ISO or standard format\n date = new Date(dateStr);\n }\n }\n\n // Check if the date is valid\n if (date && !Number.isNaN(date.getTime())) {\n return date;\n }\n\n // Fallback: try direct parsing\n const fallback = new Date(dateStr);\n if (!Number.isNaN(fallback.getTime())) {\n return fallback;\n }\n\n return null;\n } catch {\n return null;\n }\n}\n\n/**\n * TLD → registry-specific regex set. Multiple TLDs share a regex when their\n * WHOIS servers use the same response shape (`.com` and `.net` are both\n * served by Verisign with identical formatting).\n */\nconst TLD_REGEX: Record<string, Regex> = {\n com: comRegex,\n net: comRegex,\n name: comRegex,\n org: orgRegex,\n me: orgRegex,\n mobi: orgRegex,\n au: auRegex,\n ru: ruRegex,\n рф: ruRegex,\n su: ruRegex,\n us: usRegex,\n biz: usRegex,\n uk: ukRegex,\n fr: frRegex,\n nl: nlRegex,\n fi: fiRegex,\n jp: jpRegex,\n pl: plRegex,\n br: brRegex,\n eu: euRegex,\n ee: eeRegex,\n kr: krRegex,\n bg: bgRegex,\n de: deRegex,\n at: atRegex,\n ca: caRegex,\n be: beRegex,\n kg: kgRegex,\n info: infoRegex,\n id: idRegex,\n sk: skRegex,\n se: seRegex,\n nu: seRegex,\n is: isRegex,\n co: coRegex,\n};\n\n/** Generic free-text WHOIS fields shared across registries. */\nconst COMMON_FIELD_PATTERNS: ReadonlyArray<{\n pattern: RegExp;\n property: keyof ParsedWhoisResult;\n multiple?: boolean;\n}> = [\n { pattern: /Name Server:\\s*(.*)/gi, property: 'nameServers', multiple: true },\n { pattern: /Registrar URL:\\s*(.*)/i, property: 'registrarUrl' },\n { pattern: /Registrar WHOIS Server:\\s*(.*)/i, property: 'registrarWhoisServer' },\n { pattern: /Registry Domain ID:\\s*(.*)/i, property: 'registryDomainId' },\n { pattern: /Registrar Abuse Contact Email:\\s*(.*)/i, property: 'registrarAbuseContactEmail' },\n { pattern: /Registrar Abuse Contact Phone:\\s*(.*)/i, property: 'registrarAbuseContactPhone' },\n { pattern: /DNSSEC:\\s*(.*)/i, property: 'dnssec' },\n { pattern: /Registrar IANA ID:\\s*(.*)/i, property: 'registrarIanaId' },\n];\n\nconst ISO_DATE_FORMAT = \"yyyy-MM-dd'T'HH:mm:ss'Z'\";\n\nfunction pickRegex(domain: string): Regex {\n const tld = domain.split('.').pop()?.toLowerCase();\n if (!tld) return defaultRegex;\n return TLD_REGEX[tld] ?? defaultRegex;\n}\n\nfunction collectStatuses(rawData: string, pattern: string): string[] {\n const out: string[] = [];\n const re = new RegExp(pattern, 'gi');\n for (const match of rawData.matchAll(re)) {\n if (match[1]) out.push(match[1].trim());\n }\n return out;\n}\n\nfunction extractDate(rawData: string, pattern: string, dateFormat: string): string | undefined {\n // The default `Creat(ed|ion) Date:` pattern wraps the keyword in a capture\n // group, so we use a non-capturing variant when reading the value.\n const dateRegex = pattern.includes('Creat(ed|ion)') ? /Creat(?:ed|ion) Date:\\s*(.+)/i : new RegExp(pattern, 'i');\n const dateStr = rawData.match(dateRegex)?.[1]?.trim();\n if (!dateStr) return undefined;\n return parseDate(dateStr, dateFormat)?.toISOString() ?? dateStr;\n}\n\nfunction applyCommonFieldPatterns(rawData: string, result: ParsedWhoisResult): void {\n for (const { pattern, property, multiple } of COMMON_FIELD_PATTERNS) {\n if (multiple) {\n const matches = Array.from(rawData.matchAll(pattern));\n if (matches.length > 0) (result[property] as string[]) = matches.map((m) => m[1].trim());\n continue;\n }\n const match = rawData.match(pattern);\n if (match?.[1]) (result[property] as string) = match[1].trim();\n }\n}\n\nexport function parseWhoisData({ rawData, domain }: { rawData: string; domain: string }): ParsedWhoisResult {\n if (!rawData) return { domainName: domain, isAvailable: true };\n\n const result: ParsedWhoisResult = { domainName: domain };\n const regexSet = pickRegex(domain);\n const dateFormat = regexSet.dateFormat ?? ISO_DATE_FORMAT;\n\n for (const [key, pattern] of Object.entries(regexSet)) {\n if (!pattern || key === 'dateFormat') continue;\n if (!new RegExp(pattern, 'i').test(rawData)) continue;\n\n switch (key as keyof Regex) {\n case 'rateLimited':\n result.rateLimited = true;\n throw new Error('Rate Limited');\n case 'notFound':\n result.isAvailable = true;\n break;\n case 'status':\n result.status = collectStatuses(rawData, pattern);\n break;\n case 'creationDate':\n case 'expirationDate':\n case 'updatedDate': {\n const value = extractDate(rawData, pattern, dateFormat);\n if (value) result[key as 'creationDate' | 'expirationDate' | 'updatedDate'] = value;\n break;\n }\n case 'domainName': {\n const m = rawData.match(new RegExp(pattern, 'i'));\n if (m?.[1]) result.domainName = m[1].toLowerCase().trim();\n break;\n }\n case 'registrar': {\n const m = rawData.match(new RegExp(pattern, 'i'));\n if (m?.[1]) result.registrar = m[1].trim();\n break;\n }\n }\n }\n\n result.isAvailable ??= false;\n applyCommonFieldPatterns(rawData, result);\n return result;\n}\n","/**\n * WHOIS lookup — TCP query against a TLD-specific WHOIS server, then parse.\n *\n * Two public surfaces:\n * - `getDomainAge`: extracts creation date and computes age.\n * - `getDomainRegistrationStatus`: extracts registrar / status / expiry.\n *\n * Both share the same `getWhoisData` retrieval pipeline:\n * 1. Strip URL/email noise from the domain (`cleanDomain`).\n * 2. Validate via `psl`.\n * 3. Look up the TLD-specific server (or fall back through IANA's referral).\n * 4. TCP-query port 43 (`queryWhoisServer`).\n * 5. Cache the parsed result.\n */\nimport * as net from 'node:net';\nimport { isValid } from 'psl';\nimport { getCacheStore } from './cache';\nimport type { Cache } from './cache-interface';\nimport whoisServersJson from './data/whois-servers.json';\nimport type { DomainAgeInfo, DomainRegistrationInfo } from './types';\nimport { type ParsedWhoisResult, parseWhoisData } from './whois-parser';\n\ntype Logger = (...args: unknown[]) => void;\nconst noopLog: Logger = () => {};\n\nconst WHOIS_PORT = 43;\nconst IANA_FALLBACK_SERVER = 'whois.iana.org';\nconst whoisServers = whoisServersJson as Record<string, string>;\n\n/** Strip protocol, path, and email-prefix noise — return just the host. */\nfunction cleanDomain(input: string): string | null {\n const stripped = input\n .replace(/^https?:\\/\\//, '')\n .split('/')[0]\n ?.split('@')\n .pop();\n return stripped || null;\n}\n\n/** TCP query the WHOIS server on port 43 with a timeout. */\nfunction queryWhoisServer(domain: string, server: string, timeout: number, log: Logger): Promise<string> {\n return new Promise((resolve, reject) => {\n const client = new net.Socket();\n let data = '';\n\n log(`[whois] querying ${server} for ${domain}`);\n\n const timer = setTimeout(() => {\n log(`[whois] timeout after ${timeout}ms — ${domain} @ ${server}`);\n client.destroy();\n reject(new Error('WHOIS query timeout'));\n }, timeout);\n\n client.connect(WHOIS_PORT, server, () => {\n log(`[whois] connected to ${server}, sending query`);\n client.write(`${domain}\\r\\n`);\n });\n\n client.on('data', (chunk) => {\n data += chunk.toString();\n });\n\n client.on('close', () => {\n clearTimeout(timer);\n log(`[whois] received ${data.length} bytes from ${server}`);\n resolve(data);\n });\n\n client.on('error', (err) => {\n clearTimeout(timer);\n log(`[whois] error from ${server}: ${err.message}`);\n reject(err);\n });\n });\n}\n\n/** Pick the TLD-specific server, or fall back through IANA's referral. */\nasync function fetchAndParse(domain: string, timeout: number, log: Logger): Promise<ParsedWhoisResult> {\n const tld = domain.split('.').pop()?.toLowerCase();\n if (!tld) throw new Error('Invalid domain');\n\n const direct = whoisServers[tld];\n if (direct) {\n log(`[whois] using ${direct} for .${tld}`);\n const raw = await queryWhoisServer(domain, direct, timeout, log);\n return parseWhoisData({ rawData: raw, domain });\n }\n\n log(`[whois] no server for .${tld}, asking IANA`);\n const ianaResponse = await queryWhoisServer(domain, IANA_FALLBACK_SERVER, timeout, log);\n const referredServer = ianaResponse.match(/refer:\\s+(\\S+)/i)?.[1];\n if (referredServer) {\n log(`[whois] IANA referred us to ${referredServer}`);\n const raw = await queryWhoisServer(domain, referredServer, timeout, log);\n return parseWhoisData({ rawData: raw, domain });\n }\n return parseWhoisData({ rawData: ianaResponse, domain });\n}\n\nasync function getWhoisData(\n domain: string,\n timeout: number,\n log: Logger,\n cache?: Cache\n): Promise<ParsedWhoisResult | null> {\n const cacheKey = `whois:${domain}`;\n const cacheStore = getCacheStore<ParsedWhoisResult>(cache, 'whois');\n\n const cached = await cacheStore.get(cacheKey);\n if (cached) {\n log(`[whois] cache hit for ${domain}`);\n return cached as ParsedWhoisResult;\n }\n\n try {\n const data = await fetchAndParse(domain, timeout, log);\n await cacheStore.set(cacheKey, data);\n return data;\n } catch (error) {\n log(`[whois] failed for ${domain}: ${error instanceof Error ? error.message : String(error)}`);\n return null;\n }\n}\n\n/** Validate domain shape + parse + cache. Returns null on any failure. */\nasync function loadWhoisFor(\n domain: string,\n timeout: number,\n log: Logger,\n cache?: Cache\n): Promise<{ host: string; data: ParsedWhoisResult } | null> {\n const host = cleanDomain(domain);\n if (!host) {\n log(`[whois] invalid domain shape: ${domain}`);\n return null;\n }\n if (!isValid(host)) {\n log(`[whois] psl rejected: ${host}`);\n return null;\n }\n const data = await getWhoisData(host, timeout, log, cache);\n return data ? { host, data } : null;\n}\n\nexport async function getDomainAge(\n domain: string,\n timeout = 5000,\n debug = false,\n cache?: Cache\n): Promise<DomainAgeInfo | null> {\n const log: Logger = debug ? console.debug : noopLog;\n const loaded = await loadWhoisFor(domain, timeout, log, cache);\n if (!loaded?.data.creationDate) return null;\n\n const { host, data } = loaded;\n // Type-narrowed by the guard above — destructuring widens it back, so re-check.\n const rawCreation = data.creationDate;\n if (!rawCreation) return null;\n const creationDate = new Date(rawCreation);\n const ageInDays = Math.floor((Date.now() - creationDate.getTime()) / 86_400_000);\n const ageInYears = parseFloat((ageInDays / 365.25).toFixed(2));\n log(`[whois] ${host} age: ${ageInDays} days (${ageInYears}y)`);\n\n return {\n domain: host,\n creationDate,\n ageInDays,\n ageInYears,\n expirationDate: data.expirationDate ? new Date(data.expirationDate) : null,\n updatedDate: data.updatedDate ? new Date(data.updatedDate) : null,\n };\n}\n\nexport async function getDomainRegistrationStatus(\n domain: string,\n timeout = 5000,\n debug = false,\n cache?: Cache\n): Promise<DomainRegistrationInfo | null> {\n const log: Logger = debug ? console.debug : noopLog;\n const loaded = await loadWhoisFor(domain, timeout, log, cache);\n if (!loaded) return null;\n\n const { host, data } = loaded;\n if (data.isAvailable) {\n log(`[whois] ${host} is available / not registered`);\n return availableResult(host);\n }\n\n const isRegistered = Boolean(data.domainName || data.creationDate || data.registrar);\n const expirationDate = data.expirationDate ? new Date(data.expirationDate) : null;\n const isExpired = expirationDate ? Date.now() > expirationDate.getTime() : false;\n const daysUntilExpiration =\n expirationDate && !isExpired ? Math.floor((expirationDate.getTime() - Date.now()) / 86_400_000) : null;\n\n // Status codes look like \"clientTransferProhibited https://...\" — keep just the code.\n const statusCodes = (data.status ?? []).map((s) => s.split(' ')[0] ?? '');\n const isPendingDelete = statusCodes.some((s) => /pendingdelete|redemption/i.test(s));\n const isLocked = statusCodes.some((s) => /(client|server)transferprohibited/i.test(s));\n\n log(\n `[whois] ${host} — registered=${isRegistered} expired=${isExpired} locked=${isLocked} pendingDelete=${isPendingDelete}`\n );\n\n return {\n domain: host,\n isRegistered,\n isAvailable: !isRegistered,\n status: statusCodes,\n registrar: data.registrar ?? null,\n nameServers: data.nameServers ?? [],\n expirationDate,\n isExpired,\n daysUntilExpiration,\n isPendingDelete,\n isLocked,\n };\n}\n\nfunction availableResult(domain: string): DomainRegistrationInfo {\n return {\n domain,\n isRegistered: false,\n isAvailable: true,\n status: [],\n registrar: null,\n nameServers: [],\n expirationDate: null,\n isExpired: false,\n daysUntilExpiration: null,\n isPendingDelete: false,\n isLocked: false,\n };\n}\n","/**\n * `verifyEmail` orchestrator + its private helpers.\n *\n * Lives in its own file so `batch-verifier.ts` can import `verifyEmail`\n * without going through `./index.ts` — that re-export was the source of the\n * `index.ts -> batch-verifier.ts -> index.ts` circular dependency Rollup\n * warned about.\n */\nimport { parse } from 'psl';\nimport { getCacheStore } from './cache';\nimport { suggestEmailDomain } from './domain-suggester';\nimport { isValidEmail, isValidEmailDomain } from './email-validator';\nimport { isDisposableEmail } from './is-disposable-email';\nimport { isFreeEmail } from './is-free-email';\nimport { resolveMxRecords } from './mx-resolver';\nimport { detectNameFromEmail } from './name-detector';\nimport { verifyMailboxSMTP } from './smtp-verifier';\nimport { ArrayTranscriptCollector, NULL_COLLECTOR, type TranscriptCollector } from './transcript';\nimport {\n type DomainSuggestion,\n type SmtpVerificationResult,\n VerificationErrorCode,\n type VerificationResult,\n type VerifyEmailParams,\n} from './types';\nimport { getDomainAge, getDomainRegistrationStatus } from './whois';\n\ntype Logger = (...args: unknown[]) => void;\n\n/** Per-MX-domain port overrides — picked when no explicit `smtpPort` was passed. */\nexport const domainPorts: Record<string, number> = {\n // 465 or 587\n // https://help.ovhcloud.com/csm/en-ca-web-paas-development-email?id=kb_article_view&sysparm_article=KB0053893\n 'ovh.net': 465,\n};\n\n/**\n * Copy SMTP verification fields onto the flat result + derive validSmtp.\n * `validSmtp` is null when we couldn't connect (so the caller knows verification\n * was inconclusive, not negative), otherwise tracks `isDeliverable`.\n */\nfunction applySmtpResult(result: VerificationResult, smtp: SmtpVerificationResult): void {\n result.canConnectSmtp = smtp.canConnectSmtp;\n result.hasFullInbox = smtp.hasFullInbox;\n result.isCatchAll = smtp.isCatchAll;\n result.isDeliverable = smtp.isDeliverable;\n result.isDisabled = smtp.isDisabled;\n result.validSmtp = smtp.canConnectSmtp ? smtp.isDeliverable : null;\n}\n\n/** Pick a port override from explicit param > known per-MX-domain map > library default. */\nfunction resolveSmtpPorts(explicitPort: number | undefined, primaryMx: string | undefined): number[] | undefined {\n if (explicitPort) return [explicitPort];\n if (!primaryMx) return undefined;\n const mxDomain = parse(primaryMx);\n if (!('domain' in mxDomain) || !mxDomain.domain) return undefined;\n const known = domainPorts[mxDomain.domain];\n return known ? [known] : undefined;\n}\n\n/**\n * Verify an email address — orchestrates format / disposable / free / MX / SMTP /\n * WHOIS / name-detection / domain-suggestion checks. Each helper below owns one\n * step and runs only when its flag is enabled. Early returns short-circuit on\n * format/domain failures.\n */\nexport async function verifyEmail(params: VerifyEmailParams): Promise<VerificationResult> {\n const startTime = Date.now();\n const debug = params.debug ?? false;\n const log: Logger = debug ? console.debug : () => {};\n const result = blankResult(params.emailAddress);\n\n // Capture collector — opt-in via `captureTranscript`. The NULL_COLLECTOR is\n // a no-op so call sites don't need to branch.\n const captureTranscript = params.captureTranscript ?? false;\n const collector: TranscriptCollector = captureTranscript ? new ArrayTranscriptCollector() : NULL_COLLECTOR;\n\n // 1. Format check — bail fast.\n const syntaxValid = await collector.record(\n 'syntax',\n () => isValidEmail(params.emailAddress),\n (ok) => ({ ok })\n );\n if (!syntaxValid) {\n return finalize(result, VerificationErrorCode.invalidFormat, startTime, collector);\n }\n result.validFormat = true;\n\n // 2. Name detection (cheap, runs on local part only).\n if (params.detectName) {\n result.detectedName = await collector.record(\n 'name-detection',\n () => detectNameFromEmail({ email: params.emailAddress, customMethod: params.nameDetectionMethod }),\n (detected) => ({ detected: detected ?? null })\n );\n }\n\n // 3. Domain suggestion (cheap, runs on domain only).\n if (params.suggestDomain ?? true) {\n result.domainSuggestion = await collector.record(\n 'domain-suggestion',\n () => runSuggestDomain(params),\n (suggestion) => ({ suggestion: suggestion ?? null })\n );\n }\n\n const [local, domain] = params.emailAddress.split('@');\n if (!domain || !local) {\n return finalize(result, VerificationErrorCode.invalidFormat, startTime, collector);\n }\n const domainValid = await collector.record(\n 'domain-validation',\n () => isValidEmailDomain(domain, params.cache),\n (valid) => ({ domain, valid })\n );\n if (!domainValid) {\n return finalize(result, VerificationErrorCode.invalidDomain, startTime, collector);\n }\n\n // 4. Disposable + free provider checks.\n if (params.checkDisposable ?? true) {\n result.isDisposable = await collector.record(\n 'disposable',\n () => isDisposableEmail({ emailOrDomain: params.emailAddress, cache: params.cache, logger: log }),\n (isDisposable) => ({ domain, isDisposable })\n );\n log(`[verifyEmail] disposable: ${result.isDisposable}`);\n if (result.isDisposable) result.metadata.error = VerificationErrorCode.disposableEmail;\n }\n if (params.checkFree ?? true) {\n result.isFree = await collector.record(\n 'free',\n () => isFreeEmail({ emailOrDomain: params.emailAddress, cache: params.cache, logger: log }),\n (isFree) => ({ domain, isFree })\n );\n log(`[verifyEmail] free: ${result.isFree}`);\n }\n\n const skipMx = (params.skipMxForDisposable ?? false) && result.isDisposable;\n const skipWhois = (params.skipDomainWhoisForDisposable ?? false) && result.isDisposable;\n\n // 5. WHOIS-driven domain age + registration (skipped for disposable when configured).\n await runWhoisChecks(domain, params, result, skipWhois, log, collector);\n\n // 6. MX + SMTP — runs when either flag is on, unless we're skipping\n // disposable addresses (the address is already known to be junk).\n const wantsMxOrSmtp = (params.verifyMx ?? true) || (params.verifySmtp ?? false);\n if (wantsMxOrSmtp && skipMx) {\n log(`[verifyEmail] skipping MX/SMTP for disposable: ${params.emailAddress}`);\n } else if (wantsMxOrSmtp) {\n await runMxAndSmtp(local, domain, params, result, log, collector);\n }\n\n result.metadata.verificationTime = Date.now() - startTime;\n if (captureTranscript) result.transcript = (collector as ArrayTranscriptCollector).steps;\n return result;\n}\n\nfunction blankResult(email: string): VerificationResult {\n return {\n email,\n validFormat: false,\n validMx: null,\n validSmtp: null,\n isDisposable: false,\n isFree: false,\n metadata: { verificationTime: 0, cached: false },\n };\n}\n\nfunction finalize(\n result: VerificationResult,\n error: VerificationErrorCode,\n startTime: number,\n collector: TranscriptCollector\n): VerificationResult {\n result.metadata.error = error;\n result.metadata.verificationTime = Date.now() - startTime;\n if (collector instanceof ArrayTranscriptCollector) {\n result.transcript = collector.steps;\n }\n return result;\n}\n\nasync function runSuggestDomain(params: VerifyEmailParams): Promise<DomainSuggestion | null> {\n const [, emailDomain] = params.emailAddress.split('@');\n if (!emailDomain) return null;\n if (params.domainSuggestionMethod) return params.domainSuggestionMethod(emailDomain);\n return suggestEmailDomain(params.emailAddress, params.commonDomains);\n}\n\nasync function runWhoisChecks(\n domain: string,\n params: VerifyEmailParams,\n result: VerificationResult,\n skipWhois: boolean,\n log: Logger,\n collector: TranscriptCollector\n): Promise<void> {\n if (!params.checkDomainAge && !params.checkDomainRegistration) return;\n if (skipWhois) {\n log(`[verifyEmail] WHOIS checks skipped for disposable: ${domain}`);\n return;\n }\n const whoisTimeoutMs = params.whoisTimeoutMs ?? 5000;\n const debug = params.debug ?? false;\n\n if (params.checkDomainAge) {\n try {\n result.domainAge = await collector.record(\n 'whois-age',\n () => getDomainAge(domain, whoisTimeoutMs, debug, params.cache),\n (info) => ({\n domain,\n found: info !== null,\n ageInDays: info?.ageInDays ?? null,\n ageInYears: info?.ageInYears ?? null,\n creationDate: info?.creationDate?.toISOString() ?? null,\n expirationDate: info?.expirationDate?.toISOString() ?? null,\n })\n );\n log(`[verifyEmail] domain age:`, result.domainAge ? `${result.domainAge.ageInDays} days` : 'null');\n } catch (error) {\n log('[verifyEmail] domain age lookup failed', error);\n result.domainAge = null;\n }\n }\n\n if (params.checkDomainRegistration) {\n try {\n result.domainRegistration = await collector.record(\n 'whois-registration',\n () => getDomainRegistrationStatus(domain, whoisTimeoutMs, debug, params.cache),\n (info) => ({\n domain,\n found: info !== null,\n isRegistered: info?.isRegistered ?? null,\n isExpired: info?.isExpired ?? null,\n isLocked: info?.isLocked ?? null,\n isPendingDelete: info?.isPendingDelete ?? null,\n daysUntilExpiration: info?.daysUntilExpiration ?? null,\n status: info?.status ?? [],\n })\n );\n log(`[verifyEmail] registered:`, result.domainRegistration?.isRegistered ?? false);\n } catch (error) {\n log('[verifyEmail] domain registration lookup failed', error);\n result.domainRegistration = null;\n }\n }\n}\n\nasync function runMxAndSmtp(\n local: string,\n domain: string,\n params: VerifyEmailParams,\n result: VerificationResult,\n log: Logger,\n collector: TranscriptCollector\n): Promise<void> {\n let mxRecords: string[];\n try {\n mxRecords = await collector.record(\n 'mx-lookup',\n () => resolveMxRecords({ domain, cache: params.cache, logger: log }),\n (records) => ({ domain, records, count: records.length })\n );\n } catch (error) {\n log('[verifyEmail] MX lookup failed', error);\n result.validMx = false;\n result.mxRecords = null;\n result.metadata.error = VerificationErrorCode.noMxRecords;\n return;\n }\n\n result.mxRecords = mxRecords;\n result.validMx = mxRecords.length > 0;\n if (!result.validMx) {\n result.metadata.error = VerificationErrorCode.noMxRecords;\n return;\n }\n\n if (!(params.verifySmtp ?? false)) return;\n\n await runSmtp(local, domain, mxRecords, params, result, log, collector);\n}\n\nasync function runSmtp(\n local: string,\n domain: string,\n mxRecords: string[],\n params: VerifyEmailParams,\n result: VerificationResult,\n log: Logger,\n collector: TranscriptCollector\n): Promise<void> {\n const cacheKey = `${params.emailAddress}:smtp`;\n const smtpCache = getCacheStore<SmtpVerificationResult>(params.cache, 'smtp');\n const cached = await smtpCache.get(cacheKey);\n\n if (cached) {\n applySmtpResult(result, cached);\n result.metadata.cached = true;\n log(`[verifyEmail] SMTP cache hit: ${result.validSmtp} for ${params.emailAddress}`);\n collector.push({\n kind: 'smtp-probe',\n startedAt: Date.now(),\n durationMs: 0,\n ok: true,\n details: {\n cacheHit: true,\n verdict: smtpVerdictFor(result.validSmtp),\n canConnectSmtp: cached.canConnectSmtp,\n },\n });\n } else {\n await collector.record(\n 'smtp-probe',\n async () => {\n const probe = await verifyMailboxSMTP({\n local,\n domain,\n mxRecords,\n options: {\n cache: params.cache,\n ports: resolveSmtpPorts(params.smtpPort, mxRecords[0]),\n perAttemptTimeoutMs: params.smtpPerAttemptTimeoutMs ?? 4000,\n totalDeadlineMs: params.smtpTotalDeadlineMs,\n maxConsecutiveFailures: params.smtpMaxConsecutiveFailures,\n maxMxHosts: params.smtpMaxMxHosts,\n retry: params.smtpRetry,\n debug: params.debug ?? false,\n // Forward transcript capture so the SMTP step's details include\n // the full per-port transcript when the caller asked for it.\n captureTranscript: params.captureTranscript ?? false,\n // Forward the high-level envelope strategy and HELO override so\n // callers can control the spam-fingerprint of the probe without\n // dropping down to `verifyMailboxSMTP` directly.\n ...(params.smtpSender !== undefined && { sender: params.smtpSender }),\n ...(params.smtpHeloHostname !== undefined && { heloHostname: params.smtpHeloHostname }),\n },\n });\n await smtpCache.set(cacheKey, probe.smtpResult);\n applySmtpResult(result, probe.smtpResult);\n result.metadata.cached = probe.cached;\n return probe;\n },\n ({ smtpResult, port, cached: probedFromCache }) => ({\n cacheHit: false,\n port,\n cached: probedFromCache,\n verdict: smtpVerdictFor(result.validSmtp),\n canConnectSmtp: smtpResult.canConnectSmtp,\n error: smtpResult.error ?? null,\n // Only present if captureTranscript was set on params.\n transcript: smtpResult.transcript ?? null,\n commands: smtpResult.commands ?? null,\n })\n );\n log(`[verifyEmail] SMTP probed: ${result.validSmtp} for ${params.emailAddress}`);\n }\n\n if (result.validSmtp === false) result.metadata.error = VerificationErrorCode.mailboxNotFound;\n else if (result.validSmtp === null) result.metadata.error = VerificationErrorCode.smtpConnectionFailed;\n}\n\nfunction smtpVerdictFor(validSmtp: boolean | null | undefined): 'deliverable' | 'undeliverable' | 'indeterminate' {\n if (validSmtp === true) return 'deliverable';\n if (validSmtp === false) return 'undeliverable';\n return 'indeterminate';\n}\n","/**\n * Output formatters for the CLI. The runner picks one based on `--format`.\n *\n * pretty — colored, human-friendly summary + transcript table (default)\n * text — plain ASCII single-line verdict + KV pairs (for piping)\n * json — full `VerificationResult` as a single JSON line (for tooling)\n */\nimport type { VerificationResult, VerificationStep } from '../types';\n\n/** Tiny ANSI color helpers — no chalk dependency. Disabled when stdout isn't a TTY. */\nfunction colorize(): {\n green: (s: string) => string;\n red: (s: string) => string;\n yellow: (s: string) => string;\n dim: (s: string) => string;\n bold: (s: string) => string;\n} {\n const enabled = process.stdout.isTTY && process.env.NO_COLOR !== '1';\n const wrap = (open: string, close: string) => (s: string) => (enabled ? `\\x1b[${open}m${s}\\x1b[${close}m` : s);\n return {\n green: wrap('32', '39'),\n red: wrap('31', '39'),\n yellow: wrap('33', '39'),\n dim: wrap('2', '22'),\n bold: wrap('1', '22'),\n };\n}\n\n/** Single-line verdict, colored if the terminal supports it. */\nexport function verdictLine(result: VerificationResult): string {\n const c = colorize();\n if (result.validFormat === false) return c.red(`✗ INVALID FORMAT ${result.email}`);\n if (result.validMx === false) return c.red(`✗ NO MX RECORDS ${result.email}`);\n if (result.validSmtp === true) return c.green(`✓ DELIVERABLE ${result.email}`);\n if (result.validSmtp === false) return c.red(`✗ UNDELIVERABLE ${result.email}`);\n // `canConnectSmtp` is the reliable signal for \"did we actually probe?\":\n // undefined → SMTP step skipped; false → probed and couldn't connect.\n const smtpProbed = result.canConnectSmtp !== undefined;\n if (smtpProbed && result.validSmtp === null) return c.yellow(`? INDETERMINATE ${result.email}`);\n return c.green(`✓ FORMAT/MX OK ${result.email} ${c.dim('(SMTP not probed)')}`);\n}\n\nexport function formatJson(result: VerificationResult): string {\n return JSON.stringify(result);\n}\n\nexport function formatText(result: VerificationResult): string {\n const lines: string[] = [];\n lines.push(verdictLine(result));\n lines.push(` format=${result.validFormat} mx=${result.validMx} smtp=${result.validSmtp}`);\n lines.push(` isDisposable=${result.isDisposable} isFree=${result.isFree}`);\n if (result.mxRecords?.length) lines.push(` mxRecords=${result.mxRecords.join(', ')}`);\n if (result.domainSuggestion) lines.push(` suggestion=${result.domainSuggestion.suggested}`);\n if (result.detectedName) {\n const { firstName, lastName, confidence } = result.detectedName;\n lines.push(` detectedName=${firstName ?? '_'} ${lastName ?? '_'} (conf=${confidence.toFixed(2)})`);\n }\n if (result.metadata.error) lines.push(` error=${result.metadata.error}`);\n lines.push(` time=${result.metadata.verificationTime}ms cached=${result.metadata.cached}`);\n return lines.join('\\n');\n}\n\nexport function formatPretty(result: VerificationResult): string {\n const c = colorize();\n const lines: string[] = [];\n lines.push(verdictLine(result));\n lines.push('');\n\n // Summary block.\n lines.push(c.bold('Summary'));\n lines.push(` ${c.dim('format:')} ${formatBool(result.validFormat)}`);\n if (result.validMx !== null)\n lines.push(\n ` ${c.dim('MX records:')} ${formatBool(result.validMx)}${result.mxRecords ? ` ${c.dim(result.mxRecords.join(', '))}` : ''}`\n );\n if (result.validSmtp !== null) lines.push(` ${c.dim('SMTP:')} ${formatBool(result.validSmtp)}`);\n lines.push(\n ` ${c.dim('disposable:')} ${formatBool(!result.isDisposable)} ${c.dim(result.isDisposable ? '(domain on disposable list)' : '')}`\n );\n lines.push(\n ` ${c.dim('free provider:')} ${formatBool(!result.isFree)} ${c.dim(result.isFree ? '(domain on free list)' : '')}`\n );\n if (result.domainSuggestion) {\n lines.push(\n ` ${c.dim('suggestion:')} ${c.yellow(result.domainSuggestion.suggested)} ${c.dim(`(conf=${result.domainSuggestion.confidence.toFixed(2)})`)}`\n );\n }\n if (result.detectedName) {\n const { firstName, lastName, confidence } = result.detectedName;\n lines.push(\n ` ${c.dim('detected name:')} ${[firstName, lastName].filter(Boolean).join(' ')} ${c.dim(`(conf=${confidence.toFixed(2)})`)}`\n );\n }\n if (result.domainAge) {\n lines.push(\n ` ${c.dim('domain age:')} ${result.domainAge.ageInDays} days ${c.dim(`(${result.domainAge.ageInYears.toFixed(1)} years)`)}`\n );\n }\n if (result.domainRegistration) {\n const r = result.domainRegistration;\n lines.push(\n ` ${c.dim('registration:')} ${r.isRegistered ? c.green('registered') : c.red('available')}${r.isExpired ? ` ${c.red('(expired)')}` : ''}${r.isLocked ? ` ${c.dim('(locked)')}` : ''}`\n );\n }\n if (result.metadata.error) lines.push(` ${c.dim('error:')} ${c.red(result.metadata.error)}`);\n lines.push(\n ` ${c.dim('elapsed:')} ${result.metadata.verificationTime} ms${result.metadata.cached ? ` ${c.dim('(cached)')}` : ''}`\n );\n\n // Transcript block (if captured).\n if (result.transcript && result.transcript.length > 0) {\n lines.push('');\n lines.push(c.bold('Transcript'));\n for (const step of result.transcript) {\n lines.push(` ${formatStep(step, c)}`);\n }\n }\n\n return lines.join('\\n');\n}\n\nfunction formatBool(value: boolean | null): string {\n const c = colorize();\n if (value === true) return c.green('✓');\n if (value === false) return c.red('✗');\n return c.dim('—');\n}\n\nfunction formatStep(step: VerificationStep, c: ReturnType<typeof colorize>): string {\n const okMark = step.ok ? c.green('✓') : c.red('✗');\n const time = `${step.durationMs}ms`.padStart(6);\n const detail = formatStepDetail(step);\n return `${okMark} ${c.dim(time)} ${c.bold(step.kind.padEnd(20))} ${detail}`;\n}\n\nfunction formatStepDetail(step: VerificationStep): string {\n const d = step.details;\n switch (step.kind) {\n case 'syntax':\n return `ok=${String(d.ok)}`;\n case 'domain-validation':\n return `domain=${String(d.domain)} valid=${String(d.valid)}`;\n case 'name-detection':\n return d.detected ? `detected ${JSON.stringify(d.detected)}` : 'no name detected';\n case 'domain-suggestion':\n return d.suggestion ? `→ ${JSON.stringify(d.suggestion)}` : 'no suggestion';\n case 'disposable':\n return `domain=${String(d.domain)} isDisposable=${String(d.isDisposable)}`;\n case 'free':\n return `domain=${String(d.domain)} isFree=${String(d.isFree)}`;\n case 'mx-lookup':\n return `domain=${String(d.domain)} count=${String(d.count)}`;\n case 'smtp-probe':\n return d.cacheHit\n ? `cache hit verdict=${String(d.verdict)}`\n : `port=${String(d.port)} verdict=${String(d.verdict)}${d.error ? ` error=${String(d.error)}` : ''}`;\n case 'whois-age':\n return d.found ? `found created=${String(d.creationDate)} ageDays=${String(d.ageInDays)}` : 'not found';\n case 'whois-registration':\n return d.found\n ? `registered=${String(d.isRegistered)} expired=${String(d.isExpired)} locked=${String(d.isLocked)}`\n : 'not found';\n }\n}\n","/**\n * CLI runner — turns ParsedArgs into a verifyEmail invocation, formats the\n * output, and optionally writes the structured result to a log file.\n *\n * Returns the process exit code:\n * 0 — deliverable / format-and-MX OK / no SMTP probe asked for\n * 1 — undeliverable / no MX records / invalid format / indeterminate\n * 2 — bad CLI arguments (handled in `index.ts` before reaching here)\n */\nimport { mkdirSync, writeFileSync } from 'node:fs';\nimport { resolve } from 'node:path';\nimport { verifyEmail } from '../index';\nimport type { VerificationResult } from '../types';\nimport { formatJson, formatPretty, formatText, verdictLine } from './format';\nimport type { ParsedArgs } from './parse-args';\n\nexport interface CliRunDeps {\n /** Allow tests to inject a custom verifier — defaults to the real one. */\n verify?: typeof verifyEmail;\n /** Write a string to the given path. Defaults to fs.writeFileSync. */\n writeFile?: (path: string, contents: string) => void;\n /** Ensure a directory exists. Defaults to fs.mkdirSync(recursive). */\n ensureDir?: (path: string) => void;\n /** stdout / stderr writers — tests inject in-memory buffers. */\n stdout?: (line: string) => void;\n stderr?: (line: string) => void;\n /** Used to build the log filename — tests pin it for determinism. */\n now?: () => Date;\n}\n\n/** Build the timestamped log filename for an email + run time. */\nexport function logFileNameFor(email: string, when: Date): string {\n const safeEmail = email.replace(/[^a-zA-Z0-9._-]+/g, '_');\n const stamp =\n `${when.getUTCFullYear()}-${pad(when.getUTCMonth() + 1)}-${pad(when.getUTCDate())}` +\n `T${pad(when.getUTCHours())}${pad(when.getUTCMinutes())}${pad(when.getUTCSeconds())}Z`;\n return `email-validate-${stamp}-${safeEmail}.json`;\n}\n\nfunction pad(n: number): string {\n return n < 10 ? `0${n}` : String(n);\n}\n\nexport async function run(args: ParsedArgs, deps: CliRunDeps = {}): Promise<number> {\n const verify = deps.verify ?? verifyEmail;\n const stdout = deps.stdout ?? ((line) => process.stdout.write(`${line}\\n`));\n const stderr = deps.stderr ?? ((line) => process.stderr.write(`${line}\\n`));\n const writeFile = deps.writeFile ?? ((path, contents) => writeFileSync(path, contents, 'utf8'));\n const ensureDir = deps.ensureDir ?? ((path) => mkdirSync(path, { recursive: true }));\n const now = deps.now ?? (() => new Date());\n\n const result = await verify({\n emailAddress: args.email,\n verifyMx: args.verifyMx,\n verifySmtp: args.verifySmtp,\n smtpPerAttemptTimeoutMs: args.timeoutMs ?? 5000,\n debug: args.debug,\n smtpPort: args.smtpPort,\n checkDisposable: args.checkDisposable,\n checkFree: args.checkFree,\n detectName: args.detectName,\n suggestDomain: args.suggestDomain,\n checkDomainAge: args.checkDomainAge,\n checkDomainRegistration: args.checkDomainRegistration,\n whoisTimeoutMs: args.whoisTimeoutMs ?? 5000,\n captureTranscript: args.captureTranscript,\n });\n\n // Stdout output.\n if (args.quiet) {\n stdout(verdictLine(result));\n } else {\n switch (args.format) {\n case 'json':\n stdout(formatJson(result));\n break;\n case 'text':\n stdout(formatText(result));\n break;\n case 'pretty':\n stdout(formatPretty(result));\n break;\n }\n }\n\n // Optional file log.\n if (args.logDir) {\n try {\n const dir = resolve(args.logDir);\n ensureDir(dir);\n const path = resolve(dir, logFileNameFor(args.email, now()));\n writeFile(path, JSON.stringify(result, null, 2));\n if (!args.quiet) stderr(`Log written: ${path}`);\n } catch (error) {\n stderr(`Warning: failed to write log file: ${error instanceof Error ? error.message : String(error)}`);\n }\n }\n\n return exitCodeFor(result);\n}\n\nexport function exitCodeFor(result: VerificationResult): number {\n if (!result.validFormat) return 1;\n if (result.validMx === false) return 1;\n if (result.validSmtp === false) return 1;\n // `canConnectSmtp` is the reliable \"did we actually probe?\" signal:\n // undefined → SMTP not requested → exit 0 if format/MX OK\n // false → probed but couldn't connect → exit 1 (indeterminate)\n // true → probed and connected → validSmtp drives the verdict above\n const smtpProbed = result.canConnectSmtp !== undefined;\n if (smtpProbed && result.validSmtp === null) return 1;\n return 0;\n}\n","/**\n * `email-validate` CLI entry point.\n *\n * Wired into `package.json#bin` so `bun add -g @emailcheck/email-validator-js`\n * (or the npm equivalent) installs an `email-validate` command.\n *\n * Programmatic users can also import these helpers directly:\n * import { parseArgs, run } from '@emailcheck/email-validator-js/cli';\n */\nimport { helpText, parseArgs } from './parse-args';\nimport { run } from './run';\n\nexport type { CliArgError, ParsedArgs, ParsedHelp, ParsedVersion, ParseResult } from './parse-args';\nexport { helpText, parseArgs } from './parse-args';\nexport type { CliRunDeps } from './run';\nexport { exitCodeFor, logFileNameFor, run } from './run';\n\nexport async function main(argv: readonly string[] = process.argv.slice(2)): Promise<number> {\n const parsed = parseArgs(argv);\n\n if (parsed.kind === 'help') {\n process.stdout.write(`${helpText()}\\n`);\n return 0;\n }\n if (parsed.kind === 'version') {\n // Read from the bundled package.json — the build copies it next to the bin.\n // For unbundled (Bun-direct) runs, fall back to a placeholder.\n try {\n const pkg = require('../../package.json') as { version: string };\n process.stdout.write(`${pkg.version}\\n`);\n } catch {\n process.stdout.write('unknown\\n');\n }\n return 0;\n }\n if (parsed.kind === 'error') {\n for (const msg of parsed.messages) process.stderr.write(`${msg}\\n`);\n process.stderr.write(`\\nRun with --help for usage.\\n`);\n return parsed.exitCode;\n }\n\n return run(parsed);\n}\n\n// When invoked directly (not imported), run main() and propagate the exit code.\n// `import.meta.main` works under Bun; for Node we check require.main.\nconst isDirectInvocation =\n // bun\n (typeof import.meta !== 'undefined' && (import.meta as { main?: boolean }).main === true) ||\n // node CommonJS bundle\n (typeof require !== 'undefined' && require.main === module);\n\nif (isDirectInvocation) {\n main()\n .then((code) => process.exit(code))\n .catch((error) => {\n process.stderr.write(\n `Unexpected error: ${error instanceof Error ? (error.stack ?? error.message) : String(error)}\\n`\n );\n process.exit(1);\n });\n}\n"],"names":["lru","VerificationErrorCode","SMTPStep","stringSimilarity","isValid","dnsPromises","randomBytes","net","metrics","smtpResult","tls","parse","writeFileSync","mkdirSync","resolve"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwDA,MAAM,SAAA,GAAY,CAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA,CAAA;AA8DlB,MAAM,UAAA,uBAAiB,GAAA,CAAI;AAAA,EACzB,IAAA;AAAA,EACA,MAAA;AAAA,EACA,YAAA;AAAA,EACA,MAAA;AAAA,EACA,gBAAA;AAAA,EACA,aAAA;AAAA,EACA,WAAA;AAAA,EACA,oBAAA;AAAA,EACA,YAAA;AAAA,EACA,UAAA;AAAA,EACA,OAAA;AAAA,EACA;AACF,CAAC,CAAA;AAED,MAAM,WAAA,mBAAc,IAAI,GAAA,CAAI,CAAC,MAAA,EAAQ,OAAA,EAAS,UAAA,EAAY,SAAA,EAAW,eAAA,EAAiB,QAAA,EAAU,SAAS,CAAC,CAAA;AAG1G,SAAS,QAAQ,IAAA,EAAmD;AAClE,EAAA,IAAI,IAAA,CAAK,UAAA,CAAW,KAAK,CAAA,EAAG,OAAO,EAAE,IAAA,EAAM,IAAA,CAAK,KAAA,CAAM,CAAC,CAAA,EAAG,QAAA,EAAU,KAAA,EAAM;AAC1E,EAAA,OAAO,EAAE,IAAA,EAAM,IAAA,EAAM,QAAA,EAAU,IAAA,EAAK;AACtC;AAEA,SAAS,UAAA,CAAW,KAAA,EAAe,IAAA,EAAc,MAAA,EAAsC;AACrF,EAAA,MAAM,CAAA,GAAI,OAAO,KAAK,CAAA;AACtB,EAAA,IAAI,CAAC,MAAA,CAAO,QAAA,CAAS,CAAC,CAAA,IAAK,CAAC,MAAA,CAAO,SAAA,CAAU,CAAC,CAAA,IAAK,CAAA,IAAK,CAAA,EAAG;AACzD,IAAA,MAAA,CAAO,IAAA,CAAK,CAAA,QAAA,EAAW,IAAI,CAAA,GAAA,EAAM,KAAK,CAAA,+BAAA,CAAiC,CAAA;AACvE,IAAA,OAAO,MAAA;AAAA,EACT;AACA,EAAA,OAAO,CAAA;AACT;AAEA,SAAS,aAAA,CAAc,OAAe,MAAA,EAAwC;AAC5E,EAAA,MAAM,KAAA,GAAQ,KAAA,CACX,KAAA,CAAM,GAAG,EACT,GAAA,CAAI,CAAC,CAAA,KAAM,CAAA,CAAE,IAAA,EAAM,CAAA,CACnB,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,MAAA,GAAS,CAAC,CAAA,CAC1B,GAAA,CAAI,CAAC,CAAA,KAAM,WAAW,CAAA,EAAG,MAAA,EAAQ,MAAM,CAAC,CAAA,CACxC,MAAA,CAAO,CAAC,CAAA,KAAmB,MAAM,MAAS,CAAA;AAC7C,EAAA,IAAI,KAAA,CAAM,WAAW,CAAA,EAAG;AACtB,IAAA,MAAA,CAAO,IAAA,CAAK,CAAA,+CAAA,EAAkD,KAAK,CAAA,EAAA,CAAI,CAAA;AACvE,IAAA,OAAO,MAAA;AAAA,EACT;AACA,EAAA,OAAO,KAAA;AACT;AAEO,SAAS,UAAU,IAAA,EAAsC;AAC9D,EAAA,MAAM,SAAmB,EAAC;AAC1B,EAAA,MAAM,aAAuB,EAAC;AAK9B,EAAA,MAAM,MAAA,GAAqB;AAAA,IACzB,KAAA,EAAO,EAAA;AAAA,IACP,QAAA,EAAU,IAAA;AAAA,IACV,UAAA,EAAY,IAAA;AAAA,IACZ,eAAA,EAAiB,IAAA;AAAA,IACjB,SAAA,EAAW,IAAA;AAAA,IACX,aAAA,EAAe,IAAA;AAAA,IACf,UAAA,EAAY,IAAA;AAAA,IACZ,cAAA,EAAgB,KAAA;AAAA,IAChB,uBAAA,EAAyB,KAAA;AAAA,IACzB,MAAA,EAAQ,QAAA;AAAA,IACR,KAAA,EAAO,KAAA;AAAA,IACP,KAAA,EAAO,KAAA;AAAA,IACP,iBAAA,EAAmB,IAAA;AAAA,IACnB,MAAA,EAAQ;AAAA,GACV;AACA,EAAA,IAAI,OAAA,GAAU,IAAA;AAEd,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,IAAA,CAAK,QAAQ,CAAA,EAAA,EAAK;AACpC,IAAA,MAAM,KAAA,GAAQ,KAAK,CAAC,CAAA;AACpB,IAAA,IAAI,UAAU,MAAA,EAAW;AAGzB,IAAA,IAAI,CAAC,KAAA,CAAM,UAAA,CAAW,GAAG,CAAA,EAAG;AAC1B,MAAA,UAAA,CAAW,KAAK,KAAK,CAAA;AACrB,MAAA;AAAA,IACF;AAEA,IAAA,IAAI,UAAU,IAAA,IAAQ,KAAA,KAAU,UAAU,OAAO,EAAE,MAAM,MAAA,EAAO;AAChE,IAAA,IAAI,UAAU,IAAA,IAAQ,KAAA,KAAU,aAAa,OAAO,EAAE,MAAM,SAAA,EAAU;AAEtE,IAAA,IAAI,CAAC,KAAA,CAAM,UAAA,CAAW,IAAI,CAAA,EAAG;AAC3B,MAAA,MAAA,CAAO,IAAA,CAAK,CAAA,qBAAA,EAAwB,KAAK,CAAA,CAAA,CAAG,CAAA;AAC5C,MAAA;AAAA,IACF;AAGA,IAAA,MAAM,KAAA,GAAQ,KAAA,CAAM,OAAA,CAAQ,GAAG,CAAA;AAC/B,IAAA,MAAM,OAAA,GAAU,KAAA,KAAU,EAAA,GAAK,KAAA,CAAM,KAAA,CAAM,CAAC,CAAA,GAAI,KAAA,CAAM,KAAA,CAAM,CAAA,EAAG,KAAK,CAAA;AACpE,IAAA,MAAM,cAAc,KAAA,KAAU,EAAA,GAAK,SAAY,KAAA,CAAM,KAAA,CAAM,QAAQ,CAAC,CAAA;AAEpE,IAAA,IAAI,UAAA,CAAW,GAAA,CAAI,OAAO,CAAA,IAAM,QAAQ,UAAA,CAAW,KAAK,CAAA,IAAK,UAAA,CAAW,GAAA,CAAI,OAAA,CAAQ,KAAA,CAAM,CAAC,CAAC,CAAA,EAAI;AAC9F,MAAA,MAAM,EAAE,IAAA,EAAM,QAAA,EAAS,GAAI,QAAQ,OAAO,CAAA;AAC1C,MAAA,QAAQ,IAAA;AAAM,QACZ,KAAK,IAAA;AACH,UAAA,MAAA,CAAO,QAAA,GAAW,QAAA;AAClB,UAAA;AAAA,QACF,KAAK,MAAA;AACH,UAAA,MAAA,CAAO,UAAA,GAAa,QAAA;AACpB,UAAA;AAAA,QACF,KAAK,YAAA;AACH,UAAA,MAAA,CAAO,eAAA,GAAkB,QAAA;AACzB,UAAA;AAAA,QACF,KAAK,MAAA;AACH,UAAA,MAAA,CAAO,SAAA,GAAY,QAAA;AACnB,UAAA;AAAA,QACF,KAAK,gBAAA;AACH,UAAA,MAAA,CAAO,aAAA,GAAgB,QAAA;AACvB,UAAA;AAAA,QACF,KAAK,aAAA;AACH,UAAA,MAAA,CAAO,UAAA,GAAa,QAAA;AACpB,UAAA;AAAA,QACF,KAAK,WAAA;AACH,UAAA,MAAA,CAAO,cAAA,GAAiB,QAAA;AACxB,UAAA;AAAA,QACF,KAAK,oBAAA;AACH,UAAA,MAAA,CAAO,uBAAA,GAA0B,QAAA;AACjC,UAAA;AAAA,QACF,KAAK,YAAA;AACH,UAAA,MAAA,CAAO,iBAAA,GAAoB,QAAA;AAC3B,UAAA;AAAA,QACF,KAAK,UAAA;AACH,UAAA,OAAA,GAAU,QAAA;AACV,UAAA;AAAA,QACF,KAAK,OAAA;AACH,UAAA,MAAA,CAAO,KAAA,GAAQ,QAAA;AACf,UAAA;AAAA,QACF,KAAK,OAAA;AACH,UAAA,MAAA,CAAO,KAAA,GAAQ,QAAA;AACf,UAAA;AAAA;AAEJ,MAAA;AAAA,IACF;AAEA,IAAA,IAAI,WAAA,CAAY,GAAA,CAAI,OAAO,CAAA,EAAG;AAC5B,MAAA,MAAM,KAAA,GAAQ,WAAA,IAAe,IAAA,CAAK,EAAE,CAAC,CAAA;AACrC,MAAA,IAAI,UAAU,MAAA,EAAW;AACvB,QAAA,MAAA,CAAO,IAAA,CAAK,CAAA,OAAA,EAAU,OAAO,CAAA,iBAAA,CAAmB,CAAA;AAChD,QAAA;AAAA,MACF;AACA,MAAA,QAAQ,OAAA;AAAS,QACf,KAAK,MAAA,EAAQ;AACX,UAAA,MAAM,IAAA,GAAO,UAAA,CAAW,KAAA,EAAO,MAAA,EAAQ,MAAM,CAAA;AAC7C,UAAA,IAAI,IAAA,KAAS,MAAA,EAAW,MAAA,CAAO,QAAA,GAAW,IAAA;AAC1C,UAAA;AAAA,QACF;AAAA,QACA,KAAK,OAAA,EAAS;AACZ,UAAA,MAAM,KAAA,GAAQ,aAAA,CAAc,KAAA,EAAO,MAAM,CAAA;AACzC,UAAA,IAAI,KAAA,SAAc,KAAA,GAAQ,KAAA;AAC1B,UAAA;AAAA,QACF;AAAA,QACA,KAAK,UAAA;AACH,UAAA,MAAA,CAAO,QAAA,GAAW,KAAA;AAClB,UAAA;AAAA,QACF,KAAK,SAAA,EAAW;AACd,UAAA,MAAM,EAAA,GAAK,UAAA,CAAW,KAAA,EAAO,WAAA,EAAa,MAAM,CAAA;AAChD,UAAA,IAAI,EAAA,KAAO,MAAA,EAAW,MAAA,CAAO,SAAA,GAAY,EAAA;AACzC,UAAA;AAAA,QACF;AAAA,QACA,KAAK,eAAA,EAAiB;AACpB,UAAA,MAAM,EAAA,GAAK,UAAA,CAAW,KAAA,EAAO,iBAAA,EAAmB,MAAM,CAAA;AACtD,UAAA,IAAI,EAAA,KAAO,MAAA,EAAW,MAAA,CAAO,cAAA,GAAiB,EAAA;AAC9C,UAAA;AAAA,QACF;AAAA,QACA,KAAK,QAAA;AACH,UAAA,IAAI,KAAA,KAAU,MAAA,IAAU,KAAA,KAAU,MAAA,IAAU,UAAU,QAAA,EAAU;AAC9D,YAAA,MAAA,CAAO,IAAA,CAAK,CAAA,+CAAA,EAAkD,KAAK,CAAA,EAAA,CAAI,CAAA;AAAA,UACzE,CAAA,MAAO;AACL,YAAA,MAAA,CAAO,MAAA,GAAS,KAAA;AAAA,UAClB;AACA,UAAA;AAAA,QACF,KAAK,SAAA;AACH,UAAA,MAAA,CAAO,MAAA,GAAS,KAAA;AAChB,UAAA;AAAA;AAEJ,MAAA;AAAA,IACF;AAEA,IAAA,MAAA,CAAO,IAAA,CAAK,CAAA,eAAA,EAAkB,KAAK,CAAA,CAAA,CAAG,CAAA;AAAA,EACxC;AAEA,EAAA,IAAI,CAAC,OAAA,EAAS,MAAA,CAAO,MAAA,GAAS,IAAA;AAE9B,EAAA,IAAI,UAAA,CAAW,MAAA,KAAW,CAAA,EAAG,MAAA,CAAO,KAAK,oCAAoC,CAAA;AAC7E,EAAA,IAAI,UAAA,CAAW,MAAA,GAAS,CAAA,EAAG,MAAA,CAAO,IAAA,CAAK,CAAA,wBAAA,EAA2B,UAAA,CAAW,MAAM,CAAA,EAAA,EAAK,UAAA,CAAW,IAAA,CAAK,IAAI,CAAC,CAAA,CAAE,CAAA;AAE/G,EAAA,IAAI,MAAA,CAAO,SAAS,CAAA,EAAG;AACrB,IAAA,OAAO,EAAE,IAAA,EAAM,OAAA,EAAS,QAAA,EAAU,MAAA,EAAQ,UAAU,CAAA,EAAE;AAAA,EACxD;AAEA,EAAA,MAAM,CAAC,KAAK,CAAA,GAAI,UAAA;AAChB,EAAA,IAAI,CAAC,KAAA,EAAO,OAAO,EAAE,IAAA,EAAM,OAAA,EAAS,QAAA,EAAU,CAAC,oCAAoC,CAAA,EAAG,QAAA,EAAU,CAAA,EAAE;AAClG,EAAA,MAAA,CAAO,KAAA,GAAQ,KAAA;AACf,EAAA,OAAO,EAAE,IAAA,EAAM,MAAA,EAAQ,GAAG,MAAA,EAAO;AACnC;AAEO,SAAS,QAAA,GAAmB;AACjC,EAAA,OAAO,SAAA;AACT;;ACzTO,MAAM,UAAA,CAAuC;AAAA,EAGlD,WAAA,CAAY,OAAA,GAAkB,GAAA,EAAM,KAAA,GAAgB,IAAA,EAAS;AAC3D,IAAA,IAAA,CAAK,GAAA,GAAMA,WAAA,CAAO,OAAA,EAAS,KAAK,CAAA;AAAA,EAClC;AAAA,EAEA,IAAI,GAAA,EAAmC;AACrC,IAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,GAAA,CAAI,GAAA,CAAI,GAAG,CAAA;AAE9B,IAAA,OAAO,KAAA,KAAU,SAAY,IAAA,GAAO,KAAA;AAAA,EACtC;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,GAAA,CAAI,GAAA,EAAa,KAAA,EAAU,MAAA,EAAgC;AAC/D,IAAA,IAAA,CAAK,GAAA,CAAI,GAAA,CAAI,GAAA,EAAK,KAAK,CAAA;AAAA,EACzB;AAAA,EAEA,MAAM,OAAO,GAAA,EAA+B;AAC1C,IAAA,IAAA,CAAK,GAAA,CAAI,OAAO,GAAG,CAAA;AACnB,IAAA,OAAO,IAAA;AAAA,EACT;AAAA,EAEA,MAAM,IAAI,GAAA,EAA+B;AACvC,IAAA,OAAO,IAAA,CAAK,GAAA,CAAI,GAAA,CAAI,GAAG,CAAA;AAAA,EACzB;AAAA,EAEA,MAAM,KAAA,GAAuB;AAC3B,IAAA,IAAA,CAAK,IAAI,KAAA,EAAM;AAAA,EACjB;AAAA,EAEA,IAAA,GAAe;AACb,IAAA,OAAO,KAAK,GAAA,CAAI,IAAA;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAA,GAAiB;AACf,IAAA,OAAO,IAAA,CAAK,GAAA;AAAA,EACd;AACF;;AC9CO,IAAK,qBAAA,qBAAAC,sBAAAA,KAAL;AACL,EAAAA,uBAAA,eAAA,CAAA,GAAgB,gBAAA;AAChB,EAAAA,uBAAA,eAAA,CAAA,GAAgB,gBAAA;AAChB,EAAAA,uBAAA,aAAA,CAAA,GAAc,eAAA;AACd,EAAAA,uBAAA,sBAAA,CAAA,GAAuB,wBAAA;AACvB,EAAAA,uBAAA,aAAA,CAAA,GAAc,cAAA;AACd,EAAAA,uBAAA,iBAAA,CAAA,GAAkB,mBAAA;AAClB,EAAAA,uBAAA,cAAA,CAAA,GAAe,eAAA;AACf,EAAAA,uBAAA,iBAAA,CAAA,GAAkB,kBAAA;AARR,EAAA,OAAAA,sBAAAA;AAAA,CAAA,EAAA,qBAAA,IAAA,EAAA,CAAA;AAmZL,IAAK,QAAA,qBAAAC,SAAAA,KAAL;AACL,EAAAA,UAAA,UAAA,CAAA,GAAW,UAAA;AACX,EAAAA,UAAA,MAAA,CAAA,GAAO,MAAA;AACP,EAAAA,UAAA,MAAA,CAAA,GAAO,MAAA;AACP,EAAAA,UAAA,UAAA,CAAA,GAAW,UAAA;AACX,EAAAA,UAAA,UAAA,CAAA,GAAW,WAAA;AACX,EAAAA,UAAA,QAAA,CAAA,GAAS,SAAA;AANC,EAAA,OAAAA,SAAAA;AAAA,CAAA,EAAA,QAAA,IAAA,EAAA,CAAA;;AC9YL,MAAM,qBAAA,GAAwB;AAAA,EACnC,GAAA,EAAK;AAAA,IACH,EAAA,EAAI,IAAA;AAAA,IACJ,UAAA,EAAY,KAAA;AAAA,IACZ,IAAA,EAAM,KAAA;AAAA,IACN,WAAA,EAAa,KAAA;AAAA,IACb,IAAA,EAAM,IAAA;AAAA,IACN,QAAA,EAAU,KAAA;AAAA,IACV,gBAAA,EAAkB,KAAA;AAAA,IAClB,KAAA,EAAO;AAAA,GACT;AAAA,EACA,OAAA,EAAS;AAAA,IACP,EAAA,EAAI,GAAA;AAAA,IACJ,UAAA,EAAY,GAAA;AAAA,IACZ,IAAA,EAAM,GAAA;AAAA,IACN,WAAA,EAAa,GAAA;AAAA,IACb,IAAA,EAAM,GAAA;AAAA,IACN,QAAA,EAAU,GAAA;AAAA,IACV,gBAAA,EAAkB,GAAA;AAAA,IAClB,KAAA,EAAO;AAAA;AAEX,CAAA;AAKA,IAAI,oBAAA,GAAqC,IAAA;AAMlC,SAAS,eAAA,GAAyB;AACvC,EAAA,IAAI,CAAC,oBAAA,EAAsB;AACzB,IAAA,oBAAA,GAAuB;AAAA,MACrB,EAAA,EAAI,IAAI,UAAA,CAAqB,qBAAA,CAAsB,QAAQ,EAAA,EAAI,qBAAA,CAAsB,IAAI,EAAE,CAAA;AAAA,MAC3F,YAAY,IAAI,UAAA;AAAA,QACd,sBAAsB,OAAA,CAAQ,UAAA;AAAA,QAC9B,sBAAsB,GAAA,CAAI;AAAA,OAC5B;AAAA,MACA,IAAA,EAAM,IAAI,UAAA,CAA4B,qBAAA,CAAsB,QAAQ,IAAA,EAAM,qBAAA,CAAsB,IAAI,IAAI,CAAA;AAAA,MACxG,aAAa,IAAI,UAAA;AAAA,QACf,sBAAsB,OAAA,CAAQ,WAAA;AAAA,QAC9B,sBAAsB,GAAA,CAAI;AAAA,OAC5B;AAAA,MACA,IAAA,EAAM,IAAI,UAAA,CAAmC,qBAAA,CAAsB,QAAQ,IAAA,EAAM,qBAAA,CAAsB,IAAI,IAAI,CAAA;AAAA,MAC/G,QAAA,EAAU,IAAI,UAAA,CAAmB,qBAAA,CAAsB,QAAQ,QAAA,EAAU,qBAAA,CAAsB,IAAI,QAAQ,CAAA;AAAA,MAC3G,kBAAkB,IAAI,UAAA;AAAA,QACpB,sBAAsB,OAAA,CAAQ,gBAAA;AAAA,QAC9B,sBAAsB,GAAA,CAAI;AAAA,OAC5B;AAAA,MACA,KAAA,EAAO,IAAI,UAAA,CAA8B,qBAAA,CAAsB,QAAQ,KAAA,EAAO,qBAAA,CAAsB,IAAI,KAAK;AAAA,KAC/G;AAAA,EACF;AACA,EAAA,OAAO,oBAAA;AACT;AAMO,SAAS,aAAA,CAAiB,OAAiC,GAAA,EAAiC;AACjG,EAAA,OAAQ,KAAA,GAAQ,GAAG,CAAA,IAAK,eAAA,GAAkB,GAAG,CAAA;AAC/C;;;;;;AC3DO,MAAM,kBAAA,GAAwC,sBAAA;AAMrD,MAAM,aAAA,GAAgB,gBAAA;AAMtB,SAAS,uBAAuB,MAAA,EAAgB;AAC9C,EAAA,MAAM,SAAS,MAAA,CAAO,MAAA;AACtB,EAAA,IAAI,MAAA,IAAU,GAAG,OAAO,IAAA;AACxB,EAAA,IAAI,MAAA,IAAU,IAAI,OAAO,GAAA;AACzB,EAAA,OAAO,IAAA;AACT;AAOA,SAAS,cAAA,CAAe,QAAgB,UAAA,EAAwD;AAC9F,EAAA,MAAM,KAAA,GAAQ,OAAO,WAAA,EAAY;AAGjC,EAAA,IAAI,UAAA,CAAW,QAAA,CAAS,KAAK,CAAA,EAAG,OAAO,IAAA;AAGvC,EAAA,KAAA,MAAW,CAAC,OAAA,EAAS,KAAK,KAAK,MAAA,CAAO,OAAA,CAAQ,aAAa,CAAA,EAAG;AAC5D,IAAA,IAAI,KAAA,CAAM,QAAA,CAAS,KAAK,CAAA,EAAG;AACzB,MAAA,OAAO,EAAE,QAAA,EAAU,MAAA,EAAQ,SAAA,EAAW,OAAA,EAAS,YAAY,IAAA,EAAK;AAAA,IAClE;AAAA,EACF;AAEA,EAAA,MAAM,SAAA,GAAY,uBAAuB,KAAK,CAAA;AAC9C,EAAA,IAAI,IAAA,GAAsD,IAAA;AAE1D,EAAA,KAAA,MAAW,aAAa,UAAA,EAAY;AAClC,IAAA,MAAM,UAAA,GAAaC,mCAAA,CAAiB,KAAA,EAAO,SAAA,CAAU,aAAa,CAAA;AAClE,IAAA,IAAI,cAAc,SAAA,KAAc,CAAC,IAAA,IAAQ,UAAA,GAAa,KAAK,UAAA,CAAA,EAAa;AACtE,MAAA,IAAA,GAAO,EAAE,MAAA,EAAQ,SAAA,EAAW,UAAA,EAAW;AAAA,IACzC;AAAA,EACF;AAGA,EAAA,IAAI,CAAC,IAAA,EAAM;AACT,IAAA,KAAA,MAAW,aAAa,UAAA,EAAY;AAClC,MAAA,IAAI,KAAK,GAAA,CAAI,KAAA,CAAM,SAAS,SAAA,CAAU,MAAM,IAAI,CAAA,EAAG;AACnD,MAAA,MAAM,UAAA,GAAaA,mCAAA,CAAiB,KAAA,EAAO,SAAA,CAAU,aAAa,CAAA;AAClE,MAAA,IAAI,cAAc,GAAA,KAAQ,CAAC,IAAA,IAAQ,UAAA,GAAa,KAAK,UAAA,CAAA,EAAa;AAChE,QAAA,IAAA,GAAO,EAAE,MAAA,EAAQ,SAAA,EAAW,UAAA,EAAW;AAAA,MACzC;AAAA,IACF;AAAA,EACF;AAEA,EAAA,IAAI,CAAC,MAAM,OAAO,IAAA;AAGlB,EAAA,IAAI,IAAA,CAAK,MAAA,CAAO,MAAA,CAAO,CAAC,CAAA,KAAM,KAAA,CAAM,MAAA,CAAO,CAAC,CAAA,IAAK,IAAA,CAAK,UAAA,GAAa,GAAA,EAAK,OAAO,IAAA;AAE/E,EAAA,OAAO,EAAE,UAAU,MAAA,EAAQ,SAAA,EAAW,KAAK,MAAA,EAAQ,UAAA,EAAY,KAAK,UAAA,EAAW;AACjF;AASA,eAAsB,kCAAA,CACpB,MAAA,EACA,aAAA,EACA,KAAA,EACkC;AAClC,EAAA,IAAI,CAAC,MAAA,IAAU,MAAA,CAAO,MAAA,GAAS,GAAG,OAAO,IAAA;AACzC,EAAA,MAAM,aAAa,aAAA,IAAiB,kBAAA;AACpC,EAAA,MAAM,WAAW,CAAA,EAAG,MAAA,CAAO,aAAa,CAAA,CAAA,EAAI,WAAW,MAAM,CAAA,CAAA;AAC7D,EAAA,MAAM,UAAA,GAAa,aAAA,CAAuC,KAAA,EAAO,kBAAkB,CAAA;AAEnF,EAAA,MAAM,MAAA,GAAS,MAAM,UAAA,CAAW,GAAA,CAAI,QAAQ,CAAA;AAC5C,EAAA,IAAI,MAAA,KAAW,IAAA,IAAQ,MAAA,KAAW,MAAA,EAAW,OAAO,MAAA;AAEpD,EAAA,MAAM,MAAA,GAAS,cAAA,CAAe,MAAA,EAAQ,UAAU,CAAA;AAChD,EAAA,MAAM,UAAA,CAAW,GAAA,CAAI,QAAA,EAAU,MAAM,CAAA;AACrC,EAAA,OAAO,MAAA;AACT;AAmBA,eAAsB,kBAAA,CACpB,KAAA,EACA,aAAA,EACA,KAAA,EACkC;AAClC,EAAA,IAAI,CAAC,KAAA,EAAO,QAAA,CAAS,GAAG,GAAG,OAAO,IAAA;AAClC,EAAA,MAAM,CAAC,SAAA,EAAW,MAAM,CAAA,GAAI,KAAA,CAAM,MAAM,GAAG,CAAA;AAC3C,EAAA,IAAI,CAAC,MAAA,IAAU,CAAC,SAAA,EAAW,OAAO,IAAA;AAElC,EAAA,MAAM,UAAA,GAAa,MAAM,kCAAA,CAAmC,MAAA,EAAQ,eAAe,KAAK,CAAA;AACxF,EAAA,IAAI,CAAC,YAAY,OAAO,IAAA;AAExB,EAAA,OAAO;AAAA,IACL,QAAA,EAAU,KAAA;AAAA,IACV,SAAA,EAAW,CAAA,EAAG,SAAS,CAAA,CAAA,EAAI,WAAW,SAAS,CAAA,CAAA;AAAA,IAC/C,YAAY,UAAA,CAAW;AAAA,GACzB;AACF;;ACjIA,eAAsB,kBAAA,CAAmB,eAAuB,KAAA,EAAwC;AACtG,EAAA,IAAI,CAAC,WAAW,WAAW,CAAA,GAAI,eAAe,KAAA,CAAM,GAAG,KAAK,EAAC;AAC7D,EAAA,IAAI,CAAC,WAAA,EAAa;AAChB,IAAA,WAAA,GAAc,SAAA;AAAA,EAChB;AACA,EAAA,IAAI,CAAC,WAAA,EAAa;AAChB,IAAA,OAAO,KAAA;AAAA,EACT;AAGA,EAAA,MAAM,UAAA,GAAa,aAAA,CAAiC,KAAA,EAAO,aAAa,CAAA;AACxE,EAAA,MAAM,MAAA,GAAS,MAAM,UAAA,CAAW,GAAA,CAAI,WAAW,CAAA;AAC/C,EAAA,IAAI,MAAA,KAAW,IAAA,IAAQ,MAAA,KAAW,MAAA,EAAW;AAC3C,IAAA,OAAO,MAAA,CAAO,OAAA;AAAA,EAChB;AAEA,EAAA,IAAI;AACF,IAAA,MAAM,aAAA,GAAgBC,WAAA,CAAQ,WAAW,CAAA,IAAK,KAAA;AAG9C,IAAA,MAAM,UAAA,GAAgC;AAAA,MACpC,OAAA,EAAS,aAAA;AAAA,MACT,KAAA,EAAO,KAAA;AAAA;AAAA,MACP,SAAA,EAAW,KAAK,GAAA;AAAI,KACtB;AAEA,IAAA,MAAM,UAAA,CAAW,GAAA,CAAI,WAAA,EAAa,UAAU,CAAA;AAC5C,IAAA,OAAO,aAAA;AAAA,EACT,SAAS,eAAA,EAAiB;AACxB,IAAA,MAAM,WAAA,GAAiC;AAAA,MACrC,OAAA,EAAS,KAAA;AAAA,MACT,KAAA,EAAO,KAAA;AAAA,MACP,SAAA,EAAW,KAAK,GAAA;AAAI,KACtB;AACA,IAAA,MAAM,UAAA,CAAW,GAAA,CAAI,WAAA,EAAa,WAAW,CAAA;AAC7C,IAAA,OAAO,KAAA;AAAA,EACT;AACF;AAWO,SAAS,aAAa,YAAA,EAAsB;AACjD,EAAA,IAAI,CAAC,YAAA,IAAgB,OAAO,YAAA,KAAiB,QAAA,EAAU;AACrD,IAAA,OAAO,KAAA;AAAA,EACT;AAIA,EAAA,MAAM,EAAA,GACJ,2IAAA;AAEF,EAAA,MAAM,UAAA,GAAa,aAAa,WAAA,EAAY;AAI5C,EAAA,IAAI,UAAA,CAAW,OAAA,CAAQ,IAAI,CAAA,KAAM,IAAI,OAAO,KAAA;AAC5C,EAAA,IAAI,UAAA,CAAW,OAAA,CAAQ,IAAI,CAAA,KAAM,IAAI,OAAO,KAAA;AAC5C,EAAA,IAAI,UAAA,CAAW,WAAW,GAAG,CAAA,IAAK,WAAW,QAAA,CAAS,GAAG,GAAG,OAAO,KAAA;AAEnE,EAAA,MAAM,KAAA,GAAQ,YAAA,CAAa,KAAA,CAAM,GAAG,CAAA;AACpC,EAAA,IAAI,KAAA,CAAM,MAAA,KAAW,CAAA,EAAG,OAAO,KAAA;AAE/B,EAAA,MAAM,CAAC,SAAA,EAAW,MAAM,CAAA,GAAI,KAAA;AAC5B,EAAA,IAAI,CAAC,SAAA,IAAa,CAAC,MAAA,EAAQ,OAAO,KAAA;AAClC,EAAA,IAAI,SAAA,CAAU,MAAA,GAAS,EAAA,EAAI,OAAO,KAAA;AAClC,EAAA,IAAI,MAAA,CAAO,MAAA,GAAS,GAAA,EAAK,OAAO,KAAA;AAEhC,EAAA,OAAO,EAAA,CAAG,KAAK,UAAU,CAAA;AAC3B;;;;AC/EA,MAAM,wBAAA,GAAwC,IAAI,GAAA,CAAI,mBAA+B,CAAA;AAOrF,eAAsB,kBAAkB,MAAA,EAAsD;AAC5F,EAAA,MAAM,EAAE,aAAA,EAAe,KAAA,EAAO,MAAA,EAAO,GAAI,MAAA;AACzC,EAAA,MAAM,GAAA,GAAM,WAAW,MAAM;AAAA,EAAC,CAAA,CAAA;AAE9B,EAAA,MAAM,KAAA,GAAQ,aAAA,CAAc,KAAA,CAAM,GAAG,CAAA;AACrC,EAAA,MAAM,WAAA,GAAc,MAAM,MAAA,GAAS,CAAA,GAAI,MAAM,CAAC,CAAA,GAAI,MAAM,CAAC,CAAA;AACzD,EAAA,IAAI,CAAC,aAAa,OAAO,KAAA;AAEzB,EAAA,MAAM,UAAA,GAAa,aAAA,CAAqC,KAAA,EAAO,YAAY,CAAA;AAC3E,EAAA,IAAI,MAAA;AACJ,EAAA,IAAI;AACF,IAAA,MAAA,GAAS,MAAM,UAAA,CAAW,GAAA,CAAI,WAAW,CAAA;AAAA,EAC3C,CAAA,CAAA,MAAQ;AACN,IAAA,MAAA,GAAS,IAAA;AAAA,EACX;AACA,EAAA,IAAI,MAAA,KAAW,IAAA,IAAQ,MAAA,KAAW,MAAA,EAAW;AAC3C,IAAA,GAAA,CAAI,CAAA,kCAAA,EAAqC,WAAW,CAAA,EAAA,EAAK,MAAA,CAAO,YAAY,CAAA,CAAE,CAAA;AAC9E,IAAA,OAAO,MAAA,CAAO,YAAA;AAAA,EAChB;AAEA,EAAA,MAAM,YAAA,GAAe,wBAAA,CAAyB,GAAA,CAAI,WAAW,CAAA;AAC7D,EAAA,MAAM,UAAA,GAAoC;AAAA,IACxC,YAAA;AAAA,IACA,MAAA,EAAQ,iCAAA;AAAA,IACR,QAAA,EAAU,eAAe,YAAA,GAAe,MAAA;AAAA,IACxC,SAAA,EAAW,KAAK,GAAA;AAAI,GACtB;AAEA,EAAA,IAAI;AACF,IAAA,MAAM,UAAA,CAAW,GAAA,CAAI,WAAA,EAAa,UAAU,CAAA;AAC5C,IAAA,GAAA,CAAI,CAAA,sCAAA,EAAyC,WAAW,CAAA,EAAA,EAAK,YAAY,CAAA,CAAE,CAAA;AAAA,EAC7E,CAAA,CAAA,MAAQ;AACN,IAAA,GAAA,CAAI,CAAA,0CAAA,EAA6C,WAAW,CAAA,CAAE,CAAA;AAAA,EAChE;AACA,EAAA,GAAA,CAAI,CAAA,qCAAA,EAAwC,WAAW,CAAA,EAAA,EAAK,YAAY,CAAA,CAAE,CAAA;AAC1E,EAAA,OAAO,YAAA;AACT;;;;AC3CA,MAAM,kBAAA,GAAkC,IAAI,GAAA,CAAI,aAAyB,CAAA;AAOzE,eAAsB,YAAY,MAAA,EAAgD;AAChF,EAAA,MAAM,EAAE,aAAA,EAAe,KAAA,EAAO,MAAA,EAAO,GAAI,MAAA;AACzC,EAAA,MAAM,GAAA,GAAM,WAAW,MAAM;AAAA,EAAC,CAAA,CAAA;AAE9B,EAAA,MAAM,KAAA,GAAQ,aAAA,CAAc,KAAA,CAAM,GAAG,CAAA;AACrC,EAAA,MAAM,WAAA,GAAc,MAAM,MAAA,GAAS,CAAA,GAAI,MAAM,CAAC,CAAA,GAAI,MAAM,CAAC,CAAA;AACzD,EAAA,IAAI,CAAC,aAAa,OAAO,KAAA;AAEzB,EAAA,MAAM,UAAA,GAAa,aAAA,CAA+B,KAAA,EAAO,MAAM,CAAA;AAC/D,EAAA,IAAI,MAAA;AACJ,EAAA,IAAI;AACF,IAAA,MAAA,GAAS,MAAM,UAAA,CAAW,GAAA,CAAI,WAAW,CAAA;AAAA,EAC3C,CAAA,CAAA,MAAQ;AACN,IAAA,MAAA,GAAS,IAAA;AAAA,EACX;AACA,EAAA,IAAI,MAAA,KAAW,IAAA,IAAQ,MAAA,KAAW,MAAA,EAAW;AAC3C,IAAA,GAAA,CAAI,CAAA,4BAAA,EAA+B,WAAW,CAAA,EAAA,EAAK,MAAA,CAAO,MAAM,CAAA,CAAE,CAAA;AAClE,IAAA,OAAO,MAAA,CAAO,MAAA;AAAA,EAChB;AAEA,EAAA,MAAM,MAAA,GAAS,kBAAA,CAAmB,GAAA,CAAI,WAAW,CAAA;AACjD,EAAA,MAAM,UAAA,GAA8B;AAAA,IAClC,MAAA;AAAA,IACA,QAAA,EAAU,SAAS,WAAA,GAAc,MAAA;AAAA,IACjC,SAAA,EAAW,KAAK,GAAA;AAAI,GACtB;AAEA,EAAA,IAAI;AACF,IAAA,MAAM,UAAA,CAAW,GAAA,CAAI,WAAA,EAAa,UAAU,CAAA;AAC5C,IAAA,GAAA,CAAI,CAAA,gCAAA,EAAmC,WAAW,CAAA,EAAA,EAAK,MAAM,CAAA,CAAE,CAAA;AAAA,EACjE,CAAA,CAAA,MAAQ;AACN,IAAA,GAAA,CAAI,CAAA,oCAAA,EAAuC,WAAW,CAAA,CAAE,CAAA;AAAA,EAC1D;AACA,EAAA,GAAA,CAAI,CAAA,+BAAA,EAAkC,WAAW,CAAA,EAAA,EAAK,MAAM,CAAA,CAAE,CAAA;AAC9D,EAAA,OAAO,MAAA;AACT;;AC1CA,eAAsB,iBAAiB,MAAA,EAA4C;AACjF,EAAA,MAAM,EAAE,MAAA,EAAQ,KAAA,EAAO,MAAA,EAAO,GAAI,MAAA;AAClC,EAAA,MAAM,GAAA,GAAM,WAAW,MAAM;AAAA,EAAC,CAAA,CAAA;AAG9B,EAAA,MAAM,UAAA,GAAa,aAAA,CAAwB,KAAA,EAAO,IAAI,CAAA;AACtD,EAAA,MAAM,MAAA,GAAS,MAAM,UAAA,CAAW,GAAA,CAAI,MAAM,CAAA;AAC1C,EAAA,IAAI,MAAA,KAAW,IAAA,IAAQ,MAAA,KAAW,MAAA,EAAW;AAC3C,IAAA,GAAA,CAAI,CAAA,iCAAA,EAAoC,MAAM,CAAA,EAAA,EAAK,MAAA,EAAQ,MAAM,CAAA,WAAA,CAAa,CAAA;AAC9E,IAAA,OAAO,MAAA;AAAA,EACT;AAEA,EAAA,GAAA,CAAI,CAAA,gDAAA,EAAmD,MAAM,CAAA,CAAE,CAAA;AAC/D,EAAA,IAAI;AACF,IAAA,MAAM,OAAA,GAAoD,MAAMC,iBAAA,CAAY,SAAA,CAAU,MAAM,CAAA;AAC5F,IAAA,OAAA,EAAS,IAAA,CAAK,CAAC,CAAA,EAAG,CAAA,KAAM;AACtB,MAAA,IAAI,CAAA,CAAE,QAAA,GAAW,CAAA,CAAE,QAAA,EAAU;AAC3B,QAAA,OAAO,CAAA,CAAA;AAAA,MACT;AACA,MAAA,IAAI,CAAA,CAAE,QAAA,GAAW,CAAA,CAAE,QAAA,EAAU;AAC3B,QAAA,OAAO,CAAA;AAAA,MACT;AACA,MAAA,OAAO,CAAA;AAAA,IACT,CAAC,CAAA;AAED,IAAA,MAAM,YAAY,OAAA,EAAS,GAAA,CAAI,CAAC,MAAA,KAAW,OAAO,QAAQ,CAAA;AAC1D,IAAA,GAAA,CAAI,CAAA,yBAAA,EAA4B,SAAA,EAAW,MAAM,CAAA,gBAAA,EAAmB,MAAM,MAAM,SAAA,EAAW,IAAA,CAAK,IAAI,CAAC,CAAA,CAAA,CAAG,CAAA;AAGxG,IAAA,MAAM,UAAA,CAAW,GAAA,CAAI,MAAA,EAAQ,SAAS,CAAA;AACtC,IAAA,GAAA,CAAI,CAAA,0BAAA,EAA6B,SAAA,EAAW,MAAM,CAAA,gBAAA,EAAmB,MAAM,CAAA,CAAE,CAAA;AAE7E,IAAA,OAAO,SAAA;AAAA,EACT,SAAS,KAAA,EAAO;AACd,IAAA,GAAA,CAAI,CAAA,wCAAA,EAA2C,MAAM,CAAA,sBAAA,CAAwB,CAAA;AAE7E,IAAA,MAAM,UAAA,CAAW,GAAA,CAAI,MAAA,EAAQ,EAAE,CAAA;AAC/B,IAAA,MAAM,KAAA;AAAA,EACR;AACF;;;;;;ACpCA,MAAM,aAAA,GAAgB,CAAC,GAAA,EAAK,GAAA,EAAK,GAAG,CAAA;AACpC,MAAM,kBAAA,GAAqB;AAAA,EACzB,MAAA;AAAA,EACA,OAAA;AAAA,EACA,SAAA;AAAA,EACA,MAAA;AAAA,EACA,OAAA;AAAA,EACA,SAAA;AAAA,EACA,OAAA;AAAA,EACA,MAAA;AAAA,EACA,SAAA;AAAA,EACA,UAAA;AAAA,EACA,YAAA;AAAA,EACA,eAAA;AAAA,EACA;AACF,CAAA;AAGA,MAAM,kBAAA,GAAqB;AAAA,EACzB,KAAA;AAAA,EACA,SAAA;AAAA,EACA,MAAA;AAAA,EACA,OAAA;AAAA,EACA,QAAA;AAAA,EACA,MAAA;AAAA,EACA,UAAA;AAAA,EACA,MAAA;AAAA,EACA,SAAA;AAAA,EACA,UAAA;AAAA,EACA,MAAA;AAAA,EACA,KAAA;AAAA,EACA,KAAA;AAAA,EACA,KAAA;AAAA,EACA;AACF,CAAA;AAGA,MAAM,aAAA,GAAgB;AAAA,EACpB,IAAA;AAAA,EACA,KAAA;AAAA,EACA,IAAA;AAAA,EACA,MAAA;AAAA,EACA,IAAA;AAAA,EACA,MAAA;AAAA,EACA,KAAA;AAAA,EACA,MAAA;AAAA,EACA,MAAA;AAAA,EACA,SAAA;AAAA,EACA,KAAA;AAAA,EACA,QAAA;AAAA,EACA;AACF,CAAA;AAKA,MAAM,eAAA,GAA+B,IAAI,GAAA,CAAI,mBAA+B,CAAA;AAG5E,MAAM,cAAA,GAA8B,IAAI,GAAA,CAAI,kBAA8B,CAAA;AAG1E,SAAS,WAAW,GAAA,EAAa;AAC/B,EAAA,OAAO,gBAAA,CAAiB,KAAK,GAAG,CAAA;AAClC;AAGA,SAAS,iBAAiB,GAAA,EAAa;AACrC,EAAA,OAAO,eAAA,CAAgB,GAAA,CAAI,GAAA,CAAI,WAAA,EAAa,CAAA;AAC9C;AAGA,SAAS,gBAAgB,GAAA,EAAa;AACpC,EAAA,OAAO,cAAA,CAAe,GAAA,CAAI,GAAA,CAAI,WAAA,EAAa,CAAA;AAC7C;AAGA,SAAS,QAAQ,GAAA,EAAa;AAC5B,EAAA,OAAO,aAAA,CAAc,SAAS,GAAA,CAAI,WAAA,GAAc,OAAA,CAAQ,GAAA,EAAK,EAAE,CAAC,CAAA;AAClE;AAIA,SAAS,kBAAkB,GAAA,EAAa;AACtC,EAAA,MAAM,KAAA,GAAQ,IAAI,WAAA,EAAY;AAC9B,EAAA,IAAI,eAAA,CAAgB,GAAA,CAAI,KAAK,CAAA,EAAG,OAAO,CAAA;AACvC,EAAA,IAAI,cAAA,CAAe,GAAA,CAAI,KAAK,CAAA,EAAG,OAAO,GAAA;AACtC,EAAA,IAAI,GAAA,CAAI,MAAA,IAAU,CAAA,IAAK,GAAA,CAAI,MAAA,IAAU,MAAM,aAAA,CAAc,IAAA,CAAK,GAAG,CAAA,EAAG,OAAO,GAAA;AAC3E,EAAA,OAAO,CAAA;AACT;AAGA,SAAS,iBAAiB,GAAA,EAAa;AACrC,EAAA,MAAM,KAAA,GAAQ,IAAI,WAAA,EAAY;AAC9B,EAAA,IAAI,cAAA,CAAe,GAAA,CAAI,KAAK,CAAA,EAAG,OAAO,CAAA;AACtC,EAAA,IAAI,eAAA,CAAgB,GAAA,CAAI,KAAK,CAAA,EAAG,OAAO,GAAA;AACvC,EAAA,IAAI,GAAA,CAAI,MAAA,IAAU,CAAA,IAAK,GAAA,CAAI,MAAA,IAAU,MAAM,aAAA,CAAc,IAAA,CAAK,GAAG,CAAA,EAAG,OAAO,GAAA;AAC3E,EAAA,OAAO,CAAA;AACT;AAKA,SAAS,eAAe,GAAA,EAAa;AACnC,EAAA,IAAI,CAAC,KAAK,OAAO,EAAA;AAGjB,EAAA,MAAM,eAAA,GAAkB;AAAA,IACtB;AAAA,MACE,OAAA,EAAS,gBAAA;AAAA,MACT,MAAA,EAAQ,CAAC,CAAA,KAAwB,CAAA,EAAA,EAAK,EAAE,CAAC,CAAA,CAAE,OAAO,CAAC,CAAA,CAAE,aAAa,CAAA,EAAG,EAAE,CAAC,CAAA,CAAE,MAAM,CAAC,CAAA,CAAE,aAAa,CAAA;AAAA,KAClG;AAAA,IACA;AAAA,MACE,OAAA,EAAS,iBAAA;AAAA,MACT,MAAA,EAAQ,CAAC,CAAA,KAAwB,CAAA,GAAA,EAAM,EAAE,CAAC,CAAA,CAAE,OAAO,CAAC,CAAA,CAAE,aAAa,CAAA,EAAG,EAAE,CAAC,CAAA,CAAE,MAAM,CAAC,CAAA,CAAE,aAAa,CAAA;AAAA,KACnG;AAAA,IACA;AAAA,MACE,OAAA,EAAS,gBAAA;AAAA,MACT,MAAA,EAAQ,CAAC,CAAA,KAAwB,CAAA,EAAA,EAAK,EAAE,CAAC,CAAA,CAAE,OAAO,CAAC,CAAA,CAAE,aAAa,CAAA,EAAG,EAAE,CAAC,CAAA,CAAE,MAAM,CAAC,CAAA,CAAE,aAAa,CAAA;AAAA,KAClG;AAAA,IACA;AAAA,MACE,OAAA,EAAS,qEAAA;AAAA,MACT,MAAA,EAAQ,CAAC,CAAA,KACP,CAAA,CAAE,CAAC,EAAE,WAAA,EAAY,GAAI,CAAA,CAAE,CAAC,CAAA,GAAI,CAAA,CAAE,CAAC,CAAA,CAAE,MAAA,CAAO,CAAC,CAAA,CAAE,WAAA,EAAY,GAAI,CAAA,CAAE,CAAC,CAAA,CAAE,KAAA,CAAM,CAAC,CAAA,CAAE,WAAA;AAAY;AACzF,GACF;AAEA,EAAA,KAAA,MAAW,EAAE,OAAA,EAAS,MAAA,EAAO,IAAK,eAAA,EAAiB;AACjD,IAAA,MAAM,KAAA,GAAQ,GAAA,CAAI,KAAA,CAAM,OAAO,CAAA;AAC/B,IAAA,IAAI,KAAA,EAAO;AACT,MAAA,OAAO,OAAO,KAAK,CAAA;AAAA,IACrB;AAAA,EACF;AAGA,EAAA,IAAI,GAAA,CAAI,QAAA,CAAS,GAAG,CAAA,EAAG;AACrB,IAAA,OAAO,GAAA,CACJ,MAAM,GAAG,CAAA,CACT,IAAI,CAAC,IAAA,KAAS,KAAK,MAAA,CAAO,CAAC,EAAE,WAAA,EAAY,GAAI,KAAK,KAAA,CAAM,CAAC,EAAE,WAAA,EAAa,CAAA,CACxE,IAAA,CAAK,GAAG,CAAA;AAAA,EACb;AAGA,EAAA,IAAI,GAAA,CAAI,SAAS,GAAG,CAAA,IAAK,IAAI,OAAA,CAAQ,GAAG,IAAI,CAAA,EAAG;AAC7C,IAAA,MAAM,KAAA,GAAQ,GAAA,CAAI,KAAA,CAAM,GAAG,CAAA;AAC3B,IAAA,OAAO,KAAA,CACJ,GAAA;AAAA,MAAI,CAAC,IAAA,EAAM,CAAA,KACV,CAAA,KAAM,CAAA,GACF,IAAA,CAAK,MAAA,CAAO,CAAC,CAAA,CAAE,WAAA,EAAY,GAAI,IAAA,CAAK,KAAA,CAAM,CAAC,CAAA,CAAE,WAAA,EAAY,GACzD,IAAA,CAAK,MAAA,CAAO,CAAC,CAAA,CAAE,WAAA,EAAY,GAAI,IAAA,CAAK,KAAA,CAAM,CAAC,CAAA,CAAE,WAAA;AAAY,KAC/D,CACC,KAAK,GAAG,CAAA;AAAA,EACb;AAGA,EAAA,IAAI,WAAA,CAAY,IAAA,CAAK,GAAG,CAAA,EAAG;AACzB,IAAA,OAAO,GAAA,CAAI,MAAA,CAAO,CAAC,CAAA,CAAE,WAAA,KAAgB,GAAA,CAAI,KAAA,CAAM,CAAC,CAAA,CAAE,WAAA,EAAY;AAAA,EAChE;AAEA,EAAA,OAAO,GAAA;AACT;AAOA,SAAS,uBAAuB,IAAA,EAI9B;AACA,EAAA,MAAM,UAAA,GAAa,IAAA,CAAK,IAAA,CAAK,IAAI,CAAA;AACjC,EAAA,IAAI,UAAA,GAAa,CAAA;AASjB,EAAA,IAAI,OAAA,GAAU,IAAA;AAGd,EAAA,MAAM,YAAA,GAA0C;AAAA,IAC9C,GAAA,EAAK,GAAA;AAAA,IACL,GAAA,EAAK,GAAA;AAAA,IACL,GAAA,EAAK,GAAA;AAAA,IACL,GAAA,EAAK,GAAA;AAAA,IACL,GAAA,EAAK,GAAA;AAAA,IACL,GAAA,EAAK,GAAA;AAAA,IACL,GAAA,EAAK;AAAA,GACP;AAGA,EAAA,IAAI,UAAA,IAAc,IAAA,CAAK,MAAA,IAAU,CAAA,EAAG;AAClC,IAAA,IAAI,WAAA,GAAc,KAAK,WAAA,EAAY;AACnC,IAAA,KAAA,MAAW,CAAC,GAAA,EAAK,MAAM,KAAK,MAAA,CAAO,OAAA,CAAQ,YAAY,CAAA,EAAG;AACxD,MAAA,WAAA,GAAc,YAAY,OAAA,CAAQ,IAAI,OAAO,GAAA,EAAK,GAAG,GAAG,MAAM,CAAA;AAAA,IAChE;AAGA,IAAA,IAAI,gBAAA,CAAiB,WAAW,CAAA,IAAK,eAAA,CAAgB,WAAW,CAAA,EAAG;AACjE,MAAA,OAAA,GAAU,WAAA;AACV,MAAA,UAAA,GAAa,GAAA;AAAA,IACf;AAAA,EACF;AAGA,EAAA,IAAI,YAAY,IAAA,EAAM;AAEpB,IAAA,MAAM,WAAA,GAAc,IAAA,CAAK,OAAA,CAAQ,eAAA,EAAiB,EAAE,CAAA;AACpD,IAAA,IAAI,WAAA,KAAgB,IAAA,IAAQ,WAAA,CAAY,MAAA,IAAU,CAAA,EAAG;AACnD,MAAA,OAAA,GAAU,WAAA;AACV,MAAA,UAAA,GAAa,GAAA;AAAA,IACf,CAAA,MAAO;AAEL,MAAA,MAAM,SAAA,GAAY,IAAA,CAAK,OAAA,CAAQ,MAAA,EAAQ,EAAE,CAAA;AAIzC,MAAA,IAAI,SAAA,CAAU,UAAU,CAAA,EAAG;AACzB,QAAA,OAAA,GAAU,SAAA;AACV,QAAA,UAAA,GAAa,aAAa,IAAA,GAAO,CAAA;AAAA,MACnC,WAAW,SAAA,CAAU,MAAA,KAAW,KAAK,YAAA,CAAa,IAAA,CAAK,SAAS,CAAA,EAAG;AAEjE,QAAA,OAAA,GAAU,SAAA;AACV,QAAA,UAAA,GAAa,GAAA;AAAA,MACf,CAAA,MAAO;AAEL,QAAA,MAAM,SAAA,GAAY,IAAA,CAAK,KAAA,CAAM,kBAAkB,CAAA;AAC/C,QAAA,IAAI,SAAA,EAAW;AACb,UAAA,OAAA,GAAU,UAAU,CAAC,CAAA;AACrB,UAAA,UAAA,GAAa,IAAA;AAAA,QACf,CAAA,MAAO;AAEL,UAAA,OAAA,GAAU,IAAA;AACV,UAAA,UAAA,GAAa,GAAA;AAAA,QACf;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAGA,EAAA,IAAI,YAAY,IAAA,EAAM;AACpB,IAAA,IAAI,gBAAA,CAAiB,OAAO,CAAA,IAAK,eAAA,CAAgB,OAAO,CAAA,EAAG;AACzD,MAAA,UAAA,GAAa,IAAA,CAAK,GAAA,CAAI,CAAA,EAAK,UAAA,GAAa,GAAG,CAAA;AAAA,IAC7C;AAAA,EACF;AAEA,EAAA,OAAO,EAAE,UAAA,EAAY,OAAA,EAAS,UAAA,EAAW;AAC3C;AAKA,SAAS,YAAA,CAAa,GAAA,EAAa,YAAA,GAAe,KAAA,EAAO,oBAAoB,KAAA,EAAO;AAClF,EAAA,IAAI,CAAC,KAAK,OAAO,KAAA;AAGjB,EAAA,IAAI,GAAA,CAAI,MAAA,GAAS,CAAA,IAAK,CAAC,mBAAmB,OAAO,KAAA;AACjD,EAAA,IAAI,GAAA,CAAI,WAAW,CAAA,IAAK,iBAAA,IAAqB,aAAa,IAAA,CAAK,GAAG,GAAG,OAAO,IAAA;AAG5E,EAAA,IAAI,mBAAmB,QAAA,CAAS,GAAA,CAAI,WAAA,EAAa,GAAG,OAAO,KAAA;AAG3D,EAAA,IAAI,YAAA,EAAc;AAEhB,IAAA,IAAI,OAAA,CAAQ,IAAA,CAAK,GAAG,CAAA,EAAG,OAAO,KAAA;AAE9B,IAAA,OAAO,IAAA;AAAA,EACT;AAGA,EAAA,MAAM,cAAc,GAAA,CAAI,KAAA,CAAM,KAAK,CAAA,IAAK,EAAC,EAAG,MAAA;AAC5C,EAAA,IAAI,UAAA,GAAa,GAAA,CAAI,MAAA,GAAS,GAAA,EAAK,OAAO,KAAA;AAK1C,EAAA,OAAO,IAAA;AACT;AAMO,SAAS,2BAA2B,KAAA,EAAoC;AAC7E,EAAA,IAAI,CAAC,KAAA,EAAO,QAAA,CAAS,GAAG,CAAA,EAAG;AACzB,IAAA,OAAO,IAAA;AAAA,EACT;AAEA,EAAA,MAAM,CAAC,SAAS,CAAA,GAAI,KAAA,CAAM,MAAM,GAAG,CAAA;AACnC,EAAA,IAAI,CAAC,SAAA,EAAW;AACd,IAAA,OAAO,IAAA;AAAA,EACT;AAGA,EAAA,MAAM,iBAAA,GAAoB,SAAA,CAAU,KAAA,CAAM,GAAG,EAAE,CAAC,CAAA;AAIhD,EAAA,MAAM,YAAA,GAAe,iBAAA;AAGrB,EAAA,IAAI,aAAa,WAAA,EAAY,KAAM,cAAc,YAAA,CAAa,WAAA,OAAkB,SAAA,EAAW;AACzF,IAAA,OAAO,IAAA;AAAA,EACT;AAEA,EAAA,IAAI,SAAA;AACJ,EAAA,IAAI,QAAA;AACJ,EAAA,IAAI,UAAA,GAAa,CAAA;AAGjB,EAAA,MAAM,iBAAA,GAAoB;AAAA,IACxB,yBAAA;AAAA;AAAA,IACA,8BAAA;AAAA;AAAA,IACA;AAAA;AAAA,GACF;AAEA,EAAA,KAAA,MAAW,WAAW,iBAAA,EAAmB;AACvC,IAAA,MAAM,KAAA,GAAQ,YAAA,CAAa,KAAA,CAAM,OAAO,CAAA;AACxC,IAAA,IAAI,KAAA,EAAO;AACT,MAAA,IAAI,KAAA,CAAM,WAAW,CAAA,EAAG;AAEtB,QAAA,MAAM,GAAG,KAAA,EAAO,IAAI,CAAA,GAAI,KAAA;AACxB,QAAA,IAAI,YAAA,CAAa,KAAK,CAAA,IAAK,YAAA,CAAa,IAAI,CAAA,EAAG;AAC7C,UAAA,MAAM,UAAA,GAAa,kBAAkB,KAAK,CAAA;AAC1C,UAAA,MAAM,SAAA,GAAY,iBAAiB,IAAI,CAAA;AAEvC,UAAA,SAAA,GAAY,eAAe,KAAK,CAAA;AAChC,UAAA,QAAA,GAAW,eAAe,IAAI,CAAA;AAC9B,UAAA,UAAA,GAAa,GAAA,GAAA,CAAO,aAAa,SAAA,IAAa,IAAA;AAC9C,UAAA;AAAA,QACF;AAAA,MACF,CAAA,MAAA,IAAW,KAAA,CAAM,MAAA,KAAW,CAAA,EAAG;AAE7B,QAAA,MAAM,GAAG,KAAA,EAAO,MAAA,EAAQ,IAAI,CAAA,GAAI,KAAA;AAChC,QAAA,MAAM,WAAW,MAAA,GAAS,IAAA;AAE1B,QAAA,IAAI,YAAA,CAAa,KAAK,CAAA,EAAG;AACvB,UAAA,SAAA,GAAY,eAAe,KAAK,CAAA;AAChC,UAAA,QAAA,GAAW,eAAe,QAAQ,CAAA;AAClC,UAAA,UAAA,GAAa,IAAA;AACb,UAAA;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAGA,EAAA,IAAI,CAAC,SAAA,IAAa,CAAC,QAAA,EAAU;AAC3B,IAAA,KAAA,MAAW,aAAa,aAAA,EAAe;AACrC,MAAA,IAAI,YAAA,CAAa,QAAA,CAAS,SAAS,CAAA,EAAG;AACpC,QAAA,MAAM,KAAA,GAAQ,YAAA,CAAa,KAAA,CAAM,SAAS,CAAA,CAAE,OAAO,CAAC,CAAA,KAAM,CAAA,CAAE,MAAA,GAAS,CAAC,CAAA;AAEtE,QAAA,IAAI,KAAA,CAAM,WAAW,CAAA,EAAG;AACtB,UAAA,MAAM,CAAC,KAAA,EAAO,IAAI,CAAA,GAAI,KAAA;AAGtB,UAAA,IAAI,OAAA,CAAQ,KAAK,CAAA,EAAG;AAElB,YAAA;AAAA,UACF;AAGA,UAAA,MAAM,WAAA,GAAc,uBAAuB,KAAK,CAAA;AAChD,UAAA,MAAM,UAAA,GAAa,uBAAuB,IAAI,CAAA;AAG9C,UAAA,MAAM,cAAA,GAAiB,iBAAA,CAAkB,WAAA,CAAY,OAAO,CAAA;AAC5D,UAAA,MAAM,aAAA,GAAgB,gBAAA,CAAiB,UAAA,CAAW,OAAO,CAAA;AAGzD,UAAA,MAAM,eAAe,gBAAA,CAAiB,WAAA,CAAY,OAAO,CAAA,GAAI,iBAAA,CAAkB,WAAW,OAAO,CAAA;AACjG,UAAA,MAAM,cAAc,cAAA,GAAiB,aAAA;AAIrC,UAAA,MAAM,WAAA,GAAc,YAAA,CAAa,KAAA,EAAO,IAAA,EAAM,IAAI,CAAA;AAClD,UAAA,MAAM,UAAA,GAAa,YAAA,CAAa,IAAA,EAAM,IAAA,EAAM,IAAI,CAAA;AAGhD,UAAA,MAAM,iBAAA,GAAoB,KAAA,CAAM,MAAA,KAAW,CAAA,IAAK,KAAK,MAAA,KAAW,CAAA;AAChE,UAAA,MAAM,iBAAA,GAAoB,iBAAA,GACtB,KAAA,CAAM,MAAA,KAAW,CAAA,GACf,KAAK,MAAA,IAAU,CAAA,GACf,KAAA,CAAM,MAAA,IAAU,CAAA,GAClB,IAAA;AAEJ,UAAA,MAAM,cAAA,GAAiB,eAAe,UAAA,IAAc,iBAAA;AAEpD,UAAA,IAAI,cAAA,EAAgB;AAKlB,YAAA,MAAM,WAAA,GAAc,eAAe,WAAA,GAAc,GAAA;AAEjD,YAAA,IAAI,WAAA,CAAY,UAAA,IAAc,UAAA,CAAW,UAAA,EAAY;AAEnD,cAAA,MAAM,eAAe,WAAA,CAAY,OAAA;AACjC,cAAA,MAAM,cAAc,UAAA,CAAW,OAAA;AAG/B,cAAA,IAAI,YAAA,CAAa,cAAc,KAAA,EAAO,IAAI,KAAK,YAAA,CAAa,WAAA,EAAa,KAAA,EAAO,IAAI,CAAA,EAAG;AAErF,gBAAA,IAAI,WAAA,EAAa;AACf,kBAAA,SAAA,GAAY,eAAe,WAAW,CAAA;AACtC,kBAAA,QAAA,GAAW,eAAe,YAAY,CAAA;AAAA,gBACxC,CAAA,MAAO;AACL,kBAAA,SAAA,GAAY,eAAe,YAAY,CAAA;AACvC,kBAAA,QAAA,GAAW,eAAe,WAAW,CAAA;AAAA,gBACvC;AAGA,gBAAA,MAAM,cAAA,GAAiB,GAAA;AACvB,gBAAA,MAAM,iBAAiB,SAAA,KAAc,GAAA,GAAM,IAAA,GAAO,SAAA,KAAc,MAAM,IAAA,GAAO,CAAA;AAC7E,gBAAA,MAAM,oBAAA,GAAuB,WAAA,GAAc,GAAA,GAAM,GAAA,GAAM,CAAA;AACvD,gBAAA,MAAM,eAAA,GAAA,CAAmB,WAAA,CAAY,UAAA,GAAa,UAAA,CAAW,cAAc,CAAA,GAAI,CAAA;AAE/E,gBAAA,UAAA,GAAa,KAAK,GAAA,CAAI,IAAA,EAAM,cAAA,GAAiB,cAAA,GAAiB,uBAAuB,eAAe,CAAA;AAAA,cACtG,CAAA,MAAO;AAGL,gBAAA,SAAA,GAAY,eAAe,KAAK,CAAA;AAChC,gBAAA,QAAA,GAAW,eAAe,IAAI,CAAA;AAC9B,gBAAA,UAAA,GAAa,GAAA;AAAA,cACf;AAAA,YACF,CAAA,MAAO;AAEL,cAAA,IAAI,WAAA,EAAa;AACf,gBAAA,SAAA,GAAY,eAAe,IAAI,CAAA;AAC/B,gBAAA,QAAA,GAAW,eAAe,KAAK,CAAA;AAAA,cACjC,CAAA,MAAO;AACL,gBAAA,SAAA,GAAY,eAAe,KAAK,CAAA;AAChC,gBAAA,QAAA,GAAW,eAAe,IAAI,CAAA;AAAA,cAChC;AAGA,cAAA,MAAM,cAAA,GAAiB,IAAA;AACvB,cAAA,MAAM,iBAAiB,SAAA,KAAc,GAAA,GAAM,IAAA,GAAO,SAAA,KAAc,MAAM,IAAA,GAAO,CAAA;AAC7E,cAAA,MAAM,oBAAA,GAAuB,IAAA,CAAK,GAAA,CAAI,IAAA,EAAM,cAAc,IAAI,CAAA;AAE9D,cAAA,UAAA,GAAa,IAAA,CAAK,GAAA,CAAI,IAAA,EAAM,cAAA,GAAiB,iBAAiB,oBAAoB,CAAA;AAAA,YACpF;AAEA,YAAA;AAAA,UACF;AAAA,QACF,CAAA,MAAA,IAAW,KAAA,CAAM,MAAA,KAAW,CAAA,EAAG;AAE7B,UAAA,MAAM,CAAC,KAAA,EAAO,MAAA,EAAQ,IAAI,CAAA,GAAI,KAAA;AAG9B,UAAA,MAAM,WAAA,GAAc,uBAAuB,KAAK,CAAA;AAChD,UAAA,MAAM,YAAA,GAAe,uBAAuB,MAAM,CAAA;AAClD,UAAA,MAAM,UAAA,GAAa,uBAAuB,IAAI,CAAA;AAG9C,UAAA,MAAM,YAAA,GACJ,kBAAA,CAAmB,QAAA,CAAS,IAAA,CAAK,aAAa,CAAA,IAC9C,kBAAA,CAAmB,QAAA,CAAS,IAAA,CAAK,WAAA,EAAa,CAAA,IAC9C,WAAW,IAAI,CAAA;AAEjB,UAAA,IAAI,YAAA,EAAc;AAChB,YAAA,IAAI,YAAA,CAAa,OAAO,IAAA,EAAM,IAAI,KAAK,YAAA,CAAa,MAAA,EAAQ,IAAA,EAAM,IAAI,CAAA,EAAG;AAEvE,cAAA,MAAM,YAAA,GAAe,WAAA,CAAY,UAAA,GAAa,WAAA,CAAY,OAAA,GAAU,KAAA;AACpE,cAAA,MAAM,aAAA,GAAgB,YAAA,CAAa,UAAA,GAAa,YAAA,CAAa,OAAA,GAAU,MAAA;AAEvE,cAAA,IAAI,YAAA,CAAa,cAAc,KAAA,EAAO,IAAI,KAAK,YAAA,CAAa,aAAA,EAAe,KAAA,EAAO,IAAI,CAAA,EAAG;AACvF,gBAAA,SAAA,GAAY,eAAe,YAAY,CAAA;AACvC,gBAAA,QAAA,GAAW,eAAe,aAAa,CAAA;AACvC,gBAAA,UAAA,GAAa,GAAA;AAAA,cACf,CAAA,MAAO;AACL,gBAAA,SAAA,GAAY,eAAe,KAAK,CAAA;AAChC,gBAAA,QAAA,GAAW,eAAe,MAAM,CAAA;AAChC,gBAAA,UAAA,GAAa,IAAA;AAAA,cACf;AACA,cAAA;AAAA,YACF;AAAA,UACF,CAAA,MAAA,IAAW,YAAA,CAAa,KAAA,EAAO,IAAA,EAAM,IAAI,KAAK,YAAA,CAAa,IAAA,EAAM,IAAA,EAAM,IAAI,CAAA,EAAG;AAE5E,YAAA,MAAM,YAAA,GAAe,WAAA,CAAY,UAAA,GAAa,WAAA,CAAY,OAAA,GAAU,KAAA;AACpE,YAAA,MAAM,WAAA,GAAc,UAAA,CAAW,UAAA,GAAa,UAAA,CAAW,OAAA,GAAU,IAAA;AAEjE,YAAA,IAAI,YAAA,CAAa,cAAc,KAAA,EAAO,IAAI,KAAK,YAAA,CAAa,WAAA,EAAa,KAAA,EAAO,IAAI,CAAA,EAAG;AACrF,cAAA,SAAA,GAAY,eAAe,YAAY,CAAA;AACvC,cAAA,QAAA,GAAW,eAAe,WAAW,CAAA;AACrC,cAAA,UAAA,GAAa,IAAA;AAAA,YACf,CAAA,MAAO;AAEL,cAAA,SAAA,GAAY,eAAe,KAAK,CAAA;AAChC,cAAA,QAAA,GAAW,eAAe,IAAI,CAAA;AAC9B,cAAA,UAAA,GAAa,IAAA;AAAA,YACf;AACA,YAAA;AAAA,UACF;AAAA,QACF,CAAA,MAAA,IAAW,KAAA,CAAM,MAAA,GAAS,CAAA,EAAG;AAG3B,UAAA,MAAM,SAAA,GAAY,MAAM,CAAC,CAAA;AAGzB,UAAA,MAAM,gBAAgB,KAAA,CAAM,KAAA,CAAM,MAAA,GAAS,CAAC,EAAE,WAAA,EAAY;AAC1D,UAAA,MAAM,gBAAA,GACJ,kBAAA,CAAmB,QAAA,CAAS,aAAa,KACzC,kBAAA,CAAmB,QAAA,CAAS,aAAa,CAAA,IACzC,UAAA,CAAW,KAAA,CAAM,KAAA,CAAM,MAAA,GAAS,CAAC,CAAC,CAAA;AACpC,UAAA,MAAM,qBAAqB,gBAAA,GAAmB,KAAA,CAAM,MAAA,GAAS,CAAA,GAAI,MAAM,MAAA,GAAS,CAAA;AAChF,UAAA,MAAM,SAAA,GAAY,kBAAA,IAAsB,CAAA,GAAI,KAAA,CAAM,kBAAkB,CAAA,GAAI,IAAA;AAExE,UAAA,IAAI,SAAA,IAAa,YAAA,CAAa,SAAA,EAAW,IAAA,EAAM,IAAI,KAAK,YAAA,CAAa,SAAA,EAAW,IAAA,EAAM,IAAI,CAAA,EAAG;AAC3F,YAAA,MAAM,WAAA,GAAc,uBAAuB,SAAS,CAAA;AACpD,YAAA,MAAM,UAAA,GAAa,uBAAuB,SAAS,CAAA;AAGnD,YAAA,MAAM,YAAA,GAAe,WAAA,CAAY,UAAA,GAAa,WAAA,CAAY,OAAA,GAAU,SAAA;AACpE,YAAA,MAAM,WAAA,GAAc,UAAA,CAAW,UAAA,GAAa,UAAA,CAAW,OAAA,GAAU,SAAA;AAEjE,YAAA,IAAI,YAAA,CAAa,cAAc,KAAA,EAAO,IAAI,KAAK,YAAA,CAAa,WAAA,EAAa,KAAA,EAAO,IAAI,CAAA,EAAG;AACrF,cAAA,SAAA,GAAY,eAAe,YAAY,CAAA;AACvC,cAAA,QAAA,GAAW,eAAe,WAAW,CAAA;AACrC,cAAA,UAAA,GAAa,GAAA;AAAA,YACf,CAAA,MAAO;AACL,cAAA,SAAA,GAAY,eAAe,SAAS,CAAA;AACpC,cAAA,QAAA,GAAW,eAAe,SAAS,CAAA;AACnC,cAAA,UAAA,GAAa,GAAA;AAAA,YACf;AACA,YAAA;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAGA,EAAA,IAAI,CAAC,SAAA,IAAa,CAAC,QAAA,EAAU;AAC3B,IAAA,MAAM,eAAA,GAAkB,YAAA,CAAa,KAAA,CAAM,aAAa,CAAA;AACxD,IAAA,IAAI,eAAA,EAAiB;AACnB,MAAA,MAAM,KAAA,GAAQ,YAAA,CACX,WAAA,EAAY,CACZ,KAAA,CAAM,GAAG,CAAA,CACT,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,MAAA,GAAS,CAAC,CAAA;AAC7B,MAAA,IAAI,KAAA,CAAM,WAAW,CAAA,EAAG;AACtB,QAAA,MAAM,CAAC,KAAA,EAAO,IAAI,CAAA,GAAI,KAAA;AACtB,QAAA,IAAI,YAAA,CAAa,KAAK,CAAA,IAAK,YAAA,CAAa,IAAI,CAAA,EAAG;AAC7C,UAAA,SAAA,GAAY,eAAe,KAAK,CAAA;AAChC,UAAA,QAAA,GAAW,eAAe,IAAI,CAAA;AAC9B,UAAA,UAAA,GAAa,IAAA;AAAA,QACf;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAGA,EAAA,IAAI,CAAC,SAAA,IAAa,CAAC,QAAA,EAAU;AAC3B,IAAA,MAAM,MAAA,GAAS,uBAAuB,YAAY,CAAA;AAGlD,IAAA,IAAI,YAAA,CAAa,YAAA,EAAc,IAAA,EAAM,KAAK,CAAA,EAAG;AAC3C,MAAA,IAAI,aAAA,CAAc,IAAA,CAAK,YAAY,CAAA,EAAG;AAEpC,QAAA,MAAM,SAAA,GAAY,KAAK,GAAA,CAAI,iBAAA,CAAkB,YAAY,CAAA,EAAG,gBAAA,CAAiB,YAAY,CAAC,CAAA;AAG1F,QAAA,IAAI,iBAAA,CAAkB,YAAY,CAAA,IAAK,gBAAA,CAAiB,YAAY,CAAA,EAAG;AACrE,UAAA,SAAA,GAAY,eAAe,YAAY,CAAA;AAAA,QACzC,CAAA,MAAO;AACL,UAAA,QAAA,GAAW,eAAe,YAAY,CAAA;AAAA,QACxC;AAEA,QAAA,UAAA,GAAa,MAAM,SAAA,GAAY,GAAA;AAAA,MACjC,WAAW,MAAA,CAAO,UAAA,IAAc,MAAA,CAAO,OAAA,CAAQ,UAAU,CAAA,EAAG;AAE1D,QAAA,MAAM,YAAA,GAAe,IAAA,CAAK,GAAA,CAAI,iBAAA,CAAkB,MAAA,CAAO,OAAO,CAAA,EAAG,gBAAA,CAAiB,MAAA,CAAO,OAAO,CAAC,CAAA;AAEjG,QAAA,IAAI,kBAAkB,MAAA,CAAO,OAAO,KAAK,gBAAA,CAAiB,MAAA,CAAO,OAAO,CAAA,EAAG;AACzE,UAAA,SAAA,GAAY,cAAA,CAAe,OAAO,OAAO,CAAA;AAAA,QAC3C,CAAA,MAAO;AACL,UAAA,QAAA,GAAW,cAAA,CAAe,OAAO,OAAO,CAAA;AAAA,QAC1C;AAEA,QAAA,UAAA,GAAa,GAAA,GAAM,YAAA,GAAe,GAAA,GAAM,MAAA,CAAO,UAAA,GAAa,GAAA;AAAA,MAC9D;AAAA,IACF;AAAA,EACF;AAEA,EAAA,IAAI,CAAC,SAAA,IAAa,CAAC,QAAA,EAAU;AAC3B,IAAA,OAAO,IAAA;AAAA,EACT;AAEA,EAAA,OAAO;AAAA,IACL,SAAA;AAAA,IACA,QAAA;AAAA,IACA,UAAA,EAAY,KAAK,GAAA,CAAI,CAAA,EAAG,KAAK,GAAA,CAAI,CAAA,EAAG,UAAU,CAAC;AAAA;AAAA,GACjD;AACF;AAOO,SAAS,oBAAoB,MAAA,EAAkD;AACpF,EAAA,MAAM,EAAE,KAAA,EAAO,YAAA,EAAa,GAAI,MAAA;AAEhC,EAAA,IAAI,CAAC,KAAA,EAAO,QAAA,CAAS,GAAG,CAAA,EAAG;AACzB,IAAA,OAAO,IAAA;AAAA,EACT;AAGA,EAAA,IAAI,YAAA,EAAc;AAChB,IAAA,IAAI;AACF,MAAA,OAAO,aAAa,KAAK,CAAA;AAAA,IAC3B,SAAS,KAAA,EAAO;AAEd,MAAA,OAAA,CAAQ,IAAA,CAAK,iEAAiE,KAAK,CAAA;AAAA,IACrF;AAAA,EACF;AAGA,EAAA,OAAO,2BAA2B,KAAK,CAAA;AACzC;;AC5mBA,MAAM,oBAAA,GAAuB,OAAA;AAetB,SAAS,oBAAA,CACd,UACA,SAAA,EACQ;AACR,EAAA,QAAQ,SAAS,IAAA;AAAM,IACrB,KAAK,aAAA;AACH,MAAA,OAAO,IAAA;AAAA,IACT,KAAK,OAAA;AACH,MAAA,OAAO,IAAA,CAAK,SAAS,OAAO,CAAA;AAAA,IAC9B,KAAK,qBAAA;AACH,MAAA,OAAO,IAAA,CAAK,GAAG,WAAA,CAAY,QAAA,CAAS,WAAW,CAAC,CAAA,CAAA,EAAI,SAAA,CAAU,MAAM,CAAA,CAAE,CAAA;AAAA,IACxE,KAAK,kBAAA;AACH,MAAA,OAAO,IAAA,CAAK,GAAG,WAAA,CAAY,QAAA,CAAS,WAAW,CAAC,CAAA,CAAA,EAAI,QAAA,CAAS,MAAM,CAAA,CAAE,CAAA;AAAA,IACvE,KAAK,QAAA;AAGH,MAAA,OAAO,QAAA,CAAS,MAAM,EAAE,KAAA,EAAO,UAAU,KAAA,EAAO,MAAA,EAAQ,SAAA,CAAU,MAAA,EAAQ,CAAA;AAAA;AAEhF;AAGA,SAAS,KAAK,OAAA,EAAyB;AACrC,EAAA,IAAI,OAAA,CAAQ,WAAW,GAAG,CAAA,IAAK,QAAQ,QAAA,CAAS,GAAG,GAAG,OAAO,OAAA;AAC7D,EAAA,OAAO,IAAI,OAAO,CAAA,CAAA,CAAA;AACpB;AAGA,SAAS,YAAY,MAAA,EAAoC;AAIvD,EAAA,MAAM,MAAA,GAASC,uBAAA,CAAY,CAAC,CAAA,CAAE,SAAS,KAAK,CAAA;AAC5C,EAAA,MAAM,aAAa,MAAA,IAAU,oBAAA;AAC7B,EAAA,OAAO,CAAA,EAAG,UAAU,CAAA,CAAA,EAAI,MAAM,CAAA,CAAA;AAChC;;ACjBA,MAAM,aAAA,GAAgB,CAAC,EAAA,EAAI,GAAA,EAAK,GAAG,CAAA;AACnC,MAAM,kBAAA,GAAqB,GAAA;AAE3B,MAAM,aAAA,GAAgB,GAAA;AAGtB,MAAM,WAAoC,EAAE,EAAA,EAAI,OAAO,GAAA,EAAK,KAAA,EAAO,KAAK,IAAA,EAAK;AAG7E,MAAM,cAAc,CAAC,IAAA,KAA0BC,cAAA,CAAI,IAAA,CAAK,IAAI,CAAA,KAAM,CAAA;AAc3D,SAAS,SAAS,KAAA,EAAiC;AACxD,EAAA,MAAM,KAAA,GAAQ,KAAA,CAAM,KAAA,CAAM,wCAAwC,CAAA;AAClE,EAAA,IAAI,CAAC,OAAO,OAAO,IAAA;AACnB,EAAA,OAAO,EAAE,KAAA,EAAO,MAAA,CAAO,MAAM,CAAC,CAAC,GAAG,OAAA,EAAS,MAAA,CAAO,KAAA,CAAM,CAAC,CAAC,CAAA,EAAG,MAAA,EAAQ,OAAO,KAAA,CAAM,CAAC,CAAC,CAAA,EAAE;AACxF;AAEA,SAAS,YAAY,GAAA,EAAwB;AAC3C,EAAA,OAAO,CAAA,EAAG,IAAI,KAAK,CAAA,CAAA,EAAI,IAAI,OAAO,CAAA,CAAA,EAAI,IAAI,MAAM,CAAA,CAAA;AAClD;AAEA,SAAS,cAAc,KAAA,EAAwB;AAC7C,EAAA,MAAM,GAAA,GAAM,SAAS,KAAK,CAAA;AAC1B,EAAA,OAAO,GAAA,EAAK,KAAA,KAAU,CAAA,IAAK,GAAA,EAAK,OAAA,KAAY,CAAA;AAC9C;AAEA,MAAM,cAAA,GACJ,8GAAA;AACF,MAAM,aAAA,GAAgB,eAAA;AACtB,MAAM,yBAAA,GAA4B,4BAAA;AAClC,MAAM,iCAAA,GAAoC,iDAAA;AAC1C,MAAM,YAAA,GAAe,SAAA;AAErB,MAAM,YAAA,GAAe,CAAC,KAAA,KAA2B,cAAA,CAAe,KAAK,KAAK,CAAA;AAC1E,MAAM,WAAA,GAAc,CAAC,KAAA,KAA2B,aAAA,CAAc,KAAK,KAAK,CAAA;AAExE,SAAS,sBAAsB,KAAA,EAAwB;AACrD,EAAA,IAAI,CAAC,yBAAA,CAA0B,IAAA,CAAK,KAAK,GAAG,OAAO,KAAA;AACnD,EAAA,IAAI,iCAAA,CAAkC,IAAA,CAAK,KAAK,CAAA,EAAG,OAAO,KAAA;AAC1D,EAAA,IAAI,aAAA,CAAc,KAAK,CAAA,EAAG,OAAO,KAAA;AACjC,EAAA,OAAO,IAAA;AACT;AAOA,SAAS,iBAAA,GAA4B;AACnC,EAAA,OAAO,GAAGD,uBAAA,CAAY,CAAC,CAAA,CAAE,QAAA,CAAS,KAAK,CAAC,CAAA,QAAA,CAAA;AAC1C;AAcA,eAAsB,kBACpB,MAAA,EACqG;AACrG,EAAA,MAAM,EAAE,KAAA,EAAO,MAAA,EAAQ,OAAA,GAAU,IAAG,GAAI,MAAA;AAExC,EAAA,MAAM,SAAA,GAAY,MAAA,CAAO,SAAA,IAAa,EAAC;AAGvC,EAAA,MAAM,KAAA,GAAA,CAAS,OAAA,CAAQ,KAAA,IAAS,aAAA,EAAe,OAAO,CAAC,IAAA,KAAS,MAAA,CAAO,SAAA,CAAU,IAAI,CAAA,IAAK,IAAA,GAAO,CAAA,IAAK,OAAO,KAAK,CAAA;AAClH,EAAA,MAAM,mBAAA,GAAsB,QAAQ,mBAAA,IAAuB,kBAAA;AAC3D,EAAA,MAAM,SAAA,GAAY,QAAQ,SAAA,IAAa,IAAA;AACvC,EAAA,MAAM,YAAA,GAAe,QAAQ,YAAA,IAAgB,WAAA;AAC7C,EAAA,MAAM,KAAA,GAAQ,QAAQ,KAAA,IAAS,KAAA;AAC/B,EAAA,MAAM,iBAAA,GAAoB,QAAQ,iBAAA,IAAqB,KAAA;AACvD,EAAA,MAAM,WAAW,OAAA,CAAQ,QAAA;AACzB,EAAA,MAAM,SAAS,OAAA,CAAQ,MAAA;AACvB,EAAA,MAAM,QAAQ,OAAA,CAAQ,KAAA;AACtB,EAAA,MAAM,GAAA,GAAM,KAAA,GAAQ,CAAA,GAAI,IAAA,KAAoB,OAAA,CAAQ,IAAI,QAAA,EAAU,GAAG,IAAI,CAAA,GAAI,MAAM;AAAA,EAAC,CAAA;AAGpF,EAAA,MAAM,kBAAkB,OAAA,CAAQ,eAAA;AAChC,EAAA,MAAM,yBAAyB,OAAA,CAAQ,sBAAA;AACvC,EAAA,MAAM,aAAa,OAAA,CAAQ,UAAA;AAC3B,EAAA,MAAM,aAAA,GAAgB,OAAA,CAAQ,KAAA,EAAO,QAAA,IAAY,CAAA;AACjD,EAAA,MAAM,YAAA,GAAe,OAAA,CAAQ,KAAA,EAAO,OAAA,IAAW,GAAA;AAC/C,EAAA,MAAM,YAAA,GAAe,OAAA,CAAQ,KAAA,EAAO,OAAA,IAAW,aAAA;AAE/C,EAAA,MAAM,WAAA,GAAc,KAAK,GAAA,EAAI;AAE7B,EAAA,MAAM,SAAA,GAAY,UAAU,CAAC,CAAA;AAC7B,EAAA,IAAI,CAAC,SAAA,EAAW;AACd,IAAA,GAAA,CAAI,qBAAqB,CAAA;AACzB,IAAA,MAAME,WAAU,WAAA,CAAY,IAAI,CAAA,EAAG,CAAA,EAAG,QAAW,WAAW,CAAA;AAC5D,IAAA,OAAO,EAAE,UAAA,EAAY,aAAA,CAAc,eAAA,EAAiBA,QAAO,CAAA,EAAG,MAAA,EAAQ,KAAA,EAAO,IAAA,EAAM,CAAA,EAAG,UAAA,EAAY,KAAA,EAAM;AAAA,EAC1G;AACA,EAAA,GAAA,CAAI,CAAA,UAAA,EAAa,KAAK,CAAA,CAAA,EAAI,MAAM,QAAQ,SAAS,CAAA,WAAA,EAAc,SAAA,CAAU,MAAM,CAAA,CAAA,CAAG,CAAA;AAElF,EAAA,MAAM,aAAuB,EAAC;AAC9B,EAAA,MAAM,WAAqB,EAAC;AAE5B,EAAA,MAAM,YAAA,GAA6B;AAAA,IACjC,KAAA;AAAA,IACA,MAAA;AAAA,IACA,mBAAA;AAAA,IACA,SAAA;AAAA,IACA,YAAA;AAAA,IACA,QAAA;AAAA,IACA,MAAA;AAAA,IACA,GAAA;AAAA,IACA,oBAAoB,OAAA,CAAQ,kBAAA;AAAA,IAC5B,UAAA,EAAY,QAAQ,UAAA,IAAc,MAAA;AAAA,IAClC,QAAA,EAAU,QAAQ,QAAA,IAAY;AAAA,GAChC;AAIA,EAAA,MAAM,YAAA,GAAe,KAAA,GAAQ,aAAA,CAAsC,KAAA,EAAO,MAAM,CAAA,GAAI,IAAA;AACpF,EAAA,MAAM,aAAa,CAAA,EAAG,SAAS,CAAA,CAAA,EAAI,KAAK,IAAI,MAAM,CAAA,CAAA;AAClD,EAAA,IAAI,YAAA,EAAc;AAChB,IAAA,MAAM,YAAA,GAAe,MAAM,YAAA,CAAa,YAAA,EAAc,UAAU,CAAA;AAChE,IAAA,IAAI,YAAA,EAAc;AAChB,MAAA,GAAA,CAAI,CAAA,0BAAA,EAA6B,YAAA,CAAa,aAAa,CAAA,CAAE,CAAA;AAC7D,MAAA,OAAO,EAAE,YAAY,YAAA,EAAc,MAAA,EAAQ,MAAM,IAAA,EAAM,CAAA,EAAG,YAAY,KAAA,EAAM;AAAA,IAC9E;AAAA,EACF;AAEA,EAAA,MAAM,SAAA,GAAY,KAAA,GAAQ,aAAA,CAAsB,KAAA,EAAO,UAAU,CAAA,GAAI,IAAA;AACrE,EAAA,MAAM,aAAa,SAAA,GAAY,MAAM,YAAA,CAAa,SAAA,EAAW,SAAS,CAAA,GAAI,IAAA;AAE1E,EAAA,MAAM,eAAyB,EAAC;AAChC,EAAA,IAAI,UAAA,GAAa,CAAA;AACjB,EAAA,IAAI,YAAA,GAAe,CAAA;AACnB,EAAA,IAAI,mBAAA,GAAsB,CAAA;AAC1B,EAAA,IAAI,UAAA,GAAa,qBAAA;AACjB,EAAA,IAAI,kBAAA;AACJ,EAAA,IAAI,gBAAA;AACJ,EAAA,IAAI,YAAA,GAA4E,IAAA;AAGhF,EAAA,MAAM,mBAAA,GAAsB,CAAC,MAAA,KAC3B,MAAA,KAAW,sBACX,MAAA,KAAW,oBAAA,IACX,MAAA,KAAW,mBAAA,IACX,MAAA,KAAW,gBAAA;AAGb,EAAA,MAAM,aAAA,GAAgB,CAAC,YAAA,KACrB,YAAA,KAAiB,gBAAgB,YAAA,GAAe,CAAA,KAAM,eAAe,CAAA,CAAA,GAAK,YAAA;AAG5E,EAAA,MAAM,cAAA,GAAiB,OAAO,MAAA,EAAgB,IAAA,KAAuC;AACnF,IAAA,IAAI,SAAA,GAAY,MAAM,QAAA,CAAS,EAAE,GAAG,YAAA,EAAc,MAAA,EAAQ,MAAM,CAAA;AAChE,IAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,IAAK,aAAA,EAAe,CAAA,EAAA,EAAK;AACvC,MAAA,IAAI,UAAU,MAAA,KAAW,IAAA,IAAQ,CAAC,mBAAA,CAAoB,SAAA,CAAU,MAAM,CAAA,EAAG;AACzE,MAAA,MAAM,KAAA,GAAQ,cAAc,CAAC,CAAA;AAC7B,MAAA,GAAA,CAAI,CAAA,MAAA,EAAS,CAAC,CAAA,CAAA,EAAI,aAAa,CAAA,IAAA,EAAO,MAAM,CAAA,CAAA,EAAI,IAAI,CAAA,OAAA,EAAU,KAAK,CAAA,UAAA,EAAa,SAAA,CAAU,MAAM,CAAA,CAAA,CAAG,CAAA;AACnG,MAAA,MAAM,IAAI,OAAA,CAAQ,CAAC,MAAM,UAAA,CAAW,CAAA,EAAG,KAAK,CAAC,CAAA;AAC7C,MAAA,YAAA,EAAA;AACA,MAAA,SAAA,GAAY,MAAM,QAAA,CAAS,EAAE,GAAG,YAAA,EAAc,MAAA,EAAQ,MAAM,CAAA;AAAA,IAC9D;AACA,IAAA,OAAO,SAAA;AAAA,EACT,CAAA;AAEA,EAAA,KAAA,EAAO,KAAA,MAAW,UAAU,SAAA,EAAW;AACrC,IAAA,IAAI,UAAA,KAAe,MAAA,IAAa,UAAA,IAAc,UAAA,EAAY;AACxD,MAAA,YAAA,GAAe,cAAA;AACf,MAAA;AAAA,IACF;AACA,IAAA,YAAA,CAAa,KAAK,MAAM,CAAA;AACxB,IAAA,UAAA,EAAA;AAGA,IAAA,MAAM,cAAA,GACJ,MAAA,KAAW,SAAA,IAAa,UAAA,GAAa,CAAC,UAAA,EAAY,GAAG,KAAA,CAAM,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,KAAM,UAAU,CAAC,CAAA,GAAI,KAAA;AAEhG,IAAA,KAAA,MAAW,QAAQ,cAAA,EAAgB;AACjC,MAAA,IAAI,oBAAoB,MAAA,IAAa,IAAA,CAAK,GAAA,EAAI,GAAI,eAAe,eAAA,EAAiB;AAChF,QAAA,YAAA,GAAe,UAAA;AACf,QAAA,MAAM,KAAA;AAAA,MACR;AACA,MAAA,YAAA,EAAA;AACA,MAAA,GAAA,CAAI,CAAA,QAAA,EAAW,MAAM,CAAA,CAAA,EAAI,IAAI,CAAA,CAAE,CAAA;AAC/B,MAAA,MAAM,KAAA,GAAQ,MAAM,cAAA,CAAe,MAAA,EAAQ,IAAI,CAAA;AAC/C,MAAA,iBAAA,CAAkB,UAAA,EAAY,QAAA,EAAU,KAAA,EAAO,MAAA,EAAQ,IAAI,CAAA;AAC3D,MAAA,UAAA,GAAa,KAAA,CAAM,MAAA;AACnB,MAAA,IAAI,KAAA,CAAM,cAAA,KAAmB,MAAA,EAAW,kBAAA,GAAqB,KAAA,CAAM,cAAA;AACnE,MAAA,IAAI,KAAA,CAAM,YAAA,KAAiB,MAAA,EAAW,gBAAA,GAAmB,KAAA,CAAM,YAAA;AAI/D,MAAA,IAAI,KAAA,CAAM,WAAW,IAAA,EAAM;AACzB,QAAA,MAAMA,WAAU,WAAA,CAAY,YAAA,EAAc,UAAA,EAAY,YAAA,EAAc,QAAQ,WAAW,CAAA;AACvF,QAAA,MAAMC,WAAAA,GAAa,yBAAyB,KAAA,EAAO;AAAA,UACjD,UAAA,EAAY,oBAAoB,UAAA,GAAa,MAAA;AAAA,UAC7C,QAAA,EAAU,oBAAoB,QAAA,GAAW,MAAA;AAAA,UACzC,OAAA,EAAAD;AAAA,SACD,CAAA;AACD,QAAA,MAAM,YAAA,CAAa,YAAA,EAAc,UAAA,EAAYC,WAAU,CAAA;AACvD,QAAA,IAAI,WAAW,SAAA,EAAW,MAAM,YAAA,CAAa,SAAA,EAAW,WAAW,IAAI,CAAA;AACvE,QAAA,OAAO,EAAE,YAAAA,WAAAA,EAAY,MAAA,EAAQ,OAAO,IAAA,EAAM,UAAA,EAAY,eAAe,IAAA,EAAK;AAAA,MAC5E;AAGA,MAAA,mBAAA,GAAsB,mBAAA,CAAoB,KAAA,CAAM,MAAM,CAAA,GAAI,sBAAsB,CAAA,GAAI,CAAA;AACpF,MAAA,IAAI,sBAAA,KAA2B,MAAA,IAAa,mBAAA,IAAuB,sBAAA,EAAwB;AACzF,QAAA,YAAA,GAAe,sBAAA;AACf,QAAA,MAAM,KAAA;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACA,EAAA,IAAI,YAAA,EAAc,GAAA,CAAI,CAAA,eAAA,EAAkB,YAAY,CAAA,CAAE,CAAA;AAKtD,EAAA,GAAA,CAAI,CAAA,mCAAA,EAAmC,UAAU,CAAA,OAAA,EAAU,YAAY,CAAA,CAAA,CAAG,CAAA;AAC1E,EAAA,MAAM,UAAU,WAAA,CAAY,YAAA,EAAc,UAAA,EAAY,YAAA,EAAc,QAAW,WAAW,CAAA;AAC1F,EAAA,MAAM,UAAA,GAAqC;AAAA,IACzC,GAAG,aAAA,CAAc,UAAA,EAAY,OAAO,CAAA;AAAA,IACpC,GAAI,kBAAA,KAAuB,MAAA,GAAY,EAAE,cAAA,EAAgB,kBAAA,KAAuB,EAAC;AAAA,IACjF,GAAI,gBAAA,KAAqB,MAAA,GAAY,EAAE,YAAA,EAAc,gBAAA,KAAqB,EAAC;AAAA,IAC3E,GAAI,iBAAA,GAAoB,EAAE,UAAA,EAAY,CAAC,GAAG,UAAU,CAAA,EAAG,QAAA,EAAU,CAAC,GAAG,QAAQ,CAAA,KAAM;AAAC,GACtF;AACA,EAAA,OAAO,EAAE,UAAA,EAAY,MAAA,EAAQ,OAAO,IAAA,EAAM,CAAA,EAAG,YAAY,KAAA,EAAM;AACjE;AAEA,SAAS,WAAA,CACP,YAAA,EACA,UAAA,EACA,YAAA,EACA,YACA,WAAA,EACkB;AAClB,EAAA,OAAO;AAAA,IACL,UAAA;AAAA,IACA,YAAA;AAAA,IACA,YAAA,EAAc,CAAC,GAAG,YAAY,CAAA;AAAA,IAC9B,GAAI,UAAA,KAAe,MAAA,GAAY,EAAE,UAAA,KAAe,EAAC;AAAA,IACjD,eAAA,EAAiB,IAAA,CAAK,GAAA,EAAI,GAAI;AAAA,GAChC;AACF;AAEA,SAAS,iBAAA,CACP,UAAA,EACA,QAAA,EACA,KAAA,EACA,QACA,IAAA,EACM;AACN,EAAA,MAAM,MAAA,GAAS,CAAA,EAAG,MAAM,CAAA,CAAA,EAAI,IAAI,CAAA,CAAA;AAChC,EAAA,KAAA,MAAW,IAAA,IAAQ,MAAM,UAAA,EAAY,UAAA,CAAW,KAAK,CAAA,EAAG,MAAM,CAAA,IAAA,EAAO,IAAI,CAAA,CAAE,CAAA;AAC3E,EAAA,KAAA,MAAW,GAAA,IAAO,MAAM,QAAA,EAAU,QAAA,CAAS,KAAK,CAAA,EAAG,MAAM,CAAA,IAAA,EAAO,GAAG,CAAA,CAAE,CAAA;AACvE;AAEA,SAAS,aAAA,CAAc,QAAgB,OAAA,EAAmD;AACxF,EAAA,OAAO;AAAA,IACL,cAAA,EAAgB,KAAA;AAAA,IAChB,YAAA,EAAc,KAAA;AAAA,IACd,UAAA,EAAY,KAAA;AAAA,IACZ,aAAA,EAAe,KAAA;AAAA,IACf,UAAA,EAAY,KAAA;AAAA,IACZ,KAAA,EAAO,MAAA;AAAA,IACP,SAAA,EAAW,KAAK,GAAA,EAAI;AAAA,IACpB;AAAA,GACF;AACF;AAQA,SAAS,wBAAA,CAAyB,OAAoB,MAAA,EAAgD;AACpG,EAAA,MAAM,SAAS,KAAA,CAAM,MAAA;AACrB,EAAA,MAAM,GAAA,GAA8B;AAAA,IAClC,gBAAgB,MAAA,KAAW,IAAA;AAAA,IAC3B,YAAA,EAAc,MAAM,MAAA,KAAW,YAAA;AAAA,IAC/B,UAAA,EAAY,MAAM,UAAA,IAAc,KAAA;AAAA,IAChC,eAAe,MAAA,KAAW,IAAA;AAAA,IAC1B,YAAY,MAAA,KAAW,KAAA;AAAA,IACvB,KAAA,EAAO,MAAA,KAAW,IAAA,GAAO,MAAA,GAAY,KAAA,CAAM,MAAA;AAAA,IAC3C,SAAA,EAAW,KAAK,GAAA,EAAI;AAAA,IACpB,SAAS,MAAA,CAAO,OAAA;AAAA,IAChB,GAAI,MAAM,cAAA,KAAmB,MAAA,GAAY,EAAE,cAAA,EAAgB,KAAA,CAAM,cAAA,EAAe,GAAI,EAAC;AAAA,IACrF,GAAI,MAAM,YAAA,KAAiB,MAAA,GAAY,EAAE,YAAA,EAAc,KAAA,CAAM,YAAA,EAAa,GAAI;AAAC,GACjF;AACA,EAAA,IAAI,OAAO,UAAA,EAAY,GAAA,CAAI,aAAa,CAAC,GAAG,OAAO,UAAU,CAAA;AAC7D,EAAA,IAAI,OAAO,QAAA,EAAU,GAAA,CAAI,WAAW,CAAC,GAAG,OAAO,QAAQ,CAAA;AACvD,EAAA,OAAO,GAAA;AACT;AAEA,eAAe,YAAA,CACb,OACA,GAAA,EACmB;AACnB,EAAA,IAAI,CAAC,OAAO,OAAO,IAAA;AACnB,EAAA,IAAI;AACF,IAAA,MAAM,CAAA,GAAI,MAAM,KAAA,CAAM,GAAA,CAAI,GAAG,CAAA;AAC7B,IAAA,OAAO,CAAA,IAAK,IAAA;AAAA,EACd,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,IAAA;AAAA,EACT;AACF;AAEA,eAAe,YAAA,CACb,KAAA,EACA,GAAA,EACA,KAAA,EACe;AACf,EAAA,IAAI,CAAC,KAAA,EAAO;AACZ,EAAA,IAAI;AACF,IAAA,MAAM,KAAA,CAAM,GAAA,CAAI,GAAA,EAAK,KAAK,CAAA;AAAA,EAC5B,CAAA,CAAA,MAAQ;AAAA,EAER;AACF;AA0CA,eAAe,SAAS,CAAA,EAAsC;AAC5D,EAAA,OAAO,IAAI,mBAAA,CAAoB,CAAC,CAAA,CAAE,GAAA,EAAI;AACxC;AAcA,MAAM,mBAAA,CAAoB;AAAA,EAkDxB,YAA6B,CAAA,EAAgB;AAAhB,IAAA,IAAA,CAAA,CAAA,GAAA,CAAA;AA/C7B,IAAA,IAAA,CAAQ,MAAA,GAAS,EAAA;AACjB,IAAA,IAAA,CAAQ,QAAA,GAAW,KAAA;AACnB,IAAA,IAAA,CAAQ,gBAAA,GAAmB,CAAA;AAI3B;AAAA,IAAA,IAAA,CAAQ,YAAA,GAAe,KAAA;AAQvB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAAA,IAAA,CAAQ,iBAAA,GAAoB,KAAA;AAQ5B,IAAA,IAAA,CAAiB,aAAuB,EAAC;AACzC,IAAA,IAAA,CAAiB,WAAqB,EAAC;AAOvC;AAAA,IAAA,IAAA,CAAQ,kBAAA,GAAqB,KAAA;AAC7B,IAAA,IAAA,CAAQ,gBAAA,GAAmB,KAAA;AAI3B,IAAA,IAAA,CAAQ,SAAA,GAAuB,MAAA;AAC/B,IAAA,IAAA,CAAQ,WAAA,GAA2B,SAAA;AACnC,IAAA,IAAA,CAAQ,YAAA,GAA4B,SAAA;AACpC,IAAA,IAAA,CAAQ,aAAA,GAAgB,KAAA;AAMxB;AAAA;AAAA;AAAA;AAAA;AAAA,IAAA,IAAA,CAAQ,eAAA,GAAqE,IAAA;AA+D7E,IAAA,IAAA,CAAQ,MAAA,GAAS,CAAC,IAAA,KAAgC;AAChD,MAAA,IAAI,KAAK,QAAA,EAAU;AACnB,MAAA,IAAA,CAAK,cAAA,EAAe;AACpB,MAAA,IAAA,CAAK,UAAU,OAAO,IAAA,KAAS,QAAA,GAAW,IAAA,GAAO,KAAK,QAAA,EAAS;AAC/D,MAAA,IAAI,GAAA;AACJ,MAAA,OAAA,CAAQ,MAAM,IAAA,CAAK,MAAA,CAAO,OAAA,CAAQ,MAAM,OAAO,EAAA,EAAI;AACjD,QAAA,MAAM,OAAO,IAAA,CAAK,MAAA,CAAO,MAAM,CAAA,EAAG,GAAG,EAAE,IAAA,EAAK;AAC5C,QAAA,IAAA,CAAK,MAAA,GAAS,IAAA,CAAK,MAAA,CAAO,KAAA,CAAM,MAAM,CAAC,CAAA;AACvC,QAAA,IAAA,CAAK,YAAY,IAAI,CAAA;AAAA,MACvB;AAAA,IACF,CAAA;AAhEE,IAAA,MAAM,YAAA,GAAe,CAAC,QAAA,CAAS,QAAA,EAAU,QAAA,CAAS,IAAA,EAAM,QAAA,CAAS,QAAA,EAAU,QAAA,CAAS,QAAA,EAAU,QAAA,CAAS,MAAM,CAAA;AAC7G,IAAA,IAAA,CAAK,QAAQ,CAAC,GAAI,CAAA,CAAE,QAAA,EAAU,SAAS,YAAa,CAAA;AACpD,IAAA,IAAA,CAAK,KAAA,GAAQ,QAAA,CAAS,CAAA,CAAE,IAAI,CAAA,KAAM,IAAA;AAClC,IAAA,MAAM,aAAa,WAAA,CAAY,CAAA,CAAE,MAAM,CAAA,GAAI,SAAY,CAAA,CAAE,MAAA;AACzD,IAAA,IAAA,CAAK,UAAA,GAAa;AAAA,MAChB,MAAM,CAAA,CAAE,MAAA;AAAA,MACR,UAAA;AAAA,MACA,kBAAA,EAAoB,KAAA;AAAA,MACpB,UAAA,EAAY,SAAA;AAAA,MACZ,GAAI,OAAO,CAAA,CAAE,cAAc,QAAA,GAAW,CAAA,CAAE,YAAY;AAAC,KACvD;AACA,IAAA,IAAA,CAAK,UAAA,GAAa,CAAA,CAAE,kBAAA,GAAqB,CAAA,CAAE,kBAAA,CAAmB,EAAE,KAAA,EAAO,CAAA,CAAE,MAAM,CAAA,GAAI,iBAAA,EAAkB;AAAA,EACvG;AAAA,EAEA,GAAA,GAA4B;AAC1B,IAAA,OAAO,IAAI,OAAA,CAAqB,CAAC,OAAA,KAAY;AAC3C,MAAA,IAAA,CAAK,SAAA,GAAY,OAAA;AACjB,MAAA,IAAI;AACF,QAAA,IAAA,CAAK,OAAA,EAAQ;AACb,QAAA,IAAA,CAAK,kBAAA,EAAmB;AAAA,MAC1B,SAAS,KAAA,EAAO;AAId,QAAA,IAAA,CAAK,CAAA,CAAE,IAAI,CAAA,eAAA,EAAkB,KAAA,YAAiB,QAAQ,KAAA,CAAM,OAAA,GAAU,SAAS,CAAA,CAAE,CAAA;AACjF,QAAA,IAAA,CAAK,MAAA,CAAO,MAAM,kBAAkB,CAAA;AAAA,MACtC;AAAA,IACF,CAAC,CAAA;AAAA,EACH;AAAA,EAEQ,OAAA,GAAgB;AACtB,IAAA,MAAM,YAAY,MAAM;AACtB,MAAA,IAAA,CAAK,CAAA,CAAE,GAAA,CAAI,CAAA,aAAA,EAAgB,IAAA,CAAK,EAAE,MAAM,CAAA,CAAA,EAAI,IAAA,CAAK,CAAA,CAAE,IAAI,CAAA,EAAG,IAAA,CAAK,KAAA,GAAQ,WAAA,GAAc,EAAE,CAAA,CAAE,CAAA;AACzF,MAAA,IAAA,CAAK,MAAA,EAAQ,EAAA,CAAG,MAAA,EAAQ,IAAA,CAAK,MAAM,CAAA;AAAA,IACrC,CAAA;AACA,IAAA,IAAI,KAAK,KAAA,EAAO;AACd,MAAA,IAAA,CAAK,MAAA,GAASC,cAAA,CAAI,OAAA,CAAQ,EAAE,GAAG,IAAA,CAAK,UAAA,EAAY,IAAA,EAAM,IAAA,CAAK,CAAA,CAAE,IAAA,EAAK,EAAG,SAAS,CAAA;AAAA,IAChF,CAAA,MAAO;AACL,MAAA,IAAA,CAAK,MAAA,GAASH,cAAA,CAAI,OAAA,CAAQ,EAAE,IAAA,EAAM,IAAA,CAAK,CAAA,CAAE,MAAA,EAAQ,IAAA,EAAM,IAAA,CAAK,CAAA,CAAE,IAAA,IAAQ,SAAS,CAAA;AAAA,IACjF;AACA,IAAA,IAAA,CAAK,MAAA,CAAO,UAAA,CAAW,IAAA,CAAK,CAAA,CAAE,mBAAA,EAAqB,MAAM,IAAA,CAAK,MAAA,CAAO,IAAA,EAAM,gBAAgB,CAAC,CAAA;AAC5F,IAAA,IAAA,CAAK,MAAA,CAAO,GAAG,OAAA,EAAS,MAAM,KAAK,MAAA,CAAO,IAAA,EAAM,kBAAkB,CAAC,CAAA;AACnE,IAAA,IAAA,CAAK,MAAA,CAAO,GAAG,OAAA,EAAS,MAAM,KAAK,MAAA,CAAO,IAAA,EAAM,mBAAmB,CAAC,CAAA;AAAA,EACtE;AAAA,EAEQ,kBAAA,GAA2B;AACjC,IAAA,IAAA,CAAK,eAAA,GAAkB,UAAA,CAAW,MAAM,IAAA,CAAK,MAAA,CAAO,MAAM,oBAAoB,CAAA,EAAG,IAAA,CAAK,CAAA,CAAE,mBAAmB,CAAA;AAAA,EAC7G;AAAA,EAEQ,cAAA,GAAuB;AAC7B,IAAA,IAAI,IAAA,CAAK,SAAA,EAAW,YAAA,CAAa,IAAA,CAAK,SAAS,CAAA;AAC/C,IAAA,IAAA,CAAK,SAAA,GAAY,UAAA,CAAW,MAAM,IAAA,CAAK,MAAA,CAAO,MAAM,cAAc,CAAA,EAAG,IAAA,CAAK,CAAA,CAAE,mBAAmB,CAAA;AAAA,EACjG;AAAA,EAcQ,KAAK,GAAA,EAAmB;AAC9B,IAAA,IAAI,KAAK,QAAA,EAAU;AACnB,IAAA,IAAA,CAAK,QAAA,CAAS,KAAK,GAAG,CAAA;AACtB,IAAA,IAAA,CAAK,CAAA,CAAE,GAAA,CAAI,CAAA,OAAA,EAAK,GAAG,CAAA,CAAE,CAAA;AACrB,IAAA,IAAA,CAAK,MAAA,EAAQ,KAAA,CAAM,CAAA,EAAG,GAAG,CAAA;AAAA,CAAM,CAAA;AAAA,EACjC;AAAA,EAEQ,QAAA,GAAiB;AACvB,IAAA,IAAA,CAAK,gBAAA,EAAA;AACL,IAAA,MAAM,IAAA,GAAO,IAAA,CAAK,KAAA,CAAM,IAAA,CAAK,gBAAgB,CAAA;AAC7C,IAAA,IAAI,SAAS,MAAA,EAAW;AACtB,MAAA,IAAA,CAAK,MAAA,CAAO,MAAM,mBAAmB,CAAA;AACrC,MAAA;AAAA,IACF;AACA,IAAA,IAAA,CAAK,YAAY,IAAI,CAAA;AAAA,EACvB;AAAA,EAEQ,YAAY,IAAA,EAAsB;AACxC,IAAA,IAAI,KAAK,QAAA,EAAU;AACnB,IAAA,QAAQ,IAAA;AAAM,MACZ,KAAK,QAAA,CAAS,QAAA;AACZ,QAAA;AAAA;AAAA,MACF,KAAK,QAAA,CAAS,IAAA;AACZ,QAAA,IAAA,CAAK,IAAA,CAAK,CAAA,KAAA,EAAQ,IAAA,CAAK,CAAA,CAAE,YAAY,CAAA,CAAE,CAAA;AACvC,QAAA;AAAA,MACF,KAAK,QAAA,CAAS,IAAA;AACZ,QAAA,IAAA,CAAK,IAAA,CAAK,CAAA,KAAA,EAAQ,IAAA,CAAK,CAAA,CAAE,YAAY,CAAA,CAAE,CAAA;AACvC,QAAA;AAAA,MACF,KAAK,QAAA,CAAS,QAAA;AACZ,QAAA,IAAA,CAAK,eAAA,EAAgB;AACrB,QAAA;AAAA,MACF,KAAK,SAAS,QAAA,EAAU;AAKtB,QAAA,MAAM,IAAA,GAAO,IAAA,CAAK,CAAA,CAAE,MAAA,GAChB,oBAAA,CAAqB,IAAA,CAAK,CAAA,CAAE,MAAA,EAAQ,EAAE,KAAA,EAAO,IAAA,CAAK,CAAA,CAAE,OAAO,MAAA,EAAQ,IAAA,CAAK,CAAA,CAAE,MAAA,EAAQ,CAAA,GACjF,IAAA,CAAK,CAAA,CAAE,QAAA,EAAU,IAAA,IAAQ,CAAA,CAAA,EAAI,IAAA,CAAK,CAAA,CAAE,KAAK,CAAA,CAAA,EAAI,IAAA,CAAK,EAAE,MAAM,CAAA,CAAA,CAAA;AAC/D,QAAA,IAAA,CAAK,IAAA,CAAK,CAAA,UAAA,EAAa,IAAI,CAAA,CAAE,CAAA;AAC7B,QAAA;AAAA,MACF;AAAA,MACA,KAAK,QAAA,CAAS,MAAA;AACZ,QAAA,IAAA,CAAK,eAAA,EAAgB;AACrB,QAAA;AAAA;AACJ,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAgBQ,eAAA,GAAwB;AAC9B,IAAA,MAAM,IAAA,GAAO,KAAK,CAAA,CAAE,QAAA;AACpB,IAAA,MAAM,YAAA,GACJ,CAAC,IAAA,CAAK,KAAA,IAAS,IAAA,KAAS,YAAY,IAAA,KAAS,OAAA,IAAY,IAAA,KAAS,MAAA,IAAU,IAAA,CAAK,gBAAA,CAAA;AAEnF,IAAA,IAAI,CAAC,YAAA,EAAc;AACjB,MAAA,IAAA,CAAK,QAAA,EAAS;AACd,MAAA;AAAA,IACF;AACA,IAAA,IAAA,CAAK,KAAK,UAAU,CAAA;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUQ,YAAA,GAAqB;AAC3B,IAAA,MAAM,cAAc,IAAA,CAAK,MAAA;AACzB,IAAA,IAAI,CAAC,WAAA,EAAa;AAChB,MAAA,IAAA,CAAK,MAAA,CAAO,MAAM,oBAAoB,CAAA;AACtC,MAAA;AAAA,IACF;AAMA,IAAA,MAAM,SAAU,WAAA,CAA8D,kBAAA;AAC9E,IAAA,IAAI,OAAO,WAAW,UAAA,EAAY;AAChC,MAAA,MAAA,CAAO,IAAA,CAAK,aAAa,MAAM,CAAA;AAC/B,MAAA,MAAA,CAAO,IAAA,CAAK,aAAa,OAAO,CAAA;AAChC,MAAA,MAAA,CAAO,IAAA,CAAK,aAAa,OAAO,CAAA;AAChC,MAAA,MAAA,CAAO,IAAA,CAAK,aAAa,SAAS,CAAA;AAAA,IACpC;AACA,IAAA,IAAI;AACF,MAAA,WAAA,CAAY,WAAW,CAAC,CAAA;AAAA,IAC1B,CAAA,CAAA,MAAQ;AAAA,IAER;AAEA,IAAA,IAAA,CAAK,YAAA,GAAe,IAAA;AACpB,IAAA,MAAM,UAAA,GAAa,YAAY,IAAA,CAAK,CAAA,CAAE,MAAM,CAAA,GAAI,MAAA,GAAY,KAAK,CAAA,CAAE,MAAA;AAEnE,IAAA,MAAM,SAAA,GAAYG,cAAA,CAAI,OAAA,CAAQ,EAAE,GAAG,IAAA,CAAK,UAAA,EAAY,MAAA,EAAQ,WAAA,EAAa,UAAA,EAAW,EAAG,MAAM;AAC3F,MAAA,IAAA,CAAK,YAAA,GAAe,KAAA;AACpB,MAAA,IAAA,CAAK,KAAA,GAAQ,IAAA;AAIb,MAAA,IAAA,CAAK,MAAA,GAAS,EAAA;AACd,MAAA,IAAA,CAAK,gBAAA,GAAmB,KAAA;AACxB,MAAA,IAAA,CAAK,kBAAA,GAAqB,KAAA;AAC1B,MAAA,IAAA,CAAK,iBAAA,GAAoB,IAAA;AACzB,MAAA,IAAA,CAAK,IAAA,CAAK,CAAA,KAAA,EAAQ,IAAA,CAAK,CAAA,CAAE,YAAY,CAAA,CAAE,CAAA;AAAA,IACzC,CAAC,CAAA;AAED,IAAA,IAAA,CAAK,MAAA,GAAS,SAAA;AACd,IAAA,IAAA,CAAK,MAAA,CAAO,EAAA,CAAG,MAAA,EAAQ,IAAA,CAAK,MAAM,CAAA;AAGlC,IAAA,IAAA,CAAK,MAAA,CAAO,EAAA,CAAG,OAAA,EAAS,MAAM;AAC5B,MAAA,IAAA,CAAK,MAAA,CAAO,IAAA,EAAM,IAAA,CAAK,YAAA,GAAe,yBAAyB,kBAAkB,CAAA;AAAA,IACnF,CAAC,CAAA;AACD,IAAA,IAAA,CAAK,MAAA,CAAO,GAAG,OAAA,EAAS,MAAM,KAAK,MAAA,CAAO,IAAA,EAAM,mBAAmB,CAAC,CAAA;AACpE,IAAA,IAAA,CAAK,MAAA,CAAO,UAAA,CAAW,IAAA,CAAK,CAAA,CAAE,mBAAA,EAAqB,MAAM,IAAA,CAAK,MAAA,CAAO,IAAA,EAAM,gBAAgB,CAAC,CAAA;AAAA,EAC9F;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,eAAA,GAAwB;AAC9B,IAAA,MAAM,eAAA,GAAkB,KAAK,CAAA,CAAE,UAAA,KAAe,WAAY,IAAA,CAAK,CAAA,CAAE,UAAA,KAAe,MAAA,IAAU,IAAA,CAAK,kBAAA;AAE/F,IAAA,MAAM,OAAA,GAAU,YAAY,IAAA,CAAK,CAAA,CAAE,KAAK,CAAA,CAAA,EAAI,IAAA,CAAK,EAAE,MAAM,CAAA,CAAA,CAAA;AAEzD,IAAA,IAAI,eAAA,EAAiB;AAGnB,MAAA,IAAA,CAAK,aAAA,GAAgB,IAAA;AACrB,MAAA,MAAM,WAAW,CAAA,SAAA,EAAY,IAAA,CAAK,UAAU,CAAA,CAAA,EAAI,IAAA,CAAK,EAAE,MAAM,CAAA,CAAA,CAAA;AAC7D,MAAA,MAAM,OAAA,GAAU,MAAA;AAChB,MAAA,IAAA,CAAK,QAAA,CAAS,IAAA,CAAK,OAAA,EAAS,QAAA,EAAU,OAAO,CAAA;AAC7C,MAAA,IAAA,CAAK,CAAA,CAAE,GAAA,CAAI,CAAA,OAAA,EAAK,OAAO,CAAA,CAAE,CAAA;AACzB,MAAA,IAAA,CAAK,CAAA,CAAE,GAAA,CAAI,CAAA,OAAA,EAAK,QAAQ,CAAA,CAAE,CAAA;AAC1B,MAAA,IAAA,CAAK,CAAA,CAAE,GAAA,CAAI,CAAA,OAAA,EAAK,OAAO,CAAA,CAAE,CAAA;AACzB,MAAA,IAAA,CAAK,MAAA,EAAQ,KAAA,CAAM,CAAA,EAAG,OAAO,CAAA;AAAA,EAAO,QAAQ,CAAA;AAAA,EAAO,OAAO,CAAA;AAAA,CAAM,CAAA;AAChE,MAAA,IAAA,CAAK,SAAA,GAAY,WAAA;AACjB,MAAA;AAAA,IACF;AAGA,IAAA,IAAA,CAAK,aAAA,GAAgB,KAAA;AACrB,IAAA,IAAA,CAAK,KAAK,OAAO,CAAA;AACjB,IAAA,IAAA,CAAK,SAAA,GAAY,WAAA;AAAA,EACnB;AAAA,EAEQ,YAAY,IAAA,EAAoB;AACtC,IAAA,IAAI,KAAK,QAAA,EAAU;AACnB,IAAA,IAAA,CAAK,UAAA,CAAW,KAAK,IAAI,CAAA;AACzB,IAAA,IAAA,CAAK,CAAA,CAAE,GAAA,CAAI,CAAA,OAAA,EAAK,IAAI,CAAA,CAAE,CAAA;AAItB,IAAA,MAAM,OAAA,GAAU,IAAA,CAAK,KAAA,CAAM,CAAA,EAAG,CAAC,CAAA;AAC/B,IAAA,MAAM,WAAA,GAAc,UAAU,IAAA,CAAK,OAAO,IAAI,QAAA,CAAS,OAAA,EAAS,EAAE,CAAA,GAAI,IAAA;AACtE,IAAA,IAAI,WAAA,KAAgB,IAAA,EAAM,IAAA,CAAK,gBAAA,GAAmB,WAAA;AAClD,IAAA,MAAM,GAAA,GAAM,SAAS,IAAI,CAAA;AACzB,IAAA,IAAI,GAAA,EAAK,IAAA,CAAK,kBAAA,GAAqB,WAAA,CAAY,GAAG,CAAA;AAOlD,IAAA,IAAI,IAAA,CAAK,SAAA,KAAc,MAAA,IAAU,IAAA,CAAK,cAAc,WAAA,EAAa;AAC/D,MAAA,IAAI,YAAA,CAAa,IAAI,CAAA,EAAG;AACtB,QAAA,IAAA,CAAK,MAAA,CAAO,MAAM,aAAa,CAAA;AAC/B,QAAA;AAAA,MACF;AACA,MAAA,IAAI,WAAA,CAAY,IAAI,CAAA,EAAG;AACrB,QAAA,IAAA,CAAK,cAAA,GAAiB,KAAA;AACtB,QAAA,IAAA,CAAK,MAAA,CAAO,OAAO,YAAY,CAAA;AAC/B,QAAA;AAAA,MACF;AACA,MAAA,IAAI,qBAAA,CAAsB,IAAI,CAAA,EAAG;AAC/B,QAAA,IAAA,CAAK,cAAA,GAAiB,KAAA;AACtB,QAAA,IAAA,CAAK,MAAA,CAAO,OAAO,WAAW,CAAA;AAC9B,QAAA;AAAA,MACF;AAAA,IACF;AAIA,IAAA,IAAI,YAAA,CAAa,IAAA,CAAK,IAAI,CAAA,EAAG;AAC3B,MAAA,MAAM,IAAA,GAAO,IAAA,CAAK,KAAA,CAAM,IAAA,CAAK,gBAAgB,CAAA;AAK7C,MAAA,MAAM,UAAA,GACJ,IAAA,KAAS,QAAA,CAAS,IAAA,IAAQ,IAAA,KAAS,SAAS,IAAA,IAAS,IAAA,KAAS,QAAA,CAAS,QAAA,IAAY,IAAA,CAAK,iBAAA;AAC1F,MAAA,IAAI,UAAA,IAAc,IAAA,CAAK,UAAA,CAAW,MAAM,CAAA,EAAG;AACzC,QAAA,MAAM,KAAA,GAAQ,KAAK,WAAA,EAAY;AAC/B,QAAA,IAAI,KAAA,CAAM,QAAA,CAAS,YAAY,CAAA,OAAQ,kBAAA,GAAqB,IAAA;AAC5D,QAAA,IAAI,KAAA,CAAM,QAAA,CAAS,UAAU,CAAA,OAAQ,gBAAA,GAAmB,IAAA;AAAA,MAC1D;AACA,MAAA;AAAA,IACF;AAEA,IAAA,IAAI,gBAAgB,IAAA,EAAM;AACxB,MAAA,IAAA,CAAK,MAAA,CAAO,MAAM,uBAAuB,CAAA;AACzC,MAAA;AAAA,IACF;AAEA,IAAA,IAAA,CAAK,QAAA,CAAS,aAAa,IAAI,CAAA;AAAA,EACjC;AAAA,EAEQ,QAAA,CAAS,MAAc,IAAA,EAAoB;AACjD,IAAA,MAAM,IAAA,GAAO,IAAA,CAAK,KAAA,CAAM,IAAA,CAAK,gBAAgB,CAAA;AAG7C,IAAA,IAAI,IAAA,CAAK,SAAA,KAAc,MAAA,IAAU,IAAA,KAAS,SAAS,MAAA,EAAQ;AACzD,MAAA,IAAA,CAAK,mBAAA,CAAoB,MAAM,IAAI,CAAA;AACnC,MAAA;AAAA,IACF;AAEA,IAAA,QAAQ,IAAA;AAAM,MACZ,KAAK,QAAA,CAAS,QAAA;AACZ,QAAA,IAAI,IAAA,KAAS,GAAA,EAAK,IAAA,CAAK,QAAA,EAAS;AAAA,aAC3B,IAAA,CAAK,MAAA,CAAO,IAAA,EAAM,aAAa,CAAA;AACpC,QAAA;AAAA,MACF,KAAK,QAAA,CAAS,IAAA;AACZ,QAAA,IAAI,IAAA,KAAS,GAAA,EAAK,IAAA,CAAK,QAAA,EAAS;AAAA,aAC3B,IAAA,CAAK,MAAA,CAAO,IAAA,EAAM,aAAa,CAAA;AACpC,QAAA;AAAA,MACF,KAAK,QAAA,CAAS,IAAA;AACZ,QAAA,IAAI,IAAA,KAAS,GAAA,EAAK,IAAA,CAAK,QAAA,EAAS;AAAA,aAC3B,IAAA,CAAK,MAAA,CAAO,IAAA,EAAM,aAAa,CAAA;AACpC,QAAA;AAAA,MACF,KAAK,QAAA,CAAS,QAAA;AAMZ,QAAA,IAAI,KAAK,iBAAA,EAAmB;AAC1B,UAAA,IAAA,CAAK,iBAAA,GAAoB,KAAA;AACzB,UAAA,IAAI,IAAA,KAAS,GAAA,EAAK,IAAA,CAAK,QAAA,EAAS;AAAA,eAC3B,IAAA,CAAK,MAAA,CAAO,IAAA,EAAM,aAAa,CAAA;AACpC,UAAA;AAAA,QACF;AACA,QAAA,IAAI,SAAS,GAAA,EAAK;AAChB,UAAA,IAAA,CAAK,YAAA,EAAa;AAAA,QACpB,CAAA,MAAO;AACL,UAAA,IAAA,CAAK,MAAA,CAAO,MAAM,oBAAoB,CAAA;AAAA,QACxC;AACA,QAAA;AAAA,MACF,KAAK,QAAA,CAAS,QAAA;AACZ,QAAA,IAAI,IAAA,KAAS,GAAA,EAAK,IAAA,CAAK,QAAA,EAAS;AAAA,aAC3B,IAAA,CAAK,MAAA,CAAO,IAAA,EAAM,oBAAoB,CAAA;AAC3C,QAAA;AAAA,MACF,KAAK,QAAA,CAAS,MAAA;AAGZ,QAAA,IAAA,CAAK,mBAAA,CAAoB,MAAM,IAAI,CAAA;AACnC,QAAA;AAAA;AACJ,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,mBAAA,CAAoB,MAAc,IAAA,EAAoB;AAC5D,IAAA,IAAI,IAAA,CAAK,cAAc,WAAA,EAAa;AAClC,MAAA,IAAA,CAAK,WAAA,GAAc,aAAa,IAAI,CAAA;AAGpC,MAAA,IAAI,SAAS,GAAA,IAAO,IAAA,KAAS,GAAA,IAAO,WAAA,CAAY,IAAI,CAAA,EAAG;AACrD,QAAA,IAAA,CAAK,cAAA,GAAiB,KAAA;AACtB,QAAA,IAAI,KAAK,aAAA,EAAe;AACtB,UAAA,IAAA,CAAK,eAAA,GAAkB,EAAE,MAAA,EAAQ,KAAA,EAAO,QAAQ,YAAA,EAAa;AAC7D,UAAA,IAAA,CAAK,SAAA,GAAY,YAAA;AACjB,UAAA;AAAA,QACF;AACA,QAAA,IAAA,CAAK,MAAA,CAAO,OAAO,YAAY,CAAA;AAC/B,QAAA;AAAA,MACF;AAGA,MAAA,IAAI,IAAA,CAAK,gBAAgB,aAAA,EAAe;AACtC,QAAA,IAAI,KAAK,aAAA,EAAe;AACtB,UAAA,IAAA,CAAK,eAAA,GAAkB,EAAE,MAAA,EAAQ,IAAA,EAAM,QAAQ,mBAAA,EAAoB;AACnE,UAAA,IAAA,CAAK,SAAA,GAAY,YAAA;AACjB,UAAA;AAAA,QACF;AACA,QAAA,IAAA,CAAK,MAAA,CAAO,MAAM,mBAAmB,CAAA;AACrC,QAAA;AAAA,MACF;AAIA,MAAA,IAAI,IAAA,CAAK,gBAAgB,aAAA,EAAe;AACtC,QAAA,MAAM,MAAA,GAAS,qBAAA,CAAsB,IAAI,CAAA,GAAI,WAAA,GAAc,WAAA;AAC3D,QAAA,MAAM,MAAA,GAAS,MAAA,KAAW,WAAA,GAAc,KAAA,GAAQ,IAAA;AAChD,QAAA,IAAA,CAAK,cAAA,GAAiB,KAAA;AACtB,QAAA,IAAI,KAAK,aAAA,EAAe;AACtB,UAAA,IAAA,CAAK,eAAA,GAAkB,EAAE,MAAA,EAAQ,MAAA,EAAO;AACxC,UAAA,IAAA,CAAK,SAAA,GAAY,YAAA;AACjB,UAAA;AAAA,QACF;AACA,QAAA,IAAA,CAAK,MAAA,CAAO,QAAQ,MAAM,CAAA;AAC1B,QAAA;AAAA,MACF;AAGA,MAAA,IAAI,KAAK,aAAA,EAAe;AACtB,QAAA,IAAA,CAAK,SAAA,GAAY,YAAA;AAAA,MACnB,CAAA,MAAO;AACL,QAAA,IAAA,CAAK,IAAA,CAAK,YAAY,IAAA,CAAK,UAAU,IAAI,IAAA,CAAK,CAAA,CAAE,MAAM,CAAA,CAAA,CAAG,CAAA;AACzD,QAAA,IAAA,CAAK,SAAA,GAAY,YAAA;AAAA,MACnB;AACA,MAAA;AAAA,IACF;AAEA,IAAA,IAAI,IAAA,CAAK,cAAc,YAAA,EAAc;AACnC,MAAA,IAAA,CAAK,YAAA,GAAe,aAAa,IAAI,CAAA;AACrC,MAAA,IAAI,KAAK,aAAA,EAAe;AACtB,QAAA,IAAA,CAAK,SAAA,GAAY,MAAA;AAAA,MACnB,CAAA,MAAO;AACL,QAAA,IAAA,CAAK,KAAK,MAAM,CAAA;AAChB,QAAA,IAAA,CAAK,SAAA,GAAY,MAAA;AAAA,MACnB;AACA,MAAA;AAAA,IACF;AAEA,IAAA,IAAI,IAAA,CAAK,cAAc,MAAA,EAAQ;AAG7B,MAAA,IAAI,KAAK,eAAA,EAAiB;AAExB,QAAA,IAAA,CAAK,OAAO,IAAA,CAAK,eAAA,CAAgB,MAAA,EAAQ,IAAA,CAAK,gBAAgB,MAAM,CAAA;AACpE,QAAA;AAAA,MACF;AACA,MAAA,IAAA,CAAK,eAAA,EAAgB;AACrB,MAAA;AAAA,IACF;AAAA,EACF;AAAA;AAAA,EAGQ,eAAA,GAAwB;AAC9B,IAAA,IAAI,IAAA,CAAK,WAAA,KAAgB,QAAA,IAAY,IAAA,CAAK,iBAAiB,QAAA,EAAU;AACnE,MAAA,IAAA,CAAK,cAAA,GAAiB,IAAA;AACtB,MAAA,IAAA,CAAK,MAAA,CAAO,MAAM,OAAO,CAAA;AAAA,IAC3B,CAAA,MAAA,IAAW,IAAA,CAAK,WAAA,KAAgB,QAAA,EAAU;AACxC,MAAA,IAAA,CAAK,cAAA,GAAiB,KAAA;AACtB,MAAA,IAAA,CAAK,MAAA,CAAO,MAAM,OAAO,CAAA;AAAA,IAC3B,CAAA,MAAA,IAAW,IAAA,CAAK,WAAA,KAAgB,aAAA,EAAe;AAC7C,MAAA,IAAA,CAAK,cAAA,GAAiB,KAAA;AACtB,MAAA,IAAA,CAAK,MAAA,CAAO,OAAO,WAAW,CAAA;AAAA,IAChC,CAAA,MAAA,IAAW,IAAA,CAAK,WAAA,KAAgB,aAAA,EAAe;AAC7C,MAAA,IAAA,CAAK,MAAA,CAAO,MAAM,mBAAmB,CAAA;AAAA,IACvC,CAAA,MAAO;AACL,MAAA,IAAA,CAAK,MAAA,CAAO,MAAM,WAAW,CAAA;AAAA,IAC/B;AAAA,EACF;AAAA,EAEQ,MAAA,CAAO,QAAwB,MAAA,EAAsB;AAC3D,IAAA,IAAI,KAAK,QAAA,EAAU;AACnB,IAAA,IAAA,CAAK,QAAA,GAAW,IAAA;AAChB,IAAA,IAAA,CAAK,CAAA,CAAE,IAAI,CAAA,EAAG,IAAA,CAAK,EAAE,IAAI,CAAA,EAAA,EAAK,MAAM,CAAA,CAAE,CAAA;AAEtC,IAAA,IAAI,IAAA,CAAK,eAAA,EAAiB,YAAA,CAAa,IAAA,CAAK,eAAe,CAAA;AAC3D,IAAA,IAAI,IAAA,CAAK,SAAA,EAAW,YAAA,CAAa,IAAA,CAAK,SAAS,CAAA;AAE/C,IAAA,IAAI;AACF,MAAA,IAAA,CAAK,MAAA,EAAQ,WAAW,CAAC,CAAA;AAAA,IAC3B,CAAA,CAAA,MAAQ;AAAA,IAER;AACA,IAAA,IAAI;AACF,MAAA,IAAA,CAAK,MAAA,EAAQ,MAAM,UAAU,CAAA;AAAA,IAC/B,CAAA,CAAA,MAAQ;AAAA,IAER;AACA,IAAA,MAAM,QAAQ,UAAA,CAAW,MAAM,KAAK,MAAA,EAAQ,OAAA,IAAW,aAAa,CAAA;AACpE,IAAA,KAAA,CAAM,KAAA,IAAQ;AAEd,IAAA,IAAA,CAAK,SAAA,CAAU;AAAA,MACb,MAAA;AAAA,MACA,MAAA;AAAA,MACA,GAAI,KAAK,kBAAA,KAAuB,MAAA,GAAY,EAAE,cAAA,EAAgB,IAAA,CAAK,kBAAA,EAAmB,GAAI,EAAC;AAAA,MAC3F,GAAI,KAAK,gBAAA,KAAqB,MAAA,GAAY,EAAE,YAAA,EAAc,IAAA,CAAK,gBAAA,EAAiB,GAAI,EAAC;AAAA,MACrF,GAAI,KAAK,cAAA,KAAmB,MAAA,GAAY,EAAE,UAAA,EAAY,IAAA,CAAK,cAAA,EAAe,GAAI,EAAC;AAAA,MAC/E,YAAY,IAAA,CAAK,UAAA;AAAA,MACjB,UAAU,IAAA,CAAK;AAAA,KAChB,CAAA;AAAA,EACH;AACF;AAEA,SAAS,aAAa,IAAA,EAA2B;AAC/C,EAAA,IAAI,IAAA,KAAS,GAAA,IAAO,IAAA,KAAS,GAAA,EAAK,OAAO,QAAA;AACzC,EAAA,IAAI,IAAA,IAAQ,GAAA,IAAO,IAAA,GAAO,GAAA,EAAK,OAAO,aAAA;AACtC,EAAA,OAAO,aAAA;AACT;;ACl7BO,MAAM,wBAAA,CAAwD;AAAA,EAA9D,WAAA,GAAA;AACL,IAAA,IAAA,CAAS,QAA4B,EAAC;AAAA,EAAA;AAAA,EAEtC,MAAM,MAAA,CACJ,IAAA,EACA,EAAA,EACA,UAAA,EACY;AACZ,IAAA,MAAM,SAAA,GAAY,KAAK,GAAA,EAAI;AAC3B,IAAA,IAAI;AACF,MAAA,MAAM,KAAA,GAAQ,MAAM,EAAA,EAAG;AACvB,MAAA,IAAA,CAAK,MAAM,IAAA,CAAK;AAAA,QACd,IAAA;AAAA,QACA,SAAA;AAAA,QACA,UAAA,EAAY,IAAA,CAAK,GAAA,EAAI,GAAI,SAAA;AAAA,QACzB,EAAA,EAAI,IAAA;AAAA,QACJ,OAAA,EAAS,WAAW,KAAK;AAAA,OAC1B,CAAA;AACD,MAAA,OAAO,KAAA;AAAA,IACT,SAAS,KAAA,EAAO;AACd,MAAA,IAAA,CAAK,MAAM,IAAA,CAAK;AAAA,QACd,IAAA;AAAA,QACA,SAAA;AAAA,QACA,UAAA,EAAY,IAAA,CAAK,GAAA,EAAI,GAAI,SAAA;AAAA,QACzB,EAAA,EAAI,KAAA;AAAA,QACJ,OAAA,EAAS,EAAE,KAAA,EAAO,KAAA,YAAiB,QAAQ,KAAA,CAAM,OAAA,GAAU,MAAA,CAAO,KAAK,CAAA;AAAE,OAC1E,CAAA;AACD,MAAA,MAAM,KAAA;AAAA,IACR;AAAA,EACF;AAAA,EAEA,KAAK,IAAA,EAA8B;AACjC,IAAA,IAAA,CAAK,KAAA,CAAM,KAAK,IAAI,CAAA;AAAA,EACtB;AACF;AAGO,MAAM,cAAA,GAAsC;AAAA,EACjD,MAAM,MAAA,CAAO,KAAA,EAAO,EAAA,EAAI;AACtB,IAAA,OAAO,EAAA,EAAG;AAAA,EACZ,CAAA;AAAA,EACA,IAAA,GAAO;AAAA,EAEP;AACF,CAAA;;;;ACnEA,MAAM,YAAA,GAAe;AAAA,EACnB,UAAA,EAAY,yBAAA;AAAA,EACZ,SAAA,EAAW,kBAAA;AAAA,EACX,WAAA,EAAa,qBAAA;AAAA,EACb,YAAA,EAAc,2BAAA;AAAA,EACd,cAAA,EAAgB,uBAAA;AAAA,EAChB,MAAA,EAAQ,wBAAA;AAAA,EACR,UAAA,EAAY,0BAAA;AAAA,EACZ,QAAA,EAAU;AACZ,CAAA;AAEA,MAAM,QAAA,GAAW,EAAE,GAAG,YAAA,EAAc,UAAU,eAAA,EAAgB;AAE9D,MAAM,QAAA,GAAW,EAAE,GAAG,YAAA,EAAc,UAAU,+BAAA,EAAgC;AAE9E,MAAM,OAAA,GAAU;AAAA,EACd,GAAG,YAAA;AAAA,EACH,WAAA,EAAa,sBAAA;AAAA,EACb,SAAA,EAAW,uBAAA;AAAA,EACX,WAAA,EAAa,sBAAA;AAAA,EACb,QAAA,EAAU;AACZ,CAAA;AAEA,MAAM,OAAA,GAAU;AAAA,EACd,GAAG,YAAA;AAAA,EACH,MAAA,EAAQ,sBAAA;AAAA,EACR,cAAA,EAAgB,+CAAA;AAAA,EAChB,QAAA,EAAU;AACZ,CAAA;AAEA,MAAM,OAAA,GAAU;AAAA,EACd,GAAG,YAAA;AAAA,EACH,UAAA,EAAY,oBAAA;AAAA,EACZ,SAAA,EAAW,kBAAA;AAAA,EACX,cAAA,EAAgB,kBAAA;AAAA,EAChB,MAAA,EAAQ,cAAA;AAAA,EACR,QAAA,EAAU;AACZ,CAAA;AAEA,MAAM,OAAA,GAAU;AAAA,EACd,GAAG,YAAA;AAAA,EACH,UAAA,EAAY,2BAAA;AAAA,EACZ,UAAA,EAAY;AACd,CAAA;AAEA,MAAM,OAAA,GAAU;AAAA,EACd,GAAG,YAAA;AAAA,EACH,UAAA,EAAY,oBAAA;AAAA,EACZ,cAAA,EAAgB,yBAAA;AAAA,EAChB,WAAA,EAAa,oBAAA;AAAA,EACb,QAAA,EAAU;AACZ,CAAA;AAEA,MAAM,OAAA,GAAU;AAAA,EACd,GAAG,YAAA;AAAA,EACH,QAAA,EAAU,eAAA;AAAA,EACV,WAAA,EAAa;AACf,CAAA;AAEA,MAAM,OAAA,GAAU;AAAA,EACd,GAAG,YAAA;AAAA,EACH,UAAA,EAAY,uBAAA;AAAA,EACZ,SAAA,EAAW,sBAAA;AAAA,EACX,MAAA,EAAQ,uBAAA;AAAA,EACR,UAAA,EAAY;AACd,CAAA;AAEA,MAAM,OAAA,GAAU;AAAA,EACd,GAAG,YAAA;AAAA,EACH,UAAA,EAAY,gCAAA;AAAA,EACZ,UAAA,EAAY,YAAA;AAAA,EACZ,QAAA,EAAU;AACZ,CAAA;AAEA,MAAM,OAAA,GAAU;AAAA,EACd,GAAG,YAAA;AAAA,EACH,UAAA,EAAY,6BAAA;AAAA,EACZ,MAAA,EAAQ,iCAAA;AAAA,EACR,cAAA,EAAgB,qBAAA;AAAA,EAChB,UAAA,EAAY;AACd,CAAA;AAEA,MAAM,OAAA,GAAU;AAAA,EACd,GAAG,YAAA;AAAA,EACH,UAAA,EAAY,uBAAA;AAAA,EACZ,UAAA,EAAY;AACd,CAAA;AAEA,MAAM,OAAA,GAAU;AAAA,EACd,GAAG,YAAA;AAAA,EACH,UAAA,EAAY,uBAAA;AAAA,EACZ,SAAA,EAAW,sCAAA;AAAA,EACX,QAAA,EAAU;AACZ,CAAA;AAEA,MAAM,OAAA,GAAU;AAAA,EACd,GAAG,YAAA;AAAA,EACH,UAAA,EAAY,2CAAA;AAAA,EACZ,MAAA,EAAQ;AACV,CAAA;AAEA,MAAM,OAAA,GAAU;AAAA,EACd,GAAG,YAAA;AAAA,EACH,UAAA,EAAY,6BAAA;AAAA,EACZ,UAAA,EAAY,eAAA;AAAA,EACZ,QAAA,EAAU;AACZ,CAAA;AAEA,MAAM,OAAA,GAAU;AAAA,EACd,GAAG,YAAA;AAAA,EACH,UAAA,EAAY,yBAAA;AAAA,EACZ,MAAA,EAAQ,8BAAA;AAAA,EACR,QAAA,EAAU,gCAAA;AAAA,EACV,WAAA,EAAa;AACf,CAAA;AAEA,MAAM,OAAA,GAAU;AAAA,EACd,GAAG,YAAA;AAAA,EACH,UAAA,EAAY,oBAAA;AAAA,EACZ,QAAA,EAAU;AACZ,CAAA;AAEA,MAAM,OAAA,GAAU;AAAA,EACd,GAAG,YAAA;AAAA,EACH,UAAA,EAAY,oBAAA;AAAA,EACZ,QAAA,EAAU,gBAAA;AAAA,EACV,UAAA,EAAY,mBAAA;AAAA,EACZ,WAAA,EAAa;AACf,CAAA;AAEA,MAAM,OAAA,GAAU;AAAA,EACd,GAAG,YAAA;AAAA,EACH,UAAA,EAAY,yBAAA;AAAA,EACZ,QAAA,EAAU;AACZ,CAAA;AAEA,MAAM,OAAA,GAAU;AAAA,EACd,GAAG,YAAA;AAAA,EACH,UAAA,EAAY,sBAAA;AAAA,EACZ,UAAA,EAAY,iBAAA;AAAA,EACZ,QAAA,EAAU;AACZ,CAAA;AAEA,MAAM,SAAA,GAAY;AAAA,EAChB,GAAG,YAAA;AAAA,EACH,QAAA,EAAU;AACZ,CAAA;AAEA,MAAM,OAAA,GAAU;AAAA,EACd,GAAG,YAAA;AAAA,EACH,UAAA,EAAY,sBAAA;AAAA,EACZ,UAAA,EAAY,0BAAA;AAAA,EACZ,QAAA,EAAU;AACZ,CAAA;AAEA,MAAM,OAAA,GAAU;AAAA,EACd,GAAG,YAAA;AAAA,EACH,UAAA,EAAY,uBAAA;AAAA,EACZ,UAAA,EAAY,4BAAA;AAAA,EACZ,QAAA,EAAU;AACZ,CAAA;AAEA,MAAM,OAAA,GAAU;AAAA,EACd,GAAG,YAAA;AAAA,EACH,UAAA,EAAY,sBAAA;AAAA,EACZ,QAAA,EAAU;AACZ,CAAA;AAEA,MAAM,OAAA,GAAU;AAAA,EACd,GAAG,YAAA;AAAA,EACH,UAAA,EAAY,wBAAA;AAAA,EACZ,QAAA,EAAU;AACZ,CAAA;AAEA,MAAM,OAAA,GAAU;AAAA,EACd,GAAG,YAAA;AAAA,EACH,UAAA,EAAY,wBAAA;AAAA,EACZ,UAAA,EAAY,aAAA;AAAA,EACZ,QAAA,EAAU;AACZ,CAAA;AAEA,MAAM,OAAA,GAAU;AAAA,EACd,GAAG,YAAA;AAAA,EACH,QAAA,EAAU;AACZ,CAAA;AAoCA,SAAS,SAAA,CAAU,SAAiB,MAAA,EAA6B;AAC/D,EAAA,IAAI;AAEF,IAAA,OAAA,GAAU,QAAQ,IAAA,EAAK;AAIvB,IAAA,IAAI,MAAA,KAAW,0BAAA,IAA8B,OAAA,CAAQ,KAAA,CAAM,sCAAsC,CAAA,EAAG;AAClG,MAAA,MAAM,OAAA,GAAU,IAAI,IAAA,CAAK,OAAO,CAAA;AAChC,MAAA,OAAO,OAAO,KAAA,CAAM,OAAA,CAAQ,OAAA,EAAS,IAAI,IAAA,GAAO,OAAA;AAAA,IAClD;AAGA,IAAA,IAAI,IAAA,GAAoB,IAAA;AAExB,IAAA,QAAQ,MAAA;AAAQ,MACd,KAAK,YAAA,EAAc;AACjB,QAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,KAAA,CAAM,GAAG,CAAA;AAC/B,QAAA,IAAI,KAAA,CAAM,WAAW,CAAA,EAAG;AACtB,UAAA,IAAA,mBAAO,IAAI,KAAK,CAAA,EAAG,KAAA,CAAM,CAAC,CAAC,CAAA,CAAA,EAAI,KAAA,CAAM,CAAC,CAAA,CAAE,QAAA,CAAS,GAAG,GAAG,CAAC,IAAI,KAAA,CAAM,CAAC,EAAE,QAAA,CAAS,CAAA,EAAG,GAAG,CAAC,CAAA,CAAE,CAAA;AAAA,QACzF;AACA,QAAA;AAAA,MACF;AAAA,MACA,KAAK,aAAA,EAAe;AAElB,QAAA,IAAA,GAAO,IAAI,IAAA,CAAK,OAAA,CAAQ,OAAA,CAAQ,IAAA,EAAM,GAAG,CAAC,CAAA;AAC1C,QAAA;AAAA,MACF;AAAA,MACA,KAAK,qBAAA,EAAuB;AAC1B,QAAA,MAAM,CAAC,QAAA,EAAU,QAAQ,CAAA,GAAI,OAAA,CAAQ,MAAM,GAAG,CAAA;AAC9C,QAAA,IAAI,QAAA,EAAU;AACZ,UAAA,MAAM,KAAA,GAAQ,QAAA,CAAS,KAAA,CAAM,GAAG,CAAA;AAChC,UAAA,IAAI,KAAA,CAAM,WAAW,CAAA,EAAG;AACtB,YAAA,MAAM,UAAA,GAAa,GAAG,KAAA,CAAM,CAAC,CAAC,CAAA,CAAA,EAAI,KAAA,CAAM,CAAC,CAAA,CAAE,QAAA,CAAS,GAAG,GAAG,CAAC,IAAI,KAAA,CAAM,CAAC,EAAE,QAAA,CAAS,CAAA,EAAG,GAAG,CAAC,CAAA,CAAA;AACxF,YAAA,IAAA,mBAAO,IAAI,IAAA,CAAK,CAAA,EAAG,UAAU,CAAA,EAAG,WAAW,CAAA,CAAA,EAAI,QAAQ,CAAA,CAAA,GAAK,EAAE,CAAA,CAAE,CAAA;AAAA,UAClE;AAAA,QACF;AACA,QAAA;AAAA,MACF;AAAA,MACA,KAAK,qBAAA,EAAuB;AAC1B,QAAA,MAAM,CAAC,QAAA,EAAU,QAAQ,CAAA,GAAI,OAAA,CAAQ,MAAM,GAAG,CAAA;AAC9C,QAAA,IAAI,QAAA,EAAU;AACZ,UAAA,MAAM,KAAA,GAAQ,QAAA,CAAS,KAAA,CAAM,GAAG,CAAA;AAChC,UAAA,IAAI,KAAA,CAAM,WAAW,CAAA,EAAG;AACtB,YAAA,MAAM,UAAA,GAAa,GAAG,KAAA,CAAM,CAAC,CAAC,CAAA,CAAA,EAAI,KAAA,CAAM,CAAC,CAAA,CAAE,QAAA,CAAS,GAAG,GAAG,CAAC,IAAI,KAAA,CAAM,CAAC,EAAE,QAAA,CAAS,CAAA,EAAG,GAAG,CAAC,CAAA,CAAA;AACxF,YAAA,IAAA,mBAAO,IAAI,IAAA,CAAK,CAAA,EAAG,UAAU,CAAA,EAAG,WAAW,CAAA,CAAA,EAAI,QAAQ,CAAA,CAAA,GAAK,EAAE,CAAA,CAAE,CAAA;AAAA,UAClE;AAAA,QACF;AACA,QAAA;AAAA,MACF;AAAA,MACA,KAAK,UAAA,EAAY;AACf,QAAA,IAAI,OAAA,CAAQ,WAAW,CAAA,EAAG;AACxB,UAAA,MAAM,IAAA,GAAO,OAAA,CAAQ,SAAA,CAAU,CAAA,EAAG,CAAC,CAAA;AACnC,UAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,SAAA,CAAU,CAAA,EAAG,CAAC,CAAA;AACpC,UAAA,MAAM,GAAA,GAAM,OAAA,CAAQ,SAAA,CAAU,CAAA,EAAG,CAAC,CAAA;AAClC,UAAA,IAAA,mBAAO,IAAI,KAAK,CAAA,EAAG,IAAI,IAAI,KAAK,CAAA,CAAA,EAAI,GAAG,CAAA,CAAE,CAAA;AAAA,QAC3C;AACA,QAAA;AAAA,MACF;AAAA,MACA,KAAK,eAAA,EAAiB;AACpB,QAAA,MAAM,UAAU,OAAA,CAAQ,OAAA,CAAQ,KAAA,EAAO,EAAE,EAAE,IAAA,EAAK;AAChD,QAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,KAAA,CAAM,KAAK,CAAA;AACjC,QAAA,IAAI,KAAA,CAAM,WAAW,CAAA,EAAG;AACtB,UAAA,IAAA,mBAAO,IAAI,KAAK,CAAA,EAAG,KAAA,CAAM,CAAC,CAAC,CAAA,CAAA,EAAI,KAAA,CAAM,CAAC,CAAA,CAAE,QAAA,CAAS,GAAG,GAAG,CAAC,IAAI,KAAA,CAAM,CAAC,EAAE,QAAA,CAAS,CAAA,EAAG,GAAG,CAAC,CAAA,CAAE,CAAA;AAAA,QACzF;AACA,QAAA;AAAA,MACF;AAAA,MACA,KAAK,iBAAA,EAAmB;AAEtB,QAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,KAAA,CAAM,KAAK,CAAA;AACjC,QAAA,IAAI,KAAA,CAAM,UAAU,CAAA,EAAG;AACrB,UAAA,IAAA,mBAAO,IAAI,IAAA,CAAK,CAAA,EAAG,KAAA,CAAM,CAAC,CAAC,CAAA,CAAA,EAAI,KAAA,CAAM,CAAC,CAAC,CAAA,CAAA,EAAI,KAAA,CAAM,CAAC,CAAC,CAAA,CAAE,CAAA;AAAA,QACvD;AACA,QAAA;AAAA,MACF;AAAA,MACA,KAAK,0BAAA,EAA4B;AAE/B,QAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,KAAA,CAAM,KAAK,CAAA;AACjC,QAAA,IAAI,KAAA,CAAM,UAAU,CAAA,EAAG;AACrB,UAAA,IAAA,uBAAW,IAAA,CAAK,CAAA,EAAG,MAAM,CAAC,CAAC,IAAI,KAAA,CAAM,CAAC,CAAC,CAAA,CAAA,EAAI,MAAM,CAAC,CAAC,IAAI,KAAA,CAAM,CAAC,CAAC,CAAA,CAAE,CAAA;AAAA,QACnE;AACA,QAAA;AAAA,MACF;AAAA,MACA,KAAK,mBAAA,EAAqB;AACxB,QAAA,MAAM,CAAC,QAAA,EAAU,QAAQ,CAAA,GAAI,OAAA,CAAQ,MAAM,GAAG,CAAA;AAC9C,QAAA,IAAI,QAAA,IAAY,QAAA,CAAS,MAAA,KAAW,CAAA,EAAG;AACrC,UAAA,MAAM,IAAA,GAAO,QAAA,CAAS,SAAA,CAAU,CAAA,EAAG,CAAC,CAAA;AACpC,UAAA,MAAM,KAAA,GAAQ,QAAA,CAAS,SAAA,CAAU,CAAA,EAAG,CAAC,CAAA;AACrC,UAAA,MAAM,GAAA,GAAM,QAAA,CAAS,SAAA,CAAU,CAAA,EAAG,CAAC,CAAA;AACnC,UAAA,IAAA,mBAAO,IAAI,IAAA,CAAK,CAAA,EAAG,IAAI,IAAI,KAAK,CAAA,CAAA,EAAI,GAAG,CAAA,EAAG,QAAA,GAAW,CAAA,CAAA,EAAI,QAAQ,CAAA,CAAA,GAAK,EAAE,CAAA,CAAE,CAAA;AAAA,QAC5E;AACA,QAAA;AAAA,MACF;AAAA,MACA,KAAK,4BAAA,EAA8B;AAEjC,QAAA,MAAM,OAAA,GAAU,OAAA,CAAQ,OAAA,CAAQ,YAAA,EAAc,EAAE,CAAA;AAChD,QAAA,IAAA,GAAO,IAAI,IAAA,CAAK,OAAA,CAAQ,OAAA,CAAQ,IAAA,EAAM,GAAG,CAAC,CAAA;AAC1C,QAAA;AAAA,MACF;AAAA,MACA,KAAK,aAAA,EAAe;AAElB,QAAA,IAAA,GAAO,IAAI,KAAK,OAAO,CAAA;AACvB,QAAA;AAAA,MACF;AAAA,MACA,SAAS;AAEP,QAAA,IAAA,GAAO,IAAI,KAAK,OAAO,CAAA;AAAA,MACzB;AAAA;AAIF,IAAA,IAAI,QAAQ,CAAC,MAAA,CAAO,MAAM,IAAA,CAAK,OAAA,EAAS,CAAA,EAAG;AACzC,MAAA,OAAO,IAAA;AAAA,IACT;AAGA,IAAA,MAAM,QAAA,GAAW,IAAI,IAAA,CAAK,OAAO,CAAA;AACjC,IAAA,IAAI,CAAC,MAAA,CAAO,KAAA,CAAM,QAAA,CAAS,OAAA,EAAS,CAAA,EAAG;AACrC,MAAA,OAAO,QAAA;AAAA,IACT;AAEA,IAAA,OAAO,IAAA;AAAA,EACT,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,IAAA;AAAA,EACT;AACF;AAOA,MAAM,SAAA,GAAmC;AAAA,EACvC,GAAA,EAAK,QAAA;AAAA,EACL,GAAA,EAAK,QAAA;AAAA,EACL,IAAA,EAAM,QAAA;AAAA,EACN,GAAA,EAAK,QAAA;AAAA,EACL,EAAA,EAAI,QAAA;AAAA,EACJ,IAAA,EAAM,QAAA;AAAA,EACN,EAAA,EAAI,OAAA;AAAA,EACJ,EAAA,EAAI,OAAA;AAAA,EACJ,YAAA,EAAI,OAAA;AAAA,EACJ,EAAA,EAAI,OAAA;AAAA,EACJ,EAAA,EAAI,OAAA;AAAA,EACJ,GAAA,EAAK,OAAA;AAAA,EACL,EAAA,EAAI,OAAA;AAAA,EACJ,EAAA,EAAI,OAAA;AAAA,EACJ,EAAA,EAAI,OAAA;AAAA,EACJ,EAAA,EAAI,OAAA;AAAA,EACJ,EAAA,EAAI,OAAA;AAAA,EACJ,EAAA,EAAI,OAAA;AAAA,EACJ,EAAA,EAAI,OAAA;AAAA,EACJ,EAAA,EAAI,OAAA;AAAA,EACJ,EAAA,EAAI,OAAA;AAAA,EACJ,EAAA,EAAI,OAAA;AAAA,EACJ,EAAA,EAAI,OAAA;AAAA,EACJ,EAAA,EAAI,OAAA;AAAA,EACJ,EAAA,EAAI,OAAA;AAAA,EACJ,EAAA,EAAI,OAAA;AAAA,EACJ,EAAA,EAAI,OAAA;AAAA,EACJ,EAAA,EAAI,OAAA;AAAA,EACJ,IAAA,EAAM,SAAA;AAAA,EACN,EAAA,EAAI,OAAA;AAAA,EACJ,EAAA,EAAI,OAAA;AAAA,EACJ,EAAA,EAAI,OAAA;AAAA,EACJ,EAAA,EAAI,OAAA;AAAA,EACJ,EAAA,EAAI,OAAA;AAAA,EACJ,EAAA,EAAI;AACN,CAAA;AAGA,MAAM,qBAAA,GAID;AAAA,EACH,EAAE,OAAA,EAAS,uBAAA,EAAyB,QAAA,EAAU,aAAA,EAAe,UAAU,IAAA,EAAK;AAAA,EAC5E,EAAE,OAAA,EAAS,wBAAA,EAA0B,QAAA,EAAU,cAAA,EAAe;AAAA,EAC9D,EAAE,OAAA,EAAS,iCAAA,EAAmC,QAAA,EAAU,sBAAA,EAAuB;AAAA,EAC/E,EAAE,OAAA,EAAS,6BAAA,EAA+B,QAAA,EAAU,kBAAA,EAAmB;AAAA,EACvE,EAAE,OAAA,EAAS,wCAAA,EAA0C,QAAA,EAAU,4BAAA,EAA6B;AAAA,EAC5F,EAAE,OAAA,EAAS,wCAAA,EAA0C,QAAA,EAAU,4BAAA,EAA6B;AAAA,EAC5F,EAAE,OAAA,EAAS,iBAAA,EAAmB,QAAA,EAAU,QAAA,EAAS;AAAA,EACjD,EAAE,OAAA,EAAS,4BAAA,EAA8B,QAAA,EAAU,iBAAA;AACrD,CAAA;AAEA,MAAM,eAAA,GAAkB,0BAAA;AAExB,SAAS,UAAU,MAAA,EAAuB;AACxC,EAAA,MAAM,MAAM,MAAA,CAAO,KAAA,CAAM,GAAG,CAAA,CAAE,GAAA,IAAO,WAAA,EAAY;AACjD,EAAA,IAAI,CAAC,KAAK,OAAO,YAAA;AACjB,EAAA,OAAO,SAAA,CAAU,GAAG,CAAA,IAAK,YAAA;AAC3B;AAEA,SAAS,eAAA,CAAgB,SAAiB,OAAA,EAA2B;AACnE,EAAA,MAAM,MAAgB,EAAC;AACvB,EAAA,MAAM,EAAA,GAAK,IAAI,MAAA,CAAO,OAAA,EAAS,IAAI,CAAA;AACnC,EAAA,KAAA,MAAW,KAAA,IAAS,OAAA,CAAQ,QAAA,CAAS,EAAE,CAAA,EAAG;AACxC,IAAA,IAAI,KAAA,CAAM,CAAC,CAAA,EAAG,GAAA,CAAI,KAAK,KAAA,CAAM,CAAC,CAAA,CAAE,IAAA,EAAM,CAAA;AAAA,EACxC;AACA,EAAA,OAAO,GAAA;AACT;AAEA,SAAS,WAAA,CAAY,OAAA,EAAiB,OAAA,EAAiB,UAAA,EAAwC;AAG7F,EAAA,MAAM,SAAA,GAAY,QAAQ,QAAA,CAAS,eAAe,IAAI,+BAAA,GAAkC,IAAI,MAAA,CAAO,OAAA,EAAS,GAAG,CAAA;AAC/G,EAAA,MAAM,UAAU,OAAA,CAAQ,KAAA,CAAM,SAAS,CAAA,GAAI,CAAC,GAAG,IAAA,EAAK;AACpD,EAAA,IAAI,CAAC,SAAS,OAAO,MAAA;AACrB,EAAA,OAAO,SAAA,CAAU,OAAA,EAAS,UAAU,CAAA,EAAG,aAAY,IAAK,OAAA;AAC1D;AAEA,SAAS,wBAAA,CAAyB,SAAiB,MAAA,EAAiC;AAClF,EAAA,KAAA,MAAW,EAAE,OAAA,EAAS,QAAA,EAAU,QAAA,MAAc,qBAAA,EAAuB;AACnE,IAAA,IAAI,QAAA,EAAU;AACZ,MAAA,MAAM,UAAU,KAAA,CAAM,IAAA,CAAK,OAAA,CAAQ,QAAA,CAAS,OAAO,CAAC,CAAA;AACpD,MAAA,IAAI,OAAA,CAAQ,MAAA,GAAS,CAAA,EAAI,OAAO,QAAQ,CAAA,GAAiB,OAAA,CAAQ,GAAA,CAAI,CAAC,CAAA,KAAM,CAAA,CAAE,CAAC,CAAA,CAAE,MAAM,CAAA;AACvF,MAAA;AAAA,IACF;AACA,IAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,KAAA,CAAM,OAAO,CAAA;AACnC,IAAA,IAAI,KAAA,GAAQ,CAAC,CAAA,EAAI,MAAA,CAAO,QAAQ,CAAA,GAAe,KAAA,CAAM,CAAC,CAAA,CAAE,IAAA,EAAK;AAAA,EAC/D;AACF;AAEO,SAAS,cAAA,CAAe,EAAE,OAAA,EAAS,MAAA,EAAO,EAA2D;AAC1G,EAAA,IAAI,CAAC,OAAA,EAAS,OAAO,EAAE,UAAA,EAAY,MAAA,EAAQ,aAAa,IAAA,EAAK;AAE7D,EAAA,MAAM,MAAA,GAA4B,EAAE,UAAA,EAAY,MAAA,EAAO;AACvD,EAAA,MAAM,QAAA,GAAW,UAAU,MAAM,CAAA;AACjC,EAAA,MAAM,UAAA,GAAa,SAAS,UAAA,IAAc,eAAA;AAE1C,EAAA,KAAA,MAAW,CAAC,GAAA,EAAK,OAAO,KAAK,MAAA,CAAO,OAAA,CAAQ,QAAQ,CAAA,EAAG;AACrD,IAAA,IAAI,CAAC,OAAA,IAAW,GAAA,KAAQ,YAAA,EAAc;AACtC,IAAA,IAAI,CAAC,IAAI,MAAA,CAAO,OAAA,EAAS,GAAG,CAAA,CAAE,IAAA,CAAK,OAAO,CAAA,EAAG;AAE7C,IAAA,QAAQ,GAAA;AAAoB,MAC1B,KAAK,aAAA;AACH,QAAA,MAAA,CAAO,WAAA,GAAc,IAAA;AACrB,QAAA,MAAM,IAAI,MAAM,cAAc,CAAA;AAAA,MAChC,KAAK,UAAA;AACH,QAAA,MAAA,CAAO,WAAA,GAAc,IAAA;AACrB,QAAA;AAAA,MACF,KAAK,QAAA;AACH,QAAA,MAAA,CAAO,MAAA,GAAS,eAAA,CAAgB,OAAA,EAAS,OAAO,CAAA;AAChD,QAAA;AAAA,MACF,KAAK,cAAA;AAAA,MACL,KAAK,gBAAA;AAAA,MACL,KAAK,aAAA,EAAe;AAClB,QAAA,MAAM,KAAA,GAAQ,WAAA,CAAY,OAAA,EAAS,OAAA,EAAS,UAAU,CAAA;AACtD,QAAA,IAAI,KAAA,EAAO,MAAA,CAAO,GAAwD,CAAA,GAAI,KAAA;AAC9E,QAAA;AAAA,MACF;AAAA,MACA,KAAK,YAAA,EAAc;AACjB,QAAA,MAAM,IAAI,OAAA,CAAQ,KAAA,CAAM,IAAI,MAAA,CAAO,OAAA,EAAS,GAAG,CAAC,CAAA;AAChD,QAAA,IAAI,CAAA,GAAI,CAAC,CAAA,EAAG,MAAA,CAAO,UAAA,GAAa,EAAE,CAAC,CAAA,CAAE,WAAA,EAAY,CAAE,IAAA,EAAK;AACxD,QAAA;AAAA,MACF;AAAA,MACA,KAAK,WAAA,EAAa;AAChB,QAAA,MAAM,IAAI,OAAA,CAAQ,KAAA,CAAM,IAAI,MAAA,CAAO,OAAA,EAAS,GAAG,CAAC,CAAA;AAChD,QAAA,IAAI,CAAA,GAAI,CAAC,CAAA,EAAG,MAAA,CAAO,YAAY,CAAA,CAAE,CAAC,EAAE,IAAA,EAAK;AACzC,QAAA;AAAA,MACF;AAAA;AACF,EACF;AAEA,EAAA,MAAA,CAAO,WAAA,KAAP,OAAO,WAAA,GAAgB,KAAA,CAAA;AACvB,EAAA,wBAAA,CAAyB,SAAS,MAAM,CAAA;AACxC,EAAA,OAAO,MAAA;AACT;;ACjdA,MAAM,UAAkB,MAAM;AAAC,CAAA;AAE/B,MAAM,UAAA,GAAa,EAAA;AACnB,MAAM,oBAAA,GAAuB,gBAAA;AAC7B,MAAM,YAAA,GAAe,gBAAA;AAGrB,SAAS,YAAY,KAAA,EAA8B;AACjD,EAAA,MAAM,QAAA,GAAW,KAAA,CACd,OAAA,CAAQ,cAAA,EAAgB,EAAE,CAAA,CAC1B,KAAA,CAAM,GAAG,CAAA,CAAE,CAAC,CAAA,EACX,KAAA,CAAM,GAAG,EACV,GAAA,EAAI;AACP,EAAA,OAAO,QAAA,IAAY,IAAA;AACrB;AAGA,SAAS,gBAAA,CAAiB,MAAA,EAAgB,MAAA,EAAgB,OAAA,EAAiB,GAAA,EAA8B;AACvG,EAAA,OAAO,IAAI,OAAA,CAAQ,CAAC,OAAA,EAAS,MAAA,KAAW;AACtC,IAAA,MAAM,MAAA,GAAS,IAAIH,cAAA,CAAI,MAAA,EAAO;AAC9B,IAAA,IAAI,IAAA,GAAO,EAAA;AAEX,IAAA,GAAA,CAAI,CAAA,iBAAA,EAAoB,MAAM,CAAA,KAAA,EAAQ,MAAM,CAAA,CAAE,CAAA;AAE9C,IAAA,MAAM,KAAA,GAAQ,WAAW,MAAM;AAC7B,MAAA,GAAA,CAAI,yBAAyB,OAAO,CAAA,UAAA,EAAQ,MAAM,CAAA,GAAA,EAAM,MAAM,CAAA,CAAE,CAAA;AAChE,MAAA,MAAA,CAAO,OAAA,EAAQ;AACf,MAAA,MAAA,CAAO,IAAI,KAAA,CAAM,qBAAqB,CAAC,CAAA;AAAA,IACzC,GAAG,OAAO,CAAA;AAEV,IAAA,MAAA,CAAO,OAAA,CAAQ,UAAA,EAAY,MAAA,EAAQ,MAAM;AACvC,MAAA,GAAA,CAAI,CAAA,qBAAA,EAAwB,MAAM,CAAA,eAAA,CAAiB,CAAA;AACnD,MAAA,MAAA,CAAO,KAAA,CAAM,GAAG,MAAM,CAAA;AAAA,CAAM,CAAA;AAAA,IAC9B,CAAC,CAAA;AAED,IAAA,MAAA,CAAO,EAAA,CAAG,MAAA,EAAQ,CAAC,KAAA,KAAU;AAC3B,MAAA,IAAA,IAAQ,MAAM,QAAA,EAAS;AAAA,IACzB,CAAC,CAAA;AAED,IAAA,MAAA,CAAO,EAAA,CAAG,SAAS,MAAM;AACvB,MAAA,YAAA,CAAa,KAAK,CAAA;AAClB,MAAA,GAAA,CAAI,CAAA,iBAAA,EAAoB,IAAA,CAAK,MAAM,CAAA,YAAA,EAAe,MAAM,CAAA,CAAE,CAAA;AAC1D,MAAA,OAAA,CAAQ,IAAI,CAAA;AAAA,IACd,CAAC,CAAA;AAED,IAAA,MAAA,CAAO,EAAA,CAAG,OAAA,EAAS,CAAC,GAAA,KAAQ;AAC1B,MAAA,YAAA,CAAa,KAAK,CAAA;AAClB,MAAA,GAAA,CAAI,CAAA,mBAAA,EAAsB,MAAM,CAAA,EAAA,EAAK,GAAA,CAAI,OAAO,CAAA,CAAE,CAAA;AAClD,MAAA,MAAA,CAAO,GAAG,CAAA;AAAA,IACZ,CAAC,CAAA;AAAA,EACH,CAAC,CAAA;AACH;AAGA,eAAe,aAAA,CAAc,MAAA,EAAgB,OAAA,EAAiB,GAAA,EAAyC;AACrG,EAAA,MAAM,MAAM,MAAA,CAAO,KAAA,CAAM,GAAG,CAAA,CAAE,GAAA,IAAO,WAAA,EAAY;AACjD,EAAA,IAAI,CAAC,GAAA,EAAK,MAAM,IAAI,MAAM,gBAAgB,CAAA;AAE1C,EAAA,MAAM,MAAA,GAAS,aAAa,GAAG,CAAA;AAC/B,EAAA,IAAI,MAAA,EAAQ;AACV,IAAA,GAAA,CAAI,CAAA,cAAA,EAAiB,MAAM,CAAA,MAAA,EAAS,GAAG,CAAA,CAAE,CAAA;AACzC,IAAA,MAAM,MAAM,MAAM,gBAAA,CAAiB,MAAA,EAAQ,MAAA,EAAQ,SAAS,GAAG,CAAA;AAC/D,IAAA,OAAO,cAAA,CAAe,EAAE,OAAA,EAAS,GAAA,EAAK,QAAQ,CAAA;AAAA,EAChD;AAEA,EAAA,GAAA,CAAI,CAAA,uBAAA,EAA0B,GAAG,CAAA,aAAA,CAAe,CAAA;AAChD,EAAA,MAAM,eAAe,MAAM,gBAAA,CAAiB,MAAA,EAAQ,oBAAA,EAAsB,SAAS,GAAG,CAAA;AACtF,EAAA,MAAM,cAAA,GAAiB,YAAA,CAAa,KAAA,CAAM,iBAAiB,IAAI,CAAC,CAAA;AAChE,EAAA,IAAI,cAAA,EAAgB;AAClB,IAAA,GAAA,CAAI,CAAA,4BAAA,EAA+B,cAAc,CAAA,CAAE,CAAA;AACnD,IAAA,MAAM,MAAM,MAAM,gBAAA,CAAiB,MAAA,EAAQ,cAAA,EAAgB,SAAS,GAAG,CAAA;AACvE,IAAA,OAAO,cAAA,CAAe,EAAE,OAAA,EAAS,GAAA,EAAK,QAAQ,CAAA;AAAA,EAChD;AACA,EAAA,OAAO,cAAA,CAAe,EAAE,OAAA,EAAS,YAAA,EAAc,QAAQ,CAAA;AACzD;AAEA,eAAe,YAAA,CACb,MAAA,EACA,OAAA,EACA,GAAA,EACA,KAAA,EACmC;AACnC,EAAA,MAAM,QAAA,GAAW,SAAS,MAAM,CAAA,CAAA;AAChC,EAAA,MAAM,UAAA,GAAa,aAAA,CAAiC,KAAA,EAAO,OAAO,CAAA;AAElE,EAAA,MAAM,MAAA,GAAS,MAAM,UAAA,CAAW,GAAA,CAAI,QAAQ,CAAA;AAC5C,EAAA,IAAI,MAAA,EAAQ;AACV,IAAA,GAAA,CAAI,CAAA,sBAAA,EAAyB,MAAM,CAAA,CAAE,CAAA;AACrC,IAAA,OAAO,MAAA;AAAA,EACT;AAEA,EAAA,IAAI;AACF,IAAA,MAAM,IAAA,GAAO,MAAM,aAAA,CAAc,MAAA,EAAQ,SAAS,GAAG,CAAA;AACrD,IAAA,MAAM,UAAA,CAAW,GAAA,CAAI,QAAA,EAAU,IAAI,CAAA;AACnC,IAAA,OAAO,IAAA;AAAA,EACT,SAAS,KAAA,EAAO;AACd,IAAA,GAAA,CAAI,CAAA,mBAAA,EAAsB,MAAM,CAAA,EAAA,EAAK,KAAA,YAAiB,KAAA,GAAQ,MAAM,OAAA,GAAU,MAAA,CAAO,KAAK,CAAC,CAAA,CAAE,CAAA;AAC7F,IAAA,OAAO,IAAA;AAAA,EACT;AACF;AAGA,eAAe,YAAA,CACb,MAAA,EACA,OAAA,EACA,GAAA,EACA,KAAA,EAC2D;AAC3D,EAAA,MAAM,IAAA,GAAO,YAAY,MAAM,CAAA;AAC/B,EAAA,IAAI,CAAC,IAAA,EAAM;AACT,IAAA,GAAA,CAAI,CAAA,8BAAA,EAAiC,MAAM,CAAA,CAAE,CAAA;AAC7C,IAAA,OAAO,IAAA;AAAA,EACT;AACA,EAAA,IAAI,CAACH,WAAA,CAAQ,IAAI,CAAA,EAAG;AAClB,IAAA,GAAA,CAAI,CAAA,sBAAA,EAAyB,IAAI,CAAA,CAAE,CAAA;AACnC,IAAA,OAAO,IAAA;AAAA,EACT;AACA,EAAA,MAAM,OAAO,MAAM,YAAA,CAAa,IAAA,EAAM,OAAA,EAAS,KAAK,KAAK,CAAA;AACzD,EAAA,OAAO,IAAA,GAAO,EAAE,IAAA,EAAM,IAAA,EAAK,GAAI,IAAA;AACjC;AAEA,eAAsB,aACpB,MAAA,EACA,OAAA,GAAU,GAAA,EACV,KAAA,GAAQ,OACR,KAAA,EAC+B;AAC/B,EAAA,MAAM,GAAA,GAAc,KAAA,GAAQ,OAAA,CAAQ,KAAA,GAAQ,OAAA;AAC5C,EAAA,MAAM,SAAS,MAAM,YAAA,CAAa,MAAA,EAAQ,OAAA,EAAS,KAAK,KAAK,CAAA;AAC7D,EAAA,IAAI,CAAC,MAAA,EAAQ,IAAA,CAAK,YAAA,EAAc,OAAO,IAAA;AAEvC,EAAA,MAAM,EAAE,IAAA,EAAM,IAAA,EAAK,GAAI,MAAA;AAEvB,EAAA,MAAM,cAAc,IAAA,CAAK,YAAA;AACzB,EAAA,IAAI,CAAC,aAAa,OAAO,IAAA;AACzB,EAAA,MAAM,YAAA,GAAe,IAAI,IAAA,CAAK,WAAW,CAAA;AACzC,EAAA,MAAM,SAAA,GAAY,KAAK,KAAA,CAAA,CAAO,IAAA,CAAK,KAAI,GAAI,YAAA,CAAa,OAAA,EAAQ,IAAK,KAAU,CAAA;AAC/E,EAAA,MAAM,aAAa,UAAA,CAAA,CAAY,SAAA,GAAY,MAAA,EAAQ,OAAA,CAAQ,CAAC,CAAC,CAAA;AAC7D,EAAA,GAAA,CAAI,WAAW,IAAI,CAAA,MAAA,EAAS,SAAS,CAAA,OAAA,EAAU,UAAU,CAAA,EAAA,CAAI,CAAA;AAE7D,EAAA,OAAO;AAAA,IACL,MAAA,EAAQ,IAAA;AAAA,IACR,YAAA;AAAA,IACA,SAAA;AAAA,IACA,UAAA;AAAA,IACA,gBAAgB,IAAA,CAAK,cAAA,GAAiB,IAAI,IAAA,CAAK,IAAA,CAAK,cAAc,CAAA,GAAI,IAAA;AAAA,IACtE,aAAa,IAAA,CAAK,WAAA,GAAc,IAAI,IAAA,CAAK,IAAA,CAAK,WAAW,CAAA,GAAI;AAAA,GAC/D;AACF;AAEA,eAAsB,4BACpB,MAAA,EACA,OAAA,GAAU,GAAA,EACV,KAAA,GAAQ,OACR,KAAA,EACwC;AACxC,EAAA,MAAM,GAAA,GAAc,KAAA,GAAQ,OAAA,CAAQ,KAAA,GAAQ,OAAA;AAC5C,EAAA,MAAM,SAAS,MAAM,YAAA,CAAa,MAAA,EAAQ,OAAA,EAAS,KAAK,KAAK,CAAA;AAC7D,EAAA,IAAI,CAAC,QAAQ,OAAO,IAAA;AAEpB,EAAA,MAAM,EAAE,IAAA,EAAM,IAAA,EAAK,GAAI,MAAA;AACvB,EAAA,IAAI,KAAK,WAAA,EAAa;AACpB,IAAA,GAAA,CAAI,CAAA,QAAA,EAAW,IAAI,CAAA,8BAAA,CAAgC,CAAA;AACnD,IAAA,OAAO,gBAAgB,IAAI,CAAA;AAAA,EAC7B;AAEA,EAAA,MAAM,eAAe,OAAA,CAAQ,IAAA,CAAK,cAAc,IAAA,CAAK,YAAA,IAAgB,KAAK,SAAS,CAAA;AACnF,EAAA,MAAM,iBAAiB,IAAA,CAAK,cAAA,GAAiB,IAAI,IAAA,CAAK,IAAA,CAAK,cAAc,CAAA,GAAI,IAAA;AAC7E,EAAA,MAAM,YAAY,cAAA,GAAiB,IAAA,CAAK,KAAI,GAAI,cAAA,CAAe,SAAQ,GAAI,KAAA;AAC3E,EAAA,MAAM,mBAAA,GACJ,cAAA,IAAkB,CAAC,SAAA,GAAY,IAAA,CAAK,KAAA,CAAA,CAAO,cAAA,CAAe,OAAA,EAAQ,GAAI,IAAA,CAAK,GAAA,EAAI,IAAK,KAAU,CAAA,GAAI,IAAA;AAGpG,EAAA,MAAM,WAAA,GAAA,CAAe,IAAA,CAAK,MAAA,IAAU,IAAI,GAAA,CAAI,CAAC,CAAA,KAAM,CAAA,CAAE,KAAA,CAAM,GAAG,CAAA,CAAE,CAAC,KAAK,EAAE,CAAA;AACxE,EAAA,MAAM,eAAA,GAAkB,YAAY,IAAA,CAAK,CAAC,MAAM,2BAAA,CAA4B,IAAA,CAAK,CAAC,CAAC,CAAA;AACnF,EAAA,MAAM,QAAA,GAAW,YAAY,IAAA,CAAK,CAAC,MAAM,oCAAA,CAAqC,IAAA,CAAK,CAAC,CAAC,CAAA;AAErF,EAAA,GAAA;AAAA,IACE,CAAA,QAAA,EAAW,IAAI,CAAA,mBAAA,EAAiB,YAAY,YAAY,SAAS,CAAA,QAAA,EAAW,QAAQ,CAAA,eAAA,EAAkB,eAAe,CAAA;AAAA,GACvH;AAEA,EAAA,OAAO;AAAA,IACL,MAAA,EAAQ,IAAA;AAAA,IACR,YAAA;AAAA,IACA,aAAa,CAAC,YAAA;AAAA,IACd,MAAA,EAAQ,WAAA;AAAA,IACR,SAAA,EAAW,KAAK,SAAA,IAAa,IAAA;AAAA,IAC7B,WAAA,EAAa,IAAA,CAAK,WAAA,IAAe,EAAC;AAAA,IAClC,cAAA;AAAA,IACA,SAAA;AAAA,IACA,mBAAA;AAAA,IACA,eAAA;AAAA,IACA;AAAA,GACF;AACF;AAEA,SAAS,gBAAgB,MAAA,EAAwC;AAC/D,EAAA,OAAO;AAAA,IACL,MAAA;AAAA,IACA,YAAA,EAAc,KAAA;AAAA,IACd,WAAA,EAAa,IAAA;AAAA,IACb,QAAQ,EAAC;AAAA,IACT,SAAA,EAAW,IAAA;AAAA,IACX,aAAa,EAAC;AAAA,IACd,cAAA,EAAgB,IAAA;AAAA,IAChB,SAAA,EAAW,KAAA;AAAA,IACX,mBAAA,EAAqB,IAAA;AAAA,IACrB,eAAA,EAAiB,KAAA;AAAA,IACjB,QAAA,EAAU;AAAA,GACZ;AACF;;AC3MO,MAAM,WAAA,GAAsC;AAAA;AAAA;AAAA,EAGjD,SAAA,EAAW;AACb,CAAA;AAOA,SAAS,eAAA,CAAgB,QAA4B,IAAA,EAAoC;AACvF,EAAA,MAAA,CAAO,iBAAiB,IAAA,CAAK,cAAA;AAC7B,EAAA,MAAA,CAAO,eAAe,IAAA,CAAK,YAAA;AAC3B,EAAA,MAAA,CAAO,aAAa,IAAA,CAAK,UAAA;AACzB,EAAA,MAAA,CAAO,gBAAgB,IAAA,CAAK,aAAA;AAC5B,EAAA,MAAA,CAAO,aAAa,IAAA,CAAK,UAAA;AACzB,EAAA,MAAA,CAAO,SAAA,GAAY,IAAA,CAAK,cAAA,GAAiB,IAAA,CAAK,aAAA,GAAgB,IAAA;AAChE;AAGA,SAAS,gBAAA,CAAiB,cAAkC,SAAA,EAAqD;AAC/G,EAAA,IAAI,YAAA,EAAc,OAAO,CAAC,YAAY,CAAA;AACtC,EAAA,IAAI,CAAC,WAAW,OAAO,MAAA;AACvB,EAAA,MAAM,QAAA,GAAWO,UAAM,SAAS,CAAA;AAChC,EAAA,IAAI,EAAE,QAAA,IAAY,QAAA,CAAA,IAAa,CAAC,QAAA,CAAS,QAAQ,OAAO,MAAA;AACxD,EAAA,MAAM,KAAA,GAAQ,WAAA,CAAY,QAAA,CAAS,MAAM,CAAA;AACzC,EAAA,OAAO,KAAA,GAAQ,CAAC,KAAK,CAAA,GAAI,MAAA;AAC3B;AAQA,eAAsB,YAAY,MAAA,EAAwD;AACxF,EAAA,MAAM,SAAA,GAAY,KAAK,GAAA,EAAI;AAC3B,EAAA,MAAM,KAAA,GAAQ,OAAO,KAAA,IAAS,KAAA;AAC9B,EAAA,MAAM,GAAA,GAAc,KAAA,GAAQ,OAAA,CAAQ,KAAA,GAAQ,MAAM;AAAA,EAAC,CAAA;AACnD,EAAA,MAAM,MAAA,GAAS,WAAA,CAAY,MAAA,CAAO,YAAY,CAAA;AAI9C,EAAA,MAAM,iBAAA,GAAoB,OAAO,iBAAA,IAAqB,KAAA;AACtD,EAAA,MAAM,SAAA,GAAiC,iBAAA,GAAoB,IAAI,wBAAA,EAAyB,GAAI,cAAA;AAG5F,EAAA,MAAM,WAAA,GAAc,MAAM,SAAA,CAAU,MAAA;AAAA,IAClC,QAAA;AAAA,IACA,MAAM,YAAA,CAAa,MAAA,CAAO,YAAY,CAAA;AAAA,IACtC,CAAC,EAAA,MAAQ,EAAE,EAAA,EAAG;AAAA,GAChB;AACA,EAAA,IAAI,CAAC,WAAA,EAAa;AAChB,IAAA,OAAO,QAAA,CAAS,MAAA,EAAQ,qBAAA,CAAsB,aAAA,EAAe,WAAW,SAAS,CAAA;AAAA,EACnF;AACA,EAAA,MAAA,CAAO,WAAA,GAAc,IAAA;AAGrB,EAAA,IAAI,OAAO,UAAA,EAAY;AACrB,IAAA,MAAA,CAAO,YAAA,GAAe,MAAM,SAAA,CAAU,MAAA;AAAA,MACpC,gBAAA;AAAA,MACA,MAAM,oBAAoB,EAAE,KAAA,EAAO,OAAO,YAAA,EAAc,YAAA,EAAc,MAAA,CAAO,mBAAA,EAAqB,CAAA;AAAA,MAClG,CAAC,QAAA,MAAc,EAAE,QAAA,EAAU,YAAY,IAAA,EAAK;AAAA,KAC9C;AAAA,EACF;AAGA,EAAA,IAAI,MAAA,CAAO,iBAAiB,IAAA,EAAM;AAChC,IAAA,MAAA,CAAO,gBAAA,GAAmB,MAAM,SAAA,CAAU,MAAA;AAAA,MACxC,mBAAA;AAAA,MACA,MAAM,iBAAiB,MAAM,CAAA;AAAA,MAC7B,CAAC,UAAA,MAAgB,EAAE,UAAA,EAAY,cAAc,IAAA,EAAK;AAAA,KACpD;AAAA,EACF;AAEA,EAAA,MAAM,CAAC,KAAA,EAAO,MAAM,IAAI,MAAA,CAAO,YAAA,CAAa,MAAM,GAAG,CAAA;AACrD,EAAA,IAAI,CAAC,MAAA,IAAU,CAAC,KAAA,EAAO;AACrB,IAAA,OAAO,QAAA,CAAS,MAAA,EAAQ,qBAAA,CAAsB,aAAA,EAAe,WAAW,SAAS,CAAA;AAAA,EACnF;AACA,EAAA,MAAM,WAAA,GAAc,MAAM,SAAA,CAAU,MAAA;AAAA,IAClC,mBAAA;AAAA,IACA,MAAM,kBAAA,CAAmB,MAAA,EAAQ,MAAA,CAAO,KAAK,CAAA;AAAA,IAC7C,CAAC,KAAA,MAAW,EAAE,MAAA,EAAQ,KAAA,EAAM;AAAA,GAC9B;AACA,EAAA,IAAI,CAAC,WAAA,EAAa;AAChB,IAAA,OAAO,QAAA,CAAS,MAAA,EAAQ,qBAAA,CAAsB,aAAA,EAAe,WAAW,SAAS,CAAA;AAAA,EACnF;AAGA,EAAA,IAAI,MAAA,CAAO,mBAAmB,IAAA,EAAM;AAClC,IAAA,MAAA,CAAO,YAAA,GAAe,MAAM,SAAA,CAAU,MAAA;AAAA,MACpC,YAAA;AAAA,MACA,MAAM,iBAAA,CAAkB,EAAE,aAAA,EAAe,MAAA,CAAO,YAAA,EAAc,KAAA,EAAO,MAAA,CAAO,KAAA,EAAO,MAAA,EAAQ,GAAA,EAAK,CAAA;AAAA,MAChG,CAAC,YAAA,MAAkB,EAAE,MAAA,EAAQ,YAAA,EAAa;AAAA,KAC5C;AACA,IAAA,GAAA,CAAI,CAAA,0BAAA,EAA6B,MAAA,CAAO,YAAY,CAAA,CAAE,CAAA;AACtD,IAAA,IAAI,MAAA,CAAO,YAAA,EAAc,MAAA,CAAO,QAAA,CAAS,QAAQ,qBAAA,CAAsB,eAAA;AAAA,EACzE;AACA,EAAA,IAAI,MAAA,CAAO,aAAa,IAAA,EAAM;AAC5B,IAAA,MAAA,CAAO,MAAA,GAAS,MAAM,SAAA,CAAU,MAAA;AAAA,MAC9B,MAAA;AAAA,MACA,MAAM,WAAA,CAAY,EAAE,aAAA,EAAe,MAAA,CAAO,YAAA,EAAc,KAAA,EAAO,MAAA,CAAO,KAAA,EAAO,MAAA,EAAQ,GAAA,EAAK,CAAA;AAAA,MAC1F,CAAC,MAAA,MAAY,EAAE,MAAA,EAAQ,MAAA,EAAO;AAAA,KAChC;AACA,IAAA,GAAA,CAAI,CAAA,oBAAA,EAAuB,MAAA,CAAO,MAAM,CAAA,CAAE,CAAA;AAAA,EAC5C;AAEA,EAAA,MAAM,MAAA,GAAA,CAAU,MAAA,CAAO,mBAAA,IAAuB,KAAA,KAAU,MAAA,CAAO,YAAA;AAC/D,EAAA,MAAM,SAAA,GAAA,CAAa,MAAA,CAAO,4BAAA,IAAgC,KAAA,KAAU,MAAA,CAAO,YAAA;AAG3E,EAAA,MAAM,eAAe,MAAA,EAAQ,MAAA,EAAQ,MAAA,EAAQ,SAAA,EAAW,KAAK,SAAS,CAAA;AAItE,EAAA,MAAM,aAAA,GAAA,CAAiB,MAAA,CAAO,QAAA,IAAY,IAAA,MAAU,OAAO,UAAA,IAAc,KAAA,CAAA;AACzE,EAAA,IAAI,iBAAiB,MAAA,EAAQ;AAC3B,IAAA,GAAA,CAAI,CAAA,+CAAA,EAAkD,MAAA,CAAO,YAAY,CAAA,CAAE,CAAA;AAAA,EAC7E,WAAW,aAAA,EAAe;AACxB,IAAA,MAAM,aAAa,KAAA,EAAO,MAAA,EAAQ,MAAA,EAAQ,MAAA,EAAQ,KAAK,SAAS,CAAA;AAAA,EAClE;AAEA,EAAA,MAAA,CAAO,QAAA,CAAS,gBAAA,GAAmB,IAAA,CAAK,GAAA,EAAI,GAAI,SAAA;AAChD,EAAA,IAAI,iBAAA,EAAmB,MAAA,CAAO,UAAA,GAAc,SAAA,CAAuC,KAAA;AACnF,EAAA,OAAO,MAAA;AACT;AAEA,SAAS,YAAY,KAAA,EAAmC;AACtD,EAAA,OAAO;AAAA,IACL,KAAA;AAAA,IACA,WAAA,EAAa,KAAA;AAAA,IACb,OAAA,EAAS,IAAA;AAAA,IACT,SAAA,EAAW,IAAA;AAAA,IACX,YAAA,EAAc,KAAA;AAAA,IACd,MAAA,EAAQ,KAAA;AAAA,IACR,QAAA,EAAU,EAAE,gBAAA,EAAkB,CAAA,EAAG,QAAQ,KAAA;AAAM,GACjD;AACF;AAEA,SAAS,QAAA,CACP,MAAA,EACA,KAAA,EACA,SAAA,EACA,SAAA,EACoB;AACpB,EAAA,MAAA,CAAO,SAAS,KAAA,GAAQ,KAAA;AACxB,EAAA,MAAA,CAAO,QAAA,CAAS,gBAAA,GAAmB,IAAA,CAAK,GAAA,EAAI,GAAI,SAAA;AAChD,EAAA,IAAI,qBAAqB,wBAAA,EAA0B;AACjD,IAAA,MAAA,CAAO,aAAa,SAAA,CAAU,KAAA;AAAA,EAChC;AACA,EAAA,OAAO,MAAA;AACT;AAEA,eAAe,iBAAiB,MAAA,EAA6D;AAC3F,EAAA,MAAM,GAAG,WAAW,IAAI,MAAA,CAAO,YAAA,CAAa,MAAM,GAAG,CAAA;AACrD,EAAA,IAAI,CAAC,aAAa,OAAO,IAAA;AACzB,EAAA,IAAI,MAAA,CAAO,sBAAA,EAAwB,OAAO,MAAA,CAAO,uBAAuB,WAAW,CAAA;AACnF,EAAA,OAAO,kBAAA,CAAmB,MAAA,CAAO,YAAA,EAAc,MAAA,CAAO,aAAa,CAAA;AACrE;AAEA,eAAe,eACb,MAAA,EACA,MAAA,EACA,MAAA,EACA,SAAA,EACA,KACA,SAAA,EACe;AACf,EAAA,IAAI,CAAC,MAAA,CAAO,cAAA,IAAkB,CAAC,OAAO,uBAAA,EAAyB;AAC/D,EAAA,IAAI,SAAA,EAAW;AACb,IAAA,GAAA,CAAI,CAAA,mDAAA,EAAsD,MAAM,CAAA,CAAE,CAAA;AAClE,IAAA;AAAA,EACF;AACA,EAAA,MAAM,cAAA,GAAiB,OAAO,cAAA,IAAkB,GAAA;AAChD,EAAA,MAAM,KAAA,GAAQ,OAAO,KAAA,IAAS,KAAA;AAE9B,EAAA,IAAI,OAAO,cAAA,EAAgB;AACzB,IAAA,IAAI;AACF,MAAA,MAAA,CAAO,SAAA,GAAY,MAAM,SAAA,CAAU,MAAA;AAAA,QACjC,WAAA;AAAA,QACA,MAAM,YAAA,CAAa,MAAA,EAAQ,cAAA,EAAgB,KAAA,EAAO,OAAO,KAAK,CAAA;AAAA,QAC9D,CAAC,IAAA,MAAU;AAAA,UACT,MAAA;AAAA,UACA,OAAO,IAAA,KAAS,IAAA;AAAA,UAChB,SAAA,EAAW,MAAM,SAAA,IAAa,IAAA;AAAA,UAC9B,UAAA,EAAY,MAAM,UAAA,IAAc,IAAA;AAAA,UAChC,YAAA,EAAc,IAAA,EAAM,YAAA,EAAc,WAAA,EAAY,IAAK,IAAA;AAAA,UACnD,cAAA,EAAgB,IAAA,EAAM,cAAA,EAAgB,WAAA,EAAY,IAAK;AAAA,SACzD;AAAA,OACF;AACA,MAAA,GAAA,CAAI,CAAA,yBAAA,CAAA,EAA6B,OAAO,SAAA,GAAY,CAAA,EAAG,OAAO,SAAA,CAAU,SAAS,UAAU,MAAM,CAAA;AAAA,IACnG,SAAS,KAAA,EAAO;AACd,MAAA,GAAA,CAAI,0CAA0C,KAAK,CAAA;AACnD,MAAA,MAAA,CAAO,SAAA,GAAY,IAAA;AAAA,IACrB;AAAA,EACF;AAEA,EAAA,IAAI,OAAO,uBAAA,EAAyB;AAClC,IAAA,IAAI;AACF,MAAA,MAAA,CAAO,kBAAA,GAAqB,MAAM,SAAA,CAAU,MAAA;AAAA,QAC1C,oBAAA;AAAA,QACA,MAAM,2BAAA,CAA4B,MAAA,EAAQ,cAAA,EAAgB,KAAA,EAAO,OAAO,KAAK,CAAA;AAAA,QAC7E,CAAC,IAAA,MAAU;AAAA,UACT,MAAA;AAAA,UACA,OAAO,IAAA,KAAS,IAAA;AAAA,UAChB,YAAA,EAAc,MAAM,YAAA,IAAgB,IAAA;AAAA,UACpC,SAAA,EAAW,MAAM,SAAA,IAAa,IAAA;AAAA,UAC9B,QAAA,EAAU,MAAM,QAAA,IAAY,IAAA;AAAA,UAC5B,eAAA,EAAiB,MAAM,eAAA,IAAmB,IAAA;AAAA,UAC1C,mBAAA,EAAqB,MAAM,mBAAA,IAAuB,IAAA;AAAA,UAClD,MAAA,EAAQ,IAAA,EAAM,MAAA,IAAU;AAAC,SAC3B;AAAA,OACF;AACA,MAAA,GAAA,CAAI,CAAA,yBAAA,CAAA,EAA6B,MAAA,CAAO,kBAAA,EAAoB,YAAA,IAAgB,KAAK,CAAA;AAAA,IACnF,SAAS,KAAA,EAAO;AACd,MAAA,GAAA,CAAI,mDAAmD,KAAK,CAAA;AAC5D,MAAA,MAAA,CAAO,kBAAA,GAAqB,IAAA;AAAA,IAC9B;AAAA,EACF;AACF;AAEA,eAAe,aACb,KAAA,EACA,MAAA,EACA,MAAA,EACA,MAAA,EACA,KACA,SAAA,EACe;AACf,EAAA,IAAI,SAAA;AACJ,EAAA,IAAI;AACF,IAAA,SAAA,GAAY,MAAM,SAAA,CAAU,MAAA;AAAA,MAC1B,WAAA;AAAA,MACA,MAAM,iBAAiB,EAAE,MAAA,EAAQ,OAAO,MAAA,CAAO,KAAA,EAAO,MAAA,EAAQ,GAAA,EAAK,CAAA;AAAA,MACnE,CAAC,OAAA,MAAa,EAAE,QAAQ,OAAA,EAAS,KAAA,EAAO,QAAQ,MAAA,EAAO;AAAA,KACzD;AAAA,EACF,SAAS,KAAA,EAAO;AACd,IAAA,GAAA,CAAI,kCAAkC,KAAK,CAAA;AAC3C,IAAA,MAAA,CAAO,OAAA,GAAU,KAAA;AACjB,IAAA,MAAA,CAAO,SAAA,GAAY,IAAA;AACnB,IAAA,MAAA,CAAO,QAAA,CAAS,QAAQ,qBAAA,CAAsB,WAAA;AAC9C,IAAA;AAAA,EACF;AAEA,EAAA,MAAA,CAAO,SAAA,GAAY,SAAA;AACnB,EAAA,MAAA,CAAO,OAAA,GAAU,UAAU,MAAA,GAAS,CAAA;AACpC,EAAA,IAAI,CAAC,OAAO,OAAA,EAAS;AACnB,IAAA,MAAA,CAAO,QAAA,CAAS,QAAQ,qBAAA,CAAsB,WAAA;AAC9C,IAAA;AAAA,EACF;AAEA,EAAA,IAAI,EAAE,MAAA,CAAO,UAAA,IAAc,KAAA,CAAA,EAAQ;AAEnC,EAAA,MAAM,QAAQ,KAAA,EAAO,MAAA,EAAQ,WAAW,MAAA,EAAQ,MAAA,EAAQ,KAAK,SAAS,CAAA;AACxE;AAEA,eAAe,QACb,KAAA,EACA,MAAA,EACA,WACA,MAAA,EACA,MAAA,EACA,KACA,SAAA,EACe;AACf,EAAA,MAAM,QAAA,GAAW,CAAA,EAAG,MAAA,CAAO,YAAY,CAAA,KAAA,CAAA;AACvC,EAAA,MAAM,SAAA,GAAY,aAAA,CAAsC,MAAA,CAAO,KAAA,EAAO,MAAM,CAAA;AAC5E,EAAA,MAAM,MAAA,GAAS,MAAM,SAAA,CAAU,GAAA,CAAI,QAAQ,CAAA;AAE3C,EAAA,IAAI,MAAA,EAAQ;AACV,IAAA,eAAA,CAAgB,QAAQ,MAAM,CAAA;AAC9B,IAAA,MAAA,CAAO,SAAS,MAAA,GAAS,IAAA;AACzB,IAAA,GAAA,CAAI,iCAAiC,MAAA,CAAO,SAAS,CAAA,KAAA,EAAQ,MAAA,CAAO,YAAY,CAAA,CAAE,CAAA;AAClF,IAAA,SAAA,CAAU,IAAA,CAAK;AAAA,MACb,IAAA,EAAM,YAAA;AAAA,MACN,SAAA,EAAW,KAAK,GAAA,EAAI;AAAA,MACpB,UAAA,EAAY,CAAA;AAAA,MACZ,EAAA,EAAI,IAAA;AAAA,MACJ,OAAA,EAAS;AAAA,QACP,QAAA,EAAU,IAAA;AAAA,QACV,OAAA,EAAS,cAAA,CAAe,MAAA,CAAO,SAAS,CAAA;AAAA,QACxC,gBAAgB,MAAA,CAAO;AAAA;AACzB,KACD,CAAA;AAAA,EACH,CAAA,MAAO;AACL,IAAA,MAAM,SAAA,CAAU,MAAA;AAAA,MACd,YAAA;AAAA,MACA,YAAY;AACV,QAAA,MAAM,KAAA,GAAQ,MAAM,iBAAA,CAAkB;AAAA,UACpC,KAAA;AAAA,UACA,MAAA;AAAA,UACA,SAAA;AAAA,UACA,OAAA,EAAS;AAAA,YACP,OAAO,MAAA,CAAO,KAAA;AAAA,YACd,OAAO,gBAAA,CAAiB,MAAA,CAAO,QAAA,EAAU,SAAA,CAAU,CAAC,CAAC,CAAA;AAAA,YACrD,mBAAA,EAAqB,OAAO,uBAAA,IAA2B,GAAA;AAAA,YACvD,iBAAiB,MAAA,CAAO,mBAAA;AAAA,YACxB,wBAAwB,MAAA,CAAO,0BAAA;AAAA,YAC/B,YAAY,MAAA,CAAO,cAAA;AAAA,YACnB,OAAO,MAAA,CAAO,SAAA;AAAA,YACd,KAAA,EAAO,OAAO,KAAA,IAAS,KAAA;AAAA;AAAA;AAAA,YAGvB,iBAAA,EAAmB,OAAO,iBAAA,IAAqB,KAAA;AAAA;AAAA;AAAA;AAAA,YAI/C,GAAI,MAAA,CAAO,UAAA,KAAe,UAAa,EAAE,MAAA,EAAQ,OAAO,UAAA,EAAW;AAAA,YACnE,GAAI,MAAA,CAAO,gBAAA,KAAqB,UAAa,EAAE,YAAA,EAAc,OAAO,gBAAA;AAAiB;AACvF,SACD,CAAA;AACD,QAAA,MAAM,SAAA,CAAU,GAAA,CAAI,QAAA,EAAU,KAAA,CAAM,UAAU,CAAA;AAC9C,QAAA,eAAA,CAAgB,MAAA,EAAQ,MAAM,UAAU,CAAA;AACxC,QAAA,MAAA,CAAO,QAAA,CAAS,SAAS,KAAA,CAAM,MAAA;AAC/B,QAAA,OAAO,KAAA;AAAA,MACT,CAAA;AAAA,MACA,CAAC,EAAE,UAAA,EAAY,IAAA,EAAM,MAAA,EAAQ,iBAAgB,MAAO;AAAA,QAClD,QAAA,EAAU,KAAA;AAAA,QACV,IAAA;AAAA,QACA,MAAA,EAAQ,eAAA;AAAA,QACR,OAAA,EAAS,cAAA,CAAe,MAAA,CAAO,SAAS,CAAA;AAAA,QACxC,gBAAgB,UAAA,CAAW,cAAA;AAAA,QAC3B,KAAA,EAAO,WAAW,KAAA,IAAS,IAAA;AAAA;AAAA,QAE3B,UAAA,EAAY,WAAW,UAAA,IAAc,IAAA;AAAA,QACrC,QAAA,EAAU,WAAW,QAAA,IAAY;AAAA,OACnC;AAAA,KACF;AACA,IAAA,GAAA,CAAI,8BAA8B,MAAA,CAAO,SAAS,CAAA,KAAA,EAAQ,MAAA,CAAO,YAAY,CAAA,CAAE,CAAA;AAAA,EACjF;AAEA,EAAA,IAAI,OAAO,SAAA,KAAc,KAAA,EAAO,MAAA,CAAO,QAAA,CAAS,QAAQ,qBAAA,CAAsB,eAAA;AAAA,OAAA,IACrE,OAAO,SAAA,KAAc,IAAA,EAAM,MAAA,CAAO,QAAA,CAAS,QAAQ,qBAAA,CAAsB,oBAAA;AACpF;AAEA,SAAS,eAAe,SAAA,EAA0F;AAChH,EAAA,IAAI,SAAA,KAAc,MAAM,OAAO,aAAA;AAC/B,EAAA,IAAI,SAAA,KAAc,OAAO,OAAO,eAAA;AAChC,EAAA,OAAO,eAAA;AACT;;ACxWA,SAAS,QAAA,GAMP;AACA,EAAA,MAAM,UAAU,OAAA,CAAQ,MAAA,CAAO,KAAA,IAAS,OAAA,CAAQ,IAAI,QAAA,KAAa,GAAA;AACjE,EAAA,MAAM,IAAA,GAAO,CAAC,IAAA,EAAc,KAAA,KAAkB,CAAC,CAAA,KAAe,OAAA,GAAU,CAAA,KAAA,EAAQ,IAAI,CAAA,CAAA,EAAI,CAAC,CAAA,KAAA,EAAQ,KAAK,CAAA,CAAA,CAAA,GAAM,CAAA;AAC5G,EAAA,OAAO;AAAA,IACL,KAAA,EAAO,IAAA,CAAK,IAAA,EAAM,IAAI,CAAA;AAAA,IACtB,GAAA,EAAK,IAAA,CAAK,IAAA,EAAM,IAAI,CAAA;AAAA,IACpB,MAAA,EAAQ,IAAA,CAAK,IAAA,EAAM,IAAI,CAAA;AAAA,IACvB,GAAA,EAAK,IAAA,CAAK,GAAA,EAAK,IAAI,CAAA;AAAA,IACnB,IAAA,EAAM,IAAA,CAAK,GAAA,EAAK,IAAI;AAAA,GACtB;AACF;AAGO,SAAS,YAAY,MAAA,EAAoC;AAC9D,EAAA,MAAM,IAAI,QAAA,EAAS;AACnB,EAAA,IAAI,MAAA,CAAO,gBAAgB,KAAA,EAAO,OAAO,EAAE,GAAA,CAAI,CAAA,uBAAA,EAAqB,MAAA,CAAO,KAAK,CAAA,CAAE,CAAA;AAClF,EAAA,IAAI,MAAA,CAAO,YAAY,KAAA,EAAO,OAAO,EAAE,GAAA,CAAI,CAAA,sBAAA,EAAoB,MAAA,CAAO,KAAK,CAAA,CAAE,CAAA;AAC7E,EAAA,IAAI,MAAA,CAAO,cAAc,IAAA,EAAM,OAAO,EAAE,KAAA,CAAM,CAAA,uBAAA,EAAqB,MAAA,CAAO,KAAK,CAAA,CAAE,CAAA;AACjF,EAAA,IAAI,MAAA,CAAO,cAAc,KAAA,EAAO,OAAO,EAAE,GAAA,CAAI,CAAA,uBAAA,EAAqB,MAAA,CAAO,KAAK,CAAA,CAAE,CAAA;AAGhF,EAAA,MAAM,UAAA,GAAa,OAAO,cAAA,KAAmB,MAAA;AAC7C,EAAA,IAAI,UAAA,IAAc,MAAA,CAAO,SAAA,KAAc,IAAA,EAAM,OAAO,EAAE,MAAA,CAAO,CAAA,kBAAA,EAAqB,MAAA,CAAO,KAAK,CAAA,CAAE,CAAA;AAChG,EAAA,OAAO,CAAA,CAAE,KAAA,CAAM,CAAA,uBAAA,EAAqB,MAAA,CAAO,KAAK,KAAK,CAAA,CAAE,GAAA,CAAI,mBAAmB,CAAC,CAAA,CAAE,CAAA;AACnF;AAEO,SAAS,WAAW,MAAA,EAAoC;AAC7D,EAAA,OAAO,IAAA,CAAK,UAAU,MAAM,CAAA;AAC9B;AAEO,SAAS,WAAW,MAAA,EAAoC;AAC7D,EAAA,MAAM,QAAkB,EAAC;AACzB,EAAA,KAAA,CAAM,IAAA,CAAK,WAAA,CAAY,MAAM,CAAC,CAAA;AAC9B,EAAA,KAAA,CAAM,IAAA,CAAK,CAAA,SAAA,EAAY,MAAA,CAAO,WAAW,CAAA,IAAA,EAAO,OAAO,OAAO,CAAA,MAAA,EAAS,MAAA,CAAO,SAAS,CAAA,CAAE,CAAA;AACzF,EAAA,KAAA,CAAM,KAAK,CAAA,eAAA,EAAkB,MAAA,CAAO,YAAY,CAAA,QAAA,EAAW,MAAA,CAAO,MAAM,CAAA,CAAE,CAAA;AAC1E,EAAA,IAAI,MAAA,CAAO,SAAA,EAAW,MAAA,EAAQ,KAAA,CAAM,IAAA,CAAK,CAAA,YAAA,EAAe,MAAA,CAAO,SAAA,CAAU,IAAA,CAAK,IAAI,CAAC,CAAA,CAAE,CAAA;AACrF,EAAA,IAAI,MAAA,CAAO,kBAAkB,KAAA,CAAM,IAAA,CAAK,gBAAgB,MAAA,CAAO,gBAAA,CAAiB,SAAS,CAAA,CAAE,CAAA;AAC3F,EAAA,IAAI,OAAO,YAAA,EAAc;AACvB,IAAA,MAAM,EAAE,SAAA,EAAW,QAAA,EAAU,UAAA,KAAe,MAAA,CAAO,YAAA;AACnD,IAAA,KAAA,CAAM,IAAA,CAAK,CAAA,eAAA,EAAkB,SAAA,IAAa,GAAG,CAAA,CAAA,EAAI,QAAA,IAAY,GAAG,CAAA,OAAA,EAAU,UAAA,CAAW,OAAA,CAAQ,CAAC,CAAC,CAAA,CAAA,CAAG,CAAA;AAAA,EACpG;AACA,EAAA,IAAI,MAAA,CAAO,SAAS,KAAA,EAAO,KAAA,CAAM,KAAK,CAAA,QAAA,EAAW,MAAA,CAAO,QAAA,CAAS,KAAK,CAAA,CAAE,CAAA;AACxE,EAAA,KAAA,CAAM,IAAA,CAAK,UAAU,MAAA,CAAO,QAAA,CAAS,gBAAgB,CAAA,UAAA,EAAa,MAAA,CAAO,QAAA,CAAS,MAAM,CAAA,CAAE,CAAA;AAC1F,EAAA,OAAO,KAAA,CAAM,KAAK,IAAI,CAAA;AACxB;AAEO,SAAS,aAAa,MAAA,EAAoC;AAC/D,EAAA,MAAM,IAAI,QAAA,EAAS;AACnB,EAAA,MAAM,QAAkB,EAAC;AACzB,EAAA,KAAA,CAAM,IAAA,CAAK,WAAA,CAAY,MAAM,CAAC,CAAA;AAC9B,EAAA,KAAA,CAAM,KAAK,EAAE,CAAA;AAGb,EAAA,KAAA,CAAM,IAAA,CAAK,CAAA,CAAE,IAAA,CAAK,SAAS,CAAC,CAAA;AAC5B,EAAA,KAAA,CAAM,IAAA,CAAK,CAAA,EAAA,EAAK,CAAA,CAAE,GAAA,CAAI,SAAS,CAAC,CAAA,QAAA,EAAW,UAAA,CAAW,MAAA,CAAO,WAAW,CAAC,CAAA,CAAE,CAAA;AAC3E,EAAA,IAAI,OAAO,OAAA,KAAY,IAAA;AACrB,IAAA,KAAA,CAAM,IAAA;AAAA,MACJ,CAAA,EAAA,EAAK,EAAE,GAAA,CAAI,aAAa,CAAC,CAAA,IAAA,EAAO,UAAA,CAAW,MAAA,CAAO,OAAO,CAAC,CAAA,EAAG,OAAO,SAAA,GAAY,CAAA,EAAA,EAAK,CAAA,CAAE,GAAA,CAAI,MAAA,CAAO,SAAA,CAAU,KAAK,IAAI,CAAC,CAAC,CAAA,CAAA,GAAK,EAAE,CAAA;AAAA,KAChI;AACF,EAAA,IAAI,MAAA,CAAO,SAAA,KAAc,IAAA,EAAM,KAAA,CAAM,KAAK,CAAA,EAAA,EAAK,CAAA,CAAE,GAAA,CAAI,OAAO,CAAC,CAAA,UAAA,EAAa,UAAA,CAAW,MAAA,CAAO,SAAS,CAAC,CAAA,CAAE,CAAA;AACxG,EAAA,KAAA,CAAM,IAAA;AAAA,IACJ,KAAK,CAAA,CAAE,GAAA,CAAI,aAAa,CAAC,CAAA,IAAA,EAAO,WAAW,CAAC,MAAA,CAAO,YAAY,CAAC,IAAI,CAAA,CAAE,GAAA,CAAI,OAAO,YAAA,GAAe,6BAAA,GAAgC,EAAE,CAAC,CAAA;AAAA,GACrI;AACA,EAAA,KAAA,CAAM,IAAA;AAAA,IACJ,KAAK,CAAA,CAAE,GAAA,CAAI,gBAAgB,CAAC,CAAA,CAAA,EAAI,WAAW,CAAC,MAAA,CAAO,MAAM,CAAC,IAAI,CAAA,CAAE,GAAA,CAAI,OAAO,MAAA,GAAS,uBAAA,GAA0B,EAAE,CAAC,CAAA;AAAA,GACnH;AACA,EAAA,IAAI,OAAO,gBAAA,EAAkB;AAC3B,IAAA,KAAA,CAAM,IAAA;AAAA,MACJ,CAAA,EAAA,EAAK,EAAE,GAAA,CAAI,aAAa,CAAC,CAAA,IAAA,EAAO,CAAA,CAAE,MAAA,CAAO,MAAA,CAAO,gBAAA,CAAiB,SAAS,CAAC,CAAA,CAAA,EAAI,CAAA,CAAE,GAAA,CAAI,CAAA,MAAA,EAAS,MAAA,CAAO,gBAAA,CAAiB,WAAW,OAAA,CAAQ,CAAC,CAAC,CAAA,CAAA,CAAG,CAAC,CAAA;AAAA,KACjJ;AAAA,EACF;AACA,EAAA,IAAI,OAAO,YAAA,EAAc;AACvB,IAAA,MAAM,EAAE,SAAA,EAAW,QAAA,EAAU,UAAA,KAAe,MAAA,CAAO,YAAA;AACnD,IAAA,KAAA,CAAM,IAAA;AAAA,MACJ,CAAA,EAAA,EAAK,CAAA,CAAE,GAAA,CAAI,gBAAgB,CAAC,IAAI,CAAC,SAAA,EAAW,QAAQ,CAAA,CAAE,MAAA,CAAO,OAAO,EAAE,IAAA,CAAK,GAAG,CAAC,CAAA,CAAA,EAAI,CAAA,CAAE,GAAA,CAAI,CAAA,MAAA,EAAS,UAAA,CAAW,OAAA,CAAQ,CAAC,CAAC,CAAA,CAAA,CAAG,CAAC,CAAA;AAAA,KAC7H;AAAA,EACF;AACA,EAAA,IAAI,OAAO,SAAA,EAAW;AACpB,IAAA,KAAA,CAAM,IAAA;AAAA,MACJ,CAAA,EAAA,EAAK,EAAE,GAAA,CAAI,aAAa,CAAC,CAAA,IAAA,EAAO,MAAA,CAAO,UAAU,SAAS,CAAA,OAAA,EAAU,EAAE,GAAA,CAAI,CAAA,CAAA,EAAI,OAAO,SAAA,CAAU,UAAA,CAAW,QAAQ,CAAC,CAAC,SAAS,CAAC,CAAA;AAAA,KAChI;AAAA,EACF;AACA,EAAA,IAAI,OAAO,kBAAA,EAAoB;AAC7B,IAAA,MAAM,IAAI,MAAA,CAAO,kBAAA;AACjB,IAAA,KAAA,CAAM,IAAA;AAAA,MACJ,CAAA,EAAA,EAAK,CAAA,CAAE,GAAA,CAAI,eAAe,CAAC,CAAA,EAAA,EAAK,CAAA,CAAE,YAAA,GAAe,CAAA,CAAE,MAAM,YAAY,CAAA,GAAI,CAAA,CAAE,GAAA,CAAI,WAAW,CAAC,CAAA,EAAG,CAAA,CAAE,SAAA,GAAY,IAAI,CAAA,CAAE,GAAA,CAAI,WAAW,CAAC,KAAK,EAAE,CAAA,EAAG,CAAA,CAAE,QAAA,GAAW,IAAI,CAAA,CAAE,GAAA,CAAI,UAAU,CAAC,KAAK,EAAE,CAAA;AAAA,KACvL;AAAA,EACF;AACA,EAAA,IAAI,OAAO,QAAA,CAAS,KAAA,EAAO,KAAA,CAAM,IAAA,CAAK,KAAK,CAAA,CAAE,GAAA,CAAI,QAAQ,CAAC,YAAY,CAAA,CAAE,GAAA,CAAI,OAAO,QAAA,CAAS,KAAK,CAAC,CAAA,CAAE,CAAA;AACpG,EAAA,KAAA,CAAM,IAAA;AAAA,IACJ,KAAK,CAAA,CAAE,GAAA,CAAI,UAAU,CAAC,CAAA,OAAA,EAAU,OAAO,QAAA,CAAS,gBAAgB,MAAM,MAAA,CAAO,QAAA,CAAS,SAAS,CAAA,CAAA,EAAI,CAAA,CAAE,IAAI,UAAU,CAAC,KAAK,EAAE,CAAA;AAAA,GAC7H;AAGA,EAAA,IAAI,MAAA,CAAO,UAAA,IAAc,MAAA,CAAO,UAAA,CAAW,SAAS,CAAA,EAAG;AACrD,IAAA,KAAA,CAAM,KAAK,EAAE,CAAA;AACb,IAAA,KAAA,CAAM,IAAA,CAAK,CAAA,CAAE,IAAA,CAAK,YAAY,CAAC,CAAA;AAC/B,IAAA,KAAA,MAAW,IAAA,IAAQ,OAAO,UAAA,EAAY;AACpC,MAAA,KAAA,CAAM,KAAK,CAAA,EAAA,EAAK,UAAA,CAAW,IAAA,EAAM,CAAC,CAAC,CAAA,CAAE,CAAA;AAAA,IACvC;AAAA,EACF;AAEA,EAAA,OAAO,KAAA,CAAM,KAAK,IAAI,CAAA;AACxB;AAEA,SAAS,WAAW,KAAA,EAA+B;AACjD,EAAA,MAAM,IAAI,QAAA,EAAS;AACnB,EAAA,IAAI,KAAA,KAAU,IAAA,EAAM,OAAO,CAAA,CAAE,MAAM,QAAG,CAAA;AACtC,EAAA,IAAI,KAAA,KAAU,KAAA,EAAO,OAAO,CAAA,CAAE,IAAI,QAAG,CAAA;AACrC,EAAA,OAAO,CAAA,CAAE,IAAI,QAAG,CAAA;AAClB;AAEA,SAAS,UAAA,CAAW,MAAwB,CAAA,EAAwC;AAClF,EAAA,MAAM,MAAA,GAAS,KAAK,EAAA,GAAK,CAAA,CAAE,MAAM,QAAG,CAAA,GAAI,CAAA,CAAE,GAAA,CAAI,QAAG,CAAA;AACjD,EAAA,MAAM,OAAO,CAAA,EAAG,IAAA,CAAK,UAAU,CAAA,EAAA,CAAA,CAAK,SAAS,CAAC,CAAA;AAC9C,EAAA,MAAM,MAAA,GAAS,iBAAiB,IAAI,CAAA;AACpC,EAAA,OAAO,GAAG,MAAM,CAAA,CAAA,EAAI,CAAA,CAAE,GAAA,CAAI,IAAI,CAAC,CAAA,EAAA,EAAK,CAAA,CAAE,IAAA,CAAK,KAAK,IAAA,CAAK,MAAA,CAAO,EAAE,CAAC,CAAC,KAAK,MAAM,CAAA,CAAA;AAC7E;AAEA,SAAS,iBAAiB,IAAA,EAAgC;AACxD,EAAA,MAAM,IAAI,IAAA,CAAK,OAAA;AACf,EAAA,QAAQ,KAAK,IAAA;AAAM,IACjB,KAAK,QAAA;AACH,MAAA,OAAO,CAAA,GAAA,EAAM,MAAA,CAAO,CAAA,CAAE,EAAE,CAAC,CAAA,CAAA;AAAA,IAC3B,KAAK,mBAAA;AACH,MAAA,OAAO,CAAA,OAAA,EAAU,OAAO,CAAA,CAAE,MAAM,CAAC,CAAA,OAAA,EAAU,MAAA,CAAO,CAAA,CAAE,KAAK,CAAC,CAAA,CAAA;AAAA,IAC5D,KAAK,gBAAA;AACH,MAAA,OAAO,CAAA,CAAE,WAAW,CAAA,SAAA,EAAY,IAAA,CAAK,UAAU,CAAA,CAAE,QAAQ,CAAC,CAAA,CAAA,GAAK,kBAAA;AAAA,IACjE,KAAK,mBAAA;AACH,MAAA,OAAO,CAAA,CAAE,aAAa,CAAA,OAAA,EAAK,IAAA,CAAK,UAAU,CAAA,CAAE,UAAU,CAAC,CAAA,CAAA,GAAK,eAAA;AAAA,IAC9D,KAAK,YAAA;AACH,MAAA,OAAO,CAAA,OAAA,EAAU,OAAO,CAAA,CAAE,MAAM,CAAC,CAAA,cAAA,EAAiB,MAAA,CAAO,CAAA,CAAE,YAAY,CAAC,CAAA,CAAA;AAAA,IAC1E,KAAK,MAAA;AACH,MAAA,OAAO,CAAA,OAAA,EAAU,OAAO,CAAA,CAAE,MAAM,CAAC,CAAA,QAAA,EAAW,MAAA,CAAO,CAAA,CAAE,MAAM,CAAC,CAAA,CAAA;AAAA,IAC9D,KAAK,WAAA;AACH,MAAA,OAAO,CAAA,OAAA,EAAU,OAAO,CAAA,CAAE,MAAM,CAAC,CAAA,OAAA,EAAU,MAAA,CAAO,CAAA,CAAE,KAAK,CAAC,CAAA,CAAA;AAAA,IAC5D,KAAK,YAAA;AACH,MAAA,OAAO,CAAA,CAAE,QAAA,GACL,CAAA,kBAAA,EAAqB,MAAA,CAAO,CAAA,CAAE,OAAO,CAAC,CAAA,CAAA,GACtC,CAAA,KAAA,EAAQ,MAAA,CAAO,CAAA,CAAE,IAAI,CAAC,CAAA,SAAA,EAAY,MAAA,CAAO,CAAA,CAAE,OAAO,CAAC,CAAA,EAAG,CAAA,CAAE,KAAA,GAAQ,CAAA,OAAA,EAAU,MAAA,CAAO,CAAA,CAAE,KAAK,CAAC,CAAA,CAAA,GAAK,EAAE,CAAA,CAAA;AAAA,IACtG,KAAK,WAAA;AACH,MAAA,OAAO,CAAA,CAAE,KAAA,GAAQ,CAAA,cAAA,EAAiB,MAAA,CAAO,CAAA,CAAE,YAAY,CAAC,CAAA,SAAA,EAAY,MAAA,CAAO,CAAA,CAAE,SAAS,CAAC,CAAA,CAAA,GAAK,WAAA;AAAA,IAC9F,KAAK,oBAAA;AACH,MAAA,OAAO,EAAE,KAAA,GACL,CAAA,WAAA,EAAc,MAAA,CAAO,CAAA,CAAE,YAAY,CAAC,CAAA,SAAA,EAAY,MAAA,CAAO,CAAA,CAAE,SAAS,CAAC,CAAA,QAAA,EAAW,OAAO,CAAA,CAAE,QAAQ,CAAC,CAAA,CAAA,GAChG,WAAA;AAAA;AAEV;;ACpIO,SAAS,cAAA,CAAe,OAAe,IAAA,EAAoB;AAChE,EAAA,MAAM,SAAA,GAAY,KAAA,CAAM,OAAA,CAAQ,mBAAA,EAAqB,GAAG,CAAA;AACxD,EAAA,MAAM,KAAA,GACJ,CAAA,EAAG,IAAA,CAAK,cAAA,EAAgB,CAAA,CAAA,EAAI,GAAA,CAAI,IAAA,CAAK,WAAA,KAAgB,CAAC,CAAC,CAAA,CAAA,EAAI,GAAA,CAAI,KAAK,UAAA,EAAY,CAAC,CAAA,CAAA,EAC7E,IAAI,IAAA,CAAK,WAAA,EAAa,CAAC,GAAG,GAAA,CAAI,IAAA,CAAK,aAAA,EAAe,CAAC,CAAA,EAAG,GAAA,CAAI,IAAA,CAAK,aAAA,EAAe,CAAC,CAAA,CAAA,CAAA;AACrF,EAAA,OAAO,CAAA,eAAA,EAAkB,KAAK,CAAA,CAAA,EAAI,SAAS,CAAA,KAAA,CAAA;AAC7C;AAEA,SAAS,IAAI,CAAA,EAAmB;AAC9B,EAAA,OAAO,IAAI,EAAA,GAAK,CAAA,CAAA,EAAI,CAAC,CAAA,CAAA,GAAK,OAAO,CAAC,CAAA;AACpC;AAEA,eAAsB,GAAA,CAAI,IAAA,EAAkB,IAAA,GAAmB,EAAC,EAAoB;AAClF,EAAA,MAAM,MAAA,GAAS,KAAK,MAAA,IAAU,WAAA;AAC9B,EAAA,MAAM,MAAA,GAAS,KAAK,MAAA,KAAW,CAAC,SAAS,OAAA,CAAQ,MAAA,CAAO,KAAA,CAAM,CAAA,EAAG,IAAI;AAAA,CAAI,CAAA,CAAA;AACzE,EAAA,MAAM,MAAA,GAAS,KAAK,MAAA,KAAW,CAAC,SAAS,OAAA,CAAQ,MAAA,CAAO,KAAA,CAAM,CAAA,EAAG,IAAI;AAAA,CAAI,CAAA,CAAA;AACzE,EAAA,MAAM,SAAA,GAAY,KAAK,SAAA,KAAc,CAAC,MAAM,QAAA,KAAaC,qBAAA,CAAc,IAAA,EAAM,QAAA,EAAU,MAAM,CAAA,CAAA;AAC7F,EAAA,MAAM,SAAA,GAAY,IAAA,CAAK,SAAA,KAAc,CAAC,IAAA,KAASC,kBAAU,IAAA,EAAM,EAAE,SAAA,EAAW,IAAA,EAAM,CAAA,CAAA;AAClF,EAAA,MAAM,GAAA,GAAM,IAAA,CAAK,GAAA,KAAQ,0BAAU,IAAA,EAAK,CAAA;AAExC,EAAA,MAAM,MAAA,GAAS,MAAM,MAAA,CAAO;AAAA,IAC1B,cAAc,IAAA,CAAK,KAAA;AAAA,IACnB,UAAU,IAAA,CAAK,QAAA;AAAA,IACf,YAAY,IAAA,CAAK,UAAA;AAAA,IACjB,uBAAA,EAAyB,KAAK,SAAA,IAAa,GAAA;AAAA,IAC3C,OAAO,IAAA,CAAK,KAAA;AAAA,IACZ,UAAU,IAAA,CAAK,QAAA;AAAA,IACf,iBAAiB,IAAA,CAAK,eAAA;AAAA,IACtB,WAAW,IAAA,CAAK,SAAA;AAAA,IAChB,YAAY,IAAA,CAAK,UAAA;AAAA,IACjB,eAAe,IAAA,CAAK,aAAA;AAAA,IACpB,gBAAgB,IAAA,CAAK,cAAA;AAAA,IACrB,yBAAyB,IAAA,CAAK,uBAAA;AAAA,IAC9B,cAAA,EAAgB,KAAK,cAAA,IAAkB,GAAA;AAAA,IACvC,mBAAmB,IAAA,CAAK;AAAA,GACzB,CAAA;AAGD,EAAA,IAAI,KAAK,KAAA,EAAO;AACd,IAAA,MAAA,CAAO,WAAA,CAAY,MAAM,CAAC,CAAA;AAAA,EAC5B,CAAA,MAAO;AACL,IAAA,QAAQ,KAAK,MAAA;AAAQ,MACnB,KAAK,MAAA;AACH,QAAA,MAAA,CAAO,UAAA,CAAW,MAAM,CAAC,CAAA;AACzB,QAAA;AAAA,MACF,KAAK,MAAA;AACH,QAAA,MAAA,CAAO,UAAA,CAAW,MAAM,CAAC,CAAA;AACzB,QAAA;AAAA,MACF,KAAK,QAAA;AACH,QAAA,MAAA,CAAO,YAAA,CAAa,MAAM,CAAC,CAAA;AAC3B,QAAA;AAAA;AACJ,EACF;AAGA,EAAA,IAAI,KAAK,MAAA,EAAQ;AACf,IAAA,IAAI;AACF,MAAA,MAAM,GAAA,GAAMC,iBAAA,CAAQ,IAAA,CAAK,MAAM,CAAA;AAC/B,MAAA,SAAA,CAAU,GAAG,CAAA;AACb,MAAA,MAAM,IAAA,GAAOA,kBAAQ,GAAA,EAAK,cAAA,CAAe,KAAK,KAAA,EAAO,GAAA,EAAK,CAAC,CAAA;AAC3D,MAAA,SAAA,CAAU,MAAM,IAAA,CAAK,SAAA,CAAU,MAAA,EAAQ,IAAA,EAAM,CAAC,CAAC,CAAA;AAC/C,MAAA,IAAI,CAAC,IAAA,CAAK,KAAA,EAAO,MAAA,CAAO,CAAA,aAAA,EAAgB,IAAI,CAAA,CAAE,CAAA;AAAA,IAChD,SAAS,KAAA,EAAO;AACd,MAAA,MAAA,CAAO,CAAA,mCAAA,EAAsC,iBAAiB,KAAA,GAAQ,KAAA,CAAM,UAAU,MAAA,CAAO,KAAK,CAAC,CAAA,CAAE,CAAA;AAAA,IACvG;AAAA,EACF;AAEA,EAAA,OAAO,YAAY,MAAM,CAAA;AAC3B;AAEO,SAAS,YAAY,MAAA,EAAoC;AAC9D,EAAA,IAAI,CAAC,MAAA,CAAO,WAAA,EAAa,OAAO,CAAA;AAChC,EAAA,IAAI,MAAA,CAAO,OAAA,KAAY,KAAA,EAAO,OAAO,CAAA;AACrC,EAAA,IAAI,MAAA,CAAO,SAAA,KAAc,KAAA,EAAO,OAAO,CAAA;AAKvC,EAAA,MAAM,UAAA,GAAa,OAAO,cAAA,KAAmB,MAAA;AAC7C,EAAA,IAAI,UAAA,IAAc,MAAA,CAAO,SAAA,KAAc,IAAA,EAAM,OAAO,CAAA;AACpD,EAAA,OAAO,CAAA;AACT;;AC/FA,eAAsB,KAAK,IAAA,GAA0B,OAAA,CAAQ,IAAA,CAAK,KAAA,CAAM,CAAC,CAAA,EAAoB;AAC3F,EAAA,MAAM,MAAA,GAAS,UAAU,IAAI,CAAA;AAE7B,EAAA,IAAI,MAAA,CAAO,SAAS,MAAA,EAAQ;AAC1B,IAAA,OAAA,CAAQ,MAAA,CAAO,KAAA,CAAM,CAAA,EAAG,QAAA,EAAU;AAAA,CAAI,CAAA;AACtC,IAAA,OAAO,CAAA;AAAA,EACT;AACA,EAAA,IAAI,MAAA,CAAO,SAAS,SAAA,EAAW;AAG7B,IAAA,IAAI;AACF,MAAA,MAAM,GAAA,GAAM,QAAQ,oBAAoB,CAAA;AACxC,MAAA,OAAA,CAAQ,MAAA,CAAO,KAAA,CAAM,CAAA,EAAG,GAAA,CAAI,OAAO;AAAA,CAAI,CAAA;AAAA,IACzC,CAAA,CAAA,MAAQ;AACN,MAAA,OAAA,CAAQ,MAAA,CAAO,MAAM,WAAW,CAAA;AAAA,IAClC;AACA,IAAA,OAAO,CAAA;AAAA,EACT;AACA,EAAA,IAAI,MAAA,CAAO,SAAS,OAAA,EAAS;AAC3B,IAAA,KAAA,MAAW,OAAO,MAAA,CAAO,QAAA,UAAkB,MAAA,CAAO,KAAA,CAAM,GAAG,GAAG;AAAA,CAAI,CAAA;AAClE,IAAA,OAAA,CAAQ,OAAO,KAAA,CAAM;AAAA;AAAA,CAAgC,CAAA;AACrD,IAAA,OAAO,MAAA,CAAO,QAAA;AAAA,EAChB;AAEA,EAAA,OAAO,IAAI,MAAM,CAAA;AACnB;AAIA,MAAM,kBAAA;AAAA;AAAA,EAEH,OAAO,qQAAA,KAAgB,WAAA,IAAgB,SAAmC,KAAS,IAAA;AAAA,EAEnF,OAAO,OAAA,KAAY,WAAA,IAAe,OAAA,CAAQ,IAAA,KAAS;AAAA,CAAA;AAEtD,IAAI,kBAAA,EAAoB;AACtB,EAAA,IAAA,EAAK,CACF,IAAA,CAAK,CAAC,IAAA,KAAS,OAAA,CAAQ,IAAA,CAAK,IAAI,CAAC,CAAA,CACjC,KAAA,CAAM,CAAC,KAAA,KAAU;AAChB,IAAA,OAAA,CAAQ,MAAA,CAAO,KAAA;AAAA,MACb,CAAA,kBAAA,EAAqB,iBAAiB,KAAA,GAAS,KAAA,CAAM,SAAS,KAAA,CAAM,OAAA,GAAW,MAAA,CAAO,KAAK,CAAC;AAAA;AAAA,KAC9F;AACA,IAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AAAA,EAChB,CAAC,CAAA;AACL;;;;;;;;;"}
|