@workos/oagen 0.12.0 → 0.14.0
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/dist/cli/index.mjs +299 -14
- package/dist/cli/index.mjs.map +1 -1
- package/dist/compat/index.d.mts +3 -1
- package/dist/compat/index.d.mts.map +1 -1
- package/dist/compat/index.mjs +5 -2
- package/dist/compat/index.mjs.map +1 -1
- package/dist/{diff-CihuFSbJ.mjs → diff-C38px0NK.mjs} +2 -2
- package/dist/diff-C38px0NK.mjs.map +1 -0
- package/dist/{differ-BTx-rDgJ.d.mts → differ-fdF9qogA.d.mts} +8 -1
- package/dist/differ-fdF9qogA.d.mts.map +1 -0
- package/dist/index.d.mts +37 -1
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +2 -2
- package/dist/index.mjs.map +1 -1
- package/dist/{overlay-DTaApIqN.mjs → overlay-DGcHh1KN.mjs} +258 -1
- package/dist/overlay-DGcHh1KN.mjs.map +1 -0
- package/dist/scripts/smoke/baseline.mjs +1 -1
- package/dist/scripts/smoke/baseline.mjs.map +1 -1
- package/dist/smoke.d.mts +24 -0
- package/dist/smoke.d.mts.map +1 -1
- package/dist/smoke.mjs +1 -1
- package/dist/smoke.mjs.map +1 -1
- package/dist/verify/index.d.mts +1 -1
- package/dist/verify/index.mjs +2 -2
- package/docs/advanced/index.md +1 -0
- package/docs/advanced/transform-spec.md +124 -0
- package/docs/cli.md +13 -12
- package/docs/core/compatibility-policy.md +26 -0
- package/docs/core/compatibility.md +6 -0
- package/docs/index.md +1 -0
- package/package.json +1 -1
- package/dist/diff-CihuFSbJ.mjs.map +0 -1
- package/dist/differ-BTx-rDgJ.d.mts.map +0 -1
- package/dist/overlay-DTaApIqN.mjs.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":["parseMethods","parseProperties","extractNamespace","safeParse","DEFAULT_EXCEPTION_BASES","isExceptionClass","buildSurface","buildSurface","safeParse","buildSurface","buildSurface","safeParseWith","extractEnumModules","extractEnumModules","parseStructFields","extractPackageName","safeParse","buildSurface","buildSurface","parseEnums","parseTypeAliases","safeParse","buildSurface","buildSurface","stripComments","extractJsonPropertyName","parseClasses","parseMethods","buildSurface","buildSurface","buildSurface","buildSurface"],"sources":["../../src/compat/concepts.ts","../../src/compat/report.ts","../../src/compat/approvals.ts","../../src/compat/extractors/shared.ts","../../src/compat/extractors/node.ts","../../src/compat/extractors/php-parser.ts","../../src/compat/extractors/php-surface.ts","../../src/compat/extractors/php.ts","../../src/compat/extractors/python-parser.ts","../../src/compat/extractors/python-surface.ts","../../src/compat/extractors/python.ts","../../src/compat/extractors/ruby-parser.ts","../../src/compat/extractors/ruby.ts","../../src/compat/extractors/go-parser.ts","../../src/compat/extractors/go-surface.ts","../../src/compat/extractors/go.ts","../../src/compat/extractors/rust-parser.ts","../../src/compat/extractors/rust-surface.ts","../../src/compat/extractors/rust.ts","../../src/compat/extractors/kotlin-parser.ts","../../src/compat/extractors/kotlin-surface.ts","../../src/compat/extractors/kotlin.ts","../../src/compat/extractors/dotnet-parser.ts","../../src/compat/extractors/dotnet-surface.ts","../../src/compat/extractors/dotnet.ts","../../src/compat/extractors/elixir-parser.ts","../../src/compat/extractors/elixir-surface.ts","../../src/compat/extractors/elixir.ts"],"sourcesContent":["/**\n * Conceptual change grouping for cross-language compatibility analysis.\n *\n * Groups related changes across languages into a single conceptual change\n * with per-language severity. This allows reports to say \"parameter rename\n * on Authorization.check is breaking in PHP, Python, Kotlin, and .NET but\n * soft-risk in Go\" rather than treating these as unrelated per-language findings.\n */\n\nimport type { LanguageId } from './ir.js';\nimport type { CompatChangeSeverity, CompatChangeCategory } from './config.js';\nimport type { CompatDiffResult } from './differ.js';\n\n/** A conceptual change with per-language severity. */\nexport interface ConceptualChange {\n /** Deterministic ID from symbol + category + match details. */\n id: string;\n /** IR-level symbol path (language-neutral). */\n symbol: string;\n /** The kind of change. */\n category: CompatChangeCategory;\n /** Per-language severity mapping. */\n impact: Partial<Record<LanguageId, CompatChangeSeverity>>;\n /** Human-readable description (from first language that reported it). */\n message: string;\n /** Old state details. */\n old: Record<string, string>;\n /** New state details. */\n new: Record<string, string>;\n}\n\n/** Cross-language conceptual rollup. */\nexport interface ConceptualRollup {\n conceptualChanges: ConceptualChange[];\n}\n\n/**\n * Group classified changes from multiple languages into conceptual changes.\n *\n * Changes are grouped by their `conceptualChangeId` — a deterministic ID\n * derived from the symbol, category, and match details. Changes with the\n * same ID across different languages represent the same conceptual change.\n */\nexport function buildConceptualRollup(\n perLanguageResults: Array<{ diff: CompatDiffResult; language: LanguageId }>,\n): ConceptualRollup {\n const grouped = new Map<string, ConceptualChange>();\n\n for (const { diff: result, language } of perLanguageResults) {\n for (const change of result.changes) {\n const existing = grouped.get(change.conceptualChangeId);\n if (existing) {\n existing.impact[language] = change.severity;\n } else {\n grouped.set(change.conceptualChangeId, {\n id: change.conceptualChangeId,\n symbol: change.symbol,\n category: change.category,\n impact: { [language]: change.severity },\n message: change.message,\n old: change.old,\n new: change.new,\n });\n }\n }\n }\n\n return {\n conceptualChanges: [...grouped.values()],\n };\n}\n\n/** Get the highest severity across all languages for a conceptual change. */\nexport function highestSeverity(change: ConceptualChange): CompatChangeSeverity {\n const severities = Object.values(change.impact);\n if (severities.includes('breaking')) return 'breaking';\n if (severities.includes('soft-risk')) return 'soft-risk';\n return 'additive';\n}\n\n/** Count conceptual changes by highest severity. */\nexport function summarizeConceptualChanges(rollup: ConceptualRollup): {\n breaking: number;\n softRisk: number;\n additive: number;\n} {\n let breaking = 0;\n let softRisk = 0;\n let additive = 0;\n for (const change of rollup.conceptualChanges) {\n const sev = highestSeverity(change);\n if (sev === 'breaking') breaking++;\n else if (sev === 'soft-risk') softRisk++;\n else additive++;\n }\n return { breaking, softRisk, additive };\n}\n","/**\n * Report generation for compatibility verification.\n *\n * Produces machine-readable JSON reports, human-readable terminal summaries,\n * and conceptual cross-language summaries.\n */\n\nimport type { LanguageId } from './ir.js';\nimport type { CompatChangeSeverity, CompatChangeCategory, CompatProvenance } from './config.js';\nimport type { CompatDiffResult } from './differ.js';\nimport { buildConceptualRollup, highestSeverity, summarizeConceptualChanges } from './concepts.js';\n\n// ---------------------------------------------------------------------------\n// Machine-readable report\n// ---------------------------------------------------------------------------\n\n/** Machine-readable compat report for a single language. */\nexport interface CompatReport {\n schemaVersion: string;\n language: string;\n summary: {\n breaking: number;\n softRisk: number;\n additive: number;\n };\n changes: CompatReportChange[];\n}\n\n/** A single change entry in the machine-readable report. */\nexport interface CompatReportChange {\n severity: CompatChangeSeverity;\n category: CompatChangeCategory;\n symbol: string;\n conceptualChangeId: string;\n provenance: CompatProvenance;\n old: Record<string, string>;\n new: Record<string, string>;\n message?: string;\n}\n\n/** Generate a machine-readable compat report from a diff result. */\nexport function generateReport(diff: CompatDiffResult, language?: string): CompatReport {\n return {\n schemaVersion: '1',\n language: language ?? 'unknown',\n summary: diff.summary,\n changes: diff.changes.map((c) => ({\n severity: c.severity,\n category: c.category,\n symbol: c.symbol,\n conceptualChangeId: c.conceptualChangeId,\n provenance: c.provenance,\n old: c.old,\n new: c.new,\n ...(c.message ? { message: c.message } : {}),\n })),\n };\n}\n\n// ---------------------------------------------------------------------------\n// Human-readable terminal summary\n// ---------------------------------------------------------------------------\n\n/** Generate a human-readable summary string for terminal output. */\nexport function formatHumanSummary(diff: CompatDiffResult, opts?: { explain?: boolean; language?: string }): string {\n const lines: string[] = [];\n\n lines.push(`Compat report${opts?.language ? ` for ${opts.language}` : ''}:`);\n lines.push(\n ` ${diff.summary.breaking} breaking, ${diff.summary.softRisk} soft-risk, ${diff.summary.additive} additive`,\n );\n\n if (diff.changes.length === 0) {\n lines.push(' No compatibility changes detected.');\n return lines.join('\\n');\n }\n\n // Group by severity for display\n const breaking = diff.changes.filter((c) => c.severity === 'breaking');\n const softRisk = diff.changes.filter((c) => c.severity === 'soft-risk');\n const additive = diff.changes.filter((c) => c.severity === 'additive');\n\n if (breaking.length > 0) {\n lines.push('');\n lines.push(' Breaking:');\n for (const c of breaking) {\n lines.push(` [${c.category}] ${c.symbol} — ${c.message}`);\n if (opts?.explain && c.provenance !== 'unknown') {\n lines.push(` provenance: ${c.provenance}`);\n }\n }\n }\n\n if (softRisk.length > 0) {\n lines.push('');\n lines.push(' Soft-risk:');\n for (const c of softRisk) {\n lines.push(` [${c.category}] ${c.symbol} — ${c.message}`);\n if (opts?.explain && c.provenance !== 'unknown') {\n lines.push(` provenance: ${c.provenance}`);\n }\n }\n }\n\n if (additive.length > 0) {\n lines.push('');\n lines.push(` Additive: ${additive.length} new symbol(s)`);\n }\n\n return lines.join('\\n');\n}\n\n// ---------------------------------------------------------------------------\n// Conceptual cross-language summary\n// ---------------------------------------------------------------------------\n\n/** Conceptual cross-language report. */\nexport interface ConceptualReport {\n conceptualChanges: {\n id: string;\n symbol: string;\n category: CompatChangeCategory;\n impact: Partial<Record<LanguageId, CompatChangeSeverity>>;\n }[];\n}\n\n/** Generate a conceptual cross-language report from multiple per-language results. */\nexport function generateConceptualReport(\n perLanguageResults: Array<{ diff: CompatDiffResult; language: LanguageId }>,\n): ConceptualReport {\n const rollup = buildConceptualRollup(perLanguageResults);\n return {\n conceptualChanges: rollup.conceptualChanges.map((c) => ({\n id: c.id,\n symbol: c.symbol,\n category: c.category,\n impact: c.impact,\n })),\n };\n}\n\n/** Format a conceptual cross-language summary for terminal output. */\nexport function formatConceptualSummary(\n perLanguageResults: Array<{ diff: CompatDiffResult; language: LanguageId }>,\n): string {\n const rollup = buildConceptualRollup(perLanguageResults);\n const summary = summarizeConceptualChanges(rollup);\n const lines: string[] = [];\n\n lines.push('Cross-language conceptual summary:');\n lines.push(` ${summary.breaking} breaking, ${summary.softRisk} soft-risk, ${summary.additive} additive`);\n\n if (rollup.conceptualChanges.length === 0) {\n lines.push(' No cross-language changes.');\n return lines.join('\\n');\n }\n\n for (const change of rollup.conceptualChanges) {\n const sev = highestSeverity(change);\n const impactStr = Object.entries(change.impact)\n .map(([lang, s]) => `${lang}: ${s}`)\n .join(', ');\n lines.push(` [${sev}] ${change.category}: ${change.symbol}`);\n lines.push(` impact: ${impactStr}`);\n }\n\n return lines.join('\\n');\n}\n","/**\n * Approval matching engine for compatibility verification.\n *\n * Matches CompatApproval entries from oagen.config.ts against classified\n * changes. Approved changes are excluded from failure thresholds.\n *\n * Approvals must be narrow (one symbol, one category, one conceptual change).\n * Overly broad approvals are rejected at validation time.\n */\n\nimport type { LanguageId } from './ir.js';\nimport type { CompatApproval } from './config.js';\nimport type { ClassifiedChange } from './classify.js';\n\n/** Result of matching a change against approvals. */\nexport interface ApprovalMatch {\n /** The change that was matched. */\n change: ClassifiedChange;\n /** The approval that matched. null if no approval covers this change. */\n approval: CompatApproval | null;\n /** Whether the change is covered by an approval. */\n approved: boolean;\n}\n\n/** Result of validating an approval for broadness. */\nexport interface ApprovalValidation {\n valid: boolean;\n errors: string[];\n}\n\n// ---------------------------------------------------------------------------\n// Validation\n// ---------------------------------------------------------------------------\n\n/** Validate that an approval is narrow enough to be accepted. */\nexport function validateApproval(approval: CompatApproval): ApprovalValidation {\n const errors: string[] = [];\n\n if (!approval.symbol || approval.symbol.trim() === '') {\n errors.push('Approval must target a specific symbol');\n }\n\n if (!approval.category) {\n errors.push('Approval must specify a change category');\n }\n\n if (!approval.reason || approval.reason.trim() === '') {\n errors.push('Approval must include a reason');\n }\n\n // Wildcard symbols are too broad\n if (approval.symbol === '*' || approval.symbol.endsWith('.*') || approval.symbol.endsWith('::*')) {\n errors.push(`Approval symbol \"${approval.symbol}\" is too broad — must target a specific symbol`);\n }\n\n return {\n valid: errors.length === 0,\n errors,\n };\n}\n\n/** Validate all approvals in a config. Returns errors keyed by index. */\nexport function validateApprovals(approvals: CompatApproval[]): Map<number, string[]> {\n const result = new Map<number, string[]>();\n for (let i = 0; i < approvals.length; i++) {\n const validation = validateApproval(approvals[i]);\n if (!validation.valid) {\n result.set(i, validation.errors);\n }\n }\n return result;\n}\n\n// ---------------------------------------------------------------------------\n// Matching\n// ---------------------------------------------------------------------------\n\n/**\n * Match a classified change against a list of approvals.\n * Returns the first matching approval, or null if none match.\n */\nexport function matchApproval(\n change: ClassifiedChange,\n approvals: CompatApproval[],\n language: LanguageId,\n): CompatApproval | null {\n for (const approval of approvals) {\n if (approvalMatchesChange(approval, change, language)) {\n return approval;\n }\n }\n return null;\n}\n\n/**\n * Apply approvals to a list of changes.\n * Returns matches for every change (approved or not).\n */\nexport function applyApprovals(\n changes: ClassifiedChange[],\n approvals: CompatApproval[],\n language: LanguageId,\n): ApprovalMatch[] {\n return changes.map((change) => {\n const approval = matchApproval(change, approvals, language);\n return {\n change,\n approval,\n approved: approval !== null,\n };\n });\n}\n\n/**\n * Filter changes to only those NOT covered by approvals.\n * These are the remaining unapproved changes that may cause failure.\n */\nexport function unapprovedChanges(\n changes: ClassifiedChange[],\n approvals: CompatApproval[],\n language: LanguageId,\n): ClassifiedChange[] {\n return changes.filter((change) => !matchApproval(change, approvals, language));\n}\n\n// ---------------------------------------------------------------------------\n// Internal matching logic\n// ---------------------------------------------------------------------------\n\nfunction approvalMatchesChange(approval: CompatApproval, change: ClassifiedChange, language: LanguageId): boolean {\n // Skip inactive approvals\n if (approval.approved === false) return false;\n\n // Category must match exactly\n if (approval.category !== change.category) return false;\n\n // Symbol must match\n if (!symbolMatches(approval.symbol, change.symbol)) return false;\n\n // Language scoping\n if (!languageMatches(approval.appliesTo, language)) return false;\n\n // Narrowing match (optional)\n if (approval.match && !narrowingMatches(approval.match, change)) return false;\n\n return true;\n}\n\nfunction symbolMatches(approvalSymbol: string, changeSymbol: string): boolean {\n // Exact match\n if (approvalSymbol === changeSymbol) return true;\n\n // Normalize common separators for cross-language matching\n // PHP uses :: and \\, others use . — normalize to dots for comparison\n const normalizedApproval = approvalSymbol.replace(/::/g, '.').replace(/\\\\/g, '.');\n const normalizedChange = changeSymbol.replace(/::/g, '.').replace(/\\\\/g, '.');\n return normalizedApproval === normalizedChange;\n}\n\nfunction languageMatches(appliesTo: CompatApproval['appliesTo'], language: LanguageId): boolean {\n if (!appliesTo || appliesTo === 'all-impacted-languages') return true;\n return appliesTo.includes(language);\n}\n\nfunction narrowingMatches(match: NonNullable<CompatApproval['match']>, change: ClassifiedChange): boolean {\n if (match.parameter) {\n // Check if the change involves this parameter\n const paramInOld = change.old.parameter === match.parameter;\n const paramInNew = change.new.parameter === match.parameter;\n if (!paramInOld && !paramInNew) return false;\n }\n if (match.member) {\n const memberInOld = change.old.member === match.member;\n const memberInNew = change.new.member === match.member;\n if (!memberInOld && !memberInNew) return false;\n }\n if (match.oldName) {\n const nameMatch = Object.values(change.old).some((v) => v === match.oldName);\n if (!nameMatch) return false;\n }\n if (match.newName) {\n const nameMatch = Object.values(change.new).some((v) => v === match.newName);\n if (!nameMatch) return false;\n }\n return true;\n}\n","/** Sort an object's keys alphabetically. Shared across all extractors for deterministic output. */\nexport function sortRecord<T>(record: Record<string, T>): Record<string, T> {\n const sorted: Record<string, T> = {};\n for (const key of Object.keys(record).sort()) {\n sorted[key] = record[key];\n }\n return sorted;\n}\n\n/** Collects per-file export names, deduplicating and sorting on finalization. */\nexport class ExportCollector {\n private map = new Map<string, Set<string>>();\n\n add(sourceFile: string, name: string): void {\n let set = this.map.get(sourceFile);\n if (!set) {\n set = new Set();\n this.map.set(sourceFile, set);\n }\n set.add(name);\n }\n\n toRecord(): Record<string, string[]> {\n const result: Record<string, string[]> = {};\n for (const [file, names] of this.map) {\n result[file] = [...names].sort();\n }\n return result;\n }\n}\n","import ts from 'typescript';\nimport { readFileSync } from 'node:fs';\nimport path, { resolve, relative } from 'node:path';\nimport { ExtractorError } from '../../errors.js';\nimport type {\n ApiSurface,\n Extractor,\n ApiClass,\n ApiMethod,\n ApiParam,\n ApiProperty,\n ApiInterface,\n ApiField,\n ApiTypeAlias,\n ApiEnum,\n} from '../types.js';\nimport type { CompatSnapshot } from '../ir.js';\nimport { apiSurfaceToSnapshot } from '../ir.js';\nimport { nodeHints } from '../language-hints.js';\nimport { sortRecord } from './shared.js';\n\nexport const nodeExtractor: Extractor = {\n language: 'node',\n hints: nodeHints,\n\n async extractSnapshot(sdkPath: string): Promise<CompatSnapshot> {\n const surface = await this.extract(sdkPath);\n return apiSurfaceToSnapshot(surface);\n },\n\n async extract(sdkPath: string): Promise<ApiSurface> {\n sdkPath = resolve(sdkPath);\n const configPath = ts.findConfigFile(sdkPath, ts.sys.fileExists, 'tsconfig.json');\n if (!configPath)\n throw new ExtractorError(\n `No tsconfig.json found in ${sdkPath}`,\n `Create a tsconfig.json in \"${sdkPath}\" or verify the --sdk-path argument points to a TypeScript project root.`,\n );\n\n const configFile = ts.readConfigFile(configPath, ts.sys.readFile);\n const parsedConfig = ts.parseJsonConfigFileContent(configFile.config, ts.sys, sdkPath);\n const program = ts.createProgram(parsedConfig.fileNames, parsedConfig.options);\n const checker = program.getTypeChecker();\n\n const entryPoint = resolveEntryPoint(sdkPath, program);\n const entrySourceFile = program.getSourceFile(entryPoint);\n if (!entrySourceFile)\n throw new ExtractorError(\n `Entry point not found: ${entryPoint}`,\n `Ensure the file \"${entryPoint}\" exists and is included in the tsconfig.json \"include\" or \"files\" array.`,\n );\n\n const moduleSymbol = checker.getSymbolAtLocation(entrySourceFile);\n if (!moduleSymbol)\n throw new ExtractorError(\n 'No exports found at entry point',\n `Verify that \"${entryPoint}\" has at least one \\`export\\` statement. The extractor needs public exports to build an API surface.`,\n );\n\n const exportedSymbols = checker.getExportsOfModule(moduleSymbol);\n\n const classes: Record<string, ApiClass> = {};\n const interfaces: Record<string, ApiInterface> = {};\n const typeAliases: Record<string, ApiTypeAlias> = {};\n const enums: Record<string, ApiEnum> = {};\n\n for (const sym of exportedSymbols) {\n const resolved = resolveAlias(sym, checker);\n const declarations = resolved.getDeclarations();\n if (!declarations || declarations.length === 0) continue;\n const decl = declarations[0];\n\n const sourceFile = relative(sdkPath, decl.getSourceFile().fileName);\n\n if (ts.isClassDeclaration(decl)) {\n classes[resolved.name] = { ...extractClass(resolved, checker), sourceFile };\n } else if (ts.isInterfaceDeclaration(decl)) {\n interfaces[resolved.name] = { ...extractInterface(resolved, checker), sourceFile };\n } else if (ts.isTypeAliasDeclaration(decl)) {\n typeAliases[resolved.name] = { ...extractTypeAlias(resolved, checker), sourceFile };\n } else if (ts.isEnumDeclaration(decl)) {\n enums[resolved.name] = { ...extractEnum(resolved, checker), sourceFile };\n }\n }\n\n // Follow property types on extracted classes to discover resource classes\n // (e.g., WorkOS.apiKeys: ApiKeys → extract ApiKeys)\n followPropertyTypeClasses(exportedSymbols, checker, classes, sdkPath);\n\n const exports = buildExportMap(entrySourceFile, checker, sdkPath, program);\n\n return {\n language: 'node',\n extractedFrom: sdkPath,\n extractedAt: new Date().toISOString(),\n classes: sortRecord(classes),\n interfaces: sortRecord(interfaces),\n typeAliases: sortRecord(typeAliases),\n enums: sortRecord(enums),\n exports: sortRecord(exports),\n };\n },\n};\n\nfunction followPropertyTypeClasses(\n exportedSymbols: ts.Symbol[],\n checker: ts.TypeChecker,\n classes: Record<string, ApiClass>,\n sdkPath: string,\n): void {\n // Build initial set of class symbols from exports\n const classSymbols = new Map<string, ts.Symbol>();\n for (const sym of exportedSymbols) {\n const resolved = resolveAlias(sym, checker);\n const decls = resolved.getDeclarations();\n if (decls?.some((d) => ts.isClassDeclaration(d))) {\n classSymbols.set(resolved.name, resolved);\n }\n }\n\n const toVisit = [...classSymbols.values()];\n const visited = new Set(classSymbols.keys());\n\n while (toVisit.length > 0) {\n const sym = toVisit.pop()!;\n const type = checker.getDeclaredTypeOfSymbol(sym);\n const decls = sym.getDeclarations();\n if (!decls || decls.length === 0) continue;\n\n for (const prop of type.getProperties()) {\n const propDecls = prop.getDeclarations();\n if (!propDecls || propDecls.length === 0) continue;\n const propDecl = propDecls[0];\n\n // Skip private/protected\n const modifiers = ts.canHaveModifiers(propDecl) ? ts.getModifiers(propDecl) : undefined;\n if (\n modifiers?.some((m) => m.kind === ts.SyntaxKind.PrivateKeyword || m.kind === ts.SyntaxKind.ProtectedKeyword)\n ) {\n continue;\n }\n\n const propType = checker.getTypeOfSymbolAtLocation(prop, propDecl);\n const propSymbol = propType.getSymbol();\n if (!propSymbol) continue;\n\n const propName = propSymbol.name;\n if (visited.has(propName)) continue;\n\n const propSymDecls = propSymbol.getDeclarations();\n if (!propSymDecls?.some((d) => ts.isClassDeclaration(d))) continue;\n\n // Found a class referenced by property type — extract it\n visited.add(propName);\n const sourceFile = relative(sdkPath, propSymDecls[0].getSourceFile().fileName);\n classes[propName] = { ...extractClass(propSymbol, checker), sourceFile };\n toVisit.push(propSymbol);\n }\n }\n}\n\nfunction resolveEntryPoint(sdkPath: string, program: ts.Program): string {\n const pkgPath = resolve(sdkPath, 'package.json');\n try {\n const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));\n // Check \"exports\" field first\n if (pkg.exports) {\n const mainExport =\n typeof pkg.exports === 'string'\n ? pkg.exports\n : (pkg.exports['.']?.import ?? pkg.exports['.']?.default ?? pkg.exports['.']);\n if (typeof mainExport === 'string') {\n const resolved = resolveSourceFile(sdkPath, mainExport, program);\n if (resolved) return resolved;\n }\n }\n // Fallback to \"main\"\n if (pkg.main) {\n const resolved = resolveSourceFile(sdkPath, pkg.main, program);\n if (resolved) return resolved;\n }\n } catch {\n // No package.json or invalid — fall through to default\n }\n\n // Default fallback\n const fallback = resolve(sdkPath, 'src/index.ts');\n if (program.getSourceFile(fallback)) return fallback;\n throw new ExtractorError(\n `No entry point found. Tried: package.json exports/main, src/index.ts`,\n `Add an \"exports\" or \"main\" field to package.json in \"${sdkPath}\", or create a src/index.ts file that re-exports the public API.`,\n );\n}\n\nfunction resolveSourceFile(sdkPath: string, entryPath: string, program: ts.Program): string | undefined {\n // Try the path as-is, then swap .js → .ts, then try index.ts\n const candidates = [\n resolve(sdkPath, entryPath),\n resolve(sdkPath, entryPath.replace(/\\.js$/, '.ts')),\n resolve(sdkPath, entryPath.replace(/\\.js$/, '/index.ts')),\n ];\n for (const candidate of candidates) {\n if (program.getSourceFile(candidate)) return candidate;\n }\n return undefined;\n}\n\nfunction resolveAlias(sym: ts.Symbol, checker: ts.TypeChecker): ts.Symbol {\n if (sym.flags & ts.SymbolFlags.Alias) {\n return checker.getAliasedSymbol(sym);\n }\n return sym;\n}\n\nfunction extractClass(sym: ts.Symbol, checker: ts.TypeChecker): ApiClass {\n const type = checker.getDeclaredTypeOfSymbol(sym);\n const methods: Record<string, ApiMethod[]> = {};\n const properties: Record<string, ApiProperty> = {};\n const constructorParams: ApiParam[] = [];\n let deprecationMessage: string | undefined;\n\n // Extract constructor params\n const declarations = sym.getDeclarations();\n if (declarations) {\n for (const decl of declarations) {\n if (ts.isClassDeclaration(decl)) {\n // Look for `@deprecated` in the class's JSDoc. JSDoc nodes are\n // attached to the declaration's parent range; TS exposes them via\n // ts.getJSDocDeprecatedTag.\n const deprecatedTag = ts.getJSDocDeprecatedTag(decl);\n if (deprecatedTag) {\n const comment = deprecatedTag.comment;\n if (typeof comment === 'string') {\n deprecationMessage = comment.trim() || '';\n } else if (Array.isArray(comment)) {\n deprecationMessage =\n comment\n .map((c) => c.text)\n .join('')\n .trim() || '';\n } else {\n deprecationMessage = '';\n }\n }\n for (const member of decl.members) {\n if (ts.isConstructorDeclaration(member)) {\n for (const param of member.parameters) {\n const { name: paramName, isDestructured } = extractParameterInfo(param, param.name.getText());\n const paramType = param.type ? checker.typeToString(checker.getTypeFromTypeNode(param.type)) : 'any';\n constructorParams.push({\n name: paramName,\n type: paramType,\n optional: !!param.questionToken || !!param.initializer,\n passingStyle: isDestructured ? 'options_object' : 'positional',\n });\n }\n }\n }\n }\n }\n }\n\n // Extract methods and properties from the type\n for (const prop of type.getProperties()) {\n // Skip private/protected members\n const propDeclarations = prop.getDeclarations();\n if (propDeclarations && propDeclarations.length > 0) {\n const decl = propDeclarations[0];\n const modifiers = ts.canHaveModifiers(decl) ? ts.getModifiers(decl) : undefined;\n if (\n modifiers?.some((m) => m.kind === ts.SyntaxKind.PrivateKeyword || m.kind === ts.SyntaxKind.ProtectedKeyword)\n ) {\n continue;\n }\n }\n\n const propType = checker.getTypeOfSymbolAtLocation(prop, declarations![0]);\n const callSignatures = propType.getCallSignatures();\n\n if (callSignatures.length > 0) {\n if (!methods[prop.name]) methods[prop.name] = [];\n // Extract ALL overloads, not just the first\n for (const sig of callSignatures) {\n methods[prop.name].push({\n name: prop.name,\n params: sig.getParameters().map((p) => extractParam(p, checker)),\n returnType: checker.typeToString(sig.getReturnType()),\n async: checker.typeToString(sig.getReturnType()).startsWith('Promise<'),\n });\n }\n } else {\n const typeStr = checker.typeToString(propType);\n const isReadonly = propDeclarations?.some((d) => {\n const mods = ts.canHaveModifiers(d) ? ts.getModifiers(d) : undefined;\n return mods?.some((m) => m.kind === ts.SyntaxKind.ReadonlyKeyword);\n });\n properties[prop.name] = {\n name: prop.name,\n type: typeStr,\n readonly: !!isReadonly,\n };\n }\n }\n\n return {\n name: sym.name,\n methods: sortRecord(methods),\n properties: sortRecord(properties),\n constructorParams,\n ...(deprecationMessage !== undefined && { deprecationMessage }),\n };\n}\n\nfunction extractParam(sym: ts.Symbol, checker: ts.TypeChecker): ApiParam {\n const decl = sym.getDeclarations()?.[0];\n const isOptional = decl && ts.isParameter(decl) ? !!decl.questionToken || !!decl.initializer : false;\n const type = checker.getTypeOfSymbolAtLocation(sym, decl!);\n const { name, isDestructured } = extractParameterInfo(decl, sym.name);\n const typeStr = checker.typeToString(type);\n\n // Detect options object pattern:\n // - destructured object binding ({a, b}: Options)\n // - single non-primitive param with an object/interface type\n let passingStyle: ApiParam['passingStyle'];\n if (isDestructured) {\n passingStyle = 'options_object';\n } else {\n const resolvedType = checker.getTypeOfSymbolAtLocation(sym, decl!);\n const isObjectLike = resolvedType.isClassOrInterface() || (resolvedType.getFlags() & ts.TypeFlags.Object) !== 0;\n const isPrimitive = [\n 'string',\n 'number',\n 'boolean',\n 'undefined',\n 'null',\n 'void',\n 'never',\n 'any',\n 'unknown',\n ].includes(typeStr);\n if (isObjectLike && !isPrimitive && !typeStr.startsWith('Promise<')) {\n passingStyle = 'options_object';\n } else {\n passingStyle = 'positional';\n }\n }\n\n return {\n name,\n type: typeStr,\n optional: isOptional,\n passingStyle,\n };\n}\n\nfunction extractParameterInfo(\n decl: ts.Declaration | undefined,\n fallback: string,\n): { name: string; isDestructured: boolean } {\n if (!decl || !ts.isParameter(decl)) return { name: fallback, isDestructured: false };\n if (ts.isIdentifier(decl.name)) return { name: decl.name.text, isDestructured: false };\n\n const parentWithParameters = decl.parent as ts.Node & { parameters?: ts.NodeArray<ts.ParameterDeclaration> };\n const index = parentWithParameters.parameters?.indexOf(decl) ?? -1;\n const suffix = index > 0 ? String(index) : '';\n\n if (ts.isObjectBindingPattern(decl.name)) return { name: `options${suffix}`, isDestructured: true };\n if (ts.isArrayBindingPattern(decl.name)) return { name: `args${suffix}`, isDestructured: false };\n\n return { name: fallback, isDestructured: false };\n}\n\nfunction extractInterface(sym: ts.Symbol, checker: ts.TypeChecker): ApiInterface {\n const type = checker.getDeclaredTypeOfSymbol(sym);\n const fields: Record<string, ApiField> = {};\n const extendsNames: string[] = [];\n\n // Get extends clauses\n const declarations = sym.getDeclarations();\n if (declarations) {\n for (const decl of declarations) {\n if (ts.isInterfaceDeclaration(decl) && decl.heritageClauses) {\n for (const clause of decl.heritageClauses) {\n for (const typeExpr of clause.types) {\n extendsNames.push(typeExpr.getText());\n }\n }\n }\n }\n }\n\n for (const prop of type.getProperties()) {\n const propType = checker.getTypeOfSymbolAtLocation(prop, declarations![0]);\n const propDecl = prop.getDeclarations()?.[0];\n const isOptional = propDecl && ts.isPropertySignature(propDecl) ? !!propDecl.questionToken : false;\n let typeStr = checker.typeToString(propType);\n if (isOptional) {\n typeStr = stripUndefined(typeStr);\n }\n fields[prop.name] = {\n name: prop.name,\n type: typeStr,\n optional: isOptional,\n };\n }\n\n // Fallback: walk AST declaration members for fields that type.getProperties() missed.\n // This handles generic interfaces (e.g., List<T>) where the checker may not resolve\n // all properties when the type parameter is unbound.\n if (declarations) {\n for (const decl of declarations) {\n if (ts.isInterfaceDeclaration(decl)) {\n for (const member of decl.members) {\n if (ts.isPropertySignature(member) && member.name) {\n const memberName = member.name.getText();\n if (!fields[memberName]) {\n const memberType = member.type ? checker.typeToString(checker.getTypeFromTypeNode(member.type)) : 'any';\n const isOpt = !!member.questionToken;\n fields[memberName] = {\n name: memberName,\n type: isOpt ? stripUndefined(memberType) : memberType,\n optional: isOpt,\n };\n }\n }\n }\n }\n }\n }\n\n return {\n name: sym.name,\n fields: sortRecord(fields),\n extends: extendsNames.sort(),\n };\n}\n\nfunction extractTypeAlias(sym: ts.Symbol, checker: ts.TypeChecker): ApiTypeAlias {\n const type = checker.getDeclaredTypeOfSymbol(sym);\n return {\n name: sym.name,\n value: checker.typeToString(type, undefined, ts.TypeFormatFlags.InTypeAlias | ts.TypeFormatFlags.NoTruncation),\n };\n}\n\nfunction extractEnum(sym: ts.Symbol, checker: ts.TypeChecker): ApiEnum {\n const members: Record<string, string | number> = {};\n const type = checker.getDeclaredTypeOfSymbol(sym);\n\n if (type.isUnion()) {\n for (const memberType of type.types) {\n if (memberType.symbol) {\n const constValue = checker.getConstantValue(memberType.symbol.getDeclarations()![0] as ts.EnumMember);\n if (constValue !== undefined) {\n members[memberType.symbol.name] = constValue;\n }\n }\n }\n }\n\n return {\n name: sym.name,\n members: sortRecord(members),\n };\n}\n\nfunction buildExportMap(\n entryFile: ts.SourceFile,\n checker: ts.TypeChecker,\n sdkPath: string,\n program: ts.Program,\n): Record<string, string[]> {\n const exports: Record<string, string[]> = {};\n const visited = new Set<string>();\n\n function walk(sourceFile: ts.SourceFile): void {\n const absPath = sourceFile.fileName;\n if (visited.has(absPath)) return;\n visited.add(absPath);\n\n const relPath = relative(sdkPath, absPath);\n const moduleSymbol = checker.getSymbolAtLocation(sourceFile);\n if (moduleSymbol) {\n const names = checker.getExportsOfModule(moduleSymbol).map((s) => s.name);\n if (names.length > 0) {\n exports[relPath] = names.sort();\n }\n }\n\n for (const stmt of sourceFile.statements) {\n if (ts.isExportDeclaration(stmt) && stmt.moduleSpecifier && ts.isStringLiteral(stmt.moduleSpecifier)) {\n const target = stmt.moduleSpecifier.text;\n const resolved = resolveSourceFile(path.dirname(absPath), target, program);\n if (resolved) {\n const targetFile = program.getSourceFile(resolved);\n if (targetFile) {\n walk(targetFile);\n }\n }\n }\n }\n }\n\n walk(entryFile);\n return exports;\n}\n\nfunction stripUndefined(typeStr: string): string {\n return typeStr.replace(/\\s*\\|\\s*undefined$/, '').replace(/^undefined\\s*\\|\\s*/, '');\n}\n","/**\n * PHP source parser — tree-sitter-based extraction of classes, interfaces,\n * methods, properties, and constants from PHP source files.\n */\nimport { readFileSync, readdirSync, statSync } from 'node:fs';\nimport { join, relative } from 'node:path';\nimport Parser from 'tree-sitter';\nimport PhpGrammar from 'tree-sitter-php';\nimport type { SyntaxNode } from 'tree-sitter';\nimport { safeParse } from '../../utils/tree-sitter.js';\n\n// ---------------------------------------------------------------------------\n// Internal types\n// ---------------------------------------------------------------------------\n\nexport interface PhpParam {\n name: string;\n type: string;\n optional: boolean;\n}\n\nexport interface PhpMethod {\n name: string;\n visibility: 'public' | 'protected' | 'private';\n isStatic: boolean;\n params: PhpParam[];\n returnType: string;\n}\n\nexport interface PhpConstant {\n name: string;\n value: string;\n}\n\nexport interface PhpProperty {\n name: string;\n type: string;\n visibility: 'public' | 'protected' | 'private';\n}\n\nexport interface PhpClass {\n name: string;\n namespace: string;\n extends: string | null;\n isInterface: boolean;\n methods: PhpMethod[];\n properties: PhpProperty[];\n constants: PhpConstant[];\n resourceAttributes: string[];\n /** True if the class defines its own constructFromResponse method (not inherited). */\n hasCustomConstructor: boolean;\n sourceFile: string;\n}\n\n// ---------------------------------------------------------------------------\n// Shared parser instance\n// ---------------------------------------------------------------------------\n\nconst phpParser = new Parser();\nphpParser.setLanguage(PhpGrammar.php_only);\n\n// ---------------------------------------------------------------------------\n// File walker\n// ---------------------------------------------------------------------------\n\nexport function walkPhpFiles(dir: string): string[] {\n const results: string[] = [];\n let entries: string[];\n try {\n entries = readdirSync(dir);\n } catch {\n return results;\n }\n for (const entry of entries) {\n const fullPath = join(dir, entry);\n let stat;\n try {\n stat = statSync(fullPath);\n } catch {\n continue;\n }\n if (stat.isDirectory()) {\n if (entry.startsWith('.') || entry === 'vendor' || entry === 'tests' || entry === 'test') continue;\n results.push(...walkPhpFiles(fullPath));\n } else if (entry.endsWith('.php')) {\n results.push(fullPath);\n }\n }\n return results.sort();\n}\n\ninterface PhpDocInfo {\n params: Map<string, string>; // $name → type\n returnType: string;\n}\n\nfunction parsePhpDoc(commentText: string): PhpDocInfo {\n const params = new Map<string, string>();\n let returnType = '';\n\n const lines = commentText.split('\\n');\n for (const line of lines) {\n // Match @param type $name\n const paramMatch = line.match(/@param\\s+(\\S+)\\s+\\$(\\w+)/);\n if (paramMatch) {\n params.set(paramMatch[2], paramMatch[1]);\n }\n // Match @return type\n const returnMatch = line.match(/@return\\s+(\\S+)/);\n if (returnMatch) {\n returnType = returnMatch[1];\n }\n }\n\n return { params, returnType };\n}\n\n/** Find the doc comment immediately preceding a node. */\nfunction findDocComment(node: SyntaxNode): PhpDocInfo | null {\n // Walk backward through siblings to find comment\n let sibling = node.previousNamedSibling;\n if (sibling && sibling.type === 'comment' && sibling.text.startsWith('/**')) {\n return parsePhpDoc(sibling.text);\n }\n return null;\n}\n\nfunction getVisibility(node: SyntaxNode): 'public' | 'protected' | 'private' {\n for (const child of node.children) {\n if (child.type === 'visibility_modifier') {\n const text = child.text.toLowerCase();\n if (text === 'public') return 'public';\n if (text === 'protected') return 'protected';\n if (text === 'private') return 'private';\n }\n }\n return 'public'; // PHP default\n}\n\nfunction isStaticMethod(node: SyntaxNode): boolean {\n for (const child of node.children) {\n if (child.type === 'static_modifier') return true;\n }\n return false;\n}\n\n/** Parse a PHP array literal to extract string values: [\"id\", \"name\", ...] */\nfunction parseArrayLiteral(node: SyntaxNode): string[] {\n const values: string[] = [];\n // In tree-sitter-php, array elements contain encapsed_string → string_content\n // For simple indexed arrays, each array_element_initializer has one encapsed_string\n for (const elemInit of node.descendantsOfType('array_element_initializer')) {\n const strings = elemInit.namedChildren.filter((c) => c.type === 'encapsed_string' || c.type === 'string');\n // For indexed arrays (no =>), there's one string per element\n if (strings.length === 1) {\n const contentNode = strings[0].namedChildren.find((c) => c.type === 'string_content');\n if (contentNode) {\n values.push(contentNode.text);\n }\n }\n }\n return values;\n}\n\n/** Extract the name and value from a const_element node. */\nfunction parseConstElement(constElement: SyntaxNode): { name: string; value: string } | null {\n const nameNode = constElement.namedChildren.find((c) => c.type === 'name');\n if (!nameNode) return null;\n\n const constName = nameNode.text;\n\n // Skip RESOURCE_ATTRIBUTES and RESPONSE_TO_RESOURCE_KEY (they're arrays, not scalar constants)\n if (constName === 'RESOURCE_ATTRIBUTES' || constName === 'RESPONSE_TO_RESOURCE_KEY') return null;\n\n // Find the value node (encapsed_string, string, integer, etc.)\n const valueNode = constElement.namedChildren.find((c) => c.type !== 'name');\n if (!valueNode) return null;\n\n // For string values, extract string_content\n if (valueNode.type === 'encapsed_string') {\n const contentNode = valueNode.namedChildren.find((c) => c.type === 'string_content');\n return { name: constName, value: contentNode ? contentNode.text : '' };\n }\n if (valueNode.type === 'string') {\n const contentNode = valueNode.namedChildren.find((c) => c.type === 'string_content');\n return { name: constName, value: contentNode ? contentNode.text : '' };\n }\n\n // For other types (integers, etc.), use the raw text\n return { name: constName, value: valueNode.text };\n}\n\n// ---------------------------------------------------------------------------\n// Method extraction\n// ---------------------------------------------------------------------------\n\nfunction parseMethods(classBody: SyntaxNode): PhpMethod[] {\n const methods: PhpMethod[] = [];\n\n for (const child of classBody.namedChildren) {\n if (child.type !== 'method_declaration') continue;\n\n const nameNode = child.childForFieldName('name');\n if (!nameNode) continue;\n const methodName = nameNode.text;\n\n // Skip magic methods except __construct\n if (methodName.startsWith('__') && methodName !== '__construct') continue;\n\n const visibility = getVisibility(child);\n const isStatic = isStaticMethod(child);\n\n // Get PHPDoc info\n const docInfo = findDocComment(child);\n\n // Parse parameters\n const params: PhpParam[] = [];\n const paramsList = child.childForFieldName('parameters');\n if (paramsList) {\n for (const paramNode of paramsList.namedChildren) {\n if (paramNode.type !== 'simple_parameter') continue;\n\n const paramNameNode = paramNode.namedChildren.find((c) => c.type === 'variable_name');\n if (!paramNameNode) continue;\n\n const paramName = paramNameNode.text.replace(/^\\$/, '');\n\n // Check for native type hint\n let paramType = '';\n const typeNode = paramNode.childForFieldName('type');\n if (typeNode) {\n paramType = typeNode.text;\n }\n // Fall back to PHPDoc\n if (!paramType && docInfo) {\n paramType = docInfo.params.get(paramName) || 'mixed';\n }\n if (!paramType) {\n paramType = 'mixed';\n }\n\n // Check for default value (means optional)\n const defaultNode = paramNode.childForFieldName('default_value');\n const hasDefault = defaultNode !== null;\n\n params.push({\n name: paramName,\n type: paramType,\n optional: hasDefault,\n });\n }\n }\n\n // Return type\n let returnType = '';\n const returnTypeNode = child.childForFieldName('return_type');\n if (returnTypeNode) {\n returnType = returnTypeNode.text;\n }\n if (!returnType && docInfo) {\n returnType = docInfo.returnType || 'mixed';\n }\n if (!returnType) {\n returnType = 'mixed';\n }\n\n methods.push({\n name: methodName,\n visibility,\n isStatic,\n params,\n returnType,\n });\n }\n\n return methods;\n}\n\n// ---------------------------------------------------------------------------\n// Property extraction\n// ---------------------------------------------------------------------------\n\nfunction parseProperties(classBody: SyntaxNode): PhpProperty[] {\n const properties: PhpProperty[] = [];\n\n for (const child of classBody.namedChildren) {\n if (child.type !== 'property_declaration') continue;\n\n const visibility = getVisibility(child);\n\n // Get property name from property_element → variable_name\n for (const propElement of child.namedChildren) {\n if (propElement.type !== 'property_element') continue;\n const varNameNode = propElement.namedChildren.find((c) => c.type === 'variable_name');\n if (!varNameNode) continue;\n\n const propName = varNameNode.text.replace(/^\\$/, '');\n\n // Check for type hint\n let propType = 'mixed';\n const typeNode = child.namedChildren.find(\n (c) =>\n c.type === 'union_type' ||\n c.type === 'named_type' ||\n c.type === 'optional_type' ||\n c.type === 'primitive_type',\n );\n if (typeNode) {\n propType = typeNode.text;\n }\n\n properties.push({\n name: propName,\n type: propType,\n visibility,\n });\n }\n }\n\n return properties;\n}\n\n// ---------------------------------------------------------------------------\n// Constant extraction\n// ---------------------------------------------------------------------------\n\nfunction parseConstants(classBody: SyntaxNode): PhpConstant[] {\n const constants: PhpConstant[] = [];\n\n for (const child of classBody.namedChildren) {\n if (child.type !== 'const_declaration') continue;\n\n for (const constElement of child.namedChildren) {\n if (constElement.type !== 'const_element') continue;\n\n const parsed = parseConstElement(constElement);\n if (parsed) {\n constants.push(parsed);\n }\n }\n }\n\n return constants;\n}\n\n// ---------------------------------------------------------------------------\n// Resource attributes extraction\n// ---------------------------------------------------------------------------\n\nfunction parseResourceAttributes(classBody: SyntaxNode): string[] {\n for (const child of classBody.namedChildren) {\n if (child.type !== 'const_declaration') continue;\n\n for (const constElement of child.namedChildren) {\n if (constElement.type !== 'const_element') continue;\n\n const nameNode = constElement.namedChildren.find((c) => c.type === 'name');\n if (!nameNode || nameNode.text !== 'RESOURCE_ATTRIBUTES') continue;\n\n const arrayNode = constElement.namedChildren.find((c) => c.type === 'array_creation_expression');\n if (!arrayNode) continue;\n\n return parseArrayLiteral(arrayNode);\n }\n }\n return [];\n}\n\n// ---------------------------------------------------------------------------\n// Namespace extraction\n// ---------------------------------------------------------------------------\n\nfunction extractNamespace(tree: Parser.Tree): string {\n for (const node of tree.rootNode.namedChildren) {\n if (node.type === 'namespace_definition') {\n const nameNode = node.childForFieldName('name');\n return nameNode ? nameNode.text : '';\n }\n }\n return '';\n}\n\n// ---------------------------------------------------------------------------\n// Class/interface extraction\n// ---------------------------------------------------------------------------\n\nfunction parseClassDeclarations(tree: Parser.Tree, sourceFile: string, namespace: string): PhpClass[] {\n const classes: PhpClass[] = [];\n\n for (const node of tree.rootNode.descendantsOfType('class_declaration')) {\n const nameNode = node.childForFieldName('name');\n if (!nameNode) continue;\n\n // Check for extends\n let extendsName: string | null = null;\n const baseClause = node.namedChildren.find((c) => c.type === 'base_clause');\n if (baseClause) {\n const baseNameNode = baseClause.namedChildren.find((c) => c.type === 'name' || c.type === 'qualified_name');\n if (baseNameNode) {\n // Strip leading backslash and namespace qualifiers for base name\n const fullName = baseNameNode.text.replace(/^\\\\/, '');\n const parts = fullName.split('\\\\');\n extendsName = parts[parts.length - 1];\n }\n }\n\n const bodyNode = node.childForFieldName('body');\n if (!bodyNode) continue;\n\n const methods = parseMethods(bodyNode);\n const properties = parseProperties(bodyNode);\n const constants = parseConstants(bodyNode);\n const resourceAttributes = parseResourceAttributes(bodyNode);\n\n const hasCustomConstructor = methods.some((m) => m.name === 'constructFromResponse' && m.isStatic);\n\n classes.push({\n name: nameNode.text,\n namespace,\n extends: extendsName,\n isInterface: false,\n methods,\n properties,\n constants,\n resourceAttributes,\n hasCustomConstructor,\n sourceFile,\n });\n }\n\n return classes;\n}\n\nfunction parseInterfaceDeclarations(tree: Parser.Tree, sourceFile: string, namespace: string): PhpClass[] {\n const interfaces: PhpClass[] = [];\n\n for (const node of tree.rootNode.descendantsOfType('interface_declaration')) {\n const nameNode = node.childForFieldName('name');\n if (!nameNode) continue;\n\n const bodyNode = node.childForFieldName('body');\n if (!bodyNode) continue;\n\n const methods = parseMethods(bodyNode);\n\n interfaces.push({\n name: nameNode.text,\n namespace,\n extends: null,\n isInterface: true,\n methods,\n properties: [],\n constants: [],\n resourceAttributes: [],\n hasCustomConstructor: false,\n sourceFile,\n });\n }\n\n return interfaces;\n}\n\n// ---------------------------------------------------------------------------\n// PHP 8.1 enum extraction\n// ---------------------------------------------------------------------------\n\nfunction parseEnumDeclarations(tree: Parser.Tree, sourceFile: string, namespace: string): PhpClass[] {\n const enums: PhpClass[] = [];\n\n for (const node of tree.rootNode.descendantsOfType('enum_declaration')) {\n const nameNode = node.childForFieldName('name');\n if (!nameNode) continue;\n\n const bodyNode = node.childForFieldName('body');\n if (!bodyNode) continue;\n\n // Extract enum cases as constants\n const constants: PhpConstant[] = [];\n for (const child of bodyNode.namedChildren) {\n if (child.type !== 'enum_case') continue;\n const caseNameNode = child.childForFieldName('name');\n if (!caseNameNode) continue;\n\n // Get the value (backed enum): case Foo = 'foo'\n let value = caseNameNode.text;\n const valueNode = child.namedChildren.find(\n (c) => c.type === 'encapsed_string' || c.type === 'string' || c.type === 'integer',\n );\n if (valueNode) {\n const contentNode = valueNode.namedChildren.find((c) => c.type === 'string_content');\n value = contentNode ? contentNode.text : valueNode.text;\n }\n\n constants.push({ name: caseNameNode.text, value });\n }\n\n const methods = parseMethods(bodyNode);\n\n enums.push({\n name: nameNode.text,\n namespace,\n extends: null,\n isInterface: false,\n methods,\n properties: [],\n constants,\n resourceAttributes: [],\n hasCustomConstructor: false,\n sourceFile,\n });\n }\n\n return enums;\n}\n\n// ---------------------------------------------------------------------------\n// Full file parser\n// ---------------------------------------------------------------------------\n\nexport interface ParsedPhpFile {\n classes: PhpClass[];\n}\n\n/** Parse a single PHP source file and return all extracted symbols. */\nexport function parsePhpFile(filePath: string, sdkPath: string): ParsedPhpFile {\n const source = readFileSync(filePath, 'utf-8');\n const relPath = relative(sdkPath, filePath);\n const tree = safeParse(phpParser, source);\n const namespace = extractNamespace(tree);\n\n const classDecls = parseClassDeclarations(tree, relPath, namespace);\n const interfaceDecls = parseInterfaceDeclarations(tree, relPath, namespace);\n const enumDecls = parseEnumDeclarations(tree, relPath, namespace);\n\n return {\n classes: [...classDecls, ...interfaceDecls, ...enumDecls],\n };\n}\n","/**\n * PHP surface builder — transforms parsed PHP classes into an ApiSurface.\n *\n * Mapping:\n * Class extending a resource base → ApiInterface (fields from RESOURCE_ATTRIBUTES)\n * Class with only constants → ApiEnum (const values)\n * Service class with public methods → ApiClass\n * Static utility class → ApiClass\n * PHP interface declaration → ApiInterface (methods as fields)\n * Exception class → ApiClass\n */\n\nimport type {\n ApiClass,\n ApiMethod,\n ApiParam,\n ApiProperty,\n ApiInterface,\n ApiField,\n ApiEnum,\n LanguageHints,\n} from '../types.js';\nimport type { PhpClass } from './php-parser.js';\nimport { sortRecord, ExportCollector } from './shared.js';\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/** Default resource base classes (empty — consumer provides via hints.modelBaseClasses). */\nconst DEFAULT_RESOURCE_BASES: string[] = [];\n\n/** Default exception base classes. */\nconst DEFAULT_EXCEPTION_BASES = ['Exception', '\\\\Exception'];\n\n/** Check if a class is a resource class (extends a known resource base and has attributes). */\nfunction isResourceClass(cls: PhpClass, resourceBases: Set<string>): boolean {\n return !!cls.extends && resourceBases.has(cls.extends) && cls.resourceAttributes.length > 0;\n}\n\n/** Check if a class is enum-like (only constants, no public methods). */\nfunction isEnumClass(cls: PhpClass): boolean {\n if (cls.isInterface) return false;\n if (cls.constants.length === 0) return false;\n // Must have only constants — no public instance methods (excluding inherited)\n const publicMethods = cls.methods.filter((m) => m.visibility === 'public' && m.name !== '__construct');\n return publicMethods.length === 0 && cls.properties.length === 0 && !cls.extends;\n}\n\n/** Check if a class is an exception. */\nfunction isExceptionClass(cls: PhpClass, exceptionBases: Set<string>): boolean {\n if (!cls.extends) return false;\n return exceptionBases.has(cls.extends);\n}\n\n// ---------------------------------------------------------------------------\n// Surface builder\n// ---------------------------------------------------------------------------\n\nexport function buildSurface(\n allClasses: PhpClass[],\n hints?: LanguageHints,\n): {\n classes: Record<string, ApiClass>;\n interfaces: Record<string, ApiInterface>;\n enums: Record<string, ApiEnum>;\n exports: Record<string, string[]>;\n} {\n const resourceBases = new Set(hints?.modelBaseClasses ?? DEFAULT_RESOURCE_BASES);\n const exceptionBases = new Set(hints?.exceptionBaseClasses ?? DEFAULT_EXCEPTION_BASES);\n\n const classes: Record<string, ApiClass> = {};\n const interfaces: Record<string, ApiInterface> = {};\n const enums: Record<string, ApiEnum> = {};\n\n const collector = new ExportCollector();\n\n for (const cls of allClasses) {\n if (cls.isInterface) {\n // PHP interface → ApiInterface\n const fields: Record<string, ApiField> = {};\n for (const method of cls.methods) {\n if (method.visibility !== 'public') continue;\n fields[method.name] = {\n name: method.name,\n type: method.returnType || 'mixed',\n optional: false,\n };\n }\n interfaces[cls.name] = {\n name: cls.name,\n sourceFile: cls.sourceFile,\n fields: sortRecord(fields),\n extends: [],\n };\n collector.add(cls.sourceFile, cls.name);\n } else if (isResourceClass(cls, resourceBases)) {\n // Resource class → ApiInterface with fields from RESOURCE_ATTRIBUTES\n // Preserve the original field order (don't sort) — it determines toArray() output order\n const fields: Record<string, ApiField> = {};\n for (const attr of cls.resourceAttributes) {\n fields[attr] = {\n name: attr,\n type: 'mixed',\n optional: false,\n };\n }\n interfaces[cls.name] = {\n name: cls.name,\n sourceFile: cls.sourceFile,\n fields, // Intentionally NOT sorted — order matches RESOURCE_ATTRIBUTES\n extends: cls.extends ? [cls.extends] : [],\n ...(cls.hasCustomConstructor ? { hasCustomConstructor: true } : {}),\n };\n collector.add(cls.sourceFile, cls.name);\n } else if (isEnumClass(cls)) {\n // Enum-like class → ApiEnum\n const members: Record<string, string | number> = {};\n for (const constant of cls.constants) {\n members[constant.name] = constant.value;\n }\n enums[cls.name] = {\n name: cls.name,\n sourceFile: cls.sourceFile,\n members: sortRecord(members),\n };\n collector.add(cls.sourceFile, cls.name);\n } else {\n // Service class, static utility class, or exception → ApiClass\n const apiMethods: Record<string, ApiMethod[]> = {};\n const properties: Record<string, ApiProperty> = {};\n\n // Only include public methods\n for (const method of cls.methods) {\n if (method.visibility !== 'public') continue;\n\n const params: ApiParam[] = method.params.map((p) => ({\n name: p.name,\n type: p.type,\n optional: p.optional,\n passingStyle: 'named' as const,\n }));\n\n if (!apiMethods[method.name]) apiMethods[method.name] = [];\n apiMethods[method.name].push({\n name: method.name,\n params,\n returnType: method.returnType || 'mixed',\n async: false, // PHP is synchronous\n });\n }\n\n // Include public properties\n for (const prop of cls.properties) {\n if (prop.visibility !== 'public') continue;\n properties[prop.name] = {\n name: prop.name,\n type: prop.type,\n readonly: false,\n };\n }\n\n // Only add if there's something meaningful (methods or properties)\n if (\n Object.keys(apiMethods).length > 0 ||\n Object.keys(properties).length > 0 ||\n isExceptionClass(cls, exceptionBases)\n ) {\n classes[cls.name] = {\n name: cls.name,\n sourceFile: cls.sourceFile,\n methods: sortRecord(apiMethods),\n properties: sortRecord(properties),\n constructorParams: [],\n };\n collector.add(cls.sourceFile, cls.name);\n }\n }\n }\n\n const exports = collector.toRecord();\n\n return {\n classes: sortRecord(classes),\n interfaces: sortRecord(interfaces),\n enums: sortRecord(enums),\n exports: sortRecord(exports),\n };\n}\n","/**\n * PHP API surface extractor.\n *\n * Walks `.php` files under `lib/` (or `src/`), parses classes, interfaces,\n * methods, properties, and constants, then builds an `ApiSurface`.\n *\n * Parser: `php-parser.ts` — tree-sitter-based PHP source analysis\n * Surface: `php-surface.ts` — ApiSurface construction\n */\n\nimport { statSync } from 'node:fs';\nimport { resolve } from 'node:path';\nimport { ExtractorError } from '../../errors.js';\nimport type { Extractor, ApiSurface, LanguageHints } from '../types.js';\nimport type { CompatSnapshot } from '../ir.js';\nimport { apiSurfaceToSnapshot } from '../ir.js';\nimport { defaultIsNullableOnlyDifference } from '../language-hints.js';\nimport { walkPhpFiles, parsePhpFile } from './php-parser.js';\nimport { buildSurface } from './php-surface.js';\nimport type { PhpClass } from './php-parser.js';\nimport { sortRecord } from './shared.js';\n\n// ---------------------------------------------------------------------------\n// Language hints\n// ---------------------------------------------------------------------------\n\nconst PHP_BODY_TYPES = new Set(['array', 'mixed']);\n\nconst phpHints: LanguageHints = {\n stripNullable(type: string): string | null {\n // ?string → string\n if (type.startsWith('?')) return type.slice(1);\n // null|string → string, string|null → string\n const parts = type.split('|').filter((p) => p.trim().toLowerCase() !== 'null');\n if (parts.length < type.split('|').length) return parts.join('|');\n return null;\n },\n isNullableOnlyDifference(a: string, b: string): boolean {\n return defaultIsNullableOnlyDifference(this, a, b);\n },\n isUnionReorder(a: string, b: string): boolean {\n // Parse pipe-separated types, sort, compare\n const sortParts = (t: string) =>\n t\n .split('|')\n .map((s) => s.trim())\n .sort()\n .join('|');\n return a !== b && sortParts(a) === sortParts(b);\n },\n isGenericTypeParam(_type: string): boolean {\n return false; // PHP has no generics\n },\n isExtractionArtifact(type: string): boolean {\n return type === 'mixed' || type === 'Object';\n },\n tolerateCategoryMismatch: false,\n extractReturnTypeName(returnType: string): string | null {\n // Strip nullable: ?Foo → Foo, null|Foo → Foo\n const stripped = this.stripNullable(returnType) ?? returnType;\n if (['string', 'int', 'float', 'bool', 'void', 'array', 'mixed'].includes(stripped)) return null;\n return stripped.replace(/^\\\\/, '');\n },\n extractParamTypeName(paramType: string): string | null {\n const stripped = this.stripNullable(paramType) ?? paramType;\n if (['string', 'int', 'float', 'bool', 'void', 'array', 'mixed', 'null', 'callable'].includes(stripped)) {\n return null;\n }\n return stripped.replace(/^\\\\/, '');\n },\n propertyMatchesClass(propertyName: string, className: string): boolean {\n // camelCase → PascalCase comparison\n return propertyName.toLowerCase() === className.toLowerCase();\n },\n derivedModelNames(_modelName: string): string[] {\n return [];\n },\n\n isSignatureEquivalent(\n baseline: import('../types.js').ApiMethod,\n candidate: import('../types.js').ApiMethod,\n _candidateSurface: import('../types.js').ApiSurface,\n ): boolean {\n // Tolerate return type differences common in PHP SDK compat:\n // - mixed ≡ any specific return type (\\\\WorkOS\\\\Resource\\\\Response ≡ void, etc.)\n // - array ≡ mixed ≡ specific resource type\n const returnOk =\n baseline.returnType === candidate.returnType ||\n baseline.returnType === 'mixed' ||\n candidate.returnType === 'mixed' ||\n (baseline.returnType === 'void' && candidate.returnType === 'void') ||\n (baseline.returnType === 'array' && candidate.returnType === 'array');\n\n // More lenient: tolerate any return type difference when one side is a\n // namespace-qualified resource type (\\\\WorkOS\\\\Resource\\\\...)\n const returnTolerated =\n returnOk || baseline.returnType.includes('\\\\Resource\\\\') || candidate.returnType.includes('\\\\Resource\\\\');\n\n if (!returnTolerated) return false;\n\n // Case 1: Same number of required params, just name differences.\n // The spec may use generic names (id) while the live SDK uses domain names (organization).\n // Tolerate when the types match but names differ.\n if (baseline.params.length === candidate.params.length) {\n let allTypesMatch = true;\n for (let i = 0; i < baseline.params.length; i++) {\n if (baseline.params[i].type !== candidate.params[i].type) {\n allTypesMatch = false;\n break;\n }\n }\n if (allTypesMatch) return true;\n }\n\n // Case 2: Candidate uses array $options / array $payload for body/query params\n // while baseline has explicit typed params.\n // Tolerate when the candidate's params are a prefix of the baseline\n // followed by an array/mixed param that absorbs the rest.\n const candHasArrayParam = candidate.params.some((p) => PHP_BODY_TYPES.has(p.type));\n if (candHasArrayParam) return true;\n\n // Case 3: Baseline has explicit params that the candidate absorbs into path params\n // with different names (e.g., organization vs id)\n if (baseline.params.length >= 1 && candidate.params.length >= 1) {\n // Check if all param types match (allow name differences)\n let typeMatch = true;\n const minLen = Math.min(baseline.params.length, candidate.params.length);\n for (let i = 0; i < minLen; i++) {\n if (baseline.params[i].type !== candidate.params[i].type) {\n typeMatch = false;\n break;\n }\n }\n // Extra candidate params must be optional\n if (typeMatch) {\n const extraCandOk = candidate.params.slice(minLen).every((p) => p.optional);\n const extraBaseOk = baseline.params.slice(minLen).every((p) => p.optional);\n if (extraCandOk && extraBaseOk) return true;\n }\n }\n\n return false;\n },\n\n modelBaseClasses: ['BaseWorkOSResource'],\n exceptionBaseClasses: ['Exception', '\\\\Exception'],\n};\n\n// ---------------------------------------------------------------------------\n// Extractor\n// ---------------------------------------------------------------------------\n\n/** Create a PHP extractor with optional hint overrides. */\nexport function createPhpExtractor(hintOverrides?: Partial<LanguageHints>): Extractor {\n const mergedHints: LanguageHints = hintOverrides ? { ...phpHints, ...hintOverrides } : phpHints;\n\n return {\n language: 'php',\n hints: mergedHints,\n\n async extractSnapshot(sdkPath: string): Promise<CompatSnapshot> {\n const surface = await this.extract(sdkPath);\n return apiSurfaceToSnapshot(surface);\n },\n\n async extract(sdkPath: string): Promise<ApiSurface> {\n // Determine the source directory: prefer lib/, fallback to src/\n let sourceDir: string;\n const libPath = resolve(sdkPath, 'lib');\n const srcPath = resolve(sdkPath, 'src');\n\n try {\n statSync(libPath);\n sourceDir = libPath;\n } catch {\n try {\n statSync(srcPath);\n sourceDir = srcPath;\n } catch {\n throw new ExtractorError(\n `No lib/ or src/ directory found in ${sdkPath}`,\n `Ensure the --sdk-path argument points to a PHP project root containing a lib/ or src/ directory.`,\n );\n }\n }\n\n const phpFiles = walkPhpFiles(sourceDir);\n if (phpFiles.length === 0) {\n throw new ExtractorError(\n `No .php files found in ${sourceDir}`,\n `Ensure the source directory contains PHP source files.`,\n );\n }\n\n const allClasses: PhpClass[] = [];\n\n for (const filePath of phpFiles) {\n const parsed = parsePhpFile(filePath, sdkPath);\n allClasses.push(...parsed.classes);\n }\n\n const { classes, interfaces, enums, exports } = buildSurface(allClasses, mergedHints);\n\n return {\n language: 'php',\n extractedFrom: sdkPath,\n extractedAt: new Date().toISOString(),\n classes: sortRecord(classes),\n interfaces: sortRecord(interfaces),\n typeAliases: {},\n enums: sortRecord(enums),\n exports: sortRecord(exports),\n };\n },\n };\n}\n\n/** Default PHP extractor with generic language hints (no SDK-specific bases). */\nexport const phpExtractor: Extractor = createPhpExtractor();\n","/** Python source parser — tree-sitter-based extraction of classes, type aliases, and symbols. */\nimport { readFileSync, readdirSync, statSync } from 'node:fs';\nimport { join, relative } from 'node:path';\nimport Parser from 'tree-sitter';\nimport Python from 'tree-sitter-python';\nimport type { SyntaxNode } from 'tree-sitter';\nimport { safeParse } from '../../utils/tree-sitter.js';\n\n// ---------------------------------------------------------------------------\n// Internal types\n// ---------------------------------------------------------------------------\n\nexport interface PythonField {\n name: string;\n type: string;\n hasDefault: boolean;\n}\n\nexport interface PythonMethod {\n name: string;\n params: {\n name: string;\n type: string;\n optional: boolean;\n passingStyle?: 'positional' | 'keyword' | 'keyword_or_positional';\n }[];\n returnType: string;\n isAsync: boolean;\n isProperty: boolean;\n isClassMethod: boolean;\n isStaticMethod: boolean;\n}\n\nexport interface PythonClass {\n name: string;\n bases: string[];\n fields: PythonField[];\n methods: PythonMethod[];\n decorators: string[];\n sourceFile: string;\n}\n\nexport interface PythonTypeAlias {\n name: string;\n value: string;\n sourceFile: string;\n}\n\nexport interface PythonImport {\n names: string[];\n sourceFile: string;\n}\n\n// ---------------------------------------------------------------------------\n// Shared parser instance\n// ---------------------------------------------------------------------------\n\nconst pythonParser = new Parser();\npythonParser.setLanguage(Python);\n\n// ---------------------------------------------------------------------------\n// File walker\n// ---------------------------------------------------------------------------\n\nexport function walkPythonFiles(dir: string): string[] {\n const results: string[] = [];\n let entries: string[];\n try {\n entries = readdirSync(dir);\n } catch {\n return results;\n }\n for (const entry of entries) {\n const fullPath = join(dir, entry);\n let stat;\n try {\n stat = statSync(fullPath);\n } catch {\n continue;\n }\n if (stat.isDirectory()) {\n if (\n entry.startsWith('.') ||\n entry === '__pycache__' ||\n entry === 'tests' ||\n entry === 'test' ||\n entry === 'node_modules'\n )\n continue;\n results.push(...walkPythonFiles(fullPath));\n } else if (entry.endsWith('.py')) {\n // Skip test files\n if (entry.endsWith('_test.py') || entry.startsWith('test_')) continue;\n // Skip private modules (but include __init__.py)\n if (entry.startsWith('_') && entry !== '__init__.py') continue;\n results.push(fullPath);\n }\n }\n return results.sort();\n}\n\n/** Find the Python source root (prefers `src/`, falls back to top-level package). */\n/** True if a directory looks like a Python package (has __init__.py or .py files). */\nfunction isPythonPackageDir(dir: string): boolean {\n try {\n statSync(join(dir, '__init__.py'));\n return true;\n } catch {\n // no __init__.py — check for .py files as a fallback\n // (generated output may omit __init__.py when it's hand-maintained)\n }\n try {\n const entries = readdirSync(dir);\n return entries.some((e) => e.endsWith('.py'));\n } catch {\n return false;\n }\n}\n\nexport function findPythonSourceRoot(sdkPath: string): string | null {\n // Strategy 1: src/ directory\n const srcDir = join(sdkPath, 'src');\n try {\n const stat = statSync(srcDir);\n if (stat.isDirectory()) {\n const entries = readdirSync(srcDir);\n for (const entry of entries) {\n const pkgDir = join(srcDir, entry);\n try {\n const pkgStat = statSync(pkgDir);\n if (pkgStat.isDirectory() && isPythonPackageDir(pkgDir)) {\n return srcDir;\n }\n } catch {\n continue;\n }\n }\n }\n } catch {\n // no src/, continue\n }\n\n // Strategy 2: top-level package directory\n try {\n const entries = readdirSync(sdkPath);\n for (const entry of entries) {\n if (entry.startsWith('.') || entry === 'tests' || entry === 'test' || entry === 'node_modules') continue;\n const pkgDir = join(sdkPath, entry);\n try {\n const pkgStat = statSync(pkgDir);\n if (pkgStat.isDirectory() && isPythonPackageDir(pkgDir)) {\n return sdkPath;\n }\n } catch {\n continue;\n }\n }\n } catch {\n // can't read sdkPath\n }\n\n return null;\n}\n\n/** Get all decorator names from a decorated_definition or class_definition. */\nfunction getDecorators(node: SyntaxNode): string[] {\n const decorators: string[] = [];\n // Decorated definition wraps the class or function\n if (node.type === 'decorated_definition') {\n for (const child of node.namedChildren) {\n if (child.type === 'decorator') {\n const exprNode = child.namedChildren[0];\n if (exprNode) decorators.push(exprNode.text);\n }\n }\n }\n return decorators;\n}\n\n/** Extract base class names from a class definition's argument_list. */\nfunction getBaseClasses(classNode: SyntaxNode): string[] {\n const bases: string[] = [];\n const argList = classNode.childForFieldName('superclasses');\n if (!argList) return bases;\n\n for (const child of argList.namedChildren) {\n if (child.type === 'identifier' || child.type === 'attribute') {\n bases.push(child.text);\n } else if (child.type === 'keyword_argument') {\n // skip keyword arguments like total=False\n }\n }\n return bases;\n}\n\n/** Extract annotated fields from a class body. */\nfunction extractClassFields(bodyNode: SyntaxNode): PythonField[] {\n const fields: PythonField[] = [];\n\n for (const child of bodyNode.namedChildren) {\n if (child.type !== 'expression_statement') continue;\n\n const stmtChild = child.namedChildren[0];\n if (!stmtChild || stmtChild.type !== 'assignment') continue;\n\n const left = stmtChild.childForFieldName('left');\n const typeNode = stmtChild.childForFieldName('type');\n\n // Must be an annotated assignment (has a type annotation)\n if (!left || !typeNode) continue;\n // Only simple identifier on left side (not tuple unpacking, etc.)\n if (left.type !== 'identifier') continue;\n\n const right = stmtChild.childForFieldName('right');\n\n fields.push({\n name: left.text,\n type: typeNode.text,\n hasDefault: right !== null,\n });\n }\n return fields;\n}\n\n/** Extract methods from a class body. */\nfunction extractClassMethods(bodyNode: SyntaxNode): PythonMethod[] {\n const methods: PythonMethod[] = [];\n\n for (const child of bodyNode.namedChildren) {\n let funcNode: SyntaxNode | null = null;\n let decorators: string[] = [];\n\n if (child.type === 'decorated_definition') {\n decorators = getDecorators(child);\n // The actual function/class is the last named child\n funcNode = child.namedChildren.find((c) => c.type === 'function_definition') || null;\n } else if (child.type === 'function_definition') {\n funcNode = child;\n }\n\n if (!funcNode) continue;\n\n const nameNode = funcNode.childForFieldName('name');\n if (!nameNode) continue;\n const methodName = nameNode.text;\n\n // Skip private methods (starting with _) but keep __init__\n if (methodName.startsWith('_') && methodName !== '__init__') continue;\n\n const isAsync = funcNode.namedChildren.some((c) => c.type === 'async');\n const isProperty = decorators.includes('property');\n const isClassMethod = decorators.includes('classmethod');\n const isStaticMethod = decorators.includes('staticmethod');\n\n // Extract parameters\n const paramsNode = funcNode.childForFieldName('parameters');\n const params = extractFunctionParams(paramsNode, isStaticMethod || isClassMethod);\n\n // Extract return type\n const returnTypeNode = funcNode.childForFieldName('return_type');\n const returnType = returnTypeNode ? returnTypeNode.text : '';\n\n methods.push({\n name: methodName,\n params,\n returnType,\n isAsync,\n isProperty,\n isClassMethod,\n isStaticMethod,\n });\n }\n\n return methods;\n}\n\n/** Extract parameters from a function's parameter list. */\nfunction extractFunctionParams(\n paramsNode: SyntaxNode | null,\n skipFirst: boolean,\n): {\n name: string;\n type: string;\n optional: boolean;\n passingStyle?: 'positional' | 'keyword' | 'keyword_or_positional';\n}[] {\n if (!paramsNode) return [];\n const params: {\n name: string;\n type: string;\n optional: boolean;\n passingStyle?: 'positional' | 'keyword' | 'keyword_or_positional';\n }[] = [];\n let skippedFirst = false;\n let seenStarMarker = false;\n\n for (const child of paramsNode.namedChildren) {\n // Skip `self` or `cls` parameter\n if (!skippedFirst && !skipFirst && child.type === 'identifier' && (child.text === 'self' || child.text === 'cls')) {\n skippedFirst = true;\n continue;\n }\n if (!skippedFirst && !skipFirst && child.type === 'typed_parameter' && child.namedChildren[0]?.text === 'self') {\n skippedFirst = true;\n continue;\n }\n\n // `*` separator in parameters (keyword-only marker)\n if (child.text === '*') {\n seenStarMarker = true;\n continue;\n }\n\n // *args — variadic positional (also marks subsequent params as keyword-only)\n if (child.type === 'list_splat_pattern') {\n seenStarMarker = true;\n const nameNode = child.namedChildren.find((c: SyntaxNode) => c.type === 'identifier');\n params.push({\n name: nameNode ? `*${nameNode.text}` : '*args',\n type: '',\n optional: true,\n passingStyle: 'positional',\n });\n continue;\n }\n\n // **kwargs — variadic keyword\n if (child.type === 'dictionary_splat_pattern') {\n const nameNode = child.namedChildren.find((c: SyntaxNode) => c.type === 'identifier');\n params.push({\n name: nameNode ? `**${nameNode.text}` : '**kwargs',\n type: '',\n optional: true,\n passingStyle: 'keyword',\n });\n continue;\n }\n\n const passingStyle = seenStarMarker ? ('keyword' as const) : ('keyword_or_positional' as const);\n\n if (child.type === 'typed_parameter') {\n const nameNode = child.namedChildren.find((c) => c.type === 'identifier');\n const typeNode = child.childForFieldName('type');\n if (nameNode) {\n params.push({\n name: nameNode.text,\n type: typeNode ? typeNode.text : '',\n optional: false,\n passingStyle,\n });\n }\n } else if (child.type === 'typed_default_parameter') {\n const nameNode = child.childForFieldName('name');\n const typeNode = child.childForFieldName('type');\n if (nameNode) {\n params.push({\n name: nameNode.text,\n type: typeNode ? typeNode.text : '',\n optional: true,\n passingStyle,\n });\n }\n } else if (child.type === 'default_parameter') {\n const nameNode = child.childForFieldName('name');\n if (nameNode) {\n params.push({\n name: nameNode.text,\n type: '',\n optional: true,\n passingStyle,\n });\n }\n } else if (child.type === 'identifier') {\n params.push({\n name: child.text,\n type: '',\n optional: false,\n passingStyle,\n });\n }\n }\n\n return params;\n}\n\n/** Extract module-level type aliases (e.g., FooType = Literal[\"a\", \"b\"]). */\nfunction extractTypeAliases(tree: Parser.Tree, sourceFile: string): PythonTypeAlias[] {\n const aliases: PythonTypeAlias[] = [];\n\n for (const node of tree.rootNode.namedChildren) {\n // type alias statement (Python 3.12+): type X = ...\n if (node.type === 'type_alias_statement') {\n const nameNode = node.childForFieldName('name');\n const valueNode = node.childForFieldName('value');\n if (nameNode && valueNode) {\n aliases.push({ name: nameNode.text, value: valueNode.text, sourceFile });\n }\n continue;\n }\n\n // Assignment: X = Literal[...] or X = \"SomeResource[...]\"\n if (node.type === 'expression_statement') {\n const inner = node.namedChildren[0];\n if (!inner || inner.type !== 'assignment') continue;\n\n const left = inner.childForFieldName('left');\n const right = inner.childForFieldName('right');\n if (!left || !right) continue;\n\n // Only consider simple name assignments (not a: type = value)\n if (left.type !== 'identifier') continue;\n\n const name = left.text;\n // Skip private names and dunder names\n if (name.startsWith('_')) continue;\n // Skip ALL_CAPS constants that are not type aliases\n if (/^[A-Z][A-Z_0-9]*$/.test(name)) continue;\n\n const value = right.text;\n\n // Only take subscript expressions (Literal[...], SomeResource[...], etc.)\n // or string literals that look like type aliases\n if (right.type === 'subscript' || (right.type === 'string' && value.includes('['))) {\n // For string literals, strip quotes\n let cleanValue = value;\n if (right.type === 'string') {\n cleanValue = value.replace(/^[\"']|[\"']$/g, '');\n }\n aliases.push({ name, value: cleanValue, sourceFile });\n }\n }\n }\n\n return aliases;\n}\n\n/** Extract __all__ exports from a module. */\nfunction extractAllExports(tree: Parser.Tree): string[] {\n const exports: string[] = [];\n\n for (const node of tree.rootNode.namedChildren) {\n if (node.type !== 'expression_statement') continue;\n const inner = node.namedChildren[0];\n if (!inner || inner.type !== 'assignment') continue;\n\n const left = inner.childForFieldName('left');\n const right = inner.childForFieldName('right');\n if (!left || !right) continue;\n if (left.text !== '__all__') continue;\n\n // __all__ = [\"Foo\", \"Bar\"]\n if (right.type === 'list') {\n for (const elem of right.namedChildren) {\n if (elem.type === 'string') {\n const text = elem.text.replace(/^[\"']|[\"']$/g, '');\n exports.push(text);\n }\n }\n }\n }\n\n return exports;\n}\n\nfunction extractClassesFromTree(tree: Parser.Tree, sourceFile: string): PythonClass[] {\n const classes: PythonClass[] = [];\n\n for (const node of tree.rootNode.namedChildren) {\n let classNode: SyntaxNode | null = null;\n let decorators: string[] = [];\n\n if (node.type === 'decorated_definition') {\n decorators = getDecorators(node);\n classNode = node.namedChildren.find((c) => c.type === 'class_definition') || null;\n } else if (node.type === 'class_definition') {\n classNode = node;\n }\n\n if (!classNode) continue;\n\n const nameNode = classNode.childForFieldName('name');\n if (!nameNode) continue;\n const className = nameNode.text;\n\n const bases = getBaseClasses(classNode);\n\n const bodyNode = classNode.childForFieldName('body');\n if (!bodyNode) {\n classes.push({ name: className, bases, fields: [], methods: [], decorators, sourceFile });\n continue;\n }\n\n const fields = extractClassFields(bodyNode);\n const methods = extractClassMethods(bodyNode);\n\n classes.push({ name: className, bases, fields, methods, decorators, sourceFile });\n }\n\n return classes;\n}\n\n// ---------------------------------------------------------------------------\n// Full file parser\n// ---------------------------------------------------------------------------\n\nexport interface ParsedPythonFile {\n classes: PythonClass[];\n typeAliases: PythonTypeAlias[];\n allExports: string[];\n sourceFile: string;\n}\n\n/** Parse a single Python source file and return all extracted symbols. */\nexport function parsePythonFile(filePath: string, sdkPath: string): ParsedPythonFile {\n const source = readFileSync(filePath, 'utf-8');\n const relPath = relative(sdkPath, filePath);\n const tree = safeParse(pythonParser, source);\n\n const classes = extractClassesFromTree(tree, relPath);\n const typeAliases = extractTypeAliases(tree, relPath);\n const allExports = extractAllExports(tree);\n\n return { classes, typeAliases, allExports, sourceFile: relPath };\n}\n","/**\n * Python surface builder — transforms parsed Python symbols into an ApiSurface.\n *\n * Mapping:\n * class Foo(BaseModel/custom model) → ApiInterface (fields from annotations)\n * class Foo(TypedDict) → ApiInterface (fields)\n * class Foo(Protocol) → ApiClass (canonical service)\n * Sync/Async impl classes → skip (Protocol takes precedence)\n * FooType = Literal[...] → ApiEnum (members = literal strings)\n * FooResource = ListResource[...] → ApiTypeAlias\n * Exception subclass → ApiClass\n * Other class with methods → ApiClass\n */\n\nimport type {\n ApiClass,\n ApiMethod,\n ApiParam,\n ApiInterface,\n ApiField,\n ApiTypeAlias,\n ApiEnum,\n LanguageHints,\n} from '../types.js';\nimport type { PythonClass, ParsedPythonFile } from './python-parser.js';\nimport { sortRecord, ExportCollector } from './shared.js';\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/** Default model base classes. Overridden by hints.modelBaseClasses when provided. */\nconst DEFAULT_MODEL_BASES: string[] = [];\n\n/** Known dict-like base classes (→ ApiInterface). */\nconst DICT_BASES = new Set(['TypedDict']);\n\n/** Known protocol bases (→ ApiClass as service). */\nconst PROTOCOL_BASES = new Set(['Protocol']);\n\n/** Default exception bases. Overridden by hints.exceptionBaseClasses when provided. */\nconst DEFAULT_EXCEPTION_BASES = ['Exception', 'BaseException'];\n\n/** Check if a class has any of the given base classes (by simple name). */\nfunction hasBase(cls: PythonClass, bases: Set<string>): boolean {\n return cls.bases.some((b) => bases.has(b));\n}\n\n/** Check if a class is a model class (inherits from BaseModel or configured model bases,\n * transitively from another class that does). */\nfunction isModelClass(cls: PythonClass, allClasses: Map<string, PythonClass>, modelBases: Set<string>): boolean {\n if (hasBase(cls, modelBases)) return true;\n // Check transitively: if parent class is a model\n for (const base of cls.bases) {\n const parentCls = allClasses.get(base);\n if (parentCls && isModelClass(parentCls, allClasses, modelBases)) return true;\n }\n return false;\n}\n\n/** Check if a class is an exception class. */\nfunction isExceptionClass(\n cls: PythonClass,\n allClasses: Map<string, PythonClass>,\n exceptionBases: Set<string>,\n): boolean {\n if (hasBase(cls, exceptionBases)) return true;\n for (const base of cls.bases) {\n const parentCls = allClasses.get(base);\n if (parentCls && isExceptionClass(parentCls, allClasses, exceptionBases)) return true;\n }\n return false;\n}\n\n/** Parse Literal[\"a\", \"b\", \"c\"] into member strings. */\nfunction parseLiteralMembers(value: string): Record<string, string> | null {\n const match = value.match(/^Literal\\[(.+)\\]$/s);\n if (!match) return null;\n\n const inner = match[1];\n const members: Record<string, string> = {};\n\n // Split by comma, handling nested brackets\n const parts: string[] = [];\n let depth = 0;\n let current = '';\n for (const char of inner) {\n if (char === '[' || char === '(') depth++;\n else if (char === ']' || char === ')') depth--;\n else if (char === ',' && depth === 0) {\n parts.push(current.trim());\n current = '';\n continue;\n }\n current += char;\n }\n if (current.trim()) parts.push(current.trim());\n\n for (const part of parts) {\n // Strip quotes\n const stripped = part.replace(/^[\"']|[\"']$/g, '');\n if (stripped) {\n members[stripped] = stripped;\n }\n }\n\n return Object.keys(members).length > 0 ? members : null;\n}\n\n/** Unwrap SyncOrAsync[T] → T. */\nfunction unwrapReturnType(returnType: string): string {\n const syncOrAsyncMatch = returnType.match(/^SyncOrAsync\\[(.+)\\]$/);\n if (syncOrAsyncMatch) return syncOrAsyncMatch[1];\n const awaitableMatch = returnType.match(/^Awaitable\\[(.+)\\]$/);\n if (awaitableMatch) return awaitableMatch[1];\n return returnType;\n}\n\n// ---------------------------------------------------------------------------\n// Surface builder\n// ---------------------------------------------------------------------------\n\nexport function buildSurface(\n parsedFiles: ParsedPythonFile[],\n hints?: LanguageHints,\n): {\n classes: Record<string, ApiClass>;\n interfaces: Record<string, ApiInterface>;\n typeAliases: Record<string, ApiTypeAlias>;\n enums: Record<string, ApiEnum>;\n exports: Record<string, string[]>;\n} {\n const MODEL_BASES = new Set(hints?.modelBaseClasses ?? DEFAULT_MODEL_BASES);\n const EXCEPTION_BASES = new Set(hints?.exceptionBaseClasses ?? DEFAULT_EXCEPTION_BASES);\n\n const classes: Record<string, ApiClass> = {};\n const interfaces: Record<string, ApiInterface> = {};\n const typeAliases: Record<string, ApiTypeAlias> = {};\n const enums: Record<string, ApiEnum> = {};\n\n // Collect all classes for transitive base lookups\n const allClassesByName = new Map<string, PythonClass>();\n for (const file of parsedFiles) {\n for (const cls of file.classes) {\n allClassesByName.set(cls.name, cls);\n }\n }\n\n // Track protocol class names to skip sync/async impls\n const protocolNames = new Set<string>();\n for (const file of parsedFiles) {\n for (const cls of file.classes) {\n if (hasBase(cls, PROTOCOL_BASES)) {\n protocolNames.add(cls.name);\n }\n }\n }\n\n // Build export map from __all__ and file-level symbols\n const collector = new ExportCollector();\n\n for (const file of parsedFiles) {\n // Process type aliases\n for (const alias of file.typeAliases) {\n const literalMembers = parseLiteralMembers(alias.value);\n if (literalMembers) {\n // Literal type alias → ApiEnum\n enums[alias.name] = {\n name: alias.name,\n sourceFile: alias.sourceFile,\n members: sortRecord(literalMembers),\n };\n collector.add(alias.sourceFile, alias.name);\n } else {\n // Regular type alias → ApiTypeAlias\n typeAliases[alias.name] = {\n name: alias.name,\n sourceFile: alias.sourceFile,\n value: alias.value,\n };\n collector.add(alias.sourceFile, alias.name);\n }\n }\n\n // Process classes\n for (const cls of file.classes) {\n // 1. Protocol classes → ApiClass (canonical service)\n if (hasBase(cls, PROTOCOL_BASES)) {\n const apiMethods: Record<string, ApiMethod[]> = {};\n\n for (const method of cls.methods) {\n // Skip __init__ for protocols (they don't have constructors)\n if (method.name === '__init__') continue;\n\n const params: ApiParam[] = method.params.map((p) => ({\n name: p.name,\n type: p.type,\n optional: p.optional,\n ...(p.passingStyle ? { passingStyle: p.passingStyle } : {}),\n }));\n\n const returnType = unwrapReturnType(method.returnType);\n\n if (!apiMethods[method.name]) apiMethods[method.name] = [];\n apiMethods[method.name].push({\n name: method.name,\n params,\n returnType,\n async: method.isAsync,\n });\n }\n\n classes[cls.name] = {\n name: cls.name,\n sourceFile: cls.sourceFile,\n methods: sortRecord(apiMethods),\n properties: {},\n constructorParams: [],\n };\n collector.add(cls.sourceFile, cls.name);\n continue;\n }\n\n // 2. Model classes (BaseModel or configured model bases) → ApiInterface\n if (isModelClass(cls, allClassesByName, MODEL_BASES)) {\n const fields: Record<string, ApiField> = {};\n for (const field of cls.fields) {\n fields[field.name] = {\n name: field.name,\n type: field.type,\n optional: field.hasDefault,\n };\n }\n\n // Compute extends list: filter out model bases themselves\n const extendsArr = cls.bases.filter((b) => !MODEL_BASES.has(b) && allClassesByName.has(b));\n\n interfaces[cls.name] = {\n name: cls.name,\n sourceFile: cls.sourceFile,\n fields: sortRecord(fields),\n extends: extendsArr,\n };\n collector.add(cls.sourceFile, cls.name);\n continue;\n }\n\n // 3. TypedDict classes → ApiInterface\n if (hasBase(cls, DICT_BASES)) {\n const fields: Record<string, ApiField> = {};\n for (const field of cls.fields) {\n fields[field.name] = {\n name: field.name,\n type: field.type,\n optional: field.hasDefault,\n };\n }\n\n interfaces[cls.name] = {\n name: cls.name,\n sourceFile: cls.sourceFile,\n fields: sortRecord(fields),\n extends: [],\n };\n collector.add(cls.sourceFile, cls.name);\n continue;\n }\n\n // 4. Exception classes → ApiClass\n if (isExceptionClass(cls, allClassesByName, EXCEPTION_BASES)) {\n const apiMethods: Record<string, ApiMethod[]> = {};\n // Extract any non-private, non-init methods\n for (const method of cls.methods) {\n if (method.name === '__init__') continue;\n const params: ApiParam[] = method.params.map((p) => ({\n name: p.name,\n type: p.type,\n optional: p.optional,\n ...(p.passingStyle ? { passingStyle: p.passingStyle } : {}),\n }));\n if (!apiMethods[method.name]) apiMethods[method.name] = [];\n apiMethods[method.name].push({\n name: method.name,\n params,\n returnType: unwrapReturnType(method.returnType),\n async: method.isAsync,\n });\n }\n\n // Exception fields as properties if they have annotations\n const fields: Record<string, ApiField> = {};\n for (const field of cls.fields) {\n fields[field.name] = {\n name: field.name,\n type: field.type,\n optional: field.hasDefault,\n };\n }\n\n classes[cls.name] = {\n name: cls.name,\n sourceFile: cls.sourceFile,\n methods: sortRecord(apiMethods),\n properties: {},\n constructorParams: [],\n };\n collector.add(cls.sourceFile, cls.name);\n continue;\n }\n\n // 5. Other class with methods → ApiClass\n if (cls.methods.length > 0) {\n const apiMethods: Record<string, ApiMethod[]> = {};\n const constructorParams: ApiParam[] = [];\n\n for (const method of cls.methods) {\n if (method.name === '__init__') {\n constructorParams.push(\n ...method.params.map((p) => ({\n name: p.name,\n type: p.type,\n optional: p.optional,\n ...(p.passingStyle ? { passingStyle: p.passingStyle } : {}),\n })),\n );\n continue;\n }\n\n const params: ApiParam[] = method.params.map((p) => ({\n name: p.name,\n type: p.type,\n optional: p.optional,\n ...(p.passingStyle ? { passingStyle: p.passingStyle } : {}),\n }));\n if (!apiMethods[method.name]) apiMethods[method.name] = [];\n apiMethods[method.name].push({\n name: method.name,\n params,\n returnType: unwrapReturnType(method.returnType),\n async: method.isAsync,\n });\n }\n\n classes[cls.name] = {\n name: cls.name,\n sourceFile: cls.sourceFile,\n methods: sortRecord(apiMethods),\n properties: {},\n constructorParams,\n };\n collector.add(cls.sourceFile, cls.name);\n continue;\n }\n\n // 6. Class with only fields and no methods → ApiInterface\n if (cls.fields.length > 0) {\n const fields: Record<string, ApiField> = {};\n for (const field of cls.fields) {\n fields[field.name] = {\n name: field.name,\n type: field.type,\n optional: field.hasDefault,\n };\n }\n interfaces[cls.name] = {\n name: cls.name,\n sourceFile: cls.sourceFile,\n fields: sortRecord(fields),\n extends: [],\n };\n collector.add(cls.sourceFile, cls.name);\n }\n }\n\n // Add __all__ exports\n if (file.allExports.length > 0) {\n for (const name of file.allExports) {\n collector.add(file.sourceFile, name);\n }\n }\n }\n\n const exports = collector.toRecord();\n\n return {\n classes: sortRecord(classes),\n interfaces: sortRecord(interfaces),\n typeAliases: sortRecord(typeAliases),\n enums: sortRecord(enums),\n exports: sortRecord(exports),\n };\n}\n","/**\n * Python API surface extractor.\n *\n * Walks `.py` files under `src/` (fallback to top-level package dirs),\n * parses classes, type aliases, and module exports, then builds an\n * `ApiSurface` with Protocol-based services, Pydantic model interfaces,\n * Literal type enums, and exception classes.\n *\n * Parser: `python-parser.ts` — tree-sitter-based Python source analysis\n * Surface: `python-surface.ts` — ApiSurface construction\n */\n\nimport { ExtractorError } from '../../errors.js';\nimport type { Extractor, ApiSurface, LanguageHints } from '../types.js';\nimport type { CompatSnapshot } from '../ir.js';\nimport { apiSurfaceToSnapshot } from '../ir.js';\nimport {\n NAMED_TYPE_RE,\n typeExistsInSurface,\n namedTypeWordsOverlap,\n defaultIsNullableOnlyDifference,\n} from '../language-hints.js';\nimport { walkPythonFiles, findPythonSourceRoot, parsePythonFile } from './python-parser.js';\nimport { buildSurface } from './python-surface.js';\nimport type { ParsedPythonFile } from './python-parser.js';\n\n// ---------------------------------------------------------------------------\n// Language hints\n// ---------------------------------------------------------------------------\n\nconst PYTHON_PRIMITIVE_TYPES = new Set(['str', 'int', 'float', 'bool', 'bytes']);\n\nconst pythonHints: LanguageHints = {\n stripNullable(type: string): string | null {\n // Normalize whitespace before matching\n const normalized = type.replace(/\\s+/g, ' ').trim();\n // Optional[T] → T\n const optMatch = normalized.match(/^Optional\\[(.+)\\]$/);\n if (optMatch) return optMatch[1].trim();\n // NotRequired[T] → T (TypedDict optionality ≡ nullable for compat purposes)\n const nrMatch = normalized.match(/^NotRequired\\[(.+)\\]$/);\n if (nrMatch) return nrMatch[1].trim();\n // T | None → T, None | T → T\n const parts = normalized\n .split('|')\n .map((p) => p.trim())\n .filter((p) => p !== 'None');\n if (parts.length < normalized.split('|').length) return parts.join(' | ');\n return null;\n },\n\n isNullableOnlyDifference(a: string, b: string): boolean {\n return defaultIsNullableOnlyDifference(this, a, b);\n },\n\n isUnionReorder(a: string, b: string): boolean {\n const parseUnion = (t: string) => {\n const unionMatch = t.match(/^Union\\[(.+)\\]$/);\n if (unionMatch)\n return unionMatch[1]\n .split(',')\n .map((s) => s.trim())\n .sort();\n return t\n .split('|')\n .map((s) => s.trim())\n .sort();\n };\n return a !== b && parseUnion(a).join(',') === parseUnion(b).join(',');\n },\n\n isGenericTypeParam(type: string): boolean {\n return /^[A-Z]$/.test(type) || /^T[A-Z][a-zA-Z]*$/.test(type);\n },\n\n isExtractionArtifact(type: string): boolean {\n return type === 'Any' || type === 'object';\n },\n\n tolerateCategoryMismatch: true,\n\n extractReturnTypeName(returnType: string): string | null {\n let inner = returnType;\n const syncOrAsyncMatch = inner.match(/^SyncOrAsync\\[(.+)\\]$/);\n if (syncOrAsyncMatch) inner = syncOrAsyncMatch[1];\n const awaitableMatch = inner.match(/^Awaitable\\[(.+)\\]$/);\n if (awaitableMatch) inner = awaitableMatch[1];\n const optMatch = inner.match(/^Optional\\[(.+)\\]$/);\n if (optMatch) inner = optMatch[1];\n // Unwrap list resource patterns (e.g., SomeListResource[T, ...] → T)\n for (const pattern of this.listResourcePatterns ?? []) {\n const prefix = pattern + '[';\n if (inner.startsWith(prefix)) {\n // Extract first type arg: everything up to the first comma or closing bracket\n const rest = inner.slice(prefix.length);\n const end = rest.search(/[,\\]]/);\n if (end > 0) {\n inner = rest.slice(0, end).trim();\n break;\n }\n }\n }\n // Sequence[T] → T\n const seqMatch = inner.match(/^Sequence\\[(.+)\\]$/);\n if (seqMatch) inner = seqMatch[1];\n if (['str', 'int', 'float', 'bool', 'None', 'bytes', 'dict', 'list'].includes(inner)) return null;\n return inner;\n },\n\n extractParamTypeName(paramType: string): string | null {\n let inner = paramType;\n const optMatch = inner.match(/^Optional\\[(.+)\\]$/);\n if (optMatch) inner = optMatch[1];\n if (['str', 'int', 'float', 'bool', 'None', 'bytes', 'dict', 'list'].includes(inner)) return null;\n return inner;\n },\n\n propertyMatchesClass(propertyName: string, className: string): boolean {\n return propertyName.replace(/_/g, '').toLowerCase() === className.toLowerCase();\n },\n\n derivedModelNames(modelName: string): string[] {\n return [`${modelName}Response`];\n },\n\n isTypeEquivalent(baselineType: string, candidateType: string, candidateSurface: ApiSurface): boolean {\n // Strip nullable wrappers from both sides\n const stripNullable = (t: string): string => {\n const normalized = t.replace(/\\s+/g, ' ').trim();\n const optMatch = normalized.match(/^Optional\\[(.+)\\]$/);\n if (optMatch) return optMatch[1].trim();\n const nrMatch = normalized.match(/^NotRequired\\[(.+)\\]$/);\n if (nrMatch) return nrMatch[1].trim();\n const parts = normalized\n .split('|')\n .map((p) => p.trim())\n .filter((p) => p !== 'None');\n if (parts.length < normalized.split('|').length) return parts.join(' | ');\n return normalized;\n };\n const baseClean = stripNullable(baselineType);\n const candClean = stripNullable(candidateType);\n\n // Literal quote style equivalence: Literal[\"foo\"] ≡ Literal['foo']\n const literalMatch = (t: string) => t.match(/^Literal\\[(['\"])(.+)\\1\\]$/);\n const baseLit = literalMatch(baseClean);\n const candLit = literalMatch(candClean);\n if (baseLit && candLit && baseLit[2] === candLit[2]) return true;\n\n // LiteralOrUntyped[T] ≡ T (custom wrapper type) — strip recursively\n const stripWrappers = (t: string): string => {\n let inner = t;\n // Strip LiteralOrUntyped[...]\n const louMatch = inner.match(/^LiteralOrUntyped\\[(.+)\\]$/);\n if (louMatch) inner = louMatch[1];\n // Strip Literal[...] to get the enum name if it's a Literal of literals\n return inner;\n };\n const baseUnwrapped = stripWrappers(baseClean);\n const candUnwrapped = stripWrappers(candClean);\n if (baseUnwrapped !== baseClean || candUnwrapped !== candClean) {\n // After unwrapping, check equivalence\n if (baseUnwrapped === candClean || candUnwrapped === baseClean) return true;\n if (baseUnwrapped === candUnwrapped) return true;\n // LiteralOrUntyped[Literal[\"a\", \"b\"]] ≡ enum type\n if (baseUnwrapped.startsWith('Literal[') && candidateSurface.enums[candClean]) return true;\n if (candUnwrapped.startsWith('Literal[') && candidateSurface.enums?.[baseClean]) return true;\n }\n\n // Sequence[T] ≡ list[T] ≡ List[T]\n const seqPattern = /^(?:Sequence|list|List)\\[(.+)\\]$/;\n const baseSeq = baseClean.match(seqPattern);\n const candSeq = candClean.match(seqPattern);\n if (baseSeq && candSeq) {\n if (baseSeq[1] === candSeq[1]) return true;\n // Inner types may differ by named type (InlineRole vs DirectoryUserRole)\n const baseInner = baseSeq[1];\n const candInner = candSeq[1];\n if (NAMED_TYPE_RE.test(baseInner) && NAMED_TYPE_RE.test(candInner)) {\n if (typeExistsInSurface(candInner, candidateSurface)) {\n if (candInner.includes(baseInner) || baseInner.includes(candInner)) return true;\n if (namedTypeWordsOverlap(baseInner, candInner)) return true;\n }\n }\n // Tolerate model collection vs primitive collection: Sequence[OrganizationDomain] ≡ list[str]\n // The spec may define a field as a primitive array while the live SDK wraps it in a model.\n const primitiveTypes = PYTHON_PRIMITIVE_TYPES;\n if (\n (primitiveTypes.has(baseInner) && NAMED_TYPE_RE.test(candInner)) ||\n (primitiveTypes.has(candInner) && NAMED_TYPE_RE.test(baseInner))\n ) {\n return true;\n }\n }\n // Cross-container tolerance: Sequence[T] vs list[str] (different container names)\n if (baseSeq && !candSeq) {\n const candListMatch = candClean.match(/^(?:list|List)\\[(.+)\\]$/);\n if (candListMatch) {\n const baseInner = baseSeq[1];\n const candInner = candListMatch[1];\n if (baseInner === candInner) return true;\n const primitiveTypes = PYTHON_PRIMITIVE_TYPES;\n if (\n (primitiveTypes.has(baseInner) && NAMED_TYPE_RE.test(candInner)) ||\n (primitiveTypes.has(candInner) && NAMED_TYPE_RE.test(baseInner))\n ) {\n return true;\n }\n }\n }\n\n // Mapping[K, V] ≡ dict[K, V] (Mapping is the ABC for dict)\n const mappingPattern = /^(?:Mapping|dict|Dict)\\[(.+)\\]$/;\n const baseMapping = baseClean.match(mappingPattern);\n const candMapping = candClean.match(mappingPattern);\n if (baseMapping && candMapping) {\n // Both are map-like — compare key/value types loosely\n return true;\n }\n\n // dict map equivalence: dict[str, str] ≡ dict[str, Any] ≡ Dict[str, Any] ≡ dict[str, str | float | bool]\n const dictLikePattern = /^(?:dict|Dict|Mapping)\\[str,\\s*.+\\]$/;\n if (dictLikePattern.test(baseClean) && dictLikePattern.test(candClean)) return true;\n\n // Named metadata type ≡ dict[str, ...] (custom type alias for dict)\n const isMapType = (t: string) => dictLikePattern.test(t) || /^(?:Metadata|AuditLog\\w*Metadata)$/.test(t);\n if (isMapType(baseClean) && isMapType(candClean)) return true;\n\n // Named type alias for a map/dict type ≡ inline dict expression\n // e.g., AuditLogMetadata ≡ dict[str, str | float | bool]\n if (NAMED_TYPE_RE.test(baseClean) && dictLikePattern.test(candClean)) {\n // Assume named types ending in \"Metadata\" or \"Attributes\" are dict aliases\n if (/(?:Metadata|Attributes)$/.test(baseClean)) return true;\n }\n if (NAMED_TYPE_RE.test(candClean) && dictLikePattern.test(baseClean)) {\n if (/(?:Metadata|Attributes)$/.test(candClean)) return true;\n }\n\n // str ≡ Literal[\"...\"] (literal string type vs plain str)\n if (baseClean === 'str' && candClean.startsWith('Literal[')) return true;\n if (candClean === 'str' && baseClean.startsWith('Literal[')) return true;\n\n // Literal[...] ≡ enum name (candidate has an enum, baseline has Literal)\n if (baseClean.startsWith('Literal[') && candidateSurface.enums[candClean]) return true;\n if (candClean.startsWith('Literal[') && candidateSurface.enums?.[baseClean]) return true;\n\n // str ≡ enum type (baseline says str, candidate uses enum)\n if (baseClean === 'str' && candidateSurface.enums[candClean]) return true;\n if (candClean === 'str' && candidateSurface.enums?.[baseClean]) return true;\n\n // int ≡ float (JSON number coercion)\n const numericTypes = new Set(['int', 'float']);\n if (numericTypes.has(baseClean) && numericTypes.has(candClean)) return true;\n\n // Named type tolerance\n if (NAMED_TYPE_RE.test(baseClean) && NAMED_TYPE_RE.test(candClean)) {\n if (typeExistsInSurface(candClean, candidateSurface)) {\n if (candClean.includes(baseClean) || baseClean.includes(candClean)) return true;\n const baseNoResp = baseClean.replace(/Response$/, '');\n const candNoResp = candClean.replace(/Response$/, '');\n if (candNoResp.includes(baseNoResp) || baseNoResp.includes(candNoResp)) return true;\n if (namedTypeWordsOverlap(baseClean, candClean)) return true;\n }\n }\n\n return false;\n },\n\n isSignatureEquivalent(\n baseline: import('../types.js').ApiMethod,\n candidate: import('../types.js').ApiMethod,\n _candidateSurface: ApiSurface,\n ): boolean {\n // Tolerate methods where the candidate uses a body dict (payload: dict[str, Any])\n // while the baseline unpacks the body into individual typed params.\n // The first N params that match by name and type are consumed, then the remaining\n // baseline params are tolerated if the candidate has a dict payload param.\n\n // Return types must be equivalent (use named type tolerance)\n if (baseline.returnType !== candidate.returnType) {\n const baseRet = baseline.returnType;\n const candRet = candidate.returnType;\n if (!(NAMED_TYPE_RE.test(baseRet) && NAMED_TYPE_RE.test(candRet))) return false;\n // Check named-type containment or word overlap\n if (!candRet.includes(baseRet) && !baseRet.includes(candRet)) {\n if (!namedTypeWordsOverlap(baseRet, candRet)) return false;\n }\n }\n\n // Check if candidate has a body dict param\n const bodyDictTypes = new Set(['dict[str, Any]', 'Dict[str, Any]', 'dict']);\n const candBodyIdx = candidate.params.findIndex(\n (p) => bodyDictTypes.has(p.type) && (p.name === 'payload' || p.name === 'body' || p.name === 'data'),\n );\n if (candBodyIdx < 0) return false;\n\n // All candidate params before the body dict must match baseline params by name and type\n for (let i = 0; i < candBodyIdx; i++) {\n if (i >= baseline.params.length) return false;\n if (baseline.params[i].name !== candidate.params[i].name) return false;\n if (baseline.params[i].type !== candidate.params[i].type) return false;\n }\n\n // Remaining baseline params after the matched prefix are tolerated as body fields\n return true;\n },\n\n // Consumers should configure modelBaseClasses for their framework (e.g., ['BaseModel'] for Pydantic)\n modelBaseClasses: [],\n exceptionBaseClasses: ['Exception', 'BaseException'],\n listResourcePatterns: [],\n};\n\n// ---------------------------------------------------------------------------\n// Extractor\n// ---------------------------------------------------------------------------\n\n/** Create a Python extractor with optional hint overrides. */\nexport function createPythonExtractor(hintOverrides?: Partial<LanguageHints>): Extractor {\n const mergedHints: LanguageHints = hintOverrides ? { ...pythonHints, ...hintOverrides } : pythonHints;\n\n return {\n language: 'python',\n hints: mergedHints,\n\n async extractSnapshot(sdkPath: string): Promise<CompatSnapshot> {\n const surface = await this.extract(sdkPath);\n return apiSurfaceToSnapshot(surface);\n },\n\n async extract(sdkPath: string): Promise<ApiSurface> {\n const sourceRoot = findPythonSourceRoot(sdkPath);\n if (!sourceRoot) {\n throw new ExtractorError(\n `No Python package found in ${sdkPath}`,\n `Ensure the --sdk-path argument points to a Python project root containing a package directory with __init__.py.`,\n );\n }\n\n const pyFiles = walkPythonFiles(sourceRoot);\n if (pyFiles.length === 0) {\n throw new ExtractorError(\n `No .py files found in ${sdkPath}`,\n `Ensure the project contains Python source files.`,\n );\n }\n\n const parsedFiles: ParsedPythonFile[] = [];\n for (const filePath of pyFiles) {\n const parsed = parsePythonFile(filePath, sdkPath);\n parsedFiles.push(parsed);\n }\n\n const { classes, interfaces, typeAliases, enums, exports } = buildSurface(parsedFiles, mergedHints);\n\n return {\n language: 'python',\n extractedFrom: sdkPath,\n extractedAt: new Date().toISOString(),\n classes,\n interfaces,\n typeAliases,\n enums,\n exports,\n };\n },\n };\n}\n\n/** Default Python extractor with generic language hints (no SDK-specific bases). */\nexport const pythonExtractor: Extractor = createPythonExtractor();\n","/**\n * Ruby entity extraction — tree-sitter-based parsing of classes, service modules,\n * and enum modules from Ruby source files.\n */\n\nimport Parser from 'tree-sitter';\nimport Ruby from 'tree-sitter-ruby';\nimport type { SyntaxNode } from 'tree-sitter';\nimport type { ApiClass, ApiEnum, ApiMethod, ApiParam, ApiProperty } from '../types.js';\nimport { safeParse as safeParseWith } from '../../utils/tree-sitter.js';\nimport { sortRecord } from './shared.js';\n\n// ---------------------------------------------------------------------------\n// Shared parser instance\n// ---------------------------------------------------------------------------\n\nconst rubyParser = new Parser();\nrubyParser.setLanguage(Ruby);\n\nfunction safeParse(source: string): Parser.Tree {\n return safeParseWith(rubyParser, source);\n}\n\n// ---------------------------------------------------------------------------\n// Public API — called from ruby.ts\n// ---------------------------------------------------------------------------\n\n/** Parse a Ruby source string and return all class declarations (excluding service modules). */\nexport function extractClasses(source: string): ApiClass[] {\n const tree = safeParse(source);\n const classes: ApiClass[] = [];\n\n // Collect line ranges of service modules so we can skip nested classes\n const serviceModuleNodes = findServiceModulesFromTree(tree.rootNode);\n const serviceRanges = serviceModuleNodes.map((n) => [n.startPosition.row, n.endPosition.row] as [number, number]);\n\n for (const node of tree.rootNode.descendantsOfType('class')) {\n // Skip singleton_class nodes (class << self)\n if (node.type !== 'class') continue;\n\n // Skip classes inside service modules\n if (isInsideRanges(node.startPosition.row, serviceRanges)) continue;\n\n // Skip if this class contains a singleton_class (class << self) — those are service modules\n if (node.descendantsOfType('singleton_class').length > 0) continue;\n\n const nameNode = node.childForFieldName('name');\n if (!nameNode) continue;\n const className = nameNode.text;\n\n const bodyNode = node.childForFieldName('body');\n\n const methods: Record<string, ApiMethod[]> = {};\n const properties: Record<string, ApiProperty> = {};\n const constructorParams: ApiParam[] = [];\n\n // Only extract body content if body exists (single-line classes like `class Foo < Bar; end` may not have a body)\n if (bodyNode) {\n // Extract attr_accessor/attr_reader\n extractAttributes(bodyNode, properties);\n\n // Extract methods (respecting visibility)\n const extractedMethods = extractMethodsFromBody(bodyNode);\n for (const method of extractedMethods) {\n if (method.name === 'initialize') {\n constructorParams.push(...method.params);\n } else {\n if (!methods[method.name]) methods[method.name] = [];\n methods[method.name].push(method);\n }\n }\n }\n\n classes.push({\n name: className,\n methods: sortRecord(methods),\n properties: sortRecord(properties),\n constructorParams,\n });\n }\n\n return classes;\n}\n\n/** Extract service modules (modules with `class << self` at immediate depth). */\nexport function extractServiceModules(source: string): ApiClass[] {\n const tree = safeParse(source);\n const services: ApiClass[] = [];\n\n for (const moduleNode of findServiceModulesFromTree(tree.rootNode)) {\n const nameNode = moduleNode.childForFieldName('name');\n if (!nameNode) continue;\n const moduleName = nameNode.text;\n\n const bodyNode = moduleNode.childForFieldName('body');\n if (!bodyNode) continue;\n\n // Find the singleton_class (class << self) at immediate depth\n const singletonNode = findImmediateSingletonClass(bodyNode);\n if (!singletonNode) continue;\n\n const singletonBody = singletonNode.childForFieldName('body');\n if (!singletonBody) continue;\n\n const methods: Record<string, ApiMethod[]> = {};\n const properties: Record<string, ApiProperty> = {};\n\n // Extract methods from the singleton class body\n const extractedMethods = extractMethodsFromBody(singletonBody);\n for (const method of extractedMethods) {\n if (!methods[method.name]) methods[method.name] = [];\n methods[method.name].push(method);\n }\n\n // Extract constants as properties\n extractConstantsAsProperties(singletonBody, properties);\n\n if (Object.keys(methods).length > 0 || Object.keys(properties).length > 0) {\n services.push({\n name: moduleName,\n methods: sortRecord(methods),\n properties: sortRecord(properties),\n constructorParams: [],\n });\n }\n }\n\n return services;\n}\n\n/** Extract enum-like modules (modules with string/number constants, no class << self). */\nexport function extractEnumModules(source: string): ApiEnum[] {\n const tree = safeParse(source);\n const enums: ApiEnum[] = [];\n\n const serviceModuleNodes = findServiceModulesFromTree(tree.rootNode);\n const serviceRanges = serviceModuleNodes.map((n) => [n.startPosition.row, n.endPosition.row] as [number, number]);\n\n for (const node of tree.rootNode.descendantsOfType('module')) {\n // Skip modules inside service modules\n if (isInsideRanges(node.startPosition.row, serviceRanges)) continue;\n\n // Skip modules that have singleton_class (service modules)\n if (node.descendantsOfType('singleton_class').length > 0) continue;\n\n const nameNode = node.childForFieldName('name');\n if (!nameNode) continue;\n\n const bodyNode = node.childForFieldName('body');\n if (!bodyNode) continue;\n\n const constants = extractEnumConstants(bodyNode);\n if (Object.keys(constants).length < 2) continue;\n\n enums.push({\n name: nameNode.text,\n members: sortRecord(constants),\n });\n }\n\n return enums;\n}\n\n/** Extract autoload declarations to build the export map. */\nexport function extractAutoloads(source: string): string[] {\n const tree = safeParse(source);\n const names: string[] = [];\n\n for (const callNode of tree.rootNode.descendantsOfType('call')) {\n const methodNode = callNode.childForFieldName('method');\n if (!methodNode || methodNode.text !== 'autoload') continue;\n\n const argsNode = callNode.childForFieldName('arguments');\n if (!argsNode) continue;\n\n // First argument is the symbol name\n const firstArg = argsNode.namedChildren[0];\n if (firstArg && (firstArg.type === 'simple_symbol' || firstArg.type === 'symbol')) {\n names.push(firstArg.text.replace(/^:/, ''));\n }\n }\n\n return names;\n}\n\n// ---------------------------------------------------------------------------\n// Internal: finding service modules\n// ---------------------------------------------------------------------------\n\n/** Find module nodes that have `class << self` at their immediate body level. */\nfunction findServiceModulesFromTree(rootNode: SyntaxNode): SyntaxNode[] {\n const result: SyntaxNode[] = [];\n\n for (const moduleNode of rootNode.descendantsOfType('module')) {\n const bodyNode = moduleNode.childForFieldName('body');\n if (!bodyNode) continue;\n\n if (findImmediateSingletonClass(bodyNode)) {\n result.push(moduleNode);\n }\n }\n\n return result;\n}\n\n/** Find a singleton_class (class << self) at the immediate body level (not nested). */\nfunction findImmediateSingletonClass(bodyNode: SyntaxNode): SyntaxNode | null {\n for (const child of bodyNode.namedChildren) {\n if (child.type === 'singleton_class') return child;\n }\n return null;\n}\n\n// ---------------------------------------------------------------------------\n// Internal: method extraction with visibility tracking\n// ---------------------------------------------------------------------------\n\n/** Extract methods from a body_statement, respecting private/protected/public markers. */\nfunction extractMethodsFromBody(bodyNode: SyntaxNode): ApiMethod[] {\n const methods: ApiMethod[] = [];\n let isPrivate = false;\n\n for (const child of bodyNode.namedChildren) {\n // Track visibility markers: bare `private`, `public`, `protected` calls\n if (child.type === 'identifier') {\n if (child.text === 'private') {\n isPrivate = true;\n continue;\n }\n if (child.text === 'public') {\n isPrivate = false;\n continue;\n }\n if (child.text === 'protected') {\n isPrivate = true;\n continue;\n }\n }\n\n if (isPrivate) continue;\n\n if (child.type === 'method') {\n const nameNode = child.childForFieldName('name');\n if (!nameNode) continue;\n\n const params = extractMethodParams(child);\n methods.push({\n name: nameNode.text,\n params,\n returnType: 'Object',\n async: false,\n });\n }\n }\n\n return methods;\n}\n\n/** Extract parameters from a method node. */\nfunction extractMethodParams(methodNode: SyntaxNode): ApiParam[] {\n const paramsNode = methodNode.childForFieldName('parameters');\n if (!paramsNode) return [];\n\n const params: ApiParam[] = [];\n\n for (const paramNode of paramsNode.namedChildren) {\n switch (paramNode.type) {\n case 'identifier': {\n // Plain positional argument\n params.push({ name: paramNode.text, type: 'Object', optional: false, passingStyle: 'positional' as const });\n break;\n }\n case 'optional_parameter': {\n // Positional argument with default: name = value\n const nameNode = paramNode.childForFieldName('name');\n if (nameNode) {\n params.push({ name: nameNode.text, type: 'Object', optional: true, passingStyle: 'positional' as const });\n }\n break;\n }\n case 'keyword_parameter': {\n // Keyword argument: name: or name: default\n const nameNode = paramNode.childForFieldName('name');\n if (nameNode) {\n const valueNode = paramNode.childForFieldName('value');\n params.push({\n name: nameNode.text,\n type: 'Object',\n optional: valueNode !== null,\n passingStyle: 'keyword' as const,\n });\n }\n break;\n }\n case 'splat_parameter': {\n // *args — variadic positional\n const nameNode = paramNode.childForFieldName('name');\n params.push({\n name: nameNode ? `*${nameNode.text}` : '*args',\n type: 'Object',\n optional: true,\n passingStyle: 'positional' as const,\n });\n break;\n }\n case 'hash_splat_parameter': {\n // **kwargs — variadic keyword\n const nameNode = paramNode.childForFieldName('name');\n params.push({\n name: nameNode ? `**${nameNode.text}` : '**kwargs',\n type: 'Object',\n optional: true,\n passingStyle: 'keyword' as const,\n });\n break;\n }\n case 'block_parameter': {\n // &block — block argument\n const nameNode = paramNode.childForFieldName('name');\n params.push({\n name: nameNode ? `&${nameNode.text}` : '&block',\n type: 'Object',\n optional: true,\n passingStyle: 'positional' as const,\n });\n break;\n }\n default:\n break;\n }\n }\n\n return params;\n}\n\n// ---------------------------------------------------------------------------\n// Internal: attribute extraction\n// ---------------------------------------------------------------------------\n\n/** Extract attr_accessor/attr_reader calls into properties. */\nfunction extractAttributes(bodyNode: SyntaxNode, properties: Record<string, ApiProperty>): void {\n for (const callNode of bodyNode.descendantsOfType('call')) {\n const methodNode = callNode.childForFieldName('method');\n if (!methodNode) continue;\n const methodName = methodNode.text;\n if (methodName !== 'attr_accessor' && methodName !== 'attr_reader') continue;\n\n const isReadonly = methodName === 'attr_reader';\n\n const argsNode = callNode.childForFieldName('arguments');\n if (!argsNode) continue;\n\n for (const argNode of argsNode.namedChildren) {\n if (argNode.type === 'simple_symbol' || argNode.type === 'symbol') {\n const name = argNode.text.replace(/^:/, '');\n properties[name] = { name, type: 'Object', readonly: isReadonly };\n }\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Internal: constant extraction\n// ---------------------------------------------------------------------------\n\n/** Extract UPPER_CASE constants from a body as readonly properties. */\nfunction extractConstantsAsProperties(bodyNode: SyntaxNode, properties: Record<string, ApiProperty>): void {\n for (const child of bodyNode.namedChildren) {\n if (child.type !== 'assignment') continue;\n const leftNode = child.childForFieldName('left');\n if (!leftNode || leftNode.type !== 'constant') continue;\n const name = leftNode.text;\n if (!/^[A-Z][A-Z_0-9]*$/.test(name)) continue;\n properties[name] = { name, type: 'Object', readonly: true };\n }\n}\n\n/** Extract enum-style constants (ConstantName = 'value') from a module body. */\nfunction extractEnumConstants(bodyNode: SyntaxNode): Record<string, string | number> {\n const constants: Record<string, string | number> = {};\n\n for (const child of bodyNode.namedChildren) {\n if (child.type !== 'assignment') continue;\n const leftNode = child.childForFieldName('left');\n if (!leftNode || leftNode.type !== 'constant') continue;\n const name = leftNode.text;\n if (name === 'ALL') continue; // Skip aggregate constants\n\n const rightNode = child.childForFieldName('right');\n if (!rightNode) continue;\n\n const value = extractLiteralValue(rightNode);\n if (value !== undefined) {\n constants[name] = value;\n }\n }\n\n return constants;\n}\n\n/** Extract a literal string or number value from a tree-sitter node. */\nfunction extractLiteralValue(node: SyntaxNode): string | number | undefined {\n if (node.type === 'string' || node.type === 'string_content') {\n // String: strip surrounding quotes\n const text = node.text;\n if ((text.startsWith(\"'\") && text.endsWith(\"'\")) || (text.startsWith('\"') && text.endsWith('\"'))) {\n return text.slice(1, -1);\n }\n // For string_content (inside a string node), return as-is\n return text;\n }\n if (node.type === 'integer') {\n return Number(node.text);\n }\n if (node.type === 'float') {\n return Number(node.text);\n }\n // For strings, tree-sitter wraps in a `string` node with `string_content` children\n if (node.type === 'string') {\n const contentNode = node.namedChildren.find((c) => c.type === 'string_content');\n if (contentNode) return contentNode.text;\n }\n return undefined;\n}\n\n// ---------------------------------------------------------------------------\n// Internal: tree traversal helpers\n// ---------------------------------------------------------------------------\n\n/** Check if a line number falls inside any of the given ranges. */\nfunction isInsideRanges(line: number, ranges: Array<[number, number]>): boolean {\n for (const [start, end] of ranges) {\n if (line > start && line < end) return true;\n }\n return false;\n}\n\nexport { sortRecord } from './shared.js';\n","/**\n * Ruby API surface extractor.\n *\n * Walks `.rb` files under `lib/`, parses class/module declarations,\n * and builds an `ApiSurface` with classes, service modules, and enum modules.\n *\n * Parser: `ruby-parser.ts` — tree-sitter-based class/module/enum extraction\n */\n\nimport { readFileSync, readdirSync, statSync } from 'node:fs';\nimport { resolve, relative, join } from 'node:path';\nimport { ExtractorError } from '../../errors.js';\nimport type { ApiSurface, Extractor, LanguageHints } from '../types.js';\nimport type { CompatSnapshot } from '../ir.js';\nimport { apiSurfaceToSnapshot } from '../ir.js';\nimport { defaultIsNullableOnlyDifference } from '../language-hints.js';\nimport {\n extractClasses,\n extractServiceModules,\n extractEnumModules,\n extractAutoloads,\n sortRecord,\n} from './ruby-parser.js';\n\n// ---------------------------------------------------------------------------\n// Language hints\n// ---------------------------------------------------------------------------\n\nconst rubyHints: LanguageHints = {\n stripNullable(type: string): string | null {\n const match = type.match(/^T\\.nilable\\((.+)\\)$/);\n return match ? match[1] : null;\n },\n isNullableOnlyDifference(a: string, b: string): boolean {\n return defaultIsNullableOnlyDifference(this, a, b);\n },\n isUnionReorder(_a: string, _b: string): boolean {\n return false;\n },\n isGenericTypeParam(type: string): boolean {\n return type === 'T.untyped';\n },\n isExtractionArtifact(type: string): boolean {\n return type === 'T.untyped' || type === 'BasicObject';\n },\n tolerateCategoryMismatch: false,\n extractReturnTypeName(returnType: string): string | null {\n return returnType || null;\n },\n extractParamTypeName(paramType: string): string | null {\n if (['String', 'Integer', 'Float', 'Boolean', 'NilClass'].includes(paramType)) return null;\n return paramType;\n },\n propertyMatchesClass(propertyName: string, className: string): boolean {\n return propertyName.replace(/_/g, '').toLowerCase() === className.toLowerCase();\n },\n derivedModelNames(_modelName: string): string[] {\n return [];\n },\n};\n\n// ---------------------------------------------------------------------------\n// File collection\n// ---------------------------------------------------------------------------\n\n/** Recursively collect all .rb files under a directory. */\nfunction collectRbFiles(dir: string): string[] {\n const result: string[] = [];\n const entries = readdirSync(dir);\n for (const entry of entries.sort()) {\n const full = join(dir, entry);\n const stat = statSync(full);\n if (stat.isDirectory()) {\n result.push(...collectRbFiles(full));\n } else if (entry.endsWith('.rb')) {\n result.push(full);\n }\n }\n return result;\n}\n\n// ---------------------------------------------------------------------------\n// Extractor\n// ---------------------------------------------------------------------------\n\nexport const rubyExtractor: Extractor = {\n language: 'ruby',\n hints: rubyHints,\n\n async extractSnapshot(sdkPath: string): Promise<CompatSnapshot> {\n const surface = await this.extract(sdkPath);\n return apiSurfaceToSnapshot(surface);\n },\n\n async extract(sdkPath: string): Promise<ApiSurface> {\n const libPath = resolve(sdkPath, 'lib');\n try {\n statSync(libPath);\n } catch {\n throw new ExtractorError(\n `No lib/ directory found in ${sdkPath}`,\n `Verify the --sdk-path argument points to a Ruby project root containing a lib/ directory.`,\n );\n }\n\n const rbFiles = collectRbFiles(libPath);\n if (rbFiles.length === 0) {\n throw new ExtractorError(\n `No .rb files found in ${libPath}`,\n `Ensure the lib/ directory contains Ruby source files.`,\n );\n }\n\n const classes: Record<string, import('../types.js').ApiClass> = {};\n const enums: Record<string, import('../types.js').ApiEnum> = {};\n const exports: Record<string, string[]> = {};\n\n for (const absPath of rbFiles) {\n const relPath = relative(sdkPath, absPath);\n const source = readFileSync(absPath, 'utf-8');\n\n const fileExports: string[] = [];\n\n // Extract classes (model classes and struct classes)\n const extractedClasses = extractClasses(source);\n for (const cls of extractedClasses) {\n classes[cls.name] = { ...cls, sourceFile: relPath };\n fileExports.push(cls.name);\n }\n\n // Extract service modules (modules with class << self)\n const extractedServices = extractServiceModules(source);\n for (const svc of extractedServices) {\n classes[svc.name] = { ...svc, sourceFile: relPath };\n fileExports.push(svc.name);\n }\n\n // Extract enum-like modules (modules with constants)\n const extractedEnums = extractEnumModules(source);\n for (const en of extractedEnums) {\n enums[en.name] = { ...en, sourceFile: relPath };\n fileExports.push(en.name);\n }\n\n // Extract autoload declarations as exports\n const autoloadNames = extractAutoloads(source);\n if (autoloadNames.length > 0) {\n fileExports.push(...autoloadNames);\n }\n\n if (fileExports.length > 0) {\n exports[relPath] = [...new Set(fileExports)].sort();\n }\n }\n\n return {\n language: 'ruby',\n extractedFrom: sdkPath,\n extractedAt: new Date().toISOString(),\n classes: sortRecord(classes),\n interfaces: {},\n typeAliases: {},\n enums: sortRecord(enums),\n exports: sortRecord(exports),\n };\n },\n};\n","/**\n * Go source parser — tree-sitter-based extraction of structs, functions, types,\n * and const blocks from Go source files.\n */\n\nimport { readFileSync, readdirSync, statSync } from 'node:fs';\nimport { join, relative } from 'node:path';\nimport Parser from 'tree-sitter';\nimport Go from 'tree-sitter-go';\nimport type { SyntaxNode } from 'tree-sitter';\nimport { safeParse } from '../../utils/tree-sitter.js';\n\n// ---------------------------------------------------------------------------\n// Internal types\n// ---------------------------------------------------------------------------\n\nexport interface GoStructField {\n name: string;\n type: string;\n jsonTag?: string;\n optional: boolean;\n}\n\nexport interface GoStruct {\n name: string;\n fields: GoStructField[];\n sourceFile: string;\n packageName: string;\n}\n\nexport interface GoFunc {\n receiverType: string | null;\n name: string;\n params: { name: string; type: string }[];\n returnTypes: string[];\n sourceFile: string;\n packageName: string;\n}\n\nexport interface GoConst {\n name: string;\n typeName: string;\n value: string;\n sourceFile: string;\n packageName: string;\n}\n\nexport interface GoTypeDecl {\n name: string;\n underlyingType: string;\n isAlias: boolean;\n sourceFile: string;\n packageName: string;\n}\n\n// ---------------------------------------------------------------------------\n// Shared parser instance\n// ---------------------------------------------------------------------------\n\nconst goParser = new Parser();\ngoParser.setLanguage(Go);\n\n// ---------------------------------------------------------------------------\n// File walker\n// ---------------------------------------------------------------------------\n\nexport function walkGoFiles(dir: string): string[] {\n const results: string[] = [];\n let entries: string[];\n try {\n entries = readdirSync(dir);\n } catch {\n return results;\n }\n for (const entry of entries) {\n const fullPath = join(dir, entry);\n let stat;\n try {\n stat = statSync(fullPath);\n } catch {\n continue;\n }\n if (stat.isDirectory()) {\n if (entry.startsWith('.') || entry === 'vendor' || entry === 'testdata' || entry === 'internal') continue;\n results.push(...walkGoFiles(fullPath));\n } else if (entry.endsWith('.go') && !entry.endsWith('_test.go')) {\n results.push(fullPath);\n }\n }\n return results.sort();\n}\n\n// ---------------------------------------------------------------------------\n// Node helpers\n// ---------------------------------------------------------------------------\n\n/** Get the text of a child node by field name, or null. */\nfunction fieldText(node: SyntaxNode, field: string): string | null {\n const child = node.childForFieldName(field);\n return child ? child.text : null;\n}\n\n/** Extract the JSON field name from a struct tag. */\nfunction extractJsonTag(tagText: string): { name: string; omitempty: boolean } | null {\n const match = tagText.match(/json:\"([^\"]*)\"/);\n if (!match) return null;\n const parts = match[1].split(',');\n const name = parts[0].trim();\n const omitempty = parts.includes('omitempty');\n if (name === '-') return null;\n return { name, omitempty };\n}\n\n/** Render a type node back to its Go source representation. */\nfunction typeNodeText(node: SyntaxNode): string {\n return node.text;\n}\n\n// ---------------------------------------------------------------------------\n// Struct extraction\n// ---------------------------------------------------------------------------\n\nfunction parseStructFields(structNode: SyntaxNode): GoStructField[] {\n const fields: GoStructField[] = [];\n const fieldList = structNode.namedChildren.find((c) => c.type === 'field_declaration_list');\n if (!fieldList) return fields;\n\n for (const fieldDecl of fieldList.namedChildren) {\n if (fieldDecl.type !== 'field_declaration') continue;\n\n // Get all field identifiers (there can be multiple: `A, B int`)\n const nameNodes = fieldDecl.namedChildren.filter((c) => c.type === 'field_identifier');\n if (nameNodes.length === 0) {\n // Embedded field (struct composition) — extract the type name as the field name.\n // e.g., `type Foo struct { Bar }` → field named \"Bar\" of type \"Bar\"\n const typeNode = fieldDecl.namedChildren.find(\n (c) => c.type !== 'raw_string_literal' && c.type !== 'interpreted_string_literal',\n );\n if (typeNode) {\n const typeName = typeNode.text.replace(/^\\*/, ''); // strip pointer\n if (/^[A-Z]/.test(typeName)) {\n fields.push({\n name: typeName,\n type: typeNode.text,\n optional: false,\n });\n }\n }\n continue;\n }\n\n // The type node: find the first named child that isn't a field_identifier and isn't a tag\n const typeNode = fieldDecl.namedChildren.find(\n (c) =>\n c.type !== 'field_identifier' && c.type !== 'raw_string_literal' && c.type !== 'interpreted_string_literal',\n );\n if (!typeNode) continue;\n\n // Only export fields that start with uppercase\n const fieldType = typeNodeText(typeNode);\n\n // Tag is a raw_string_literal child\n const tagNode = fieldDecl.namedChildren.find(\n (c) => c.type === 'raw_string_literal' || c.type === 'interpreted_string_literal',\n );\n const jsonTag = tagNode ? extractJsonTag(tagNode.text) : null;\n\n for (const nameNode of nameNodes) {\n const name = nameNode.text;\n if (!/^[A-Z]/.test(name)) continue; // skip unexported\n fields.push({\n name,\n type: fieldType,\n jsonTag: jsonTag?.name || undefined,\n optional: jsonTag?.omitempty || false,\n });\n }\n }\n return fields;\n}\n\n// ---------------------------------------------------------------------------\n// Type declarations\n// ---------------------------------------------------------------------------\n\nexport function parseTypeDecls(\n tree: Parser.Tree,\n sourceFile: string,\n packageName: string,\n): { structs: GoStruct[]; types: GoTypeDecl[] } {\n const structs: GoStruct[] = [];\n const types: GoTypeDecl[] = [];\n\n for (const node of tree.rootNode.namedChildren) {\n if (node.type !== 'type_declaration') continue;\n\n for (const spec of node.namedChildren) {\n const name = fieldText(spec, 'name');\n if (!name || !/^[A-Z]/.test(name)) continue;\n\n if (spec.type === 'type_spec') {\n const typeNode = spec.childForFieldName('type');\n if (!typeNode) continue;\n\n if (typeNode.type === 'struct_type') {\n structs.push({ name, fields: parseStructFields(typeNode), sourceFile, packageName });\n } else if (typeNode.type !== 'interface_type') {\n types.push({ name, underlyingType: typeNodeText(typeNode), isAlias: false, sourceFile, packageName });\n }\n } else if (spec.type === 'type_alias') {\n const typeNode = spec.childForFieldName('type');\n if (typeNode) {\n types.push({ name, underlyingType: typeNodeText(typeNode), isAlias: true, sourceFile, packageName });\n }\n }\n }\n }\n\n return { structs, types };\n}\n\n// ---------------------------------------------------------------------------\n// Const blocks\n// ---------------------------------------------------------------------------\n\n/** Strip surrounding quotes from a string value. */\nfunction stripQuotes(value: string): string {\n if ((value.startsWith('\"') && value.endsWith('\"')) || (value.startsWith(\"'\") && value.endsWith(\"'\"))) {\n return value.slice(1, -1);\n }\n const convMatch = value.match(/^\\w+(?:\\.\\w+)?\\(\"([^\"]*)\"\\)$/);\n if (convMatch) return convMatch[1];\n return value;\n}\n\nexport function parseConstBlocks(tree: Parser.Tree, sourceFile: string, packageName: string): GoConst[] {\n const consts: GoConst[] = [];\n\n for (const node of tree.rootNode.namedChildren) {\n if (node.type !== 'const_declaration') continue;\n\n let lastType = '';\n\n for (const spec of node.namedChildren) {\n if (spec.type !== 'const_spec') continue;\n\n const nameNodes = spec.namedChildren.filter((c) => c.type === 'identifier');\n if (nameNodes.length === 0) continue;\n const constName = nameNodes[0].text;\n if (!/^[A-Z]/.test(constName)) continue;\n\n // Type field (optional)\n const typeNode = spec.childForFieldName('type');\n if (typeNode) {\n lastType = typeNode.text;\n }\n\n // Value field\n const valueNode = spec.childForFieldName('value');\n if (valueNode) {\n // expression_list may contain a single value or a call expression\n const valueText = valueNode.text.trim();\n const strippedValue = stripQuotes(valueText);\n\n // Check for type conversion: TypeName(\"value\") or TypeName(value)\n if (!typeNode) {\n const convMatch = valueText.match(/^([A-Z]\\w*)\\((.+)\\)$/);\n if (convMatch) {\n consts.push({\n name: constName,\n typeName: convMatch[1],\n value: stripQuotes(convMatch[2].trim()),\n sourceFile,\n packageName,\n });\n continue;\n }\n }\n\n if (lastType) {\n consts.push({ name: constName, typeName: lastType, value: strippedValue, sourceFile, packageName });\n }\n } else if (lastType) {\n // iota continuation — no value node\n consts.push({ name: constName, typeName: lastType, value: constName, sourceFile, packageName });\n }\n }\n }\n\n return consts;\n}\n\n// ---------------------------------------------------------------------------\n// Function & method declarations\n// ---------------------------------------------------------------------------\n\nfunction parseParamList(paramListNode: SyntaxNode | null): { name: string; type: string }[] {\n if (!paramListNode) return [];\n const params: { name: string; type: string }[] = [];\n\n let unnamedIndex = 0;\n for (const paramDecl of paramListNode.namedChildren) {\n if (paramDecl.type !== 'parameter_declaration' && paramDecl.type !== 'variadic_parameter_declaration') continue;\n\n const nameNode = paramDecl.namedChildren.find((c) => c.type === 'identifier');\n const typeNode = paramDecl.childForFieldName('type');\n if (!typeNode) continue;\n\n // When Go omits the parameter name (e.g., `func Foo(string, int)`),\n // synthesize a positional name so signature matching doesn't break.\n const name = nameNode ? nameNode.text : `_arg${unnamedIndex++}`;\n params.push({\n name,\n type: typeNodeText(typeNode),\n });\n }\n return params;\n}\n\nfunction parseReturnTypes(resultNode: SyntaxNode | null): string[] {\n if (!resultNode) return [];\n\n if (resultNode.type === 'parameter_list') {\n // Multiple return values: (Type1, Type2)\n return resultNode.namedChildren\n .filter((c) => c.type === 'parameter_declaration')\n .map((c) => {\n const t = c.childForFieldName('type');\n return t ? typeNodeText(t) : c.text;\n });\n }\n\n // Single return value\n return [typeNodeText(resultNode)];\n}\n\nexport function parseFunctions(tree: Parser.Tree, sourceFile: string, packageName: string): GoFunc[] {\n const funcs: GoFunc[] = [];\n\n for (const node of tree.rootNode.namedChildren) {\n if (node.type === 'function_declaration') {\n const name = fieldText(node, 'name');\n if (!name || !/^[A-Z]/.test(name)) continue;\n\n funcs.push({\n receiverType: null,\n name,\n params: parseParamList(node.childForFieldName('parameters')),\n returnTypes: parseReturnTypes(node.childForFieldName('result')),\n sourceFile,\n packageName,\n });\n } else if (node.type === 'method_declaration') {\n const name = fieldText(node, 'name');\n if (!name || !/^[A-Z]/.test(name)) continue;\n\n // Extract receiver type\n const receiverNode = node.childForFieldName('receiver');\n let receiverType: string | null = null;\n if (receiverNode) {\n const paramDecl = receiverNode.namedChildren.find((c) => c.type === 'parameter_declaration');\n if (paramDecl) {\n const typeNode = paramDecl.childForFieldName('type');\n if (typeNode) {\n // Strip pointer: *Foo → Foo\n receiverType = typeNode.text.replace(/^\\*/, '');\n }\n }\n }\n\n funcs.push({\n receiverType,\n name,\n params: parseParamList(node.childForFieldName('parameters')),\n returnTypes: parseReturnTypes(node.childForFieldName('result')),\n sourceFile,\n packageName,\n });\n }\n }\n return funcs;\n}\n\n// ---------------------------------------------------------------------------\n// Package name extraction\n// ---------------------------------------------------------------------------\n\nexport function extractPackageName(tree: Parser.Tree): string {\n const pkgClause = tree.rootNode.namedChildren.find((c) => c.type === 'package_clause');\n if (!pkgClause) return 'unknown';\n const nameNode = pkgClause.namedChildren.find((c) => c.type === 'package_identifier');\n return nameNode ? nameNode.text : 'unknown';\n}\n\n// ---------------------------------------------------------------------------\n// Full file parser\n// ---------------------------------------------------------------------------\n\nexport interface ParsedGoFile {\n structs: GoStruct[];\n types: GoTypeDecl[];\n funcs: GoFunc[];\n consts: GoConst[];\n}\n\n/** Parse a single Go source file and return all extracted symbols. */\nexport function parseGoFile(filePath: string, sdkPath: string): ParsedGoFile {\n const source = readFileSync(filePath, 'utf-8');\n const relPath = relative(sdkPath, filePath);\n const tree = safeParse(goParser, source);\n const packageName = extractPackageName(tree);\n\n const { structs, types } = parseTypeDecls(tree, relPath, packageName);\n const funcs = parseFunctions(tree, relPath, packageName);\n const consts = parseConstBlocks(tree, relPath, packageName);\n\n return { structs, types, funcs, consts };\n}\n","/**\n * Go surface builder — transforms parsed Go symbols into an ApiSurface\n * with proper package-qualified names for collision avoidance.\n */\n\nimport { basename, dirname } from 'node:path';\nimport type {\n ApiClass,\n ApiMethod,\n ApiParam,\n ApiProperty,\n ApiInterface,\n ApiField,\n ApiTypeAlias,\n ApiEnum,\n} from '../types.js';\nimport type { GoStruct, GoTypeDecl, GoFunc, GoConst } from './go-parser.js';\nimport { sortRecord, ExportCollector } from './shared.js';\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction goTypeToString(t: string): string {\n return t.replace(/json\\.RawMessage/g, '[]byte').replace(/\\bcontext\\.Context\\b/g, 'context.Context');\n}\n\nfunction buildReturnType(returnTypes: string[]): string {\n const nonError = returnTypes.filter((r) => r !== 'error');\n if (nonError.length === 0) return 'error';\n if (nonError.length === 1) return goTypeToString(nonError[0]);\n return `(${nonError.map(goTypeToString).join(', ')})`;\n}\n\n/** Get the package directory name from a source file relative path. */\nfunction getPackageDirName(relPath: string): string {\n const dir = dirname(relPath);\n return basename(dir) || 'root';\n}\n\n// ---------------------------------------------------------------------------\n// Qualified name resolution\n// ---------------------------------------------------------------------------\n\n/**\n * When multiple packages define the same exported symbol, qualify with the\n * package directory name (e.g., \"organizations.Client\", \"sso.Client\").\n * Unique symbols keep their bare name.\n */\nfunction buildQualifiedNames(\n items: Array<{ name: string; packageName: string; sourceFile: string }>,\n): Map<string, string> {\n const nameToPackages = new Map<string, Set<string>>();\n for (const item of items) {\n if (!nameToPackages.has(item.name)) nameToPackages.set(item.name, new Set());\n nameToPackages.get(item.name)!.add(item.packageName);\n }\n\n const result = new Map<string, string>();\n for (const item of items) {\n const key = `${item.sourceFile}:${item.name}`;\n const packages = nameToPackages.get(item.name)!;\n result.set(key, packages.size > 1 ? `${getPackageDirName(item.sourceFile)}.${item.name}` : item.name);\n }\n return result;\n}\n\n// ---------------------------------------------------------------------------\n// Surface builder\n// ---------------------------------------------------------------------------\n\nexport function buildSurface(\n allStructs: GoStruct[],\n allTypes: GoTypeDecl[],\n allFuncs: GoFunc[],\n allConsts: GoConst[],\n): {\n classes: Record<string, ApiClass>;\n interfaces: Record<string, ApiInterface>;\n typeAliases: Record<string, ApiTypeAlias>;\n enums: Record<string, ApiEnum>;\n exports: Record<string, string[]>;\n} {\n const classes: Record<string, ApiClass> = {};\n const interfaces: Record<string, ApiInterface> = {};\n const typeAliases: Record<string, ApiTypeAlias> = {};\n const enums: Record<string, ApiEnum> = {};\n\n // Group consts by (packageName, typeName)\n const constsByPkgAndType = new Map<string, GoConst[]>();\n for (const c of allConsts) {\n const key = `${c.packageName}:${c.typeName}`;\n if (!constsByPkgAndType.has(key)) constsByPkgAndType.set(key, []);\n constsByPkgAndType.get(key)!.push(c);\n }\n\n // Group methods by (packageName, receiverType)\n const methodsByPkgAndReceiver = new Map<string, GoFunc[]>();\n const packageFuncs: GoFunc[] = [];\n for (const fn of allFuncs) {\n if (fn.receiverType) {\n const key = `${fn.packageName}:${fn.receiverType}`;\n if (!methodsByPkgAndReceiver.has(key)) methodsByPkgAndReceiver.set(key, []);\n methodsByPkgAndReceiver.get(key)!.push(fn);\n } else {\n packageFuncs.push(fn);\n }\n }\n\n // Build qualified names\n const allSymbols: Array<{ name: string; packageName: string; sourceFile: string }> = [];\n for (const s of allStructs) allSymbols.push({ name: s.name, packageName: s.packageName, sourceFile: s.sourceFile });\n for (const t of allTypes) allSymbols.push({ name: t.name, packageName: t.packageName, sourceFile: t.sourceFile });\n const qualifiedNames = buildQualifiedNames(allSymbols);\n\n // Process type declarations\n for (const typeDecl of allTypes) {\n const qName = qualifiedNames.get(`${typeDecl.sourceFile}:${typeDecl.name}`) || typeDecl.name;\n const typeConsts = constsByPkgAndType.get(`${typeDecl.packageName}:${typeDecl.name}`);\n\n if (typeDecl.isAlias) {\n typeAliases[qName] = {\n name: qName,\n sourceFile: typeDecl.sourceFile,\n value: goTypeToString(typeDecl.underlyingType),\n };\n } else if (typeConsts && typeConsts.length > 0) {\n const members: Record<string, string | number> = {};\n for (const c of typeConsts) {\n // Strip the type name prefix from enum constant names to produce\n // consistent short member keys (e.g., \"AuthenticationFactorTypeGenericOtp\"\n // → \"GenericOtp\"). This matches Go SDK conventions where the type prefix\n // is an implementation detail, not part of the public API contract.\n const memberKey = c.name.startsWith(typeDecl.name) ? c.name.slice(typeDecl.name.length) || c.name : c.name;\n members[memberKey] = c.value;\n }\n enums[qName] = { name: qName, sourceFile: typeDecl.sourceFile, members: sortRecord(members) };\n } else {\n typeAliases[qName] = {\n name: qName,\n sourceFile: typeDecl.sourceFile,\n value: goTypeToString(typeDecl.underlyingType),\n };\n }\n }\n\n // Process structs\n for (const s of allStructs) {\n const qName = qualifiedNames.get(`${s.sourceFile}:${s.name}`) || s.name;\n const methods = methodsByPkgAndReceiver.get(`${s.packageName}:${s.name}`);\n\n if (methods && methods.length > 0) {\n const apiMethods: Record<string, ApiMethod[]> = {};\n const properties: Record<string, ApiProperty> = {};\n\n for (const field of s.fields) {\n properties[field.name] = { name: field.name, type: goTypeToString(field.type), readonly: false };\n }\n\n for (const fn of methods) {\n const params: ApiParam[] = fn.params\n .filter((p) => p.type !== 'context.Context')\n .map((p) => ({\n name: p.name,\n type: goTypeToString(p.type),\n optional: false,\n passingStyle: 'positional' as const,\n }));\n if (!apiMethods[fn.name]) apiMethods[fn.name] = [];\n apiMethods[fn.name].push({ name: fn.name, params, returnType: buildReturnType(fn.returnTypes), async: false });\n }\n\n classes[qName] = {\n name: qName,\n sourceFile: s.sourceFile,\n methods: sortRecord(apiMethods),\n properties: sortRecord(properties),\n constructorParams: [],\n };\n } else {\n const fields: Record<string, ApiField> = {};\n for (const field of s.fields) {\n const fieldName = field.jsonTag || field.name;\n fields[fieldName] = { name: fieldName, type: goTypeToString(field.type), optional: field.optional };\n }\n interfaces[qName] = { name: qName, sourceFile: s.sourceFile, fields: sortRecord(fields), extends: [] };\n }\n }\n\n // Build export map\n const collector = new ExportCollector();\n\n for (const [name, cls] of Object.entries(classes)) if (cls.sourceFile) collector.add(cls.sourceFile, name);\n for (const [name, iface] of Object.entries(interfaces)) if (iface.sourceFile) collector.add(iface.sourceFile, name);\n for (const [name, ta] of Object.entries(typeAliases)) if (ta.sourceFile) collector.add(ta.sourceFile, name);\n for (const [name, en] of Object.entries(enums)) if (en.sourceFile) collector.add(en.sourceFile, name);\n for (const c of allConsts) {\n const typeDecl = allTypes.find((t) => t.name === c.typeName && t.packageName === c.packageName);\n if (typeDecl) collector.add(typeDecl.sourceFile, c.name);\n }\n for (const fn of packageFuncs) collector.add(fn.sourceFile, fn.name);\n\n const exports = collector.toRecord();\n\n return {\n classes: sortRecord(classes),\n interfaces: sortRecord(interfaces),\n typeAliases: sortRecord(typeAliases),\n enums: sortRecord(enums),\n exports: sortRecord(exports),\n };\n}\n","/**\n * Go API surface extractor.\n *\n * Walks `.go` files (excluding `_test.go` and `internal/`), parses exported\n * structs, functions, type declarations, and const blocks, then builds an\n * `ApiSurface` with package-qualified names to avoid collisions when\n * multiple packages define the same symbol (e.g., `Client`).\n *\n * Parser: `go-parser.ts` — regex-based Go source analysis\n * Surface: `go-surface.ts` — ApiSurface construction & name qualification\n */\n\nimport { ExtractorError } from '../../errors.js';\nimport type { Extractor, ApiSurface, LanguageHints } from '../types.js';\nimport type { CompatSnapshot } from '../ir.js';\nimport { apiSurfaceToSnapshot } from '../ir.js';\nimport { defaultIsNullableOnlyDifference } from '../language-hints.js';\nimport { walkGoFiles, parseGoFile } from './go-parser.js';\nimport { buildSurface } from './go-surface.js';\nimport type { GoStruct, GoTypeDecl, GoFunc, GoConst } from './go-parser.js';\n\n// ---------------------------------------------------------------------------\n// Language hints\n// ---------------------------------------------------------------------------\n\n/**\n * Go acronyms that may differ in casing between hand-written and generated code.\n * e.g., hand-written uses \"Json\" / \"Uri\" while generated uses \"JSON\" / \"URI\".\n */\nconst GO_ACRONYMS = [\n 'ID',\n 'URL',\n 'API',\n 'HTTP',\n 'HTTPS',\n 'JSON',\n 'XML',\n 'SQL',\n 'HTML',\n 'CSS',\n 'URI',\n 'SSO',\n 'IP',\n 'TLS',\n 'SSL',\n 'DNS',\n 'TCP',\n 'UDP',\n 'SSH',\n 'JWT',\n 'MFA',\n 'SAML',\n 'SCIM',\n];\n\n// Precompiled regex matching all acronym forms (uppercase + title-case) in a single pass.\nconst GO_ACRONYM_RE = new RegExp(\n GO_ACRONYMS.flatMap((a) => [a, a.charAt(0) + a.slice(1).toLowerCase()]).join('|'),\n 'g',\n);\n\n/**\n * Normalize a Go type string so that acronym casing differences don't cause\n * false mismatches. Lowercases all known Go acronyms to a canonical form.\n */\nfunction normalizeGoAcronyms(type: string): string {\n return type.replace(GO_ACRONYM_RE, (match) => match.toLowerCase());\n}\n\nconst goHints: LanguageHints = {\n stripNullable(type: string): string | null {\n if (type.startsWith('*')) return type.slice(1);\n return null;\n },\n isNullableOnlyDifference(a: string, b: string): boolean {\n return defaultIsNullableOnlyDifference(this, a, b);\n },\n isUnionReorder(_a: string, _b: string): boolean {\n return false;\n },\n isGenericTypeParam(type: string): boolean {\n return type === 'interface{}' || type === 'any';\n },\n isExtractionArtifact(type: string): boolean {\n return type === 'interface{}' || type === 'any';\n },\n tolerateCategoryMismatch: false,\n extractReturnTypeName(returnType: string): string | null {\n const stripped = returnType.replace(/^\\*/, '').replace(/\\[\\]/, '');\n return stripped || null;\n },\n extractParamTypeName(paramType: string): string | null {\n const stripped = paramType.replace(/^\\*/, '');\n if (['string', 'int', 'int64', 'float64', 'bool'].includes(stripped)) return null;\n return stripped;\n },\n propertyMatchesClass(propertyName: string, className: string): boolean {\n return propertyName.toLowerCase() === className.toLowerCase();\n },\n derivedModelNames(_modelName: string): string[] {\n // Go SDK does not generate *Response wrapper types — models are returned directly.\n // Don't derive extra names, as they would create false positives in compat checks\n // when the live SDK has hand-written response wrappers.\n return [];\n },\n isTypeEquivalent(baselineType: string, candidateType: string, candidateSurface: ApiSurface): boolean {\n // Normalize Go acronym casing differences (e.g., \"Json\" vs \"JSON\", \"Uri\" vs \"URI\")\n const normBase = normalizeGoAcronyms(baselineType);\n const normCand = normalizeGoAcronyms(candidateType);\n if (normBase === normCand) return true;\n\n // Also try after stripping nullable wrappers and slice prefixes on both sides\n const stripType = (t: string) => t.replace(/^\\*/, '').replace(/^\\[\\]/, '');\n const strippedBase = stripType(normBase);\n const strippedCand = stripType(normCand);\n if (strippedBase === strippedCand) return true;\n\n // Strip package qualifiers (e.g., \"common.RoleResponse\" → \"RoleResponse\")\n const unqualBase = strippedBase.includes('.') ? strippedBase.split('.').pop()! : strippedBase;\n const unqualCand = strippedCand.includes('.') ? strippedCand.split('.').pop()! : strippedCand;\n if (unqualBase === unqualCand) return true;\n\n // Suffix match: the baseline may use a shorter shared type name while the\n // generated code prefixes it with the parent struct name.\n // e.g., baseline \"FactorType\" matches generated \"AuthenticationFactorType\"\n // Only match if the candidate type actually exists in the generated surface.\n const candRaw = stripType(candidateType);\n if (unqualCand.endsWith(unqualBase) && unqualCand.length > unqualBase.length) {\n const exists =\n candidateSurface.enums[candRaw] != null ||\n candidateSurface.interfaces[candRaw] != null ||\n candidateSurface.classes[candRaw] != null ||\n candidateSurface.typeAliases[candRaw] != null;\n if (exists) return true;\n }\n\n return false;\n },\n};\n\n// ---------------------------------------------------------------------------\n// Extractor\n// ---------------------------------------------------------------------------\n\nexport const goExtractor: Extractor = {\n language: 'go',\n hints: goHints,\n\n async extractSnapshot(sdkPath: string): Promise<CompatSnapshot> {\n const surface = await this.extract(sdkPath);\n return apiSurfaceToSnapshot(surface);\n },\n\n async extract(sdkPath: string): Promise<ApiSurface> {\n const goFiles = walkGoFiles(sdkPath);\n if (goFiles.length === 0) {\n throw new ExtractorError(\n `No .go files found in ${sdkPath}`,\n `Ensure the --sdk-path argument points to a Go project root containing .go source files.`,\n );\n }\n\n const allStructs: GoStruct[] = [];\n const allTypes: GoTypeDecl[] = [];\n const allFuncs: GoFunc[] = [];\n const allConsts: GoConst[] = [];\n\n for (const filePath of goFiles) {\n const parsed = parseGoFile(filePath, sdkPath);\n allStructs.push(...parsed.structs);\n allTypes.push(...parsed.types);\n allFuncs.push(...parsed.funcs);\n allConsts.push(...parsed.consts);\n }\n\n const { classes, interfaces, typeAliases, enums, exports } = buildSurface(\n allStructs,\n allTypes,\n allFuncs,\n allConsts,\n );\n\n return {\n language: 'go',\n extractedFrom: sdkPath,\n extractedAt: new Date().toISOString(),\n classes,\n interfaces,\n typeAliases,\n enums,\n exports,\n };\n },\n};\n","/**\n * Rust source parser — tree-sitter-based extraction of structs, enums,\n * impl blocks, traits, type aliases, and functions from Rust source files.\n */\n\nimport { readFileSync, readdirSync, statSync } from 'node:fs';\nimport { join, relative } from 'node:path';\nimport Parser from 'tree-sitter';\nimport RustLang from 'tree-sitter-rust';\nimport type { SyntaxNode } from 'tree-sitter';\nimport { safeParse } from '../../utils/tree-sitter.js';\n\n// ---------------------------------------------------------------------------\n// Internal types\n// ---------------------------------------------------------------------------\n\nexport interface RustStructField {\n name: string;\n type: string;\n serdeRename?: string;\n optional: boolean;\n}\n\nexport interface RustStruct {\n name: string;\n fields: RustStructField[];\n sourceFile: string;\n}\n\nexport interface RustEnum {\n name: string;\n variants: RustEnumVariant[];\n sourceFile: string;\n}\n\nexport interface RustEnumVariant {\n name: string;\n serdeRename?: string;\n}\n\nexport interface RustFunc {\n receiverType: string | null;\n name: string;\n params: { name: string; type: string }[];\n returnType: string;\n isAsync: boolean;\n sourceFile: string;\n}\n\nexport interface RustTypeAlias {\n name: string;\n underlyingType: string;\n sourceFile: string;\n}\n\nexport interface RustTrait {\n name: string;\n methods: RustFunc[];\n sourceFile: string;\n}\n\n// ---------------------------------------------------------------------------\n// Shared parser instance\n// ---------------------------------------------------------------------------\n\nconst rustParser = new Parser();\nrustParser.setLanguage(RustLang);\n\n// ---------------------------------------------------------------------------\n// File walker\n// ---------------------------------------------------------------------------\n\nexport function walkRustFiles(dir: string): string[] {\n const results: string[] = [];\n let entries: string[];\n try {\n entries = readdirSync(dir);\n } catch {\n return results;\n }\n for (const entry of entries) {\n const fullPath = join(dir, entry);\n let stat;\n try {\n stat = statSync(fullPath);\n } catch {\n continue;\n }\n if (stat.isDirectory()) {\n if (entry.startsWith('.') || entry === 'target' || entry === 'benches' || entry === 'examples') continue;\n results.push(...walkRustFiles(fullPath));\n } else if (entry.endsWith('.rs') && !entry.endsWith('_test.rs')) {\n results.push(fullPath);\n }\n }\n return results.sort();\n}\n\n// ---------------------------------------------------------------------------\n// Serde attribute helpers\n// ---------------------------------------------------------------------------\n\n/** Extract the serde rename value from an attribute_item preceding a node. */\nfunction extractSerdeRename(attributeNode: SyntaxNode): string | null {\n const attr = attributeNode.namedChildren.find((c) => c.type === 'attribute');\n if (!attr) return null;\n\n const ident = attr.namedChildren.find((c) => c.type === 'identifier');\n if (!ident || ident.text !== 'serde') return null;\n\n const tokenTree = attr.namedChildren.find((c) => c.type === 'token_tree');\n if (!tokenTree) return null;\n\n const renameIdent = tokenTree.namedChildren.find((c) => c.type === 'identifier' && c.text === 'rename');\n if (!renameIdent) return null;\n\n const strLit = tokenTree.namedChildren.find((c) => c.type === 'string_literal');\n if (!strLit) return null;\n\n const content = strLit.namedChildren.find((c) => c.type === 'string_content');\n return content ? content.text : null;\n}\n\n/** Check if a node is preceded by a serde(skip) or serde(skip_serializing) attribute. */\nfunction hasSerdeSkip(attributeNode: SyntaxNode): boolean {\n const attr = attributeNode.namedChildren.find((c) => c.type === 'attribute');\n if (!attr) return false;\n\n const ident = attr.namedChildren.find((c) => c.type === 'identifier');\n if (!ident || ident.text !== 'serde') return false;\n\n const tokenTree = attr.namedChildren.find((c) => c.type === 'token_tree');\n if (!tokenTree) return false;\n\n return tokenTree.namedChildren.some(\n (c) => c.type === 'identifier' && (c.text === 'skip' || c.text === 'skip_serializing'),\n );\n}\n\n/** Check if a type is Option<T> and return the inner type. */\nfunction isOptionType(typeText: string): boolean {\n return typeText.startsWith('Option<') && typeText.endsWith('>');\n}\n\n/** Check if a node has `pub` visibility. */\nfunction isPublic(node: SyntaxNode): boolean {\n return node.namedChildren.some((c) => c.type === 'visibility_modifier');\n}\n\n// ---------------------------------------------------------------------------\n// Struct extraction\n// ---------------------------------------------------------------------------\n\nfunction parseStructFields(bodyNode: SyntaxNode): RustStructField[] {\n const fields: RustStructField[] = [];\n let pendingAttr: SyntaxNode | null = null;\n\n for (const child of bodyNode.namedChildren) {\n if (child.type === 'attribute_item') {\n pendingAttr = child;\n continue;\n }\n\n if (child.type === 'field_declaration') {\n // Skip non-pub fields\n if (!isPublic(child)) {\n pendingAttr = null;\n continue;\n }\n\n // Skip serde(skip) fields\n if (pendingAttr && hasSerdeSkip(pendingAttr)) {\n pendingAttr = null;\n continue;\n }\n\n const nameNode = child.namedChildren.find((c) => c.type === 'field_identifier');\n const typeNode = child.childForFieldName('type');\n if (!nameNode || !typeNode) {\n pendingAttr = null;\n continue;\n }\n\n const fieldName = nameNode.text;\n const fieldType = typeNode.text;\n const serdeRename = pendingAttr ? extractSerdeRename(pendingAttr) : null;\n\n fields.push({\n name: fieldName,\n type: fieldType,\n serdeRename: serdeRename || undefined,\n optional: isOptionType(fieldType),\n });\n\n pendingAttr = null;\n } else {\n pendingAttr = null;\n }\n }\n return fields;\n}\n\nexport function parseStructs(tree: Parser.Tree, sourceFile: string): RustStruct[] {\n const structs: RustStruct[] = [];\n\n for (const node of tree.rootNode.descendantsOfType('struct_item')) {\n if (!isPublic(node)) continue;\n\n const nameNode = node.childForFieldName('name');\n if (!nameNode) continue;\n\n const bodyNode = node.childForFieldName('body');\n if (!bodyNode || bodyNode.type !== 'field_declaration_list') {\n // Tuple struct or unit struct — no named fields\n structs.push({ name: nameNode.text, fields: [], sourceFile });\n continue;\n }\n\n structs.push({ name: nameNode.text, fields: parseStructFields(bodyNode), sourceFile });\n }\n\n return structs;\n}\n\n// ---------------------------------------------------------------------------\n// Enum extraction\n// ---------------------------------------------------------------------------\n\nexport function parseEnums(tree: Parser.Tree, sourceFile: string): RustEnum[] {\n const enums: RustEnum[] = [];\n\n for (const node of tree.rootNode.descendantsOfType('enum_item')) {\n if (!isPublic(node)) continue;\n\n const nameNode = node.childForFieldName('name');\n if (!nameNode) continue;\n\n const bodyNode = node.childForFieldName('body');\n if (!bodyNode) continue;\n\n const variants: RustEnumVariant[] = [];\n let pendingAttr: SyntaxNode | null = null;\n\n for (const child of bodyNode.namedChildren) {\n if (child.type === 'attribute_item') {\n pendingAttr = child;\n continue;\n }\n if (child.type === 'enum_variant') {\n const variantName = child.childForFieldName('name');\n if (variantName) {\n const serdeRename = pendingAttr ? extractSerdeRename(pendingAttr) : null;\n variants.push({ name: variantName.text, serdeRename: serdeRename || undefined });\n }\n pendingAttr = null;\n } else {\n pendingAttr = null;\n }\n }\n\n if (variants.length > 0) {\n enums.push({ name: nameNode.text, variants, sourceFile });\n }\n }\n\n return enums;\n}\n\n// ---------------------------------------------------------------------------\n// Impl & function extraction\n// ---------------------------------------------------------------------------\n\nfunction parseParams(paramsNode: SyntaxNode): { name: string; type: string }[] {\n const params: { name: string; type: string }[] = [];\n\n for (const child of paramsNode.namedChildren) {\n if (child.type === 'self_parameter') continue; // skip &self, &mut self\n\n if (child.type === 'parameter') {\n const patternNode = child.childForFieldName('pattern');\n const typeNode = child.childForFieldName('type');\n if (patternNode && typeNode) {\n params.push({ name: patternNode.text, type: typeNode.text });\n }\n }\n }\n\n return params;\n}\n\nfunction extractReturnType(funcNode: SyntaxNode): string {\n const retNode = funcNode.childForFieldName('return_type');\n if (!retNode) return '()';\n return retNode.text;\n}\n\nfunction isAsyncFunc(funcNode: SyntaxNode): boolean {\n return funcNode.namedChildren.some((c) => c.type === 'function_modifiers' && c.text.includes('async'));\n}\n\nexport function parseImplBlocks(tree: Parser.Tree, sourceFile: string): RustFunc[] {\n const funcs: RustFunc[] = [];\n\n for (const implNode of tree.rootNode.descendantsOfType('impl_item')) {\n const typeNode = implNode.childForFieldName('type');\n if (!typeNode) continue;\n const receiverType = typeNode.text;\n\n const bodyNode = implNode.childForFieldName('body');\n if (!bodyNode) continue;\n\n for (const child of bodyNode.namedChildren) {\n if (child.type !== 'function_item') continue;\n if (!isPublic(child)) continue;\n\n const nameNode = child.childForFieldName('name');\n if (!nameNode) continue;\n\n const paramsNode = child.childForFieldName('parameters');\n\n funcs.push({\n receiverType,\n name: nameNode.text,\n params: paramsNode ? parseParams(paramsNode) : [],\n returnType: extractReturnType(child),\n isAsync: isAsyncFunc(child),\n sourceFile,\n });\n }\n }\n\n return funcs;\n}\n\n// ---------------------------------------------------------------------------\n// Trait extraction\n// ---------------------------------------------------------------------------\n\nexport function parseTraits(tree: Parser.Tree, sourceFile: string): RustTrait[] {\n const traits: RustTrait[] = [];\n\n for (const traitNode of tree.rootNode.descendantsOfType('trait_item')) {\n if (!isPublic(traitNode)) continue;\n\n const nameNode = traitNode.childForFieldName('name');\n if (!nameNode) continue;\n\n const bodyNode = traitNode.childForFieldName('body');\n if (!bodyNode) continue;\n\n const methods: RustFunc[] = [];\n\n for (const child of bodyNode.namedChildren) {\n // Trait methods appear as function_signature_item (no body)\n if (child.type !== 'function_signature_item' && child.type !== 'function_item') continue;\n\n const methodName = child.childForFieldName('name');\n if (!methodName) continue;\n\n const paramsNode = child.childForFieldName('parameters');\n\n methods.push({\n receiverType: null,\n name: methodName.text,\n params: paramsNode ? parseParams(paramsNode) : [],\n returnType: extractReturnType(child),\n isAsync: isAsyncFunc(child),\n sourceFile,\n });\n }\n\n if (methods.length > 0) {\n traits.push({ name: nameNode.text, methods, sourceFile });\n }\n }\n\n return traits;\n}\n\n// ---------------------------------------------------------------------------\n// Type alias extraction\n// ---------------------------------------------------------------------------\n\nexport function parseTypeAliases(tree: Parser.Tree, sourceFile: string): RustTypeAlias[] {\n const aliases: RustTypeAlias[] = [];\n\n for (const node of tree.rootNode.descendantsOfType('type_item')) {\n if (!isPublic(node)) continue;\n\n const nameNode = node.childForFieldName('name');\n const typeNode = node.childForFieldName('type');\n if (!nameNode || !typeNode) continue;\n\n aliases.push({ name: nameNode.text, underlyingType: typeNode.text, sourceFile });\n }\n\n return aliases;\n}\n\n// ---------------------------------------------------------------------------\n// Full file parser\n// ---------------------------------------------------------------------------\n\nexport interface ParsedRustFile {\n structs: RustStruct[];\n enums: RustEnum[];\n funcs: RustFunc[];\n traits: RustTrait[];\n typeAliases: RustTypeAlias[];\n}\n\nexport function parseRustFile(filePath: string, sdkPath: string): ParsedRustFile {\n const source = readFileSync(filePath, 'utf-8');\n const relPath = relative(sdkPath, filePath);\n const tree = safeParse(rustParser, source);\n\n return {\n structs: parseStructs(tree, relPath),\n enums: parseEnums(tree, relPath),\n funcs: parseImplBlocks(tree, relPath),\n traits: parseTraits(tree, relPath),\n typeAliases: parseTypeAliases(tree, relPath),\n };\n}\n","/**\n * Rust surface builder — transforms parsed Rust symbols into an ApiSurface.\n *\n * Mapping:\n * pub struct + impl methods → ApiClass\n * pub struct (no methods) → ApiInterface (data-only)\n * pub enum → ApiEnum (serde renames as member values)\n * pub type X = Y → ApiTypeAlias\n * pub trait → ApiClass (trait methods as API surface)\n */\n\nimport type {\n ApiClass,\n ApiMethod,\n ApiParam,\n ApiProperty,\n ApiInterface,\n ApiField,\n ApiTypeAlias,\n ApiEnum,\n} from '../types.js';\nimport type { RustStruct, RustEnum, RustFunc, RustTrait, RustTypeAlias as RustTypeAliasType } from './rust-parser.js';\nimport { sortRecord, ExportCollector } from './shared.js';\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction rustTypeToString(t: string): string {\n return t;\n}\n\n/** Strip Result<T, E> to just T. */\nfunction unwrapResultType(returnType: string): string {\n const match = returnType.match(/^Result\\s*<\\s*(.+)\\s*,\\s*.+\\s*>$/);\n if (match) return match[1].trim();\n return returnType;\n}\n\n// ---------------------------------------------------------------------------\n// Surface builder\n// ---------------------------------------------------------------------------\n\nexport function buildSurface(\n allStructs: RustStruct[],\n allEnums: RustEnum[],\n allFuncs: RustFunc[],\n allTraits: RustTrait[],\n allTypeAliases: RustTypeAliasType[],\n): {\n classes: Record<string, ApiClass>;\n interfaces: Record<string, ApiInterface>;\n typeAliases: Record<string, ApiTypeAlias>;\n enums: Record<string, ApiEnum>;\n exports: Record<string, string[]>;\n} {\n const classes: Record<string, ApiClass> = {};\n const interfaces: Record<string, ApiInterface> = {};\n const typeAliases: Record<string, ApiTypeAlias> = {};\n const enums: Record<string, ApiEnum> = {};\n\n // Group impl methods by receiver type\n const methodsByReceiver = new Map<string, RustFunc[]>();\n for (const fn of allFuncs) {\n if (!fn.receiverType) continue;\n if (!methodsByReceiver.has(fn.receiverType)) methodsByReceiver.set(fn.receiverType, []);\n methodsByReceiver.get(fn.receiverType)!.push(fn);\n }\n\n // Process structs\n for (const s of allStructs) {\n const methods = methodsByReceiver.get(s.name);\n\n if (methods && methods.length > 0) {\n // Struct with impl methods → ApiClass\n const apiMethods: Record<string, ApiMethod[]> = {};\n const properties: Record<string, ApiProperty> = {};\n\n for (const field of s.fields) {\n const fieldName = field.serdeRename || field.name;\n properties[fieldName] = {\n name: fieldName,\n type: rustTypeToString(field.type),\n readonly: false,\n };\n }\n\n for (const fn of methods) {\n const params: ApiParam[] = fn.params.map((p) => ({\n name: p.name,\n type: rustTypeToString(p.type),\n optional: p.type.startsWith('Option<'),\n passingStyle: 'positional' as const,\n }));\n const returnType = unwrapResultType(fn.returnType);\n if (!apiMethods[fn.name]) apiMethods[fn.name] = [];\n apiMethods[fn.name].push({\n name: fn.name,\n params,\n returnType: rustTypeToString(returnType),\n async: fn.isAsync,\n });\n }\n\n classes[s.name] = {\n name: s.name,\n sourceFile: s.sourceFile,\n methods: sortRecord(apiMethods),\n properties: sortRecord(properties),\n constructorParams: [],\n };\n } else {\n // Struct without methods → ApiInterface\n const fields: Record<string, ApiField> = {};\n for (const field of s.fields) {\n const fieldName = field.serdeRename || field.name;\n fields[fieldName] = {\n name: fieldName,\n type: rustTypeToString(field.type),\n optional: field.optional,\n };\n }\n interfaces[s.name] = {\n name: s.name,\n sourceFile: s.sourceFile,\n fields: sortRecord(fields),\n extends: [],\n };\n }\n }\n\n // Process enums\n for (const e of allEnums) {\n const members: Record<string, string | number> = {};\n for (const v of e.variants) {\n members[v.name] = v.serdeRename || v.name;\n }\n enums[e.name] = { name: e.name, sourceFile: e.sourceFile, members: sortRecord(members) };\n }\n\n // Process type aliases\n for (const ta of allTypeAliases) {\n typeAliases[ta.name] = { name: ta.name, sourceFile: ta.sourceFile, value: rustTypeToString(ta.underlyingType) };\n }\n\n // Process traits → ApiClass (trait methods define the API contract)\n for (const trait of allTraits) {\n const apiMethods: Record<string, ApiMethod[]> = {};\n\n for (const fn of trait.methods) {\n const params: ApiParam[] = fn.params.map((p) => ({\n name: p.name,\n type: rustTypeToString(p.type),\n optional: p.type.startsWith('Option<'),\n }));\n const returnType = unwrapResultType(fn.returnType);\n if (!apiMethods[fn.name]) apiMethods[fn.name] = [];\n apiMethods[fn.name].push({\n name: fn.name,\n params,\n returnType: rustTypeToString(returnType),\n async: fn.isAsync,\n });\n }\n\n classes[trait.name] = {\n name: trait.name,\n sourceFile: trait.sourceFile,\n methods: sortRecord(apiMethods),\n properties: {},\n constructorParams: [],\n };\n }\n\n // Build export map\n const collector = new ExportCollector();\n\n for (const [name, cls] of Object.entries(classes)) if (cls.sourceFile) collector.add(cls.sourceFile, name);\n for (const [name, iface] of Object.entries(interfaces)) if (iface.sourceFile) collector.add(iface.sourceFile, name);\n for (const [name, ta] of Object.entries(typeAliases)) if (ta.sourceFile) collector.add(ta.sourceFile, name);\n for (const [name, en] of Object.entries(enums)) if (en.sourceFile) collector.add(en.sourceFile, name);\n\n const exports = collector.toRecord();\n\n return {\n classes: sortRecord(classes),\n interfaces: sortRecord(interfaces),\n typeAliases: sortRecord(typeAliases),\n enums: sortRecord(enums),\n exports: sortRecord(exports),\n };\n}\n","/**\n * Rust API surface extractor.\n *\n * Walks `.rs` files under `src/`, parses pub structs, enums, impl blocks,\n * traits, and type aliases, then builds an ApiSurface.\n *\n * Parser: `rust-parser.ts` — tree-sitter-based Rust source analysis\n * Surface: `rust-surface.ts` — ApiSurface construction\n */\n\nimport { ExtractorError } from '../../errors.js';\nimport type { Extractor, ApiSurface, LanguageHints } from '../types.js';\nimport type { CompatSnapshot } from '../ir.js';\nimport { apiSurfaceToSnapshot } from '../ir.js';\nimport { defaultIsNullableOnlyDifference } from '../language-hints.js';\nimport { walkRustFiles, parseRustFile } from './rust-parser.js';\nimport { buildSurface } from './rust-surface.js';\nimport type { RustStruct, RustEnum, RustFunc, RustTrait, RustTypeAlias } from './rust-parser.js';\n\n// ---------------------------------------------------------------------------\n// Language hints\n// ---------------------------------------------------------------------------\n\nconst rustHints: LanguageHints = {\n stripNullable(type: string): string | null {\n const match = type.match(/^Option<(.+)>$/);\n return match ? match[1] : null;\n },\n isNullableOnlyDifference(a: string, b: string): boolean {\n return defaultIsNullableOnlyDifference(this, a, b);\n },\n isUnionReorder(_a: string, _b: string): boolean {\n return false; // Rust doesn't have union types in the TS sense\n },\n isGenericTypeParam(type: string): boolean {\n // Single uppercase letter or T-prefixed: T, U, V, TResult\n return /^[A-Z]$/.test(type) || /^T[A-Z][a-zA-Z]*$/.test(type);\n },\n isExtractionArtifact(type: string): boolean {\n return type === 'serde_json::Value' || type === 'Box<dyn std::error::Error>';\n },\n tolerateCategoryMismatch: false,\n extractReturnTypeName(returnType: string): string | null {\n // Unwrap Result<T, E> → T, Vec<T> → T, Option<T> → T\n let inner = returnType;\n const resultMatch = inner.match(/^Result\\s*<\\s*(.+)\\s*,\\s*.+\\s*>$/);\n if (resultMatch) inner = resultMatch[1].trim();\n const vecMatch = inner.match(/^Vec\\s*<\\s*(.+)\\s*>$/);\n if (vecMatch) inner = vecMatch[1].trim();\n const optMatch = inner.match(/^Option\\s*<\\s*(.+)\\s*>$/);\n if (optMatch) inner = optMatch[1].trim();\n // Strip references\n inner = inner.replace(/^&(?:mut\\s+)?(?:'[a-z]+\\s+)?/, '');\n if (['()', 'String', 'str', 'bool', 'i32', 'i64', 'u32', 'u64', 'f32', 'f64', 'usize'].includes(inner)) {\n return null;\n }\n return inner;\n },\n extractParamTypeName(paramType: string): string | null {\n let inner = paramType.replace(/^&(?:mut\\s+)?(?:'[a-z]+\\s+)?/, '');\n if (['String', '&str', 'str', 'bool', 'i32', 'i64', 'u32', 'u64', 'f32', 'f64', 'usize'].includes(inner)) {\n return null;\n }\n return inner;\n },\n propertyMatchesClass(propertyName: string, className: string): boolean {\n // snake_case property vs PascalCase class\n const normalized = propertyName.replace(/_/g, '').toLowerCase();\n return normalized === className.toLowerCase();\n },\n derivedModelNames(modelName: string): string[] {\n return [`${modelName}Response`];\n },\n};\n\n// ---------------------------------------------------------------------------\n// Extractor\n// ---------------------------------------------------------------------------\n\nexport const rustExtractor: Extractor = {\n language: 'rust',\n hints: rustHints,\n\n async extractSnapshot(sdkPath: string): Promise<CompatSnapshot> {\n const surface = await this.extract(sdkPath);\n return apiSurfaceToSnapshot(surface);\n },\n\n async extract(sdkPath: string): Promise<ApiSurface> {\n const rsFiles = walkRustFiles(sdkPath);\n if (rsFiles.length === 0) {\n throw new ExtractorError(\n `No .rs files found in ${sdkPath}`,\n `Ensure the --sdk-path argument points to a Rust project root containing .rs source files.`,\n );\n }\n\n const allStructs: RustStruct[] = [];\n const allEnums: RustEnum[] = [];\n const allFuncs: RustFunc[] = [];\n const allTraits: RustTrait[] = [];\n const allTypeAliases: RustTypeAlias[] = [];\n\n for (const filePath of rsFiles) {\n const parsed = parseRustFile(filePath, sdkPath);\n allStructs.push(...parsed.structs);\n allEnums.push(...parsed.enums);\n allFuncs.push(...parsed.funcs);\n allTraits.push(...parsed.traits);\n allTypeAliases.push(...parsed.typeAliases);\n }\n\n const { classes, interfaces, typeAliases, enums, exports } = buildSurface(\n allStructs,\n allEnums,\n allFuncs,\n allTraits,\n allTypeAliases,\n );\n\n return {\n language: 'rust',\n extractedFrom: sdkPath,\n extractedAt: new Date().toISOString(),\n classes,\n interfaces,\n typeAliases,\n enums,\n exports,\n };\n },\n};\n","/**\n * Kotlin source parser — regex-based extraction of classes, data classes,\n * enum classes, functions, and type aliases from Kotlin source files.\n */\n\nimport { readFileSync, readdirSync, statSync } from 'node:fs';\nimport { join, relative } from 'node:path';\n\n// ---------------------------------------------------------------------------\n// Internal types\n// ---------------------------------------------------------------------------\n\nexport interface KotlinField {\n name: string;\n type: string;\n jsonName?: string;\n optional: boolean;\n}\n\nexport interface KotlinDataClass {\n name: string;\n fields: KotlinField[];\n sourceFile: string;\n packageName: string;\n}\n\nexport interface KotlinClass {\n name: string;\n constructorParams: { name: string; type: string }[];\n methods: KotlinMethod[];\n sourceFile: string;\n packageName: string;\n}\n\nexport interface KotlinMethod {\n name: string;\n params: { name: string; type: string; optional: boolean }[];\n returnType: string;\n visibility: string;\n}\n\nexport interface KotlinEnum {\n name: string;\n members: Record<string, string>;\n sourceFile: string;\n packageName: string;\n}\n\nexport interface KotlinTypeAlias {\n name: string;\n value: string;\n sourceFile: string;\n packageName: string;\n}\n\nexport interface ParsedKotlinFile {\n dataClasses: KotlinDataClass[];\n classes: KotlinClass[];\n enums: KotlinEnum[];\n typeAliases: KotlinTypeAlias[];\n}\n\n// ---------------------------------------------------------------------------\n// File walker\n// ---------------------------------------------------------------------------\n\nexport function walkKotlinFiles(dir: string): string[] {\n const results: string[] = [];\n let entries: string[];\n try {\n entries = readdirSync(dir);\n } catch {\n return results;\n }\n for (const entry of entries) {\n const fullPath = join(dir, entry);\n let stat;\n try {\n stat = statSync(fullPath);\n } catch {\n continue;\n }\n if (stat.isDirectory()) {\n if (entry.startsWith('.') || entry === 'build' || entry === 'test' || entry === 'androidTest') continue;\n results.push(...walkKotlinFiles(fullPath));\n } else if (entry.endsWith('.kt') && !entry.endsWith('Test.kt')) {\n results.push(fullPath);\n }\n }\n return results.sort();\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/** Extract the package name from a Kotlin source file. */\nfunction extractPackageName(source: string): string {\n const match = source.match(/^package\\s+([\\w.]+)/m);\n return match ? match[1] : 'unknown';\n}\n\n/** Strip single-line and block comments from source to avoid false matches. */\nfunction stripComments(source: string): string {\n // Remove block comments\n let result = source.replace(/\\/\\*[\\s\\S]*?\\*\\//g, '');\n // Remove single-line comments\n result = result.replace(/\\/\\/[^\\n]*/g, '');\n return result;\n}\n\n/**\n * Extract the @JsonProperty(\"name\") annotation value before a parameter.\n * Looks for the pattern immediately preceding the parameter declaration.\n */\nfunction extractJsonPropertyName(text: string): string | null {\n const match = text.match(/@JsonProperty\\(\"([^\"]+)\"\\)/);\n return match ? match[1] : null;\n}\n\n/**\n * Parse constructor parameters from a data class or class declaration.\n * Handles multi-line parameter lists with annotations.\n */\nfunction parseConstructorParams(paramsBlock: string): KotlinField[] {\n const fields: KotlinField[] = [];\n\n // Split by top-level commas (not nested in angle brackets or parens)\n const params = splitTopLevelCommas(paramsBlock);\n\n for (const param of params) {\n const trimmed = param.trim();\n if (!trimmed) continue;\n\n // Extract JsonProperty annotation if present\n const jsonName = extractJsonPropertyName(trimmed);\n\n // Match val/var name: Type pattern, possibly with default value\n const paramMatch = trimmed.match(\n /(?:(?:override|private|protected)\\s+)?(?:val|var)\\s+(\\w+)\\s*:\\s*([^=,]+?)(?:\\s*=\\s*(.+))?$/m,\n );\n if (!paramMatch) continue;\n\n const name = paramMatch[1];\n const rawType = paramMatch[2].trim();\n const hasDefault = paramMatch[3] !== undefined;\n\n // Check if the type is nullable (ends with ?)\n const isNullable = rawType.endsWith('?');\n const type = rawType;\n\n fields.push({\n name,\n type,\n jsonName: jsonName || undefined,\n optional: isNullable || hasDefault,\n });\n }\n\n return fields;\n}\n\n/** Split a string by top-level commas, ignoring commas inside angle brackets, parens, or strings. */\nfunction splitTopLevelCommas(text: string): string[] {\n const result: string[] = [];\n let depth = 0;\n let current = '';\n let inString = false;\n let stringChar = '';\n\n for (let i = 0; i < text.length; i++) {\n const ch = text[i];\n\n if (inString) {\n current += ch;\n if (ch === stringChar && text[i - 1] !== '\\\\') {\n inString = false;\n }\n continue;\n }\n\n if (ch === '\"' || ch === \"'\") {\n inString = true;\n stringChar = ch;\n current += ch;\n continue;\n }\n\n if (ch === '<' || ch === '(' || ch === '[') {\n depth++;\n current += ch;\n } else if (ch === '>' || ch === ')' || ch === ']') {\n depth--;\n current += ch;\n } else if (ch === ',' && depth === 0) {\n result.push(current);\n current = '';\n } else {\n current += ch;\n }\n }\n\n if (current.trim()) {\n result.push(current);\n }\n\n return result;\n}\n\n// ---------------------------------------------------------------------------\n// Enum extraction\n// ---------------------------------------------------------------------------\n\nfunction parseEnumClass(source: string, sourceFile: string, packageName: string): KotlinEnum[] {\n const enums: KotlinEnum[] = [];\n\n // Match: enum class Name(@JsonValue val value: Type) { Member1(\"val1\"), Member2(\"val2\") }\n const enumRegex = /enum\\s+class\\s+(\\w+)(?:\\([^)]*\\))?\\s*\\{([^}]*)\\}/g;\n let match;\n while ((match = enumRegex.exec(source)) !== null) {\n const name = match[1];\n const body = match[2];\n\n const members: Record<string, string> = {};\n\n // Match enum members: MemberName(\"value\") or MemberName\n const memberRegex = /(\\w+)\\s*(?:\\(\"([^\"]*)\"\\))?/g;\n let memberMatch;\n while ((memberMatch = memberRegex.exec(body)) !== null) {\n const memberName = memberMatch[1];\n // Skip keywords that might match\n if (['val', 'var', 'fun', 'override', 'companion', 'object'].includes(memberName)) continue;\n const memberValue = memberMatch[2] !== undefined ? memberMatch[2] : memberName;\n members[memberName] = memberValue;\n }\n\n if (Object.keys(members).length > 0) {\n enums.push({ name, members, sourceFile, packageName });\n }\n }\n\n return enums;\n}\n\n// ---------------------------------------------------------------------------\n// Data class extraction\n// ---------------------------------------------------------------------------\n\nfunction parseDataClasses(source: string, sourceFile: string, packageName: string): KotlinDataClass[] {\n const dataClasses: KotlinDataClass[] = [];\n\n // Match: data class Name(params) or data class Name @Annotation constructor(params)\n // Use a regex that captures the opening paren, then find the matching close\n const dataClassStartRegex = /data\\s+class\\s+(\\w+)\\s*(?:@\\w+(?:\\([^)]*\\))?\\s+)?(?:constructor\\s*)?\\(/g;\n let match;\n while ((match = dataClassStartRegex.exec(source)) !== null) {\n const name = match[1];\n const startIdx = match.index + match[0].length;\n\n // Find matching closing paren\n let depth = 1;\n let idx = startIdx;\n while (idx < source.length && depth > 0) {\n if (source[idx] === '(') depth++;\n else if (source[idx] === ')') depth--;\n idx++;\n }\n\n const paramsBlock = source.slice(startIdx, idx - 1);\n const fields = parseConstructorParams(paramsBlock);\n\n dataClasses.push({ name, fields, sourceFile, packageName });\n }\n\n return dataClasses;\n}\n\n// ---------------------------------------------------------------------------\n// Class extraction (non-data classes)\n// ---------------------------------------------------------------------------\n\nfunction parseClasses(source: string, sourceFile: string, packageName: string): KotlinClass[] {\n const classes: KotlinClass[] = [];\n\n // Match non-data, non-enum classes: class Name(params) { body }\n // Skip abstract, sealed, and open classes that aren't services\n const classStartRegex =\n /(?<!data\\s)(?<!enum\\s)(?<!abstract\\s)(?<!sealed\\s)(?:open\\s+)?class\\s+(\\w+)\\s*(?:\\(([^)]*)\\))?\\s*(?::\\s*[^{]+)?\\s*\\{/g;\n let match;\n while ((match = classStartRegex.exec(source)) !== null) {\n const name = match[1];\n const constructorBlock = match[2] || '';\n\n // Find matching closing brace for the class body\n const braceStart = source.indexOf('{', match.index + match[0].length - 1);\n let depth = 1;\n let idx = braceStart + 1;\n while (idx < source.length && depth > 0) {\n if (source[idx] === '{') depth++;\n else if (source[idx] === '}') depth--;\n idx++;\n }\n\n const classBody = source.slice(braceStart + 1, idx - 1);\n\n // Parse constructor params\n const constructorParams: { name: string; type: string }[] = [];\n if (constructorBlock.trim()) {\n const params = splitTopLevelCommas(constructorBlock);\n for (const param of params) {\n const trimmed = param.trim();\n const paramMatch = trimmed.match(/(?:(?:private|protected)\\s+)?(?:val|var)\\s+(\\w+)\\s*:\\s*(.+)/);\n if (paramMatch) {\n constructorParams.push({ name: paramMatch[1], type: paramMatch[2].trim() });\n }\n }\n }\n\n // Parse methods\n const methods = parseMethods(classBody);\n\n if (methods.length > 0) {\n classes.push({ name, constructorParams, methods, sourceFile, packageName });\n }\n }\n\n return classes;\n}\n\n/** Parse method declarations from a class body. */\nfunction parseMethods(classBody: string): KotlinMethod[] {\n const methods: KotlinMethod[] = [];\n\n // Match: fun methodName(params): ReturnType or fun methodName(params)\n // Handle suspend fun, private fun, etc.\n const methodRegex =\n /(private|protected|internal|public)?\\s*(?:suspend\\s+)?fun\\s+(\\w+)\\s*\\(([^)]*)\\)\\s*(?::\\s*([^\\s{]+))?/g;\n let match;\n while ((match = methodRegex.exec(classBody)) !== null) {\n const visibility = match[1] || 'public';\n const name = match[2];\n const paramsStr = match[3];\n const returnType = match[4] || 'Unit';\n\n // Skip private/protected methods\n if (visibility === 'private' || visibility === 'protected') continue;\n\n const params: { name: string; type: string; optional: boolean }[] = [];\n if (paramsStr.trim()) {\n const paramParts = splitTopLevelCommas(paramsStr);\n for (const part of paramParts) {\n const trimmed = part.trim();\n const paramMatch = trimmed.match(/(\\w+)\\s*:\\s*([^=]+?)(?:\\s*=\\s*(.+))?$/);\n if (paramMatch) {\n const paramType = paramMatch[2].trim();\n const hasDefault = paramMatch[3] !== undefined;\n params.push({\n name: paramMatch[1],\n type: paramType,\n optional: paramType.endsWith('?') || hasDefault,\n });\n }\n }\n }\n\n methods.push({ name, params, returnType, visibility });\n }\n\n return methods;\n}\n\n// ---------------------------------------------------------------------------\n// Type alias extraction\n// ---------------------------------------------------------------------------\n\nfunction parseTypeAliases(source: string, sourceFile: string, packageName: string): KotlinTypeAlias[] {\n const aliases: KotlinTypeAlias[] = [];\n\n const aliasRegex = /typealias\\s+(\\w+)\\s*=\\s*([^\\n]+)/g;\n let match;\n while ((match = aliasRegex.exec(source)) !== null) {\n aliases.push({\n name: match[1],\n value: match[2].trim(),\n sourceFile,\n packageName,\n });\n }\n\n return aliases;\n}\n\n// ---------------------------------------------------------------------------\n// Full file parser\n// ---------------------------------------------------------------------------\n\n/** Parse a single Kotlin source file and return all extracted symbols. */\nexport function parseKotlinFile(filePath: string, sdkPath: string): ParsedKotlinFile {\n const source = readFileSync(filePath, 'utf-8');\n const relPath = relative(sdkPath, filePath);\n const cleaned = stripComments(source);\n const packageName = extractPackageName(cleaned);\n\n return {\n dataClasses: parseDataClasses(cleaned, relPath, packageName),\n classes: parseClasses(cleaned, relPath, packageName),\n enums: parseEnumClass(cleaned, relPath, packageName),\n typeAliases: parseTypeAliases(cleaned, relPath, packageName),\n };\n}\n","/**\n * Kotlin surface builder — transforms parsed Kotlin symbols into an ApiSurface.\n */\n\nimport type {\n ApiClass,\n ApiMethod,\n ApiParam,\n ApiProperty,\n ApiInterface,\n ApiField,\n ApiTypeAlias,\n ApiEnum,\n} from '../types.js';\nimport type { KotlinDataClass, KotlinClass, KotlinEnum, KotlinTypeAlias } from './kotlin-parser.js';\nimport { sortRecord, ExportCollector } from './shared.js';\n\n// ---------------------------------------------------------------------------\n// Surface builder\n// ---------------------------------------------------------------------------\n\nexport function buildSurface(\n allDataClasses: KotlinDataClass[],\n allClasses: KotlinClass[],\n allEnums: KotlinEnum[],\n allTypeAliases: KotlinTypeAlias[],\n): {\n classes: Record<string, ApiClass>;\n interfaces: Record<string, ApiInterface>;\n typeAliases: Record<string, ApiTypeAlias>;\n enums: Record<string, ApiEnum>;\n exports: Record<string, string[]>;\n} {\n const classes: Record<string, ApiClass> = {};\n const interfaces: Record<string, ApiInterface> = {};\n const typeAliases: Record<string, ApiTypeAlias> = {};\n const enums: Record<string, ApiEnum> = {};\n\n const collector = new ExportCollector();\n\n // Process data classes as interfaces (they represent data models)\n for (const dc of allDataClasses) {\n const fields: Record<string, ApiField> = {};\n for (const field of dc.fields) {\n const fieldName = field.jsonName || field.name;\n fields[fieldName] = {\n name: fieldName,\n type: field.type,\n optional: field.optional,\n };\n }\n interfaces[dc.name] = {\n name: dc.name,\n sourceFile: dc.sourceFile,\n fields: sortRecord(fields),\n extends: [],\n };\n collector.add(dc.sourceFile, dc.name);\n }\n\n // Process classes (service classes with methods)\n for (const cls of allClasses) {\n const methods: Record<string, ApiMethod[]> = {};\n const properties: Record<string, ApiProperty> = {};\n\n for (const method of cls.methods) {\n const params: ApiParam[] = method.params.map((p) => ({\n name: p.name,\n type: p.type,\n optional: p.optional,\n passingStyle: 'named' as const,\n }));\n\n if (!methods[method.name]) methods[method.name] = [];\n methods[method.name].push({\n name: method.name,\n params,\n returnType: method.returnType,\n async: false,\n });\n }\n\n const constructorParams: ApiParam[] = cls.constructorParams.map((p) => ({\n name: p.name,\n type: p.type,\n optional: false,\n passingStyle: 'named' as const,\n }));\n\n classes[cls.name] = {\n name: cls.name,\n sourceFile: cls.sourceFile,\n methods: sortRecord(methods),\n properties: sortRecord(properties),\n constructorParams,\n };\n collector.add(cls.sourceFile, cls.name);\n }\n\n // Process enums\n for (const en of allEnums) {\n enums[en.name] = {\n name: en.name,\n sourceFile: en.sourceFile,\n members: sortRecord(en.members),\n };\n collector.add(en.sourceFile, en.name);\n }\n\n // Process type aliases\n for (const ta of allTypeAliases) {\n typeAliases[ta.name] = {\n name: ta.name,\n sourceFile: ta.sourceFile,\n value: ta.value,\n };\n collector.add(ta.sourceFile, ta.name);\n }\n\n const exports = collector.toRecord();\n\n return {\n classes: sortRecord(classes),\n interfaces: sortRecord(interfaces),\n typeAliases: sortRecord(typeAliases),\n enums: sortRecord(enums),\n exports: sortRecord(exports),\n };\n}\n","/**\n * Kotlin API surface extractor.\n *\n * Walks `.kt` files (excluding test files and build directories), parses\n * data classes, classes, enum classes, and type aliases, then builds an\n * `ApiSurface`.\n *\n * Parser: `kotlin-parser.ts` — regex-based Kotlin source analysis\n * Surface: `kotlin-surface.ts` — ApiSurface construction\n */\n\nimport { ExtractorError } from '../../errors.js';\nimport type { Extractor, ApiSurface, LanguageHints } from '../types.js';\nimport type { CompatSnapshot } from '../ir.js';\nimport { apiSurfaceToSnapshot } from '../ir.js';\nimport { defaultIsNullableOnlyDifference } from '../language-hints.js';\nimport { walkKotlinFiles, parseKotlinFile } from './kotlin-parser.js';\nimport { buildSurface } from './kotlin-surface.js';\nimport type { KotlinDataClass, KotlinClass, KotlinEnum, KotlinTypeAlias } from './kotlin-parser.js';\n\n// ---------------------------------------------------------------------------\n// Language hints\n// ---------------------------------------------------------------------------\n\nconst kotlinHints: LanguageHints = {\n stripNullable(type: string): string | null {\n if (type.endsWith('?')) return type.slice(0, -1);\n return null;\n },\n isNullableOnlyDifference(a: string, b: string): boolean {\n return defaultIsNullableOnlyDifference(this, a, b);\n },\n isUnionReorder(_a: string, _b: string): boolean {\n return false; // Kotlin doesn't have union types\n },\n isGenericTypeParam(type: string): boolean {\n return /^[A-Z]$/.test(type) || /^T[A-Z][a-zA-Z]*$/.test(type);\n },\n isExtractionArtifact(type: string): boolean {\n return type === 'Any' || type === 'Any?';\n },\n tolerateCategoryMismatch: true,\n extractReturnTypeName(returnType: string): string | null {\n let inner = returnType;\n // Unwrap nullable\n if (inner.endsWith('?')) inner = inner.slice(0, -1);\n // Unwrap List<T> → T\n const listMatch = inner.match(/^(?:List|MutableList|ArrayList)<(.+)>$/);\n if (listMatch) inner = listMatch[1];\n // Unwrap PaginatedList<T> → T\n const paginatedMatch = inner.match(/^PaginatedList<(.+)>$/);\n if (paginatedMatch) inner = paginatedMatch[1];\n // Primitives\n if (['String', 'Int', 'Long', 'Float', 'Double', 'Boolean', 'Unit', 'Void'].includes(inner)) return null;\n return inner;\n },\n extractParamTypeName(paramType: string): string | null {\n let inner = paramType;\n if (inner.endsWith('?')) inner = inner.slice(0, -1);\n if (['String', 'Int', 'Long', 'Float', 'Double', 'Boolean'].includes(inner)) return null;\n return inner;\n },\n propertyMatchesClass(propertyName: string, className: string): boolean {\n // camelCase property vs PascalCase class\n return propertyName.toLowerCase() === className.toLowerCase();\n },\n derivedModelNames(modelName: string): string[] {\n return [`${modelName}Response`];\n },\n};\n\n// ---------------------------------------------------------------------------\n// Extractor\n// ---------------------------------------------------------------------------\n\nexport const kotlinExtractor: Extractor = {\n language: 'kotlin',\n hints: kotlinHints,\n\n async extractSnapshot(sdkPath: string): Promise<CompatSnapshot> {\n const surface = await this.extract(sdkPath);\n return apiSurfaceToSnapshot(surface);\n },\n\n async extract(sdkPath: string): Promise<ApiSurface> {\n const ktFiles = walkKotlinFiles(sdkPath);\n if (ktFiles.length === 0) {\n throw new ExtractorError(\n `No .kt files found in ${sdkPath}`,\n `Ensure the --sdk-path argument points to a Kotlin project root containing .kt source files.`,\n );\n }\n\n const allDataClasses: KotlinDataClass[] = [];\n const allClasses: KotlinClass[] = [];\n const allEnums: KotlinEnum[] = [];\n const allTypeAliases: KotlinTypeAlias[] = [];\n\n for (const filePath of ktFiles) {\n const parsed = parseKotlinFile(filePath, sdkPath);\n allDataClasses.push(...parsed.dataClasses);\n allClasses.push(...parsed.classes);\n allEnums.push(...parsed.enums);\n allTypeAliases.push(...parsed.typeAliases);\n }\n\n const { classes, interfaces, typeAliases, enums, exports } = buildSurface(\n allDataClasses,\n allClasses,\n allEnums,\n allTypeAliases,\n );\n\n return {\n language: 'kotlin',\n extractedFrom: sdkPath,\n extractedAt: new Date().toISOString(),\n classes,\n interfaces,\n typeAliases,\n enums,\n exports,\n };\n },\n};\n","/**\n * C# (.NET) source parser — regex-based extraction of classes, enums,\n * properties, and methods from C# source files.\n */\n\nimport { readFileSync, readdirSync, statSync } from 'node:fs';\nimport { join, relative } from 'node:path';\n\n// ---------------------------------------------------------------------------\n// Internal types\n// ---------------------------------------------------------------------------\n\nexport interface CSharpProperty {\n name: string;\n type: string;\n jsonName?: string;\n readonly: boolean;\n}\n\nexport interface CSharpMethod {\n name: string;\n params: { name: string; type: string; optional: boolean }[];\n returnType: string;\n visibility: string;\n isAsync: boolean;\n}\n\nexport interface CSharpClass {\n name: string;\n namespace: string;\n properties: CSharpProperty[];\n methods: CSharpMethod[];\n constructorParams: { name: string; type: string }[];\n isService: boolean;\n sourceFile: string;\n}\n\nexport interface CSharpEnum {\n name: string;\n namespace: string;\n members: Record<string, string>;\n sourceFile: string;\n}\n\nexport interface ParsedCSharpFile {\n classes: CSharpClass[];\n enums: CSharpEnum[];\n}\n\n// ---------------------------------------------------------------------------\n// File walker\n// ---------------------------------------------------------------------------\n\nexport function walkCSharpFiles(dir: string): string[] {\n const results: string[] = [];\n let entries: string[];\n try {\n entries = readdirSync(dir);\n } catch {\n return results;\n }\n for (const entry of entries) {\n const fullPath = join(dir, entry);\n let stat;\n try {\n stat = statSync(fullPath);\n } catch {\n continue;\n }\n if (stat.isDirectory()) {\n if (entry.startsWith('.') || entry === 'bin' || entry === 'obj' || entry === 'test' || entry === 'tests') {\n continue;\n }\n results.push(...walkCSharpFiles(fullPath));\n } else if (entry.endsWith('.cs') && !entry.endsWith('Test.cs') && !entry.endsWith('Tests.cs')) {\n results.push(fullPath);\n }\n }\n return results.sort();\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/** Extract the namespace from a C# source file. */\nfunction extractNamespace(source: string): string {\n // File-scoped namespace (C# 10+): namespace Foo.Bar;\n const fileScopedMatch = source.match(/^namespace\\s+([\\w.]+)\\s*;/m);\n if (fileScopedMatch) return fileScopedMatch[1];\n\n // Block-scoped namespace: namespace Foo.Bar { ... }\n const blockMatch = source.match(/^namespace\\s+([\\w.]+)\\s*\\{/m);\n if (blockMatch) return blockMatch[1];\n\n return 'unknown';\n}\n\n/** Strip single-line and block comments from source. */\nfunction stripComments(source: string): string {\n let result = source.replace(/\\/\\*[\\s\\S]*?\\*\\//g, '');\n result = result.replace(/\\/\\/[^\\n]*/g, '');\n return result;\n}\n\n/** Extract [JsonProperty(\"name\")] value from text preceding a property. */\nfunction extractJsonPropertyName(text: string): string | null {\n const match = text.match(/\\[JsonProperty\\(\"([^\"]+)\"\\)\\]/);\n return match ? match[1] : null;\n}\n\n/** Extract [EnumMember(Value = \"name\")] value from text. */\nfunction extractEnumMemberValue(text: string): string | null {\n const match = text.match(/\\[EnumMember\\(Value\\s*=\\s*\"([^\"]+)\"\\)\\]/);\n return match ? match[1] : null;\n}\n\n// ---------------------------------------------------------------------------\n// Enum extraction\n// ---------------------------------------------------------------------------\n\nfunction parseEnums(source: string, sourceFile: string): CSharpEnum[] {\n const enums: CSharpEnum[] = [];\n const ns = extractNamespace(source);\n\n // Match: public enum Name { ... }\n const enumRegex = /public\\s+enum\\s+(\\w+)\\s*\\{([^}]*)\\}/g;\n let match;\n while ((match = enumRegex.exec(source)) !== null) {\n const name = match[1];\n const body = match[2];\n const members: Record<string, string> = {};\n\n // Split by commas and extract each member\n const lines = body.split(',');\n for (const line of lines) {\n const trimmed = line.trim();\n if (!trimmed) continue;\n\n const enumValue = extractEnumMemberValue(trimmed);\n const memberNameMatch = trimmed.match(/(\\w+)\\s*$/);\n if (memberNameMatch) {\n const memberName = memberNameMatch[1];\n members[memberName] = enumValue || memberName;\n }\n }\n\n if (Object.keys(members).length > 0) {\n enums.push({ name, namespace: ns, members, sourceFile });\n }\n }\n\n return enums;\n}\n\n// ---------------------------------------------------------------------------\n// Class extraction\n// ---------------------------------------------------------------------------\n\nfunction parseClasses(source: string, sourceFile: string): CSharpClass[] {\n const classes: CSharpClass[] = [];\n const ns = extractNamespace(source);\n\n // Match: public class Name { ... } — need to handle nested braces\n const classStartRegex = /public\\s+class\\s+(\\w+)(?:\\s*:\\s*[\\w.,\\s<>]+)?\\s*\\{/g;\n let match;\n while ((match = classStartRegex.exec(source)) !== null) {\n const name = match[1];\n const braceStart = source.indexOf('{', match.index + match[0].length - 1);\n\n // Find matching closing brace\n let depth = 1;\n let idx = braceStart + 1;\n while (idx < source.length && depth > 0) {\n if (source[idx] === '{') depth++;\n else if (source[idx] === '}') depth--;\n idx++;\n }\n\n const classBody = source.slice(braceStart + 1, idx - 1);\n\n // Parse properties\n const properties = parseProperties(classBody);\n\n // Parse methods\n const methods = parseMethods(classBody);\n\n // Parse constructor params\n const constructorParams = parseConstructor(classBody, name);\n\n // A class is a \"service\" if it has methods\n const isService = methods.length > 0;\n\n classes.push({\n name,\n namespace: ns,\n properties,\n methods,\n constructorParams,\n isService,\n sourceFile,\n });\n }\n\n return classes;\n}\n\n/** Parse properties from a class body. */\nfunction parseProperties(classBody: string): CSharpProperty[] {\n const properties: CSharpProperty[] = [];\n\n // Split into lines so we can look at annotations on the line above\n const lines = classBody.split('\\n');\n let pendingJsonName: string | null = null;\n\n for (const line of lines) {\n const trimmed = line.trim();\n\n // Check for JsonProperty annotation\n const jsonPropMatch = extractJsonPropertyName(trimmed);\n if (jsonPropMatch) {\n pendingJsonName = jsonPropMatch;\n continue;\n }\n\n // Match: public Type Name { get; set; } or public Type Name { get; }\n const propMatch = trimmed.match(/public\\s+(\\S+(?:<[^>]+>)?(?:\\?)?)\\s+(\\w+)\\s*\\{\\s*get;\\s*(set;\\s*)?\\}/);\n if (propMatch) {\n const type = propMatch[1];\n const name = propMatch[2];\n const hasSetter = !!propMatch[3];\n\n properties.push({\n name,\n type,\n jsonName: pendingJsonName || undefined,\n readonly: !hasSetter,\n });\n pendingJsonName = null;\n continue;\n }\n\n // Reset pending annotation if we hit a non-annotation, non-property line\n if (!trimmed.startsWith('[') && trimmed.length > 0) {\n pendingJsonName = null;\n }\n }\n\n return properties;\n}\n\n/** Parse methods from a class body. */\nfunction parseMethods(classBody: string): CSharpMethod[] {\n const methods: CSharpMethod[] = [];\n\n // Match: public [async] ReturnType MethodName(params)\n const methodRegex =\n /(private|protected|internal|public)\\s+(?:(static)\\s+)?(?:(async)\\s+)?(\\S+(?:<[^>]+>)?)\\s+(\\w+)\\s*\\(([^)]*)\\)/g;\n let match;\n while ((match = methodRegex.exec(classBody)) !== null) {\n const visibility = match[1];\n const isAsync = match[3] === 'async';\n const returnType = match[4];\n const name = match[5];\n const paramsStr = match[6];\n\n // Skip private/protected methods and constructors\n if (visibility === 'private' || visibility === 'protected') continue;\n\n const params: { name: string; type: string; optional: boolean }[] = [];\n if (paramsStr.trim()) {\n const paramParts = paramsStr.split(',');\n for (const part of paramParts) {\n const trimmed = part.trim();\n // Match: Type name or Type name = default\n const paramMatch = trimmed.match(/(\\S+(?:<[^>]+>)?(?:\\?)?)\\s+(\\w+)(?:\\s*=\\s*(.+))?/);\n if (paramMatch) {\n const paramType = paramMatch[1];\n const paramName = paramMatch[2];\n const hasDefault = paramMatch[3] !== undefined;\n params.push({\n name: paramName,\n type: paramType,\n optional: paramType.endsWith('?') || hasDefault,\n });\n }\n }\n }\n\n methods.push({\n name,\n params,\n returnType,\n visibility,\n isAsync,\n });\n }\n\n return methods;\n}\n\n/** Parse constructor parameters. */\nfunction parseConstructor(classBody: string, className: string): { name: string; type: string }[] {\n const params: { name: string; type: string }[] = [];\n\n // Match: public ClassName(params) — use indexOf to find the constructor\n const ctorPrefix = `public ${className}`;\n const ctorIdx = classBody.indexOf(ctorPrefix);\n if (ctorIdx < 0) return params;\n const afterCtor = classBody.slice(ctorIdx + ctorPrefix.length);\n const match = afterCtor.match(/^\\s*\\(([^)]*)\\)/);\n if (!match) return params;\n\n const paramsStr = match[1];\n if (!paramsStr.trim()) return params;\n\n const paramParts = paramsStr.split(',');\n for (const part of paramParts) {\n const trimmed = part.trim();\n const paramMatch = trimmed.match(/(\\S+(?:<[^>]+>)?)\\s+(\\w+)/);\n if (paramMatch) {\n params.push({ name: paramMatch[2], type: paramMatch[1] });\n }\n }\n\n return params;\n}\n\n// ---------------------------------------------------------------------------\n// Full file parser\n// ---------------------------------------------------------------------------\n\n/** Parse a single C# source file and return all extracted symbols. */\nexport function parseCSharpFile(filePath: string, sdkPath: string): ParsedCSharpFile {\n const source = readFileSync(filePath, 'utf-8');\n const relPath = relative(sdkPath, filePath);\n const cleaned = stripComments(source);\n\n return {\n classes: parseClasses(cleaned, relPath),\n enums: parseEnums(cleaned, relPath),\n };\n}\n","/**\n * DotNet (.NET/C#) surface builder — transforms parsed C# symbols into an ApiSurface.\n */\n\nimport type {\n ApiClass,\n ApiMethod,\n ApiParam,\n ApiProperty,\n ApiInterface,\n ApiField,\n ApiEnum,\n LanguageHints,\n} from '../types.js';\nimport type { CSharpClass, CSharpEnum } from './dotnet-parser.js';\nimport { sortRecord, ExportCollector } from './shared.js';\n\n// ---------------------------------------------------------------------------\n// Surface builder\n// ---------------------------------------------------------------------------\n\nexport function buildSurface(\n allClasses: CSharpClass[],\n allEnums: CSharpEnum[],\n _hints: LanguageHints,\n): {\n classes: Record<string, ApiClass>;\n interfaces: Record<string, ApiInterface>;\n enums: Record<string, ApiEnum>;\n exports: Record<string, string[]>;\n} {\n const classes: Record<string, ApiClass> = {};\n const interfaces: Record<string, ApiInterface> = {};\n const enums: Record<string, ApiEnum> = {};\n\n const collector = new ExportCollector();\n\n // Process classes\n for (const cls of allClasses) {\n if (cls.isService) {\n // Service class — has methods\n const methods: Record<string, ApiMethod[]> = {};\n const properties: Record<string, ApiProperty> = {};\n\n for (const method of cls.methods) {\n const params: ApiParam[] = method.params.map((p) => ({\n name: p.name,\n type: p.type,\n optional: p.optional,\n passingStyle: 'named' as const,\n }));\n\n if (!methods[method.name]) methods[method.name] = [];\n methods[method.name].push({\n name: method.name,\n params,\n returnType: method.returnType,\n async: method.isAsync,\n });\n }\n\n // Add public properties to service class\n for (const prop of cls.properties) {\n const propName = prop.jsonName || prop.name;\n properties[propName] = {\n name: propName,\n type: prop.type,\n readonly: prop.readonly,\n };\n }\n\n const constructorParams: ApiParam[] = cls.constructorParams.map((p) => ({\n name: p.name,\n type: p.type,\n optional: false,\n passingStyle: 'named' as const,\n }));\n\n classes[cls.name] = {\n name: cls.name,\n sourceFile: cls.sourceFile,\n methods: sortRecord(methods),\n properties: sortRecord(properties),\n constructorParams,\n };\n } else {\n // Data class — no methods, treat as interface\n const fields: Record<string, ApiField> = {};\n for (const prop of cls.properties) {\n const fieldName = prop.jsonName || prop.name;\n const isNullable = prop.type.endsWith('?');\n fields[fieldName] = {\n name: fieldName,\n type: prop.type,\n optional: isNullable,\n };\n }\n\n interfaces[cls.name] = {\n name: cls.name,\n sourceFile: cls.sourceFile,\n fields: sortRecord(fields),\n extends: [],\n };\n }\n collector.add(cls.sourceFile, cls.name);\n }\n\n // Process enums\n for (const en of allEnums) {\n enums[en.name] = {\n name: en.name,\n sourceFile: en.sourceFile,\n members: sortRecord(en.members),\n };\n collector.add(en.sourceFile, en.name);\n }\n\n const exports = collector.toRecord();\n\n return {\n classes: sortRecord(classes),\n interfaces: sortRecord(interfaces),\n enums: sortRecord(enums),\n exports: sortRecord(exports),\n };\n}\n","/**\n * DotNet (C#) API surface extractor.\n *\n * Walks `.cs` files (excluding test, bin, and obj directories), parses\n * classes, enums, properties, and methods, then builds an `ApiSurface`.\n *\n * Parser: `dotnet-parser.ts` — regex-based C# source analysis\n * Surface: `dotnet-surface.ts` — ApiSurface construction\n */\n\nimport { statSync } from 'node:fs';\nimport { resolve } from 'node:path';\nimport { ExtractorError } from '../../errors.js';\nimport type { Extractor, ApiSurface, LanguageHints } from '../types.js';\nimport type { CompatSnapshot } from '../ir.js';\nimport { apiSurfaceToSnapshot } from '../ir.js';\nimport {\n NAMED_TYPE_RE,\n typeExistsInSurface,\n namedTypeWordsOverlap,\n defaultIsNullableOnlyDifference,\n} from '../language-hints.js';\nimport { walkCSharpFiles, parseCSharpFile } from './dotnet-parser.js';\nimport { buildSurface } from './dotnet-surface.js';\nimport type { CSharpClass, CSharpEnum } from './dotnet-parser.js';\n\n// ---------------------------------------------------------------------------\n// Language hints\n// ---------------------------------------------------------------------------\n\nconst DOTNET_PRIMITIVE_TYPES = new Set(['string', 'int', 'long', 'float', 'double', 'bool', 'decimal']);\n\nconst dotnetHints: LanguageHints = {\n stripNullable(type: string): string | null {\n // Nullable<T> → T\n const nullableMatch = type.match(/^Nullable<(.+)>$/);\n if (nullableMatch) return nullableMatch[1];\n // T? → T\n if (type.endsWith('?')) return type.slice(0, -1);\n return null;\n },\n isNullableOnlyDifference(a: string, b: string): boolean {\n return defaultIsNullableOnlyDifference(this, a, b);\n },\n isUnionReorder(_a: string, _b: string): boolean {\n return false; // C# doesn't have union types\n },\n isGenericTypeParam(type: string): boolean {\n return /^[A-Z]$/.test(type) || /^T[A-Z][a-zA-Z]*$/.test(type);\n },\n isExtractionArtifact(type: string): boolean {\n return type === 'object' || type === 'dynamic';\n },\n tolerateCategoryMismatch: false,\n extractReturnTypeName(returnType: string): string | null {\n let inner = returnType;\n // Unwrap Task<T> → T\n const taskMatch = inner.match(/^Task<(.+)>$/);\n if (taskMatch) inner = taskMatch[1];\n // Unwrap Task → void\n if (inner === 'Task') return null;\n // Unwrap nullable\n if (inner.endsWith('?')) inner = inner.slice(0, -1);\n // Unwrap List<T> → T\n const listMatch = inner.match(/^(?:List|IList|IEnumerable|IReadOnlyList)<(.+)>$/);\n if (listMatch) inner = listMatch[1];\n // Primitives\n if (['string', 'int', 'long', 'float', 'double', 'bool', 'void', 'decimal'].includes(inner)) return null;\n return inner;\n },\n extractParamTypeName(paramType: string): string | null {\n let inner = paramType;\n if (inner.endsWith('?')) inner = inner.slice(0, -1);\n if (['string', 'int', 'long', 'float', 'double', 'bool', 'decimal'].includes(inner)) return null;\n return inner;\n },\n propertyMatchesClass(propertyName: string, className: string): boolean {\n return propertyName.toLowerCase() === className.toLowerCase();\n },\n derivedModelNames(modelName: string): string[] {\n return [`${modelName}Response`];\n },\n\n isTypeEquivalent(baselineType: string, candidateType: string, candidateSurface: ApiSurface): boolean {\n // Strip nullable from both sides for comparison\n const stripNullable = (t: string) => {\n if (t.endsWith('?')) return t.slice(0, -1);\n const m = t.match(/^Nullable<(.+)>$/);\n return m ? m[1] : t;\n };\n const baseClean = stripNullable(baselineType);\n const candClean = stripNullable(candidateType);\n\n // Map/dictionary equivalence: Dictionary<string, string> ≡ Dictionary<string, object>\n const dictPattern = /^Dictionary<string,\\s*(string|object|dynamic|Object)>$/;\n if (dictPattern.test(baseClean) && dictPattern.test(candClean)) {\n return true;\n }\n\n // Array notation equivalence: T[] ≡ List<T>\n const arrayMatch = baseClean.match(/^(.+)\\[\\]$/);\n const listMatch = candClean.match(/^(?:List|IList|IEnumerable|IReadOnlyList)<(.+)>$/);\n if (arrayMatch && listMatch) {\n // Compare inner types — allow named type tolerance\n const baseInner = arrayMatch[1];\n const candInner = listMatch[1];\n if (baseInner === candInner) return true;\n // Recurse for named type equivalence\n if (NAMED_TYPE_RE.test(baseInner) && NAMED_TYPE_RE.test(candInner)) {\n if (typeExistsInSurface(candInner, candidateSurface)) {\n if (candInner.includes(baseInner) || baseInner.includes(candInner)) return true;\n const baseNoResp = baseInner.replace(/Response$/, '');\n const candNoResp = candInner.replace(/Response$/, '');\n if (candNoResp.includes(baseNoResp) || baseNoResp.includes(candNoResp)) return true;\n // Word overlap\n if (namedTypeWordsOverlap(baseInner, candInner)) return true;\n }\n }\n // Tolerate model collection vs primitive collection: OrganizationDomain[] ≡ List<string>\n // The spec may define a field as a primitive array while the live SDK wraps it in a model.\n if (\n (DOTNET_PRIMITIVE_TYPES.has(baseInner) && NAMED_TYPE_RE.test(candInner)) ||\n (DOTNET_PRIMITIVE_TYPES.has(candInner) && NAMED_TYPE_RE.test(baseInner))\n ) {\n return true;\n }\n }\n // Also handle reverse: baseline is List<T>, candidate is T[]\n const baseListMatch = baseClean.match(/^(?:List|IList|IEnumerable|IReadOnlyList)<(.+)>$/);\n const candArrayMatch = candClean.match(/^(.+)\\[\\]$/);\n if (baseListMatch && candArrayMatch) {\n const baseInner = baseListMatch[1];\n const candInner = candArrayMatch[1];\n if (baseInner === candInner) return true;\n if (NAMED_TYPE_RE.test(baseInner) && NAMED_TYPE_RE.test(candInner)) {\n if (typeExistsInSurface(candInner, candidateSurface)) {\n if (candInner.includes(baseInner) || baseInner.includes(candInner)) return true;\n }\n }\n }\n\n // Generic container equivalence: List<T> vs List<U>, T[] vs U[]\n // where T and U are different named types for the same concept\n const genericPattern = /^(?:List|IList|IEnumerable|IReadOnlyList)<(.+)>$/;\n const baseGeneric = baseClean.match(genericPattern);\n const candGeneric = candClean.match(genericPattern);\n if (baseGeneric && candGeneric) {\n const baseInner = baseGeneric[1];\n const candInner = candGeneric[1];\n if (baseInner === candInner) return true;\n if (NAMED_TYPE_RE.test(baseInner) && NAMED_TYPE_RE.test(candInner)) {\n if (typeExistsInSurface(candInner, candidateSurface)) {\n if (candInner.includes(baseInner) || baseInner.includes(candInner)) return true;\n const baseNoResp = baseInner.replace(/Response$/, '');\n const candNoResp = candInner.replace(/Response$/, '');\n if (candNoResp.includes(baseNoResp) || baseNoResp.includes(candNoResp)) return true;\n if (namedTypeWordsOverlap(baseInner, candInner)) return true;\n }\n }\n }\n\n // Named type tolerance: different PascalCase names for the same concept\n // (e.g., EmailObject vs DirectoryUsersEmail, RoleResponse vs DirectoryUserRole)\n if (NAMED_TYPE_RE.test(baseClean) && NAMED_TYPE_RE.test(candClean)) {\n if (typeExistsInSurface(candClean, candidateSurface)) {\n if (candClean.includes(baseClean) || baseClean.includes(candClean)) return true;\n const baseNoResp = baseClean.replace(/Response$/, '');\n const candNoResp = candClean.replace(/Response$/, '');\n if (candNoResp.includes(baseNoResp) || baseNoResp.includes(candNoResp)) return true;\n // Word-component overlap\n if (namedTypeWordsOverlap(baseClean, candClean)) return true;\n }\n }\n\n // Numeric type equivalence: int ≡ double, long ≡ double (JSON numbers)\n const numericTypes = new Set(['int', 'long', 'float', 'double', 'decimal']);\n if (numericTypes.has(baseClean) && numericTypes.has(candClean)) return true;\n\n // Date type equivalence: DateTime ≡ string (spec uses string with date-time format)\n if ((baseClean === 'DateTime' && candClean === 'string') || (baseClean === 'string' && candClean === 'DateTime')) {\n return true;\n }\n\n // Enum name vs string equivalence (candidate has an enum, baseline says string)\n if (baseClean === 'string' && candidateSurface.enums[candClean]) return true;\n if (candClean === 'string' && candidateSurface.enums?.[baseClean]) return true;\n\n return false;\n },\n\n modelBaseClasses: [],\n exceptionBaseClasses: ['Exception'],\n};\n\n// ---------------------------------------------------------------------------\n// Extractor\n// ---------------------------------------------------------------------------\n\n/** Create a DotNet extractor with optional hint overrides. */\nexport function createDotnetExtractor(hintOverrides?: Partial<LanguageHints>): Extractor {\n const mergedHints: LanguageHints = hintOverrides ? { ...dotnetHints, ...hintOverrides } : dotnetHints;\n\n return {\n language: 'dotnet',\n hints: mergedHints,\n\n async extractSnapshot(sdkPath: string): Promise<CompatSnapshot> {\n const surface = await this.extract(sdkPath);\n return apiSurfaceToSnapshot(surface);\n },\n\n async extract(sdkPath: string): Promise<ApiSurface> {\n // Determine the source directory: prefer src/, fallback to root\n let sourceDir: string;\n const srcPath = resolve(sdkPath, 'src');\n\n try {\n statSync(srcPath);\n sourceDir = srcPath;\n } catch {\n sourceDir = sdkPath;\n }\n\n const csFiles = walkCSharpFiles(sourceDir);\n if (csFiles.length === 0) {\n throw new ExtractorError(\n `No .cs files found in ${sdkPath}`,\n `Ensure the --sdk-path argument points to a .NET project root containing .cs source files.`,\n );\n }\n\n const allClasses: CSharpClass[] = [];\n const allEnums: CSharpEnum[] = [];\n\n for (const filePath of csFiles) {\n const parsed = parseCSharpFile(filePath, sdkPath);\n allClasses.push(...parsed.classes);\n allEnums.push(...parsed.enums);\n }\n\n const { classes, interfaces, enums, exports } = buildSurface(allClasses, allEnums, mergedHints);\n\n return {\n language: 'dotnet',\n extractedFrom: sdkPath,\n extractedAt: new Date().toISOString(),\n classes,\n interfaces,\n typeAliases: {},\n enums,\n exports,\n };\n },\n };\n}\n\n/** Default DotNet extractor with generic language hints. */\nexport const dotnetExtractor: Extractor = createDotnetExtractor();\n","/**\n * Elixir source parser — regex-based extraction of modules, structs,\n * functions, and type specs from Elixir source files.\n */\n\nimport { readFileSync, readdirSync, statSync } from 'node:fs';\nimport { join, relative } from 'node:path';\n\n// ---------------------------------------------------------------------------\n// Internal types\n// ---------------------------------------------------------------------------\n\nexport interface ElixirStruct {\n moduleName: string;\n fields: string[];\n sourceFile: string;\n}\n\nexport interface ElixirFunction {\n moduleName: string;\n name: string;\n arity: number;\n params: string[];\n /** Per-param passing style: 'positional' or 'keyword' (for keyword list params). */\n paramStyles: ('positional' | 'keyword')[];\n isPrivate: boolean;\n sourceFile: string;\n}\n\nexport interface ElixirTypeSpec {\n moduleName: string;\n name: string;\n definition: string;\n sourceFile: string;\n}\n\nexport interface ElixirEnumModule {\n moduleName: string;\n members: Record<string, string>;\n sourceFile: string;\n}\n\nexport interface ParsedElixirFile {\n structs: ElixirStruct[];\n functions: ElixirFunction[];\n typeSpecs: ElixirTypeSpec[];\n enumModules: ElixirEnumModule[];\n moduleNames: string[];\n}\n\n// ---------------------------------------------------------------------------\n// File walker\n// ---------------------------------------------------------------------------\n\nexport function walkElixirFiles(dir: string): string[] {\n const results: string[] = [];\n let entries: string[];\n try {\n entries = readdirSync(dir);\n } catch {\n return results;\n }\n for (const entry of entries) {\n const fullPath = join(dir, entry);\n let stat;\n try {\n stat = statSync(fullPath);\n } catch {\n continue;\n }\n if (stat.isDirectory()) {\n if (entry.startsWith('.') || entry === '_build' || entry === 'deps' || entry === 'test') continue;\n results.push(...walkElixirFiles(fullPath));\n } else if (entry.endsWith('.ex') && !entry.endsWith('_test.exs')) {\n results.push(fullPath);\n }\n }\n return results.sort();\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Strip comments and heredoc strings from Elixir source code.\n * This prevents false matches of keywords like `do`/`end` inside strings\n * and doc comments.\n */\nfunction stripCommentsAndHeredocs(source: string): string {\n // Replace triple-quoted heredocs (@moduledoc \"\"\", @doc \"\"\", etc.)\n let result = source.replace(/\"\"\"[\\s\\S]*?\"\"\"/g, '\"\"\"\"\"\"');\n // Remove single-line comments\n result = result.replace(/#[^\\n]*/g, '');\n return result;\n}\n\n// ---------------------------------------------------------------------------\n// Module body extraction using line-based do/end counting\n// ---------------------------------------------------------------------------\n\n/**\n * Given the full source and the position right after `defmodule ... do`,\n * find the module body text up to the matching `end`.\n *\n * Uses a character-by-character scan that skips string literals and\n * counts block-level `do`/`end` keywords only when they appear as\n * standalone tokens (word boundaries).\n */\nfunction extractModuleBody(source: string, startIdx: number): string | null {\n let depth = 1;\n // Walk through source counting do/end as word boundaries\n // Skip strings (single and double quoted)\n let i = startIdx;\n while (i < source.length && depth > 0) {\n const ch = source[i];\n\n // Skip string literals\n if (ch === '\"') {\n i++;\n while (i < source.length && source[i] !== '\"') {\n if (source[i] === '\\\\') i++; // skip escaped char\n i++;\n }\n i++; // skip closing quote\n continue;\n }\n if (ch === \"'\") {\n i++;\n while (i < source.length && source[i] !== \"'\") {\n if (source[i] === '\\\\') i++;\n i++;\n }\n i++;\n continue;\n }\n\n // Check for word-boundary keywords\n // Only match `do` and `end` as full words (not `done`, `donut`, `endor`, etc.)\n if (isWordBoundary(source, i)) {\n if (source.slice(i, i + 2) === 'do' && isWordEnd(source, i + 2)) {\n // Make sure this is block `do`, not keyword `do:` form\n if (source[i + 2] !== ':') {\n depth++;\n }\n i += 2;\n continue;\n }\n if (source.slice(i, i + 2) === 'fn' && isWordEnd(source, i + 2)) {\n depth++;\n i += 2;\n continue;\n }\n if (source.slice(i, i + 3) === 'end' && isWordEnd(source, i + 3)) {\n depth--;\n if (depth === 0) {\n return source.slice(startIdx, i);\n }\n i += 3;\n continue;\n }\n }\n\n i++;\n }\n\n return null;\n}\n\nfunction isWordBoundary(source: string, idx: number): boolean {\n if (idx === 0) return true;\n const prev = source[idx - 1];\n return !/[a-zA-Z0-9_]/.test(prev);\n}\n\nfunction isWordEnd(source: string, idx: number): boolean {\n if (idx >= source.length) return true;\n return !/[a-zA-Z0-9_]/.test(source[idx]);\n}\n\n// ---------------------------------------------------------------------------\n// Module extraction\n// ---------------------------------------------------------------------------\n\ninterface ExtractedModule {\n name: string;\n body: string;\n}\n\n/** Find all defmodule blocks and extract their bodies in a single pass. */\nfunction extractModules(source: string): ExtractedModule[] {\n const modules: ExtractedModule[] = [];\n const moduleRegex = /defmodule\\s+([\\w.]+)\\s+do\\b/g;\n let match;\n while ((match = moduleRegex.exec(source)) !== null) {\n const body = extractModuleBody(source, match.index + match[0].length);\n if (body) {\n modules.push({ name: match[1], body });\n }\n }\n return modules;\n}\n\n// ---------------------------------------------------------------------------\n// Struct extraction\n// ---------------------------------------------------------------------------\n\nfunction extractStructs(modules: ExtractedModule[], sourceFile: string): ElixirStruct[] {\n const structs: ElixirStruct[] = [];\n\n for (const { name: moduleName, body: moduleBody } of modules) {\n // Look for defstruct inside this module\n const structMatch = moduleBody.match(/defstruct\\s+\\[([^\\]]*)\\]/);\n if (!structMatch) continue;\n\n const fieldsStr = structMatch[1];\n const fields: string[] = [];\n const fieldRegex = /:(\\w+)/g;\n let fieldMatch;\n while ((fieldMatch = fieldRegex.exec(fieldsStr)) !== null) {\n fields.push(fieldMatch[1]);\n }\n\n if (fields.length > 0) {\n structs.push({ moduleName, fields, sourceFile });\n }\n }\n\n return structs;\n}\n\n// ---------------------------------------------------------------------------\n// Function extraction\n// ---------------------------------------------------------------------------\n\nfunction extractFunctions(modules: ExtractedModule[], sourceFile: string): ElixirFunction[] {\n const functions: ElixirFunction[] = [];\n\n for (const { name: moduleName, body: moduleBody } of modules) {\n // Match both styles:\n // 1. Block: def name(params) do ... end\n // 2. Keyword: def name(params), do: ...\n // 3. Keyword no-args: def name, do: ...\n const funcRegex = /(def|defp)\\s+(\\w+)(?:\\(([^)]*)\\))?(?:\\s+do\\b|\\s*,\\s*do:)/g;\n let funcMatch;\n while ((funcMatch = funcRegex.exec(moduleBody)) !== null) {\n const isPrivate = funcMatch[1] === 'defp';\n const name = funcMatch[2];\n const paramsStr = funcMatch[3] || '';\n\n // Skip module/struct macros\n if (name === 'defstruct' || name === 'defmodule') continue;\n\n const params: string[] = [];\n const paramStyles: ('positional' | 'keyword')[] = [];\n if (paramsStr.trim()) {\n const paramParts = paramsStr.split(',');\n for (const part of paramParts) {\n const trimmed = part.trim();\n // Extract parameter name (before :: type annotation or \\\\ default)\n const paramNameMatch = trimmed.match(/^(\\w+)/);\n if (paramNameMatch) {\n params.push(paramNameMatch[1]);\n // Detect keyword list params: `opts \\\\ []` or `options \\\\ []`\n const isKeywordList = /\\\\\\\\\\s*\\[/.test(trimmed);\n paramStyles.push(isKeywordList ? 'keyword' : 'positional');\n }\n }\n }\n\n functions.push({\n moduleName,\n name,\n arity: params.length,\n params,\n paramStyles,\n isPrivate,\n sourceFile,\n });\n }\n }\n\n return functions;\n}\n\n// ---------------------------------------------------------------------------\n// Type spec extraction\n// ---------------------------------------------------------------------------\n\nfunction extractTypeSpecs(modules: ExtractedModule[], sourceFile: string): ElixirTypeSpec[] {\n const specs: ElixirTypeSpec[] = [];\n\n for (const { name: moduleName, body: moduleBody } of modules) {\n // Match @type t :: ... capturing multi-line definitions\n // The definition continues until we hit a blank line, a new @-attribute, or def/defstruct\n const typeRegex = /@type\\s+(\\w+)\\s*::\\s*/g;\n let typeMatch;\n while ((typeMatch = typeRegex.exec(moduleBody)) !== null) {\n const typeName = typeMatch[1];\n const defStart = typeMatch.index + typeMatch[0].length;\n\n // Find the end of the type definition:\n // It ends at a blank line, a new @attribute, def, defp, defstruct, or end-of-module\n let defEnd = defStart;\n let braceDepth = 0;\n for (let j = defStart; j < moduleBody.length; j++) {\n const ch = moduleBody[j];\n if (ch === '{') braceDepth++;\n else if (ch === '}') {\n braceDepth--;\n if (braceDepth < 0) break;\n if (braceDepth === 0) {\n defEnd = j + 1;\n break;\n }\n } else if (braceDepth === 0 && ch === '\\n') {\n // Check if next non-whitespace line starts a new declaration\n const remaining = moduleBody.slice(j + 1);\n const nextLineMatch = remaining.match(/^\\s*\\S/);\n if (nextLineMatch) {\n const nextContent = remaining.trimStart();\n if (\n nextContent.startsWith('@') ||\n nextContent.startsWith('def ') ||\n nextContent.startsWith('defp ') ||\n nextContent.startsWith('defstruct') ||\n nextContent.startsWith('defmodule')\n ) {\n defEnd = j;\n break;\n }\n } else {\n // Blank line — end of definition\n defEnd = j;\n break;\n }\n }\n defEnd = j + 1;\n }\n\n const definition = moduleBody.slice(defStart, defEnd).trim();\n specs.push({ moduleName, name: typeName, definition, sourceFile });\n }\n }\n\n return specs;\n}\n\n// ---------------------------------------------------------------------------\n// Enum module extraction\n// ---------------------------------------------------------------------------\n\nfunction extractEnumModules(modules: ExtractedModule[], sourceFile: string): ElixirEnumModule[] {\n const enumModules: ElixirEnumModule[] = [];\n\n for (const { name: moduleName, body: moduleBody } of modules) {\n // Check if this module has a `values` function (indicator of enum-like module)\n if (!moduleBody.match(/def\\s+values[\\s,]/)) continue;\n\n // Also verify there's no defstruct (structs aren't enums)\n if (moduleBody.match(/defstruct\\b/)) continue;\n\n const members: Record<string, string> = {};\n\n // Extract individual value functions: def name, do: \"value\"\n const valueFuncRegex = /def\\s+(\\w+),\\s*do:\\s*\"([^\"]+)\"/g;\n let valueFuncMatch;\n while ((valueFuncMatch = valueFuncRegex.exec(moduleBody)) !== null) {\n const funcName = valueFuncMatch[1];\n const funcValue = valueFuncMatch[2];\n if (funcName === 'values') continue;\n members[funcName] = funcValue;\n }\n\n if (Object.keys(members).length > 0) {\n enumModules.push({ moduleName, members, sourceFile });\n }\n }\n\n return enumModules;\n}\n\n// ---------------------------------------------------------------------------\n// Full file parser\n// ---------------------------------------------------------------------------\n\n/** Parse a single Elixir source file and return all extracted symbols. */\nexport function parseElixirFile(filePath: string, sdkPath: string): ParsedElixirFile {\n const source = readFileSync(filePath, 'utf-8');\n const relPath = relative(sdkPath, filePath);\n const cleaned = stripCommentsAndHeredocs(source);\n const modules = extractModules(cleaned);\n\n return {\n structs: extractStructs(modules, relPath),\n functions: extractFunctions(modules, relPath),\n typeSpecs: extractTypeSpecs(modules, relPath),\n enumModules: extractEnumModules(modules, relPath),\n moduleNames: modules.map((m) => m.name),\n };\n}\n","/**\n * Elixir surface builder — transforms parsed Elixir symbols into an ApiSurface.\n *\n * Elixir conventions:\n * - Data types (defstruct) → ApiInterface\n * - Modules with public functions → ApiClass\n * - Enum-like modules (with value functions) → ApiEnum\n */\n\nimport type { ApiClass, ApiMethod, ApiParam, ApiInterface, ApiField, ApiEnum } from '../types.js';\nimport type { ElixirStruct, ElixirFunction, ElixirEnumModule, ElixirTypeSpec } from './elixir-parser.js';\nimport { sortRecord, ExportCollector } from './shared.js';\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/** Get the short name from a fully qualified Elixir module name. */\nfunction shortName(moduleName: string): string {\n const parts = moduleName.split('.');\n return parts[parts.length - 1];\n}\n\n// ---------------------------------------------------------------------------\n// Surface builder\n// ---------------------------------------------------------------------------\n\nexport function buildSurface(\n allStructs: ElixirStruct[],\n allFunctions: ElixirFunction[],\n allEnumModules: ElixirEnumModule[],\n allTypeSpecs: ElixirTypeSpec[],\n): {\n classes: Record<string, ApiClass>;\n interfaces: Record<string, ApiInterface>;\n enums: Record<string, ApiEnum>;\n exports: Record<string, string[]>;\n} {\n const classes: Record<string, ApiClass> = {};\n const interfaces: Record<string, ApiInterface> = {};\n const enums: Record<string, ApiEnum> = {};\n\n const collector = new ExportCollector();\n\n // Collect struct module names so we can distinguish struct modules from service modules\n const structModuleNames = new Set(allStructs.map((s) => s.moduleName));\n const enumModuleNames = new Set(allEnumModules.map((e) => e.moduleName));\n\n // Process structs as interfaces\n for (const struct of allStructs) {\n const name = shortName(struct.moduleName);\n const fields: Record<string, ApiField> = {};\n\n // Build fields from struct keys — types come from @type spec if available\n const typeSpec = allTypeSpecs.find((ts) => ts.moduleName === struct.moduleName && ts.name === 't');\n\n for (const field of struct.fields) {\n // Try to extract type from the @type spec\n let fieldType = 'any';\n let optional = false;\n\n if (typeSpec) {\n // Parse the type definition to find this field's type\n const fieldPrefix = field + ':';\n const prefixIdx = typeSpec.definition.indexOf(fieldPrefix);\n const fieldTypeMatch =\n prefixIdx >= 0 ? typeSpec.definition.slice(prefixIdx + fieldPrefix.length).match(/^\\s*([^,}]+)/) : null;\n if (fieldTypeMatch) {\n fieldType = fieldTypeMatch[1].trim();\n // Check if nullable (contains | nil)\n if (fieldType.includes('| nil') || fieldType.includes('nil |')) {\n optional = true;\n fieldType = fieldType\n .replace(/\\s*\\|\\s*nil/g, '')\n .replace(/nil\\s*\\|\\s*/g, '')\n .trim();\n }\n }\n }\n\n fields[field] = {\n name: field,\n type: fieldType,\n optional,\n };\n }\n\n interfaces[name] = {\n name,\n sourceFile: struct.sourceFile,\n fields: sortRecord(fields),\n extends: [],\n };\n collector.add(struct.sourceFile, name);\n }\n\n // Process enum modules\n for (const enumModule of allEnumModules) {\n const name = shortName(enumModule.moduleName);\n enums[name] = {\n name,\n sourceFile: enumModule.sourceFile,\n members: sortRecord(enumModule.members),\n };\n collector.add(enumModule.sourceFile, name);\n }\n\n // Group public functions by module\n const funcsByModule = new Map<string, ElixirFunction[]>();\n for (const func of allFunctions) {\n if (func.isPrivate) continue;\n\n // Skip functions from struct modules (they are data, not services)\n // and enum modules (already handled)\n if (structModuleNames.has(func.moduleName) && !funcsByModule.has(func.moduleName)) {\n // Struct modules might still have functions, but only if they have\n // functions beyond just struct-related ones\n }\n if (enumModuleNames.has(func.moduleName)) continue;\n\n if (!funcsByModule.has(func.moduleName)) funcsByModule.set(func.moduleName, []);\n funcsByModule.get(func.moduleName)!.push(func);\n }\n\n // Convert function modules to classes\n for (const [moduleName, funcs] of funcsByModule) {\n // Skip if this is a struct-only module (no meaningful functions)\n if (structModuleNames.has(moduleName)) continue;\n\n const name = shortName(moduleName);\n const methods: Record<string, ApiMethod[]> = {};\n\n // Deduplicate by function name (Elixir allows multiple clauses)\n const seenFuncs = new Set<string>();\n for (const func of funcs) {\n if (seenFuncs.has(func.name)) continue;\n seenFuncs.add(func.name);\n\n const params: ApiParam[] = func.params.map((p, i) => ({\n name: p,\n type: 'any',\n optional: false,\n passingStyle: func.paramStyles[i] ?? ('positional' as const),\n }));\n\n if (!methods[func.name]) methods[func.name] = [];\n methods[func.name].push({\n name: func.name,\n params,\n returnType: 'any',\n async: false,\n });\n }\n\n if (Object.keys(methods).length > 0) {\n classes[name] = {\n name,\n sourceFile: funcs[0].sourceFile,\n methods: sortRecord(methods),\n properties: {},\n constructorParams: [],\n };\n collector.add(funcs[0].sourceFile, name);\n }\n }\n\n const exports = collector.toRecord();\n\n return {\n classes: sortRecord(classes),\n interfaces: sortRecord(interfaces),\n enums: sortRecord(enums),\n exports: sortRecord(exports),\n };\n}\n","/**\n * Elixir API surface extractor.\n *\n * Walks `.ex` files under `lib/` (the standard Elixir source directory),\n * parses modules, structs, functions, and type specs, then builds an\n * `ApiSurface`.\n *\n * Parser: `elixir-parser.ts` — regex-based Elixir source analysis\n * Surface: `elixir-surface.ts` — ApiSurface construction\n */\n\nimport { statSync } from 'node:fs';\nimport { resolve } from 'node:path';\nimport { ExtractorError } from '../../errors.js';\nimport type { Extractor, ApiSurface, LanguageHints } from '../types.js';\nimport type { CompatSnapshot } from '../ir.js';\nimport { apiSurfaceToSnapshot } from '../ir.js';\nimport { defaultIsNullableOnlyDifference } from '../language-hints.js';\nimport { walkElixirFiles, parseElixirFile } from './elixir-parser.js';\nimport { buildSurface } from './elixir-surface.js';\nimport type { ElixirStruct, ElixirFunction, ElixirEnumModule, ElixirTypeSpec } from './elixir-parser.js';\n\n// ---------------------------------------------------------------------------\n// Language hints\n// ---------------------------------------------------------------------------\n\nconst elixirHints: LanguageHints = {\n stripNullable(type: string): string | null {\n // T | nil → T\n if (type.includes('| nil')) return type.replace(/\\s*\\|\\s*nil/g, '').trim();\n if (type.includes('nil |')) return type.replace(/nil\\s*\\|\\s*/g, '').trim();\n return null;\n },\n isNullableOnlyDifference(a: string, b: string): boolean {\n return defaultIsNullableOnlyDifference(this, a, b);\n },\n isUnionReorder(a: string, b: string): boolean {\n // Parse pipe-separated types, sort, compare\n const sortParts = (t: string) =>\n t\n .split('|')\n .map((s) => s.trim())\n .sort()\n .join('|');\n return a !== b && sortParts(a) === sortParts(b);\n },\n isGenericTypeParam(type: string): boolean {\n // Elixir doesn't have generic type params in the same sense\n return type === 'any' || type === 'term';\n },\n isExtractionArtifact(type: string): boolean {\n return type === 'any' || type === 'term' || type === 'any()';\n },\n tolerateCategoryMismatch: true,\n extractReturnTypeName(returnType: string): string | null {\n let inner = returnType;\n // Unwrap {:ok, T} → T\n const okMatch = inner.match(/^\\{:ok,\\s*(.+)\\}$/);\n if (okMatch) inner = okMatch[1].trim();\n // Unwrap [T] → T\n const listMatch = inner.match(/^\\[(.+)\\]$/);\n if (listMatch) inner = listMatch[1].trim();\n // Primitives\n if (['any', 'term', 'atom', 'binary', 'boolean', 'integer', 'float', 'number', 'pid'].includes(inner)) {\n return null;\n }\n // String.t() → String\n const typeCallMatch = inner.match(/^(\\w+)\\.t\\(\\)$/);\n if (typeCallMatch) return typeCallMatch[1];\n return inner || null;\n },\n extractParamTypeName(paramType: string): string | null {\n if (\n ['any', 'term', 'atom', 'binary', 'boolean', 'integer', 'float', 'number', 'pid', 'keyword'].includes(paramType)\n ) {\n return null;\n }\n const typeCallMatch = paramType.match(/^(\\w+)\\.t\\(\\)$/);\n if (typeCallMatch) return typeCallMatch[1];\n return paramType;\n },\n propertyMatchesClass(propertyName: string, className: string): boolean {\n // snake_case → PascalCase comparison\n return propertyName.replace(/_/g, '').toLowerCase() === className.toLowerCase();\n },\n derivedModelNames(modelName: string): string[] {\n return [`${modelName}Response`];\n },\n};\n\n// ---------------------------------------------------------------------------\n// Extractor\n// ---------------------------------------------------------------------------\n\nexport const elixirExtractor: Extractor = {\n language: 'elixir',\n hints: elixirHints,\n\n async extractSnapshot(sdkPath: string): Promise<CompatSnapshot> {\n const surface = await this.extract(sdkPath);\n return apiSurfaceToSnapshot(surface);\n },\n\n async extract(sdkPath: string): Promise<ApiSurface> {\n // Determine the source directory: prefer lib/, fallback to root\n let sourceDir: string;\n const libPath = resolve(sdkPath, 'lib');\n\n try {\n statSync(libPath);\n sourceDir = libPath;\n } catch {\n sourceDir = sdkPath;\n }\n\n const exFiles = walkElixirFiles(sourceDir);\n if (exFiles.length === 0) {\n throw new ExtractorError(\n `No .ex files found in ${sdkPath}`,\n `Ensure the --sdk-path argument points to an Elixir project root containing .ex source files in lib/.`,\n );\n }\n\n const allStructs: ElixirStruct[] = [];\n const allFunctions: ElixirFunction[] = [];\n const allEnumModules: ElixirEnumModule[] = [];\n const allTypeSpecs: ElixirTypeSpec[] = [];\n\n for (const filePath of exFiles) {\n const parsed = parseElixirFile(filePath, sdkPath);\n allStructs.push(...parsed.structs);\n allFunctions.push(...parsed.functions);\n allEnumModules.push(...parsed.enumModules);\n allTypeSpecs.push(...parsed.typeSpecs);\n }\n\n const { classes, interfaces, enums, exports } = buildSurface(\n allStructs,\n allFunctions,\n allEnumModules,\n allTypeSpecs,\n );\n\n return {\n language: 'elixir',\n extractedFrom: sdkPath,\n extractedAt: new Date().toISOString(),\n classes,\n interfaces,\n typeAliases: {},\n enums,\n exports,\n };\n },\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;AA2CA,SAAgB,sBACd,oBACkB;CAClB,MAAM,0BAAU,IAAI,KAA+B;AAEnD,MAAK,MAAM,EAAE,MAAM,QAAQ,cAAc,mBACvC,MAAK,MAAM,UAAU,OAAO,SAAS;EACnC,MAAM,WAAW,QAAQ,IAAI,OAAO,mBAAmB;AACvD,MAAI,SACF,UAAS,OAAO,YAAY,OAAO;MAEnC,SAAQ,IAAI,OAAO,oBAAoB;GACrC,IAAI,OAAO;GACX,QAAQ,OAAO;GACf,UAAU,OAAO;GACjB,QAAQ,GAAG,WAAW,OAAO,UAAU;GACvC,SAAS,OAAO;GAChB,KAAK,OAAO;GACZ,KAAK,OAAO;GACb,CAAC;;AAKR,QAAO,EACL,mBAAmB,CAAC,GAAG,QAAQ,QAAQ,CAAC,EACzC;;;AAIH,SAAgB,gBAAgB,QAAgD;CAC9E,MAAM,aAAa,OAAO,OAAO,OAAO,OAAO;AAC/C,KAAI,WAAW,SAAS,WAAW,CAAE,QAAO;AAC5C,KAAI,WAAW,SAAS,YAAY,CAAE,QAAO;AAC7C,QAAO;;;AAIT,SAAgB,2BAA2B,QAIzC;CACA,IAAI,WAAW;CACf,IAAI,WAAW;CACf,IAAI,WAAW;AACf,MAAK,MAAM,UAAU,OAAO,mBAAmB;EAC7C,MAAM,MAAM,gBAAgB,OAAO;AACnC,MAAI,QAAQ,WAAY;WACf,QAAQ,YAAa;MACzB;;AAEP,QAAO;EAAE;EAAU;EAAU;EAAU;;;;;ACtDzC,SAAgB,eAAe,MAAwB,UAAiC;AACtF,QAAO;EACL,eAAe;EACf,UAAU,YAAY;EACtB,SAAS,KAAK;EACd,SAAS,KAAK,QAAQ,KAAK,OAAO;GAChC,UAAU,EAAE;GACZ,UAAU,EAAE;GACZ,QAAQ,EAAE;GACV,oBAAoB,EAAE;GACtB,YAAY,EAAE;GACd,KAAK,EAAE;GACP,KAAK,EAAE;GACP,GAAI,EAAE,UAAU,EAAE,SAAS,EAAE,SAAS,GAAG,EAAE;GAC5C,EAAE;EACJ;;;AAQH,SAAgB,mBAAmB,MAAwB,MAAyD;CAClH,MAAM,QAAkB,EAAE;AAE1B,OAAM,KAAK,gBAAgB,MAAM,WAAW,QAAQ,KAAK,aAAa,GAAG,GAAG;AAC5E,OAAM,KACJ,KAAK,KAAK,QAAQ,SAAS,aAAa,KAAK,QAAQ,SAAS,cAAc,KAAK,QAAQ,SAAS,WACnG;AAED,KAAI,KAAK,QAAQ,WAAW,GAAG;AAC7B,QAAM,KAAK,uCAAuC;AAClD,SAAO,MAAM,KAAK,KAAK;;CAIzB,MAAM,WAAW,KAAK,QAAQ,QAAQ,MAAM,EAAE,aAAa,WAAW;CACtE,MAAM,WAAW,KAAK,QAAQ,QAAQ,MAAM,EAAE,aAAa,YAAY;CACvE,MAAM,WAAW,KAAK,QAAQ,QAAQ,MAAM,EAAE,aAAa,WAAW;AAEtE,KAAI,SAAS,SAAS,GAAG;AACvB,QAAM,KAAK,GAAG;AACd,QAAM,KAAK,cAAc;AACzB,OAAK,MAAM,KAAK,UAAU;AACxB,SAAM,KAAK,QAAQ,EAAE,SAAS,IAAI,EAAE,OAAO,KAAK,EAAE,UAAU;AAC5D,OAAI,MAAM,WAAW,EAAE,eAAe,UACpC,OAAM,KAAK,qBAAqB,EAAE,aAAa;;;AAKrD,KAAI,SAAS,SAAS,GAAG;AACvB,QAAM,KAAK,GAAG;AACd,QAAM,KAAK,eAAe;AAC1B,OAAK,MAAM,KAAK,UAAU;AACxB,SAAM,KAAK,QAAQ,EAAE,SAAS,IAAI,EAAE,OAAO,KAAK,EAAE,UAAU;AAC5D,OAAI,MAAM,WAAW,EAAE,eAAe,UACpC,OAAM,KAAK,qBAAqB,EAAE,aAAa;;;AAKrD,KAAI,SAAS,SAAS,GAAG;AACvB,QAAM,KAAK,GAAG;AACd,QAAM,KAAK,eAAe,SAAS,OAAO,gBAAgB;;AAG5D,QAAO,MAAM,KAAK,KAAK;;;AAkBzB,SAAgB,yBACd,oBACkB;AAElB,QAAO,EACL,mBAFa,sBAAsB,mBAAmB,CAE5B,kBAAkB,KAAK,OAAO;EACtD,IAAI,EAAE;EACN,QAAQ,EAAE;EACV,UAAU,EAAE;EACZ,QAAQ,EAAE;EACX,EAAE,EACJ;;;AAIH,SAAgB,wBACd,oBACQ;CACR,MAAM,SAAS,sBAAsB,mBAAmB;CACxD,MAAM,UAAU,2BAA2B,OAAO;CAClD,MAAM,QAAkB,EAAE;AAE1B,OAAM,KAAK,qCAAqC;AAChD,OAAM,KAAK,KAAK,QAAQ,SAAS,aAAa,QAAQ,SAAS,cAAc,QAAQ,SAAS,WAAW;AAEzG,KAAI,OAAO,kBAAkB,WAAW,GAAG;AACzC,QAAM,KAAK,+BAA+B;AAC1C,SAAO,MAAM,KAAK,KAAK;;AAGzB,MAAK,MAAM,UAAU,OAAO,mBAAmB;EAC7C,MAAM,MAAM,gBAAgB,OAAO;EACnC,MAAM,YAAY,OAAO,QAAQ,OAAO,OAAO,CAC5C,KAAK,CAAC,MAAM,OAAO,GAAG,KAAK,IAAI,IAAI,CACnC,KAAK,KAAK;AACb,QAAM,KAAK,MAAM,IAAI,IAAI,OAAO,SAAS,IAAI,OAAO,SAAS;AAC7D,QAAM,KAAK,eAAe,YAAY;;AAGxC,QAAO,MAAM,KAAK,KAAK;;;;;ACnIzB,SAAgB,iBAAiB,UAA8C;CAC7E,MAAM,SAAmB,EAAE;AAE3B,KAAI,CAAC,SAAS,UAAU,SAAS,OAAO,MAAM,KAAK,GACjD,QAAO,KAAK,yCAAyC;AAGvD,KAAI,CAAC,SAAS,SACZ,QAAO,KAAK,0CAA0C;AAGxD,KAAI,CAAC,SAAS,UAAU,SAAS,OAAO,MAAM,KAAK,GACjD,QAAO,KAAK,iCAAiC;AAI/C,KAAI,SAAS,WAAW,OAAO,SAAS,OAAO,SAAS,KAAK,IAAI,SAAS,OAAO,SAAS,MAAM,CAC9F,QAAO,KAAK,oBAAoB,SAAS,OAAO,gDAAgD;AAGlG,QAAO;EACL,OAAO,OAAO,WAAW;EACzB;EACD;;;AAIH,SAAgB,kBAAkB,WAAoD;CACpF,MAAM,yBAAS,IAAI,KAAuB;AAC1C,MAAK,IAAI,IAAI,GAAG,IAAI,UAAU,QAAQ,KAAK;EACzC,MAAM,aAAa,iBAAiB,UAAU,GAAG;AACjD,MAAI,CAAC,WAAW,MACd,QAAO,IAAI,GAAG,WAAW,OAAO;;AAGpC,QAAO;;;;;;AAWT,SAAgB,cACd,QACA,WACA,UACuB;AACvB,MAAK,MAAM,YAAY,UACrB,KAAI,sBAAsB,UAAU,QAAQ,SAAS,CACnD,QAAO;AAGX,QAAO;;;;;;AAOT,SAAgB,eACd,SACA,WACA,UACiB;AACjB,QAAO,QAAQ,KAAK,WAAW;EAC7B,MAAM,WAAW,cAAc,QAAQ,WAAW,SAAS;AAC3D,SAAO;GACL;GACA;GACA,UAAU,aAAa;GACxB;GACD;;;;;;AAOJ,SAAgB,kBACd,SACA,WACA,UACoB;AACpB,QAAO,QAAQ,QAAQ,WAAW,CAAC,cAAc,QAAQ,WAAW,SAAS,CAAC;;AAOhF,SAAS,sBAAsB,UAA0B,QAA0B,UAA+B;AAEhH,KAAI,SAAS,aAAa,MAAO,QAAO;AAGxC,KAAI,SAAS,aAAa,OAAO,SAAU,QAAO;AAGlD,KAAI,CAAC,cAAc,SAAS,QAAQ,OAAO,OAAO,CAAE,QAAO;AAG3D,KAAI,CAAC,gBAAgB,SAAS,WAAW,SAAS,CAAE,QAAO;AAG3D,KAAI,SAAS,SAAS,CAAC,iBAAiB,SAAS,OAAO,OAAO,CAAE,QAAO;AAExE,QAAO;;AAGT,SAAS,cAAc,gBAAwB,cAA+B;AAE5E,KAAI,mBAAmB,aAAc,QAAO;AAM5C,QAF2B,eAAe,QAAQ,OAAO,IAAI,CAAC,QAAQ,OAAO,IAAI,KACxD,aAAa,QAAQ,OAAO,IAAI,CAAC,QAAQ,OAAO,IAAI;;AAI/E,SAAS,gBAAgB,WAAwC,UAA+B;AAC9F,KAAI,CAAC,aAAa,cAAc,yBAA0B,QAAO;AACjE,QAAO,UAAU,SAAS,SAAS;;AAGrC,SAAS,iBAAiB,OAA6C,QAAmC;AACxG,KAAI,MAAM,WAAW;EAEnB,MAAM,aAAa,OAAO,IAAI,cAAc,MAAM;EAClD,MAAM,aAAa,OAAO,IAAI,cAAc,MAAM;AAClD,MAAI,CAAC,cAAc,CAAC,WAAY,QAAO;;AAEzC,KAAI,MAAM,QAAQ;EAChB,MAAM,cAAc,OAAO,IAAI,WAAW,MAAM;EAChD,MAAM,cAAc,OAAO,IAAI,WAAW,MAAM;AAChD,MAAI,CAAC,eAAe,CAAC,YAAa,QAAO;;AAE3C,KAAI,MAAM;MAEJ,CADc,OAAO,OAAO,OAAO,IAAI,CAAC,MAAM,MAAM,MAAM,MAAM,QAAQ,CAC5D,QAAO;;AAEzB,KAAI,MAAM;MAEJ,CADc,OAAO,OAAO,OAAO,IAAI,CAAC,MAAM,MAAM,MAAM,MAAM,QAAQ,CAC5D,QAAO;;AAEzB,QAAO;;;;;ACvLT,SAAgB,WAAc,QAA8C;CAC1E,MAAM,SAA4B,EAAE;AACpC,MAAK,MAAM,OAAO,OAAO,KAAK,OAAO,CAAC,MAAM,CAC1C,QAAO,OAAO,OAAO;AAEvB,QAAO;;;AAIT,IAAa,kBAAb,MAA6B;CAC3B,sBAAc,IAAI,KAA0B;CAE5C,IAAI,YAAoB,MAAoB;EAC1C,IAAI,MAAM,KAAK,IAAI,IAAI,WAAW;AAClC,MAAI,CAAC,KAAK;AACR,yBAAM,IAAI,KAAK;AACf,QAAK,IAAI,IAAI,YAAY,IAAI;;AAE/B,MAAI,IAAI,KAAK;;CAGf,WAAqC;EACnC,MAAM,SAAmC,EAAE;AAC3C,OAAK,MAAM,CAAC,MAAM,UAAU,KAAK,IAC/B,QAAO,QAAQ,CAAC,GAAG,MAAM,CAAC,MAAM;AAElC,SAAO;;;;;ACNX,MAAa,gBAA2B;CACtC,UAAU;CACV,OAAO;CAEP,MAAM,gBAAgB,SAA0C;AAE9D,SAAO,qBADS,MAAM,KAAK,QAAQ,QAAQ,CACP;;CAGtC,MAAM,QAAQ,SAAsC;AAClD,YAAU,QAAQ,QAAQ;EAC1B,MAAM,aAAa,GAAG,eAAe,SAAS,GAAG,IAAI,YAAY,gBAAgB;AACjF,MAAI,CAAC,WACH,OAAM,IAAI,eACR,6BAA6B,WAC7B,8BAA8B,QAAQ,0EACvC;EAEH,MAAM,aAAa,GAAG,eAAe,YAAY,GAAG,IAAI,SAAS;EACjE,MAAM,eAAe,GAAG,2BAA2B,WAAW,QAAQ,GAAG,KAAK,QAAQ;EACtF,MAAM,UAAU,GAAG,cAAc,aAAa,WAAW,aAAa,QAAQ;EAC9E,MAAM,UAAU,QAAQ,gBAAgB;EAExC,MAAM,aAAa,kBAAkB,SAAS,QAAQ;EACtD,MAAM,kBAAkB,QAAQ,cAAc,WAAW;AACzD,MAAI,CAAC,gBACH,OAAM,IAAI,eACR,0BAA0B,cAC1B,oBAAoB,WAAW,2EAChC;EAEH,MAAM,eAAe,QAAQ,oBAAoB,gBAAgB;AACjE,MAAI,CAAC,aACH,OAAM,IAAI,eACR,mCACA,gBAAgB,WAAW,sGAC5B;EAEH,MAAM,kBAAkB,QAAQ,mBAAmB,aAAa;EAEhE,MAAM,UAAoC,EAAE;EAC5C,MAAM,aAA2C,EAAE;EACnD,MAAM,cAA4C,EAAE;EACpD,MAAM,QAAiC,EAAE;AAEzC,OAAK,MAAM,OAAO,iBAAiB;GACjC,MAAM,WAAW,aAAa,KAAK,QAAQ;GAC3C,MAAM,eAAe,SAAS,iBAAiB;AAC/C,OAAI,CAAC,gBAAgB,aAAa,WAAW,EAAG;GAChD,MAAM,OAAO,aAAa;GAE1B,MAAM,aAAa,SAAS,SAAS,KAAK,eAAe,CAAC,SAAS;AAEnE,OAAI,GAAG,mBAAmB,KAAK,CAC7B,SAAQ,SAAS,QAAQ;IAAE,GAAG,aAAa,UAAU,QAAQ;IAAE;IAAY;YAClE,GAAG,uBAAuB,KAAK,CACxC,YAAW,SAAS,QAAQ;IAAE,GAAG,iBAAiB,UAAU,QAAQ;IAAE;IAAY;YACzE,GAAG,uBAAuB,KAAK,CACxC,aAAY,SAAS,QAAQ;IAAE,GAAG,iBAAiB,UAAU,QAAQ;IAAE;IAAY;YAC1E,GAAG,kBAAkB,KAAK,CACnC,OAAM,SAAS,QAAQ;IAAE,GAAG,YAAY,UAAU,QAAQ;IAAE;IAAY;;AAM5E,4BAA0B,iBAAiB,SAAS,SAAS,QAAQ;EAErE,MAAM,UAAU,eAAe,iBAAiB,SAAS,SAAS,QAAQ;AAE1E,SAAO;GACL,UAAU;GACV,eAAe;GACf,8BAAa,IAAI,MAAM,EAAC,aAAa;GACrC,SAAS,WAAW,QAAQ;GAC5B,YAAY,WAAW,WAAW;GAClC,aAAa,WAAW,YAAY;GACpC,OAAO,WAAW,MAAM;GACxB,SAAS,WAAW,QAAQ;GAC7B;;CAEJ;AAED,SAAS,0BACP,iBACA,SACA,SACA,SACM;CAEN,MAAM,+BAAe,IAAI,KAAwB;AACjD,MAAK,MAAM,OAAO,iBAAiB;EACjC,MAAM,WAAW,aAAa,KAAK,QAAQ;AAE3C,MADc,SAAS,iBAAiB,EAC7B,MAAM,MAAM,GAAG,mBAAmB,EAAE,CAAC,CAC9C,cAAa,IAAI,SAAS,MAAM,SAAS;;CAI7C,MAAM,UAAU,CAAC,GAAG,aAAa,QAAQ,CAAC;CAC1C,MAAM,UAAU,IAAI,IAAI,aAAa,MAAM,CAAC;AAE5C,QAAO,QAAQ,SAAS,GAAG;EACzB,MAAM,MAAM,QAAQ,KAAK;EACzB,MAAM,OAAO,QAAQ,wBAAwB,IAAI;EACjD,MAAM,QAAQ,IAAI,iBAAiB;AACnC,MAAI,CAAC,SAAS,MAAM,WAAW,EAAG;AAElC,OAAK,MAAM,QAAQ,KAAK,eAAe,EAAE;GACvC,MAAM,YAAY,KAAK,iBAAiB;AACxC,OAAI,CAAC,aAAa,UAAU,WAAW,EAAG;GAC1C,MAAM,WAAW,UAAU;AAI3B,QADkB,GAAG,iBAAiB,SAAS,GAAG,GAAG,aAAa,SAAS,GAAG,KAAA,IAEjE,MAAM,MAAM,EAAE,SAAS,GAAG,WAAW,kBAAkB,EAAE,SAAS,GAAG,WAAW,iBAAiB,CAE5G;GAIF,MAAM,aADW,QAAQ,0BAA0B,MAAM,SAAS,CACtC,WAAW;AACvC,OAAI,CAAC,WAAY;GAEjB,MAAM,WAAW,WAAW;AAC5B,OAAI,QAAQ,IAAI,SAAS,CAAE;GAE3B,MAAM,eAAe,WAAW,iBAAiB;AACjD,OAAI,CAAC,cAAc,MAAM,MAAM,GAAG,mBAAmB,EAAE,CAAC,CAAE;AAG1D,WAAQ,IAAI,SAAS;GACrB,MAAM,aAAa,SAAS,SAAS,aAAa,GAAG,eAAe,CAAC,SAAS;AAC9E,WAAQ,YAAY;IAAE,GAAG,aAAa,YAAY,QAAQ;IAAE;IAAY;AACxE,WAAQ,KAAK,WAAW;;;;AAK9B,SAAS,kBAAkB,SAAiB,SAA6B;CACvE,MAAM,UAAU,QAAQ,SAAS,eAAe;AAChD,KAAI;EACF,MAAM,MAAM,KAAK,MAAM,aAAa,SAAS,QAAQ,CAAC;AAEtD,MAAI,IAAI,SAAS;GACf,MAAM,aACJ,OAAO,IAAI,YAAY,WACnB,IAAI,UACH,IAAI,QAAQ,MAAM,UAAU,IAAI,QAAQ,MAAM,WAAW,IAAI,QAAQ;AAC5E,OAAI,OAAO,eAAe,UAAU;IAClC,MAAM,WAAW,kBAAkB,SAAS,YAAY,QAAQ;AAChE,QAAI,SAAU,QAAO;;;AAIzB,MAAI,IAAI,MAAM;GACZ,MAAM,WAAW,kBAAkB,SAAS,IAAI,MAAM,QAAQ;AAC9D,OAAI,SAAU,QAAO;;SAEjB;CAKR,MAAM,WAAW,QAAQ,SAAS,eAAe;AACjD,KAAI,QAAQ,cAAc,SAAS,CAAE,QAAO;AAC5C,OAAM,IAAI,eACR,wEACA,wDAAwD,QAAQ,kEACjE;;AAGH,SAAS,kBAAkB,SAAiB,WAAmB,SAAyC;CAEtG,MAAM,aAAa;EACjB,QAAQ,SAAS,UAAU;EAC3B,QAAQ,SAAS,UAAU,QAAQ,SAAS,MAAM,CAAC;EACnD,QAAQ,SAAS,UAAU,QAAQ,SAAS,YAAY,CAAC;EAC1D;AACD,MAAK,MAAM,aAAa,WACtB,KAAI,QAAQ,cAAc,UAAU,CAAE,QAAO;;AAKjD,SAAS,aAAa,KAAgB,SAAoC;AACxE,KAAI,IAAI,QAAQ,GAAG,YAAY,MAC7B,QAAO,QAAQ,iBAAiB,IAAI;AAEtC,QAAO;;AAGT,SAAS,aAAa,KAAgB,SAAmC;CACvE,MAAM,OAAO,QAAQ,wBAAwB,IAAI;CACjD,MAAM,UAAuC,EAAE;CAC/C,MAAM,aAA0C,EAAE;CAClD,MAAM,oBAAgC,EAAE;CACxC,IAAI;CAGJ,MAAM,eAAe,IAAI,iBAAiB;AAC1C,KAAI;OACG,MAAM,QAAQ,aACjB,KAAI,GAAG,mBAAmB,KAAK,EAAE;GAI/B,MAAM,gBAAgB,GAAG,sBAAsB,KAAK;AACpD,OAAI,eAAe;IACjB,MAAM,UAAU,cAAc;AAC9B,QAAI,OAAO,YAAY,SACrB,sBAAqB,QAAQ,MAAM,IAAI;aAC9B,MAAM,QAAQ,QAAQ,CAC/B,sBACE,QACG,KAAK,MAAM,EAAE,KAAK,CAClB,KAAK,GAAG,CACR,MAAM,IAAI;QAEf,sBAAqB;;AAGzB,QAAK,MAAM,UAAU,KAAK,QACxB,KAAI,GAAG,yBAAyB,OAAO,CACrC,MAAK,MAAM,SAAS,OAAO,YAAY;IACrC,MAAM,EAAE,MAAM,WAAW,mBAAmB,qBAAqB,OAAO,MAAM,KAAK,SAAS,CAAC;IAC7F,MAAM,YAAY,MAAM,OAAO,QAAQ,aAAa,QAAQ,oBAAoB,MAAM,KAAK,CAAC,GAAG;AAC/F,sBAAkB,KAAK;KACrB,MAAM;KACN,MAAM;KACN,UAAU,CAAC,CAAC,MAAM,iBAAiB,CAAC,CAAC,MAAM;KAC3C,cAAc,iBAAiB,mBAAmB;KACnD,CAAC;;;;AASd,MAAK,MAAM,QAAQ,KAAK,eAAe,EAAE;EAEvC,MAAM,mBAAmB,KAAK,iBAAiB;AAC/C,MAAI,oBAAoB,iBAAiB,SAAS,GAAG;GACnD,MAAM,OAAO,iBAAiB;AAE9B,QADkB,GAAG,iBAAiB,KAAK,GAAG,GAAG,aAAa,KAAK,GAAG,KAAA,IAEzD,MAAM,MAAM,EAAE,SAAS,GAAG,WAAW,kBAAkB,EAAE,SAAS,GAAG,WAAW,iBAAiB,CAE5G;;EAIJ,MAAM,WAAW,QAAQ,0BAA0B,MAAM,aAAc,GAAG;EAC1E,MAAM,iBAAiB,SAAS,mBAAmB;AAEnD,MAAI,eAAe,SAAS,GAAG;AAC7B,OAAI,CAAC,QAAQ,KAAK,MAAO,SAAQ,KAAK,QAAQ,EAAE;AAEhD,QAAK,MAAM,OAAO,eAChB,SAAQ,KAAK,MAAM,KAAK;IACtB,MAAM,KAAK;IACX,QAAQ,IAAI,eAAe,CAAC,KAAK,MAAM,aAAa,GAAG,QAAQ,CAAC;IAChE,YAAY,QAAQ,aAAa,IAAI,eAAe,CAAC;IACrD,OAAO,QAAQ,aAAa,IAAI,eAAe,CAAC,CAAC,WAAW,WAAW;IACxE,CAAC;SAEC;GACL,MAAM,UAAU,QAAQ,aAAa,SAAS;GAC9C,MAAM,aAAa,kBAAkB,MAAM,MAAM;AAE/C,YADa,GAAG,iBAAiB,EAAE,GAAG,GAAG,aAAa,EAAE,GAAG,KAAA,IAC9C,MAAM,MAAM,EAAE,SAAS,GAAG,WAAW,gBAAgB;KAClE;AACF,cAAW,KAAK,QAAQ;IACtB,MAAM,KAAK;IACX,MAAM;IACN,UAAU,CAAC,CAAC;IACb;;;AAIL,QAAO;EACL,MAAM,IAAI;EACV,SAAS,WAAW,QAAQ;EAC5B,YAAY,WAAW,WAAW;EAClC;EACA,GAAI,uBAAuB,KAAA,KAAa,EAAE,oBAAoB;EAC/D;;AAGH,SAAS,aAAa,KAAgB,SAAmC;CACvE,MAAM,OAAO,IAAI,iBAAiB,GAAG;CACrC,MAAM,aAAa,QAAQ,GAAG,YAAY,KAAK,GAAG,CAAC,CAAC,KAAK,iBAAiB,CAAC,CAAC,KAAK,cAAc;CAC/F,MAAM,OAAO,QAAQ,0BAA0B,KAAK,KAAM;CAC1D,MAAM,EAAE,MAAM,mBAAmB,qBAAqB,MAAM,IAAI,KAAK;CACrE,MAAM,UAAU,QAAQ,aAAa,KAAK;CAK1C,IAAI;AACJ,KAAI,eACF,gBAAe;MACV;EACL,MAAM,eAAe,QAAQ,0BAA0B,KAAK,KAAM;EAClE,MAAM,eAAe,aAAa,oBAAoB,KAAK,aAAa,UAAU,GAAG,GAAG,UAAU,YAAY;EAC9G,MAAM,cAAc;GAClB;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACD,CAAC,SAAS,QAAQ;AACnB,MAAI,gBAAgB,CAAC,eAAe,CAAC,QAAQ,WAAW,WAAW,CACjE,gBAAe;MAEf,gBAAe;;AAInB,QAAO;EACL;EACA,MAAM;EACN,UAAU;EACV;EACD;;AAGH,SAAS,qBACP,MACA,UAC2C;AAC3C,KAAI,CAAC,QAAQ,CAAC,GAAG,YAAY,KAAK,CAAE,QAAO;EAAE,MAAM;EAAU,gBAAgB;EAAO;AACpF,KAAI,GAAG,aAAa,KAAK,KAAK,CAAE,QAAO;EAAE,MAAM,KAAK,KAAK;EAAM,gBAAgB;EAAO;CAGtF,MAAM,QADuB,KAAK,OACC,YAAY,QAAQ,KAAK,IAAI;CAChE,MAAM,SAAS,QAAQ,IAAI,OAAO,MAAM,GAAG;AAE3C,KAAI,GAAG,uBAAuB,KAAK,KAAK,CAAE,QAAO;EAAE,MAAM,UAAU;EAAU,gBAAgB;EAAM;AACnG,KAAI,GAAG,sBAAsB,KAAK,KAAK,CAAE,QAAO;EAAE,MAAM,OAAO;EAAU,gBAAgB;EAAO;AAEhG,QAAO;EAAE,MAAM;EAAU,gBAAgB;EAAO;;AAGlD,SAAS,iBAAiB,KAAgB,SAAuC;CAC/E,MAAM,OAAO,QAAQ,wBAAwB,IAAI;CACjD,MAAM,SAAmC,EAAE;CAC3C,MAAM,eAAyB,EAAE;CAGjC,MAAM,eAAe,IAAI,iBAAiB;AAC1C,KAAI;OACG,MAAM,QAAQ,aACjB,KAAI,GAAG,uBAAuB,KAAK,IAAI,KAAK,gBAC1C,MAAK,MAAM,UAAU,KAAK,gBACxB,MAAK,MAAM,YAAY,OAAO,MAC5B,cAAa,KAAK,SAAS,SAAS,CAAC;;AAO/C,MAAK,MAAM,QAAQ,KAAK,eAAe,EAAE;EACvC,MAAM,WAAW,QAAQ,0BAA0B,MAAM,aAAc,GAAG;EAC1E,MAAM,WAAW,KAAK,iBAAiB,GAAG;EAC1C,MAAM,aAAa,YAAY,GAAG,oBAAoB,SAAS,GAAG,CAAC,CAAC,SAAS,gBAAgB;EAC7F,IAAI,UAAU,QAAQ,aAAa,SAAS;AAC5C,MAAI,WACF,WAAU,eAAe,QAAQ;AAEnC,SAAO,KAAK,QAAQ;GAClB,MAAM,KAAK;GACX,MAAM;GACN,UAAU;GACX;;AAMH,KAAI;OACG,MAAM,QAAQ,aACjB,KAAI,GAAG,uBAAuB,KAAK;QAC5B,MAAM,UAAU,KAAK,QACxB,KAAI,GAAG,oBAAoB,OAAO,IAAI,OAAO,MAAM;IACjD,MAAM,aAAa,OAAO,KAAK,SAAS;AACxC,QAAI,CAAC,OAAO,aAAa;KACvB,MAAM,aAAa,OAAO,OAAO,QAAQ,aAAa,QAAQ,oBAAoB,OAAO,KAAK,CAAC,GAAG;KAClG,MAAM,QAAQ,CAAC,CAAC,OAAO;AACvB,YAAO,cAAc;MACnB,MAAM;MACN,MAAM,QAAQ,eAAe,WAAW,GAAG;MAC3C,UAAU;MACX;;;;;AAQb,QAAO;EACL,MAAM,IAAI;EACV,QAAQ,WAAW,OAAO;EAC1B,SAAS,aAAa,MAAM;EAC7B;;AAGH,SAAS,iBAAiB,KAAgB,SAAuC;CAC/E,MAAM,OAAO,QAAQ,wBAAwB,IAAI;AACjD,QAAO;EACL,MAAM,IAAI;EACV,OAAO,QAAQ,aAAa,MAAM,KAAA,GAAW,GAAG,gBAAgB,cAAc,GAAG,gBAAgB,aAAa;EAC/G;;AAGH,SAAS,YAAY,KAAgB,SAAkC;CACrE,MAAM,UAA2C,EAAE;CACnD,MAAM,OAAO,QAAQ,wBAAwB,IAAI;AAEjD,KAAI,KAAK,SAAS;OACX,MAAM,cAAc,KAAK,MAC5B,KAAI,WAAW,QAAQ;GACrB,MAAM,aAAa,QAAQ,iBAAiB,WAAW,OAAO,iBAAiB,CAAE,GAAoB;AACrG,OAAI,eAAe,KAAA,EACjB,SAAQ,WAAW,OAAO,QAAQ;;;AAM1C,QAAO;EACL,MAAM,IAAI;EACV,SAAS,WAAW,QAAQ;EAC7B;;AAGH,SAAS,eACP,WACA,SACA,SACA,SAC0B;CAC1B,MAAM,UAAoC,EAAE;CAC5C,MAAM,0BAAU,IAAI,KAAa;CAEjC,SAAS,KAAK,YAAiC;EAC7C,MAAM,UAAU,WAAW;AAC3B,MAAI,QAAQ,IAAI,QAAQ,CAAE;AAC1B,UAAQ,IAAI,QAAQ;EAEpB,MAAM,UAAU,SAAS,SAAS,QAAQ;EAC1C,MAAM,eAAe,QAAQ,oBAAoB,WAAW;AAC5D,MAAI,cAAc;GAChB,MAAM,QAAQ,QAAQ,mBAAmB,aAAa,CAAC,KAAK,MAAM,EAAE,KAAK;AACzE,OAAI,MAAM,SAAS,EACjB,SAAQ,WAAW,MAAM,MAAM;;AAInC,OAAK,MAAM,QAAQ,WAAW,WAC5B,KAAI,GAAG,oBAAoB,KAAK,IAAI,KAAK,mBAAmB,GAAG,gBAAgB,KAAK,gBAAgB,EAAE;GACpG,MAAM,SAAS,KAAK,gBAAgB;GACpC,MAAM,WAAW,kBAAkB,KAAK,QAAQ,QAAQ,EAAE,QAAQ,QAAQ;AAC1E,OAAI,UAAU;IACZ,MAAM,aAAa,QAAQ,cAAc,SAAS;AAClD,QAAI,WACF,MAAK,WAAW;;;;AAO1B,MAAK,UAAU;AACf,QAAO;;AAGT,SAAS,eAAe,SAAyB;AAC/C,QAAO,QAAQ,QAAQ,sBAAsB,GAAG,CAAC,QAAQ,sBAAsB,GAAG;;;;;;;;AClcpF,MAAM,YAAY,IAAI,QAAQ;AAC9B,UAAU,YAAY,WAAW,SAAS;AAM1C,SAAgB,aAAa,KAAuB;CAClD,MAAM,UAAoB,EAAE;CAC5B,IAAI;AACJ,KAAI;AACF,YAAU,YAAY,IAAI;SACpB;AACN,SAAO;;AAET,MAAK,MAAM,SAAS,SAAS;EAC3B,MAAM,WAAW,KAAK,KAAK,MAAM;EACjC,IAAI;AACJ,MAAI;AACF,UAAO,SAAS,SAAS;UACnB;AACN;;AAEF,MAAI,KAAK,aAAa,EAAE;AACtB,OAAI,MAAM,WAAW,IAAI,IAAI,UAAU,YAAY,UAAU,WAAW,UAAU,OAAQ;AAC1F,WAAQ,KAAK,GAAG,aAAa,SAAS,CAAC;aAC9B,MAAM,SAAS,OAAO,CAC/B,SAAQ,KAAK,SAAS;;AAG1B,QAAO,QAAQ,MAAM;;AAQvB,SAAS,YAAY,aAAiC;CACpD,MAAM,yBAAS,IAAI,KAAqB;CACxC,IAAI,aAAa;CAEjB,MAAM,QAAQ,YAAY,MAAM,KAAK;AACrC,MAAK,MAAM,QAAQ,OAAO;EAExB,MAAM,aAAa,KAAK,MAAM,2BAA2B;AACzD,MAAI,WACF,QAAO,IAAI,WAAW,IAAI,WAAW,GAAG;EAG1C,MAAM,cAAc,KAAK,MAAM,kBAAkB;AACjD,MAAI,YACF,cAAa,YAAY;;AAI7B,QAAO;EAAE;EAAQ;EAAY;;;AAI/B,SAAS,eAAe,MAAqC;CAE3D,IAAI,UAAU,KAAK;AACnB,KAAI,WAAW,QAAQ,SAAS,aAAa,QAAQ,KAAK,WAAW,MAAM,CACzE,QAAO,YAAY,QAAQ,KAAK;AAElC,QAAO;;AAGT,SAAS,cAAc,MAAsD;AAC3E,MAAK,MAAM,SAAS,KAAK,SACvB,KAAI,MAAM,SAAS,uBAAuB;EACxC,MAAM,OAAO,MAAM,KAAK,aAAa;AACrC,MAAI,SAAS,SAAU,QAAO;AAC9B,MAAI,SAAS,YAAa,QAAO;AACjC,MAAI,SAAS,UAAW,QAAO;;AAGnC,QAAO;;AAGT,SAAS,eAAe,MAA2B;AACjD,MAAK,MAAM,SAAS,KAAK,SACvB,KAAI,MAAM,SAAS,kBAAmB,QAAO;AAE/C,QAAO;;;AAIT,SAAS,kBAAkB,MAA4B;CACrD,MAAM,SAAmB,EAAE;AAG3B,MAAK,MAAM,YAAY,KAAK,kBAAkB,4BAA4B,EAAE;EAC1E,MAAM,UAAU,SAAS,cAAc,QAAQ,MAAM,EAAE,SAAS,qBAAqB,EAAE,SAAS,SAAS;AAEzG,MAAI,QAAQ,WAAW,GAAG;GACxB,MAAM,cAAc,QAAQ,GAAG,cAAc,MAAM,MAAM,EAAE,SAAS,iBAAiB;AACrF,OAAI,YACF,QAAO,KAAK,YAAY,KAAK;;;AAInC,QAAO;;;AAIT,SAAS,kBAAkB,cAAkE;CAC3F,MAAM,WAAW,aAAa,cAAc,MAAM,MAAM,EAAE,SAAS,OAAO;AAC1E,KAAI,CAAC,SAAU,QAAO;CAEtB,MAAM,YAAY,SAAS;AAG3B,KAAI,cAAc,yBAAyB,cAAc,2BAA4B,QAAO;CAG5F,MAAM,YAAY,aAAa,cAAc,MAAM,MAAM,EAAE,SAAS,OAAO;AAC3E,KAAI,CAAC,UAAW,QAAO;AAGvB,KAAI,UAAU,SAAS,mBAAmB;EACxC,MAAM,cAAc,UAAU,cAAc,MAAM,MAAM,EAAE,SAAS,iBAAiB;AACpF,SAAO;GAAE,MAAM;GAAW,OAAO,cAAc,YAAY,OAAO;GAAI;;AAExE,KAAI,UAAU,SAAS,UAAU;EAC/B,MAAM,cAAc,UAAU,cAAc,MAAM,MAAM,EAAE,SAAS,iBAAiB;AACpF,SAAO;GAAE,MAAM;GAAW,OAAO,cAAc,YAAY,OAAO;GAAI;;AAIxE,QAAO;EAAE,MAAM;EAAW,OAAO,UAAU;EAAM;;AAOnD,SAASA,eAAa,WAAoC;CACxD,MAAM,UAAuB,EAAE;AAE/B,MAAK,MAAM,SAAS,UAAU,eAAe;AAC3C,MAAI,MAAM,SAAS,qBAAsB;EAEzC,MAAM,WAAW,MAAM,kBAAkB,OAAO;AAChD,MAAI,CAAC,SAAU;EACf,MAAM,aAAa,SAAS;AAG5B,MAAI,WAAW,WAAW,KAAK,IAAI,eAAe,cAAe;EAEjE,MAAM,aAAa,cAAc,MAAM;EACvC,MAAM,WAAW,eAAe,MAAM;EAGtC,MAAM,UAAU,eAAe,MAAM;EAGrC,MAAM,SAAqB,EAAE;EAC7B,MAAM,aAAa,MAAM,kBAAkB,aAAa;AACxD,MAAI,WACF,MAAK,MAAM,aAAa,WAAW,eAAe;AAChD,OAAI,UAAU,SAAS,mBAAoB;GAE3C,MAAM,gBAAgB,UAAU,cAAc,MAAM,MAAM,EAAE,SAAS,gBAAgB;AACrF,OAAI,CAAC,cAAe;GAEpB,MAAM,YAAY,cAAc,KAAK,QAAQ,OAAO,GAAG;GAGvD,IAAI,YAAY;GAChB,MAAM,WAAW,UAAU,kBAAkB,OAAO;AACpD,OAAI,SACF,aAAY,SAAS;AAGvB,OAAI,CAAC,aAAa,QAChB,aAAY,QAAQ,OAAO,IAAI,UAAU,IAAI;AAE/C,OAAI,CAAC,UACH,aAAY;GAKd,MAAM,aADc,UAAU,kBAAkB,gBAAgB,KAC7B;AAEnC,UAAO,KAAK;IACV,MAAM;IACN,MAAM;IACN,UAAU;IACX,CAAC;;EAKN,IAAI,aAAa;EACjB,MAAM,iBAAiB,MAAM,kBAAkB,cAAc;AAC7D,MAAI,eACF,cAAa,eAAe;AAE9B,MAAI,CAAC,cAAc,QACjB,cAAa,QAAQ,cAAc;AAErC,MAAI,CAAC,WACH,cAAa;AAGf,UAAQ,KAAK;GACX,MAAM;GACN;GACA;GACA;GACA;GACD,CAAC;;AAGJ,QAAO;;AAOT,SAASC,kBAAgB,WAAsC;CAC7D,MAAM,aAA4B,EAAE;AAEpC,MAAK,MAAM,SAAS,UAAU,eAAe;AAC3C,MAAI,MAAM,SAAS,uBAAwB;EAE3C,MAAM,aAAa,cAAc,MAAM;AAGvC,OAAK,MAAM,eAAe,MAAM,eAAe;AAC7C,OAAI,YAAY,SAAS,mBAAoB;GAC7C,MAAM,cAAc,YAAY,cAAc,MAAM,MAAM,EAAE,SAAS,gBAAgB;AACrF,OAAI,CAAC,YAAa;GAElB,MAAM,WAAW,YAAY,KAAK,QAAQ,OAAO,GAAG;GAGpD,IAAI,WAAW;GACf,MAAM,WAAW,MAAM,cAAc,MAClC,MACC,EAAE,SAAS,gBACX,EAAE,SAAS,gBACX,EAAE,SAAS,mBACX,EAAE,SAAS,iBACd;AACD,OAAI,SACF,YAAW,SAAS;AAGtB,cAAW,KAAK;IACd,MAAM;IACN,MAAM;IACN;IACD,CAAC;;;AAIN,QAAO;;AAOT,SAAS,eAAe,WAAsC;CAC5D,MAAM,YAA2B,EAAE;AAEnC,MAAK,MAAM,SAAS,UAAU,eAAe;AAC3C,MAAI,MAAM,SAAS,oBAAqB;AAExC,OAAK,MAAM,gBAAgB,MAAM,eAAe;AAC9C,OAAI,aAAa,SAAS,gBAAiB;GAE3C,MAAM,SAAS,kBAAkB,aAAa;AAC9C,OAAI,OACF,WAAU,KAAK,OAAO;;;AAK5B,QAAO;;AAOT,SAAS,wBAAwB,WAAiC;AAChE,MAAK,MAAM,SAAS,UAAU,eAAe;AAC3C,MAAI,MAAM,SAAS,oBAAqB;AAExC,OAAK,MAAM,gBAAgB,MAAM,eAAe;AAC9C,OAAI,aAAa,SAAS,gBAAiB;GAE3C,MAAM,WAAW,aAAa,cAAc,MAAM,MAAM,EAAE,SAAS,OAAO;AAC1E,OAAI,CAAC,YAAY,SAAS,SAAS,sBAAuB;GAE1D,MAAM,YAAY,aAAa,cAAc,MAAM,MAAM,EAAE,SAAS,4BAA4B;AAChG,OAAI,CAAC,UAAW;AAEhB,UAAO,kBAAkB,UAAU;;;AAGvC,QAAO,EAAE;;AAOX,SAASC,mBAAiB,MAA2B;AACnD,MAAK,MAAM,QAAQ,KAAK,SAAS,cAC/B,KAAI,KAAK,SAAS,wBAAwB;EACxC,MAAM,WAAW,KAAK,kBAAkB,OAAO;AAC/C,SAAO,WAAW,SAAS,OAAO;;AAGtC,QAAO;;AAOT,SAAS,uBAAuB,MAAmB,YAAoB,WAA+B;CACpG,MAAM,UAAsB,EAAE;AAE9B,MAAK,MAAM,QAAQ,KAAK,SAAS,kBAAkB,oBAAoB,EAAE;EACvE,MAAM,WAAW,KAAK,kBAAkB,OAAO;AAC/C,MAAI,CAAC,SAAU;EAGf,IAAI,cAA6B;EACjC,MAAM,aAAa,KAAK,cAAc,MAAM,MAAM,EAAE,SAAS,cAAc;AAC3E,MAAI,YAAY;GACd,MAAM,eAAe,WAAW,cAAc,MAAM,MAAM,EAAE,SAAS,UAAU,EAAE,SAAS,iBAAiB;AAC3G,OAAI,cAAc;IAGhB,MAAM,QADW,aAAa,KAAK,QAAQ,OAAO,GAAG,CAC9B,MAAM,KAAK;AAClC,kBAAc,MAAM,MAAM,SAAS;;;EAIvC,MAAM,WAAW,KAAK,kBAAkB,OAAO;AAC/C,MAAI,CAAC,SAAU;EAEf,MAAM,UAAUF,eAAa,SAAS;EACtC,MAAM,aAAaC,kBAAgB,SAAS;EAC5C,MAAM,YAAY,eAAe,SAAS;EAC1C,MAAM,qBAAqB,wBAAwB,SAAS;EAE5D,MAAM,uBAAuB,QAAQ,MAAM,MAAM,EAAE,SAAS,2BAA2B,EAAE,SAAS;AAElG,UAAQ,KAAK;GACX,MAAM,SAAS;GACf;GACA,SAAS;GACT,aAAa;GACb;GACA;GACA;GACA;GACA;GACA;GACD,CAAC;;AAGJ,QAAO;;AAGT,SAAS,2BAA2B,MAAmB,YAAoB,WAA+B;CACxG,MAAM,aAAyB,EAAE;AAEjC,MAAK,MAAM,QAAQ,KAAK,SAAS,kBAAkB,wBAAwB,EAAE;EAC3E,MAAM,WAAW,KAAK,kBAAkB,OAAO;AAC/C,MAAI,CAAC,SAAU;EAEf,MAAM,WAAW,KAAK,kBAAkB,OAAO;AAC/C,MAAI,CAAC,SAAU;EAEf,MAAM,UAAUD,eAAa,SAAS;AAEtC,aAAW,KAAK;GACd,MAAM,SAAS;GACf;GACA,SAAS;GACT,aAAa;GACb;GACA,YAAY,EAAE;GACd,WAAW,EAAE;GACb,oBAAoB,EAAE;GACtB,sBAAsB;GACtB;GACD,CAAC;;AAGJ,QAAO;;AAOT,SAAS,sBAAsB,MAAmB,YAAoB,WAA+B;CACnG,MAAM,QAAoB,EAAE;AAE5B,MAAK,MAAM,QAAQ,KAAK,SAAS,kBAAkB,mBAAmB,EAAE;EACtE,MAAM,WAAW,KAAK,kBAAkB,OAAO;AAC/C,MAAI,CAAC,SAAU;EAEf,MAAM,WAAW,KAAK,kBAAkB,OAAO;AAC/C,MAAI,CAAC,SAAU;EAGf,MAAM,YAA2B,EAAE;AACnC,OAAK,MAAM,SAAS,SAAS,eAAe;AAC1C,OAAI,MAAM,SAAS,YAAa;GAChC,MAAM,eAAe,MAAM,kBAAkB,OAAO;AACpD,OAAI,CAAC,aAAc;GAGnB,IAAI,QAAQ,aAAa;GACzB,MAAM,YAAY,MAAM,cAAc,MACnC,MAAM,EAAE,SAAS,qBAAqB,EAAE,SAAS,YAAY,EAAE,SAAS,UAC1E;AACD,OAAI,WAAW;IACb,MAAM,cAAc,UAAU,cAAc,MAAM,MAAM,EAAE,SAAS,iBAAiB;AACpF,YAAQ,cAAc,YAAY,OAAO,UAAU;;AAGrD,aAAU,KAAK;IAAE,MAAM,aAAa;IAAM;IAAO,CAAC;;EAGpD,MAAM,UAAUA,eAAa,SAAS;AAEtC,QAAM,KAAK;GACT,MAAM,SAAS;GACf;GACA,SAAS;GACT,aAAa;GACb;GACA,YAAY,EAAE;GACd;GACA,oBAAoB,EAAE;GACtB,sBAAsB;GACtB;GACD,CAAC;;AAGJ,QAAO;;;AAYT,SAAgB,aAAa,UAAkB,SAAgC;CAC7E,MAAM,SAAS,aAAa,UAAU,QAAQ;CAC9C,MAAM,UAAU,SAAS,SAAS,SAAS;CAC3C,MAAM,OAAOG,YAAU,WAAW,OAAO;CACzC,MAAM,YAAYD,mBAAiB,KAAK;CAExC,MAAM,aAAa,uBAAuB,MAAM,SAAS,UAAU;CACnE,MAAM,iBAAiB,2BAA2B,MAAM,SAAS,UAAU;CAC3E,MAAM,YAAY,sBAAsB,MAAM,SAAS,UAAU;AAEjE,QAAO,EACL,SAAS;EAAC,GAAG;EAAY,GAAG;EAAgB,GAAG;EAAU,EAC1D;;;;;AC1fH,MAAM,yBAAmC,EAAE;;AAG3C,MAAME,4BAA0B,CAAC,aAAa,cAAc;;AAG5D,SAAS,gBAAgB,KAAe,eAAqC;AAC3E,QAAO,CAAC,CAAC,IAAI,WAAW,cAAc,IAAI,IAAI,QAAQ,IAAI,IAAI,mBAAmB,SAAS;;;AAI5F,SAAS,YAAY,KAAwB;AAC3C,KAAI,IAAI,YAAa,QAAO;AAC5B,KAAI,IAAI,UAAU,WAAW,EAAG,QAAO;AAGvC,QADsB,IAAI,QAAQ,QAAQ,MAAM,EAAE,eAAe,YAAY,EAAE,SAAS,cAAc,CACjF,WAAW,KAAK,IAAI,WAAW,WAAW,KAAK,CAAC,IAAI;;;AAI3E,SAASC,mBAAiB,KAAe,gBAAsC;AAC7E,KAAI,CAAC,IAAI,QAAS,QAAO;AACzB,QAAO,eAAe,IAAI,IAAI,QAAQ;;AAOxC,SAAgBC,eACd,YACA,OAMA;CACA,MAAM,gBAAgB,IAAI,IAAI,OAAO,oBAAoB,uBAAuB;CAChF,MAAM,iBAAiB,IAAI,IAAI,OAAO,wBAAwBF,0BAAwB;CAEtF,MAAM,UAAoC,EAAE;CAC5C,MAAM,aAA2C,EAAE;CACnD,MAAM,QAAiC,EAAE;CAEzC,MAAM,YAAY,IAAI,iBAAiB;AAEvC,MAAK,MAAM,OAAO,WAChB,KAAI,IAAI,aAAa;EAEnB,MAAM,SAAmC,EAAE;AAC3C,OAAK,MAAM,UAAU,IAAI,SAAS;AAChC,OAAI,OAAO,eAAe,SAAU;AACpC,UAAO,OAAO,QAAQ;IACpB,MAAM,OAAO;IACb,MAAM,OAAO,cAAc;IAC3B,UAAU;IACX;;AAEH,aAAW,IAAI,QAAQ;GACrB,MAAM,IAAI;GACV,YAAY,IAAI;GAChB,QAAQ,WAAW,OAAO;GAC1B,SAAS,EAAE;GACZ;AACD,YAAU,IAAI,IAAI,YAAY,IAAI,KAAK;YAC9B,gBAAgB,KAAK,cAAc,EAAE;EAG9C,MAAM,SAAmC,EAAE;AAC3C,OAAK,MAAM,QAAQ,IAAI,mBACrB,QAAO,QAAQ;GACb,MAAM;GACN,MAAM;GACN,UAAU;GACX;AAEH,aAAW,IAAI,QAAQ;GACrB,MAAM,IAAI;GACV,YAAY,IAAI;GAChB;GACA,SAAS,IAAI,UAAU,CAAC,IAAI,QAAQ,GAAG,EAAE;GACzC,GAAI,IAAI,uBAAuB,EAAE,sBAAsB,MAAM,GAAG,EAAE;GACnE;AACD,YAAU,IAAI,IAAI,YAAY,IAAI,KAAK;YAC9B,YAAY,IAAI,EAAE;EAE3B,MAAM,UAA2C,EAAE;AACnD,OAAK,MAAM,YAAY,IAAI,UACzB,SAAQ,SAAS,QAAQ,SAAS;AAEpC,QAAM,IAAI,QAAQ;GAChB,MAAM,IAAI;GACV,YAAY,IAAI;GAChB,SAAS,WAAW,QAAQ;GAC7B;AACD,YAAU,IAAI,IAAI,YAAY,IAAI,KAAK;QAClC;EAEL,MAAM,aAA0C,EAAE;EAClD,MAAM,aAA0C,EAAE;AAGlD,OAAK,MAAM,UAAU,IAAI,SAAS;AAChC,OAAI,OAAO,eAAe,SAAU;GAEpC,MAAM,SAAqB,OAAO,OAAO,KAAK,OAAO;IACnD,MAAM,EAAE;IACR,MAAM,EAAE;IACR,UAAU,EAAE;IACZ,cAAc;IACf,EAAE;AAEH,OAAI,CAAC,WAAW,OAAO,MAAO,YAAW,OAAO,QAAQ,EAAE;AAC1D,cAAW,OAAO,MAAM,KAAK;IAC3B,MAAM,OAAO;IACb;IACA,YAAY,OAAO,cAAc;IACjC,OAAO;IACR,CAAC;;AAIJ,OAAK,MAAM,QAAQ,IAAI,YAAY;AACjC,OAAI,KAAK,eAAe,SAAU;AAClC,cAAW,KAAK,QAAQ;IACtB,MAAM,KAAK;IACX,MAAM,KAAK;IACX,UAAU;IACX;;AAIH,MACE,OAAO,KAAK,WAAW,CAAC,SAAS,KACjC,OAAO,KAAK,WAAW,CAAC,SAAS,KACjCC,mBAAiB,KAAK,eAAe,EACrC;AACA,WAAQ,IAAI,QAAQ;IAClB,MAAM,IAAI;IACV,YAAY,IAAI;IAChB,SAAS,WAAW,WAAW;IAC/B,YAAY,WAAW,WAAW;IAClC,mBAAmB,EAAE;IACtB;AACD,aAAU,IAAI,IAAI,YAAY,IAAI,KAAK;;;CAK7C,MAAM,UAAU,UAAU,UAAU;AAEpC,QAAO;EACL,SAAS,WAAW,QAAQ;EAC5B,YAAY,WAAW,WAAW;EAClC,OAAO,WAAW,MAAM;EACxB,SAAS,WAAW,QAAQ;EAC7B;;;;;;;;;;;;;ACjKH,MAAM,iBAAiB,IAAI,IAAI,CAAC,SAAS,QAAQ,CAAC;AAElD,MAAM,WAA0B;CAC9B,cAAc,MAA6B;AAEzC,MAAI,KAAK,WAAW,IAAI,CAAE,QAAO,KAAK,MAAM,EAAE;EAE9C,MAAM,QAAQ,KAAK,MAAM,IAAI,CAAC,QAAQ,MAAM,EAAE,MAAM,CAAC,aAAa,KAAK,OAAO;AAC9E,MAAI,MAAM,SAAS,KAAK,MAAM,IAAI,CAAC,OAAQ,QAAO,MAAM,KAAK,IAAI;AACjE,SAAO;;CAET,yBAAyB,GAAW,GAAoB;AACtD,SAAO,gCAAgC,MAAM,GAAG,EAAE;;CAEpD,eAAe,GAAW,GAAoB;EAE5C,MAAM,aAAa,MACjB,EACG,MAAM,IAAI,CACV,KAAK,MAAM,EAAE,MAAM,CAAC,CACpB,MAAM,CACN,KAAK,IAAI;AACd,SAAO,MAAM,KAAK,UAAU,EAAE,KAAK,UAAU,EAAE;;CAEjD,mBAAmB,OAAwB;AACzC,SAAO;;CAET,qBAAqB,MAAuB;AAC1C,SAAO,SAAS,WAAW,SAAS;;CAEtC,0BAA0B;CAC1B,sBAAsB,YAAmC;EAEvD,MAAM,WAAW,KAAK,cAAc,WAAW,IAAI;AACnD,MAAI;GAAC;GAAU;GAAO;GAAS;GAAQ;GAAQ;GAAS;GAAQ,CAAC,SAAS,SAAS,CAAE,QAAO;AAC5F,SAAO,SAAS,QAAQ,OAAO,GAAG;;CAEpC,qBAAqB,WAAkC;EACrD,MAAM,WAAW,KAAK,cAAc,UAAU,IAAI;AAClD,MAAI;GAAC;GAAU;GAAO;GAAS;GAAQ;GAAQ;GAAS;GAAS;GAAQ;GAAW,CAAC,SAAS,SAAS,CACrG,QAAO;AAET,SAAO,SAAS,QAAQ,OAAO,GAAG;;CAEpC,qBAAqB,cAAsB,WAA4B;AAErE,SAAO,aAAa,aAAa,KAAK,UAAU,aAAa;;CAE/D,kBAAkB,YAA8B;AAC9C,SAAO,EAAE;;CAGX,sBACE,UACA,WACA,mBACS;AAgBT,MAAI,EAXF,SAAS,eAAe,UAAU,cAClC,SAAS,eAAe,WACxB,UAAU,eAAe,WACxB,SAAS,eAAe,UAAU,UAAU,eAAe,UAC3D,SAAS,eAAe,WAAW,UAAU,eAAe,WAKjD,SAAS,WAAW,SAAS,eAAe,IAAI,UAAU,WAAW,SAAS,eAAe,EAErF,QAAO;AAK7B,MAAI,SAAS,OAAO,WAAW,UAAU,OAAO,QAAQ;GACtD,IAAI,gBAAgB;AACpB,QAAK,IAAI,IAAI,GAAG,IAAI,SAAS,OAAO,QAAQ,IAC1C,KAAI,SAAS,OAAO,GAAG,SAAS,UAAU,OAAO,GAAG,MAAM;AACxD,oBAAgB;AAChB;;AAGJ,OAAI,cAAe,QAAO;;AAQ5B,MAD0B,UAAU,OAAO,MAAM,MAAM,eAAe,IAAI,EAAE,KAAK,CAAC,CAC3D,QAAO;AAI9B,MAAI,SAAS,OAAO,UAAU,KAAK,UAAU,OAAO,UAAU,GAAG;GAE/D,IAAI,YAAY;GAChB,MAAM,SAAS,KAAK,IAAI,SAAS,OAAO,QAAQ,UAAU,OAAO,OAAO;AACxE,QAAK,IAAI,IAAI,GAAG,IAAI,QAAQ,IAC1B,KAAI,SAAS,OAAO,GAAG,SAAS,UAAU,OAAO,GAAG,MAAM;AACxD,gBAAY;AACZ;;AAIJ,OAAI,WAAW;IACb,MAAM,cAAc,UAAU,OAAO,MAAM,OAAO,CAAC,OAAO,MAAM,EAAE,SAAS;IAC3E,MAAM,cAAc,SAAS,OAAO,MAAM,OAAO,CAAC,OAAO,MAAM,EAAE,SAAS;AAC1E,QAAI,eAAe,YAAa,QAAO;;;AAI3C,SAAO;;CAGT,kBAAkB,CAAC,qBAAqB;CACxC,sBAAsB,CAAC,aAAa,cAAc;CACnD;;AAOD,SAAgB,mBAAmB,eAAmD;CACpF,MAAM,cAA6B,gBAAgB;EAAE,GAAG;EAAU,GAAG;EAAe,GAAG;AAEvF,QAAO;EACL,UAAU;EACV,OAAO;EAEP,MAAM,gBAAgB,SAA0C;AAE9D,UAAO,qBADS,MAAM,KAAK,QAAQ,QAAQ,CACP;;EAGtC,MAAM,QAAQ,SAAsC;GAElD,IAAI;GACJ,MAAM,UAAU,QAAQ,SAAS,MAAM;GACvC,MAAM,UAAU,QAAQ,SAAS,MAAM;AAEvC,OAAI;AACF,aAAS,QAAQ;AACjB,gBAAY;WACN;AACN,QAAI;AACF,cAAS,QAAQ;AACjB,iBAAY;YACN;AACN,WAAM,IAAI,eACR,sCAAsC,WACtC,mGACD;;;GAIL,MAAM,WAAW,aAAa,UAAU;AACxC,OAAI,SAAS,WAAW,EACtB,OAAM,IAAI,eACR,0BAA0B,aAC1B,yDACD;GAGH,MAAM,aAAyB,EAAE;AAEjC,QAAK,MAAM,YAAY,UAAU;IAC/B,MAAM,SAAS,aAAa,UAAU,QAAQ;AAC9C,eAAW,KAAK,GAAG,OAAO,QAAQ;;GAGpC,MAAM,EAAE,SAAS,YAAY,OAAO,YAAYE,eAAa,YAAY,YAAY;AAErF,UAAO;IACL,UAAU;IACV,eAAe;IACf,8BAAa,IAAI,MAAM,EAAC,aAAa;IACrC,SAAS,WAAW,QAAQ;IAC5B,YAAY,WAAW,WAAW;IAClC,aAAa,EAAE;IACf,OAAO,WAAW,MAAM;IACxB,SAAS,WAAW,QAAQ;IAC7B;;EAEJ;;;AAIH,MAAa,eAA0B,oBAAoB;;;;ACjK3D,MAAM,eAAe,IAAI,QAAQ;AACjC,aAAa,YAAY,OAAO;AAMhC,SAAgB,gBAAgB,KAAuB;CACrD,MAAM,UAAoB,EAAE;CAC5B,IAAI;AACJ,KAAI;AACF,YAAU,YAAY,IAAI;SACpB;AACN,SAAO;;AAET,MAAK,MAAM,SAAS,SAAS;EAC3B,MAAM,WAAW,KAAK,KAAK,MAAM;EACjC,IAAI;AACJ,MAAI;AACF,UAAO,SAAS,SAAS;UACnB;AACN;;AAEF,MAAI,KAAK,aAAa,EAAE;AACtB,OACE,MAAM,WAAW,IAAI,IACrB,UAAU,iBACV,UAAU,WACV,UAAU,UACV,UAAU,eAEV;AACF,WAAQ,KAAK,GAAG,gBAAgB,SAAS,CAAC;aACjC,MAAM,SAAS,MAAM,EAAE;AAEhC,OAAI,MAAM,SAAS,WAAW,IAAI,MAAM,WAAW,QAAQ,CAAE;AAE7D,OAAI,MAAM,WAAW,IAAI,IAAI,UAAU,cAAe;AACtD,WAAQ,KAAK,SAAS;;;AAG1B,QAAO,QAAQ,MAAM;;;;AAKvB,SAAS,mBAAmB,KAAsB;AAChD,KAAI;AACF,WAAS,KAAK,KAAK,cAAc,CAAC;AAClC,SAAO;SACD;AAIR,KAAI;AAEF,SADgB,YAAY,IAAI,CACjB,MAAM,MAAM,EAAE,SAAS,MAAM,CAAC;SACvC;AACN,SAAO;;;AAIX,SAAgB,qBAAqB,SAAgC;CAEnE,MAAM,SAAS,KAAK,SAAS,MAAM;AACnC,KAAI;AAEF,MADa,SAAS,OAAO,CACpB,aAAa,EAAE;GACtB,MAAM,UAAU,YAAY,OAAO;AACnC,QAAK,MAAM,SAAS,SAAS;IAC3B,MAAM,SAAS,KAAK,QAAQ,MAAM;AAClC,QAAI;AAEF,SADgB,SAAS,OAAO,CACpB,aAAa,IAAI,mBAAmB,OAAO,CACrD,QAAO;YAEH;AACN;;;;SAIA;AAKR,KAAI;EACF,MAAM,UAAU,YAAY,QAAQ;AACpC,OAAK,MAAM,SAAS,SAAS;AAC3B,OAAI,MAAM,WAAW,IAAI,IAAI,UAAU,WAAW,UAAU,UAAU,UAAU,eAAgB;GAChG,MAAM,SAAS,KAAK,SAAS,MAAM;AACnC,OAAI;AAEF,QADgB,SAAS,OAAO,CACpB,aAAa,IAAI,mBAAmB,OAAO,CACrD,QAAO;WAEH;AACN;;;SAGE;AAIR,QAAO;;;AAIT,SAAS,cAAc,MAA4B;CACjD,MAAM,aAAuB,EAAE;AAE/B,KAAI,KAAK,SAAS;OACX,MAAM,SAAS,KAAK,cACvB,KAAI,MAAM,SAAS,aAAa;GAC9B,MAAM,WAAW,MAAM,cAAc;AACrC,OAAI,SAAU,YAAW,KAAK,SAAS,KAAK;;;AAIlD,QAAO;;;AAIT,SAAS,eAAe,WAAiC;CACvD,MAAM,QAAkB,EAAE;CAC1B,MAAM,UAAU,UAAU,kBAAkB,eAAe;AAC3D,KAAI,CAAC,QAAS,QAAO;AAErB,MAAK,MAAM,SAAS,QAAQ,cAC1B,KAAI,MAAM,SAAS,gBAAgB,MAAM,SAAS,YAChD,OAAM,KAAK,MAAM,KAAK;UACb,MAAM,SAAS,oBAAoB;AAIhD,QAAO;;;AAIT,SAAS,mBAAmB,UAAqC;CAC/D,MAAM,SAAwB,EAAE;AAEhC,MAAK,MAAM,SAAS,SAAS,eAAe;AAC1C,MAAI,MAAM,SAAS,uBAAwB;EAE3C,MAAM,YAAY,MAAM,cAAc;AACtC,MAAI,CAAC,aAAa,UAAU,SAAS,aAAc;EAEnD,MAAM,OAAO,UAAU,kBAAkB,OAAO;EAChD,MAAM,WAAW,UAAU,kBAAkB,OAAO;AAGpD,MAAI,CAAC,QAAQ,CAAC,SAAU;AAExB,MAAI,KAAK,SAAS,aAAc;EAEhC,MAAM,QAAQ,UAAU,kBAAkB,QAAQ;AAElD,SAAO,KAAK;GACV,MAAM,KAAK;GACX,MAAM,SAAS;GACf,YAAY,UAAU;GACvB,CAAC;;AAEJ,QAAO;;;AAIT,SAAS,oBAAoB,UAAsC;CACjE,MAAM,UAA0B,EAAE;AAElC,MAAK,MAAM,SAAS,SAAS,eAAe;EAC1C,IAAI,WAA8B;EAClC,IAAI,aAAuB,EAAE;AAE7B,MAAI,MAAM,SAAS,wBAAwB;AACzC,gBAAa,cAAc,MAAM;AAEjC,cAAW,MAAM,cAAc,MAAM,MAAM,EAAE,SAAS,sBAAsB,IAAI;aACvE,MAAM,SAAS,sBACxB,YAAW;AAGb,MAAI,CAAC,SAAU;EAEf,MAAM,WAAW,SAAS,kBAAkB,OAAO;AACnD,MAAI,CAAC,SAAU;EACf,MAAM,aAAa,SAAS;AAG5B,MAAI,WAAW,WAAW,IAAI,IAAI,eAAe,WAAY;EAE7D,MAAM,UAAU,SAAS,cAAc,MAAM,MAAM,EAAE,SAAS,QAAQ;EACtE,MAAM,aAAa,WAAW,SAAS,WAAW;EAClD,MAAM,gBAAgB,WAAW,SAAS,cAAc;EACxD,MAAM,iBAAiB,WAAW,SAAS,eAAe;EAI1D,MAAM,SAAS,sBADI,SAAS,kBAAkB,aAAa,EACV,kBAAkB,cAAc;EAGjF,MAAM,iBAAiB,SAAS,kBAAkB,cAAc;EAChE,MAAM,aAAa,iBAAiB,eAAe,OAAO;AAE1D,UAAQ,KAAK;GACX,MAAM;GACN;GACA;GACA;GACA;GACA;GACA;GACD,CAAC;;AAGJ,QAAO;;;AAIT,SAAS,sBACP,YACA,WAME;AACF,KAAI,CAAC,WAAY,QAAO,EAAE;CAC1B,MAAM,SAKA,EAAE;CACR,IAAI,eAAe;CACnB,IAAI,iBAAiB;AAErB,MAAK,MAAM,SAAS,WAAW,eAAe;AAE5C,MAAI,CAAC,gBAAgB,CAAC,aAAa,MAAM,SAAS,iBAAiB,MAAM,SAAS,UAAU,MAAM,SAAS,QAAQ;AACjH,kBAAe;AACf;;AAEF,MAAI,CAAC,gBAAgB,CAAC,aAAa,MAAM,SAAS,qBAAqB,MAAM,cAAc,IAAI,SAAS,QAAQ;AAC9G,kBAAe;AACf;;AAIF,MAAI,MAAM,SAAS,KAAK;AACtB,oBAAiB;AACjB;;AAIF,MAAI,MAAM,SAAS,sBAAsB;AACvC,oBAAiB;GACjB,MAAM,WAAW,MAAM,cAAc,MAAM,MAAkB,EAAE,SAAS,aAAa;AACrF,UAAO,KAAK;IACV,MAAM,WAAW,IAAI,SAAS,SAAS;IACvC,MAAM;IACN,UAAU;IACV,cAAc;IACf,CAAC;AACF;;AAIF,MAAI,MAAM,SAAS,4BAA4B;GAC7C,MAAM,WAAW,MAAM,cAAc,MAAM,MAAkB,EAAE,SAAS,aAAa;AACrF,UAAO,KAAK;IACV,MAAM,WAAW,KAAK,SAAS,SAAS;IACxC,MAAM;IACN,UAAU;IACV,cAAc;IACf,CAAC;AACF;;EAGF,MAAM,eAAe,iBAAkB,YAAuB;AAE9D,MAAI,MAAM,SAAS,mBAAmB;GACpC,MAAM,WAAW,MAAM,cAAc,MAAM,MAAM,EAAE,SAAS,aAAa;GACzE,MAAM,WAAW,MAAM,kBAAkB,OAAO;AAChD,OAAI,SACF,QAAO,KAAK;IACV,MAAM,SAAS;IACf,MAAM,WAAW,SAAS,OAAO;IACjC,UAAU;IACV;IACD,CAAC;aAEK,MAAM,SAAS,2BAA2B;GACnD,MAAM,WAAW,MAAM,kBAAkB,OAAO;GAChD,MAAM,WAAW,MAAM,kBAAkB,OAAO;AAChD,OAAI,SACF,QAAO,KAAK;IACV,MAAM,SAAS;IACf,MAAM,WAAW,SAAS,OAAO;IACjC,UAAU;IACV;IACD,CAAC;aAEK,MAAM,SAAS,qBAAqB;GAC7C,MAAM,WAAW,MAAM,kBAAkB,OAAO;AAChD,OAAI,SACF,QAAO,KAAK;IACV,MAAM,SAAS;IACf,MAAM;IACN,UAAU;IACV;IACD,CAAC;aAEK,MAAM,SAAS,aACxB,QAAO,KAAK;GACV,MAAM,MAAM;GACZ,MAAM;GACN,UAAU;GACV;GACD,CAAC;;AAIN,QAAO;;;AAIT,SAAS,mBAAmB,MAAmB,YAAuC;CACpF,MAAM,UAA6B,EAAE;AAErC,MAAK,MAAM,QAAQ,KAAK,SAAS,eAAe;AAE9C,MAAI,KAAK,SAAS,wBAAwB;GACxC,MAAM,WAAW,KAAK,kBAAkB,OAAO;GAC/C,MAAM,YAAY,KAAK,kBAAkB,QAAQ;AACjD,OAAI,YAAY,UACd,SAAQ,KAAK;IAAE,MAAM,SAAS;IAAM,OAAO,UAAU;IAAM;IAAY,CAAC;AAE1E;;AAIF,MAAI,KAAK,SAAS,wBAAwB;GACxC,MAAM,QAAQ,KAAK,cAAc;AACjC,OAAI,CAAC,SAAS,MAAM,SAAS,aAAc;GAE3C,MAAM,OAAO,MAAM,kBAAkB,OAAO;GAC5C,MAAM,QAAQ,MAAM,kBAAkB,QAAQ;AAC9C,OAAI,CAAC,QAAQ,CAAC,MAAO;AAGrB,OAAI,KAAK,SAAS,aAAc;GAEhC,MAAM,OAAO,KAAK;AAElB,OAAI,KAAK,WAAW,IAAI,CAAE;AAE1B,OAAI,oBAAoB,KAAK,KAAK,CAAE;GAEpC,MAAM,QAAQ,MAAM;AAIpB,OAAI,MAAM,SAAS,eAAgB,MAAM,SAAS,YAAY,MAAM,SAAS,IAAI,EAAG;IAElF,IAAI,aAAa;AACjB,QAAI,MAAM,SAAS,SACjB,cAAa,MAAM,QAAQ,gBAAgB,GAAG;AAEhD,YAAQ,KAAK;KAAE;KAAM,OAAO;KAAY;KAAY,CAAC;;;;AAK3D,QAAO;;;AAIT,SAAS,kBAAkB,MAA6B;CACtD,MAAM,UAAoB,EAAE;AAE5B,MAAK,MAAM,QAAQ,KAAK,SAAS,eAAe;AAC9C,MAAI,KAAK,SAAS,uBAAwB;EAC1C,MAAM,QAAQ,KAAK,cAAc;AACjC,MAAI,CAAC,SAAS,MAAM,SAAS,aAAc;EAE3C,MAAM,OAAO,MAAM,kBAAkB,OAAO;EAC5C,MAAM,QAAQ,MAAM,kBAAkB,QAAQ;AAC9C,MAAI,CAAC,QAAQ,CAAC,MAAO;AACrB,MAAI,KAAK,SAAS,UAAW;AAG7B,MAAI,MAAM,SAAS;QACZ,MAAM,QAAQ,MAAM,cACvB,KAAI,KAAK,SAAS,UAAU;IAC1B,MAAM,OAAO,KAAK,KAAK,QAAQ,gBAAgB,GAAG;AAClD,YAAQ,KAAK,KAAK;;;;AAM1B,QAAO;;AAGT,SAAS,uBAAuB,MAAmB,YAAmC;CACpF,MAAM,UAAyB,EAAE;AAEjC,MAAK,MAAM,QAAQ,KAAK,SAAS,eAAe;EAC9C,IAAI,YAA+B;EACnC,IAAI,aAAuB,EAAE;AAE7B,MAAI,KAAK,SAAS,wBAAwB;AACxC,gBAAa,cAAc,KAAK;AAChC,eAAY,KAAK,cAAc,MAAM,MAAM,EAAE,SAAS,mBAAmB,IAAI;aACpE,KAAK,SAAS,mBACvB,aAAY;AAGd,MAAI,CAAC,UAAW;EAEhB,MAAM,WAAW,UAAU,kBAAkB,OAAO;AACpD,MAAI,CAAC,SAAU;EACf,MAAM,YAAY,SAAS;EAE3B,MAAM,QAAQ,eAAe,UAAU;EAEvC,MAAM,WAAW,UAAU,kBAAkB,OAAO;AACpD,MAAI,CAAC,UAAU;AACb,WAAQ,KAAK;IAAE,MAAM;IAAW;IAAO,QAAQ,EAAE;IAAE,SAAS,EAAE;IAAE;IAAY;IAAY,CAAC;AACzF;;EAGF,MAAM,SAAS,mBAAmB,SAAS;EAC3C,MAAM,UAAU,oBAAoB,SAAS;AAE7C,UAAQ,KAAK;GAAE,MAAM;GAAW;GAAO;GAAQ;GAAS;GAAY;GAAY,CAAC;;AAGnF,QAAO;;;AAeT,SAAgB,gBAAgB,UAAkB,SAAmC;CACnF,MAAM,SAAS,aAAa,UAAU,QAAQ;CAC9C,MAAM,UAAU,SAAS,SAAS,SAAS;CAC3C,MAAM,OAAOC,YAAU,cAAc,OAAO;AAM5C,QAAO;EAAE,SAJO,uBAAuB,MAAM,QAAQ;EAInC,aAHE,mBAAmB,MAAM,QAAQ;EAGtB,YAFZ,kBAAkB,KAAK;EAEC,YAAY;EAAS;;;;;AC1elE,MAAM,sBAAgC,EAAE;;AAGxC,MAAM,aAAa,IAAI,IAAI,CAAC,YAAY,CAAC;;AAGzC,MAAM,iBAAiB,IAAI,IAAI,CAAC,WAAW,CAAC;;AAG5C,MAAM,0BAA0B,CAAC,aAAa,gBAAgB;;AAG9D,SAAS,QAAQ,KAAkB,OAA6B;AAC9D,QAAO,IAAI,MAAM,MAAM,MAAM,MAAM,IAAI,EAAE,CAAC;;;;AAK5C,SAAS,aAAa,KAAkB,YAAsC,YAAkC;AAC9G,KAAI,QAAQ,KAAK,WAAW,CAAE,QAAO;AAErC,MAAK,MAAM,QAAQ,IAAI,OAAO;EAC5B,MAAM,YAAY,WAAW,IAAI,KAAK;AACtC,MAAI,aAAa,aAAa,WAAW,YAAY,WAAW,CAAE,QAAO;;AAE3E,QAAO;;;AAIT,SAAS,iBACP,KACA,YACA,gBACS;AACT,KAAI,QAAQ,KAAK,eAAe,CAAE,QAAO;AACzC,MAAK,MAAM,QAAQ,IAAI,OAAO;EAC5B,MAAM,YAAY,WAAW,IAAI,KAAK;AACtC,MAAI,aAAa,iBAAiB,WAAW,YAAY,eAAe,CAAE,QAAO;;AAEnF,QAAO;;;AAIT,SAAS,oBAAoB,OAA8C;CACzE,MAAM,QAAQ,MAAM,MAAM,qBAAqB;AAC/C,KAAI,CAAC,MAAO,QAAO;CAEnB,MAAM,QAAQ,MAAM;CACpB,MAAM,UAAkC,EAAE;CAG1C,MAAM,QAAkB,EAAE;CAC1B,IAAI,QAAQ;CACZ,IAAI,UAAU;AACd,MAAK,MAAM,QAAQ,OAAO;AACxB,MAAI,SAAS,OAAO,SAAS,IAAK;WACzB,SAAS,OAAO,SAAS,IAAK;WAC9B,SAAS,OAAO,UAAU,GAAG;AACpC,SAAM,KAAK,QAAQ,MAAM,CAAC;AAC1B,aAAU;AACV;;AAEF,aAAW;;AAEb,KAAI,QAAQ,MAAM,CAAE,OAAM,KAAK,QAAQ,MAAM,CAAC;AAE9C,MAAK,MAAM,QAAQ,OAAO;EAExB,MAAM,WAAW,KAAK,QAAQ,gBAAgB,GAAG;AACjD,MAAI,SACF,SAAQ,YAAY;;AAIxB,QAAO,OAAO,KAAK,QAAQ,CAAC,SAAS,IAAI,UAAU;;;AAIrD,SAAS,iBAAiB,YAA4B;CACpD,MAAM,mBAAmB,WAAW,MAAM,wBAAwB;AAClE,KAAI,iBAAkB,QAAO,iBAAiB;CAC9C,MAAM,iBAAiB,WAAW,MAAM,sBAAsB;AAC9D,KAAI,eAAgB,QAAO,eAAe;AAC1C,QAAO;;AAOT,SAAgBC,eACd,aACA,OAOA;CACA,MAAM,cAAc,IAAI,IAAI,OAAO,oBAAoB,oBAAoB;CAC3E,MAAM,kBAAkB,IAAI,IAAI,OAAO,wBAAwB,wBAAwB;CAEvF,MAAM,UAAoC,EAAE;CAC5C,MAAM,aAA2C,EAAE;CACnD,MAAM,cAA4C,EAAE;CACpD,MAAM,QAAiC,EAAE;CAGzC,MAAM,mCAAmB,IAAI,KAA0B;AACvD,MAAK,MAAM,QAAQ,YACjB,MAAK,MAAM,OAAO,KAAK,QACrB,kBAAiB,IAAI,IAAI,MAAM,IAAI;CAKvC,MAAM,gCAAgB,IAAI,KAAa;AACvC,MAAK,MAAM,QAAQ,YACjB,MAAK,MAAM,OAAO,KAAK,QACrB,KAAI,QAAQ,KAAK,eAAe,CAC9B,eAAc,IAAI,IAAI,KAAK;CAMjC,MAAM,YAAY,IAAI,iBAAiB;AAEvC,MAAK,MAAM,QAAQ,aAAa;AAE9B,OAAK,MAAM,SAAS,KAAK,aAAa;GACpC,MAAM,iBAAiB,oBAAoB,MAAM,MAAM;AACvD,OAAI,gBAAgB;AAElB,UAAM,MAAM,QAAQ;KAClB,MAAM,MAAM;KACZ,YAAY,MAAM;KAClB,SAAS,WAAW,eAAe;KACpC;AACD,cAAU,IAAI,MAAM,YAAY,MAAM,KAAK;UACtC;AAEL,gBAAY,MAAM,QAAQ;KACxB,MAAM,MAAM;KACZ,YAAY,MAAM;KAClB,OAAO,MAAM;KACd;AACD,cAAU,IAAI,MAAM,YAAY,MAAM,KAAK;;;AAK/C,OAAK,MAAM,OAAO,KAAK,SAAS;AAE9B,OAAI,QAAQ,KAAK,eAAe,EAAE;IAChC,MAAM,aAA0C,EAAE;AAElD,SAAK,MAAM,UAAU,IAAI,SAAS;AAEhC,SAAI,OAAO,SAAS,WAAY;KAEhC,MAAM,SAAqB,OAAO,OAAO,KAAK,OAAO;MACnD,MAAM,EAAE;MACR,MAAM,EAAE;MACR,UAAU,EAAE;MACZ,GAAI,EAAE,eAAe,EAAE,cAAc,EAAE,cAAc,GAAG,EAAE;MAC3D,EAAE;KAEH,MAAM,aAAa,iBAAiB,OAAO,WAAW;AAEtD,SAAI,CAAC,WAAW,OAAO,MAAO,YAAW,OAAO,QAAQ,EAAE;AAC1D,gBAAW,OAAO,MAAM,KAAK;MAC3B,MAAM,OAAO;MACb;MACA;MACA,OAAO,OAAO;MACf,CAAC;;AAGJ,YAAQ,IAAI,QAAQ;KAClB,MAAM,IAAI;KACV,YAAY,IAAI;KAChB,SAAS,WAAW,WAAW;KAC/B,YAAY,EAAE;KACd,mBAAmB,EAAE;KACtB;AACD,cAAU,IAAI,IAAI,YAAY,IAAI,KAAK;AACvC;;AAIF,OAAI,aAAa,KAAK,kBAAkB,YAAY,EAAE;IACpD,MAAM,SAAmC,EAAE;AAC3C,SAAK,MAAM,SAAS,IAAI,OACtB,QAAO,MAAM,QAAQ;KACnB,MAAM,MAAM;KACZ,MAAM,MAAM;KACZ,UAAU,MAAM;KACjB;IAIH,MAAM,aAAa,IAAI,MAAM,QAAQ,MAAM,CAAC,YAAY,IAAI,EAAE,IAAI,iBAAiB,IAAI,EAAE,CAAC;AAE1F,eAAW,IAAI,QAAQ;KACrB,MAAM,IAAI;KACV,YAAY,IAAI;KAChB,QAAQ,WAAW,OAAO;KAC1B,SAAS;KACV;AACD,cAAU,IAAI,IAAI,YAAY,IAAI,KAAK;AACvC;;AAIF,OAAI,QAAQ,KAAK,WAAW,EAAE;IAC5B,MAAM,SAAmC,EAAE;AAC3C,SAAK,MAAM,SAAS,IAAI,OACtB,QAAO,MAAM,QAAQ;KACnB,MAAM,MAAM;KACZ,MAAM,MAAM;KACZ,UAAU,MAAM;KACjB;AAGH,eAAW,IAAI,QAAQ;KACrB,MAAM,IAAI;KACV,YAAY,IAAI;KAChB,QAAQ,WAAW,OAAO;KAC1B,SAAS,EAAE;KACZ;AACD,cAAU,IAAI,IAAI,YAAY,IAAI,KAAK;AACvC;;AAIF,OAAI,iBAAiB,KAAK,kBAAkB,gBAAgB,EAAE;IAC5D,MAAM,aAA0C,EAAE;AAElD,SAAK,MAAM,UAAU,IAAI,SAAS;AAChC,SAAI,OAAO,SAAS,WAAY;KAChC,MAAM,SAAqB,OAAO,OAAO,KAAK,OAAO;MACnD,MAAM,EAAE;MACR,MAAM,EAAE;MACR,UAAU,EAAE;MACZ,GAAI,EAAE,eAAe,EAAE,cAAc,EAAE,cAAc,GAAG,EAAE;MAC3D,EAAE;AACH,SAAI,CAAC,WAAW,OAAO,MAAO,YAAW,OAAO,QAAQ,EAAE;AAC1D,gBAAW,OAAO,MAAM,KAAK;MAC3B,MAAM,OAAO;MACb;MACA,YAAY,iBAAiB,OAAO,WAAW;MAC/C,OAAO,OAAO;MACf,CAAC;;IAIJ,MAAM,SAAmC,EAAE;AAC3C,SAAK,MAAM,SAAS,IAAI,OACtB,QAAO,MAAM,QAAQ;KACnB,MAAM,MAAM;KACZ,MAAM,MAAM;KACZ,UAAU,MAAM;KACjB;AAGH,YAAQ,IAAI,QAAQ;KAClB,MAAM,IAAI;KACV,YAAY,IAAI;KAChB,SAAS,WAAW,WAAW;KAC/B,YAAY,EAAE;KACd,mBAAmB,EAAE;KACtB;AACD,cAAU,IAAI,IAAI,YAAY,IAAI,KAAK;AACvC;;AAIF,OAAI,IAAI,QAAQ,SAAS,GAAG;IAC1B,MAAM,aAA0C,EAAE;IAClD,MAAM,oBAAgC,EAAE;AAExC,SAAK,MAAM,UAAU,IAAI,SAAS;AAChC,SAAI,OAAO,SAAS,YAAY;AAC9B,wBAAkB,KAChB,GAAG,OAAO,OAAO,KAAK,OAAO;OAC3B,MAAM,EAAE;OACR,MAAM,EAAE;OACR,UAAU,EAAE;OACZ,GAAI,EAAE,eAAe,EAAE,cAAc,EAAE,cAAc,GAAG,EAAE;OAC3D,EAAE,CACJ;AACD;;KAGF,MAAM,SAAqB,OAAO,OAAO,KAAK,OAAO;MACnD,MAAM,EAAE;MACR,MAAM,EAAE;MACR,UAAU,EAAE;MACZ,GAAI,EAAE,eAAe,EAAE,cAAc,EAAE,cAAc,GAAG,EAAE;MAC3D,EAAE;AACH,SAAI,CAAC,WAAW,OAAO,MAAO,YAAW,OAAO,QAAQ,EAAE;AAC1D,gBAAW,OAAO,MAAM,KAAK;MAC3B,MAAM,OAAO;MACb;MACA,YAAY,iBAAiB,OAAO,WAAW;MAC/C,OAAO,OAAO;MACf,CAAC;;AAGJ,YAAQ,IAAI,QAAQ;KAClB,MAAM,IAAI;KACV,YAAY,IAAI;KAChB,SAAS,WAAW,WAAW;KAC/B,YAAY,EAAE;KACd;KACD;AACD,cAAU,IAAI,IAAI,YAAY,IAAI,KAAK;AACvC;;AAIF,OAAI,IAAI,OAAO,SAAS,GAAG;IACzB,MAAM,SAAmC,EAAE;AAC3C,SAAK,MAAM,SAAS,IAAI,OACtB,QAAO,MAAM,QAAQ;KACnB,MAAM,MAAM;KACZ,MAAM,MAAM;KACZ,UAAU,MAAM;KACjB;AAEH,eAAW,IAAI,QAAQ;KACrB,MAAM,IAAI;KACV,YAAY,IAAI;KAChB,QAAQ,WAAW,OAAO;KAC1B,SAAS,EAAE;KACZ;AACD,cAAU,IAAI,IAAI,YAAY,IAAI,KAAK;;;AAK3C,MAAI,KAAK,WAAW,SAAS,EAC3B,MAAK,MAAM,QAAQ,KAAK,WACtB,WAAU,IAAI,KAAK,YAAY,KAAK;;CAK1C,MAAM,UAAU,UAAU,UAAU;AAEpC,QAAO;EACL,SAAS,WAAW,QAAQ;EAC5B,YAAY,WAAW,WAAW;EAClC,aAAa,WAAW,YAAY;EACpC,OAAO,WAAW,MAAM;EACxB,SAAS,WAAW,QAAQ;EAC7B;;;;;;;;;;;;;;;ACxWH,MAAM,yBAAyB,IAAI,IAAI;CAAC;CAAO;CAAO;CAAS;CAAQ;CAAQ,CAAC;AAEhF,MAAM,cAA6B;CACjC,cAAc,MAA6B;EAEzC,MAAM,aAAa,KAAK,QAAQ,QAAQ,IAAI,CAAC,MAAM;EAEnD,MAAM,WAAW,WAAW,MAAM,qBAAqB;AACvD,MAAI,SAAU,QAAO,SAAS,GAAG,MAAM;EAEvC,MAAM,UAAU,WAAW,MAAM,wBAAwB;AACzD,MAAI,QAAS,QAAO,QAAQ,GAAG,MAAM;EAErC,MAAM,QAAQ,WACX,MAAM,IAAI,CACV,KAAK,MAAM,EAAE,MAAM,CAAC,CACpB,QAAQ,MAAM,MAAM,OAAO;AAC9B,MAAI,MAAM,SAAS,WAAW,MAAM,IAAI,CAAC,OAAQ,QAAO,MAAM,KAAK,MAAM;AACzE,SAAO;;CAGT,yBAAyB,GAAW,GAAoB;AACtD,SAAO,gCAAgC,MAAM,GAAG,EAAE;;CAGpD,eAAe,GAAW,GAAoB;EAC5C,MAAM,cAAc,MAAc;GAChC,MAAM,aAAa,EAAE,MAAM,kBAAkB;AAC7C,OAAI,WACF,QAAO,WAAW,GACf,MAAM,IAAI,CACV,KAAK,MAAM,EAAE,MAAM,CAAC,CACpB,MAAM;AACX,UAAO,EACJ,MAAM,IAAI,CACV,KAAK,MAAM,EAAE,MAAM,CAAC,CACpB,MAAM;;AAEX,SAAO,MAAM,KAAK,WAAW,EAAE,CAAC,KAAK,IAAI,KAAK,WAAW,EAAE,CAAC,KAAK,IAAI;;CAGvE,mBAAmB,MAAuB;AACxC,SAAO,UAAU,KAAK,KAAK,IAAI,oBAAoB,KAAK,KAAK;;CAG/D,qBAAqB,MAAuB;AAC1C,SAAO,SAAS,SAAS,SAAS;;CAGpC,0BAA0B;CAE1B,sBAAsB,YAAmC;EACvD,IAAI,QAAQ;EACZ,MAAM,mBAAmB,MAAM,MAAM,wBAAwB;AAC7D,MAAI,iBAAkB,SAAQ,iBAAiB;EAC/C,MAAM,iBAAiB,MAAM,MAAM,sBAAsB;AACzD,MAAI,eAAgB,SAAQ,eAAe;EAC3C,MAAM,WAAW,MAAM,MAAM,qBAAqB;AAClD,MAAI,SAAU,SAAQ,SAAS;AAE/B,OAAK,MAAM,WAAW,KAAK,wBAAwB,EAAE,EAAE;GACrD,MAAM,SAAS,UAAU;AACzB,OAAI,MAAM,WAAW,OAAO,EAAE;IAE5B,MAAM,OAAO,MAAM,MAAM,OAAO,OAAO;IACvC,MAAM,MAAM,KAAK,OAAO,QAAQ;AAChC,QAAI,MAAM,GAAG;AACX,aAAQ,KAAK,MAAM,GAAG,IAAI,CAAC,MAAM;AACjC;;;;EAKN,MAAM,WAAW,MAAM,MAAM,qBAAqB;AAClD,MAAI,SAAU,SAAQ,SAAS;AAC/B,MAAI;GAAC;GAAO;GAAO;GAAS;GAAQ;GAAQ;GAAS;GAAQ;GAAO,CAAC,SAAS,MAAM,CAAE,QAAO;AAC7F,SAAO;;CAGT,qBAAqB,WAAkC;EACrD,IAAI,QAAQ;EACZ,MAAM,WAAW,MAAM,MAAM,qBAAqB;AAClD,MAAI,SAAU,SAAQ,SAAS;AAC/B,MAAI;GAAC;GAAO;GAAO;GAAS;GAAQ;GAAQ;GAAS;GAAQ;GAAO,CAAC,SAAS,MAAM,CAAE,QAAO;AAC7F,SAAO;;CAGT,qBAAqB,cAAsB,WAA4B;AACrE,SAAO,aAAa,QAAQ,MAAM,GAAG,CAAC,aAAa,KAAK,UAAU,aAAa;;CAGjF,kBAAkB,WAA6B;AAC7C,SAAO,CAAC,GAAG,UAAU,UAAU;;CAGjC,iBAAiB,cAAsB,eAAuB,kBAAuC;EAEnG,MAAM,iBAAiB,MAAsB;GAC3C,MAAM,aAAa,EAAE,QAAQ,QAAQ,IAAI,CAAC,MAAM;GAChD,MAAM,WAAW,WAAW,MAAM,qBAAqB;AACvD,OAAI,SAAU,QAAO,SAAS,GAAG,MAAM;GACvC,MAAM,UAAU,WAAW,MAAM,wBAAwB;AACzD,OAAI,QAAS,QAAO,QAAQ,GAAG,MAAM;GACrC,MAAM,QAAQ,WACX,MAAM,IAAI,CACV,KAAK,MAAM,EAAE,MAAM,CAAC,CACpB,QAAQ,MAAM,MAAM,OAAO;AAC9B,OAAI,MAAM,SAAS,WAAW,MAAM,IAAI,CAAC,OAAQ,QAAO,MAAM,KAAK,MAAM;AACzE,UAAO;;EAET,MAAM,YAAY,cAAc,aAAa;EAC7C,MAAM,YAAY,cAAc,cAAc;EAG9C,MAAM,gBAAgB,MAAc,EAAE,MAAM,4BAA4B;EACxE,MAAM,UAAU,aAAa,UAAU;EACvC,MAAM,UAAU,aAAa,UAAU;AACvC,MAAI,WAAW,WAAW,QAAQ,OAAO,QAAQ,GAAI,QAAO;EAG5D,MAAM,iBAAiB,MAAsB;GAC3C,IAAI,QAAQ;GAEZ,MAAM,WAAW,MAAM,MAAM,6BAA6B;AAC1D,OAAI,SAAU,SAAQ,SAAS;AAE/B,UAAO;;EAET,MAAM,gBAAgB,cAAc,UAAU;EAC9C,MAAM,gBAAgB,cAAc,UAAU;AAC9C,MAAI,kBAAkB,aAAa,kBAAkB,WAAW;AAE9D,OAAI,kBAAkB,aAAa,kBAAkB,UAAW,QAAO;AACvE,OAAI,kBAAkB,cAAe,QAAO;AAE5C,OAAI,cAAc,WAAW,WAAW,IAAI,iBAAiB,MAAM,WAAY,QAAO;AACtF,OAAI,cAAc,WAAW,WAAW,IAAI,iBAAiB,QAAQ,WAAY,QAAO;;EAI1F,MAAM,aAAa;EACnB,MAAM,UAAU,UAAU,MAAM,WAAW;EAC3C,MAAM,UAAU,UAAU,MAAM,WAAW;AAC3C,MAAI,WAAW,SAAS;AACtB,OAAI,QAAQ,OAAO,QAAQ,GAAI,QAAO;GAEtC,MAAM,YAAY,QAAQ;GAC1B,MAAM,YAAY,QAAQ;AAC1B,OAAI,cAAc,KAAK,UAAU,IAAI,cAAc,KAAK,UAAU;QAC5D,oBAAoB,WAAW,iBAAiB,EAAE;AACpD,SAAI,UAAU,SAAS,UAAU,IAAI,UAAU,SAAS,UAAU,CAAE,QAAO;AAC3E,SAAI,sBAAsB,WAAW,UAAU,CAAE,QAAO;;;GAK5D,MAAM,iBAAiB;AACvB,OACG,eAAe,IAAI,UAAU,IAAI,cAAc,KAAK,UAAU,IAC9D,eAAe,IAAI,UAAU,IAAI,cAAc,KAAK,UAAU,CAE/D,QAAO;;AAIX,MAAI,WAAW,CAAC,SAAS;GACvB,MAAM,gBAAgB,UAAU,MAAM,0BAA0B;AAChE,OAAI,eAAe;IACjB,MAAM,YAAY,QAAQ;IAC1B,MAAM,YAAY,cAAc;AAChC,QAAI,cAAc,UAAW,QAAO;IACpC,MAAM,iBAAiB;AACvB,QACG,eAAe,IAAI,UAAU,IAAI,cAAc,KAAK,UAAU,IAC9D,eAAe,IAAI,UAAU,IAAI,cAAc,KAAK,UAAU,CAE/D,QAAO;;;EAMb,MAAM,iBAAiB;EACvB,MAAM,cAAc,UAAU,MAAM,eAAe;EACnD,MAAM,cAAc,UAAU,MAAM,eAAe;AACnD,MAAI,eAAe,YAEjB,QAAO;EAIT,MAAM,kBAAkB;AACxB,MAAI,gBAAgB,KAAK,UAAU,IAAI,gBAAgB,KAAK,UAAU,CAAE,QAAO;EAG/E,MAAM,aAAa,MAAc,gBAAgB,KAAK,EAAE,IAAI,qCAAqC,KAAK,EAAE;AACxG,MAAI,UAAU,UAAU,IAAI,UAAU,UAAU,CAAE,QAAO;AAIzD,MAAI,cAAc,KAAK,UAAU,IAAI,gBAAgB,KAAK,UAAU;OAE9D,2BAA2B,KAAK,UAAU,CAAE,QAAO;;AAEzD,MAAI,cAAc,KAAK,UAAU,IAAI,gBAAgB,KAAK,UAAU;OAC9D,2BAA2B,KAAK,UAAU,CAAE,QAAO;;AAIzD,MAAI,cAAc,SAAS,UAAU,WAAW,WAAW,CAAE,QAAO;AACpE,MAAI,cAAc,SAAS,UAAU,WAAW,WAAW,CAAE,QAAO;AAGpE,MAAI,UAAU,WAAW,WAAW,IAAI,iBAAiB,MAAM,WAAY,QAAO;AAClF,MAAI,UAAU,WAAW,WAAW,IAAI,iBAAiB,QAAQ,WAAY,QAAO;AAGpF,MAAI,cAAc,SAAS,iBAAiB,MAAM,WAAY,QAAO;AACrE,MAAI,cAAc,SAAS,iBAAiB,QAAQ,WAAY,QAAO;EAGvE,MAAM,eAAe,IAAI,IAAI,CAAC,OAAO,QAAQ,CAAC;AAC9C,MAAI,aAAa,IAAI,UAAU,IAAI,aAAa,IAAI,UAAU,CAAE,QAAO;AAGvE,MAAI,cAAc,KAAK,UAAU,IAAI,cAAc,KAAK,UAAU;OAC5D,oBAAoB,WAAW,iBAAiB,EAAE;AACpD,QAAI,UAAU,SAAS,UAAU,IAAI,UAAU,SAAS,UAAU,CAAE,QAAO;IAC3E,MAAM,aAAa,UAAU,QAAQ,aAAa,GAAG;IACrD,MAAM,aAAa,UAAU,QAAQ,aAAa,GAAG;AACrD,QAAI,WAAW,SAAS,WAAW,IAAI,WAAW,SAAS,WAAW,CAAE,QAAO;AAC/E,QAAI,sBAAsB,WAAW,UAAU,CAAE,QAAO;;;AAI5D,SAAO;;CAGT,sBACE,UACA,WACA,mBACS;AAOT,MAAI,SAAS,eAAe,UAAU,YAAY;GAChD,MAAM,UAAU,SAAS;GACzB,MAAM,UAAU,UAAU;AAC1B,OAAI,EAAE,cAAc,KAAK,QAAQ,IAAI,cAAc,KAAK,QAAQ,EAAG,QAAO;AAE1E,OAAI,CAAC,QAAQ,SAAS,QAAQ,IAAI,CAAC,QAAQ,SAAS,QAAQ;QACtD,CAAC,sBAAsB,SAAS,QAAQ,CAAE,QAAO;;;EAKzD,MAAM,gBAAgB,IAAI,IAAI;GAAC;GAAkB;GAAkB;GAAO,CAAC;EAC3E,MAAM,cAAc,UAAU,OAAO,WAClC,MAAM,cAAc,IAAI,EAAE,KAAK,KAAK,EAAE,SAAS,aAAa,EAAE,SAAS,UAAU,EAAE,SAAS,QAC9F;AACD,MAAI,cAAc,EAAG,QAAO;AAG5B,OAAK,IAAI,IAAI,GAAG,IAAI,aAAa,KAAK;AACpC,OAAI,KAAK,SAAS,OAAO,OAAQ,QAAO;AACxC,OAAI,SAAS,OAAO,GAAG,SAAS,UAAU,OAAO,GAAG,KAAM,QAAO;AACjE,OAAI,SAAS,OAAO,GAAG,SAAS,UAAU,OAAO,GAAG,KAAM,QAAO;;AAInE,SAAO;;CAIT,kBAAkB,EAAE;CACpB,sBAAsB,CAAC,aAAa,gBAAgB;CACpD,sBAAsB,EAAE;CACzB;;AAOD,SAAgB,sBAAsB,eAAmD;CACvF,MAAM,cAA6B,gBAAgB;EAAE,GAAG;EAAa,GAAG;EAAe,GAAG;AAE1F,QAAO;EACL,UAAU;EACV,OAAO;EAEP,MAAM,gBAAgB,SAA0C;AAE9D,UAAO,qBADS,MAAM,KAAK,QAAQ,QAAQ,CACP;;EAGtC,MAAM,QAAQ,SAAsC;GAClD,MAAM,aAAa,qBAAqB,QAAQ;AAChD,OAAI,CAAC,WACH,OAAM,IAAI,eACR,8BAA8B,WAC9B,kHACD;GAGH,MAAM,UAAU,gBAAgB,WAAW;AAC3C,OAAI,QAAQ,WAAW,EACrB,OAAM,IAAI,eACR,yBAAyB,WACzB,mDACD;GAGH,MAAM,cAAkC,EAAE;AAC1C,QAAK,MAAM,YAAY,SAAS;IAC9B,MAAM,SAAS,gBAAgB,UAAU,QAAQ;AACjD,gBAAY,KAAK,OAAO;;GAG1B,MAAM,EAAE,SAAS,YAAY,aAAa,OAAO,YAAYC,eAAa,aAAa,YAAY;AAEnG,UAAO;IACL,UAAU;IACV,eAAe;IACf,8BAAa,IAAI,MAAM,EAAC,aAAa;IACrC;IACA;IACA;IACA;IACA;IACD;;EAEJ;;;AAIH,MAAa,kBAA6B,uBAAuB;;;;;;;AClWjE,MAAM,aAAa,IAAI,QAAQ;AAC/B,WAAW,YAAY,KAAK;AAE5B,SAAS,UAAU,QAA6B;AAC9C,QAAOC,YAAc,YAAY,OAAO;;;AAQ1C,SAAgB,eAAe,QAA4B;CACzD,MAAM,OAAO,UAAU,OAAO;CAC9B,MAAM,UAAsB,EAAE;CAI9B,MAAM,gBADqB,2BAA2B,KAAK,SAAS,CAC3B,KAAK,MAAM,CAAC,EAAE,cAAc,KAAK,EAAE,YAAY,IAAI,CAAqB;AAEjH,MAAK,MAAM,QAAQ,KAAK,SAAS,kBAAkB,QAAQ,EAAE;AAE3D,MAAI,KAAK,SAAS,QAAS;AAG3B,MAAI,eAAe,KAAK,cAAc,KAAK,cAAc,CAAE;AAG3D,MAAI,KAAK,kBAAkB,kBAAkB,CAAC,SAAS,EAAG;EAE1D,MAAM,WAAW,KAAK,kBAAkB,OAAO;AAC/C,MAAI,CAAC,SAAU;EACf,MAAM,YAAY,SAAS;EAE3B,MAAM,WAAW,KAAK,kBAAkB,OAAO;EAE/C,MAAM,UAAuC,EAAE;EAC/C,MAAM,aAA0C,EAAE;EAClD,MAAM,oBAAgC,EAAE;AAGxC,MAAI,UAAU;AAEZ,qBAAkB,UAAU,WAAW;GAGvC,MAAM,mBAAmB,uBAAuB,SAAS;AACzD,QAAK,MAAM,UAAU,iBACnB,KAAI,OAAO,SAAS,aAClB,mBAAkB,KAAK,GAAG,OAAO,OAAO;QACnC;AACL,QAAI,CAAC,QAAQ,OAAO,MAAO,SAAQ,OAAO,QAAQ,EAAE;AACpD,YAAQ,OAAO,MAAM,KAAK,OAAO;;;AAKvC,UAAQ,KAAK;GACX,MAAM;GACN,SAAS,WAAW,QAAQ;GAC5B,YAAY,WAAW,WAAW;GAClC;GACD,CAAC;;AAGJ,QAAO;;;AAIT,SAAgB,sBAAsB,QAA4B;CAChE,MAAM,OAAO,UAAU,OAAO;CAC9B,MAAM,WAAuB,EAAE;AAE/B,MAAK,MAAM,cAAc,2BAA2B,KAAK,SAAS,EAAE;EAClE,MAAM,WAAW,WAAW,kBAAkB,OAAO;AACrD,MAAI,CAAC,SAAU;EACf,MAAM,aAAa,SAAS;EAE5B,MAAM,WAAW,WAAW,kBAAkB,OAAO;AACrD,MAAI,CAAC,SAAU;EAGf,MAAM,gBAAgB,4BAA4B,SAAS;AAC3D,MAAI,CAAC,cAAe;EAEpB,MAAM,gBAAgB,cAAc,kBAAkB,OAAO;AAC7D,MAAI,CAAC,cAAe;EAEpB,MAAM,UAAuC,EAAE;EAC/C,MAAM,aAA0C,EAAE;EAGlD,MAAM,mBAAmB,uBAAuB,cAAc;AAC9D,OAAK,MAAM,UAAU,kBAAkB;AACrC,OAAI,CAAC,QAAQ,OAAO,MAAO,SAAQ,OAAO,QAAQ,EAAE;AACpD,WAAQ,OAAO,MAAM,KAAK,OAAO;;AAInC,+BAA6B,eAAe,WAAW;AAEvD,MAAI,OAAO,KAAK,QAAQ,CAAC,SAAS,KAAK,OAAO,KAAK,WAAW,CAAC,SAAS,EACtE,UAAS,KAAK;GACZ,MAAM;GACN,SAAS,WAAW,QAAQ;GAC5B,YAAY,WAAW,WAAW;GAClC,mBAAmB,EAAE;GACtB,CAAC;;AAIN,QAAO;;;AAIT,SAAgBC,qBAAmB,QAA2B;CAC5D,MAAM,OAAO,UAAU,OAAO;CAC9B,MAAM,QAAmB,EAAE;CAG3B,MAAM,gBADqB,2BAA2B,KAAK,SAAS,CAC3B,KAAK,MAAM,CAAC,EAAE,cAAc,KAAK,EAAE,YAAY,IAAI,CAAqB;AAEjH,MAAK,MAAM,QAAQ,KAAK,SAAS,kBAAkB,SAAS,EAAE;AAE5D,MAAI,eAAe,KAAK,cAAc,KAAK,cAAc,CAAE;AAG3D,MAAI,KAAK,kBAAkB,kBAAkB,CAAC,SAAS,EAAG;EAE1D,MAAM,WAAW,KAAK,kBAAkB,OAAO;AAC/C,MAAI,CAAC,SAAU;EAEf,MAAM,WAAW,KAAK,kBAAkB,OAAO;AAC/C,MAAI,CAAC,SAAU;EAEf,MAAM,YAAY,qBAAqB,SAAS;AAChD,MAAI,OAAO,KAAK,UAAU,CAAC,SAAS,EAAG;AAEvC,QAAM,KAAK;GACT,MAAM,SAAS;GACf,SAAS,WAAW,UAAU;GAC/B,CAAC;;AAGJ,QAAO;;;AAIT,SAAgB,iBAAiB,QAA0B;CACzD,MAAM,OAAO,UAAU,OAAO;CAC9B,MAAM,QAAkB,EAAE;AAE1B,MAAK,MAAM,YAAY,KAAK,SAAS,kBAAkB,OAAO,EAAE;EAC9D,MAAM,aAAa,SAAS,kBAAkB,SAAS;AACvD,MAAI,CAAC,cAAc,WAAW,SAAS,WAAY;EAEnD,MAAM,WAAW,SAAS,kBAAkB,YAAY;AACxD,MAAI,CAAC,SAAU;EAGf,MAAM,WAAW,SAAS,cAAc;AACxC,MAAI,aAAa,SAAS,SAAS,mBAAmB,SAAS,SAAS,UACtE,OAAM,KAAK,SAAS,KAAK,QAAQ,MAAM,GAAG,CAAC;;AAI/C,QAAO;;;AAQT,SAAS,2BAA2B,UAAoC;CACtE,MAAM,SAAuB,EAAE;AAE/B,MAAK,MAAM,cAAc,SAAS,kBAAkB,SAAS,EAAE;EAC7D,MAAM,WAAW,WAAW,kBAAkB,OAAO;AACrD,MAAI,CAAC,SAAU;AAEf,MAAI,4BAA4B,SAAS,CACvC,QAAO,KAAK,WAAW;;AAI3B,QAAO;;;AAIT,SAAS,4BAA4B,UAAyC;AAC5E,MAAK,MAAM,SAAS,SAAS,cAC3B,KAAI,MAAM,SAAS,kBAAmB,QAAO;AAE/C,QAAO;;;AAQT,SAAS,uBAAuB,UAAmC;CACjE,MAAM,UAAuB,EAAE;CAC/B,IAAI,YAAY;AAEhB,MAAK,MAAM,SAAS,SAAS,eAAe;AAE1C,MAAI,MAAM,SAAS,cAAc;AAC/B,OAAI,MAAM,SAAS,WAAW;AAC5B,gBAAY;AACZ;;AAEF,OAAI,MAAM,SAAS,UAAU;AAC3B,gBAAY;AACZ;;AAEF,OAAI,MAAM,SAAS,aAAa;AAC9B,gBAAY;AACZ;;;AAIJ,MAAI,UAAW;AAEf,MAAI,MAAM,SAAS,UAAU;GAC3B,MAAM,WAAW,MAAM,kBAAkB,OAAO;AAChD,OAAI,CAAC,SAAU;GAEf,MAAM,SAAS,oBAAoB,MAAM;AACzC,WAAQ,KAAK;IACX,MAAM,SAAS;IACf;IACA,YAAY;IACZ,OAAO;IACR,CAAC;;;AAIN,QAAO;;;AAIT,SAAS,oBAAoB,YAAoC;CAC/D,MAAM,aAAa,WAAW,kBAAkB,aAAa;AAC7D,KAAI,CAAC,WAAY,QAAO,EAAE;CAE1B,MAAM,SAAqB,EAAE;AAE7B,MAAK,MAAM,aAAa,WAAW,cACjC,SAAQ,UAAU,MAAlB;EACE,KAAK;AAEH,UAAO,KAAK;IAAE,MAAM,UAAU;IAAM,MAAM;IAAU,UAAU;IAAO,cAAc;IAAuB,CAAC;AAC3G;EAEF,KAAK,sBAAsB;GAEzB,MAAM,WAAW,UAAU,kBAAkB,OAAO;AACpD,OAAI,SACF,QAAO,KAAK;IAAE,MAAM,SAAS;IAAM,MAAM;IAAU,UAAU;IAAM,cAAc;IAAuB,CAAC;AAE3G;;EAEF,KAAK,qBAAqB;GAExB,MAAM,WAAW,UAAU,kBAAkB,OAAO;AACpD,OAAI,UAAU;IACZ,MAAM,YAAY,UAAU,kBAAkB,QAAQ;AACtD,WAAO,KAAK;KACV,MAAM,SAAS;KACf,MAAM;KACN,UAAU,cAAc;KACxB,cAAc;KACf,CAAC;;AAEJ;;EAEF,KAAK,mBAAmB;GAEtB,MAAM,WAAW,UAAU,kBAAkB,OAAO;AACpD,UAAO,KAAK;IACV,MAAM,WAAW,IAAI,SAAS,SAAS;IACvC,MAAM;IACN,UAAU;IACV,cAAc;IACf,CAAC;AACF;;EAEF,KAAK,wBAAwB;GAE3B,MAAM,WAAW,UAAU,kBAAkB,OAAO;AACpD,UAAO,KAAK;IACV,MAAM,WAAW,KAAK,SAAS,SAAS;IACxC,MAAM;IACN,UAAU;IACV,cAAc;IACf,CAAC;AACF;;EAEF,KAAK,mBAAmB;GAEtB,MAAM,WAAW,UAAU,kBAAkB,OAAO;AACpD,UAAO,KAAK;IACV,MAAM,WAAW,IAAI,SAAS,SAAS;IACvC,MAAM;IACN,UAAU;IACV,cAAc;IACf,CAAC;AACF;;EAEF,QACE;;AAIN,QAAO;;;AAQT,SAAS,kBAAkB,UAAsB,YAA+C;AAC9F,MAAK,MAAM,YAAY,SAAS,kBAAkB,OAAO,EAAE;EACzD,MAAM,aAAa,SAAS,kBAAkB,SAAS;AACvD,MAAI,CAAC,WAAY;EACjB,MAAM,aAAa,WAAW;AAC9B,MAAI,eAAe,mBAAmB,eAAe,cAAe;EAEpE,MAAM,aAAa,eAAe;EAElC,MAAM,WAAW,SAAS,kBAAkB,YAAY;AACxD,MAAI,CAAC,SAAU;AAEf,OAAK,MAAM,WAAW,SAAS,cAC7B,KAAI,QAAQ,SAAS,mBAAmB,QAAQ,SAAS,UAAU;GACjE,MAAM,OAAO,QAAQ,KAAK,QAAQ,MAAM,GAAG;AAC3C,cAAW,QAAQ;IAAE;IAAM,MAAM;IAAU,UAAU;IAAY;;;;;AAWzE,SAAS,6BAA6B,UAAsB,YAA+C;AACzG,MAAK,MAAM,SAAS,SAAS,eAAe;AAC1C,MAAI,MAAM,SAAS,aAAc;EACjC,MAAM,WAAW,MAAM,kBAAkB,OAAO;AAChD,MAAI,CAAC,YAAY,SAAS,SAAS,WAAY;EAC/C,MAAM,OAAO,SAAS;AACtB,MAAI,CAAC,oBAAoB,KAAK,KAAK,CAAE;AACrC,aAAW,QAAQ;GAAE;GAAM,MAAM;GAAU,UAAU;GAAM;;;;AAK/D,SAAS,qBAAqB,UAAuD;CACnF,MAAM,YAA6C,EAAE;AAErD,MAAK,MAAM,SAAS,SAAS,eAAe;AAC1C,MAAI,MAAM,SAAS,aAAc;EACjC,MAAM,WAAW,MAAM,kBAAkB,OAAO;AAChD,MAAI,CAAC,YAAY,SAAS,SAAS,WAAY;EAC/C,MAAM,OAAO,SAAS;AACtB,MAAI,SAAS,MAAO;EAEpB,MAAM,YAAY,MAAM,kBAAkB,QAAQ;AAClD,MAAI,CAAC,UAAW;EAEhB,MAAM,QAAQ,oBAAoB,UAAU;AAC5C,MAAI,UAAU,KAAA,EACZ,WAAU,QAAQ;;AAItB,QAAO;;;AAIT,SAAS,oBAAoB,MAA+C;AAC1E,KAAI,KAAK,SAAS,YAAY,KAAK,SAAS,kBAAkB;EAE5D,MAAM,OAAO,KAAK;AAClB,MAAK,KAAK,WAAW,IAAI,IAAI,KAAK,SAAS,IAAI,IAAM,KAAK,WAAW,KAAI,IAAI,KAAK,SAAS,KAAI,CAC7F,QAAO,KAAK,MAAM,GAAG,GAAG;AAG1B,SAAO;;AAET,KAAI,KAAK,SAAS,UAChB,QAAO,OAAO,KAAK,KAAK;AAE1B,KAAI,KAAK,SAAS,QAChB,QAAO,OAAO,KAAK,KAAK;AAG1B,KAAI,KAAK,SAAS,UAAU;EAC1B,MAAM,cAAc,KAAK,cAAc,MAAM,MAAM,EAAE,SAAS,iBAAiB;AAC/E,MAAI,YAAa,QAAO,YAAY;;;;AAUxC,SAAS,eAAe,MAAc,QAA0C;AAC9E,MAAK,MAAM,CAAC,OAAO,QAAQ,OACzB,KAAI,OAAO,SAAS,OAAO,IAAK,QAAO;AAEzC,QAAO;;;;;;;;;;;;ACtZT,MAAM,YAA2B;CAC/B,cAAc,MAA6B;EACzC,MAAM,QAAQ,KAAK,MAAM,uBAAuB;AAChD,SAAO,QAAQ,MAAM,KAAK;;CAE5B,yBAAyB,GAAW,GAAoB;AACtD,SAAO,gCAAgC,MAAM,GAAG,EAAE;;CAEpD,eAAe,IAAY,IAAqB;AAC9C,SAAO;;CAET,mBAAmB,MAAuB;AACxC,SAAO,SAAS;;CAElB,qBAAqB,MAAuB;AAC1C,SAAO,SAAS,eAAe,SAAS;;CAE1C,0BAA0B;CAC1B,sBAAsB,YAAmC;AACvD,SAAO,cAAc;;CAEvB,qBAAqB,WAAkC;AACrD,MAAI;GAAC;GAAU;GAAW;GAAS;GAAW;GAAW,CAAC,SAAS,UAAU,CAAE,QAAO;AACtF,SAAO;;CAET,qBAAqB,cAAsB,WAA4B;AACrE,SAAO,aAAa,QAAQ,MAAM,GAAG,CAAC,aAAa,KAAK,UAAU,aAAa;;CAEjF,kBAAkB,YAA8B;AAC9C,SAAO,EAAE;;CAEZ;;AAOD,SAAS,eAAe,KAAuB;CAC7C,MAAM,SAAmB,EAAE;CAC3B,MAAM,UAAU,YAAY,IAAI;AAChC,MAAK,MAAM,SAAS,QAAQ,MAAM,EAAE;EAClC,MAAM,OAAO,KAAK,KAAK,MAAM;AAE7B,MADa,SAAS,KAAK,CAClB,aAAa,CACpB,QAAO,KAAK,GAAG,eAAe,KAAK,CAAC;WAC3B,MAAM,SAAS,MAAM,CAC9B,QAAO,KAAK,KAAK;;AAGrB,QAAO;;AAOT,MAAa,gBAA2B;CACtC,UAAU;CACV,OAAO;CAEP,MAAM,gBAAgB,SAA0C;AAE9D,SAAO,qBADS,MAAM,KAAK,QAAQ,QAAQ,CACP;;CAGtC,MAAM,QAAQ,SAAsC;EAClD,MAAM,UAAU,QAAQ,SAAS,MAAM;AACvC,MAAI;AACF,YAAS,QAAQ;UACX;AACN,SAAM,IAAI,eACR,8BAA8B,WAC9B,4FACD;;EAGH,MAAM,UAAU,eAAe,QAAQ;AACvC,MAAI,QAAQ,WAAW,EACrB,OAAM,IAAI,eACR,yBAAyB,WACzB,wDACD;EAGH,MAAM,UAA0D,EAAE;EAClE,MAAM,QAAuD,EAAE;EAC/D,MAAM,UAAoC,EAAE;AAE5C,OAAK,MAAM,WAAW,SAAS;GAC7B,MAAM,UAAU,SAAS,SAAS,QAAQ;GAC1C,MAAM,SAAS,aAAa,SAAS,QAAQ;GAE7C,MAAM,cAAwB,EAAE;GAGhC,MAAM,mBAAmB,eAAe,OAAO;AAC/C,QAAK,MAAM,OAAO,kBAAkB;AAClC,YAAQ,IAAI,QAAQ;KAAE,GAAG;KAAK,YAAY;KAAS;AACnD,gBAAY,KAAK,IAAI,KAAK;;GAI5B,MAAM,oBAAoB,sBAAsB,OAAO;AACvD,QAAK,MAAM,OAAO,mBAAmB;AACnC,YAAQ,IAAI,QAAQ;KAAE,GAAG;KAAK,YAAY;KAAS;AACnD,gBAAY,KAAK,IAAI,KAAK;;GAI5B,MAAM,iBAAiBC,qBAAmB,OAAO;AACjD,QAAK,MAAM,MAAM,gBAAgB;AAC/B,UAAM,GAAG,QAAQ;KAAE,GAAG;KAAI,YAAY;KAAS;AAC/C,gBAAY,KAAK,GAAG,KAAK;;GAI3B,MAAM,gBAAgB,iBAAiB,OAAO;AAC9C,OAAI,cAAc,SAAS,EACzB,aAAY,KAAK,GAAG,cAAc;AAGpC,OAAI,YAAY,SAAS,EACvB,SAAQ,WAAW,CAAC,GAAG,IAAI,IAAI,YAAY,CAAC,CAAC,MAAM;;AAIvD,SAAO;GACL,UAAU;GACV,eAAe;GACf,8BAAa,IAAI,MAAM,EAAC,aAAa;GACrC,SAAS,WAAW,QAAQ;GAC5B,YAAY,EAAE;GACd,aAAa,EAAE;GACf,OAAO,WAAW,MAAM;GACxB,SAAS,WAAW,QAAQ;GAC7B;;CAEJ;;;;;;;AC3GD,MAAM,WAAW,IAAI,QAAQ;AAC7B,SAAS,YAAY,GAAG;AAMxB,SAAgB,YAAY,KAAuB;CACjD,MAAM,UAAoB,EAAE;CAC5B,IAAI;AACJ,KAAI;AACF,YAAU,YAAY,IAAI;SACpB;AACN,SAAO;;AAET,MAAK,MAAM,SAAS,SAAS;EAC3B,MAAM,WAAW,KAAK,KAAK,MAAM;EACjC,IAAI;AACJ,MAAI;AACF,UAAO,SAAS,SAAS;UACnB;AACN;;AAEF,MAAI,KAAK,aAAa,EAAE;AACtB,OAAI,MAAM,WAAW,IAAI,IAAI,UAAU,YAAY,UAAU,cAAc,UAAU,WAAY;AACjG,WAAQ,KAAK,GAAG,YAAY,SAAS,CAAC;aAC7B,MAAM,SAAS,MAAM,IAAI,CAAC,MAAM,SAAS,WAAW,CAC7D,SAAQ,KAAK,SAAS;;AAG1B,QAAO,QAAQ,MAAM;;;AAQvB,SAAS,UAAU,MAAkB,OAA8B;CACjE,MAAM,QAAQ,KAAK,kBAAkB,MAAM;AAC3C,QAAO,QAAQ,MAAM,OAAO;;;AAI9B,SAAS,eAAe,SAA8D;CACpF,MAAM,QAAQ,QAAQ,MAAM,iBAAiB;AAC7C,KAAI,CAAC,MAAO,QAAO;CACnB,MAAM,QAAQ,MAAM,GAAG,MAAM,IAAI;CACjC,MAAM,OAAO,MAAM,GAAG,MAAM;CAC5B,MAAM,YAAY,MAAM,SAAS,YAAY;AAC7C,KAAI,SAAS,IAAK,QAAO;AACzB,QAAO;EAAE;EAAM;EAAW;;;AAI5B,SAAS,aAAa,MAA0B;AAC9C,QAAO,KAAK;;AAOd,SAASC,oBAAkB,YAAyC;CAClE,MAAM,SAA0B,EAAE;CAClC,MAAM,YAAY,WAAW,cAAc,MAAM,MAAM,EAAE,SAAS,yBAAyB;AAC3F,KAAI,CAAC,UAAW,QAAO;AAEvB,MAAK,MAAM,aAAa,UAAU,eAAe;AAC/C,MAAI,UAAU,SAAS,oBAAqB;EAG5C,MAAM,YAAY,UAAU,cAAc,QAAQ,MAAM,EAAE,SAAS,mBAAmB;AACtF,MAAI,UAAU,WAAW,GAAG;GAG1B,MAAM,WAAW,UAAU,cAAc,MACtC,MAAM,EAAE,SAAS,wBAAwB,EAAE,SAAS,6BACtD;AACD,OAAI,UAAU;IACZ,MAAM,WAAW,SAAS,KAAK,QAAQ,OAAO,GAAG;AACjD,QAAI,SAAS,KAAK,SAAS,CACzB,QAAO,KAAK;KACV,MAAM;KACN,MAAM,SAAS;KACf,UAAU;KACX,CAAC;;AAGN;;EAIF,MAAM,WAAW,UAAU,cAAc,MACtC,MACC,EAAE,SAAS,sBAAsB,EAAE,SAAS,wBAAwB,EAAE,SAAS,6BAClF;AACD,MAAI,CAAC,SAAU;EAGf,MAAM,YAAY,aAAa,SAAS;EAGxC,MAAM,UAAU,UAAU,cAAc,MACrC,MAAM,EAAE,SAAS,wBAAwB,EAAE,SAAS,6BACtD;EACD,MAAM,UAAU,UAAU,eAAe,QAAQ,KAAK,GAAG;AAEzD,OAAK,MAAM,YAAY,WAAW;GAChC,MAAM,OAAO,SAAS;AACtB,OAAI,CAAC,SAAS,KAAK,KAAK,CAAE;AAC1B,UAAO,KAAK;IACV;IACA,MAAM;IACN,SAAS,SAAS,QAAQ,KAAA;IAC1B,UAAU,SAAS,aAAa;IACjC,CAAC;;;AAGN,QAAO;;AAOT,SAAgB,eACd,MACA,YACA,aAC8C;CAC9C,MAAM,UAAsB,EAAE;CAC9B,MAAM,QAAsB,EAAE;AAE9B,MAAK,MAAM,QAAQ,KAAK,SAAS,eAAe;AAC9C,MAAI,KAAK,SAAS,mBAAoB;AAEtC,OAAK,MAAM,QAAQ,KAAK,eAAe;GACrC,MAAM,OAAO,UAAU,MAAM,OAAO;AACpC,OAAI,CAAC,QAAQ,CAAC,SAAS,KAAK,KAAK,CAAE;AAEnC,OAAI,KAAK,SAAS,aAAa;IAC7B,MAAM,WAAW,KAAK,kBAAkB,OAAO;AAC/C,QAAI,CAAC,SAAU;AAEf,QAAI,SAAS,SAAS,cACpB,SAAQ,KAAK;KAAE;KAAM,QAAQA,oBAAkB,SAAS;KAAE;KAAY;KAAa,CAAC;aAC3E,SAAS,SAAS,iBAC3B,OAAM,KAAK;KAAE;KAAM,gBAAgB,aAAa,SAAS;KAAE,SAAS;KAAO;KAAY;KAAa,CAAC;cAE9F,KAAK,SAAS,cAAc;IACrC,MAAM,WAAW,KAAK,kBAAkB,OAAO;AAC/C,QAAI,SACF,OAAM,KAAK;KAAE;KAAM,gBAAgB,aAAa,SAAS;KAAE,SAAS;KAAM;KAAY;KAAa,CAAC;;;;AAM5G,QAAO;EAAE;EAAS;EAAO;;;AAQ3B,SAAS,YAAY,OAAuB;AAC1C,KAAK,MAAM,WAAW,KAAI,IAAI,MAAM,SAAS,KAAI,IAAM,MAAM,WAAW,IAAI,IAAI,MAAM,SAAS,IAAI,CACjG,QAAO,MAAM,MAAM,GAAG,GAAG;CAE3B,MAAM,YAAY,MAAM,MAAM,+BAA+B;AAC7D,KAAI,UAAW,QAAO,UAAU;AAChC,QAAO;;AAGT,SAAgB,iBAAiB,MAAmB,YAAoB,aAAgC;CACtG,MAAM,SAAoB,EAAE;AAE5B,MAAK,MAAM,QAAQ,KAAK,SAAS,eAAe;AAC9C,MAAI,KAAK,SAAS,oBAAqB;EAEvC,IAAI,WAAW;AAEf,OAAK,MAAM,QAAQ,KAAK,eAAe;AACrC,OAAI,KAAK,SAAS,aAAc;GAEhC,MAAM,YAAY,KAAK,cAAc,QAAQ,MAAM,EAAE,SAAS,aAAa;AAC3E,OAAI,UAAU,WAAW,EAAG;GAC5B,MAAM,YAAY,UAAU,GAAG;AAC/B,OAAI,CAAC,SAAS,KAAK,UAAU,CAAE;GAG/B,MAAM,WAAW,KAAK,kBAAkB,OAAO;AAC/C,OAAI,SACF,YAAW,SAAS;GAItB,MAAM,YAAY,KAAK,kBAAkB,QAAQ;AACjD,OAAI,WAAW;IAEb,MAAM,YAAY,UAAU,KAAK,MAAM;IACvC,MAAM,gBAAgB,YAAY,UAAU;AAG5C,QAAI,CAAC,UAAU;KACb,MAAM,YAAY,UAAU,MAAM,uBAAuB;AACzD,SAAI,WAAW;AACb,aAAO,KAAK;OACV,MAAM;OACN,UAAU,UAAU;OACpB,OAAO,YAAY,UAAU,GAAG,MAAM,CAAC;OACvC;OACA;OACD,CAAC;AACF;;;AAIJ,QAAI,SACF,QAAO,KAAK;KAAE,MAAM;KAAW,UAAU;KAAU,OAAO;KAAe;KAAY;KAAa,CAAC;cAE5F,SAET,QAAO,KAAK;IAAE,MAAM;IAAW,UAAU;IAAU,OAAO;IAAW;IAAY;IAAa,CAAC;;;AAKrG,QAAO;;AAOT,SAAS,eAAe,eAAoE;AAC1F,KAAI,CAAC,cAAe,QAAO,EAAE;CAC7B,MAAM,SAA2C,EAAE;CAEnD,IAAI,eAAe;AACnB,MAAK,MAAM,aAAa,cAAc,eAAe;AACnD,MAAI,UAAU,SAAS,2BAA2B,UAAU,SAAS,iCAAkC;EAEvG,MAAM,WAAW,UAAU,cAAc,MAAM,MAAM,EAAE,SAAS,aAAa;EAC7E,MAAM,WAAW,UAAU,kBAAkB,OAAO;AACpD,MAAI,CAAC,SAAU;EAIf,MAAM,OAAO,WAAW,SAAS,OAAO,OAAO;AAC/C,SAAO,KAAK;GACV;GACA,MAAM,aAAa,SAAS;GAC7B,CAAC;;AAEJ,QAAO;;AAGT,SAAS,iBAAiB,YAAyC;AACjE,KAAI,CAAC,WAAY,QAAO,EAAE;AAE1B,KAAI,WAAW,SAAS,iBAEtB,QAAO,WAAW,cACf,QAAQ,MAAM,EAAE,SAAS,wBAAwB,CACjD,KAAK,MAAM;EACV,MAAM,IAAI,EAAE,kBAAkB,OAAO;AACrC,SAAO,IAAI,aAAa,EAAE,GAAG,EAAE;GAC/B;AAIN,QAAO,CAAC,aAAa,WAAW,CAAC;;AAGnC,SAAgB,eAAe,MAAmB,YAAoB,aAA+B;CACnG,MAAM,QAAkB,EAAE;AAE1B,MAAK,MAAM,QAAQ,KAAK,SAAS,cAC/B,KAAI,KAAK,SAAS,wBAAwB;EACxC,MAAM,OAAO,UAAU,MAAM,OAAO;AACpC,MAAI,CAAC,QAAQ,CAAC,SAAS,KAAK,KAAK,CAAE;AAEnC,QAAM,KAAK;GACT,cAAc;GACd;GACA,QAAQ,eAAe,KAAK,kBAAkB,aAAa,CAAC;GAC5D,aAAa,iBAAiB,KAAK,kBAAkB,SAAS,CAAC;GAC/D;GACA;GACD,CAAC;YACO,KAAK,SAAS,sBAAsB;EAC7C,MAAM,OAAO,UAAU,MAAM,OAAO;AACpC,MAAI,CAAC,QAAQ,CAAC,SAAS,KAAK,KAAK,CAAE;EAGnC,MAAM,eAAe,KAAK,kBAAkB,WAAW;EACvD,IAAI,eAA8B;AAClC,MAAI,cAAc;GAChB,MAAM,YAAY,aAAa,cAAc,MAAM,MAAM,EAAE,SAAS,wBAAwB;AAC5F,OAAI,WAAW;IACb,MAAM,WAAW,UAAU,kBAAkB,OAAO;AACpD,QAAI,SAEF,gBAAe,SAAS,KAAK,QAAQ,OAAO,GAAG;;;AAKrD,QAAM,KAAK;GACT;GACA;GACA,QAAQ,eAAe,KAAK,kBAAkB,aAAa,CAAC;GAC5D,aAAa,iBAAiB,KAAK,kBAAkB,SAAS,CAAC;GAC/D;GACA;GACD,CAAC;;AAGN,QAAO;;AAOT,SAAgBC,qBAAmB,MAA2B;CAC5D,MAAM,YAAY,KAAK,SAAS,cAAc,MAAM,MAAM,EAAE,SAAS,iBAAiB;AACtF,KAAI,CAAC,UAAW,QAAO;CACvB,MAAM,WAAW,UAAU,cAAc,MAAM,MAAM,EAAE,SAAS,qBAAqB;AACrF,QAAO,WAAW,SAAS,OAAO;;;AAepC,SAAgB,YAAY,UAAkB,SAA+B;CAC3E,MAAM,SAAS,aAAa,UAAU,QAAQ;CAC9C,MAAM,UAAU,SAAS,SAAS,SAAS;CAC3C,MAAM,OAAOC,YAAU,UAAU,OAAO;CACxC,MAAM,cAAcD,qBAAmB,KAAK;CAE5C,MAAM,EAAE,SAAS,UAAU,eAAe,MAAM,SAAS,YAAY;AAIrE,QAAO;EAAE;EAAS;EAAO,OAHX,eAAe,MAAM,SAAS,YAAY;EAGxB,QAFjB,iBAAiB,MAAM,SAAS,YAAY;EAEnB;;;;;;;;ACzY1C,SAAS,eAAe,GAAmB;AACzC,QAAO,EAAE,QAAQ,qBAAqB,SAAS,CAAC,QAAQ,yBAAyB,kBAAkB;;AAGrG,SAAS,gBAAgB,aAA+B;CACtD,MAAM,WAAW,YAAY,QAAQ,MAAM,MAAM,QAAQ;AACzD,KAAI,SAAS,WAAW,EAAG,QAAO;AAClC,KAAI,SAAS,WAAW,EAAG,QAAO,eAAe,SAAS,GAAG;AAC7D,QAAO,IAAI,SAAS,IAAI,eAAe,CAAC,KAAK,KAAK,CAAC;;;AAIrD,SAAS,kBAAkB,SAAyB;AAElD,QAAO,SADK,QAAQ,QAAQ,CACR,IAAI;;;;;;;AAY1B,SAAS,oBACP,OACqB;CACrB,MAAM,iCAAiB,IAAI,KAA0B;AACrD,MAAK,MAAM,QAAQ,OAAO;AACxB,MAAI,CAAC,eAAe,IAAI,KAAK,KAAK,CAAE,gBAAe,IAAI,KAAK,sBAAM,IAAI,KAAK,CAAC;AAC5E,iBAAe,IAAI,KAAK,KAAK,CAAE,IAAI,KAAK,YAAY;;CAGtD,MAAM,yBAAS,IAAI,KAAqB;AACxC,MAAK,MAAM,QAAQ,OAAO;EACxB,MAAM,MAAM,GAAG,KAAK,WAAW,GAAG,KAAK;EACvC,MAAM,WAAW,eAAe,IAAI,KAAK,KAAK;AAC9C,SAAO,IAAI,KAAK,SAAS,OAAO,IAAI,GAAG,kBAAkB,KAAK,WAAW,CAAC,GAAG,KAAK,SAAS,KAAK,KAAK;;AAEvG,QAAO;;AAOT,SAAgBE,eACd,YACA,UACA,UACA,WAOA;CACA,MAAM,UAAoC,EAAE;CAC5C,MAAM,aAA2C,EAAE;CACnD,MAAM,cAA4C,EAAE;CACpD,MAAM,QAAiC,EAAE;CAGzC,MAAM,qCAAqB,IAAI,KAAwB;AACvD,MAAK,MAAM,KAAK,WAAW;EACzB,MAAM,MAAM,GAAG,EAAE,YAAY,GAAG,EAAE;AAClC,MAAI,CAAC,mBAAmB,IAAI,IAAI,CAAE,oBAAmB,IAAI,KAAK,EAAE,CAAC;AACjE,qBAAmB,IAAI,IAAI,CAAE,KAAK,EAAE;;CAItC,MAAM,0CAA0B,IAAI,KAAuB;CAC3D,MAAM,eAAyB,EAAE;AACjC,MAAK,MAAM,MAAM,SACf,KAAI,GAAG,cAAc;EACnB,MAAM,MAAM,GAAG,GAAG,YAAY,GAAG,GAAG;AACpC,MAAI,CAAC,wBAAwB,IAAI,IAAI,CAAE,yBAAwB,IAAI,KAAK,EAAE,CAAC;AAC3E,0BAAwB,IAAI,IAAI,CAAE,KAAK,GAAG;OAE1C,cAAa,KAAK,GAAG;CAKzB,MAAM,aAA+E,EAAE;AACvF,MAAK,MAAM,KAAK,WAAY,YAAW,KAAK;EAAE,MAAM,EAAE;EAAM,aAAa,EAAE;EAAa,YAAY,EAAE;EAAY,CAAC;AACnH,MAAK,MAAM,KAAK,SAAU,YAAW,KAAK;EAAE,MAAM,EAAE;EAAM,aAAa,EAAE;EAAa,YAAY,EAAE;EAAY,CAAC;CACjH,MAAM,iBAAiB,oBAAoB,WAAW;AAGtD,MAAK,MAAM,YAAY,UAAU;EAC/B,MAAM,QAAQ,eAAe,IAAI,GAAG,SAAS,WAAW,GAAG,SAAS,OAAO,IAAI,SAAS;EACxF,MAAM,aAAa,mBAAmB,IAAI,GAAG,SAAS,YAAY,GAAG,SAAS,OAAO;AAErF,MAAI,SAAS,QACX,aAAY,SAAS;GACnB,MAAM;GACN,YAAY,SAAS;GACrB,OAAO,eAAe,SAAS,eAAe;GAC/C;WACQ,cAAc,WAAW,SAAS,GAAG;GAC9C,MAAM,UAA2C,EAAE;AACnD,QAAK,MAAM,KAAK,YAAY;IAK1B,MAAM,YAAY,EAAE,KAAK,WAAW,SAAS,KAAK,GAAG,EAAE,KAAK,MAAM,SAAS,KAAK,OAAO,IAAI,EAAE,OAAO,EAAE;AACtG,YAAQ,aAAa,EAAE;;AAEzB,SAAM,SAAS;IAAE,MAAM;IAAO,YAAY,SAAS;IAAY,SAAS,WAAW,QAAQ;IAAE;QAE7F,aAAY,SAAS;GACnB,MAAM;GACN,YAAY,SAAS;GACrB,OAAO,eAAe,SAAS,eAAe;GAC/C;;AAKL,MAAK,MAAM,KAAK,YAAY;EAC1B,MAAM,QAAQ,eAAe,IAAI,GAAG,EAAE,WAAW,GAAG,EAAE,OAAO,IAAI,EAAE;EACnE,MAAM,UAAU,wBAAwB,IAAI,GAAG,EAAE,YAAY,GAAG,EAAE,OAAO;AAEzE,MAAI,WAAW,QAAQ,SAAS,GAAG;GACjC,MAAM,aAA0C,EAAE;GAClD,MAAM,aAA0C,EAAE;AAElD,QAAK,MAAM,SAAS,EAAE,OACpB,YAAW,MAAM,QAAQ;IAAE,MAAM,MAAM;IAAM,MAAM,eAAe,MAAM,KAAK;IAAE,UAAU;IAAO;AAGlG,QAAK,MAAM,MAAM,SAAS;IACxB,MAAM,SAAqB,GAAG,OAC3B,QAAQ,MAAM,EAAE,SAAS,kBAAkB,CAC3C,KAAK,OAAO;KACX,MAAM,EAAE;KACR,MAAM,eAAe,EAAE,KAAK;KAC5B,UAAU;KACV,cAAc;KACf,EAAE;AACL,QAAI,CAAC,WAAW,GAAG,MAAO,YAAW,GAAG,QAAQ,EAAE;AAClD,eAAW,GAAG,MAAM,KAAK;KAAE,MAAM,GAAG;KAAM;KAAQ,YAAY,gBAAgB,GAAG,YAAY;KAAE,OAAO;KAAO,CAAC;;AAGhH,WAAQ,SAAS;IACf,MAAM;IACN,YAAY,EAAE;IACd,SAAS,WAAW,WAAW;IAC/B,YAAY,WAAW,WAAW;IAClC,mBAAmB,EAAE;IACtB;SACI;GACL,MAAM,SAAmC,EAAE;AAC3C,QAAK,MAAM,SAAS,EAAE,QAAQ;IAC5B,MAAM,YAAY,MAAM,WAAW,MAAM;AACzC,WAAO,aAAa;KAAE,MAAM;KAAW,MAAM,eAAe,MAAM,KAAK;KAAE,UAAU,MAAM;KAAU;;AAErG,cAAW,SAAS;IAAE,MAAM;IAAO,YAAY,EAAE;IAAY,QAAQ,WAAW,OAAO;IAAE,SAAS,EAAE;IAAE;;;CAK1G,MAAM,YAAY,IAAI,iBAAiB;AAEvC,MAAK,MAAM,CAAC,MAAM,QAAQ,OAAO,QAAQ,QAAQ,CAAE,KAAI,IAAI,WAAY,WAAU,IAAI,IAAI,YAAY,KAAK;AAC1G,MAAK,MAAM,CAAC,MAAM,UAAU,OAAO,QAAQ,WAAW,CAAE,KAAI,MAAM,WAAY,WAAU,IAAI,MAAM,YAAY,KAAK;AACnH,MAAK,MAAM,CAAC,MAAM,OAAO,OAAO,QAAQ,YAAY,CAAE,KAAI,GAAG,WAAY,WAAU,IAAI,GAAG,YAAY,KAAK;AAC3G,MAAK,MAAM,CAAC,MAAM,OAAO,OAAO,QAAQ,MAAM,CAAE,KAAI,GAAG,WAAY,WAAU,IAAI,GAAG,YAAY,KAAK;AACrG,MAAK,MAAM,KAAK,WAAW;EACzB,MAAM,WAAW,SAAS,MAAM,MAAM,EAAE,SAAS,EAAE,YAAY,EAAE,gBAAgB,EAAE,YAAY;AAC/F,MAAI,SAAU,WAAU,IAAI,SAAS,YAAY,EAAE,KAAK;;AAE1D,MAAK,MAAM,MAAM,aAAc,WAAU,IAAI,GAAG,YAAY,GAAG,KAAK;CAEpE,MAAM,UAAU,UAAU,UAAU;AAEpC,QAAO;EACL,SAAS,WAAW,QAAQ;EAC5B,YAAY,WAAW,WAAW;EAClC,aAAa,WAAW,YAAY;EACpC,OAAO,WAAW,MAAM;EACxB,SAAS,WAAW,QAAQ;EAC7B;;;;;;;;;;;;;;;AC1JH,MAAM,gBAAgB,IAAI,OA3BN;CAClB;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD,CAIa,SAAS,MAAM,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC,KAAK,IAAI,EACjF,IACD;;;;;AAMD,SAAS,oBAAoB,MAAsB;AACjD,QAAO,KAAK,QAAQ,gBAAgB,UAAU,MAAM,aAAa,CAAC;;AA8EpE,MAAa,cAAyB;CACpC,UAAU;CACV,OA7E6B;EAC7B,cAAc,MAA6B;AACzC,OAAI,KAAK,WAAW,IAAI,CAAE,QAAO,KAAK,MAAM,EAAE;AAC9C,UAAO;;EAET,yBAAyB,GAAW,GAAoB;AACtD,UAAO,gCAAgC,MAAM,GAAG,EAAE;;EAEpD,eAAe,IAAY,IAAqB;AAC9C,UAAO;;EAET,mBAAmB,MAAuB;AACxC,UAAO,SAAS,iBAAiB,SAAS;;EAE5C,qBAAqB,MAAuB;AAC1C,UAAO,SAAS,iBAAiB,SAAS;;EAE5C,0BAA0B;EAC1B,sBAAsB,YAAmC;AAEvD,UADiB,WAAW,QAAQ,OAAO,GAAG,CAAC,QAAQ,QAAQ,GAAG,IAC/C;;EAErB,qBAAqB,WAAkC;GACrD,MAAM,WAAW,UAAU,QAAQ,OAAO,GAAG;AAC7C,OAAI;IAAC;IAAU;IAAO;IAAS;IAAW;IAAO,CAAC,SAAS,SAAS,CAAE,QAAO;AAC7E,UAAO;;EAET,qBAAqB,cAAsB,WAA4B;AACrE,UAAO,aAAa,aAAa,KAAK,UAAU,aAAa;;EAE/D,kBAAkB,YAA8B;AAI9C,UAAO,EAAE;;EAEX,iBAAiB,cAAsB,eAAuB,kBAAuC;GAEnG,MAAM,WAAW,oBAAoB,aAAa;GAClD,MAAM,WAAW,oBAAoB,cAAc;AACnD,OAAI,aAAa,SAAU,QAAO;GAGlC,MAAM,aAAa,MAAc,EAAE,QAAQ,OAAO,GAAG,CAAC,QAAQ,SAAS,GAAG;GAC1E,MAAM,eAAe,UAAU,SAAS;GACxC,MAAM,eAAe,UAAU,SAAS;AACxC,OAAI,iBAAiB,aAAc,QAAO;GAG1C,MAAM,aAAa,aAAa,SAAS,IAAI,GAAG,aAAa,MAAM,IAAI,CAAC,KAAK,GAAI;GACjF,MAAM,aAAa,aAAa,SAAS,IAAI,GAAG,aAAa,MAAM,IAAI,CAAC,KAAK,GAAI;AACjF,OAAI,eAAe,WAAY,QAAO;GAMtC,MAAM,UAAU,UAAU,cAAc;AACxC,OAAI,WAAW,SAAS,WAAW,IAAI,WAAW,SAAS,WAAW;QAElE,iBAAiB,MAAM,YAAY,QACnC,iBAAiB,WAAW,YAAY,QACxC,iBAAiB,QAAQ,YAAY,QACrC,iBAAiB,YAAY,YAAY,KAC/B,QAAO;;AAGrB,UAAO;;EAEV;CAUC,MAAM,gBAAgB,SAA0C;AAE9D,SAAO,qBADS,MAAM,KAAK,QAAQ,QAAQ,CACP;;CAGtC,MAAM,QAAQ,SAAsC;EAClD,MAAM,UAAU,YAAY,QAAQ;AACpC,MAAI,QAAQ,WAAW,EACrB,OAAM,IAAI,eACR,yBAAyB,WACzB,0FACD;EAGH,MAAM,aAAyB,EAAE;EACjC,MAAM,WAAyB,EAAE;EACjC,MAAM,WAAqB,EAAE;EAC7B,MAAM,YAAuB,EAAE;AAE/B,OAAK,MAAM,YAAY,SAAS;GAC9B,MAAM,SAAS,YAAY,UAAU,QAAQ;AAC7C,cAAW,KAAK,GAAG,OAAO,QAAQ;AAClC,YAAS,KAAK,GAAG,OAAO,MAAM;AAC9B,YAAS,KAAK,GAAG,OAAO,MAAM;AAC9B,aAAU,KAAK,GAAG,OAAO,OAAO;;EAGlC,MAAM,EAAE,SAAS,YAAY,aAAa,OAAO,YAAYC,eAC3D,YACA,UACA,UACA,UACD;AAED,SAAO;GACL,UAAU;GACV,eAAe;GACf,8BAAa,IAAI,MAAM,EAAC,aAAa;GACrC;GACA;GACA;GACA;GACA;GACD;;CAEJ;;;;;;;AChID,MAAM,aAAa,IAAI,QAAQ;AAC/B,WAAW,YAAY,SAAS;AAMhC,SAAgB,cAAc,KAAuB;CACnD,MAAM,UAAoB,EAAE;CAC5B,IAAI;AACJ,KAAI;AACF,YAAU,YAAY,IAAI;SACpB;AACN,SAAO;;AAET,MAAK,MAAM,SAAS,SAAS;EAC3B,MAAM,WAAW,KAAK,KAAK,MAAM;EACjC,IAAI;AACJ,MAAI;AACF,UAAO,SAAS,SAAS;UACnB;AACN;;AAEF,MAAI,KAAK,aAAa,EAAE;AACtB,OAAI,MAAM,WAAW,IAAI,IAAI,UAAU,YAAY,UAAU,aAAa,UAAU,WAAY;AAChG,WAAQ,KAAK,GAAG,cAAc,SAAS,CAAC;aAC/B,MAAM,SAAS,MAAM,IAAI,CAAC,MAAM,SAAS,WAAW,CAC7D,SAAQ,KAAK,SAAS;;AAG1B,QAAO,QAAQ,MAAM;;;AAQvB,SAAS,mBAAmB,eAA0C;CACpE,MAAM,OAAO,cAAc,cAAc,MAAM,MAAM,EAAE,SAAS,YAAY;AAC5E,KAAI,CAAC,KAAM,QAAO;CAElB,MAAM,QAAQ,KAAK,cAAc,MAAM,MAAM,EAAE,SAAS,aAAa;AACrE,KAAI,CAAC,SAAS,MAAM,SAAS,QAAS,QAAO;CAE7C,MAAM,YAAY,KAAK,cAAc,MAAM,MAAM,EAAE,SAAS,aAAa;AACzE,KAAI,CAAC,UAAW,QAAO;AAGvB,KAAI,CADgB,UAAU,cAAc,MAAM,MAAM,EAAE,SAAS,gBAAgB,EAAE,SAAS,SAAS,CACrF,QAAO;CAEzB,MAAM,SAAS,UAAU,cAAc,MAAM,MAAM,EAAE,SAAS,iBAAiB;AAC/E,KAAI,CAAC,OAAQ,QAAO;CAEpB,MAAM,UAAU,OAAO,cAAc,MAAM,MAAM,EAAE,SAAS,iBAAiB;AAC7E,QAAO,UAAU,QAAQ,OAAO;;;AAIlC,SAAS,aAAa,eAAoC;CACxD,MAAM,OAAO,cAAc,cAAc,MAAM,MAAM,EAAE,SAAS,YAAY;AAC5E,KAAI,CAAC,KAAM,QAAO;CAElB,MAAM,QAAQ,KAAK,cAAc,MAAM,MAAM,EAAE,SAAS,aAAa;AACrE,KAAI,CAAC,SAAS,MAAM,SAAS,QAAS,QAAO;CAE7C,MAAM,YAAY,KAAK,cAAc,MAAM,MAAM,EAAE,SAAS,aAAa;AACzE,KAAI,CAAC,UAAW,QAAO;AAEvB,QAAO,UAAU,cAAc,MAC5B,MAAM,EAAE,SAAS,iBAAiB,EAAE,SAAS,UAAU,EAAE,SAAS,oBACpE;;;AAIH,SAAS,aAAa,UAA2B;AAC/C,QAAO,SAAS,WAAW,UAAU,IAAI,SAAS,SAAS,IAAI;;;AAIjE,SAAS,SAAS,MAA2B;AAC3C,QAAO,KAAK,cAAc,MAAM,MAAM,EAAE,SAAS,sBAAsB;;AAOzE,SAAS,kBAAkB,UAAyC;CAClE,MAAM,SAA4B,EAAE;CACpC,IAAI,cAAiC;AAErC,MAAK,MAAM,SAAS,SAAS,eAAe;AAC1C,MAAI,MAAM,SAAS,kBAAkB;AACnC,iBAAc;AACd;;AAGF,MAAI,MAAM,SAAS,qBAAqB;AAEtC,OAAI,CAAC,SAAS,MAAM,EAAE;AACpB,kBAAc;AACd;;AAIF,OAAI,eAAe,aAAa,YAAY,EAAE;AAC5C,kBAAc;AACd;;GAGF,MAAM,WAAW,MAAM,cAAc,MAAM,MAAM,EAAE,SAAS,mBAAmB;GAC/E,MAAM,WAAW,MAAM,kBAAkB,OAAO;AAChD,OAAI,CAAC,YAAY,CAAC,UAAU;AAC1B,kBAAc;AACd;;GAGF,MAAM,YAAY,SAAS;GAC3B,MAAM,YAAY,SAAS;GAC3B,MAAM,cAAc,cAAc,mBAAmB,YAAY,GAAG;AAEpE,UAAO,KAAK;IACV,MAAM;IACN,MAAM;IACN,aAAa,eAAe,KAAA;IAC5B,UAAU,aAAa,UAAU;IAClC,CAAC;AAEF,iBAAc;QAEd,eAAc;;AAGlB,QAAO;;AAGT,SAAgB,aAAa,MAAmB,YAAkC;CAChF,MAAM,UAAwB,EAAE;AAEhC,MAAK,MAAM,QAAQ,KAAK,SAAS,kBAAkB,cAAc,EAAE;AACjE,MAAI,CAAC,SAAS,KAAK,CAAE;EAErB,MAAM,WAAW,KAAK,kBAAkB,OAAO;AAC/C,MAAI,CAAC,SAAU;EAEf,MAAM,WAAW,KAAK,kBAAkB,OAAO;AAC/C,MAAI,CAAC,YAAY,SAAS,SAAS,0BAA0B;AAE3D,WAAQ,KAAK;IAAE,MAAM,SAAS;IAAM,QAAQ,EAAE;IAAE;IAAY,CAAC;AAC7D;;AAGF,UAAQ,KAAK;GAAE,MAAM,SAAS;GAAM,QAAQ,kBAAkB,SAAS;GAAE;GAAY,CAAC;;AAGxF,QAAO;;AAOT,SAAgBC,aAAW,MAAmB,YAAgC;CAC5E,MAAM,QAAoB,EAAE;AAE5B,MAAK,MAAM,QAAQ,KAAK,SAAS,kBAAkB,YAAY,EAAE;AAC/D,MAAI,CAAC,SAAS,KAAK,CAAE;EAErB,MAAM,WAAW,KAAK,kBAAkB,OAAO;AAC/C,MAAI,CAAC,SAAU;EAEf,MAAM,WAAW,KAAK,kBAAkB,OAAO;AAC/C,MAAI,CAAC,SAAU;EAEf,MAAM,WAA8B,EAAE;EACtC,IAAI,cAAiC;AAErC,OAAK,MAAM,SAAS,SAAS,eAAe;AAC1C,OAAI,MAAM,SAAS,kBAAkB;AACnC,kBAAc;AACd;;AAEF,OAAI,MAAM,SAAS,gBAAgB;IACjC,MAAM,cAAc,MAAM,kBAAkB,OAAO;AACnD,QAAI,aAAa;KACf,MAAM,cAAc,cAAc,mBAAmB,YAAY,GAAG;AACpE,cAAS,KAAK;MAAE,MAAM,YAAY;MAAM,aAAa,eAAe,KAAA;MAAW,CAAC;;AAElF,kBAAc;SAEd,eAAc;;AAIlB,MAAI,SAAS,SAAS,EACpB,OAAM,KAAK;GAAE,MAAM,SAAS;GAAM;GAAU;GAAY,CAAC;;AAI7D,QAAO;;AAOT,SAAS,YAAY,YAA0D;CAC7E,MAAM,SAA2C,EAAE;AAEnD,MAAK,MAAM,SAAS,WAAW,eAAe;AAC5C,MAAI,MAAM,SAAS,iBAAkB;AAErC,MAAI,MAAM,SAAS,aAAa;GAC9B,MAAM,cAAc,MAAM,kBAAkB,UAAU;GACtD,MAAM,WAAW,MAAM,kBAAkB,OAAO;AAChD,OAAI,eAAe,SACjB,QAAO,KAAK;IAAE,MAAM,YAAY;IAAM,MAAM,SAAS;IAAM,CAAC;;;AAKlE,QAAO;;AAGT,SAAS,kBAAkB,UAA8B;CACvD,MAAM,UAAU,SAAS,kBAAkB,cAAc;AACzD,KAAI,CAAC,QAAS,QAAO;AACrB,QAAO,QAAQ;;AAGjB,SAAS,YAAY,UAA+B;AAClD,QAAO,SAAS,cAAc,MAAM,MAAM,EAAE,SAAS,wBAAwB,EAAE,KAAK,SAAS,QAAQ,CAAC;;AAGxG,SAAgB,gBAAgB,MAAmB,YAAgC;CACjF,MAAM,QAAoB,EAAE;AAE5B,MAAK,MAAM,YAAY,KAAK,SAAS,kBAAkB,YAAY,EAAE;EACnE,MAAM,WAAW,SAAS,kBAAkB,OAAO;AACnD,MAAI,CAAC,SAAU;EACf,MAAM,eAAe,SAAS;EAE9B,MAAM,WAAW,SAAS,kBAAkB,OAAO;AACnD,MAAI,CAAC,SAAU;AAEf,OAAK,MAAM,SAAS,SAAS,eAAe;AAC1C,OAAI,MAAM,SAAS,gBAAiB;AACpC,OAAI,CAAC,SAAS,MAAM,CAAE;GAEtB,MAAM,WAAW,MAAM,kBAAkB,OAAO;AAChD,OAAI,CAAC,SAAU;GAEf,MAAM,aAAa,MAAM,kBAAkB,aAAa;AAExD,SAAM,KAAK;IACT;IACA,MAAM,SAAS;IACf,QAAQ,aAAa,YAAY,WAAW,GAAG,EAAE;IACjD,YAAY,kBAAkB,MAAM;IACpC,SAAS,YAAY,MAAM;IAC3B;IACD,CAAC;;;AAIN,QAAO;;AAOT,SAAgB,YAAY,MAAmB,YAAiC;CAC9E,MAAM,SAAsB,EAAE;AAE9B,MAAK,MAAM,aAAa,KAAK,SAAS,kBAAkB,aAAa,EAAE;AACrE,MAAI,CAAC,SAAS,UAAU,CAAE;EAE1B,MAAM,WAAW,UAAU,kBAAkB,OAAO;AACpD,MAAI,CAAC,SAAU;EAEf,MAAM,WAAW,UAAU,kBAAkB,OAAO;AACpD,MAAI,CAAC,SAAU;EAEf,MAAM,UAAsB,EAAE;AAE9B,OAAK,MAAM,SAAS,SAAS,eAAe;AAE1C,OAAI,MAAM,SAAS,6BAA6B,MAAM,SAAS,gBAAiB;GAEhF,MAAM,aAAa,MAAM,kBAAkB,OAAO;AAClD,OAAI,CAAC,WAAY;GAEjB,MAAM,aAAa,MAAM,kBAAkB,aAAa;AAExD,WAAQ,KAAK;IACX,cAAc;IACd,MAAM,WAAW;IACjB,QAAQ,aAAa,YAAY,WAAW,GAAG,EAAE;IACjD,YAAY,kBAAkB,MAAM;IACpC,SAAS,YAAY,MAAM;IAC3B;IACD,CAAC;;AAGJ,MAAI,QAAQ,SAAS,EACnB,QAAO,KAAK;GAAE,MAAM,SAAS;GAAM;GAAS;GAAY,CAAC;;AAI7D,QAAO;;AAOT,SAAgBC,mBAAiB,MAAmB,YAAqC;CACvF,MAAM,UAA2B,EAAE;AAEnC,MAAK,MAAM,QAAQ,KAAK,SAAS,kBAAkB,YAAY,EAAE;AAC/D,MAAI,CAAC,SAAS,KAAK,CAAE;EAErB,MAAM,WAAW,KAAK,kBAAkB,OAAO;EAC/C,MAAM,WAAW,KAAK,kBAAkB,OAAO;AAC/C,MAAI,CAAC,YAAY,CAAC,SAAU;AAE5B,UAAQ,KAAK;GAAE,MAAM,SAAS;GAAM,gBAAgB,SAAS;GAAM;GAAY,CAAC;;AAGlF,QAAO;;AAeT,SAAgB,cAAc,UAAkB,SAAiC;CAC/E,MAAM,SAAS,aAAa,UAAU,QAAQ;CAC9C,MAAM,UAAU,SAAS,SAAS,SAAS;CAC3C,MAAM,OAAOC,YAAU,YAAY,OAAO;AAE1C,QAAO;EACL,SAAS,aAAa,MAAM,QAAQ;EACpC,OAAOF,aAAW,MAAM,QAAQ;EAChC,OAAO,gBAAgB,MAAM,QAAQ;EACrC,QAAQ,YAAY,MAAM,QAAQ;EAClC,aAAaC,mBAAiB,MAAM,QAAQ;EAC7C;;;;AC1YH,SAAS,iBAAiB,GAAmB;AAC3C,QAAO;;;AAIT,SAAS,iBAAiB,YAA4B;CACpD,MAAM,QAAQ,WAAW,MAAM,mCAAmC;AAClE,KAAI,MAAO,QAAO,MAAM,GAAG,MAAM;AACjC,QAAO;;AAOT,SAAgBE,eACd,YACA,UACA,UACA,WACA,gBAOA;CACA,MAAM,UAAoC,EAAE;CAC5C,MAAM,aAA2C,EAAE;CACnD,MAAM,cAA4C,EAAE;CACpD,MAAM,QAAiC,EAAE;CAGzC,MAAM,oCAAoB,IAAI,KAAyB;AACvD,MAAK,MAAM,MAAM,UAAU;AACzB,MAAI,CAAC,GAAG,aAAc;AACtB,MAAI,CAAC,kBAAkB,IAAI,GAAG,aAAa,CAAE,mBAAkB,IAAI,GAAG,cAAc,EAAE,CAAC;AACvF,oBAAkB,IAAI,GAAG,aAAa,CAAE,KAAK,GAAG;;AAIlD,MAAK,MAAM,KAAK,YAAY;EAC1B,MAAM,UAAU,kBAAkB,IAAI,EAAE,KAAK;AAE7C,MAAI,WAAW,QAAQ,SAAS,GAAG;GAEjC,MAAM,aAA0C,EAAE;GAClD,MAAM,aAA0C,EAAE;AAElD,QAAK,MAAM,SAAS,EAAE,QAAQ;IAC5B,MAAM,YAAY,MAAM,eAAe,MAAM;AAC7C,eAAW,aAAa;KACtB,MAAM;KACN,MAAM,iBAAiB,MAAM,KAAK;KAClC,UAAU;KACX;;AAGH,QAAK,MAAM,MAAM,SAAS;IACxB,MAAM,SAAqB,GAAG,OAAO,KAAK,OAAO;KAC/C,MAAM,EAAE;KACR,MAAM,iBAAiB,EAAE,KAAK;KAC9B,UAAU,EAAE,KAAK,WAAW,UAAU;KACtC,cAAc;KACf,EAAE;IACH,MAAM,aAAa,iBAAiB,GAAG,WAAW;AAClD,QAAI,CAAC,WAAW,GAAG,MAAO,YAAW,GAAG,QAAQ,EAAE;AAClD,eAAW,GAAG,MAAM,KAAK;KACvB,MAAM,GAAG;KACT;KACA,YAAY,iBAAiB,WAAW;KACxC,OAAO,GAAG;KACX,CAAC;;AAGJ,WAAQ,EAAE,QAAQ;IAChB,MAAM,EAAE;IACR,YAAY,EAAE;IACd,SAAS,WAAW,WAAW;IAC/B,YAAY,WAAW,WAAW;IAClC,mBAAmB,EAAE;IACtB;SACI;GAEL,MAAM,SAAmC,EAAE;AAC3C,QAAK,MAAM,SAAS,EAAE,QAAQ;IAC5B,MAAM,YAAY,MAAM,eAAe,MAAM;AAC7C,WAAO,aAAa;KAClB,MAAM;KACN,MAAM,iBAAiB,MAAM,KAAK;KAClC,UAAU,MAAM;KACjB;;AAEH,cAAW,EAAE,QAAQ;IACnB,MAAM,EAAE;IACR,YAAY,EAAE;IACd,QAAQ,WAAW,OAAO;IAC1B,SAAS,EAAE;IACZ;;;AAKL,MAAK,MAAM,KAAK,UAAU;EACxB,MAAM,UAA2C,EAAE;AACnD,OAAK,MAAM,KAAK,EAAE,SAChB,SAAQ,EAAE,QAAQ,EAAE,eAAe,EAAE;AAEvC,QAAM,EAAE,QAAQ;GAAE,MAAM,EAAE;GAAM,YAAY,EAAE;GAAY,SAAS,WAAW,QAAQ;GAAE;;AAI1F,MAAK,MAAM,MAAM,eACf,aAAY,GAAG,QAAQ;EAAE,MAAM,GAAG;EAAM,YAAY,GAAG;EAAY,OAAO,iBAAiB,GAAG,eAAe;EAAE;AAIjH,MAAK,MAAM,SAAS,WAAW;EAC7B,MAAM,aAA0C,EAAE;AAElD,OAAK,MAAM,MAAM,MAAM,SAAS;GAC9B,MAAM,SAAqB,GAAG,OAAO,KAAK,OAAO;IAC/C,MAAM,EAAE;IACR,MAAM,iBAAiB,EAAE,KAAK;IAC9B,UAAU,EAAE,KAAK,WAAW,UAAU;IACvC,EAAE;GACH,MAAM,aAAa,iBAAiB,GAAG,WAAW;AAClD,OAAI,CAAC,WAAW,GAAG,MAAO,YAAW,GAAG,QAAQ,EAAE;AAClD,cAAW,GAAG,MAAM,KAAK;IACvB,MAAM,GAAG;IACT;IACA,YAAY,iBAAiB,WAAW;IACxC,OAAO,GAAG;IACX,CAAC;;AAGJ,UAAQ,MAAM,QAAQ;GACpB,MAAM,MAAM;GACZ,YAAY,MAAM;GAClB,SAAS,WAAW,WAAW;GAC/B,YAAY,EAAE;GACd,mBAAmB,EAAE;GACtB;;CAIH,MAAM,YAAY,IAAI,iBAAiB;AAEvC,MAAK,MAAM,CAAC,MAAM,QAAQ,OAAO,QAAQ,QAAQ,CAAE,KAAI,IAAI,WAAY,WAAU,IAAI,IAAI,YAAY,KAAK;AAC1G,MAAK,MAAM,CAAC,MAAM,UAAU,OAAO,QAAQ,WAAW,CAAE,KAAI,MAAM,WAAY,WAAU,IAAI,MAAM,YAAY,KAAK;AACnH,MAAK,MAAM,CAAC,MAAM,OAAO,OAAO,QAAQ,YAAY,CAAE,KAAI,GAAG,WAAY,WAAU,IAAI,GAAG,YAAY,KAAK;AAC3G,MAAK,MAAM,CAAC,MAAM,OAAO,OAAO,QAAQ,MAAM,CAAE,KAAI,GAAG,WAAY,WAAU,IAAI,GAAG,YAAY,KAAK;CAErG,MAAM,UAAU,UAAU,UAAU;AAEpC,QAAO;EACL,SAAS,WAAW,QAAQ;EAC5B,YAAY,WAAW,WAAW;EAClC,aAAa,WAAW,YAAY;EACpC,OAAO,WAAW,MAAM;EACxB,SAAS,WAAW,QAAQ;EAC7B;;AC/GH,MAAa,gBAA2B;CACtC,UAAU;CACV,OA1D+B;EAC/B,cAAc,MAA6B;GACzC,MAAM,QAAQ,KAAK,MAAM,iBAAiB;AAC1C,UAAO,QAAQ,MAAM,KAAK;;EAE5B,yBAAyB,GAAW,GAAoB;AACtD,UAAO,gCAAgC,MAAM,GAAG,EAAE;;EAEpD,eAAe,IAAY,IAAqB;AAC9C,UAAO;;EAET,mBAAmB,MAAuB;AAExC,UAAO,UAAU,KAAK,KAAK,IAAI,oBAAoB,KAAK,KAAK;;EAE/D,qBAAqB,MAAuB;AAC1C,UAAO,SAAS,uBAAuB,SAAS;;EAElD,0BAA0B;EAC1B,sBAAsB,YAAmC;GAEvD,IAAI,QAAQ;GACZ,MAAM,cAAc,MAAM,MAAM,mCAAmC;AACnE,OAAI,YAAa,SAAQ,YAAY,GAAG,MAAM;GAC9C,MAAM,WAAW,MAAM,MAAM,uBAAuB;AACpD,OAAI,SAAU,SAAQ,SAAS,GAAG,MAAM;GACxC,MAAM,WAAW,MAAM,MAAM,0BAA0B;AACvD,OAAI,SAAU,SAAQ,SAAS,GAAG,MAAM;AAExC,WAAQ,MAAM,QAAQ,gCAAgC,GAAG;AACzD,OAAI;IAAC;IAAM;IAAU;IAAO;IAAQ;IAAO;IAAO;IAAO;IAAO;IAAO;IAAO;IAAQ,CAAC,SAAS,MAAM,CACpG,QAAO;AAET,UAAO;;EAET,qBAAqB,WAAkC;GACrD,IAAI,QAAQ,UAAU,QAAQ,gCAAgC,GAAG;AACjE,OAAI;IAAC;IAAU;IAAQ;IAAO;IAAQ;IAAO;IAAO;IAAO;IAAO;IAAO;IAAO;IAAQ,CAAC,SAAS,MAAM,CACtG,QAAO;AAET,UAAO;;EAET,qBAAqB,cAAsB,WAA4B;AAGrE,UADmB,aAAa,QAAQ,MAAM,GAAG,CAAC,aAAa,KACzC,UAAU,aAAa;;EAE/C,kBAAkB,WAA6B;AAC7C,UAAO,CAAC,GAAG,UAAU,UAAU;;EAElC;CAUC,MAAM,gBAAgB,SAA0C;AAE9D,SAAO,qBADS,MAAM,KAAK,QAAQ,QAAQ,CACP;;CAGtC,MAAM,QAAQ,SAAsC;EAClD,MAAM,UAAU,cAAc,QAAQ;AACtC,MAAI,QAAQ,WAAW,EACrB,OAAM,IAAI,eACR,yBAAyB,WACzB,4FACD;EAGH,MAAM,aAA2B,EAAE;EACnC,MAAM,WAAuB,EAAE;EAC/B,MAAM,WAAuB,EAAE;EAC/B,MAAM,YAAyB,EAAE;EACjC,MAAM,iBAAkC,EAAE;AAE1C,OAAK,MAAM,YAAY,SAAS;GAC9B,MAAM,SAAS,cAAc,UAAU,QAAQ;AAC/C,cAAW,KAAK,GAAG,OAAO,QAAQ;AAClC,YAAS,KAAK,GAAG,OAAO,MAAM;AAC9B,YAAS,KAAK,GAAG,OAAO,MAAM;AAC9B,aAAU,KAAK,GAAG,OAAO,OAAO;AAChC,kBAAe,KAAK,GAAG,OAAO,YAAY;;EAG5C,MAAM,EAAE,SAAS,YAAY,aAAa,OAAO,YAAYC,eAC3D,YACA,UACA,UACA,WACA,eACD;AAED,SAAO;GACL,UAAU;GACV,eAAe;GACf,8BAAa,IAAI,MAAM,EAAC,aAAa;GACrC;GACA;GACA;GACA;GACA;GACD;;CAEJ;;;;;;;ACjED,SAAgB,gBAAgB,KAAuB;CACrD,MAAM,UAAoB,EAAE;CAC5B,IAAI;AACJ,KAAI;AACF,YAAU,YAAY,IAAI;SACpB;AACN,SAAO;;AAET,MAAK,MAAM,SAAS,SAAS;EAC3B,MAAM,WAAW,KAAK,KAAK,MAAM;EACjC,IAAI;AACJ,MAAI;AACF,UAAO,SAAS,SAAS;UACnB;AACN;;AAEF,MAAI,KAAK,aAAa,EAAE;AACtB,OAAI,MAAM,WAAW,IAAI,IAAI,UAAU,WAAW,UAAU,UAAU,UAAU,cAAe;AAC/F,WAAQ,KAAK,GAAG,gBAAgB,SAAS,CAAC;aACjC,MAAM,SAAS,MAAM,IAAI,CAAC,MAAM,SAAS,UAAU,CAC5D,SAAQ,KAAK,SAAS;;AAG1B,QAAO,QAAQ,MAAM;;;AAQvB,SAAS,mBAAmB,QAAwB;CAClD,MAAM,QAAQ,OAAO,MAAM,uBAAuB;AAClD,QAAO,QAAQ,MAAM,KAAK;;;AAI5B,SAASC,gBAAc,QAAwB;CAE7C,IAAI,SAAS,OAAO,QAAQ,qBAAqB,GAAG;AAEpD,UAAS,OAAO,QAAQ,eAAe,GAAG;AAC1C,QAAO;;;;;;AAOT,SAASC,0BAAwB,MAA6B;CAC5D,MAAM,QAAQ,KAAK,MAAM,6BAA6B;AACtD,QAAO,QAAQ,MAAM,KAAK;;;;;;AAO5B,SAAS,uBAAuB,aAAoC;CAClE,MAAM,SAAwB,EAAE;CAGhC,MAAM,SAAS,oBAAoB,YAAY;AAE/C,MAAK,MAAM,SAAS,QAAQ;EAC1B,MAAM,UAAU,MAAM,MAAM;AAC5B,MAAI,CAAC,QAAS;EAGd,MAAM,WAAWA,0BAAwB,QAAQ;EAGjD,MAAM,aAAa,QAAQ,MACzB,8FACD;AACD,MAAI,CAAC,WAAY;EAEjB,MAAM,OAAO,WAAW;EACxB,MAAM,UAAU,WAAW,GAAG,MAAM;EACpC,MAAM,aAAa,WAAW,OAAO,KAAA;EAGrC,MAAM,aAAa,QAAQ,SAAS,IAAI;EACxC,MAAM,OAAO;AAEb,SAAO,KAAK;GACV;GACA;GACA,UAAU,YAAY,KAAA;GACtB,UAAU,cAAc;GACzB,CAAC;;AAGJ,QAAO;;;AAIT,SAAS,oBAAoB,MAAwB;CACnD,MAAM,SAAmB,EAAE;CAC3B,IAAI,QAAQ;CACZ,IAAI,UAAU;CACd,IAAI,WAAW;CACf,IAAI,aAAa;AAEjB,MAAK,IAAI,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;EACpC,MAAM,KAAK,KAAK;AAEhB,MAAI,UAAU;AACZ,cAAW;AACX,OAAI,OAAO,cAAc,KAAK,IAAI,OAAO,KACvC,YAAW;AAEb;;AAGF,MAAI,OAAO,QAAO,OAAO,KAAK;AAC5B,cAAW;AACX,gBAAa;AACb,cAAW;AACX;;AAGF,MAAI,OAAO,OAAO,OAAO,OAAO,OAAO,KAAK;AAC1C;AACA,cAAW;aACF,OAAO,OAAO,OAAO,OAAO,OAAO,KAAK;AACjD;AACA,cAAW;aACF,OAAO,OAAO,UAAU,GAAG;AACpC,UAAO,KAAK,QAAQ;AACpB,aAAU;QAEV,YAAW;;AAIf,KAAI,QAAQ,MAAM,CAChB,QAAO,KAAK,QAAQ;AAGtB,QAAO;;AAOT,SAAS,eAAe,QAAgB,YAAoB,aAAmC;CAC7F,MAAM,QAAsB,EAAE;CAG9B,MAAM,YAAY;CAClB,IAAI;AACJ,SAAQ,QAAQ,UAAU,KAAK,OAAO,MAAM,MAAM;EAChD,MAAM,OAAO,MAAM;EACnB,MAAM,OAAO,MAAM;EAEnB,MAAM,UAAkC,EAAE;EAG1C,MAAM,cAAc;EACpB,IAAI;AACJ,UAAQ,cAAc,YAAY,KAAK,KAAK,MAAM,MAAM;GACtD,MAAM,aAAa,YAAY;AAE/B,OAAI;IAAC;IAAO;IAAO;IAAO;IAAY;IAAa;IAAS,CAAC,SAAS,WAAW,CAAE;AAEnF,WAAQ,cADY,YAAY,OAAO,KAAA,IAAY,YAAY,KAAK;;AAItE,MAAI,OAAO,KAAK,QAAQ,CAAC,SAAS,EAChC,OAAM,KAAK;GAAE;GAAM;GAAS;GAAY;GAAa,CAAC;;AAI1D,QAAO;;AAOT,SAAS,iBAAiB,QAAgB,YAAoB,aAAwC;CACpG,MAAM,cAAiC,EAAE;CAIzC,MAAM,sBAAsB;CAC5B,IAAI;AACJ,SAAQ,QAAQ,oBAAoB,KAAK,OAAO,MAAM,MAAM;EAC1D,MAAM,OAAO,MAAM;EACnB,MAAM,WAAW,MAAM,QAAQ,MAAM,GAAG;EAGxC,IAAI,QAAQ;EACZ,IAAI,MAAM;AACV,SAAO,MAAM,OAAO,UAAU,QAAQ,GAAG;AACvC,OAAI,OAAO,SAAS,IAAK;YAChB,OAAO,SAAS,IAAK;AAC9B;;EAIF,MAAM,SAAS,uBADK,OAAO,MAAM,UAAU,MAAM,EAAE,CACD;AAElD,cAAY,KAAK;GAAE;GAAM;GAAQ;GAAY;GAAa,CAAC;;AAG7D,QAAO;;AAOT,SAASC,eAAa,QAAgB,YAAoB,aAAoC;CAC5F,MAAM,UAAyB,EAAE;CAIjC,MAAM,kBACJ;CACF,IAAI;AACJ,SAAQ,QAAQ,gBAAgB,KAAK,OAAO,MAAM,MAAM;EACtD,MAAM,OAAO,MAAM;EACnB,MAAM,mBAAmB,MAAM,MAAM;EAGrC,MAAM,aAAa,OAAO,QAAQ,KAAK,MAAM,QAAQ,MAAM,GAAG,SAAS,EAAE;EACzE,IAAI,QAAQ;EACZ,IAAI,MAAM,aAAa;AACvB,SAAO,MAAM,OAAO,UAAU,QAAQ,GAAG;AACvC,OAAI,OAAO,SAAS,IAAK;YAChB,OAAO,SAAS,IAAK;AAC9B;;EAGF,MAAM,YAAY,OAAO,MAAM,aAAa,GAAG,MAAM,EAAE;EAGvD,MAAM,oBAAsD,EAAE;AAC9D,MAAI,iBAAiB,MAAM,EAAE;GAC3B,MAAM,SAAS,oBAAoB,iBAAiB;AACpD,QAAK,MAAM,SAAS,QAAQ;IAE1B,MAAM,aADU,MAAM,MAAM,CACD,MAAM,8DAA8D;AAC/F,QAAI,WACF,mBAAkB,KAAK;KAAE,MAAM,WAAW;KAAI,MAAM,WAAW,GAAG,MAAM;KAAE,CAAC;;;EAMjF,MAAM,UAAUC,eAAa,UAAU;AAEvC,MAAI,QAAQ,SAAS,EACnB,SAAQ,KAAK;GAAE;GAAM;GAAmB;GAAS;GAAY;GAAa,CAAC;;AAI/E,QAAO;;;AAIT,SAASA,eAAa,WAAmC;CACvD,MAAM,UAA0B,EAAE;CAIlC,MAAM,cACJ;CACF,IAAI;AACJ,SAAQ,QAAQ,YAAY,KAAK,UAAU,MAAM,MAAM;EACrD,MAAM,aAAa,MAAM,MAAM;EAC/B,MAAM,OAAO,MAAM;EACnB,MAAM,YAAY,MAAM;EACxB,MAAM,aAAa,MAAM,MAAM;AAG/B,MAAI,eAAe,aAAa,eAAe,YAAa;EAE5D,MAAM,SAA8D,EAAE;AACtE,MAAI,UAAU,MAAM,EAAE;GACpB,MAAM,aAAa,oBAAoB,UAAU;AACjD,QAAK,MAAM,QAAQ,YAAY;IAE7B,MAAM,aADU,KAAK,MAAM,CACA,MAAM,wCAAwC;AACzE,QAAI,YAAY;KACd,MAAM,YAAY,WAAW,GAAG,MAAM;KACtC,MAAM,aAAa,WAAW,OAAO,KAAA;AACrC,YAAO,KAAK;MACV,MAAM,WAAW;MACjB,MAAM;MACN,UAAU,UAAU,SAAS,IAAI,IAAI;MACtC,CAAC;;;;AAKR,UAAQ,KAAK;GAAE;GAAM;GAAQ;GAAY;GAAY,CAAC;;AAGxD,QAAO;;AAOT,SAAS,iBAAiB,QAAgB,YAAoB,aAAwC;CACpG,MAAM,UAA6B,EAAE;CAErC,MAAM,aAAa;CACnB,IAAI;AACJ,SAAQ,QAAQ,WAAW,KAAK,OAAO,MAAM,KAC3C,SAAQ,KAAK;EACX,MAAM,MAAM;EACZ,OAAO,MAAM,GAAG,MAAM;EACtB;EACA;EACD,CAAC;AAGJ,QAAO;;;AAQT,SAAgB,gBAAgB,UAAkB,SAAmC;CACnF,MAAM,SAAS,aAAa,UAAU,QAAQ;CAC9C,MAAM,UAAU,SAAS,SAAS,SAAS;CAC3C,MAAM,UAAUH,gBAAc,OAAO;CACrC,MAAM,cAAc,mBAAmB,QAAQ;AAE/C,QAAO;EACL,aAAa,iBAAiB,SAAS,SAAS,YAAY;EAC5D,SAASE,eAAa,SAAS,SAAS,YAAY;EACpD,OAAO,eAAe,SAAS,SAAS,YAAY;EACpD,aAAa,iBAAiB,SAAS,SAAS,YAAY;EAC7D;;;;ACnYH,SAAgBE,eACd,gBACA,YACA,UACA,gBAOA;CACA,MAAM,UAAoC,EAAE;CAC5C,MAAM,aAA2C,EAAE;CACnD,MAAM,cAA4C,EAAE;CACpD,MAAM,QAAiC,EAAE;CAEzC,MAAM,YAAY,IAAI,iBAAiB;AAGvC,MAAK,MAAM,MAAM,gBAAgB;EAC/B,MAAM,SAAmC,EAAE;AAC3C,OAAK,MAAM,SAAS,GAAG,QAAQ;GAC7B,MAAM,YAAY,MAAM,YAAY,MAAM;AAC1C,UAAO,aAAa;IAClB,MAAM;IACN,MAAM,MAAM;IACZ,UAAU,MAAM;IACjB;;AAEH,aAAW,GAAG,QAAQ;GACpB,MAAM,GAAG;GACT,YAAY,GAAG;GACf,QAAQ,WAAW,OAAO;GAC1B,SAAS,EAAE;GACZ;AACD,YAAU,IAAI,GAAG,YAAY,GAAG,KAAK;;AAIvC,MAAK,MAAM,OAAO,YAAY;EAC5B,MAAM,UAAuC,EAAE;EAC/C,MAAM,aAA0C,EAAE;AAElD,OAAK,MAAM,UAAU,IAAI,SAAS;GAChC,MAAM,SAAqB,OAAO,OAAO,KAAK,OAAO;IACnD,MAAM,EAAE;IACR,MAAM,EAAE;IACR,UAAU,EAAE;IACZ,cAAc;IACf,EAAE;AAEH,OAAI,CAAC,QAAQ,OAAO,MAAO,SAAQ,OAAO,QAAQ,EAAE;AACpD,WAAQ,OAAO,MAAM,KAAK;IACxB,MAAM,OAAO;IACb;IACA,YAAY,OAAO;IACnB,OAAO;IACR,CAAC;;EAGJ,MAAM,oBAAgC,IAAI,kBAAkB,KAAK,OAAO;GACtE,MAAM,EAAE;GACR,MAAM,EAAE;GACR,UAAU;GACV,cAAc;GACf,EAAE;AAEH,UAAQ,IAAI,QAAQ;GAClB,MAAM,IAAI;GACV,YAAY,IAAI;GAChB,SAAS,WAAW,QAAQ;GAC5B,YAAY,WAAW,WAAW;GAClC;GACD;AACD,YAAU,IAAI,IAAI,YAAY,IAAI,KAAK;;AAIzC,MAAK,MAAM,MAAM,UAAU;AACzB,QAAM,GAAG,QAAQ;GACf,MAAM,GAAG;GACT,YAAY,GAAG;GACf,SAAS,WAAW,GAAG,QAAQ;GAChC;AACD,YAAU,IAAI,GAAG,YAAY,GAAG,KAAK;;AAIvC,MAAK,MAAM,MAAM,gBAAgB;AAC/B,cAAY,GAAG,QAAQ;GACrB,MAAM,GAAG;GACT,YAAY,GAAG;GACf,OAAO,GAAG;GACX;AACD,YAAU,IAAI,GAAG,YAAY,GAAG,KAAK;;CAGvC,MAAM,UAAU,UAAU,UAAU;AAEpC,QAAO;EACL,SAAS,WAAW,QAAQ;EAC5B,YAAY,WAAW,WAAW;EAClC,aAAa,WAAW,YAAY;EACpC,OAAO,WAAW,MAAM;EACxB,SAAS,WAAW,QAAQ;EAC7B;;ACpDH,MAAa,kBAA6B;CACxC,UAAU;CACV,OArDiC;EACjC,cAAc,MAA6B;AACzC,OAAI,KAAK,SAAS,IAAI,CAAE,QAAO,KAAK,MAAM,GAAG,GAAG;AAChD,UAAO;;EAET,yBAAyB,GAAW,GAAoB;AACtD,UAAO,gCAAgC,MAAM,GAAG,EAAE;;EAEpD,eAAe,IAAY,IAAqB;AAC9C,UAAO;;EAET,mBAAmB,MAAuB;AACxC,UAAO,UAAU,KAAK,KAAK,IAAI,oBAAoB,KAAK,KAAK;;EAE/D,qBAAqB,MAAuB;AAC1C,UAAO,SAAS,SAAS,SAAS;;EAEpC,0BAA0B;EAC1B,sBAAsB,YAAmC;GACvD,IAAI,QAAQ;AAEZ,OAAI,MAAM,SAAS,IAAI,CAAE,SAAQ,MAAM,MAAM,GAAG,GAAG;GAEnD,MAAM,YAAY,MAAM,MAAM,yCAAyC;AACvE,OAAI,UAAW,SAAQ,UAAU;GAEjC,MAAM,iBAAiB,MAAM,MAAM,wBAAwB;AAC3D,OAAI,eAAgB,SAAQ,eAAe;AAE3C,OAAI;IAAC;IAAU;IAAO;IAAQ;IAAS;IAAU;IAAW;IAAQ;IAAO,CAAC,SAAS,MAAM,CAAE,QAAO;AACpG,UAAO;;EAET,qBAAqB,WAAkC;GACrD,IAAI,QAAQ;AACZ,OAAI,MAAM,SAAS,IAAI,CAAE,SAAQ,MAAM,MAAM,GAAG,GAAG;AACnD,OAAI;IAAC;IAAU;IAAO;IAAQ;IAAS;IAAU;IAAU,CAAC,SAAS,MAAM,CAAE,QAAO;AACpF,UAAO;;EAET,qBAAqB,cAAsB,WAA4B;AAErE,UAAO,aAAa,aAAa,KAAK,UAAU,aAAa;;EAE/D,kBAAkB,WAA6B;AAC7C,UAAO,CAAC,GAAG,UAAU,UAAU;;EAElC;CAUC,MAAM,gBAAgB,SAA0C;AAE9D,SAAO,qBADS,MAAM,KAAK,QAAQ,QAAQ,CACP;;CAGtC,MAAM,QAAQ,SAAsC;EAClD,MAAM,UAAU,gBAAgB,QAAQ;AACxC,MAAI,QAAQ,WAAW,EACrB,OAAM,IAAI,eACR,yBAAyB,WACzB,8FACD;EAGH,MAAM,iBAAoC,EAAE;EAC5C,MAAM,aAA4B,EAAE;EACpC,MAAM,WAAyB,EAAE;EACjC,MAAM,iBAAoC,EAAE;AAE5C,OAAK,MAAM,YAAY,SAAS;GAC9B,MAAM,SAAS,gBAAgB,UAAU,QAAQ;AACjD,kBAAe,KAAK,GAAG,OAAO,YAAY;AAC1C,cAAW,KAAK,GAAG,OAAO,QAAQ;AAClC,YAAS,KAAK,GAAG,OAAO,MAAM;AAC9B,kBAAe,KAAK,GAAG,OAAO,YAAY;;EAG5C,MAAM,EAAE,SAAS,YAAY,aAAa,OAAO,YAAYC,eAC3D,gBACA,YACA,UACA,eACD;AAED,SAAO;GACL,UAAU;GACV,eAAe;GACf,8BAAa,IAAI,MAAM,EAAC,aAAa;GACrC;GACA;GACA;GACA;GACA;GACD;;CAEJ;;;;;;;ACvED,SAAgB,gBAAgB,KAAuB;CACrD,MAAM,UAAoB,EAAE;CAC5B,IAAI;AACJ,KAAI;AACF,YAAU,YAAY,IAAI;SACpB;AACN,SAAO;;AAET,MAAK,MAAM,SAAS,SAAS;EAC3B,MAAM,WAAW,KAAK,KAAK,MAAM;EACjC,IAAI;AACJ,MAAI;AACF,UAAO,SAAS,SAAS;UACnB;AACN;;AAEF,MAAI,KAAK,aAAa,EAAE;AACtB,OAAI,MAAM,WAAW,IAAI,IAAI,UAAU,SAAS,UAAU,SAAS,UAAU,UAAU,UAAU,QAC/F;AAEF,WAAQ,KAAK,GAAG,gBAAgB,SAAS,CAAC;aACjC,MAAM,SAAS,MAAM,IAAI,CAAC,MAAM,SAAS,UAAU,IAAI,CAAC,MAAM,SAAS,WAAW,CAC3F,SAAQ,KAAK,SAAS;;AAG1B,QAAO,QAAQ,MAAM;;;AAQvB,SAAS,iBAAiB,QAAwB;CAEhD,MAAM,kBAAkB,OAAO,MAAM,6BAA6B;AAClE,KAAI,gBAAiB,QAAO,gBAAgB;CAG5C,MAAM,aAAa,OAAO,MAAM,8BAA8B;AAC9D,KAAI,WAAY,QAAO,WAAW;AAElC,QAAO;;;AAIT,SAAS,cAAc,QAAwB;CAC7C,IAAI,SAAS,OAAO,QAAQ,qBAAqB,GAAG;AACpD,UAAS,OAAO,QAAQ,eAAe,GAAG;AAC1C,QAAO;;;AAIT,SAAS,wBAAwB,MAA6B;CAC5D,MAAM,QAAQ,KAAK,MAAM,gCAAgC;AACzD,QAAO,QAAQ,MAAM,KAAK;;;AAI5B,SAAS,uBAAuB,MAA6B;CAC3D,MAAM,QAAQ,KAAK,MAAM,0CAA0C;AACnE,QAAO,QAAQ,MAAM,KAAK;;AAO5B,SAAS,WAAW,QAAgB,YAAkC;CACpE,MAAM,QAAsB,EAAE;CAC9B,MAAM,KAAK,iBAAiB,OAAO;CAGnC,MAAM,YAAY;CAClB,IAAI;AACJ,SAAQ,QAAQ,UAAU,KAAK,OAAO,MAAM,MAAM;EAChD,MAAM,OAAO,MAAM;EACnB,MAAM,OAAO,MAAM;EACnB,MAAM,UAAkC,EAAE;EAG1C,MAAM,QAAQ,KAAK,MAAM,IAAI;AAC7B,OAAK,MAAM,QAAQ,OAAO;GACxB,MAAM,UAAU,KAAK,MAAM;AAC3B,OAAI,CAAC,QAAS;GAEd,MAAM,YAAY,uBAAuB,QAAQ;GACjD,MAAM,kBAAkB,QAAQ,MAAM,YAAY;AAClD,OAAI,iBAAiB;IACnB,MAAM,aAAa,gBAAgB;AACnC,YAAQ,cAAc,aAAa;;;AAIvC,MAAI,OAAO,KAAK,QAAQ,CAAC,SAAS,EAChC,OAAM,KAAK;GAAE;GAAM,WAAW;GAAI;GAAS;GAAY,CAAC;;AAI5D,QAAO;;AAOT,SAAS,aAAa,QAAgB,YAAmC;CACvE,MAAM,UAAyB,EAAE;CACjC,MAAM,KAAK,iBAAiB,OAAO;CAGnC,MAAM,kBAAkB;CACxB,IAAI;AACJ,SAAQ,QAAQ,gBAAgB,KAAK,OAAO,MAAM,MAAM;EACtD,MAAM,OAAO,MAAM;EACnB,MAAM,aAAa,OAAO,QAAQ,KAAK,MAAM,QAAQ,MAAM,GAAG,SAAS,EAAE;EAGzE,IAAI,QAAQ;EACZ,IAAI,MAAM,aAAa;AACvB,SAAO,MAAM,OAAO,UAAU,QAAQ,GAAG;AACvC,OAAI,OAAO,SAAS,IAAK;YAChB,OAAO,SAAS,IAAK;AAC9B;;EAGF,MAAM,YAAY,OAAO,MAAM,aAAa,GAAG,MAAM,EAAE;EAGvD,MAAM,aAAa,gBAAgB,UAAU;EAG7C,MAAM,UAAU,aAAa,UAAU;EAGvC,MAAM,oBAAoB,iBAAiB,WAAW,KAAK;EAG3D,MAAM,YAAY,QAAQ,SAAS;AAEnC,UAAQ,KAAK;GACX;GACA,WAAW;GACX;GACA;GACA;GACA;GACA;GACD,CAAC;;AAGJ,QAAO;;;AAIT,SAAS,gBAAgB,WAAqC;CAC5D,MAAM,aAA+B,EAAE;CAGvC,MAAM,QAAQ,UAAU,MAAM,KAAK;CACnC,IAAI,kBAAiC;AAErC,MAAK,MAAM,QAAQ,OAAO;EACxB,MAAM,UAAU,KAAK,MAAM;EAG3B,MAAM,gBAAgB,wBAAwB,QAAQ;AACtD,MAAI,eAAe;AACjB,qBAAkB;AAClB;;EAIF,MAAM,YAAY,QAAQ,MAAM,uEAAuE;AACvG,MAAI,WAAW;GACb,MAAM,OAAO,UAAU;GACvB,MAAM,OAAO,UAAU;GACvB,MAAM,YAAY,CAAC,CAAC,UAAU;AAE9B,cAAW,KAAK;IACd;IACA;IACA,UAAU,mBAAmB,KAAA;IAC7B,UAAU,CAAC;IACZ,CAAC;AACF,qBAAkB;AAClB;;AAIF,MAAI,CAAC,QAAQ,WAAW,IAAI,IAAI,QAAQ,SAAS,EAC/C,mBAAkB;;AAItB,QAAO;;;AAIT,SAAS,aAAa,WAAmC;CACvD,MAAM,UAA0B,EAAE;CAGlC,MAAM,cACJ;CACF,IAAI;AACJ,SAAQ,QAAQ,YAAY,KAAK,UAAU,MAAM,MAAM;EACrD,MAAM,aAAa,MAAM;EACzB,MAAM,UAAU,MAAM,OAAO;EAC7B,MAAM,aAAa,MAAM;EACzB,MAAM,OAAO,MAAM;EACnB,MAAM,YAAY,MAAM;AAGxB,MAAI,eAAe,aAAa,eAAe,YAAa;EAE5D,MAAM,SAA8D,EAAE;AACtE,MAAI,UAAU,MAAM,EAAE;GACpB,MAAM,aAAa,UAAU,MAAM,IAAI;AACvC,QAAK,MAAM,QAAQ,YAAY;IAG7B,MAAM,aAFU,KAAK,MAAM,CAEA,MAAM,mDAAmD;AACpF,QAAI,YAAY;KACd,MAAM,YAAY,WAAW;KAC7B,MAAM,YAAY,WAAW;KAC7B,MAAM,aAAa,WAAW,OAAO,KAAA;AACrC,YAAO,KAAK;MACV,MAAM;MACN,MAAM;MACN,UAAU,UAAU,SAAS,IAAI,IAAI;MACtC,CAAC;;;;AAKR,UAAQ,KAAK;GACX;GACA;GACA;GACA;GACA;GACD,CAAC;;AAGJ,QAAO;;;AAIT,SAAS,iBAAiB,WAAmB,WAAqD;CAChG,MAAM,SAA2C,EAAE;CAGnD,MAAM,aAAa,UAAU;CAC7B,MAAM,UAAU,UAAU,QAAQ,WAAW;AAC7C,KAAI,UAAU,EAAG,QAAO;CAExB,MAAM,QADY,UAAU,MAAM,UAAU,WAAW,OAAO,CACtC,MAAM,kBAAkB;AAChD,KAAI,CAAC,MAAO,QAAO;CAEnB,MAAM,YAAY,MAAM;AACxB,KAAI,CAAC,UAAU,MAAM,CAAE,QAAO;CAE9B,MAAM,aAAa,UAAU,MAAM,IAAI;AACvC,MAAK,MAAM,QAAQ,YAAY;EAE7B,MAAM,aADU,KAAK,MAAM,CACA,MAAM,4BAA4B;AAC7D,MAAI,WACF,QAAO,KAAK;GAAE,MAAM,WAAW;GAAI,MAAM,WAAW;GAAI,CAAC;;AAI7D,QAAO;;;AAQT,SAAgB,gBAAgB,UAAkB,SAAmC;CACnF,MAAM,SAAS,aAAa,UAAU,QAAQ;CAC9C,MAAM,UAAU,SAAS,SAAS,SAAS;CAC3C,MAAM,UAAU,cAAc,OAAO;AAErC,QAAO;EACL,SAAS,aAAa,SAAS,QAAQ;EACvC,OAAO,WAAW,SAAS,QAAQ;EACpC;;;;AChUH,SAAgBC,eACd,YACA,UACA,QAMA;CACA,MAAM,UAAoC,EAAE;CAC5C,MAAM,aAA2C,EAAE;CACnD,MAAM,QAAiC,EAAE;CAEzC,MAAM,YAAY,IAAI,iBAAiB;AAGvC,MAAK,MAAM,OAAO,YAAY;AAC5B,MAAI,IAAI,WAAW;GAEjB,MAAM,UAAuC,EAAE;GAC/C,MAAM,aAA0C,EAAE;AAElD,QAAK,MAAM,UAAU,IAAI,SAAS;IAChC,MAAM,SAAqB,OAAO,OAAO,KAAK,OAAO;KACnD,MAAM,EAAE;KACR,MAAM,EAAE;KACR,UAAU,EAAE;KACZ,cAAc;KACf,EAAE;AAEH,QAAI,CAAC,QAAQ,OAAO,MAAO,SAAQ,OAAO,QAAQ,EAAE;AACpD,YAAQ,OAAO,MAAM,KAAK;KACxB,MAAM,OAAO;KACb;KACA,YAAY,OAAO;KACnB,OAAO,OAAO;KACf,CAAC;;AAIJ,QAAK,MAAM,QAAQ,IAAI,YAAY;IACjC,MAAM,WAAW,KAAK,YAAY,KAAK;AACvC,eAAW,YAAY;KACrB,MAAM;KACN,MAAM,KAAK;KACX,UAAU,KAAK;KAChB;;GAGH,MAAM,oBAAgC,IAAI,kBAAkB,KAAK,OAAO;IACtE,MAAM,EAAE;IACR,MAAM,EAAE;IACR,UAAU;IACV,cAAc;IACf,EAAE;AAEH,WAAQ,IAAI,QAAQ;IAClB,MAAM,IAAI;IACV,YAAY,IAAI;IAChB,SAAS,WAAW,QAAQ;IAC5B,YAAY,WAAW,WAAW;IAClC;IACD;SACI;GAEL,MAAM,SAAmC,EAAE;AAC3C,QAAK,MAAM,QAAQ,IAAI,YAAY;IACjC,MAAM,YAAY,KAAK,YAAY,KAAK;IACxC,MAAM,aAAa,KAAK,KAAK,SAAS,IAAI;AAC1C,WAAO,aAAa;KAClB,MAAM;KACN,MAAM,KAAK;KACX,UAAU;KACX;;AAGH,cAAW,IAAI,QAAQ;IACrB,MAAM,IAAI;IACV,YAAY,IAAI;IAChB,QAAQ,WAAW,OAAO;IAC1B,SAAS,EAAE;IACZ;;AAEH,YAAU,IAAI,IAAI,YAAY,IAAI,KAAK;;AAIzC,MAAK,MAAM,MAAM,UAAU;AACzB,QAAM,GAAG,QAAQ;GACf,MAAM,GAAG;GACT,YAAY,GAAG;GACf,SAAS,WAAW,GAAG,QAAQ;GAChC;AACD,YAAU,IAAI,GAAG,YAAY,GAAG,KAAK;;CAGvC,MAAM,UAAU,UAAU,UAAU;AAEpC,QAAO;EACL,SAAS,WAAW,QAAQ;EAC5B,YAAY,WAAW,WAAW;EAClC,OAAO,WAAW,MAAM;EACxB,SAAS,WAAW,QAAQ;EAC7B;;;;;;;;;;;;;AC/FH,MAAM,yBAAyB,IAAI,IAAI;CAAC;CAAU;CAAO;CAAQ;CAAS;CAAU;CAAQ;CAAU,CAAC;AAEvG,MAAM,cAA6B;CACjC,cAAc,MAA6B;EAEzC,MAAM,gBAAgB,KAAK,MAAM,mBAAmB;AACpD,MAAI,cAAe,QAAO,cAAc;AAExC,MAAI,KAAK,SAAS,IAAI,CAAE,QAAO,KAAK,MAAM,GAAG,GAAG;AAChD,SAAO;;CAET,yBAAyB,GAAW,GAAoB;AACtD,SAAO,gCAAgC,MAAM,GAAG,EAAE;;CAEpD,eAAe,IAAY,IAAqB;AAC9C,SAAO;;CAET,mBAAmB,MAAuB;AACxC,SAAO,UAAU,KAAK,KAAK,IAAI,oBAAoB,KAAK,KAAK;;CAE/D,qBAAqB,MAAuB;AAC1C,SAAO,SAAS,YAAY,SAAS;;CAEvC,0BAA0B;CAC1B,sBAAsB,YAAmC;EACvD,IAAI,QAAQ;EAEZ,MAAM,YAAY,MAAM,MAAM,eAAe;AAC7C,MAAI,UAAW,SAAQ,UAAU;AAEjC,MAAI,UAAU,OAAQ,QAAO;AAE7B,MAAI,MAAM,SAAS,IAAI,CAAE,SAAQ,MAAM,MAAM,GAAG,GAAG;EAEnD,MAAM,YAAY,MAAM,MAAM,mDAAmD;AACjF,MAAI,UAAW,SAAQ,UAAU;AAEjC,MAAI;GAAC;GAAU;GAAO;GAAQ;GAAS;GAAU;GAAQ;GAAQ;GAAU,CAAC,SAAS,MAAM,CAAE,QAAO;AACpG,SAAO;;CAET,qBAAqB,WAAkC;EACrD,IAAI,QAAQ;AACZ,MAAI,MAAM,SAAS,IAAI,CAAE,SAAQ,MAAM,MAAM,GAAG,GAAG;AACnD,MAAI;GAAC;GAAU;GAAO;GAAQ;GAAS;GAAU;GAAQ;GAAU,CAAC,SAAS,MAAM,CAAE,QAAO;AAC5F,SAAO;;CAET,qBAAqB,cAAsB,WAA4B;AACrE,SAAO,aAAa,aAAa,KAAK,UAAU,aAAa;;CAE/D,kBAAkB,WAA6B;AAC7C,SAAO,CAAC,GAAG,UAAU,UAAU;;CAGjC,iBAAiB,cAAsB,eAAuB,kBAAuC;EAEnG,MAAM,iBAAiB,MAAc;AACnC,OAAI,EAAE,SAAS,IAAI,CAAE,QAAO,EAAE,MAAM,GAAG,GAAG;GAC1C,MAAM,IAAI,EAAE,MAAM,mBAAmB;AACrC,UAAO,IAAI,EAAE,KAAK;;EAEpB,MAAM,YAAY,cAAc,aAAa;EAC7C,MAAM,YAAY,cAAc,cAAc;EAG9C,MAAM,cAAc;AACpB,MAAI,YAAY,KAAK,UAAU,IAAI,YAAY,KAAK,UAAU,CAC5D,QAAO;EAIT,MAAM,aAAa,UAAU,MAAM,aAAa;EAChD,MAAM,YAAY,UAAU,MAAM,mDAAmD;AACrF,MAAI,cAAc,WAAW;GAE3B,MAAM,YAAY,WAAW;GAC7B,MAAM,YAAY,UAAU;AAC5B,OAAI,cAAc,UAAW,QAAO;AAEpC,OAAI,cAAc,KAAK,UAAU,IAAI,cAAc,KAAK,UAAU;QAC5D,oBAAoB,WAAW,iBAAiB,EAAE;AACpD,SAAI,UAAU,SAAS,UAAU,IAAI,UAAU,SAAS,UAAU,CAAE,QAAO;KAC3E,MAAM,aAAa,UAAU,QAAQ,aAAa,GAAG;KACrD,MAAM,aAAa,UAAU,QAAQ,aAAa,GAAG;AACrD,SAAI,WAAW,SAAS,WAAW,IAAI,WAAW,SAAS,WAAW,CAAE,QAAO;AAE/E,SAAI,sBAAsB,WAAW,UAAU,CAAE,QAAO;;;AAK5D,OACG,uBAAuB,IAAI,UAAU,IAAI,cAAc,KAAK,UAAU,IACtE,uBAAuB,IAAI,UAAU,IAAI,cAAc,KAAK,UAAU,CAEvE,QAAO;;EAIX,MAAM,gBAAgB,UAAU,MAAM,mDAAmD;EACzF,MAAM,iBAAiB,UAAU,MAAM,aAAa;AACpD,MAAI,iBAAiB,gBAAgB;GACnC,MAAM,YAAY,cAAc;GAChC,MAAM,YAAY,eAAe;AACjC,OAAI,cAAc,UAAW,QAAO;AACpC,OAAI,cAAc,KAAK,UAAU,IAAI,cAAc,KAAK,UAAU;QAC5D,oBAAoB,WAAW,iBAAiB;SAC9C,UAAU,SAAS,UAAU,IAAI,UAAU,SAAS,UAAU,CAAE,QAAO;;;;EAOjF,MAAM,iBAAiB;EACvB,MAAM,cAAc,UAAU,MAAM,eAAe;EACnD,MAAM,cAAc,UAAU,MAAM,eAAe;AACnD,MAAI,eAAe,aAAa;GAC9B,MAAM,YAAY,YAAY;GAC9B,MAAM,YAAY,YAAY;AAC9B,OAAI,cAAc,UAAW,QAAO;AACpC,OAAI,cAAc,KAAK,UAAU,IAAI,cAAc,KAAK,UAAU;QAC5D,oBAAoB,WAAW,iBAAiB,EAAE;AACpD,SAAI,UAAU,SAAS,UAAU,IAAI,UAAU,SAAS,UAAU,CAAE,QAAO;KAC3E,MAAM,aAAa,UAAU,QAAQ,aAAa,GAAG;KACrD,MAAM,aAAa,UAAU,QAAQ,aAAa,GAAG;AACrD,SAAI,WAAW,SAAS,WAAW,IAAI,WAAW,SAAS,WAAW,CAAE,QAAO;AAC/E,SAAI,sBAAsB,WAAW,UAAU,CAAE,QAAO;;;;AAO9D,MAAI,cAAc,KAAK,UAAU,IAAI,cAAc,KAAK,UAAU;OAC5D,oBAAoB,WAAW,iBAAiB,EAAE;AACpD,QAAI,UAAU,SAAS,UAAU,IAAI,UAAU,SAAS,UAAU,CAAE,QAAO;IAC3E,MAAM,aAAa,UAAU,QAAQ,aAAa,GAAG;IACrD,MAAM,aAAa,UAAU,QAAQ,aAAa,GAAG;AACrD,QAAI,WAAW,SAAS,WAAW,IAAI,WAAW,SAAS,WAAW,CAAE,QAAO;AAE/E,QAAI,sBAAsB,WAAW,UAAU,CAAE,QAAO;;;EAK5D,MAAM,eAAe,IAAI,IAAI;GAAC;GAAO;GAAQ;GAAS;GAAU;GAAU,CAAC;AAC3E,MAAI,aAAa,IAAI,UAAU,IAAI,aAAa,IAAI,UAAU,CAAE,QAAO;AAGvE,MAAK,cAAc,cAAc,cAAc,YAAc,cAAc,YAAY,cAAc,WACnG,QAAO;AAIT,MAAI,cAAc,YAAY,iBAAiB,MAAM,WAAY,QAAO;AACxE,MAAI,cAAc,YAAY,iBAAiB,QAAQ,WAAY,QAAO;AAE1E,SAAO;;CAGT,kBAAkB,EAAE;CACpB,sBAAsB,CAAC,YAAY;CACpC;;AAOD,SAAgB,sBAAsB,eAAmD;CACvF,MAAM,cAA6B,gBAAgB;EAAE,GAAG;EAAa,GAAG;EAAe,GAAG;AAE1F,QAAO;EACL,UAAU;EACV,OAAO;EAEP,MAAM,gBAAgB,SAA0C;AAE9D,UAAO,qBADS,MAAM,KAAK,QAAQ,QAAQ,CACP;;EAGtC,MAAM,QAAQ,SAAsC;GAElD,IAAI;GACJ,MAAM,UAAU,QAAQ,SAAS,MAAM;AAEvC,OAAI;AACF,aAAS,QAAQ;AACjB,gBAAY;WACN;AACN,gBAAY;;GAGd,MAAM,UAAU,gBAAgB,UAAU;AAC1C,OAAI,QAAQ,WAAW,EACrB,OAAM,IAAI,eACR,yBAAyB,WACzB,4FACD;GAGH,MAAM,aAA4B,EAAE;GACpC,MAAM,WAAyB,EAAE;AAEjC,QAAK,MAAM,YAAY,SAAS;IAC9B,MAAM,SAAS,gBAAgB,UAAU,QAAQ;AACjD,eAAW,KAAK,GAAG,OAAO,QAAQ;AAClC,aAAS,KAAK,GAAG,OAAO,MAAM;;GAGhC,MAAM,EAAE,SAAS,YAAY,OAAO,YAAYC,eAAa,YAAY,UAAU,YAAY;AAE/F,UAAO;IACL,UAAU;IACV,eAAe;IACf,8BAAa,IAAI,MAAM,EAAC,aAAa;IACrC;IACA;IACA,aAAa,EAAE;IACf;IACA;IACD;;EAEJ;;;AAIH,MAAa,kBAA6B,uBAAuB;;;;;;;AC3MjE,SAAgB,gBAAgB,KAAuB;CACrD,MAAM,UAAoB,EAAE;CAC5B,IAAI;AACJ,KAAI;AACF,YAAU,YAAY,IAAI;SACpB;AACN,SAAO;;AAET,MAAK,MAAM,SAAS,SAAS;EAC3B,MAAM,WAAW,KAAK,KAAK,MAAM;EACjC,IAAI;AACJ,MAAI;AACF,UAAO,SAAS,SAAS;UACnB;AACN;;AAEF,MAAI,KAAK,aAAa,EAAE;AACtB,OAAI,MAAM,WAAW,IAAI,IAAI,UAAU,YAAY,UAAU,UAAU,UAAU,OAAQ;AACzF,WAAQ,KAAK,GAAG,gBAAgB,SAAS,CAAC;aACjC,MAAM,SAAS,MAAM,IAAI,CAAC,MAAM,SAAS,YAAY,CAC9D,SAAQ,KAAK,SAAS;;AAG1B,QAAO,QAAQ,MAAM;;;;;;;AAYvB,SAAS,yBAAyB,QAAwB;CAExD,IAAI,SAAS,OAAO,QAAQ,mBAAmB,eAAS;AAExD,UAAS,OAAO,QAAQ,YAAY,GAAG;AACvC,QAAO;;;;;;;;;;AAeT,SAAS,kBAAkB,QAAgB,UAAiC;CAC1E,IAAI,QAAQ;CAGZ,IAAI,IAAI;AACR,QAAO,IAAI,OAAO,UAAU,QAAQ,GAAG;EACrC,MAAM,KAAK,OAAO;AAGlB,MAAI,OAAO,MAAK;AACd;AACA,UAAO,IAAI,OAAO,UAAU,OAAO,OAAO,MAAK;AAC7C,QAAI,OAAO,OAAO,KAAM;AACxB;;AAEF;AACA;;AAEF,MAAI,OAAO,KAAK;AACd;AACA,UAAO,IAAI,OAAO,UAAU,OAAO,OAAO,KAAK;AAC7C,QAAI,OAAO,OAAO,KAAM;AACxB;;AAEF;AACA;;AAKF,MAAI,eAAe,QAAQ,EAAE,EAAE;AAC7B,OAAI,OAAO,MAAM,GAAG,IAAI,EAAE,KAAK,QAAQ,UAAU,QAAQ,IAAI,EAAE,EAAE;AAE/D,QAAI,OAAO,IAAI,OAAO,IACpB;AAEF,SAAK;AACL;;AAEF,OAAI,OAAO,MAAM,GAAG,IAAI,EAAE,KAAK,QAAQ,UAAU,QAAQ,IAAI,EAAE,EAAE;AAC/D;AACA,SAAK;AACL;;AAEF,OAAI,OAAO,MAAM,GAAG,IAAI,EAAE,KAAK,SAAS,UAAU,QAAQ,IAAI,EAAE,EAAE;AAChE;AACA,QAAI,UAAU,EACZ,QAAO,OAAO,MAAM,UAAU,EAAE;AAElC,SAAK;AACL;;;AAIJ;;AAGF,QAAO;;AAGT,SAAS,eAAe,QAAgB,KAAsB;AAC5D,KAAI,QAAQ,EAAG,QAAO;CACtB,MAAM,OAAO,OAAO,MAAM;AAC1B,QAAO,CAAC,eAAe,KAAK,KAAK;;AAGnC,SAAS,UAAU,QAAgB,KAAsB;AACvD,KAAI,OAAO,OAAO,OAAQ,QAAO;AACjC,QAAO,CAAC,eAAe,KAAK,OAAO,KAAK;;;AAa1C,SAAS,eAAe,QAAmC;CACzD,MAAM,UAA6B,EAAE;CACrC,MAAM,cAAc;CACpB,IAAI;AACJ,SAAQ,QAAQ,YAAY,KAAK,OAAO,MAAM,MAAM;EAClD,MAAM,OAAO,kBAAkB,QAAQ,MAAM,QAAQ,MAAM,GAAG,OAAO;AACrE,MAAI,KACF,SAAQ,KAAK;GAAE,MAAM,MAAM;GAAI;GAAM,CAAC;;AAG1C,QAAO;;AAOT,SAAS,eAAe,SAA4B,YAAoC;CACtF,MAAM,UAA0B,EAAE;AAElC,MAAK,MAAM,EAAE,MAAM,YAAY,MAAM,gBAAgB,SAAS;EAE5D,MAAM,cAAc,WAAW,MAAM,2BAA2B;AAChE,MAAI,CAAC,YAAa;EAElB,MAAM,YAAY,YAAY;EAC9B,MAAM,SAAmB,EAAE;EAC3B,MAAM,aAAa;EACnB,IAAI;AACJ,UAAQ,aAAa,WAAW,KAAK,UAAU,MAAM,KACnD,QAAO,KAAK,WAAW,GAAG;AAG5B,MAAI,OAAO,SAAS,EAClB,SAAQ,KAAK;GAAE;GAAY;GAAQ;GAAY,CAAC;;AAIpD,QAAO;;AAOT,SAAS,iBAAiB,SAA4B,YAAsC;CAC1F,MAAM,YAA8B,EAAE;AAEtC,MAAK,MAAM,EAAE,MAAM,YAAY,MAAM,gBAAgB,SAAS;EAK5D,MAAM,YAAY;EAClB,IAAI;AACJ,UAAQ,YAAY,UAAU,KAAK,WAAW,MAAM,MAAM;GACxD,MAAM,YAAY,UAAU,OAAO;GACnC,MAAM,OAAO,UAAU;GACvB,MAAM,YAAY,UAAU,MAAM;AAGlC,OAAI,SAAS,eAAe,SAAS,YAAa;GAElD,MAAM,SAAmB,EAAE;GAC3B,MAAM,cAA4C,EAAE;AACpD,OAAI,UAAU,MAAM,EAAE;IACpB,MAAM,aAAa,UAAU,MAAM,IAAI;AACvC,SAAK,MAAM,QAAQ,YAAY;KAC7B,MAAM,UAAU,KAAK,MAAM;KAE3B,MAAM,iBAAiB,QAAQ,MAAM,SAAS;AAC9C,SAAI,gBAAgB;AAClB,aAAO,KAAK,eAAe,GAAG;MAE9B,MAAM,gBAAgB,YAAY,KAAK,QAAQ;AAC/C,kBAAY,KAAK,gBAAgB,YAAY,aAAa;;;;AAKhE,aAAU,KAAK;IACb;IACA;IACA,OAAO,OAAO;IACd;IACA;IACA;IACA;IACD,CAAC;;;AAIN,QAAO;;AAOT,SAAS,iBAAiB,SAA4B,YAAsC;CAC1F,MAAM,QAA0B,EAAE;AAElC,MAAK,MAAM,EAAE,MAAM,YAAY,MAAM,gBAAgB,SAAS;EAG5D,MAAM,YAAY;EAClB,IAAI;AACJ,UAAQ,YAAY,UAAU,KAAK,WAAW,MAAM,MAAM;GACxD,MAAM,WAAW,UAAU;GAC3B,MAAM,WAAW,UAAU,QAAQ,UAAU,GAAG;GAIhD,IAAI,SAAS;GACb,IAAI,aAAa;AACjB,QAAK,IAAI,IAAI,UAAU,IAAI,WAAW,QAAQ,KAAK;IACjD,MAAM,KAAK,WAAW;AACtB,QAAI,OAAO,IAAK;aACP,OAAO,KAAK;AACnB;AACA,SAAI,aAAa,EAAG;AACpB,SAAI,eAAe,GAAG;AACpB,eAAS,IAAI;AACb;;eAEO,eAAe,KAAK,OAAO,MAAM;KAE1C,MAAM,YAAY,WAAW,MAAM,IAAI,EAAE;AAEzC,SADsB,UAAU,MAAM,SAAS,EAC5B;MACjB,MAAM,cAAc,UAAU,WAAW;AACzC,UACE,YAAY,WAAW,IAAI,IAC3B,YAAY,WAAW,OAAO,IAC9B,YAAY,WAAW,QAAQ,IAC/B,YAAY,WAAW,YAAY,IACnC,YAAY,WAAW,YAAY,EACnC;AACA,gBAAS;AACT;;YAEG;AAEL,eAAS;AACT;;;AAGJ,aAAS,IAAI;;GAGf,MAAM,aAAa,WAAW,MAAM,UAAU,OAAO,CAAC,MAAM;AAC5D,SAAM,KAAK;IAAE;IAAY,MAAM;IAAU;IAAY;IAAY,CAAC;;;AAItE,QAAO;;AAOT,SAAS,mBAAmB,SAA4B,YAAwC;CAC9F,MAAM,cAAkC,EAAE;AAE1C,MAAK,MAAM,EAAE,MAAM,YAAY,MAAM,gBAAgB,SAAS;AAE5D,MAAI,CAAC,WAAW,MAAM,oBAAoB,CAAE;AAG5C,MAAI,WAAW,MAAM,cAAc,CAAE;EAErC,MAAM,UAAkC,EAAE;EAG1C,MAAM,iBAAiB;EACvB,IAAI;AACJ,UAAQ,iBAAiB,eAAe,KAAK,WAAW,MAAM,MAAM;GAClE,MAAM,WAAW,eAAe;GAChC,MAAM,YAAY,eAAe;AACjC,OAAI,aAAa,SAAU;AAC3B,WAAQ,YAAY;;AAGtB,MAAI,OAAO,KAAK,QAAQ,CAAC,SAAS,EAChC,aAAY,KAAK;GAAE;GAAY;GAAS;GAAY,CAAC;;AAIzD,QAAO;;;AAQT,SAAgB,gBAAgB,UAAkB,SAAmC;CACnF,MAAM,SAAS,aAAa,UAAU,QAAQ;CAC9C,MAAM,UAAU,SAAS,SAAS,SAAS;CAE3C,MAAM,UAAU,eADA,yBAAyB,OAAO,CACT;AAEvC,QAAO;EACL,SAAS,eAAe,SAAS,QAAQ;EACzC,WAAW,iBAAiB,SAAS,QAAQ;EAC7C,WAAW,iBAAiB,SAAS,QAAQ;EAC7C,aAAa,mBAAmB,SAAS,QAAQ;EACjD,aAAa,QAAQ,KAAK,MAAM,EAAE,KAAK;EACxC;;;;;AC7XH,SAAS,UAAU,YAA4B;CAC7C,MAAM,QAAQ,WAAW,MAAM,IAAI;AACnC,QAAO,MAAM,MAAM,SAAS;;AAO9B,SAAgB,aACd,YACA,cACA,gBACA,cAMA;CACA,MAAM,UAAoC,EAAE;CAC5C,MAAM,aAA2C,EAAE;CACnD,MAAM,QAAiC,EAAE;CAEzC,MAAM,YAAY,IAAI,iBAAiB;CAGvC,MAAM,oBAAoB,IAAI,IAAI,WAAW,KAAK,MAAM,EAAE,WAAW,CAAC;CACtE,MAAM,kBAAkB,IAAI,IAAI,eAAe,KAAK,MAAM,EAAE,WAAW,CAAC;AAGxE,MAAK,MAAM,UAAU,YAAY;EAC/B,MAAM,OAAO,UAAU,OAAO,WAAW;EACzC,MAAM,SAAmC,EAAE;EAG3C,MAAM,WAAW,aAAa,MAAM,OAAO,GAAG,eAAe,OAAO,cAAc,GAAG,SAAS,IAAI;AAElG,OAAK,MAAM,SAAS,OAAO,QAAQ;GAEjC,IAAI,YAAY;GAChB,IAAI,WAAW;AAEf,OAAI,UAAU;IAEZ,MAAM,cAAc,QAAQ;IAC5B,MAAM,YAAY,SAAS,WAAW,QAAQ,YAAY;IAC1D,MAAM,iBACJ,aAAa,IAAI,SAAS,WAAW,MAAM,YAAY,YAAY,OAAO,CAAC,MAAM,eAAe,GAAG;AACrG,QAAI,gBAAgB;AAClB,iBAAY,eAAe,GAAG,MAAM;AAEpC,SAAI,UAAU,SAAS,QAAQ,IAAI,UAAU,SAAS,QAAQ,EAAE;AAC9D,iBAAW;AACX,kBAAY,UACT,QAAQ,gBAAgB,GAAG,CAC3B,QAAQ,gBAAgB,GAAG,CAC3B,MAAM;;;;AAKf,UAAO,SAAS;IACd,MAAM;IACN,MAAM;IACN;IACD;;AAGH,aAAW,QAAQ;GACjB;GACA,YAAY,OAAO;GACnB,QAAQ,WAAW,OAAO;GAC1B,SAAS,EAAE;GACZ;AACD,YAAU,IAAI,OAAO,YAAY,KAAK;;AAIxC,MAAK,MAAM,cAAc,gBAAgB;EACvC,MAAM,OAAO,UAAU,WAAW,WAAW;AAC7C,QAAM,QAAQ;GACZ;GACA,YAAY,WAAW;GACvB,SAAS,WAAW,WAAW,QAAQ;GACxC;AACD,YAAU,IAAI,WAAW,YAAY,KAAK;;CAI5C,MAAM,gCAAgB,IAAI,KAA+B;AACzD,MAAK,MAAM,QAAQ,cAAc;AAC/B,MAAI,KAAK,UAAW;AAIpB,MAAI,kBAAkB,IAAI,KAAK,WAAW,IAAI,CAAC,cAAc,IAAI,KAAK,WAAW,EAAE;AAInF,MAAI,gBAAgB,IAAI,KAAK,WAAW,CAAE;AAE1C,MAAI,CAAC,cAAc,IAAI,KAAK,WAAW,CAAE,eAAc,IAAI,KAAK,YAAY,EAAE,CAAC;AAC/E,gBAAc,IAAI,KAAK,WAAW,CAAE,KAAK,KAAK;;AAIhD,MAAK,MAAM,CAAC,YAAY,UAAU,eAAe;AAE/C,MAAI,kBAAkB,IAAI,WAAW,CAAE;EAEvC,MAAM,OAAO,UAAU,WAAW;EAClC,MAAM,UAAuC,EAAE;EAG/C,MAAM,4BAAY,IAAI,KAAa;AACnC,OAAK,MAAM,QAAQ,OAAO;AACxB,OAAI,UAAU,IAAI,KAAK,KAAK,CAAE;AAC9B,aAAU,IAAI,KAAK,KAAK;GAExB,MAAM,SAAqB,KAAK,OAAO,KAAK,GAAG,OAAO;IACpD,MAAM;IACN,MAAM;IACN,UAAU;IACV,cAAc,KAAK,YAAY,MAAO;IACvC,EAAE;AAEH,OAAI,CAAC,QAAQ,KAAK,MAAO,SAAQ,KAAK,QAAQ,EAAE;AAChD,WAAQ,KAAK,MAAM,KAAK;IACtB,MAAM,KAAK;IACX;IACA,YAAY;IACZ,OAAO;IACR,CAAC;;AAGJ,MAAI,OAAO,KAAK,QAAQ,CAAC,SAAS,GAAG;AACnC,WAAQ,QAAQ;IACd;IACA,YAAY,MAAM,GAAG;IACrB,SAAS,WAAW,QAAQ;IAC5B,YAAY,EAAE;IACd,mBAAmB,EAAE;IACtB;AACD,aAAU,IAAI,MAAM,GAAG,YAAY,KAAK;;;CAI5C,MAAM,UAAU,UAAU,UAAU;AAEpC,QAAO;EACL,SAAS,WAAW,QAAQ;EAC5B,YAAY,WAAW,WAAW;EAClC,OAAO,WAAW,MAAM;EACxB,SAAS,WAAW,QAAQ;EAC7B;;AC/EH,MAAa,kBAA6B;CACxC,UAAU;CACV,OAtEiC;EACjC,cAAc,MAA6B;AAEzC,OAAI,KAAK,SAAS,QAAQ,CAAE,QAAO,KAAK,QAAQ,gBAAgB,GAAG,CAAC,MAAM;AAC1E,OAAI,KAAK,SAAS,QAAQ,CAAE,QAAO,KAAK,QAAQ,gBAAgB,GAAG,CAAC,MAAM;AAC1E,UAAO;;EAET,yBAAyB,GAAW,GAAoB;AACtD,UAAO,gCAAgC,MAAM,GAAG,EAAE;;EAEpD,eAAe,GAAW,GAAoB;GAE5C,MAAM,aAAa,MACjB,EACG,MAAM,IAAI,CACV,KAAK,MAAM,EAAE,MAAM,CAAC,CACpB,MAAM,CACN,KAAK,IAAI;AACd,UAAO,MAAM,KAAK,UAAU,EAAE,KAAK,UAAU,EAAE;;EAEjD,mBAAmB,MAAuB;AAExC,UAAO,SAAS,SAAS,SAAS;;EAEpC,qBAAqB,MAAuB;AAC1C,UAAO,SAAS,SAAS,SAAS,UAAU,SAAS;;EAEvD,0BAA0B;EAC1B,sBAAsB,YAAmC;GACvD,IAAI,QAAQ;GAEZ,MAAM,UAAU,MAAM,MAAM,oBAAoB;AAChD,OAAI,QAAS,SAAQ,QAAQ,GAAG,MAAM;GAEtC,MAAM,YAAY,MAAM,MAAM,aAAa;AAC3C,OAAI,UAAW,SAAQ,UAAU,GAAG,MAAM;AAE1C,OAAI;IAAC;IAAO;IAAQ;IAAQ;IAAU;IAAW;IAAW;IAAS;IAAU;IAAM,CAAC,SAAS,MAAM,CACnG,QAAO;GAGT,MAAM,gBAAgB,MAAM,MAAM,iBAAiB;AACnD,OAAI,cAAe,QAAO,cAAc;AACxC,UAAO,SAAS;;EAElB,qBAAqB,WAAkC;AACrD,OACE;IAAC;IAAO;IAAQ;IAAQ;IAAU;IAAW;IAAW;IAAS;IAAU;IAAO;IAAU,CAAC,SAAS,UAAU,CAEhH,QAAO;GAET,MAAM,gBAAgB,UAAU,MAAM,iBAAiB;AACvD,OAAI,cAAe,QAAO,cAAc;AACxC,UAAO;;EAET,qBAAqB,cAAsB,WAA4B;AAErE,UAAO,aAAa,QAAQ,MAAM,GAAG,CAAC,aAAa,KAAK,UAAU,aAAa;;EAEjF,kBAAkB,WAA6B;AAC7C,UAAO,CAAC,GAAG,UAAU,UAAU;;EAElC;CAUC,MAAM,gBAAgB,SAA0C;AAE9D,SAAO,qBADS,MAAM,KAAK,QAAQ,QAAQ,CACP;;CAGtC,MAAM,QAAQ,SAAsC;EAElD,IAAI;EACJ,MAAM,UAAU,QAAQ,SAAS,MAAM;AAEvC,MAAI;AACF,YAAS,QAAQ;AACjB,eAAY;UACN;AACN,eAAY;;EAGd,MAAM,UAAU,gBAAgB,UAAU;AAC1C,MAAI,QAAQ,WAAW,EACrB,OAAM,IAAI,eACR,yBAAyB,WACzB,uGACD;EAGH,MAAM,aAA6B,EAAE;EACrC,MAAM,eAAiC,EAAE;EACzC,MAAM,iBAAqC,EAAE;EAC7C,MAAM,eAAiC,EAAE;AAEzC,OAAK,MAAM,YAAY,SAAS;GAC9B,MAAM,SAAS,gBAAgB,UAAU,QAAQ;AACjD,cAAW,KAAK,GAAG,OAAO,QAAQ;AAClC,gBAAa,KAAK,GAAG,OAAO,UAAU;AACtC,kBAAe,KAAK,GAAG,OAAO,YAAY;AAC1C,gBAAa,KAAK,GAAG,OAAO,UAAU;;EAGxC,MAAM,EAAE,SAAS,YAAY,OAAO,YAAY,aAC9C,YACA,cACA,gBACA,aACD;AAED,SAAO;GACL,UAAU;GACV,eAAe;GACf,8BAAa,IAAI,MAAM,EAAC,aAAa;GACrC;GACA;GACA,aAAa,EAAE;GACf;GACA;GACD;;CAEJ"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":["parseMethods","parseProperties","extractNamespace","safeParse","DEFAULT_EXCEPTION_BASES","isExceptionClass","buildSurface","buildSurface","safeParse","buildSurface","buildSurface","safeParseWith","extractEnumModules","extractEnumModules","parseStructFields","extractPackageName","safeParse","buildSurface","buildSurface","parseEnums","parseTypeAliases","safeParse","buildSurface","buildSurface","stripComments","extractJsonPropertyName","parseClasses","parseMethods","buildSurface","buildSurface","buildSurface","buildSurface"],"sources":["../../src/compat/concepts.ts","../../src/compat/report.ts","../../src/compat/approvals.ts","../../src/compat/extractors/shared.ts","../../src/compat/extractors/node.ts","../../src/compat/extractors/php-parser.ts","../../src/compat/extractors/php-surface.ts","../../src/compat/extractors/php.ts","../../src/compat/extractors/python-parser.ts","../../src/compat/extractors/python-surface.ts","../../src/compat/extractors/python.ts","../../src/compat/extractors/ruby-parser.ts","../../src/compat/extractors/ruby.ts","../../src/compat/extractors/go-parser.ts","../../src/compat/extractors/go-surface.ts","../../src/compat/extractors/go.ts","../../src/compat/extractors/rust-parser.ts","../../src/compat/extractors/rust-surface.ts","../../src/compat/extractors/rust.ts","../../src/compat/extractors/kotlin-parser.ts","../../src/compat/extractors/kotlin-surface.ts","../../src/compat/extractors/kotlin.ts","../../src/compat/extractors/dotnet-parser.ts","../../src/compat/extractors/dotnet-surface.ts","../../src/compat/extractors/dotnet.ts","../../src/compat/extractors/elixir-parser.ts","../../src/compat/extractors/elixir-surface.ts","../../src/compat/extractors/elixir.ts"],"sourcesContent":["/**\n * Conceptual change grouping for cross-language compatibility analysis.\n *\n * Groups related changes across languages into a single conceptual change\n * with per-language severity. This allows reports to say \"parameter rename\n * on Authorization.check is breaking in PHP, Python, Kotlin, and .NET but\n * soft-risk in Go\" rather than treating these as unrelated per-language findings.\n */\n\nimport type { LanguageId } from './ir.js';\nimport type { CompatChangeSeverity, CompatChangeCategory } from './config.js';\nimport type { CompatDiffResult } from './differ.js';\n\n/** A conceptual change with per-language severity. */\nexport interface ConceptualChange {\n /** Deterministic ID from symbol + category + match details. */\n id: string;\n /** IR-level symbol path (language-neutral). */\n symbol: string;\n /** The kind of change. */\n category: CompatChangeCategory;\n /** Per-language severity mapping. */\n impact: Partial<Record<LanguageId, CompatChangeSeverity>>;\n /** Human-readable description (from first language that reported it). */\n message: string;\n /** Old state details. */\n old: Record<string, string>;\n /** New state details. */\n new: Record<string, string>;\n}\n\n/** Cross-language conceptual rollup. */\nexport interface ConceptualRollup {\n conceptualChanges: ConceptualChange[];\n}\n\n/**\n * Group classified changes from multiple languages into conceptual changes.\n *\n * Changes are grouped by their `conceptualChangeId` — a deterministic ID\n * derived from the symbol, category, and match details. Changes with the\n * same ID across different languages represent the same conceptual change.\n */\nexport function buildConceptualRollup(\n perLanguageResults: Array<{ diff: CompatDiffResult; language: LanguageId }>,\n): ConceptualRollup {\n const grouped = new Map<string, ConceptualChange>();\n\n for (const { diff: result, language } of perLanguageResults) {\n for (const change of result.changes) {\n const existing = grouped.get(change.conceptualChangeId);\n if (existing) {\n existing.impact[language] = change.severity;\n } else {\n grouped.set(change.conceptualChangeId, {\n id: change.conceptualChangeId,\n symbol: change.symbol,\n category: change.category,\n impact: { [language]: change.severity },\n message: change.message,\n old: change.old,\n new: change.new,\n });\n }\n }\n }\n\n return {\n conceptualChanges: [...grouped.values()],\n };\n}\n\n/** Get the highest severity across all languages for a conceptual change. */\nexport function highestSeverity(change: ConceptualChange): CompatChangeSeverity {\n const severities = Object.values(change.impact);\n if (severities.includes('breaking')) return 'breaking';\n if (severities.includes('soft-risk')) return 'soft-risk';\n return 'additive';\n}\n\n/** Count conceptual changes by highest severity. */\nexport function summarizeConceptualChanges(rollup: ConceptualRollup): {\n breaking: number;\n softRisk: number;\n additive: number;\n} {\n let breaking = 0;\n let softRisk = 0;\n let additive = 0;\n for (const change of rollup.conceptualChanges) {\n const sev = highestSeverity(change);\n if (sev === 'breaking') breaking++;\n else if (sev === 'soft-risk') softRisk++;\n else additive++;\n }\n return { breaking, softRisk, additive };\n}\n","/**\n * Report generation for compatibility verification.\n *\n * Produces machine-readable JSON reports, human-readable terminal summaries,\n * and conceptual cross-language summaries.\n */\n\nimport type { LanguageId } from './ir.js';\nimport type { CompatChangeSeverity, CompatChangeCategory, CompatProvenance } from './config.js';\nimport type { CompatDiffResult } from './differ.js';\nimport { buildConceptualRollup, highestSeverity, summarizeConceptualChanges } from './concepts.js';\n\n// ---------------------------------------------------------------------------\n// Machine-readable report\n// ---------------------------------------------------------------------------\n\n/** Machine-readable compat report for a single language. */\nexport interface CompatReport {\n schemaVersion: string;\n language: string;\n summary: {\n breaking: number;\n softRisk: number;\n additive: number;\n };\n changes: CompatReportChange[];\n}\n\n/** A single change entry in the machine-readable report. */\nexport interface CompatReportChange {\n severity: CompatChangeSeverity;\n category: CompatChangeCategory;\n symbol: string;\n conceptualChangeId: string;\n provenance: CompatProvenance;\n old: Record<string, string>;\n new: Record<string, string>;\n message?: string;\n /** Spec-level remediation hint when a recognized upstream pattern was detected. */\n remediation?: string;\n}\n\n/** Generate a machine-readable compat report from a diff result. */\nexport function generateReport(diff: CompatDiffResult, language?: string): CompatReport {\n return {\n schemaVersion: '1',\n language: language ?? 'unknown',\n summary: diff.summary,\n changes: diff.changes.map((c) => ({\n severity: c.severity,\n category: c.category,\n symbol: c.symbol,\n conceptualChangeId: c.conceptualChangeId,\n provenance: c.provenance,\n old: c.old,\n new: c.new,\n ...(c.message ? { message: c.message } : {}),\n ...(c.remediation ? { remediation: c.remediation } : {}),\n })),\n };\n}\n\n// ---------------------------------------------------------------------------\n// Human-readable terminal summary\n// ---------------------------------------------------------------------------\n\n/** Generate a human-readable summary string for terminal output. */\nexport function formatHumanSummary(diff: CompatDiffResult, opts?: { explain?: boolean; language?: string }): string {\n const lines: string[] = [];\n\n lines.push(`Compat report${opts?.language ? ` for ${opts.language}` : ''}:`);\n lines.push(\n ` ${diff.summary.breaking} breaking, ${diff.summary.softRisk} soft-risk, ${diff.summary.additive} additive`,\n );\n\n if (diff.changes.length === 0) {\n lines.push(' No compatibility changes detected.');\n return lines.join('\\n');\n }\n\n // Group by severity for display\n const breaking = diff.changes.filter((c) => c.severity === 'breaking');\n const softRisk = diff.changes.filter((c) => c.severity === 'soft-risk');\n const additive = diff.changes.filter((c) => c.severity === 'additive');\n\n if (breaking.length > 0) {\n lines.push('');\n lines.push(' Breaking:');\n for (const c of breaking) {\n lines.push(` [${c.category}] ${c.symbol} — ${c.message}`);\n if (c.remediation) {\n lines.push(` hint: ${c.remediation}`);\n }\n if (opts?.explain && c.provenance !== 'unknown') {\n lines.push(` provenance: ${c.provenance}`);\n }\n }\n }\n\n if (softRisk.length > 0) {\n lines.push('');\n lines.push(' Soft-risk:');\n for (const c of softRisk) {\n lines.push(` [${c.category}] ${c.symbol} — ${c.message}`);\n if (c.remediation) {\n lines.push(` hint: ${c.remediation}`);\n }\n if (opts?.explain && c.provenance !== 'unknown') {\n lines.push(` provenance: ${c.provenance}`);\n }\n }\n }\n\n if (additive.length > 0) {\n lines.push('');\n lines.push(` Additive: ${additive.length} new symbol(s)`);\n }\n\n return lines.join('\\n');\n}\n\n// ---------------------------------------------------------------------------\n// Conceptual cross-language summary\n// ---------------------------------------------------------------------------\n\n/** Conceptual cross-language report. */\nexport interface ConceptualReport {\n conceptualChanges: {\n id: string;\n symbol: string;\n category: CompatChangeCategory;\n impact: Partial<Record<LanguageId, CompatChangeSeverity>>;\n }[];\n}\n\n/** Generate a conceptual cross-language report from multiple per-language results. */\nexport function generateConceptualReport(\n perLanguageResults: Array<{ diff: CompatDiffResult; language: LanguageId }>,\n): ConceptualReport {\n const rollup = buildConceptualRollup(perLanguageResults);\n return {\n conceptualChanges: rollup.conceptualChanges.map((c) => ({\n id: c.id,\n symbol: c.symbol,\n category: c.category,\n impact: c.impact,\n })),\n };\n}\n\n/** Format a conceptual cross-language summary for terminal output. */\nexport function formatConceptualSummary(\n perLanguageResults: Array<{ diff: CompatDiffResult; language: LanguageId }>,\n): string {\n const rollup = buildConceptualRollup(perLanguageResults);\n const summary = summarizeConceptualChanges(rollup);\n const lines: string[] = [];\n\n lines.push('Cross-language conceptual summary:');\n lines.push(` ${summary.breaking} breaking, ${summary.softRisk} soft-risk, ${summary.additive} additive`);\n\n if (rollup.conceptualChanges.length === 0) {\n lines.push(' No cross-language changes.');\n return lines.join('\\n');\n }\n\n for (const change of rollup.conceptualChanges) {\n const sev = highestSeverity(change);\n const impactStr = Object.entries(change.impact)\n .map(([lang, s]) => `${lang}: ${s}`)\n .join(', ');\n lines.push(` [${sev}] ${change.category}: ${change.symbol}`);\n lines.push(` impact: ${impactStr}`);\n }\n\n return lines.join('\\n');\n}\n","/**\n * Approval matching engine for compatibility verification.\n *\n * Matches CompatApproval entries from oagen.config.ts against classified\n * changes. Approved changes are excluded from failure thresholds.\n *\n * Approvals must be narrow (one symbol, one category, one conceptual change).\n * Overly broad approvals are rejected at validation time.\n */\n\nimport type { LanguageId } from './ir.js';\nimport type { CompatApproval } from './config.js';\nimport type { ClassifiedChange } from './classify.js';\n\n/** Result of matching a change against approvals. */\nexport interface ApprovalMatch {\n /** The change that was matched. */\n change: ClassifiedChange;\n /** The approval that matched. null if no approval covers this change. */\n approval: CompatApproval | null;\n /** Whether the change is covered by an approval. */\n approved: boolean;\n}\n\n/** Result of validating an approval for broadness. */\nexport interface ApprovalValidation {\n valid: boolean;\n errors: string[];\n}\n\n// ---------------------------------------------------------------------------\n// Validation\n// ---------------------------------------------------------------------------\n\n/** Validate that an approval is narrow enough to be accepted. */\nexport function validateApproval(approval: CompatApproval): ApprovalValidation {\n const errors: string[] = [];\n\n if (!approval.symbol || approval.symbol.trim() === '') {\n errors.push('Approval must target a specific symbol');\n }\n\n if (!approval.category) {\n errors.push('Approval must specify a change category');\n }\n\n if (!approval.reason || approval.reason.trim() === '') {\n errors.push('Approval must include a reason');\n }\n\n // Wildcard symbols are too broad\n if (approval.symbol === '*' || approval.symbol.endsWith('.*') || approval.symbol.endsWith('::*')) {\n errors.push(`Approval symbol \"${approval.symbol}\" is too broad — must target a specific symbol`);\n }\n\n return {\n valid: errors.length === 0,\n errors,\n };\n}\n\n/** Validate all approvals in a config. Returns errors keyed by index. */\nexport function validateApprovals(approvals: CompatApproval[]): Map<number, string[]> {\n const result = new Map<number, string[]>();\n for (let i = 0; i < approvals.length; i++) {\n const validation = validateApproval(approvals[i]);\n if (!validation.valid) {\n result.set(i, validation.errors);\n }\n }\n return result;\n}\n\n// ---------------------------------------------------------------------------\n// Matching\n// ---------------------------------------------------------------------------\n\n/**\n * Match a classified change against a list of approvals.\n * Returns the first matching approval, or null if none match.\n */\nexport function matchApproval(\n change: ClassifiedChange,\n approvals: CompatApproval[],\n language: LanguageId,\n): CompatApproval | null {\n for (const approval of approvals) {\n if (approvalMatchesChange(approval, change, language)) {\n return approval;\n }\n }\n return null;\n}\n\n/**\n * Apply approvals to a list of changes.\n * Returns matches for every change (approved or not).\n */\nexport function applyApprovals(\n changes: ClassifiedChange[],\n approvals: CompatApproval[],\n language: LanguageId,\n): ApprovalMatch[] {\n return changes.map((change) => {\n const approval = matchApproval(change, approvals, language);\n return {\n change,\n approval,\n approved: approval !== null,\n };\n });\n}\n\n/**\n * Filter changes to only those NOT covered by approvals.\n * These are the remaining unapproved changes that may cause failure.\n */\nexport function unapprovedChanges(\n changes: ClassifiedChange[],\n approvals: CompatApproval[],\n language: LanguageId,\n): ClassifiedChange[] {\n return changes.filter((change) => !matchApproval(change, approvals, language));\n}\n\n// ---------------------------------------------------------------------------\n// Internal matching logic\n// ---------------------------------------------------------------------------\n\nfunction approvalMatchesChange(approval: CompatApproval, change: ClassifiedChange, language: LanguageId): boolean {\n // Skip inactive approvals\n if (approval.approved === false) return false;\n\n // Category must match exactly\n if (approval.category !== change.category) return false;\n\n // Symbol must match\n if (!symbolMatches(approval.symbol, change.symbol)) return false;\n\n // Language scoping\n if (!languageMatches(approval.appliesTo, language)) return false;\n\n // Narrowing match (optional)\n if (approval.match && !narrowingMatches(approval.match, change)) return false;\n\n return true;\n}\n\nfunction symbolMatches(approvalSymbol: string, changeSymbol: string): boolean {\n // Exact match\n if (approvalSymbol === changeSymbol) return true;\n\n // Normalize common separators for cross-language matching\n // PHP uses :: and \\, others use . — normalize to dots for comparison\n const normalizedApproval = approvalSymbol.replace(/::/g, '.').replace(/\\\\/g, '.');\n const normalizedChange = changeSymbol.replace(/::/g, '.').replace(/\\\\/g, '.');\n return normalizedApproval === normalizedChange;\n}\n\nfunction languageMatches(appliesTo: CompatApproval['appliesTo'], language: LanguageId): boolean {\n if (!appliesTo || appliesTo === 'all-impacted-languages') return true;\n return appliesTo.includes(language);\n}\n\nfunction narrowingMatches(match: NonNullable<CompatApproval['match']>, change: ClassifiedChange): boolean {\n if (match.parameter) {\n // Check if the change involves this parameter\n const paramInOld = change.old.parameter === match.parameter;\n const paramInNew = change.new.parameter === match.parameter;\n if (!paramInOld && !paramInNew) return false;\n }\n if (match.member) {\n const memberInOld = change.old.member === match.member;\n const memberInNew = change.new.member === match.member;\n if (!memberInOld && !memberInNew) return false;\n }\n if (match.oldName) {\n const nameMatch = Object.values(change.old).some((v) => v === match.oldName);\n if (!nameMatch) return false;\n }\n if (match.newName) {\n const nameMatch = Object.values(change.new).some((v) => v === match.newName);\n if (!nameMatch) return false;\n }\n return true;\n}\n","/** Sort an object's keys alphabetically. Shared across all extractors for deterministic output. */\nexport function sortRecord<T>(record: Record<string, T>): Record<string, T> {\n const sorted: Record<string, T> = {};\n for (const key of Object.keys(record).sort()) {\n sorted[key] = record[key];\n }\n return sorted;\n}\n\n/** Collects per-file export names, deduplicating and sorting on finalization. */\nexport class ExportCollector {\n private map = new Map<string, Set<string>>();\n\n add(sourceFile: string, name: string): void {\n let set = this.map.get(sourceFile);\n if (!set) {\n set = new Set();\n this.map.set(sourceFile, set);\n }\n set.add(name);\n }\n\n toRecord(): Record<string, string[]> {\n const result: Record<string, string[]> = {};\n for (const [file, names] of this.map) {\n result[file] = [...names].sort();\n }\n return result;\n }\n}\n","import ts from 'typescript';\nimport { readFileSync } from 'node:fs';\nimport path, { resolve, relative } from 'node:path';\nimport { ExtractorError } from '../../errors.js';\nimport type {\n ApiSurface,\n Extractor,\n ApiClass,\n ApiMethod,\n ApiParam,\n ApiProperty,\n ApiInterface,\n ApiField,\n ApiTypeAlias,\n ApiEnum,\n} from '../types.js';\nimport type { CompatSnapshot } from '../ir.js';\nimport { apiSurfaceToSnapshot } from '../ir.js';\nimport { nodeHints } from '../language-hints.js';\nimport { sortRecord } from './shared.js';\n\nexport const nodeExtractor: Extractor = {\n language: 'node',\n hints: nodeHints,\n\n async extractSnapshot(sdkPath: string): Promise<CompatSnapshot> {\n const surface = await this.extract(sdkPath);\n return apiSurfaceToSnapshot(surface);\n },\n\n async extract(sdkPath: string): Promise<ApiSurface> {\n sdkPath = resolve(sdkPath);\n const configPath = ts.findConfigFile(sdkPath, ts.sys.fileExists, 'tsconfig.json');\n if (!configPath)\n throw new ExtractorError(\n `No tsconfig.json found in ${sdkPath}`,\n `Create a tsconfig.json in \"${sdkPath}\" or verify the --sdk-path argument points to a TypeScript project root.`,\n );\n\n const configFile = ts.readConfigFile(configPath, ts.sys.readFile);\n const parsedConfig = ts.parseJsonConfigFileContent(configFile.config, ts.sys, sdkPath);\n const program = ts.createProgram(parsedConfig.fileNames, parsedConfig.options);\n const checker = program.getTypeChecker();\n\n const entryPoint = resolveEntryPoint(sdkPath, program);\n const entrySourceFile = program.getSourceFile(entryPoint);\n if (!entrySourceFile)\n throw new ExtractorError(\n `Entry point not found: ${entryPoint}`,\n `Ensure the file \"${entryPoint}\" exists and is included in the tsconfig.json \"include\" or \"files\" array.`,\n );\n\n const moduleSymbol = checker.getSymbolAtLocation(entrySourceFile);\n if (!moduleSymbol)\n throw new ExtractorError(\n 'No exports found at entry point',\n `Verify that \"${entryPoint}\" has at least one \\`export\\` statement. The extractor needs public exports to build an API surface.`,\n );\n\n const exportedSymbols = checker.getExportsOfModule(moduleSymbol);\n\n const classes: Record<string, ApiClass> = {};\n const interfaces: Record<string, ApiInterface> = {};\n const typeAliases: Record<string, ApiTypeAlias> = {};\n const enums: Record<string, ApiEnum> = {};\n\n for (const sym of exportedSymbols) {\n const resolved = resolveAlias(sym, checker);\n const declarations = resolved.getDeclarations();\n if (!declarations || declarations.length === 0) continue;\n const decl = declarations[0];\n\n const sourceFile = relative(sdkPath, decl.getSourceFile().fileName);\n\n if (ts.isClassDeclaration(decl)) {\n classes[resolved.name] = { ...extractClass(resolved, checker), sourceFile };\n } else if (ts.isInterfaceDeclaration(decl)) {\n interfaces[resolved.name] = { ...extractInterface(resolved, checker), sourceFile };\n } else if (ts.isTypeAliasDeclaration(decl)) {\n typeAliases[resolved.name] = { ...extractTypeAlias(resolved, checker), sourceFile };\n } else if (ts.isEnumDeclaration(decl)) {\n enums[resolved.name] = { ...extractEnum(resolved, checker), sourceFile };\n }\n }\n\n // Follow property types on extracted classes to discover resource classes\n // (e.g., WorkOS.apiKeys: ApiKeys → extract ApiKeys)\n followPropertyTypeClasses(exportedSymbols, checker, classes, sdkPath);\n\n const exports = buildExportMap(entrySourceFile, checker, sdkPath, program);\n\n return {\n language: 'node',\n extractedFrom: sdkPath,\n extractedAt: new Date().toISOString(),\n classes: sortRecord(classes),\n interfaces: sortRecord(interfaces),\n typeAliases: sortRecord(typeAliases),\n enums: sortRecord(enums),\n exports: sortRecord(exports),\n };\n },\n};\n\nfunction followPropertyTypeClasses(\n exportedSymbols: ts.Symbol[],\n checker: ts.TypeChecker,\n classes: Record<string, ApiClass>,\n sdkPath: string,\n): void {\n // Build initial set of class symbols from exports\n const classSymbols = new Map<string, ts.Symbol>();\n for (const sym of exportedSymbols) {\n const resolved = resolveAlias(sym, checker);\n const decls = resolved.getDeclarations();\n if (decls?.some((d) => ts.isClassDeclaration(d))) {\n classSymbols.set(resolved.name, resolved);\n }\n }\n\n const toVisit = [...classSymbols.values()];\n const visited = new Set(classSymbols.keys());\n\n while (toVisit.length > 0) {\n const sym = toVisit.pop()!;\n const type = checker.getDeclaredTypeOfSymbol(sym);\n const decls = sym.getDeclarations();\n if (!decls || decls.length === 0) continue;\n\n for (const prop of type.getProperties()) {\n const propDecls = prop.getDeclarations();\n if (!propDecls || propDecls.length === 0) continue;\n const propDecl = propDecls[0];\n\n // Skip private/protected\n const modifiers = ts.canHaveModifiers(propDecl) ? ts.getModifiers(propDecl) : undefined;\n if (\n modifiers?.some((m) => m.kind === ts.SyntaxKind.PrivateKeyword || m.kind === ts.SyntaxKind.ProtectedKeyword)\n ) {\n continue;\n }\n\n const propType = checker.getTypeOfSymbolAtLocation(prop, propDecl);\n const propSymbol = propType.getSymbol();\n if (!propSymbol) continue;\n\n const propName = propSymbol.name;\n if (visited.has(propName)) continue;\n\n const propSymDecls = propSymbol.getDeclarations();\n if (!propSymDecls?.some((d) => ts.isClassDeclaration(d))) continue;\n\n // Found a class referenced by property type — extract it\n visited.add(propName);\n const sourceFile = relative(sdkPath, propSymDecls[0].getSourceFile().fileName);\n classes[propName] = { ...extractClass(propSymbol, checker), sourceFile };\n toVisit.push(propSymbol);\n }\n }\n}\n\nfunction resolveEntryPoint(sdkPath: string, program: ts.Program): string {\n const pkgPath = resolve(sdkPath, 'package.json');\n try {\n const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));\n // Check \"exports\" field first\n if (pkg.exports) {\n const mainExport =\n typeof pkg.exports === 'string'\n ? pkg.exports\n : (pkg.exports['.']?.import ?? pkg.exports['.']?.default ?? pkg.exports['.']);\n if (typeof mainExport === 'string') {\n const resolved = resolveSourceFile(sdkPath, mainExport, program);\n if (resolved) return resolved;\n }\n }\n // Fallback to \"main\"\n if (pkg.main) {\n const resolved = resolveSourceFile(sdkPath, pkg.main, program);\n if (resolved) return resolved;\n }\n } catch {\n // No package.json or invalid — fall through to default\n }\n\n // Default fallback\n const fallback = resolve(sdkPath, 'src/index.ts');\n if (program.getSourceFile(fallback)) return fallback;\n throw new ExtractorError(\n `No entry point found. Tried: package.json exports/main, src/index.ts`,\n `Add an \"exports\" or \"main\" field to package.json in \"${sdkPath}\", or create a src/index.ts file that re-exports the public API.`,\n );\n}\n\nfunction resolveSourceFile(sdkPath: string, entryPath: string, program: ts.Program): string | undefined {\n // Try the path as-is, then swap .js → .ts, then try index.ts\n const candidates = [\n resolve(sdkPath, entryPath),\n resolve(sdkPath, entryPath.replace(/\\.js$/, '.ts')),\n resolve(sdkPath, entryPath.replace(/\\.js$/, '/index.ts')),\n ];\n for (const candidate of candidates) {\n if (program.getSourceFile(candidate)) return candidate;\n }\n return undefined;\n}\n\nfunction resolveAlias(sym: ts.Symbol, checker: ts.TypeChecker): ts.Symbol {\n if (sym.flags & ts.SymbolFlags.Alias) {\n return checker.getAliasedSymbol(sym);\n }\n return sym;\n}\n\nfunction extractClass(sym: ts.Symbol, checker: ts.TypeChecker): ApiClass {\n const type = checker.getDeclaredTypeOfSymbol(sym);\n const methods: Record<string, ApiMethod[]> = {};\n const properties: Record<string, ApiProperty> = {};\n const constructorParams: ApiParam[] = [];\n let deprecationMessage: string | undefined;\n\n // Extract constructor params\n const declarations = sym.getDeclarations();\n if (declarations) {\n for (const decl of declarations) {\n if (ts.isClassDeclaration(decl)) {\n // Look for `@deprecated` in the class's JSDoc. JSDoc nodes are\n // attached to the declaration's parent range; TS exposes them via\n // ts.getJSDocDeprecatedTag.\n const deprecatedTag = ts.getJSDocDeprecatedTag(decl);\n if (deprecatedTag) {\n const comment = deprecatedTag.comment;\n if (typeof comment === 'string') {\n deprecationMessage = comment.trim() || '';\n } else if (Array.isArray(comment)) {\n deprecationMessage =\n comment\n .map((c) => c.text)\n .join('')\n .trim() || '';\n } else {\n deprecationMessage = '';\n }\n }\n for (const member of decl.members) {\n if (ts.isConstructorDeclaration(member)) {\n for (const param of member.parameters) {\n const { name: paramName, isDestructured } = extractParameterInfo(param, param.name.getText());\n const paramType = param.type ? checker.typeToString(checker.getTypeFromTypeNode(param.type)) : 'any';\n constructorParams.push({\n name: paramName,\n type: paramType,\n optional: !!param.questionToken || !!param.initializer,\n passingStyle: isDestructured ? 'options_object' : 'positional',\n });\n }\n }\n }\n }\n }\n }\n\n // Extract methods and properties from the type\n for (const prop of type.getProperties()) {\n // Skip private/protected members\n const propDeclarations = prop.getDeclarations();\n if (propDeclarations && propDeclarations.length > 0) {\n const decl = propDeclarations[0];\n const modifiers = ts.canHaveModifiers(decl) ? ts.getModifiers(decl) : undefined;\n if (\n modifiers?.some((m) => m.kind === ts.SyntaxKind.PrivateKeyword || m.kind === ts.SyntaxKind.ProtectedKeyword)\n ) {\n continue;\n }\n }\n\n const propType = checker.getTypeOfSymbolAtLocation(prop, declarations![0]);\n const callSignatures = propType.getCallSignatures();\n\n if (callSignatures.length > 0) {\n if (!methods[prop.name]) methods[prop.name] = [];\n // Extract ALL overloads, not just the first\n for (const sig of callSignatures) {\n methods[prop.name].push({\n name: prop.name,\n params: sig.getParameters().map((p) => extractParam(p, checker)),\n returnType: checker.typeToString(sig.getReturnType()),\n async: checker.typeToString(sig.getReturnType()).startsWith('Promise<'),\n });\n }\n } else {\n const typeStr = checker.typeToString(propType);\n const isReadonly = propDeclarations?.some((d) => {\n const mods = ts.canHaveModifiers(d) ? ts.getModifiers(d) : undefined;\n return mods?.some((m) => m.kind === ts.SyntaxKind.ReadonlyKeyword);\n });\n properties[prop.name] = {\n name: prop.name,\n type: typeStr,\n readonly: !!isReadonly,\n };\n }\n }\n\n return {\n name: sym.name,\n methods: sortRecord(methods),\n properties: sortRecord(properties),\n constructorParams,\n ...(deprecationMessage !== undefined && { deprecationMessage }),\n };\n}\n\nfunction extractParam(sym: ts.Symbol, checker: ts.TypeChecker): ApiParam {\n const decl = sym.getDeclarations()?.[0];\n const isOptional = decl && ts.isParameter(decl) ? !!decl.questionToken || !!decl.initializer : false;\n const type = checker.getTypeOfSymbolAtLocation(sym, decl!);\n const { name, isDestructured } = extractParameterInfo(decl, sym.name);\n const typeStr = checker.typeToString(type);\n\n // Detect options object pattern:\n // - destructured object binding ({a, b}: Options)\n // - single non-primitive param with an object/interface type\n let passingStyle: ApiParam['passingStyle'];\n if (isDestructured) {\n passingStyle = 'options_object';\n } else {\n const resolvedType = checker.getTypeOfSymbolAtLocation(sym, decl!);\n const isObjectLike = resolvedType.isClassOrInterface() || (resolvedType.getFlags() & ts.TypeFlags.Object) !== 0;\n const isPrimitive = [\n 'string',\n 'number',\n 'boolean',\n 'undefined',\n 'null',\n 'void',\n 'never',\n 'any',\n 'unknown',\n ].includes(typeStr);\n if (isObjectLike && !isPrimitive && !typeStr.startsWith('Promise<')) {\n passingStyle = 'options_object';\n } else {\n passingStyle = 'positional';\n }\n }\n\n return {\n name,\n type: typeStr,\n optional: isOptional,\n passingStyle,\n };\n}\n\nfunction extractParameterInfo(\n decl: ts.Declaration | undefined,\n fallback: string,\n): { name: string; isDestructured: boolean } {\n if (!decl || !ts.isParameter(decl)) return { name: fallback, isDestructured: false };\n if (ts.isIdentifier(decl.name)) return { name: decl.name.text, isDestructured: false };\n\n const parentWithParameters = decl.parent as ts.Node & { parameters?: ts.NodeArray<ts.ParameterDeclaration> };\n const index = parentWithParameters.parameters?.indexOf(decl) ?? -1;\n const suffix = index > 0 ? String(index) : '';\n\n if (ts.isObjectBindingPattern(decl.name)) return { name: `options${suffix}`, isDestructured: true };\n if (ts.isArrayBindingPattern(decl.name)) return { name: `args${suffix}`, isDestructured: false };\n\n return { name: fallback, isDestructured: false };\n}\n\nfunction extractInterface(sym: ts.Symbol, checker: ts.TypeChecker): ApiInterface {\n const type = checker.getDeclaredTypeOfSymbol(sym);\n const fields: Record<string, ApiField> = {};\n const extendsNames: string[] = [];\n\n // Get extends clauses\n const declarations = sym.getDeclarations();\n if (declarations) {\n for (const decl of declarations) {\n if (ts.isInterfaceDeclaration(decl) && decl.heritageClauses) {\n for (const clause of decl.heritageClauses) {\n for (const typeExpr of clause.types) {\n extendsNames.push(typeExpr.getText());\n }\n }\n }\n }\n }\n\n for (const prop of type.getProperties()) {\n const propType = checker.getTypeOfSymbolAtLocation(prop, declarations![0]);\n const propDecl = prop.getDeclarations()?.[0];\n const isOptional = propDecl && ts.isPropertySignature(propDecl) ? !!propDecl.questionToken : false;\n let typeStr = checker.typeToString(propType);\n if (isOptional) {\n typeStr = stripUndefined(typeStr);\n }\n fields[prop.name] = {\n name: prop.name,\n type: typeStr,\n optional: isOptional,\n };\n }\n\n // Fallback: walk AST declaration members for fields that type.getProperties() missed.\n // This handles generic interfaces (e.g., List<T>) where the checker may not resolve\n // all properties when the type parameter is unbound.\n if (declarations) {\n for (const decl of declarations) {\n if (ts.isInterfaceDeclaration(decl)) {\n for (const member of decl.members) {\n if (ts.isPropertySignature(member) && member.name) {\n const memberName = member.name.getText();\n if (!fields[memberName]) {\n const memberType = member.type ? checker.typeToString(checker.getTypeFromTypeNode(member.type)) : 'any';\n const isOpt = !!member.questionToken;\n fields[memberName] = {\n name: memberName,\n type: isOpt ? stripUndefined(memberType) : memberType,\n optional: isOpt,\n };\n }\n }\n }\n }\n }\n }\n\n return {\n name: sym.name,\n fields: sortRecord(fields),\n extends: extendsNames.sort(),\n };\n}\n\nfunction extractTypeAlias(sym: ts.Symbol, checker: ts.TypeChecker): ApiTypeAlias {\n const type = checker.getDeclaredTypeOfSymbol(sym);\n return {\n name: sym.name,\n value: checker.typeToString(type, undefined, ts.TypeFormatFlags.InTypeAlias | ts.TypeFormatFlags.NoTruncation),\n };\n}\n\nfunction extractEnum(sym: ts.Symbol, checker: ts.TypeChecker): ApiEnum {\n const members: Record<string, string | number> = {};\n const type = checker.getDeclaredTypeOfSymbol(sym);\n\n if (type.isUnion()) {\n for (const memberType of type.types) {\n if (memberType.symbol) {\n const constValue = checker.getConstantValue(memberType.symbol.getDeclarations()![0] as ts.EnumMember);\n if (constValue !== undefined) {\n members[memberType.symbol.name] = constValue;\n }\n }\n }\n }\n\n return {\n name: sym.name,\n members: sortRecord(members),\n };\n}\n\nfunction buildExportMap(\n entryFile: ts.SourceFile,\n checker: ts.TypeChecker,\n sdkPath: string,\n program: ts.Program,\n): Record<string, string[]> {\n const exports: Record<string, string[]> = {};\n const visited = new Set<string>();\n\n function walk(sourceFile: ts.SourceFile): void {\n const absPath = sourceFile.fileName;\n if (visited.has(absPath)) return;\n visited.add(absPath);\n\n const relPath = relative(sdkPath, absPath);\n const moduleSymbol = checker.getSymbolAtLocation(sourceFile);\n if (moduleSymbol) {\n const names = checker.getExportsOfModule(moduleSymbol).map((s) => s.name);\n if (names.length > 0) {\n exports[relPath] = names.sort();\n }\n }\n\n for (const stmt of sourceFile.statements) {\n if (ts.isExportDeclaration(stmt) && stmt.moduleSpecifier && ts.isStringLiteral(stmt.moduleSpecifier)) {\n const target = stmt.moduleSpecifier.text;\n const resolved = resolveSourceFile(path.dirname(absPath), target, program);\n if (resolved) {\n const targetFile = program.getSourceFile(resolved);\n if (targetFile) {\n walk(targetFile);\n }\n }\n }\n }\n }\n\n walk(entryFile);\n return exports;\n}\n\nfunction stripUndefined(typeStr: string): string {\n return typeStr.replace(/\\s*\\|\\s*undefined$/, '').replace(/^undefined\\s*\\|\\s*/, '');\n}\n","/**\n * PHP source parser — tree-sitter-based extraction of classes, interfaces,\n * methods, properties, and constants from PHP source files.\n */\nimport { readFileSync, readdirSync, statSync } from 'node:fs';\nimport { join, relative } from 'node:path';\nimport Parser from 'tree-sitter';\nimport PhpGrammar from 'tree-sitter-php';\nimport type { SyntaxNode } from 'tree-sitter';\nimport { safeParse } from '../../utils/tree-sitter.js';\n\n// ---------------------------------------------------------------------------\n// Internal types\n// ---------------------------------------------------------------------------\n\nexport interface PhpParam {\n name: string;\n type: string;\n optional: boolean;\n}\n\nexport interface PhpMethod {\n name: string;\n visibility: 'public' | 'protected' | 'private';\n isStatic: boolean;\n params: PhpParam[];\n returnType: string;\n}\n\nexport interface PhpConstant {\n name: string;\n value: string;\n}\n\nexport interface PhpProperty {\n name: string;\n type: string;\n visibility: 'public' | 'protected' | 'private';\n}\n\nexport interface PhpClass {\n name: string;\n namespace: string;\n extends: string | null;\n isInterface: boolean;\n methods: PhpMethod[];\n properties: PhpProperty[];\n constants: PhpConstant[];\n resourceAttributes: string[];\n /** True if the class defines its own constructFromResponse method (not inherited). */\n hasCustomConstructor: boolean;\n sourceFile: string;\n}\n\n// ---------------------------------------------------------------------------\n// Shared parser instance\n// ---------------------------------------------------------------------------\n\nconst phpParser = new Parser();\nphpParser.setLanguage(PhpGrammar.php_only);\n\n// ---------------------------------------------------------------------------\n// File walker\n// ---------------------------------------------------------------------------\n\nexport function walkPhpFiles(dir: string): string[] {\n const results: string[] = [];\n let entries: string[];\n try {\n entries = readdirSync(dir);\n } catch {\n return results;\n }\n for (const entry of entries) {\n const fullPath = join(dir, entry);\n let stat;\n try {\n stat = statSync(fullPath);\n } catch {\n continue;\n }\n if (stat.isDirectory()) {\n if (entry.startsWith('.') || entry === 'vendor' || entry === 'tests' || entry === 'test') continue;\n results.push(...walkPhpFiles(fullPath));\n } else if (entry.endsWith('.php')) {\n results.push(fullPath);\n }\n }\n return results.sort();\n}\n\ninterface PhpDocInfo {\n params: Map<string, string>; // $name → type\n returnType: string;\n}\n\nfunction parsePhpDoc(commentText: string): PhpDocInfo {\n const params = new Map<string, string>();\n let returnType = '';\n\n const lines = commentText.split('\\n');\n for (const line of lines) {\n // Match @param type $name\n const paramMatch = line.match(/@param\\s+(\\S+)\\s+\\$(\\w+)/);\n if (paramMatch) {\n params.set(paramMatch[2], paramMatch[1]);\n }\n // Match @return type\n const returnMatch = line.match(/@return\\s+(\\S+)/);\n if (returnMatch) {\n returnType = returnMatch[1];\n }\n }\n\n return { params, returnType };\n}\n\n/** Find the doc comment immediately preceding a node. */\nfunction findDocComment(node: SyntaxNode): PhpDocInfo | null {\n // Walk backward through siblings to find comment\n let sibling = node.previousNamedSibling;\n if (sibling && sibling.type === 'comment' && sibling.text.startsWith('/**')) {\n return parsePhpDoc(sibling.text);\n }\n return null;\n}\n\nfunction getVisibility(node: SyntaxNode): 'public' | 'protected' | 'private' {\n for (const child of node.children) {\n if (child.type === 'visibility_modifier') {\n const text = child.text.toLowerCase();\n if (text === 'public') return 'public';\n if (text === 'protected') return 'protected';\n if (text === 'private') return 'private';\n }\n }\n return 'public'; // PHP default\n}\n\nfunction isStaticMethod(node: SyntaxNode): boolean {\n for (const child of node.children) {\n if (child.type === 'static_modifier') return true;\n }\n return false;\n}\n\n/** Parse a PHP array literal to extract string values: [\"id\", \"name\", ...] */\nfunction parseArrayLiteral(node: SyntaxNode): string[] {\n const values: string[] = [];\n // In tree-sitter-php, array elements contain encapsed_string → string_content\n // For simple indexed arrays, each array_element_initializer has one encapsed_string\n for (const elemInit of node.descendantsOfType('array_element_initializer')) {\n const strings = elemInit.namedChildren.filter((c) => c.type === 'encapsed_string' || c.type === 'string');\n // For indexed arrays (no =>), there's one string per element\n if (strings.length === 1) {\n const contentNode = strings[0].namedChildren.find((c) => c.type === 'string_content');\n if (contentNode) {\n values.push(contentNode.text);\n }\n }\n }\n return values;\n}\n\n/** Extract the name and value from a const_element node. */\nfunction parseConstElement(constElement: SyntaxNode): { name: string; value: string } | null {\n const nameNode = constElement.namedChildren.find((c) => c.type === 'name');\n if (!nameNode) return null;\n\n const constName = nameNode.text;\n\n // Skip RESOURCE_ATTRIBUTES and RESPONSE_TO_RESOURCE_KEY (they're arrays, not scalar constants)\n if (constName === 'RESOURCE_ATTRIBUTES' || constName === 'RESPONSE_TO_RESOURCE_KEY') return null;\n\n // Find the value node (encapsed_string, string, integer, etc.)\n const valueNode = constElement.namedChildren.find((c) => c.type !== 'name');\n if (!valueNode) return null;\n\n // For string values, extract string_content\n if (valueNode.type === 'encapsed_string') {\n const contentNode = valueNode.namedChildren.find((c) => c.type === 'string_content');\n return { name: constName, value: contentNode ? contentNode.text : '' };\n }\n if (valueNode.type === 'string') {\n const contentNode = valueNode.namedChildren.find((c) => c.type === 'string_content');\n return { name: constName, value: contentNode ? contentNode.text : '' };\n }\n\n // For other types (integers, etc.), use the raw text\n return { name: constName, value: valueNode.text };\n}\n\n// ---------------------------------------------------------------------------\n// Method extraction\n// ---------------------------------------------------------------------------\n\nfunction parseMethods(classBody: SyntaxNode): PhpMethod[] {\n const methods: PhpMethod[] = [];\n\n for (const child of classBody.namedChildren) {\n if (child.type !== 'method_declaration') continue;\n\n const nameNode = child.childForFieldName('name');\n if (!nameNode) continue;\n const methodName = nameNode.text;\n\n // Skip magic methods except __construct\n if (methodName.startsWith('__') && methodName !== '__construct') continue;\n\n const visibility = getVisibility(child);\n const isStatic = isStaticMethod(child);\n\n // Get PHPDoc info\n const docInfo = findDocComment(child);\n\n // Parse parameters\n const params: PhpParam[] = [];\n const paramsList = child.childForFieldName('parameters');\n if (paramsList) {\n for (const paramNode of paramsList.namedChildren) {\n if (paramNode.type !== 'simple_parameter') continue;\n\n const paramNameNode = paramNode.namedChildren.find((c) => c.type === 'variable_name');\n if (!paramNameNode) continue;\n\n const paramName = paramNameNode.text.replace(/^\\$/, '');\n\n // Check for native type hint\n let paramType = '';\n const typeNode = paramNode.childForFieldName('type');\n if (typeNode) {\n paramType = typeNode.text;\n }\n // Fall back to PHPDoc\n if (!paramType && docInfo) {\n paramType = docInfo.params.get(paramName) || 'mixed';\n }\n if (!paramType) {\n paramType = 'mixed';\n }\n\n // Check for default value (means optional)\n const defaultNode = paramNode.childForFieldName('default_value');\n const hasDefault = defaultNode !== null;\n\n params.push({\n name: paramName,\n type: paramType,\n optional: hasDefault,\n });\n }\n }\n\n // Return type\n let returnType = '';\n const returnTypeNode = child.childForFieldName('return_type');\n if (returnTypeNode) {\n returnType = returnTypeNode.text;\n }\n if (!returnType && docInfo) {\n returnType = docInfo.returnType || 'mixed';\n }\n if (!returnType) {\n returnType = 'mixed';\n }\n\n methods.push({\n name: methodName,\n visibility,\n isStatic,\n params,\n returnType,\n });\n }\n\n return methods;\n}\n\n// ---------------------------------------------------------------------------\n// Property extraction\n// ---------------------------------------------------------------------------\n\nfunction parseProperties(classBody: SyntaxNode): PhpProperty[] {\n const properties: PhpProperty[] = [];\n\n for (const child of classBody.namedChildren) {\n if (child.type !== 'property_declaration') continue;\n\n const visibility = getVisibility(child);\n\n // Get property name from property_element → variable_name\n for (const propElement of child.namedChildren) {\n if (propElement.type !== 'property_element') continue;\n const varNameNode = propElement.namedChildren.find((c) => c.type === 'variable_name');\n if (!varNameNode) continue;\n\n const propName = varNameNode.text.replace(/^\\$/, '');\n\n // Check for type hint\n let propType = 'mixed';\n const typeNode = child.namedChildren.find(\n (c) =>\n c.type === 'union_type' ||\n c.type === 'named_type' ||\n c.type === 'optional_type' ||\n c.type === 'primitive_type',\n );\n if (typeNode) {\n propType = typeNode.text;\n }\n\n properties.push({\n name: propName,\n type: propType,\n visibility,\n });\n }\n }\n\n return properties;\n}\n\n// ---------------------------------------------------------------------------\n// Constant extraction\n// ---------------------------------------------------------------------------\n\nfunction parseConstants(classBody: SyntaxNode): PhpConstant[] {\n const constants: PhpConstant[] = [];\n\n for (const child of classBody.namedChildren) {\n if (child.type !== 'const_declaration') continue;\n\n for (const constElement of child.namedChildren) {\n if (constElement.type !== 'const_element') continue;\n\n const parsed = parseConstElement(constElement);\n if (parsed) {\n constants.push(parsed);\n }\n }\n }\n\n return constants;\n}\n\n// ---------------------------------------------------------------------------\n// Resource attributes extraction\n// ---------------------------------------------------------------------------\n\nfunction parseResourceAttributes(classBody: SyntaxNode): string[] {\n for (const child of classBody.namedChildren) {\n if (child.type !== 'const_declaration') continue;\n\n for (const constElement of child.namedChildren) {\n if (constElement.type !== 'const_element') continue;\n\n const nameNode = constElement.namedChildren.find((c) => c.type === 'name');\n if (!nameNode || nameNode.text !== 'RESOURCE_ATTRIBUTES') continue;\n\n const arrayNode = constElement.namedChildren.find((c) => c.type === 'array_creation_expression');\n if (!arrayNode) continue;\n\n return parseArrayLiteral(arrayNode);\n }\n }\n return [];\n}\n\n// ---------------------------------------------------------------------------\n// Namespace extraction\n// ---------------------------------------------------------------------------\n\nfunction extractNamespace(tree: Parser.Tree): string {\n for (const node of tree.rootNode.namedChildren) {\n if (node.type === 'namespace_definition') {\n const nameNode = node.childForFieldName('name');\n return nameNode ? nameNode.text : '';\n }\n }\n return '';\n}\n\n// ---------------------------------------------------------------------------\n// Class/interface extraction\n// ---------------------------------------------------------------------------\n\nfunction parseClassDeclarations(tree: Parser.Tree, sourceFile: string, namespace: string): PhpClass[] {\n const classes: PhpClass[] = [];\n\n for (const node of tree.rootNode.descendantsOfType('class_declaration')) {\n const nameNode = node.childForFieldName('name');\n if (!nameNode) continue;\n\n // Check for extends\n let extendsName: string | null = null;\n const baseClause = node.namedChildren.find((c) => c.type === 'base_clause');\n if (baseClause) {\n const baseNameNode = baseClause.namedChildren.find((c) => c.type === 'name' || c.type === 'qualified_name');\n if (baseNameNode) {\n // Strip leading backslash and namespace qualifiers for base name\n const fullName = baseNameNode.text.replace(/^\\\\/, '');\n const parts = fullName.split('\\\\');\n extendsName = parts[parts.length - 1];\n }\n }\n\n const bodyNode = node.childForFieldName('body');\n if (!bodyNode) continue;\n\n const methods = parseMethods(bodyNode);\n const properties = parseProperties(bodyNode);\n const constants = parseConstants(bodyNode);\n const resourceAttributes = parseResourceAttributes(bodyNode);\n\n const hasCustomConstructor = methods.some((m) => m.name === 'constructFromResponse' && m.isStatic);\n\n classes.push({\n name: nameNode.text,\n namespace,\n extends: extendsName,\n isInterface: false,\n methods,\n properties,\n constants,\n resourceAttributes,\n hasCustomConstructor,\n sourceFile,\n });\n }\n\n return classes;\n}\n\nfunction parseInterfaceDeclarations(tree: Parser.Tree, sourceFile: string, namespace: string): PhpClass[] {\n const interfaces: PhpClass[] = [];\n\n for (const node of tree.rootNode.descendantsOfType('interface_declaration')) {\n const nameNode = node.childForFieldName('name');\n if (!nameNode) continue;\n\n const bodyNode = node.childForFieldName('body');\n if (!bodyNode) continue;\n\n const methods = parseMethods(bodyNode);\n\n interfaces.push({\n name: nameNode.text,\n namespace,\n extends: null,\n isInterface: true,\n methods,\n properties: [],\n constants: [],\n resourceAttributes: [],\n hasCustomConstructor: false,\n sourceFile,\n });\n }\n\n return interfaces;\n}\n\n// ---------------------------------------------------------------------------\n// PHP 8.1 enum extraction\n// ---------------------------------------------------------------------------\n\nfunction parseEnumDeclarations(tree: Parser.Tree, sourceFile: string, namespace: string): PhpClass[] {\n const enums: PhpClass[] = [];\n\n for (const node of tree.rootNode.descendantsOfType('enum_declaration')) {\n const nameNode = node.childForFieldName('name');\n if (!nameNode) continue;\n\n const bodyNode = node.childForFieldName('body');\n if (!bodyNode) continue;\n\n // Extract enum cases as constants\n const constants: PhpConstant[] = [];\n for (const child of bodyNode.namedChildren) {\n if (child.type !== 'enum_case') continue;\n const caseNameNode = child.childForFieldName('name');\n if (!caseNameNode) continue;\n\n // Get the value (backed enum): case Foo = 'foo'\n let value = caseNameNode.text;\n const valueNode = child.namedChildren.find(\n (c) => c.type === 'encapsed_string' || c.type === 'string' || c.type === 'integer',\n );\n if (valueNode) {\n const contentNode = valueNode.namedChildren.find((c) => c.type === 'string_content');\n value = contentNode ? contentNode.text : valueNode.text;\n }\n\n constants.push({ name: caseNameNode.text, value });\n }\n\n const methods = parseMethods(bodyNode);\n\n enums.push({\n name: nameNode.text,\n namespace,\n extends: null,\n isInterface: false,\n methods,\n properties: [],\n constants,\n resourceAttributes: [],\n hasCustomConstructor: false,\n sourceFile,\n });\n }\n\n return enums;\n}\n\n// ---------------------------------------------------------------------------\n// Full file parser\n// ---------------------------------------------------------------------------\n\nexport interface ParsedPhpFile {\n classes: PhpClass[];\n}\n\n/** Parse a single PHP source file and return all extracted symbols. */\nexport function parsePhpFile(filePath: string, sdkPath: string): ParsedPhpFile {\n const source = readFileSync(filePath, 'utf-8');\n const relPath = relative(sdkPath, filePath);\n const tree = safeParse(phpParser, source);\n const namespace = extractNamespace(tree);\n\n const classDecls = parseClassDeclarations(tree, relPath, namespace);\n const interfaceDecls = parseInterfaceDeclarations(tree, relPath, namespace);\n const enumDecls = parseEnumDeclarations(tree, relPath, namespace);\n\n return {\n classes: [...classDecls, ...interfaceDecls, ...enumDecls],\n };\n}\n","/**\n * PHP surface builder — transforms parsed PHP classes into an ApiSurface.\n *\n * Mapping:\n * Class extending a resource base → ApiInterface (fields from RESOURCE_ATTRIBUTES)\n * Class with only constants → ApiEnum (const values)\n * Service class with public methods → ApiClass\n * Static utility class → ApiClass\n * PHP interface declaration → ApiInterface (methods as fields)\n * Exception class → ApiClass\n */\n\nimport type {\n ApiClass,\n ApiMethod,\n ApiParam,\n ApiProperty,\n ApiInterface,\n ApiField,\n ApiEnum,\n LanguageHints,\n} from '../types.js';\nimport type { PhpClass } from './php-parser.js';\nimport { sortRecord, ExportCollector } from './shared.js';\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/** Default resource base classes (empty — consumer provides via hints.modelBaseClasses). */\nconst DEFAULT_RESOURCE_BASES: string[] = [];\n\n/** Default exception base classes. */\nconst DEFAULT_EXCEPTION_BASES = ['Exception', '\\\\Exception'];\n\n/** Check if a class is a resource class (extends a known resource base and has attributes). */\nfunction isResourceClass(cls: PhpClass, resourceBases: Set<string>): boolean {\n return !!cls.extends && resourceBases.has(cls.extends) && cls.resourceAttributes.length > 0;\n}\n\n/** Check if a class is enum-like (only constants, no public methods). */\nfunction isEnumClass(cls: PhpClass): boolean {\n if (cls.isInterface) return false;\n if (cls.constants.length === 0) return false;\n // Must have only constants — no public instance methods (excluding inherited)\n const publicMethods = cls.methods.filter((m) => m.visibility === 'public' && m.name !== '__construct');\n return publicMethods.length === 0 && cls.properties.length === 0 && !cls.extends;\n}\n\n/** Check if a class is an exception. */\nfunction isExceptionClass(cls: PhpClass, exceptionBases: Set<string>): boolean {\n if (!cls.extends) return false;\n return exceptionBases.has(cls.extends);\n}\n\n// ---------------------------------------------------------------------------\n// Surface builder\n// ---------------------------------------------------------------------------\n\nexport function buildSurface(\n allClasses: PhpClass[],\n hints?: LanguageHints,\n): {\n classes: Record<string, ApiClass>;\n interfaces: Record<string, ApiInterface>;\n enums: Record<string, ApiEnum>;\n exports: Record<string, string[]>;\n} {\n const resourceBases = new Set(hints?.modelBaseClasses ?? DEFAULT_RESOURCE_BASES);\n const exceptionBases = new Set(hints?.exceptionBaseClasses ?? DEFAULT_EXCEPTION_BASES);\n\n const classes: Record<string, ApiClass> = {};\n const interfaces: Record<string, ApiInterface> = {};\n const enums: Record<string, ApiEnum> = {};\n\n const collector = new ExportCollector();\n\n for (const cls of allClasses) {\n if (cls.isInterface) {\n // PHP interface → ApiInterface\n const fields: Record<string, ApiField> = {};\n for (const method of cls.methods) {\n if (method.visibility !== 'public') continue;\n fields[method.name] = {\n name: method.name,\n type: method.returnType || 'mixed',\n optional: false,\n };\n }\n interfaces[cls.name] = {\n name: cls.name,\n sourceFile: cls.sourceFile,\n fields: sortRecord(fields),\n extends: [],\n };\n collector.add(cls.sourceFile, cls.name);\n } else if (isResourceClass(cls, resourceBases)) {\n // Resource class → ApiInterface with fields from RESOURCE_ATTRIBUTES\n // Preserve the original field order (don't sort) — it determines toArray() output order\n const fields: Record<string, ApiField> = {};\n for (const attr of cls.resourceAttributes) {\n fields[attr] = {\n name: attr,\n type: 'mixed',\n optional: false,\n };\n }\n interfaces[cls.name] = {\n name: cls.name,\n sourceFile: cls.sourceFile,\n fields, // Intentionally NOT sorted — order matches RESOURCE_ATTRIBUTES\n extends: cls.extends ? [cls.extends] : [],\n ...(cls.hasCustomConstructor ? { hasCustomConstructor: true } : {}),\n };\n collector.add(cls.sourceFile, cls.name);\n } else if (isEnumClass(cls)) {\n // Enum-like class → ApiEnum\n const members: Record<string, string | number> = {};\n for (const constant of cls.constants) {\n members[constant.name] = constant.value;\n }\n enums[cls.name] = {\n name: cls.name,\n sourceFile: cls.sourceFile,\n members: sortRecord(members),\n };\n collector.add(cls.sourceFile, cls.name);\n } else {\n // Service class, static utility class, or exception → ApiClass\n const apiMethods: Record<string, ApiMethod[]> = {};\n const properties: Record<string, ApiProperty> = {};\n\n // Only include public methods\n for (const method of cls.methods) {\n if (method.visibility !== 'public') continue;\n\n const params: ApiParam[] = method.params.map((p) => ({\n name: p.name,\n type: p.type,\n optional: p.optional,\n passingStyle: 'named' as const,\n }));\n\n if (!apiMethods[method.name]) apiMethods[method.name] = [];\n apiMethods[method.name].push({\n name: method.name,\n params,\n returnType: method.returnType || 'mixed',\n async: false, // PHP is synchronous\n });\n }\n\n // Include public properties\n for (const prop of cls.properties) {\n if (prop.visibility !== 'public') continue;\n properties[prop.name] = {\n name: prop.name,\n type: prop.type,\n readonly: false,\n };\n }\n\n // Only add if there's something meaningful (methods or properties)\n if (\n Object.keys(apiMethods).length > 0 ||\n Object.keys(properties).length > 0 ||\n isExceptionClass(cls, exceptionBases)\n ) {\n classes[cls.name] = {\n name: cls.name,\n sourceFile: cls.sourceFile,\n methods: sortRecord(apiMethods),\n properties: sortRecord(properties),\n constructorParams: [],\n };\n collector.add(cls.sourceFile, cls.name);\n }\n }\n }\n\n const exports = collector.toRecord();\n\n return {\n classes: sortRecord(classes),\n interfaces: sortRecord(interfaces),\n enums: sortRecord(enums),\n exports: sortRecord(exports),\n };\n}\n","/**\n * PHP API surface extractor.\n *\n * Walks `.php` files under `lib/` (or `src/`), parses classes, interfaces,\n * methods, properties, and constants, then builds an `ApiSurface`.\n *\n * Parser: `php-parser.ts` — tree-sitter-based PHP source analysis\n * Surface: `php-surface.ts` — ApiSurface construction\n */\n\nimport { statSync } from 'node:fs';\nimport { resolve } from 'node:path';\nimport { ExtractorError } from '../../errors.js';\nimport type { Extractor, ApiSurface, LanguageHints } from '../types.js';\nimport type { CompatSnapshot } from '../ir.js';\nimport { apiSurfaceToSnapshot } from '../ir.js';\nimport { defaultIsNullableOnlyDifference } from '../language-hints.js';\nimport { walkPhpFiles, parsePhpFile } from './php-parser.js';\nimport { buildSurface } from './php-surface.js';\nimport type { PhpClass } from './php-parser.js';\nimport { sortRecord } from './shared.js';\n\n// ---------------------------------------------------------------------------\n// Language hints\n// ---------------------------------------------------------------------------\n\nconst PHP_BODY_TYPES = new Set(['array', 'mixed']);\n\nconst phpHints: LanguageHints = {\n stripNullable(type: string): string | null {\n // ?string → string\n if (type.startsWith('?')) return type.slice(1);\n // null|string → string, string|null → string\n const parts = type.split('|').filter((p) => p.trim().toLowerCase() !== 'null');\n if (parts.length < type.split('|').length) return parts.join('|');\n return null;\n },\n isNullableOnlyDifference(a: string, b: string): boolean {\n return defaultIsNullableOnlyDifference(this, a, b);\n },\n isUnionReorder(a: string, b: string): boolean {\n // Parse pipe-separated types, sort, compare\n const sortParts = (t: string) =>\n t\n .split('|')\n .map((s) => s.trim())\n .sort()\n .join('|');\n return a !== b && sortParts(a) === sortParts(b);\n },\n isGenericTypeParam(_type: string): boolean {\n return false; // PHP has no generics\n },\n isExtractionArtifact(type: string): boolean {\n return type === 'mixed' || type === 'Object';\n },\n tolerateCategoryMismatch: false,\n extractReturnTypeName(returnType: string): string | null {\n // Strip nullable: ?Foo → Foo, null|Foo → Foo\n const stripped = this.stripNullable(returnType) ?? returnType;\n if (['string', 'int', 'float', 'bool', 'void', 'array', 'mixed'].includes(stripped)) return null;\n return stripped.replace(/^\\\\/, '');\n },\n extractParamTypeName(paramType: string): string | null {\n const stripped = this.stripNullable(paramType) ?? paramType;\n if (['string', 'int', 'float', 'bool', 'void', 'array', 'mixed', 'null', 'callable'].includes(stripped)) {\n return null;\n }\n return stripped.replace(/^\\\\/, '');\n },\n propertyMatchesClass(propertyName: string, className: string): boolean {\n // camelCase → PascalCase comparison\n return propertyName.toLowerCase() === className.toLowerCase();\n },\n derivedModelNames(_modelName: string): string[] {\n return [];\n },\n\n isSignatureEquivalent(\n baseline: import('../types.js').ApiMethod,\n candidate: import('../types.js').ApiMethod,\n _candidateSurface: import('../types.js').ApiSurface,\n ): boolean {\n // Tolerate return type differences common in PHP SDK compat:\n // - mixed ≡ any specific return type (\\\\WorkOS\\\\Resource\\\\Response ≡ void, etc.)\n // - array ≡ mixed ≡ specific resource type\n const returnOk =\n baseline.returnType === candidate.returnType ||\n baseline.returnType === 'mixed' ||\n candidate.returnType === 'mixed' ||\n (baseline.returnType === 'void' && candidate.returnType === 'void') ||\n (baseline.returnType === 'array' && candidate.returnType === 'array');\n\n // More lenient: tolerate any return type difference when one side is a\n // namespace-qualified resource type (\\\\WorkOS\\\\Resource\\\\...)\n const returnTolerated =\n returnOk || baseline.returnType.includes('\\\\Resource\\\\') || candidate.returnType.includes('\\\\Resource\\\\');\n\n if (!returnTolerated) return false;\n\n // Case 1: Same number of required params, just name differences.\n // The spec may use generic names (id) while the live SDK uses domain names (organization).\n // Tolerate when the types match but names differ.\n if (baseline.params.length === candidate.params.length) {\n let allTypesMatch = true;\n for (let i = 0; i < baseline.params.length; i++) {\n if (baseline.params[i].type !== candidate.params[i].type) {\n allTypesMatch = false;\n break;\n }\n }\n if (allTypesMatch) return true;\n }\n\n // Case 2: Candidate uses array $options / array $payload for body/query params\n // while baseline has explicit typed params.\n // Tolerate when the candidate's params are a prefix of the baseline\n // followed by an array/mixed param that absorbs the rest.\n const candHasArrayParam = candidate.params.some((p) => PHP_BODY_TYPES.has(p.type));\n if (candHasArrayParam) return true;\n\n // Case 3: Baseline has explicit params that the candidate absorbs into path params\n // with different names (e.g., organization vs id)\n if (baseline.params.length >= 1 && candidate.params.length >= 1) {\n // Check if all param types match (allow name differences)\n let typeMatch = true;\n const minLen = Math.min(baseline.params.length, candidate.params.length);\n for (let i = 0; i < minLen; i++) {\n if (baseline.params[i].type !== candidate.params[i].type) {\n typeMatch = false;\n break;\n }\n }\n // Extra candidate params must be optional\n if (typeMatch) {\n const extraCandOk = candidate.params.slice(minLen).every((p) => p.optional);\n const extraBaseOk = baseline.params.slice(minLen).every((p) => p.optional);\n if (extraCandOk && extraBaseOk) return true;\n }\n }\n\n return false;\n },\n\n modelBaseClasses: ['BaseWorkOSResource'],\n exceptionBaseClasses: ['Exception', '\\\\Exception'],\n};\n\n// ---------------------------------------------------------------------------\n// Extractor\n// ---------------------------------------------------------------------------\n\n/** Create a PHP extractor with optional hint overrides. */\nexport function createPhpExtractor(hintOverrides?: Partial<LanguageHints>): Extractor {\n const mergedHints: LanguageHints = hintOverrides ? { ...phpHints, ...hintOverrides } : phpHints;\n\n return {\n language: 'php',\n hints: mergedHints,\n\n async extractSnapshot(sdkPath: string): Promise<CompatSnapshot> {\n const surface = await this.extract(sdkPath);\n return apiSurfaceToSnapshot(surface);\n },\n\n async extract(sdkPath: string): Promise<ApiSurface> {\n // Determine the source directory: prefer lib/, fallback to src/\n let sourceDir: string;\n const libPath = resolve(sdkPath, 'lib');\n const srcPath = resolve(sdkPath, 'src');\n\n try {\n statSync(libPath);\n sourceDir = libPath;\n } catch {\n try {\n statSync(srcPath);\n sourceDir = srcPath;\n } catch {\n throw new ExtractorError(\n `No lib/ or src/ directory found in ${sdkPath}`,\n `Ensure the --sdk-path argument points to a PHP project root containing a lib/ or src/ directory.`,\n );\n }\n }\n\n const phpFiles = walkPhpFiles(sourceDir);\n if (phpFiles.length === 0) {\n throw new ExtractorError(\n `No .php files found in ${sourceDir}`,\n `Ensure the source directory contains PHP source files.`,\n );\n }\n\n const allClasses: PhpClass[] = [];\n\n for (const filePath of phpFiles) {\n const parsed = parsePhpFile(filePath, sdkPath);\n allClasses.push(...parsed.classes);\n }\n\n const { classes, interfaces, enums, exports } = buildSurface(allClasses, mergedHints);\n\n return {\n language: 'php',\n extractedFrom: sdkPath,\n extractedAt: new Date().toISOString(),\n classes: sortRecord(classes),\n interfaces: sortRecord(interfaces),\n typeAliases: {},\n enums: sortRecord(enums),\n exports: sortRecord(exports),\n };\n },\n };\n}\n\n/** Default PHP extractor with generic language hints (no SDK-specific bases). */\nexport const phpExtractor: Extractor = createPhpExtractor();\n","/** Python source parser — tree-sitter-based extraction of classes, type aliases, and symbols. */\nimport { readFileSync, readdirSync, statSync } from 'node:fs';\nimport { join, relative } from 'node:path';\nimport Parser from 'tree-sitter';\nimport Python from 'tree-sitter-python';\nimport type { SyntaxNode } from 'tree-sitter';\nimport { safeParse } from '../../utils/tree-sitter.js';\n\n// ---------------------------------------------------------------------------\n// Internal types\n// ---------------------------------------------------------------------------\n\nexport interface PythonField {\n name: string;\n type: string;\n hasDefault: boolean;\n}\n\nexport interface PythonMethod {\n name: string;\n params: {\n name: string;\n type: string;\n optional: boolean;\n passingStyle?: 'positional' | 'keyword' | 'keyword_or_positional';\n }[];\n returnType: string;\n isAsync: boolean;\n isProperty: boolean;\n isClassMethod: boolean;\n isStaticMethod: boolean;\n}\n\nexport interface PythonClass {\n name: string;\n bases: string[];\n fields: PythonField[];\n methods: PythonMethod[];\n decorators: string[];\n sourceFile: string;\n}\n\nexport interface PythonTypeAlias {\n name: string;\n value: string;\n sourceFile: string;\n}\n\nexport interface PythonImport {\n names: string[];\n sourceFile: string;\n}\n\n// ---------------------------------------------------------------------------\n// Shared parser instance\n// ---------------------------------------------------------------------------\n\nconst pythonParser = new Parser();\npythonParser.setLanguage(Python);\n\n// ---------------------------------------------------------------------------\n// File walker\n// ---------------------------------------------------------------------------\n\nexport function walkPythonFiles(dir: string): string[] {\n const results: string[] = [];\n let entries: string[];\n try {\n entries = readdirSync(dir);\n } catch {\n return results;\n }\n for (const entry of entries) {\n const fullPath = join(dir, entry);\n let stat;\n try {\n stat = statSync(fullPath);\n } catch {\n continue;\n }\n if (stat.isDirectory()) {\n if (\n entry.startsWith('.') ||\n entry === '__pycache__' ||\n entry === 'tests' ||\n entry === 'test' ||\n entry === 'node_modules'\n )\n continue;\n results.push(...walkPythonFiles(fullPath));\n } else if (entry.endsWith('.py')) {\n // Skip test files\n if (entry.endsWith('_test.py') || entry.startsWith('test_')) continue;\n // Skip private modules (but include __init__.py)\n if (entry.startsWith('_') && entry !== '__init__.py') continue;\n results.push(fullPath);\n }\n }\n return results.sort();\n}\n\n/** Find the Python source root (prefers `src/`, falls back to top-level package). */\n/** True if a directory looks like a Python package (has __init__.py or .py files). */\nfunction isPythonPackageDir(dir: string): boolean {\n try {\n statSync(join(dir, '__init__.py'));\n return true;\n } catch {\n // no __init__.py — check for .py files as a fallback\n // (generated output may omit __init__.py when it's hand-maintained)\n }\n try {\n const entries = readdirSync(dir);\n return entries.some((e) => e.endsWith('.py'));\n } catch {\n return false;\n }\n}\n\nexport function findPythonSourceRoot(sdkPath: string): string | null {\n // Strategy 1: src/ directory\n const srcDir = join(sdkPath, 'src');\n try {\n const stat = statSync(srcDir);\n if (stat.isDirectory()) {\n const entries = readdirSync(srcDir);\n for (const entry of entries) {\n const pkgDir = join(srcDir, entry);\n try {\n const pkgStat = statSync(pkgDir);\n if (pkgStat.isDirectory() && isPythonPackageDir(pkgDir)) {\n return srcDir;\n }\n } catch {\n continue;\n }\n }\n }\n } catch {\n // no src/, continue\n }\n\n // Strategy 2: top-level package directory\n try {\n const entries = readdirSync(sdkPath);\n for (const entry of entries) {\n if (entry.startsWith('.') || entry === 'tests' || entry === 'test' || entry === 'node_modules') continue;\n const pkgDir = join(sdkPath, entry);\n try {\n const pkgStat = statSync(pkgDir);\n if (pkgStat.isDirectory() && isPythonPackageDir(pkgDir)) {\n return sdkPath;\n }\n } catch {\n continue;\n }\n }\n } catch {\n // can't read sdkPath\n }\n\n return null;\n}\n\n/** Get all decorator names from a decorated_definition or class_definition. */\nfunction getDecorators(node: SyntaxNode): string[] {\n const decorators: string[] = [];\n // Decorated definition wraps the class or function\n if (node.type === 'decorated_definition') {\n for (const child of node.namedChildren) {\n if (child.type === 'decorator') {\n const exprNode = child.namedChildren[0];\n if (exprNode) decorators.push(exprNode.text);\n }\n }\n }\n return decorators;\n}\n\n/** Extract base class names from a class definition's argument_list. */\nfunction getBaseClasses(classNode: SyntaxNode): string[] {\n const bases: string[] = [];\n const argList = classNode.childForFieldName('superclasses');\n if (!argList) return bases;\n\n for (const child of argList.namedChildren) {\n if (child.type === 'identifier' || child.type === 'attribute') {\n bases.push(child.text);\n } else if (child.type === 'keyword_argument') {\n // skip keyword arguments like total=False\n }\n }\n return bases;\n}\n\n/** Extract annotated fields from a class body. */\nfunction extractClassFields(bodyNode: SyntaxNode): PythonField[] {\n const fields: PythonField[] = [];\n\n for (const child of bodyNode.namedChildren) {\n if (child.type !== 'expression_statement') continue;\n\n const stmtChild = child.namedChildren[0];\n if (!stmtChild || stmtChild.type !== 'assignment') continue;\n\n const left = stmtChild.childForFieldName('left');\n const typeNode = stmtChild.childForFieldName('type');\n\n // Must be an annotated assignment (has a type annotation)\n if (!left || !typeNode) continue;\n // Only simple identifier on left side (not tuple unpacking, etc.)\n if (left.type !== 'identifier') continue;\n\n const right = stmtChild.childForFieldName('right');\n\n fields.push({\n name: left.text,\n type: typeNode.text,\n hasDefault: right !== null,\n });\n }\n return fields;\n}\n\n/** Extract methods from a class body. */\nfunction extractClassMethods(bodyNode: SyntaxNode): PythonMethod[] {\n const methods: PythonMethod[] = [];\n\n for (const child of bodyNode.namedChildren) {\n let funcNode: SyntaxNode | null = null;\n let decorators: string[] = [];\n\n if (child.type === 'decorated_definition') {\n decorators = getDecorators(child);\n // The actual function/class is the last named child\n funcNode = child.namedChildren.find((c) => c.type === 'function_definition') || null;\n } else if (child.type === 'function_definition') {\n funcNode = child;\n }\n\n if (!funcNode) continue;\n\n const nameNode = funcNode.childForFieldName('name');\n if (!nameNode) continue;\n const methodName = nameNode.text;\n\n // Skip private methods (starting with _) but keep __init__\n if (methodName.startsWith('_') && methodName !== '__init__') continue;\n\n const isAsync = funcNode.namedChildren.some((c) => c.type === 'async');\n const isProperty = decorators.includes('property');\n const isClassMethod = decorators.includes('classmethod');\n const isStaticMethod = decorators.includes('staticmethod');\n\n // Extract parameters\n const paramsNode = funcNode.childForFieldName('parameters');\n const params = extractFunctionParams(paramsNode, isStaticMethod || isClassMethod);\n\n // Extract return type\n const returnTypeNode = funcNode.childForFieldName('return_type');\n const returnType = returnTypeNode ? returnTypeNode.text : '';\n\n methods.push({\n name: methodName,\n params,\n returnType,\n isAsync,\n isProperty,\n isClassMethod,\n isStaticMethod,\n });\n }\n\n return methods;\n}\n\n/** Extract parameters from a function's parameter list. */\nfunction extractFunctionParams(\n paramsNode: SyntaxNode | null,\n skipFirst: boolean,\n): {\n name: string;\n type: string;\n optional: boolean;\n passingStyle?: 'positional' | 'keyword' | 'keyword_or_positional';\n}[] {\n if (!paramsNode) return [];\n const params: {\n name: string;\n type: string;\n optional: boolean;\n passingStyle?: 'positional' | 'keyword' | 'keyword_or_positional';\n }[] = [];\n let skippedFirst = false;\n let seenStarMarker = false;\n\n for (const child of paramsNode.namedChildren) {\n // Skip `self` or `cls` parameter\n if (!skippedFirst && !skipFirst && child.type === 'identifier' && (child.text === 'self' || child.text === 'cls')) {\n skippedFirst = true;\n continue;\n }\n if (!skippedFirst && !skipFirst && child.type === 'typed_parameter' && child.namedChildren[0]?.text === 'self') {\n skippedFirst = true;\n continue;\n }\n\n // `*` separator in parameters (keyword-only marker)\n if (child.text === '*') {\n seenStarMarker = true;\n continue;\n }\n\n // *args — variadic positional (also marks subsequent params as keyword-only)\n if (child.type === 'list_splat_pattern') {\n seenStarMarker = true;\n const nameNode = child.namedChildren.find((c: SyntaxNode) => c.type === 'identifier');\n params.push({\n name: nameNode ? `*${nameNode.text}` : '*args',\n type: '',\n optional: true,\n passingStyle: 'positional',\n });\n continue;\n }\n\n // **kwargs — variadic keyword\n if (child.type === 'dictionary_splat_pattern') {\n const nameNode = child.namedChildren.find((c: SyntaxNode) => c.type === 'identifier');\n params.push({\n name: nameNode ? `**${nameNode.text}` : '**kwargs',\n type: '',\n optional: true,\n passingStyle: 'keyword',\n });\n continue;\n }\n\n const passingStyle = seenStarMarker ? ('keyword' as const) : ('keyword_or_positional' as const);\n\n if (child.type === 'typed_parameter') {\n const nameNode = child.namedChildren.find((c) => c.type === 'identifier');\n const typeNode = child.childForFieldName('type');\n if (nameNode) {\n params.push({\n name: nameNode.text,\n type: typeNode ? typeNode.text : '',\n optional: false,\n passingStyle,\n });\n }\n } else if (child.type === 'typed_default_parameter') {\n const nameNode = child.childForFieldName('name');\n const typeNode = child.childForFieldName('type');\n if (nameNode) {\n params.push({\n name: nameNode.text,\n type: typeNode ? typeNode.text : '',\n optional: true,\n passingStyle,\n });\n }\n } else if (child.type === 'default_parameter') {\n const nameNode = child.childForFieldName('name');\n if (nameNode) {\n params.push({\n name: nameNode.text,\n type: '',\n optional: true,\n passingStyle,\n });\n }\n } else if (child.type === 'identifier') {\n params.push({\n name: child.text,\n type: '',\n optional: false,\n passingStyle,\n });\n }\n }\n\n return params;\n}\n\n/** Extract module-level type aliases (e.g., FooType = Literal[\"a\", \"b\"]). */\nfunction extractTypeAliases(tree: Parser.Tree, sourceFile: string): PythonTypeAlias[] {\n const aliases: PythonTypeAlias[] = [];\n\n for (const node of tree.rootNode.namedChildren) {\n // type alias statement (Python 3.12+): type X = ...\n if (node.type === 'type_alias_statement') {\n const nameNode = node.childForFieldName('name');\n const valueNode = node.childForFieldName('value');\n if (nameNode && valueNode) {\n aliases.push({ name: nameNode.text, value: valueNode.text, sourceFile });\n }\n continue;\n }\n\n // Assignment: X = Literal[...] or X = \"SomeResource[...]\"\n if (node.type === 'expression_statement') {\n const inner = node.namedChildren[0];\n if (!inner || inner.type !== 'assignment') continue;\n\n const left = inner.childForFieldName('left');\n const right = inner.childForFieldName('right');\n if (!left || !right) continue;\n\n // Only consider simple name assignments (not a: type = value)\n if (left.type !== 'identifier') continue;\n\n const name = left.text;\n // Skip private names and dunder names\n if (name.startsWith('_')) continue;\n // Skip ALL_CAPS constants that are not type aliases\n if (/^[A-Z][A-Z_0-9]*$/.test(name)) continue;\n\n const value = right.text;\n\n // Only take subscript expressions (Literal[...], SomeResource[...], etc.)\n // or string literals that look like type aliases\n if (right.type === 'subscript' || (right.type === 'string' && value.includes('['))) {\n // For string literals, strip quotes\n let cleanValue = value;\n if (right.type === 'string') {\n cleanValue = value.replace(/^[\"']|[\"']$/g, '');\n }\n aliases.push({ name, value: cleanValue, sourceFile });\n }\n }\n }\n\n return aliases;\n}\n\n/** Extract __all__ exports from a module. */\nfunction extractAllExports(tree: Parser.Tree): string[] {\n const exports: string[] = [];\n\n for (const node of tree.rootNode.namedChildren) {\n if (node.type !== 'expression_statement') continue;\n const inner = node.namedChildren[0];\n if (!inner || inner.type !== 'assignment') continue;\n\n const left = inner.childForFieldName('left');\n const right = inner.childForFieldName('right');\n if (!left || !right) continue;\n if (left.text !== '__all__') continue;\n\n // __all__ = [\"Foo\", \"Bar\"]\n if (right.type === 'list') {\n for (const elem of right.namedChildren) {\n if (elem.type === 'string') {\n const text = elem.text.replace(/^[\"']|[\"']$/g, '');\n exports.push(text);\n }\n }\n }\n }\n\n return exports;\n}\n\nfunction extractClassesFromTree(tree: Parser.Tree, sourceFile: string): PythonClass[] {\n const classes: PythonClass[] = [];\n\n for (const node of tree.rootNode.namedChildren) {\n let classNode: SyntaxNode | null = null;\n let decorators: string[] = [];\n\n if (node.type === 'decorated_definition') {\n decorators = getDecorators(node);\n classNode = node.namedChildren.find((c) => c.type === 'class_definition') || null;\n } else if (node.type === 'class_definition') {\n classNode = node;\n }\n\n if (!classNode) continue;\n\n const nameNode = classNode.childForFieldName('name');\n if (!nameNode) continue;\n const className = nameNode.text;\n\n const bases = getBaseClasses(classNode);\n\n const bodyNode = classNode.childForFieldName('body');\n if (!bodyNode) {\n classes.push({ name: className, bases, fields: [], methods: [], decorators, sourceFile });\n continue;\n }\n\n const fields = extractClassFields(bodyNode);\n const methods = extractClassMethods(bodyNode);\n\n classes.push({ name: className, bases, fields, methods, decorators, sourceFile });\n }\n\n return classes;\n}\n\n// ---------------------------------------------------------------------------\n// Full file parser\n// ---------------------------------------------------------------------------\n\nexport interface ParsedPythonFile {\n classes: PythonClass[];\n typeAliases: PythonTypeAlias[];\n allExports: string[];\n sourceFile: string;\n}\n\n/** Parse a single Python source file and return all extracted symbols. */\nexport function parsePythonFile(filePath: string, sdkPath: string): ParsedPythonFile {\n const source = readFileSync(filePath, 'utf-8');\n const relPath = relative(sdkPath, filePath);\n const tree = safeParse(pythonParser, source);\n\n const classes = extractClassesFromTree(tree, relPath);\n const typeAliases = extractTypeAliases(tree, relPath);\n const allExports = extractAllExports(tree);\n\n return { classes, typeAliases, allExports, sourceFile: relPath };\n}\n","/**\n * Python surface builder — transforms parsed Python symbols into an ApiSurface.\n *\n * Mapping:\n * class Foo(BaseModel/custom model) → ApiInterface (fields from annotations)\n * class Foo(TypedDict) → ApiInterface (fields)\n * class Foo(Protocol) → ApiClass (canonical service)\n * Sync/Async impl classes → skip (Protocol takes precedence)\n * FooType = Literal[...] → ApiEnum (members = literal strings)\n * FooResource = ListResource[...] → ApiTypeAlias\n * Exception subclass → ApiClass\n * Other class with methods → ApiClass\n */\n\nimport type {\n ApiClass,\n ApiMethod,\n ApiParam,\n ApiInterface,\n ApiField,\n ApiTypeAlias,\n ApiEnum,\n LanguageHints,\n} from '../types.js';\nimport type { PythonClass, ParsedPythonFile } from './python-parser.js';\nimport { sortRecord, ExportCollector } from './shared.js';\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/** Default model base classes. Overridden by hints.modelBaseClasses when provided. */\nconst DEFAULT_MODEL_BASES: string[] = [];\n\n/** Known dict-like base classes (→ ApiInterface). */\nconst DICT_BASES = new Set(['TypedDict']);\n\n/** Known protocol bases (→ ApiClass as service). */\nconst PROTOCOL_BASES = new Set(['Protocol']);\n\n/** Default exception bases. Overridden by hints.exceptionBaseClasses when provided. */\nconst DEFAULT_EXCEPTION_BASES = ['Exception', 'BaseException'];\n\n/** Check if a class has any of the given base classes (by simple name). */\nfunction hasBase(cls: PythonClass, bases: Set<string>): boolean {\n return cls.bases.some((b) => bases.has(b));\n}\n\n/** Check if a class is a model class (inherits from BaseModel or configured model bases,\n * transitively from another class that does). */\nfunction isModelClass(cls: PythonClass, allClasses: Map<string, PythonClass>, modelBases: Set<string>): boolean {\n if (hasBase(cls, modelBases)) return true;\n // Check transitively: if parent class is a model\n for (const base of cls.bases) {\n const parentCls = allClasses.get(base);\n if (parentCls && isModelClass(parentCls, allClasses, modelBases)) return true;\n }\n return false;\n}\n\n/** Check if a class is an exception class. */\nfunction isExceptionClass(\n cls: PythonClass,\n allClasses: Map<string, PythonClass>,\n exceptionBases: Set<string>,\n): boolean {\n if (hasBase(cls, exceptionBases)) return true;\n for (const base of cls.bases) {\n const parentCls = allClasses.get(base);\n if (parentCls && isExceptionClass(parentCls, allClasses, exceptionBases)) return true;\n }\n return false;\n}\n\n/** Parse Literal[\"a\", \"b\", \"c\"] into member strings. */\nfunction parseLiteralMembers(value: string): Record<string, string> | null {\n const match = value.match(/^Literal\\[(.+)\\]$/s);\n if (!match) return null;\n\n const inner = match[1];\n const members: Record<string, string> = {};\n\n // Split by comma, handling nested brackets\n const parts: string[] = [];\n let depth = 0;\n let current = '';\n for (const char of inner) {\n if (char === '[' || char === '(') depth++;\n else if (char === ']' || char === ')') depth--;\n else if (char === ',' && depth === 0) {\n parts.push(current.trim());\n current = '';\n continue;\n }\n current += char;\n }\n if (current.trim()) parts.push(current.trim());\n\n for (const part of parts) {\n // Strip quotes\n const stripped = part.replace(/^[\"']|[\"']$/g, '');\n if (stripped) {\n members[stripped] = stripped;\n }\n }\n\n return Object.keys(members).length > 0 ? members : null;\n}\n\n/** Unwrap SyncOrAsync[T] → T. */\nfunction unwrapReturnType(returnType: string): string {\n const syncOrAsyncMatch = returnType.match(/^SyncOrAsync\\[(.+)\\]$/);\n if (syncOrAsyncMatch) return syncOrAsyncMatch[1];\n const awaitableMatch = returnType.match(/^Awaitable\\[(.+)\\]$/);\n if (awaitableMatch) return awaitableMatch[1];\n return returnType;\n}\n\n// ---------------------------------------------------------------------------\n// Surface builder\n// ---------------------------------------------------------------------------\n\nexport function buildSurface(\n parsedFiles: ParsedPythonFile[],\n hints?: LanguageHints,\n): {\n classes: Record<string, ApiClass>;\n interfaces: Record<string, ApiInterface>;\n typeAliases: Record<string, ApiTypeAlias>;\n enums: Record<string, ApiEnum>;\n exports: Record<string, string[]>;\n} {\n const MODEL_BASES = new Set(hints?.modelBaseClasses ?? DEFAULT_MODEL_BASES);\n const EXCEPTION_BASES = new Set(hints?.exceptionBaseClasses ?? DEFAULT_EXCEPTION_BASES);\n\n const classes: Record<string, ApiClass> = {};\n const interfaces: Record<string, ApiInterface> = {};\n const typeAliases: Record<string, ApiTypeAlias> = {};\n const enums: Record<string, ApiEnum> = {};\n\n // Collect all classes for transitive base lookups\n const allClassesByName = new Map<string, PythonClass>();\n for (const file of parsedFiles) {\n for (const cls of file.classes) {\n allClassesByName.set(cls.name, cls);\n }\n }\n\n // Track protocol class names to skip sync/async impls\n const protocolNames = new Set<string>();\n for (const file of parsedFiles) {\n for (const cls of file.classes) {\n if (hasBase(cls, PROTOCOL_BASES)) {\n protocolNames.add(cls.name);\n }\n }\n }\n\n // Build export map from __all__ and file-level symbols\n const collector = new ExportCollector();\n\n for (const file of parsedFiles) {\n // Process type aliases\n for (const alias of file.typeAliases) {\n const literalMembers = parseLiteralMembers(alias.value);\n if (literalMembers) {\n // Literal type alias → ApiEnum\n enums[alias.name] = {\n name: alias.name,\n sourceFile: alias.sourceFile,\n members: sortRecord(literalMembers),\n };\n collector.add(alias.sourceFile, alias.name);\n } else {\n // Regular type alias → ApiTypeAlias\n typeAliases[alias.name] = {\n name: alias.name,\n sourceFile: alias.sourceFile,\n value: alias.value,\n };\n collector.add(alias.sourceFile, alias.name);\n }\n }\n\n // Process classes\n for (const cls of file.classes) {\n // 1. Protocol classes → ApiClass (canonical service)\n if (hasBase(cls, PROTOCOL_BASES)) {\n const apiMethods: Record<string, ApiMethod[]> = {};\n\n for (const method of cls.methods) {\n // Skip __init__ for protocols (they don't have constructors)\n if (method.name === '__init__') continue;\n\n const params: ApiParam[] = method.params.map((p) => ({\n name: p.name,\n type: p.type,\n optional: p.optional,\n ...(p.passingStyle ? { passingStyle: p.passingStyle } : {}),\n }));\n\n const returnType = unwrapReturnType(method.returnType);\n\n if (!apiMethods[method.name]) apiMethods[method.name] = [];\n apiMethods[method.name].push({\n name: method.name,\n params,\n returnType,\n async: method.isAsync,\n });\n }\n\n classes[cls.name] = {\n name: cls.name,\n sourceFile: cls.sourceFile,\n methods: sortRecord(apiMethods),\n properties: {},\n constructorParams: [],\n };\n collector.add(cls.sourceFile, cls.name);\n continue;\n }\n\n // 2. Model classes (BaseModel or configured model bases) → ApiInterface\n if (isModelClass(cls, allClassesByName, MODEL_BASES)) {\n const fields: Record<string, ApiField> = {};\n for (const field of cls.fields) {\n fields[field.name] = {\n name: field.name,\n type: field.type,\n optional: field.hasDefault,\n };\n }\n\n // Compute extends list: filter out model bases themselves\n const extendsArr = cls.bases.filter((b) => !MODEL_BASES.has(b) && allClassesByName.has(b));\n\n interfaces[cls.name] = {\n name: cls.name,\n sourceFile: cls.sourceFile,\n fields: sortRecord(fields),\n extends: extendsArr,\n };\n collector.add(cls.sourceFile, cls.name);\n continue;\n }\n\n // 3. TypedDict classes → ApiInterface\n if (hasBase(cls, DICT_BASES)) {\n const fields: Record<string, ApiField> = {};\n for (const field of cls.fields) {\n fields[field.name] = {\n name: field.name,\n type: field.type,\n optional: field.hasDefault,\n };\n }\n\n interfaces[cls.name] = {\n name: cls.name,\n sourceFile: cls.sourceFile,\n fields: sortRecord(fields),\n extends: [],\n };\n collector.add(cls.sourceFile, cls.name);\n continue;\n }\n\n // 4. Exception classes → ApiClass\n if (isExceptionClass(cls, allClassesByName, EXCEPTION_BASES)) {\n const apiMethods: Record<string, ApiMethod[]> = {};\n // Extract any non-private, non-init methods\n for (const method of cls.methods) {\n if (method.name === '__init__') continue;\n const params: ApiParam[] = method.params.map((p) => ({\n name: p.name,\n type: p.type,\n optional: p.optional,\n ...(p.passingStyle ? { passingStyle: p.passingStyle } : {}),\n }));\n if (!apiMethods[method.name]) apiMethods[method.name] = [];\n apiMethods[method.name].push({\n name: method.name,\n params,\n returnType: unwrapReturnType(method.returnType),\n async: method.isAsync,\n });\n }\n\n // Exception fields as properties if they have annotations\n const fields: Record<string, ApiField> = {};\n for (const field of cls.fields) {\n fields[field.name] = {\n name: field.name,\n type: field.type,\n optional: field.hasDefault,\n };\n }\n\n classes[cls.name] = {\n name: cls.name,\n sourceFile: cls.sourceFile,\n methods: sortRecord(apiMethods),\n properties: {},\n constructorParams: [],\n };\n collector.add(cls.sourceFile, cls.name);\n continue;\n }\n\n // 5. Other class with methods → ApiClass\n if (cls.methods.length > 0) {\n const apiMethods: Record<string, ApiMethod[]> = {};\n const constructorParams: ApiParam[] = [];\n\n for (const method of cls.methods) {\n if (method.name === '__init__') {\n constructorParams.push(\n ...method.params.map((p) => ({\n name: p.name,\n type: p.type,\n optional: p.optional,\n ...(p.passingStyle ? { passingStyle: p.passingStyle } : {}),\n })),\n );\n continue;\n }\n\n const params: ApiParam[] = method.params.map((p) => ({\n name: p.name,\n type: p.type,\n optional: p.optional,\n ...(p.passingStyle ? { passingStyle: p.passingStyle } : {}),\n }));\n if (!apiMethods[method.name]) apiMethods[method.name] = [];\n apiMethods[method.name].push({\n name: method.name,\n params,\n returnType: unwrapReturnType(method.returnType),\n async: method.isAsync,\n });\n }\n\n classes[cls.name] = {\n name: cls.name,\n sourceFile: cls.sourceFile,\n methods: sortRecord(apiMethods),\n properties: {},\n constructorParams,\n };\n collector.add(cls.sourceFile, cls.name);\n continue;\n }\n\n // 6. Class with only fields and no methods → ApiInterface\n if (cls.fields.length > 0) {\n const fields: Record<string, ApiField> = {};\n for (const field of cls.fields) {\n fields[field.name] = {\n name: field.name,\n type: field.type,\n optional: field.hasDefault,\n };\n }\n interfaces[cls.name] = {\n name: cls.name,\n sourceFile: cls.sourceFile,\n fields: sortRecord(fields),\n extends: [],\n };\n collector.add(cls.sourceFile, cls.name);\n }\n }\n\n // Add __all__ exports\n if (file.allExports.length > 0) {\n for (const name of file.allExports) {\n collector.add(file.sourceFile, name);\n }\n }\n }\n\n const exports = collector.toRecord();\n\n return {\n classes: sortRecord(classes),\n interfaces: sortRecord(interfaces),\n typeAliases: sortRecord(typeAliases),\n enums: sortRecord(enums),\n exports: sortRecord(exports),\n };\n}\n","/**\n * Python API surface extractor.\n *\n * Walks `.py` files under `src/` (fallback to top-level package dirs),\n * parses classes, type aliases, and module exports, then builds an\n * `ApiSurface` with Protocol-based services, Pydantic model interfaces,\n * Literal type enums, and exception classes.\n *\n * Parser: `python-parser.ts` — tree-sitter-based Python source analysis\n * Surface: `python-surface.ts` — ApiSurface construction\n */\n\nimport { ExtractorError } from '../../errors.js';\nimport type { Extractor, ApiSurface, LanguageHints } from '../types.js';\nimport type { CompatSnapshot } from '../ir.js';\nimport { apiSurfaceToSnapshot } from '../ir.js';\nimport {\n NAMED_TYPE_RE,\n typeExistsInSurface,\n namedTypeWordsOverlap,\n defaultIsNullableOnlyDifference,\n} from '../language-hints.js';\nimport { walkPythonFiles, findPythonSourceRoot, parsePythonFile } from './python-parser.js';\nimport { buildSurface } from './python-surface.js';\nimport type { ParsedPythonFile } from './python-parser.js';\n\n// ---------------------------------------------------------------------------\n// Language hints\n// ---------------------------------------------------------------------------\n\nconst PYTHON_PRIMITIVE_TYPES = new Set(['str', 'int', 'float', 'bool', 'bytes']);\n\nconst pythonHints: LanguageHints = {\n stripNullable(type: string): string | null {\n // Normalize whitespace before matching\n const normalized = type.replace(/\\s+/g, ' ').trim();\n // Optional[T] → T\n const optMatch = normalized.match(/^Optional\\[(.+)\\]$/);\n if (optMatch) return optMatch[1].trim();\n // NotRequired[T] → T (TypedDict optionality ≡ nullable for compat purposes)\n const nrMatch = normalized.match(/^NotRequired\\[(.+)\\]$/);\n if (nrMatch) return nrMatch[1].trim();\n // T | None → T, None | T → T\n const parts = normalized\n .split('|')\n .map((p) => p.trim())\n .filter((p) => p !== 'None');\n if (parts.length < normalized.split('|').length) return parts.join(' | ');\n return null;\n },\n\n isNullableOnlyDifference(a: string, b: string): boolean {\n return defaultIsNullableOnlyDifference(this, a, b);\n },\n\n isUnionReorder(a: string, b: string): boolean {\n const parseUnion = (t: string) => {\n const unionMatch = t.match(/^Union\\[(.+)\\]$/);\n if (unionMatch)\n return unionMatch[1]\n .split(',')\n .map((s) => s.trim())\n .sort();\n return t\n .split('|')\n .map((s) => s.trim())\n .sort();\n };\n return a !== b && parseUnion(a).join(',') === parseUnion(b).join(',');\n },\n\n isGenericTypeParam(type: string): boolean {\n return /^[A-Z]$/.test(type) || /^T[A-Z][a-zA-Z]*$/.test(type);\n },\n\n isExtractionArtifact(type: string): boolean {\n return type === 'Any' || type === 'object';\n },\n\n tolerateCategoryMismatch: true,\n\n extractReturnTypeName(returnType: string): string | null {\n let inner = returnType;\n const syncOrAsyncMatch = inner.match(/^SyncOrAsync\\[(.+)\\]$/);\n if (syncOrAsyncMatch) inner = syncOrAsyncMatch[1];\n const awaitableMatch = inner.match(/^Awaitable\\[(.+)\\]$/);\n if (awaitableMatch) inner = awaitableMatch[1];\n const optMatch = inner.match(/^Optional\\[(.+)\\]$/);\n if (optMatch) inner = optMatch[1];\n // Unwrap list resource patterns (e.g., SomeListResource[T, ...] → T)\n for (const pattern of this.listResourcePatterns ?? []) {\n const prefix = pattern + '[';\n if (inner.startsWith(prefix)) {\n // Extract first type arg: everything up to the first comma or closing bracket\n const rest = inner.slice(prefix.length);\n const end = rest.search(/[,\\]]/);\n if (end > 0) {\n inner = rest.slice(0, end).trim();\n break;\n }\n }\n }\n // Sequence[T] → T\n const seqMatch = inner.match(/^Sequence\\[(.+)\\]$/);\n if (seqMatch) inner = seqMatch[1];\n if (['str', 'int', 'float', 'bool', 'None', 'bytes', 'dict', 'list'].includes(inner)) return null;\n return inner;\n },\n\n extractParamTypeName(paramType: string): string | null {\n let inner = paramType;\n const optMatch = inner.match(/^Optional\\[(.+)\\]$/);\n if (optMatch) inner = optMatch[1];\n if (['str', 'int', 'float', 'bool', 'None', 'bytes', 'dict', 'list'].includes(inner)) return null;\n return inner;\n },\n\n propertyMatchesClass(propertyName: string, className: string): boolean {\n return propertyName.replace(/_/g, '').toLowerCase() === className.toLowerCase();\n },\n\n derivedModelNames(modelName: string): string[] {\n return [`${modelName}Response`];\n },\n\n isTypeEquivalent(baselineType: string, candidateType: string, candidateSurface: ApiSurface): boolean {\n // Strip nullable wrappers from both sides\n const stripNullable = (t: string): string => {\n const normalized = t.replace(/\\s+/g, ' ').trim();\n const optMatch = normalized.match(/^Optional\\[(.+)\\]$/);\n if (optMatch) return optMatch[1].trim();\n const nrMatch = normalized.match(/^NotRequired\\[(.+)\\]$/);\n if (nrMatch) return nrMatch[1].trim();\n const parts = normalized\n .split('|')\n .map((p) => p.trim())\n .filter((p) => p !== 'None');\n if (parts.length < normalized.split('|').length) return parts.join(' | ');\n return normalized;\n };\n const baseClean = stripNullable(baselineType);\n const candClean = stripNullable(candidateType);\n\n // Literal quote style equivalence: Literal[\"foo\"] ≡ Literal['foo']\n const literalMatch = (t: string) => t.match(/^Literal\\[(['\"])(.+)\\1\\]$/);\n const baseLit = literalMatch(baseClean);\n const candLit = literalMatch(candClean);\n if (baseLit && candLit && baseLit[2] === candLit[2]) return true;\n\n // LiteralOrUntyped[T] ≡ T (custom wrapper type) — strip recursively\n const stripWrappers = (t: string): string => {\n let inner = t;\n // Strip LiteralOrUntyped[...]\n const louMatch = inner.match(/^LiteralOrUntyped\\[(.+)\\]$/);\n if (louMatch) inner = louMatch[1];\n // Strip Literal[...] to get the enum name if it's a Literal of literals\n return inner;\n };\n const baseUnwrapped = stripWrappers(baseClean);\n const candUnwrapped = stripWrappers(candClean);\n if (baseUnwrapped !== baseClean || candUnwrapped !== candClean) {\n // After unwrapping, check equivalence\n if (baseUnwrapped === candClean || candUnwrapped === baseClean) return true;\n if (baseUnwrapped === candUnwrapped) return true;\n // LiteralOrUntyped[Literal[\"a\", \"b\"]] ≡ enum type\n if (baseUnwrapped.startsWith('Literal[') && candidateSurface.enums[candClean]) return true;\n if (candUnwrapped.startsWith('Literal[') && candidateSurface.enums?.[baseClean]) return true;\n }\n\n // Sequence[T] ≡ list[T] ≡ List[T]\n const seqPattern = /^(?:Sequence|list|List)\\[(.+)\\]$/;\n const baseSeq = baseClean.match(seqPattern);\n const candSeq = candClean.match(seqPattern);\n if (baseSeq && candSeq) {\n if (baseSeq[1] === candSeq[1]) return true;\n // Inner types may differ by named type (InlineRole vs DirectoryUserRole)\n const baseInner = baseSeq[1];\n const candInner = candSeq[1];\n if (NAMED_TYPE_RE.test(baseInner) && NAMED_TYPE_RE.test(candInner)) {\n if (typeExistsInSurface(candInner, candidateSurface)) {\n if (candInner.includes(baseInner) || baseInner.includes(candInner)) return true;\n if (namedTypeWordsOverlap(baseInner, candInner)) return true;\n }\n }\n // Tolerate model collection vs primitive collection: Sequence[OrganizationDomain] ≡ list[str]\n // The spec may define a field as a primitive array while the live SDK wraps it in a model.\n const primitiveTypes = PYTHON_PRIMITIVE_TYPES;\n if (\n (primitiveTypes.has(baseInner) && NAMED_TYPE_RE.test(candInner)) ||\n (primitiveTypes.has(candInner) && NAMED_TYPE_RE.test(baseInner))\n ) {\n return true;\n }\n }\n // Cross-container tolerance: Sequence[T] vs list[str] (different container names)\n if (baseSeq && !candSeq) {\n const candListMatch = candClean.match(/^(?:list|List)\\[(.+)\\]$/);\n if (candListMatch) {\n const baseInner = baseSeq[1];\n const candInner = candListMatch[1];\n if (baseInner === candInner) return true;\n const primitiveTypes = PYTHON_PRIMITIVE_TYPES;\n if (\n (primitiveTypes.has(baseInner) && NAMED_TYPE_RE.test(candInner)) ||\n (primitiveTypes.has(candInner) && NAMED_TYPE_RE.test(baseInner))\n ) {\n return true;\n }\n }\n }\n\n // Mapping[K, V] ≡ dict[K, V] (Mapping is the ABC for dict)\n const mappingPattern = /^(?:Mapping|dict|Dict)\\[(.+)\\]$/;\n const baseMapping = baseClean.match(mappingPattern);\n const candMapping = candClean.match(mappingPattern);\n if (baseMapping && candMapping) {\n // Both are map-like — compare key/value types loosely\n return true;\n }\n\n // dict map equivalence: dict[str, str] ≡ dict[str, Any] ≡ Dict[str, Any] ≡ dict[str, str | float | bool]\n const dictLikePattern = /^(?:dict|Dict|Mapping)\\[str,\\s*.+\\]$/;\n if (dictLikePattern.test(baseClean) && dictLikePattern.test(candClean)) return true;\n\n // Named metadata type ≡ dict[str, ...] (custom type alias for dict)\n const isMapType = (t: string) => dictLikePattern.test(t) || /^(?:Metadata|AuditLog\\w*Metadata)$/.test(t);\n if (isMapType(baseClean) && isMapType(candClean)) return true;\n\n // Named type alias for a map/dict type ≡ inline dict expression\n // e.g., AuditLogMetadata ≡ dict[str, str | float | bool]\n if (NAMED_TYPE_RE.test(baseClean) && dictLikePattern.test(candClean)) {\n // Assume named types ending in \"Metadata\" or \"Attributes\" are dict aliases\n if (/(?:Metadata|Attributes)$/.test(baseClean)) return true;\n }\n if (NAMED_TYPE_RE.test(candClean) && dictLikePattern.test(baseClean)) {\n if (/(?:Metadata|Attributes)$/.test(candClean)) return true;\n }\n\n // str ≡ Literal[\"...\"] (literal string type vs plain str)\n if (baseClean === 'str' && candClean.startsWith('Literal[')) return true;\n if (candClean === 'str' && baseClean.startsWith('Literal[')) return true;\n\n // Literal[...] ≡ enum name (candidate has an enum, baseline has Literal)\n if (baseClean.startsWith('Literal[') && candidateSurface.enums[candClean]) return true;\n if (candClean.startsWith('Literal[') && candidateSurface.enums?.[baseClean]) return true;\n\n // str ≡ enum type (baseline says str, candidate uses enum)\n if (baseClean === 'str' && candidateSurface.enums[candClean]) return true;\n if (candClean === 'str' && candidateSurface.enums?.[baseClean]) return true;\n\n // int ≡ float (JSON number coercion)\n const numericTypes = new Set(['int', 'float']);\n if (numericTypes.has(baseClean) && numericTypes.has(candClean)) return true;\n\n // Named type tolerance\n if (NAMED_TYPE_RE.test(baseClean) && NAMED_TYPE_RE.test(candClean)) {\n if (typeExistsInSurface(candClean, candidateSurface)) {\n if (candClean.includes(baseClean) || baseClean.includes(candClean)) return true;\n const baseNoResp = baseClean.replace(/Response$/, '');\n const candNoResp = candClean.replace(/Response$/, '');\n if (candNoResp.includes(baseNoResp) || baseNoResp.includes(candNoResp)) return true;\n if (namedTypeWordsOverlap(baseClean, candClean)) return true;\n }\n }\n\n return false;\n },\n\n isSignatureEquivalent(\n baseline: import('../types.js').ApiMethod,\n candidate: import('../types.js').ApiMethod,\n _candidateSurface: ApiSurface,\n ): boolean {\n // Tolerate methods where the candidate uses a body dict (payload: dict[str, Any])\n // while the baseline unpacks the body into individual typed params.\n // The first N params that match by name and type are consumed, then the remaining\n // baseline params are tolerated if the candidate has a dict payload param.\n\n // Return types must be equivalent (use named type tolerance)\n if (baseline.returnType !== candidate.returnType) {\n const baseRet = baseline.returnType;\n const candRet = candidate.returnType;\n if (!(NAMED_TYPE_RE.test(baseRet) && NAMED_TYPE_RE.test(candRet))) return false;\n // Check named-type containment or word overlap\n if (!candRet.includes(baseRet) && !baseRet.includes(candRet)) {\n if (!namedTypeWordsOverlap(baseRet, candRet)) return false;\n }\n }\n\n // Check if candidate has a body dict param\n const bodyDictTypes = new Set(['dict[str, Any]', 'Dict[str, Any]', 'dict']);\n const candBodyIdx = candidate.params.findIndex(\n (p) => bodyDictTypes.has(p.type) && (p.name === 'payload' || p.name === 'body' || p.name === 'data'),\n );\n if (candBodyIdx < 0) return false;\n\n // All candidate params before the body dict must match baseline params by name and type\n for (let i = 0; i < candBodyIdx; i++) {\n if (i >= baseline.params.length) return false;\n if (baseline.params[i].name !== candidate.params[i].name) return false;\n if (baseline.params[i].type !== candidate.params[i].type) return false;\n }\n\n // Remaining baseline params after the matched prefix are tolerated as body fields\n return true;\n },\n\n // Consumers should configure modelBaseClasses for their framework (e.g., ['BaseModel'] for Pydantic)\n modelBaseClasses: [],\n exceptionBaseClasses: ['Exception', 'BaseException'],\n listResourcePatterns: [],\n};\n\n// ---------------------------------------------------------------------------\n// Extractor\n// ---------------------------------------------------------------------------\n\n/** Create a Python extractor with optional hint overrides. */\nexport function createPythonExtractor(hintOverrides?: Partial<LanguageHints>): Extractor {\n const mergedHints: LanguageHints = hintOverrides ? { ...pythonHints, ...hintOverrides } : pythonHints;\n\n return {\n language: 'python',\n hints: mergedHints,\n\n async extractSnapshot(sdkPath: string): Promise<CompatSnapshot> {\n const surface = await this.extract(sdkPath);\n return apiSurfaceToSnapshot(surface);\n },\n\n async extract(sdkPath: string): Promise<ApiSurface> {\n const sourceRoot = findPythonSourceRoot(sdkPath);\n if (!sourceRoot) {\n throw new ExtractorError(\n `No Python package found in ${sdkPath}`,\n `Ensure the --sdk-path argument points to a Python project root containing a package directory with __init__.py.`,\n );\n }\n\n const pyFiles = walkPythonFiles(sourceRoot);\n if (pyFiles.length === 0) {\n throw new ExtractorError(\n `No .py files found in ${sdkPath}`,\n `Ensure the project contains Python source files.`,\n );\n }\n\n const parsedFiles: ParsedPythonFile[] = [];\n for (const filePath of pyFiles) {\n const parsed = parsePythonFile(filePath, sdkPath);\n parsedFiles.push(parsed);\n }\n\n const { classes, interfaces, typeAliases, enums, exports } = buildSurface(parsedFiles, mergedHints);\n\n return {\n language: 'python',\n extractedFrom: sdkPath,\n extractedAt: new Date().toISOString(),\n classes,\n interfaces,\n typeAliases,\n enums,\n exports,\n };\n },\n };\n}\n\n/** Default Python extractor with generic language hints (no SDK-specific bases). */\nexport const pythonExtractor: Extractor = createPythonExtractor();\n","/**\n * Ruby entity extraction — tree-sitter-based parsing of classes, service modules,\n * and enum modules from Ruby source files.\n */\n\nimport Parser from 'tree-sitter';\nimport Ruby from 'tree-sitter-ruby';\nimport type { SyntaxNode } from 'tree-sitter';\nimport type { ApiClass, ApiEnum, ApiMethod, ApiParam, ApiProperty } from '../types.js';\nimport { safeParse as safeParseWith } from '../../utils/tree-sitter.js';\nimport { sortRecord } from './shared.js';\n\n// ---------------------------------------------------------------------------\n// Shared parser instance\n// ---------------------------------------------------------------------------\n\nconst rubyParser = new Parser();\nrubyParser.setLanguage(Ruby);\n\nfunction safeParse(source: string): Parser.Tree {\n return safeParseWith(rubyParser, source);\n}\n\n// ---------------------------------------------------------------------------\n// Public API — called from ruby.ts\n// ---------------------------------------------------------------------------\n\n/** Parse a Ruby source string and return all class declarations (excluding service modules). */\nexport function extractClasses(source: string): ApiClass[] {\n const tree = safeParse(source);\n const classes: ApiClass[] = [];\n\n // Collect line ranges of service modules so we can skip nested classes\n const serviceModuleNodes = findServiceModulesFromTree(tree.rootNode);\n const serviceRanges = serviceModuleNodes.map((n) => [n.startPosition.row, n.endPosition.row] as [number, number]);\n\n for (const node of tree.rootNode.descendantsOfType('class')) {\n // Skip singleton_class nodes (class << self)\n if (node.type !== 'class') continue;\n\n // Skip classes inside service modules\n if (isInsideRanges(node.startPosition.row, serviceRanges)) continue;\n\n // Skip if this class contains a singleton_class (class << self) — those are service modules\n if (node.descendantsOfType('singleton_class').length > 0) continue;\n\n const nameNode = node.childForFieldName('name');\n if (!nameNode) continue;\n const className = nameNode.text;\n\n const bodyNode = node.childForFieldName('body');\n\n const methods: Record<string, ApiMethod[]> = {};\n const properties: Record<string, ApiProperty> = {};\n const constructorParams: ApiParam[] = [];\n\n // Only extract body content if body exists (single-line classes like `class Foo < Bar; end` may not have a body)\n if (bodyNode) {\n // Extract attr_accessor/attr_reader\n extractAttributes(bodyNode, properties);\n\n // Extract methods (respecting visibility)\n const extractedMethods = extractMethodsFromBody(bodyNode);\n for (const method of extractedMethods) {\n if (method.name === 'initialize') {\n constructorParams.push(...method.params);\n } else {\n if (!methods[method.name]) methods[method.name] = [];\n methods[method.name].push(method);\n }\n }\n }\n\n classes.push({\n name: className,\n methods: sortRecord(methods),\n properties: sortRecord(properties),\n constructorParams,\n });\n }\n\n return classes;\n}\n\n/** Extract service modules (modules with `class << self` at immediate depth). */\nexport function extractServiceModules(source: string): ApiClass[] {\n const tree = safeParse(source);\n const services: ApiClass[] = [];\n\n for (const moduleNode of findServiceModulesFromTree(tree.rootNode)) {\n const nameNode = moduleNode.childForFieldName('name');\n if (!nameNode) continue;\n const moduleName = nameNode.text;\n\n const bodyNode = moduleNode.childForFieldName('body');\n if (!bodyNode) continue;\n\n // Find the singleton_class (class << self) at immediate depth\n const singletonNode = findImmediateSingletonClass(bodyNode);\n if (!singletonNode) continue;\n\n const singletonBody = singletonNode.childForFieldName('body');\n if (!singletonBody) continue;\n\n const methods: Record<string, ApiMethod[]> = {};\n const properties: Record<string, ApiProperty> = {};\n\n // Extract methods from the singleton class body\n const extractedMethods = extractMethodsFromBody(singletonBody);\n for (const method of extractedMethods) {\n if (!methods[method.name]) methods[method.name] = [];\n methods[method.name].push(method);\n }\n\n // Extract constants as properties\n extractConstantsAsProperties(singletonBody, properties);\n\n if (Object.keys(methods).length > 0 || Object.keys(properties).length > 0) {\n services.push({\n name: moduleName,\n methods: sortRecord(methods),\n properties: sortRecord(properties),\n constructorParams: [],\n });\n }\n }\n\n return services;\n}\n\n/** Extract enum-like modules (modules with string/number constants, no class << self). */\nexport function extractEnumModules(source: string): ApiEnum[] {\n const tree = safeParse(source);\n const enums: ApiEnum[] = [];\n\n const serviceModuleNodes = findServiceModulesFromTree(tree.rootNode);\n const serviceRanges = serviceModuleNodes.map((n) => [n.startPosition.row, n.endPosition.row] as [number, number]);\n\n for (const node of tree.rootNode.descendantsOfType('module')) {\n // Skip modules inside service modules\n if (isInsideRanges(node.startPosition.row, serviceRanges)) continue;\n\n // Skip modules that have singleton_class (service modules)\n if (node.descendantsOfType('singleton_class').length > 0) continue;\n\n const nameNode = node.childForFieldName('name');\n if (!nameNode) continue;\n\n const bodyNode = node.childForFieldName('body');\n if (!bodyNode) continue;\n\n const constants = extractEnumConstants(bodyNode);\n if (Object.keys(constants).length < 2) continue;\n\n enums.push({\n name: nameNode.text,\n members: sortRecord(constants),\n });\n }\n\n return enums;\n}\n\n/** Extract autoload declarations to build the export map. */\nexport function extractAutoloads(source: string): string[] {\n const tree = safeParse(source);\n const names: string[] = [];\n\n for (const callNode of tree.rootNode.descendantsOfType('call')) {\n const methodNode = callNode.childForFieldName('method');\n if (!methodNode || methodNode.text !== 'autoload') continue;\n\n const argsNode = callNode.childForFieldName('arguments');\n if (!argsNode) continue;\n\n // First argument is the symbol name\n const firstArg = argsNode.namedChildren[0];\n if (firstArg && (firstArg.type === 'simple_symbol' || firstArg.type === 'symbol')) {\n names.push(firstArg.text.replace(/^:/, ''));\n }\n }\n\n return names;\n}\n\n// ---------------------------------------------------------------------------\n// Internal: finding service modules\n// ---------------------------------------------------------------------------\n\n/** Find module nodes that have `class << self` at their immediate body level. */\nfunction findServiceModulesFromTree(rootNode: SyntaxNode): SyntaxNode[] {\n const result: SyntaxNode[] = [];\n\n for (const moduleNode of rootNode.descendantsOfType('module')) {\n const bodyNode = moduleNode.childForFieldName('body');\n if (!bodyNode) continue;\n\n if (findImmediateSingletonClass(bodyNode)) {\n result.push(moduleNode);\n }\n }\n\n return result;\n}\n\n/** Find a singleton_class (class << self) at the immediate body level (not nested). */\nfunction findImmediateSingletonClass(bodyNode: SyntaxNode): SyntaxNode | null {\n for (const child of bodyNode.namedChildren) {\n if (child.type === 'singleton_class') return child;\n }\n return null;\n}\n\n// ---------------------------------------------------------------------------\n// Internal: method extraction with visibility tracking\n// ---------------------------------------------------------------------------\n\n/** Extract methods from a body_statement, respecting private/protected/public markers. */\nfunction extractMethodsFromBody(bodyNode: SyntaxNode): ApiMethod[] {\n const methods: ApiMethod[] = [];\n let isPrivate = false;\n\n for (const child of bodyNode.namedChildren) {\n // Track visibility markers: bare `private`, `public`, `protected` calls\n if (child.type === 'identifier') {\n if (child.text === 'private') {\n isPrivate = true;\n continue;\n }\n if (child.text === 'public') {\n isPrivate = false;\n continue;\n }\n if (child.text === 'protected') {\n isPrivate = true;\n continue;\n }\n }\n\n if (isPrivate) continue;\n\n if (child.type === 'method') {\n const nameNode = child.childForFieldName('name');\n if (!nameNode) continue;\n\n const params = extractMethodParams(child);\n methods.push({\n name: nameNode.text,\n params,\n returnType: 'Object',\n async: false,\n });\n }\n }\n\n return methods;\n}\n\n/** Extract parameters from a method node. */\nfunction extractMethodParams(methodNode: SyntaxNode): ApiParam[] {\n const paramsNode = methodNode.childForFieldName('parameters');\n if (!paramsNode) return [];\n\n const params: ApiParam[] = [];\n\n for (const paramNode of paramsNode.namedChildren) {\n switch (paramNode.type) {\n case 'identifier': {\n // Plain positional argument\n params.push({ name: paramNode.text, type: 'Object', optional: false, passingStyle: 'positional' as const });\n break;\n }\n case 'optional_parameter': {\n // Positional argument with default: name = value\n const nameNode = paramNode.childForFieldName('name');\n if (nameNode) {\n params.push({ name: nameNode.text, type: 'Object', optional: true, passingStyle: 'positional' as const });\n }\n break;\n }\n case 'keyword_parameter': {\n // Keyword argument: name: or name: default\n const nameNode = paramNode.childForFieldName('name');\n if (nameNode) {\n const valueNode = paramNode.childForFieldName('value');\n params.push({\n name: nameNode.text,\n type: 'Object',\n optional: valueNode !== null,\n passingStyle: 'keyword' as const,\n });\n }\n break;\n }\n case 'splat_parameter': {\n // *args — variadic positional\n const nameNode = paramNode.childForFieldName('name');\n params.push({\n name: nameNode ? `*${nameNode.text}` : '*args',\n type: 'Object',\n optional: true,\n passingStyle: 'positional' as const,\n });\n break;\n }\n case 'hash_splat_parameter': {\n // **kwargs — variadic keyword\n const nameNode = paramNode.childForFieldName('name');\n params.push({\n name: nameNode ? `**${nameNode.text}` : '**kwargs',\n type: 'Object',\n optional: true,\n passingStyle: 'keyword' as const,\n });\n break;\n }\n case 'block_parameter': {\n // &block — block argument\n const nameNode = paramNode.childForFieldName('name');\n params.push({\n name: nameNode ? `&${nameNode.text}` : '&block',\n type: 'Object',\n optional: true,\n passingStyle: 'positional' as const,\n });\n break;\n }\n default:\n break;\n }\n }\n\n return params;\n}\n\n// ---------------------------------------------------------------------------\n// Internal: attribute extraction\n// ---------------------------------------------------------------------------\n\n/** Extract attr_accessor/attr_reader calls into properties. */\nfunction extractAttributes(bodyNode: SyntaxNode, properties: Record<string, ApiProperty>): void {\n for (const callNode of bodyNode.descendantsOfType('call')) {\n const methodNode = callNode.childForFieldName('method');\n if (!methodNode) continue;\n const methodName = methodNode.text;\n if (methodName !== 'attr_accessor' && methodName !== 'attr_reader') continue;\n\n const isReadonly = methodName === 'attr_reader';\n\n const argsNode = callNode.childForFieldName('arguments');\n if (!argsNode) continue;\n\n for (const argNode of argsNode.namedChildren) {\n if (argNode.type === 'simple_symbol' || argNode.type === 'symbol') {\n const name = argNode.text.replace(/^:/, '');\n properties[name] = { name, type: 'Object', readonly: isReadonly };\n }\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Internal: constant extraction\n// ---------------------------------------------------------------------------\n\n/** Extract UPPER_CASE constants from a body as readonly properties. */\nfunction extractConstantsAsProperties(bodyNode: SyntaxNode, properties: Record<string, ApiProperty>): void {\n for (const child of bodyNode.namedChildren) {\n if (child.type !== 'assignment') continue;\n const leftNode = child.childForFieldName('left');\n if (!leftNode || leftNode.type !== 'constant') continue;\n const name = leftNode.text;\n if (!/^[A-Z][A-Z_0-9]*$/.test(name)) continue;\n properties[name] = { name, type: 'Object', readonly: true };\n }\n}\n\n/** Extract enum-style constants (ConstantName = 'value') from a module body. */\nfunction extractEnumConstants(bodyNode: SyntaxNode): Record<string, string | number> {\n const constants: Record<string, string | number> = {};\n\n for (const child of bodyNode.namedChildren) {\n if (child.type !== 'assignment') continue;\n const leftNode = child.childForFieldName('left');\n if (!leftNode || leftNode.type !== 'constant') continue;\n const name = leftNode.text;\n if (name === 'ALL') continue; // Skip aggregate constants\n\n const rightNode = child.childForFieldName('right');\n if (!rightNode) continue;\n\n const value = extractLiteralValue(rightNode);\n if (value !== undefined) {\n constants[name] = value;\n }\n }\n\n return constants;\n}\n\n/** Extract a literal string or number value from a tree-sitter node. */\nfunction extractLiteralValue(node: SyntaxNode): string | number | undefined {\n if (node.type === 'string' || node.type === 'string_content') {\n // String: strip surrounding quotes\n const text = node.text;\n if ((text.startsWith(\"'\") && text.endsWith(\"'\")) || (text.startsWith('\"') && text.endsWith('\"'))) {\n return text.slice(1, -1);\n }\n // For string_content (inside a string node), return as-is\n return text;\n }\n if (node.type === 'integer') {\n return Number(node.text);\n }\n if (node.type === 'float') {\n return Number(node.text);\n }\n // For strings, tree-sitter wraps in a `string` node with `string_content` children\n if (node.type === 'string') {\n const contentNode = node.namedChildren.find((c) => c.type === 'string_content');\n if (contentNode) return contentNode.text;\n }\n return undefined;\n}\n\n// ---------------------------------------------------------------------------\n// Internal: tree traversal helpers\n// ---------------------------------------------------------------------------\n\n/** Check if a line number falls inside any of the given ranges. */\nfunction isInsideRanges(line: number, ranges: Array<[number, number]>): boolean {\n for (const [start, end] of ranges) {\n if (line > start && line < end) return true;\n }\n return false;\n}\n\nexport { sortRecord } from './shared.js';\n","/**\n * Ruby API surface extractor.\n *\n * Walks `.rb` files under `lib/`, parses class/module declarations,\n * and builds an `ApiSurface` with classes, service modules, and enum modules.\n *\n * Parser: `ruby-parser.ts` — tree-sitter-based class/module/enum extraction\n */\n\nimport { readFileSync, readdirSync, statSync } from 'node:fs';\nimport { resolve, relative, join } from 'node:path';\nimport { ExtractorError } from '../../errors.js';\nimport type { ApiSurface, Extractor, LanguageHints } from '../types.js';\nimport type { CompatSnapshot } from '../ir.js';\nimport { apiSurfaceToSnapshot } from '../ir.js';\nimport { defaultIsNullableOnlyDifference } from '../language-hints.js';\nimport {\n extractClasses,\n extractServiceModules,\n extractEnumModules,\n extractAutoloads,\n sortRecord,\n} from './ruby-parser.js';\n\n// ---------------------------------------------------------------------------\n// Language hints\n// ---------------------------------------------------------------------------\n\nconst rubyHints: LanguageHints = {\n stripNullable(type: string): string | null {\n const match = type.match(/^T\\.nilable\\((.+)\\)$/);\n return match ? match[1] : null;\n },\n isNullableOnlyDifference(a: string, b: string): boolean {\n return defaultIsNullableOnlyDifference(this, a, b);\n },\n isUnionReorder(_a: string, _b: string): boolean {\n return false;\n },\n isGenericTypeParam(type: string): boolean {\n return type === 'T.untyped';\n },\n isExtractionArtifact(type: string): boolean {\n return type === 'T.untyped' || type === 'BasicObject';\n },\n tolerateCategoryMismatch: false,\n extractReturnTypeName(returnType: string): string | null {\n return returnType || null;\n },\n extractParamTypeName(paramType: string): string | null {\n if (['String', 'Integer', 'Float', 'Boolean', 'NilClass'].includes(paramType)) return null;\n return paramType;\n },\n propertyMatchesClass(propertyName: string, className: string): boolean {\n return propertyName.replace(/_/g, '').toLowerCase() === className.toLowerCase();\n },\n derivedModelNames(_modelName: string): string[] {\n return [];\n },\n};\n\n// ---------------------------------------------------------------------------\n// File collection\n// ---------------------------------------------------------------------------\n\n/** Recursively collect all .rb files under a directory. */\nfunction collectRbFiles(dir: string): string[] {\n const result: string[] = [];\n const entries = readdirSync(dir);\n for (const entry of entries.sort()) {\n const full = join(dir, entry);\n const stat = statSync(full);\n if (stat.isDirectory()) {\n result.push(...collectRbFiles(full));\n } else if (entry.endsWith('.rb')) {\n result.push(full);\n }\n }\n return result;\n}\n\n// ---------------------------------------------------------------------------\n// Extractor\n// ---------------------------------------------------------------------------\n\nexport const rubyExtractor: Extractor = {\n language: 'ruby',\n hints: rubyHints,\n\n async extractSnapshot(sdkPath: string): Promise<CompatSnapshot> {\n const surface = await this.extract(sdkPath);\n return apiSurfaceToSnapshot(surface);\n },\n\n async extract(sdkPath: string): Promise<ApiSurface> {\n const libPath = resolve(sdkPath, 'lib');\n try {\n statSync(libPath);\n } catch {\n throw new ExtractorError(\n `No lib/ directory found in ${sdkPath}`,\n `Verify the --sdk-path argument points to a Ruby project root containing a lib/ directory.`,\n );\n }\n\n const rbFiles = collectRbFiles(libPath);\n if (rbFiles.length === 0) {\n throw new ExtractorError(\n `No .rb files found in ${libPath}`,\n `Ensure the lib/ directory contains Ruby source files.`,\n );\n }\n\n const classes: Record<string, import('../types.js').ApiClass> = {};\n const enums: Record<string, import('../types.js').ApiEnum> = {};\n const exports: Record<string, string[]> = {};\n\n for (const absPath of rbFiles) {\n const relPath = relative(sdkPath, absPath);\n const source = readFileSync(absPath, 'utf-8');\n\n const fileExports: string[] = [];\n\n // Extract classes (model classes and struct classes)\n const extractedClasses = extractClasses(source);\n for (const cls of extractedClasses) {\n classes[cls.name] = { ...cls, sourceFile: relPath };\n fileExports.push(cls.name);\n }\n\n // Extract service modules (modules with class << self)\n const extractedServices = extractServiceModules(source);\n for (const svc of extractedServices) {\n classes[svc.name] = { ...svc, sourceFile: relPath };\n fileExports.push(svc.name);\n }\n\n // Extract enum-like modules (modules with constants)\n const extractedEnums = extractEnumModules(source);\n for (const en of extractedEnums) {\n enums[en.name] = { ...en, sourceFile: relPath };\n fileExports.push(en.name);\n }\n\n // Extract autoload declarations as exports\n const autoloadNames = extractAutoloads(source);\n if (autoloadNames.length > 0) {\n fileExports.push(...autoloadNames);\n }\n\n if (fileExports.length > 0) {\n exports[relPath] = [...new Set(fileExports)].sort();\n }\n }\n\n return {\n language: 'ruby',\n extractedFrom: sdkPath,\n extractedAt: new Date().toISOString(),\n classes: sortRecord(classes),\n interfaces: {},\n typeAliases: {},\n enums: sortRecord(enums),\n exports: sortRecord(exports),\n };\n },\n};\n","/**\n * Go source parser — tree-sitter-based extraction of structs, functions, types,\n * and const blocks from Go source files.\n */\n\nimport { readFileSync, readdirSync, statSync } from 'node:fs';\nimport { join, relative } from 'node:path';\nimport Parser from 'tree-sitter';\nimport Go from 'tree-sitter-go';\nimport type { SyntaxNode } from 'tree-sitter';\nimport { safeParse } from '../../utils/tree-sitter.js';\n\n// ---------------------------------------------------------------------------\n// Internal types\n// ---------------------------------------------------------------------------\n\nexport interface GoStructField {\n name: string;\n type: string;\n jsonTag?: string;\n optional: boolean;\n}\n\nexport interface GoStruct {\n name: string;\n fields: GoStructField[];\n sourceFile: string;\n packageName: string;\n}\n\nexport interface GoFunc {\n receiverType: string | null;\n name: string;\n params: { name: string; type: string }[];\n returnTypes: string[];\n sourceFile: string;\n packageName: string;\n}\n\nexport interface GoConst {\n name: string;\n typeName: string;\n value: string;\n sourceFile: string;\n packageName: string;\n}\n\nexport interface GoTypeDecl {\n name: string;\n underlyingType: string;\n isAlias: boolean;\n sourceFile: string;\n packageName: string;\n}\n\n// ---------------------------------------------------------------------------\n// Shared parser instance\n// ---------------------------------------------------------------------------\n\nconst goParser = new Parser();\ngoParser.setLanguage(Go);\n\n// ---------------------------------------------------------------------------\n// File walker\n// ---------------------------------------------------------------------------\n\nexport function walkGoFiles(dir: string): string[] {\n const results: string[] = [];\n let entries: string[];\n try {\n entries = readdirSync(dir);\n } catch {\n return results;\n }\n for (const entry of entries) {\n const fullPath = join(dir, entry);\n let stat;\n try {\n stat = statSync(fullPath);\n } catch {\n continue;\n }\n if (stat.isDirectory()) {\n if (entry.startsWith('.') || entry === 'vendor' || entry === 'testdata' || entry === 'internal') continue;\n results.push(...walkGoFiles(fullPath));\n } else if (entry.endsWith('.go') && !entry.endsWith('_test.go')) {\n results.push(fullPath);\n }\n }\n return results.sort();\n}\n\n// ---------------------------------------------------------------------------\n// Node helpers\n// ---------------------------------------------------------------------------\n\n/** Get the text of a child node by field name, or null. */\nfunction fieldText(node: SyntaxNode, field: string): string | null {\n const child = node.childForFieldName(field);\n return child ? child.text : null;\n}\n\n/** Extract the JSON field name from a struct tag. */\nfunction extractJsonTag(tagText: string): { name: string; omitempty: boolean } | null {\n const match = tagText.match(/json:\"([^\"]*)\"/);\n if (!match) return null;\n const parts = match[1].split(',');\n const name = parts[0].trim();\n const omitempty = parts.includes('omitempty');\n if (name === '-') return null;\n return { name, omitempty };\n}\n\n/** Render a type node back to its Go source representation. */\nfunction typeNodeText(node: SyntaxNode): string {\n return node.text;\n}\n\n// ---------------------------------------------------------------------------\n// Struct extraction\n// ---------------------------------------------------------------------------\n\nfunction parseStructFields(structNode: SyntaxNode): GoStructField[] {\n const fields: GoStructField[] = [];\n const fieldList = structNode.namedChildren.find((c) => c.type === 'field_declaration_list');\n if (!fieldList) return fields;\n\n for (const fieldDecl of fieldList.namedChildren) {\n if (fieldDecl.type !== 'field_declaration') continue;\n\n // Get all field identifiers (there can be multiple: `A, B int`)\n const nameNodes = fieldDecl.namedChildren.filter((c) => c.type === 'field_identifier');\n if (nameNodes.length === 0) {\n // Embedded field (struct composition) — extract the type name as the field name.\n // e.g., `type Foo struct { Bar }` → field named \"Bar\" of type \"Bar\"\n const typeNode = fieldDecl.namedChildren.find(\n (c) => c.type !== 'raw_string_literal' && c.type !== 'interpreted_string_literal',\n );\n if (typeNode) {\n const typeName = typeNode.text.replace(/^\\*/, ''); // strip pointer\n if (/^[A-Z]/.test(typeName)) {\n fields.push({\n name: typeName,\n type: typeNode.text,\n optional: false,\n });\n }\n }\n continue;\n }\n\n // The type node: find the first named child that isn't a field_identifier and isn't a tag\n const typeNode = fieldDecl.namedChildren.find(\n (c) =>\n c.type !== 'field_identifier' && c.type !== 'raw_string_literal' && c.type !== 'interpreted_string_literal',\n );\n if (!typeNode) continue;\n\n // Only export fields that start with uppercase\n const fieldType = typeNodeText(typeNode);\n\n // Tag is a raw_string_literal child\n const tagNode = fieldDecl.namedChildren.find(\n (c) => c.type === 'raw_string_literal' || c.type === 'interpreted_string_literal',\n );\n const jsonTag = tagNode ? extractJsonTag(tagNode.text) : null;\n\n for (const nameNode of nameNodes) {\n const name = nameNode.text;\n if (!/^[A-Z]/.test(name)) continue; // skip unexported\n fields.push({\n name,\n type: fieldType,\n jsonTag: jsonTag?.name || undefined,\n optional: jsonTag?.omitempty || false,\n });\n }\n }\n return fields;\n}\n\n// ---------------------------------------------------------------------------\n// Type declarations\n// ---------------------------------------------------------------------------\n\nexport function parseTypeDecls(\n tree: Parser.Tree,\n sourceFile: string,\n packageName: string,\n): { structs: GoStruct[]; types: GoTypeDecl[] } {\n const structs: GoStruct[] = [];\n const types: GoTypeDecl[] = [];\n\n for (const node of tree.rootNode.namedChildren) {\n if (node.type !== 'type_declaration') continue;\n\n for (const spec of node.namedChildren) {\n const name = fieldText(spec, 'name');\n if (!name || !/^[A-Z]/.test(name)) continue;\n\n if (spec.type === 'type_spec') {\n const typeNode = spec.childForFieldName('type');\n if (!typeNode) continue;\n\n if (typeNode.type === 'struct_type') {\n structs.push({ name, fields: parseStructFields(typeNode), sourceFile, packageName });\n } else if (typeNode.type !== 'interface_type') {\n types.push({ name, underlyingType: typeNodeText(typeNode), isAlias: false, sourceFile, packageName });\n }\n } else if (spec.type === 'type_alias') {\n const typeNode = spec.childForFieldName('type');\n if (typeNode) {\n types.push({ name, underlyingType: typeNodeText(typeNode), isAlias: true, sourceFile, packageName });\n }\n }\n }\n }\n\n return { structs, types };\n}\n\n// ---------------------------------------------------------------------------\n// Const blocks\n// ---------------------------------------------------------------------------\n\n/** Strip surrounding quotes from a string value. */\nfunction stripQuotes(value: string): string {\n if ((value.startsWith('\"') && value.endsWith('\"')) || (value.startsWith(\"'\") && value.endsWith(\"'\"))) {\n return value.slice(1, -1);\n }\n const convMatch = value.match(/^\\w+(?:\\.\\w+)?\\(\"([^\"]*)\"\\)$/);\n if (convMatch) return convMatch[1];\n return value;\n}\n\nexport function parseConstBlocks(tree: Parser.Tree, sourceFile: string, packageName: string): GoConst[] {\n const consts: GoConst[] = [];\n\n for (const node of tree.rootNode.namedChildren) {\n if (node.type !== 'const_declaration') continue;\n\n let lastType = '';\n\n for (const spec of node.namedChildren) {\n if (spec.type !== 'const_spec') continue;\n\n const nameNodes = spec.namedChildren.filter((c) => c.type === 'identifier');\n if (nameNodes.length === 0) continue;\n const constName = nameNodes[0].text;\n if (!/^[A-Z]/.test(constName)) continue;\n\n // Type field (optional)\n const typeNode = spec.childForFieldName('type');\n if (typeNode) {\n lastType = typeNode.text;\n }\n\n // Value field\n const valueNode = spec.childForFieldName('value');\n if (valueNode) {\n // expression_list may contain a single value or a call expression\n const valueText = valueNode.text.trim();\n const strippedValue = stripQuotes(valueText);\n\n // Check for type conversion: TypeName(\"value\") or TypeName(value)\n if (!typeNode) {\n const convMatch = valueText.match(/^([A-Z]\\w*)\\((.+)\\)$/);\n if (convMatch) {\n consts.push({\n name: constName,\n typeName: convMatch[1],\n value: stripQuotes(convMatch[2].trim()),\n sourceFile,\n packageName,\n });\n continue;\n }\n }\n\n if (lastType) {\n consts.push({ name: constName, typeName: lastType, value: strippedValue, sourceFile, packageName });\n }\n } else if (lastType) {\n // iota continuation — no value node\n consts.push({ name: constName, typeName: lastType, value: constName, sourceFile, packageName });\n }\n }\n }\n\n return consts;\n}\n\n// ---------------------------------------------------------------------------\n// Function & method declarations\n// ---------------------------------------------------------------------------\n\nfunction parseParamList(paramListNode: SyntaxNode | null): { name: string; type: string }[] {\n if (!paramListNode) return [];\n const params: { name: string; type: string }[] = [];\n\n let unnamedIndex = 0;\n for (const paramDecl of paramListNode.namedChildren) {\n if (paramDecl.type !== 'parameter_declaration' && paramDecl.type !== 'variadic_parameter_declaration') continue;\n\n const nameNode = paramDecl.namedChildren.find((c) => c.type === 'identifier');\n const typeNode = paramDecl.childForFieldName('type');\n if (!typeNode) continue;\n\n // When Go omits the parameter name (e.g., `func Foo(string, int)`),\n // synthesize a positional name so signature matching doesn't break.\n const name = nameNode ? nameNode.text : `_arg${unnamedIndex++}`;\n params.push({\n name,\n type: typeNodeText(typeNode),\n });\n }\n return params;\n}\n\nfunction parseReturnTypes(resultNode: SyntaxNode | null): string[] {\n if (!resultNode) return [];\n\n if (resultNode.type === 'parameter_list') {\n // Multiple return values: (Type1, Type2)\n return resultNode.namedChildren\n .filter((c) => c.type === 'parameter_declaration')\n .map((c) => {\n const t = c.childForFieldName('type');\n return t ? typeNodeText(t) : c.text;\n });\n }\n\n // Single return value\n return [typeNodeText(resultNode)];\n}\n\nexport function parseFunctions(tree: Parser.Tree, sourceFile: string, packageName: string): GoFunc[] {\n const funcs: GoFunc[] = [];\n\n for (const node of tree.rootNode.namedChildren) {\n if (node.type === 'function_declaration') {\n const name = fieldText(node, 'name');\n if (!name || !/^[A-Z]/.test(name)) continue;\n\n funcs.push({\n receiverType: null,\n name,\n params: parseParamList(node.childForFieldName('parameters')),\n returnTypes: parseReturnTypes(node.childForFieldName('result')),\n sourceFile,\n packageName,\n });\n } else if (node.type === 'method_declaration') {\n const name = fieldText(node, 'name');\n if (!name || !/^[A-Z]/.test(name)) continue;\n\n // Extract receiver type\n const receiverNode = node.childForFieldName('receiver');\n let receiverType: string | null = null;\n if (receiverNode) {\n const paramDecl = receiverNode.namedChildren.find((c) => c.type === 'parameter_declaration');\n if (paramDecl) {\n const typeNode = paramDecl.childForFieldName('type');\n if (typeNode) {\n // Strip pointer: *Foo → Foo\n receiverType = typeNode.text.replace(/^\\*/, '');\n }\n }\n }\n\n funcs.push({\n receiverType,\n name,\n params: parseParamList(node.childForFieldName('parameters')),\n returnTypes: parseReturnTypes(node.childForFieldName('result')),\n sourceFile,\n packageName,\n });\n }\n }\n return funcs;\n}\n\n// ---------------------------------------------------------------------------\n// Package name extraction\n// ---------------------------------------------------------------------------\n\nexport function extractPackageName(tree: Parser.Tree): string {\n const pkgClause = tree.rootNode.namedChildren.find((c) => c.type === 'package_clause');\n if (!pkgClause) return 'unknown';\n const nameNode = pkgClause.namedChildren.find((c) => c.type === 'package_identifier');\n return nameNode ? nameNode.text : 'unknown';\n}\n\n// ---------------------------------------------------------------------------\n// Full file parser\n// ---------------------------------------------------------------------------\n\nexport interface ParsedGoFile {\n structs: GoStruct[];\n types: GoTypeDecl[];\n funcs: GoFunc[];\n consts: GoConst[];\n}\n\n/** Parse a single Go source file and return all extracted symbols. */\nexport function parseGoFile(filePath: string, sdkPath: string): ParsedGoFile {\n const source = readFileSync(filePath, 'utf-8');\n const relPath = relative(sdkPath, filePath);\n const tree = safeParse(goParser, source);\n const packageName = extractPackageName(tree);\n\n const { structs, types } = parseTypeDecls(tree, relPath, packageName);\n const funcs = parseFunctions(tree, relPath, packageName);\n const consts = parseConstBlocks(tree, relPath, packageName);\n\n return { structs, types, funcs, consts };\n}\n","/**\n * Go surface builder — transforms parsed Go symbols into an ApiSurface\n * with proper package-qualified names for collision avoidance.\n */\n\nimport { basename, dirname } from 'node:path';\nimport type {\n ApiClass,\n ApiMethod,\n ApiParam,\n ApiProperty,\n ApiInterface,\n ApiField,\n ApiTypeAlias,\n ApiEnum,\n} from '../types.js';\nimport type { GoStruct, GoTypeDecl, GoFunc, GoConst } from './go-parser.js';\nimport { sortRecord, ExportCollector } from './shared.js';\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction goTypeToString(t: string): string {\n return t.replace(/json\\.RawMessage/g, '[]byte').replace(/\\bcontext\\.Context\\b/g, 'context.Context');\n}\n\nfunction buildReturnType(returnTypes: string[]): string {\n const nonError = returnTypes.filter((r) => r !== 'error');\n if (nonError.length === 0) return 'error';\n if (nonError.length === 1) return goTypeToString(nonError[0]);\n return `(${nonError.map(goTypeToString).join(', ')})`;\n}\n\n/** Get the package directory name from a source file relative path. */\nfunction getPackageDirName(relPath: string): string {\n const dir = dirname(relPath);\n return basename(dir) || 'root';\n}\n\n// ---------------------------------------------------------------------------\n// Qualified name resolution\n// ---------------------------------------------------------------------------\n\n/**\n * When multiple packages define the same exported symbol, qualify with the\n * package directory name (e.g., \"organizations.Client\", \"sso.Client\").\n * Unique symbols keep their bare name.\n */\nfunction buildQualifiedNames(\n items: Array<{ name: string; packageName: string; sourceFile: string }>,\n): Map<string, string> {\n const nameToPackages = new Map<string, Set<string>>();\n for (const item of items) {\n if (!nameToPackages.has(item.name)) nameToPackages.set(item.name, new Set());\n nameToPackages.get(item.name)!.add(item.packageName);\n }\n\n const result = new Map<string, string>();\n for (const item of items) {\n const key = `${item.sourceFile}:${item.name}`;\n const packages = nameToPackages.get(item.name)!;\n result.set(key, packages.size > 1 ? `${getPackageDirName(item.sourceFile)}.${item.name}` : item.name);\n }\n return result;\n}\n\n// ---------------------------------------------------------------------------\n// Surface builder\n// ---------------------------------------------------------------------------\n\nexport function buildSurface(\n allStructs: GoStruct[],\n allTypes: GoTypeDecl[],\n allFuncs: GoFunc[],\n allConsts: GoConst[],\n): {\n classes: Record<string, ApiClass>;\n interfaces: Record<string, ApiInterface>;\n typeAliases: Record<string, ApiTypeAlias>;\n enums: Record<string, ApiEnum>;\n exports: Record<string, string[]>;\n} {\n const classes: Record<string, ApiClass> = {};\n const interfaces: Record<string, ApiInterface> = {};\n const typeAliases: Record<string, ApiTypeAlias> = {};\n const enums: Record<string, ApiEnum> = {};\n\n // Group consts by (packageName, typeName)\n const constsByPkgAndType = new Map<string, GoConst[]>();\n for (const c of allConsts) {\n const key = `${c.packageName}:${c.typeName}`;\n if (!constsByPkgAndType.has(key)) constsByPkgAndType.set(key, []);\n constsByPkgAndType.get(key)!.push(c);\n }\n\n // Group methods by (packageName, receiverType)\n const methodsByPkgAndReceiver = new Map<string, GoFunc[]>();\n const packageFuncs: GoFunc[] = [];\n for (const fn of allFuncs) {\n if (fn.receiverType) {\n const key = `${fn.packageName}:${fn.receiverType}`;\n if (!methodsByPkgAndReceiver.has(key)) methodsByPkgAndReceiver.set(key, []);\n methodsByPkgAndReceiver.get(key)!.push(fn);\n } else {\n packageFuncs.push(fn);\n }\n }\n\n // Build qualified names\n const allSymbols: Array<{ name: string; packageName: string; sourceFile: string }> = [];\n for (const s of allStructs) allSymbols.push({ name: s.name, packageName: s.packageName, sourceFile: s.sourceFile });\n for (const t of allTypes) allSymbols.push({ name: t.name, packageName: t.packageName, sourceFile: t.sourceFile });\n const qualifiedNames = buildQualifiedNames(allSymbols);\n\n // Process type declarations\n for (const typeDecl of allTypes) {\n const qName = qualifiedNames.get(`${typeDecl.sourceFile}:${typeDecl.name}`) || typeDecl.name;\n const typeConsts = constsByPkgAndType.get(`${typeDecl.packageName}:${typeDecl.name}`);\n\n if (typeDecl.isAlias) {\n typeAliases[qName] = {\n name: qName,\n sourceFile: typeDecl.sourceFile,\n value: goTypeToString(typeDecl.underlyingType),\n };\n } else if (typeConsts && typeConsts.length > 0) {\n const members: Record<string, string | number> = {};\n for (const c of typeConsts) {\n // Strip the type name prefix from enum constant names to produce\n // consistent short member keys (e.g., \"AuthenticationFactorTypeGenericOtp\"\n // → \"GenericOtp\"). This matches Go SDK conventions where the type prefix\n // is an implementation detail, not part of the public API contract.\n const memberKey = c.name.startsWith(typeDecl.name) ? c.name.slice(typeDecl.name.length) || c.name : c.name;\n members[memberKey] = c.value;\n }\n enums[qName] = { name: qName, sourceFile: typeDecl.sourceFile, members: sortRecord(members) };\n } else {\n typeAliases[qName] = {\n name: qName,\n sourceFile: typeDecl.sourceFile,\n value: goTypeToString(typeDecl.underlyingType),\n };\n }\n }\n\n // Process structs\n for (const s of allStructs) {\n const qName = qualifiedNames.get(`${s.sourceFile}:${s.name}`) || s.name;\n const methods = methodsByPkgAndReceiver.get(`${s.packageName}:${s.name}`);\n\n if (methods && methods.length > 0) {\n const apiMethods: Record<string, ApiMethod[]> = {};\n const properties: Record<string, ApiProperty> = {};\n\n for (const field of s.fields) {\n properties[field.name] = { name: field.name, type: goTypeToString(field.type), readonly: false };\n }\n\n for (const fn of methods) {\n const params: ApiParam[] = fn.params\n .filter((p) => p.type !== 'context.Context')\n .map((p) => ({\n name: p.name,\n type: goTypeToString(p.type),\n optional: false,\n passingStyle: 'positional' as const,\n }));\n if (!apiMethods[fn.name]) apiMethods[fn.name] = [];\n apiMethods[fn.name].push({ name: fn.name, params, returnType: buildReturnType(fn.returnTypes), async: false });\n }\n\n classes[qName] = {\n name: qName,\n sourceFile: s.sourceFile,\n methods: sortRecord(apiMethods),\n properties: sortRecord(properties),\n constructorParams: [],\n };\n } else {\n const fields: Record<string, ApiField> = {};\n for (const field of s.fields) {\n const fieldName = field.jsonTag || field.name;\n fields[fieldName] = { name: fieldName, type: goTypeToString(field.type), optional: field.optional };\n }\n interfaces[qName] = { name: qName, sourceFile: s.sourceFile, fields: sortRecord(fields), extends: [] };\n }\n }\n\n // Build export map\n const collector = new ExportCollector();\n\n for (const [name, cls] of Object.entries(classes)) if (cls.sourceFile) collector.add(cls.sourceFile, name);\n for (const [name, iface] of Object.entries(interfaces)) if (iface.sourceFile) collector.add(iface.sourceFile, name);\n for (const [name, ta] of Object.entries(typeAliases)) if (ta.sourceFile) collector.add(ta.sourceFile, name);\n for (const [name, en] of Object.entries(enums)) if (en.sourceFile) collector.add(en.sourceFile, name);\n for (const c of allConsts) {\n const typeDecl = allTypes.find((t) => t.name === c.typeName && t.packageName === c.packageName);\n if (typeDecl) collector.add(typeDecl.sourceFile, c.name);\n }\n for (const fn of packageFuncs) collector.add(fn.sourceFile, fn.name);\n\n const exports = collector.toRecord();\n\n return {\n classes: sortRecord(classes),\n interfaces: sortRecord(interfaces),\n typeAliases: sortRecord(typeAliases),\n enums: sortRecord(enums),\n exports: sortRecord(exports),\n };\n}\n","/**\n * Go API surface extractor.\n *\n * Walks `.go` files (excluding `_test.go` and `internal/`), parses exported\n * structs, functions, type declarations, and const blocks, then builds an\n * `ApiSurface` with package-qualified names to avoid collisions when\n * multiple packages define the same symbol (e.g., `Client`).\n *\n * Parser: `go-parser.ts` — regex-based Go source analysis\n * Surface: `go-surface.ts` — ApiSurface construction & name qualification\n */\n\nimport { ExtractorError } from '../../errors.js';\nimport type { Extractor, ApiSurface, LanguageHints } from '../types.js';\nimport type { CompatSnapshot } from '../ir.js';\nimport { apiSurfaceToSnapshot } from '../ir.js';\nimport { defaultIsNullableOnlyDifference } from '../language-hints.js';\nimport { walkGoFiles, parseGoFile } from './go-parser.js';\nimport { buildSurface } from './go-surface.js';\nimport type { GoStruct, GoTypeDecl, GoFunc, GoConst } from './go-parser.js';\n\n// ---------------------------------------------------------------------------\n// Language hints\n// ---------------------------------------------------------------------------\n\n/**\n * Go acronyms that may differ in casing between hand-written and generated code.\n * e.g., hand-written uses \"Json\" / \"Uri\" while generated uses \"JSON\" / \"URI\".\n */\nconst GO_ACRONYMS = [\n 'ID',\n 'URL',\n 'API',\n 'HTTP',\n 'HTTPS',\n 'JSON',\n 'XML',\n 'SQL',\n 'HTML',\n 'CSS',\n 'URI',\n 'SSO',\n 'IP',\n 'TLS',\n 'SSL',\n 'DNS',\n 'TCP',\n 'UDP',\n 'SSH',\n 'JWT',\n 'MFA',\n 'SAML',\n 'SCIM',\n];\n\n// Precompiled regex matching all acronym forms (uppercase + title-case) in a single pass.\nconst GO_ACRONYM_RE = new RegExp(\n GO_ACRONYMS.flatMap((a) => [a, a.charAt(0) + a.slice(1).toLowerCase()]).join('|'),\n 'g',\n);\n\n/**\n * Normalize a Go type string so that acronym casing differences don't cause\n * false mismatches. Lowercases all known Go acronyms to a canonical form.\n */\nfunction normalizeGoAcronyms(type: string): string {\n return type.replace(GO_ACRONYM_RE, (match) => match.toLowerCase());\n}\n\nconst goHints: LanguageHints = {\n stripNullable(type: string): string | null {\n if (type.startsWith('*')) return type.slice(1);\n return null;\n },\n isNullableOnlyDifference(a: string, b: string): boolean {\n return defaultIsNullableOnlyDifference(this, a, b);\n },\n isUnionReorder(_a: string, _b: string): boolean {\n return false;\n },\n isGenericTypeParam(type: string): boolean {\n return type === 'interface{}' || type === 'any';\n },\n isExtractionArtifact(type: string): boolean {\n return type === 'interface{}' || type === 'any';\n },\n tolerateCategoryMismatch: false,\n extractReturnTypeName(returnType: string): string | null {\n const stripped = returnType.replace(/^\\*/, '').replace(/\\[\\]/, '');\n return stripped || null;\n },\n extractParamTypeName(paramType: string): string | null {\n const stripped = paramType.replace(/^\\*/, '');\n if (['string', 'int', 'int64', 'float64', 'bool'].includes(stripped)) return null;\n return stripped;\n },\n propertyMatchesClass(propertyName: string, className: string): boolean {\n return propertyName.toLowerCase() === className.toLowerCase();\n },\n derivedModelNames(_modelName: string): string[] {\n // Go SDK does not generate *Response wrapper types — models are returned directly.\n // Don't derive extra names, as they would create false positives in compat checks\n // when the live SDK has hand-written response wrappers.\n return [];\n },\n isTypeEquivalent(baselineType: string, candidateType: string, candidateSurface: ApiSurface): boolean {\n // Normalize Go acronym casing differences (e.g., \"Json\" vs \"JSON\", \"Uri\" vs \"URI\")\n const normBase = normalizeGoAcronyms(baselineType);\n const normCand = normalizeGoAcronyms(candidateType);\n if (normBase === normCand) return true;\n\n // Also try after stripping nullable wrappers and slice prefixes on both sides\n const stripType = (t: string) => t.replace(/^\\*/, '').replace(/^\\[\\]/, '');\n const strippedBase = stripType(normBase);\n const strippedCand = stripType(normCand);\n if (strippedBase === strippedCand) return true;\n\n // Strip package qualifiers (e.g., \"common.RoleResponse\" → \"RoleResponse\")\n const unqualBase = strippedBase.includes('.') ? strippedBase.split('.').pop()! : strippedBase;\n const unqualCand = strippedCand.includes('.') ? strippedCand.split('.').pop()! : strippedCand;\n if (unqualBase === unqualCand) return true;\n\n // Suffix match: the baseline may use a shorter shared type name while the\n // generated code prefixes it with the parent struct name.\n // e.g., baseline \"FactorType\" matches generated \"AuthenticationFactorType\"\n // Only match if the candidate type actually exists in the generated surface.\n const candRaw = stripType(candidateType);\n if (unqualCand.endsWith(unqualBase) && unqualCand.length > unqualBase.length) {\n const exists =\n candidateSurface.enums[candRaw] != null ||\n candidateSurface.interfaces[candRaw] != null ||\n candidateSurface.classes[candRaw] != null ||\n candidateSurface.typeAliases[candRaw] != null;\n if (exists) return true;\n }\n\n return false;\n },\n};\n\n// ---------------------------------------------------------------------------\n// Extractor\n// ---------------------------------------------------------------------------\n\nexport const goExtractor: Extractor = {\n language: 'go',\n hints: goHints,\n\n async extractSnapshot(sdkPath: string): Promise<CompatSnapshot> {\n const surface = await this.extract(sdkPath);\n return apiSurfaceToSnapshot(surface);\n },\n\n async extract(sdkPath: string): Promise<ApiSurface> {\n const goFiles = walkGoFiles(sdkPath);\n if (goFiles.length === 0) {\n throw new ExtractorError(\n `No .go files found in ${sdkPath}`,\n `Ensure the --sdk-path argument points to a Go project root containing .go source files.`,\n );\n }\n\n const allStructs: GoStruct[] = [];\n const allTypes: GoTypeDecl[] = [];\n const allFuncs: GoFunc[] = [];\n const allConsts: GoConst[] = [];\n\n for (const filePath of goFiles) {\n const parsed = parseGoFile(filePath, sdkPath);\n allStructs.push(...parsed.structs);\n allTypes.push(...parsed.types);\n allFuncs.push(...parsed.funcs);\n allConsts.push(...parsed.consts);\n }\n\n const { classes, interfaces, typeAliases, enums, exports } = buildSurface(\n allStructs,\n allTypes,\n allFuncs,\n allConsts,\n );\n\n return {\n language: 'go',\n extractedFrom: sdkPath,\n extractedAt: new Date().toISOString(),\n classes,\n interfaces,\n typeAliases,\n enums,\n exports,\n };\n },\n};\n","/**\n * Rust source parser — tree-sitter-based extraction of structs, enums,\n * impl blocks, traits, type aliases, and functions from Rust source files.\n */\n\nimport { readFileSync, readdirSync, statSync } from 'node:fs';\nimport { join, relative } from 'node:path';\nimport Parser from 'tree-sitter';\nimport RustLang from 'tree-sitter-rust';\nimport type { SyntaxNode } from 'tree-sitter';\nimport { safeParse } from '../../utils/tree-sitter.js';\n\n// ---------------------------------------------------------------------------\n// Internal types\n// ---------------------------------------------------------------------------\n\nexport interface RustStructField {\n name: string;\n type: string;\n serdeRename?: string;\n optional: boolean;\n}\n\nexport interface RustStruct {\n name: string;\n fields: RustStructField[];\n sourceFile: string;\n}\n\nexport interface RustEnum {\n name: string;\n variants: RustEnumVariant[];\n sourceFile: string;\n}\n\nexport interface RustEnumVariant {\n name: string;\n serdeRename?: string;\n}\n\nexport interface RustFunc {\n receiverType: string | null;\n name: string;\n params: { name: string; type: string }[];\n returnType: string;\n isAsync: boolean;\n sourceFile: string;\n}\n\nexport interface RustTypeAlias {\n name: string;\n underlyingType: string;\n sourceFile: string;\n}\n\nexport interface RustTrait {\n name: string;\n methods: RustFunc[];\n sourceFile: string;\n}\n\n// ---------------------------------------------------------------------------\n// Shared parser instance\n// ---------------------------------------------------------------------------\n\nconst rustParser = new Parser();\nrustParser.setLanguage(RustLang);\n\n// ---------------------------------------------------------------------------\n// File walker\n// ---------------------------------------------------------------------------\n\nexport function walkRustFiles(dir: string): string[] {\n const results: string[] = [];\n let entries: string[];\n try {\n entries = readdirSync(dir);\n } catch {\n return results;\n }\n for (const entry of entries) {\n const fullPath = join(dir, entry);\n let stat;\n try {\n stat = statSync(fullPath);\n } catch {\n continue;\n }\n if (stat.isDirectory()) {\n if (entry.startsWith('.') || entry === 'target' || entry === 'benches' || entry === 'examples') continue;\n results.push(...walkRustFiles(fullPath));\n } else if (entry.endsWith('.rs') && !entry.endsWith('_test.rs')) {\n results.push(fullPath);\n }\n }\n return results.sort();\n}\n\n// ---------------------------------------------------------------------------\n// Serde attribute helpers\n// ---------------------------------------------------------------------------\n\n/** Extract the serde rename value from an attribute_item preceding a node. */\nfunction extractSerdeRename(attributeNode: SyntaxNode): string | null {\n const attr = attributeNode.namedChildren.find((c) => c.type === 'attribute');\n if (!attr) return null;\n\n const ident = attr.namedChildren.find((c) => c.type === 'identifier');\n if (!ident || ident.text !== 'serde') return null;\n\n const tokenTree = attr.namedChildren.find((c) => c.type === 'token_tree');\n if (!tokenTree) return null;\n\n const renameIdent = tokenTree.namedChildren.find((c) => c.type === 'identifier' && c.text === 'rename');\n if (!renameIdent) return null;\n\n const strLit = tokenTree.namedChildren.find((c) => c.type === 'string_literal');\n if (!strLit) return null;\n\n const content = strLit.namedChildren.find((c) => c.type === 'string_content');\n return content ? content.text : null;\n}\n\n/** Check if a node is preceded by a serde(skip) or serde(skip_serializing) attribute. */\nfunction hasSerdeSkip(attributeNode: SyntaxNode): boolean {\n const attr = attributeNode.namedChildren.find((c) => c.type === 'attribute');\n if (!attr) return false;\n\n const ident = attr.namedChildren.find((c) => c.type === 'identifier');\n if (!ident || ident.text !== 'serde') return false;\n\n const tokenTree = attr.namedChildren.find((c) => c.type === 'token_tree');\n if (!tokenTree) return false;\n\n return tokenTree.namedChildren.some(\n (c) => c.type === 'identifier' && (c.text === 'skip' || c.text === 'skip_serializing'),\n );\n}\n\n/** Check if a type is Option<T> and return the inner type. */\nfunction isOptionType(typeText: string): boolean {\n return typeText.startsWith('Option<') && typeText.endsWith('>');\n}\n\n/** Check if a node has `pub` visibility. */\nfunction isPublic(node: SyntaxNode): boolean {\n return node.namedChildren.some((c) => c.type === 'visibility_modifier');\n}\n\n// ---------------------------------------------------------------------------\n// Struct extraction\n// ---------------------------------------------------------------------------\n\nfunction parseStructFields(bodyNode: SyntaxNode): RustStructField[] {\n const fields: RustStructField[] = [];\n let pendingAttr: SyntaxNode | null = null;\n\n for (const child of bodyNode.namedChildren) {\n if (child.type === 'attribute_item') {\n pendingAttr = child;\n continue;\n }\n\n if (child.type === 'field_declaration') {\n // Skip non-pub fields\n if (!isPublic(child)) {\n pendingAttr = null;\n continue;\n }\n\n // Skip serde(skip) fields\n if (pendingAttr && hasSerdeSkip(pendingAttr)) {\n pendingAttr = null;\n continue;\n }\n\n const nameNode = child.namedChildren.find((c) => c.type === 'field_identifier');\n const typeNode = child.childForFieldName('type');\n if (!nameNode || !typeNode) {\n pendingAttr = null;\n continue;\n }\n\n const fieldName = nameNode.text;\n const fieldType = typeNode.text;\n const serdeRename = pendingAttr ? extractSerdeRename(pendingAttr) : null;\n\n fields.push({\n name: fieldName,\n type: fieldType,\n serdeRename: serdeRename || undefined,\n optional: isOptionType(fieldType),\n });\n\n pendingAttr = null;\n } else {\n pendingAttr = null;\n }\n }\n return fields;\n}\n\nexport function parseStructs(tree: Parser.Tree, sourceFile: string): RustStruct[] {\n const structs: RustStruct[] = [];\n\n for (const node of tree.rootNode.descendantsOfType('struct_item')) {\n if (!isPublic(node)) continue;\n\n const nameNode = node.childForFieldName('name');\n if (!nameNode) continue;\n\n const bodyNode = node.childForFieldName('body');\n if (!bodyNode || bodyNode.type !== 'field_declaration_list') {\n // Tuple struct or unit struct — no named fields\n structs.push({ name: nameNode.text, fields: [], sourceFile });\n continue;\n }\n\n structs.push({ name: nameNode.text, fields: parseStructFields(bodyNode), sourceFile });\n }\n\n return structs;\n}\n\n// ---------------------------------------------------------------------------\n// Enum extraction\n// ---------------------------------------------------------------------------\n\nexport function parseEnums(tree: Parser.Tree, sourceFile: string): RustEnum[] {\n const enums: RustEnum[] = [];\n\n for (const node of tree.rootNode.descendantsOfType('enum_item')) {\n if (!isPublic(node)) continue;\n\n const nameNode = node.childForFieldName('name');\n if (!nameNode) continue;\n\n const bodyNode = node.childForFieldName('body');\n if (!bodyNode) continue;\n\n const variants: RustEnumVariant[] = [];\n let pendingAttr: SyntaxNode | null = null;\n\n for (const child of bodyNode.namedChildren) {\n if (child.type === 'attribute_item') {\n pendingAttr = child;\n continue;\n }\n if (child.type === 'enum_variant') {\n const variantName = child.childForFieldName('name');\n if (variantName) {\n const serdeRename = pendingAttr ? extractSerdeRename(pendingAttr) : null;\n variants.push({ name: variantName.text, serdeRename: serdeRename || undefined });\n }\n pendingAttr = null;\n } else {\n pendingAttr = null;\n }\n }\n\n if (variants.length > 0) {\n enums.push({ name: nameNode.text, variants, sourceFile });\n }\n }\n\n return enums;\n}\n\n// ---------------------------------------------------------------------------\n// Impl & function extraction\n// ---------------------------------------------------------------------------\n\nfunction parseParams(paramsNode: SyntaxNode): { name: string; type: string }[] {\n const params: { name: string; type: string }[] = [];\n\n for (const child of paramsNode.namedChildren) {\n if (child.type === 'self_parameter') continue; // skip &self, &mut self\n\n if (child.type === 'parameter') {\n const patternNode = child.childForFieldName('pattern');\n const typeNode = child.childForFieldName('type');\n if (patternNode && typeNode) {\n params.push({ name: patternNode.text, type: typeNode.text });\n }\n }\n }\n\n return params;\n}\n\nfunction extractReturnType(funcNode: SyntaxNode): string {\n const retNode = funcNode.childForFieldName('return_type');\n if (!retNode) return '()';\n return retNode.text;\n}\n\nfunction isAsyncFunc(funcNode: SyntaxNode): boolean {\n return funcNode.namedChildren.some((c) => c.type === 'function_modifiers' && c.text.includes('async'));\n}\n\nexport function parseImplBlocks(tree: Parser.Tree, sourceFile: string): RustFunc[] {\n const funcs: RustFunc[] = [];\n\n for (const implNode of tree.rootNode.descendantsOfType('impl_item')) {\n const typeNode = implNode.childForFieldName('type');\n if (!typeNode) continue;\n const receiverType = typeNode.text;\n\n const bodyNode = implNode.childForFieldName('body');\n if (!bodyNode) continue;\n\n for (const child of bodyNode.namedChildren) {\n if (child.type !== 'function_item') continue;\n if (!isPublic(child)) continue;\n\n const nameNode = child.childForFieldName('name');\n if (!nameNode) continue;\n\n const paramsNode = child.childForFieldName('parameters');\n\n funcs.push({\n receiverType,\n name: nameNode.text,\n params: paramsNode ? parseParams(paramsNode) : [],\n returnType: extractReturnType(child),\n isAsync: isAsyncFunc(child),\n sourceFile,\n });\n }\n }\n\n return funcs;\n}\n\n// ---------------------------------------------------------------------------\n// Trait extraction\n// ---------------------------------------------------------------------------\n\nexport function parseTraits(tree: Parser.Tree, sourceFile: string): RustTrait[] {\n const traits: RustTrait[] = [];\n\n for (const traitNode of tree.rootNode.descendantsOfType('trait_item')) {\n if (!isPublic(traitNode)) continue;\n\n const nameNode = traitNode.childForFieldName('name');\n if (!nameNode) continue;\n\n const bodyNode = traitNode.childForFieldName('body');\n if (!bodyNode) continue;\n\n const methods: RustFunc[] = [];\n\n for (const child of bodyNode.namedChildren) {\n // Trait methods appear as function_signature_item (no body)\n if (child.type !== 'function_signature_item' && child.type !== 'function_item') continue;\n\n const methodName = child.childForFieldName('name');\n if (!methodName) continue;\n\n const paramsNode = child.childForFieldName('parameters');\n\n methods.push({\n receiverType: null,\n name: methodName.text,\n params: paramsNode ? parseParams(paramsNode) : [],\n returnType: extractReturnType(child),\n isAsync: isAsyncFunc(child),\n sourceFile,\n });\n }\n\n if (methods.length > 0) {\n traits.push({ name: nameNode.text, methods, sourceFile });\n }\n }\n\n return traits;\n}\n\n// ---------------------------------------------------------------------------\n// Type alias extraction\n// ---------------------------------------------------------------------------\n\nexport function parseTypeAliases(tree: Parser.Tree, sourceFile: string): RustTypeAlias[] {\n const aliases: RustTypeAlias[] = [];\n\n for (const node of tree.rootNode.descendantsOfType('type_item')) {\n if (!isPublic(node)) continue;\n\n const nameNode = node.childForFieldName('name');\n const typeNode = node.childForFieldName('type');\n if (!nameNode || !typeNode) continue;\n\n aliases.push({ name: nameNode.text, underlyingType: typeNode.text, sourceFile });\n }\n\n return aliases;\n}\n\n// ---------------------------------------------------------------------------\n// Full file parser\n// ---------------------------------------------------------------------------\n\nexport interface ParsedRustFile {\n structs: RustStruct[];\n enums: RustEnum[];\n funcs: RustFunc[];\n traits: RustTrait[];\n typeAliases: RustTypeAlias[];\n}\n\nexport function parseRustFile(filePath: string, sdkPath: string): ParsedRustFile {\n const source = readFileSync(filePath, 'utf-8');\n const relPath = relative(sdkPath, filePath);\n const tree = safeParse(rustParser, source);\n\n return {\n structs: parseStructs(tree, relPath),\n enums: parseEnums(tree, relPath),\n funcs: parseImplBlocks(tree, relPath),\n traits: parseTraits(tree, relPath),\n typeAliases: parseTypeAliases(tree, relPath),\n };\n}\n","/**\n * Rust surface builder — transforms parsed Rust symbols into an ApiSurface.\n *\n * Mapping:\n * pub struct + impl methods → ApiClass\n * pub struct (no methods) → ApiInterface (data-only)\n * pub enum → ApiEnum (serde renames as member values)\n * pub type X = Y → ApiTypeAlias\n * pub trait → ApiClass (trait methods as API surface)\n */\n\nimport type {\n ApiClass,\n ApiMethod,\n ApiParam,\n ApiProperty,\n ApiInterface,\n ApiField,\n ApiTypeAlias,\n ApiEnum,\n} from '../types.js';\nimport type { RustStruct, RustEnum, RustFunc, RustTrait, RustTypeAlias as RustTypeAliasType } from './rust-parser.js';\nimport { sortRecord, ExportCollector } from './shared.js';\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction rustTypeToString(t: string): string {\n return t;\n}\n\n/** Strip Result<T, E> to just T. */\nfunction unwrapResultType(returnType: string): string {\n const match = returnType.match(/^Result\\s*<\\s*(.+)\\s*,\\s*.+\\s*>$/);\n if (match) return match[1].trim();\n return returnType;\n}\n\n// ---------------------------------------------------------------------------\n// Surface builder\n// ---------------------------------------------------------------------------\n\nexport function buildSurface(\n allStructs: RustStruct[],\n allEnums: RustEnum[],\n allFuncs: RustFunc[],\n allTraits: RustTrait[],\n allTypeAliases: RustTypeAliasType[],\n): {\n classes: Record<string, ApiClass>;\n interfaces: Record<string, ApiInterface>;\n typeAliases: Record<string, ApiTypeAlias>;\n enums: Record<string, ApiEnum>;\n exports: Record<string, string[]>;\n} {\n const classes: Record<string, ApiClass> = {};\n const interfaces: Record<string, ApiInterface> = {};\n const typeAliases: Record<string, ApiTypeAlias> = {};\n const enums: Record<string, ApiEnum> = {};\n\n // Group impl methods by receiver type\n const methodsByReceiver = new Map<string, RustFunc[]>();\n for (const fn of allFuncs) {\n if (!fn.receiverType) continue;\n if (!methodsByReceiver.has(fn.receiverType)) methodsByReceiver.set(fn.receiverType, []);\n methodsByReceiver.get(fn.receiverType)!.push(fn);\n }\n\n // Process structs\n for (const s of allStructs) {\n const methods = methodsByReceiver.get(s.name);\n\n if (methods && methods.length > 0) {\n // Struct with impl methods → ApiClass\n const apiMethods: Record<string, ApiMethod[]> = {};\n const properties: Record<string, ApiProperty> = {};\n\n for (const field of s.fields) {\n const fieldName = field.serdeRename || field.name;\n properties[fieldName] = {\n name: fieldName,\n type: rustTypeToString(field.type),\n readonly: false,\n };\n }\n\n for (const fn of methods) {\n const params: ApiParam[] = fn.params.map((p) => ({\n name: p.name,\n type: rustTypeToString(p.type),\n optional: p.type.startsWith('Option<'),\n passingStyle: 'positional' as const,\n }));\n const returnType = unwrapResultType(fn.returnType);\n if (!apiMethods[fn.name]) apiMethods[fn.name] = [];\n apiMethods[fn.name].push({\n name: fn.name,\n params,\n returnType: rustTypeToString(returnType),\n async: fn.isAsync,\n });\n }\n\n classes[s.name] = {\n name: s.name,\n sourceFile: s.sourceFile,\n methods: sortRecord(apiMethods),\n properties: sortRecord(properties),\n constructorParams: [],\n };\n } else {\n // Struct without methods → ApiInterface\n const fields: Record<string, ApiField> = {};\n for (const field of s.fields) {\n const fieldName = field.serdeRename || field.name;\n fields[fieldName] = {\n name: fieldName,\n type: rustTypeToString(field.type),\n optional: field.optional,\n };\n }\n interfaces[s.name] = {\n name: s.name,\n sourceFile: s.sourceFile,\n fields: sortRecord(fields),\n extends: [],\n };\n }\n }\n\n // Process enums\n for (const e of allEnums) {\n const members: Record<string, string | number> = {};\n for (const v of e.variants) {\n members[v.name] = v.serdeRename || v.name;\n }\n enums[e.name] = { name: e.name, sourceFile: e.sourceFile, members: sortRecord(members) };\n }\n\n // Process type aliases\n for (const ta of allTypeAliases) {\n typeAliases[ta.name] = { name: ta.name, sourceFile: ta.sourceFile, value: rustTypeToString(ta.underlyingType) };\n }\n\n // Process traits → ApiClass (trait methods define the API contract)\n for (const trait of allTraits) {\n const apiMethods: Record<string, ApiMethod[]> = {};\n\n for (const fn of trait.methods) {\n const params: ApiParam[] = fn.params.map((p) => ({\n name: p.name,\n type: rustTypeToString(p.type),\n optional: p.type.startsWith('Option<'),\n }));\n const returnType = unwrapResultType(fn.returnType);\n if (!apiMethods[fn.name]) apiMethods[fn.name] = [];\n apiMethods[fn.name].push({\n name: fn.name,\n params,\n returnType: rustTypeToString(returnType),\n async: fn.isAsync,\n });\n }\n\n classes[trait.name] = {\n name: trait.name,\n sourceFile: trait.sourceFile,\n methods: sortRecord(apiMethods),\n properties: {},\n constructorParams: [],\n };\n }\n\n // Build export map\n const collector = new ExportCollector();\n\n for (const [name, cls] of Object.entries(classes)) if (cls.sourceFile) collector.add(cls.sourceFile, name);\n for (const [name, iface] of Object.entries(interfaces)) if (iface.sourceFile) collector.add(iface.sourceFile, name);\n for (const [name, ta] of Object.entries(typeAliases)) if (ta.sourceFile) collector.add(ta.sourceFile, name);\n for (const [name, en] of Object.entries(enums)) if (en.sourceFile) collector.add(en.sourceFile, name);\n\n const exports = collector.toRecord();\n\n return {\n classes: sortRecord(classes),\n interfaces: sortRecord(interfaces),\n typeAliases: sortRecord(typeAliases),\n enums: sortRecord(enums),\n exports: sortRecord(exports),\n };\n}\n","/**\n * Rust API surface extractor.\n *\n * Walks `.rs` files under `src/`, parses pub structs, enums, impl blocks,\n * traits, and type aliases, then builds an ApiSurface.\n *\n * Parser: `rust-parser.ts` — tree-sitter-based Rust source analysis\n * Surface: `rust-surface.ts` — ApiSurface construction\n */\n\nimport { ExtractorError } from '../../errors.js';\nimport type { Extractor, ApiSurface, LanguageHints } from '../types.js';\nimport type { CompatSnapshot } from '../ir.js';\nimport { apiSurfaceToSnapshot } from '../ir.js';\nimport { defaultIsNullableOnlyDifference } from '../language-hints.js';\nimport { walkRustFiles, parseRustFile } from './rust-parser.js';\nimport { buildSurface } from './rust-surface.js';\nimport type { RustStruct, RustEnum, RustFunc, RustTrait, RustTypeAlias } from './rust-parser.js';\n\n// ---------------------------------------------------------------------------\n// Language hints\n// ---------------------------------------------------------------------------\n\nconst rustHints: LanguageHints = {\n stripNullable(type: string): string | null {\n const match = type.match(/^Option<(.+)>$/);\n return match ? match[1] : null;\n },\n isNullableOnlyDifference(a: string, b: string): boolean {\n return defaultIsNullableOnlyDifference(this, a, b);\n },\n isUnionReorder(_a: string, _b: string): boolean {\n return false; // Rust doesn't have union types in the TS sense\n },\n isGenericTypeParam(type: string): boolean {\n // Single uppercase letter or T-prefixed: T, U, V, TResult\n return /^[A-Z]$/.test(type) || /^T[A-Z][a-zA-Z]*$/.test(type);\n },\n isExtractionArtifact(type: string): boolean {\n return type === 'serde_json::Value' || type === 'Box<dyn std::error::Error>';\n },\n tolerateCategoryMismatch: false,\n extractReturnTypeName(returnType: string): string | null {\n // Unwrap Result<T, E> → T, Vec<T> → T, Option<T> → T\n let inner = returnType;\n const resultMatch = inner.match(/^Result\\s*<\\s*(.+)\\s*,\\s*.+\\s*>$/);\n if (resultMatch) inner = resultMatch[1].trim();\n const vecMatch = inner.match(/^Vec\\s*<\\s*(.+)\\s*>$/);\n if (vecMatch) inner = vecMatch[1].trim();\n const optMatch = inner.match(/^Option\\s*<\\s*(.+)\\s*>$/);\n if (optMatch) inner = optMatch[1].trim();\n // Strip references\n inner = inner.replace(/^&(?:mut\\s+)?(?:'[a-z]+\\s+)?/, '');\n if (['()', 'String', 'str', 'bool', 'i32', 'i64', 'u32', 'u64', 'f32', 'f64', 'usize'].includes(inner)) {\n return null;\n }\n return inner;\n },\n extractParamTypeName(paramType: string): string | null {\n let inner = paramType.replace(/^&(?:mut\\s+)?(?:'[a-z]+\\s+)?/, '');\n if (['String', '&str', 'str', 'bool', 'i32', 'i64', 'u32', 'u64', 'f32', 'f64', 'usize'].includes(inner)) {\n return null;\n }\n return inner;\n },\n propertyMatchesClass(propertyName: string, className: string): boolean {\n // snake_case property vs PascalCase class\n const normalized = propertyName.replace(/_/g, '').toLowerCase();\n return normalized === className.toLowerCase();\n },\n derivedModelNames(modelName: string): string[] {\n return [`${modelName}Response`];\n },\n};\n\n// ---------------------------------------------------------------------------\n// Extractor\n// ---------------------------------------------------------------------------\n\nexport const rustExtractor: Extractor = {\n language: 'rust',\n hints: rustHints,\n\n async extractSnapshot(sdkPath: string): Promise<CompatSnapshot> {\n const surface = await this.extract(sdkPath);\n return apiSurfaceToSnapshot(surface);\n },\n\n async extract(sdkPath: string): Promise<ApiSurface> {\n const rsFiles = walkRustFiles(sdkPath);\n if (rsFiles.length === 0) {\n throw new ExtractorError(\n `No .rs files found in ${sdkPath}`,\n `Ensure the --sdk-path argument points to a Rust project root containing .rs source files.`,\n );\n }\n\n const allStructs: RustStruct[] = [];\n const allEnums: RustEnum[] = [];\n const allFuncs: RustFunc[] = [];\n const allTraits: RustTrait[] = [];\n const allTypeAliases: RustTypeAlias[] = [];\n\n for (const filePath of rsFiles) {\n const parsed = parseRustFile(filePath, sdkPath);\n allStructs.push(...parsed.structs);\n allEnums.push(...parsed.enums);\n allFuncs.push(...parsed.funcs);\n allTraits.push(...parsed.traits);\n allTypeAliases.push(...parsed.typeAliases);\n }\n\n const { classes, interfaces, typeAliases, enums, exports } = buildSurface(\n allStructs,\n allEnums,\n allFuncs,\n allTraits,\n allTypeAliases,\n );\n\n return {\n language: 'rust',\n extractedFrom: sdkPath,\n extractedAt: new Date().toISOString(),\n classes,\n interfaces,\n typeAliases,\n enums,\n exports,\n };\n },\n};\n","/**\n * Kotlin source parser — regex-based extraction of classes, data classes,\n * enum classes, functions, and type aliases from Kotlin source files.\n */\n\nimport { readFileSync, readdirSync, statSync } from 'node:fs';\nimport { join, relative } from 'node:path';\n\n// ---------------------------------------------------------------------------\n// Internal types\n// ---------------------------------------------------------------------------\n\nexport interface KotlinField {\n name: string;\n type: string;\n jsonName?: string;\n optional: boolean;\n}\n\nexport interface KotlinDataClass {\n name: string;\n fields: KotlinField[];\n sourceFile: string;\n packageName: string;\n}\n\nexport interface KotlinClass {\n name: string;\n constructorParams: { name: string; type: string }[];\n methods: KotlinMethod[];\n sourceFile: string;\n packageName: string;\n}\n\nexport interface KotlinMethod {\n name: string;\n params: { name: string; type: string; optional: boolean }[];\n returnType: string;\n visibility: string;\n}\n\nexport interface KotlinEnum {\n name: string;\n members: Record<string, string>;\n sourceFile: string;\n packageName: string;\n}\n\nexport interface KotlinTypeAlias {\n name: string;\n value: string;\n sourceFile: string;\n packageName: string;\n}\n\nexport interface ParsedKotlinFile {\n dataClasses: KotlinDataClass[];\n classes: KotlinClass[];\n enums: KotlinEnum[];\n typeAliases: KotlinTypeAlias[];\n}\n\n// ---------------------------------------------------------------------------\n// File walker\n// ---------------------------------------------------------------------------\n\nexport function walkKotlinFiles(dir: string): string[] {\n const results: string[] = [];\n let entries: string[];\n try {\n entries = readdirSync(dir);\n } catch {\n return results;\n }\n for (const entry of entries) {\n const fullPath = join(dir, entry);\n let stat;\n try {\n stat = statSync(fullPath);\n } catch {\n continue;\n }\n if (stat.isDirectory()) {\n if (entry.startsWith('.') || entry === 'build' || entry === 'test' || entry === 'androidTest') continue;\n results.push(...walkKotlinFiles(fullPath));\n } else if (entry.endsWith('.kt') && !entry.endsWith('Test.kt')) {\n results.push(fullPath);\n }\n }\n return results.sort();\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/** Extract the package name from a Kotlin source file. */\nfunction extractPackageName(source: string): string {\n const match = source.match(/^package\\s+([\\w.]+)/m);\n return match ? match[1] : 'unknown';\n}\n\n/** Strip single-line and block comments from source to avoid false matches. */\nfunction stripComments(source: string): string {\n // Remove block comments\n let result = source.replace(/\\/\\*[\\s\\S]*?\\*\\//g, '');\n // Remove single-line comments\n result = result.replace(/\\/\\/[^\\n]*/g, '');\n return result;\n}\n\n/**\n * Extract the @JsonProperty(\"name\") annotation value before a parameter.\n * Looks for the pattern immediately preceding the parameter declaration.\n */\nfunction extractJsonPropertyName(text: string): string | null {\n const match = text.match(/@JsonProperty\\(\"([^\"]+)\"\\)/);\n return match ? match[1] : null;\n}\n\n/**\n * Parse constructor parameters from a data class or class declaration.\n * Handles multi-line parameter lists with annotations.\n */\nfunction parseConstructorParams(paramsBlock: string): KotlinField[] {\n const fields: KotlinField[] = [];\n\n // Split by top-level commas (not nested in angle brackets or parens)\n const params = splitTopLevelCommas(paramsBlock);\n\n for (const param of params) {\n const trimmed = param.trim();\n if (!trimmed) continue;\n\n // Extract JsonProperty annotation if present\n const jsonName = extractJsonPropertyName(trimmed);\n\n // Match val/var name: Type pattern, possibly with default value\n const paramMatch = trimmed.match(\n /(?:(?:override|private|protected)\\s+)?(?:val|var)\\s+(\\w+)\\s*:\\s*([^=,]+?)(?:\\s*=\\s*(.+))?$/m,\n );\n if (!paramMatch) continue;\n\n const name = paramMatch[1];\n const rawType = paramMatch[2].trim();\n const hasDefault = paramMatch[3] !== undefined;\n\n // Check if the type is nullable (ends with ?)\n const isNullable = rawType.endsWith('?');\n const type = rawType;\n\n fields.push({\n name,\n type,\n jsonName: jsonName || undefined,\n optional: isNullable || hasDefault,\n });\n }\n\n return fields;\n}\n\n/** Split a string by top-level commas, ignoring commas inside angle brackets, parens, or strings. */\nfunction splitTopLevelCommas(text: string): string[] {\n const result: string[] = [];\n let depth = 0;\n let current = '';\n let inString = false;\n let stringChar = '';\n\n for (let i = 0; i < text.length; i++) {\n const ch = text[i];\n\n if (inString) {\n current += ch;\n if (ch === stringChar && text[i - 1] !== '\\\\') {\n inString = false;\n }\n continue;\n }\n\n if (ch === '\"' || ch === \"'\") {\n inString = true;\n stringChar = ch;\n current += ch;\n continue;\n }\n\n if (ch === '<' || ch === '(' || ch === '[') {\n depth++;\n current += ch;\n } else if (ch === '>' || ch === ')' || ch === ']') {\n depth--;\n current += ch;\n } else if (ch === ',' && depth === 0) {\n result.push(current);\n current = '';\n } else {\n current += ch;\n }\n }\n\n if (current.trim()) {\n result.push(current);\n }\n\n return result;\n}\n\n// ---------------------------------------------------------------------------\n// Enum extraction\n// ---------------------------------------------------------------------------\n\nfunction parseEnumClass(source: string, sourceFile: string, packageName: string): KotlinEnum[] {\n const enums: KotlinEnum[] = [];\n\n // Match: enum class Name(@JsonValue val value: Type) { Member1(\"val1\"), Member2(\"val2\") }\n const enumRegex = /enum\\s+class\\s+(\\w+)(?:\\([^)]*\\))?\\s*\\{([^}]*)\\}/g;\n let match;\n while ((match = enumRegex.exec(source)) !== null) {\n const name = match[1];\n const body = match[2];\n\n const members: Record<string, string> = {};\n\n // Match enum members: MemberName(\"value\") or MemberName\n const memberRegex = /(\\w+)\\s*(?:\\(\"([^\"]*)\"\\))?/g;\n let memberMatch;\n while ((memberMatch = memberRegex.exec(body)) !== null) {\n const memberName = memberMatch[1];\n // Skip keywords that might match\n if (['val', 'var', 'fun', 'override', 'companion', 'object'].includes(memberName)) continue;\n const memberValue = memberMatch[2] !== undefined ? memberMatch[2] : memberName;\n members[memberName] = memberValue;\n }\n\n if (Object.keys(members).length > 0) {\n enums.push({ name, members, sourceFile, packageName });\n }\n }\n\n return enums;\n}\n\n// ---------------------------------------------------------------------------\n// Data class extraction\n// ---------------------------------------------------------------------------\n\nfunction parseDataClasses(source: string, sourceFile: string, packageName: string): KotlinDataClass[] {\n const dataClasses: KotlinDataClass[] = [];\n\n // Match: data class Name(params) or data class Name @Annotation constructor(params)\n // Use a regex that captures the opening paren, then find the matching close\n const dataClassStartRegex = /data\\s+class\\s+(\\w+)\\s*(?:@\\w+(?:\\([^)]*\\))?\\s+)?(?:constructor\\s*)?\\(/g;\n let match;\n while ((match = dataClassStartRegex.exec(source)) !== null) {\n const name = match[1];\n const startIdx = match.index + match[0].length;\n\n // Find matching closing paren\n let depth = 1;\n let idx = startIdx;\n while (idx < source.length && depth > 0) {\n if (source[idx] === '(') depth++;\n else if (source[idx] === ')') depth--;\n idx++;\n }\n\n const paramsBlock = source.slice(startIdx, idx - 1);\n const fields = parseConstructorParams(paramsBlock);\n\n dataClasses.push({ name, fields, sourceFile, packageName });\n }\n\n return dataClasses;\n}\n\n// ---------------------------------------------------------------------------\n// Class extraction (non-data classes)\n// ---------------------------------------------------------------------------\n\nfunction parseClasses(source: string, sourceFile: string, packageName: string): KotlinClass[] {\n const classes: KotlinClass[] = [];\n\n // Match non-data, non-enum classes: class Name(params) { body }\n // Skip abstract, sealed, and open classes that aren't services\n const classStartRegex =\n /(?<!data\\s)(?<!enum\\s)(?<!abstract\\s)(?<!sealed\\s)(?:open\\s+)?class\\s+(\\w+)\\s*(?:\\(([^)]*)\\))?\\s*(?::\\s*[^{]+)?\\s*\\{/g;\n let match;\n while ((match = classStartRegex.exec(source)) !== null) {\n const name = match[1];\n const constructorBlock = match[2] || '';\n\n // Find matching closing brace for the class body\n const braceStart = source.indexOf('{', match.index + match[0].length - 1);\n let depth = 1;\n let idx = braceStart + 1;\n while (idx < source.length && depth > 0) {\n if (source[idx] === '{') depth++;\n else if (source[idx] === '}') depth--;\n idx++;\n }\n\n const classBody = source.slice(braceStart + 1, idx - 1);\n\n // Parse constructor params\n const constructorParams: { name: string; type: string }[] = [];\n if (constructorBlock.trim()) {\n const params = splitTopLevelCommas(constructorBlock);\n for (const param of params) {\n const trimmed = param.trim();\n const paramMatch = trimmed.match(/(?:(?:private|protected)\\s+)?(?:val|var)\\s+(\\w+)\\s*:\\s*(.+)/);\n if (paramMatch) {\n constructorParams.push({ name: paramMatch[1], type: paramMatch[2].trim() });\n }\n }\n }\n\n // Parse methods\n const methods = parseMethods(classBody);\n\n if (methods.length > 0) {\n classes.push({ name, constructorParams, methods, sourceFile, packageName });\n }\n }\n\n return classes;\n}\n\n/** Parse method declarations from a class body. */\nfunction parseMethods(classBody: string): KotlinMethod[] {\n const methods: KotlinMethod[] = [];\n\n // Match: fun methodName(params): ReturnType or fun methodName(params)\n // Handle suspend fun, private fun, etc.\n const methodRegex =\n /(private|protected|internal|public)?\\s*(?:suspend\\s+)?fun\\s+(\\w+)\\s*\\(([^)]*)\\)\\s*(?::\\s*([^\\s{]+))?/g;\n let match;\n while ((match = methodRegex.exec(classBody)) !== null) {\n const visibility = match[1] || 'public';\n const name = match[2];\n const paramsStr = match[3];\n const returnType = match[4] || 'Unit';\n\n // Skip private/protected methods\n if (visibility === 'private' || visibility === 'protected') continue;\n\n const params: { name: string; type: string; optional: boolean }[] = [];\n if (paramsStr.trim()) {\n const paramParts = splitTopLevelCommas(paramsStr);\n for (const part of paramParts) {\n const trimmed = part.trim();\n const paramMatch = trimmed.match(/(\\w+)\\s*:\\s*([^=]+?)(?:\\s*=\\s*(.+))?$/);\n if (paramMatch) {\n const paramType = paramMatch[2].trim();\n const hasDefault = paramMatch[3] !== undefined;\n params.push({\n name: paramMatch[1],\n type: paramType,\n optional: paramType.endsWith('?') || hasDefault,\n });\n }\n }\n }\n\n methods.push({ name, params, returnType, visibility });\n }\n\n return methods;\n}\n\n// ---------------------------------------------------------------------------\n// Type alias extraction\n// ---------------------------------------------------------------------------\n\nfunction parseTypeAliases(source: string, sourceFile: string, packageName: string): KotlinTypeAlias[] {\n const aliases: KotlinTypeAlias[] = [];\n\n const aliasRegex = /typealias\\s+(\\w+)\\s*=\\s*([^\\n]+)/g;\n let match;\n while ((match = aliasRegex.exec(source)) !== null) {\n aliases.push({\n name: match[1],\n value: match[2].trim(),\n sourceFile,\n packageName,\n });\n }\n\n return aliases;\n}\n\n// ---------------------------------------------------------------------------\n// Full file parser\n// ---------------------------------------------------------------------------\n\n/** Parse a single Kotlin source file and return all extracted symbols. */\nexport function parseKotlinFile(filePath: string, sdkPath: string): ParsedKotlinFile {\n const source = readFileSync(filePath, 'utf-8');\n const relPath = relative(sdkPath, filePath);\n const cleaned = stripComments(source);\n const packageName = extractPackageName(cleaned);\n\n return {\n dataClasses: parseDataClasses(cleaned, relPath, packageName),\n classes: parseClasses(cleaned, relPath, packageName),\n enums: parseEnumClass(cleaned, relPath, packageName),\n typeAliases: parseTypeAliases(cleaned, relPath, packageName),\n };\n}\n","/**\n * Kotlin surface builder — transforms parsed Kotlin symbols into an ApiSurface.\n */\n\nimport type {\n ApiClass,\n ApiMethod,\n ApiParam,\n ApiProperty,\n ApiInterface,\n ApiField,\n ApiTypeAlias,\n ApiEnum,\n} from '../types.js';\nimport type { KotlinDataClass, KotlinClass, KotlinEnum, KotlinTypeAlias } from './kotlin-parser.js';\nimport { sortRecord, ExportCollector } from './shared.js';\n\n// ---------------------------------------------------------------------------\n// Surface builder\n// ---------------------------------------------------------------------------\n\nexport function buildSurface(\n allDataClasses: KotlinDataClass[],\n allClasses: KotlinClass[],\n allEnums: KotlinEnum[],\n allTypeAliases: KotlinTypeAlias[],\n): {\n classes: Record<string, ApiClass>;\n interfaces: Record<string, ApiInterface>;\n typeAliases: Record<string, ApiTypeAlias>;\n enums: Record<string, ApiEnum>;\n exports: Record<string, string[]>;\n} {\n const classes: Record<string, ApiClass> = {};\n const interfaces: Record<string, ApiInterface> = {};\n const typeAliases: Record<string, ApiTypeAlias> = {};\n const enums: Record<string, ApiEnum> = {};\n\n const collector = new ExportCollector();\n\n // Process data classes as interfaces (they represent data models)\n for (const dc of allDataClasses) {\n const fields: Record<string, ApiField> = {};\n for (const field of dc.fields) {\n const fieldName = field.jsonName || field.name;\n fields[fieldName] = {\n name: fieldName,\n type: field.type,\n optional: field.optional,\n };\n }\n interfaces[dc.name] = {\n name: dc.name,\n sourceFile: dc.sourceFile,\n fields: sortRecord(fields),\n extends: [],\n };\n collector.add(dc.sourceFile, dc.name);\n }\n\n // Process classes (service classes with methods)\n for (const cls of allClasses) {\n const methods: Record<string, ApiMethod[]> = {};\n const properties: Record<string, ApiProperty> = {};\n\n for (const method of cls.methods) {\n const params: ApiParam[] = method.params.map((p) => ({\n name: p.name,\n type: p.type,\n optional: p.optional,\n passingStyle: 'named' as const,\n }));\n\n if (!methods[method.name]) methods[method.name] = [];\n methods[method.name].push({\n name: method.name,\n params,\n returnType: method.returnType,\n async: false,\n });\n }\n\n const constructorParams: ApiParam[] = cls.constructorParams.map((p) => ({\n name: p.name,\n type: p.type,\n optional: false,\n passingStyle: 'named' as const,\n }));\n\n classes[cls.name] = {\n name: cls.name,\n sourceFile: cls.sourceFile,\n methods: sortRecord(methods),\n properties: sortRecord(properties),\n constructorParams,\n };\n collector.add(cls.sourceFile, cls.name);\n }\n\n // Process enums\n for (const en of allEnums) {\n enums[en.name] = {\n name: en.name,\n sourceFile: en.sourceFile,\n members: sortRecord(en.members),\n };\n collector.add(en.sourceFile, en.name);\n }\n\n // Process type aliases\n for (const ta of allTypeAliases) {\n typeAliases[ta.name] = {\n name: ta.name,\n sourceFile: ta.sourceFile,\n value: ta.value,\n };\n collector.add(ta.sourceFile, ta.name);\n }\n\n const exports = collector.toRecord();\n\n return {\n classes: sortRecord(classes),\n interfaces: sortRecord(interfaces),\n typeAliases: sortRecord(typeAliases),\n enums: sortRecord(enums),\n exports: sortRecord(exports),\n };\n}\n","/**\n * Kotlin API surface extractor.\n *\n * Walks `.kt` files (excluding test files and build directories), parses\n * data classes, classes, enum classes, and type aliases, then builds an\n * `ApiSurface`.\n *\n * Parser: `kotlin-parser.ts` — regex-based Kotlin source analysis\n * Surface: `kotlin-surface.ts` — ApiSurface construction\n */\n\nimport { ExtractorError } from '../../errors.js';\nimport type { Extractor, ApiSurface, LanguageHints } from '../types.js';\nimport type { CompatSnapshot } from '../ir.js';\nimport { apiSurfaceToSnapshot } from '../ir.js';\nimport { defaultIsNullableOnlyDifference } from '../language-hints.js';\nimport { walkKotlinFiles, parseKotlinFile } from './kotlin-parser.js';\nimport { buildSurface } from './kotlin-surface.js';\nimport type { KotlinDataClass, KotlinClass, KotlinEnum, KotlinTypeAlias } from './kotlin-parser.js';\n\n// ---------------------------------------------------------------------------\n// Language hints\n// ---------------------------------------------------------------------------\n\nconst kotlinHints: LanguageHints = {\n stripNullable(type: string): string | null {\n if (type.endsWith('?')) return type.slice(0, -1);\n return null;\n },\n isNullableOnlyDifference(a: string, b: string): boolean {\n return defaultIsNullableOnlyDifference(this, a, b);\n },\n isUnionReorder(_a: string, _b: string): boolean {\n return false; // Kotlin doesn't have union types\n },\n isGenericTypeParam(type: string): boolean {\n return /^[A-Z]$/.test(type) || /^T[A-Z][a-zA-Z]*$/.test(type);\n },\n isExtractionArtifact(type: string): boolean {\n return type === 'Any' || type === 'Any?';\n },\n tolerateCategoryMismatch: true,\n extractReturnTypeName(returnType: string): string | null {\n let inner = returnType;\n // Unwrap nullable\n if (inner.endsWith('?')) inner = inner.slice(0, -1);\n // Unwrap List<T> → T\n const listMatch = inner.match(/^(?:List|MutableList|ArrayList)<(.+)>$/);\n if (listMatch) inner = listMatch[1];\n // Unwrap PaginatedList<T> → T\n const paginatedMatch = inner.match(/^PaginatedList<(.+)>$/);\n if (paginatedMatch) inner = paginatedMatch[1];\n // Primitives\n if (['String', 'Int', 'Long', 'Float', 'Double', 'Boolean', 'Unit', 'Void'].includes(inner)) return null;\n return inner;\n },\n extractParamTypeName(paramType: string): string | null {\n let inner = paramType;\n if (inner.endsWith('?')) inner = inner.slice(0, -1);\n if (['String', 'Int', 'Long', 'Float', 'Double', 'Boolean'].includes(inner)) return null;\n return inner;\n },\n propertyMatchesClass(propertyName: string, className: string): boolean {\n // camelCase property vs PascalCase class\n return propertyName.toLowerCase() === className.toLowerCase();\n },\n derivedModelNames(modelName: string): string[] {\n return [`${modelName}Response`];\n },\n};\n\n// ---------------------------------------------------------------------------\n// Extractor\n// ---------------------------------------------------------------------------\n\nexport const kotlinExtractor: Extractor = {\n language: 'kotlin',\n hints: kotlinHints,\n\n async extractSnapshot(sdkPath: string): Promise<CompatSnapshot> {\n const surface = await this.extract(sdkPath);\n return apiSurfaceToSnapshot(surface);\n },\n\n async extract(sdkPath: string): Promise<ApiSurface> {\n const ktFiles = walkKotlinFiles(sdkPath);\n if (ktFiles.length === 0) {\n throw new ExtractorError(\n `No .kt files found in ${sdkPath}`,\n `Ensure the --sdk-path argument points to a Kotlin project root containing .kt source files.`,\n );\n }\n\n const allDataClasses: KotlinDataClass[] = [];\n const allClasses: KotlinClass[] = [];\n const allEnums: KotlinEnum[] = [];\n const allTypeAliases: KotlinTypeAlias[] = [];\n\n for (const filePath of ktFiles) {\n const parsed = parseKotlinFile(filePath, sdkPath);\n allDataClasses.push(...parsed.dataClasses);\n allClasses.push(...parsed.classes);\n allEnums.push(...parsed.enums);\n allTypeAliases.push(...parsed.typeAliases);\n }\n\n const { classes, interfaces, typeAliases, enums, exports } = buildSurface(\n allDataClasses,\n allClasses,\n allEnums,\n allTypeAliases,\n );\n\n return {\n language: 'kotlin',\n extractedFrom: sdkPath,\n extractedAt: new Date().toISOString(),\n classes,\n interfaces,\n typeAliases,\n enums,\n exports,\n };\n },\n};\n","/**\n * C# (.NET) source parser — regex-based extraction of classes, enums,\n * properties, and methods from C# source files.\n */\n\nimport { readFileSync, readdirSync, statSync } from 'node:fs';\nimport { join, relative } from 'node:path';\n\n// ---------------------------------------------------------------------------\n// Internal types\n// ---------------------------------------------------------------------------\n\nexport interface CSharpProperty {\n name: string;\n type: string;\n jsonName?: string;\n readonly: boolean;\n}\n\nexport interface CSharpMethod {\n name: string;\n params: { name: string; type: string; optional: boolean }[];\n returnType: string;\n visibility: string;\n isAsync: boolean;\n}\n\nexport interface CSharpClass {\n name: string;\n namespace: string;\n properties: CSharpProperty[];\n methods: CSharpMethod[];\n constructorParams: { name: string; type: string }[];\n isService: boolean;\n sourceFile: string;\n}\n\nexport interface CSharpEnum {\n name: string;\n namespace: string;\n members: Record<string, string>;\n sourceFile: string;\n}\n\nexport interface ParsedCSharpFile {\n classes: CSharpClass[];\n enums: CSharpEnum[];\n}\n\n// ---------------------------------------------------------------------------\n// File walker\n// ---------------------------------------------------------------------------\n\nexport function walkCSharpFiles(dir: string): string[] {\n const results: string[] = [];\n let entries: string[];\n try {\n entries = readdirSync(dir);\n } catch {\n return results;\n }\n for (const entry of entries) {\n const fullPath = join(dir, entry);\n let stat;\n try {\n stat = statSync(fullPath);\n } catch {\n continue;\n }\n if (stat.isDirectory()) {\n if (entry.startsWith('.') || entry === 'bin' || entry === 'obj' || entry === 'test' || entry === 'tests') {\n continue;\n }\n results.push(...walkCSharpFiles(fullPath));\n } else if (entry.endsWith('.cs') && !entry.endsWith('Test.cs') && !entry.endsWith('Tests.cs')) {\n results.push(fullPath);\n }\n }\n return results.sort();\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/** Extract the namespace from a C# source file. */\nfunction extractNamespace(source: string): string {\n // File-scoped namespace (C# 10+): namespace Foo.Bar;\n const fileScopedMatch = source.match(/^namespace\\s+([\\w.]+)\\s*;/m);\n if (fileScopedMatch) return fileScopedMatch[1];\n\n // Block-scoped namespace: namespace Foo.Bar { ... }\n const blockMatch = source.match(/^namespace\\s+([\\w.]+)\\s*\\{/m);\n if (blockMatch) return blockMatch[1];\n\n return 'unknown';\n}\n\n/** Strip single-line and block comments from source. */\nfunction stripComments(source: string): string {\n let result = source.replace(/\\/\\*[\\s\\S]*?\\*\\//g, '');\n result = result.replace(/\\/\\/[^\\n]*/g, '');\n return result;\n}\n\n/** Extract [JsonProperty(\"name\")] value from text preceding a property. */\nfunction extractJsonPropertyName(text: string): string | null {\n const match = text.match(/\\[JsonProperty\\(\"([^\"]+)\"\\)\\]/);\n return match ? match[1] : null;\n}\n\n/** Extract [EnumMember(Value = \"name\")] value from text. */\nfunction extractEnumMemberValue(text: string): string | null {\n const match = text.match(/\\[EnumMember\\(Value\\s*=\\s*\"([^\"]+)\"\\)\\]/);\n return match ? match[1] : null;\n}\n\n// ---------------------------------------------------------------------------\n// Enum extraction\n// ---------------------------------------------------------------------------\n\nfunction parseEnums(source: string, sourceFile: string): CSharpEnum[] {\n const enums: CSharpEnum[] = [];\n const ns = extractNamespace(source);\n\n // Match: public enum Name { ... }\n const enumRegex = /public\\s+enum\\s+(\\w+)\\s*\\{([^}]*)\\}/g;\n let match;\n while ((match = enumRegex.exec(source)) !== null) {\n const name = match[1];\n const body = match[2];\n const members: Record<string, string> = {};\n\n // Split by commas and extract each member\n const lines = body.split(',');\n for (const line of lines) {\n const trimmed = line.trim();\n if (!trimmed) continue;\n\n const enumValue = extractEnumMemberValue(trimmed);\n const memberNameMatch = trimmed.match(/(\\w+)\\s*$/);\n if (memberNameMatch) {\n const memberName = memberNameMatch[1];\n members[memberName] = enumValue || memberName;\n }\n }\n\n if (Object.keys(members).length > 0) {\n enums.push({ name, namespace: ns, members, sourceFile });\n }\n }\n\n return enums;\n}\n\n// ---------------------------------------------------------------------------\n// Class extraction\n// ---------------------------------------------------------------------------\n\nfunction parseClasses(source: string, sourceFile: string): CSharpClass[] {\n const classes: CSharpClass[] = [];\n const ns = extractNamespace(source);\n\n // Match: public class Name { ... } — need to handle nested braces\n const classStartRegex = /public\\s+class\\s+(\\w+)(?:\\s*:\\s*[\\w.,\\s<>]+)?\\s*\\{/g;\n let match;\n while ((match = classStartRegex.exec(source)) !== null) {\n const name = match[1];\n const braceStart = source.indexOf('{', match.index + match[0].length - 1);\n\n // Find matching closing brace\n let depth = 1;\n let idx = braceStart + 1;\n while (idx < source.length && depth > 0) {\n if (source[idx] === '{') depth++;\n else if (source[idx] === '}') depth--;\n idx++;\n }\n\n const classBody = source.slice(braceStart + 1, idx - 1);\n\n // Parse properties\n const properties = parseProperties(classBody);\n\n // Parse methods\n const methods = parseMethods(classBody);\n\n // Parse constructor params\n const constructorParams = parseConstructor(classBody, name);\n\n // A class is a \"service\" if it has methods\n const isService = methods.length > 0;\n\n classes.push({\n name,\n namespace: ns,\n properties,\n methods,\n constructorParams,\n isService,\n sourceFile,\n });\n }\n\n return classes;\n}\n\n/** Parse properties from a class body. */\nfunction parseProperties(classBody: string): CSharpProperty[] {\n const properties: CSharpProperty[] = [];\n\n // Split into lines so we can look at annotations on the line above\n const lines = classBody.split('\\n');\n let pendingJsonName: string | null = null;\n\n for (const line of lines) {\n const trimmed = line.trim();\n\n // Check for JsonProperty annotation\n const jsonPropMatch = extractJsonPropertyName(trimmed);\n if (jsonPropMatch) {\n pendingJsonName = jsonPropMatch;\n continue;\n }\n\n // Match: public Type Name { get; set; } or public Type Name { get; }\n const propMatch = trimmed.match(/public\\s+(\\S+(?:<[^>]+>)?(?:\\?)?)\\s+(\\w+)\\s*\\{\\s*get;\\s*(set;\\s*)?\\}/);\n if (propMatch) {\n const type = propMatch[1];\n const name = propMatch[2];\n const hasSetter = !!propMatch[3];\n\n properties.push({\n name,\n type,\n jsonName: pendingJsonName || undefined,\n readonly: !hasSetter,\n });\n pendingJsonName = null;\n continue;\n }\n\n // Reset pending annotation if we hit a non-annotation, non-property line\n if (!trimmed.startsWith('[') && trimmed.length > 0) {\n pendingJsonName = null;\n }\n }\n\n return properties;\n}\n\n/** Parse methods from a class body. */\nfunction parseMethods(classBody: string): CSharpMethod[] {\n const methods: CSharpMethod[] = [];\n\n // Match: public [async] ReturnType MethodName(params)\n const methodRegex =\n /(private|protected|internal|public)\\s+(?:(static)\\s+)?(?:(async)\\s+)?(\\S+(?:<[^>]+>)?)\\s+(\\w+)\\s*\\(([^)]*)\\)/g;\n let match;\n while ((match = methodRegex.exec(classBody)) !== null) {\n const visibility = match[1];\n const isAsync = match[3] === 'async';\n const returnType = match[4];\n const name = match[5];\n const paramsStr = match[6];\n\n // Skip private/protected methods and constructors\n if (visibility === 'private' || visibility === 'protected') continue;\n\n const params: { name: string; type: string; optional: boolean }[] = [];\n if (paramsStr.trim()) {\n const paramParts = paramsStr.split(',');\n for (const part of paramParts) {\n const trimmed = part.trim();\n // Match: Type name or Type name = default\n const paramMatch = trimmed.match(/(\\S+(?:<[^>]+>)?(?:\\?)?)\\s+(\\w+)(?:\\s*=\\s*(.+))?/);\n if (paramMatch) {\n const paramType = paramMatch[1];\n const paramName = paramMatch[2];\n const hasDefault = paramMatch[3] !== undefined;\n params.push({\n name: paramName,\n type: paramType,\n optional: paramType.endsWith('?') || hasDefault,\n });\n }\n }\n }\n\n methods.push({\n name,\n params,\n returnType,\n visibility,\n isAsync,\n });\n }\n\n return methods;\n}\n\n/** Parse constructor parameters. */\nfunction parseConstructor(classBody: string, className: string): { name: string; type: string }[] {\n const params: { name: string; type: string }[] = [];\n\n // Match: public ClassName(params) — use indexOf to find the constructor\n const ctorPrefix = `public ${className}`;\n const ctorIdx = classBody.indexOf(ctorPrefix);\n if (ctorIdx < 0) return params;\n const afterCtor = classBody.slice(ctorIdx + ctorPrefix.length);\n const match = afterCtor.match(/^\\s*\\(([^)]*)\\)/);\n if (!match) return params;\n\n const paramsStr = match[1];\n if (!paramsStr.trim()) return params;\n\n const paramParts = paramsStr.split(',');\n for (const part of paramParts) {\n const trimmed = part.trim();\n const paramMatch = trimmed.match(/(\\S+(?:<[^>]+>)?)\\s+(\\w+)/);\n if (paramMatch) {\n params.push({ name: paramMatch[2], type: paramMatch[1] });\n }\n }\n\n return params;\n}\n\n// ---------------------------------------------------------------------------\n// Full file parser\n// ---------------------------------------------------------------------------\n\n/** Parse a single C# source file and return all extracted symbols. */\nexport function parseCSharpFile(filePath: string, sdkPath: string): ParsedCSharpFile {\n const source = readFileSync(filePath, 'utf-8');\n const relPath = relative(sdkPath, filePath);\n const cleaned = stripComments(source);\n\n return {\n classes: parseClasses(cleaned, relPath),\n enums: parseEnums(cleaned, relPath),\n };\n}\n","/**\n * DotNet (.NET/C#) surface builder — transforms parsed C# symbols into an ApiSurface.\n */\n\nimport type {\n ApiClass,\n ApiMethod,\n ApiParam,\n ApiProperty,\n ApiInterface,\n ApiField,\n ApiEnum,\n LanguageHints,\n} from '../types.js';\nimport type { CSharpClass, CSharpEnum } from './dotnet-parser.js';\nimport { sortRecord, ExportCollector } from './shared.js';\n\n// ---------------------------------------------------------------------------\n// Surface builder\n// ---------------------------------------------------------------------------\n\nexport function buildSurface(\n allClasses: CSharpClass[],\n allEnums: CSharpEnum[],\n _hints: LanguageHints,\n): {\n classes: Record<string, ApiClass>;\n interfaces: Record<string, ApiInterface>;\n enums: Record<string, ApiEnum>;\n exports: Record<string, string[]>;\n} {\n const classes: Record<string, ApiClass> = {};\n const interfaces: Record<string, ApiInterface> = {};\n const enums: Record<string, ApiEnum> = {};\n\n const collector = new ExportCollector();\n\n // Process classes\n for (const cls of allClasses) {\n if (cls.isService) {\n // Service class — has methods\n const methods: Record<string, ApiMethod[]> = {};\n const properties: Record<string, ApiProperty> = {};\n\n for (const method of cls.methods) {\n const params: ApiParam[] = method.params.map((p) => ({\n name: p.name,\n type: p.type,\n optional: p.optional,\n passingStyle: 'named' as const,\n }));\n\n if (!methods[method.name]) methods[method.name] = [];\n methods[method.name].push({\n name: method.name,\n params,\n returnType: method.returnType,\n async: method.isAsync,\n });\n }\n\n // Add public properties to service class\n for (const prop of cls.properties) {\n const propName = prop.jsonName || prop.name;\n properties[propName] = {\n name: propName,\n type: prop.type,\n readonly: prop.readonly,\n };\n }\n\n const constructorParams: ApiParam[] = cls.constructorParams.map((p) => ({\n name: p.name,\n type: p.type,\n optional: false,\n passingStyle: 'named' as const,\n }));\n\n classes[cls.name] = {\n name: cls.name,\n sourceFile: cls.sourceFile,\n methods: sortRecord(methods),\n properties: sortRecord(properties),\n constructorParams,\n };\n } else {\n // Data class — no methods, treat as interface\n const fields: Record<string, ApiField> = {};\n for (const prop of cls.properties) {\n const fieldName = prop.jsonName || prop.name;\n const isNullable = prop.type.endsWith('?');\n fields[fieldName] = {\n name: fieldName,\n type: prop.type,\n optional: isNullable,\n };\n }\n\n interfaces[cls.name] = {\n name: cls.name,\n sourceFile: cls.sourceFile,\n fields: sortRecord(fields),\n extends: [],\n };\n }\n collector.add(cls.sourceFile, cls.name);\n }\n\n // Process enums\n for (const en of allEnums) {\n enums[en.name] = {\n name: en.name,\n sourceFile: en.sourceFile,\n members: sortRecord(en.members),\n };\n collector.add(en.sourceFile, en.name);\n }\n\n const exports = collector.toRecord();\n\n return {\n classes: sortRecord(classes),\n interfaces: sortRecord(interfaces),\n enums: sortRecord(enums),\n exports: sortRecord(exports),\n };\n}\n","/**\n * DotNet (C#) API surface extractor.\n *\n * Walks `.cs` files (excluding test, bin, and obj directories), parses\n * classes, enums, properties, and methods, then builds an `ApiSurface`.\n *\n * Parser: `dotnet-parser.ts` — regex-based C# source analysis\n * Surface: `dotnet-surface.ts` — ApiSurface construction\n */\n\nimport { statSync } from 'node:fs';\nimport { resolve } from 'node:path';\nimport { ExtractorError } from '../../errors.js';\nimport type { Extractor, ApiSurface, LanguageHints } from '../types.js';\nimport type { CompatSnapshot } from '../ir.js';\nimport { apiSurfaceToSnapshot } from '../ir.js';\nimport {\n NAMED_TYPE_RE,\n typeExistsInSurface,\n namedTypeWordsOverlap,\n defaultIsNullableOnlyDifference,\n} from '../language-hints.js';\nimport { walkCSharpFiles, parseCSharpFile } from './dotnet-parser.js';\nimport { buildSurface } from './dotnet-surface.js';\nimport type { CSharpClass, CSharpEnum } from './dotnet-parser.js';\n\n// ---------------------------------------------------------------------------\n// Language hints\n// ---------------------------------------------------------------------------\n\nconst DOTNET_PRIMITIVE_TYPES = new Set(['string', 'int', 'long', 'float', 'double', 'bool', 'decimal']);\n\nconst dotnetHints: LanguageHints = {\n stripNullable(type: string): string | null {\n // Nullable<T> → T\n const nullableMatch = type.match(/^Nullable<(.+)>$/);\n if (nullableMatch) return nullableMatch[1];\n // T? → T\n if (type.endsWith('?')) return type.slice(0, -1);\n return null;\n },\n isNullableOnlyDifference(a: string, b: string): boolean {\n return defaultIsNullableOnlyDifference(this, a, b);\n },\n isUnionReorder(_a: string, _b: string): boolean {\n return false; // C# doesn't have union types\n },\n isGenericTypeParam(type: string): boolean {\n return /^[A-Z]$/.test(type) || /^T[A-Z][a-zA-Z]*$/.test(type);\n },\n isExtractionArtifact(type: string): boolean {\n return type === 'object' || type === 'dynamic';\n },\n tolerateCategoryMismatch: false,\n extractReturnTypeName(returnType: string): string | null {\n let inner = returnType;\n // Unwrap Task<T> → T\n const taskMatch = inner.match(/^Task<(.+)>$/);\n if (taskMatch) inner = taskMatch[1];\n // Unwrap Task → void\n if (inner === 'Task') return null;\n // Unwrap nullable\n if (inner.endsWith('?')) inner = inner.slice(0, -1);\n // Unwrap List<T> → T\n const listMatch = inner.match(/^(?:List|IList|IEnumerable|IReadOnlyList)<(.+)>$/);\n if (listMatch) inner = listMatch[1];\n // Primitives\n if (['string', 'int', 'long', 'float', 'double', 'bool', 'void', 'decimal'].includes(inner)) return null;\n return inner;\n },\n extractParamTypeName(paramType: string): string | null {\n let inner = paramType;\n if (inner.endsWith('?')) inner = inner.slice(0, -1);\n if (['string', 'int', 'long', 'float', 'double', 'bool', 'decimal'].includes(inner)) return null;\n return inner;\n },\n propertyMatchesClass(propertyName: string, className: string): boolean {\n return propertyName.toLowerCase() === className.toLowerCase();\n },\n derivedModelNames(modelName: string): string[] {\n return [`${modelName}Response`];\n },\n\n isTypeEquivalent(baselineType: string, candidateType: string, candidateSurface: ApiSurface): boolean {\n // Strip nullable from both sides for comparison\n const stripNullable = (t: string) => {\n if (t.endsWith('?')) return t.slice(0, -1);\n const m = t.match(/^Nullable<(.+)>$/);\n return m ? m[1] : t;\n };\n const baseClean = stripNullable(baselineType);\n const candClean = stripNullable(candidateType);\n\n // Map/dictionary equivalence: Dictionary<string, string> ≡ Dictionary<string, object>\n const dictPattern = /^Dictionary<string,\\s*(string|object|dynamic|Object)>$/;\n if (dictPattern.test(baseClean) && dictPattern.test(candClean)) {\n return true;\n }\n\n // Array notation equivalence: T[] ≡ List<T>\n const arrayMatch = baseClean.match(/^(.+)\\[\\]$/);\n const listMatch = candClean.match(/^(?:List|IList|IEnumerable|IReadOnlyList)<(.+)>$/);\n if (arrayMatch && listMatch) {\n // Compare inner types — allow named type tolerance\n const baseInner = arrayMatch[1];\n const candInner = listMatch[1];\n if (baseInner === candInner) return true;\n // Recurse for named type equivalence\n if (NAMED_TYPE_RE.test(baseInner) && NAMED_TYPE_RE.test(candInner)) {\n if (typeExistsInSurface(candInner, candidateSurface)) {\n if (candInner.includes(baseInner) || baseInner.includes(candInner)) return true;\n const baseNoResp = baseInner.replace(/Response$/, '');\n const candNoResp = candInner.replace(/Response$/, '');\n if (candNoResp.includes(baseNoResp) || baseNoResp.includes(candNoResp)) return true;\n // Word overlap\n if (namedTypeWordsOverlap(baseInner, candInner)) return true;\n }\n }\n // Tolerate model collection vs primitive collection: OrganizationDomain[] ≡ List<string>\n // The spec may define a field as a primitive array while the live SDK wraps it in a model.\n if (\n (DOTNET_PRIMITIVE_TYPES.has(baseInner) && NAMED_TYPE_RE.test(candInner)) ||\n (DOTNET_PRIMITIVE_TYPES.has(candInner) && NAMED_TYPE_RE.test(baseInner))\n ) {\n return true;\n }\n }\n // Also handle reverse: baseline is List<T>, candidate is T[]\n const baseListMatch = baseClean.match(/^(?:List|IList|IEnumerable|IReadOnlyList)<(.+)>$/);\n const candArrayMatch = candClean.match(/^(.+)\\[\\]$/);\n if (baseListMatch && candArrayMatch) {\n const baseInner = baseListMatch[1];\n const candInner = candArrayMatch[1];\n if (baseInner === candInner) return true;\n if (NAMED_TYPE_RE.test(baseInner) && NAMED_TYPE_RE.test(candInner)) {\n if (typeExistsInSurface(candInner, candidateSurface)) {\n if (candInner.includes(baseInner) || baseInner.includes(candInner)) return true;\n }\n }\n }\n\n // Generic container equivalence: List<T> vs List<U>, T[] vs U[]\n // where T and U are different named types for the same concept\n const genericPattern = /^(?:List|IList|IEnumerable|IReadOnlyList)<(.+)>$/;\n const baseGeneric = baseClean.match(genericPattern);\n const candGeneric = candClean.match(genericPattern);\n if (baseGeneric && candGeneric) {\n const baseInner = baseGeneric[1];\n const candInner = candGeneric[1];\n if (baseInner === candInner) return true;\n if (NAMED_TYPE_RE.test(baseInner) && NAMED_TYPE_RE.test(candInner)) {\n if (typeExistsInSurface(candInner, candidateSurface)) {\n if (candInner.includes(baseInner) || baseInner.includes(candInner)) return true;\n const baseNoResp = baseInner.replace(/Response$/, '');\n const candNoResp = candInner.replace(/Response$/, '');\n if (candNoResp.includes(baseNoResp) || baseNoResp.includes(candNoResp)) return true;\n if (namedTypeWordsOverlap(baseInner, candInner)) return true;\n }\n }\n }\n\n // Named type tolerance: different PascalCase names for the same concept\n // (e.g., EmailObject vs DirectoryUsersEmail, RoleResponse vs DirectoryUserRole)\n if (NAMED_TYPE_RE.test(baseClean) && NAMED_TYPE_RE.test(candClean)) {\n if (typeExistsInSurface(candClean, candidateSurface)) {\n if (candClean.includes(baseClean) || baseClean.includes(candClean)) return true;\n const baseNoResp = baseClean.replace(/Response$/, '');\n const candNoResp = candClean.replace(/Response$/, '');\n if (candNoResp.includes(baseNoResp) || baseNoResp.includes(candNoResp)) return true;\n // Word-component overlap\n if (namedTypeWordsOverlap(baseClean, candClean)) return true;\n }\n }\n\n // Numeric type equivalence: int ≡ double, long ≡ double (JSON numbers)\n const numericTypes = new Set(['int', 'long', 'float', 'double', 'decimal']);\n if (numericTypes.has(baseClean) && numericTypes.has(candClean)) return true;\n\n // Date type equivalence: DateTime ≡ string (spec uses string with date-time format)\n if ((baseClean === 'DateTime' && candClean === 'string') || (baseClean === 'string' && candClean === 'DateTime')) {\n return true;\n }\n\n // Enum name vs string equivalence (candidate has an enum, baseline says string)\n if (baseClean === 'string' && candidateSurface.enums[candClean]) return true;\n if (candClean === 'string' && candidateSurface.enums?.[baseClean]) return true;\n\n return false;\n },\n\n modelBaseClasses: [],\n exceptionBaseClasses: ['Exception'],\n};\n\n// ---------------------------------------------------------------------------\n// Extractor\n// ---------------------------------------------------------------------------\n\n/** Create a DotNet extractor with optional hint overrides. */\nexport function createDotnetExtractor(hintOverrides?: Partial<LanguageHints>): Extractor {\n const mergedHints: LanguageHints = hintOverrides ? { ...dotnetHints, ...hintOverrides } : dotnetHints;\n\n return {\n language: 'dotnet',\n hints: mergedHints,\n\n async extractSnapshot(sdkPath: string): Promise<CompatSnapshot> {\n const surface = await this.extract(sdkPath);\n return apiSurfaceToSnapshot(surface);\n },\n\n async extract(sdkPath: string): Promise<ApiSurface> {\n // Determine the source directory: prefer src/, fallback to root\n let sourceDir: string;\n const srcPath = resolve(sdkPath, 'src');\n\n try {\n statSync(srcPath);\n sourceDir = srcPath;\n } catch {\n sourceDir = sdkPath;\n }\n\n const csFiles = walkCSharpFiles(sourceDir);\n if (csFiles.length === 0) {\n throw new ExtractorError(\n `No .cs files found in ${sdkPath}`,\n `Ensure the --sdk-path argument points to a .NET project root containing .cs source files.`,\n );\n }\n\n const allClasses: CSharpClass[] = [];\n const allEnums: CSharpEnum[] = [];\n\n for (const filePath of csFiles) {\n const parsed = parseCSharpFile(filePath, sdkPath);\n allClasses.push(...parsed.classes);\n allEnums.push(...parsed.enums);\n }\n\n const { classes, interfaces, enums, exports } = buildSurface(allClasses, allEnums, mergedHints);\n\n return {\n language: 'dotnet',\n extractedFrom: sdkPath,\n extractedAt: new Date().toISOString(),\n classes,\n interfaces,\n typeAliases: {},\n enums,\n exports,\n };\n },\n };\n}\n\n/** Default DotNet extractor with generic language hints. */\nexport const dotnetExtractor: Extractor = createDotnetExtractor();\n","/**\n * Elixir source parser — regex-based extraction of modules, structs,\n * functions, and type specs from Elixir source files.\n */\n\nimport { readFileSync, readdirSync, statSync } from 'node:fs';\nimport { join, relative } from 'node:path';\n\n// ---------------------------------------------------------------------------\n// Internal types\n// ---------------------------------------------------------------------------\n\nexport interface ElixirStruct {\n moduleName: string;\n fields: string[];\n sourceFile: string;\n}\n\nexport interface ElixirFunction {\n moduleName: string;\n name: string;\n arity: number;\n params: string[];\n /** Per-param passing style: 'positional' or 'keyword' (for keyword list params). */\n paramStyles: ('positional' | 'keyword')[];\n isPrivate: boolean;\n sourceFile: string;\n}\n\nexport interface ElixirTypeSpec {\n moduleName: string;\n name: string;\n definition: string;\n sourceFile: string;\n}\n\nexport interface ElixirEnumModule {\n moduleName: string;\n members: Record<string, string>;\n sourceFile: string;\n}\n\nexport interface ParsedElixirFile {\n structs: ElixirStruct[];\n functions: ElixirFunction[];\n typeSpecs: ElixirTypeSpec[];\n enumModules: ElixirEnumModule[];\n moduleNames: string[];\n}\n\n// ---------------------------------------------------------------------------\n// File walker\n// ---------------------------------------------------------------------------\n\nexport function walkElixirFiles(dir: string): string[] {\n const results: string[] = [];\n let entries: string[];\n try {\n entries = readdirSync(dir);\n } catch {\n return results;\n }\n for (const entry of entries) {\n const fullPath = join(dir, entry);\n let stat;\n try {\n stat = statSync(fullPath);\n } catch {\n continue;\n }\n if (stat.isDirectory()) {\n if (entry.startsWith('.') || entry === '_build' || entry === 'deps' || entry === 'test') continue;\n results.push(...walkElixirFiles(fullPath));\n } else if (entry.endsWith('.ex') && !entry.endsWith('_test.exs')) {\n results.push(fullPath);\n }\n }\n return results.sort();\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Strip comments and heredoc strings from Elixir source code.\n * This prevents false matches of keywords like `do`/`end` inside strings\n * and doc comments.\n */\nfunction stripCommentsAndHeredocs(source: string): string {\n // Replace triple-quoted heredocs (@moduledoc \"\"\", @doc \"\"\", etc.)\n let result = source.replace(/\"\"\"[\\s\\S]*?\"\"\"/g, '\"\"\"\"\"\"');\n // Remove single-line comments\n result = result.replace(/#[^\\n]*/g, '');\n return result;\n}\n\n// ---------------------------------------------------------------------------\n// Module body extraction using line-based do/end counting\n// ---------------------------------------------------------------------------\n\n/**\n * Given the full source and the position right after `defmodule ... do`,\n * find the module body text up to the matching `end`.\n *\n * Uses a character-by-character scan that skips string literals and\n * counts block-level `do`/`end` keywords only when they appear as\n * standalone tokens (word boundaries).\n */\nfunction extractModuleBody(source: string, startIdx: number): string | null {\n let depth = 1;\n // Walk through source counting do/end as word boundaries\n // Skip strings (single and double quoted)\n let i = startIdx;\n while (i < source.length && depth > 0) {\n const ch = source[i];\n\n // Skip string literals\n if (ch === '\"') {\n i++;\n while (i < source.length && source[i] !== '\"') {\n if (source[i] === '\\\\') i++; // skip escaped char\n i++;\n }\n i++; // skip closing quote\n continue;\n }\n if (ch === \"'\") {\n i++;\n while (i < source.length && source[i] !== \"'\") {\n if (source[i] === '\\\\') i++;\n i++;\n }\n i++;\n continue;\n }\n\n // Check for word-boundary keywords\n // Only match `do` and `end` as full words (not `done`, `donut`, `endor`, etc.)\n if (isWordBoundary(source, i)) {\n if (source.slice(i, i + 2) === 'do' && isWordEnd(source, i + 2)) {\n // Make sure this is block `do`, not keyword `do:` form\n if (source[i + 2] !== ':') {\n depth++;\n }\n i += 2;\n continue;\n }\n if (source.slice(i, i + 2) === 'fn' && isWordEnd(source, i + 2)) {\n depth++;\n i += 2;\n continue;\n }\n if (source.slice(i, i + 3) === 'end' && isWordEnd(source, i + 3)) {\n depth--;\n if (depth === 0) {\n return source.slice(startIdx, i);\n }\n i += 3;\n continue;\n }\n }\n\n i++;\n }\n\n return null;\n}\n\nfunction isWordBoundary(source: string, idx: number): boolean {\n if (idx === 0) return true;\n const prev = source[idx - 1];\n return !/[a-zA-Z0-9_]/.test(prev);\n}\n\nfunction isWordEnd(source: string, idx: number): boolean {\n if (idx >= source.length) return true;\n return !/[a-zA-Z0-9_]/.test(source[idx]);\n}\n\n// ---------------------------------------------------------------------------\n// Module extraction\n// ---------------------------------------------------------------------------\n\ninterface ExtractedModule {\n name: string;\n body: string;\n}\n\n/** Find all defmodule blocks and extract their bodies in a single pass. */\nfunction extractModules(source: string): ExtractedModule[] {\n const modules: ExtractedModule[] = [];\n const moduleRegex = /defmodule\\s+([\\w.]+)\\s+do\\b/g;\n let match;\n while ((match = moduleRegex.exec(source)) !== null) {\n const body = extractModuleBody(source, match.index + match[0].length);\n if (body) {\n modules.push({ name: match[1], body });\n }\n }\n return modules;\n}\n\n// ---------------------------------------------------------------------------\n// Struct extraction\n// ---------------------------------------------------------------------------\n\nfunction extractStructs(modules: ExtractedModule[], sourceFile: string): ElixirStruct[] {\n const structs: ElixirStruct[] = [];\n\n for (const { name: moduleName, body: moduleBody } of modules) {\n // Look for defstruct inside this module\n const structMatch = moduleBody.match(/defstruct\\s+\\[([^\\]]*)\\]/);\n if (!structMatch) continue;\n\n const fieldsStr = structMatch[1];\n const fields: string[] = [];\n const fieldRegex = /:(\\w+)/g;\n let fieldMatch;\n while ((fieldMatch = fieldRegex.exec(fieldsStr)) !== null) {\n fields.push(fieldMatch[1]);\n }\n\n if (fields.length > 0) {\n structs.push({ moduleName, fields, sourceFile });\n }\n }\n\n return structs;\n}\n\n// ---------------------------------------------------------------------------\n// Function extraction\n// ---------------------------------------------------------------------------\n\nfunction extractFunctions(modules: ExtractedModule[], sourceFile: string): ElixirFunction[] {\n const functions: ElixirFunction[] = [];\n\n for (const { name: moduleName, body: moduleBody } of modules) {\n // Match both styles:\n // 1. Block: def name(params) do ... end\n // 2. Keyword: def name(params), do: ...\n // 3. Keyword no-args: def name, do: ...\n const funcRegex = /(def|defp)\\s+(\\w+)(?:\\(([^)]*)\\))?(?:\\s+do\\b|\\s*,\\s*do:)/g;\n let funcMatch;\n while ((funcMatch = funcRegex.exec(moduleBody)) !== null) {\n const isPrivate = funcMatch[1] === 'defp';\n const name = funcMatch[2];\n const paramsStr = funcMatch[3] || '';\n\n // Skip module/struct macros\n if (name === 'defstruct' || name === 'defmodule') continue;\n\n const params: string[] = [];\n const paramStyles: ('positional' | 'keyword')[] = [];\n if (paramsStr.trim()) {\n const paramParts = paramsStr.split(',');\n for (const part of paramParts) {\n const trimmed = part.trim();\n // Extract parameter name (before :: type annotation or \\\\ default)\n const paramNameMatch = trimmed.match(/^(\\w+)/);\n if (paramNameMatch) {\n params.push(paramNameMatch[1]);\n // Detect keyword list params: `opts \\\\ []` or `options \\\\ []`\n const isKeywordList = /\\\\\\\\\\s*\\[/.test(trimmed);\n paramStyles.push(isKeywordList ? 'keyword' : 'positional');\n }\n }\n }\n\n functions.push({\n moduleName,\n name,\n arity: params.length,\n params,\n paramStyles,\n isPrivate,\n sourceFile,\n });\n }\n }\n\n return functions;\n}\n\n// ---------------------------------------------------------------------------\n// Type spec extraction\n// ---------------------------------------------------------------------------\n\nfunction extractTypeSpecs(modules: ExtractedModule[], sourceFile: string): ElixirTypeSpec[] {\n const specs: ElixirTypeSpec[] = [];\n\n for (const { name: moduleName, body: moduleBody } of modules) {\n // Match @type t :: ... capturing multi-line definitions\n // The definition continues until we hit a blank line, a new @-attribute, or def/defstruct\n const typeRegex = /@type\\s+(\\w+)\\s*::\\s*/g;\n let typeMatch;\n while ((typeMatch = typeRegex.exec(moduleBody)) !== null) {\n const typeName = typeMatch[1];\n const defStart = typeMatch.index + typeMatch[0].length;\n\n // Find the end of the type definition:\n // It ends at a blank line, a new @attribute, def, defp, defstruct, or end-of-module\n let defEnd = defStart;\n let braceDepth = 0;\n for (let j = defStart; j < moduleBody.length; j++) {\n const ch = moduleBody[j];\n if (ch === '{') braceDepth++;\n else if (ch === '}') {\n braceDepth--;\n if (braceDepth < 0) break;\n if (braceDepth === 0) {\n defEnd = j + 1;\n break;\n }\n } else if (braceDepth === 0 && ch === '\\n') {\n // Check if next non-whitespace line starts a new declaration\n const remaining = moduleBody.slice(j + 1);\n const nextLineMatch = remaining.match(/^\\s*\\S/);\n if (nextLineMatch) {\n const nextContent = remaining.trimStart();\n if (\n nextContent.startsWith('@') ||\n nextContent.startsWith('def ') ||\n nextContent.startsWith('defp ') ||\n nextContent.startsWith('defstruct') ||\n nextContent.startsWith('defmodule')\n ) {\n defEnd = j;\n break;\n }\n } else {\n // Blank line — end of definition\n defEnd = j;\n break;\n }\n }\n defEnd = j + 1;\n }\n\n const definition = moduleBody.slice(defStart, defEnd).trim();\n specs.push({ moduleName, name: typeName, definition, sourceFile });\n }\n }\n\n return specs;\n}\n\n// ---------------------------------------------------------------------------\n// Enum module extraction\n// ---------------------------------------------------------------------------\n\nfunction extractEnumModules(modules: ExtractedModule[], sourceFile: string): ElixirEnumModule[] {\n const enumModules: ElixirEnumModule[] = [];\n\n for (const { name: moduleName, body: moduleBody } of modules) {\n // Check if this module has a `values` function (indicator of enum-like module)\n if (!moduleBody.match(/def\\s+values[\\s,]/)) continue;\n\n // Also verify there's no defstruct (structs aren't enums)\n if (moduleBody.match(/defstruct\\b/)) continue;\n\n const members: Record<string, string> = {};\n\n // Extract individual value functions: def name, do: \"value\"\n const valueFuncRegex = /def\\s+(\\w+),\\s*do:\\s*\"([^\"]+)\"/g;\n let valueFuncMatch;\n while ((valueFuncMatch = valueFuncRegex.exec(moduleBody)) !== null) {\n const funcName = valueFuncMatch[1];\n const funcValue = valueFuncMatch[2];\n if (funcName === 'values') continue;\n members[funcName] = funcValue;\n }\n\n if (Object.keys(members).length > 0) {\n enumModules.push({ moduleName, members, sourceFile });\n }\n }\n\n return enumModules;\n}\n\n// ---------------------------------------------------------------------------\n// Full file parser\n// ---------------------------------------------------------------------------\n\n/** Parse a single Elixir source file and return all extracted symbols. */\nexport function parseElixirFile(filePath: string, sdkPath: string): ParsedElixirFile {\n const source = readFileSync(filePath, 'utf-8');\n const relPath = relative(sdkPath, filePath);\n const cleaned = stripCommentsAndHeredocs(source);\n const modules = extractModules(cleaned);\n\n return {\n structs: extractStructs(modules, relPath),\n functions: extractFunctions(modules, relPath),\n typeSpecs: extractTypeSpecs(modules, relPath),\n enumModules: extractEnumModules(modules, relPath),\n moduleNames: modules.map((m) => m.name),\n };\n}\n","/**\n * Elixir surface builder — transforms parsed Elixir symbols into an ApiSurface.\n *\n * Elixir conventions:\n * - Data types (defstruct) → ApiInterface\n * - Modules with public functions → ApiClass\n * - Enum-like modules (with value functions) → ApiEnum\n */\n\nimport type { ApiClass, ApiMethod, ApiParam, ApiInterface, ApiField, ApiEnum } from '../types.js';\nimport type { ElixirStruct, ElixirFunction, ElixirEnumModule, ElixirTypeSpec } from './elixir-parser.js';\nimport { sortRecord, ExportCollector } from './shared.js';\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/** Get the short name from a fully qualified Elixir module name. */\nfunction shortName(moduleName: string): string {\n const parts = moduleName.split('.');\n return parts[parts.length - 1];\n}\n\n// ---------------------------------------------------------------------------\n// Surface builder\n// ---------------------------------------------------------------------------\n\nexport function buildSurface(\n allStructs: ElixirStruct[],\n allFunctions: ElixirFunction[],\n allEnumModules: ElixirEnumModule[],\n allTypeSpecs: ElixirTypeSpec[],\n): {\n classes: Record<string, ApiClass>;\n interfaces: Record<string, ApiInterface>;\n enums: Record<string, ApiEnum>;\n exports: Record<string, string[]>;\n} {\n const classes: Record<string, ApiClass> = {};\n const interfaces: Record<string, ApiInterface> = {};\n const enums: Record<string, ApiEnum> = {};\n\n const collector = new ExportCollector();\n\n // Collect struct module names so we can distinguish struct modules from service modules\n const structModuleNames = new Set(allStructs.map((s) => s.moduleName));\n const enumModuleNames = new Set(allEnumModules.map((e) => e.moduleName));\n\n // Process structs as interfaces\n for (const struct of allStructs) {\n const name = shortName(struct.moduleName);\n const fields: Record<string, ApiField> = {};\n\n // Build fields from struct keys — types come from @type spec if available\n const typeSpec = allTypeSpecs.find((ts) => ts.moduleName === struct.moduleName && ts.name === 't');\n\n for (const field of struct.fields) {\n // Try to extract type from the @type spec\n let fieldType = 'any';\n let optional = false;\n\n if (typeSpec) {\n // Parse the type definition to find this field's type\n const fieldPrefix = field + ':';\n const prefixIdx = typeSpec.definition.indexOf(fieldPrefix);\n const fieldTypeMatch =\n prefixIdx >= 0 ? typeSpec.definition.slice(prefixIdx + fieldPrefix.length).match(/^\\s*([^,}]+)/) : null;\n if (fieldTypeMatch) {\n fieldType = fieldTypeMatch[1].trim();\n // Check if nullable (contains | nil)\n if (fieldType.includes('| nil') || fieldType.includes('nil |')) {\n optional = true;\n fieldType = fieldType\n .replace(/\\s*\\|\\s*nil/g, '')\n .replace(/nil\\s*\\|\\s*/g, '')\n .trim();\n }\n }\n }\n\n fields[field] = {\n name: field,\n type: fieldType,\n optional,\n };\n }\n\n interfaces[name] = {\n name,\n sourceFile: struct.sourceFile,\n fields: sortRecord(fields),\n extends: [],\n };\n collector.add(struct.sourceFile, name);\n }\n\n // Process enum modules\n for (const enumModule of allEnumModules) {\n const name = shortName(enumModule.moduleName);\n enums[name] = {\n name,\n sourceFile: enumModule.sourceFile,\n members: sortRecord(enumModule.members),\n };\n collector.add(enumModule.sourceFile, name);\n }\n\n // Group public functions by module\n const funcsByModule = new Map<string, ElixirFunction[]>();\n for (const func of allFunctions) {\n if (func.isPrivate) continue;\n\n // Skip functions from struct modules (they are data, not services)\n // and enum modules (already handled)\n if (structModuleNames.has(func.moduleName) && !funcsByModule.has(func.moduleName)) {\n // Struct modules might still have functions, but only if they have\n // functions beyond just struct-related ones\n }\n if (enumModuleNames.has(func.moduleName)) continue;\n\n if (!funcsByModule.has(func.moduleName)) funcsByModule.set(func.moduleName, []);\n funcsByModule.get(func.moduleName)!.push(func);\n }\n\n // Convert function modules to classes\n for (const [moduleName, funcs] of funcsByModule) {\n // Skip if this is a struct-only module (no meaningful functions)\n if (structModuleNames.has(moduleName)) continue;\n\n const name = shortName(moduleName);\n const methods: Record<string, ApiMethod[]> = {};\n\n // Deduplicate by function name (Elixir allows multiple clauses)\n const seenFuncs = new Set<string>();\n for (const func of funcs) {\n if (seenFuncs.has(func.name)) continue;\n seenFuncs.add(func.name);\n\n const params: ApiParam[] = func.params.map((p, i) => ({\n name: p,\n type: 'any',\n optional: false,\n passingStyle: func.paramStyles[i] ?? ('positional' as const),\n }));\n\n if (!methods[func.name]) methods[func.name] = [];\n methods[func.name].push({\n name: func.name,\n params,\n returnType: 'any',\n async: false,\n });\n }\n\n if (Object.keys(methods).length > 0) {\n classes[name] = {\n name,\n sourceFile: funcs[0].sourceFile,\n methods: sortRecord(methods),\n properties: {},\n constructorParams: [],\n };\n collector.add(funcs[0].sourceFile, name);\n }\n }\n\n const exports = collector.toRecord();\n\n return {\n classes: sortRecord(classes),\n interfaces: sortRecord(interfaces),\n enums: sortRecord(enums),\n exports: sortRecord(exports),\n };\n}\n","/**\n * Elixir API surface extractor.\n *\n * Walks `.ex` files under `lib/` (the standard Elixir source directory),\n * parses modules, structs, functions, and type specs, then builds an\n * `ApiSurface`.\n *\n * Parser: `elixir-parser.ts` — regex-based Elixir source analysis\n * Surface: `elixir-surface.ts` — ApiSurface construction\n */\n\nimport { statSync } from 'node:fs';\nimport { resolve } from 'node:path';\nimport { ExtractorError } from '../../errors.js';\nimport type { Extractor, ApiSurface, LanguageHints } from '../types.js';\nimport type { CompatSnapshot } from '../ir.js';\nimport { apiSurfaceToSnapshot } from '../ir.js';\nimport { defaultIsNullableOnlyDifference } from '../language-hints.js';\nimport { walkElixirFiles, parseElixirFile } from './elixir-parser.js';\nimport { buildSurface } from './elixir-surface.js';\nimport type { ElixirStruct, ElixirFunction, ElixirEnumModule, ElixirTypeSpec } from './elixir-parser.js';\n\n// ---------------------------------------------------------------------------\n// Language hints\n// ---------------------------------------------------------------------------\n\nconst elixirHints: LanguageHints = {\n stripNullable(type: string): string | null {\n // T | nil → T\n if (type.includes('| nil')) return type.replace(/\\s*\\|\\s*nil/g, '').trim();\n if (type.includes('nil |')) return type.replace(/nil\\s*\\|\\s*/g, '').trim();\n return null;\n },\n isNullableOnlyDifference(a: string, b: string): boolean {\n return defaultIsNullableOnlyDifference(this, a, b);\n },\n isUnionReorder(a: string, b: string): boolean {\n // Parse pipe-separated types, sort, compare\n const sortParts = (t: string) =>\n t\n .split('|')\n .map((s) => s.trim())\n .sort()\n .join('|');\n return a !== b && sortParts(a) === sortParts(b);\n },\n isGenericTypeParam(type: string): boolean {\n // Elixir doesn't have generic type params in the same sense\n return type === 'any' || type === 'term';\n },\n isExtractionArtifact(type: string): boolean {\n return type === 'any' || type === 'term' || type === 'any()';\n },\n tolerateCategoryMismatch: true,\n extractReturnTypeName(returnType: string): string | null {\n let inner = returnType;\n // Unwrap {:ok, T} → T\n const okMatch = inner.match(/^\\{:ok,\\s*(.+)\\}$/);\n if (okMatch) inner = okMatch[1].trim();\n // Unwrap [T] → T\n const listMatch = inner.match(/^\\[(.+)\\]$/);\n if (listMatch) inner = listMatch[1].trim();\n // Primitives\n if (['any', 'term', 'atom', 'binary', 'boolean', 'integer', 'float', 'number', 'pid'].includes(inner)) {\n return null;\n }\n // String.t() → String\n const typeCallMatch = inner.match(/^(\\w+)\\.t\\(\\)$/);\n if (typeCallMatch) return typeCallMatch[1];\n return inner || null;\n },\n extractParamTypeName(paramType: string): string | null {\n if (\n ['any', 'term', 'atom', 'binary', 'boolean', 'integer', 'float', 'number', 'pid', 'keyword'].includes(paramType)\n ) {\n return null;\n }\n const typeCallMatch = paramType.match(/^(\\w+)\\.t\\(\\)$/);\n if (typeCallMatch) return typeCallMatch[1];\n return paramType;\n },\n propertyMatchesClass(propertyName: string, className: string): boolean {\n // snake_case → PascalCase comparison\n return propertyName.replace(/_/g, '').toLowerCase() === className.toLowerCase();\n },\n derivedModelNames(modelName: string): string[] {\n return [`${modelName}Response`];\n },\n};\n\n// ---------------------------------------------------------------------------\n// Extractor\n// ---------------------------------------------------------------------------\n\nexport const elixirExtractor: Extractor = {\n language: 'elixir',\n hints: elixirHints,\n\n async extractSnapshot(sdkPath: string): Promise<CompatSnapshot> {\n const surface = await this.extract(sdkPath);\n return apiSurfaceToSnapshot(surface);\n },\n\n async extract(sdkPath: string): Promise<ApiSurface> {\n // Determine the source directory: prefer lib/, fallback to root\n let sourceDir: string;\n const libPath = resolve(sdkPath, 'lib');\n\n try {\n statSync(libPath);\n sourceDir = libPath;\n } catch {\n sourceDir = sdkPath;\n }\n\n const exFiles = walkElixirFiles(sourceDir);\n if (exFiles.length === 0) {\n throw new ExtractorError(\n `No .ex files found in ${sdkPath}`,\n `Ensure the --sdk-path argument points to an Elixir project root containing .ex source files in lib/.`,\n );\n }\n\n const allStructs: ElixirStruct[] = [];\n const allFunctions: ElixirFunction[] = [];\n const allEnumModules: ElixirEnumModule[] = [];\n const allTypeSpecs: ElixirTypeSpec[] = [];\n\n for (const filePath of exFiles) {\n const parsed = parseElixirFile(filePath, sdkPath);\n allStructs.push(...parsed.structs);\n allFunctions.push(...parsed.functions);\n allEnumModules.push(...parsed.enumModules);\n allTypeSpecs.push(...parsed.typeSpecs);\n }\n\n const { classes, interfaces, enums, exports } = buildSurface(\n allStructs,\n allFunctions,\n allEnumModules,\n allTypeSpecs,\n );\n\n return {\n language: 'elixir',\n extractedFrom: sdkPath,\n extractedAt: new Date().toISOString(),\n classes,\n interfaces,\n typeAliases: {},\n enums,\n exports,\n };\n },\n};\n"],"mappings":"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"}
|