@workos/oagen 0.2.0 → 0.3.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.
@@ -1 +1 @@
1
- {"version":3,"file":"smoke.mjs","names":[],"sources":["../src/utils/naming.ts","../src/errors.ts","../src/parser/refs.ts","../src/ir/types.ts","../src/parser/inline-models.ts","../src/parser/schemas.ts","../src/parser/pagination.ts","../src/parser/responses.ts","../src/parser/operations.ts","../src/parser/normalize-inline-models.ts","../src/parser/collect-inline-enums.ts","../src/parser/normalize-model-refs.ts","../src/parser/parse.ts","../scripts/smoke/shared.ts"],"sourcesContent":["/**\n * Split a string into words, handling:\n * - camelCase / PascalCase boundaries\n * - snake_case / kebab-case separators\n * - Consecutive capitals (e.g., \"HTTPClient\" → [\"HTTP\", \"Client\"])\n * - Numbers as word boundaries (e.g., \"OAuth2Token\" → [\"OAuth\", \"2\", \"Token\"])\n */\nexport function splitWords(s: string): string[] {\n if (!s) return [];\n\n return s\n .replace(/[^a-zA-Z0-9_\\-\\s.]/g, '_') // replace non-alphanumeric chars with separator\n .replace(/([a-z])([A-Z])/g, '$1\\0$2') // camelCase boundary\n .replace(/([A-Z]+)([A-Z][a-z])/g, '$1\\0$2') // consecutive caps boundary\n .replace(/([a-zA-Z])(\\d)/g, '$1\\0$2') // letter to number\n .replace(/(\\d)([a-zA-Z])/g, '$1\\0$2') // number to letter\n .split(/[\\0_\\-\\s.]+/)\n .filter((w) => w.length > 0);\n}\n\nexport const ACRONYM_SET = new Set(['SSO', 'FGA', 'SAML', 'SCIM', 'JWT', 'HMAC']);\n\nexport function toPascalCase(s: string, acronyms?: Set<string>): string {\n const merged = acronyms ? new Set([...ACRONYM_SET, ...acronyms]) : ACRONYM_SET;\n return splitWords(s)\n .map((w) => {\n const upper = w.toUpperCase();\n if (merged.has(upper)) return upper;\n // Special case: OAuth should stay as OAuth, not OAUTH\n if (upper === 'OAUTH') return 'OAuth';\n return w.charAt(0).toUpperCase() + w.slice(1).toLowerCase();\n })\n .join('');\n}\n\nexport function toCamelCase(s: string, acronyms?: Set<string>): string {\n const merged = acronyms ? new Set([...ACRONYM_SET, ...acronyms]) : ACRONYM_SET;\n const words = splitWords(s);\n if (words.length === 0) return '';\n return words\n .map((w, i) => {\n if (i === 0) return w.toLowerCase();\n const upper = w.toUpperCase();\n if (merged.has(upper)) return upper;\n if (upper === 'OAUTH') return 'OAuth';\n return w.charAt(0).toUpperCase() + w.slice(1).toLowerCase();\n })\n .join('');\n}\n\nexport function toSnakeCase(s: string): string {\n return splitWords(s)\n .map((w) => w.toLowerCase())\n .join('_');\n}\n\nexport function toKebabCase(s: string): string {\n return splitWords(s)\n .map((w) => w.toLowerCase())\n .join('-');\n}\n\nexport function toUpperSnakeCase(s: string): string {\n return splitWords(s)\n .map((w) => w.toUpperCase())\n .join('_');\n}\n\nconst BACKEND_SUFFIXES = ['Dto', 'DTO', 'Controller'];\n\nexport function stripBackendSuffixes(name: string): string {\n for (const suffix of BACKEND_SUFFIXES) {\n if (name.endsWith(suffix) && name.length > suffix.length) {\n return name.slice(0, -suffix.length);\n }\n }\n return name;\n}\n\nexport function stripBackendPrefixes(name: string): string {\n return name.replace(/Userland/g, '').replace(/Controller/g, '');\n}\n\n/**\n * Remove ListItem / ByExternalId / ByResourceId / ForResource markers from PascalCase names.\n * E.g. \"DirectoriesListItemState\" → \"DirectoriesState\"\n */\nexport function stripListItemMarkers(name: string): string {\n return name\n .replace(/ListItem/g, '')\n .replace(/ByExternalId/g, '')\n .replace(/ByResourceId/g, '')\n .replace(/ForResource/g, '');\n}\n\n/** Words that look plural but must NOT be singularized. */\nconst SINGULAR_SAFE_LIST = new Set([\n 'Status',\n 'Address',\n 'Access',\n 'Process',\n 'Progress',\n 'Success',\n 'Radius',\n 'Canvas',\n 'Alias',\n 'Basis',\n 'Bus',\n]);\n\n/**\n * Conservative singularize for the leading PascalCase word.\n * Only applied to the first word of a PascalCase name (the resource word).\n * - `ies` → `y` (e.g. Directories → Directory)\n * - trailing `s` for words >4 chars (e.g. Organizations → Organization)\n * Safe-listed words are never singularized.\n */\nexport function singularize(word: string): string {\n if (SINGULAR_SAFE_LIST.has(word)) return word;\n if (word.endsWith('ies') && word.length > 4) {\n return word.slice(0, -3) + 'y';\n }\n if (word.endsWith('ses') && word.length > 4) {\n // e.g. \"Processes\" — but \"Process\" is safe-listed, this handles non-safe ones\n return word.slice(0, -2);\n }\n if (word.endsWith('s') && !word.endsWith('ss') && word.length > 4) {\n return word.slice(0, -1);\n }\n return word;\n}\n\n/**\n * Compose all backend name cleaning transforms in order:\n * 1. Strip backend prefixes (Userland, Controller)\n * 2. Strip backend suffixes (Dto, DTO, Controller)\n * 3. Strip ListItem / ByExternalId markers\n * 4. Singularize leading resource word\n *\n * Must be idempotent: `cleanSchemaName(cleanSchemaName(x)) === cleanSchemaName(x)`\n */\n/** Strip `.js` extensions from import/export specifiers for dedup comparison. */\nexport function normalizeJsExtension(text: string): string {\n return text.replace(/\\.js(['\"])/g, '$1');\n}\n\nexport function cleanSchemaName(name: string): string {\n let result = stripBackendPrefixes(stripBackendSuffixes(name));\n result = stripListItemMarkers(result);\n\n // Singularize the leading PascalCase word\n const match = result.match(/^([A-Z][a-z]*)/);\n if (match) {\n const leadWord = match[1];\n const singular = singularize(leadWord);\n if (singular !== leadWord) {\n result = singular + result.slice(leadWord.length);\n }\n }\n\n return result;\n}\n","/**\n * Structured error hierarchy for oagen.\n *\n * Every error carries a human-readable `hint` that suggests a recovery action.\n * The hint is appended to the `message` so it appears in stack traces and logs.\n */\n\n/** Base class for all oagen errors. */\nexport class OagenError extends Error {\n readonly hint: string;\n\n constructor(message: string, hint: string) {\n const fullMessage = hint ? `${message}\\nHint: ${hint}` : message;\n super(fullMessage);\n this.name = 'OagenError';\n this.hint = hint;\n }\n}\n\n/** Thrown when a command should terminate with a specific exit code. */\nexport class CommandError extends OagenError {\n readonly exitCode: number;\n\n constructor(message: string, hint: string, exitCode: number) {\n super(message, hint);\n this.name = 'CommandError';\n this.exitCode = exitCode;\n }\n}\n\n/** Thrown when an OpenAPI spec cannot be parsed or has an unsupported version. */\nexport class SpecParseError extends OagenError {\n constructor(message: string, hint: string) {\n super(message, hint);\n this.name = 'SpecParseError';\n }\n}\n\n/** Thrown when configuration files (manifests, API surfaces, overlays) are missing or malformed. */\nexport class ConfigError extends OagenError {\n constructor(message: string, hint: string) {\n super(message, hint);\n this.name = 'ConfigError';\n }\n}\n\n/** Thrown when a config file exists but cannot be loaded or evaluated. */\nexport class ConfigLoadError extends ConfigError {\n constructor(message: string, hint: string) {\n super(message, hint);\n this.name = 'ConfigLoadError';\n }\n}\n\n/** Thrown when a config targets a different IR version than the installed package. */\nexport class ConfigVersionMismatchError extends ConfigError {\n constructor(message: string, hint: string) {\n super(message, hint);\n this.name = 'ConfigVersionMismatchError';\n }\n}\n\n/** Thrown when an API surface extractor encounters a problem. */\nexport class ExtractorError extends OagenError {\n constructor(message: string, hint: string) {\n super(message, hint);\n this.name = 'ExtractorError';\n }\n}\n\n/** Thrown when a requested language or extractor is not found in a registry. */\nexport class RegistryError extends OagenError {\n constructor(message: string, hint: string) {\n super(message, hint);\n this.name = 'RegistryError';\n }\n}\n\n/** Thrown for internal invariant violations that indicate a bug. */\nexport class InternalError extends OagenError {\n constructor(message: string, hint: string) {\n super(message, hint);\n this.name = 'InternalError';\n }\n}\n","import { readFile } from 'node:fs/promises';\nimport { resolve } from 'node:path';\nimport { pathToFileURL } from 'node:url';\nimport { makeDocumentFromString, bundleDocument, createConfig, BaseResolver } from '@redocly/openapi-core';\nimport { SpecParseError } from '../errors.js';\n\nexport interface BundledSpec {\n parsed: Record<string, unknown>;\n specPath: string;\n}\n\nexport async function loadAndBundleSpec(specPath: string): Promise<BundledSpec> {\n const absolutePath = resolve(specPath);\n const content = await readFile(absolutePath, 'utf-8');\n const document = makeDocumentFromString(content, pathToFileURL(absolutePath).href);\n\n const config = await createConfig({});\n const resolver = new BaseResolver();\n\n const result = await bundleDocument({\n document,\n config: config.styleguide,\n externalRefResolver: resolver,\n dereference: false,\n });\n\n if (result.problems.some((p) => p.severity === 'error')) {\n const errors = result.problems\n .filter((p) => p.severity === 'error')\n .map((p) => p.message)\n .join('\\n');\n throw new SpecParseError(\n `Failed to parse spec: ${errors}`,\n `Check the OpenAPI spec at \"${absolutePath}\" for syntax errors. Run a linter such as \\`npx @redocly/cli lint ${specPath}\\` to identify issues.`,\n );\n }\n\n return {\n parsed: result.bundle.parsed as Record<string, unknown>,\n specPath: absolutePath,\n };\n}\n","/** Authentication scheme extracted from OpenAPI securitySchemes */\nexport type AuthScheme =\n | { kind: 'bearer' }\n | { kind: 'apiKey'; in: 'header' | 'query' | 'cookie'; name: string }\n | { kind: 'oauth2'; flows: Record<string, unknown> };\n\n/** Root IR node representing the full API surface */\n/** A server entry from the OpenAPI servers array */\nexport interface ServerEntry {\n url: string;\n description?: string;\n}\n\n/** Root IR node representing the full API surface */\nexport interface ApiSpec {\n name: string;\n version: string;\n description?: string;\n baseUrl: string;\n servers?: ServerEntry[];\n services: Service[];\n models: Model[];\n enums: Enum[];\n auth?: AuthScheme[];\n}\n\n/** A service groups related operations (maps to an SDK resource class) */\nexport interface Service {\n name: string;\n description?: string;\n operations: Operation[];\n}\n\n/** A single API operation (maps to an SDK method) */\nexport interface Operation {\n name: string;\n description?: string;\n httpMethod: HttpMethod;\n path: string;\n pathParams: Parameter[];\n queryParams: Parameter[];\n headerParams: Parameter[];\n cookieParams?: Parameter[];\n requestBody?: TypeRef;\n requestBodyEncoding?: 'json' | 'form-data' | 'form-urlencoded' | 'binary' | 'text';\n response: TypeRef;\n successResponses?: SuccessResponse[];\n errors: ErrorResponse[];\n pagination?: PaginationMeta;\n injectIdempotencyKey: boolean;\n deprecated?: boolean;\n async?: boolean;\n}\n\n/** Structured pagination metadata for auto-paging iterator generation */\nexport interface PaginationMeta {\n strategy: 'cursor' | 'offset' | 'link-header';\n param: string;\n limitParam?: string;\n dataPath?: string;\n itemType: TypeRef;\n}\n\nexport type HttpMethod = 'get' | 'post' | 'put' | 'patch' | 'delete' | 'head' | 'options' | 'trace';\n\nexport interface Parameter {\n name: string;\n type: TypeRef;\n required: boolean;\n description?: string;\n deprecated?: boolean;\n default?: unknown;\n example?: unknown;\n}\n\n/** Type reference — the core type system of the IR */\nexport type TypeRef = PrimitiveType | ArrayType | ModelRef | EnumRef | UnionType | NullableType | LiteralType | MapType;\n\nexport interface PrimitiveType {\n kind: 'primitive';\n type: 'string' | 'integer' | 'number' | 'boolean' | 'unknown';\n format?: string;\n}\n\nexport interface ArrayType {\n kind: 'array';\n items: TypeRef;\n}\n\nexport interface ModelRef {\n kind: 'model';\n name: string;\n}\n\nexport interface EnumRef {\n kind: 'enum';\n name: string;\n values?: (string | number)[];\n}\n\nexport interface LiteralType {\n kind: 'literal';\n value: string | number | boolean | null;\n}\n\nexport interface UnionType {\n kind: 'union';\n variants: TypeRef[];\n discriminator?: { property: string; mapping: Record<string, string> };\n /** Which OAS composition keyword produced this union. Emitters can use this to\n * distinguish inheritance (allOf) from exclusive union (oneOf) from open union (anyOf). */\n compositionKind?: 'allOf' | 'oneOf' | 'anyOf';\n}\n\nexport interface NullableType {\n kind: 'nullable';\n inner: TypeRef;\n}\n\nexport interface MapType {\n kind: 'map';\n valueType: TypeRef;\n keyType?: TypeRef;\n}\n\n/**\n * A generic type parameter on a model.\n * Example: `DirectoryUser<TCustomAttributes = Record<string, unknown>>`\n * → `{ name: 'TCustomAttributes', default: { kind: 'map', valueType: { kind: 'primitive', type: 'unknown' } } }`\n */\nexport interface TypeParam {\n name: string;\n /** Default type when the param is not specified. */\n default?: TypeRef;\n}\n\n/** Model definition (maps to an SDK model/data class) */\nexport interface Model {\n name: string;\n description?: string;\n fields: Field[];\n /** Generic type parameters. Empty/undefined for non-generic models. */\n typeParams?: TypeParam[];\n}\n\nexport interface Field {\n name: string;\n type: TypeRef;\n required: boolean;\n description?: string;\n readOnly?: boolean;\n writeOnly?: boolean;\n deprecated?: boolean;\n default?: unknown;\n example?: unknown;\n}\n\n/** Enum definition */\nexport interface Enum {\n name: string;\n values: EnumValue[];\n}\n\nexport interface EnumValue {\n name: string;\n value: string | number;\n description?: string;\n deprecated?: boolean;\n}\n\n/**\n * Exhaustive check helper for TypeRef switches.\n * If a new kind is added to TypeRef, any switch that doesn't handle it\n * will fail to compile because `never` won't accept the unhandled variant.\n *\n * Usage:\n * switch (ref.kind) {\n * case 'primitive': ...\n * case 'array': ...\n * // If you forget 'literal', TypeScript errors here:\n * default: assertNever(ref);\n * }\n */\nexport function assertNever(x: never): never {\n // Inline to avoid importing from ../errors.js (ir/ is layer 0, must not import upward)\n const kind = (x as TypeRef).kind;\n const err = new Error(\n `Unexpected TypeRef kind: ${kind}\\nHint: If you added a new TypeRef variant, handle it in every switch/case that calls assertNever.`,\n );\n err.name = 'InternalError';\n throw err;\n}\n\n/**\n * Generic depth-first walker for TypeRef trees.\n * Handles recursion into array/nullable/union/map children and provides\n * an exhaustive `assertNever` check so callers don't need to repeat the\n * switch boilerplate. Supply callbacks only for the leaf kinds you care about.\n */\nexport function walkTypeRef(\n ref: TypeRef,\n visitor: {\n model?: (ref: ModelRef) => void;\n enum?: (ref: EnumRef) => void;\n primitive?: (ref: PrimitiveType) => void;\n literal?: (ref: LiteralType) => void;\n },\n): void {\n switch (ref.kind) {\n case 'model':\n visitor.model?.(ref);\n break;\n case 'enum':\n visitor.enum?.(ref);\n break;\n case 'array':\n walkTypeRef(ref.items, visitor);\n break;\n case 'nullable':\n walkTypeRef(ref.inner, visitor);\n break;\n case 'union':\n for (const v of ref.variants) walkTypeRef(v, visitor);\n break;\n case 'map':\n if (ref.keyType) walkTypeRef(ref.keyType, visitor);\n walkTypeRef(ref.valueType, visitor);\n break;\n case 'literal':\n visitor.literal?.(ref);\n break;\n case 'primitive':\n visitor.primitive?.(ref);\n break;\n default:\n assertNever(ref);\n }\n}\n\n/**\n * Generic depth-first mapper for TypeRef trees.\n * Like walkTypeRef but returns a transformed value instead of void.\n * Handles recursion into array/nullable/union/map children, passing\n * already-mapped child values to the parent callback.\n */\nexport function mapTypeRef<T>(\n ref: TypeRef,\n mapper: {\n primitive: (ref: PrimitiveType) => T;\n array: (ref: ArrayType, mappedItems: T) => T;\n model: (ref: ModelRef) => T;\n enum: (ref: EnumRef) => T;\n union: (ref: UnionType, mappedVariants: T[]) => T;\n nullable: (ref: NullableType, mappedInner: T) => T;\n literal: (ref: LiteralType) => T;\n map: (ref: MapType, mappedValue: T, mappedKey?: T) => T;\n },\n): T {\n switch (ref.kind) {\n case 'primitive':\n return mapper.primitive(ref);\n case 'array':\n return mapper.array(ref, mapTypeRef(ref.items, mapper));\n case 'model':\n return mapper.model(ref);\n case 'enum':\n return mapper.enum(ref);\n case 'union':\n return mapper.union(\n ref,\n ref.variants.map((v) => mapTypeRef(v, mapper)),\n );\n case 'nullable':\n return mapper.nullable(ref, mapTypeRef(ref.inner, mapper));\n case 'literal':\n return mapper.literal(ref);\n case 'map':\n return mapper.map(\n ref,\n mapTypeRef(ref.valueType, mapper),\n ref.keyType ? mapTypeRef(ref.keyType, mapper) : undefined,\n );\n default:\n return assertNever(ref);\n }\n}\n\n// --- IR traversal utilities ---\n\n/**\n * Collect all model names referenced (directly or transitively) by a TypeRef.\n */\nexport function collectModelRefs(ref: TypeRef): string[] {\n const names: string[] = [];\n walkTypeRef(ref, { model: (r) => names.push(r.name) });\n return names;\n}\n\n/**\n * Collect all enum names referenced by a TypeRef.\n */\nexport function collectEnumRefs(ref: TypeRef): string[] {\n const names: string[] = [];\n walkTypeRef(ref, { enum: (r) => names.push(r.name) });\n return names;\n}\n\n/**\n * Collect all TypeRef-referenced model and enum names from a model's fields.\n * Returns { models, enums } sets for generating import statements.\n */\nexport function collectFieldDependencies(model: Model): {\n models: Set<string>;\n enums: Set<string>;\n} {\n const models = new Set<string>();\n const enums = new Set<string>();\n\n for (const field of model.fields) {\n for (const name of collectModelRefs(field.type)) {\n if (name !== model.name) models.add(name);\n }\n for (const name of collectEnumRefs(field.type)) {\n enums.add(name);\n }\n }\n\n return { models, enums };\n}\n\n/**\n * Assign each model to the service that first references it.\n * Models referenced by multiple services are assigned to the first.\n * Models not referenced by any service are unassigned (absent from the map).\n */\nexport function assignModelsToServices(models: Model[], services: Service[]): Map<string, string> {\n const modelToService = new Map<string, string>();\n const modelNames = new Set(models.map((m) => m.name));\n\n for (const service of services) {\n const referencedModels = new Set<string>();\n\n for (const op of service.operations) {\n if (op.requestBody) {\n for (const name of collectModelRefs(op.requestBody)) {\n referencedModels.add(name);\n }\n }\n for (const name of collectModelRefs(op.response)) {\n referencedModels.add(name);\n }\n for (const param of [...op.pathParams, ...op.queryParams, ...op.headerParams, ...(op.cookieParams ?? [])]) {\n for (const name of collectModelRefs(param.type)) {\n referencedModels.add(name);\n }\n }\n if (op.pagination) {\n for (const name of collectModelRefs(op.pagination.itemType)) {\n referencedModels.add(name);\n }\n }\n }\n\n // Transitively collect models referenced by the directly-referenced models\n const toVisit = [...referencedModels];\n while (toVisit.length > 0) {\n const name = toVisit.pop()!;\n const model = models.find((m) => m.name === name);\n if (!model) continue;\n for (const field of model.fields) {\n for (const ref of collectModelRefs(field.type)) {\n if (!referencedModels.has(ref) && modelNames.has(ref)) {\n referencedModels.add(ref);\n toVisit.push(ref);\n }\n }\n }\n }\n\n for (const name of referencedModels) {\n if (!modelToService.has(name)) {\n modelToService.set(name, service.name);\n }\n }\n }\n\n return modelToService;\n}\n\n/**\n * Collect all model names referenced as request bodies across all services.\n */\nexport function collectRequestBodyModels(services: Service[]): Set<string> {\n const result = new Set<string>();\n for (const service of services) {\n for (const op of service.operations) {\n if (op.requestBody) {\n for (const name of collectModelRefs(op.requestBody)) {\n result.add(name);\n }\n }\n }\n }\n return result;\n}\n\nexport interface ErrorResponse {\n statusCode: number;\n type?: TypeRef;\n}\n\n/** A successful response entry from a 2xx status code */\nexport interface SuccessResponse {\n statusCode: number;\n type: TypeRef;\n}\n","import type { Model, Field } from '../ir/types.js';\nimport { toPascalCase, cleanSchemaName, stripListItemMarkers, singularize } from '../utils/naming.js';\nimport type { SchemaObject } from './schemas.js';\nimport { buildFieldFromSchema } from './schemas.js';\n\n/**\n * Qualify an inline model name with the parent schema name.\n * If `parentName` is provided and the field name doesn't already start with\n * the parent, the result is `${parentName}${PascalField}` with the trailing\n * word singularized (e.g., Connection + Domains → ConnectionDomain).\n */\nexport function qualifyInlineModelName(baseName: string, parentName?: string): string {\n if (!parentName) return baseName;\n // Strip ListItem/ByExternalId markers from parent name so inline model names\n // are clean and match the names produced by qualifyNestedName() in responses.ts.\n // e.g., ConnectionListItem + Domains → Connection + Domain = ConnectionDomain\n const cleanParent = stripListItemMarkers(parentName);\n if (baseName.startsWith(cleanParent)) return baseName;\n // Singularize the trailing PascalCase word of the combined name.\n // Split baseName into leading words + trailing word, singularize trailing.\n const trailingMatch = baseName.match(/^(.*?)([A-Z][a-z]*)$/);\n if (trailingMatch) {\n const [, prefix, trailingWord] = trailingMatch;\n const singular = singularize(trailingWord);\n return `${cleanParent}${prefix}${singular}`;\n }\n return `${cleanParent}${baseName}`;\n}\n\n/**\n * Walk all component schemas and extract inline Model definitions for fields\n * that are objects with properties (or arrays of such objects).\n * These correspond to the ModelRef entries created by schemaToTypeRef.\n */\nexport function extractInlineModelsFromSchemas(schemas: Record<string, SchemaObject> | undefined): Model[] {\n if (!schemas) return [];\n\n const inlineModels: Model[] = [];\n\n for (const [schemaName, schema] of Object.entries(schemas)) {\n const parentName = cleanSchemaName(toPascalCase(schemaName));\n extractInlineModelsFromProperties(schema, inlineModels, parentName);\n }\n\n return inlineModels;\n}\n\nfunction extractInlineModelsFromProperties(schema: SchemaObject, results: Model[], parentName?: string): void {\n const properties = schema.properties ?? {};\n const allOfSchemas = schema.allOf ?? [];\n\n for (const sub of allOfSchemas) {\n if (sub.properties) {\n extractInlineModelsFromProperties(sub, results, parentName);\n }\n }\n\n for (const [fieldName, fieldSchema] of Object.entries(properties)) {\n if (!fieldSchema) continue;\n // Direct inline object with properties (with or without explicit type: 'object')\n if (fieldSchema.properties && (fieldSchema.type === 'object' || !fieldSchema.type)) {\n const baseName = toPascalCase(fieldName);\n const modelName = qualifyInlineModelName(baseName, parentName);\n results.push(buildInlineModel(modelName, fieldSchema));\n extractInlineModelsFromProperties(fieldSchema, results, modelName);\n }\n\n // Array of inline objects\n if (fieldSchema.type === 'array' && fieldSchema.items) {\n const items = fieldSchema.items;\n if (items.properties && (items.type === 'object' || !items.type)) {\n const baseName = toPascalCase(fieldName);\n const modelName = qualifyInlineModelName(baseName, parentName);\n results.push(buildInlineModel(modelName, items));\n extractInlineModelsFromProperties(items, results, modelName);\n }\n }\n\n // oneOf containing objects — extract the first non-null variant as a model\n // This handles: totp: { oneOf: [{ type: object, properties: {...} }, { type: 'null' }] }\n if (fieldSchema.oneOf) {\n const objectVariant = fieldSchema.oneOf.find((v) => v.properties && (v.type === 'object' || !v.type));\n if (objectVariant) {\n const baseName = toPascalCase(fieldName);\n const modelName = qualifyInlineModelName(baseName, parentName);\n const existingNames = new Set(results.map((r) => r.name));\n if (!existingNames.has(modelName)) {\n results.push(buildInlineModel(modelName, objectVariant));\n extractInlineModelsFromProperties(objectVariant, results, modelName);\n }\n }\n }\n }\n}\n\nfunction buildInlineModel(name: string, schema: SchemaObject): Model {\n const requiredSet = new Set(schema.required ?? []);\n const fields: Field[] = [];\n\n for (const [fieldName, fieldSchema] of Object.entries(schema.properties ?? {})) {\n if (!fieldSchema) continue;\n fields.push(buildFieldFromSchema(fieldName, fieldSchema, name, requiredSet));\n }\n\n return { name, description: schema.description, fields };\n}\n","import type { Model, Enum, EnumValue, Field, TypeRef } from '../ir/types.js';\nimport { walkTypeRef } from '../ir/types.js';\nimport { toPascalCase, toUpperSnakeCase, cleanSchemaName, stripListItemMarkers } from '../utils/naming.js';\n\nexport interface SchemaObject {\n type?: string | string[];\n format?: string;\n description?: string;\n properties?: Record<string, SchemaObject | undefined>;\n required?: string[];\n items?: SchemaObject;\n enum?: (string | number)[];\n allOf?: SchemaObject[];\n oneOf?: SchemaObject[];\n anyOf?: SchemaObject[];\n discriminator?: { propertyName: string; mapping?: Record<string, string> };\n readOnly?: boolean;\n writeOnly?: boolean;\n nullable?: boolean;\n $ref?: string;\n additionalProperties?: boolean | SchemaObject;\n const?: unknown;\n patternProperties?: Record<string, SchemaObject>;\n deprecated?: boolean;\n default?: unknown;\n example?: unknown;\n [key: string]: unknown;\n}\n\nexport interface ExtractedSchemas {\n models: Model[];\n enums: Enum[];\n}\n\nexport function extractSchemas(schemas: Record<string, SchemaObject> | undefined): ExtractedSchemas {\n const enums: Enum[] = [];\n\n if (!schemas) return { models: [], enums };\n\n const modelsByCleanName = new Map<string, Model>();\n\n for (const [name, schema] of Object.entries(schemas)) {\n const pascalName = cleanSchemaName(toPascalCase(name));\n\n if (schema.enum) {\n enums.push(extractEnum(pascalName, schema));\n } else {\n const model = extractModel(pascalName, schema, schemas);\n const existing = modelsByCleanName.get(pascalName);\n if (existing) {\n // Keep the model with more fields when names collide after cleaning\n if (model.fields.length > existing.fields.length) {\n modelsByCleanName.set(pascalName, model);\n }\n } else {\n modelsByCleanName.set(pascalName, model);\n }\n }\n }\n\n const models = [...modelsByCleanName.values()];\n\n // Collect inline models from nested object/oneOf properties\n // that schemaToTypeRef created model refs for but weren't extracted\n const modelNames = new Set(models.map((m) => m.name));\n const inlineQueue: Model[] = [...models];\n while (inlineQueue.length > 0) {\n const model = inlineQueue.pop()!;\n for (const field of model.fields) {\n collectNestedInlineModels(field.type, field.name, model.name, schemas ?? {}, models, modelNames, inlineQueue);\n }\n }\n\n // Collect inline enums from model fields\n for (const model of models) {\n collectInlineEnums(model.fields, enums);\n }\n\n return { models, enums };\n}\n\n/**\n * Walk a single TypeRef and extract inline enum refs as top-level enum definitions.\n * Shared by both schemas.ts (field-level) and parse.ts (model-level) collection passes.\n */\nexport function collectInlineEnumFromRef(ref: TypeRef, enums: Enum[], seen: Set<string>): void {\n walkTypeRef(ref, {\n enum: (r) => {\n if (r.values && !seen.has(r.name)) {\n seen.add(r.name);\n enums.push({\n name: r.name,\n values: r.values.map((v) => ({\n name: toUpperSnakeCase(String(v)),\n value: v,\n description: undefined,\n })),\n });\n }\n },\n });\n}\n\n/**\n * Walk model fields and extract inline enum refs as top-level enum definitions.\n * This ensures type alias files are generated for inline enums.\n */\nfunction collectInlineEnums(fields: Field[], enums: Enum[]): void {\n const seen = new Set(enums.map((e) => e.name));\n for (const field of fields) {\n collectInlineEnumFromRef(field.type, enums, seen);\n }\n}\n\n/**\n * Walk a TypeRef tree and extract inline models for any model refs that point\n * to schemas with inline object properties (not in components/schemas).\n * This handles nested objects like `totp: { oneOf: [{ type: object, properties: {...} }] }`\n * that schemaToTypeRef turns into model refs but aren't extracted from components.\n */\nfunction collectNestedInlineModels(\n ref: TypeRef,\n fieldName: string,\n parentModelName: string,\n schemas: Record<string, SchemaObject>,\n models: Model[],\n modelNames: Set<string>,\n queue: Model[],\n): void {\n walkTypeRef(ref, {\n model: (modelRef) => {\n if (modelNames.has(modelRef.name)) return; // already extracted\n // Check if this model name corresponds to a component schema\n // by checking all possible original names that would map to this PascalCase name\n const isComponent = Object.keys(schemas).some((k) => cleanSchemaName(toPascalCase(k)) === modelRef.name);\n if (isComponent) return; // will be extracted from components\n\n // This is a reference to a nested inline model that wasn't extracted.\n // Look up the field schema in the parent model's component schema to extract it.\n const parentSchema = findSchemaByName(parentModelName, schemas);\n if (!parentSchema) return;\n\n const fieldSchema = findNestedFieldSchema(fieldName, parentSchema, schemas);\n if (!fieldSchema) return;\n\n // Extract inline models from the field schema\n const extracted = extractNestedSchema(modelRef.name, fieldSchema);\n for (const m of extracted) {\n if (!modelNames.has(m.name)) {\n models.push(m);\n modelNames.add(m.name);\n queue.push(m); // re-scan for deeper nesting\n }\n }\n },\n });\n}\n\n/** Find a component schema by PascalCase name. */\nfunction findSchemaByName(pascalName: string, schemas: Record<string, SchemaObject>): SchemaObject | null {\n for (const [k, v] of Object.entries(schemas)) {\n if (cleanSchemaName(toPascalCase(k)) === pascalName) return v;\n }\n return null;\n}\n\n/** Walk into a schema to find a field's sub-schema, resolving allOf. */\nfunction findNestedFieldSchema(\n fieldName: string,\n parentSchema: SchemaObject,\n schemas: Record<string, SchemaObject>,\n): SchemaObject | null {\n if (parentSchema.properties?.[fieldName]) {\n return parentSchema.properties[fieldName]!;\n }\n if (parentSchema.allOf) {\n for (const sub of parentSchema.allOf) {\n let resolved = sub;\n if (sub.$ref) {\n const segments = sub.$ref.split('/');\n const refName = segments[segments.length - 1];\n if (refName && schemas[refName]) resolved = schemas[refName];\n }\n if (resolved.properties?.[fieldName]) {\n return resolved.properties[fieldName]!;\n }\n }\n }\n return null;\n}\n\n/** Extract a model (and nested models) from an inline field schema. */\nfunction extractNestedSchema(name: string, schema: SchemaObject): Model[] {\n // Handle oneOf: extract each object variant as its own model\n if (schema.oneOf) {\n const models: Model[] = [];\n for (const variant of schema.oneOf) {\n if (variant.$ref) continue;\n if (variant.properties && (variant.type === 'object' || !variant.type)) {\n const requiredSet = new Set(variant.required ?? []);\n const fields: Field[] = [];\n for (const [fn, fs] of Object.entries(variant.properties)) {\n if (!fs) continue;\n fields.push(buildFieldFromSchema(fn, fs, name, requiredSet));\n }\n // Use the name for the first variant, suffix for subsequent\n const variantName = models.length === 0 ? name : `${name}${models.length + 1}`;\n models.push({ name: variantName, description: variant.description, fields });\n }\n }\n return models;\n }\n\n // Handle direct object\n if (schema.properties && (schema.type === 'object' || !schema.type)) {\n const requiredSet = new Set(schema.required ?? []);\n const fields: Field[] = [];\n for (const [fn, fs] of Object.entries(schema.properties)) {\n if (!fs) continue;\n fields.push(buildFieldFromSchema(fn, fs, name, requiredSet));\n }\n return [{ name, description: schema.description, fields }];\n }\n\n // Handle array with inline items\n if (schema.type === 'array' && schema.items?.properties) {\n const requiredSet = new Set(schema.items.required ?? []);\n const fields: Field[] = [];\n for (const [fn, fs] of Object.entries(schema.items.properties)) {\n if (!fs) continue;\n fields.push(buildFieldFromSchema(fn, fs, name, requiredSet));\n }\n return [{ name, description: schema.items.description, fields }];\n }\n\n return [];\n}\n\n/** Build a single Field from a schema property entry. Shared across all extraction sites. */\nexport function buildFieldFromSchema(\n fieldName: string,\n fieldSchema: SchemaObject,\n contextName: string,\n requiredSet: Set<string>,\n): Field {\n return {\n name: fieldName,\n type: schemaToTypeRef(fieldSchema, fieldName, contextName),\n required: requiredSet.has(fieldName),\n description: fieldSchema.description,\n readOnly: fieldSchema.readOnly || undefined,\n writeOnly: fieldSchema.writeOnly || undefined,\n deprecated: fieldSchema.deprecated || undefined,\n default: fieldSchema.default,\n example: fieldSchema.example,\n };\n}\n\nfunction extractEnum(name: string, schema: SchemaObject): Enum {\n const values: EnumValue[] = (schema.enum ?? []).map((v) => ({\n name: toUpperSnakeCase(String(v)),\n value: typeof v === 'number' ? v : String(v),\n description: undefined,\n }));\n\n return { name, values };\n}\nfunction extractModel(name: string, schema: SchemaObject, schemas?: Record<string, SchemaObject>): Model {\n if (schema.allOf) {\n return extractAllOfModel(name, schema, schemas);\n }\n\n const requiredSet = new Set(schema.required ?? []);\n const fields: Field[] = [];\n\n for (const [fieldName, fieldSchema] of Object.entries(schema.properties ?? {})) {\n if (!fieldSchema) continue;\n fields.push(buildFieldFromSchema(fieldName, fieldSchema, name, requiredSet));\n }\n\n // When additionalProperties is an object schema alongside properties,\n // surface it as a catch-all map field so emitters can generate Map<string, T>.\n if (schema.additionalProperties && typeof schema.additionalProperties === 'object' && schema.properties) {\n const apKeys = Object.keys(schema.additionalProperties);\n if (apKeys.length > 0) {\n const valueType = schemaToTypeRef(schema.additionalProperties as SchemaObject, 'additionalProperties', name);\n fields.push({\n name: 'additionalProperties',\n type: { kind: 'map', valueType },\n required: false,\n description: 'Additional properties not captured by named fields',\n });\n }\n }\n\n return { name, description: schema.description, fields };\n}\n\nfunction extractAllOfModel(name: string, schema: SchemaObject, schemas?: Record<string, SchemaObject>): Model {\n const fields: Field[] = [];\n const requiredSet = new Set<string>();\n\n for (const subSchema of schema.allOf ?? []) {\n // Resolve $ref sub-schemas by looking up the referenced component schema\n let resolved = subSchema;\n if (subSchema.$ref && schemas) {\n const segments = subSchema.$ref.split('/');\n const refName = segments[segments.length - 1];\n if (refName && schemas[refName]) {\n resolved = schemas[refName];\n }\n }\n\n // If the resolved schema is itself an allOf, recursively extract its fields\n if (resolved.allOf) {\n const nested = extractAllOfModel(name, resolved, schemas);\n for (const f of nested.fields) {\n fields.push({ ...f, required: false }); // will be re-set below\n if (f.required) requiredSet.add(f.name);\n }\n } else {\n if (resolved.required) {\n for (const r of resolved.required) requiredSet.add(r);\n }\n if (resolved.properties) {\n // Use an empty requiredSet — required flags are set in the final pass below\n const emptyRequired = new Set<string>();\n for (const [fieldName, fieldSchema] of Object.entries(resolved.properties)) {\n if (!fieldSchema) continue;\n fields.push(buildFieldFromSchema(fieldName, fieldSchema, name, emptyRequired));\n }\n }\n }\n }\n\n // Also collect required from the outer schema\n if (schema.required) {\n for (const r of schema.required) requiredSet.add(r);\n }\n\n // Set required flags\n for (const f of fields) {\n f.required = requiredSet.has(f.name);\n }\n\n return { name, description: schema.description, fields };\n}\n\nexport function schemaToTypeRef(schema: SchemaObject, contextName?: string, parentModelName?: string): TypeRef {\n // Handle $ref → ModelRef\n if (schema.$ref) {\n const segments = schema.$ref.split('/');\n const rawName = segments[segments.length - 1];\n return { kind: 'model', name: cleanSchemaName(toPascalCase(rawName)) };\n }\n\n // Handle OAS 3.1 nullable type arrays: type: [string, null]\n if (Array.isArray(schema.type)) {\n const nonNullTypes = schema.type.filter((t: string) => t !== 'null');\n // type: ['null'] — only null, no real type\n if (nonNullTypes.length === 0) {\n return { kind: 'nullable', inner: { kind: 'primitive', type: 'unknown' } };\n }\n if (schema.type.includes('null') && nonNullTypes.length === 1) {\n return {\n kind: 'nullable',\n inner: schemaToTypeRef({ ...schema, type: nonNullTypes[0], nullable: false }, contextName),\n };\n }\n // Multiple non-null types → union\n if (nonNullTypes.length > 1) {\n const variants = nonNullTypes.map((t: string) => schemaToTypeRef({ ...schema, type: t }, contextName));\n const ref: TypeRef = { kind: 'union', variants };\n if (schema.type.includes('null')) {\n return { kind: 'nullable', inner: ref };\n }\n return ref;\n }\n }\n\n // Handle OAS 3.0 nullable flag\n if (schema.nullable && schema.type) {\n return {\n kind: 'nullable',\n inner: schemaToTypeRef({ ...schema, nullable: false }, contextName),\n };\n }\n\n // Handle allOf — merge properties from all sub-schemas.\n // This handles patterns like: allOf: [{ type: object, properties: {...} }, { oneOf: [...] }]\n // which are valid OAS 3.1 but weren't handled for field-level schemas.\n if (schema.allOf) {\n // If allOf contains a $ref, prefer the ref (it's a named type)\n const refItem = schema.allOf.find((s: SchemaObject) => s.$ref);\n if (refItem) {\n // If allOf has $ref AND siblings with properties, return a merged model ref\n // to avoid losing the augmentation properties\n const hasAugmentation = schema.allOf.some((s: SchemaObject) => !s.$ref && (s.properties || s.type === 'object'));\n if (hasAugmentation) {\n const baseName = toPascalCase(contextName ?? 'UnknownModel');\n return { kind: 'model', name: qualifyInlineModelName(baseName, parentModelName) };\n }\n return schemaToTypeRef(refItem, contextName, parentModelName);\n }\n // If allOf has a single item, unwrap it\n if (schema.allOf.length === 1) {\n return schemaToTypeRef(schema.allOf[0], contextName, parentModelName);\n }\n // If allOf items all have properties, treat as a merged model\n const hasProperties = schema.allOf.some((s: SchemaObject) => s.properties);\n if (hasProperties) {\n const baseName = toPascalCase(contextName ?? 'UnknownModel');\n return {\n kind: 'model',\n name: qualifyInlineModelName(baseName, parentModelName),\n };\n }\n // Fall through to other checks\n }\n\n // Handle oneOf / anyOf → Union or Nullable\n // Valid OAS 3.1: properties can have { oneOf: [{ type: object }, { type: 'null' }] }\n // without a wrapping `type` field.\n if (schema.oneOf || schema.anyOf) {\n const compositionKind: 'oneOf' | 'anyOf' = schema.oneOf ? 'oneOf' : 'anyOf';\n const rawVariants: SchemaObject[] = schema.oneOf ?? schema.anyOf ?? [];\n\n // Check for nullable pattern: oneOf: [realType, { type: 'null' }]\n const nullVariant = rawVariants.find(\n (v: SchemaObject) => v.type === 'null' || (Array.isArray(v.type) && v.type.length === 1 && v.type[0] === 'null'),\n );\n const nonNullVariants = rawVariants.filter((v) => v !== nullVariant);\n\n if (nullVariant && nonNullVariants.length === 1) {\n // Nullable single type — unwrap as nullable\n return {\n kind: 'nullable',\n inner: schemaToTypeRef(nonNullVariants[0], contextName, parentModelName),\n };\n }\n\n // General union\n const variants = rawVariants\n .filter((v: SchemaObject) => v.type !== 'null')\n .map((v: SchemaObject) => schemaToTypeRef(v, contextName, parentModelName));\n const hasNull = !!nullVariant;\n const union: TypeRef = {\n kind: 'union',\n variants,\n compositionKind,\n ...(schema.discriminator\n ? {\n discriminator: {\n property: schema.discriminator.propertyName,\n mapping: Object.fromEntries(\n Object.entries(schema.discriminator.mapping ?? {}).map(([k, v]) => [\n k,\n v.replace(/^#\\/components\\/schemas\\//, ''),\n ]),\n ),\n },\n }\n : {}),\n };\n return hasNull ? { kind: 'nullable', inner: union } : union;\n }\n\n // Handle const → LiteralType (supports string, number, boolean)\n if (schema.const !== undefined) {\n if (typeof schema.const === 'string' || typeof schema.const === 'number' || typeof schema.const === 'boolean') {\n return { kind: 'literal', value: schema.const };\n }\n // null const → nullable unknown\n if (schema.const === null) {\n return { kind: 'nullable', inner: { kind: 'primitive', type: 'unknown' } };\n }\n // const of object/array → map or array with unknown values\n if (typeof schema.const === 'object') {\n if (Array.isArray(schema.const)) {\n return { kind: 'array', items: { kind: 'primitive', type: 'unknown' } };\n }\n return { kind: 'map', valueType: { kind: 'primitive', type: 'unknown' } };\n }\n }\n if (schema.enum && schema.enum.length === 1) {\n const v = schema.enum[0];\n return { kind: 'literal', value: typeof v === 'number' ? v : String(v) };\n }\n\n // Handle enum\n if (schema.enum) {\n const baseName = toPascalCase(contextName ?? 'UnknownEnum');\n // Strip ListItem/ByExternalId markers from parent name so enum names are clean:\n // e.g., DirectoryListItem + State → Directory + State = DirectoryState\n const cleanParent = parentModelName ? stripListItemMarkers(parentModelName) : undefined;\n // Avoid redundant prefix: Connection + ConnectionType → ConnectionType\n const qualifiedName = cleanParent && !baseName.startsWith(cleanParent) ? `${cleanParent}${baseName}` : baseName;\n return {\n kind: 'enum',\n name: qualifiedName,\n values: schema.enum.map((v) => (typeof v === 'number' ? v : String(v))),\n };\n }\n\n // Handle array — pass parentModelName through to qualify inline items\n if (schema.type === 'array' && schema.items) {\n return {\n kind: 'array',\n items: schemaToTypeRef(schema.items, contextName, parentModelName),\n };\n }\n // Handle array without explicit type but with items (valid OAS 3.1)\n if (!schema.type && schema.items) {\n return {\n kind: 'array',\n items: schemaToTypeRef(schema.items, contextName, parentModelName),\n };\n }\n\n // Handle object → ModelRef (if it has properties, it's a named model reference)\n // When additionalProperties is also present, we still return a ModelRef so the\n // named properties are preserved. The extractModel path will pick up the extra\n // properties as a catch-all map field named `additionalProperties`.\n if (schema.type === 'object' && schema.properties) {\n const baseName = toPascalCase(contextName ?? 'UnknownModel');\n return {\n kind: 'model',\n name: qualifyInlineModelName(baseName, parentModelName),\n };\n }\n\n // Handle freeform object with additionalProperties or patternProperties → Map<string, T>\n if (schema.type === 'object' && !schema.properties) {\n let valueType: TypeRef = { kind: 'primitive', type: 'unknown' };\n if (schema.additionalProperties && typeof schema.additionalProperties === 'object') {\n // Empty additionalProperties ({}) means \"any value\" — keep as unknown\n const apKeys = Object.keys(schema.additionalProperties);\n if (apKeys.length > 0) {\n valueType = schemaToTypeRef(schema.additionalProperties as SchemaObject, contextName);\n }\n } else if (schema.patternProperties) {\n // patternProperties: { \"pattern\": schema } → use the first pattern's schema as value type\n const patterns = Object.values(schema.patternProperties);\n if (patterns.length > 0) {\n valueType = schemaToTypeRef(patterns[0], contextName);\n }\n }\n return {\n kind: 'map',\n valueType,\n };\n }\n\n // Handle primitives\n const primitiveMap: Record<string, 'string' | 'integer' | 'number' | 'boolean'> = {\n string: 'string',\n integer: 'integer',\n number: 'number',\n boolean: 'boolean',\n };\n\n const typeStr = Array.isArray(schema.type) ? schema.type[0] : schema.type;\n if (typeStr && primitiveMap[typeStr]) {\n return {\n kind: 'primitive',\n type: primitiveMap[typeStr],\n ...(schema.format ? { format: schema.format } : {}),\n };\n }\n\n // Handle schemas with no type — if it has properties, treat as model\n if (!schema.type && schema.properties) {\n const baseName = toPascalCase(contextName ?? 'UnknownModel');\n return {\n kind: 'model',\n name: qualifyInlineModelName(baseName, parentModelName),\n };\n }\n\n // Empty schema {} → unknown\n if (\n !schema.type &&\n !schema.$ref &&\n !schema.oneOf &&\n !schema.anyOf &&\n !schema.allOf &&\n !schema.enum &&\n !schema.properties &&\n !schema.items\n ) {\n return { kind: 'primitive', type: 'unknown' };\n }\n\n // Fallback: treat unknown schemas as unknown\n if (contextName) {\n console.warn(`[oagen] Warning: Unknown schema shape treated as unknown (context: ${contextName})`);\n }\n return { kind: 'primitive', type: 'unknown' };\n}\n\nimport { qualifyInlineModelName } from './inline-models.js';\n\nexport { qualifyInlineModelName, extractInlineModelsFromSchemas } from './inline-models.js';\n","import type { TypeRef, Parameter, PaginationMeta } from '../ir/types.js';\n\nconst CURSOR_PARAMS = ['cursor', 'after', 'before', 'starting_after', 'ending_before', 'page_token', 'next_token'];\n\nconst OFFSET_PARAMS = ['offset', 'page', 'page_number', 'skip'];\nconst LIMIT_PARAMS = ['limit', 'page_size', 'per_page', 'size', 'count'];\n\n/**\n * Detect if an operation uses pagination and return structured metadata\n * for auto-paging iterator generation.\n *\n * Supports two strategies:\n * 1. **Cursor-based**: query params include a cursor-like parameter\n * 2. **Offset-based**: query params include both an offset-like and limit-like parameter\n *\n * Returns null if no pagination pattern is detected.\n */\nexport function detectPagination(\n response: TypeRef,\n queryParams: Parameter[],\n dataPath?: string,\n): PaginationMeta | null {\n // Try cursor-based first (preferred)\n const cursorParam = queryParams.find((p) => CURSOR_PARAMS.includes(p.name));\n\n if (cursorParam) {\n const itemType: TypeRef = response.kind === 'array' ? response.items : response;\n return {\n strategy: 'cursor',\n param: cursorParam.name,\n dataPath: dataPath,\n itemType,\n };\n }\n\n // Try offset-based pagination\n const offsetParam = queryParams.find((p) => OFFSET_PARAMS.includes(p.name));\n const limitParam = queryParams.find((p) => LIMIT_PARAMS.includes(p.name));\n\n if (offsetParam && limitParam) {\n const itemType: TypeRef = response.kind === 'array' ? response.items : response;\n return {\n strategy: 'offset',\n param: offsetParam.name,\n limitParam: limitParam.name,\n dataPath: dataPath,\n itemType,\n };\n }\n\n return null;\n}\n","import type { TypeRef, Model, Field } from '../ir/types.js';\nimport { toPascalCase, singularize, stripListItemMarkers } from '../utils/naming.js';\nimport type { SchemaObject } from './schemas.js';\nimport { schemaToTypeRef, buildFieldFromSchema } from './schemas.js';\n\nexport interface ResponseExtractionResult {\n /** The TypeRef to use as the operation's response type */\n response: TypeRef;\n /** Any inline models discovered during extraction (to merge into ir.models) */\n inlineModels: Model[];\n /** Whether this response indicates a paginated list */\n isPaginated: boolean;\n /** Path to the data array within the response envelope (e.g., 'data') */\n dataPath?: string;\n /** TypeRef of individual items in a paginated list */\n itemType?: TypeRef;\n}\n\nexport function classifyAndExtractResponse(schema: SchemaObject, contextName: string): ResponseExtractionResult {\n // 1. If schema is a $ref, resolve to model name (Phase 1)\n if (schema.$ref) {\n return { response: schemaToTypeRef(schema, contextName), inlineModels: [], isPaginated: false };\n }\n\n // 2. Check for list envelope (structural detection: array prop + non-array companion)\n const envelope = detectListEnvelope(schema);\n if (envelope.isEnvelope) {\n return extractListResponse(schema, contextName, envelope.dataPath!);\n }\n\n // 3. Check for single-resource wrapper ({ resource_name: { object: \"...\", ... } })\n if (isSingleResourceWrapper(schema)) {\n return extractWrappedResource(schema, contextName);\n }\n\n // 4. Direct resource or plain inline object\n return extractDirectResource(schema, contextName);\n}\n\ninterface ListEnvelopeResult {\n isEnvelope: boolean;\n dataPath: string | null;\n}\n\nconst KNOWN_DATA_PATHS = new Set(['data', 'items', 'results', 'records', 'entries', 'values', 'nodes', 'edges']);\n\nconst PAGINATION_METADATA_PATTERNS = [\n 'metadata',\n 'pagination',\n 'cursor',\n 'has_more',\n 'page_info',\n 'total',\n 'next_page',\n 'previous_page',\n 'offset',\n];\n\nfunction detectListEnvelope(schema: SchemaObject): ListEnvelopeResult {\n // Collect all property sources (allOf sub-schemas or flat schema)\n const propSources: Record<string, SchemaObject | undefined>[] = [];\n if (schema.allOf) {\n for (const sub of schema.allOf) {\n if (sub.properties) propSources.push(sub.properties);\n }\n }\n if (schema.properties) {\n propSources.push(schema.properties);\n }\n\n if (propSources.length === 0) return { isEnvelope: false, dataPath: null };\n\n // Merge all properties into a single view\n const mergedProps: Record<string, SchemaObject | undefined> = {};\n for (const source of propSources) {\n Object.assign(mergedProps, source);\n }\n\n // Find array-typed properties and non-array companion properties\n const arrayProps: string[] = [];\n const nonArrayKeys: string[] = [];\n\n for (const [key, propSchema] of Object.entries(mergedProps)) {\n if (!propSchema) continue;\n if (propSchema.type === 'array') {\n arrayProps.push(key);\n } else {\n nonArrayKeys.push(key);\n }\n }\n\n // List envelope heuristic: exactly one array property + at least one non-array companion\n if (arrayProps.length === 1 && nonArrayKeys.length >= 1) {\n const arrayPropName = arrayProps[0];\n\n // The array property must be a known data path...\n if (KNOWN_DATA_PATHS.has(arrayPropName)) {\n return { isEnvelope: true, dataPath: arrayPropName };\n }\n\n // ...OR a companion property must look like pagination metadata\n const hasPaginationCompanion = nonArrayKeys.some((key) =>\n PAGINATION_METADATA_PATTERNS.some((pattern) => key.toLowerCase().includes(pattern)),\n );\n if (hasPaginationCompanion) {\n return { isEnvelope: true, dataPath: arrayPropName };\n }\n }\n\n return { isEnvelope: false, dataPath: null };\n}\n\nfunction extractListResponse(schema: SchemaObject, contextName: string, dataPath: string): ResponseExtractionResult {\n let itemTypeRef: TypeRef = { kind: 'primitive', type: 'string' };\n const inlineModels: Model[] = [];\n\n // Collect all property sources (allOf sub-schemas or flat schema)\n const propSources: Record<string, SchemaObject | undefined>[] = [];\n if (schema.allOf) {\n for (const sub of schema.allOf) {\n if (sub.properties) propSources.push(sub.properties);\n }\n }\n if (schema.properties) {\n propSources.push(schema.properties);\n }\n\n for (const props of propSources) {\n const dataProp = props[dataPath];\n if (!dataProp) continue;\n\n if (dataProp.type === 'array' && dataProp.items) {\n const items = dataProp.items;\n if (items.$ref) {\n itemTypeRef = schemaToTypeRef(items, contextName);\n } else if (items.type === 'object' && items.properties) {\n const itemName = contextName.replace(/Response$/, '') + 'Item';\n itemTypeRef = { kind: 'model', name: itemName };\n inlineModels.push(...extractInlineModel(itemName, items));\n }\n }\n }\n\n return {\n response: { kind: 'array', items: itemTypeRef },\n inlineModels,\n isPaginated: true,\n dataPath,\n itemType: itemTypeRef,\n };\n}\n\nfunction hasDiscriminantConstField(schema: SchemaObject): { property: string; value: string } | null {\n if (!schema.properties) return null;\n\n // Prefer well-known discriminant properties for backward compatibility\n const preferred = ['object', 'type'];\n for (const name of preferred) {\n const field = schema.properties[name];\n if (!field) continue;\n if (field.const !== undefined && typeof field.const === 'string') {\n return { property: name, value: field.const };\n }\n if (field.enum && field.enum.length === 1 && typeof field.enum[0] === 'string') {\n return { property: name, value: field.enum[0] };\n }\n }\n\n // Fall back to any property with a const or single-value enum\n for (const [name, field] of Object.entries(schema.properties)) {\n if (!field) continue;\n if (field.const !== undefined && typeof field.const === 'string') {\n return { property: name, value: field.const };\n }\n if (field.enum && field.enum.length === 1 && typeof field.enum[0] === 'string') {\n return { property: name, value: field.enum[0] };\n }\n }\n\n return null;\n}\n\nfunction isSingleResourceWrapper(schema: SchemaObject): boolean {\n if (schema.type !== 'object') return false;\n if (!schema.properties) return false;\n\n // Find the wrapper property: use required[0] if available, or the single property key\n let wrapperKey: string | undefined;\n if (schema.required && schema.required.length === 1) {\n wrapperKey = schema.required[0];\n } else {\n const propKeys = Object.keys(schema.properties);\n if (propKeys.length === 1) {\n wrapperKey = propKeys[0];\n }\n }\n if (!wrapperKey) return false;\n\n const propSchema = schema.properties[wrapperKey];\n if (!propSchema) return false;\n\n // Direct object with a discriminant const field\n if (propSchema.type === 'object' && hasDiscriminantConstField(propSchema) !== null) return true;\n\n // oneOf with object + null (nullable resource)\n if (propSchema.oneOf) {\n return propSchema.oneOf.some((v) => v.type === 'object' && hasDiscriminantConstField(v) !== null);\n }\n\n return false;\n}\n\nfunction extractWrappedResource(schema: SchemaObject, contextName: string): ResponseExtractionResult {\n const props = schema.properties!;\n const wrapperKey = schema.required && schema.required.length === 1 ? schema.required[0] : Object.keys(props)[0];\n const propSchema = props[wrapperKey]!;\n const inlineModels: Model[] = [];\n\n // Derive model name from the object const value or wrapper property name\n const resourceName = contextName.replace(/Response$/, '');\n\n if (propSchema.oneOf) {\n const objectVariant = propSchema.oneOf.find((v) => v.type === 'object' && hasDiscriminantConstField(v) !== null);\n\n if (objectVariant) {\n const modelName = deriveModelName(objectVariant, resourceName);\n inlineModels.push(...extractInlineModel(modelName, objectVariant));\n\n const hasNullVariant = propSchema.oneOf.some(\n (v) => v.type === 'null' || (Array.isArray(v.type) && v.type.includes('null')),\n );\n\n const modelRef: TypeRef = { kind: 'model', name: modelName };\n return {\n response: hasNullVariant ? { kind: 'nullable', inner: modelRef } : modelRef,\n inlineModels,\n isPaginated: false,\n };\n }\n }\n\n // Direct object\n const modelName = deriveModelName(propSchema, resourceName);\n inlineModels.push(...extractInlineModel(modelName, propSchema));\n\n return {\n response: { kind: 'model', name: modelName },\n inlineModels,\n isPaginated: false,\n };\n}\n\nfunction extractDirectResource(schema: SchemaObject, contextName: string): ResponseExtractionResult {\n const inlineModels: Model[] = [];\n\n // Direct object with properties (with or without explicit type: 'object')\n if (schema.properties && (schema.type === 'object' || !schema.type)) {\n const modelName = deriveModelName(schema, contextName);\n inlineModels.push(...extractInlineModel(modelName, schema));\n return {\n response: { kind: 'model', name: modelName },\n inlineModels,\n isPaginated: false,\n };\n }\n\n // allOf with properties — merge into a single model\n if (schema.allOf) {\n const mergedProperties: Record<string, SchemaObject | undefined> = {};\n const mergedRequired: string[] = [];\n for (const sub of schema.allOf) {\n if (sub.properties) {\n Object.assign(mergedProperties, sub.properties);\n }\n if (sub.required) {\n mergedRequired.push(...sub.required);\n }\n }\n if (Object.keys(mergedProperties).length > 0) {\n const merged: SchemaObject = { type: 'object', properties: mergedProperties, required: mergedRequired };\n const modelName = deriveModelName(merged, contextName);\n inlineModels.push(...extractInlineModel(modelName, merged));\n return {\n response: { kind: 'model', name: modelName },\n inlineModels,\n isPaginated: false,\n };\n }\n }\n\n // oneOf — delegate to schemaToTypeRef (returns union) but also extract inline models\n // from object variants so the model refs resolve\n if (schema.oneOf) {\n for (const variant of schema.oneOf) {\n if (variant.properties && (variant.type === 'object' || !variant.type)) {\n const modelName = deriveModelName(variant, contextName);\n const existingNames = new Set(inlineModels.map((m) => m.name));\n if (!existingNames.has(modelName)) {\n inlineModels.push(...extractInlineModel(modelName, variant));\n }\n }\n }\n }\n\n // Array with inline object items — extract the item model\n if (schema.type === 'array' && schema.items) {\n const items = schema.items;\n if (items.$ref) {\n return {\n response: { kind: 'array', items: schemaToTypeRef(items, contextName) },\n inlineModels,\n isPaginated: false,\n };\n }\n if (items.properties && (items.type === 'object' || !items.type)) {\n const itemName = contextName.replace(/Response$/, '') + 'Item';\n inlineModels.push(...extractInlineModel(itemName, items));\n return {\n response: { kind: 'array', items: { kind: 'model', name: itemName } },\n inlineModels,\n isPaginated: false,\n };\n }\n }\n\n // Non-object schema (primitive, union, etc.) — delegate to schemaToTypeRef\n return {\n response: schemaToTypeRef(schema, contextName),\n inlineModels,\n isPaginated: false,\n };\n}\n\nfunction deriveModelName(schema: SchemaObject, fallback: string): string {\n if (!schema.properties) return toPascalCase(fallback);\n\n // Prefer well-known discriminant properties for backward compatibility\n const preferred = ['object', 'type'];\n for (const name of preferred) {\n const field = schema.properties[name];\n if (field && field.const && typeof field.const === 'string') {\n return toPascalCase(field.const);\n }\n }\n\n // Fall back to any property with a const string value\n for (const [, field] of Object.entries(schema.properties)) {\n if (field && field.const && typeof field.const === 'string') {\n return toPascalCase(field.const);\n }\n }\n\n return toPascalCase(fallback);\n}\n\n/**\n * Qualify a nested inline model name with its parent to avoid generic names.\n * e.g., parent=\"Connection\" + field=\"domains\" → \"ConnectionDomain\" (singularized)\n * Only qualifies when the field name alone would be too generic.\n */\nfunction qualifyNestedName(parentName: string, fieldName: string): string {\n const pascalField = toPascalCase(fieldName);\n // If the field name already starts with the parent name, don't double-prefix\n if (pascalField.startsWith(parentName)) return pascalField;\n // Qualify with parent and singularize:\n // Connection + Domains → ConnectionDomains → singularize lead word → ConnectionDomain\n const cleanParent = stripListItemMarkers(parentName);\n const qualified = `${cleanParent}${pascalField}`;\n // Singularize the trailing word: ConnectionDomains → ConnectionDomain\n const match = qualified.match(/^(.+?)([A-Z][a-z]+s?)$/);\n if (match && match[2]) {\n const trailing = singularize(match[2]);\n return match[1] + trailing;\n }\n return qualified;\n}\n\nfunction extractInlineModel(name: string, schema: SchemaObject): Model[] {\n const requiredSet = new Set(schema.required ?? []);\n const fields: Field[] = [];\n const properties = schema.properties ?? {};\n const nestedModels: Model[] = [];\n\n for (const [fieldName, fieldSchema] of Object.entries(properties)) {\n if (!fieldSchema) continue;\n fields.push(buildFieldFromSchema(fieldName, fieldSchema, name, requiredSet));\n\n // Recursively extract nested inline objects — qualify with parent name\n // to avoid generic names like \"Domains\" when multiple parents have a \"domains\" field\n if (fieldSchema.type === 'object' && fieldSchema.properties) {\n const nestedName = qualifyNestedName(name, fieldName);\n nestedModels.push(...extractInlineModel(nestedName, fieldSchema));\n }\n if (fieldSchema.type === 'array' && fieldSchema.items) {\n const items = fieldSchema.items;\n if (items.type === 'object' && items.properties) {\n const nestedName = qualifyNestedName(name, fieldName);\n nestedModels.push(...extractInlineModel(nestedName, items));\n }\n }\n // Handle allOf with inline object properties — merge into a single nested model\n if (fieldSchema.allOf) {\n const mergedProperties: Record<string, SchemaObject | undefined> = {};\n const mergedRequired: string[] = [];\n for (const sub of fieldSchema.allOf) {\n if (sub.properties) Object.assign(mergedProperties, sub.properties);\n if (sub.required) mergedRequired.push(...sub.required);\n }\n if (Object.keys(mergedProperties).length > 0) {\n const nestedName = qualifyNestedName(name, fieldName);\n const merged: SchemaObject = { type: 'object', properties: mergedProperties, required: mergedRequired };\n const existingNames = new Set(nestedModels.map((m) => m.name));\n if (!existingNames.has(nestedName)) {\n nestedModels.push(...extractInlineModel(nestedName, merged));\n }\n }\n }\n // Handle oneOf containing inline objects — extract the first non-null object variant\n if (fieldSchema.oneOf) {\n const objectVariant = fieldSchema.oneOf.find((v) => v.properties && (v.type === 'object' || !v.type));\n if (objectVariant) {\n const nestedName = qualifyNestedName(name, fieldName);\n const existingNames = new Set(nestedModels.map((m) => m.name));\n if (!existingNames.has(nestedName)) {\n nestedModels.push(...extractInlineModel(nestedName, objectVariant));\n }\n }\n }\n }\n\n return [{ name, description: schema.description, fields }, ...nestedModels];\n}\n","import type {\n Service,\n Operation,\n HttpMethod,\n Parameter,\n TypeRef,\n ErrorResponse,\n SuccessResponse,\n Model,\n Field,\n PaginationMeta,\n} from '../ir/types.js';\nimport { toPascalCase, toCamelCase, cleanSchemaName } from '../utils/naming.js';\nimport type { SchemaObject } from './schemas.js';\nimport { schemaToTypeRef, buildFieldFromSchema } from './schemas.js';\nimport { detectPagination } from './pagination.js';\nimport { classifyAndExtractResponse } from './responses.js';\n\ninterface PathItem {\n get?: OperationObject;\n post?: OperationObject;\n put?: OperationObject;\n patch?: OperationObject;\n delete?: OperationObject;\n head?: OperationObject;\n options?: OperationObject;\n trace?: OperationObject;\n parameters?: ParameterObject[];\n}\n\ninterface OperationObject {\n operationId?: string;\n summary?: string;\n description?: string;\n tags?: string[];\n parameters?: ParameterObject[];\n requestBody?: RequestBodyObject;\n responses?: Record<string, ResponseObject>;\n deprecated?: boolean;\n 'x-oagen-async'?: boolean;\n}\n\ninterface ParameterObject {\n name: string;\n in: 'path' | 'query' | 'header' | 'cookie';\n required?: boolean;\n description?: string;\n schema?: SchemaObject;\n deprecated?: boolean;\n example?: unknown;\n}\n\ninterface RequestBodyObject {\n required?: boolean;\n content?: Record<string, { schema?: SchemaObject }>;\n}\n\ninterface ResponseObject {\n description?: string;\n content?: Record<string, { schema?: SchemaObject }>;\n}\n\nconst HTTP_METHODS: HttpMethod[] = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace'];\n\nexport interface OperationExtractionResult {\n services: Service[];\n inlineModels: Model[];\n}\n\nexport function extractOperations(\n paths: Record<string, PathItem> | undefined,\n operationIdTransform?: (id: string) => string,\n): OperationExtractionResult {\n if (!paths) return { services: [], inlineModels: [] };\n\n const serviceMap = new Map<string, Operation[]>();\n const inlineModels: Model[] = [];\n\n for (const [path, pathItem] of Object.entries(paths)) {\n const pathLevelParams = pathItem.parameters ?? [];\n\n for (const method of HTTP_METHODS) {\n const op = pathItem[method];\n if (!op) continue;\n\n const serviceName = inferServiceName(path, op.tags?.[0]);\n\n const { operation, inlineModels: opModels } = buildOperation(\n method,\n path,\n op,\n pathLevelParams,\n operationIdTransform,\n );\n inlineModels.push(...opModels);\n const ops = serviceMap.get(serviceName) ?? [];\n ops.push(operation);\n serviceMap.set(serviceName, ops);\n }\n }\n\n // Disambiguate operation names within each service.\n // Multiple operations can get the same name (e.g., several \"list\" endpoints\n // in UserManagement for users, invitations, auth factors, etc.).\n for (const [, operations] of serviceMap) {\n disambiguateOperationNames(operations);\n }\n\n const services = Array.from(serviceMap.entries()).map(([name, operations]) => ({\n name,\n operations,\n }));\n\n return { services, inlineModels };\n}\n\nfunction inferServiceName(path: string, tag?: string): string {\n // Prefer OpenAPI tag when available — tags represent the logical grouping\n // (e.g., \"multi-factor-auth\" for /auth/factors/* endpoints).\n if (tag) {\n return toPascalCase(tag);\n }\n // Fallback: extract first meaningful path segment: /widgets/{id}/sub → \"Widgets\"\n const segments = path.split('/').filter(Boolean);\n const first = segments[0] ?? 'Default';\n // Skip path params\n if (first.startsWith('{')) return 'Default';\n return toPascalCase(first);\n}\n\nfunction inferOperationName(\n method: HttpMethod,\n path: string,\n operationId?: string,\n operationIdTransform?: (id: string) => string,\n): string {\n if (operationId) {\n if (operationIdTransform) {\n return operationIdTransform(operationId);\n }\n return toCamelCase(operationId);\n }\n\n // Fallback when no operationId is available — use method + path to build\n // a descriptive name like \"listUsers\", \"getOrganization\", \"deleteAuthFactor\"\n const verb = inferVerb(method, path);\n const resource = inferResourceFromPath(path);\n return resource ? toCamelCase(`${verb}_${resource}`) : verb;\n}\n\n/**\n * Infer the CRUD verb from HTTP method and path shape.\n */\nfunction inferVerb(method: HttpMethod, path: string): string {\n const segments = path.split('/').filter(Boolean);\n const hasTrailingParam = segments.length > 0 && segments[segments.length - 1].startsWith('{');\n\n switch (method) {\n case 'get':\n return hasTrailingParam ? 'get' : 'list';\n case 'post':\n return 'create';\n case 'put':\n case 'patch':\n return 'update';\n case 'delete':\n return 'delete';\n case 'head':\n return 'check';\n case 'options':\n return 'options';\n case 'trace':\n return 'trace';\n default:\n return method;\n }\n}\n\n/**\n * Extract a resource noun from the path for operation naming.\n * Uses the last non-param segment (the resource being operated on).\n *\n * Examples:\n * /user_management/users → \"Users\"\n * /user_management/users/{id} → \"User\" (singular for item operations)\n * /user_management/users/{id}/auth_factors → \"AuthFactors\"\n * /organizations/{id}/api_keys → \"ApiKeys\"\n * /sso/authorize → \"Authorize\" (action endpoint)\n */\nfunction inferResourceFromPath(path: string): string | null {\n const segments = path.split('/').filter(Boolean);\n if (segments.length <= 1) return null;\n\n // Find the last meaningful (non-param) segment\n let resourceSegment: string | null = null;\n for (let i = segments.length - 1; i >= 0; i--) {\n if (!segments[i].startsWith('{')) {\n resourceSegment = segments[i];\n break;\n }\n }\n\n if (!resourceSegment) return null;\n // Skip the service name (first segment) — it would be redundant\n if (resourceSegment === segments[0]) return null;\n\n return toPascalCase(resourceSegment);\n}\n\n/**\n * Detect and resolve name collisions within a service's operations.\n *\n * When multiple operations share the same name (e.g., several \"list\" from\n * different sub-resources), disambiguate by appending the resource noun\n * from the path. Only renames operations on DIFFERENT paths — same-name\n * operations on the same path (e.g., PUT + PATCH both \"update\") are left as-is\n * since they represent the same logical resource.\n */\nfunction disambiguateOperationNames(operations: Operation[]): void {\n // Group by name\n const byName = new Map<string, Operation[]>();\n for (const op of operations) {\n const group = byName.get(op.name) ?? [];\n group.push(op);\n byName.set(op.name, group);\n }\n\n for (const [name, group] of byName) {\n if (group.length <= 1) continue;\n\n // Check if these are genuinely different resources (different paths)\n // vs the same resource with different methods (PUT + PATCH)\n const uniquePaths = new Set(group.map((op) => op.path));\n if (uniquePaths.size <= 1) continue; // same path, different methods — no disambiguation needed\n\n for (const op of group) {\n const resource = inferResourceFromPath(op.path);\n if (resource) {\n const newName = toCamelCase(`${name}_${resource}`);\n (op as { name: string }).name = newName;\n }\n }\n\n // If disambiguation still left collisions (same sub-resource),\n // use the full distinguishing path segment chain\n const renamed = new Map<string, Operation[]>();\n for (const op of group) {\n const rGroup = renamed.get(op.name) ?? [];\n rGroup.push(op);\n renamed.set(op.name, rGroup);\n }\n for (const [, rGroup] of renamed) {\n if (rGroup.length <= 1) continue;\n // Still colliding — different paths map to same resource name.\n // Use deeper path context to disambiguate.\n for (const op of rGroup) {\n const deeper = inferDeeperContext(op.path);\n if (deeper) {\n (op as { name: string }).name = toCamelCase(`${op.name}_${deeper}`);\n }\n }\n }\n }\n}\n\n/**\n * Extract a deeper disambiguation context from the path when the last\n * segment isn't unique enough. Uses the second-to-last non-param segment.\n *\n * /users/{id}/auth_factors → already captured as \"AuthFactors\"\n * /users/external_id/{external_id} → \"ExternalId\" (special path, not a sub-resource)\n */\nfunction inferDeeperContext(path: string): string | null {\n const segments = path.split('/').filter(Boolean);\n const nonParams = segments.filter((s) => !s.startsWith('{'));\n // Skip first (service) and last (already used) — use the middle ones\n if (nonParams.length >= 3) {\n return toPascalCase(nonParams.slice(1, -1).join('_'));\n }\n return null;\n}\n\nfunction buildOperation(\n method: HttpMethod,\n path: string,\n op: OperationObject,\n pathLevelParams: ParameterObject[],\n operationIdTransform?: (id: string) => string,\n): { operation: Operation; inlineModels: Model[] } {\n const allParams = [...pathLevelParams, ...(op.parameters ?? [])];\n\n const hasIdempotencyHeader = allParams.some((p) => p.in === 'header' && p.name.toLowerCase() === 'idempotency-key');\n\n const pathParams = extractParams(allParams, 'path');\n const queryParams = extractParams(allParams, 'query');\n const headerParams = extractParams(allParams, 'header').filter((p) => p.name.toLowerCase() !== 'idempotency-key');\n const cookieParams = extractParams(allParams, 'cookie');\n\n const reqBodyModels: Model[] = [];\n const { body: requestBody, encoding: requestBodyEncoding } = extractRequestBody(op.requestBody, op, reqBodyModels);\n const {\n response,\n successResponses,\n errors,\n inlineModels,\n isPaginated,\n dataPath: responseDataPath,\n itemType: responseItemType,\n } = extractResponses(op.responses, op, path, method);\n inlineModels.push(...reqBodyModels);\n\n // Build structured pagination metadata from response classification and query param detection\n const paginationFromParams = detectPagination(response, queryParams, responseDataPath);\n let pagination: PaginationMeta | undefined;\n if (isPaginated) {\n const itemType = responseItemType ?? (response.kind === 'array' ? response.items : response);\n pagination = {\n strategy: paginationFromParams?.strategy ?? 'cursor',\n param: paginationFromParams?.param ?? 'after',\n limitParam: paginationFromParams?.limitParam,\n dataPath: responseDataPath ?? paginationFromParams?.dataPath,\n itemType,\n };\n } else if (paginationFromParams) {\n pagination = paginationFromParams;\n }\n\n return {\n operation: {\n name: inferOperationName(method, path, op.operationId, operationIdTransform),\n description: buildDescription(op.summary, op.description),\n httpMethod: method,\n path,\n pathParams,\n queryParams,\n headerParams,\n cookieParams: cookieParams.length > 0 ? cookieParams : undefined,\n requestBody,\n requestBodyEncoding,\n response,\n successResponses,\n errors,\n pagination,\n injectIdempotencyKey: hasIdempotencyHeader,\n deprecated: op.deprecated || undefined,\n async: op['x-oagen-async'],\n },\n inlineModels,\n };\n}\n\nfunction buildDescription(summary: string | undefined, description: string | undefined): string | undefined {\n if (summary && description && summary !== description) {\n return `${summary}\\n\\n${description}`;\n }\n return description ?? summary;\n}\n\nfunction extractParams(params: ParameterObject[], location: 'path' | 'query' | 'header' | 'cookie'): Parameter[] {\n return params\n .filter((p) => p.in === location)\n .map((p) => ({\n name: p.name,\n type: p.schema ? schemaToTypeRef(p.schema, p.name) : ({ kind: 'primitive', type: 'string' } as TypeRef),\n required: p.required ?? false,\n description: p.description,\n deprecated: p.deprecated || p.schema?.deprecated || undefined,\n default: p.schema?.default,\n example: p.example ?? p.schema?.example,\n }));\n}\n\nfunction extractRequestBody(\n body: RequestBodyObject | undefined,\n op: OperationObject | undefined,\n inlineModels: Model[],\n): { body?: TypeRef; encoding?: 'json' | 'form-data' | 'form-urlencoded' | 'binary' | 'text' } {\n if (!body?.content) return {};\n\n // Detect encoding and find schema from content type in priority order\n let encoding: 'json' | 'form-data' | 'form-urlencoded' | 'binary' | 'text' = 'json';\n let schema: SchemaObject | undefined;\n\n if (body.content['application/json']?.schema) {\n encoding = 'json';\n schema = body.content['application/json']!.schema;\n } else if (body.content['multipart/form-data']?.schema) {\n encoding = 'form-data';\n schema = body.content['multipart/form-data']!.schema;\n } else if (body.content['application/x-www-form-urlencoded']?.schema) {\n encoding = 'form-urlencoded';\n schema = body.content['application/x-www-form-urlencoded']!.schema;\n } else if (body.content['application/octet-stream']) {\n encoding = 'binary';\n schema = body.content['application/octet-stream']!.schema;\n } else if (body.content['text/plain']) {\n encoding = 'text';\n schema = body.content['text/plain']!.schema;\n }\n\n if (!schema) {\n // For binary/text, a schema is optional — produce a primitive TypeRef\n if (encoding === 'binary') {\n return { body: { kind: 'primitive', type: 'string', format: 'binary' }, encoding };\n }\n if (encoding === 'text') {\n return { body: { kind: 'primitive', type: 'string' }, encoding };\n }\n return {};\n }\n\n const rawName = op?.operationId ? toPascalCase(op.operationId) + 'Request' : 'RequestBody';\n const contextName = cleanSchemaName(rawName);\n\n // If the request body is an inline object with properties, extract it as a model\n if (schema.properties && (schema.type === 'object' || !schema.type)) {\n const requiredSet = new Set(schema.required ?? []);\n const fields: Field[] = [];\n for (const [fieldName, fieldSchema] of Object.entries(schema.properties)) {\n if (!fieldSchema) continue;\n fields.push(buildFieldFromSchema(fieldName, fieldSchema, contextName, requiredSet));\n }\n inlineModels.push({ name: contextName, description: undefined, fields });\n return { body: { kind: 'model', name: contextName }, encoding };\n }\n\n // If the request body is a oneOf, extract each variant as an inline model\n // and build a union type pointing to them by name.\n if (schema.oneOf) {\n const variants: TypeRef[] = [];\n\n for (const variant of schema.oneOf) {\n if (variant.$ref) {\n const ref = schemaToTypeRef(variant, contextName);\n variants.push(ref);\n } else if (variant.type === 'null') {\n // skip null variant in union, handle separately\n } else if (variant.properties && (variant.type === 'object' || !variant.type)) {\n const variantName = deriveOneOfVariantName(variant, contextName, inlineModels);\n const requiredSet = new Set(variant.required ?? []);\n const fields: Field[] = [];\n for (const [fieldName, fieldSchema] of Object.entries(variant.properties)) {\n if (!fieldSchema) continue;\n fields.push(buildFieldFromSchema(fieldName, fieldSchema, variantName, requiredSet));\n }\n inlineModels.push({ name: variantName, description: variant.description, fields });\n variants.push({ kind: 'model', name: variantName });\n } else {\n variants.push(schemaToTypeRef(variant, contextName));\n }\n }\n\n const hasNull = schema.oneOf.some(\n (v: SchemaObject) => v.type === 'null' || (Array.isArray(v.type) && v.type.includes('null')),\n );\n const union: TypeRef = {\n kind: 'union',\n variants,\n ...(schema.discriminator\n ? {\n discriminator: { property: schema.discriminator.propertyName, mapping: schema.discriminator.mapping ?? {} },\n }\n : {}),\n };\n const body = hasNull ? ({ kind: 'nullable', inner: union } as TypeRef) : union;\n return { body, encoding };\n }\n\n return { body: schemaToTypeRef(schema, contextName), encoding };\n}\n\n/** Derive a unique variant name for a oneOf inline model. */\nfunction deriveOneOfVariantName(variant: SchemaObject, baseName: string, existingModels: Model[]): string {\n // Try to use a distinguishing property (e.g., \"grant_type\" field's const/enum value)\n if (variant.properties) {\n for (const [, propSchema] of Object.entries(variant.properties)) {\n if (propSchema?.const && typeof propSchema.const === 'string') {\n return toPascalCase(propSchema.const) + baseName.replace(/Request$/, '') + 'Request';\n }\n }\n }\n // Fallback: append a numeric suffix\n const existingNames = new Set(existingModels.map((m) => m.name));\n let name = baseName;\n let suffix = 2;\n while (existingNames.has(name)) {\n name = `${baseName}${suffix}`;\n suffix++;\n }\n return name;\n}\n\nfunction deriveResponseName(op: OperationObject | undefined, path: string, method: HttpMethod): string {\n if (op?.operationId) {\n return cleanSchemaName(toPascalCase(op.operationId) + 'Response');\n }\n const segments = path.split('/').filter(Boolean);\n const resource = segments[0] ?? 'Unknown';\n return toPascalCase(resource) + toPascalCase(method) + 'Response';\n}\n\nfunction extractResponses(\n responses?: Record<string, ResponseObject>,\n op?: OperationObject,\n path?: string,\n method?: HttpMethod,\n): {\n response: TypeRef;\n successResponses?: SuccessResponse[];\n errors: ErrorResponse[];\n inlineModels: Model[];\n isPaginated: boolean;\n dataPath?: string;\n itemType?: TypeRef;\n} {\n const errors: ErrorResponse[] = [];\n let response: TypeRef = { kind: 'primitive', type: 'string' };\n let inlineModels: Model[] = [];\n let isPaginated = false;\n let dataPath: string | undefined;\n let itemType: TypeRef | undefined;\n\n if (!responses) return { response, errors, inlineModels, isPaginated };\n\n const allSuccessResponses: SuccessResponse[] = [];\n\n for (const [statusCode, resp] of Object.entries(responses)) {\n const code = parseInt(statusCode, 10);\n\n if (code >= 200 && code < 300) {\n let extractedType: TypeRef = { kind: 'primitive', type: 'unknown' };\n const jsonContent = resp.content?.['application/json'];\n if (jsonContent?.schema) {\n const contextName = deriveResponseName(op, path ?? '/', method ?? 'get');\n const result = classifyAndExtractResponse(jsonContent.schema, contextName);\n extractedType = result.response;\n // Keep track of inline models and pagination from the latest 2xx with a schema\n inlineModels = result.inlineModels;\n isPaginated = result.isPaginated;\n dataPath = result.dataPath;\n itemType = result.itemType;\n } else if (resp.content) {\n // Handle non-JSON response content types (text/plain, binary, XML, etc.)\n if (resp.content['application/octet-stream'] || resp.content['application/pdf']) {\n extractedType = { kind: 'primitive', type: 'string', format: 'binary' };\n } else if (\n resp.content['text/plain'] ||\n resp.content['text/html'] ||\n resp.content['text/xml'] ||\n resp.content['application/xml']\n ) {\n extractedType = { kind: 'primitive', type: 'string' };\n } else {\n // Try the first available content type's schema\n const firstKey = Object.keys(resp.content)[0];\n if (firstKey) {\n const firstContent = resp.content[firstKey];\n if (firstContent?.schema) {\n extractedType = schemaToTypeRef(\n firstContent.schema,\n deriveResponseName(op, path ?? '/', method ?? 'get'),\n );\n }\n }\n }\n }\n allSuccessResponses.push({ statusCode: code, type: extractedType });\n } else if (code >= 400) {\n const jsonContent = resp.content?.['application/json'];\n const type = jsonContent?.schema ? schemaToTypeRef(jsonContent.schema, `Error${code}`) : undefined;\n errors.push({ statusCode: code, type });\n }\n }\n\n // Primary response = lowest 2xx with a body schema, falling back to first 2xx\n if (allSuccessResponses.length > 0) {\n const sorted = [...allSuccessResponses].sort((a, b) => a.statusCode - b.statusCode);\n const primary =\n sorted.find((r) => r.type.kind !== 'primitive' || (r.type as { type: string }).type !== 'unknown') ?? sorted[0];\n response = primary.type;\n }\n\n const successResponses = allSuccessResponses.length > 1 ? allSuccessResponses : undefined;\n\n return { response, successResponses, errors, inlineModels, isPaginated, dataPath, itemType };\n}\n","import type { Model, Service, TypeRef } from '../ir/types.js';\nimport { walkTypeRef } from '../ir/types.js';\n\nfunction keepLargestByName(models: Model[]): Model[] {\n const byName = new Map<string, Model>();\n for (const model of models) {\n const existing = byName.get(model.name);\n if (!existing || model.fields.length > existing.fields.length) {\n byName.set(model.name, model);\n }\n }\n return [...byName.values()];\n}\n\nfunction rewriteModelRef(ref: TypeRef, oldName: string, newName: string): void {\n walkTypeRef(ref, {\n model: (r) => {\n if (r.name === oldName) (r as { name: string }).name = newName;\n },\n });\n}\n\nfunction rewriteModelRefs(models: Model[], services: Service[], oldName: string, newName: string): void {\n for (const model of models) {\n for (const field of model.fields) {\n rewriteModelRef(field.type, oldName, newName);\n }\n }\n for (const service of services) {\n for (const op of service.operations) {\n rewriteModelRef(op.response, oldName, newName);\n if (op.requestBody) {\n rewriteModelRef(op.requestBody, oldName, newName);\n }\n }\n }\n}\n\nexport function mergeInlineResponseModels(schemaModels: Model[], inlineModels: Model[]): Model[] {\n const mergedSchemaModels = [...schemaModels];\n const schemaModelNames = new Set(mergedSchemaModels.map((m) => m.name));\n const schemaModelsByName = new Map(mergedSchemaModels.map((m) => [m.name, m]));\n\n const deduplicatedInlineModels = inlineModels.filter((model) => {\n if (!schemaModelNames.has(model.name)) return true;\n\n const existing = schemaModelsByName.get(model.name)!;\n const existingFieldNames = new Set(existing.fields.map((f) => f.name));\n const inlineFieldNames = new Set(model.fields.map((f) => f.name));\n const hasDifference =\n model.fields.some((f) => !existingFieldNames.has(f.name)) ||\n existing.fields.some((f) => !inlineFieldNames.has(f.name));\n\n if (hasDifference && model.fields.length > existing.fields.length) {\n const idx = mergedSchemaModels.indexOf(existing);\n if (idx !== -1) mergedSchemaModels[idx] = model;\n schemaModelsByName.set(model.name, model);\n console.warn(\n `[oagen] Warning: Inline model \"${model.name}\" has more fields than component schema (${model.fields.length} vs ${existing.fields.length}) — using inline response model`,\n );\n } else if (hasDifference) {\n console.warn(\n `[oagen] Warning: Inline model \"${model.name}\" has different fields than component schema — using component schema`,\n );\n }\n\n return false;\n });\n\n return [...mergedSchemaModels, ...keepLargestByName(deduplicatedInlineModels)];\n}\n\nexport function mergeFieldInlineModels(existingModels: Model[], fieldInlineModels: Model[]): Model[] {\n const modelNames = new Set(existingModels.map((m) => m.name));\n const modelsByName = new Map(existingModels.map((m) => [m.name, m]));\n\n const deduplicatedFieldModels = fieldInlineModels.filter((model) => {\n if (!modelNames.has(model.name)) return true;\n\n const existing = modelsByName.get(model.name)!;\n const existingFieldNames = new Set(existing.fields.map((f) => f.name));\n const inlineFieldNames = new Set(model.fields.map((f) => f.name));\n const hasDifference =\n model.fields.some((f) => !existingFieldNames.has(f.name)) ||\n existing.fields.some((f) => !inlineFieldNames.has(f.name));\n\n if (hasDifference) {\n console.warn(\n `[oagen] Warning: Inline model \"${model.name}\" has different fields than component schema — using component schema`,\n );\n }\n\n return false;\n });\n\n return [...existingModels, ...keepLargestByName(deduplicatedFieldModels)];\n}\n\nfunction hasModelConstDiscriminant(model: Model): boolean {\n return model.fields.some(\n (f) => (f.name === 'object' || f.name === 'type') && f.type.kind === 'literal' && typeof f.type.value === 'string',\n );\n}\n\nfunction isModelReferencedByOthers(name: string, models: Model[], excludeNames: Set<string>): boolean {\n for (const model of models) {\n if (excludeNames.has(model.name)) continue;\n for (const field of model.fields) {\n let found = false;\n walkTypeRef(field.type, {\n model: (r) => {\n if (r.name === name) found = true;\n },\n });\n if (found) return true;\n }\n }\n return false;\n}\n\nexport function collapseJsonSuffixModels(models: Model[], services: Service[]): Model[] {\n const normalizedModels = [...models];\n const byName = new Map(normalizedModels.map((m) => [m.name, m]));\n\n // Pass 1: collect merge candidates\n const mergeCandidates: Array<{ jsonModel: Model; baseModel: Model }> = [];\n for (const model of normalizedModels) {\n if (!model.name.endsWith('Json')) continue;\n\n const baseName = model.name.slice(0, -4);\n const baseModel = byName.get(baseName);\n if (!baseModel || model.fields.length <= baseModel.fields.length) continue;\n\n const isSuperset = baseModel.fields.every((f) => model.fields.some((mf) => mf.name === f.name));\n if (!isSuperset) continue;\n\n // Guard: both models have a const discriminant — they are distinct entities\n if (hasModelConstDiscriminant(model) && hasModelConstDiscriminant(baseModel)) continue;\n\n // Guard: a third model explicitly references the Json-suffix model\n if (isModelReferencedByOthers(model.name, normalizedModels, new Set([model.name, baseName]))) continue;\n\n mergeCandidates.push({ jsonModel: model, baseModel });\n }\n\n // Pass 2: apply merges\n const toRemove = new Set<string>();\n for (const { jsonModel, baseModel } of mergeCandidates) {\n baseModel.fields = jsonModel.fields;\n toRemove.add(jsonModel.name);\n rewriteModelRefs(normalizedModels, services, jsonModel.name, baseModel.name);\n console.warn(\n `[oagen] Merged \"${jsonModel.name}\" into \"${baseModel.name}\" (${jsonModel.fields.length} fields, superset)`,\n );\n }\n\n return normalizedModels.filter((m) => !toRemove.has(m.name));\n}\n","import type { Enum, Model } from '../ir/types.js';\nimport { collectInlineEnumFromRef } from './schemas.js';\n\nexport function collectInlineEnumsFromModels(models: Model[], enums: Enum[]): void {\n const enumNames = new Set(enums.map((e) => e.name));\n for (const model of models) {\n for (const field of model.fields) {\n collectInlineEnumFromRef(field.type, enums, enumNames);\n }\n }\n}\n","import type { ApiSpec, TypeRef } from '../ir/types.js';\nimport { walkTypeRef } from '../ir/types.js';\n\nexport function validateModelRefs(spec: ApiSpec): void {\n const knownNames = new Set<string>();\n for (const m of spec.models) knownNames.add(m.name);\n for (const e of spec.enums) knownNames.add(e.name);\n\n function walkRef(ref: TypeRef, context: string): void {\n walkTypeRef(ref, {\n model: (r) => {\n if (!knownNames.has(r.name)) {\n console.warn(`[oagen] Warning: Unresolved model reference \"${r.name}\" (context: ${context})`);\n }\n },\n });\n }\n\n for (const model of spec.models) {\n for (const field of model.fields) {\n walkRef(field.type, `${model.name}.${field.name}`);\n }\n }\n\n for (const service of spec.services) {\n for (const op of service.operations) {\n for (const p of [...op.pathParams, ...op.queryParams, ...op.headerParams]) {\n walkRef(p.type, `${service.name}.${op.name}.${p.name}`);\n }\n if (op.requestBody) walkRef(op.requestBody, `${service.name}.${op.name}.requestBody`);\n walkRef(op.response, `${service.name}.${op.name}.response`);\n }\n }\n}\n","import type { ApiSpec, AuthScheme, ServerEntry } from '../ir/types.js';\nimport { SpecParseError } from '../errors.js';\nimport { loadAndBundleSpec } from './refs.js';\nimport { extractSchemas, extractInlineModelsFromSchemas } from './schemas.js';\nimport { extractOperations } from './operations.js';\nimport {\n mergeInlineResponseModels,\n collapseJsonSuffixModels,\n mergeFieldInlineModels,\n} from './normalize-inline-models.js';\nimport { collectInlineEnumsFromModels } from './collect-inline-enums.js';\nimport { validateModelRefs } from './normalize-model-refs.js';\n\nexport interface ParseOptions {\n operationIdTransform?: (id: string) => string;\n}\n\nexport async function parseSpec(specPath: string, options?: ParseOptions): Promise<ApiSpec> {\n const { parsed } = await loadAndBundleSpec(specPath);\n\n const spec = parsed as {\n openapi?: string;\n info?: { title?: string; version?: string; description?: string };\n servers?: Array<{ url?: string; description?: string }>;\n paths?: Record<string, unknown>;\n components?: {\n schemas?: Record<string, unknown>;\n securitySchemes?: Record<\n string,\n { type: string; scheme?: string; in?: string; name?: string; flows?: Record<string, unknown> }\n >;\n };\n };\n\n // Validate OpenAPI version\n const version = spec.openapi ?? '';\n if (!version.startsWith('3.')) {\n throw new SpecParseError(\n `Unsupported OpenAPI version: ${version}. oagen requires OpenAPI 3.x`,\n `Update the spec to OpenAPI 3.0 or 3.1. If you are using Swagger 2.x, convert it first with \\`npx swagger2openapi ${specPath}\\`.`,\n );\n }\n\n const { models, enums } = extractSchemas(\n spec.components?.schemas as Record<string, Record<string, unknown>> | undefined,\n );\n\n const { services, inlineModels } = extractOperations(\n spec.paths as Record<string, Record<string, unknown>> | undefined,\n options?.operationIdTransform,\n );\n\n const responseNormalizedModels = mergeInlineResponseModels(models, inlineModels);\n\n // Extract inline models from model field definitions (objects/arrays with properties)\n const fieldInlineModels = extractInlineModelsFromSchemas(\n spec.components?.schemas as Record<string, Record<string, unknown>> | undefined,\n );\n const fieldMergedModels = mergeFieldInlineModels(responseNormalizedModels, fieldInlineModels);\n const finalModels = collapseJsonSuffixModels(fieldMergedModels, services);\n collectInlineEnumsFromModels(finalModels, enums);\n\n const auth = extractAuthSchemes(spec.components?.securitySchemes);\n\n const serverEntries: ServerEntry[] = (spec.servers ?? [])\n .map((s) => ({ url: s.url ?? '', description: s.description }))\n .filter((s) => s.url);\n\n const result: ApiSpec = {\n name: spec.info?.title ?? 'Unknown API',\n version: spec.info?.version ?? '0.0.0',\n description: spec.info?.description,\n baseUrl: serverEntries[0]?.url ?? '',\n servers: serverEntries.length > 0 ? serverEntries : undefined,\n services,\n models: finalModels,\n enums,\n auth,\n };\n\n validateModelRefs(result);\n\n return result;\n}\n/** Extract authentication schemes from OpenAPI securitySchemes. */\nfunction extractAuthSchemes(\n securitySchemes?: Record<\n string,\n { type: string; scheme?: string; in?: string; name?: string; flows?: Record<string, unknown> }\n >,\n): AuthScheme[] | undefined {\n if (!securitySchemes) return undefined;\n const schemes: AuthScheme[] = [];\n for (const [, scheme] of Object.entries(securitySchemes)) {\n if (scheme.type === 'http' && scheme.scheme === 'bearer') {\n schemes.push({ kind: 'bearer' });\n } else if (scheme.type === 'apiKey' && scheme.in && scheme.name) {\n schemes.push({ kind: 'apiKey', in: scheme.in as 'header' | 'query' | 'cookie', name: scheme.name });\n } else if (scheme.type === 'oauth2' && scheme.flows) {\n schemes.push({ kind: 'oauth2', flows: scheme.flows });\n }\n }\n return schemes.length > 0 ? schemes : undefined;\n}\n","/**\n * Shared infrastructure for smoke tests.\n *\n * Types, operation planning, payload generation, ID registry, and capture format\n * used by both raw HTTP and SDK smoke test scripts.\n */\n\nimport 'dotenv/config';\nimport { readFileSync } from 'node:fs';\nimport type { ApiSpec, Operation, Parameter, TypeRef } from '../../src/ir/types.js';\nimport { toSnakeCase, toCamelCase } from '../../src/utils/naming.js';\n\n// Re-export types and functions that external smoke runners need from oagen core.\n// External runners import from '@workos/oagen/smoke' which bundles this module.\nexport { parseSpec } from '../../src/parser/parse.js';\nexport { toCamelCase, toSnakeCase } from '../../src/utils/naming.js';\n\n// ---------------------------------------------------------------------------\n// Capture format\n// ---------------------------------------------------------------------------\n\nexport interface ExchangeProvenance {\n resolutionTier: 'exact' | 'crud-prefix' | 'fuzzy' | 'manifest';\n resolutionConfidence: number;\n sdkMethodName: string;\n captureIndex: number;\n totalCaptures: number;\n}\n\nexport interface CapturedExchange {\n operationId: string;\n service: string;\n operationName: string;\n request: {\n method: string;\n path: string;\n queryParams: Record<string, string>;\n body: unknown | null;\n };\n response: {\n status: number;\n body: unknown | null;\n };\n outcome: 'success' | 'api-error' | 'skipped';\n error?: string;\n /** True when the response status code is not declared in the OpenAPI spec for this operation */\n unexpectedStatus?: boolean;\n /** Status codes declared in the OpenAPI spec (success + error codes) */\n expectedStatusCodes?: number[];\n durationMs: number;\n /** How the SDK method was resolved and which capture was selected */\n provenance?: ExchangeProvenance;\n}\n\nexport interface SmokeResults {\n source: 'raw' | 'spec-baseline' | `sdk-${string}`;\n timestamp: string;\n specVersion: string;\n exchanges: CapturedExchange[];\n}\n\n// ---------------------------------------------------------------------------\n// Operation planning\n// ---------------------------------------------------------------------------\n\nexport interface PlannedOperation {\n service: string;\n operation: Operation;\n}\n\nexport interface PlannedGroup {\n service: string;\n operations: PlannedOperation[];\n}\n\n// ---------------------------------------------------------------------------\n// Smoke config — mutable state populated by loadSmokeConfig()\n// ---------------------------------------------------------------------------\n\n/** Operations that require complex preconditions and can't be auto-tested */\nexport let SKIP_OPERATIONS = new Set<string>();\n\n/** Services to skip entirely */\nexport let SKIP_SERVICES = new Set<string>();\n\n/**\n * Services that produce IDs other services depend on should run first.\n * Lower number = runs earlier. Unlisted services default to 50.\n */\nlet SERVICE_PRIORITY: Record<string, number> = {};\n\n/**\n * Map IR service names to SDK property names on the client object.\n * Empty = use toCamelCase(serviceName) as fallback.\n */\nexport let SERVICE_PROPERTY_MAP: Record<string, string> = {};\n\nexport interface SmokeConfig {\n skipOperations: string[];\n skipServices: string[];\n servicePriority: Record<string, number>;\n servicePropertyMap: Record<string, string>;\n}\n\n/** Load smoke test configuration from a JSON file */\nexport function loadSmokeConfig(configPath?: string): void {\n if (!configPath) return;\n const raw = readFileSync(configPath, 'utf-8');\n const config: SmokeConfig = JSON.parse(raw);\n\n if (config.skipOperations) SKIP_OPERATIONS = new Set(config.skipOperations);\n if (config.skipServices) SKIP_SERVICES = new Set(config.skipServices);\n if (config.servicePriority) SERVICE_PRIORITY = config.servicePriority;\n if (config.servicePropertyMap) SERVICE_PROPERTY_MAP = config.servicePropertyMap;\n}\n\n/** Return the current smoke config values (for diff.ts to consume) */\nexport function getSmokeConfig() {\n return {\n skipOperations: SKIP_OPERATIONS,\n skipServices: SKIP_SERVICES,\n servicePriority: SERVICE_PRIORITY,\n servicePropertyMap: SERVICE_PROPERTY_MAP,\n };\n}\n\n/**\n * Assign a numeric sort key to an operation so that ID-producing operations\n * (parameterless creates and lists) run before ID-consuming ones.\n */\nfunction operationSortKey(op: Operation): number {\n const hasParams = op.pathParams.length > 0;\n const method = op.httpMethod;\n\n if (method === 'post' && !hasParams) return 0; // top-level create\n if (method === 'get' && !hasParams && op.pagination) return 1; // top-level list\n if (method === 'get' && !hasParams) return 2; // top-level singular GET\n if (method === 'post' && hasParams) return 3; // sub-entity create\n if (method === 'get' && hasParams && op.pagination) return 4; // sub-entity list\n if (method === 'get' && hasParams) return 5; // singular GET by ID\n if (method === 'put' || method === 'patch') return 6; // update\n if (method === 'delete') return 7; // delete\n return 99;\n}\n\nexport function planOperations(spec: ApiSpec): PlannedGroup[] {\n const groups: PlannedGroup[] = [];\n\n for (const service of spec.services) {\n if (SKIP_SERVICES.has(service.name)) continue;\n\n const ops: PlannedOperation[] = [];\n for (const op of service.operations) {\n if (SKIP_OPERATIONS.has(op.name)) continue;\n\n ops.push({ service: service.name, operation: op });\n }\n\n if (ops.length === 0) continue;\n\n // Sort to maximize ID availability:\n // 1. Parameterless POSTs (create new top-level entities → produce IDs)\n // 2. Parameterless list GETs (discover existing IDs)\n // 3. Parameterized POSTs (create sub-entities, need parent IDs)\n // 4. Parameterized list GETs\n // 5. Parameterized singular GETs (retrieve by ID)\n // 6. PUT/PATCH (update)\n // 7. DELETE\n ops.sort((a, b) => {\n return operationSortKey(a.operation) - operationSortKey(b.operation);\n });\n\n groups.push({ service: service.name, operations: ops });\n }\n\n // Sort service groups so ID-producing services run first\n groups.sort((a, b) => {\n const aPri = SERVICE_PRIORITY[a.service] ?? 50;\n const bPri = SERVICE_PRIORITY[b.service] ?? 50;\n return aPri - bPri;\n });\n\n return groups;\n}\n\n// ---------------------------------------------------------------------------\n// Wave-based operation planning for batched runners\n// ---------------------------------------------------------------------------\n\n/**\n * A single wave of operations that can be planned and executed together.\n * Wave 0 contains parameterless operations. Subsequent waves contain\n * operations whose path params became resolvable after earlier waves ran.\n */\nexport interface OperationWave {\n /** Operations in this wave, with pre-resolved path params */\n calls: Array<{\n op: Operation;\n irService: string;\n pathParams: Record<string, string>;\n }>;\n}\n\n/**\n * Plan operations in waves so that batched runners can execute each wave,\n * extract IDs from responses, then plan the next wave.\n *\n * Returns an iterator that yields one wave at a time. The caller must\n * execute each wave and populate the IdRegistry before calling next().\n *\n * @param groups - service groups from planOperations()\n * @param ids - the IdRegistry (mutated by the caller between waves)\n * @param resolveMethod - optional filter; return null to skip an operation\n */\nexport function* planWaves(\n groups: PlannedGroup[],\n ids: IdRegistry,\n resolveMethod?: (op: Operation, irService: string) => boolean,\n): Generator<OperationWave, PlannedOperation[], void> {\n // Flatten all operations into a single ordered list\n const remaining: PlannedOperation[] = [];\n for (const group of groups) {\n for (const planned of group.operations) {\n remaining.push(planned);\n }\n }\n\n // Track which operations have been emitted\n const emitted = new Set<number>();\n const skipped: PlannedOperation[] = [];\n\n // Pre-filter: mark operations that fail the resolveMethod check as skipped\n for (let i = 0; i < remaining.length; i++) {\n const { operation: op, service: irService } = remaining[i];\n if (resolveMethod && !resolveMethod(op, irService)) {\n emitted.add(i);\n skipped.push(remaining[i]);\n }\n }\n\n // Wave 0: operations with no path params\n let wave: OperationWave = { calls: [] };\n for (let i = 0; i < remaining.length; i++) {\n if (emitted.has(i)) continue;\n const { operation: op, service: irService } = remaining[i];\n if (op.pathParams.length === 0) {\n wave.calls.push({ op, irService, pathParams: {} });\n emitted.add(i);\n }\n }\n\n if (wave.calls.length > 0) {\n yield wave;\n }\n\n // Subsequent waves: try to resolve remaining operations\n let madeProgress = true;\n while (madeProgress) {\n madeProgress = false;\n wave = { calls: [] };\n\n for (let i = 0; i < remaining.length; i++) {\n if (emitted.has(i)) continue;\n const { operation: op, service: irService } = remaining[i];\n\n const resolved = ids.resolvePathParams(op, irService);\n if (resolved) {\n wave.calls.push({ op, irService, pathParams: resolved });\n emitted.add(i);\n madeProgress = true;\n }\n }\n\n if (wave.calls.length > 0) {\n yield wave;\n }\n }\n\n // Collect truly unresolvable operations for the caller to mark as skipped\n const unresolved: PlannedOperation[] = [];\n for (let i = 0; i < remaining.length; i++) {\n if (!emitted.has(i)) {\n unresolved.push(remaining[i]);\n }\n }\n return unresolved;\n}\n\n// ---------------------------------------------------------------------------\n// Payload generation\n// ---------------------------------------------------------------------------\n\nexport function generateFixtureValue(typeRef: TypeRef, fieldName: string, spec: ApiSpec): unknown {\n switch (typeRef.kind) {\n case 'primitive':\n return generatePrimitiveFixture(typeRef.type, typeRef.format, fieldName);\n case 'array':\n return [generateFixtureValue(typeRef.items, fieldName, spec)];\n case 'model': {\n const model = spec.models.find((m) => m.name === typeRef.name);\n if (model) {\n const obj: Record<string, unknown> = {};\n for (const field of model.fields) {\n if (field.required) {\n obj[toSnakeCase(field.name)] = generateFixtureValue(field.type, field.name, spec);\n }\n }\n return obj;\n }\n return {};\n }\n case 'enum': {\n const e = spec.enums.find((en) => en.name === typeRef.name);\n return e?.values[0]?.value ?? 'unknown';\n }\n case 'nullable':\n return generateFixtureValue(typeRef.inner, fieldName, spec);\n case 'union':\n if (typeRef.variants.length > 0) {\n return generateFixtureValue(typeRef.variants[0], fieldName, spec);\n }\n return null;\n }\n}\n\nfunction generatePrimitiveFixture(type: string, format: string | undefined, fieldName: string): unknown {\n if (type === 'string') {\n if (format === 'uuid') return '550e8400-e29b-41d4-a716-446655440000';\n if (format === 'date') return '2024-01-01';\n if (format === 'date-time') return '2024-01-01T00:00:00Z';\n if (format === 'email') return 'test@example.com';\n if (format === 'uri' || format === 'url') return 'https://example.com';\n return `test_${toSnakeCase(fieldName)}`;\n }\n if (type === 'integer') return 1;\n if (type === 'number') return 1.0;\n if (type === 'boolean') return true;\n return null;\n}\n\n/** Generate a snake_case request body payload from an operation's requestBody type */\nexport function generatePayload(op: Operation, spec: ApiSpec): Record<string, unknown> | null {\n if (!op.requestBody) return null;\n\n const bodyType = op.requestBody;\n if (bodyType.kind === 'model') {\n const model = spec.models.find((m) => m.name === bodyType.name);\n if (!model) return {};\n\n const payload: Record<string, unknown> = {};\n for (const field of model.fields) {\n if (!field.required) continue;\n const key = toSnakeCase(field.name);\n let value = generateFixtureValue(field.type, field.name, spec);\n\n // Inject uniqueness markers for name/slug fields\n if ((key === 'name' || key === 'slug') && typeof value === 'string') {\n value = `smoke-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;\n }\n payload[key] = value;\n }\n return payload;\n }\n\n // Fallback for non-model body types\n return {};\n}\n\n/** Generate a fixture value with SDK-friendly types (e.g. Date objects for date-time) */\nfunction generateSDKFixtureValue(typeRef: TypeRef, fieldName: string, spec: ApiSpec): unknown {\n const value = generateFixtureValue(typeRef, fieldName, spec);\n // SDK methods expect Date objects for date-time fields, not ISO strings\n if (typeRef.kind === 'primitive' && typeRef.format === 'date-time' && typeof value === 'string') {\n return new Date(value);\n }\n return value;\n}\n\n/** Generate a camelCase payload for SDK method calls */\nexport function generateCamelPayload(op: Operation, spec: ApiSpec): Record<string, unknown> | null {\n if (!op.requestBody) return null;\n\n const bodyType = op.requestBody;\n if (bodyType.kind === 'model') {\n const model = spec.models.find((m) => m.name === bodyType.name);\n if (!model) return {};\n\n const payload: Record<string, unknown> = {};\n for (const field of model.fields) {\n if (!field.required) continue;\n const key = toCamelCase(field.name);\n let value = generateSDKFixtureValue(field.type, field.name, spec);\n\n if ((field.name === 'name' || field.name === 'slug') && typeof value === 'string') {\n value = `smoke-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;\n }\n payload[key] = value;\n }\n return payload;\n }\n\n return {};\n}\n\n/** Generate query params for an operation (required params only, plus limit=1 for lists) */\nexport function generateQueryParams(op: Operation, spec: ApiSpec): Record<string, string> {\n const params: Record<string, string> = {};\n\n if (op.pagination) {\n params['limit'] = '1';\n }\n\n for (const p of op.queryParams) {\n if (!p.required) continue;\n const value = generateFixtureValue(p.type, p.name, spec);\n params[toSnakeCase(p.name)] = String(value);\n }\n\n // Sort by key\n const sorted: Record<string, string> = {};\n for (const key of Object.keys(params).sort()) {\n sorted[key] = params[key];\n }\n return sorted;\n}\n\n/** Generate camelCase query params for SDK method calls */\nexport function generateCamelQueryParams(op: Operation, spec: ApiSpec): Record<string, unknown> {\n const params: Record<string, unknown> = {};\n\n if (op.pagination) {\n params['limit'] = 1;\n }\n\n for (const p of op.queryParams) {\n if (!p.required) continue;\n const value = generateFixtureValue(p.type, p.name, spec);\n params[toCamelCase(p.name)] = value;\n }\n\n return params;\n}\n\n// ---------------------------------------------------------------------------\n// ID Registry\n// ---------------------------------------------------------------------------\n\nexport class IdRegistry {\n private ids = new Map<string, string>();\n\n set(service: string, field: string, value: string): void {\n this.ids.set(`${service}.${field}`, value);\n }\n\n get(service: string, field: string): string | undefined {\n return this.ids.get(`${service}.${field}`);\n }\n\n /** Resolve path parameters for an operation using stored IDs */\n resolvePathParams(op: Operation, service: string): Record<string, string> | null {\n const resolved: Record<string, string> = {};\n for (const p of op.pathParams) {\n const value =\n this.get(service, p.name) ||\n this.get(service, 'id') ||\n this.findAcrossServices(p.name) ||\n this.resolveFromParamName(p.name) ||\n this.resolveFromExample(p);\n\n if (!value) return null;\n resolved[p.name] = value;\n }\n return resolved;\n }\n\n /** Try to find a param value across all services */\n private findAcrossServices(field: string): string | undefined {\n for (const [key, value] of this.ids.entries()) {\n if (key.endsWith(`.${field}`)) return value;\n }\n // Also try snake_case variant: \"organizationId\" → \"organization_id\"\n const snakeField = toSnakeCase(field);\n if (snakeField !== field) {\n for (const [key, value] of this.ids.entries()) {\n if (key.endsWith(`.${snakeField}`)) return value;\n }\n }\n return undefined;\n }\n\n /**\n * Resolve a path param like \"organizationId\" by mapping it to the\n * service that stores that entity's ID (e.g. Organizations.id).\n * Also handles snake_case suffixed with _id by stripping the suffix\n * and looking up the pluralized service name.\n */\n private resolveFromParamName(paramName: string): string | undefined {\n // Infer from param name: \"resource_id\" → \"Resources\", \"role_assignment_id\" → \"RoleAssignments\"\n // Handle snake_case: strip trailing _id, PascalCase+pluralize the rest\n if (paramName.endsWith('_id')) {\n const base = paramName.slice(0, -3); // e.g. \"resource_type\" from \"resource_type_id\"\n const pascal = base\n .split('_')\n .map((w) => w.charAt(0).toUpperCase() + w.slice(1))\n .join('');\n const plural = pascal.endsWith('s') ? pascal : pascal + 's';\n const val = this.get(plural, 'id') || this.get(plural, 'slug');\n if (val) return val;\n\n // Fallback: find any service whose name ends with the plural suffix\n // e.g. \"user_id\" → \"Users\" not found → try \"UserManagementUsers\"\n const suffixVal = this.findByServiceSuffix(plural, 'id') || this.findByServiceSuffix(plural, 'slug');\n if (suffixVal) return suffixVal;\n }\n\n // Handle camelCase: \"resourceId\" → strip \"Id\", pluralize → \"Resources\"\n if (paramName.endsWith('Id') && paramName.length > 2) {\n const base = paramName.slice(0, -2); // e.g. \"organization\"\n const pascal = base.charAt(0).toUpperCase() + base.slice(1);\n const plural = pascal.endsWith('s') ? pascal : pascal + 's';\n const val = this.get(plural, 'id') || this.get(plural, 'slug');\n if (val) return val;\n\n // Fallback: find any service whose name ends with the plural suffix\n const suffixVal = this.findByServiceSuffix(plural, 'id') || this.findByServiceSuffix(plural, 'slug');\n if (suffixVal) return suffixVal;\n }\n\n return undefined;\n }\n\n /**\n * Find a value by looking for any service name that ends with the given suffix.\n * e.g. suffix \"Users\" matches \"UserManagementUsers.id\"\n */\n private findByServiceSuffix(suffix: string, field: string): string | undefined {\n for (const [key, value] of this.ids.entries()) {\n if (key.endsWith(`.${field}`)) {\n const servicePart = key.slice(0, -(field.length + 1));\n if (servicePart.endsWith(suffix)) {\n return value;\n }\n }\n }\n return undefined;\n }\n\n /**\n * Last-resort fallback: use the spec's example or default value for a parameter.\n * Many path params (e.g. actionName, slug, type) have example values in the spec.\n */\n private resolveFromExample(param: Parameter): string | undefined {\n const value = param.example ?? param.default;\n if (value !== undefined && value !== null) {\n return String(value);\n }\n return undefined;\n }\n\n /**\n * Extract IDs from a response body and store them.\n * @param isTopLevel - true for operations without path params (their `id` belongs to this service).\n * false for sub-resource operations (their `id` is a child entity, don't overwrite).\n */\n extractAndStore(service: string, responseBody: unknown, isTopLevel = true): void {\n if (!responseBody || typeof responseBody !== 'object') return;\n\n const body = responseBody as Record<string, unknown>;\n\n // Only store direct ID from top-level operations to avoid overwriting\n // e.g. Organizations.id with an API key ID from /organizations/{id}/api_keys\n if (isTopLevel) {\n if (typeof body.id === 'string') {\n this.set(service, 'id', body.id);\n }\n\n // List response: extract from first item\n if (Array.isArray(body.data) && body.data.length > 0) {\n const first = body.data[0] as Record<string, unknown> | undefined;\n if (first && typeof first === 'object') {\n if (typeof first.id === 'string') {\n this.set(service, 'id', first.id);\n }\n this.extractNestedIds(service, first);\n }\n }\n\n if (typeof body.slug === 'string') this.set(service, 'slug', body.slug);\n if (typeof body.key === 'string') this.set(service, 'key', body.key);\n }\n\n // Always extract nested reference IDs (e.g. organization_id, connection_id)\n this.extractNestedIds(service, body);\n if (Array.isArray(body.data) && body.data.length > 0) {\n const first = body.data[0] as Record<string, unknown> | undefined;\n if (first && typeof first === 'object') {\n this.extractNestedIds(service, first);\n }\n }\n }\n\n /** Extract fields ending in _id or Id and store them for cross-service resolution */\n private extractNestedIds(service: string, obj: Record<string, unknown>): void {\n for (const [key, value] of Object.entries(obj)) {\n if (typeof value !== 'string') continue;\n if (key === 'id') continue; // already handled\n // Store fields like \"organization_id\", \"connection_id\" directly\n if (key.endsWith('_id') || (key.endsWith('Id') && key.length > 2)) {\n this.set(service, key, value);\n }\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Status code checking\n// ---------------------------------------------------------------------------\n\n/** Get the set of status codes declared in the spec for an operation (success + errors) */\nexport function getExpectedStatusCodes(op: Operation): number[] {\n const codes: number[] = [];\n // The success response code is implied by HTTP method if not explicit in errors\n // Common defaults: POST→201, GET→200, PUT→200, PATCH→200, DELETE→204\n const defaultSuccess: Record<string, number> = {\n post: 201,\n get: 200,\n put: 200,\n patch: 200,\n delete: 204,\n };\n codes.push(defaultSuccess[op.httpMethod] ?? 200);\n // Add declared error codes from the spec\n for (const err of op.errors) {\n if (!codes.includes(err.statusCode)) {\n codes.push(err.statusCode);\n }\n }\n return codes.sort((a, b) => a - b);\n}\n\n/** Check if a status code is unexpected (not declared in the spec) */\nexport function isUnexpectedStatus(status: number, op: Operation): boolean {\n if (status === 0) return false; // skipped or network error, not a status mismatch\n const expected = getExpectedStatusCodes(op);\n return !expected.includes(status);\n}\n\n// ---------------------------------------------------------------------------\n// Path resolution\n// ---------------------------------------------------------------------------\n\nexport function resolvePath(op: Operation, pathParams: Record<string, string>): string {\n let path = op.path;\n for (const [name, value] of Object.entries(pathParams)) {\n path = path.replace(`{${name}}`, value);\n }\n return path;\n}\n\n// ---------------------------------------------------------------------------\n// Utilities\n// ---------------------------------------------------------------------------\n\nexport function delay(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nexport function parseCliArgs(): { spec: string; sdkPath?: string; smokeConfig?: string } {\n const args = process.argv.slice(2);\n const specIdx = args.indexOf('--spec');\n const spec = specIdx !== -1 && args[specIdx + 1] ? args[specIdx + 1] : process.env.OPENAPI_SPEC_PATH;\n if (!spec) {\n console.error('OpenAPI spec path is required. Set OPENAPI_SPEC_PATH env var or pass --spec <path>.');\n process.exit(1);\n }\n const sdkPathIdx = args.indexOf('--sdk-path');\n const sdkPath = sdkPathIdx !== -1 && args[sdkPathIdx + 1] ? args[sdkPathIdx + 1] : undefined;\n const configIdx = args.indexOf('--smoke-config');\n const smokeConfig = configIdx !== -1 && args[configIdx + 1] ? args[configIdx + 1] : process.env.SMOKE_CONFIG;\n return { spec, sdkPath, smokeConfig };\n}\n"],"mappings":";;;;;;;;;;;;;;AAOA,SAAgB,WAAW,GAAqB;AAC9C,KAAI,CAAC,EAAG,QAAO,EAAE;AAEjB,QAAO,EACJ,QAAQ,uBAAuB,IAAI,CACnC,QAAQ,mBAAmB,SAAS,CACpC,QAAQ,yBAAyB,SAAS,CAC1C,QAAQ,mBAAmB,SAAS,CACpC,QAAQ,mBAAmB,SAAS,CACpC,MAAM,cAAc,CACpB,QAAQ,MAAM,EAAE,SAAS,EAAE;;AAGhC,MAAa,cAAc,IAAI,IAAI;CAAC;CAAO;CAAO;CAAQ;CAAQ;CAAO;CAAO,CAAC;AAEjF,SAAgB,aAAa,GAAW,UAAgC;CACtE,MAAM,SAAS,WAAW,IAAI,IAAI,CAAC,GAAG,aAAa,GAAG,SAAS,CAAC,GAAG;AACnE,QAAO,WAAW,EAAE,CACjB,KAAK,MAAM;EACV,MAAM,QAAQ,EAAE,aAAa;AAC7B,MAAI,OAAO,IAAI,MAAM,CAAE,QAAO;AAE9B,MAAI,UAAU,QAAS,QAAO;AAC9B,SAAO,EAAE,OAAO,EAAE,CAAC,aAAa,GAAG,EAAE,MAAM,EAAE,CAAC,aAAa;GAC3D,CACD,KAAK,GAAG;;AAGb,SAAgB,YAAY,GAAW,UAAgC;CACrE,MAAM,SAAS,WAAW,IAAI,IAAI,CAAC,GAAG,aAAa,GAAG,SAAS,CAAC,GAAG;CACnE,MAAM,QAAQ,WAAW,EAAE;AAC3B,KAAI,MAAM,WAAW,EAAG,QAAO;AAC/B,QAAO,MACJ,KAAK,GAAG,MAAM;AACb,MAAI,MAAM,EAAG,QAAO,EAAE,aAAa;EACnC,MAAM,QAAQ,EAAE,aAAa;AAC7B,MAAI,OAAO,IAAI,MAAM,CAAE,QAAO;AAC9B,MAAI,UAAU,QAAS,QAAO;AAC9B,SAAO,EAAE,OAAO,EAAE,CAAC,aAAa,GAAG,EAAE,MAAM,EAAE,CAAC,aAAa;GAC3D,CACD,KAAK,GAAG;;AAGb,SAAgB,YAAY,GAAmB;AAC7C,QAAO,WAAW,EAAE,CACjB,KAAK,MAAM,EAAE,aAAa,CAAC,CAC3B,KAAK,IAAI;;AASd,SAAgB,iBAAiB,GAAmB;AAClD,QAAO,WAAW,EAAE,CACjB,KAAK,MAAM,EAAE,aAAa,CAAC,CAC3B,KAAK,IAAI;;AAGd,MAAM,mBAAmB;CAAC;CAAO;CAAO;CAAa;AAErD,SAAgB,qBAAqB,MAAsB;AACzD,MAAK,MAAM,UAAU,iBACnB,KAAI,KAAK,SAAS,OAAO,IAAI,KAAK,SAAS,OAAO,OAChD,QAAO,KAAK,MAAM,GAAG,CAAC,OAAO,OAAO;AAGxC,QAAO;;AAGT,SAAgB,qBAAqB,MAAsB;AACzD,QAAO,KAAK,QAAQ,aAAa,GAAG,CAAC,QAAQ,eAAe,GAAG;;;;;;AAOjE,SAAgB,qBAAqB,MAAsB;AACzD,QAAO,KACJ,QAAQ,aAAa,GAAG,CACxB,QAAQ,iBAAiB,GAAG,CAC5B,QAAQ,iBAAiB,GAAG,CAC5B,QAAQ,gBAAgB,GAAG;;;AAIhC,MAAM,qBAAqB,IAAI,IAAI;CACjC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD,CAAC;;;;;;;;AASF,SAAgB,YAAY,MAAsB;AAChD,KAAI,mBAAmB,IAAI,KAAK,CAAE,QAAO;AACzC,KAAI,KAAK,SAAS,MAAM,IAAI,KAAK,SAAS,EACxC,QAAO,KAAK,MAAM,GAAG,GAAG,GAAG;AAE7B,KAAI,KAAK,SAAS,MAAM,IAAI,KAAK,SAAS,EAExC,QAAO,KAAK,MAAM,GAAG,GAAG;AAE1B,KAAI,KAAK,SAAS,IAAI,IAAI,CAAC,KAAK,SAAS,KAAK,IAAI,KAAK,SAAS,EAC9D,QAAO,KAAK,MAAM,GAAG,GAAG;AAE1B,QAAO;;AAiBT,SAAgB,gBAAgB,MAAsB;CACpD,IAAI,SAAS,qBAAqB,qBAAqB,KAAK,CAAC;AAC7D,UAAS,qBAAqB,OAAO;CAGrC,MAAM,QAAQ,OAAO,MAAM,iBAAiB;AAC5C,KAAI,OAAO;EACT,MAAM,WAAW,MAAM;EACvB,MAAM,WAAW,YAAY,SAAS;AACtC,MAAI,aAAa,SACf,UAAS,WAAW,OAAO,MAAM,SAAS,OAAO;;AAIrD,QAAO;;;;;;;;;;;ACxJT,IAAa,aAAb,cAAgC,MAAM;CACpC;CAEA,YAAY,SAAiB,MAAc;EACzC,MAAM,cAAc,OAAO,GAAG,QAAQ,UAAU,SAAS;AACzD,QAAM,YAAY;AAClB,OAAK,OAAO;AACZ,OAAK,OAAO;;;;AAgBhB,IAAa,iBAAb,cAAoC,WAAW;CAC7C,YAAY,SAAiB,MAAc;AACzC,QAAM,SAAS,KAAK;AACpB,OAAK,OAAO;;;;;ACvBhB,eAAsB,kBAAkB,UAAwC;CAC9E,MAAM,eAAe,QAAQ,SAAS;CAEtC,MAAM,WAAW,uBADD,MAAM,SAAS,cAAc,QAAQ,EACJ,cAAc,aAAa,CAAC,KAAK;CAElF,MAAM,SAAS,MAAM,aAAa,EAAE,CAAC;CACrC,MAAM,WAAW,IAAI,cAAc;CAEnC,MAAM,SAAS,MAAM,eAAe;EAClC;EACA,QAAQ,OAAO;EACf,qBAAqB;EACrB,aAAa;EACd,CAAC;AAEF,KAAI,OAAO,SAAS,MAAM,MAAM,EAAE,aAAa,QAAQ,CAKrD,OAAM,IAAI,eACR,yBALa,OAAO,SACnB,QAAQ,MAAM,EAAE,aAAa,QAAQ,CACrC,KAAK,MAAM,EAAE,QAAQ,CACrB,KAAK,KAAK,IAGX,8BAA8B,aAAa,oEAAoE,SAAS,wBACzH;AAGH,QAAO;EACL,QAAQ,OAAO,OAAO;EACtB,UAAU;EACX;;;;;;;;;;;;;;;;;AC+IH,SAAgB,YAAY,GAAiB;CAE3C,MAAM,OAAQ,EAAc;CAC5B,MAAM,sBAAM,IAAI,MACd,4BAA4B,KAAK,oGAClC;AACD,KAAI,OAAO;AACX,OAAM;;;;;;;;AASR,SAAgB,YACd,KACA,SAMM;AACN,SAAQ,IAAI,MAAZ;EACE,KAAK;AACH,WAAQ,QAAQ,IAAI;AACpB;EACF,KAAK;AACH,WAAQ,OAAO,IAAI;AACnB;EACF,KAAK;AACH,eAAY,IAAI,OAAO,QAAQ;AAC/B;EACF,KAAK;AACH,eAAY,IAAI,OAAO,QAAQ;AAC/B;EACF,KAAK;AACH,QAAK,MAAM,KAAK,IAAI,SAAU,aAAY,GAAG,QAAQ;AACrD;EACF,KAAK;AACH,OAAI,IAAI,QAAS,aAAY,IAAI,SAAS,QAAQ;AAClD,eAAY,IAAI,WAAW,QAAQ;AACnC;EACF,KAAK;AACH,WAAQ,UAAU,IAAI;AACtB;EACF,KAAK;AACH,WAAQ,YAAY,IAAI;AACxB;EACF,QACE,aAAY,IAAI;;;;;;;;;;;AChOtB,SAAgB,uBAAuB,UAAkB,YAA6B;AACpF,KAAI,CAAC,WAAY,QAAO;CAIxB,MAAM,cAAc,qBAAqB,WAAW;AACpD,KAAI,SAAS,WAAW,YAAY,CAAE,QAAO;CAG7C,MAAM,gBAAgB,SAAS,MAAM,uBAAuB;AAC5D,KAAI,eAAe;EACjB,MAAM,GAAG,QAAQ,gBAAgB;AAEjC,SAAO,GAAG,cAAc,SADP,YAAY,aAAa;;AAG5C,QAAO,GAAG,cAAc;;;;;;;AAQ1B,SAAgB,+BAA+B,SAA4D;AACzG,KAAI,CAAC,QAAS,QAAO,EAAE;CAEvB,MAAM,eAAwB,EAAE;AAEhC,MAAK,MAAM,CAAC,YAAY,WAAW,OAAO,QAAQ,QAAQ,CAExD,mCAAkC,QAAQ,cADvB,gBAAgB,aAAa,WAAW,CAAC,CACO;AAGrE,QAAO;;AAGT,SAAS,kCAAkC,QAAsB,SAAkB,YAA2B;CAC5G,MAAM,aAAa,OAAO,cAAc,EAAE;CAC1C,MAAM,eAAe,OAAO,SAAS,EAAE;AAEvC,MAAK,MAAM,OAAO,aAChB,KAAI,IAAI,WACN,mCAAkC,KAAK,SAAS,WAAW;AAI/D,MAAK,MAAM,CAAC,WAAW,gBAAgB,OAAO,QAAQ,WAAW,EAAE;AACjE,MAAI,CAAC,YAAa;AAElB,MAAI,YAAY,eAAe,YAAY,SAAS,YAAY,CAAC,YAAY,OAAO;GAElF,MAAM,YAAY,uBADD,aAAa,UAAU,EACW,WAAW;AAC9D,WAAQ,KAAK,iBAAiB,WAAW,YAAY,CAAC;AACtD,qCAAkC,aAAa,SAAS,UAAU;;AAIpE,MAAI,YAAY,SAAS,WAAW,YAAY,OAAO;GACrD,MAAM,QAAQ,YAAY;AAC1B,OAAI,MAAM,eAAe,MAAM,SAAS,YAAY,CAAC,MAAM,OAAO;IAEhE,MAAM,YAAY,uBADD,aAAa,UAAU,EACW,WAAW;AAC9D,YAAQ,KAAK,iBAAiB,WAAW,MAAM,CAAC;AAChD,sCAAkC,OAAO,SAAS,UAAU;;;AAMhE,MAAI,YAAY,OAAO;GACrB,MAAM,gBAAgB,YAAY,MAAM,MAAM,MAAM,EAAE,eAAe,EAAE,SAAS,YAAY,CAAC,EAAE,MAAM;AACrG,OAAI,eAAe;IAEjB,MAAM,YAAY,uBADD,aAAa,UAAU,EACW,WAAW;AAE9D,QAAI,CADkB,IAAI,IAAI,QAAQ,KAAK,MAAM,EAAE,KAAK,CAAC,CACtC,IAAI,UAAU,EAAE;AACjC,aAAQ,KAAK,iBAAiB,WAAW,cAAc,CAAC;AACxD,uCAAkC,eAAe,SAAS,UAAU;;;;;;AAO9E,SAAS,iBAAiB,MAAc,QAA6B;CACnE,MAAM,cAAc,IAAI,IAAI,OAAO,YAAY,EAAE,CAAC;CAClD,MAAM,SAAkB,EAAE;AAE1B,MAAK,MAAM,CAAC,WAAW,gBAAgB,OAAO,QAAQ,OAAO,cAAc,EAAE,CAAC,EAAE;AAC9E,MAAI,CAAC,YAAa;AAClB,SAAO,KAAK,qBAAqB,WAAW,aAAa,MAAM,YAAY,CAAC;;AAG9E,QAAO;EAAE;EAAM,aAAa,OAAO;EAAa;EAAQ;;;;ACtE1D,SAAgB,eAAe,SAAqE;CAClG,MAAM,QAAgB,EAAE;AAExB,KAAI,CAAC,QAAS,QAAO;EAAE,QAAQ,EAAE;EAAE;EAAO;CAE1C,MAAM,oCAAoB,IAAI,KAAoB;AAElD,MAAK,MAAM,CAAC,MAAM,WAAW,OAAO,QAAQ,QAAQ,EAAE;EACpD,MAAM,aAAa,gBAAgB,aAAa,KAAK,CAAC;AAEtD,MAAI,OAAO,KACT,OAAM,KAAK,YAAY,YAAY,OAAO,CAAC;OACtC;GACL,MAAM,QAAQ,aAAa,YAAY,QAAQ,QAAQ;GACvD,MAAM,WAAW,kBAAkB,IAAI,WAAW;AAClD,OAAI;QAEE,MAAM,OAAO,SAAS,SAAS,OAAO,OACxC,mBAAkB,IAAI,YAAY,MAAM;SAG1C,mBAAkB,IAAI,YAAY,MAAM;;;CAK9C,MAAM,SAAS,CAAC,GAAG,kBAAkB,QAAQ,CAAC;CAI9C,MAAM,aAAa,IAAI,IAAI,OAAO,KAAK,MAAM,EAAE,KAAK,CAAC;CACrD,MAAM,cAAuB,CAAC,GAAG,OAAO;AACxC,QAAO,YAAY,SAAS,GAAG;EAC7B,MAAM,QAAQ,YAAY,KAAK;AAC/B,OAAK,MAAM,SAAS,MAAM,OACxB,2BAA0B,MAAM,MAAM,MAAM,MAAM,MAAM,MAAM,WAAW,EAAE,EAAE,QAAQ,YAAY,YAAY;;AAKjH,MAAK,MAAM,SAAS,OAClB,oBAAmB,MAAM,QAAQ,MAAM;AAGzC,QAAO;EAAE;EAAQ;EAAO;;;;;;AAO1B,SAAgB,yBAAyB,KAAc,OAAe,MAAyB;AAC7F,aAAY,KAAK,EACf,OAAO,MAAM;AACX,MAAI,EAAE,UAAU,CAAC,KAAK,IAAI,EAAE,KAAK,EAAE;AACjC,QAAK,IAAI,EAAE,KAAK;AAChB,SAAM,KAAK;IACT,MAAM,EAAE;IACR,QAAQ,EAAE,OAAO,KAAK,OAAO;KAC3B,MAAM,iBAAiB,OAAO,EAAE,CAAC;KACjC,OAAO;KACP,aAAa,KAAA;KACd,EAAE;IACJ,CAAC;;IAGP,CAAC;;;;;;AAOJ,SAAS,mBAAmB,QAAiB,OAAqB;CAChE,MAAM,OAAO,IAAI,IAAI,MAAM,KAAK,MAAM,EAAE,KAAK,CAAC;AAC9C,MAAK,MAAM,SAAS,OAClB,0BAAyB,MAAM,MAAM,OAAO,KAAK;;;;;;;;AAUrD,SAAS,0BACP,KACA,WACA,iBACA,SACA,QACA,YACA,OACM;AACN,aAAY,KAAK,EACf,QAAQ,aAAa;AACnB,MAAI,WAAW,IAAI,SAAS,KAAK,CAAE;AAInC,MADoB,OAAO,KAAK,QAAQ,CAAC,MAAM,MAAM,gBAAgB,aAAa,EAAE,CAAC,KAAK,SAAS,KAAK,CACvF;EAIjB,MAAM,eAAe,iBAAiB,iBAAiB,QAAQ;AAC/D,MAAI,CAAC,aAAc;EAEnB,MAAM,cAAc,sBAAsB,WAAW,cAAc,QAAQ;AAC3E,MAAI,CAAC,YAAa;EAGlB,MAAM,YAAY,oBAAoB,SAAS,MAAM,YAAY;AACjE,OAAK,MAAM,KAAK,UACd,KAAI,CAAC,WAAW,IAAI,EAAE,KAAK,EAAE;AAC3B,UAAO,KAAK,EAAE;AACd,cAAW,IAAI,EAAE,KAAK;AACtB,SAAM,KAAK,EAAE;;IAIpB,CAAC;;;AAIJ,SAAS,iBAAiB,YAAoB,SAA4D;AACxG,MAAK,MAAM,CAAC,GAAG,MAAM,OAAO,QAAQ,QAAQ,CAC1C,KAAI,gBAAgB,aAAa,EAAE,CAAC,KAAK,WAAY,QAAO;AAE9D,QAAO;;;AAIT,SAAS,sBACP,WACA,cACA,SACqB;AACrB,KAAI,aAAa,aAAa,WAC5B,QAAO,aAAa,WAAW;AAEjC,KAAI,aAAa,MACf,MAAK,MAAM,OAAO,aAAa,OAAO;EACpC,IAAI,WAAW;AACf,MAAI,IAAI,MAAM;GACZ,MAAM,WAAW,IAAI,KAAK,MAAM,IAAI;GACpC,MAAM,UAAU,SAAS,SAAS,SAAS;AAC3C,OAAI,WAAW,QAAQ,SAAU,YAAW,QAAQ;;AAEtD,MAAI,SAAS,aAAa,WACxB,QAAO,SAAS,WAAW;;AAIjC,QAAO;;;AAIT,SAAS,oBAAoB,MAAc,QAA+B;AAExE,KAAI,OAAO,OAAO;EAChB,MAAM,SAAkB,EAAE;AAC1B,OAAK,MAAM,WAAW,OAAO,OAAO;AAClC,OAAI,QAAQ,KAAM;AAClB,OAAI,QAAQ,eAAe,QAAQ,SAAS,YAAY,CAAC,QAAQ,OAAO;IACtE,MAAM,cAAc,IAAI,IAAI,QAAQ,YAAY,EAAE,CAAC;IACnD,MAAM,SAAkB,EAAE;AAC1B,SAAK,MAAM,CAAC,IAAI,OAAO,OAAO,QAAQ,QAAQ,WAAW,EAAE;AACzD,SAAI,CAAC,GAAI;AACT,YAAO,KAAK,qBAAqB,IAAI,IAAI,MAAM,YAAY,CAAC;;IAG9D,MAAM,cAAc,OAAO,WAAW,IAAI,OAAO,GAAG,OAAO,OAAO,SAAS;AAC3E,WAAO,KAAK;KAAE,MAAM;KAAa,aAAa,QAAQ;KAAa;KAAQ,CAAC;;;AAGhF,SAAO;;AAIT,KAAI,OAAO,eAAe,OAAO,SAAS,YAAY,CAAC,OAAO,OAAO;EACnE,MAAM,cAAc,IAAI,IAAI,OAAO,YAAY,EAAE,CAAC;EAClD,MAAM,SAAkB,EAAE;AAC1B,OAAK,MAAM,CAAC,IAAI,OAAO,OAAO,QAAQ,OAAO,WAAW,EAAE;AACxD,OAAI,CAAC,GAAI;AACT,UAAO,KAAK,qBAAqB,IAAI,IAAI,MAAM,YAAY,CAAC;;AAE9D,SAAO,CAAC;GAAE;GAAM,aAAa,OAAO;GAAa;GAAQ,CAAC;;AAI5D,KAAI,OAAO,SAAS,WAAW,OAAO,OAAO,YAAY;EACvD,MAAM,cAAc,IAAI,IAAI,OAAO,MAAM,YAAY,EAAE,CAAC;EACxD,MAAM,SAAkB,EAAE;AAC1B,OAAK,MAAM,CAAC,IAAI,OAAO,OAAO,QAAQ,OAAO,MAAM,WAAW,EAAE;AAC9D,OAAI,CAAC,GAAI;AACT,UAAO,KAAK,qBAAqB,IAAI,IAAI,MAAM,YAAY,CAAC;;AAE9D,SAAO,CAAC;GAAE;GAAM,aAAa,OAAO,MAAM;GAAa;GAAQ,CAAC;;AAGlE,QAAO,EAAE;;;AAIX,SAAgB,qBACd,WACA,aACA,aACA,aACO;AACP,QAAO;EACL,MAAM;EACN,MAAM,gBAAgB,aAAa,WAAW,YAAY;EAC1D,UAAU,YAAY,IAAI,UAAU;EACpC,aAAa,YAAY;EACzB,UAAU,YAAY,YAAY,KAAA;EAClC,WAAW,YAAY,aAAa,KAAA;EACpC,YAAY,YAAY,cAAc,KAAA;EACtC,SAAS,YAAY;EACrB,SAAS,YAAY;EACtB;;AAGH,SAAS,YAAY,MAAc,QAA4B;AAO7D,QAAO;EAAE;EAAM,SANc,OAAO,QAAQ,EAAE,EAAE,KAAK,OAAO;GAC1D,MAAM,iBAAiB,OAAO,EAAE,CAAC;GACjC,OAAO,OAAO,MAAM,WAAW,IAAI,OAAO,EAAE;GAC5C,aAAa,KAAA;GACd,EAAE;EAEoB;;AAEzB,SAAS,aAAa,MAAc,QAAsB,SAA+C;AACvG,KAAI,OAAO,MACT,QAAO,kBAAkB,MAAM,QAAQ,QAAQ;CAGjD,MAAM,cAAc,IAAI,IAAI,OAAO,YAAY,EAAE,CAAC;CAClD,MAAM,SAAkB,EAAE;AAE1B,MAAK,MAAM,CAAC,WAAW,gBAAgB,OAAO,QAAQ,OAAO,cAAc,EAAE,CAAC,EAAE;AAC9E,MAAI,CAAC,YAAa;AAClB,SAAO,KAAK,qBAAqB,WAAW,aAAa,MAAM,YAAY,CAAC;;AAK9E,KAAI,OAAO,wBAAwB,OAAO,OAAO,yBAAyB,YAAY,OAAO;MAC5E,OAAO,KAAK,OAAO,qBAAqB,CAC5C,SAAS,GAAG;GACrB,MAAM,YAAY,gBAAgB,OAAO,sBAAsC,wBAAwB,KAAK;AAC5G,UAAO,KAAK;IACV,MAAM;IACN,MAAM;KAAE,MAAM;KAAO;KAAW;IAChC,UAAU;IACV,aAAa;IACd,CAAC;;;AAIN,QAAO;EAAE;EAAM,aAAa,OAAO;EAAa;EAAQ;;AAG1D,SAAS,kBAAkB,MAAc,QAAsB,SAA+C;CAC5G,MAAM,SAAkB,EAAE;CAC1B,MAAM,8BAAc,IAAI,KAAa;AAErC,MAAK,MAAM,aAAa,OAAO,SAAS,EAAE,EAAE;EAE1C,IAAI,WAAW;AACf,MAAI,UAAU,QAAQ,SAAS;GAC7B,MAAM,WAAW,UAAU,KAAK,MAAM,IAAI;GAC1C,MAAM,UAAU,SAAS,SAAS,SAAS;AAC3C,OAAI,WAAW,QAAQ,SACrB,YAAW,QAAQ;;AAKvB,MAAI,SAAS,OAAO;GAClB,MAAM,SAAS,kBAAkB,MAAM,UAAU,QAAQ;AACzD,QAAK,MAAM,KAAK,OAAO,QAAQ;AAC7B,WAAO,KAAK;KAAE,GAAG;KAAG,UAAU;KAAO,CAAC;AACtC,QAAI,EAAE,SAAU,aAAY,IAAI,EAAE,KAAK;;SAEpC;AACL,OAAI,SAAS,SACX,MAAK,MAAM,KAAK,SAAS,SAAU,aAAY,IAAI,EAAE;AAEvD,OAAI,SAAS,YAAY;IAEvB,MAAM,gCAAgB,IAAI,KAAa;AACvC,SAAK,MAAM,CAAC,WAAW,gBAAgB,OAAO,QAAQ,SAAS,WAAW,EAAE;AAC1E,SAAI,CAAC,YAAa;AAClB,YAAO,KAAK,qBAAqB,WAAW,aAAa,MAAM,cAAc,CAAC;;;;;AAOtF,KAAI,OAAO,SACT,MAAK,MAAM,KAAK,OAAO,SAAU,aAAY,IAAI,EAAE;AAIrD,MAAK,MAAM,KAAK,OACd,GAAE,WAAW,YAAY,IAAI,EAAE,KAAK;AAGtC,QAAO;EAAE;EAAM,aAAa,OAAO;EAAa;EAAQ;;AAG1D,SAAgB,gBAAgB,QAAsB,aAAsB,iBAAmC;AAE7G,KAAI,OAAO,MAAM;EACf,MAAM,WAAW,OAAO,KAAK,MAAM,IAAI;EACvC,MAAM,UAAU,SAAS,SAAS,SAAS;AAC3C,SAAO;GAAE,MAAM;GAAS,MAAM,gBAAgB,aAAa,QAAQ,CAAC;GAAE;;AAIxE,KAAI,MAAM,QAAQ,OAAO,KAAK,EAAE;EAC9B,MAAM,eAAe,OAAO,KAAK,QAAQ,MAAc,MAAM,OAAO;AAEpE,MAAI,aAAa,WAAW,EAC1B,QAAO;GAAE,MAAM;GAAY,OAAO;IAAE,MAAM;IAAa,MAAM;IAAW;GAAE;AAE5E,MAAI,OAAO,KAAK,SAAS,OAAO,IAAI,aAAa,WAAW,EAC1D,QAAO;GACL,MAAM;GACN,OAAO,gBAAgB;IAAE,GAAG;IAAQ,MAAM,aAAa;IAAI,UAAU;IAAO,EAAE,YAAY;GAC3F;AAGH,MAAI,aAAa,SAAS,GAAG;GAE3B,MAAM,MAAe;IAAE,MAAM;IAAS,UADrB,aAAa,KAAK,MAAc,gBAAgB;KAAE,GAAG;KAAQ,MAAM;KAAG,EAAE,YAAY,CAAC;IACtD;AAChD,OAAI,OAAO,KAAK,SAAS,OAAO,CAC9B,QAAO;IAAE,MAAM;IAAY,OAAO;IAAK;AAEzC,UAAO;;;AAKX,KAAI,OAAO,YAAY,OAAO,KAC5B,QAAO;EACL,MAAM;EACN,OAAO,gBAAgB;GAAE,GAAG;GAAQ,UAAU;GAAO,EAAE,YAAY;EACpE;AAMH,KAAI,OAAO,OAAO;EAEhB,MAAM,UAAU,OAAO,MAAM,MAAM,MAAoB,EAAE,KAAK;AAC9D,MAAI,SAAS;AAIX,OADwB,OAAO,MAAM,MAAM,MAAoB,CAAC,EAAE,SAAS,EAAE,cAAc,EAAE,SAAS,UAAU,CAG9G,QAAO;IAAE,MAAM;IAAS,MAAM,uBADb,aAAa,eAAe,eAAe,EACG,gBAAgB;IAAE;AAEnF,UAAO,gBAAgB,SAAS,aAAa,gBAAgB;;AAG/D,MAAI,OAAO,MAAM,WAAW,EAC1B,QAAO,gBAAgB,OAAO,MAAM,IAAI,aAAa,gBAAgB;AAIvE,MADsB,OAAO,MAAM,MAAM,MAAoB,EAAE,WAAW,CAGxE,QAAO;GACL,MAAM;GACN,MAAM,uBAHS,aAAa,eAAe,eAAe,EAGnB,gBAAgB;GACxD;;AAQL,KAAI,OAAO,SAAS,OAAO,OAAO;EAChC,MAAM,kBAAqC,OAAO,QAAQ,UAAU;EACpE,MAAM,cAA8B,OAAO,SAAS,OAAO,SAAS,EAAE;EAGtE,MAAM,cAAc,YAAY,MAC7B,MAAoB,EAAE,SAAS,UAAW,MAAM,QAAQ,EAAE,KAAK,IAAI,EAAE,KAAK,WAAW,KAAK,EAAE,KAAK,OAAO,OAC1G;EACD,MAAM,kBAAkB,YAAY,QAAQ,MAAM,MAAM,YAAY;AAEpE,MAAI,eAAe,gBAAgB,WAAW,EAE5C,QAAO;GACL,MAAM;GACN,OAAO,gBAAgB,gBAAgB,IAAI,aAAa,gBAAgB;GACzE;EAIH,MAAM,WAAW,YACd,QAAQ,MAAoB,EAAE,SAAS,OAAO,CAC9C,KAAK,MAAoB,gBAAgB,GAAG,aAAa,gBAAgB,CAAC;EAC7E,MAAM,UAAU,CAAC,CAAC;EAClB,MAAM,QAAiB;GACrB,MAAM;GACN;GACA;GACA,GAAI,OAAO,gBACP,EACE,eAAe;IACb,UAAU,OAAO,cAAc;IAC/B,SAAS,OAAO,YACd,OAAO,QAAQ,OAAO,cAAc,WAAW,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,OAAO,CACjE,GACA,EAAE,QAAQ,6BAA6B,GAAG,CAC3C,CAAC,CACH;IACF,EACF,GACD,EAAE;GACP;AACD,SAAO,UAAU;GAAE,MAAM;GAAY,OAAO;GAAO,GAAG;;AAIxD,KAAI,OAAO,UAAU,KAAA,GAAW;AAC9B,MAAI,OAAO,OAAO,UAAU,YAAY,OAAO,OAAO,UAAU,YAAY,OAAO,OAAO,UAAU,UAClG,QAAO;GAAE,MAAM;GAAW,OAAO,OAAO;GAAO;AAGjD,MAAI,OAAO,UAAU,KACnB,QAAO;GAAE,MAAM;GAAY,OAAO;IAAE,MAAM;IAAa,MAAM;IAAW;GAAE;AAG5E,MAAI,OAAO,OAAO,UAAU,UAAU;AACpC,OAAI,MAAM,QAAQ,OAAO,MAAM,CAC7B,QAAO;IAAE,MAAM;IAAS,OAAO;KAAE,MAAM;KAAa,MAAM;KAAW;IAAE;AAEzE,UAAO;IAAE,MAAM;IAAO,WAAW;KAAE,MAAM;KAAa,MAAM;KAAW;IAAE;;;AAG7E,KAAI,OAAO,QAAQ,OAAO,KAAK,WAAW,GAAG;EAC3C,MAAM,IAAI,OAAO,KAAK;AACtB,SAAO;GAAE,MAAM;GAAW,OAAO,OAAO,MAAM,WAAW,IAAI,OAAO,EAAE;GAAE;;AAI1E,KAAI,OAAO,MAAM;EACf,MAAM,WAAW,aAAa,eAAe,cAAc;EAG3D,MAAM,cAAc,kBAAkB,qBAAqB,gBAAgB,GAAG,KAAA;AAG9E,SAAO;GACL,MAAM;GACN,MAHoB,eAAe,CAAC,SAAS,WAAW,YAAY,GAAG,GAAG,cAAc,aAAa;GAIrG,QAAQ,OAAO,KAAK,KAAK,MAAO,OAAO,MAAM,WAAW,IAAI,OAAO,EAAE,CAAE;GACxE;;AAIH,KAAI,OAAO,SAAS,WAAW,OAAO,MACpC,QAAO;EACL,MAAM;EACN,OAAO,gBAAgB,OAAO,OAAO,aAAa,gBAAgB;EACnE;AAGH,KAAI,CAAC,OAAO,QAAQ,OAAO,MACzB,QAAO;EACL,MAAM;EACN,OAAO,gBAAgB,OAAO,OAAO,aAAa,gBAAgB;EACnE;AAOH,KAAI,OAAO,SAAS,YAAY,OAAO,WAErC,QAAO;EACL,MAAM;EACN,MAAM,uBAHS,aAAa,eAAe,eAAe,EAGnB,gBAAgB;EACxD;AAIH,KAAI,OAAO,SAAS,YAAY,CAAC,OAAO,YAAY;EAClD,IAAI,YAAqB;GAAE,MAAM;GAAa,MAAM;GAAW;AAC/D,MAAI,OAAO,wBAAwB,OAAO,OAAO,yBAAyB;OAEzD,OAAO,KAAK,OAAO,qBAAqB,CAC5C,SAAS,EAClB,aAAY,gBAAgB,OAAO,sBAAsC,YAAY;aAE9E,OAAO,mBAAmB;GAEnC,MAAM,WAAW,OAAO,OAAO,OAAO,kBAAkB;AACxD,OAAI,SAAS,SAAS,EACpB,aAAY,gBAAgB,SAAS,IAAI,YAAY;;AAGzD,SAAO;GACL,MAAM;GACN;GACD;;CAIH,MAAM,eAA4E;EAChF,QAAQ;EACR,SAAS;EACT,QAAQ;EACR,SAAS;EACV;CAED,MAAM,UAAU,MAAM,QAAQ,OAAO,KAAK,GAAG,OAAO,KAAK,KAAK,OAAO;AACrE,KAAI,WAAW,aAAa,SAC1B,QAAO;EACL,MAAM;EACN,MAAM,aAAa;EACnB,GAAI,OAAO,SAAS,EAAE,QAAQ,OAAO,QAAQ,GAAG,EAAE;EACnD;AAIH,KAAI,CAAC,OAAO,QAAQ,OAAO,WAEzB,QAAO;EACL,MAAM;EACN,MAAM,uBAHS,aAAa,eAAe,eAAe,EAGnB,gBAAgB;EACxD;AAIH,KACE,CAAC,OAAO,QACR,CAAC,OAAO,QACR,CAAC,OAAO,SACR,CAAC,OAAO,SACR,CAAC,OAAO,SACR,CAAC,OAAO,QACR,CAAC,OAAO,cACR,CAAC,OAAO,MAER,QAAO;EAAE,MAAM;EAAa,MAAM;EAAW;AAI/C,KAAI,YACF,SAAQ,KAAK,sEAAsE,YAAY,GAAG;AAEpG,QAAO;EAAE,MAAM;EAAa,MAAM;EAAW;;;;ACnlB/C,MAAM,gBAAgB;CAAC;CAAU;CAAS;CAAU;CAAkB;CAAiB;CAAc;CAAa;AAElH,MAAM,gBAAgB;CAAC;CAAU;CAAQ;CAAe;CAAO;AAC/D,MAAM,eAAe;CAAC;CAAS;CAAa;CAAY;CAAQ;CAAQ;;;;;;;;;;;AAYxE,SAAgB,iBACd,UACA,aACA,UACuB;CAEvB,MAAM,cAAc,YAAY,MAAM,MAAM,cAAc,SAAS,EAAE,KAAK,CAAC;AAE3E,KAAI,aAAa;EACf,MAAM,WAAoB,SAAS,SAAS,UAAU,SAAS,QAAQ;AACvE,SAAO;GACL,UAAU;GACV,OAAO,YAAY;GACT;GACV;GACD;;CAIH,MAAM,cAAc,YAAY,MAAM,MAAM,cAAc,SAAS,EAAE,KAAK,CAAC;CAC3E,MAAM,aAAa,YAAY,MAAM,MAAM,aAAa,SAAS,EAAE,KAAK,CAAC;AAEzE,KAAI,eAAe,YAAY;EAC7B,MAAM,WAAoB,SAAS,SAAS,UAAU,SAAS,QAAQ;AACvE,SAAO;GACL,UAAU;GACV,OAAO,YAAY;GACnB,YAAY,WAAW;GACb;GACV;GACD;;AAGH,QAAO;;;;AChCT,SAAgB,2BAA2B,QAAsB,aAA+C;AAE9G,KAAI,OAAO,KACT,QAAO;EAAE,UAAU,gBAAgB,QAAQ,YAAY;EAAE,cAAc,EAAE;EAAE,aAAa;EAAO;CAIjG,MAAM,WAAW,mBAAmB,OAAO;AAC3C,KAAI,SAAS,WACX,QAAO,oBAAoB,QAAQ,aAAa,SAAS,SAAU;AAIrE,KAAI,wBAAwB,OAAO,CACjC,QAAO,uBAAuB,QAAQ,YAAY;AAIpD,QAAO,sBAAsB,QAAQ,YAAY;;AAQnD,MAAM,mBAAmB,IAAI,IAAI;CAAC;CAAQ;CAAS;CAAW;CAAW;CAAW;CAAU;CAAS;CAAQ,CAAC;AAEhH,MAAM,+BAA+B;CACnC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD;AAED,SAAS,mBAAmB,QAA0C;CAEpE,MAAM,cAA0D,EAAE;AAClE,KAAI,OAAO;OACJ,MAAM,OAAO,OAAO,MACvB,KAAI,IAAI,WAAY,aAAY,KAAK,IAAI,WAAW;;AAGxD,KAAI,OAAO,WACT,aAAY,KAAK,OAAO,WAAW;AAGrC,KAAI,YAAY,WAAW,EAAG,QAAO;EAAE,YAAY;EAAO,UAAU;EAAM;CAG1E,MAAM,cAAwD,EAAE;AAChE,MAAK,MAAM,UAAU,YACnB,QAAO,OAAO,aAAa,OAAO;CAIpC,MAAM,aAAuB,EAAE;CAC/B,MAAM,eAAyB,EAAE;AAEjC,MAAK,MAAM,CAAC,KAAK,eAAe,OAAO,QAAQ,YAAY,EAAE;AAC3D,MAAI,CAAC,WAAY;AACjB,MAAI,WAAW,SAAS,QACtB,YAAW,KAAK,IAAI;MAEpB,cAAa,KAAK,IAAI;;AAK1B,KAAI,WAAW,WAAW,KAAK,aAAa,UAAU,GAAG;EACvD,MAAM,gBAAgB,WAAW;AAGjC,MAAI,iBAAiB,IAAI,cAAc,CACrC,QAAO;GAAE,YAAY;GAAM,UAAU;GAAe;AAOtD,MAH+B,aAAa,MAAM,QAChD,6BAA6B,MAAM,YAAY,IAAI,aAAa,CAAC,SAAS,QAAQ,CAAC,CACpF,CAEC,QAAO;GAAE,YAAY;GAAM,UAAU;GAAe;;AAIxD,QAAO;EAAE,YAAY;EAAO,UAAU;EAAM;;AAG9C,SAAS,oBAAoB,QAAsB,aAAqB,UAA4C;CAClH,IAAI,cAAuB;EAAE,MAAM;EAAa,MAAM;EAAU;CAChE,MAAM,eAAwB,EAAE;CAGhC,MAAM,cAA0D,EAAE;AAClE,KAAI,OAAO;OACJ,MAAM,OAAO,OAAO,MACvB,KAAI,IAAI,WAAY,aAAY,KAAK,IAAI,WAAW;;AAGxD,KAAI,OAAO,WACT,aAAY,KAAK,OAAO,WAAW;AAGrC,MAAK,MAAM,SAAS,aAAa;EAC/B,MAAM,WAAW,MAAM;AACvB,MAAI,CAAC,SAAU;AAEf,MAAI,SAAS,SAAS,WAAW,SAAS,OAAO;GAC/C,MAAM,QAAQ,SAAS;AACvB,OAAI,MAAM,KACR,eAAc,gBAAgB,OAAO,YAAY;YACxC,MAAM,SAAS,YAAY,MAAM,YAAY;IACtD,MAAM,WAAW,YAAY,QAAQ,aAAa,GAAG,GAAG;AACxD,kBAAc;KAAE,MAAM;KAAS,MAAM;KAAU;AAC/C,iBAAa,KAAK,GAAG,mBAAmB,UAAU,MAAM,CAAC;;;;AAK/D,QAAO;EACL,UAAU;GAAE,MAAM;GAAS,OAAO;GAAa;EAC/C;EACA,aAAa;EACb;EACA,UAAU;EACX;;AAGH,SAAS,0BAA0B,QAAkE;AACnG,KAAI,CAAC,OAAO,WAAY,QAAO;AAI/B,MAAK,MAAM,QADO,CAAC,UAAU,OAAO,EACN;EAC5B,MAAM,QAAQ,OAAO,WAAW;AAChC,MAAI,CAAC,MAAO;AACZ,MAAI,MAAM,UAAU,KAAA,KAAa,OAAO,MAAM,UAAU,SACtD,QAAO;GAAE,UAAU;GAAM,OAAO,MAAM;GAAO;AAE/C,MAAI,MAAM,QAAQ,MAAM,KAAK,WAAW,KAAK,OAAO,MAAM,KAAK,OAAO,SACpE,QAAO;GAAE,UAAU;GAAM,OAAO,MAAM,KAAK;GAAI;;AAKnD,MAAK,MAAM,CAAC,MAAM,UAAU,OAAO,QAAQ,OAAO,WAAW,EAAE;AAC7D,MAAI,CAAC,MAAO;AACZ,MAAI,MAAM,UAAU,KAAA,KAAa,OAAO,MAAM,UAAU,SACtD,QAAO;GAAE,UAAU;GAAM,OAAO,MAAM;GAAO;AAE/C,MAAI,MAAM,QAAQ,MAAM,KAAK,WAAW,KAAK,OAAO,MAAM,KAAK,OAAO,SACpE,QAAO;GAAE,UAAU;GAAM,OAAO,MAAM,KAAK;GAAI;;AAInD,QAAO;;AAGT,SAAS,wBAAwB,QAA+B;AAC9D,KAAI,OAAO,SAAS,SAAU,QAAO;AACrC,KAAI,CAAC,OAAO,WAAY,QAAO;CAG/B,IAAI;AACJ,KAAI,OAAO,YAAY,OAAO,SAAS,WAAW,EAChD,cAAa,OAAO,SAAS;MACxB;EACL,MAAM,WAAW,OAAO,KAAK,OAAO,WAAW;AAC/C,MAAI,SAAS,WAAW,EACtB,cAAa,SAAS;;AAG1B,KAAI,CAAC,WAAY,QAAO;CAExB,MAAM,aAAa,OAAO,WAAW;AACrC,KAAI,CAAC,WAAY,QAAO;AAGxB,KAAI,WAAW,SAAS,YAAY,0BAA0B,WAAW,KAAK,KAAM,QAAO;AAG3F,KAAI,WAAW,MACb,QAAO,WAAW,MAAM,MAAM,MAAM,EAAE,SAAS,YAAY,0BAA0B,EAAE,KAAK,KAAK;AAGnG,QAAO;;AAGT,SAAS,uBAAuB,QAAsB,aAA+C;CACnG,MAAM,QAAQ,OAAO;CAErB,MAAM,aAAa,MADA,OAAO,YAAY,OAAO,SAAS,WAAW,IAAI,OAAO,SAAS,KAAK,OAAO,KAAK,MAAM,CAAC;CAE7G,MAAM,eAAwB,EAAE;CAGhC,MAAM,eAAe,YAAY,QAAQ,aAAa,GAAG;AAEzD,KAAI,WAAW,OAAO;EACpB,MAAM,gBAAgB,WAAW,MAAM,MAAM,MAAM,EAAE,SAAS,YAAY,0BAA0B,EAAE,KAAK,KAAK;AAEhH,MAAI,eAAe;GACjB,MAAM,YAAY,gBAAgB,eAAe,aAAa;AAC9D,gBAAa,KAAK,GAAG,mBAAmB,WAAW,cAAc,CAAC;GAElE,MAAM,iBAAiB,WAAW,MAAM,MACrC,MAAM,EAAE,SAAS,UAAW,MAAM,QAAQ,EAAE,KAAK,IAAI,EAAE,KAAK,SAAS,OAAO,CAC9E;GAED,MAAM,WAAoB;IAAE,MAAM;IAAS,MAAM;IAAW;AAC5D,UAAO;IACL,UAAU,iBAAiB;KAAE,MAAM;KAAY,OAAO;KAAU,GAAG;IACnE;IACA,aAAa;IACd;;;CAKL,MAAM,YAAY,gBAAgB,YAAY,aAAa;AAC3D,cAAa,KAAK,GAAG,mBAAmB,WAAW,WAAW,CAAC;AAE/D,QAAO;EACL,UAAU;GAAE,MAAM;GAAS,MAAM;GAAW;EAC5C;EACA,aAAa;EACd;;AAGH,SAAS,sBAAsB,QAAsB,aAA+C;CAClG,MAAM,eAAwB,EAAE;AAGhC,KAAI,OAAO,eAAe,OAAO,SAAS,YAAY,CAAC,OAAO,OAAO;EACnE,MAAM,YAAY,gBAAgB,QAAQ,YAAY;AACtD,eAAa,KAAK,GAAG,mBAAmB,WAAW,OAAO,CAAC;AAC3D,SAAO;GACL,UAAU;IAAE,MAAM;IAAS,MAAM;IAAW;GAC5C;GACA,aAAa;GACd;;AAIH,KAAI,OAAO,OAAO;EAChB,MAAM,mBAA6D,EAAE;EACrE,MAAM,iBAA2B,EAAE;AACnC,OAAK,MAAM,OAAO,OAAO,OAAO;AAC9B,OAAI,IAAI,WACN,QAAO,OAAO,kBAAkB,IAAI,WAAW;AAEjD,OAAI,IAAI,SACN,gBAAe,KAAK,GAAG,IAAI,SAAS;;AAGxC,MAAI,OAAO,KAAK,iBAAiB,CAAC,SAAS,GAAG;GAC5C,MAAM,SAAuB;IAAE,MAAM;IAAU,YAAY;IAAkB,UAAU;IAAgB;GACvG,MAAM,YAAY,gBAAgB,QAAQ,YAAY;AACtD,gBAAa,KAAK,GAAG,mBAAmB,WAAW,OAAO,CAAC;AAC3D,UAAO;IACL,UAAU;KAAE,MAAM;KAAS,MAAM;KAAW;IAC5C;IACA,aAAa;IACd;;;AAML,KAAI,OAAO;OACJ,MAAM,WAAW,OAAO,MAC3B,KAAI,QAAQ,eAAe,QAAQ,SAAS,YAAY,CAAC,QAAQ,OAAO;GACtE,MAAM,YAAY,gBAAgB,SAAS,YAAY;AAEvD,OAAI,CADkB,IAAI,IAAI,aAAa,KAAK,MAAM,EAAE,KAAK,CAAC,CAC3C,IAAI,UAAU,CAC/B,cAAa,KAAK,GAAG,mBAAmB,WAAW,QAAQ,CAAC;;;AAOpE,KAAI,OAAO,SAAS,WAAW,OAAO,OAAO;EAC3C,MAAM,QAAQ,OAAO;AACrB,MAAI,MAAM,KACR,QAAO;GACL,UAAU;IAAE,MAAM;IAAS,OAAO,gBAAgB,OAAO,YAAY;IAAE;GACvE;GACA,aAAa;GACd;AAEH,MAAI,MAAM,eAAe,MAAM,SAAS,YAAY,CAAC,MAAM,OAAO;GAChE,MAAM,WAAW,YAAY,QAAQ,aAAa,GAAG,GAAG;AACxD,gBAAa,KAAK,GAAG,mBAAmB,UAAU,MAAM,CAAC;AACzD,UAAO;IACL,UAAU;KAAE,MAAM;KAAS,OAAO;MAAE,MAAM;MAAS,MAAM;MAAU;KAAE;IACrE;IACA,aAAa;IACd;;;AAKL,QAAO;EACL,UAAU,gBAAgB,QAAQ,YAAY;EAC9C;EACA,aAAa;EACd;;AAGH,SAAS,gBAAgB,QAAsB,UAA0B;AACvE,KAAI,CAAC,OAAO,WAAY,QAAO,aAAa,SAAS;AAIrD,MAAK,MAAM,QADO,CAAC,UAAU,OAAO,EACN;EAC5B,MAAM,QAAQ,OAAO,WAAW;AAChC,MAAI,SAAS,MAAM,SAAS,OAAO,MAAM,UAAU,SACjD,QAAO,aAAa,MAAM,MAAM;;AAKpC,MAAK,MAAM,GAAG,UAAU,OAAO,QAAQ,OAAO,WAAW,CACvD,KAAI,SAAS,MAAM,SAAS,OAAO,MAAM,UAAU,SACjD,QAAO,aAAa,MAAM,MAAM;AAIpC,QAAO,aAAa,SAAS;;;;;;;AAQ/B,SAAS,kBAAkB,YAAoB,WAA2B;CACxE,MAAM,cAAc,aAAa,UAAU;AAE3C,KAAI,YAAY,WAAW,WAAW,CAAE,QAAO;CAI/C,MAAM,YAAY,GADE,qBAAqB,WAAW,GACjB;CAEnC,MAAM,QAAQ,UAAU,MAAM,yBAAyB;AACvD,KAAI,SAAS,MAAM,IAAI;EACrB,MAAM,WAAW,YAAY,MAAM,GAAG;AACtC,SAAO,MAAM,KAAK;;AAEpB,QAAO;;AAGT,SAAS,mBAAmB,MAAc,QAA+B;CACvE,MAAM,cAAc,IAAI,IAAI,OAAO,YAAY,EAAE,CAAC;CAClD,MAAM,SAAkB,EAAE;CAC1B,MAAM,aAAa,OAAO,cAAc,EAAE;CAC1C,MAAM,eAAwB,EAAE;AAEhC,MAAK,MAAM,CAAC,WAAW,gBAAgB,OAAO,QAAQ,WAAW,EAAE;AACjE,MAAI,CAAC,YAAa;AAClB,SAAO,KAAK,qBAAqB,WAAW,aAAa,MAAM,YAAY,CAAC;AAI5E,MAAI,YAAY,SAAS,YAAY,YAAY,YAAY;GAC3D,MAAM,aAAa,kBAAkB,MAAM,UAAU;AACrD,gBAAa,KAAK,GAAG,mBAAmB,YAAY,YAAY,CAAC;;AAEnE,MAAI,YAAY,SAAS,WAAW,YAAY,OAAO;GACrD,MAAM,QAAQ,YAAY;AAC1B,OAAI,MAAM,SAAS,YAAY,MAAM,YAAY;IAC/C,MAAM,aAAa,kBAAkB,MAAM,UAAU;AACrD,iBAAa,KAAK,GAAG,mBAAmB,YAAY,MAAM,CAAC;;;AAI/D,MAAI,YAAY,OAAO;GACrB,MAAM,mBAA6D,EAAE;GACrE,MAAM,iBAA2B,EAAE;AACnC,QAAK,MAAM,OAAO,YAAY,OAAO;AACnC,QAAI,IAAI,WAAY,QAAO,OAAO,kBAAkB,IAAI,WAAW;AACnE,QAAI,IAAI,SAAU,gBAAe,KAAK,GAAG,IAAI,SAAS;;AAExD,OAAI,OAAO,KAAK,iBAAiB,CAAC,SAAS,GAAG;IAC5C,MAAM,aAAa,kBAAkB,MAAM,UAAU;IACrD,MAAM,SAAuB;KAAE,MAAM;KAAU,YAAY;KAAkB,UAAU;KAAgB;AAEvG,QAAI,CADkB,IAAI,IAAI,aAAa,KAAK,MAAM,EAAE,KAAK,CAAC,CAC3C,IAAI,WAAW,CAChC,cAAa,KAAK,GAAG,mBAAmB,YAAY,OAAO,CAAC;;;AAKlE,MAAI,YAAY,OAAO;GACrB,MAAM,gBAAgB,YAAY,MAAM,MAAM,MAAM,EAAE,eAAe,EAAE,SAAS,YAAY,CAAC,EAAE,MAAM;AACrG,OAAI,eAAe;IACjB,MAAM,aAAa,kBAAkB,MAAM,UAAU;AAErD,QAAI,CADkB,IAAI,IAAI,aAAa,KAAK,MAAM,EAAE,KAAK,CAAC,CAC3C,IAAI,WAAW,CAChC,cAAa,KAAK,GAAG,mBAAmB,YAAY,cAAc,CAAC;;;;AAM3E,QAAO,CAAC;EAAE;EAAM,aAAa,OAAO;EAAa;EAAQ,EAAE,GAAG,aAAa;;;;AChX7E,MAAM,eAA6B;CAAC;CAAO;CAAQ;CAAO;CAAS;CAAU;CAAQ;CAAW;CAAQ;AAOxG,SAAgB,kBACd,OACA,sBAC2B;AAC3B,KAAI,CAAC,MAAO,QAAO;EAAE,UAAU,EAAE;EAAE,cAAc,EAAE;EAAE;CAErD,MAAM,6BAAa,IAAI,KAA0B;CACjD,MAAM,eAAwB,EAAE;AAEhC,MAAK,MAAM,CAAC,MAAM,aAAa,OAAO,QAAQ,MAAM,EAAE;EACpD,MAAM,kBAAkB,SAAS,cAAc,EAAE;AAEjD,OAAK,MAAM,UAAU,cAAc;GACjC,MAAM,KAAK,SAAS;AACpB,OAAI,CAAC,GAAI;GAET,MAAM,cAAc,iBAAiB,MAAM,GAAG,OAAO,GAAG;GAExD,MAAM,EAAE,WAAW,cAAc,aAAa,eAC5C,QACA,MACA,IACA,iBACA,qBACD;AACD,gBAAa,KAAK,GAAG,SAAS;GAC9B,MAAM,MAAM,WAAW,IAAI,YAAY,IAAI,EAAE;AAC7C,OAAI,KAAK,UAAU;AACnB,cAAW,IAAI,aAAa,IAAI;;;AAOpC,MAAK,MAAM,GAAG,eAAe,WAC3B,4BAA2B,WAAW;AAQxC,QAAO;EAAE,UALQ,MAAM,KAAK,WAAW,SAAS,CAAC,CAAC,KAAK,CAAC,MAAM,iBAAiB;GAC7E;GACA;GACD,EAAE;EAEgB;EAAc;;AAGnC,SAAS,iBAAiB,MAAc,KAAsB;AAG5D,KAAI,IACF,QAAO,aAAa,IAAI;CAI1B,MAAM,QADW,KAAK,MAAM,IAAI,CAAC,OAAO,QAAQ,CACzB,MAAM;AAE7B,KAAI,MAAM,WAAW,IAAI,CAAE,QAAO;AAClC,QAAO,aAAa,MAAM;;AAG5B,SAAS,mBACP,QACA,MACA,aACA,sBACQ;AACR,KAAI,aAAa;AACf,MAAI,qBACF,QAAO,qBAAqB,YAAY;AAE1C,SAAO,YAAY,YAAY;;CAKjC,MAAM,OAAO,UAAU,QAAQ,KAAK;CACpC,MAAM,WAAW,sBAAsB,KAAK;AAC5C,QAAO,WAAW,YAAY,GAAG,KAAK,GAAG,WAAW,GAAG;;;;;AAMzD,SAAS,UAAU,QAAoB,MAAsB;CAC3D,MAAM,WAAW,KAAK,MAAM,IAAI,CAAC,OAAO,QAAQ;CAChD,MAAM,mBAAmB,SAAS,SAAS,KAAK,SAAS,SAAS,SAAS,GAAG,WAAW,IAAI;AAE7F,SAAQ,QAAR;EACE,KAAK,MACH,QAAO,mBAAmB,QAAQ;EACpC,KAAK,OACH,QAAO;EACT,KAAK;EACL,KAAK,QACH,QAAO;EACT,KAAK,SACH,QAAO;EACT,KAAK,OACH,QAAO;EACT,KAAK,UACH,QAAO;EACT,KAAK,QACH,QAAO;EACT,QACE,QAAO;;;;;;;;;;;;;;AAeb,SAAS,sBAAsB,MAA6B;CAC1D,MAAM,WAAW,KAAK,MAAM,IAAI,CAAC,OAAO,QAAQ;AAChD,KAAI,SAAS,UAAU,EAAG,QAAO;CAGjC,IAAI,kBAAiC;AACrC,MAAK,IAAI,IAAI,SAAS,SAAS,GAAG,KAAK,GAAG,IACxC,KAAI,CAAC,SAAS,GAAG,WAAW,IAAI,EAAE;AAChC,oBAAkB,SAAS;AAC3B;;AAIJ,KAAI,CAAC,gBAAiB,QAAO;AAE7B,KAAI,oBAAoB,SAAS,GAAI,QAAO;AAE5C,QAAO,aAAa,gBAAgB;;;;;;;;;;;AAYtC,SAAS,2BAA2B,YAA+B;CAEjE,MAAM,yBAAS,IAAI,KAA0B;AAC7C,MAAK,MAAM,MAAM,YAAY;EAC3B,MAAM,QAAQ,OAAO,IAAI,GAAG,KAAK,IAAI,EAAE;AACvC,QAAM,KAAK,GAAG;AACd,SAAO,IAAI,GAAG,MAAM,MAAM;;AAG5B,MAAK,MAAM,CAAC,MAAM,UAAU,QAAQ;AAClC,MAAI,MAAM,UAAU,EAAG;AAKvB,MADoB,IAAI,IAAI,MAAM,KAAK,OAAO,GAAG,KAAK,CAAC,CACvC,QAAQ,EAAG;AAE3B,OAAK,MAAM,MAAM,OAAO;GACtB,MAAM,WAAW,sBAAsB,GAAG,KAAK;AAC/C,OAAI,SAED,IAAwB,OADT,YAAY,GAAG,KAAK,GAAG,WAAW;;EAOtD,MAAM,0BAAU,IAAI,KAA0B;AAC9C,OAAK,MAAM,MAAM,OAAO;GACtB,MAAM,SAAS,QAAQ,IAAI,GAAG,KAAK,IAAI,EAAE;AACzC,UAAO,KAAK,GAAG;AACf,WAAQ,IAAI,GAAG,MAAM,OAAO;;AAE9B,OAAK,MAAM,GAAG,WAAW,SAAS;AAChC,OAAI,OAAO,UAAU,EAAG;AAGxB,QAAK,MAAM,MAAM,QAAQ;IACvB,MAAM,SAAS,mBAAmB,GAAG,KAAK;AAC1C,QAAI,OACD,IAAwB,OAAO,YAAY,GAAG,GAAG,KAAK,GAAG,SAAS;;;;;;;;;;;;AAc7E,SAAS,mBAAmB,MAA6B;CAEvD,MAAM,YADW,KAAK,MAAM,IAAI,CAAC,OAAO,QAAQ,CACrB,QAAQ,MAAM,CAAC,EAAE,WAAW,IAAI,CAAC;AAE5D,KAAI,UAAU,UAAU,EACtB,QAAO,aAAa,UAAU,MAAM,GAAG,GAAG,CAAC,KAAK,IAAI,CAAC;AAEvD,QAAO;;AAGT,SAAS,eACP,QACA,MACA,IACA,iBACA,sBACiD;CACjD,MAAM,YAAY,CAAC,GAAG,iBAAiB,GAAI,GAAG,cAAc,EAAE,CAAE;CAEhE,MAAM,uBAAuB,UAAU,MAAM,MAAM,EAAE,OAAO,YAAY,EAAE,KAAK,aAAa,KAAK,kBAAkB;CAEnH,MAAM,aAAa,cAAc,WAAW,OAAO;CACnD,MAAM,cAAc,cAAc,WAAW,QAAQ;CACrD,MAAM,eAAe,cAAc,WAAW,SAAS,CAAC,QAAQ,MAAM,EAAE,KAAK,aAAa,KAAK,kBAAkB;CACjH,MAAM,eAAe,cAAc,WAAW,SAAS;CAEvD,MAAM,gBAAyB,EAAE;CACjC,MAAM,EAAE,MAAM,aAAa,UAAU,wBAAwB,mBAAmB,GAAG,aAAa,IAAI,cAAc;CAClH,MAAM,EACJ,UACA,kBACA,QACA,cACA,aACA,UAAU,kBACV,UAAU,qBACR,iBAAiB,GAAG,WAAW,IAAI,MAAM,OAAO;AACpD,cAAa,KAAK,GAAG,cAAc;CAGnC,MAAM,uBAAuB,iBAAiB,UAAU,aAAa,iBAAiB;CACtF,IAAI;AACJ,KAAI,aAAa;EACf,MAAM,WAAW,qBAAqB,SAAS,SAAS,UAAU,SAAS,QAAQ;AACnF,eAAa;GACX,UAAU,sBAAsB,YAAY;GAC5C,OAAO,sBAAsB,SAAS;GACtC,YAAY,sBAAsB;GAClC,UAAU,oBAAoB,sBAAsB;GACpD;GACD;YACQ,qBACT,cAAa;AAGf,QAAO;EACL,WAAW;GACT,MAAM,mBAAmB,QAAQ,MAAM,GAAG,aAAa,qBAAqB;GAC5E,aAAa,iBAAiB,GAAG,SAAS,GAAG,YAAY;GACzD,YAAY;GACZ;GACA;GACA;GACA;GACA,cAAc,aAAa,SAAS,IAAI,eAAe,KAAA;GACvD;GACA;GACA;GACA;GACA;GACA;GACA,sBAAsB;GACtB,YAAY,GAAG,cAAc,KAAA;GAC7B,OAAO,GAAG;GACX;EACD;EACD;;AAGH,SAAS,iBAAiB,SAA6B,aAAqD;AAC1G,KAAI,WAAW,eAAe,YAAY,YACxC,QAAO,GAAG,QAAQ,MAAM;AAE1B,QAAO,eAAe;;AAGxB,SAAS,cAAc,QAA2B,UAA+D;AAC/G,QAAO,OACJ,QAAQ,MAAM,EAAE,OAAO,SAAS,CAChC,KAAK,OAAO;EACX,MAAM,EAAE;EACR,MAAM,EAAE,SAAS,gBAAgB,EAAE,QAAQ,EAAE,KAAK,GAAI;GAAE,MAAM;GAAa,MAAM;GAAU;EAC3F,UAAU,EAAE,YAAY;EACxB,aAAa,EAAE;EACf,YAAY,EAAE,cAAc,EAAE,QAAQ,cAAc,KAAA;EACpD,SAAS,EAAE,QAAQ;EACnB,SAAS,EAAE,WAAW,EAAE,QAAQ;EACjC,EAAE;;AAGP,SAAS,mBACP,MACA,IACA,cAC6F;AAC7F,KAAI,CAAC,MAAM,QAAS,QAAO,EAAE;CAG7B,IAAI,WAAyE;CAC7E,IAAI;AAEJ,KAAI,KAAK,QAAQ,qBAAqB,QAAQ;AAC5C,aAAW;AACX,WAAS,KAAK,QAAQ,oBAAqB;YAClC,KAAK,QAAQ,wBAAwB,QAAQ;AACtD,aAAW;AACX,WAAS,KAAK,QAAQ,uBAAwB;YACrC,KAAK,QAAQ,sCAAsC,QAAQ;AACpE,aAAW;AACX,WAAS,KAAK,QAAQ,qCAAsC;YACnD,KAAK,QAAQ,6BAA6B;AACnD,aAAW;AACX,WAAS,KAAK,QAAQ,4BAA6B;YAC1C,KAAK,QAAQ,eAAe;AACrC,aAAW;AACX,WAAS,KAAK,QAAQ,cAAe;;AAGvC,KAAI,CAAC,QAAQ;AAEX,MAAI,aAAa,SACf,QAAO;GAAE,MAAM;IAAE,MAAM;IAAa,MAAM;IAAU,QAAQ;IAAU;GAAE;GAAU;AAEpF,MAAI,aAAa,OACf,QAAO;GAAE,MAAM;IAAE,MAAM;IAAa,MAAM;IAAU;GAAE;GAAU;AAElE,SAAO,EAAE;;CAIX,MAAM,cAAc,gBADJ,IAAI,cAAc,aAAa,GAAG,YAAY,GAAG,YAAY,cACjC;AAG5C,KAAI,OAAO,eAAe,OAAO,SAAS,YAAY,CAAC,OAAO,OAAO;EACnE,MAAM,cAAc,IAAI,IAAI,OAAO,YAAY,EAAE,CAAC;EAClD,MAAM,SAAkB,EAAE;AAC1B,OAAK,MAAM,CAAC,WAAW,gBAAgB,OAAO,QAAQ,OAAO,WAAW,EAAE;AACxE,OAAI,CAAC,YAAa;AAClB,UAAO,KAAK,qBAAqB,WAAW,aAAa,aAAa,YAAY,CAAC;;AAErF,eAAa,KAAK;GAAE,MAAM;GAAa,aAAa,KAAA;GAAW;GAAQ,CAAC;AACxE,SAAO;GAAE,MAAM;IAAE,MAAM;IAAS,MAAM;IAAa;GAAE;GAAU;;AAKjE,KAAI,OAAO,OAAO;EAChB,MAAM,WAAsB,EAAE;AAE9B,OAAK,MAAM,WAAW,OAAO,MAC3B,KAAI,QAAQ,MAAM;GAChB,MAAM,MAAM,gBAAgB,SAAS,YAAY;AACjD,YAAS,KAAK,IAAI;aACT,QAAQ,SAAS,QAAQ,YAEzB,QAAQ,eAAe,QAAQ,SAAS,YAAY,CAAC,QAAQ,OAAO;GAC7E,MAAM,cAAc,uBAAuB,SAAS,aAAa,aAAa;GAC9E,MAAM,cAAc,IAAI,IAAI,QAAQ,YAAY,EAAE,CAAC;GACnD,MAAM,SAAkB,EAAE;AAC1B,QAAK,MAAM,CAAC,WAAW,gBAAgB,OAAO,QAAQ,QAAQ,WAAW,EAAE;AACzE,QAAI,CAAC,YAAa;AAClB,WAAO,KAAK,qBAAqB,WAAW,aAAa,aAAa,YAAY,CAAC;;AAErF,gBAAa,KAAK;IAAE,MAAM;IAAa,aAAa,QAAQ;IAAa;IAAQ,CAAC;AAClF,YAAS,KAAK;IAAE,MAAM;IAAS,MAAM;IAAa,CAAC;QAEnD,UAAS,KAAK,gBAAgB,SAAS,YAAY,CAAC;EAIxD,MAAM,UAAU,OAAO,MAAM,MAC1B,MAAoB,EAAE,SAAS,UAAW,MAAM,QAAQ,EAAE,KAAK,IAAI,EAAE,KAAK,SAAS,OAAO,CAC5F;EACD,MAAM,QAAiB;GACrB,MAAM;GACN;GACA,GAAI,OAAO,gBACP,EACE,eAAe;IAAE,UAAU,OAAO,cAAc;IAAc,SAAS,OAAO,cAAc,WAAW,EAAE;IAAE,EAC5G,GACD,EAAE;GACP;AAED,SAAO;GAAE,MADI,UAAW;IAAE,MAAM;IAAY,OAAO;IAAO,GAAe;GAC1D;GAAU;;AAG3B,QAAO;EAAE,MAAM,gBAAgB,QAAQ,YAAY;EAAE;EAAU;;;AAIjE,SAAS,uBAAuB,SAAuB,UAAkB,gBAAiC;AAExG,KAAI,QAAQ;OACL,MAAM,GAAG,eAAe,OAAO,QAAQ,QAAQ,WAAW,CAC7D,KAAI,YAAY,SAAS,OAAO,WAAW,UAAU,SACnD,QAAO,aAAa,WAAW,MAAM,GAAG,SAAS,QAAQ,YAAY,GAAG,GAAG;;CAKjF,MAAM,gBAAgB,IAAI,IAAI,eAAe,KAAK,MAAM,EAAE,KAAK,CAAC;CAChE,IAAI,OAAO;CACX,IAAI,SAAS;AACb,QAAO,cAAc,IAAI,KAAK,EAAE;AAC9B,SAAO,GAAG,WAAW;AACrB;;AAEF,QAAO;;AAGT,SAAS,mBAAmB,IAAiC,MAAc,QAA4B;AACrG,KAAI,IAAI,YACN,QAAO,gBAAgB,aAAa,GAAG,YAAY,GAAG,WAAW;AAInE,QAAO,aAFU,KAAK,MAAM,IAAI,CAAC,OAAO,QAAQ,CACtB,MAAM,UACH,GAAG,aAAa,OAAO,GAAG;;AAGzD,SAAS,iBACP,WACA,IACA,MACA,QASA;CACA,MAAM,SAA0B,EAAE;CAClC,IAAI,WAAoB;EAAE,MAAM;EAAa,MAAM;EAAU;CAC7D,IAAI,eAAwB,EAAE;CAC9B,IAAI,cAAc;CAClB,IAAI;CACJ,IAAI;AAEJ,KAAI,CAAC,UAAW,QAAO;EAAE;EAAU;EAAQ;EAAc;EAAa;CAEtE,MAAM,sBAAyC,EAAE;AAEjD,MAAK,MAAM,CAAC,YAAY,SAAS,OAAO,QAAQ,UAAU,EAAE;EAC1D,MAAM,OAAO,SAAS,YAAY,GAAG;AAErC,MAAI,QAAQ,OAAO,OAAO,KAAK;GAC7B,IAAI,gBAAyB;IAAE,MAAM;IAAa,MAAM;IAAW;GACnE,MAAM,cAAc,KAAK,UAAU;AACnC,OAAI,aAAa,QAAQ;IACvB,MAAM,cAAc,mBAAmB,IAAI,QAAQ,KAAK,UAAU,MAAM;IACxE,MAAM,SAAS,2BAA2B,YAAY,QAAQ,YAAY;AAC1E,oBAAgB,OAAO;AAEvB,mBAAe,OAAO;AACtB,kBAAc,OAAO;AACrB,eAAW,OAAO;AAClB,eAAW,OAAO;cACT,KAAK,QAEd,KAAI,KAAK,QAAQ,+BAA+B,KAAK,QAAQ,mBAC3D,iBAAgB;IAAE,MAAM;IAAa,MAAM;IAAU,QAAQ;IAAU;YAEvE,KAAK,QAAQ,iBACb,KAAK,QAAQ,gBACb,KAAK,QAAQ,eACb,KAAK,QAAQ,mBAEb,iBAAgB;IAAE,MAAM;IAAa,MAAM;IAAU;QAChD;IAEL,MAAM,WAAW,OAAO,KAAK,KAAK,QAAQ,CAAC;AAC3C,QAAI,UAAU;KACZ,MAAM,eAAe,KAAK,QAAQ;AAClC,SAAI,cAAc,OAChB,iBAAgB,gBACd,aAAa,QACb,mBAAmB,IAAI,QAAQ,KAAK,UAAU,MAAM,CACrD;;;AAKT,uBAAoB,KAAK;IAAE,YAAY;IAAM,MAAM;IAAe,CAAC;aAC1D,QAAQ,KAAK;GACtB,MAAM,cAAc,KAAK,UAAU;GACnC,MAAM,OAAO,aAAa,SAAS,gBAAgB,YAAY,QAAQ,QAAQ,OAAO,GAAG,KAAA;AACzF,UAAO,KAAK;IAAE,YAAY;IAAM;IAAM,CAAC;;;AAK3C,KAAI,oBAAoB,SAAS,GAAG;EAClC,MAAM,SAAS,CAAC,GAAG,oBAAoB,CAAC,MAAM,GAAG,MAAM,EAAE,aAAa,EAAE,WAAW;AAGnF,cADE,OAAO,MAAM,MAAM,EAAE,KAAK,SAAS,eAAgB,EAAE,KAA0B,SAAS,UAAU,IAAI,OAAO,IAC5F;;CAGrB,MAAM,mBAAmB,oBAAoB,SAAS,IAAI,sBAAsB,KAAA;AAEhF,QAAO;EAAE;EAAU;EAAkB;EAAQ;EAAc;EAAa;EAAU;EAAU;;;;ACrkB9F,SAAS,kBAAkB,QAA0B;CACnD,MAAM,yBAAS,IAAI,KAAoB;AACvC,MAAK,MAAM,SAAS,QAAQ;EAC1B,MAAM,WAAW,OAAO,IAAI,MAAM,KAAK;AACvC,MAAI,CAAC,YAAY,MAAM,OAAO,SAAS,SAAS,OAAO,OACrD,QAAO,IAAI,MAAM,MAAM,MAAM;;AAGjC,QAAO,CAAC,GAAG,OAAO,QAAQ,CAAC;;AAG7B,SAAS,gBAAgB,KAAc,SAAiB,SAAuB;AAC7E,aAAY,KAAK,EACf,QAAQ,MAAM;AACZ,MAAI,EAAE,SAAS,QAAU,GAAuB,OAAO;IAE1D,CAAC;;AAGJ,SAAS,iBAAiB,QAAiB,UAAqB,SAAiB,SAAuB;AACtG,MAAK,MAAM,SAAS,OAClB,MAAK,MAAM,SAAS,MAAM,OACxB,iBAAgB,MAAM,MAAM,SAAS,QAAQ;AAGjD,MAAK,MAAM,WAAW,SACpB,MAAK,MAAM,MAAM,QAAQ,YAAY;AACnC,kBAAgB,GAAG,UAAU,SAAS,QAAQ;AAC9C,MAAI,GAAG,YACL,iBAAgB,GAAG,aAAa,SAAS,QAAQ;;;AAMzD,SAAgB,0BAA0B,cAAuB,cAAgC;CAC/F,MAAM,qBAAqB,CAAC,GAAG,aAAa;CAC5C,MAAM,mBAAmB,IAAI,IAAI,mBAAmB,KAAK,MAAM,EAAE,KAAK,CAAC;CACvE,MAAM,qBAAqB,IAAI,IAAI,mBAAmB,KAAK,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;CAE9E,MAAM,2BAA2B,aAAa,QAAQ,UAAU;AAC9D,MAAI,CAAC,iBAAiB,IAAI,MAAM,KAAK,CAAE,QAAO;EAE9C,MAAM,WAAW,mBAAmB,IAAI,MAAM,KAAK;EACnD,MAAM,qBAAqB,IAAI,IAAI,SAAS,OAAO,KAAK,MAAM,EAAE,KAAK,CAAC;EACtE,MAAM,mBAAmB,IAAI,IAAI,MAAM,OAAO,KAAK,MAAM,EAAE,KAAK,CAAC;EACjE,MAAM,gBACJ,MAAM,OAAO,MAAM,MAAM,CAAC,mBAAmB,IAAI,EAAE,KAAK,CAAC,IACzD,SAAS,OAAO,MAAM,MAAM,CAAC,iBAAiB,IAAI,EAAE,KAAK,CAAC;AAE5D,MAAI,iBAAiB,MAAM,OAAO,SAAS,SAAS,OAAO,QAAQ;GACjE,MAAM,MAAM,mBAAmB,QAAQ,SAAS;AAChD,OAAI,QAAQ,GAAI,oBAAmB,OAAO;AAC1C,sBAAmB,IAAI,MAAM,MAAM,MAAM;AACzC,WAAQ,KACN,kCAAkC,MAAM,KAAK,2CAA2C,MAAM,OAAO,OAAO,MAAM,SAAS,OAAO,OAAO,iCAC1I;aACQ,cACT,SAAQ,KACN,kCAAkC,MAAM,KAAK,uEAC9C;AAGH,SAAO;GACP;AAEF,QAAO,CAAC,GAAG,oBAAoB,GAAG,kBAAkB,yBAAyB,CAAC;;AAGhF,SAAgB,uBAAuB,gBAAyB,mBAAqC;CACnG,MAAM,aAAa,IAAI,IAAI,eAAe,KAAK,MAAM,EAAE,KAAK,CAAC;CAC7D,MAAM,eAAe,IAAI,IAAI,eAAe,KAAK,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;CAEpE,MAAM,0BAA0B,kBAAkB,QAAQ,UAAU;AAClE,MAAI,CAAC,WAAW,IAAI,MAAM,KAAK,CAAE,QAAO;EAExC,MAAM,WAAW,aAAa,IAAI,MAAM,KAAK;EAC7C,MAAM,qBAAqB,IAAI,IAAI,SAAS,OAAO,KAAK,MAAM,EAAE,KAAK,CAAC;EACtE,MAAM,mBAAmB,IAAI,IAAI,MAAM,OAAO,KAAK,MAAM,EAAE,KAAK,CAAC;AAKjE,MAHE,MAAM,OAAO,MAAM,MAAM,CAAC,mBAAmB,IAAI,EAAE,KAAK,CAAC,IACzD,SAAS,OAAO,MAAM,MAAM,CAAC,iBAAiB,IAAI,EAAE,KAAK,CAAC,CAG1D,SAAQ,KACN,kCAAkC,MAAM,KAAK,uEAC9C;AAGH,SAAO;GACP;AAEF,QAAO,CAAC,GAAG,gBAAgB,GAAG,kBAAkB,wBAAwB,CAAC;;AAG3E,SAAS,0BAA0B,OAAuB;AACxD,QAAO,MAAM,OAAO,MACjB,OAAO,EAAE,SAAS,YAAY,EAAE,SAAS,WAAW,EAAE,KAAK,SAAS,aAAa,OAAO,EAAE,KAAK,UAAU,SAC3G;;AAGH,SAAS,0BAA0B,MAAc,QAAiB,cAAoC;AACpG,MAAK,MAAM,SAAS,QAAQ;AAC1B,MAAI,aAAa,IAAI,MAAM,KAAK,CAAE;AAClC,OAAK,MAAM,SAAS,MAAM,QAAQ;GAChC,IAAI,QAAQ;AACZ,eAAY,MAAM,MAAM,EACtB,QAAQ,MAAM;AACZ,QAAI,EAAE,SAAS,KAAM,SAAQ;MAEhC,CAAC;AACF,OAAI,MAAO,QAAO;;;AAGtB,QAAO;;AAGT,SAAgB,yBAAyB,QAAiB,UAA8B;CACtF,MAAM,mBAAmB,CAAC,GAAG,OAAO;CACpC,MAAM,SAAS,IAAI,IAAI,iBAAiB,KAAK,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;CAGhE,MAAM,kBAAiE,EAAE;AACzE,MAAK,MAAM,SAAS,kBAAkB;AACpC,MAAI,CAAC,MAAM,KAAK,SAAS,OAAO,CAAE;EAElC,MAAM,WAAW,MAAM,KAAK,MAAM,GAAG,GAAG;EACxC,MAAM,YAAY,OAAO,IAAI,SAAS;AACtC,MAAI,CAAC,aAAa,MAAM,OAAO,UAAU,UAAU,OAAO,OAAQ;AAGlE,MAAI,CADe,UAAU,OAAO,OAAO,MAAM,MAAM,OAAO,MAAM,OAAO,GAAG,SAAS,EAAE,KAAK,CAAC,CAC9E;AAGjB,MAAI,0BAA0B,MAAM,IAAI,0BAA0B,UAAU,CAAE;AAG9E,MAAI,0BAA0B,MAAM,MAAM,kBAAkB,IAAI,IAAI,CAAC,MAAM,MAAM,SAAS,CAAC,CAAC,CAAE;AAE9F,kBAAgB,KAAK;GAAE,WAAW;GAAO;GAAW,CAAC;;CAIvD,MAAM,2BAAW,IAAI,KAAa;AAClC,MAAK,MAAM,EAAE,WAAW,eAAe,iBAAiB;AACtD,YAAU,SAAS,UAAU;AAC7B,WAAS,IAAI,UAAU,KAAK;AAC5B,mBAAiB,kBAAkB,UAAU,UAAU,MAAM,UAAU,KAAK;AAC5E,UAAQ,KACN,mBAAmB,UAAU,KAAK,UAAU,UAAU,KAAK,KAAK,UAAU,OAAO,OAAO,oBACzF;;AAGH,QAAO,iBAAiB,QAAQ,MAAM,CAAC,SAAS,IAAI,EAAE,KAAK,CAAC;;;;ACzJ9D,SAAgB,6BAA6B,QAAiB,OAAqB;CACjF,MAAM,YAAY,IAAI,IAAI,MAAM,KAAK,MAAM,EAAE,KAAK,CAAC;AACnD,MAAK,MAAM,SAAS,OAClB,MAAK,MAAM,SAAS,MAAM,OACxB,0BAAyB,MAAM,MAAM,OAAO,UAAU;;;;ACJ5D,SAAgB,kBAAkB,MAAqB;CACrD,MAAM,6BAAa,IAAI,KAAa;AACpC,MAAK,MAAM,KAAK,KAAK,OAAQ,YAAW,IAAI,EAAE,KAAK;AACnD,MAAK,MAAM,KAAK,KAAK,MAAO,YAAW,IAAI,EAAE,KAAK;CAElD,SAAS,QAAQ,KAAc,SAAuB;AACpD,cAAY,KAAK,EACf,QAAQ,MAAM;AACZ,OAAI,CAAC,WAAW,IAAI,EAAE,KAAK,CACzB,SAAQ,KAAK,gDAAgD,EAAE,KAAK,cAAc,QAAQ,GAAG;KAGlG,CAAC;;AAGJ,MAAK,MAAM,SAAS,KAAK,OACvB,MAAK,MAAM,SAAS,MAAM,OACxB,SAAQ,MAAM,MAAM,GAAG,MAAM,KAAK,GAAG,MAAM,OAAO;AAItD,MAAK,MAAM,WAAW,KAAK,SACzB,MAAK,MAAM,MAAM,QAAQ,YAAY;AACnC,OAAK,MAAM,KAAK;GAAC,GAAG,GAAG;GAAY,GAAG,GAAG;GAAa,GAAG,GAAG;GAAa,CACvE,SAAQ,EAAE,MAAM,GAAG,QAAQ,KAAK,GAAG,GAAG,KAAK,GAAG,EAAE,OAAO;AAEzD,MAAI,GAAG,YAAa,SAAQ,GAAG,aAAa,GAAG,QAAQ,KAAK,GAAG,GAAG,KAAK,cAAc;AACrF,UAAQ,GAAG,UAAU,GAAG,QAAQ,KAAK,GAAG,GAAG,KAAK,WAAW;;;;;ACbjE,eAAsB,UAAU,UAAkB,SAA0C;CAC1F,MAAM,EAAE,WAAW,MAAM,kBAAkB,SAAS;CAEpD,MAAM,OAAO;CAeb,MAAM,UAAU,KAAK,WAAW;AAChC,KAAI,CAAC,QAAQ,WAAW,KAAK,CAC3B,OAAM,IAAI,eACR,gCAAgC,QAAQ,+BACxC,oHAAoH,SAAS,KAC9H;CAGH,MAAM,EAAE,QAAQ,UAAU,eACxB,KAAK,YAAY,QAClB;CAED,MAAM,EAAE,UAAU,iBAAiB,kBACjC,KAAK,OACL,SAAS,qBACV;CASD,MAAM,cAAc,yBADM,uBANO,0BAA0B,QAAQ,aAAa,EAGtD,+BACxB,KAAK,YAAY,QAClB,CAC4F,EAC7B,SAAS;AACzE,8BAA6B,aAAa,MAAM;CAEhD,MAAM,OAAO,mBAAmB,KAAK,YAAY,gBAAgB;CAEjE,MAAM,iBAAgC,KAAK,WAAW,EAAE,EACrD,KAAK,OAAO;EAAE,KAAK,EAAE,OAAO;EAAI,aAAa,EAAE;EAAa,EAAE,CAC9D,QAAQ,MAAM,EAAE,IAAI;CAEvB,MAAM,SAAkB;EACtB,MAAM,KAAK,MAAM,SAAS;EAC1B,SAAS,KAAK,MAAM,WAAW;EAC/B,aAAa,KAAK,MAAM;EACxB,SAAS,cAAc,IAAI,OAAO;EAClC,SAAS,cAAc,SAAS,IAAI,gBAAgB,KAAA;EACpD;EACA,QAAQ;EACR;EACA;EACD;AAED,mBAAkB,OAAO;AAEzB,QAAO;;;AAGT,SAAS,mBACP,iBAI0B;AAC1B,KAAI,CAAC,gBAAiB,QAAO,KAAA;CAC7B,MAAM,UAAwB,EAAE;AAChC,MAAK,MAAM,GAAG,WAAW,OAAO,QAAQ,gBAAgB,CACtD,KAAI,OAAO,SAAS,UAAU,OAAO,WAAW,SAC9C,SAAQ,KAAK,EAAE,MAAM,UAAU,CAAC;UACvB,OAAO,SAAS,YAAY,OAAO,MAAM,OAAO,KACzD,SAAQ,KAAK;EAAE,MAAM;EAAU,IAAI,OAAO;EAAqC,MAAM,OAAO;EAAM,CAAC;UAC1F,OAAO,SAAS,YAAY,OAAO,MAC5C,SAAQ,KAAK;EAAE,MAAM;EAAU,OAAO,OAAO;EAAO,CAAC;AAGzD,QAAO,QAAQ,SAAS,IAAI,UAAU,KAAA;;;;;ACtBxC,IAAW,kCAAkB,IAAI,KAAa;;AAG9C,IAAW,gCAAgB,IAAI,KAAa;;;;;AAM5C,IAAI,mBAA2C,EAAE;;;;;AAMjD,IAAW,uBAA+C,EAAE;;AAU5D,SAAgB,gBAAgB,YAA2B;AACzD,KAAI,CAAC,WAAY;CACjB,MAAM,MAAM,aAAa,YAAY,QAAQ;CAC7C,MAAM,SAAsB,KAAK,MAAM,IAAI;AAE3C,KAAI,OAAO,eAAgB,mBAAkB,IAAI,IAAI,OAAO,eAAe;AAC3E,KAAI,OAAO,aAAc,iBAAgB,IAAI,IAAI,OAAO,aAAa;AACrE,KAAI,OAAO,gBAAiB,oBAAmB,OAAO;AACtD,KAAI,OAAO,mBAAoB,wBAAuB,OAAO;;;AAI/D,SAAgB,iBAAiB;AAC/B,QAAO;EACL,gBAAgB;EAChB,cAAc;EACd,iBAAiB;EACjB,oBAAoB;EACrB;;;;;;AAOH,SAAS,iBAAiB,IAAuB;CAC/C,MAAM,YAAY,GAAG,WAAW,SAAS;CACzC,MAAM,SAAS,GAAG;AAElB,KAAI,WAAW,UAAU,CAAC,UAAW,QAAO;AAC5C,KAAI,WAAW,SAAS,CAAC,aAAa,GAAG,WAAY,QAAO;AAC5D,KAAI,WAAW,SAAS,CAAC,UAAW,QAAO;AAC3C,KAAI,WAAW,UAAU,UAAW,QAAO;AAC3C,KAAI,WAAW,SAAS,aAAa,GAAG,WAAY,QAAO;AAC3D,KAAI,WAAW,SAAS,UAAW,QAAO;AAC1C,KAAI,WAAW,SAAS,WAAW,QAAS,QAAO;AACnD,KAAI,WAAW,SAAU,QAAO;AAChC,QAAO;;AAGT,SAAgB,eAAe,MAA+B;CAC5D,MAAM,SAAyB,EAAE;AAEjC,MAAK,MAAM,WAAW,KAAK,UAAU;AACnC,MAAI,cAAc,IAAI,QAAQ,KAAK,CAAE;EAErC,MAAM,MAA0B,EAAE;AAClC,OAAK,MAAM,MAAM,QAAQ,YAAY;AACnC,OAAI,gBAAgB,IAAI,GAAG,KAAK,CAAE;AAElC,OAAI,KAAK;IAAE,SAAS,QAAQ;IAAM,WAAW;IAAI,CAAC;;AAGpD,MAAI,IAAI,WAAW,EAAG;AAUtB,MAAI,MAAM,GAAG,MAAM;AACjB,UAAO,iBAAiB,EAAE,UAAU,GAAG,iBAAiB,EAAE,UAAU;IACpE;AAEF,SAAO,KAAK;GAAE,SAAS,QAAQ;GAAM,YAAY;GAAK,CAAC;;AAIzD,QAAO,MAAM,GAAG,MAAM;AAGpB,UAFa,iBAAiB,EAAE,YAAY,OAC/B,iBAAiB,EAAE,YAAY;GAE5C;AAEF,QAAO;;;;;;;;;;;;;AAgCT,UAAiB,UACf,QACA,KACA,eACoD;CAEpD,MAAM,YAAgC,EAAE;AACxC,MAAK,MAAM,SAAS,OAClB,MAAK,MAAM,WAAW,MAAM,WAC1B,WAAU,KAAK,QAAQ;CAK3B,MAAM,0BAAU,IAAI,KAAa;CACjC,MAAM,UAA8B,EAAE;AAGtC,MAAK,IAAI,IAAI,GAAG,IAAI,UAAU,QAAQ,KAAK;EACzC,MAAM,EAAE,WAAW,IAAI,SAAS,cAAc,UAAU;AACxD,MAAI,iBAAiB,CAAC,cAAc,IAAI,UAAU,EAAE;AAClD,WAAQ,IAAI,EAAE;AACd,WAAQ,KAAK,UAAU,GAAG;;;CAK9B,IAAI,OAAsB,EAAE,OAAO,EAAE,EAAE;AACvC,MAAK,IAAI,IAAI,GAAG,IAAI,UAAU,QAAQ,KAAK;AACzC,MAAI,QAAQ,IAAI,EAAE,CAAE;EACpB,MAAM,EAAE,WAAW,IAAI,SAAS,cAAc,UAAU;AACxD,MAAI,GAAG,WAAW,WAAW,GAAG;AAC9B,QAAK,MAAM,KAAK;IAAE;IAAI;IAAW,YAAY,EAAE;IAAE,CAAC;AAClD,WAAQ,IAAI,EAAE;;;AAIlB,KAAI,KAAK,MAAM,SAAS,EACtB,OAAM;CAIR,IAAI,eAAe;AACnB,QAAO,cAAc;AACnB,iBAAe;AACf,SAAO,EAAE,OAAO,EAAE,EAAE;AAEpB,OAAK,IAAI,IAAI,GAAG,IAAI,UAAU,QAAQ,KAAK;AACzC,OAAI,QAAQ,IAAI,EAAE,CAAE;GACpB,MAAM,EAAE,WAAW,IAAI,SAAS,cAAc,UAAU;GAExD,MAAM,WAAW,IAAI,kBAAkB,IAAI,UAAU;AACrD,OAAI,UAAU;AACZ,SAAK,MAAM,KAAK;KAAE;KAAI;KAAW,YAAY;KAAU,CAAC;AACxD,YAAQ,IAAI,EAAE;AACd,mBAAe;;;AAInB,MAAI,KAAK,MAAM,SAAS,EACtB,OAAM;;CAKV,MAAM,aAAiC,EAAE;AACzC,MAAK,IAAI,IAAI,GAAG,IAAI,UAAU,QAAQ,IACpC,KAAI,CAAC,QAAQ,IAAI,EAAE,CACjB,YAAW,KAAK,UAAU,GAAG;AAGjC,QAAO;;AAOT,SAAgB,qBAAqB,SAAkB,WAAmB,MAAwB;AAChG,SAAQ,QAAQ,MAAhB;EACE,KAAK,YACH,QAAO,yBAAyB,QAAQ,MAAM,QAAQ,QAAQ,UAAU;EAC1E,KAAK,QACH,QAAO,CAAC,qBAAqB,QAAQ,OAAO,WAAW,KAAK,CAAC;EAC/D,KAAK,SAAS;GACZ,MAAM,QAAQ,KAAK,OAAO,MAAM,MAAM,EAAE,SAAS,QAAQ,KAAK;AAC9D,OAAI,OAAO;IACT,MAAM,MAA+B,EAAE;AACvC,SAAK,MAAM,SAAS,MAAM,OACxB,KAAI,MAAM,SACR,KAAI,YAAY,MAAM,KAAK,IAAI,qBAAqB,MAAM,MAAM,MAAM,MAAM,KAAK;AAGrF,WAAO;;AAET,UAAO,EAAE;;EAEX,KAAK,OAEH,QADU,KAAK,MAAM,MAAM,OAAO,GAAG,SAAS,QAAQ,KAAK,EACjD,OAAO,IAAI,SAAS;EAEhC,KAAK,WACH,QAAO,qBAAqB,QAAQ,OAAO,WAAW,KAAK;EAC7D,KAAK;AACH,OAAI,QAAQ,SAAS,SAAS,EAC5B,QAAO,qBAAqB,QAAQ,SAAS,IAAI,WAAW,KAAK;AAEnE,UAAO;;;AAIb,SAAS,yBAAyB,MAAc,QAA4B,WAA4B;AACtG,KAAI,SAAS,UAAU;AACrB,MAAI,WAAW,OAAQ,QAAO;AAC9B,MAAI,WAAW,OAAQ,QAAO;AAC9B,MAAI,WAAW,YAAa,QAAO;AACnC,MAAI,WAAW,QAAS,QAAO;AAC/B,MAAI,WAAW,SAAS,WAAW,MAAO,QAAO;AACjD,SAAO,QAAQ,YAAY,UAAU;;AAEvC,KAAI,SAAS,UAAW,QAAO;AAC/B,KAAI,SAAS,SAAU,QAAO;AAC9B,KAAI,SAAS,UAAW,QAAO;AAC/B,QAAO;;;AAIT,SAAgB,gBAAgB,IAAe,MAA+C;AAC5F,KAAI,CAAC,GAAG,YAAa,QAAO;CAE5B,MAAM,WAAW,GAAG;AACpB,KAAI,SAAS,SAAS,SAAS;EAC7B,MAAM,QAAQ,KAAK,OAAO,MAAM,MAAM,EAAE,SAAS,SAAS,KAAK;AAC/D,MAAI,CAAC,MAAO,QAAO,EAAE;EAErB,MAAM,UAAmC,EAAE;AAC3C,OAAK,MAAM,SAAS,MAAM,QAAQ;AAChC,OAAI,CAAC,MAAM,SAAU;GACrB,MAAM,MAAM,YAAY,MAAM,KAAK;GACnC,IAAI,QAAQ,qBAAqB,MAAM,MAAM,MAAM,MAAM,KAAK;AAG9D,QAAK,QAAQ,UAAU,QAAQ,WAAW,OAAO,UAAU,SACzD,SAAQ,SAAS,KAAK,KAAK,CAAC,GAAG,KAAK,QAAQ,CAAC,SAAS,GAAG,CAAC,MAAM,GAAG,EAAE;AAEvE,WAAQ,OAAO;;AAEjB,SAAO;;AAIT,QAAO,EAAE;;;AAIX,SAAS,wBAAwB,SAAkB,WAAmB,MAAwB;CAC5F,MAAM,QAAQ,qBAAqB,SAAS,WAAW,KAAK;AAE5D,KAAI,QAAQ,SAAS,eAAe,QAAQ,WAAW,eAAe,OAAO,UAAU,SACrF,QAAO,IAAI,KAAK,MAAM;AAExB,QAAO;;;AAIT,SAAgB,qBAAqB,IAAe,MAA+C;AACjG,KAAI,CAAC,GAAG,YAAa,QAAO;CAE5B,MAAM,WAAW,GAAG;AACpB,KAAI,SAAS,SAAS,SAAS;EAC7B,MAAM,QAAQ,KAAK,OAAO,MAAM,MAAM,EAAE,SAAS,SAAS,KAAK;AAC/D,MAAI,CAAC,MAAO,QAAO,EAAE;EAErB,MAAM,UAAmC,EAAE;AAC3C,OAAK,MAAM,SAAS,MAAM,QAAQ;AAChC,OAAI,CAAC,MAAM,SAAU;GACrB,MAAM,MAAM,YAAY,MAAM,KAAK;GACnC,IAAI,QAAQ,wBAAwB,MAAM,MAAM,MAAM,MAAM,KAAK;AAEjE,QAAK,MAAM,SAAS,UAAU,MAAM,SAAS,WAAW,OAAO,UAAU,SACvE,SAAQ,SAAS,KAAK,KAAK,CAAC,GAAG,KAAK,QAAQ,CAAC,SAAS,GAAG,CAAC,MAAM,GAAG,EAAE;AAEvE,WAAQ,OAAO;;AAEjB,SAAO;;AAGT,QAAO,EAAE;;;AAIX,SAAgB,oBAAoB,IAAe,MAAuC;CACxF,MAAM,SAAiC,EAAE;AAEzC,KAAI,GAAG,WACL,QAAO,WAAW;AAGpB,MAAK,MAAM,KAAK,GAAG,aAAa;AAC9B,MAAI,CAAC,EAAE,SAAU;EACjB,MAAM,QAAQ,qBAAqB,EAAE,MAAM,EAAE,MAAM,KAAK;AACxD,SAAO,YAAY,EAAE,KAAK,IAAI,OAAO,MAAM;;CAI7C,MAAM,SAAiC,EAAE;AACzC,MAAK,MAAM,OAAO,OAAO,KAAK,OAAO,CAAC,MAAM,CAC1C,QAAO,OAAO,OAAO;AAEvB,QAAO;;;AAIT,SAAgB,yBAAyB,IAAe,MAAwC;CAC9F,MAAM,SAAkC,EAAE;AAE1C,KAAI,GAAG,WACL,QAAO,WAAW;AAGpB,MAAK,MAAM,KAAK,GAAG,aAAa;AAC9B,MAAI,CAAC,EAAE,SAAU;EACjB,MAAM,QAAQ,qBAAqB,EAAE,MAAM,EAAE,MAAM,KAAK;AACxD,SAAO,YAAY,EAAE,KAAK,IAAI;;AAGhC,QAAO;;AAOT,IAAa,aAAb,MAAwB;CACtB,sBAAc,IAAI,KAAqB;CAEvC,IAAI,SAAiB,OAAe,OAAqB;AACvD,OAAK,IAAI,IAAI,GAAG,QAAQ,GAAG,SAAS,MAAM;;CAG5C,IAAI,SAAiB,OAAmC;AACtD,SAAO,KAAK,IAAI,IAAI,GAAG,QAAQ,GAAG,QAAQ;;;CAI5C,kBAAkB,IAAe,SAAgD;EAC/E,MAAM,WAAmC,EAAE;AAC3C,OAAK,MAAM,KAAK,GAAG,YAAY;GAC7B,MAAM,QACJ,KAAK,IAAI,SAAS,EAAE,KAAK,IACzB,KAAK,IAAI,SAAS,KAAK,IACvB,KAAK,mBAAmB,EAAE,KAAK,IAC/B,KAAK,qBAAqB,EAAE,KAAK,IACjC,KAAK,mBAAmB,EAAE;AAE5B,OAAI,CAAC,MAAO,QAAO;AACnB,YAAS,EAAE,QAAQ;;AAErB,SAAO;;;CAIT,mBAA2B,OAAmC;AAC5D,OAAK,MAAM,CAAC,KAAK,UAAU,KAAK,IAAI,SAAS,CAC3C,KAAI,IAAI,SAAS,IAAI,QAAQ,CAAE,QAAO;EAGxC,MAAM,aAAa,YAAY,MAAM;AACrC,MAAI,eAAe;QACZ,MAAM,CAAC,KAAK,UAAU,KAAK,IAAI,SAAS,CAC3C,KAAI,IAAI,SAAS,IAAI,aAAa,CAAE,QAAO;;;;;;;;;CAYjD,qBAA6B,WAAuC;AAGlE,MAAI,UAAU,SAAS,MAAM,EAAE;GAE7B,MAAM,SADO,UAAU,MAAM,GAAG,GAAG,CAEhC,MAAM,IAAI,CACV,KAAK,MAAM,EAAE,OAAO,EAAE,CAAC,aAAa,GAAG,EAAE,MAAM,EAAE,CAAC,CAClD,KAAK,GAAG;GACX,MAAM,SAAS,OAAO,SAAS,IAAI,GAAG,SAAS,SAAS;GACxD,MAAM,MAAM,KAAK,IAAI,QAAQ,KAAK,IAAI,KAAK,IAAI,QAAQ,OAAO;AAC9D,OAAI,IAAK,QAAO;GAIhB,MAAM,YAAY,KAAK,oBAAoB,QAAQ,KAAK,IAAI,KAAK,oBAAoB,QAAQ,OAAO;AACpG,OAAI,UAAW,QAAO;;AAIxB,MAAI,UAAU,SAAS,KAAK,IAAI,UAAU,SAAS,GAAG;GACpD,MAAM,OAAO,UAAU,MAAM,GAAG,GAAG;GACnC,MAAM,SAAS,KAAK,OAAO,EAAE,CAAC,aAAa,GAAG,KAAK,MAAM,EAAE;GAC3D,MAAM,SAAS,OAAO,SAAS,IAAI,GAAG,SAAS,SAAS;GACxD,MAAM,MAAM,KAAK,IAAI,QAAQ,KAAK,IAAI,KAAK,IAAI,QAAQ,OAAO;AAC9D,OAAI,IAAK,QAAO;GAGhB,MAAM,YAAY,KAAK,oBAAoB,QAAQ,KAAK,IAAI,KAAK,oBAAoB,QAAQ,OAAO;AACpG,OAAI,UAAW,QAAO;;;;;;;CAU1B,oBAA4B,QAAgB,OAAmC;AAC7E,OAAK,MAAM,CAAC,KAAK,UAAU,KAAK,IAAI,SAAS,CAC3C,KAAI,IAAI,SAAS,IAAI,QAAQ;OACP,IAAI,MAAM,GAAG,EAAE,MAAM,SAAS,GAAG,CACrC,SAAS,OAAO,CAC9B,QAAO;;;;;;;CAWf,mBAA2B,OAAsC;EAC/D,MAAM,QAAQ,MAAM,WAAW,MAAM;AACrC,MAAI,UAAU,KAAA,KAAa,UAAU,KACnC,QAAO,OAAO,MAAM;;;;;;;CAUxB,gBAAgB,SAAiB,cAAuB,aAAa,MAAY;AAC/E,MAAI,CAAC,gBAAgB,OAAO,iBAAiB,SAAU;EAEvD,MAAM,OAAO;AAIb,MAAI,YAAY;AACd,OAAI,OAAO,KAAK,OAAO,SACrB,MAAK,IAAI,SAAS,MAAM,KAAK,GAAG;AAIlC,OAAI,MAAM,QAAQ,KAAK,KAAK,IAAI,KAAK,KAAK,SAAS,GAAG;IACpD,MAAM,QAAQ,KAAK,KAAK;AACxB,QAAI,SAAS,OAAO,UAAU,UAAU;AACtC,SAAI,OAAO,MAAM,OAAO,SACtB,MAAK,IAAI,SAAS,MAAM,MAAM,GAAG;AAEnC,UAAK,iBAAiB,SAAS,MAAM;;;AAIzC,OAAI,OAAO,KAAK,SAAS,SAAU,MAAK,IAAI,SAAS,QAAQ,KAAK,KAAK;AACvE,OAAI,OAAO,KAAK,QAAQ,SAAU,MAAK,IAAI,SAAS,OAAO,KAAK,IAAI;;AAItE,OAAK,iBAAiB,SAAS,KAAK;AACpC,MAAI,MAAM,QAAQ,KAAK,KAAK,IAAI,KAAK,KAAK,SAAS,GAAG;GACpD,MAAM,QAAQ,KAAK,KAAK;AACxB,OAAI,SAAS,OAAO,UAAU,SAC5B,MAAK,iBAAiB,SAAS,MAAM;;;;CAM3C,iBAAyB,SAAiB,KAAoC;AAC5E,OAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,IAAI,EAAE;AAC9C,OAAI,OAAO,UAAU,SAAU;AAC/B,OAAI,QAAQ,KAAM;AAElB,OAAI,IAAI,SAAS,MAAM,IAAK,IAAI,SAAS,KAAK,IAAI,IAAI,SAAS,EAC7D,MAAK,IAAI,SAAS,KAAK,MAAM;;;;;AAWrC,SAAgB,uBAAuB,IAAyB;CAC9D,MAAM,QAAkB,EAAE;AAU1B,OAAM,KAPyC;EAC7C,MAAM;EACN,KAAK;EACL,KAAK;EACL,OAAO;EACP,QAAQ;EACT,CACyB,GAAG,eAAe,IAAI;AAEhD,MAAK,MAAM,OAAO,GAAG,OACnB,KAAI,CAAC,MAAM,SAAS,IAAI,WAAW,CACjC,OAAM,KAAK,IAAI,WAAW;AAG9B,QAAO,MAAM,MAAM,GAAG,MAAM,IAAI,EAAE;;;AAIpC,SAAgB,mBAAmB,QAAgB,IAAwB;AACzE,KAAI,WAAW,EAAG,QAAO;AAEzB,QAAO,CADU,uBAAuB,GAAG,CAC1B,SAAS,OAAO;;AAOnC,SAAgB,YAAY,IAAe,YAA4C;CACrF,IAAI,OAAO,GAAG;AACd,MAAK,MAAM,CAAC,MAAM,UAAU,OAAO,QAAQ,WAAW,CACpD,QAAO,KAAK,QAAQ,IAAI,KAAK,IAAI,MAAM;AAEzC,QAAO;;AAOT,SAAgB,MAAM,IAA2B;AAC/C,QAAO,IAAI,SAAS,YAAY,WAAW,SAAS,GAAG,CAAC;;AAG1D,SAAgB,eAAyE;CACvF,MAAM,OAAO,QAAQ,KAAK,MAAM,EAAE;CAClC,MAAM,UAAU,KAAK,QAAQ,SAAS;CACtC,MAAM,OAAO,YAAY,MAAM,KAAK,UAAU,KAAK,KAAK,UAAU,KAAK,QAAQ,IAAI;AACnF,KAAI,CAAC,MAAM;AACT,UAAQ,MAAM,sFAAsF;AACpG,UAAQ,KAAK,EAAE;;CAEjB,MAAM,aAAa,KAAK,QAAQ,aAAa;CAC7C,MAAM,UAAU,eAAe,MAAM,KAAK,aAAa,KAAK,KAAK,aAAa,KAAK,KAAA;CACnF,MAAM,YAAY,KAAK,QAAQ,iBAAiB;AAEhD,QAAO;EAAE;EAAM;EAAS,aADJ,cAAc,MAAM,KAAK,YAAY,KAAK,KAAK,YAAY,KAAK,QAAQ,IAAI;EAC3D"}
1
+ {"version":3,"file":"smoke.mjs","names":[],"sources":["../src/utils/naming.ts","../src/errors.ts","../src/parser/refs.ts","../src/ir/types.ts","../src/parser/inline-models.ts","../src/parser/schemas.ts","../src/parser/pagination.ts","../src/parser/responses.ts","../src/parser/operations.ts","../src/parser/normalize-inline-models.ts","../src/parser/collect-inline-enums.ts","../src/parser/normalize-model-refs.ts","../src/parser/parse.ts","../scripts/smoke/shared.ts"],"sourcesContent":["/**\n * Known compound tokens that the regex-based splitter over-splits.\n * Each entry is [lowercase-word-sequence, canonical-form].\n * Sorted longest-first so greedy matching works correctly.\n */\nconst COMPOUND_WORDS: [string[], string][] = [\n [['m', '2', 'm'], 'M2M'],\n [['o', 'auth'], 'OAuth'],\n];\n\n/**\n * Recombine adjacent words that form a known compound token.\n */\nfunction recombineCompounds(words: string[]): string[] {\n const result: string[] = [];\n let i = 0;\n while (i < words.length) {\n let matched = false;\n for (const [pattern, canonical] of COMPOUND_WORDS) {\n if (i + pattern.length <= words.length) {\n const matches = pattern.every((p, j) => words[i + j].toLowerCase() === p);\n if (matches) {\n result.push(canonical);\n i += pattern.length;\n matched = true;\n break;\n }\n }\n }\n if (!matched) {\n result.push(words[i]);\n i++;\n }\n }\n return result;\n}\n\n/**\n * Split a string into words, handling:\n * - camelCase / PascalCase boundaries\n * - snake_case / kebab-case separators\n * - Consecutive capitals (e.g., \"HTTPClient\" → [\"HTTP\", \"Client\"])\n * - Numbers as word boundaries (e.g., \"OAuth2Token\" → [\"OAuth\", \"2\", \"Token\"])\n * - Known compounds are recombined (e.g., \"M2M\" stays as one word)\n */\nexport function splitWords(s: string): string[] {\n if (!s) return [];\n\n const words = s\n .replace(/[^a-zA-Z0-9_\\-\\s.]/g, '_') // replace non-alphanumeric chars with separator\n .replace(/([a-z])([A-Z])/g, '$1\\0$2') // camelCase boundary\n .replace(/([A-Z]+)([A-Z][a-z])/g, '$1\\0$2') // consecutive caps boundary\n .replace(/([a-zA-Z])(\\d)/g, '$1\\0$2') // letter to number\n .replace(/(\\d)([a-zA-Z])/g, '$1\\0$2') // number to letter\n .split(/[\\0_\\-\\s.]+/)\n .filter((w) => w.length > 0);\n\n return recombineCompounds(words);\n}\n\nexport const ACRONYM_SET = new Set(['SSO', 'FGA', 'SAML', 'SCIM', 'JWT', 'HMAC', 'M2M']);\n\nexport function toPascalCase(s: string, acronyms?: Set<string>): string {\n const merged = acronyms ? new Set([...ACRONYM_SET, ...acronyms]) : ACRONYM_SET;\n return splitWords(s)\n .map((w) => {\n const upper = w.toUpperCase();\n if (merged.has(upper)) return upper;\n // Special case: OAuth should stay as OAuth, not OAUTH\n if (upper === 'OAUTH') return 'OAuth';\n return w.charAt(0).toUpperCase() + w.slice(1).toLowerCase();\n })\n .join('');\n}\n\nexport function toCamelCase(s: string, acronyms?: Set<string>): string {\n const merged = acronyms ? new Set([...ACRONYM_SET, ...acronyms]) : ACRONYM_SET;\n const words = splitWords(s);\n if (words.length === 0) return '';\n return words\n .map((w, i) => {\n if (i === 0) return w.toLowerCase();\n const upper = w.toUpperCase();\n if (merged.has(upper)) return upper;\n if (upper === 'OAUTH') return 'OAuth';\n return w.charAt(0).toUpperCase() + w.slice(1).toLowerCase();\n })\n .join('');\n}\n\nexport function toSnakeCase(s: string): string {\n return splitWords(s)\n .map((w) => w.toLowerCase())\n .join('_');\n}\n\nexport function toKebabCase(s: string): string {\n return splitWords(s)\n .map((w) => w.toLowerCase())\n .join('-');\n}\n\nexport function toUpperSnakeCase(s: string): string {\n return splitWords(s)\n .map((w) => w.toUpperCase())\n .join('_');\n}\n\nconst BACKEND_SUFFIXES = ['Dto', 'DTO', 'Controller'];\n\nexport function stripBackendSuffixes(name: string): string {\n for (const suffix of BACKEND_SUFFIXES) {\n if (name.endsWith(suffix) && name.length > suffix.length) {\n return name.slice(0, -suffix.length);\n }\n }\n return name;\n}\n\nexport function stripBackendPrefixes(name: string): string {\n return name.replace(/Userland/g, '').replace(/Controller/g, '');\n}\n\n/**\n * Remove ListItem / ByExternalId / ByResourceId / ForResource markers from PascalCase names.\n * E.g. \"DirectoriesListItemState\" → \"DirectoriesState\"\n */\nexport function stripListItemMarkers(name: string): string {\n return name\n .replace(/ListItem/g, '')\n .replace(/ByExternalId/g, '')\n .replace(/ByResourceId/g, '')\n .replace(/ForResource/g, '');\n}\n\n/** Words that look plural but must NOT be singularized. */\nconst SINGULAR_SAFE_LIST = new Set([\n 'Status',\n 'Address',\n 'Access',\n 'Process',\n 'Progress',\n 'Success',\n 'Radius',\n 'Canvas',\n 'Alias',\n 'Basis',\n 'Bus',\n]);\n\n/**\n * Conservative singularize for the leading PascalCase word.\n * Only applied to the first word of a PascalCase name (the resource word).\n * - `ies` → `y` (e.g. Directories → Directory)\n * - trailing `s` for words >4 chars (e.g. Organizations → Organization)\n * Safe-listed words are never singularized.\n */\nexport function singularize(word: string): string {\n if (SINGULAR_SAFE_LIST.has(word)) return word;\n if (word.endsWith('ies') && word.length > 4) {\n return word.slice(0, -3) + 'y';\n }\n if (word.endsWith('ses') && word.length > 4) {\n // e.g. \"Processes\" — but \"Process\" is safe-listed, this handles non-safe ones\n return word.slice(0, -2);\n }\n if (word.endsWith('s') && !word.endsWith('ss') && word.length > 4) {\n return word.slice(0, -1);\n }\n return word;\n}\n\n/**\n * Compose all backend name cleaning transforms in order:\n * 1. Strip backend prefixes (Userland, Controller)\n * 2. Strip backend suffixes (Dto, DTO, Controller)\n * 3. Strip ListItem / ByExternalId markers\n * 4. Singularize leading resource word\n *\n * Must be idempotent: `cleanSchemaName(cleanSchemaName(x)) === cleanSchemaName(x)`\n */\n/** Strip `.js` extensions from import/export specifiers for dedup comparison. */\nexport function normalizeJsExtension(text: string): string {\n return text.replace(/\\.js(['\"])/g, '$1');\n}\n\nexport function cleanSchemaName(name: string): string {\n let result = stripBackendPrefixes(stripBackendSuffixes(name));\n result = stripListItemMarkers(result);\n\n // Singularize the leading PascalCase word\n const match = result.match(/^([A-Z][a-z]*)/);\n if (match) {\n const leadWord = match[1];\n const singular = singularize(leadWord);\n if (singular !== leadWord) {\n result = singular + result.slice(leadWord.length);\n }\n }\n\n return result;\n}\n","/**\n * Structured error hierarchy for oagen.\n *\n * Every error carries a human-readable `hint` that suggests a recovery action.\n * The hint is appended to the `message` so it appears in stack traces and logs.\n */\n\n/** Base class for all oagen errors. */\nexport class OagenError extends Error {\n readonly hint: string;\n\n constructor(message: string, hint: string) {\n const fullMessage = hint ? `${message}\\nHint: ${hint}` : message;\n super(fullMessage);\n this.name = 'OagenError';\n this.hint = hint;\n }\n}\n\n/** Thrown when a command should terminate with a specific exit code. */\nexport class CommandError extends OagenError {\n readonly exitCode: number;\n\n constructor(message: string, hint: string, exitCode: number) {\n super(message, hint);\n this.name = 'CommandError';\n this.exitCode = exitCode;\n }\n}\n\n/** Thrown when an OpenAPI spec cannot be parsed or has an unsupported version. */\nexport class SpecParseError extends OagenError {\n constructor(message: string, hint: string) {\n super(message, hint);\n this.name = 'SpecParseError';\n }\n}\n\n/** Thrown when configuration files (manifests, API surfaces, overlays) are missing or malformed. */\nexport class ConfigError extends OagenError {\n constructor(message: string, hint: string) {\n super(message, hint);\n this.name = 'ConfigError';\n }\n}\n\n/** Thrown when a config file exists but cannot be loaded or evaluated. */\nexport class ConfigLoadError extends ConfigError {\n constructor(message: string, hint: string) {\n super(message, hint);\n this.name = 'ConfigLoadError';\n }\n}\n\n/** Thrown when a config targets a different IR version than the installed package. */\nexport class ConfigVersionMismatchError extends ConfigError {\n constructor(message: string, hint: string) {\n super(message, hint);\n this.name = 'ConfigVersionMismatchError';\n }\n}\n\n/** Thrown when an API surface extractor encounters a problem. */\nexport class ExtractorError extends OagenError {\n constructor(message: string, hint: string) {\n super(message, hint);\n this.name = 'ExtractorError';\n }\n}\n\n/** Thrown when a requested language or extractor is not found in a registry. */\nexport class RegistryError extends OagenError {\n constructor(message: string, hint: string) {\n super(message, hint);\n this.name = 'RegistryError';\n }\n}\n\n/** Thrown for internal invariant violations that indicate a bug. */\nexport class InternalError extends OagenError {\n constructor(message: string, hint: string) {\n super(message, hint);\n this.name = 'InternalError';\n }\n}\n","import { readFile } from 'node:fs/promises';\nimport { resolve } from 'node:path';\nimport { pathToFileURL } from 'node:url';\nimport { makeDocumentFromString, bundleDocument, createConfig, BaseResolver } from '@redocly/openapi-core';\nimport { SpecParseError } from '../errors.js';\n\nexport interface BundledSpec {\n parsed: Record<string, unknown>;\n specPath: string;\n}\n\nexport async function loadAndBundleSpec(specPath: string): Promise<BundledSpec> {\n const absolutePath = resolve(specPath);\n const content = await readFile(absolutePath, 'utf-8');\n const document = makeDocumentFromString(content, pathToFileURL(absolutePath).href);\n\n const config = await createConfig({});\n const resolver = new BaseResolver();\n\n const result = await bundleDocument({\n document,\n config: config.styleguide,\n externalRefResolver: resolver,\n dereference: false,\n });\n\n if (result.problems.some((p) => p.severity === 'error')) {\n const errors = result.problems\n .filter((p) => p.severity === 'error')\n .map((p) => p.message)\n .join('\\n');\n throw new SpecParseError(\n `Failed to parse spec: ${errors}`,\n `Check the OpenAPI spec at \"${absolutePath}\" for syntax errors. Run a linter such as \\`npx @redocly/cli lint ${specPath}\\` to identify issues.`,\n );\n }\n\n return {\n parsed: result.bundle.parsed as Record<string, unknown>,\n specPath: absolutePath,\n };\n}\n","/** Authentication scheme extracted from OpenAPI securitySchemes */\nexport type AuthScheme =\n | { kind: 'bearer' }\n | { kind: 'apiKey'; in: 'header' | 'query' | 'cookie'; name: string }\n | { kind: 'oauth2'; flows: Record<string, unknown> };\n\n/** Root IR node representing the full API surface */\n/** A server entry from the OpenAPI servers array */\nexport interface ServerEntry {\n url: string;\n description?: string;\n}\n\n/** Root IR node representing the full API surface */\nexport interface ApiSpec {\n name: string;\n version: string;\n description?: string;\n baseUrl: string;\n servers?: ServerEntry[];\n services: Service[];\n models: Model[];\n enums: Enum[];\n auth?: AuthScheme[];\n}\n\n/** A service groups related operations (maps to an SDK resource class) */\nexport interface Service {\n name: string;\n description?: string;\n operations: Operation[];\n}\n\n/** A single API operation (maps to an SDK method) */\nexport interface Operation {\n name: string;\n description?: string;\n httpMethod: HttpMethod;\n path: string;\n pathParams: Parameter[];\n queryParams: Parameter[];\n headerParams: Parameter[];\n cookieParams?: Parameter[];\n requestBody?: TypeRef;\n requestBodyEncoding?: 'json' | 'form-data' | 'form-urlencoded' | 'binary' | 'text';\n response: TypeRef;\n successResponses?: SuccessResponse[];\n errors: ErrorResponse[];\n pagination?: PaginationMeta;\n injectIdempotencyKey: boolean;\n deprecated?: boolean;\n async?: boolean;\n}\n\n/** Structured pagination metadata for auto-paging iterator generation */\nexport interface PaginationMeta {\n strategy: 'cursor' | 'offset' | 'link-header';\n param: string;\n limitParam?: string;\n dataPath?: string;\n itemType: TypeRef;\n}\n\nexport type HttpMethod = 'get' | 'post' | 'put' | 'patch' | 'delete' | 'head' | 'options' | 'trace';\n\nexport interface Parameter {\n name: string;\n type: TypeRef;\n required: boolean;\n description?: string;\n deprecated?: boolean;\n default?: unknown;\n example?: unknown;\n}\n\n/** Type reference — the core type system of the IR */\nexport type TypeRef = PrimitiveType | ArrayType | ModelRef | EnumRef | UnionType | NullableType | LiteralType | MapType;\n\nexport interface PrimitiveType {\n kind: 'primitive';\n type: 'string' | 'integer' | 'number' | 'boolean' | 'unknown';\n format?: string;\n}\n\nexport interface ArrayType {\n kind: 'array';\n items: TypeRef;\n}\n\nexport interface ModelRef {\n kind: 'model';\n name: string;\n}\n\nexport interface EnumRef {\n kind: 'enum';\n name: string;\n values?: (string | number)[];\n}\n\nexport interface LiteralType {\n kind: 'literal';\n value: string | number | boolean | null;\n}\n\nexport interface UnionType {\n kind: 'union';\n variants: TypeRef[];\n discriminator?: { property: string; mapping: Record<string, string> };\n /** Which OAS composition keyword produced this union. Emitters can use this to\n * distinguish inheritance (allOf) from exclusive union (oneOf) from open union (anyOf). */\n compositionKind?: 'allOf' | 'oneOf' | 'anyOf';\n}\n\nexport interface NullableType {\n kind: 'nullable';\n inner: TypeRef;\n}\n\nexport interface MapType {\n kind: 'map';\n valueType: TypeRef;\n keyType?: TypeRef;\n}\n\n/**\n * A generic type parameter on a model.\n * Example: `DirectoryUser<TCustomAttributes = Record<string, unknown>>`\n * → `{ name: 'TCustomAttributes', default: { kind: 'map', valueType: { kind: 'primitive', type: 'unknown' } } }`\n */\nexport interface TypeParam {\n name: string;\n /** Default type when the param is not specified. */\n default?: TypeRef;\n}\n\n/** Model definition (maps to an SDK model/data class) */\nexport interface Model {\n name: string;\n description?: string;\n fields: Field[];\n /** Generic type parameters. Empty/undefined for non-generic models. */\n typeParams?: TypeParam[];\n}\n\nexport interface Field {\n name: string;\n type: TypeRef;\n required: boolean;\n description?: string;\n readOnly?: boolean;\n writeOnly?: boolean;\n deprecated?: boolean;\n default?: unknown;\n example?: unknown;\n}\n\n/** Enum definition */\nexport interface Enum {\n name: string;\n values: EnumValue[];\n}\n\nexport interface EnumValue {\n name: string;\n value: string | number;\n description?: string;\n deprecated?: boolean;\n}\n\n/**\n * Exhaustive check helper for TypeRef switches.\n * If a new kind is added to TypeRef, any switch that doesn't handle it\n * will fail to compile because `never` won't accept the unhandled variant.\n *\n * Usage:\n * switch (ref.kind) {\n * case 'primitive': ...\n * case 'array': ...\n * // If you forget 'literal', TypeScript errors here:\n * default: assertNever(ref);\n * }\n */\nexport function assertNever(x: never): never {\n // Inline to avoid importing from ../errors.js (ir/ is layer 0, must not import upward)\n const kind = (x as TypeRef).kind;\n const err = new Error(\n `Unexpected TypeRef kind: ${kind}\\nHint: If you added a new TypeRef variant, handle it in every switch/case that calls assertNever.`,\n );\n err.name = 'InternalError';\n throw err;\n}\n\n/**\n * Generic depth-first walker for TypeRef trees.\n * Handles recursion into array/nullable/union/map children and provides\n * an exhaustive `assertNever` check so callers don't need to repeat the\n * switch boilerplate. Supply callbacks only for the leaf kinds you care about.\n */\nexport function walkTypeRef(\n ref: TypeRef,\n visitor: {\n model?: (ref: ModelRef) => void;\n enum?: (ref: EnumRef) => void;\n primitive?: (ref: PrimitiveType) => void;\n literal?: (ref: LiteralType) => void;\n },\n): void {\n switch (ref.kind) {\n case 'model':\n visitor.model?.(ref);\n break;\n case 'enum':\n visitor.enum?.(ref);\n break;\n case 'array':\n walkTypeRef(ref.items, visitor);\n break;\n case 'nullable':\n walkTypeRef(ref.inner, visitor);\n break;\n case 'union':\n for (const v of ref.variants) walkTypeRef(v, visitor);\n break;\n case 'map':\n if (ref.keyType) walkTypeRef(ref.keyType, visitor);\n walkTypeRef(ref.valueType, visitor);\n break;\n case 'literal':\n visitor.literal?.(ref);\n break;\n case 'primitive':\n visitor.primitive?.(ref);\n break;\n default:\n assertNever(ref);\n }\n}\n\n/**\n * Generic depth-first mapper for TypeRef trees.\n * Like walkTypeRef but returns a transformed value instead of void.\n * Handles recursion into array/nullable/union/map children, passing\n * already-mapped child values to the parent callback.\n */\nexport function mapTypeRef<T>(\n ref: TypeRef,\n mapper: {\n primitive: (ref: PrimitiveType) => T;\n array: (ref: ArrayType, mappedItems: T) => T;\n model: (ref: ModelRef) => T;\n enum: (ref: EnumRef) => T;\n union: (ref: UnionType, mappedVariants: T[]) => T;\n nullable: (ref: NullableType, mappedInner: T) => T;\n literal: (ref: LiteralType) => T;\n map: (ref: MapType, mappedValue: T, mappedKey?: T) => T;\n },\n): T {\n switch (ref.kind) {\n case 'primitive':\n return mapper.primitive(ref);\n case 'array':\n return mapper.array(ref, mapTypeRef(ref.items, mapper));\n case 'model':\n return mapper.model(ref);\n case 'enum':\n return mapper.enum(ref);\n case 'union':\n return mapper.union(\n ref,\n ref.variants.map((v) => mapTypeRef(v, mapper)),\n );\n case 'nullable':\n return mapper.nullable(ref, mapTypeRef(ref.inner, mapper));\n case 'literal':\n return mapper.literal(ref);\n case 'map':\n return mapper.map(\n ref,\n mapTypeRef(ref.valueType, mapper),\n ref.keyType ? mapTypeRef(ref.keyType, mapper) : undefined,\n );\n default:\n return assertNever(ref);\n }\n}\n\n// --- IR traversal utilities ---\n\n/**\n * Collect all model names referenced (directly or transitively) by a TypeRef.\n */\nexport function collectModelRefs(ref: TypeRef): string[] {\n const names: string[] = [];\n walkTypeRef(ref, { model: (r) => names.push(r.name) });\n return names;\n}\n\n/**\n * Collect all enum names referenced by a TypeRef.\n */\nexport function collectEnumRefs(ref: TypeRef): string[] {\n const names: string[] = [];\n walkTypeRef(ref, { enum: (r) => names.push(r.name) });\n return names;\n}\n\n/**\n * Collect all TypeRef-referenced model and enum names from a model's fields.\n * Returns { models, enums } sets for generating import statements.\n */\nexport function collectFieldDependencies(model: Model): {\n models: Set<string>;\n enums: Set<string>;\n} {\n const models = new Set<string>();\n const enums = new Set<string>();\n\n for (const field of model.fields) {\n for (const name of collectModelRefs(field.type)) {\n if (name !== model.name) models.add(name);\n }\n for (const name of collectEnumRefs(field.type)) {\n enums.add(name);\n }\n }\n\n return { models, enums };\n}\n\n/**\n * Assign each model to the service that first references it.\n * Models referenced by multiple services are assigned to the first.\n * Models not referenced by any service are unassigned (absent from the map).\n */\nexport function assignModelsToServices(models: Model[], services: Service[]): Map<string, string> {\n const modelToService = new Map<string, string>();\n const modelNames = new Set(models.map((m) => m.name));\n\n for (const service of services) {\n const referencedModels = new Set<string>();\n\n for (const op of service.operations) {\n if (op.requestBody) {\n for (const name of collectModelRefs(op.requestBody)) {\n referencedModels.add(name);\n }\n }\n for (const name of collectModelRefs(op.response)) {\n referencedModels.add(name);\n }\n for (const param of [...op.pathParams, ...op.queryParams, ...op.headerParams, ...(op.cookieParams ?? [])]) {\n for (const name of collectModelRefs(param.type)) {\n referencedModels.add(name);\n }\n }\n if (op.pagination) {\n for (const name of collectModelRefs(op.pagination.itemType)) {\n referencedModels.add(name);\n }\n }\n }\n\n // Transitively collect models referenced by the directly-referenced models\n const toVisit = [...referencedModels];\n while (toVisit.length > 0) {\n const name = toVisit.pop()!;\n const model = models.find((m) => m.name === name);\n if (!model) continue;\n for (const field of model.fields) {\n for (const ref of collectModelRefs(field.type)) {\n if (!referencedModels.has(ref) && modelNames.has(ref)) {\n referencedModels.add(ref);\n toVisit.push(ref);\n }\n }\n }\n }\n\n for (const name of referencedModels) {\n if (!modelToService.has(name)) {\n modelToService.set(name, service.name);\n }\n }\n }\n\n return modelToService;\n}\n\n/**\n * Collect all model names referenced as request bodies across all services.\n */\nexport function collectRequestBodyModels(services: Service[]): Set<string> {\n const result = new Set<string>();\n for (const service of services) {\n for (const op of service.operations) {\n if (op.requestBody) {\n for (const name of collectModelRefs(op.requestBody)) {\n result.add(name);\n }\n }\n }\n }\n return result;\n}\n\nexport interface ErrorResponse {\n statusCode: number;\n type?: TypeRef;\n}\n\n/** A successful response entry from a 2xx status code */\nexport interface SuccessResponse {\n statusCode: number;\n type: TypeRef;\n}\n","import type { Model, Field } from '../ir/types.js';\nimport { toPascalCase, cleanSchemaName, stripListItemMarkers, singularize } from '../utils/naming.js';\nimport type { SchemaObject } from './schemas.js';\nimport { buildFieldFromSchema } from './schemas.js';\n\n/**\n * Qualify an inline model name with the parent schema name.\n * If `parentName` is provided and the field name doesn't already start with\n * the parent, the result is `${parentName}${PascalField}` with the trailing\n * word singularized (e.g., Connection + Domains → ConnectionDomain).\n */\nexport function qualifyInlineModelName(baseName: string, parentName?: string): string {\n if (!parentName) return baseName;\n // Strip ListItem/ByExternalId markers from parent name so inline model names\n // are clean and match the names produced by qualifyNestedName() in responses.ts.\n // e.g., ConnectionListItem + Domains → Connection + Domain = ConnectionDomain\n const cleanParent = stripListItemMarkers(parentName);\n if (baseName.startsWith(cleanParent)) return baseName;\n // Singularize the trailing PascalCase word of the combined name.\n // Split baseName into leading words + trailing word, singularize trailing.\n const trailingMatch = baseName.match(/^(.*?)([A-Z][a-z]*)$/);\n if (trailingMatch) {\n const [, prefix, trailingWord] = trailingMatch;\n const singular = singularize(trailingWord);\n return `${cleanParent}${prefix}${singular}`;\n }\n return `${cleanParent}${baseName}`;\n}\n\n/**\n * Walk all component schemas and extract inline Model definitions for fields\n * that are objects with properties (or arrays of such objects).\n * These correspond to the ModelRef entries created by schemaToTypeRef.\n */\nexport function extractInlineModelsFromSchemas(schemas: Record<string, SchemaObject> | undefined): Model[] {\n if (!schemas) return [];\n\n const inlineModels: Model[] = [];\n\n for (const [schemaName, schema] of Object.entries(schemas)) {\n const parentName = cleanSchemaName(toPascalCase(schemaName));\n extractInlineModelsFromProperties(schema, inlineModels, parentName);\n }\n\n return inlineModels;\n}\n\nfunction extractInlineModelsFromProperties(schema: SchemaObject, results: Model[], parentName?: string): void {\n const properties = schema.properties ?? {};\n const allOfSchemas = schema.allOf ?? [];\n\n for (const sub of allOfSchemas) {\n if (sub.properties) {\n extractInlineModelsFromProperties(sub, results, parentName);\n }\n }\n\n for (const [fieldName, fieldSchema] of Object.entries(properties)) {\n if (!fieldSchema) continue;\n // Direct inline object with properties (with or without explicit type: 'object')\n if (fieldSchema.properties && (fieldSchema.type === 'object' || !fieldSchema.type)) {\n const baseName = toPascalCase(fieldName);\n const modelName = qualifyInlineModelName(baseName, parentName);\n results.push(buildInlineModel(modelName, fieldSchema));\n extractInlineModelsFromProperties(fieldSchema, results, modelName);\n }\n\n // Array of inline objects\n if (fieldSchema.type === 'array' && fieldSchema.items) {\n const items = fieldSchema.items;\n if (items.properties && (items.type === 'object' || !items.type)) {\n const baseName = toPascalCase(fieldName);\n const modelName = qualifyInlineModelName(baseName, parentName);\n results.push(buildInlineModel(modelName, items));\n extractInlineModelsFromProperties(items, results, modelName);\n }\n }\n\n // oneOf containing objects — extract the first non-null variant as a model\n // This handles: totp: { oneOf: [{ type: object, properties: {...} }, { type: 'null' }] }\n if (fieldSchema.oneOf) {\n const objectVariant = fieldSchema.oneOf.find((v) => v.properties && (v.type === 'object' || !v.type));\n if (objectVariant) {\n const baseName = toPascalCase(fieldName);\n const modelName = qualifyInlineModelName(baseName, parentName);\n const existingNames = new Set(results.map((r) => r.name));\n if (!existingNames.has(modelName)) {\n results.push(buildInlineModel(modelName, objectVariant));\n extractInlineModelsFromProperties(objectVariant, results, modelName);\n }\n }\n }\n }\n}\n\nfunction buildInlineModel(name: string, schema: SchemaObject): Model {\n const requiredSet = new Set(schema.required ?? []);\n const fields: Field[] = [];\n\n for (const [fieldName, fieldSchema] of Object.entries(schema.properties ?? {})) {\n if (!fieldSchema) continue;\n fields.push(buildFieldFromSchema(fieldName, fieldSchema, name, requiredSet));\n }\n\n return { name, description: schema.description, fields };\n}\n","import type { Model, Enum, EnumValue, Field, TypeRef } from '../ir/types.js';\nimport { walkTypeRef } from '../ir/types.js';\nimport { toPascalCase, toUpperSnakeCase, cleanSchemaName, stripListItemMarkers } from '../utils/naming.js';\n\nexport interface SchemaObject {\n type?: string | string[];\n format?: string;\n description?: string;\n properties?: Record<string, SchemaObject | undefined>;\n required?: string[];\n items?: SchemaObject;\n enum?: (string | number)[];\n allOf?: SchemaObject[];\n oneOf?: SchemaObject[];\n anyOf?: SchemaObject[];\n discriminator?: { propertyName: string; mapping?: Record<string, string> };\n readOnly?: boolean;\n writeOnly?: boolean;\n nullable?: boolean;\n $ref?: string;\n additionalProperties?: boolean | SchemaObject;\n const?: unknown;\n patternProperties?: Record<string, SchemaObject>;\n deprecated?: boolean;\n default?: unknown;\n example?: unknown;\n [key: string]: unknown;\n}\n\nexport interface ExtractedSchemas {\n models: Model[];\n enums: Enum[];\n}\n\nexport function extractSchemas(schemas: Record<string, SchemaObject> | undefined): ExtractedSchemas {\n const enums: Enum[] = [];\n\n if (!schemas) return { models: [], enums };\n\n const modelsByCleanName = new Map<string, Model>();\n\n for (const [name, schema] of Object.entries(schemas)) {\n const pascalName = cleanSchemaName(toPascalCase(name));\n\n if (schema.enum) {\n enums.push(extractEnum(pascalName, schema));\n } else {\n const model = extractModel(pascalName, schema, schemas);\n const existing = modelsByCleanName.get(pascalName);\n if (existing) {\n // Keep the model with more fields when names collide after cleaning\n if (model.fields.length > existing.fields.length) {\n modelsByCleanName.set(pascalName, model);\n }\n } else {\n modelsByCleanName.set(pascalName, model);\n }\n }\n }\n\n const models = [...modelsByCleanName.values()];\n\n // Collect inline models from nested object/oneOf properties\n // that schemaToTypeRef created model refs for but weren't extracted\n const modelNames = new Set(models.map((m) => m.name));\n const inlineQueue: Model[] = [...models];\n while (inlineQueue.length > 0) {\n const model = inlineQueue.pop()!;\n for (const field of model.fields) {\n collectNestedInlineModels(field.type, field.name, model.name, schemas ?? {}, models, modelNames, inlineQueue);\n }\n }\n\n // Collect inline enums from model fields\n for (const model of models) {\n collectInlineEnums(model.fields, enums);\n }\n\n return { models, enums };\n}\n\n/**\n * Walk a single TypeRef and extract inline enum refs as top-level enum definitions.\n * Shared by both schemas.ts (field-level) and parse.ts (model-level) collection passes.\n */\nexport function collectInlineEnumFromRef(ref: TypeRef, enums: Enum[], seen: Set<string>): void {\n walkTypeRef(ref, {\n enum: (r) => {\n if (r.values && !seen.has(r.name)) {\n seen.add(r.name);\n enums.push({\n name: r.name,\n values: r.values.map((v) => ({\n name: toUpperSnakeCase(String(v)),\n value: v,\n description: undefined,\n })),\n });\n }\n },\n });\n}\n\n/**\n * Walk model fields and extract inline enum refs as top-level enum definitions.\n * This ensures type alias files are generated for inline enums.\n */\nfunction collectInlineEnums(fields: Field[], enums: Enum[]): void {\n const seen = new Set(enums.map((e) => e.name));\n for (const field of fields) {\n collectInlineEnumFromRef(field.type, enums, seen);\n }\n}\n\n/**\n * Walk a TypeRef tree and extract inline models for any model refs that point\n * to schemas with inline object properties (not in components/schemas).\n * This handles nested objects like `totp: { oneOf: [{ type: object, properties: {...} }] }`\n * that schemaToTypeRef turns into model refs but aren't extracted from components.\n */\nfunction collectNestedInlineModels(\n ref: TypeRef,\n fieldName: string,\n parentModelName: string,\n schemas: Record<string, SchemaObject>,\n models: Model[],\n modelNames: Set<string>,\n queue: Model[],\n): void {\n walkTypeRef(ref, {\n model: (modelRef) => {\n if (modelNames.has(modelRef.name)) return; // already extracted\n // Check if this model name corresponds to a component schema\n // by checking all possible original names that would map to this PascalCase name\n const isComponent = Object.keys(schemas).some((k) => cleanSchemaName(toPascalCase(k)) === modelRef.name);\n if (isComponent) return; // will be extracted from components\n\n // This is a reference to a nested inline model that wasn't extracted.\n // Look up the field schema in the parent model's component schema to extract it.\n const parentSchema = findSchemaByName(parentModelName, schemas);\n if (!parentSchema) return;\n\n const fieldSchema = findNestedFieldSchema(fieldName, parentSchema, schemas);\n if (!fieldSchema) return;\n\n // Extract inline models from the field schema\n const extracted = extractNestedSchema(modelRef.name, fieldSchema);\n for (const m of extracted) {\n if (!modelNames.has(m.name)) {\n models.push(m);\n modelNames.add(m.name);\n queue.push(m); // re-scan for deeper nesting\n }\n }\n },\n });\n}\n\n/** Find a component schema by PascalCase name. */\nfunction findSchemaByName(pascalName: string, schemas: Record<string, SchemaObject>): SchemaObject | null {\n for (const [k, v] of Object.entries(schemas)) {\n if (cleanSchemaName(toPascalCase(k)) === pascalName) return v;\n }\n return null;\n}\n\n/** Walk into a schema to find a field's sub-schema, resolving allOf. */\nfunction findNestedFieldSchema(\n fieldName: string,\n parentSchema: SchemaObject,\n schemas: Record<string, SchemaObject>,\n): SchemaObject | null {\n if (parentSchema.properties?.[fieldName]) {\n return parentSchema.properties[fieldName]!;\n }\n if (parentSchema.allOf) {\n for (const sub of parentSchema.allOf) {\n let resolved = sub;\n if (sub.$ref) {\n const segments = sub.$ref.split('/');\n const refName = segments[segments.length - 1];\n if (refName && schemas[refName]) resolved = schemas[refName];\n }\n if (resolved.properties?.[fieldName]) {\n return resolved.properties[fieldName]!;\n }\n }\n }\n return null;\n}\n\n/** Extract a model (and nested models) from an inline field schema. */\nfunction extractNestedSchema(name: string, schema: SchemaObject): Model[] {\n // Handle oneOf: extract each object variant as its own model\n if (schema.oneOf) {\n const models: Model[] = [];\n for (const variant of schema.oneOf) {\n if (variant.$ref) continue;\n if (variant.properties && (variant.type === 'object' || !variant.type)) {\n const requiredSet = new Set(variant.required ?? []);\n const fields: Field[] = [];\n for (const [fn, fs] of Object.entries(variant.properties)) {\n if (!fs) continue;\n fields.push(buildFieldFromSchema(fn, fs, name, requiredSet));\n }\n // Use the name for the first variant, suffix for subsequent\n const variantName = models.length === 0 ? name : `${name}${models.length + 1}`;\n models.push({ name: variantName, description: variant.description, fields });\n }\n }\n return models;\n }\n\n // Handle direct object\n if (schema.properties && (schema.type === 'object' || !schema.type)) {\n const requiredSet = new Set(schema.required ?? []);\n const fields: Field[] = [];\n for (const [fn, fs] of Object.entries(schema.properties)) {\n if (!fs) continue;\n fields.push(buildFieldFromSchema(fn, fs, name, requiredSet));\n }\n return [{ name, description: schema.description, fields }];\n }\n\n // Handle array with inline items\n if (schema.type === 'array' && schema.items?.properties) {\n const requiredSet = new Set(schema.items.required ?? []);\n const fields: Field[] = [];\n for (const [fn, fs] of Object.entries(schema.items.properties)) {\n if (!fs) continue;\n fields.push(buildFieldFromSchema(fn, fs, name, requiredSet));\n }\n return [{ name, description: schema.items.description, fields }];\n }\n\n return [];\n}\n\n/** Build a single Field from a schema property entry. Shared across all extraction sites. */\nexport function buildFieldFromSchema(\n fieldName: string,\n fieldSchema: SchemaObject,\n contextName: string,\n requiredSet: Set<string>,\n): Field {\n return {\n name: fieldName,\n type: schemaToTypeRef(fieldSchema, fieldName, contextName),\n required: requiredSet.has(fieldName),\n description: fieldSchema.description,\n readOnly: fieldSchema.readOnly || undefined,\n writeOnly: fieldSchema.writeOnly || undefined,\n deprecated: fieldSchema.deprecated || undefined,\n default: fieldSchema.default,\n example: fieldSchema.example,\n };\n}\n\nfunction extractEnum(name: string, schema: SchemaObject): Enum {\n const values: EnumValue[] = (schema.enum ?? []).map((v) => ({\n name: toUpperSnakeCase(String(v)),\n value: typeof v === 'number' ? v : String(v),\n description: undefined,\n }));\n\n return { name, values };\n}\nfunction extractModel(name: string, schema: SchemaObject, schemas?: Record<string, SchemaObject>): Model {\n if (schema.allOf) {\n return extractAllOfModel(name, schema, schemas);\n }\n\n const requiredSet = new Set(schema.required ?? []);\n const fields: Field[] = [];\n\n for (const [fieldName, fieldSchema] of Object.entries(schema.properties ?? {})) {\n if (!fieldSchema) continue;\n fields.push(buildFieldFromSchema(fieldName, fieldSchema, name, requiredSet));\n }\n\n // When additionalProperties is an object schema alongside properties,\n // surface it as a catch-all map field so emitters can generate Map<string, T>.\n if (schema.additionalProperties && typeof schema.additionalProperties === 'object' && schema.properties) {\n const apKeys = Object.keys(schema.additionalProperties);\n if (apKeys.length > 0) {\n const valueType = schemaToTypeRef(schema.additionalProperties as SchemaObject, 'additionalProperties', name);\n fields.push({\n name: 'additionalProperties',\n type: { kind: 'map', valueType },\n required: false,\n description: 'Additional properties not captured by named fields',\n });\n }\n }\n\n return { name, description: schema.description, fields };\n}\n\nfunction extractAllOfModel(name: string, schema: SchemaObject, schemas?: Record<string, SchemaObject>): Model {\n const fields: Field[] = [];\n const requiredSet = new Set<string>();\n\n for (const subSchema of schema.allOf ?? []) {\n // Resolve $ref sub-schemas by looking up the referenced component schema\n let resolved = subSchema;\n if (subSchema.$ref && schemas) {\n const segments = subSchema.$ref.split('/');\n const refName = segments[segments.length - 1];\n if (refName && schemas[refName]) {\n resolved = schemas[refName];\n }\n }\n\n // If the resolved schema is itself an allOf, recursively extract its fields\n if (resolved.allOf) {\n const nested = extractAllOfModel(name, resolved, schemas);\n for (const f of nested.fields) {\n fields.push({ ...f, required: false }); // will be re-set below\n if (f.required) requiredSet.add(f.name);\n }\n } else {\n if (resolved.required) {\n for (const r of resolved.required) requiredSet.add(r);\n }\n if (resolved.properties) {\n // Use an empty requiredSet — required flags are set in the final pass below\n const emptyRequired = new Set<string>();\n for (const [fieldName, fieldSchema] of Object.entries(resolved.properties)) {\n if (!fieldSchema) continue;\n fields.push(buildFieldFromSchema(fieldName, fieldSchema, name, emptyRequired));\n }\n }\n }\n }\n\n // Also collect required from the outer schema\n if (schema.required) {\n for (const r of schema.required) requiredSet.add(r);\n }\n\n // Set required flags\n for (const f of fields) {\n f.required = requiredSet.has(f.name);\n }\n\n return { name, description: schema.description, fields };\n}\n\nexport function schemaToTypeRef(schema: SchemaObject, contextName?: string, parentModelName?: string): TypeRef {\n // Handle $ref → ModelRef\n if (schema.$ref) {\n const segments = schema.$ref.split('/');\n const rawName = segments[segments.length - 1];\n return { kind: 'model', name: cleanSchemaName(toPascalCase(rawName)) };\n }\n\n // Handle OAS 3.1 nullable type arrays: type: [string, null]\n if (Array.isArray(schema.type)) {\n const nonNullTypes = schema.type.filter((t: string) => t !== 'null');\n // type: ['null'] — only null, no real type\n if (nonNullTypes.length === 0) {\n return { kind: 'nullable', inner: { kind: 'primitive', type: 'unknown' } };\n }\n if (schema.type.includes('null') && nonNullTypes.length === 1) {\n return {\n kind: 'nullable',\n inner: schemaToTypeRef({ ...schema, type: nonNullTypes[0], nullable: false }, contextName),\n };\n }\n // Multiple non-null types → union\n if (nonNullTypes.length > 1) {\n const variants = nonNullTypes.map((t: string) => schemaToTypeRef({ ...schema, type: t }, contextName));\n const ref: TypeRef = { kind: 'union', variants };\n if (schema.type.includes('null')) {\n return { kind: 'nullable', inner: ref };\n }\n return ref;\n }\n }\n\n // Handle OAS 3.0 nullable flag\n if (schema.nullable && schema.type) {\n return {\n kind: 'nullable',\n inner: schemaToTypeRef({ ...schema, nullable: false }, contextName),\n };\n }\n\n // Handle allOf — merge properties from all sub-schemas.\n // This handles patterns like: allOf: [{ type: object, properties: {...} }, { oneOf: [...] }]\n // which are valid OAS 3.1 but weren't handled for field-level schemas.\n if (schema.allOf) {\n // If allOf contains a $ref, prefer the ref (it's a named type)\n const refItem = schema.allOf.find((s: SchemaObject) => s.$ref);\n if (refItem) {\n // If allOf has $ref AND siblings with properties, return a merged model ref\n // to avoid losing the augmentation properties\n const hasAugmentation = schema.allOf.some((s: SchemaObject) => !s.$ref && (s.properties || s.type === 'object'));\n if (hasAugmentation) {\n const baseName = toPascalCase(contextName ?? 'UnknownModel');\n return { kind: 'model', name: qualifyInlineModelName(baseName, parentModelName) };\n }\n return schemaToTypeRef(refItem, contextName, parentModelName);\n }\n // If allOf has a single item, unwrap it\n if (schema.allOf.length === 1) {\n return schemaToTypeRef(schema.allOf[0], contextName, parentModelName);\n }\n // If allOf items all have properties, treat as a merged model\n const hasProperties = schema.allOf.some((s: SchemaObject) => s.properties);\n if (hasProperties) {\n const baseName = toPascalCase(contextName ?? 'UnknownModel');\n return {\n kind: 'model',\n name: qualifyInlineModelName(baseName, parentModelName),\n };\n }\n // Fall through to other checks\n }\n\n // Handle oneOf / anyOf → Union or Nullable\n // Valid OAS 3.1: properties can have { oneOf: [{ type: object }, { type: 'null' }] }\n // without a wrapping `type` field.\n if (schema.oneOf || schema.anyOf) {\n const compositionKind: 'oneOf' | 'anyOf' = schema.oneOf ? 'oneOf' : 'anyOf';\n const rawVariants: SchemaObject[] = schema.oneOf ?? schema.anyOf ?? [];\n\n // Check for nullable pattern: oneOf: [realType, { type: 'null' }]\n const nullVariant = rawVariants.find(\n (v: SchemaObject) => v.type === 'null' || (Array.isArray(v.type) && v.type.length === 1 && v.type[0] === 'null'),\n );\n const nonNullVariants = rawVariants.filter((v) => v !== nullVariant);\n\n if (nullVariant && nonNullVariants.length === 1) {\n // Nullable single type — unwrap as nullable\n return {\n kind: 'nullable',\n inner: schemaToTypeRef(nonNullVariants[0], contextName, parentModelName),\n };\n }\n\n // General union\n const variants = rawVariants\n .filter((v: SchemaObject) => v.type !== 'null')\n .map((v: SchemaObject) => schemaToTypeRef(v, contextName, parentModelName));\n const hasNull = !!nullVariant;\n const union: TypeRef = {\n kind: 'union',\n variants,\n compositionKind,\n ...(schema.discriminator\n ? {\n discriminator: {\n property: schema.discriminator.propertyName,\n mapping: Object.fromEntries(\n Object.entries(schema.discriminator.mapping ?? {}).map(([k, v]) => [\n k,\n v.replace(/^#\\/components\\/schemas\\//, ''),\n ]),\n ),\n },\n }\n : {}),\n };\n return hasNull ? { kind: 'nullable', inner: union } : union;\n }\n\n // Handle const → LiteralType (supports string, number, boolean)\n if (schema.const !== undefined) {\n if (typeof schema.const === 'string' || typeof schema.const === 'number' || typeof schema.const === 'boolean') {\n return { kind: 'literal', value: schema.const };\n }\n // null const → nullable unknown\n if (schema.const === null) {\n return { kind: 'nullable', inner: { kind: 'primitive', type: 'unknown' } };\n }\n // const of object/array → map or array with unknown values\n if (typeof schema.const === 'object') {\n if (Array.isArray(schema.const)) {\n return { kind: 'array', items: { kind: 'primitive', type: 'unknown' } };\n }\n return { kind: 'map', valueType: { kind: 'primitive', type: 'unknown' } };\n }\n }\n if (schema.enum && schema.enum.length === 1) {\n const v = schema.enum[0];\n return { kind: 'literal', value: typeof v === 'number' ? v : String(v) };\n }\n\n // Handle enum\n if (schema.enum) {\n const baseName = toPascalCase(contextName ?? 'UnknownEnum');\n // Strip ListItem/ByExternalId markers from parent name so enum names are clean:\n // e.g., DirectoryListItem + State → Directory + State = DirectoryState\n const cleanParent = parentModelName ? stripListItemMarkers(parentModelName) : undefined;\n // Avoid redundant prefix: Connection + ConnectionType → ConnectionType\n const qualifiedName = cleanParent && !baseName.startsWith(cleanParent) ? `${cleanParent}${baseName}` : baseName;\n return {\n kind: 'enum',\n name: qualifiedName,\n values: schema.enum.map((v) => (typeof v === 'number' ? v : String(v))),\n };\n }\n\n // Handle array — pass parentModelName through to qualify inline items\n if (schema.type === 'array' && schema.items) {\n return {\n kind: 'array',\n items: schemaToTypeRef(schema.items, contextName, parentModelName),\n };\n }\n // Handle array without explicit type but with items (valid OAS 3.1)\n if (!schema.type && schema.items) {\n return {\n kind: 'array',\n items: schemaToTypeRef(schema.items, contextName, parentModelName),\n };\n }\n\n // Handle object → ModelRef (if it has properties, it's a named model reference)\n // When additionalProperties is also present, we still return a ModelRef so the\n // named properties are preserved. The extractModel path will pick up the extra\n // properties as a catch-all map field named `additionalProperties`.\n if (schema.type === 'object' && schema.properties) {\n const baseName = toPascalCase(contextName ?? 'UnknownModel');\n return {\n kind: 'model',\n name: qualifyInlineModelName(baseName, parentModelName),\n };\n }\n\n // Handle freeform object with additionalProperties or patternProperties → Map<string, T>\n if (schema.type === 'object' && !schema.properties) {\n let valueType: TypeRef = { kind: 'primitive', type: 'unknown' };\n if (schema.additionalProperties && typeof schema.additionalProperties === 'object') {\n // Empty additionalProperties ({}) means \"any value\" — keep as unknown\n const apKeys = Object.keys(schema.additionalProperties);\n if (apKeys.length > 0) {\n valueType = schemaToTypeRef(schema.additionalProperties as SchemaObject, contextName);\n }\n } else if (schema.patternProperties) {\n // patternProperties: { \"pattern\": schema } → use the first pattern's schema as value type\n const patterns = Object.values(schema.patternProperties);\n if (patterns.length > 0) {\n valueType = schemaToTypeRef(patterns[0], contextName);\n }\n }\n return {\n kind: 'map',\n valueType,\n };\n }\n\n // Handle primitives\n const primitiveMap: Record<string, 'string' | 'integer' | 'number' | 'boolean'> = {\n string: 'string',\n integer: 'integer',\n number: 'number',\n boolean: 'boolean',\n };\n\n const typeStr = Array.isArray(schema.type) ? schema.type[0] : schema.type;\n if (typeStr && primitiveMap[typeStr]) {\n return {\n kind: 'primitive',\n type: primitiveMap[typeStr],\n ...(schema.format ? { format: schema.format } : {}),\n };\n }\n\n // Handle schemas with no type — if it has properties, treat as model\n if (!schema.type && schema.properties) {\n const baseName = toPascalCase(contextName ?? 'UnknownModel');\n return {\n kind: 'model',\n name: qualifyInlineModelName(baseName, parentModelName),\n };\n }\n\n // Empty schema {} → unknown\n if (\n !schema.type &&\n !schema.$ref &&\n !schema.oneOf &&\n !schema.anyOf &&\n !schema.allOf &&\n !schema.enum &&\n !schema.properties &&\n !schema.items\n ) {\n return { kind: 'primitive', type: 'unknown' };\n }\n\n // Fallback: treat unknown schemas as unknown\n if (contextName) {\n console.warn(`[oagen] Warning: Unknown schema shape treated as unknown (context: ${contextName})`);\n }\n return { kind: 'primitive', type: 'unknown' };\n}\n\nimport { qualifyInlineModelName } from './inline-models.js';\n\nexport { qualifyInlineModelName, extractInlineModelsFromSchemas } from './inline-models.js';\n","import type { TypeRef, Parameter, PaginationMeta } from '../ir/types.js';\n\nconst CURSOR_PARAMS = ['cursor', 'after', 'before', 'starting_after', 'ending_before', 'page_token', 'next_token'];\n\nconst OFFSET_PARAMS = ['offset', 'page', 'page_number', 'skip'];\nconst LIMIT_PARAMS = ['limit', 'page_size', 'per_page', 'size', 'count'];\n\n/**\n * Detect if an operation uses pagination and return structured metadata\n * for auto-paging iterator generation.\n *\n * Supports two strategies:\n * 1. **Cursor-based**: query params include a cursor-like parameter\n * 2. **Offset-based**: query params include both an offset-like and limit-like parameter\n *\n * Returns null if no pagination pattern is detected.\n */\nexport function detectPagination(\n response: TypeRef,\n queryParams: Parameter[],\n dataPath?: string,\n): PaginationMeta | null {\n // Try cursor-based first (preferred)\n const cursorParam = queryParams.find((p) => CURSOR_PARAMS.includes(p.name));\n\n if (cursorParam) {\n const itemType: TypeRef = response.kind === 'array' ? response.items : response;\n return {\n strategy: 'cursor',\n param: cursorParam.name,\n dataPath: dataPath,\n itemType,\n };\n }\n\n // Try offset-based pagination\n const offsetParam = queryParams.find((p) => OFFSET_PARAMS.includes(p.name));\n const limitParam = queryParams.find((p) => LIMIT_PARAMS.includes(p.name));\n\n if (offsetParam && limitParam) {\n const itemType: TypeRef = response.kind === 'array' ? response.items : response;\n return {\n strategy: 'offset',\n param: offsetParam.name,\n limitParam: limitParam.name,\n dataPath: dataPath,\n itemType,\n };\n }\n\n return null;\n}\n","import type { TypeRef, Model, Field } from '../ir/types.js';\nimport { toPascalCase, singularize, stripListItemMarkers } from '../utils/naming.js';\nimport type { SchemaObject } from './schemas.js';\nimport { schemaToTypeRef, buildFieldFromSchema } from './schemas.js';\n\nexport interface ResponseExtractionResult {\n /** The TypeRef to use as the operation's response type */\n response: TypeRef;\n /** Any inline models discovered during extraction (to merge into ir.models) */\n inlineModels: Model[];\n /** Whether this response indicates a paginated list */\n isPaginated: boolean;\n /** Path to the data array within the response envelope (e.g., 'data') */\n dataPath?: string;\n /** TypeRef of individual items in a paginated list */\n itemType?: TypeRef;\n}\n\nexport function classifyAndExtractResponse(schema: SchemaObject, contextName: string): ResponseExtractionResult {\n // 1. If schema is a $ref, resolve to model name (Phase 1)\n if (schema.$ref) {\n return { response: schemaToTypeRef(schema, contextName), inlineModels: [], isPaginated: false };\n }\n\n // 2. Check for list envelope (structural detection: array prop + non-array companion)\n const envelope = detectListEnvelope(schema);\n if (envelope.isEnvelope) {\n return extractListResponse(schema, contextName, envelope.dataPath!);\n }\n\n // 3. Check for single-resource wrapper ({ resource_name: { object: \"...\", ... } })\n if (isSingleResourceWrapper(schema)) {\n return extractWrappedResource(schema, contextName);\n }\n\n // 4. Direct resource or plain inline object\n return extractDirectResource(schema, contextName);\n}\n\ninterface ListEnvelopeResult {\n isEnvelope: boolean;\n dataPath: string | null;\n}\n\nconst KNOWN_DATA_PATHS = new Set(['data', 'items', 'results', 'records', 'entries', 'values', 'nodes', 'edges']);\n\nconst PAGINATION_METADATA_PATTERNS = [\n 'metadata',\n 'pagination',\n 'cursor',\n 'has_more',\n 'page_info',\n 'total',\n 'next_page',\n 'previous_page',\n 'offset',\n];\n\nfunction detectListEnvelope(schema: SchemaObject): ListEnvelopeResult {\n // Collect all property sources (allOf sub-schemas or flat schema)\n const propSources: Record<string, SchemaObject | undefined>[] = [];\n if (schema.allOf) {\n for (const sub of schema.allOf) {\n if (sub.properties) propSources.push(sub.properties);\n }\n }\n if (schema.properties) {\n propSources.push(schema.properties);\n }\n\n if (propSources.length === 0) return { isEnvelope: false, dataPath: null };\n\n // Merge all properties into a single view\n const mergedProps: Record<string, SchemaObject | undefined> = {};\n for (const source of propSources) {\n Object.assign(mergedProps, source);\n }\n\n // Find array-typed properties and non-array companion properties\n const arrayProps: string[] = [];\n const nonArrayKeys: string[] = [];\n\n for (const [key, propSchema] of Object.entries(mergedProps)) {\n if (!propSchema) continue;\n if (propSchema.type === 'array') {\n arrayProps.push(key);\n } else {\n nonArrayKeys.push(key);\n }\n }\n\n // List envelope heuristic: exactly one array property + at least one non-array companion\n if (arrayProps.length === 1 && nonArrayKeys.length >= 1) {\n const arrayPropName = arrayProps[0];\n\n // The array property must be a known data path...\n if (KNOWN_DATA_PATHS.has(arrayPropName)) {\n return { isEnvelope: true, dataPath: arrayPropName };\n }\n\n // ...OR a companion property must look like pagination metadata\n const hasPaginationCompanion = nonArrayKeys.some((key) =>\n PAGINATION_METADATA_PATTERNS.some((pattern) => key.toLowerCase().includes(pattern)),\n );\n if (hasPaginationCompanion) {\n return { isEnvelope: true, dataPath: arrayPropName };\n }\n }\n\n return { isEnvelope: false, dataPath: null };\n}\n\nfunction extractListResponse(schema: SchemaObject, contextName: string, dataPath: string): ResponseExtractionResult {\n let itemTypeRef: TypeRef = { kind: 'primitive', type: 'string' };\n const inlineModels: Model[] = [];\n\n // Collect all property sources (allOf sub-schemas or flat schema)\n const propSources: Record<string, SchemaObject | undefined>[] = [];\n if (schema.allOf) {\n for (const sub of schema.allOf) {\n if (sub.properties) propSources.push(sub.properties);\n }\n }\n if (schema.properties) {\n propSources.push(schema.properties);\n }\n\n for (const props of propSources) {\n const dataProp = props[dataPath];\n if (!dataProp) continue;\n\n if (dataProp.type === 'array' && dataProp.items) {\n const items = dataProp.items;\n if (items.$ref) {\n itemTypeRef = schemaToTypeRef(items, contextName);\n } else if (items.type === 'object' && items.properties) {\n const itemName = contextName.replace(/Response$/, '') + 'Item';\n itemTypeRef = { kind: 'model', name: itemName };\n inlineModels.push(...extractInlineModel(itemName, items));\n }\n }\n }\n\n return {\n response: { kind: 'array', items: itemTypeRef },\n inlineModels,\n isPaginated: true,\n dataPath,\n itemType: itemTypeRef,\n };\n}\n\nfunction hasDiscriminantConstField(schema: SchemaObject): { property: string; value: string } | null {\n if (!schema.properties) return null;\n\n // Prefer well-known discriminant properties for backward compatibility\n const preferred = ['object', 'type'];\n for (const name of preferred) {\n const field = schema.properties[name];\n if (!field) continue;\n if (field.const !== undefined && typeof field.const === 'string') {\n return { property: name, value: field.const };\n }\n if (field.enum && field.enum.length === 1 && typeof field.enum[0] === 'string') {\n return { property: name, value: field.enum[0] };\n }\n }\n\n // Fall back to any property with a const or single-value enum\n for (const [name, field] of Object.entries(schema.properties)) {\n if (!field) continue;\n if (field.const !== undefined && typeof field.const === 'string') {\n return { property: name, value: field.const };\n }\n if (field.enum && field.enum.length === 1 && typeof field.enum[0] === 'string') {\n return { property: name, value: field.enum[0] };\n }\n }\n\n return null;\n}\n\nfunction isSingleResourceWrapper(schema: SchemaObject): boolean {\n if (schema.type !== 'object') return false;\n if (!schema.properties) return false;\n\n // Find the wrapper property: use required[0] if available, or the single property key\n let wrapperKey: string | undefined;\n if (schema.required && schema.required.length === 1) {\n wrapperKey = schema.required[0];\n } else {\n const propKeys = Object.keys(schema.properties);\n if (propKeys.length === 1) {\n wrapperKey = propKeys[0];\n }\n }\n if (!wrapperKey) return false;\n\n const propSchema = schema.properties[wrapperKey];\n if (!propSchema) return false;\n\n // Direct object with a discriminant const field\n if (propSchema.type === 'object' && hasDiscriminantConstField(propSchema) !== null) return true;\n\n // oneOf with object + null (nullable resource)\n if (propSchema.oneOf) {\n return propSchema.oneOf.some((v) => v.type === 'object' && hasDiscriminantConstField(v) !== null);\n }\n\n return false;\n}\n\nfunction extractWrappedResource(schema: SchemaObject, contextName: string): ResponseExtractionResult {\n const props = schema.properties!;\n const wrapperKey = schema.required && schema.required.length === 1 ? schema.required[0] : Object.keys(props)[0];\n const propSchema = props[wrapperKey]!;\n const inlineModels: Model[] = [];\n\n // Derive model name from the object const value or wrapper property name\n const resourceName = contextName.replace(/Response$/, '');\n\n if (propSchema.oneOf) {\n const objectVariant = propSchema.oneOf.find((v) => v.type === 'object' && hasDiscriminantConstField(v) !== null);\n\n if (objectVariant) {\n const modelName = deriveModelName(objectVariant, resourceName);\n inlineModels.push(...extractInlineModel(modelName, objectVariant));\n\n const hasNullVariant = propSchema.oneOf.some(\n (v) => v.type === 'null' || (Array.isArray(v.type) && v.type.includes('null')),\n );\n\n const modelRef: TypeRef = { kind: 'model', name: modelName };\n return {\n response: hasNullVariant ? { kind: 'nullable', inner: modelRef } : modelRef,\n inlineModels,\n isPaginated: false,\n };\n }\n }\n\n // Direct object\n const modelName = deriveModelName(propSchema, resourceName);\n inlineModels.push(...extractInlineModel(modelName, propSchema));\n\n return {\n response: { kind: 'model', name: modelName },\n inlineModels,\n isPaginated: false,\n };\n}\n\nfunction extractDirectResource(schema: SchemaObject, contextName: string): ResponseExtractionResult {\n const inlineModels: Model[] = [];\n\n // Direct object with properties (with or without explicit type: 'object')\n if (schema.properties && (schema.type === 'object' || !schema.type)) {\n const modelName = deriveModelName(schema, contextName);\n inlineModels.push(...extractInlineModel(modelName, schema));\n return {\n response: { kind: 'model', name: modelName },\n inlineModels,\n isPaginated: false,\n };\n }\n\n // allOf with properties — merge into a single model\n if (schema.allOf) {\n const mergedProperties: Record<string, SchemaObject | undefined> = {};\n const mergedRequired: string[] = [];\n for (const sub of schema.allOf) {\n if (sub.properties) {\n Object.assign(mergedProperties, sub.properties);\n }\n if (sub.required) {\n mergedRequired.push(...sub.required);\n }\n }\n if (Object.keys(mergedProperties).length > 0) {\n const merged: SchemaObject = { type: 'object', properties: mergedProperties, required: mergedRequired };\n const modelName = deriveModelName(merged, contextName);\n inlineModels.push(...extractInlineModel(modelName, merged));\n return {\n response: { kind: 'model', name: modelName },\n inlineModels,\n isPaginated: false,\n };\n }\n }\n\n // oneOf — delegate to schemaToTypeRef (returns union) but also extract inline models\n // from object variants so the model refs resolve\n if (schema.oneOf) {\n for (const variant of schema.oneOf) {\n if (variant.properties && (variant.type === 'object' || !variant.type)) {\n const modelName = deriveModelName(variant, contextName);\n const existingNames = new Set(inlineModels.map((m) => m.name));\n if (!existingNames.has(modelName)) {\n inlineModels.push(...extractInlineModel(modelName, variant));\n }\n }\n }\n }\n\n // Array with inline object items — extract the item model\n if (schema.type === 'array' && schema.items) {\n const items = schema.items;\n if (items.$ref) {\n return {\n response: { kind: 'array', items: schemaToTypeRef(items, contextName) },\n inlineModels,\n isPaginated: false,\n };\n }\n if (items.properties && (items.type === 'object' || !items.type)) {\n const itemName = contextName.replace(/Response$/, '') + 'Item';\n inlineModels.push(...extractInlineModel(itemName, items));\n return {\n response: { kind: 'array', items: { kind: 'model', name: itemName } },\n inlineModels,\n isPaginated: false,\n };\n }\n }\n\n // Non-object schema (primitive, union, etc.) — delegate to schemaToTypeRef\n return {\n response: schemaToTypeRef(schema, contextName),\n inlineModels,\n isPaginated: false,\n };\n}\n\nfunction deriveModelName(schema: SchemaObject, fallback: string): string {\n if (!schema.properties) return toPascalCase(fallback);\n\n // Prefer well-known discriminant properties for backward compatibility\n const preferred = ['object', 'type'];\n for (const name of preferred) {\n const field = schema.properties[name];\n if (field && field.const && typeof field.const === 'string') {\n return toPascalCase(field.const);\n }\n }\n\n // Fall back to any property with a const string value\n for (const [, field] of Object.entries(schema.properties)) {\n if (field && field.const && typeof field.const === 'string') {\n return toPascalCase(field.const);\n }\n }\n\n return toPascalCase(fallback);\n}\n\n/**\n * Qualify a nested inline model name with its parent to avoid generic names.\n * e.g., parent=\"Connection\" + field=\"domains\" → \"ConnectionDomain\" (singularized)\n * Only qualifies when the field name alone would be too generic.\n */\nfunction qualifyNestedName(parentName: string, fieldName: string): string {\n const pascalField = toPascalCase(fieldName);\n // If the field name already starts with the parent name, don't double-prefix\n if (pascalField.startsWith(parentName)) return pascalField;\n // Qualify with parent and singularize:\n // Connection + Domains → ConnectionDomains → singularize lead word → ConnectionDomain\n const cleanParent = stripListItemMarkers(parentName);\n const qualified = `${cleanParent}${pascalField}`;\n // Singularize the trailing word: ConnectionDomains → ConnectionDomain\n const match = qualified.match(/^(.+?)([A-Z][a-z]+s?)$/);\n if (match && match[2]) {\n const trailing = singularize(match[2]);\n return match[1] + trailing;\n }\n return qualified;\n}\n\nfunction extractInlineModel(name: string, schema: SchemaObject): Model[] {\n const requiredSet = new Set(schema.required ?? []);\n const fields: Field[] = [];\n const properties = schema.properties ?? {};\n const nestedModels: Model[] = [];\n\n for (const [fieldName, fieldSchema] of Object.entries(properties)) {\n if (!fieldSchema) continue;\n fields.push(buildFieldFromSchema(fieldName, fieldSchema, name, requiredSet));\n\n // Recursively extract nested inline objects — qualify with parent name\n // to avoid generic names like \"Domains\" when multiple parents have a \"domains\" field\n if (fieldSchema.type === 'object' && fieldSchema.properties) {\n const nestedName = qualifyNestedName(name, fieldName);\n nestedModels.push(...extractInlineModel(nestedName, fieldSchema));\n }\n if (fieldSchema.type === 'array' && fieldSchema.items) {\n const items = fieldSchema.items;\n if (items.type === 'object' && items.properties) {\n const nestedName = qualifyNestedName(name, fieldName);\n nestedModels.push(...extractInlineModel(nestedName, items));\n }\n }\n // Handle allOf with inline object properties — merge into a single nested model\n if (fieldSchema.allOf) {\n const mergedProperties: Record<string, SchemaObject | undefined> = {};\n const mergedRequired: string[] = [];\n for (const sub of fieldSchema.allOf) {\n if (sub.properties) Object.assign(mergedProperties, sub.properties);\n if (sub.required) mergedRequired.push(...sub.required);\n }\n if (Object.keys(mergedProperties).length > 0) {\n const nestedName = qualifyNestedName(name, fieldName);\n const merged: SchemaObject = { type: 'object', properties: mergedProperties, required: mergedRequired };\n const existingNames = new Set(nestedModels.map((m) => m.name));\n if (!existingNames.has(nestedName)) {\n nestedModels.push(...extractInlineModel(nestedName, merged));\n }\n }\n }\n // Handle oneOf containing inline objects — extract the first non-null object variant\n if (fieldSchema.oneOf) {\n const objectVariant = fieldSchema.oneOf.find((v) => v.properties && (v.type === 'object' || !v.type));\n if (objectVariant) {\n const nestedName = qualifyNestedName(name, fieldName);\n const existingNames = new Set(nestedModels.map((m) => m.name));\n if (!existingNames.has(nestedName)) {\n nestedModels.push(...extractInlineModel(nestedName, objectVariant));\n }\n }\n }\n }\n\n return [{ name, description: schema.description, fields }, ...nestedModels];\n}\n","import type {\n Service,\n Operation,\n HttpMethod,\n Parameter,\n TypeRef,\n ErrorResponse,\n SuccessResponse,\n Model,\n Field,\n PaginationMeta,\n} from '../ir/types.js';\nimport { toPascalCase, toCamelCase, cleanSchemaName } from '../utils/naming.js';\nimport type { SchemaObject } from './schemas.js';\nimport { schemaToTypeRef, buildFieldFromSchema } from './schemas.js';\nimport { detectPagination } from './pagination.js';\nimport { classifyAndExtractResponse } from './responses.js';\n\ninterface PathItem {\n get?: OperationObject;\n post?: OperationObject;\n put?: OperationObject;\n patch?: OperationObject;\n delete?: OperationObject;\n head?: OperationObject;\n options?: OperationObject;\n trace?: OperationObject;\n parameters?: ParameterObject[];\n}\n\ninterface OperationObject {\n operationId?: string;\n summary?: string;\n description?: string;\n tags?: string[];\n parameters?: ParameterObject[];\n requestBody?: RequestBodyObject;\n responses?: Record<string, ResponseObject>;\n deprecated?: boolean;\n 'x-oagen-async'?: boolean;\n}\n\ninterface ParameterObject {\n name: string;\n in: 'path' | 'query' | 'header' | 'cookie';\n required?: boolean;\n description?: string;\n schema?: SchemaObject;\n deprecated?: boolean;\n example?: unknown;\n}\n\ninterface RequestBodyObject {\n required?: boolean;\n content?: Record<string, { schema?: SchemaObject }>;\n}\n\ninterface ResponseObject {\n description?: string;\n content?: Record<string, { schema?: SchemaObject }>;\n}\n\nconst HTTP_METHODS: HttpMethod[] = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace'];\n\nexport interface OperationExtractionResult {\n services: Service[];\n inlineModels: Model[];\n}\n\nexport function extractOperations(\n paths: Record<string, PathItem> | undefined,\n operationIdTransform?: (id: string) => string,\n): OperationExtractionResult {\n if (!paths) return { services: [], inlineModels: [] };\n\n const serviceMap = new Map<string, Operation[]>();\n const inlineModels: Model[] = [];\n\n for (const [path, pathItem] of Object.entries(paths)) {\n const pathLevelParams = pathItem.parameters ?? [];\n\n for (const method of HTTP_METHODS) {\n const op = pathItem[method];\n if (!op) continue;\n\n const serviceName = inferServiceName(path, op.tags?.[0]);\n\n const { operation, inlineModels: opModels } = buildOperation(\n method,\n path,\n op,\n pathLevelParams,\n operationIdTransform,\n );\n inlineModels.push(...opModels);\n const ops = serviceMap.get(serviceName) ?? [];\n ops.push(operation);\n serviceMap.set(serviceName, ops);\n }\n }\n\n // Disambiguate operation names within each service.\n // Multiple operations can get the same name (e.g., several \"list\" endpoints\n // in UserManagement for users, invitations, auth factors, etc.).\n for (const [, operations] of serviceMap) {\n disambiguateOperationNames(operations);\n }\n\n const services = Array.from(serviceMap.entries()).map(([name, operations]) => ({\n name,\n operations,\n }));\n\n return { services, inlineModels };\n}\n\nfunction inferServiceName(path: string, tag?: string): string {\n // Prefer OpenAPI tag when available — tags represent the logical grouping\n // (e.g., \"multi-factor-auth\" for /auth/factors/* endpoints).\n if (tag) {\n return toPascalCase(tag);\n }\n // Fallback: extract first meaningful path segment: /widgets/{id}/sub → \"Widgets\"\n const segments = path.split('/').filter(Boolean);\n const first = segments[0] ?? 'Default';\n // Skip path params\n if (first.startsWith('{')) return 'Default';\n return toPascalCase(first);\n}\n\nfunction inferOperationName(\n method: HttpMethod,\n path: string,\n operationId?: string,\n operationIdTransform?: (id: string) => string,\n): string {\n if (operationId) {\n if (operationIdTransform) {\n return operationIdTransform(operationId);\n }\n return toCamelCase(operationId);\n }\n\n // Fallback when no operationId is available — use method + path to build\n // a descriptive name like \"listUsers\", \"getOrganization\", \"deleteAuthFactor\"\n const verb = inferVerb(method, path);\n const resource = inferResourceFromPath(path);\n return resource ? toCamelCase(`${verb}_${resource}`) : verb;\n}\n\n/**\n * Infer the CRUD verb from HTTP method and path shape.\n */\nfunction inferVerb(method: HttpMethod, path: string): string {\n const segments = path.split('/').filter(Boolean);\n const hasTrailingParam = segments.length > 0 && segments[segments.length - 1].startsWith('{');\n\n switch (method) {\n case 'get':\n return hasTrailingParam ? 'get' : 'list';\n case 'post':\n return 'create';\n case 'put':\n case 'patch':\n return 'update';\n case 'delete':\n return 'delete';\n case 'head':\n return 'check';\n case 'options':\n return 'options';\n case 'trace':\n return 'trace';\n default:\n return method;\n }\n}\n\n/**\n * Extract a resource noun from the path for operation naming.\n * Uses the last non-param segment (the resource being operated on).\n *\n * Examples:\n * /user_management/users → \"Users\"\n * /user_management/users/{id} → \"User\" (singular for item operations)\n * /user_management/users/{id}/auth_factors → \"AuthFactors\"\n * /organizations/{id}/api_keys → \"ApiKeys\"\n * /sso/authorize → \"Authorize\" (action endpoint)\n */\nfunction inferResourceFromPath(path: string): string | null {\n const segments = path.split('/').filter(Boolean);\n if (segments.length <= 1) return null;\n\n // Find the last meaningful (non-param) segment\n let resourceSegment: string | null = null;\n for (let i = segments.length - 1; i >= 0; i--) {\n if (!segments[i].startsWith('{')) {\n resourceSegment = segments[i];\n break;\n }\n }\n\n if (!resourceSegment) return null;\n // Skip the service name (first segment) — it would be redundant\n if (resourceSegment === segments[0]) return null;\n\n return toPascalCase(resourceSegment);\n}\n\n/**\n * Detect and resolve name collisions within a service's operations.\n *\n * When multiple operations share the same name (e.g., several \"list\" from\n * different sub-resources), disambiguate by appending the resource noun\n * from the path. Only renames operations on DIFFERENT paths — same-name\n * operations on the same path (e.g., PUT + PATCH both \"update\") are left as-is\n * since they represent the same logical resource.\n */\nfunction disambiguateOperationNames(operations: Operation[]): void {\n // Group by name\n const byName = new Map<string, Operation[]>();\n for (const op of operations) {\n const group = byName.get(op.name) ?? [];\n group.push(op);\n byName.set(op.name, group);\n }\n\n for (const [name, group] of byName) {\n if (group.length <= 1) continue;\n\n // Check if these are genuinely different resources (different paths)\n // vs the same resource with different methods (PUT + PATCH)\n const uniquePaths = new Set(group.map((op) => op.path));\n if (uniquePaths.size <= 1) continue; // same path, different methods — no disambiguation needed\n\n for (const op of group) {\n const resource = inferResourceFromPath(op.path);\n if (resource) {\n const newName = toCamelCase(`${name}_${resource}`);\n (op as { name: string }).name = newName;\n }\n }\n\n // If disambiguation still left collisions (same sub-resource),\n // use the full distinguishing path segment chain\n const renamed = new Map<string, Operation[]>();\n for (const op of group) {\n const rGroup = renamed.get(op.name) ?? [];\n rGroup.push(op);\n renamed.set(op.name, rGroup);\n }\n for (const [, rGroup] of renamed) {\n if (rGroup.length <= 1) continue;\n // Still colliding — different paths map to same resource name.\n // Use deeper path context to disambiguate.\n for (const op of rGroup) {\n const deeper = inferDeeperContext(op.path);\n if (deeper) {\n (op as { name: string }).name = toCamelCase(`${op.name}_${deeper}`);\n }\n }\n }\n }\n}\n\n/**\n * Extract a deeper disambiguation context from the path when the last\n * segment isn't unique enough. Uses the second-to-last non-param segment.\n *\n * /users/{id}/auth_factors → already captured as \"AuthFactors\"\n * /users/external_id/{external_id} → \"ExternalId\" (special path, not a sub-resource)\n */\nfunction inferDeeperContext(path: string): string | null {\n const segments = path.split('/').filter(Boolean);\n const nonParams = segments.filter((s) => !s.startsWith('{'));\n // Skip first (service) and last (already used) — use the middle ones\n if (nonParams.length >= 3) {\n return toPascalCase(nonParams.slice(1, -1).join('_'));\n }\n return null;\n}\n\nfunction buildOperation(\n method: HttpMethod,\n path: string,\n op: OperationObject,\n pathLevelParams: ParameterObject[],\n operationIdTransform?: (id: string) => string,\n): { operation: Operation; inlineModels: Model[] } {\n const allParams = [...pathLevelParams, ...(op.parameters ?? [])];\n\n const hasIdempotencyHeader = allParams.some((p) => p.in === 'header' && p.name.toLowerCase() === 'idempotency-key');\n\n const pathParams = extractParams(allParams, 'path');\n const queryParams = extractParams(allParams, 'query');\n const headerParams = extractParams(allParams, 'header').filter((p) => p.name.toLowerCase() !== 'idempotency-key');\n const cookieParams = extractParams(allParams, 'cookie');\n\n const reqBodyModels: Model[] = [];\n const { body: requestBody, encoding: requestBodyEncoding } = extractRequestBody(op.requestBody, op, reqBodyModels);\n const {\n response,\n successResponses,\n errors,\n inlineModels,\n isPaginated,\n dataPath: responseDataPath,\n itemType: responseItemType,\n } = extractResponses(op.responses, op, path, method);\n inlineModels.push(...reqBodyModels);\n\n // Build structured pagination metadata from response classification and query param detection\n const paginationFromParams = detectPagination(response, queryParams, responseDataPath);\n let pagination: PaginationMeta | undefined;\n if (isPaginated) {\n const itemType = responseItemType ?? (response.kind === 'array' ? response.items : response);\n pagination = {\n strategy: paginationFromParams?.strategy ?? 'cursor',\n param: paginationFromParams?.param ?? 'after',\n limitParam: paginationFromParams?.limitParam,\n dataPath: responseDataPath ?? paginationFromParams?.dataPath,\n itemType,\n };\n } else if (paginationFromParams) {\n pagination = paginationFromParams;\n }\n\n return {\n operation: {\n name: inferOperationName(method, path, op.operationId, operationIdTransform),\n description: buildDescription(op.summary, op.description),\n httpMethod: method,\n path,\n pathParams,\n queryParams,\n headerParams,\n cookieParams: cookieParams.length > 0 ? cookieParams : undefined,\n requestBody,\n requestBodyEncoding,\n response,\n successResponses,\n errors,\n pagination,\n injectIdempotencyKey: hasIdempotencyHeader,\n deprecated: op.deprecated || undefined,\n async: op['x-oagen-async'],\n },\n inlineModels,\n };\n}\n\nfunction buildDescription(summary: string | undefined, description: string | undefined): string | undefined {\n if (summary && description && summary !== description) {\n return `${summary}\\n\\n${description}`;\n }\n return description ?? summary;\n}\n\nfunction extractParams(params: ParameterObject[], location: 'path' | 'query' | 'header' | 'cookie'): Parameter[] {\n return params\n .filter((p) => p.in === location)\n .map((p) => ({\n name: p.name,\n type: p.schema ? schemaToTypeRef(p.schema, p.name) : ({ kind: 'primitive', type: 'string' } as TypeRef),\n required: p.required ?? false,\n description: p.description,\n deprecated: p.deprecated || p.schema?.deprecated || undefined,\n default: p.schema?.default,\n example: p.example ?? p.schema?.example,\n }));\n}\n\nfunction extractRequestBody(\n body: RequestBodyObject | undefined,\n op: OperationObject | undefined,\n inlineModels: Model[],\n): { body?: TypeRef; encoding?: 'json' | 'form-data' | 'form-urlencoded' | 'binary' | 'text' } {\n if (!body?.content) return {};\n\n // Detect encoding and find schema from content type in priority order\n let encoding: 'json' | 'form-data' | 'form-urlencoded' | 'binary' | 'text' = 'json';\n let schema: SchemaObject | undefined;\n\n if (body.content['application/json']?.schema) {\n encoding = 'json';\n schema = body.content['application/json']!.schema;\n } else if (body.content['multipart/form-data']?.schema) {\n encoding = 'form-data';\n schema = body.content['multipart/form-data']!.schema;\n } else if (body.content['application/x-www-form-urlencoded']?.schema) {\n encoding = 'form-urlencoded';\n schema = body.content['application/x-www-form-urlencoded']!.schema;\n } else if (body.content['application/octet-stream']) {\n encoding = 'binary';\n schema = body.content['application/octet-stream']!.schema;\n } else if (body.content['text/plain']) {\n encoding = 'text';\n schema = body.content['text/plain']!.schema;\n }\n\n if (!schema) {\n // For binary/text, a schema is optional — produce a primitive TypeRef\n if (encoding === 'binary') {\n return { body: { kind: 'primitive', type: 'string', format: 'binary' }, encoding };\n }\n if (encoding === 'text') {\n return { body: { kind: 'primitive', type: 'string' }, encoding };\n }\n return {};\n }\n\n const rawName = op?.operationId ? toPascalCase(op.operationId) + 'Request' : 'RequestBody';\n const contextName = cleanSchemaName(rawName);\n\n // If the request body is an inline object with properties, extract it as a model\n if (schema.properties && (schema.type === 'object' || !schema.type)) {\n const requiredSet = new Set(schema.required ?? []);\n const fields: Field[] = [];\n for (const [fieldName, fieldSchema] of Object.entries(schema.properties)) {\n if (!fieldSchema) continue;\n fields.push(buildFieldFromSchema(fieldName, fieldSchema, contextName, requiredSet));\n }\n inlineModels.push({ name: contextName, description: undefined, fields });\n return { body: { kind: 'model', name: contextName }, encoding };\n }\n\n // If the request body is a oneOf, extract each variant as an inline model\n // and build a union type pointing to them by name.\n if (schema.oneOf) {\n const variants: TypeRef[] = [];\n\n for (const variant of schema.oneOf) {\n if (variant.$ref) {\n const ref = schemaToTypeRef(variant, contextName);\n variants.push(ref);\n } else if (variant.type === 'null') {\n // skip null variant in union, handle separately\n } else if (variant.properties && (variant.type === 'object' || !variant.type)) {\n const variantName = deriveOneOfVariantName(variant, contextName, inlineModels);\n const requiredSet = new Set(variant.required ?? []);\n const fields: Field[] = [];\n for (const [fieldName, fieldSchema] of Object.entries(variant.properties)) {\n if (!fieldSchema) continue;\n fields.push(buildFieldFromSchema(fieldName, fieldSchema, variantName, requiredSet));\n }\n inlineModels.push({ name: variantName, description: variant.description, fields });\n variants.push({ kind: 'model', name: variantName });\n } else {\n variants.push(schemaToTypeRef(variant, contextName));\n }\n }\n\n const hasNull = schema.oneOf.some(\n (v: SchemaObject) => v.type === 'null' || (Array.isArray(v.type) && v.type.includes('null')),\n );\n const union: TypeRef = {\n kind: 'union',\n variants,\n ...(schema.discriminator\n ? {\n discriminator: { property: schema.discriminator.propertyName, mapping: schema.discriminator.mapping ?? {} },\n }\n : {}),\n };\n const body = hasNull ? ({ kind: 'nullable', inner: union } as TypeRef) : union;\n return { body, encoding };\n }\n\n return { body: schemaToTypeRef(schema, contextName), encoding };\n}\n\n/** Derive a unique variant name for a oneOf inline model. */\nfunction deriveOneOfVariantName(variant: SchemaObject, baseName: string, existingModels: Model[]): string {\n // Try to use a distinguishing property (e.g., \"grant_type\" field's const/enum value)\n if (variant.properties) {\n for (const [, propSchema] of Object.entries(variant.properties)) {\n if (propSchema?.const && typeof propSchema.const === 'string') {\n return toPascalCase(propSchema.const) + baseName.replace(/Request$/, '') + 'Request';\n }\n }\n }\n // Fallback: append a numeric suffix\n const existingNames = new Set(existingModels.map((m) => m.name));\n let name = baseName;\n let suffix = 2;\n while (existingNames.has(name)) {\n name = `${baseName}${suffix}`;\n suffix++;\n }\n return name;\n}\n\nfunction deriveResponseName(op: OperationObject | undefined, path: string, method: HttpMethod): string {\n if (op?.operationId) {\n return cleanSchemaName(toPascalCase(op.operationId) + 'Response');\n }\n const segments = path.split('/').filter(Boolean);\n const resource = segments[0] ?? 'Unknown';\n return toPascalCase(resource) + toPascalCase(method) + 'Response';\n}\n\nfunction extractResponses(\n responses?: Record<string, ResponseObject>,\n op?: OperationObject,\n path?: string,\n method?: HttpMethod,\n): {\n response: TypeRef;\n successResponses?: SuccessResponse[];\n errors: ErrorResponse[];\n inlineModels: Model[];\n isPaginated: boolean;\n dataPath?: string;\n itemType?: TypeRef;\n} {\n const errors: ErrorResponse[] = [];\n let response: TypeRef = { kind: 'primitive', type: 'string' };\n let inlineModels: Model[] = [];\n let isPaginated = false;\n let dataPath: string | undefined;\n let itemType: TypeRef | undefined;\n\n if (!responses) return { response, errors, inlineModels, isPaginated };\n\n const allSuccessResponses: SuccessResponse[] = [];\n\n for (const [statusCode, resp] of Object.entries(responses)) {\n const code = parseInt(statusCode, 10);\n\n if (code >= 200 && code < 300) {\n let extractedType: TypeRef = { kind: 'primitive', type: 'unknown' };\n const jsonContent = resp.content?.['application/json'];\n if (jsonContent?.schema) {\n const contextName = deriveResponseName(op, path ?? '/', method ?? 'get');\n const result = classifyAndExtractResponse(jsonContent.schema, contextName);\n extractedType = result.response;\n // Keep track of inline models and pagination from the latest 2xx with a schema\n inlineModels = result.inlineModels;\n isPaginated = result.isPaginated;\n dataPath = result.dataPath;\n itemType = result.itemType;\n } else if (resp.content) {\n // Handle non-JSON response content types (text/plain, binary, XML, etc.)\n if (resp.content['application/octet-stream'] || resp.content['application/pdf']) {\n extractedType = { kind: 'primitive', type: 'string', format: 'binary' };\n } else if (\n resp.content['text/plain'] ||\n resp.content['text/html'] ||\n resp.content['text/xml'] ||\n resp.content['application/xml']\n ) {\n extractedType = { kind: 'primitive', type: 'string' };\n } else {\n // Try the first available content type's schema\n const firstKey = Object.keys(resp.content)[0];\n if (firstKey) {\n const firstContent = resp.content[firstKey];\n if (firstContent?.schema) {\n extractedType = schemaToTypeRef(\n firstContent.schema,\n deriveResponseName(op, path ?? '/', method ?? 'get'),\n );\n }\n }\n }\n }\n allSuccessResponses.push({ statusCode: code, type: extractedType });\n } else if (code >= 400) {\n const jsonContent = resp.content?.['application/json'];\n const type = jsonContent?.schema ? schemaToTypeRef(jsonContent.schema, `Error${code}`) : undefined;\n errors.push({ statusCode: code, type });\n }\n }\n\n // Primary response = lowest 2xx with a body schema, falling back to first 2xx\n if (allSuccessResponses.length > 0) {\n const sorted = [...allSuccessResponses].sort((a, b) => a.statusCode - b.statusCode);\n const primary =\n sorted.find((r) => r.type.kind !== 'primitive' || (r.type as { type: string }).type !== 'unknown') ?? sorted[0];\n response = primary.type;\n }\n\n const successResponses = allSuccessResponses.length > 1 ? allSuccessResponses : undefined;\n\n return { response, successResponses, errors, inlineModels, isPaginated, dataPath, itemType };\n}\n","import type { Model, Service, TypeRef } from '../ir/types.js';\nimport { walkTypeRef } from '../ir/types.js';\n\nfunction keepLargestByName(models: Model[]): Model[] {\n const byName = new Map<string, Model>();\n for (const model of models) {\n const existing = byName.get(model.name);\n if (!existing || model.fields.length > existing.fields.length) {\n byName.set(model.name, model);\n }\n }\n return [...byName.values()];\n}\n\nfunction rewriteModelRef(ref: TypeRef, oldName: string, newName: string): void {\n walkTypeRef(ref, {\n model: (r) => {\n if (r.name === oldName) (r as { name: string }).name = newName;\n },\n });\n}\n\nfunction rewriteModelRefs(models: Model[], services: Service[], oldName: string, newName: string): void {\n for (const model of models) {\n for (const field of model.fields) {\n rewriteModelRef(field.type, oldName, newName);\n }\n }\n for (const service of services) {\n for (const op of service.operations) {\n rewriteModelRef(op.response, oldName, newName);\n if (op.requestBody) {\n rewriteModelRef(op.requestBody, oldName, newName);\n }\n }\n }\n}\n\nexport function mergeInlineResponseModels(schemaModels: Model[], inlineModels: Model[]): Model[] {\n const mergedSchemaModels = [...schemaModels];\n const schemaModelNames = new Set(mergedSchemaModels.map((m) => m.name));\n const schemaModelsByName = new Map(mergedSchemaModels.map((m) => [m.name, m]));\n\n const deduplicatedInlineModels = inlineModels.filter((model) => {\n if (!schemaModelNames.has(model.name)) return true;\n\n const existing = schemaModelsByName.get(model.name)!;\n const existingFieldNames = new Set(existing.fields.map((f) => f.name));\n const inlineFieldNames = new Set(model.fields.map((f) => f.name));\n const hasDifference =\n model.fields.some((f) => !existingFieldNames.has(f.name)) ||\n existing.fields.some((f) => !inlineFieldNames.has(f.name));\n\n if (hasDifference && model.fields.length > existing.fields.length) {\n const idx = mergedSchemaModels.indexOf(existing);\n if (idx !== -1) mergedSchemaModels[idx] = model;\n schemaModelsByName.set(model.name, model);\n console.warn(\n `[oagen] Warning: Inline model \"${model.name}\" has more fields than component schema (${model.fields.length} vs ${existing.fields.length}) — using inline response model`,\n );\n } else if (hasDifference) {\n console.warn(\n `[oagen] Warning: Inline model \"${model.name}\" has different fields than component schema — using component schema`,\n );\n }\n\n return false;\n });\n\n return [...mergedSchemaModels, ...keepLargestByName(deduplicatedInlineModels)];\n}\n\nexport function mergeFieldInlineModels(existingModels: Model[], fieldInlineModels: Model[]): Model[] {\n const modelNames = new Set(existingModels.map((m) => m.name));\n const modelsByName = new Map(existingModels.map((m) => [m.name, m]));\n\n const deduplicatedFieldModels = fieldInlineModels.filter((model) => {\n if (!modelNames.has(model.name)) return true;\n\n const existing = modelsByName.get(model.name)!;\n const existingFieldNames = new Set(existing.fields.map((f) => f.name));\n const inlineFieldNames = new Set(model.fields.map((f) => f.name));\n const hasDifference =\n model.fields.some((f) => !existingFieldNames.has(f.name)) ||\n existing.fields.some((f) => !inlineFieldNames.has(f.name));\n\n if (hasDifference) {\n console.warn(\n `[oagen] Warning: Inline model \"${model.name}\" has different fields than component schema — using component schema`,\n );\n }\n\n return false;\n });\n\n return [...existingModels, ...keepLargestByName(deduplicatedFieldModels)];\n}\n\nfunction hasModelConstDiscriminant(model: Model): boolean {\n return model.fields.some(\n (f) => (f.name === 'object' || f.name === 'type') && f.type.kind === 'literal' && typeof f.type.value === 'string',\n );\n}\n\nfunction isModelReferencedByOthers(name: string, models: Model[], excludeNames: Set<string>): boolean {\n for (const model of models) {\n if (excludeNames.has(model.name)) continue;\n for (const field of model.fields) {\n let found = false;\n walkTypeRef(field.type, {\n model: (r) => {\n if (r.name === name) found = true;\n },\n });\n if (found) return true;\n }\n }\n return false;\n}\n\nexport function collapseJsonSuffixModels(models: Model[], services: Service[]): Model[] {\n const normalizedModels = [...models];\n const byName = new Map(normalizedModels.map((m) => [m.name, m]));\n\n // Pass 1: collect merge candidates\n const mergeCandidates: Array<{ jsonModel: Model; baseModel: Model }> = [];\n for (const model of normalizedModels) {\n if (!model.name.endsWith('Json')) continue;\n\n const baseName = model.name.slice(0, -4);\n const baseModel = byName.get(baseName);\n if (!baseModel || model.fields.length <= baseModel.fields.length) continue;\n\n const isSuperset = baseModel.fields.every((f) => model.fields.some((mf) => mf.name === f.name));\n if (!isSuperset) continue;\n\n // Guard: both models have a const discriminant — they are distinct entities\n if (hasModelConstDiscriminant(model) && hasModelConstDiscriminant(baseModel)) continue;\n\n // Guard: a third model explicitly references the Json-suffix model\n if (isModelReferencedByOthers(model.name, normalizedModels, new Set([model.name, baseName]))) continue;\n\n mergeCandidates.push({ jsonModel: model, baseModel });\n }\n\n // Pass 2: apply merges\n const toRemove = new Set<string>();\n for (const { jsonModel, baseModel } of mergeCandidates) {\n baseModel.fields = jsonModel.fields;\n toRemove.add(jsonModel.name);\n rewriteModelRefs(normalizedModels, services, jsonModel.name, baseModel.name);\n console.warn(\n `[oagen] Merged \"${jsonModel.name}\" into \"${baseModel.name}\" (${jsonModel.fields.length} fields, superset)`,\n );\n }\n\n return normalizedModels.filter((m) => !toRemove.has(m.name));\n}\n","import type { Enum, Model } from '../ir/types.js';\nimport { collectInlineEnumFromRef } from './schemas.js';\n\nexport function collectInlineEnumsFromModels(models: Model[], enums: Enum[]): void {\n const enumNames = new Set(enums.map((e) => e.name));\n for (const model of models) {\n for (const field of model.fields) {\n collectInlineEnumFromRef(field.type, enums, enumNames);\n }\n }\n}\n","import type { ApiSpec, TypeRef } from '../ir/types.js';\nimport { walkTypeRef } from '../ir/types.js';\n\nexport function validateModelRefs(spec: ApiSpec): void {\n const knownNames = new Set<string>();\n for (const m of spec.models) knownNames.add(m.name);\n for (const e of spec.enums) knownNames.add(e.name);\n\n function walkRef(ref: TypeRef, context: string): void {\n walkTypeRef(ref, {\n model: (r) => {\n if (!knownNames.has(r.name)) {\n console.warn(`[oagen] Warning: Unresolved model reference \"${r.name}\" (context: ${context})`);\n }\n },\n });\n }\n\n for (const model of spec.models) {\n for (const field of model.fields) {\n walkRef(field.type, `${model.name}.${field.name}`);\n }\n }\n\n for (const service of spec.services) {\n for (const op of service.operations) {\n for (const p of [...op.pathParams, ...op.queryParams, ...op.headerParams]) {\n walkRef(p.type, `${service.name}.${op.name}.${p.name}`);\n }\n if (op.requestBody) walkRef(op.requestBody, `${service.name}.${op.name}.requestBody`);\n walkRef(op.response, `${service.name}.${op.name}.response`);\n }\n }\n}\n","import type { ApiSpec, AuthScheme, ServerEntry } from '../ir/types.js';\nimport { SpecParseError } from '../errors.js';\nimport { loadAndBundleSpec } from './refs.js';\nimport { extractSchemas, extractInlineModelsFromSchemas } from './schemas.js';\nimport { extractOperations } from './operations.js';\nimport {\n mergeInlineResponseModels,\n collapseJsonSuffixModels,\n mergeFieldInlineModels,\n} from './normalize-inline-models.js';\nimport { collectInlineEnumsFromModels } from './collect-inline-enums.js';\nimport { validateModelRefs } from './normalize-model-refs.js';\n\nexport interface ParseOptions {\n operationIdTransform?: (id: string) => string;\n}\n\nexport async function parseSpec(specPath: string, options?: ParseOptions): Promise<ApiSpec> {\n const { parsed } = await loadAndBundleSpec(specPath);\n\n const spec = parsed as {\n openapi?: string;\n info?: { title?: string; version?: string; description?: string };\n servers?: Array<{ url?: string; description?: string }>;\n paths?: Record<string, unknown>;\n components?: {\n schemas?: Record<string, unknown>;\n securitySchemes?: Record<\n string,\n { type: string; scheme?: string; in?: string; name?: string; flows?: Record<string, unknown> }\n >;\n };\n };\n\n // Validate OpenAPI version\n const version = spec.openapi ?? '';\n if (!version.startsWith('3.')) {\n throw new SpecParseError(\n `Unsupported OpenAPI version: ${version}. oagen requires OpenAPI 3.x`,\n `Update the spec to OpenAPI 3.0 or 3.1. If you are using Swagger 2.x, convert it first with \\`npx swagger2openapi ${specPath}\\`.`,\n );\n }\n\n const { models, enums } = extractSchemas(\n spec.components?.schemas as Record<string, Record<string, unknown>> | undefined,\n );\n\n const { services, inlineModels } = extractOperations(\n spec.paths as Record<string, Record<string, unknown>> | undefined,\n options?.operationIdTransform,\n );\n\n const responseNormalizedModels = mergeInlineResponseModels(models, inlineModels);\n\n // Extract inline models from model field definitions (objects/arrays with properties)\n const fieldInlineModels = extractInlineModelsFromSchemas(\n spec.components?.schemas as Record<string, Record<string, unknown>> | undefined,\n );\n const fieldMergedModels = mergeFieldInlineModels(responseNormalizedModels, fieldInlineModels);\n const finalModels = collapseJsonSuffixModels(fieldMergedModels, services);\n collectInlineEnumsFromModels(finalModels, enums);\n\n const auth = extractAuthSchemes(spec.components?.securitySchemes);\n\n const serverEntries: ServerEntry[] = (spec.servers ?? [])\n .map((s) => ({ url: s.url ?? '', description: s.description }))\n .filter((s) => s.url);\n\n const result: ApiSpec = {\n name: spec.info?.title ?? 'Unknown API',\n version: spec.info?.version ?? '0.0.0',\n description: spec.info?.description,\n baseUrl: serverEntries[0]?.url ?? '',\n servers: serverEntries.length > 0 ? serverEntries : undefined,\n services,\n models: finalModels,\n enums,\n auth,\n };\n\n validateModelRefs(result);\n\n return result;\n}\n/** Extract authentication schemes from OpenAPI securitySchemes. */\nfunction extractAuthSchemes(\n securitySchemes?: Record<\n string,\n { type: string; scheme?: string; in?: string; name?: string; flows?: Record<string, unknown> }\n >,\n): AuthScheme[] | undefined {\n if (!securitySchemes) return undefined;\n const schemes: AuthScheme[] = [];\n for (const [, scheme] of Object.entries(securitySchemes)) {\n if (scheme.type === 'http' && scheme.scheme === 'bearer') {\n schemes.push({ kind: 'bearer' });\n } else if (scheme.type === 'apiKey' && scheme.in && scheme.name) {\n schemes.push({ kind: 'apiKey', in: scheme.in as 'header' | 'query' | 'cookie', name: scheme.name });\n } else if (scheme.type === 'oauth2' && scheme.flows) {\n schemes.push({ kind: 'oauth2', flows: scheme.flows });\n }\n }\n return schemes.length > 0 ? schemes : undefined;\n}\n","/**\n * Shared infrastructure for smoke tests.\n *\n * Types, operation planning, payload generation, ID registry, and capture format\n * used by both raw HTTP and SDK smoke test scripts.\n */\n\nimport 'dotenv/config';\nimport { readFileSync } from 'node:fs';\nimport type { ApiSpec, Operation, Parameter, TypeRef } from '../../src/ir/types.js';\nimport { toSnakeCase, toCamelCase } from '../../src/utils/naming.js';\n\n// Re-export types and functions that external smoke runners need from oagen core.\n// External runners import from '@workos/oagen/smoke' which bundles this module.\nexport { parseSpec } from '../../src/parser/parse.js';\nexport { toCamelCase, toSnakeCase } from '../../src/utils/naming.js';\n\n// ---------------------------------------------------------------------------\n// Capture format\n// ---------------------------------------------------------------------------\n\nexport interface ExchangeProvenance {\n resolutionTier: 'exact' | 'crud-prefix' | 'fuzzy' | 'manifest';\n resolutionConfidence: number;\n sdkMethodName: string;\n captureIndex: number;\n totalCaptures: number;\n}\n\nexport interface CapturedExchange {\n operationId: string;\n service: string;\n operationName: string;\n request: {\n method: string;\n path: string;\n queryParams: Record<string, string>;\n body: unknown | null;\n };\n response: {\n status: number;\n body: unknown | null;\n };\n outcome: 'success' | 'api-error' | 'skipped';\n error?: string;\n /** True when the response status code is not declared in the OpenAPI spec for this operation */\n unexpectedStatus?: boolean;\n /** Status codes declared in the OpenAPI spec (success + error codes) */\n expectedStatusCodes?: number[];\n durationMs: number;\n /** How the SDK method was resolved and which capture was selected */\n provenance?: ExchangeProvenance;\n}\n\nexport interface SmokeResults {\n source: 'raw' | 'spec-baseline' | `sdk-${string}`;\n timestamp: string;\n specVersion: string;\n exchanges: CapturedExchange[];\n}\n\n// ---------------------------------------------------------------------------\n// Operation planning\n// ---------------------------------------------------------------------------\n\nexport interface PlannedOperation {\n service: string;\n operation: Operation;\n}\n\nexport interface PlannedGroup {\n service: string;\n operations: PlannedOperation[];\n}\n\n// ---------------------------------------------------------------------------\n// Smoke config — mutable state populated by loadSmokeConfig()\n// ---------------------------------------------------------------------------\n\n/** Operations that require complex preconditions and can't be auto-tested */\nexport let SKIP_OPERATIONS = new Set<string>();\n\n/** Services to skip entirely */\nexport let SKIP_SERVICES = new Set<string>();\n\n/**\n * Services that produce IDs other services depend on should run first.\n * Lower number = runs earlier. Unlisted services default to 50.\n */\nlet SERVICE_PRIORITY: Record<string, number> = {};\n\n/**\n * Map IR service names to SDK property names on the client object.\n * Empty = use toCamelCase(serviceName) as fallback.\n */\nexport let SERVICE_PROPERTY_MAP: Record<string, string> = {};\n\nexport interface SmokeConfig {\n skipOperations: string[];\n skipServices: string[];\n servicePriority: Record<string, number>;\n servicePropertyMap: Record<string, string>;\n}\n\n/** Load smoke test configuration from a JSON file */\nexport function loadSmokeConfig(configPath?: string): void {\n if (!configPath) return;\n const raw = readFileSync(configPath, 'utf-8');\n const config: SmokeConfig = JSON.parse(raw);\n\n if (config.skipOperations) SKIP_OPERATIONS = new Set(config.skipOperations);\n if (config.skipServices) SKIP_SERVICES = new Set(config.skipServices);\n if (config.servicePriority) SERVICE_PRIORITY = config.servicePriority;\n if (config.servicePropertyMap) SERVICE_PROPERTY_MAP = config.servicePropertyMap;\n}\n\n/** Return the current smoke config values (for diff.ts to consume) */\nexport function getSmokeConfig() {\n return {\n skipOperations: SKIP_OPERATIONS,\n skipServices: SKIP_SERVICES,\n servicePriority: SERVICE_PRIORITY,\n servicePropertyMap: SERVICE_PROPERTY_MAP,\n };\n}\n\n/**\n * Assign a numeric sort key to an operation so that ID-producing operations\n * (parameterless creates and lists) run before ID-consuming ones.\n */\nfunction operationSortKey(op: Operation): number {\n const hasParams = op.pathParams.length > 0;\n const method = op.httpMethod;\n\n if (method === 'post' && !hasParams) return 0; // top-level create\n if (method === 'get' && !hasParams && op.pagination) return 1; // top-level list\n if (method === 'get' && !hasParams) return 2; // top-level singular GET\n if (method === 'post' && hasParams) return 3; // sub-entity create\n if (method === 'get' && hasParams && op.pagination) return 4; // sub-entity list\n if (method === 'get' && hasParams) return 5; // singular GET by ID\n if (method === 'put' || method === 'patch') return 6; // update\n if (method === 'delete') return 7; // delete\n return 99;\n}\n\nexport function planOperations(spec: ApiSpec): PlannedGroup[] {\n const groups: PlannedGroup[] = [];\n\n for (const service of spec.services) {\n if (SKIP_SERVICES.has(service.name)) continue;\n\n const ops: PlannedOperation[] = [];\n for (const op of service.operations) {\n if (SKIP_OPERATIONS.has(op.name)) continue;\n\n ops.push({ service: service.name, operation: op });\n }\n\n if (ops.length === 0) continue;\n\n // Sort to maximize ID availability:\n // 1. Parameterless POSTs (create new top-level entities → produce IDs)\n // 2. Parameterless list GETs (discover existing IDs)\n // 3. Parameterized POSTs (create sub-entities, need parent IDs)\n // 4. Parameterized list GETs\n // 5. Parameterized singular GETs (retrieve by ID)\n // 6. PUT/PATCH (update)\n // 7. DELETE\n ops.sort((a, b) => {\n return operationSortKey(a.operation) - operationSortKey(b.operation);\n });\n\n groups.push({ service: service.name, operations: ops });\n }\n\n // Sort service groups so ID-producing services run first\n groups.sort((a, b) => {\n const aPri = SERVICE_PRIORITY[a.service] ?? 50;\n const bPri = SERVICE_PRIORITY[b.service] ?? 50;\n return aPri - bPri;\n });\n\n return groups;\n}\n\n// ---------------------------------------------------------------------------\n// Wave-based operation planning for batched runners\n// ---------------------------------------------------------------------------\n\n/**\n * A single wave of operations that can be planned and executed together.\n * Wave 0 contains parameterless operations. Subsequent waves contain\n * operations whose path params became resolvable after earlier waves ran.\n */\nexport interface OperationWave {\n /** Operations in this wave, with pre-resolved path params */\n calls: Array<{\n op: Operation;\n irService: string;\n pathParams: Record<string, string>;\n }>;\n}\n\n/**\n * Plan operations in waves so that batched runners can execute each wave,\n * extract IDs from responses, then plan the next wave.\n *\n * Returns an iterator that yields one wave at a time. The caller must\n * execute each wave and populate the IdRegistry before calling next().\n *\n * @param groups - service groups from planOperations()\n * @param ids - the IdRegistry (mutated by the caller between waves)\n * @param resolveMethod - optional filter; return null to skip an operation\n */\nexport function* planWaves(\n groups: PlannedGroup[],\n ids: IdRegistry,\n resolveMethod?: (op: Operation, irService: string) => boolean,\n): Generator<OperationWave, PlannedOperation[], void> {\n // Flatten all operations into a single ordered list\n const remaining: PlannedOperation[] = [];\n for (const group of groups) {\n for (const planned of group.operations) {\n remaining.push(planned);\n }\n }\n\n // Track which operations have been emitted\n const emitted = new Set<number>();\n const skipped: PlannedOperation[] = [];\n\n // Pre-filter: mark operations that fail the resolveMethod check as skipped\n for (let i = 0; i < remaining.length; i++) {\n const { operation: op, service: irService } = remaining[i];\n if (resolveMethod && !resolveMethod(op, irService)) {\n emitted.add(i);\n skipped.push(remaining[i]);\n }\n }\n\n // Wave 0: operations with no path params\n let wave: OperationWave = { calls: [] };\n for (let i = 0; i < remaining.length; i++) {\n if (emitted.has(i)) continue;\n const { operation: op, service: irService } = remaining[i];\n if (op.pathParams.length === 0) {\n wave.calls.push({ op, irService, pathParams: {} });\n emitted.add(i);\n }\n }\n\n if (wave.calls.length > 0) {\n yield wave;\n }\n\n // Subsequent waves: try to resolve remaining operations\n let madeProgress = true;\n while (madeProgress) {\n madeProgress = false;\n wave = { calls: [] };\n\n for (let i = 0; i < remaining.length; i++) {\n if (emitted.has(i)) continue;\n const { operation: op, service: irService } = remaining[i];\n\n const resolved = ids.resolvePathParams(op, irService);\n if (resolved) {\n wave.calls.push({ op, irService, pathParams: resolved });\n emitted.add(i);\n madeProgress = true;\n }\n }\n\n if (wave.calls.length > 0) {\n yield wave;\n }\n }\n\n // Collect truly unresolvable operations for the caller to mark as skipped\n const unresolved: PlannedOperation[] = [];\n for (let i = 0; i < remaining.length; i++) {\n if (!emitted.has(i)) {\n unresolved.push(remaining[i]);\n }\n }\n return unresolved;\n}\n\n// ---------------------------------------------------------------------------\n// Payload generation\n// ---------------------------------------------------------------------------\n\nexport function generateFixtureValue(typeRef: TypeRef, fieldName: string, spec: ApiSpec): unknown {\n switch (typeRef.kind) {\n case 'primitive':\n return generatePrimitiveFixture(typeRef.type, typeRef.format, fieldName);\n case 'array':\n return [generateFixtureValue(typeRef.items, fieldName, spec)];\n case 'model': {\n const model = spec.models.find((m) => m.name === typeRef.name);\n if (model) {\n const obj: Record<string, unknown> = {};\n for (const field of model.fields) {\n if (field.required) {\n obj[toSnakeCase(field.name)] = generateFixtureValue(field.type, field.name, spec);\n }\n }\n return obj;\n }\n return {};\n }\n case 'enum': {\n const e = spec.enums.find((en) => en.name === typeRef.name);\n return e?.values[0]?.value ?? 'unknown';\n }\n case 'nullable':\n return generateFixtureValue(typeRef.inner, fieldName, spec);\n case 'union':\n if (typeRef.variants.length > 0) {\n return generateFixtureValue(typeRef.variants[0], fieldName, spec);\n }\n return null;\n }\n}\n\nfunction generatePrimitiveFixture(type: string, format: string | undefined, fieldName: string): unknown {\n if (type === 'string') {\n if (format === 'uuid') return '550e8400-e29b-41d4-a716-446655440000';\n if (format === 'date') return '2024-01-01';\n if (format === 'date-time') return '2024-01-01T00:00:00Z';\n if (format === 'email') return 'test@example.com';\n if (format === 'uri' || format === 'url') return 'https://example.com';\n return `test_${toSnakeCase(fieldName)}`;\n }\n if (type === 'integer') return 1;\n if (type === 'number') return 1.0;\n if (type === 'boolean') return true;\n return null;\n}\n\n/** Generate a snake_case request body payload from an operation's requestBody type */\nexport function generatePayload(op: Operation, spec: ApiSpec): Record<string, unknown> | null {\n if (!op.requestBody) return null;\n\n const bodyType = op.requestBody;\n if (bodyType.kind === 'model') {\n const model = spec.models.find((m) => m.name === bodyType.name);\n if (!model) return {};\n\n const payload: Record<string, unknown> = {};\n for (const field of model.fields) {\n if (!field.required) continue;\n const key = toSnakeCase(field.name);\n let value = generateFixtureValue(field.type, field.name, spec);\n\n // Inject uniqueness markers for name/slug fields\n if ((key === 'name' || key === 'slug') && typeof value === 'string') {\n value = `smoke-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;\n }\n payload[key] = value;\n }\n return payload;\n }\n\n // Fallback for non-model body types\n return {};\n}\n\n/** Generate a fixture value with SDK-friendly types (e.g. Date objects for date-time) */\nfunction generateSDKFixtureValue(typeRef: TypeRef, fieldName: string, spec: ApiSpec): unknown {\n const value = generateFixtureValue(typeRef, fieldName, spec);\n // SDK methods expect Date objects for date-time fields, not ISO strings\n if (typeRef.kind === 'primitive' && typeRef.format === 'date-time' && typeof value === 'string') {\n return new Date(value);\n }\n return value;\n}\n\n/** Generate a camelCase payload for SDK method calls */\nexport function generateCamelPayload(op: Operation, spec: ApiSpec): Record<string, unknown> | null {\n if (!op.requestBody) return null;\n\n const bodyType = op.requestBody;\n if (bodyType.kind === 'model') {\n const model = spec.models.find((m) => m.name === bodyType.name);\n if (!model) return {};\n\n const payload: Record<string, unknown> = {};\n for (const field of model.fields) {\n if (!field.required) continue;\n const key = toCamelCase(field.name);\n let value = generateSDKFixtureValue(field.type, field.name, spec);\n\n if ((field.name === 'name' || field.name === 'slug') && typeof value === 'string') {\n value = `smoke-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;\n }\n payload[key] = value;\n }\n return payload;\n }\n\n return {};\n}\n\n/** Generate query params for an operation (required params only, plus limit=1 for lists) */\nexport function generateQueryParams(op: Operation, spec: ApiSpec): Record<string, string> {\n const params: Record<string, string> = {};\n\n if (op.pagination) {\n params['limit'] = '1';\n }\n\n for (const p of op.queryParams) {\n if (!p.required) continue;\n const value = generateFixtureValue(p.type, p.name, spec);\n params[toSnakeCase(p.name)] = String(value);\n }\n\n // Sort by key\n const sorted: Record<string, string> = {};\n for (const key of Object.keys(params).sort()) {\n sorted[key] = params[key];\n }\n return sorted;\n}\n\n/** Generate camelCase query params for SDK method calls */\nexport function generateCamelQueryParams(op: Operation, spec: ApiSpec): Record<string, unknown> {\n const params: Record<string, unknown> = {};\n\n if (op.pagination) {\n params['limit'] = 1;\n }\n\n for (const p of op.queryParams) {\n if (!p.required) continue;\n const value = generateFixtureValue(p.type, p.name, spec);\n params[toCamelCase(p.name)] = value;\n }\n\n return params;\n}\n\n// ---------------------------------------------------------------------------\n// ID Registry\n// ---------------------------------------------------------------------------\n\nexport class IdRegistry {\n private ids = new Map<string, string>();\n\n set(service: string, field: string, value: string): void {\n this.ids.set(`${service}.${field}`, value);\n }\n\n get(service: string, field: string): string | undefined {\n return this.ids.get(`${service}.${field}`);\n }\n\n /** Resolve path parameters for an operation using stored IDs */\n resolvePathParams(op: Operation, service: string): Record<string, string> | null {\n const resolved: Record<string, string> = {};\n for (const p of op.pathParams) {\n const value =\n this.get(service, p.name) ||\n this.get(service, 'id') ||\n this.findAcrossServices(p.name) ||\n this.resolveFromParamName(p.name) ||\n this.resolveFromExample(p);\n\n if (!value) return null;\n resolved[p.name] = value;\n }\n return resolved;\n }\n\n /** Try to find a param value across all services */\n private findAcrossServices(field: string): string | undefined {\n for (const [key, value] of this.ids.entries()) {\n if (key.endsWith(`.${field}`)) return value;\n }\n // Also try snake_case variant: \"organizationId\" → \"organization_id\"\n const snakeField = toSnakeCase(field);\n if (snakeField !== field) {\n for (const [key, value] of this.ids.entries()) {\n if (key.endsWith(`.${snakeField}`)) return value;\n }\n }\n return undefined;\n }\n\n /**\n * Resolve a path param like \"organizationId\" by mapping it to the\n * service that stores that entity's ID (e.g. Organizations.id).\n * Also handles snake_case suffixed with _id by stripping the suffix\n * and looking up the pluralized service name.\n */\n private resolveFromParamName(paramName: string): string | undefined {\n // Infer from param name: \"resource_id\" → \"Resources\", \"role_assignment_id\" → \"RoleAssignments\"\n // Handle snake_case: strip trailing _id, PascalCase+pluralize the rest\n if (paramName.endsWith('_id')) {\n const base = paramName.slice(0, -3); // e.g. \"resource_type\" from \"resource_type_id\"\n const pascal = base\n .split('_')\n .map((w) => w.charAt(0).toUpperCase() + w.slice(1))\n .join('');\n const plural = pascal.endsWith('s') ? pascal : pascal + 's';\n const val = this.get(plural, 'id') || this.get(plural, 'slug');\n if (val) return val;\n\n // Fallback: find any service whose name ends with the plural suffix\n // e.g. \"user_id\" → \"Users\" not found → try \"UserManagementUsers\"\n const suffixVal = this.findByServiceSuffix(plural, 'id') || this.findByServiceSuffix(plural, 'slug');\n if (suffixVal) return suffixVal;\n }\n\n // Handle camelCase: \"resourceId\" → strip \"Id\", pluralize → \"Resources\"\n if (paramName.endsWith('Id') && paramName.length > 2) {\n const base = paramName.slice(0, -2); // e.g. \"organization\"\n const pascal = base.charAt(0).toUpperCase() + base.slice(1);\n const plural = pascal.endsWith('s') ? pascal : pascal + 's';\n const val = this.get(plural, 'id') || this.get(plural, 'slug');\n if (val) return val;\n\n // Fallback: find any service whose name ends with the plural suffix\n const suffixVal = this.findByServiceSuffix(plural, 'id') || this.findByServiceSuffix(plural, 'slug');\n if (suffixVal) return suffixVal;\n }\n\n return undefined;\n }\n\n /**\n * Find a value by looking for any service name that ends with the given suffix.\n * e.g. suffix \"Users\" matches \"UserManagementUsers.id\"\n */\n private findByServiceSuffix(suffix: string, field: string): string | undefined {\n for (const [key, value] of this.ids.entries()) {\n if (key.endsWith(`.${field}`)) {\n const servicePart = key.slice(0, -(field.length + 1));\n if (servicePart.endsWith(suffix)) {\n return value;\n }\n }\n }\n return undefined;\n }\n\n /**\n * Last-resort fallback: use the spec's example or default value for a parameter.\n * Many path params (e.g. actionName, slug, type) have example values in the spec.\n */\n private resolveFromExample(param: Parameter): string | undefined {\n const value = param.example ?? param.default;\n if (value !== undefined && value !== null) {\n return String(value);\n }\n return undefined;\n }\n\n /**\n * Extract IDs from a response body and store them.\n * @param isTopLevel - true for operations without path params (their `id` belongs to this service).\n * false for sub-resource operations (their `id` is a child entity, don't overwrite).\n */\n extractAndStore(service: string, responseBody: unknown, isTopLevel = true): void {\n if (!responseBody || typeof responseBody !== 'object') return;\n\n const body = responseBody as Record<string, unknown>;\n\n // Only store direct ID from top-level operations to avoid overwriting\n // e.g. Organizations.id with an API key ID from /organizations/{id}/api_keys\n if (isTopLevel) {\n if (typeof body.id === 'string') {\n this.set(service, 'id', body.id);\n }\n\n // List response: extract from first item\n if (Array.isArray(body.data) && body.data.length > 0) {\n const first = body.data[0] as Record<string, unknown> | undefined;\n if (first && typeof first === 'object') {\n if (typeof first.id === 'string') {\n this.set(service, 'id', first.id);\n }\n this.extractNestedIds(service, first);\n }\n }\n\n if (typeof body.slug === 'string') this.set(service, 'slug', body.slug);\n if (typeof body.key === 'string') this.set(service, 'key', body.key);\n }\n\n // Always extract nested reference IDs (e.g. organization_id, connection_id)\n this.extractNestedIds(service, body);\n if (Array.isArray(body.data) && body.data.length > 0) {\n const first = body.data[0] as Record<string, unknown> | undefined;\n if (first && typeof first === 'object') {\n this.extractNestedIds(service, first);\n }\n }\n }\n\n /** Extract fields ending in _id or Id and store them for cross-service resolution */\n private extractNestedIds(service: string, obj: Record<string, unknown>): void {\n for (const [key, value] of Object.entries(obj)) {\n if (typeof value !== 'string') continue;\n if (key === 'id') continue; // already handled\n // Store fields like \"organization_id\", \"connection_id\" directly\n if (key.endsWith('_id') || (key.endsWith('Id') && key.length > 2)) {\n this.set(service, key, value);\n }\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Status code checking\n// ---------------------------------------------------------------------------\n\n/** Get the set of status codes declared in the spec for an operation (success + errors) */\nexport function getExpectedStatusCodes(op: Operation): number[] {\n const codes: number[] = [];\n // The success response code is implied by HTTP method if not explicit in errors\n // Common defaults: POST→201, GET→200, PUT→200, PATCH→200, DELETE→204\n const defaultSuccess: Record<string, number> = {\n post: 201,\n get: 200,\n put: 200,\n patch: 200,\n delete: 204,\n };\n codes.push(defaultSuccess[op.httpMethod] ?? 200);\n // Add declared error codes from the spec\n for (const err of op.errors) {\n if (!codes.includes(err.statusCode)) {\n codes.push(err.statusCode);\n }\n }\n return codes.sort((a, b) => a - b);\n}\n\n/** Check if a status code is unexpected (not declared in the spec) */\nexport function isUnexpectedStatus(status: number, op: Operation): boolean {\n if (status === 0) return false; // skipped or network error, not a status mismatch\n const expected = getExpectedStatusCodes(op);\n return !expected.includes(status);\n}\n\n// ---------------------------------------------------------------------------\n// Path resolution\n// ---------------------------------------------------------------------------\n\nexport function resolvePath(op: Operation, pathParams: Record<string, string>): string {\n let path = op.path;\n for (const [name, value] of Object.entries(pathParams)) {\n path = path.replace(`{${name}}`, value);\n }\n return path;\n}\n\n// ---------------------------------------------------------------------------\n// Utilities\n// ---------------------------------------------------------------------------\n\nexport function delay(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nexport function parseCliArgs(): { spec: string; sdkPath?: string; smokeConfig?: string } {\n const args = process.argv.slice(2);\n const specIdx = args.indexOf('--spec');\n const spec = specIdx !== -1 && args[specIdx + 1] ? args[specIdx + 1] : process.env.OPENAPI_SPEC_PATH;\n if (!spec) {\n console.error('OpenAPI spec path is required. Set OPENAPI_SPEC_PATH env var or pass --spec <path>.');\n process.exit(1);\n }\n const sdkPathIdx = args.indexOf('--sdk-path');\n const sdkPath = sdkPathIdx !== -1 && args[sdkPathIdx + 1] ? args[sdkPathIdx + 1] : undefined;\n const configIdx = args.indexOf('--smoke-config');\n const smokeConfig = configIdx !== -1 && args[configIdx + 1] ? args[configIdx + 1] : process.env.SMOKE_CONFIG;\n return { spec, sdkPath, smokeConfig };\n}\n"],"mappings":"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"}