@workos/oagen 0.9.2 → 0.10.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/index.mjs +81 -31
- package/dist/cli/index.mjs.map +1 -1
- package/dist/compat/index.mjs +1 -1
- package/dist/differ-CTl98yoS.d.mts.map +1 -1
- package/dist/{overlay-Bt6oz0dg.mjs → overlay-DWU6W29l.mjs} +39 -19
- package/dist/overlay-DWU6W29l.mjs.map +1 -0
- package/dist/verify/index.mjs +1 -1
- package/package.json +1 -1
- package/dist/overlay-Bt6oz0dg.mjs.map +0 -1
package/dist/cli/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":["singularize","singularize","singularize","singularize","extractDeclarationName","declarationKey","path","path","path","defaultNodeHints","path","path","path","path"],"sources":["../../src/ir/sdk-behavior.ts","../../src/errors.ts","../../src/parser/refs.ts","../../src/ir/types.ts","../../src/utils/naming.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","../../src/cli/parse.ts","../../src/engine/merge-adapters/url-fingerprint.ts","../../src/engine/merge-adapters/dotnet.ts","../../src/engine/merge-adapters/elixir.ts","../../src/engine/merge-adapters/go.ts","../../src/engine/merge-adapters/kotlin.ts","../../src/engine/merge-adapters/node.ts","../../src/engine/merge-adapters/php.ts","../../src/engine/merge-adapters/python.ts","../../src/engine/merge-adapters/ruby.ts","../../src/engine/merge-adapters/rust.ts","../../src/engine/merge-adapters/index.ts","../../src/utils/tree-sitter.ts","../../src/engine/merger.ts","../../src/engine/json-merge.ts","../../src/engine/writer.ts","../../src/ir/operation-hints.ts","../../src/engine/generate-files.ts","../../src/engine/integrate.ts","../../src/engine/formatter.ts","../../src/engine/manifest.ts","../../src/engine/orchestrator.ts","../../src/engine/registry.ts","../../src/compat/language-hints.ts","../../src/compat/overlay.ts","../../src/compat/extractor-registry.ts","../../src/engine/manifest-reader.ts","../../src/cli/overlay-loader.ts","../../src/utils/expand-doc-urls.ts","../../src/cli/generate.ts","../../src/differ/classify.ts","../../src/differ/models.ts","../../src/differ/operations.ts","../../src/differ/services.ts","../../src/differ/diff.ts","../../src/cli/diff.ts","../../src/cli/extract.ts","../../src/compat/policy.ts","../../src/compat/schema.ts","../../src/compat/ir.ts","../../src/cli/compat-extract.ts","../../src/compat/config.ts","../../src/compat/classify.ts","../../src/compat/spec-filter.ts","../../src/compat/differ.ts","../../src/compat/concepts.ts","../../src/compat/report.ts","../../src/cli/compat-diff.ts","../../src/cli/compat-summary.ts","../../src/compat/approvals.ts","../../src/verify/run-compat-check.ts","../../src/verify/run-overlay-retry-loop.ts","../../src/compat/staleness.ts","../../src/verify/run-staleness-check.ts","../../src/verify/run-smoke-check.ts","../../src/verify/write-diagnostics.ts","../../src/cli/verify.ts","../../src/cli/templates/init.ts","../../src/cli/init.ts","../../src/cli/resolve.ts","../../src/cli/config-loader.ts","../../src/cli/plugin-loader.ts","../../src/cli/index.ts"],"sourcesContent":["/**\n * SDK Behavior IR — language-agnostic runtime policies for generated SDKs.\n *\n * These types capture the \"what\" of SDK behavior (retry, telemetry, errors, etc.)\n * while emitters provide the \"how\" (language-specific mechanism).\n *\n * Emitters access these via `ctx.spec.sdk` — always populated, never undefined.\n */\n\n// ── Retry ──────────────────────────────────────────────────────────\n\n/** Retry policy — when and how to retry failed requests. */\nexport interface RetryPolicy {\n /** HTTP status codes that trigger a retry. */\n retryableStatusCodes: number[];\n /** Maximum number of retry attempts (0 = no retries). */\n maxRetries: number;\n /** Whether to retry on connection errors (DNS failure, TCP reset). */\n retryOnConnectionError: boolean;\n /** Whether to retry on timeout errors. */\n retryOnTimeout: boolean;\n /** Backoff strategy between retries. */\n backoff: BackoffStrategy;\n}\n\n/** Exponential backoff configuration.\n *\n * Formula: `delay = min(initialDelay * multiplier^attempt, maxDelay)`\n * With jitter: `delay += delay * jitterFactor * random(0, 1)`\n */\nexport interface BackoffStrategy {\n /** Initial delay in seconds before the first retry. */\n initialDelay: number;\n /** Multiplier applied to the delay on each subsequent retry. */\n multiplier: number;\n /** Maximum delay in seconds (cap). */\n maxDelay: number;\n /** Jitter factor (0..1). 0.5 means up to 50% random jitter added. */\n jitterFactor: number;\n}\n\n// ── Errors ─────────────────────────────────────────────────────────\n\n/** Error mapping — status codes to named exception kinds. */\nexport interface ErrorPolicy {\n /** Map from HTTP status code to a logical error kind name (e.g. 400 → 'BadRequest').\n * Emitters append language-specific suffixes (e.g. 'BadRequestException'). */\n statusCodeMap: Record<number, string>;\n /** Catch-all error kind for 5xx status codes not in the map. */\n serverErrorKind: string;\n /** Catch-all error kind for unrecognized status codes. */\n clientErrorKind: string;\n /** URL template for error documentation. Use {code} as placeholder for the API error code.\n * Example: 'https://workos.com/docs/errors/{code}' */\n errorDocUrlTemplate?: string;\n}\n\n// ── Telemetry ──────────────────────────────────────────────────────\n\n/** Telemetry — what request metrics to track and send. */\nexport interface TelemetryPolicy {\n /** Whether telemetry is enabled by default. Users can opt out via constructor param. */\n enabledByDefault: boolean;\n /** Header name for client telemetry data (previous request's ID + latency). */\n headerName: string;\n /** Response header name for the request ID. */\n requestIdHeader: string;\n}\n\n// ── Pagination ─────────────────────────────────────────────────────\n\n/** Pagination behavior defaults. */\nexport interface PaginationPolicy {\n /** Delay in milliseconds between pages during auto-pagination. 0 = no delay. */\n autoPageDelayMs: number;\n}\n\n// ── Idempotency ────────────────────────────────────────────────────\n\n/** Idempotency auto-generation rules. */\nexport interface IdempotencyPolicy {\n /** Header name for the idempotency key. */\n headerName: string;\n /** Whether to auto-generate a UUID v4 idempotency key for POST requests when retries > 0. */\n autoGenerateForPost: boolean;\n}\n\n// ── Logging ────────────────────────────────────────────────────────\n\n/** Logging contract — what to log at which level. */\nexport interface LoggingPolicy {\n /** Whether structured logging hooks are generated. */\n enabled: boolean;\n /** Log events that the generated client emits. */\n events: LogEvent[];\n}\n\n/** A discrete loggable event in the request lifecycle. */\nexport type LogEvent =\n | 'request.start'\n | 'request.success'\n | 'request.retry'\n | 'request.rate_limited'\n | 'request.error'\n | 'request.connection_error';\n\n// ── User-Agent ─────────────────────────────────────────────────────\n\n/** User-Agent construction rules. */\nexport interface UserAgentPolicy {\n /** Template for the SDK identifier string.\n * Placeholders: {name} = spec name, {lang} = emitter language, {version} = SDK version.\n * Each emitter interpolates with its own language string and casing conventions.\n * Example: '{name} {lang}/{version}' → 'WorkOS PHP/4.32.0' */\n sdkIdentifierTemplate: string;\n /** Whether to append the runtime/language version (e.g. PHP 8.2, Python 3.12). */\n includeRuntimeVersion: boolean;\n /** Whether to allow app info enrichment via setAppInfo(name, version, url). */\n allowAppInfo: boolean;\n /** AI agent environment variable detection entries. */\n aiAgentEnvVars: AiAgentEnvVar[];\n}\n\n/** Maps an environment variable to an AI agent slug for User-Agent enrichment. */\nexport interface AiAgentEnvVar {\n /** Environment variable to check (e.g. 'CLAUDE_CODE'). */\n envVar: string;\n /** Agent name to append to User-Agent (e.g. 'ClaudeCode'). */\n agentName: string;\n}\n\n// ── Request Guards ─────────────────────────────────────────────────\n\n/** Guards that validate request params before sending. */\nexport interface RequestGuardPolicy {\n /** Keys that should be in RequestOptions, not in params.\n * If detected in the body or query params, the SDK throws an error. */\n optionKeys: string[];\n}\n\n// ── Timeouts ───────────────────────────────────────────────────────\n\n/** Timeout configuration. */\nexport interface TimeoutPolicy {\n /** Default HTTP request timeout in seconds. */\n defaultTimeoutSeconds: number;\n /** Environment variable name to override the timeout (e.g. 'WORKOS_REQUEST_TIMEOUT'). */\n timeoutEnvVar?: string;\n}\n\n// ── Root ───────────────────────────────────────────────────────────\n\n/** Language-agnostic runtime policies for generated SDKs.\n * Attached to `ApiSpec.sdk` and consumed by emitters via `ctx.spec.sdk`. */\nexport interface SdkBehavior {\n retry: RetryPolicy;\n errors: ErrorPolicy;\n telemetry: TelemetryPolicy;\n pagination: PaginationPolicy;\n idempotency: IdempotencyPolicy;\n logging: LoggingPolicy;\n userAgent: UserAgentPolicy;\n requestGuard: RequestGuardPolicy;\n timeout: TimeoutPolicy;\n}\n\n// ── Defaults ───────────────────────────────────────────────────────\n\n/**\n * Canonical SDK behavior defaults. These match the PHP emitter's current\n * implementation (the most complete). Per-language overrides can be applied\n * via `mergeSdkBehavior()` in each SDK's `oagen.config.ts`.\n *\n * - Retry: exponential backoff with jitter, retries on 429/5xx\n * - Errors: standard HTTP status → exception kind mapping\n * - Telemetry: enabled by default, tracks request ID + latency\n * - Pagination: no inter-page delay (Node overrides to 350ms)\n * - Idempotency: auto-generate UUID v4 for retryable POSTs\n * - Logging: all lifecycle events enabled\n * - User-Agent: SDK identifier + runtime version + app info + AI agent detection\n * - Request guards: detect misplaced RequestOptions keys in params\n * - Timeout: 60s default (Python overrides to 30s)\n */\nexport function defaultSdkBehavior(): SdkBehavior {\n return {\n retry: {\n retryableStatusCodes: [429, 500, 502, 503, 504],\n maxRetries: 3,\n retryOnConnectionError: true,\n retryOnTimeout: true,\n backoff: {\n initialDelay: 1.0,\n multiplier: 2.0,\n maxDelay: 30.0,\n jitterFactor: 0.5,\n },\n },\n errors: {\n statusCodeMap: {\n 400: 'BadRequest',\n 401: 'Authentication',\n 403: 'Authorization',\n 404: 'NotFound',\n 409: 'Conflict',\n 422: 'UnprocessableEntity',\n 429: 'RateLimitExceeded',\n },\n serverErrorKind: 'Server',\n clientErrorKind: 'Api',\n errorDocUrlTemplate: 'https://workos.com/docs/errors/{code}',\n },\n telemetry: {\n enabledByDefault: true,\n headerName: 'X-WorkOS-Client-Telemetry',\n requestIdHeader: 'X-Request-ID',\n },\n pagination: {\n autoPageDelayMs: 0,\n },\n idempotency: {\n headerName: 'Idempotency-Key',\n autoGenerateForPost: true,\n },\n logging: {\n enabled: true,\n events: [\n 'request.start',\n 'request.success',\n 'request.retry',\n 'request.rate_limited',\n 'request.error',\n 'request.connection_error',\n ],\n },\n userAgent: {\n sdkIdentifierTemplate: '{name} {lang}/{version}',\n includeRuntimeVersion: true,\n allowAppInfo: true,\n aiAgentEnvVars: [\n { envVar: 'CLAUDE_CODE', agentName: 'ClaudeCode' },\n { envVar: 'CURSOR_AGENT', agentName: 'Cursor' },\n { envVar: 'CLINE_ACTIVE', agentName: 'Cline' },\n { envVar: 'WINDSURF_ACTIVE', agentName: 'Windsurf' },\n { envVar: 'COPILOT_AGENT', agentName: 'Copilot' },\n ],\n },\n requestGuard: {\n optionKeys: [\n 'api_key',\n 'apiKey',\n 'idempotency_key',\n 'idempotencyKey',\n 'extra_headers',\n 'extraHeaders',\n 'max_retries',\n 'maxRetries',\n 'base_url',\n 'baseUrl',\n ],\n },\n timeout: {\n defaultTimeoutSeconds: 60,\n },\n };\n}\n\n// ── Merge ──────────────────────────────────────────────────────────\n\n/** Recursive partial type for deep overrides. */\nexport type DeepPartial<T> = {\n [K in keyof T]?: T[K] extends (infer U)[]\n ? U[] // Arrays replace entirely (don't concat)\n : T[K] extends object\n ? DeepPartial<T[K]>\n : T[K];\n};\n\n/**\n * Deep-merge partial overrides into the canonical defaults.\n * Arrays replace entirely (so `retryableStatusCodes: [429]` replaces the full list,\n * rather than appending). Object properties are merged recursively.\n */\nexport function mergeSdkBehavior(overrides: DeepPartial<SdkBehavior>): SdkBehavior {\n return deepMerge(\n defaultSdkBehavior() as unknown as Record<string, unknown>,\n overrides as unknown as Record<string, unknown>,\n ) as unknown as SdkBehavior;\n}\n\n/**\n * Self-contained deep merge (no external imports — ir/ is layer 0).\n * Arrays and primitives from `source` replace those in `target`.\n * Objects are merged recursively.\n */\nfunction deepMerge(target: Record<string, unknown>, source: Record<string, unknown>): Record<string, unknown> {\n const result: Record<string, unknown> = { ...target };\n for (const key of Object.keys(source)) {\n const sourceVal = source[key];\n const targetVal = target[key];\n if (sourceVal === undefined) continue;\n if (\n sourceVal !== null &&\n typeof sourceVal === 'object' &&\n !Array.isArray(sourceVal) &&\n targetVal !== null &&\n typeof targetVal === 'object' &&\n !Array.isArray(targetVal)\n ) {\n result[key] = deepMerge(targetVal as Record<string, unknown>, sourceVal as Record<string, unknown>);\n } else {\n result[key] = sourceVal;\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, Oas3_1Types } 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,\n types: Oas3_1Types,\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","import type { SdkBehavior } from './sdk-behavior.js';\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 /** Language-agnostic runtime policies (retry, errors, telemetry, etc.). */\n sdk: SdkBehavior;\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) */\n/** Per-operation security requirement: scheme name → scope list. */\nexport interface SecurityRequirement {\n schemeName: string;\n scopes: string[];\n}\n\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 /** Per-operation security overrides. When present, overrides the global spec-level security. */\n security?: SecurityRequirement[];\n /**\n * Mutually-exclusive parameter groups parsed from `x-mutually-exclusive-parameter-groups`.\n * Each group represents a logical choice the caller must (or may) make between\n * several subsets of query/path/header parameters. The grouped parameters remain\n * in their original arrays (queryParams, pathParams, etc.) for wire-format purposes;\n * this field adds the grouping metadata so emitters can render sum types.\n */\n parameterGroups?: ParameterGroup[];\n}\n\n/**\n * A mutually-exclusive parameter group. The caller must supply exactly one\n * variant (when `optional` is false) or may omit the group entirely (when true).\n */\nexport interface ParameterGroup {\n /** Group name from the extension (e.g. \"parent_resource\"). */\n name: string;\n /** True when the whole group may be omitted. */\n optional: boolean;\n /** Ordered variants (insertion order matches the spec). */\n variants: ParameterGroupVariant[];\n}\n\n/**\n * One variant within a mutually-exclusive parameter group.\n */\nexport interface ParameterGroupVariant {\n /** Variant name from the extension (e.g. \"by_id\", \"by_external_id\"). */\n name: string;\n /**\n * References to the actual parameter IR nodes. These are the same\n * objects that live in operation.queryParams / .pathParams / .headerParams --\n * shared by identity, not duplicated.\n */\n parameters: Parameter[];\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 style?: 'form' | 'simple' | 'label' | 'matrix';\n explode?: boolean;\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 * When set, this model is a discriminated union over allOf+oneOf variants.\n * Emitters should generate a dispatcher (factory) instead of a regular dataclass.\n * The `property` field is the discriminator key (e.g. \"event\"), and `mapping`\n * maps each discriminator value to the concrete variant model name.\n */\n discriminator?: {\n property: string;\n mapping: Record<string, string>;\n };\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","/**\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 = ['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 'Species',\n 'Series',\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","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, singularize, stripListItemMarkers } from '../utils/naming.js';\n\n/**\n * Module-level transform set during extractSchemas(). Used by schemaToTypeRef()\n * to apply the same name transform to $ref model/enum references.\n */\nlet activeSchemaNameTransform: ((name: string) => string) | null = null;\n\n/** Apply cleanSchemaName + the active transform (if any) to a raw schema name. */\nfunction resolveSchemaName(rawName: string): string {\n let name = cleanSchemaName(toPascalCase(rawName));\n if (activeSchemaNameTransform) name = activeSchemaNameTransform(name);\n return name;\n}\n\nexport interface SchemaExtractionOptions {\n schemaNameTransform?: (name: string) => string;\n}\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(\n schemas: Record<string, SchemaObject> | undefined,\n options?: SchemaExtractionOptions,\n): ExtractedSchemas {\n const enums: Enum[] = [];\n\n if (!schemas) return { models: [], enums };\n\n // Build collision-safe transform if provided\n if (options?.schemaNameTransform) {\n const transform = options.schemaNameTransform;\n const rawNames = Object.keys(schemas);\n const cleanedNames = rawNames.map((n) => cleanSchemaName(toPascalCase(n)));\n const transformedToOriginals = new Map<string, string[]>();\n for (const cleaned of cleanedNames) {\n const transformed = transform(cleaned);\n if (!transformedToOriginals.has(transformed)) transformedToOriginals.set(transformed, []);\n transformedToOriginals.get(transformed)!.push(cleaned);\n }\n const unsafeToTransform = new Set<string>();\n for (const [, originals] of transformedToOriginals) {\n if (originals.length > 1) {\n for (const n of originals) unsafeToTransform.add(n);\n }\n }\n activeSchemaNameTransform = (name: string) => (unsafeToTransform.has(name) ? name : transform(name));\n } else {\n activeSchemaNameTransform = null;\n }\n\n const modelsByCleanName = new Map<string, Model>();\n\n for (const [name, schema] of Object.entries(schemas)) {\n const pascalName = resolveSchemaName(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 for (const inlineModel of extractDiscriminatedAllOfVariantModels(schema, pascalName)) {\n const existingInline = modelsByCleanName.get(inlineModel.name);\n if (existingInline) {\n if (inlineModel.fields.length > existingInline.fields.length) {\n modelsByCleanName.set(inlineModel.name, inlineModel);\n }\n } else {\n modelsByCleanName.set(inlineModel.name, inlineModel);\n }\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 // NOTE: activeSchemaNameTransform is intentionally NOT cleared here.\n // extractOperations() calls schemaToTypeRef() for $ref resolution and\n // needs the same transform active. parseSpec() calls clearSchemaNameTransform()\n // after all extraction is complete.\n return { models, enums };\n}\n\n/** Clear the module-level schemaNameTransform. Called by parseSpec() after all extraction phases. */\nexport function clearSchemaNameTransform(): void {\n activeSchemaNameTransform = null;\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) => resolveSchemaName(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 (resolveSchemaName(k) === pascalName) return v;\n }\n return null;\n}\n\n/** Walk into a schema to find a field's sub-schema, resolving allOf and oneOf/anyOf. */\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 // Also check inside oneOf/anyOf variants (pure oneOf schemas flatten variant\n // properties into the model, so the field may live inside a variant).\n for (const variant of [...(parentSchema.oneOf ?? []), ...(parentSchema.anyOf ?? [])]) {\n let resolved = variant;\n if (variant.$ref) {\n const segments = variant.$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 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\n/**\n * If every non-null oneOf/anyOf variant is a string-valued const, return the\n * list of those const values so the union can collapse into a single enum.\n * Returns null when any variant isn't a pure string-const (model ref,\n * number const, nullable, etc.).\n */\nfunction collectLiteralStringConsts(variants: SchemaObject[]): string[] | null {\n if (variants.length === 0) return null;\n const values: string[] = [];\n for (const v of variants) {\n // A single-element enum is semantically identical to const.\n if (typeof v.const === 'string') {\n values.push(v.const);\n continue;\n }\n if (Array.isArray(v.enum) && v.enum.length === 1 && typeof v.enum[0] === 'string') {\n values.push(v.enum[0]);\n continue;\n }\n return null;\n }\n return values;\n}\n\n/** Build an EnumRef the same way the regular enum path does for naming. */\nfunction buildSyntheticEnumRef(\n values: string[],\n contextName: string | undefined,\n parentModelName: string | undefined,\n): TypeRef {\n const baseName = toPascalCase(contextName ?? 'UnknownEnum');\n const cleanParent = parentModelName ? stripListItemMarkers(parentModelName) : undefined;\n const qualifiedName = cleanParent && !baseName.startsWith(cleanParent) ? `${cleanParent}${baseName}` : baseName;\n return { kind: 'enum', name: qualifiedName, values };\n}\n\n/**\n * Detect an implicit discriminator on an oneOf where every variant is an\n * object schema that pins the same property to a const value. Returns\n * { property, mapping } so the IR can represent the union as discriminated\n * without needing an explicit `discriminator:` key in the spec.\n *\n * Both shapes are supported:\n * { properties: { event: { const: \"x\" } }, required: [\"event\"] }\n * { properties: { event: { type: \"string\", enum: [\"x\"] } } }\n *\n * Returns null when any variant doesn't fit the pattern or when variants\n * disagree on which property carries the discriminator.\n */\nfunction detectConstPropertyDiscriminator(\n variants: SchemaObject[],\n): { property: string; mapping: Record<string, string> } | null {\n if (variants.length < 2) return null;\n\n // Find properties whose const value is present on every variant.\n let candidateProperty: string | null = null;\n const candidates = Object.keys(variants[0]?.properties ?? {});\n for (const propName of candidates) {\n if (variants.every((v) => getConstPropertyValue(v, propName) !== null)) {\n candidateProperty = propName;\n break;\n }\n }\n\n if (!candidateProperty) return null;\n\n const mapping: Record<string, string> = {};\n for (const v of variants) {\n const value = getConstPropertyValue(v, candidateProperty);\n if (value === null) return null;\n // Require a $ref or title so we have a concrete model name to map to.\n const variantName = resolveVariantModelName(v);\n if (!variantName) return null;\n mapping[value] = variantName;\n }\n\n return { property: candidateProperty, mapping };\n}\n\nfunction getConstPropertyValue(schema: SchemaObject, property: string): string | null {\n const prop = schema.properties?.[property];\n if (!prop) return null;\n if (typeof prop.const === 'string') return prop.const;\n if (Array.isArray(prop.enum) && prop.enum.length === 1 && typeof prop.enum[0] === 'string') {\n return prop.enum[0];\n }\n return null;\n}\n\nfunction resolveVariantModelName(schema: SchemaObject): string | null {\n if (schema.$ref) {\n return resolveSchemaName(schema.$ref.replace(/^#\\/components\\/schemas\\//, ''));\n }\n const title = typeof schema['title'] === 'string' ? (schema['title'] as string) : null;\n if (title) return resolveSchemaName(title);\n return null;\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 // Pure oneOf/anyOf schemas (no allOf, no properties): merge variant fields\n // as optional. This handles schemas like UpdateOrganizationMembership which\n // is a oneOf with mutually exclusive field groups (role_slug vs role_slugs).\n if (fields.length === 0 && (schema.oneOf || schema.anyOf)) {\n const variants = schema.oneOf ?? schema.anyOf ?? [];\n const emptyRequired = new Set<string>();\n const seenFieldNames = new Set<string>();\n for (const variant of variants) {\n if (!variant.properties) continue;\n for (const [fieldName, fieldSchema] of Object.entries(variant.properties)) {\n if (!fieldSchema || seenFieldNames.has(fieldName)) continue;\n seenFieldNames.add(fieldName);\n fields.push(buildFieldFromSchema(fieldName, fieldSchema as SchemaObject, name, emptyRequired));\n }\n }\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 let resultDiscriminator: { property: string; mapping: Record<string, string> } | undefined;\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 if (resolved.oneOf || resolved.anyOf) {\n const variants = resolved.oneOf ?? resolved.anyOf ?? [];\n // Detect discriminated union: every variant pins the same property to a\n // distinct const value (e.g. EventSchema where each variant has event: const).\n // When detected, store the discriminator instead of flattening variant fields —\n // the base allOf schema already captures the common fields.\n const discriminatorInfo = detectAllOfVariantDiscriminator(variants, name);\n if (discriminatorInfo) {\n resultDiscriminator = discriminatorInfo;\n } else {\n // Flatten oneOf/anyOf variant fields into the parent model as optional\n // fields. This handles the common allOf + oneOf pattern where the spec\n // uses mutually exclusive variant groups (e.g. password vs password_hash).\n const emptyRequired = new Set<string>();\n const seenFieldNames = new Set(fields.map((f) => f.name));\n for (const variant of variants) {\n if (!variant.properties) continue;\n for (const [fieldName, fieldSchema] of Object.entries(variant.properties)) {\n if (!fieldSchema || seenFieldNames.has(fieldName)) continue;\n seenFieldNames.add(fieldName);\n fields.push(buildFieldFromSchema(fieldName, fieldSchema as SchemaObject, name, emptyRequired));\n }\n }\n // Do NOT add variant-level required to the requiredSet — these fields\n // are optional at the parent level because they come from mutually\n // exclusive branches.\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 {\n name,\n description: schema.description,\n fields,\n ...(resultDiscriminator ? { discriminator: resultDiscriminator } : {}),\n };\n}\n\n/**\n * Detect an implicit discriminator on an allOf+oneOf where every variant is an\n * object that pins the same property to a distinct const value. Unlike\n * detectConstPropertyDiscriminator (which requires $ref or title for variant\n * model names), this version derives model names from the const value itself\n * using deriveDiscriminatedVariantName — matching how extractDiscriminatedAllOfVariantModels\n * names those models.\n *\n * Returns null when no discriminator can be reliably detected.\n */\nfunction detectAllOfVariantDiscriminator(\n variants: SchemaObject[],\n fallbackName: string,\n): { property: string; mapping: Record<string, string> } | null {\n if (variants.length < 2) return null;\n\n // Find a property whose const value is present on every variant\n const candidates = Object.keys(variants[0]?.properties ?? {});\n let candidateProperty: string | null = null;\n for (const propName of candidates) {\n if (variants.every((v) => getConstPropertyValue(v, propName) !== null)) {\n candidateProperty = propName;\n break;\n }\n }\n if (!candidateProperty) return null;\n\n const mapping: Record<string, string> = {};\n const seenModelNames = new Set<string>();\n for (const v of variants) {\n const value = getConstPropertyValue(v, candidateProperty);\n if (value === null) return null;\n const modelName = deriveDiscriminatedVariantName(v, fallbackName);\n // If two variants map to the same model name, the discriminator is ambiguous\n if (seenModelNames.has(modelName)) return null;\n seenModelNames.add(modelName);\n mapping[value] = modelName;\n }\n\n return { property: candidateProperty, mapping };\n}\n\nfunction extractDiscriminatedAllOfVariantModels(schema: SchemaObject, fallbackName: string): Model[] {\n const models: Model[] = [];\n const seenNames = new Set<string>();\n\n for (const subSchema of schema.allOf ?? []) {\n for (const variant of subSchema.oneOf ?? []) {\n if (!variant.properties || (variant.type !== undefined && variant.type !== 'object')) continue;\n\n const variantName = deriveDiscriminatedVariantName(variant, fallbackName);\n for (const model of extractInlineModelDeep(variantName, variant)) {\n if (seenNames.has(model.name)) continue;\n seenNames.add(model.name);\n models.push(model);\n }\n }\n }\n\n return models;\n}\n\nfunction deriveDiscriminatedVariantName(schema: SchemaObject, fallbackName: string): string {\n if (!schema.properties) return fallbackName;\n\n const preferred = ['event', 'type', 'object'];\n for (const name of preferred) {\n const field = schema.properties[name];\n if (!field) continue;\n if (typeof field.const === 'string') {\n return toPascalCase(field.const);\n }\n if (field.enum && field.enum.length === 1 && typeof field.enum[0] === 'string') {\n return toPascalCase(field.enum[0]);\n }\n }\n\n for (const field of Object.values(schema.properties)) {\n if (!field) continue;\n if (typeof field.const === 'string') {\n return toPascalCase(field.const);\n }\n if (field.enum && field.enum.length === 1 && typeof field.enum[0] === 'string') {\n return toPascalCase(field.enum[0]);\n }\n }\n\n return fallbackName;\n}\n\nfunction extractInlineModelDeep(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 if (fieldSchema.type === 'object' && fieldSchema.properties) {\n nestedModels.push(...extractInlineModelDeep(qualifyNestedInlineName(name, fieldName), fieldSchema));\n }\n\n if (fieldSchema.type === 'array' && fieldSchema.items?.properties) {\n nestedModels.push(...extractInlineModelDeep(qualifyNestedInlineName(name, fieldName), fieldSchema.items));\n }\n\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 nestedModels.push(\n ...extractInlineModelDeep(qualifyNestedInlineName(name, fieldName), {\n type: 'object',\n properties: mergedProperties,\n required: mergedRequired,\n }),\n );\n }\n }\n\n if (fieldSchema.oneOf) {\n const objectVariant = fieldSchema.oneOf.find((v) => v.properties && (v.type === 'object' || !v.type));\n if (objectVariant) {\n nestedModels.push(...extractInlineModelDeep(qualifyNestedInlineName(name, fieldName), objectVariant));\n }\n }\n }\n\n return [{ name, description: schema.description, fields }, ...nestedModels];\n}\n\nfunction qualifyNestedInlineName(parentName: string, fieldName: string): string {\n const pascalField = toPascalCase(fieldName);\n if (pascalField.startsWith(parentName)) return pascalField;\n\n const cleanParent = stripListItemMarkers(parentName);\n const qualified = `${cleanParent}${pascalField}`;\n const match = qualified.match(/^(.+?)([A-Z][a-z]+s?)$/);\n if (match && match[2]) {\n return match[1] + singularize(match[2]);\n }\n return qualified;\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: resolveSchemaName(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 // Collapse an oneOf/anyOf whose non-null variants are all string-const\n // schemas into a single enum. This turns patterns like\n // provider: { oneOf: [{ const: \"AppleOAuth\" }, { const: \"GitHubOAuth\" }, ...] }\n // into a proper enum type with one member per variant instead of a\n // structurally-opaque union of literal refs.\n const literalStrings = collectLiteralStringConsts(nonNullVariants);\n if (literalStrings !== null && literalStrings.length >= 2) {\n const enumRef = buildSyntheticEnumRef(literalStrings, contextName, parentModelName);\n return nullVariant ? { kind: 'nullable', inner: enumRef } : enumRef;\n }\n\n // Synthesize a discriminator when all non-null variants are objects that\n // share a property whose schema carries a `const` value. Covers the\n // EventSchema-style pattern where each oneOf variant pins `event:\n // const: \"...\"` instead of the spec using an explicit `discriminator:`.\n const syntheticDiscriminator =\n !schema.discriminator && compositionKind === 'oneOf' ? detectConstPropertyDiscriminator(nonNullVariants) : null;\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 : syntheticDiscriminator\n ? { discriminator: syntheticDiscriminator }\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 'meta',\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 // that looks like pagination metadata. A `data` array alone (e.g. with only an\n // `object` discriminant companion) is NOT sufficient — the companion must indicate\n // actual pagination (cursor, metadata, total, etc.).\n if (arrayProps.length === 1 && nonArrayKeys.length >= 1) {\n const arrayPropName = arrayProps[0];\n\n const hasPaginationCompanion = nonArrayKeys.some((key) =>\n PAGINATION_METADATA_PATTERNS.some((pattern) => key.toLowerCase().includes(pattern)),\n );\n\n if (KNOWN_DATA_PATHS.has(arrayPropName) && hasPaginationCompanion) {\n return { isEnvelope: true, dataPath: arrayPropName };\n }\n\n // Non-standard array property name — still treat as envelope if pagination companion exists\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 ParameterGroup,\n TypeRef,\n ErrorResponse,\n SuccessResponse,\n SecurityRequirement,\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 ParameterGroupExtension {\n optional: boolean;\n variants: Record<string, string[]>;\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 security?: Array<Record<string, string[]>>;\n 'x-mutually-exclusive-parameter-groups'?: Record<string, ParameterGroupExtension>;\n 'x-mutually-exclusive-body-groups'?: Record<string, ParameterGroupExtension>;\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 style?: string;\n explode?: boolean;\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 serviceName,\n );\n inlineModels.push(...opModels);\n const ops = serviceMap.get(serviceName) ?? [];\n ops.push(operation);\n serviceMap.set(serviceName, ops);\n }\n }\n\n // Split services when a single tag groups operations from multiple path prefixes.\n // Example: /organizations and /organization_domains both tagged \"organizations\"\n // should become separate services based on their first path segment.\n for (const [serviceName, operations] of serviceMap) {\n const pathGroups = new Map<string, Operation[]>();\n for (const op of operations) {\n const firstSeg = op.path.split('/').filter(Boolean)[0] ?? '';\n const groupKey = firstSeg.startsWith('{') ? serviceName : toPascalCase(firstSeg);\n const group = pathGroups.get(groupKey) ?? [];\n group.push(op);\n pathGroups.set(groupKey, group);\n }\n // Only split if there are multiple distinct path-prefix groups AND\n // at least one group name differs from the current service name\n if (pathGroups.size > 1) {\n const needsSplit = [...pathGroups.keys()].some((k) => k !== serviceName);\n if (needsSplit) {\n serviceMap.delete(serviceName);\n for (const [groupName, groupOps] of pathGroups) {\n const existing = serviceMap.get(groupName) ?? [];\n existing.push(...groupOps);\n serviceMap.set(groupName, existing);\n }\n }\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\n/**\n * Extract mutually-exclusive parameter groups from the `x-mutually-exclusive-parameter-groups`\n * operation extension. Cross-references grouped parameter names against the already-extracted\n * IR parameter arrays so emitters get object-identity references.\n */\nfunction extractParameterGroups(\n op: OperationObject,\n allIRParams: Parameter[],\n operationContext: string,\n): ParameterGroup[] | undefined {\n const raw = op['x-mutually-exclusive-parameter-groups'];\n if (!raw || typeof raw !== 'object') return undefined;\n\n const paramByName = new Map<string, Parameter>();\n for (const p of allIRParams) {\n paramByName.set(p.name, p);\n }\n\n const groups: ParameterGroup[] = [];\n\n for (const [groupName, groupDef] of Object.entries(raw)) {\n if (!groupDef || typeof groupDef !== 'object') {\n throw new Error(\n `Malformed x-mutually-exclusive-parameter-groups.${groupName} in ${operationContext}: expected an object with \"optional\" and \"variants\".`,\n );\n }\n\n if (typeof groupDef.optional !== 'boolean') {\n throw new Error(\n `Malformed x-mutually-exclusive-parameter-groups.${groupName}.optional in ${operationContext}: expected a boolean.`,\n );\n }\n\n if (!groupDef.variants || typeof groupDef.variants !== 'object') {\n throw new Error(\n `Malformed x-mutually-exclusive-parameter-groups.${groupName}.variants in ${operationContext}: expected an object mapping variant names to parameter name arrays.`,\n );\n }\n\n if (Object.keys(groupDef.variants).length === 0) {\n throw new Error(\n `Malformed x-mutually-exclusive-parameter-groups.${groupName} in ${operationContext}: group has zero variants.`,\n );\n }\n\n const variants = Object.entries(groupDef.variants).map(([variantName, paramNames]) => {\n if (!Array.isArray(paramNames) || paramNames.length === 0) {\n throw new Error(\n `Malformed x-mutually-exclusive-parameter-groups.${groupName}.variants.${variantName} in ${operationContext}: expected a non-empty array of parameter names.`,\n );\n }\n const parameters: Parameter[] = paramNames.map((pName) => {\n const irParam = paramByName.get(pName);\n if (!irParam) {\n throw new Error(\n `x-mutually-exclusive-parameter-groups.${groupName}.variants.${variantName} references parameter \"${pName}\" which does not exist in the operation's parameters[] (${operationContext}).`,\n );\n }\n return irParam;\n });\n return { name: variantName, parameters };\n });\n\n groups.push({\n name: groupName,\n optional: groupDef.optional,\n variants,\n });\n }\n\n return groups.length > 0 ? groups : undefined;\n}\n\n/**\n * Extract mutually-exclusive body parameter groups from the\n * `x-mutually-exclusive-body-groups` operation extension. Unlike query\n * parameter groups (whose parameters live in operation.queryParams), body\n * group parameters are synthetic — built from the oneOf variant schemas in\n * the request body. Emitters use the group's presence to generate sum-type\n * interfaces and custom JSON marshalling instead of flat optional fields.\n */\nfunction extractBodyParameterGroups(op: OperationObject, operationContext: string): ParameterGroup[] | undefined {\n const raw = op['x-mutually-exclusive-body-groups'];\n if (!raw || typeof raw !== 'object') return undefined;\n\n // Collect the body schema's oneOf variant fields so we can resolve types.\n // The body schema has been structurally rewritten to allOf: [base, { oneOf: [...] }]\n // by the spec generator; the variant properties live inside oneOf branches.\n const bodySchema = op.requestBody?.content?.['application/json']?.schema;\n const variantFieldSchemas = new Map<string, SchemaObject>();\n\n if (bodySchema) {\n // Walk allOf → oneOf → variant.properties to find all variant fields\n for (const sub of bodySchema.allOf ?? []) {\n for (const variant of sub.oneOf ?? []) {\n if (variant.properties) {\n for (const [name, fieldSchema] of Object.entries(variant.properties)) {\n if (fieldSchema) variantFieldSchemas.set(name, fieldSchema);\n }\n }\n }\n }\n // Also check top-level oneOf (for inline schemas that aren't wrapped in allOf)\n for (const variant of bodySchema.oneOf ?? []) {\n if (variant.properties) {\n for (const [name, fieldSchema] of Object.entries(variant.properties)) {\n if (fieldSchema) variantFieldSchemas.set(name, fieldSchema);\n }\n }\n }\n }\n\n const groups: ParameterGroup[] = [];\n\n for (const [groupName, groupDef] of Object.entries(raw)) {\n if (!groupDef || typeof groupDef !== 'object') continue;\n if (typeof groupDef.optional !== 'boolean') continue;\n if (!groupDef.variants || typeof groupDef.variants !== 'object') continue;\n if (Object.keys(groupDef.variants).length === 0) continue;\n\n const variants = Object.entries(groupDef.variants).map(([variantName, paramNames]) => {\n if (!Array.isArray(paramNames) || paramNames.length === 0) {\n throw new Error(\n `Malformed x-mutually-exclusive-body-groups.${groupName}.variants.${variantName} in ${operationContext}: expected a non-empty array of parameter names.`,\n );\n }\n const parameters: Parameter[] = paramNames.map((pName) => {\n const fieldSchema = variantFieldSchemas.get(pName);\n const fieldType: TypeRef = fieldSchema\n ? schemaToTypeRef(fieldSchema, toPascalCase(pName))\n : { kind: 'primitive', type: 'string' };\n return {\n name: pName,\n type: fieldType,\n required: false, // group variant fields are always optional at the struct level\n description: fieldSchema?.description,\n };\n });\n return { name: variantName, parameters };\n });\n\n groups.push({\n name: groupName,\n optional: groupDef.optional,\n variants,\n });\n }\n\n return groups.length > 0 ? groups : undefined;\n}\n\nfunction buildOperation(\n method: HttpMethod,\n path: string,\n op: OperationObject,\n pathLevelParams: ParameterObject[],\n operationIdTransform?: (id: string) => string,\n serviceName?: 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 // Use the service name as context so inline parameter enums get qualified\n // names. e.g., service \"SSO\" + param \"provider\" → \"SSOProvider\".\n const opContext = serviceName;\n const pathParams = extractParams(allParams, 'path', opContext);\n const queryParams = extractParams(allParams, 'query', opContext);\n const headerParams = extractParams(allParams, 'header', opContext).filter(\n (p) => p.name.toLowerCase() !== 'idempotency-key',\n );\n const cookieParams = extractParams(allParams, 'cookie', opContext);\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 // Extract per-operation security overrides\n const security = extractOperationSecurity(op.security);\n\n // Extract mutually-exclusive parameter groups (query/path/header/cookie)\n const allIRParams = [...pathParams, ...queryParams, ...headerParams, ...cookieParams];\n const opLabel = op.operationId ?? `${method.toUpperCase()} ${path}`;\n const queryParamGroups = extractParameterGroups(op, allIRParams, opLabel);\n\n // Extract mutually-exclusive body parameter groups\n const bodyParamGroups = extractBodyParameterGroups(op, opLabel);\n\n // Merge both sources into a single parameterGroups array\n const parameterGroups =\n queryParamGroups || bodyParamGroups ? [...(queryParamGroups ?? []), ...(bodyParamGroups ?? [])] : undefined;\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 security,\n parameterGroups,\n },\n inlineModels,\n };\n}\n\n/**\n * Extract per-operation security requirements from an OpenAPI security directive.\n * Returns undefined when the operation uses the spec-level default security.\n *\n * OpenAPI security format: `security: [{ schemeName: [scope1, scope2] }]`\n */\nfunction extractOperationSecurity(\n security: Array<Record<string, string[]>> | undefined,\n): SecurityRequirement[] | undefined {\n if (!security || security.length === 0) return undefined;\n\n const requirements: SecurityRequirement[] = [];\n for (const entry of security) {\n for (const [schemeName, scopes] of Object.entries(entry)) {\n requirements.push({ schemeName, scopes: scopes ?? [] });\n }\n }\n return requirements.length > 0 ? requirements : undefined;\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(\n params: ParameterObject[],\n location: 'path' | 'query' | 'header' | 'cookie',\n operationContext?: string,\n): Parameter[] {\n return params\n .filter((p) => p.in === location)\n .map((p) => ({\n name: p.name,\n type: p.schema\n ? schemaToTypeRef(p.schema, p.name, operationContext ? toPascalCase(operationContext) : undefined)\n : ({ 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 style: p.style as Parameter['style'],\n explode: p.explode,\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 >= 300 && code < 400) {\n // 3xx redirects — include so emitter can detect redirect endpoints\n allSuccessResponses.push({ statusCode: code, type: { kind: 'primitive', type: 'unknown' } });\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, Service } 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\n/**\n * Collect inline enum definitions from operation parameters (query, path, header)\n * and promote them to top-level enums so emitters can generate typed enum files.\n */\nexport function collectInlineEnumsFromOperations(services: Service[], enums: Enum[]): void {\n const enumNames = new Set(enums.map((e) => e.name));\n for (const service of services) {\n for (const op of service.operations) {\n for (const param of [...op.pathParams, ...op.queryParams, ...op.headerParams, ...(op.cookieParams ?? [])]) {\n collectInlineEnumFromRef(param.type, enums, enumNames);\n }\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 { defaultSdkBehavior } from '../ir/sdk-behavior.js';\nimport { SpecParseError } from '../errors.js';\nimport { loadAndBundleSpec } from './refs.js';\nimport { extractSchemas, extractInlineModelsFromSchemas, clearSchemaNameTransform } from './schemas.js';\nimport { extractOperations } from './operations.js';\nimport {\n mergeInlineResponseModels,\n collapseJsonSuffixModels,\n mergeFieldInlineModels,\n} from './normalize-inline-models.js';\nimport { collectInlineEnumsFromModels, collectInlineEnumsFromOperations } from './collect-inline-enums.js';\nimport { validateModelRefs } from './normalize-model-refs.js';\n\nexport interface ParseOptions {\n operationIdTransform?: (id: string) => string;\n schemaNameTransform?: (name: 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 { schemaNameTransform: options?.schemaNameTransform },\n );\n\n const { services, inlineModels } = extractOperations(\n spec.paths as Record<string, Record<string, unknown>> | undefined,\n options?.operationIdTransform,\n );\n\n // schemaNameTransform is kept active through extractOperations so that\n // $ref-based TypeRefs in operations resolve to the same transformed names.\n // Now that all extraction is done, clear it.\n clearSchemaNameTransform();\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 collectInlineEnumsFromOperations(services, 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 sdk: defaultSdkBehavior(),\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","import { parseSpec } from '../parser/parse.js';\n\nexport async function parseCommand(opts: { spec: string }): Promise<void> {\n const ir = await parseSpec(opts.spec);\n console.log(JSON.stringify(ir, null, 2));\n}\n","import type Parser from 'tree-sitter';\nimport type { UrlFingerprintConfig } from './types.js';\n\n/**\n * Extract a URL path fingerprint from a method body using tree-sitter AST traversal.\n *\n * Walks the AST subtree of the member node looking for the first string literal\n * that starts with '/'. Normalizes interpolation expressions to '{}' and format\n * specifiers (%s, %d, etc.) to '{}' for cross-language comparison.\n *\n * @returns A normalized URL fingerprint like \"/organizations/{}\" or undefined if none found.\n */\nexport function extractUrlFingerprint(memberNode: Parser.SyntaxNode, config: UrlFingerprintConfig): string | undefined {\n const stringTypes = new Set(config.stringNodeTypes);\n const contentTypes = new Set(config.contentNodeTypes);\n const interpolationTypes = new Set(config.interpolationNodeTypes);\n const formatFns = config.formatFunctionNames ? new Set(config.formatFunctionNames) : null;\n\n // Iterative DFS through the method's AST subtree\n const stack: Parser.SyntaxNode[] = [memberNode];\n\n while (stack.length > 0) {\n const node = stack.pop()!;\n\n if (stringTypes.has(node.type)) {\n const fp = resolveFingerprint(node, contentTypes, interpolationTypes);\n if (fp?.startsWith('/')) return fp;\n }\n\n // For format functions (Go's Sprintf, Rust's format!): check if this call\n // matches and extract the first string argument.\n if (formatFns && isFormatCall(node, formatFns)) {\n const fp = extractFromFormatCall(node, stringTypes, contentTypes, interpolationTypes);\n if (fp?.startsWith('/')) return fp;\n }\n\n // Push children in reverse order so leftmost child is processed first\n for (let i = node.childCount - 1; i >= 0; i--) {\n const child = node.child(i);\n if (child) stack.push(child);\n }\n }\n\n return undefined;\n}\n\n/**\n * Resolve the text content of a string node, normalizing interpolations to '{}'.\n */\nfunction resolveFingerprint(\n stringNode: Parser.SyntaxNode,\n contentTypes: Set<string>,\n interpolationTypes: Set<string>,\n): string | undefined {\n // Leaf string node (no children besides quotes) — strip quotes\n if (stringNode.namedChildCount === 0) {\n return normalizeFormatSpecifiers(stripQuotes(stringNode.text));\n }\n\n // Composite string (has content fragments + interpolation children)\n let result = '';\n for (let i = 0; i < stringNode.childCount; i++) {\n const child = stringNode.child(i)!;\n if (contentTypes.has(child.type)) {\n result += child.text;\n } else if (interpolationTypes.has(child.type)) {\n result += '{}';\n }\n // Skip quote delimiters, interpolation markers, etc.\n }\n\n return result ? normalizeFormatSpecifiers(result) : normalizeFormatSpecifiers(stripQuotes(stringNode.text));\n}\n\n/** Check if a node is a call to one of the format functions (e.g., fmt.Sprintf, format!). */\nfunction isFormatCall(node: Parser.SyntaxNode, formatFns: Set<string>): boolean {\n // Rust macro: format!(...) — tree-sitter may parse as macro_invocation\n if (node.type === 'macro_invocation') {\n const macroName = node.childForFieldName('macro')?.text;\n return !!(macroName && formatFns.has(macroName.replace(/!$/, '')));\n }\n\n if (node.type !== 'call_expression') return false;\n const fnNode = node.childForFieldName('function');\n if (!fnNode) return false;\n\n // Direct call: Sprintf(...) or format!(...)\n if (formatFns.has(fnNode.text)) return true;\n\n // Member call: fmt.Sprintf(...)\n if (fnNode.type === 'selector_expression' || fnNode.type === 'member_expression') {\n const prop = fnNode.childForFieldName('field') ?? fnNode.childForFieldName('property');\n if (prop && formatFns.has(prop.text)) return true;\n }\n return false;\n}\n\n/** Extract the first string argument from a format function call. */\nfunction extractFromFormatCall(\n callNode: Parser.SyntaxNode,\n stringTypes: Set<string>,\n contentTypes: Set<string>,\n interpolationTypes: Set<string>,\n): string | undefined {\n const args = callNode.childForFieldName('arguments');\n if (!args) return undefined;\n\n for (let i = 0; i < args.childCount; i++) {\n const arg = args.child(i)!;\n if (stringTypes.has(arg.type)) {\n return resolveFingerprint(arg, contentTypes, interpolationTypes);\n }\n }\n return undefined;\n}\n\n/** Strip surrounding quote characters from a string literal. */\nfunction stripQuotes(text: string): string {\n // Handle various quote styles: \"...\", '...', `...`, f\"...\", $\"...\", @\"...\"\n const match = text.match(/^(?:f|r|b|@|\\$)?(?:\"\"\"([\\s\\S]*)\"\"\"|'''([\\s\\S]*)'''|\"(.*)\"|'(.*)'|`(.*)`)$/s);\n if (match) return match[1] ?? match[2] ?? match[3] ?? match[4] ?? match[5] ?? text;\n return text;\n}\n\n/** Replace printf-style format specifiers (%s, %d, %v, %f) with {}. */\nfunction normalizeFormatSpecifiers(s: string): string {\n return s.replace(/%[sdvf]/g, '{}');\n}\n","import type Parser from 'tree-sitter';\nimport type {\n MergeAdapter,\n MergeStatement,\n MergeImport,\n DocstringInfo,\n SymbolDocstrings,\n MemberDocstrings,\n} from './types.js';\nimport { extractUrlFingerprint } from './url-fingerprint.js';\n\nconst DOTNET_URL_FINGERPRINT_CONFIG = {\n stringNodeTypes: ['string_literal', 'interpolated_string_expression'],\n contentNodeTypes: ['string_content', 'string_literal_content'],\n interpolationNodeTypes: ['interpolation'],\n};\n\nconst DECLARATION_TYPES = new Set([\n 'class_declaration',\n 'struct_declaration',\n 'interface_declaration',\n 'enum_declaration',\n 'record_declaration',\n]);\n\nfunction extractDeclarationName(node: Parser.SyntaxNode): string | null {\n if (DECLARATION_TYPES.has(node.type)) {\n const nameNode = node.childForFieldName('name') ?? node.children.find((c) => c.type === 'identifier');\n return nameNode?.text ?? null;\n }\n if (node.type === 'namespace_declaration' || node.type === 'file_scoped_namespace_declaration') {\n const nameNode =\n node.children.find((c) => c.type === 'qualified_name') ?? node.children.find((c) => c.type === 'identifier');\n return nameNode ? `__namespace:${nameNode.text}` : null;\n }\n return null;\n}\n\nfunction collectPrecedingXmlDocComments(\n children: Parser.SyntaxNode[],\n index: number,\n source: string,\n): DocstringInfo | null {\n let lastIdx = -1;\n let firstIdx = -1;\n for (let k = index - 1; k >= 0; k--) {\n const prev = children[k];\n if (prev.type === 'comment') {\n const text = source.slice(prev.startIndex, prev.endIndex);\n if (text.startsWith('///')) {\n if (lastIdx === -1) lastIdx = k;\n firstIdx = k;\n } else {\n break;\n }\n } else {\n break;\n }\n }\n if (firstIdx === -1) return null;\n const first = children[firstIdx];\n const last = children[lastIdx];\n return { text: source.slice(first.startIndex, last.endIndex), startIndex: first.startIndex, endIndex: last.endIndex };\n}\n\n/**\n * Collect declarations from a list of sibling nodes (root level or namespace body).\n */\nfunction collectDeclarations(\n children: Parser.SyntaxNode[],\n source: string,\n statements: MergeStatement[],\n imports: MergeImport[],\n importAnchors: string[],\n importInsertionAnchor: { value?: string },\n): void {\n for (const child of children) {\n if (child.type === 'comment') continue;\n\n if (child.type === 'using_directive') {\n const text = source.slice(child.startIndex, child.endIndex);\n imports.push({ key: text.trim(), text });\n importAnchors.push(text);\n continue;\n }\n\n if (child.type === 'file_scoped_namespace_declaration') {\n importInsertionAnchor.value = source.slice(child.startIndex, child.endIndex);\n // File-scoped namespace: subsequent declarations are siblings at root\n continue;\n }\n\n if (child.type === 'namespace_declaration') {\n importInsertionAnchor.value = source.slice(child.startIndex, child.endIndex);\n // Block namespace: recurse into declaration_list\n const body = child.children.find((c) => c.type === 'declaration_list');\n if (body) {\n collectDeclarations(body.namedChildren, source, statements, imports, importAnchors, importInsertionAnchor);\n }\n continue;\n }\n\n const name = extractDeclarationName(child);\n statements.push({\n key: name,\n kind: name ? 'declaration' : 'other',\n text: source.slice(child.startIndex, child.endIndex),\n });\n }\n}\n\nexport const dotnetMergeAdapter: MergeAdapter = {\n language: 'dotnet',\n grammarModule: 'tree-sitter-c-sharp',\n testFilePatterns: [/Tests?\\.cs$/],\n urlFingerprintConfig: DOTNET_URL_FINGERPRINT_CONFIG,\n parseStatements(tree, source) {\n const imports: MergeImport[] = [];\n const importAnchors: string[] = [];\n const statements: MergeStatement[] = [];\n const importInsertionAnchor: { value?: string } = {};\n\n collectDeclarations(tree.rootNode.children, source, statements, imports, importAnchors, importInsertionAnchor);\n\n return {\n imports,\n importAnchors,\n importInsertionAnchor: importInsertionAnchor.value,\n statements,\n };\n },\n renderImports(imports) {\n return imports.map((entry) => entry.text);\n },\n extractDocstrings(tree, source) {\n const result = new Map<string, SymbolDocstrings>();\n\n function processChildren(children: Parser.SyntaxNode[]): void {\n for (let i = 0; i < children.length; i++) {\n const child = children[i];\n\n // Recurse into namespaces\n if (child.type === 'namespace_declaration') {\n const body = child.children.find((c) => c.type === 'declaration_list');\n if (body) processChildren(body.children);\n continue;\n }\n\n const name = extractDeclarationName(child);\n if (!name || name.startsWith('__namespace:')) continue;\n\n const docstring = collectPrecedingXmlDocComments(children, i, source);\n const members = new Map<string, MemberDocstrings>();\n\n // Extract member docstrings\n const body = child.children.find((c) => c.type === 'declaration_list');\n if (body) {\n const bodyChildren = body.children;\n for (let j = 0; j < bodyChildren.length; j++) {\n const member = bodyChildren[j];\n if (member.type !== 'method_declaration' && member.type !== 'property_declaration') continue;\n // For methods, the second identifier is the name (first is return type)\n const identifiers = member.children.filter((c) => c.type === 'identifier');\n const memberName =\n member.type === 'method_declaration'\n ? identifiers.length >= 2\n ? identifiers[1]!.text\n : identifiers[0]?.text\n : identifiers[0]?.text;\n if (!memberName) continue;\n const memberDoc = collectPrecedingXmlDocComments(bodyChildren, j, source);\n members.set(memberName, {\n docstring: memberDoc,\n declStartIndex: member.startIndex,\n declColumn: member.startPosition.column,\n urlFingerprint: extractUrlFingerprint(member, DOTNET_URL_FINGERPRINT_CONFIG),\n });\n }\n }\n\n result.set(name, {\n docstring,\n declStartIndex: child.startIndex,\n declColumn: child.startPosition.column,\n members,\n });\n }\n }\n\n processChildren(tree.rootNode.children);\n return result;\n },\n};\n","import type Parser from 'tree-sitter';\nimport type {\n MergeAdapter,\n MergeStatement,\n MergeImport,\n DocstringInfo,\n SymbolDocstrings,\n MemberDocstrings,\n} from './types.js';\nimport { extractUrlFingerprint } from './url-fingerprint.js';\n\nconst ELIXIR_URL_FINGERPRINT_CONFIG = {\n stringNodeTypes: ['string'],\n contentNodeTypes: ['quoted_content'],\n interpolationNodeTypes: ['interpolation'],\n};\n\nfunction isDefmodule(node: Parser.SyntaxNode): boolean {\n return node.type === 'call' && node.children[0]?.text === 'defmodule';\n}\n\nfunction getModuleName(node: Parser.SyntaxNode): string | null {\n if (!isDefmodule(node)) return null;\n const args = node.children.find((c) => c.type === 'arguments');\n if (!args) return null;\n const alias = args.children.find((c) => c.type === 'alias');\n return alias?.text ?? null;\n}\n\nfunction getDoBlock(node: Parser.SyntaxNode): Parser.SyntaxNode | null {\n return node.children.find((c) => c.type === 'do_block') ?? null;\n}\n\n/** Check if a node is an @moduledoc or @doc attribute. */\nfunction isDocAttribute(node: Parser.SyntaxNode): string | null {\n if (node.type !== 'unary_operator') return null;\n const call = node.children.find((c) => c.type === 'call');\n if (!call) return null;\n const id = call.children.find((c) => c.type === 'identifier');\n if (id?.text === 'moduledoc' || id?.text === 'doc') return id.text;\n return null;\n}\n\n/** Check if a node is a def/defp call. */\nfunction getDefName(node: Parser.SyntaxNode): string | null {\n if (node.type !== 'call') return null;\n const id = node.children[0];\n if (!id || (id.text !== 'def' && id.text !== 'defp')) return null;\n const args = node.children.find((c) => c.type === 'arguments');\n if (!args) return null;\n // The function name is either a simple identifier or a call (for functions with params)\n for (const arg of args.namedChildren) {\n if (arg.type === 'identifier') return arg.text;\n if (arg.type === 'call') {\n const nameNode = arg.children.find((c) => c.type === 'identifier');\n return nameNode?.text ?? null;\n }\n }\n return null;\n}\n\n/** Check if a node is an alias/import/require/use call. */\nfunction isImportLike(node: Parser.SyntaxNode): boolean {\n if (node.type !== 'call') return false;\n const id = node.children[0];\n return id?.type === 'identifier' && ['alias', 'import', 'require', 'use'].includes(id.text);\n}\n\nexport const elixirMergeAdapter: MergeAdapter = {\n language: 'elixir',\n grammarModule: 'tree-sitter-elixir',\n testFilePatterns: [/_test\\.exs$/],\n urlFingerprintConfig: ELIXIR_URL_FINGERPRINT_CONFIG,\n parseStatements(tree, source) {\n const imports: MergeImport[] = [];\n const importAnchors: string[] = [];\n const statements: MergeStatement[] = [];\n\n for (const child of tree.rootNode.children) {\n if (child.type === 'comment') continue;\n\n // Top-level alias/import/require/use (rare but possible outside modules)\n if (isImportLike(child)) {\n const text = source.slice(child.startIndex, child.endIndex);\n imports.push({ key: text.trim(), text });\n importAnchors.push(text);\n continue;\n }\n\n const moduleName = getModuleName(child);\n statements.push({\n key: moduleName,\n kind: moduleName ? 'declaration' : 'other',\n text: source.slice(child.startIndex, child.endIndex),\n });\n }\n\n return { imports, importAnchors, statements };\n },\n renderImports(imports) {\n return imports.map((entry) => entry.text);\n },\n extractDocstrings(tree, source) {\n const result = new Map<string, SymbolDocstrings>();\n const rootChildren = tree.rootNode.children;\n\n for (let i = 0; i < rootChildren.length; i++) {\n const child = rootChildren[i];\n const moduleName = getModuleName(child);\n if (!moduleName) continue;\n\n // Look for @moduledoc inside the do_block\n let docstring: DocstringInfo | null = null;\n const doBlock = getDoBlock(child);\n const members = new Map<string, MemberDocstrings>();\n\n if (doBlock) {\n const bodyChildren = doBlock.children;\n\n // Find @moduledoc\n for (const bodyChild of bodyChildren) {\n if (isDocAttribute(bodyChild) === 'moduledoc') {\n docstring = {\n text: source.slice(bodyChild.startIndex, bodyChild.endIndex),\n startIndex: bodyChild.startIndex,\n endIndex: bodyChild.endIndex,\n };\n break;\n }\n }\n\n // Find @doc + def pairs for member docstrings\n for (let j = 0; j < bodyChildren.length; j++) {\n const bodyChild = bodyChildren[j];\n const defName = getDefName(bodyChild);\n if (!defName) continue;\n\n // Look for preceding @doc attribute\n let memberDoc: DocstringInfo | null = null;\n for (let k = j - 1; k >= 0; k--) {\n const prev = bodyChildren[k];\n if (isDocAttribute(prev) === 'doc') {\n memberDoc = {\n text: source.slice(prev.startIndex, prev.endIndex),\n startIndex: prev.startIndex,\n endIndex: prev.endIndex,\n };\n break;\n }\n if (prev.type === 'comment') continue;\n break;\n }\n\n members.set(defName, {\n docstring: memberDoc,\n declStartIndex: bodyChild.startIndex,\n declColumn: bodyChild.startPosition.column,\n urlFingerprint: extractUrlFingerprint(bodyChild, ELIXIR_URL_FINGERPRINT_CONFIG),\n });\n }\n }\n\n result.set(moduleName, {\n docstring,\n declStartIndex: child.startIndex,\n declColumn: child.startPosition.column,\n members,\n });\n }\n\n return result;\n },\n};\n","import type Parser from 'tree-sitter';\nimport type { MergeAdapter, MergeStatement, MergeImport, DocstringInfo, SymbolDocstrings } from './types.js';\n\nconst GO_URL_FINGERPRINT_CONFIG = {\n stringNodeTypes: ['interpreted_string_literal'],\n contentNodeTypes: ['interpreted_string_literal_content'],\n interpolationNodeTypes: [],\n formatFunctionNames: ['Sprintf'],\n};\n\nfunction lastIdentifier(text: string): string | null {\n const matches = [...text.matchAll(/[A-Za-z_][A-Za-z0-9_]*/g)];\n return matches.length > 0 ? matches[matches.length - 1]![0] : null;\n}\n\nfunction receiverKey(node: Parser.SyntaxNode): string | null {\n const receiver = node.childForFieldName('receiver');\n if (!receiver) return null;\n return lastIdentifier(receiver.text);\n}\n\nfunction declarationKey(node: Parser.SyntaxNode): string | null {\n switch (node.type) {\n case 'package_clause': {\n const pkg = lastIdentifier(node.text);\n return pkg ? `__package:${pkg}` : '__package:';\n }\n case 'type_declaration': {\n const spec = node.firstNamedChild?.type === 'type_spec' ? node.firstNamedChild : node.namedChildren[0];\n const nameNode = spec?.childForFieldName('name');\n return nameNode?.text ?? null;\n }\n case 'function_declaration': {\n return node.childForFieldName('name')?.text ?? null;\n }\n case 'method_declaration': {\n const name = node.childForFieldName('name')?.text ?? null;\n const receiver = receiverKey(node);\n return name && receiver ? `method:${receiver}.${name}` : name;\n }\n case 'const_declaration':\n case 'var_declaration': {\n return node.text.split(/\\s+/).slice(0, 3).join(' ');\n }\n default:\n return null;\n }\n}\n\nfunction importEntries(node: Parser.SyntaxNode, source: string): MergeImport[] {\n const entries: MergeImport[] = [];\n\n const collect = (spec: Parser.SyntaxNode): void => {\n const path = spec.childForFieldName('path')?.text ?? spec.text;\n const name = spec.childForFieldName('name')?.text ?? '';\n const text = source.slice(spec.startIndex, spec.endIndex);\n entries.push({\n key: `${name}:${path.replace(/^\"|\"$/g, '')}`,\n text,\n });\n };\n\n for (const child of node.namedChildren) {\n if (child.type === 'import_spec') {\n collect(child);\n continue;\n }\n if (child.type === 'import_spec_list') {\n for (const spec of child.namedChildren) {\n if (spec.type === 'import_spec') collect(spec);\n }\n }\n }\n\n return entries;\n}\n\nfunction collectPrecedingGoComments(\n children: Parser.SyntaxNode[],\n index: number,\n source: string,\n): DocstringInfo | null {\n let lastIdx = -1;\n let firstIdx = -1;\n for (let k = index - 1; k >= 0; k--) {\n const prev = children[k];\n if (prev.type === 'comment') {\n const text = source.slice(prev.startIndex, prev.endIndex);\n if (text.startsWith('//')) {\n if (lastIdx === -1) lastIdx = k;\n firstIdx = k;\n } else {\n break;\n }\n } else {\n break;\n }\n }\n if (firstIdx === -1) return null;\n const first = children[firstIdx];\n const last = children[lastIdx];\n return { text: source.slice(first.startIndex, last.endIndex), startIndex: first.startIndex, endIndex: last.endIndex };\n}\n\nexport const goMergeAdapter: MergeAdapter = {\n language: 'go',\n grammarModule: 'tree-sitter-go',\n testFilePatterns: [/_test\\.go$/],\n urlFingerprintConfig: GO_URL_FINGERPRINT_CONFIG,\n parseStatements(tree, source) {\n const imports: MergeImport[] = [];\n const importAnchors: string[] = [];\n let importInsertionAnchor: string | undefined;\n const statements: MergeStatement[] = [];\n\n for (const child of tree.rootNode.children) {\n if (child.type === 'comment') continue;\n\n if (child.type === 'package_clause') {\n importInsertionAnchor = source.slice(child.startIndex, child.endIndex);\n }\n\n if (child.type === 'import_declaration') {\n imports.push(...importEntries(child, source));\n importAnchors.push(source.slice(child.startIndex, child.endIndex));\n continue;\n }\n\n const key = declarationKey(child);\n statements.push({\n key,\n kind: key ? 'declaration' : 'other',\n text: source.slice(child.startIndex, child.endIndex),\n });\n }\n\n return { imports, importAnchors, importInsertionAnchor, statements };\n },\n renderImports(imports) {\n if (imports.length === 0) return [];\n if (imports.length === 1) return [`import ${imports[0]!.text}`];\n return [`import (\\n${imports.map((entry) => ` ${entry.text}`).join('\\n')}\\n)`];\n },\n extractDocstrings(tree, source) {\n const result = new Map<string, SymbolDocstrings>();\n const rootChildren = tree.rootNode.children;\n\n for (let i = 0; i < rootChildren.length; i++) {\n const child = rootChildren[i];\n const key = declarationKey(child);\n if (!key || key.startsWith('__package:')) continue;\n\n const docstring = collectPrecedingGoComments(rootChildren, i, source);\n result.set(key, {\n docstring,\n declStartIndex: child.startIndex,\n declColumn: child.startPosition.column,\n members: new Map(),\n });\n }\n\n return result;\n },\n};\n","import type Parser from 'tree-sitter';\nimport type {\n MergeAdapter,\n MergeStatement,\n MergeImport,\n MergeMember,\n DeepMergeSymbol,\n DocstringInfo,\n SymbolDocstrings,\n MemberDocstrings,\n} from './types.js';\nimport { extractUrlFingerprint } from './url-fingerprint.js';\n\nconst KOTLIN_URL_FINGERPRINT_CONFIG = {\n stringNodeTypes: ['string_literal'],\n contentNodeTypes: ['string_content'],\n interpolationNodeTypes: ['interpolated_expression'],\n};\n\nfunction extractDeclarationName(node: Parser.SyntaxNode): string | null {\n if (node.type === 'class_declaration') {\n // Handles class, data class, enum class, etc.\n const nameNode = node.children.find((c) => c.type === 'type_identifier');\n return nameNode?.text ?? null;\n }\n if (node.type === 'function_declaration') {\n const nameNode = node.children.find((c) => c.type === 'simple_identifier');\n return nameNode?.text ?? null;\n }\n if (node.type === 'object_declaration') {\n const nameNode = node.children.find((c) => c.type === 'type_identifier');\n return nameNode?.text ?? null;\n }\n if (node.type === 'type_alias') {\n const nameNode = node.children.find((c) => c.type === 'type_identifier');\n return nameNode?.text ?? null;\n }\n if (node.type === 'property_declaration') {\n const nameNode = node.children.find((c) => c.type === 'variable_declaration');\n if (nameNode) {\n const id = nameNode.children.find((c) => c.type === 'simple_identifier');\n return id?.text ?? null;\n }\n }\n return null;\n}\n\nfunction findPrecedingKdoc(children: Parser.SyntaxNode[], index: number, source: string): DocstringInfo | null {\n for (let k = index - 1; k >= 0; k--) {\n const prev = children[k];\n if (prev.type === 'multiline_comment') {\n const text = source.slice(prev.startIndex, prev.endIndex);\n if (text.startsWith('/**')) {\n return { text, startIndex: prev.startIndex, endIndex: prev.endIndex };\n }\n return null;\n }\n if (prev.type === 'line_comment') continue;\n return null;\n }\n return null;\n}\n\nfunction extractKotlinClassMembers(classBody: Parser.SyntaxNode, source: string): MergeMember[] {\n const members: MergeMember[] = [];\n const children = classBody.namedChildren;\n\n for (let i = 0; i < children.length; i++) {\n const child = children[i];\n let memberName: string | null = null;\n\n if (child.type === 'property_declaration') {\n const varDecl = child.children.find((c) => c.type === 'variable_declaration');\n memberName = varDecl?.children.find((c) => c.type === 'simple_identifier')?.text ?? null;\n } else if (child.type === 'function_declaration') {\n memberName = child.children.find((c) => c.type === 'simple_identifier')?.text ?? null;\n } else if (child.type === 'companion_object') {\n memberName = 'companion';\n }\n\n if (!memberName) continue;\n\n // Fold trailing getter/setter into the property's text span\n let endIdx = child.endIndex;\n if (child.type === 'property_declaration') {\n while (i + 1 < children.length) {\n const next = children[i + 1];\n if (next.type === 'getter' || next.type === 'setter') {\n endIdx = next.endIndex;\n i++;\n } else {\n break;\n }\n }\n }\n\n // Include preceding KDoc comment in the text span so deep merge\n // inserts the member with its documentation intact.\n let startIdx = child.startIndex;\n for (let k = i - 1; k >= 0; k--) {\n const prev = children[k];\n if (prev.type === 'multiline_comment') {\n const text = source.slice(prev.startIndex, prev.endIndex);\n if (text.startsWith('/**')) startIdx = prev.startIndex;\n break;\n }\n if (prev.type === 'line_comment') continue;\n break;\n }\n\n members.push({ key: memberName, text: source.slice(startIdx, endIdx) });\n }\n\n return members;\n}\n\nexport const kotlinMergeAdapter: MergeAdapter = {\n language: 'kotlin',\n grammarModule: 'tree-sitter-kotlin',\n testFilePatterns: [/Test\\.kt$/],\n urlFingerprintConfig: KOTLIN_URL_FINGERPRINT_CONFIG,\n parseStatements(tree, source) {\n const imports: MergeImport[] = [];\n const importAnchors: string[] = [];\n const statements: MergeStatement[] = [];\n\n for (const child of tree.rootNode.children) {\n if (child.type === 'multiline_comment' || child.type === 'line_comment') continue;\n\n if (child.type === 'import_list') {\n const fullText = source.slice(child.startIndex, child.endIndex);\n importAnchors.push(fullText);\n for (const imp of child.namedChildren) {\n if (imp.type === 'import_header') {\n const text = source.slice(imp.startIndex, imp.endIndex).trim();\n // Key on the full import path\n const idNode = imp.children.find((c) => c.type === 'identifier');\n const key = idNode?.text ?? text;\n imports.push({ key, text });\n }\n }\n continue;\n }\n\n const name = extractDeclarationName(child);\n statements.push({\n key: name,\n kind: name ? 'declaration' : 'other',\n text: source.slice(child.startIndex, child.endIndex),\n });\n }\n\n return { imports, importAnchors, statements };\n },\n renderImports(imports) {\n return imports.map((entry) => entry.text);\n },\n shouldSkipDeepMerge(_symbolName, existingMemberKeys, newMembers) {\n // Skip if new members reference instance properties that don't exist in the target\n const newText = newMembers.map((m) => m.text).join('\\n');\n for (const match of newText.matchAll(/this\\.(\\w+)/g)) {\n const propName = match[1];\n if (propName && !existingMemberKeys.has(propName)) return true;\n }\n return false;\n },\n extractMembers(tree, source) {\n const result = new Map<string, DeepMergeSymbol>();\n\n for (const child of tree.rootNode.children) {\n if (child.type !== 'class_declaration') continue;\n const nameNode = child.children.find((c) => c.type === 'type_identifier');\n if (!nameNode) continue;\n const body = child.children.find((c) => c.type === 'class_body');\n if (!body) continue;\n\n const members = extractKotlinClassMembers(body, source);\n const firstMember = body.firstNamedChild;\n const memberIndent = firstMember ? ' '.repeat(firstMember.startPosition.column) : undefined;\n result.set(nameNode.text, { members, bodyEndLine: body.endPosition.row, memberIndent });\n }\n\n return result;\n },\n extractDocstrings(tree, source) {\n const result = new Map<string, SymbolDocstrings>();\n const rootChildren = tree.rootNode.children;\n\n for (let i = 0; i < rootChildren.length; i++) {\n const child = rootChildren[i];\n const name = extractDeclarationName(child);\n if (!name) continue;\n\n const docstring = findPrecedingKdoc(rootChildren, i, source);\n const members = new Map<string, MemberDocstrings>();\n\n // Extract member docstrings for classes\n if (child.type === 'class_declaration') {\n const body = child.children.find((c) => c.type === 'class_body' || c.type === 'enum_class_body');\n if (body) {\n const bodyChildren = body.children;\n for (let j = 0; j < bodyChildren.length; j++) {\n const member = bodyChildren[j];\n const memberName = extractDeclarationName(member);\n if (!memberName) continue;\n const memberDoc = findPrecedingKdoc(bodyChildren, j, source);\n members.set(memberName, {\n docstring: memberDoc,\n declStartIndex: member.startIndex,\n declColumn: member.startPosition.column,\n urlFingerprint: extractUrlFingerprint(member, KOTLIN_URL_FINGERPRINT_CONFIG),\n });\n }\n }\n }\n\n result.set(name, {\n docstring,\n declStartIndex: child.startIndex,\n declColumn: child.startPosition.column,\n members,\n });\n }\n\n return result;\n },\n};\n","import type Parser from 'tree-sitter';\nimport { normalizeJsExtension } from '../../utils/naming.js';\nimport type {\n MergeAdapter,\n MergeStatement,\n MergeImport,\n DeepMergeSymbol,\n MergeMember,\n DocstringInfo,\n SymbolDocstrings,\n} from './types.js';\nimport { extractUrlFingerprint } from './url-fingerprint.js';\n\nconst REEXPORT_PREFIX = '__export:';\n\nfunction extractDeclName(node: Parser.SyntaxNode): string | null {\n const nameNode = node.childForFieldName('name');\n if (nameNode) return nameNode.text;\n\n if (node.type === 'lexical_declaration') {\n const declarator = node.firstNamedChild;\n if (declarator?.type === 'variable_declarator') {\n const name = declarator.childForFieldName('name');\n if (name) return name.text;\n }\n }\n\n return null;\n}\n\nfunction extractNodeKey(node: Parser.SyntaxNode): { key: string | null; kind: MergeStatement['kind'] } {\n if (node.type === 'export_statement') {\n const decl = node.childForFieldName('declaration');\n if (decl) {\n return { key: extractDeclName(decl), kind: 'declaration' };\n }\n\n const source = node.childForFieldName('source');\n if (source) {\n return { key: `${REEXPORT_PREFIX}${normalizeJsExtension(source.text)}`, kind: 'reexport' };\n }\n\n return { key: null, kind: 'other' };\n }\n return { key: extractDeclName(node), kind: extractDeclName(node) ? 'declaration' : 'other' };\n}\n\nfunction extractClassMembers(classBody: Parser.SyntaxNode, source: string): MergeMember[] {\n const members: MergeMember[] = [];\n for (const child of classBody.namedChildren) {\n if (child.type === 'method_definition') {\n const nameNode = child.childForFieldName('name');\n if (nameNode && nameNode.text !== 'constructor') {\n members.push({ key: nameNode.text, text: source.slice(child.startIndex, child.endIndex) });\n }\n } else if (child.type === 'public_field_definition') {\n const nameNode = child.childForFieldName('name');\n if (nameNode) {\n // tree-sitter may exclude the trailing semicolon from\n // public_field_definition nodes — include it if present\n let endIdx = child.endIndex;\n if (source[endIdx] === ';') {\n endIdx += 1;\n }\n members.push({ key: nameNode.text, text: source.slice(child.startIndex, endIdx) });\n }\n }\n }\n return members;\n}\n\nfunction extractInterfaceMembers(body: Parser.SyntaxNode, source: string): MergeMember[] {\n const members: MergeMember[] = [];\n for (const child of body.namedChildren) {\n if (child.type === 'property_signature' || child.type === 'method_signature') {\n const nameNode = child.childForFieldName('name');\n if (nameNode) {\n members.push({ key: nameNode.text, text: source.slice(child.startIndex, child.endIndex) });\n }\n }\n }\n return members;\n}\n\nfunction extractEnumMembers(body: Parser.SyntaxNode, source: string): MergeMember[] {\n const members: MergeMember[] = [];\n for (const child of body.namedChildren) {\n if (child.type === 'enum_assignment') {\n const nameNode = child.childForFieldName('name');\n if (nameNode) {\n members.push({ key: nameNode.text, text: source.slice(child.startIndex, child.endIndex) });\n }\n } else if (child.type === 'property_identifier') {\n members.push({ key: child.text, text: source.slice(child.startIndex, child.endIndex) });\n }\n }\n return members;\n}\n\nfunction isCommentNode(node: Parser.SyntaxNode): boolean {\n // tree-sitter extras (comments) may report the parent node's type\n // instead of 'comment' — check grammarType as fallback\n return node.type === 'comment' || (node as any).grammarType === 'comment';\n}\n\nfunction findPrecedingDocstring(children: Parser.SyntaxNode[], index: number, source: string): DocstringInfo | null {\n for (let k = index - 1; k >= 0; k--) {\n const prev = children[k];\n if (isCommentNode(prev)) {\n const text = source.slice(prev.startIndex, prev.endIndex);\n if (text.startsWith('/**')) {\n return { text, startIndex: prev.startIndex, endIndex: prev.endIndex };\n }\n return null;\n }\n if (prev.type === ',' || prev.type === ';' || prev.type === '{') continue;\n return null;\n }\n return null;\n}\n\nconst CLASS_MEMBER_TYPES = new Set(['method_definition', 'public_field_definition']);\nconst INTERFACE_MEMBER_TYPES = new Set(['property_signature', 'method_signature']);\nconst ENUM_MEMBER_TYPES = new Set(['enum_assignment', 'property_identifier']);\n\nconst NODE_URL_FINGERPRINT_CONFIG = {\n stringNodeTypes: ['string', 'template_string'],\n contentNodeTypes: ['string_fragment'],\n interpolationNodeTypes: ['template_substitution'],\n};\n\nfunction extractBodyMemberDocstrings(\n body: Parser.SyntaxNode,\n source: string,\n memberTypes: Set<string>,\n): Map<\n string,\n { docstring: DocstringInfo | null; declStartIndex: number; declColumn: number; urlFingerprint?: string }\n> {\n const result = new Map<\n string,\n { docstring: DocstringInfo | null; declStartIndex: number; declColumn: number; urlFingerprint?: string }\n >();\n const allChildren = body.children;\n for (let i = 0; i < allChildren.length; i++) {\n const child = allChildren[i];\n if (!memberTypes.has(child.type)) continue;\n let memberName: string | null = null;\n if (child.type === 'property_identifier') {\n memberName = child.text;\n } else {\n const nameNode = child.childForFieldName('name');\n if (nameNode) memberName = nameNode.text;\n }\n if (!memberName || memberName === 'constructor') continue;\n const docstring = findPrecedingDocstring(allChildren, i, source);\n const fp = extractUrlFingerprint(child, NODE_URL_FINGERPRINT_CONFIG);\n result.set(memberName, {\n docstring,\n declStartIndex: child.startIndex,\n declColumn: child.startPosition.column,\n urlFingerprint: fp,\n });\n }\n return result;\n}\n\nexport const nodeMergeAdapter: MergeAdapter = {\n language: 'node',\n grammarModule: 'tree-sitter-typescript/bindings/node/typescript.js',\n normalizeReexport: normalizeJsExtension,\n testFilePatterns: [/\\.(spec|test)\\.[jt]sx?$/],\n urlFingerprintConfig: NODE_URL_FINGERPRINT_CONFIG,\n shouldSkipDeepMerge(_symbolName, existingMemberKeys, newMembers) {\n // If new members reference instance properties (this.X) that don't exist\n // in the target class, the merged code would be broken.\n // Exception: `this.workos` is always valid — it's the constructor-injected\n // WorkOS client instance that every generated resource class uses.\n const newText = newMembers.map((m) => m.text).join('\\n');\n for (const match of newText.matchAll(/this\\.(\\w+)/g)) {\n const propName = match[1];\n if (propName === 'workos') continue;\n if (propName && !existingMemberKeys.has(propName)) {\n return true;\n }\n }\n return false;\n },\n parseStatements(tree, source) {\n const imports: MergeImport[] = [];\n const importAnchors: string[] = [];\n const statements: MergeStatement[] = [];\n\n for (const child of tree.rootNode.children) {\n if (child.type === 'comment') continue;\n\n if (child.type === 'import_statement') {\n const text = source.slice(child.startIndex, child.endIndex);\n // Key on module path so `import { X }` and `import type { X }` from\n // the same module are treated as duplicates\n const sourceNode = child.childForFieldName('source');\n const modulePath = sourceNode ? normalizeJsExtension(sourceNode.text) : normalizeJsExtension(text.trim());\n imports.push({ key: modulePath, text });\n importAnchors.push(text);\n continue;\n }\n\n const { key, kind } = extractNodeKey(child);\n statements.push({\n key,\n kind,\n text: source.slice(child.startIndex, child.endIndex),\n });\n }\n\n return { imports, importAnchors, statements };\n },\n renderImports(imports) {\n return imports.map((entry) => entry.text);\n },\n extractMembers(tree, source) {\n const result = new Map<string, DeepMergeSymbol>();\n\n for (const child of tree.rootNode.children) {\n if (child.type !== 'export_statement') continue;\n const decl = child.childForFieldName('declaration');\n if (!decl) continue;\n\n const nameNode = decl.childForFieldName('name');\n if (!nameNode) continue;\n const symbolName = nameNode.text;\n\n if (decl.type === 'class_declaration') {\n const body = decl.childForFieldName('body');\n if (!body) continue;\n const members = extractClassMembers(body, source);\n const firstMember = body.firstNamedChild;\n const memberIndent = firstMember ? ' '.repeat(firstMember.startPosition.column) : undefined;\n result.set(symbolName, { members, bodyEndLine: body.endPosition.row, memberIndent });\n } else if (decl.type === 'interface_declaration') {\n const body = decl.childForFieldName('body');\n if (!body) continue;\n const members = extractInterfaceMembers(body, source);\n const firstMember = body.firstNamedChild;\n const memberIndent = firstMember ? ' '.repeat(firstMember.startPosition.column) : undefined;\n result.set(symbolName, { members, bodyEndLine: body.endPosition.row, memberIndent });\n } else if (decl.type === 'enum_declaration') {\n const body = decl.childForFieldName('body');\n if (!body) continue;\n const members = extractEnumMembers(body, source);\n const firstMember = body.firstNamedChild;\n const memberIndent = firstMember ? ' '.repeat(firstMember.startPosition.column) : undefined;\n result.set(symbolName, { members, bodyEndLine: body.endPosition.row, memberIndent });\n }\n }\n\n return result;\n },\n extractDocstrings(tree, source) {\n const result = new Map<string, SymbolDocstrings>();\n const rootChildren = tree.rootNode.children;\n\n for (let i = 0; i < rootChildren.length; i++) {\n const child = rootChildren[i];\n if (child.type !== 'export_statement') continue;\n const decl = child.childForFieldName('declaration');\n if (!decl) continue;\n const nameNode = decl.childForFieldName('name');\n if (!nameNode) continue;\n\n // Find preceding JSDoc for this top-level symbol\n const docstring = findPrecedingDocstring(rootChildren, i, source);\n\n // Extract member-level docstrings\n let members = new Map<string, { docstring: DocstringInfo | null; declStartIndex: number; declColumn: number }>();\n const body = decl.childForFieldName('body');\n if (body) {\n if (decl.type === 'class_declaration') {\n members = extractBodyMemberDocstrings(body, source, CLASS_MEMBER_TYPES);\n } else if (decl.type === 'interface_declaration') {\n members = extractBodyMemberDocstrings(body, source, INTERFACE_MEMBER_TYPES);\n } else if (decl.type === 'enum_declaration') {\n members = extractBodyMemberDocstrings(body, source, ENUM_MEMBER_TYPES);\n }\n }\n\n result.set(nameNode.text, {\n docstring,\n declStartIndex: child.startIndex,\n declColumn: child.startPosition.column,\n members,\n });\n }\n\n return result;\n },\n};\n","import type Parser from 'tree-sitter';\nimport type {\n MergeAdapter,\n MergeStatement,\n MergeImport,\n DocstringInfo,\n SymbolDocstrings,\n MemberDocstrings,\n} from './types.js';\nimport { extractUrlFingerprint } from './url-fingerprint.js';\n\nconst PHP_URL_FINGERPRINT_CONFIG = {\n stringNodeTypes: ['encapsed_string', 'string'],\n contentNodeTypes: ['string_content'],\n interpolationNodeTypes: ['variable_name'],\n};\n\nfunction extractPhpDeclarationName(node: Parser.SyntaxNode): string | null {\n switch (node.type) {\n case 'class_declaration':\n case 'interface_declaration':\n case 'trait_declaration':\n case 'enum_declaration':\n case 'function_definition': {\n const nameNode = node.childForFieldName('name');\n return nameNode?.text ?? null;\n }\n case 'namespace_definition': {\n const nameNode = node.childForFieldName('name');\n return nameNode ? `__namespace:${nameNode.text}` : '__namespace:';\n }\n default:\n return null;\n }\n}\n\nfunction findPhpDocstring(children: Parser.SyntaxNode[], index: number, source: string): DocstringInfo | null {\n for (let k = index - 1; k >= 0; k--) {\n const prev = children[k];\n if (prev.type === 'comment') {\n const text = source.slice(prev.startIndex, prev.endIndex);\n if (text.startsWith('/**')) {\n return { text, startIndex: prev.startIndex, endIndex: prev.endIndex };\n }\n return null;\n }\n if (prev.type === ';' || prev.type === '{') continue;\n return null;\n }\n return null;\n}\n\nexport const phpMergeAdapter: MergeAdapter = {\n language: 'php',\n grammarModule: 'tree-sitter-php',\n testFilePatterns: [/Test\\.php$/],\n urlFingerprintConfig: PHP_URL_FINGERPRINT_CONFIG,\n resolveGrammar: (mod) => {\n // ESM import wraps in { default: { php, php_only } }\n const m = (mod as Record<string, unknown>)?.default ?? mod;\n if (typeof m === 'object' && m !== null && 'php' in (m as Record<string, unknown>))\n return (m as { php: unknown }).php;\n return m;\n },\n parseStatements(tree, source) {\n const imports: MergeImport[] = [];\n const importAnchors: string[] = [];\n let importInsertionAnchor: string | undefined;\n const statements: MergeStatement[] = [];\n\n for (const child of tree.rootNode.children) {\n if (child.type === 'comment') continue;\n\n if (child.type === 'namespace_definition') {\n importInsertionAnchor = source.slice(child.startIndex, child.endIndex);\n }\n\n if (child.type === 'namespace_use_declaration') {\n const text = source.slice(child.startIndex, child.endIndex);\n imports.push({ key: text.trim(), text });\n importAnchors.push(text);\n continue;\n }\n\n const declarationName = extractPhpDeclarationName(child);\n const kind: MergeStatement['kind'] = declarationName ? 'declaration' : 'other';\n\n statements.push({\n key: declarationName,\n kind,\n text: source.slice(child.startIndex, child.endIndex),\n });\n }\n\n return { imports, importAnchors, importInsertionAnchor, statements };\n },\n renderImports(imports) {\n return imports.map((entry) => entry.text);\n },\n extractDocstrings(tree, source) {\n const result = new Map<string, SymbolDocstrings>();\n const rootChildren = tree.rootNode.children;\n\n for (let i = 0; i < rootChildren.length; i++) {\n const child = rootChildren[i];\n const name = extractPhpDeclarationName(child);\n if (!name || name.startsWith('__namespace:')) continue;\n\n const docstring = findPhpDocstring(rootChildren, i, source);\n const members = new Map<string, MemberDocstrings>();\n\n const body = child.childForFieldName('body');\n if (body) {\n const bodyChildren = body.children;\n for (let j = 0; j < bodyChildren.length; j++) {\n const member = bodyChildren[j];\n if (member.type !== 'method_declaration') continue;\n const memberName = member.childForFieldName('name')?.text;\n if (!memberName) continue;\n const memberDoc = findPhpDocstring(bodyChildren, j, source);\n members.set(memberName, {\n docstring: memberDoc,\n declStartIndex: member.startIndex,\n declColumn: member.startPosition.column,\n urlFingerprint: extractUrlFingerprint(member, PHP_URL_FINGERPRINT_CONFIG),\n });\n }\n }\n\n result.set(name, {\n docstring,\n declStartIndex: child.startIndex,\n declColumn: child.startPosition.column,\n members,\n });\n }\n\n return result;\n },\n};\n","import type Parser from 'tree-sitter';\nimport type {\n MergeAdapter,\n MergeStatement,\n MergeImport,\n DocstringInfo,\n SymbolDocstrings,\n MemberDocstrings,\n} from './types.js';\nimport { extractUrlFingerprint } from './url-fingerprint.js';\n\nconst PYTHON_URL_FINGERPRINT_CONFIG = {\n stringNodeTypes: ['string'],\n contentNodeTypes: ['string_content'],\n interpolationNodeTypes: ['interpolation'],\n};\n\nfunction extractPythonDeclarationName(node: Parser.SyntaxNode): string | null {\n if (node.type === 'class_definition' || node.type === 'function_definition') {\n const nameNode = node.childForFieldName('name');\n return nameNode?.text ?? null;\n }\n\n // Detect `__all__ = [...]` assignments so they get a key and can be deduplicated\n if (node.type === 'expression_statement') {\n const firstChild = node.firstNamedChild;\n if (firstChild?.type === 'assignment') {\n const left = firstChild.childForFieldName('left');\n if (left?.type === 'identifier' && left.text === '__all__') {\n return '__all__';\n }\n }\n }\n\n return null;\n}\n\nfunction extractPythonDocstring(bodyNode: Parser.SyntaxNode, source: string): DocstringInfo | null {\n // Python docstrings are the first expression_statement in a body block\n // where the expression is a string literal\n for (const child of bodyNode.namedChildren) {\n if (child.type === 'expression_statement') {\n const expr = child.firstNamedChild;\n if (expr?.type === 'string') {\n const text = source.slice(child.startIndex, child.endIndex);\n return { text, startIndex: child.startIndex, endIndex: child.endIndex };\n }\n }\n // Only the FIRST statement can be a docstring\n break;\n }\n return null;\n}\n\nfunction collectPrecedingPythonComments(\n children: Parser.SyntaxNode[],\n index: number,\n source: string,\n): DocstringInfo | null {\n let lastIdx = -1;\n let firstIdx = -1;\n for (let k = index - 1; k >= 0; k--) {\n const prev = children[k];\n if (prev.type === 'comment') {\n if (lastIdx === -1) lastIdx = k;\n firstIdx = k;\n } else {\n break;\n }\n }\n if (firstIdx === -1) return null;\n const first = children[firstIdx];\n const last = children[lastIdx];\n return { text: source.slice(first.startIndex, last.endIndex), startIndex: first.startIndex, endIndex: last.endIndex };\n}\n\nexport const pythonMergeAdapter: MergeAdapter = {\n language: 'python',\n grammarModule: 'tree-sitter-python',\n testFilePatterns: [/(?:^|\\/)test_.*\\.py$/, /_test\\.py$/],\n urlFingerprintConfig: PYTHON_URL_FINGERPRINT_CONFIG,\n parseStatements(tree, source) {\n const imports: MergeImport[] = [];\n const importAnchors: string[] = [];\n const statements: MergeStatement[] = [];\n\n for (const child of tree.rootNode.children) {\n if (child.type === 'comment') continue;\n\n if (child.type === 'import_statement' || child.type === 'import_from_statement') {\n const text = source.slice(child.startIndex, child.endIndex);\n imports.push({ key: text.trim(), text });\n importAnchors.push(text);\n continue;\n }\n\n const declarationName = extractPythonDeclarationName(child);\n const kind: MergeStatement['kind'] = declarationName ? 'declaration' : 'other';\n\n statements.push({\n key: declarationName,\n kind,\n text: source.slice(child.startIndex, child.endIndex),\n });\n }\n\n return { imports, importAnchors, statements };\n },\n renderImports(imports) {\n return imports.map((entry) => entry.text);\n },\n extractDocstrings(tree, source) {\n const result = new Map<string, SymbolDocstrings>();\n const rootChildren = tree.rootNode.children;\n\n for (let i = 0; i < rootChildren.length; i++) {\n const child = rootChildren[i];\n const name = extractPythonDeclarationName(child);\n if (!name) continue;\n\n // Python: class/function docstrings are inside the body, OR use # comments before\n let docstring: DocstringInfo | null = null;\n const body = child.childForFieldName('body');\n if (body) {\n docstring = extractPythonDocstring(body, source);\n }\n // Fallback: check for # comments before the declaration\n if (!docstring) {\n docstring = collectPrecedingPythonComments(rootChildren, i, source);\n }\n\n const members = new Map<string, MemberDocstrings>();\n\n // Extract method docstrings for classes\n if (child.type === 'class_definition' && body) {\n for (const member of body.namedChildren) {\n if (member.type !== 'function_definition') continue;\n const memberName = member.childForFieldName('name')?.text;\n if (!memberName) continue;\n\n let memberDoc: DocstringInfo | null = null;\n const memberBody = member.childForFieldName('body');\n if (memberBody) {\n memberDoc = extractPythonDocstring(memberBody, source);\n }\n\n members.set(memberName, {\n docstring: memberDoc,\n declStartIndex: member.startIndex,\n declColumn: member.startPosition.column,\n urlFingerprint: extractUrlFingerprint(member, PYTHON_URL_FINGERPRINT_CONFIG),\n });\n }\n }\n\n result.set(name, {\n docstring,\n declStartIndex: child.startIndex,\n declColumn: child.startPosition.column,\n members,\n });\n }\n\n return result;\n },\n};\n","import type Parser from 'tree-sitter';\nimport type {\n MergeAdapter,\n MergeStatement,\n MergeImport,\n DocstringInfo,\n SymbolDocstrings,\n MemberDocstrings,\n} from './types.js';\nimport { extractUrlFingerprint } from './url-fingerprint.js';\n\nconst RUBY_URL_FINGERPRINT_CONFIG = {\n stringNodeTypes: ['string'],\n contentNodeTypes: ['string_content'],\n interpolationNodeTypes: ['interpolation'],\n};\n\nfunction isRequireCall(node: Parser.SyntaxNode): boolean {\n if (node.type !== 'call') return false;\n const method = node.childForFieldName('method');\n if (!method) return false;\n return method.text === 'require' || method.text === 'require_relative';\n}\n\nfunction extractRubyDeclarationName(node: Parser.SyntaxNode): string | null {\n if (node.type !== 'class' && node.type !== 'module') return null;\n const nameNode = node.childForFieldName('name');\n return nameNode?.text ?? null;\n}\n\nfunction collectPrecedingRubyComments(\n children: Parser.SyntaxNode[],\n index: number,\n source: string,\n): DocstringInfo | null {\n let lastIdx = -1;\n let firstIdx = -1;\n for (let k = index - 1; k >= 0; k--) {\n const prev = children[k];\n const nodeType = (prev as any).grammarType ?? prev.type;\n if (nodeType === 'comment') {\n const text = source.slice(prev.startIndex, prev.endIndex);\n if (text.startsWith('#')) {\n if (lastIdx === -1) lastIdx = k;\n firstIdx = k;\n } else {\n break;\n }\n } else {\n break;\n }\n }\n if (firstIdx === -1) return null;\n const first = children[firstIdx];\n const last = children[lastIdx];\n return { text: source.slice(first.startIndex, last.endIndex), startIndex: first.startIndex, endIndex: last.endIndex };\n}\n\nexport const rubyMergeAdapter: MergeAdapter = {\n language: 'ruby',\n grammarModule: 'tree-sitter-ruby',\n testFilePatterns: [/_test\\.rb$/, /_spec\\.rb$/],\n urlFingerprintConfig: RUBY_URL_FINGERPRINT_CONFIG,\n parseStatements(tree, source) {\n const imports: MergeImport[] = [];\n const importAnchors: string[] = [];\n const statements: MergeStatement[] = [];\n\n for (const child of tree.rootNode.children) {\n if (child.type === 'comment') continue;\n\n const declarationName = extractRubyDeclarationName(child);\n if (isRequireCall(child)) {\n const text = source.slice(child.startIndex, child.endIndex);\n imports.push({ key: text.trim(), text });\n importAnchors.push(text);\n continue;\n }\n\n const kind: MergeStatement['kind'] = declarationName ? 'declaration' : 'other';\n\n statements.push({\n key: declarationName,\n kind,\n text: source.slice(child.startIndex, child.endIndex),\n });\n }\n\n return { imports, importAnchors, statements };\n },\n renderImports(imports) {\n return imports.map((entry) => entry.text);\n },\n extractDocstrings(tree, source) {\n const result = new Map<string, SymbolDocstrings>();\n const rootChildren = tree.rootNode.children;\n\n for (let i = 0; i < rootChildren.length; i++) {\n const child = rootChildren[i];\n const name = extractRubyDeclarationName(child);\n if (!name) continue;\n\n const docstring = collectPrecedingRubyComments(rootChildren, i, source);\n const members = new Map<string, MemberDocstrings>();\n\n // Ruby class/module bodies: comments may appear in class children\n // (before body_statement) or in body_statement children (between methods)\n if (child.type === 'class' || child.type === 'module') {\n const allClassChildren = child.children;\n const body = child.childForFieldName('body');\n\n // Check for comment before body_statement in class children\n // (docstring for the first method)\n let firstMethodDocFromClass: DocstringInfo | null = null;\n for (let j = 0; j < allClassChildren.length; j++) {\n if (allClassChildren[j] === body || allClassChildren[j].type === 'body_statement') {\n firstMethodDocFromClass = collectPrecedingRubyComments(allClassChildren, j, source);\n break;\n }\n }\n\n if (body) {\n const bodyChildren = body.children;\n let firstMethodHandled = false;\n for (let j = 0; j < bodyChildren.length; j++) {\n const member = bodyChildren[j];\n if (member.type !== 'method') continue;\n const memberName = member.childForFieldName('name')?.text;\n if (!memberName) continue;\n\n let memberDoc: DocstringInfo | null;\n if (!firstMethodHandled && firstMethodDocFromClass) {\n memberDoc = firstMethodDocFromClass;\n firstMethodHandled = true;\n } else {\n memberDoc = collectPrecedingRubyComments(bodyChildren, j, source);\n firstMethodHandled = true;\n }\n\n members.set(memberName, {\n docstring: memberDoc,\n declStartIndex: member.startIndex,\n declColumn: member.startPosition.column,\n urlFingerprint: extractUrlFingerprint(member, RUBY_URL_FINGERPRINT_CONFIG),\n });\n }\n }\n }\n\n result.set(name, {\n docstring,\n declStartIndex: child.startIndex,\n declColumn: child.startPosition.column,\n members,\n });\n }\n\n return result;\n },\n};\n","import type Parser from 'tree-sitter';\nimport type { MergeAdapter, MergeStatement, MergeImport, DocstringInfo, SymbolDocstrings } from './types.js';\n\nconst RUST_URL_FINGERPRINT_CONFIG = {\n stringNodeTypes: ['string_literal'],\n contentNodeTypes: ['string_content'],\n interpolationNodeTypes: [],\n};\n\nfunction declarationKey(node: Parser.SyntaxNode): string | null {\n switch (node.type) {\n case 'struct_item':\n case 'enum_item':\n case 'function_item':\n case 'trait_item':\n case 'type_item':\n case 'const_item': {\n return node.childForFieldName('name')?.text ?? null;\n }\n case 'impl_item': {\n const typeName = node.childForFieldName('type')?.text ?? 'unknown';\n const traitName = node.childForFieldName('trait')?.text;\n return traitName ? `impl:${traitName}->${typeName}` : `impl:${typeName}`;\n }\n default:\n return null;\n }\n}\n\nfunction collectPrecedingRustDocComments(\n children: Parser.SyntaxNode[],\n index: number,\n source: string,\n): DocstringInfo | null {\n let lastIdx = -1;\n let firstIdx = -1;\n for (let k = index - 1; k >= 0; k--) {\n const prev = children[k];\n if (prev.type === 'line_comment') {\n const text = source.slice(prev.startIndex, prev.endIndex);\n if (text.startsWith('///')) {\n if (lastIdx === -1) lastIdx = k;\n firstIdx = k;\n } else {\n break;\n }\n } else {\n break;\n }\n }\n if (firstIdx === -1) return null;\n const first = children[firstIdx];\n const last = children[lastIdx];\n return { text: source.slice(first.startIndex, last.endIndex), startIndex: first.startIndex, endIndex: last.endIndex };\n}\n\nexport const rustMergeAdapter: MergeAdapter = {\n language: 'rust',\n grammarModule: 'tree-sitter-rust',\n testFilePatterns: [/_test\\.rs$/, /(?:^|\\/)tests\\/.*\\.rs$/],\n urlFingerprintConfig: RUST_URL_FINGERPRINT_CONFIG,\n parseStatements(tree, source) {\n const imports: MergeImport[] = [];\n const importAnchors: string[] = [];\n const statements: MergeStatement[] = [];\n\n for (const child of tree.rootNode.children) {\n if (child.type === 'comment') continue;\n\n if (child.type === 'use_declaration') {\n const text = source.slice(child.startIndex, child.endIndex);\n imports.push({ key: text.trim(), text });\n importAnchors.push(text);\n continue;\n }\n\n const key = declarationKey(child);\n statements.push({\n key,\n kind: key ? 'declaration' : 'other',\n text: source.slice(child.startIndex, child.endIndex),\n });\n }\n\n return { imports, importAnchors, statements };\n },\n renderImports(imports) {\n return imports.map((entry) => entry.text);\n },\n extractDocstrings(tree, source) {\n const result = new Map<string, SymbolDocstrings>();\n const rootChildren = tree.rootNode.children;\n\n for (let i = 0; i < rootChildren.length; i++) {\n const child = rootChildren[i];\n const key = declarationKey(child);\n if (!key) continue;\n\n const docstring = collectPrecedingRustDocComments(rootChildren, i, source);\n result.set(key, {\n docstring,\n declStartIndex: child.startIndex,\n declColumn: child.startPosition.column,\n members: new Map(),\n });\n }\n\n return result;\n },\n};\n","import type { MergeAdapter } from './types.js';\nimport { dotnetMergeAdapter } from './dotnet.js';\nimport { elixirMergeAdapter } from './elixir.js';\nimport { goMergeAdapter } from './go.js';\nimport { kotlinMergeAdapter } from './kotlin.js';\nimport { nodeMergeAdapter } from './node.js';\nimport { phpMergeAdapter } from './php.js';\nimport { pythonMergeAdapter } from './python.js';\nimport { rubyMergeAdapter } from './ruby.js';\nimport { rustMergeAdapter } from './rust.js';\n\nconst adapters = new Map<string, MergeAdapter>([\n ['dotnet', dotnetMergeAdapter],\n ['elixir', elixirMergeAdapter],\n ['go', goMergeAdapter],\n ['kotlin', kotlinMergeAdapter],\n ['node', nodeMergeAdapter],\n ['php', phpMergeAdapter],\n ['python', pythonMergeAdapter],\n ['ruby', rubyMergeAdapter],\n ['rust', rustMergeAdapter],\n]);\n\nexport function getMergeAdapter(language: string): MergeAdapter | undefined {\n return adapters.get(language);\n}\n","/**\n * Shared tree-sitter utilities.\n *\n * tree-sitter 0.21.x has a native binding bug: its internal UTF-16 buffer is\n * 32 768 uint16 units (32 768 characters for BMP text). When the JS input\n * callback returns a string >= 32 768 chars, `napi_get_value_string_utf16`\n * overflows and the C layer throws \"Invalid argument\". Work around this by\n * supplying a chunked callback for large sources instead of a raw string.\n */\n\nimport type Parser from 'tree-sitter';\n\nconst TS_SAFE_CHUNK = 32_767;\n\nexport function safeParse(parser: Parser, source: string): Parser.Tree {\n if (source.length < TS_SAFE_CHUNK) {\n return parser.parse(source);\n }\n return parser.parse((offset: number) => source.slice(offset, offset + TS_SAFE_CHUNK));\n}\n","/**\n * AST-level file merger using tree-sitter.\n *\n * When generating into a directory that already contains files, the merger\n * parses both the existing and generated content, detects top-level symbols,\n * and only appends symbols that don't already exist. Hand-written code is\n * never modified or removed.\n *\n * Supports any language with a tree-sitter grammar package.\n */\n\nimport Parser from 'tree-sitter';\nimport { getMergeAdapter } from './merge-adapters/index.js';\nimport type { MergeImport, ParsedMergeFile, SymbolDocstrings } from './merge-adapters/types.js';\n\n// Cache parser instances per language\nconst parserCache = new Map<string, Parser>();\n\nimport { safeParse } from '../utils/tree-sitter.js';\n\n// --- @deprecated preservation ---\n\n/**\n * When replacing an existing docstring with a generated one, carry over any\n * `@deprecated` lines from the existing doc that aren't present in the\n * generated doc. This prevents hand-written deprecation notices from being\n * silently dropped during docstring refresh.\n */\nfunction preserveDeprecatedTags(existingDoc: string, generatedDoc: string): string {\n // Check if the existing docstring contains @deprecated anywhere\n if (!existingDoc.includes('@deprecated')) return generatedDoc;\n\n // If generated doc already has @deprecated, no need to merge\n if (generatedDoc.includes('@deprecated')) return generatedDoc;\n\n // Extract the @deprecated content from the existing doc.\n // Handle both multi-line (`* @deprecated ...`) and one-liner (`/** @deprecated ... */`) formats.\n const deprecatedParts: string[] = [];\n for (const line of existingDoc.split('\\n')) {\n if (/@deprecated\\b/.test(line)) {\n // Normalize to JSDoc member format: ` * @deprecated ...`\n const match = line.match(/@deprecated\\b.*/);\n if (match) {\n // Strip trailing */ and whitespace (from one-liner JSDoc like `/** @deprecated ... */`)\n const cleaned = match[0].replace(/\\s*\\*\\/\\s*$/, '');\n deprecatedParts.push(` * ${cleaned}`);\n }\n }\n }\n if (deprecatedParts.length === 0) return generatedDoc;\n\n // Insert @deprecated lines before the closing */ of the generated doc\n const closingIdx = generatedDoc.lastIndexOf('*/');\n if (closingIdx === -1) return generatedDoc;\n const before = generatedDoc.slice(0, closingIdx);\n const after = generatedDoc.slice(closingIdx);\n return before + deprecatedParts.join('\\n') + '\\n ' + after;\n}\n\n// --- @oagen-ignore region helpers ---\n\ninterface IgnoredRegion {\n startIndex: number;\n endIndex: number;\n}\n\nfunction findIgnoredRegions(source: string): IgnoredRegion[] {\n const regions: IgnoredRegion[] = [];\n const startTag = '@oagen-ignore-start';\n const endTag = '@oagen-ignore-end';\n let searchFrom = 0;\n\n while (true) {\n const startIdx = source.indexOf(startTag, searchFrom);\n if (startIdx === -1) break;\n const endIdx = source.indexOf(endTag, startIdx + startTag.length);\n if (endIdx === -1) break; // Unclosed — silently ignore\n regions.push({ startIndex: startIdx, endIndex: endIdx + endTag.length });\n searchFrom = endIdx + endTag.length;\n }\n\n return regions;\n}\n\nfunction buildIgnoredSymbolNames(docstrings: Map<string, SymbolDocstrings>, regions: IgnoredRegion[]): Set<string> {\n if (regions.length === 0) return new Set();\n const ignored = new Set<string>();\n for (const [name, info] of docstrings) {\n if (regions.some((r) => info.declStartIndex >= r.startIndex && info.declStartIndex <= r.endIndex)) {\n ignored.add(name);\n }\n }\n return ignored;\n}\n\nfunction clampIndex(value: number, contentLength: number): number {\n if (!Number.isFinite(value)) return 0;\n if (value < 0) return 0;\n if (value > contentLength) return contentLength;\n return value;\n}\n\n/**\n * Resolve the declaration line start for insertion using the current content,\n * instead of relying on parser column arithmetic. This avoids misplaced inserts\n * when parser columns/offsets drift.\n */\nfunction declarationLineStart(content: string, declStartIndex: number): number {\n const idx = clampIndex(declStartIndex, content.length);\n const prevNewline = content.lastIndexOf('\\n', Math.max(0, idx - 1));\n return prevNewline === -1 ? 0 : prevNewline + 1;\n}\n\n/**\n * Resolve a docstring range by searching for the nearest matching text before\n * the declaration start. Falls back to parser-provided offsets when search fails.\n */\nfunction resolveDocRange(\n content: string,\n docText: string,\n declStartIndex: number,\n fallbackStart: number,\n fallbackEnd: number,\n): { start: number; end: number } {\n const safeDecl = clampIndex(declStartIndex, content.length);\n const safeFallbackStart = clampIndex(fallbackStart, content.length);\n const safeFallbackEnd = clampIndex(fallbackEnd, content.length);\n const found = content.lastIndexOf(docText, safeDecl);\n if (found !== -1) {\n return { start: found, end: found + docText.length };\n }\n return { start: safeFallbackStart, end: safeFallbackEnd };\n}\n\n/**\n * Check if a tree-sitter grammar is configured for the given language.\n */\nexport function hasGrammar(language: string): boolean {\n return getMergeAdapter(language) !== undefined;\n}\n\nasync function getParser(language: string): Promise<Parser> {\n const cached = parserCache.get(language);\n if (cached) return cached;\n\n const adapter = getMergeAdapter(language);\n if (!adapter) {\n throw new Error(\n `No tree-sitter grammar configured for language \"${language}\". ` +\n `Add a merge adapter and install the corresponding tree-sitter grammar package.`,\n );\n }\n\n const mod = await import(adapter.grammarModule);\n const exported = adapter.resolveGrammar ? adapter.resolveGrammar(mod) : mod;\n const grammar = (exported as { default?: unknown }).default ?? exported;\n const parser = new Parser();\n parser.setLanguage(grammar);\n parserCache.set(language, parser);\n return parser;\n}\n\ninterface ParsedSymbols {\n names: Set<string>;\n /** Trimmed text of unnamed top-level statements (for text-based dedup) */\n unnamedTexts: Set<string>;\n}\n\n/**\n * Extract all top-level symbol names (and unnamed statement texts) from source code.\n */\nexport async function extractTopLevelSymbols(source: string, language: string): Promise<ParsedSymbols> {\n const parser = await getParser(language);\n const adapter = getMergeAdapter(language);\n if (!adapter) {\n throw new Error(`No merge adapter configured for language \"${language}\"`);\n }\n if (typeof source !== 'string') {\n throw new Error(`extractTopLevelSymbols: expected string source, got ${typeof source}`);\n }\n const tree = safeParse(parser, source);\n const names = new Set<string>();\n const unnamedTexts = new Set<string>();\n const parsed = adapter.parseStatements(tree, source);\n\n for (const imp of parsed.imports) {\n names.add(imp.key);\n }\n for (const statement of parsed.statements) {\n if (statement.key) {\n names.add(statement.key);\n } else {\n unnamedTexts.add(statement.text.trim());\n }\n }\n\n return { names, unnamedTexts };\n}\n\n/** Convenience wrapper that returns only the name set. */\nexport async function extractTopLevelNames(source: string, language: string): Promise<Set<string>> {\n return (await extractTopLevelSymbols(source, language)).names;\n}\n\n/**\n * Extract top-level statements from generated source with their names\n * and exact text span.\n */\nexport async function extractStatements(source: string, language: string): Promise<ParsedMergeFile> {\n const parser = await getParser(language);\n const adapter = getMergeAdapter(language);\n if (!adapter) {\n throw new Error(`No merge adapter configured for language \"${language}\"`);\n }\n const tree = safeParse(parser, source);\n return adapter.parseStatements(tree, source);\n}\n\n/**\n * Return a map of top-level class name → { bodyEndLine, bodyEndCol } using\n * tree-sitter. `bodyEndLine` is 0-based. For brace-delimited classes the\n * end points at the closing brace line; for indentation-delimited classes\n * it points one past the last line of the class body.\n */\nexport async function extractClassEndLines(\n source: string,\n language: string,\n): Promise<Map<string, { bodyEndLine: number }>> {\n const parser = await getParser(language);\n const tree = safeParse(parser, source);\n const map = new Map<string, { bodyEndLine: number }>();\n\n function processClassNode(node: Parser.SyntaxNode): void {\n const nameNode = node.childForFieldName('name');\n if (!nameNode) return;\n const name = nameNode.text;\n\n const body = node.childForFieldName('body');\n const endRow = body ? body.endPosition.row : node.endPosition.row;\n const lastChar = source[body ? body.endIndex - 1 : node.endIndex - 1];\n\n if (lastChar === '}') {\n map.set(name, { bodyEndLine: endRow });\n } else {\n map.set(name, { bodyEndLine: endRow + 1 });\n }\n }\n\n // Walk the tree recursively. Ruby (and Python) often nest target classes\n // inside `module Foo` / `class Outer:` containers, so a flat iteration over\n // root children would miss them.\n function walk(node: Parser.SyntaxNode): void {\n if (node.type === 'class' || node.type === 'class_definition' || node.type === 'class_declaration') {\n processClassNode(node);\n }\n if (node.type === 'decorated_definition') {\n for (const inner of node.namedChildren) {\n if (inner.type === 'class_definition') processClassNode(inner);\n }\n }\n if (node.type === 'export_statement') {\n for (const inner of node.namedChildren) {\n if (inner.type === 'class_declaration') processClassNode(inner);\n }\n }\n for (const child of node.namedChildren) walk(child);\n }\n for (const child of tree.rootNode.children) {\n walk(child);\n }\n\n return map;\n}\n\nexport interface MergeResult {\n content: string;\n added: number;\n preserved: number;\n changed: boolean;\n}\n\n/**\n * Merge generated content into an existing file.\n *\n * - Parses both files with tree-sitter\n * - Detects which top-level symbols already exist\n * - Appends only new symbols\n * - Never modifies or removes existing code\n * - Adds auto-generated header if not present\n */\nexport async function mergeIntoExisting(\n existingContent: string,\n generatedContent: string,\n language: string,\n header: string,\n): Promise<MergeResult> {\n const adapter = getMergeAdapter(language);\n if (!adapter) {\n throw new Error(`No merge adapter configured for language \"${language}\"`);\n }\n\n // Parse existing file once — extract both symbols and statements from the same AST pass\n const existingStatements = await extractStatements(existingContent, language);\n const generatedStatements = await extractStatements(generatedContent, language);\n\n const existingKeys = new Set<string>();\n const existingUnnamedTexts = new Set<string>();\n const existingImportKeys = new Set<string>();\n const existingReexports = new Set<string>();\n let lastImportEndIndex = -1;\n\n // Collect import keys AND imported identifiers (to prevent adding declarations\n // that clash with already-imported names)\n const existingImportedNames = new Set<string>();\n for (const imp of existingStatements.imports) {\n existingImportKeys.add(imp.key);\n // Extract identifiers from import text: import { Foo, Bar } from '...'\n const braceMatch = imp.text.match(/\\{([^}]+)\\}/);\n if (braceMatch) {\n for (const name of braceMatch[1].split(',')) {\n const trimmed = name.replace(/\\btype\\b/, '').trim();\n if (trimmed) existingImportedNames.add(trimmed);\n }\n }\n }\n for (const anchor of existingStatements.importAnchors) {\n const linesBefore = existingContent.slice(0, existingContent.indexOf(anchor)).split('\\n').length - 1;\n const stmtLines = anchor.split('\\n').length;\n lastImportEndIndex = linesBefore + stmtLines - 1;\n }\n if (lastImportEndIndex === -1 && existingStatements.importInsertionAnchor) {\n const linesBefore =\n existingContent.slice(0, existingContent.indexOf(existingStatements.importInsertionAnchor)).split('\\n').length -\n 1;\n const stmtLines = existingStatements.importInsertionAnchor.split('\\n').length;\n lastImportEndIndex = linesBefore + stmtLines - 1;\n }\n\n // Track all names exported by existing statements (both direct exports and\n // re-export aliases like `export { X as Y }`). Used to prevent the merger\n // from appending a re-export that introduces a duplicate exported name.\n const existingExportedNames = new Set<string>();\n\n for (const stmt of existingStatements.statements) {\n if (stmt.kind === 'reexport') {\n existingReexports.add(adapter.normalizeReexport ? adapter.normalizeReexport(stmt.text.trim()) : stmt.text.trim());\n // Collect aliased export names from re-exports\n const braceMatch = stmt.text.match(/\\{([^}]+)\\}/);\n if (braceMatch) {\n for (const part of braceMatch[1].split(',')) {\n const segments = part.trim().split(/\\s+as\\s+/);\n const exportedName = (segments[1] ?? segments[0]).trim();\n if (exportedName) existingExportedNames.add(exportedName);\n }\n }\n }\n if (stmt.key) {\n existingKeys.add(stmt.key);\n existingExportedNames.add(stmt.key);\n } else {\n existingUnnamedTexts.add(stmt.text.trim());\n }\n }\n\n const headerLine = header.trim();\n\n const newImports: MergeImport[] = [];\n const toAppend: string[] = [];\n let preserved = 0;\n\n for (const imp of generatedStatements.imports) {\n if (imp.text.trim() === headerLine) continue;\n if (existingImportKeys.has(imp.key)) {\n // The existing file already imports from this module path.\n // Check if the generated import adds identifiers not present in\n // the existing import — if so, create a supplemental import with\n // only the new identifiers. The supplemental participates in the\n // usage-based filter (below) so unused identifiers are dropped.\n const braceMatch = imp.text.match(/\\{([^}]+)\\}/);\n if (braceMatch) {\n const names = braceMatch[1]\n .split(',')\n .map((n) => n.replace(/\\btype\\b/, '').trim())\n .filter(Boolean);\n const newNames = names.filter((n) => !existingImportedNames.has(n) && !existingKeys.has(n));\n if (newNames.length > 0) {\n const isTypeImport = imp.text.trimStart().startsWith('import type');\n const prefix = isTypeImport ? 'import type' : 'import';\n const sourceMatch = imp.text.match(/from\\s+(['\"][^'\"]+['\"]);?/);\n if (sourceMatch) {\n newImports.push({\n key: imp.key + '#supplemental',\n text: `${prefix} { ${newNames.join(', ')} } from ${sourceMatch[1]};`,\n });\n }\n }\n }\n preserved++;\n continue;\n }\n // Strip out identifiers that are already imported from another path.\n // This prevents duplicates when the generated file uses a specific path\n // (e.g., '../interfaces/organization.interface') while the existing file\n // imports the same names from a barrel (e.g., '../interfaces').\n const braceMatch = imp.text.match(/\\{([^}]+)\\}/);\n if (braceMatch) {\n const names = braceMatch[1]\n .split(',')\n .map((n) => n.replace(/\\btype\\b/, '').trim())\n .filter(Boolean);\n // Check against both existing imports AND existing top-level declarations\n const isAlreadyDefined = (n: string) => existingImportedNames.has(n) || existingKeys.has(n);\n if (names.length > 0 && names.every(isAlreadyDefined)) {\n preserved++;\n continue;\n }\n // If only SOME identifiers are already defined, strip them out and keep only new ones\n if (names.some(isAlreadyDefined)) {\n const newNames = names.filter((n) => !isAlreadyDefined(n));\n if (newNames.length === 0) {\n preserved++;\n continue;\n }\n // Rebuild the import with only new identifiers\n const isTypeImport = imp.text.trimStart().startsWith('import type');\n const prefix = isTypeImport ? 'import type' : 'import';\n const sourceMatch = imp.text.match(/from\\s+(['\"][^'\"]+['\"]);?/);\n if (sourceMatch) {\n const newText = `${prefix} { ${newNames.join(', ')} } from ${sourceMatch[1]};`;\n newImports.push({ key: imp.key, text: newText });\n continue;\n }\n }\n }\n newImports.push(imp);\n }\n\n for (const stmt of generatedStatements.statements) {\n // Skip the header comment\n if (stmt.text.trim() === headerLine) continue;\n\n // Skip re-export statements that duplicate existing re-exports\n // (e.g., generated uses .js extension but existing doesn't).\n // Allow genuinely new re-exports through.\n if (stmt.kind === 'reexport') {\n const normalizedText = adapter.normalizeReexport ? adapter.normalizeReexport(stmt.text.trim()) : stmt.text.trim();\n if (existingReexports.has(normalizedText) || (stmt.key !== null && existingKeys.has(stmt.key))) {\n preserved++;\n continue;\n }\n // Also skip re-exports whose aliased names are already defined as\n // top-level exports in the existing file (e.g., generated file has\n // `export { X as deserializeFoo } from '...'` but existing file\n // already has `export const deserializeFoo = ...`).\n const braceMatch = stmt.text.match(/\\{([^}]+)\\}/);\n if (braceMatch) {\n const exportedNames = braceMatch[1]\n .split(',')\n .map((n) => {\n const parts = n.trim().split(/\\s+as\\s+/);\n return (parts[1] ?? parts[0]).trim();\n })\n .filter(Boolean);\n if (exportedNames.length > 0 && exportedNames.every((n) => existingExportedNames.has(n))) {\n preserved++;\n continue;\n }\n }\n }\n\n if (stmt.key && (existingKeys.has(stmt.key) || existingImportedNames.has(stmt.key))) {\n preserved++;\n continue;\n }\n\n if (!stmt.key) {\n if (existingUnnamedTexts.has(stmt.text.trim())) {\n preserved++;\n continue;\n }\n }\n\n toAppend.push(stmt.text);\n }\n\n if (newImports.length === 0 && toAppend.length === 0) {\n // No top-level changes — check for deep merge before returning\n if (!adapter.extractMembers) {\n // Still need to check docstring refresh below\n }\n }\n\n let result = existingContent;\n\n // Append new top-level symbols first (so deep merge can see them)\n if (toAppend.length > 0) {\n result = result.trimEnd() + '\\n\\n' + toAppend.join('\\n\\n') + '\\n';\n }\n\n // Deep merge pass: add new members to existing symbols\n // Runs after import/symbol merge so line numbers are based on the updated content\n let deepAdded = 0;\n const insertions: { line: number; text: string }[] = [];\n if (adapter.extractMembers) {\n const parser = await getParser(language);\n const resultTree = safeParse(parser, result);\n const generatedTree = safeParse(parser, generatedContent);\n const resultSymbols = adapter.extractMembers(resultTree, result);\n const generatedSymbols = adapter.extractMembers(generatedTree, generatedContent);\n\n // Build ignored symbol set from @oagen-ignore-start/@oagen-ignore-end regions\n const existingTree = safeParse(parser, existingContent);\n const existingDocs = adapter.extractDocstrings(existingTree, existingContent);\n const deepIgnoredRegions = findIgnoredRegions(existingContent);\n const deepIgnoredSymbols = buildIgnoredSymbolNames(existingDocs, deepIgnoredRegions);\n\n for (const [symbolName, genSymbol] of generatedSymbols) {\n if (deepIgnoredSymbols.has(symbolName)) continue;\n const existSymbol = resultSymbols.get(symbolName);\n if (!existSymbol) continue; // New symbol — handled by top-level append\n\n const existingMemberKeys = new Set(existSymbol.members.map((m) => m.key));\n const newMembers = genSymbol.members.filter((m) => !existingMemberKeys.has(m.key));\n\n if (newMembers.length > 0) {\n // Let the adapter decide whether to skip deep merge (e.g., when new members\n // reference dependencies the existing symbol doesn't provide)\n if (adapter.shouldSkipDeepMerge?.(symbolName, existingMemberKeys, newMembers)) {\n continue;\n }\n\n const indent = existSymbol.memberIndent ?? ' ';\n const insertText = newMembers.map((m) => indent + m.text).join('\\n\\n');\n // Leading blank line separates inserted members from existing ones.\n insertions.push({ line: existSymbol.bodyEndLine, text: '\\n' + insertText });\n deepAdded += newMembers.length;\n }\n }\n\n if (insertions.length > 0) {\n // Apply bottom-up to avoid offset shifting\n insertions.sort((a, b) => b.line - a.line);\n const resultLines = result.split('\\n');\n for (const ins of insertions) {\n resultLines.splice(ins.line, 0, ins.text);\n }\n result = resultLines.join('\\n');\n }\n }\n\n // Insert new imports only when new symbols or members were actually added.\n // This prevents orphaned imports for generated code that wasn't merged in.\n // Additionally, filter imports to only include identifiers actually used in the\n // appended/inserted code — prevents orphaned imports for generated code that\n // referenced types used in other (non-appended) generated functions.\n if (newImports.length > 0 && (toAppend.length > 0 || deepAdded > 0)) {\n // Build text of all new code that was actually added (appended + deep-merged members)\n const addedParts: string[] = [...toAppend];\n if (insertions) {\n for (const ins of insertions) {\n addedParts.push(ins.text);\n }\n }\n const addedCodeText = addedParts.join('\\n');\n\n // Filter imports to only identifiers that appear in the added code.\n // Strip individual unused identifiers from each import rather than\n // keeping/dropping the entire import — prevents orphaned imports when\n // a generated import line contains both used and unused identifiers\n // (e.g., `import { deserializeFoo, serializeFoo }` where only\n // serializeFoo is used in the appended code).\n const filteredImports: MergeImport[] = [];\n for (const imp of newImports) {\n const braceMatch = imp.text.match(/\\{([^}]+)\\}/);\n if (!braceMatch) {\n // Non-destructured import (e.g., default import) — keep as-is\n filteredImports.push(imp);\n continue;\n }\n const names = braceMatch[1]\n .split(',')\n .map((n) => n.replace(/\\btype\\b/, '').trim())\n .filter(Boolean);\n const usedNames = names.filter((name) => addedCodeText.includes(name));\n if (usedNames.length === 0) continue; // Drop entirely\n if (usedNames.length === names.length) {\n // All identifiers used — keep original import\n filteredImports.push(imp);\n } else {\n // Rebuild import with only used identifiers\n const isTypeImport = imp.text.trimStart().startsWith('import type');\n const prefix = isTypeImport ? 'import type' : 'import';\n const sourceMatch = imp.text.match(/from\\s+(['\"][^'\"]+['\"]);?/);\n if (sourceMatch) {\n filteredImports.push({\n key: imp.key,\n text: `${prefix} { ${usedNames.join(', ')} } from ${sourceMatch[1]};`,\n });\n } else {\n filteredImports.push(imp);\n }\n }\n }\n\n if (filteredImports.length > 0) {\n const renderedImports = adapter.renderImports\n ? adapter.renderImports(filteredImports)\n : filteredImports.map((entry) => entry.text);\n const lines = result.split('\\n');\n const insertIdx = lastImportEndIndex + 1;\n lines.splice(insertIdx, 0, ...renderedImports);\n result = lines.join('\\n');\n }\n }\n\n // Docstring refresh pass: update existing docstrings to match generated content\n let docstringUpdates = 0;\n {\n const parser = await getParser(language);\n const resultTree = safeParse(parser, result);\n const generatedTree = safeParse(parser, generatedContent);\n const resultDocs = adapter.extractDocstrings(resultTree, result);\n const generatedDocs = adapter.extractDocstrings(generatedTree, generatedContent);\n const docIgnoredRegions = findIgnoredRegions(result);\n const docIgnoredSymbols = buildIgnoredSymbolNames(resultDocs, docIgnoredRegions);\n\n const edits: { start: number; end: number; newText: string }[] = [];\n\n for (const [symbolName, genInfo] of generatedDocs) {\n const existInfo = resultDocs.get(symbolName);\n if (!existInfo) continue;\n if (docIgnoredSymbols.has(symbolName)) continue;\n\n // Skip header comments being treated as docstrings\n const genDoc = genInfo.docstring && genInfo.docstring.text.trim() !== headerLine ? genInfo.docstring : null;\n\n // Top-level docstring\n if (genDoc) {\n if (existInfo.docstring) {\n const isPreserved = existInfo.docstring.text.includes('@oagen-ignore');\n if (!isPreserved && existInfo.docstring.text !== genDoc.text) {\n const newText = preserveDeprecatedTags(existInfo.docstring.text, genDoc.text);\n const range = resolveDocRange(\n result,\n existInfo.docstring.text,\n existInfo.declStartIndex,\n existInfo.docstring.startIndex,\n existInfo.docstring.endIndex,\n );\n edits.push({\n start: range.start,\n end: range.end,\n newText,\n });\n docstringUpdates++;\n }\n } else {\n const lineStart = declarationLineStart(result, existInfo.declStartIndex);\n const indent = ' '.repeat(existInfo.declColumn);\n edits.push({\n start: lineStart,\n end: lineStart,\n newText: indent + genDoc.text + '\\n',\n });\n docstringUpdates++;\n }\n }\n\n // Member-level docstrings — first pass: match by name\n const matchedExistMembers = new Set<string>();\n for (const [memberName, genMember] of genInfo.members) {\n const existMember = existInfo.members.get(memberName);\n if (!existMember) continue;\n matchedExistMembers.add(memberName);\n if (!genMember.docstring) continue;\n\n if (existMember.docstring) {\n const isPreserved = existMember.docstring.text.includes('@oagen-ignore');\n if (!isPreserved && existMember.docstring.text !== genMember.docstring.text) {\n const newText = preserveDeprecatedTags(existMember.docstring.text, genMember.docstring.text);\n const range = resolveDocRange(\n result,\n existMember.docstring.text,\n existMember.declStartIndex,\n existMember.docstring.startIndex,\n existMember.docstring.endIndex,\n );\n edits.push({\n start: range.start,\n end: range.end,\n newText,\n });\n docstringUpdates++;\n }\n } else {\n const lineStart = declarationLineStart(result, existMember.declStartIndex);\n const indent = ' '.repeat(existMember.declColumn);\n edits.push({\n start: lineStart,\n end: lineStart,\n newText: indent + genMember.docstring.text + '\\n',\n });\n docstringUpdates++;\n }\n }\n\n // Member-level docstrings — second pass: URL fingerprint fallback\n // Match generated members to existing members by URL pattern when\n // name-based matching fails (e.g., generated \"find\" vs existing \"getOrganization\"\n // both call this.workos.get('/organizations/${id}')).\n //\n // Safety: only attempt fingerprint matching when there is exactly ONE\n // unmatched generated member and ONE unmatched existing member for a\n // given fingerprint. When multiple members share the same URL path\n // (e.g., POST and GET on /authorization/roles), fingerprint matching\n // is ambiguous and would swap docstrings between methods.\n const unmatchedGenByFp = new Map<\n string,\n { name: string; member: typeof genInfo.members extends Map<string, infer V> ? V : never }[]\n >();\n for (const [genName, genMember] of genInfo.members) {\n if (matchedExistMembers.has(genName)) continue; // name-matched in pass 1 (as an exist member) — skip\n if (!genMember.docstring || !genMember.urlFingerprint) continue;\n // Skip if this generated member was already name-matched\n if (existInfo.members.has(genName)) continue;\n const bucket = unmatchedGenByFp.get(genMember.urlFingerprint) ?? [];\n bucket.push({ name: genName, member: genMember });\n unmatchedGenByFp.set(genMember.urlFingerprint, bucket);\n }\n const unmatchedExistByFp = new Map<\n string,\n { name: string; member: typeof existInfo.members extends Map<string, infer V> ? V : never }[]\n >();\n for (const [existName, existMember] of existInfo.members) {\n if (matchedExistMembers.has(existName)) continue;\n if (!existMember.urlFingerprint) continue;\n const bucket = unmatchedExistByFp.get(existMember.urlFingerprint) ?? [];\n bucket.push({ name: existName, member: existMember });\n unmatchedExistByFp.set(existMember.urlFingerprint, bucket);\n }\n for (const [fp, genBucket] of unmatchedGenByFp) {\n if (genBucket.length !== 1) continue; // ambiguous — skip\n const existBucket = unmatchedExistByFp.get(fp);\n if (!existBucket || existBucket.length !== 1) continue; // ambiguous — skip\n const genMember = genBucket[0].member;\n const existEntry = existBucket[0];\n const existMember = existEntry.member;\n if (!genMember.docstring) continue;\n\n if (existMember.docstring) {\n const isPreserved = existMember.docstring.text.includes('@oagen-ignore');\n if (isPreserved) continue;\n if (existMember.docstring.text !== genMember.docstring.text) {\n const newText = preserveDeprecatedTags(existMember.docstring.text, genMember.docstring.text);\n const range = resolveDocRange(\n result,\n existMember.docstring.text,\n existMember.declStartIndex,\n existMember.docstring.startIndex,\n existMember.docstring.endIndex,\n );\n edits.push({\n start: range.start,\n end: range.end,\n newText,\n });\n docstringUpdates++;\n }\n } else {\n const lineStart = declarationLineStart(result, existMember.declStartIndex);\n const indent = ' '.repeat(existMember.declColumn);\n edits.push({\n start: lineStart,\n end: lineStart,\n newText: indent + genMember.docstring.text + '\\n',\n });\n docstringUpdates++;\n }\n matchedExistMembers.add(existEntry.name);\n }\n }\n\n if (edits.length > 0) {\n edits.sort((a, b) => b.start - a.start);\n for (const edit of edits) {\n result = result.slice(0, edit.start) + edit.newText + result.slice(edit.end);\n }\n }\n }\n\n const importsActuallyAdded =\n toAppend.length > 0 || deepAdded > 0\n ? adapter.renderImports\n ? adapter.renderImports(newImports).length\n : newImports.length\n : 0;\n const topLevelAdded = importsActuallyAdded + toAppend.length;\n const totalAdded = topLevelAdded + deepAdded;\n\n if (totalAdded === 0 && docstringUpdates === 0) {\n return { content: existingContent, added: 0, preserved, changed: false };\n }\n\n return {\n content: result,\n added: totalAdded,\n preserved,\n changed: true,\n };\n}\n","/**\n * Deep merge two parsed JSON values.\n *\n * - Objects: recursively merge, preserving existing keys not in generated\n * - Arrays: generated replaces existing entirely (generated owns array contents)\n * - Primitives: generated wins\n */\nexport function deepMergeJson(existing: unknown, generated: unknown): unknown {\n if (\n typeof existing === 'object' &&\n existing !== null &&\n !Array.isArray(existing) &&\n typeof generated === 'object' &&\n generated !== null &&\n !Array.isArray(generated)\n ) {\n const merged: Record<string, unknown> = { ...(existing as Record<string, unknown>) };\n for (const [key, value] of Object.entries(generated as Record<string, unknown>)) {\n if (key in merged) {\n merged[key] = deepMergeJson(merged[key], value);\n } else {\n merged[key] = value;\n }\n }\n return merged;\n }\n\n // Arrays and primitives: generated wins\n return generated;\n}\n","import * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport type { GeneratedFile } from './types.js';\nimport { mergeIntoExisting, hasGrammar, extractClassEndLines } from './merger.js';\nimport { deepMergeJson } from './json-merge.js';\nimport { getMergeAdapter } from './merge-adapters/index.js';\n\nexport interface WriteOptions {\n /** The emitter language (e.g., \"node\", \"ruby\"). Used to select the\n * tree-sitter grammar for AST-level merging. */\n language?: string;\n /** The auto-generated file header string. */\n header?: string;\n}\n\nexport interface WriteResult {\n written: string[];\n merged: string[];\n skipped: string[];\n identical: string[];\n ignored: string[];\n}\n\n/**\n * Write generated files to disk with AST-level merging.\n *\n * When a file already exists:\n * - skipIfExists → leave it alone entirely\n * - AST merge available → parse both, append only new symbols\n * - No grammar → skip (never clobber hand-written code)\n *\n * New files are always written in full.\n */\nexport async function writeFiles(\n files: GeneratedFile[],\n outputDir: string,\n options?: WriteOptions,\n): Promise<WriteResult> {\n const result: WriteResult = { written: [], merged: [], skipped: [], identical: [], ignored: [] };\n const sorted = [...files].sort((a, b) => a.path.localeCompare(b.path));\n const language = options?.language;\n const header = options?.header ?? '';\n\n for (const file of sorted) {\n const fullPath = path.join(outputDir, file.path);\n\n // Check if file already exists\n let existingContent: string | null = null;\n try {\n existingContent = await fs.readFile(fullPath, 'utf-8');\n } catch {\n // File doesn't exist\n }\n\n // New file → write in full\n if (existingContent === null) {\n await fs.mkdir(path.dirname(fullPath), { recursive: true });\n await fs.writeFile(fullPath, file.content, 'utf-8');\n result.written.push(file.path);\n continue;\n }\n\n // skipIfExists → hard skip, no merge (but ensure header is present)\n if (file.skipIfExists) {\n if (header && !existingContent.startsWith(header)) {\n await fs.writeFile(fullPath, header + '\\n\\n' + existingContent, 'utf-8');\n }\n result.skipped.push(file.path);\n continue;\n }\n\n // @oagen-ignore-file → skip entirely (existing file opts out of all generation)\n if (existingContent.includes('@oagen-ignore-file')) {\n result.ignored.push(file.path);\n continue;\n }\n\n // Don't merge test files into hand-written test files — generated tests are\n // designed for the standalone generated SDK and will have wrong\n // signatures/fixtures when merged into hand-written tests.\n // However, if the existing test file is itself auto-generated (has the oagen\n // header), allow overwriteExisting to take effect so new methods get coverage.\n const adapter = language ? getMergeAdapter(language) : undefined;\n const isTestFile = adapter?.testFilePatterns\n ? adapter.testFilePatterns.some((p) => p.test(file.path))\n : isDefaultTestFile(file.path);\n if (isTestFile) {\n const isExistingAutoGenerated = header && existingContent.startsWith(header);\n if (!isExistingAutoGenerated) {\n result.skipped.push(file.path);\n continue;\n }\n // Auto-generated test file — fall through to overwriteExisting / identical checks\n }\n\n // Identical content → no-op\n if (existingContent === file.content) {\n result.identical.push(file.path);\n continue;\n }\n\n // Force overwrite — but preserve any @oagen-ignore regions from existing content\n if (file.overwriteExisting) {\n const content =\n existingContent.includes('@oagen-ignore-start') && language && hasGrammar(language)\n ? await overwriteWithPreservedRegions(existingContent, file.content, language)\n : file.content;\n await fs.writeFile(fullPath, content, 'utf-8');\n result.written.push(file.path);\n continue;\n }\n\n // JSON files → deep merge preserving existing keys\n if (file.path.endsWith('.json')) {\n try {\n const existingJson = JSON.parse(existingContent);\n const generatedJson = JSON.parse(file.content);\n const merged = deepMergeJson(existingJson, generatedJson);\n const mergedContent = JSON.stringify(merged, null, 2) + '\\n';\n if (mergedContent === existingContent) {\n result.identical.push(file.path);\n } else {\n await fs.writeFile(fullPath, mergedContent, 'utf-8');\n result.merged.push(file.path);\n }\n } catch {\n // Parse failed — fall back to overwrite\n await fs.writeFile(fullPath, file.content, 'utf-8');\n result.written.push(file.path);\n }\n continue;\n }\n\n // Source files with grammar → AST-level merge\n if (language && hasGrammar(language)) {\n try {\n const mergeResult = await mergeIntoExisting(existingContent, file.content, language, header);\n\n // Ensure header is present on merged content\n let finalContent = mergeResult.content;\n if (header && !finalContent.startsWith(header)) {\n finalContent = header + '\\n\\n' + finalContent;\n }\n\n if (!mergeResult.changed && finalContent === existingContent) {\n result.identical.push(file.path);\n continue;\n }\n\n await fs.writeFile(fullPath, finalContent, 'utf-8');\n result.merged.push(file.path);\n continue;\n } catch (err) {\n // AST merge failed (e.g. tree-sitter grammar ABI issue) — fall back to overwrite\n console.warn(\n `[oagen] AST merge failed for ${file.path}, falling back to overwrite.${err instanceof Error ? ` ${err.message}` : ''}`,\n );\n await fs.writeFile(fullPath, file.content, 'utf-8');\n result.written.push(file.path);\n continue;\n }\n }\n\n // No grammar available → skip to avoid clobbering\n result.skipped.push(file.path);\n }\n\n return result;\n}\n\n/** Comprehensive fallback when no adapter is available. */\nfunction isDefaultTestFile(filePath: string): boolean {\n return (\n /\\.(spec|test)\\.[jt]sx?$/.test(filePath) ||\n filePath.endsWith('_test.go') ||\n filePath.endsWith('_test.rb') ||\n filePath.endsWith('_spec.rb') ||\n /(?:^|\\/)test_.*\\.py$/.test(filePath) ||\n filePath.endsWith('_test.py') ||\n filePath.endsWith('Test.php') ||\n filePath.endsWith('_test.rs') ||\n /(?:^|\\/)tests\\/.*\\.rs$/.test(filePath)\n );\n}\n\n// --- @oagen-ignore region preservation for overwriteExisting ---\n\n/**\n * Overwrite a file with generated content while preserving\n * `@oagen-ignore-start` / `@oagen-ignore-end` regions (and their\n * required imports) from the existing file.\n *\n * Uses tree-sitter via `extractClassEndLines` to find accurate class\n * boundaries so ignore blocks are inserted at the correct position even\n * when docstrings contain unindented text.\n */\nexport async function overwriteWithPreservedRegions(\n existingContent: string,\n generatedContent: string,\n language: string,\n): Promise<string> {\n const existingLines = existingContent.split('\\n');\n const generatedLines = generatedContent.split('\\n');\n\n // 1. Extract ignore blocks and their containing class from existing content.\n const blocks: { containingClass: string; lines: string[] }[] = [];\n for (let i = 0; i < existingLines.length; i++) {\n if (!existingLines[i].includes('@oagen-ignore-start')) continue;\n const startIdx = i;\n while (i < existingLines.length && !existingLines[i].includes('@oagen-ignore-end')) i++;\n blocks.push({\n containingClass: findContainingClass(existingLines, startIdx),\n lines: existingLines.slice(startIdx, i + 1),\n });\n }\n if (blocks.length === 0) return generatedContent;\n\n // 2. Splice extra imports from existing into generated.\n // First strip any `@oagen-ignore-start`..`@oagen-ignore-end` regions the\n // generator itself emitted: we are about to re-insert the on-disk versions,\n // and if we left the generator's seed blocks in place we'd end up with two\n // copies of every ignore block per regeneration (monotonically growing).\n const result = stripIgnoreRegions(generatedLines);\n spliceExtraImports(existingLines, result);\n\n // 3. Build class-end map from the generated content (after import splicing)\n // via tree-sitter for accurate boundary detection.\n const genSource = result.join('\\n');\n const classEndLines = await extractClassEndLines(genSource, language);\n\n // 4. Group ignore blocks by class and determine insertion points\n const blocksByClass = new Map<string, string[][]>();\n for (const b of blocks) {\n if (!blocksByClass.has(b.containingClass)) blocksByClass.set(b.containingClass, []);\n blocksByClass.get(b.containingClass)!.push(b.lines);\n }\n\n // 4a. Handle replacement blocks: ignore blocks that redefine their\n // containing class replace the generated class entirely.\n // Also handles top-level blocks (no containing class) that define\n // a class matching one in the generated content.\n const replacedClasses = new Set<string>();\n const handledBlockKeys = new Set<string>();\n const replacements: { startLine: number; endLine: number; content: string[] }[] = [];\n for (const [className, classBlocks] of blocksByClass) {\n // Determine the target class for replacement. When the block has a\n // containing class, we check if the block redefines that class. When\n // there is no containing class (top-level ignore block), we look for a\n // class definition inside the block that matches a generated class.\n let targetClass = className;\n if (!targetClass) {\n for (const blockLines of classBlocks) {\n for (const l of blockLines) {\n const m = l.match(/^(?:export\\s+)?class\\s+(\\w+)/);\n if (m && classEndLines.has(m[1])) {\n targetClass = m[1];\n break;\n }\n }\n if (targetClass) break;\n }\n }\n if (!targetClass) continue;\n const isReplacement = classBlocks.some((blockLines) =>\n blockLines.some((l) => {\n const m = l.match(/^(?:export\\s+)?class\\s+(\\w+)/);\n return m?.[1] === targetClass;\n }),\n );\n if (!isReplacement) continue;\n const info = classEndLines.get(targetClass);\n if (!info) continue;\n const startLine = findClassDeclarationStart(result, targetClass, info.bodyEndLine);\n if (startLine < 0) continue;\n const content: string[] = [];\n for (const block of classBlocks) {\n content.push('');\n content.push(...block);\n }\n replacements.push({ startLine, endLine: info.bodyEndLine, content });\n replacedClasses.add(targetClass);\n handledBlockKeys.add(className);\n }\n // Apply replacements bottom-up to preserve line indices\n replacements.sort((a, b) => b.startLine - a.startLine);\n for (const rep of replacements) {\n result.splice(rep.startLine, rep.endLine - rep.startLine, ...rep.content);\n }\n\n // 4b. Standard insertions for non-replacement blocks\n // Rebuild class end lines if replacements shifted line numbers.\n let effectiveClassEndLines = classEndLines;\n if (replacedClasses.size > 0) {\n effectiveClassEndLines = await extractClassEndLines(result.join('\\n'), language);\n }\n\n const insertions: { line: number; content: string[] }[] = [];\n for (const [className, classBlocks] of blocksByClass) {\n if (handledBlockKeys.has(className) || replacedClasses.has(className)) continue;\n const info = className ? effectiveClassEndLines.get(className) : undefined;\n const insertLine = info ? info.bodyEndLine : result.length;\n const content: string[] = [];\n for (const block of classBlocks) {\n content.push('');\n content.push(...block);\n }\n insertions.push({ line: insertLine, content });\n }\n\n // Apply bottom-up to preserve line indices\n insertions.sort((a, b) => b.line - a.line);\n for (const ins of insertions) {\n result.splice(ins.line, 0, ...ins.content);\n }\n\n return result.join('\\n');\n}\n\n/**\n * Remove every `@oagen-ignore-start`..`@oagen-ignore-end` region from the\n * supplied lines, collapsing stretches of blank lines that get left behind.\n * Used to drop generator-emitted seed blocks before splicing the on-disk\n * versions back in — otherwise every regen doubles up.\n */\nfunction stripIgnoreRegions(lines: string[]): string[] {\n const out: string[] = [];\n let skipping = false;\n for (const line of lines) {\n if (!skipping && line.includes('@oagen-ignore-start')) {\n skipping = true;\n // Drop a preceding blank line if we have one queued up — otherwise\n // regen leaves a stray blank line above the spliced-in block.\n while (out.length > 0 && out[out.length - 1].trim() === '') out.pop();\n continue;\n }\n if (skipping) {\n if (line.includes('@oagen-ignore-end')) skipping = false;\n continue;\n }\n out.push(line);\n }\n return out;\n}\n\n/** Scan backwards from `lineIdx` to find the nearest class declaration name. */\nfunction findContainingClass(lines: string[], lineIdx: number): string {\n // Allow leading whitespace so indented declarations (e.g. Ruby classes\n // nested inside `module Foo`, Python nested classes) are recognized.\n for (let j = lineIdx - 1; j >= 0; j--) {\n const m = lines[j].match(/^\\s*(?:export\\s+)?class\\s+(\\w+)/);\n if (m) return m[1];\n }\n return '';\n}\n\n/**\n * Find the start line of a class declaration (including decorators above it)\n * by scanning backwards from `beforeLine`.\n */\nfunction findClassDeclarationStart(lines: string[], className: string, beforeLine: number): number {\n // Match optional indentation so Ruby/Python nested classes are found.\n const classPattern = new RegExp(`^\\\\s*(?:export\\\\s+)?class\\\\s+${className}\\\\b`);\n for (let i = beforeLine - 1; i >= 0; i--) {\n if (!classPattern.test(lines[i])) continue;\n // Scan backward past decorators\n let start = i;\n while (start > 0 && /^\\s*@\\w+/.test(lines[start - 1])) {\n start--;\n }\n return start;\n }\n return -1;\n}\n\n/**\n * Collect `from X import Y, Z` identifiers grouped by module, handling\n * both single-line and multiline (parenthesized) forms.\n */\nfunction collectFromImports(lines: string[]): Map<string, Set<string>> {\n const byModule = new Map<string, Set<string>>();\n for (let i = 0; i < lines.length; i++) {\n if (!/^from\\s+/.test(lines[i])) continue;\n\n let fullText = lines[i];\n if (fullText.includes('(') && !fullText.includes(')')) {\n while (i + 1 < lines.length) {\n i++;\n fullText += ' ' + lines[i].trim();\n if (lines[i].includes(')')) break;\n }\n }\n\n const normalized = fullText.replace(/[()]/g, '').replace(/\\s+/g, ' ').trim();\n const match = normalized.match(/^from\\s+(\\S+)\\s+import\\s+(.+)$/);\n if (!match) continue;\n\n const mod = match[1];\n if (!byModule.has(mod)) byModule.set(mod, new Set());\n for (const id of match[2]\n .split(',')\n .map((s) => s.trim())\n .filter(Boolean)) {\n byModule.get(mod)!.add(id);\n }\n }\n return byModule;\n}\n\n/**\n * Add imports from the existing file that are absent from the generated\n * result. Handles both `import X` and `from X import Y` forms.\n * Mutates `resultLines` in place.\n */\nfunction spliceExtraImports(existingLines: string[], resultLines: string[]): void {\n const isSimpleImport = (l: string) => /^import\\s+\\w/.test(l);\n\n // Simple imports (import hashlib, import json, …)\n const existingSimple = new Set(existingLines.filter(isSimpleImport).map((l) => l.trim()));\n const generatedSimple = new Set(resultLines.filter(isSimpleImport).map((l) => l.trim()));\n const extraSimple = [...existingSimple].filter((l) => !generatedSimple.has(l));\n\n // From-imports — compare by module and find extra identifiers\n const existingFrom = collectFromImports(existingLines);\n const generatedFrom = collectFromImports(resultLines);\n\n // Build a set of all identifiers imported by the generated file (across all modules)\n // so we can detect when an existing barrel import's identifiers are covered by\n // more-specific generated imports (e.g., `from x.y import Z` covers `from x import Z`).\n const allGeneratedIds = new Set<string>();\n for (const ids of generatedFrom.values()) {\n for (const id of ids) allGeneratedIds.add(id);\n }\n\n const extraFromLines: string[] = [];\n for (const [mod, existIds] of existingFrom) {\n const genIds = generatedFrom.get(mod);\n if (!genIds) {\n // The exact module isn't in the generated file — but check whether every\n // identifier is already imported from a different (e.g., more-specific) module.\n const extra = [...existIds].filter((id) => !allGeneratedIds.has(id));\n if (extra.length > 0) {\n extraFromLines.push(`from ${mod} import ${extra.join(', ')}`);\n }\n } else {\n const extra = [...existIds].filter((id) => !genIds.has(id) && !allGeneratedIds.has(id));\n if (extra.length > 0) {\n extraFromLines.push(`from ${mod} import ${extra.join(', ')}`);\n }\n }\n }\n\n const allExtra = [...extraSimple, ...extraFromLines];\n if (allExtra.length === 0) return;\n\n // Find last import line in resultLines (accounting for multiline imports)\n let lastImportIdx = -1;\n for (let i = 0; i < resultLines.length; i++) {\n if (isSimpleImport(resultLines[i]) || /^from\\s+/.test(resultLines[i])) {\n lastImportIdx = i;\n if (resultLines[i].includes('(') && !resultLines[i].includes(')')) {\n while (i + 1 < resultLines.length) {\n i++;\n lastImportIdx = i;\n if (resultLines[i].includes(')')) break;\n }\n }\n }\n }\n\n if (lastImportIdx >= 0) {\n resultLines.splice(lastImportIdx + 1, 0, ...allExtra);\n }\n}\n","import type { ApiSpec, Service, Operation, HttpMethod } from './types.js';\n\n/** Minimal snake_case converter for path segments (avoids cross-layer import). */\nfunction toSnake(s: string): string {\n return s\n .replace(/([a-z])([A-Z])/g, '$1_$2')\n .replace(/[-\\s.]+/g, '_')\n .toLowerCase();\n}\n\n// ---------------------------------------------------------------------------\n// Hint types — consumer-provided overrides for operation resolution\n// ---------------------------------------------------------------------------\n\n/** Per-operation override keyed by \"METHOD /path\" (e.g. \"POST /sso/token\"). */\nexport interface OperationHint {\n /** Override the algorithm-derived method name. */\n name?: string;\n /** Remount this operation to a different service/namespace (PascalCase). */\n mountOn?: string;\n /** Split a union-body operation into N typed wrapper methods. */\n split?: SplitHint[];\n /** Inject constant body defaults (e.g. { grant_type: 'password' }). */\n defaults?: Record<string, string | number | boolean>;\n /** Fields the SDK reads from client config at runtime (e.g. ['client_id']). */\n inferFromClient?: string[];\n /**\n * Marks this operation as a URL builder rather than a real HTTP call. Emitters\n * should generate a method that returns the constructed URL (typically as a\n * string) without performing any I/O. Used for OAuth-style redirect endpoints\n * such as /sso/authorize and /user_management/sessions/logout.\n */\n urlBuilder?: boolean;\n}\n\nexport interface SplitHint {\n /** Wrapper method name (snake_case). */\n name: string;\n /** The discriminated union variant model name (e.g. 'PasswordSessionAuthenticateRequest'). */\n targetVariant: string;\n /** Constant body fields injected by the wrapper. */\n defaults?: Record<string, string | number | boolean>;\n /** Fields the SDK reads from client config at runtime. */\n inferFromClient?: string[];\n /** Only these body fields are exposed as method params. If omitted, all non-default/non-inferred fields are exposed. */\n exposedParams?: string[];\n /**\n * Subset of exposedParams that should be emitted as optional even when the\n * variant model would otherwise mark them required (or when the variant has\n * no addressable model, as happens for inline oneOf branches).\n */\n optionalParams?: string[];\n}\n\n// ---------------------------------------------------------------------------\n// Resolved output — consumed by emitters\n// ---------------------------------------------------------------------------\n\nexport interface ResolvedOperation {\n /** The original IR operation (preserves description, params, types, etc.). */\n operation: Operation;\n /** The original IR service that owns this operation. */\n service: Service;\n /** Resolved snake_case method name (emitters convert to their convention). */\n methodName: string;\n /** Resolved target service/namespace (PascalCase). */\n mountOn: string;\n /** For split operations: one wrapper per union variant. */\n wrappers?: ResolvedWrapper[];\n /** Constant defaults injected into query/body at runtime (from operation-level hint). */\n defaults: Record<string, string | number | boolean>;\n /** Fields the SDK reads from client config at runtime (from operation-level hint). */\n inferFromClient: string[];\n /** Marks this operation as a URL builder; emitters should not generate an HTTP call. */\n urlBuilder: boolean;\n}\n\nexport interface ResolvedWrapper {\n /** Wrapper method name (snake_case). */\n name: string;\n /** The discriminated union variant model name. */\n targetVariant: string;\n /** Constant body defaults injected by the wrapper. */\n defaults: Record<string, string | number | boolean>;\n /** Fields read from client config at runtime. */\n inferFromClient: string[];\n /** Body fields exposed as method params. */\n exposedParams: string[];\n /** Optional body fields (not required in the variant). */\n optionalParams: string[];\n /** Response model name (if any). */\n responseModelName: string | null;\n}\n\n// ---------------------------------------------------------------------------\n// Algorithm\n// ---------------------------------------------------------------------------\n\n/**\n * Action verbs recognised at the terminal path segment.\n * When a path ends with one of these, we use it as the verb instead of\n * deriving a CRUD verb from the HTTP method.\n */\nconst ACTION_VERBS = new Set([\n 'accept',\n 'activate',\n 'authorize',\n 'challenge',\n 'check',\n 'complete',\n 'confirm',\n 'deactivate',\n 'disable',\n 'enable',\n 'enroll',\n 'generate',\n 'reactivate',\n 'resend',\n 'revoke',\n 'send',\n 'verify',\n]);\n\n/** Map HTTP method → default CRUD verb. */\nconst CRUD_VERB: Record<HttpMethod, string> = {\n get: 'list',\n post: 'create',\n put: 'update',\n patch: 'update',\n delete: 'delete',\n head: 'get',\n options: 'list',\n trace: 'list',\n};\n\n/**\n * Naive singularization: strips trailing \"s\" with common-sense exceptions.\n * Good enough for API resource nouns; not a general-purpose English stemmer.\n */\nfunction singularize(word: string): string {\n if (word.length <= 2) return word;\n if (word.endsWith('ies')) return word.slice(0, -3) + 'y';\n if (\n word.endsWith('ses') ||\n word.endsWith('zes') ||\n word.endsWith('xes') ||\n word.endsWith('ches') ||\n word.endsWith('shes')\n ) {\n return word.slice(0, -2);\n }\n if (word.endsWith('ss') || word.endsWith('us') || word.endsWith('is')) return word;\n if (word.endsWith('s')) return word.slice(0, -1);\n return word;\n}\n\n/**\n * Derive a snake_case method name from an operation's HTTP method and path.\n *\n * Rules:\n * 1. Strip path-param segments (`{id}`, `{slug}`, etc.)\n * 2. If the terminal segment is an action verb, use it as the verb\n * 3. Otherwise, use the CRUD verb for the HTTP method\n * 4. For GET on a collection (no trailing {id}), use \"list\"; with {id}, use \"get\"\n * 5. For POST on a resource path, if only one path param, use \"create\" singular\n * 6. Singularize the resource noun for single-resource operations\n */\nexport function deriveMethodName(op: Operation, _service: Service): string {\n const segments = op.path.split('/').filter(Boolean);\n\n // Separate static segments from param segments\n const staticSegments: string[] = [];\n let trailingParam = false;\n for (const seg of segments) {\n if (seg.startsWith('{') && seg.endsWith('}')) {\n trailingParam = true;\n } else {\n staticSegments.push(seg);\n trailingParam = false;\n }\n }\n\n if (staticSegments.length === 0) {\n return `${CRUD_VERB[op.httpMethod] ?? 'get'}_root`;\n }\n\n const terminal = toSnake(staticSegments[staticSegments.length - 1]);\n\n // Check if terminal is an action verb\n if (ACTION_VERBS.has(terminal)) {\n // Resource context from preceding segments\n const context = staticSegments.slice(0, -1).filter((s) => !s.startsWith('{'));\n const resource = context.length > 0 ? toSnake(singularize(context[context.length - 1])) : '';\n if (resource) {\n return `${terminal}_${resource}`;\n }\n return terminal;\n }\n\n // Determine verb from HTTP method\n let verb = CRUD_VERB[op.httpMethod] ?? 'get';\n\n // GET with trailing {id} → \"get\" instead of \"list\"\n if (op.httpMethod === 'get' && trailingParam) {\n verb = 'get';\n }\n\n // Build resource name from static segments.\n // When path params separate static segments, include the penultimate static\n // segment (singularized) as a parent-context prefix to disambiguate nested paths.\n // e.g. /authorization/organizations/{id}/roles → \"organization_roles\"\n let resource = toSnake(terminal);\n if (staticSegments.length >= 2) {\n const penultimate = staticSegments[staticSegments.length - 2];\n // Check if a path param appears between the penultimate and terminal segments\n // in the original path by finding both positions and looking for {…} between them.\n const penIdx = segments.lastIndexOf(penultimate);\n const termIdx = segments.lastIndexOf(staticSegments[staticSegments.length - 1]);\n const hasParamBetween = segments.slice(penIdx + 1, termIdx).some((s) => s.startsWith('{'));\n if (hasParamBetween) {\n const prefix = toSnake(singularize(penultimate));\n resource = `${prefix}_${resource}`;\n }\n }\n\n // Singularize when:\n // * there's a trailing path param (single-resource read/update/delete), or\n // * the verb itself implies a single-resource operation (e.g. POST → create\n // always creates one item even when posted to a collection endpoint).\n const isSingleResource = trailingParam || verb === 'create';\n const noun = isSingleResource ? singularize(resource) : resource;\n\n // For \"list\" verb, keep plural\n const finalNoun = verb === 'list' ? resource : noun;\n\n return `${verb}_${finalNoun}`;\n}\n\n/**\n * Resolve all operations in the spec, applying hints and mount rules.\n *\n * @param spec - The parsed API spec\n * @param hints - Per-operation overrides keyed by \"METHOD /path\"\n * @param mountRules - Service name → target service mappings\n * @returns Resolved operations ready for emitter consumption\n */\nexport function resolveOperations(\n spec: ApiSpec,\n hints?: Record<string, OperationHint>,\n mountRules?: Record<string, string>,\n): ResolvedOperation[] {\n const resolved: ResolvedOperation[] = [];\n const hintMap = hints ?? {};\n const mounts = mountRules ?? {};\n\n for (const service of spec.services) {\n for (const op of service.operations) {\n const key = `${op.httpMethod.toUpperCase()} ${op.path}`;\n const hint = hintMap[key];\n\n // Resolve method name: hint > algorithm\n const methodName = hint?.name ?? deriveMethodName(op, service);\n\n // Resolve mount target: per-op hint > service mount rule > original service\n const mountOn = hint?.mountOn ?? mounts[service.name] ?? service.name;\n\n // Build wrappers for split operations\n let wrappers: ResolvedWrapper[] | undefined;\n if (hint?.split) {\n wrappers = hint.split.map((sh) => ({\n name: sh.name,\n targetVariant: sh.targetVariant,\n defaults: sh.defaults ?? {},\n inferFromClient: sh.inferFromClient ?? [],\n exposedParams: sh.exposedParams ?? [],\n optionalParams: sh.optionalParams ?? [],\n responseModelName: resolveResponseModelName(op),\n }));\n }\n\n resolved.push({\n operation: op,\n service,\n methodName,\n mountOn,\n wrappers,\n defaults: hint?.defaults ?? {},\n inferFromClient: hint?.inferFromClient ?? [],\n urlBuilder: hint?.urlBuilder ?? false,\n });\n }\n }\n\n return resolved;\n}\n\n/** Extract the response model name from an operation (for wrapper metadata). */\nfunction resolveResponseModelName(op: Operation): string | null {\n if (op.httpMethod === 'delete') return null;\n const ref = op.response;\n if (ref.kind === 'model') return ref.name;\n if (ref.kind === 'nullable' && ref.inner.kind === 'model') return ref.inner.name;\n return null;\n}\n","import type { ApiSpec, Model, TypeRef, Service } from '../ir/types.js';\nimport { walkTypeRef } from '../ir/types.js';\nimport type { OperationHint } from '../ir/operation-hints.js';\nimport { resolveOperations } from '../ir/operation-hints.js';\nimport type { Emitter, EmitterContext, GeneratedFile, OperationsMap } from './types.js';\nimport type { ApiSurface, OverlayLookup } from '../compat/types.js';\nimport { toSnakeCase } from '../utils/naming.js';\n\nexport function buildEmitterContext(\n spec: ApiSpec,\n options: {\n namespace: string;\n outputDir: string;\n apiSurface?: ApiSurface;\n overlayLookup?: OverlayLookup;\n operationHints?: Record<string, OperationHint>;\n mountRules?: Record<string, string>;\n target?: string;\n priorTargetManifestPaths?: Set<string>;\n },\n): EmitterContext {\n return {\n namespace: toSnakeCase(options.namespace),\n namespacePascal: options.namespace,\n spec,\n outputDir: options.outputDir,\n apiSurface: options.apiSurface,\n overlayLookup: options.overlayLookup,\n resolvedOperations: resolveOperations(spec, options.operationHints, options.mountRules),\n targetDir: options.target,\n priorTargetManifestPaths: options.priorTargetManifestPaths,\n };\n}\n\n/**\n * Collect model and enum names transitively referenced by service operations.\n * Walks operation parameters, request bodies, responses, and pagination item\n * types, then chases model field references until the set stabilizes.\n */\nexport function collectReferencedNames(\n services: Service[],\n models: Model[],\n): { models: Set<string>; enums: Set<string> } {\n const referencedModels = new Set<string>();\n const referencedEnums = new Set<string>();\n\n const collectFromTypeRef = (ref: TypeRef): void => {\n walkTypeRef(ref, {\n model: (r) => referencedModels.add(r.name),\n enum: (r) => referencedEnums.add(r.name),\n });\n };\n\n // Seed: walk every operation's params, request body, response, errors, and pagination\n for (const service of services) {\n for (const op of service.operations) {\n for (const p of [...op.pathParams, ...op.queryParams, ...op.headerParams, ...(op.cookieParams ?? [])]) {\n collectFromTypeRef(p.type);\n }\n if (op.requestBody) collectFromTypeRef(op.requestBody);\n collectFromTypeRef(op.response);\n if (op.pagination) collectFromTypeRef(op.pagination.itemType);\n for (const err of op.errors) {\n if (err.type) collectFromTypeRef(err.type);\n }\n if (op.successResponses) {\n for (const sr of op.successResponses) {\n collectFromTypeRef(sr.type);\n }\n }\n }\n }\n\n // Preserve discriminated models as public SDK types even when no operation\n // returns them directly. This matters for event/webhook unions where the base\n // operation references a generic envelope but the variant structs are still\n // useful public surface.\n for (const model of models) {\n if (isDiscriminatedModel(model)) {\n referencedModels.add(model.name);\n }\n }\n\n // Chase: transitively resolve model field references until stable\n const modelsByName = new Map(models.map((m) => [m.name, m]));\n const visited = new Set<string>();\n const queue = [...referencedModels];\n while (queue.length > 0) {\n const name = queue.pop()!;\n if (visited.has(name)) continue;\n visited.add(name);\n const model = modelsByName.get(name);\n if (!model) continue;\n for (const field of model.fields) {\n collectFromTypeRef(field.type);\n // If new models were discovered, enqueue them\n for (const m of referencedModels) {\n if (!visited.has(m)) queue.push(m);\n }\n }\n }\n\n return { models: referencedModels, enums: referencedEnums };\n}\n\nfunction isDiscriminatedModel(model: Model): boolean {\n return model.fields.some(\n (field) =>\n (field.name === 'event' || field.name === 'type' || field.name === 'object') && field.type.kind === 'literal',\n );\n}\n\n/** Collect all generated files from an emitter (no headers, no path prefixes). */\nexport function generateAllFiles(spec: ApiSpec, emitter: Emitter, ctx: EmitterContext): GeneratedFile[] {\n const referenced = collectReferencedNames(spec.services, spec.models);\n const reachableModels = spec.models.filter((m) => referenced.models.has(m.name));\n const reachableEnums = spec.enums.filter((e) => referenced.enums.has(e.name));\n const reachableSpec: ApiSpec = { ...spec, models: reachableModels, enums: reachableEnums };\n\n return [\n ...emitter.generateModels(reachableModels, ctx),\n ...emitter.generateEnums(reachableEnums, ctx),\n ...emitter.generateResources(spec.services, ctx),\n ...emitter.generateClient(spec, ctx),\n ...emitter.generateErrors(ctx),\n ...(emitter.generateTypeSignatures?.(reachableSpec, ctx) ?? []),\n ...emitter.generateTests(reachableSpec, ctx),\n ];\n}\n\n/** Apply file header to generated files, respecting headerPlacement and JSON files. */\nexport function applyFileHeaders(files: GeneratedFile[], header: string): GeneratedFile[] {\n return files.map((f) => ({\n ...f,\n content:\n !header || f.path.endsWith('.json') || f.headerPlacement === 'skip' ? f.content : header + '\\n\\n' + f.content,\n skipIfExists: f.skipIfExists ?? false,\n }));\n}\n\nexport function generateFiles(\n spec: ApiSpec,\n emitter: Emitter,\n options: {\n namespace: string;\n outputDir: string;\n apiSurface?: ApiSurface;\n overlayLookup?: OverlayLookup;\n operationHints?: Record<string, OperationHint>;\n mountRules?: Record<string, string>;\n target?: string;\n priorTargetManifestPaths?: Set<string>;\n },\n): { files: GeneratedFile[]; ctx: EmitterContext; header: string; operations?: OperationsMap } {\n const ctx = buildEmitterContext(spec, options);\n const files = generateAllFiles(spec, emitter, ctx);\n const operations = emitter.buildOperationsMap?.(spec, ctx);\n const header = emitter.fileHeader();\n return { files: applyFileHeaders(files, header), ctx, header, operations };\n}\n","import * as fs from 'node:fs/promises';\nimport path from 'node:path';\nimport type { GeneratedFile } from './types.js';\nimport { writeFiles, type WriteResult } from './writer.js';\nimport { extractStatements } from './merger.js';\nimport { hasGrammar } from './merger.js';\n\n/**\n * Resolve a relative import path against a source file path to get the\n * target file path. Handles implicit .ts extensions and /index.ts.\n */\nfunction resolveImportPath(\n fromFilePath: string,\n importModulePath: string,\n knownPaths: Set<string>,\n): string | undefined {\n // Strip quotes from module path key (tree-sitter keeps them)\n const cleaned = importModulePath.replace(/^['\"]|['\"]$/g, '');\n // Skip non-relative imports (node_modules, bare specifiers)\n if (!cleaned.startsWith('.')) return undefined;\n\n const dir = path.dirname(fromFilePath);\n const resolved = path.normalize(path.join(dir, cleaned));\n\n // Try exact match, .ts, /index.ts\n for (const candidate of [resolved, `${resolved}.ts`, `${resolved}/index.ts`]) {\n if (knownPaths.has(candidate)) return candidate;\n }\n return undefined;\n}\n\n/**\n * Determine whether a generated file is a \"root\" — a file that should always\n * be integrated into the target. Roots are entry points from which we trace\n * the import graph. Everything else must be reachable from a root.\n *\n * Roots: resource classes, client, config, errors, enums, barrel index files.\n * Non-roots: serializers, fixtures, standalone interfaces, test files.\n */\nfunction isRootFile(filePath: string): boolean {\n // Fixtures are never roots (and should be filtered by integrateTarget already)\n if (filePath.includes('/fixtures/')) return false;\n // Test files are roots — they are standalone entry points that belong in the\n // target repo even though nothing imports them.\n if (filePath.endsWith('.spec.ts') || filePath.endsWith('.test.ts')) return true;\n // Serializer files\n if (filePath.includes('/serializers/')) return false;\n // Standalone interface files (not barrel/index)\n if (filePath.includes('/interfaces/') && !filePath.endsWith('/index.ts')) return false;\n // Everything else is a root: resource classes, client, config, errors, enums, barrel files\n return true;\n}\n\n/**\n * Build a file-level dependency graph from generated files and return only\n * files reachable from root entry points. Uses tree-sitter to parse imports.\n */\nexport async function treeShakeFiles(files: GeneratedFile[], language: string): Promise<GeneratedFile[]> {\n if (!hasGrammar(language)) return files;\n\n const knownPaths = new Set(files.map((f) => f.path));\n\n // Build dependency graph: file → set of files it imports\n const deps = new Map<string, Set<string>>();\n for (const file of files) {\n // Only parse .ts/.js files (skip JSON, etc.)\n if (!file.path.endsWith('.ts') && !file.path.endsWith('.js')) {\n deps.set(file.path, new Set());\n continue;\n }\n const parsed = await extractStatements(file.content, language);\n const fileDeps = new Set<string>();\n for (const imp of parsed.imports) {\n const resolved = resolveImportPath(file.path, imp.key, knownPaths);\n if (resolved) fileDeps.add(resolved);\n }\n // Also check re-export statements (export * from './foo')\n for (const stmt of parsed.statements) {\n if (stmt.kind === 'reexport') {\n // Extract module path from \"export * from './foo'\" or \"export { X } from './foo'\"\n const match = stmt.text.match(/from\\s+['\"]([^'\"]+)['\"]/);\n if (match) {\n const resolved = resolveImportPath(file.path, match[1], knownPaths);\n if (resolved) fileDeps.add(resolved);\n }\n }\n }\n deps.set(file.path, fileDeps);\n }\n\n // Determine which file extensions are source code for this language\n const codeExtensions = new Set([\n '.ts',\n '.js',\n '.tsx',\n '.jsx',\n '.py',\n '.rb',\n '.go',\n '.rs',\n '.kt',\n '.cs',\n '.ex',\n '.exs',\n '.php',\n ]);\n\n // BFS from roots\n const reachable = new Set<string>();\n const queue: string[] = [];\n for (const file of files) {\n const ext = file.path.slice(file.path.lastIndexOf('.'));\n // Non-code files (JSON, etc.) are always reachable — they can't participate\n // in the import graph and are loaded at runtime (e.g. test fixtures).\n if (!codeExtensions.has(ext)) {\n reachable.add(file.path);\n continue;\n }\n if (isRootFile(file.path)) {\n reachable.add(file.path);\n queue.push(file.path);\n }\n }\n while (queue.length > 0) {\n const current = queue.pop()!;\n const fileDeps = deps.get(current);\n if (!fileDeps) continue;\n for (const dep of fileDeps) {\n if (!reachable.has(dep)) {\n reachable.add(dep);\n queue.push(dep);\n }\n }\n }\n\n return files.filter((f) => reachable.has(f.path));\n}\n\nexport function mapFilesForTargetIntegration(files: GeneratedFile[], language: string): GeneratedFile[] {\n const langPrefix = `${language}/`;\n return files\n .filter((f) => f.integrateTarget !== false) // integrateTarget: false files are standalone-only\n .map((f) => {\n const stripped = f.path.startsWith(langPrefix) ? f.path.replace(langPrefix, '') : f.path;\n return {\n ...f,\n skipIfExists: false, // Always merge in target — never hard-skip\n path: stripped,\n };\n });\n}\n\n/**\n * Resolve file-to-directory conflicts in the target.\n *\n * When a generated file creates a package directory (e.g., `api_keys/__init__.py`)\n * that would shadow an existing module file (e.g., `api_keys.py`), move the\n * module file's content into `_compat.py` inside the package and add a\n * re-export from `__init__.py`. This preserves backward-compatible imports\n * (e.g., `from workos.api_keys import ApiKeysModule`) while the package directory\n * provides the generated models and resource classes.\n */\nasync function resolveFileToDirectoryConflicts(\n files: GeneratedFile[],\n targetDir: string,\n): Promise<{ files: GeneratedFile[]; removals: string[] }> {\n const result = [...files];\n const removals: string[] = [];\n\n for (let i = 0; i < result.length; i++) {\n const file = result[i];\n // Match package init files: e.g., src/workos/api_keys/__init__.py\n const match = file.path.match(/^(.+)\\/__init__\\.py$/);\n if (!match) continue;\n\n const dirPath = match[1]; // e.g., src/workos/api_keys\n const moduleFilePath = `${dirPath}.py`; // e.g., src/workos/api_keys.py\n const fullModulePath = path.join(targetDir, moduleFilePath);\n\n let moduleContent: string;\n try {\n moduleContent = await fs.readFile(fullModulePath, 'utf-8');\n } catch {\n continue; // Module file doesn't exist — no conflict\n }\n\n // Create a compat shim inside the package with the old module's content\n const compatPath = `${dirPath}/_compat.py`;\n result.push({\n path: compatPath,\n content: moduleContent,\n overwriteExisting: true,\n });\n\n // Append re-export from _compat to __init__.py so existing imports work.\n // Compat must come AFTER generated models so hand-written types take\n // precedence over generated types with the same name.\n const compatImport = 'from ._compat import * # noqa: F401,F403 # pyright: ignore[reportUnusedImport]';\n const existingContent = file.content.endsWith('\\n') ? file.content : file.content + '\\n';\n result[i] = {\n ...file,\n content: existingContent + compatImport + '\\n',\n };\n\n // Schedule the shadowed module file for removal\n removals.push(fullModulePath);\n }\n\n return { files: result, removals };\n}\n\nexport interface IntegrateResult extends WriteResult {\n /** Final set of paths this run claims ownership of in the target (post tree-shake + conflict resolution). */\n emittedPaths: string[];\n}\n\nexport async function integrateGeneratedFiles(opts: {\n files: GeneratedFile[];\n language: string;\n targetDir: string;\n header: string;\n}): Promise<IntegrateResult> {\n const mapped = mapFilesForTargetIntegration(opts.files, opts.language);\n const shaken = await treeShakeFiles(mapped, opts.language);\n\n // Handle file-to-directory conflicts before writing\n const { files: resolved, removals } = await resolveFileToDirectoryConflicts(shaken, opts.targetDir);\n\n const result = await writeFiles(resolved, opts.targetDir, {\n language: opts.language,\n header: opts.header,\n });\n\n // Remove shadowed module files after integration\n for (const filePath of removals) {\n try {\n await fs.unlink(filePath);\n } catch {\n // File may already be gone\n }\n }\n\n // The manifest tracks ALL files oagen owns, including tree-shaken ones.\n // Tree-shaking decides what to write, but shaken files are still oagen-managed\n // and must not be pruned from the target on subsequent runs.\n return { ...result, emittedPaths: mapped.map((f) => f.path) };\n}\n","/**\n * Post-integration formatter.\n *\n * After generating and merging files into a target directory, runs the\n * emitter-provided format command on all written/merged files so that\n * generated code matches the target project's style conventions.\n */\n\nimport { execFile } from 'node:child_process';\nimport { promisify } from 'node:util';\nimport * as path from 'node:path';\nimport type { Emitter } from './types.js';\n\nconst execFileAsync = promisify(execFile);\n\n/**\n * Run the emitter's format command on the given target files.\n * Silently skips if the emitter has no formatCommand or returns null.\n */\nexport async function formatTargetFiles(emitter: Emitter, targetDir: string, filePaths: string[]): Promise<void> {\n if (filePaths.length === 0) return;\n if (!emitter.formatCommand) return;\n\n const formatCmd = emitter.formatCommand(targetDir);\n if (!formatCmd) return;\n\n const absolutePaths = filePaths.map((f) => path.resolve(targetDir, f));\n const batchSize = formatCmd.batchSize ?? 100;\n\n process.stderr.write(\n `[oagen] formatting ${absolutePaths.length} file(s) with ${formatCmd.cmd} (batch ${batchSize})\\n`,\n );\n\n for (let i = 0; i < absolutePaths.length; i += batchSize) {\n const batch = absolutePaths.slice(i, i + batchSize);\n try {\n await execFileAsync(formatCmd.cmd, [...formatCmd.args, ...batch], {\n cwd: targetDir,\n maxBuffer: 10 * 1024 * 1024,\n timeout: 120_000,\n });\n } catch (err) {\n // Formatter failed on this batch — continue with remaining batches.\n // Surface the failure on stderr so misconfigured commands don't silently\n // leave generated code unformatted every regen.\n const msg = err instanceof Error ? err.message : String(err);\n process.stderr.write(`[oagen] formatter batch failed: ${msg}\\n`);\n }\n }\n}\n","import * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\n\n/**\n * Prune-manifest support for `oagen generate`.\n *\n * The manifest records every auto-generated file emitted on the previous run,\n * relative to the directory it lives in (either the `--output` standalone dir\n * or the `--target` integration dir). On the next run we diff the previous\n * list against the current emission set and delete anything that's no longer\n * produced — preventing stale-file accumulation across regens.\n *\n * Design notes:\n * - The manifest is versioned so future format changes can be handled safely.\n * - Paths are stored sorted for deterministic diffs in git.\n * - Deletion is gated on a header guard when one is available: we only remove\n * files whose contents start with the auto-generated header. This protects\n * a hand-maintained file that happens to share a name with a previously\n * generated one (extremely rare, but worth catching).\n * - On first adoption (no previous manifest), pruning is skipped and a\n * one-line notice is printed — no surprise deletions.\n */\n\nexport const MANIFEST_FILENAME = '.oagen-manifest.json';\nconst MANIFEST_VERSION = 2;\n\nexport interface Manifest {\n /** Schema version. Bump when the format changes incompatibly. */\n version: number;\n /** Emitter language (e.g. \"python\"). Used only as a consistency hint. */\n language: string;\n /** Human-readable or package-level SDK identity (e.g. \"workos-php\"). */\n sdkName?: string;\n /** ISO-8601 timestamp of the run that produced this manifest. */\n generatedAt: string;\n /** SHA-256 hash of the source OpenAPI spec used for generation. */\n specSha?: string;\n /** Path or reference to the source spec. */\n specPath?: string;\n /** Git SHA or version of the emitter code used. */\n emitterSha?: string;\n /** Emitter version string if available. */\n emitterVersion?: string;\n /** SHA-256 hash of the effective oagen.config.ts after resolution. */\n configSha?: string;\n /** Version of the compat snapshot/report schema expected by this generation. */\n compatSchemaVersion?: string;\n /** Sorted list of paths, relative to the manifest's containing directory. */\n files: string[];\n /** Maps \"METHOD /path\" to SDK method + service property name. */\n operations?: Record<string, unknown>;\n}\n\nexport interface PruneResult {\n /** Paths actually deleted. */\n pruned: string[];\n /** Paths skipped because the header guard didn't match (preserved). */\n preserved: string[];\n /** Paths already absent on disk (nothing to do). */\n missing: string[];\n}\n\n/** Read `.oagen-manifest.json` from a directory. Returns null if absent or malformed. */\nexport async function readManifest(dir: string): Promise<Manifest | null> {\n const manifestPath = path.join(dir, MANIFEST_FILENAME);\n let raw: string;\n try {\n raw = await fs.readFile(manifestPath, 'utf-8');\n } catch {\n return null;\n }\n try {\n const parsed = JSON.parse(raw) as Partial<Manifest>;\n if (\n typeof parsed.version !== 'number' ||\n typeof parsed.language !== 'string' ||\n typeof parsed.generatedAt !== 'string' ||\n !Array.isArray(parsed.files) ||\n !parsed.files.every((p): p is string => typeof p === 'string')\n ) {\n return null;\n }\n if (parsed.version > MANIFEST_VERSION) {\n console.warn(\n `[oagen] ${MANIFEST_FILENAME} schema version ${parsed.version} is newer than supported (${MANIFEST_VERSION}); ignoring for pruning.`,\n );\n return null;\n }\n // v1 manifests are forward-compatible — new fields are simply absent\n return parsed as Manifest;\n } catch {\n return null;\n }\n}\n\n/** Options for writing a manifest. */\nexport interface WriteManifestOpts {\n language: string;\n files: Iterable<string>;\n sdkName?: string;\n specSha?: string;\n specPath?: string;\n emitterSha?: string;\n emitterVersion?: string;\n configSha?: string;\n compatSchemaVersion?: string;\n operations?: Record<string, unknown>;\n}\n\n/** Write `.oagen-manifest.json` to a directory with sorted paths. */\nexport async function writeManifest(dir: string, opts: WriteManifestOpts): Promise<void> {\n const manifest: Manifest = {\n version: MANIFEST_VERSION,\n language: opts.language,\n ...(opts.sdkName !== undefined ? { sdkName: opts.sdkName } : {}),\n generatedAt: new Date().toISOString(),\n ...(opts.specSha !== undefined ? { specSha: opts.specSha } : {}),\n ...(opts.specPath !== undefined ? { specPath: opts.specPath } : {}),\n ...(opts.emitterSha !== undefined ? { emitterSha: opts.emitterSha } : {}),\n ...(opts.emitterVersion !== undefined ? { emitterVersion: opts.emitterVersion } : {}),\n ...(opts.configSha !== undefined ? { configSha: opts.configSha } : {}),\n ...(opts.compatSchemaVersion !== undefined ? { compatSchemaVersion: opts.compatSchemaVersion } : {}),\n files: [...new Set(opts.files)].sort(),\n ...(opts.operations !== undefined ? { operations: opts.operations } : {}),\n };\n const manifestPath = path.join(dir, MANIFEST_FILENAME);\n await fs.mkdir(dir, { recursive: true });\n await fs.writeFile(manifestPath, JSON.stringify(manifest, null, 2) + '\\n', 'utf-8');\n}\n\n/** Return the set of previous paths no longer present in the current emission. */\nexport function computeStalePaths(prev: Manifest, currentPaths: Iterable<string>): string[] {\n const current = new Set(currentPaths);\n return prev.files.filter((p) => !current.has(p)).sort();\n}\n\n/**\n * Delete stale files from `dir`.\n *\n * When `header` is provided, a file is only deleted if its contents start with\n * that header — so hand-maintained files that somehow collide with a previously\n * generated path can't be clobbered. When `header` is omitted, the guard is\n * skipped (useful for non-source artifacts like fixture JSON).\n *\n * Returns lists for reporting. Empty parent directories are removed after\n * deletion, up to (but not including) `dir` itself.\n */\nexport async function pruneStaleFiles(\n dir: string,\n paths: string[],\n opts: { header?: string } = {},\n): Promise<PruneResult> {\n const pruned: string[] = [];\n const preserved: string[] = [];\n const missing: string[] = [];\n\n for (const relPath of paths) {\n const fullPath = path.join(dir, relPath);\n let content: string;\n try {\n content = await fs.readFile(fullPath, 'utf-8');\n } catch {\n missing.push(relPath);\n continue;\n }\n if (opts.header && !content.startsWith(opts.header)) {\n preserved.push(relPath);\n continue;\n }\n try {\n await fs.unlink(fullPath);\n pruned.push(relPath);\n } catch {\n // Racing deletion or permission issue — treat as missing rather than fatal.\n missing.push(relPath);\n continue;\n }\n await removeEmptyParents(path.dirname(fullPath), dir);\n }\n\n return { pruned, preserved, missing };\n}\n\n/**\n * Walk up from `startDir` removing empty directories until we hit `stopDir`\n * (exclusive) or a non-empty directory. Silently ignores errors.\n */\nasync function removeEmptyParents(startDir: string, stopDir: string): Promise<void> {\n let current = path.resolve(startDir);\n const stop = path.resolve(stopDir);\n while (current.startsWith(stop + path.sep) && current !== stop) {\n let entries: string[];\n try {\n entries = await fs.readdir(current);\n } catch {\n return;\n }\n if (entries.length > 0) return;\n try {\n await fs.rmdir(current);\n } catch {\n return;\n }\n current = path.dirname(current);\n }\n}\n","import type { ApiSpec } from '../ir/types.js';\nimport type { OperationHint } from '../ir/operation-hints.js';\nimport type { Emitter, GeneratedFile } from './types.js';\nimport type { ApiSurface, OverlayLookup } from '../compat/types.js';\nimport { writeFiles } from './writer.js';\nimport { generateFiles } from './generate-files.js';\nimport { integrateGeneratedFiles } from './integrate.js';\nimport { formatTargetFiles } from './formatter.js';\nimport { computeStalePaths, MANIFEST_FILENAME, pruneStaleFiles, readManifest, writeManifest } from './manifest.js';\n\nexport async function generate(\n spec: ApiSpec,\n emitter: Emitter,\n options: {\n namespace: string;\n dryRun?: boolean;\n outputDir: string;\n target?: string;\n apiSurface?: ApiSurface;\n overlayLookup?: OverlayLookup;\n operationHints?: Record<string, OperationHint>;\n mountRules?: Record<string, string>;\n /** When true, skip deletion of files recorded in the previous manifest but not in the current emission. */\n noPrune?: boolean;\n },\n): Promise<GeneratedFile[]> {\n // Read the target's previous manifest up front so emitters can mark files\n // the prior run wrote as safe-to-overwrite (vs files a human hand-maintains).\n // Skipped when --no-prune is set so users opting out of lifecycle tracking\n // also opt out of overwrite-on-regen behavior.\n const targetManifestForCtx = options.target && !options.noPrune ? await readManifest(options.target) : null;\n const priorTargetManifestPaths = targetManifestForCtx ? new Set(targetManifestForCtx.files) : undefined;\n\n const {\n files: withHeaders,\n header,\n operations,\n } = generateFiles(spec, emitter, {\n ...options,\n priorTargetManifestPaths,\n });\n\n if (options.dryRun) {\n if (options.target) {\n console.log(`\\nTarget integration (${options.target}):`);\n for (const f of withHeaders) {\n console.log(` ${f.path}`);\n }\n }\n return withHeaders;\n }\n\n // Read previous manifest BEFORE writing so a manifest overwrite can't alter the diff.\n const outputPrevManifest = options.noPrune ? null : await readManifest(options.outputDir);\n\n const writeResult = await writeFiles(withHeaders, options.outputDir, {\n language: emitter.language,\n header,\n });\n\n if (writeResult.merged.length > 0) {\n console.log(`Merged into ${writeResult.merged.length} existing files (additive only)`);\n }\n if (writeResult.ignored.length > 0) {\n console.log(`Ignored ${writeResult.ignored.length} files (@oagen-ignore-file)`);\n }\n\n const outputEmittedPaths = withHeaders.map((f) => f.path);\n await applyManifestPrune({\n dir: options.outputDir,\n label: 'Output',\n prevManifest: outputPrevManifest,\n currentPaths: outputEmittedPaths,\n language: emitter.language,\n header,\n noPrune: options.noPrune,\n operations,\n });\n\n // Format output files so the emitter's formatter runs even without --target.\n const allOutputFiles = [...writeResult.written, ...writeResult.merged];\n if (allOutputFiles.length > 0) {\n await formatTargetFiles(emitter, options.outputDir, allOutputFiles);\n }\n\n // Target integration pass\n if (options.target) {\n // Reuse the manifest we already read to build the emitter context. This\n // is correct because nothing between the two reads writes the manifest.\n const targetPrevManifest = targetManifestForCtx;\n\n const targetResult = await integrateGeneratedFiles({\n files: withHeaders,\n language: emitter.language,\n targetDir: options.target,\n header,\n });\n\n if (targetResult.written.length > 0) {\n console.log(`Target: created ${targetResult.written.length} new files`);\n }\n if (targetResult.merged.length > 0) {\n console.log(`Target: merged into ${targetResult.merged.length} existing files (additive only)`);\n }\n if (targetResult.skipped.length > 0) {\n console.log(`Target: skipped ${targetResult.skipped.length} files (excluded or no grammar)`);\n }\n\n await applyManifestPrune({\n dir: options.target,\n label: 'Target',\n prevManifest: targetPrevManifest,\n currentPaths: targetResult.emittedPaths,\n language: emitter.language,\n header,\n noPrune: options.noPrune,\n operations,\n });\n\n // Run the emitter's formatter on all written/merged/identical files\n const allTargetFiles = [...targetResult.written, ...targetResult.merged, ...targetResult.identical];\n if (allTargetFiles.length > 0) {\n await formatTargetFiles(emitter, options.target, allTargetFiles);\n }\n }\n\n return withHeaders;\n}\n\n/**\n * Prune files recorded in the previous manifest but absent from the current emission,\n * then write the fresh manifest. Safe on first adoption (no previous manifest).\n */\nasync function applyManifestPrune(opts: {\n dir: string;\n label: string;\n prevManifest: Awaited<ReturnType<typeof readManifest>>;\n currentPaths: string[];\n language: string;\n header: string;\n noPrune?: boolean;\n operations?: Record<string, unknown>;\n}): Promise<void> {\n const manifestOpts = { language: opts.language, files: opts.currentPaths, operations: opts.operations };\n if (opts.noPrune) {\n // Still refresh the manifest so future runs with pruning enabled have a baseline.\n await writeManifest(opts.dir, manifestOpts);\n return;\n }\n\n if (!opts.prevManifest) {\n console.log(\n `${opts.label}: no ${MANIFEST_FILENAME} found — skipping prune (this baseline manifest will be written now).`,\n );\n await writeManifest(opts.dir, manifestOpts);\n return;\n }\n\n const stale = computeStalePaths(opts.prevManifest, opts.currentPaths);\n if (stale.length > 0) {\n const { pruned, preserved } = await pruneStaleFiles(opts.dir, stale, { header: opts.header });\n if (pruned.length > 0) {\n console.log(`${opts.label}: pruned ${pruned.length} stale file${pruned.length === 1 ? '' : 's'}`);\n }\n if (preserved.length > 0) {\n console.log(\n `${opts.label}: preserved ${preserved.length} file${preserved.length === 1 ? '' : 's'} in previous manifest but lacking the auto-generated header (possibly hand-edited).`,\n );\n for (const p of preserved) console.log(` ${p}`);\n }\n }\n\n await writeManifest(opts.dir, manifestOpts);\n}\n","import { RegistryError } from '../errors.js';\nimport type { Emitter } from './types.js';\n\nconst emitters = new Map<string, Emitter>();\n\nexport function registerEmitter(emitter: Emitter): void {\n emitters.set(emitter.language, emitter);\n}\n\nexport function getEmitter(language: string): Emitter {\n const emitter = emitters.get(language);\n if (!emitter) {\n const available = [...emitters.keys()].join(', ') || '(none)';\n throw new RegistryError(\n `Unknown language: ${language}. Available: ${available}`,\n `Register an emitter for \"${language}\" via registerEmitter() or check your oagen.config.ts plugin configuration.`,\n );\n }\n return emitter;\n}\n","import type { ApiSurface, LanguageHints } from './types.js';\nimport { splitWords } from '../utils/naming.js';\n\n/** Untyped map patterns — hoisted to avoid allocation on every isTypeEquivalent call. */\nconst UNTYPED_MAP_PATTERNS = new Set([\n 'Record<string, unknown>',\n 'Record<string, any>',\n '{ [key: string]: any; }',\n '{ [key: string]: unknown; }',\n 'any',\n]);\n\nexport const NAMED_TYPE_RE = /^[A-Z][a-zA-Z0-9]*$/;\n\n/** Check whether a type name exists as an interface, class, or enum in a surface. */\nexport function typeExistsInSurface(name: string, surface: ApiSurface): boolean {\n return !!(surface.interfaces[name] || surface.classes[name] || surface.enums[name]);\n}\n\n/** Split a PascalCase string into words, keeping only words > 2 chars. */\nfunction splitPascalWords(s: string): string[] {\n return splitWords(s).filter((w) => w.length > 2);\n}\n\n/**\n * Check whether two named types share enough PascalCase word components to\n * be considered equivalent (handles name reordering from Json merges, etc.).\n * Both names have `Response$` stripped before comparison.\n */\nexport function namedTypeWordsOverlap(a: string, b: string, minOverlap = 1): boolean {\n const aNoResp = a.replace(/Response$/, '');\n const bNoResp = b.replace(/Response$/, '');\n const aWords = new Set(splitPascalWords(aNoResp).map((w) => w.toLowerCase()));\n const bWords = new Set(splitPascalWords(bNoResp).map((w) => w.toLowerCase()));\n const overlap = [...aWords].filter((w) => bWords.has(w));\n return overlap.length >= minOverlap && overlap.length >= Math.min(aWords.size, bWords.size) - 1;\n}\n\n/** Split a pipe-delimited union string into trimmed, non-empty members. */\nfunction parseUnionMembers(s: string): string[] {\n return s\n .split('|')\n .map((p) => p.trim())\n .filter(Boolean);\n}\n\n/**\n * Default implementation of isNullableOnlyDifference — shared across extractors.\n * Returns true when stripping nullable wrappers from both sides yields the same\n * type, but the original types differ (i.e., the only difference is nullability).\n */\nexport function defaultIsNullableOnlyDifference(\n hints: Pick<LanguageHints, 'stripNullable'>,\n a: string,\n b: string,\n): boolean {\n return (hints.stripNullable(a) ?? a) === (hints.stripNullable(b) ?? b) && a !== b;\n}\n\n/**\n * Node/TypeScript language hints — reference implementation.\n * Extracted from the hardcoded logic previously in differ.ts and overlay.ts.\n */\nexport const nodeHints: LanguageHints = {\n stripNullable(type: string): string | null {\n const members = parseUnionMembers(type);\n const stripped = members.filter((p) => p !== 'null');\n if (stripped.length === members.length) {\n return null; // no null member found\n }\n return stripped.join(' | ');\n },\n\n isNullableOnlyDifference(a: string, b: string): boolean {\n return (nodeHints.stripNullable(a) ?? a) === (nodeHints.stripNullable(b) ?? b) && a !== b;\n },\n\n isUnionReorder(a: string, b: string): boolean {\n const membersA = parseUnionMembers(a).sort();\n const membersB = parseUnionMembers(b).sort();\n if (membersA.length !== membersB.length || membersA.length < 2) return false;\n return membersA.every((m, i) => m === membersB[i]);\n },\n\n isGenericTypeParam(type: string): boolean {\n if (/^[A-Z]$/.test(type)) return true;\n if (/^T[A-Z][a-zA-Z]*$/.test(type)) return true;\n if (/^[A-Z]\\[\\]$/.test(type) || /^T[A-Z][a-zA-Z]*\\[\\]$/.test(type)) return true;\n return false;\n },\n\n isExtractionArtifact(type: string): boolean {\n return type === 'any' || type === 'Record<string, unknown>';\n },\n\n tolerateCategoryMismatch: true,\n\n extractReturnTypeName(returnType: string): string | null {\n let inner = returnType;\n while (inner.startsWith('Promise<') && inner.endsWith('>')) {\n inner = inner.slice(8, -1);\n }\n const genericMatch = inner.match(/^[A-Za-z]+<(.+)>$/);\n if (genericMatch) {\n inner = genericMatch[1];\n }\n inner = inner.replace(/\\[\\]$/, '');\n if (['void', 'string', 'number', 'boolean', 'any', 'unknown', 'null', 'undefined'].includes(inner)) {\n return null;\n }\n return inner;\n },\n\n extractParamTypeName(paramType: string): string | null {\n if (['string', 'number', 'boolean', 'any', 'unknown'].includes(paramType)) {\n return null;\n }\n return paramType;\n },\n\n propertyMatchesClass(propertyName: string, className: string): boolean {\n // Support both camelCase and snake_case properties matching PascalCase classes\n // e.g., \"organizations\" ≡ \"Organizations\", \"api_keys\" ≡ \"ApiKeys\"\n const normalizedProp = propertyName.replace(/[-_]/g, '').toLowerCase();\n return normalizedProp === className.toLowerCase();\n },\n\n derivedModelNames(modelName: string): string[] {\n return [`${modelName}Response`, `Serialized${modelName}`];\n },\n\n isTypeEquivalent(baselineType: string, candidateType: string, candidateSurface: ApiSurface): boolean {\n // Check if one side is a named enum and the other is an inline union\n // of that enum's string literal values.\n // e.g., baseline: '\"active\" | \"inactive\"', candidate: 'ConnectionState'\n // or baseline: 'ConnectionState', candidate: '\"active\" | \"inactive\"'\n\n // Try: candidate is enum name, baseline is inline union of string literals.\n // The generated enum may have MORE members than the baseline (new spec values),\n // so check that all baseline members exist in the enum (subset match).\n const candEnum = candidateSurface.enums[candidateType];\n if (candEnum) {\n const enumValuesSet = new Set(Object.values(candEnum.members).flatMap((v) => [`\"${v}\"`, `'${v}'`]));\n const baseMembers = parseUnionMembers(baselineType);\n if (baseMembers.length > 0 && baseMembers.every((m) => enumValuesSet.has(m))) {\n return true;\n }\n }\n\n // Tolerate untyped-map equivalences:\n // { [key: string]: any; } ≡ Record<string, unknown> ≡ Record<string, any>\n if (UNTYPED_MAP_PATTERNS.has(baselineType) && UNTYPED_MAP_PATTERNS.has(candidateType)) {\n return true;\n }\n\n // Tolerate inline object literal vs named model in candidate.\n // e.g., baseline: '{ type: \"organization\"; id: string; }', candidate: 'ApiKeyOwner'\n // The named model is more structured but semantically equivalent.\n if (baselineType.startsWith('{') && baselineType.endsWith('}')) {\n if (typeExistsInSurface(candidateType, candidateSurface)) {\n return true;\n }\n }\n\n // Tolerate named-type-to-named-type mismatches when both types exist\n // as models/interfaces/enums in their respective surfaces. This handles\n // cases where the parser qualifies inline types with parent names while\n // the live SDK uses shared types:\n // baseline: RoleResponse, candidate: OrganizationMembershipRole\n // baseline: ConnectionType, candidate: ProfileConnectionType\n // baseline: AuditLogTargetSchema[], candidate: AuditLogSchemaJsonTarget[]\n const baseClean = baselineType.replace(/\\[\\]$/, '');\n const candClean = candidateType.replace(/\\[\\]$/, '');\n const sameArrayness = baselineType.endsWith('[]') === candidateType.endsWith('[]');\n\n // Response suffix equivalence (both directions)\n if (sameArrayness) {\n if (candClean === baseClean + 'Response' || baseClean === candClean + 'Response') {\n return true;\n }\n }\n\n // Both are named types (PascalCase, no operators) — check if candidate\n // is a known model/interface/enum, and baseline looks like a named type too.\n // This tolerates the parser's qualified naming vs the live SDK's shared naming.\n if (sameArrayness && NAMED_TYPE_RE.test(baseClean) && NAMED_TYPE_RE.test(candClean)) {\n if (typeExistsInSurface(candClean, candidateSurface)) {\n // One name contains the other (e.g., ProfileConnectionType contains ConnectionType)\n if (candClean.includes(baseClean) || baseClean.includes(candClean)) {\n return true;\n }\n // Strip Response suffix and check containment\n const baseNoResp = baseClean.replace(/Response$/, '');\n const candNoResp = candClean.replace(/Response$/, '');\n if (candNoResp.includes(baseNoResp) || baseNoResp.includes(candNoResp)) {\n return true;\n }\n // Word-component overlap: split PascalCase into words and check\n // if they share enough meaningful words (handles name reordering\n // from Json merges: AuditLogTargetSchema vs AuditLogSchemaJsonTarget)\n if (namedTypeWordsOverlap(baseClean, candClean, 2)) {\n return true;\n }\n }\n }\n\n return false;\n },\n};\n\n/**\n * Merge partial language hint overrides over nodeHints defaults.\n * Any hint not provided falls back to the Node/TypeScript implementation.\n */\nexport function resolveHints(overrides: Partial<LanguageHints>): LanguageHints {\n return { ...nodeHints, ...overrides };\n}\n","import type { ApiSurface, ApiInterface, ApiMethod, OverlayLookup, LanguageHints } from './types.js';\nimport type { ClassifiedChange } from './classify.js';\nimport type { ApiSpec, Model } from '../ir/types.js';\nimport { toSnakeCase, splitWords } from '../utils/naming.js';\nimport { nodeHints as defaultNodeHints } from './language-hints.js';\n\nexport type { MethodOverlay, OverlayLookup } from './types.js';\n\nexport interface ManifestEntry {\n operationId: string;\n sdkResourceProperty: string;\n sdkMethodName: string;\n httpMethod: string;\n path: string;\n pathParams: string[];\n bodyFields: string[];\n queryFields: string[];\n}\n\n/**\n * Find the class name that owns a given SDK resource property.\n * E.g. if the surface has a class \"Organizations\" with property \"organizations\",\n * and sdkResourceProperty is \"organizations\", return \"Organizations\".\n */\nfunction findClassForProperty(\n surface: ApiSurface,\n sdkResourceProperty: string,\n hints: LanguageHints,\n): string | undefined {\n for (const [className, cls] of Object.entries(surface.classes)) {\n // Check if the class itself maps to this property (language-specific match)\n if (hints.propertyMatchesClass(sdkResourceProperty, className)) {\n return className;\n }\n // Check properties — resolve to the property's type class, not the parent.\n // This prevents generic parent classes (e.g., WorkOS) from being returned\n // when the actual resource class (e.g., ApiKeys) should be used.\n for (const [propName, prop] of Object.entries(cls.properties)) {\n if (propName === sdkResourceProperty) {\n const propType = (prop as { type?: string }).type;\n if (propType && surface.classes[propType]) {\n return propType;\n }\n // Property type not in surface — skip rather than return the parent\n return undefined;\n }\n }\n }\n\n // Strategy 3: Word-suffix fallback\n // \"adminPortal\" → [\"admin\",\"portal\"]; class \"Portal\" → [\"portal\"]\n // [\"portal\"] is a suffix of [\"admin\",\"portal\"] → match\n const propWords = splitWords(sdkResourceProperty).map((w) => w.toLowerCase());\n if (propWords.length > 1) {\n for (const [className] of Object.entries(surface.classes)) {\n const classWords = splitWords(className).map((w) => w.toLowerCase());\n if (classWords.length > 0 && classWords.length < propWords.length) {\n const suffix = propWords.slice(propWords.length - classWords.length);\n if (classWords.every((w, i) => w === suffix[i])) {\n return className;\n }\n }\n }\n }\n\n return undefined;\n}\n\nexport function buildOverlayLookup(\n surface: ApiSurface,\n manifest?: ManifestEntry[],\n spec?: ApiSpec,\n hints?: LanguageHints,\n options?: { strictModelMatch?: boolean },\n): OverlayLookup {\n const resolvedHints = hints ?? defaultNodeHints;\n const lookup: OverlayLookup = {\n methodByOperation: new Map(),\n httpKeyByMethod: new Map(),\n interfaceByName: new Map(),\n typeAliasByName: new Map(),\n requiredExports: new Map(),\n modelNameByIR: new Map(),\n fileBySymbol: new Map(),\n };\n\n // If manifest available, map operationId → HTTP method + path → existing method\n if (manifest) {\n for (const entry of manifest) {\n const key = `${entry.httpMethod.toUpperCase()} ${entry.path}`;\n const className = findClassForProperty(surface, entry.sdkResourceProperty, resolvedHints);\n if (className) {\n let resolvedMethodName = entry.sdkMethodName;\n let methods = surface.classes[className]?.methods[resolvedMethodName];\n\n // Exact match failed — try prefix match on the resolved class.\n // Handles cases where the generated name is shorter than the existing name\n // (e.g., manifest says \"delete\" but existing SDK has \"deleteApiKey\").\n // Only accept when exactly one candidate matches — ambiguous matches are worse than no match.\n if (!methods) {\n const classMethods = surface.classes[className]?.methods ?? {};\n const prefix = resolvedMethodName.toLowerCase();\n const candidates: [string, ApiMethod[]][] = [];\n for (const [name, overloads] of Object.entries(classMethods)) {\n if (name.toLowerCase().startsWith(prefix) && name !== resolvedMethodName) {\n candidates.push([name, overloads]);\n }\n }\n if (candidates.length === 1) {\n methods = candidates[0][1];\n resolvedMethodName = candidates[0][0];\n } else if (candidates.length > 1) {\n // Disambiguate: prefer the candidate whose name is <prefix><pathSegment>\n // derived from the FIRST segment of the operation path. This avoids\n // mismatching when a class combines operations from multiple path groups\n // (e.g., /organizations and /organization_domains both in Organizations).\n const firstSegment =\n entry.path\n .split('/')\n .filter(Boolean)[0]\n ?.replace(/[{}_-]/g, '') ?? '';\n if (firstSegment) {\n const segLower = firstSegment.toLowerCase();\n // Try the path segment as-is and as singular\n const segSingular = segLower.endsWith('s') ? segLower.slice(0, -1) : segLower;\n const best = candidates.find(([name]) => {\n const lower = name.toLowerCase();\n return lower === prefix + segLower || lower === prefix + segSingular;\n });\n if (best) {\n methods = best[1];\n resolvedMethodName = best[0];\n }\n }\n\n // HTTP verb disambiguation: when path disambiguation fails, use the\n // HTTP method to prefer method names that match the verb semantics.\n // E.g., GET → list/get, POST → create, PUT → set/update, DELETE → delete/remove.\n if (!methods) {\n const verbMatch = disambiguateByHttpVerb(candidates, entry.httpMethod);\n if (verbMatch) {\n methods = verbMatch[1];\n resolvedMethodName = verbMatch[0];\n }\n }\n }\n }\n\n // Suffix match: the existing SDK may use a longer controller-prefixed\n // method name that ends with the transformed name.\n // (e.g., manifest says \"validate_api_key\" but existing SDK has\n // \"api_keys_controller_validate_api_key\").\n // Only accept when exactly one candidate matches — ambiguous matches are worse than no match.\n if (!methods) {\n const classMethods = surface.classes[className]?.methods ?? {};\n const suffix = resolvedMethodName.toLowerCase();\n const candidates: [string, ApiMethod[]][] = [];\n for (const [name, overloads] of Object.entries(classMethods)) {\n if (name.toLowerCase().endsWith(suffix) && name !== resolvedMethodName) {\n candidates.push([name, overloads]);\n }\n }\n if (candidates.length === 1) {\n methods = candidates[0][1];\n resolvedMethodName = candidates[0][0];\n }\n }\n\n // Word-part subsequence match: the surface method may have extra words\n // inserted into the manifest method name. For example:\n // \"disableFlag\" → \"disableFeatureFlag\" ([\"disable\",\"Flag\"] ⊂ [\"disable\",\"Feature\",\"Flag\"])\n // \"getByExternalId\" → \"getOrganizationByExternalId\"\n // Only accept when exactly one candidate matches, or use HTTP verb disambiguation.\n if (!methods) {\n const manifestWords = splitCamelCase(resolvedMethodName);\n if (manifestWords.length >= 2) {\n const classMethods = surface.classes[className]?.methods ?? {};\n const candidates: [string, ApiMethod[]][] = [];\n for (const [name, overloads] of Object.entries(classMethods)) {\n if (name === resolvedMethodName) continue;\n const surfaceWords = splitCamelCase(name);\n if (surfaceWords.length > manifestWords.length && isSubsequence(manifestWords, surfaceWords)) {\n candidates.push([name, overloads]);\n }\n }\n if (candidates.length === 1) {\n methods = candidates[0][1];\n resolvedMethodName = candidates[0][0];\n } else if (candidates.length > 1) {\n const verbMatch = disambiguateByHttpVerb(candidates, entry.httpMethod);\n if (verbMatch) {\n methods = verbMatch[1];\n resolvedMethodName = verbMatch[0];\n }\n }\n }\n }\n\n // Reverse prefix match: the manifest name may be LONGER than the surface\n // name (e.g., \"createResources\" → \"createResource\", \"removeRoleByCriteria\" → \"removeRole\").\n // Check if the manifest name starts with a surface name. Only accept unique matches.\n if (!methods) {\n const classMethods = surface.classes[className]?.methods ?? {};\n const manifestLower = resolvedMethodName.toLowerCase();\n const candidates: [string, ApiMethod[]][] = [];\n for (const [name, overloads] of Object.entries(classMethods)) {\n if (name === resolvedMethodName) continue;\n if (manifestLower.startsWith(name.toLowerCase()) && name.length >= 3) {\n candidates.push([name, overloads]);\n }\n }\n if (candidates.length === 1) {\n methods = candidates[0][1];\n resolvedMethodName = candidates[0][0];\n } else if (candidates.length > 1) {\n const verbMatch = disambiguateByHttpVerb(candidates, entry.httpMethod);\n if (verbMatch) {\n methods = verbMatch[1];\n resolvedMethodName = verbMatch[0];\n }\n }\n }\n\n const method = methods?.[0];\n if (method) {\n lookup.methodByOperation.set(key, {\n className,\n methodName: resolvedMethodName,\n params: method.params,\n returnType: method.returnType,\n });\n lookup.httpKeyByMethod.set(`${className}.${resolvedMethodName}`, key);\n }\n }\n }\n }\n\n // Map interface and type alias names\n for (const name of Object.keys(surface.interfaces)) {\n lookup.interfaceByName.set(name, name);\n }\n for (const name of Object.keys(surface.typeAliases)) {\n lookup.typeAliasByName.set(name, name);\n }\n\n // Map barrel exports\n for (const [path, symbols] of Object.entries(surface.exports)) {\n lookup.requiredExports.set(path, new Set(symbols));\n }\n\n // Populate fileBySymbol from enriched surface\n for (const record of [surface.classes, surface.interfaces, surface.typeAliases, surface.enums] as Record<\n string,\n { sourceFile?: string }\n >[]) {\n for (const [name, item] of Object.entries(record)) {\n if (item.sourceFile) lookup.fileBySymbol.set(name, item.sourceFile);\n }\n }\n\n // Auto-infer IR model name → SDK interface name mappings\n if (spec) {\n buildModelNameMap(surface, spec, lookup, resolvedHints, options);\n\n // Remap fileBySymbol so IR model names point to the SDK symbol's file\n for (const [irName, sdkName] of lookup.modelNameByIR) {\n const filePath = lookup.fileBySymbol.get(sdkName);\n if (filePath) {\n lookup.fileBySymbol.set(irName, filePath);\n }\n }\n }\n\n return lookup;\n}\n\n// ---------------------------------------------------------------------------\n// HTTP verb disambiguation\n// ---------------------------------------------------------------------------\n\n/** Map HTTP methods to preferred method name prefixes for disambiguation. */\nconst HTTP_VERB_PREFIXES: Record<string, string[]> = {\n GET: ['list', 'get', 'fetch', 'retrieve', 'find'],\n POST: ['create', 'add', 'insert', 'send'],\n PUT: ['set', 'update', 'replace', 'put'],\n PATCH: ['update', 'patch', 'modify'],\n DELETE: ['delete', 'remove', 'revoke'],\n};\n\n/**\n * Disambiguate multiple method candidates using HTTP verb semantics.\n * Returns the best match or undefined if no unique match is found.\n */\nfunction disambiguateByHttpVerb<T>(candidates: [string, T][], httpMethod: string): [string, T] | undefined {\n const prefixes = HTTP_VERB_PREFIXES[httpMethod.toUpperCase()];\n if (!prefixes) return undefined;\n\n const verbCandidates = candidates.filter(([name]) => {\n const lower = name.toLowerCase();\n return prefixes.some((p) => lower.startsWith(p));\n });\n\n if (verbCandidates.length === 1) return verbCandidates[0];\n return undefined;\n}\n\n// ---------------------------------------------------------------------------\n// Word-part matching helpers\n// ---------------------------------------------------------------------------\n\n/** Split a camelCase identifier into its word parts (e.g., \"getByExternalId\" → [\"get\",\"By\",\"External\",\"Id\"]). */\nfunction splitCamelCase(name: string): string[] {\n const parts: string[] = [];\n let start = 0;\n for (let i = 1; i < name.length; i++) {\n if (name[i] >= 'A' && name[i] <= 'Z') {\n parts.push(name.slice(start, i));\n start = i;\n }\n }\n parts.push(name.slice(start));\n return parts;\n}\n\n/** Check if `needle` words form a subsequence of `haystack` words (case-insensitive). */\nfunction isSubsequence(needle: string[], haystack: string[]): boolean {\n let ni = 0;\n for (let hi = 0; hi < haystack.length && ni < needle.length; hi++) {\n if (needle[ni].toLowerCase() === haystack[hi].toLowerCase()) ni++;\n }\n return ni === needle.length;\n}\n\n// ---------------------------------------------------------------------------\n// Automatic model name inference\n// ---------------------------------------------------------------------------\n\n/**\n * Normalize a field name to a canonical form for comparison.\n * Handles camelCase → snake_case so \"createdAt\" and \"created_at\" match.\n */\nfunction normalizeFieldName(name: string): string {\n return toSnakeCase(name);\n}\n\n/**\n * Compute the Jaccard similarity between two sets of normalized field names.\n * Returns score (0–1) and raw intersection count.\n */\nfunction jaccardSimilarity(a: Set<string>, b: Set<string>): { score: number; intersection: number } {\n if (a.size === 0 && b.size === 0) return { score: 0, intersection: 0 };\n let intersection = 0;\n for (const item of a) {\n if (b.has(item)) intersection++;\n }\n const union = a.size + b.size - intersection;\n return { score: union === 0 ? 0 : intersection / union, intersection };\n}\n\n/**\n * Build a set of normalized field names from an IR model.\n */\nfunction irModelFieldSignature(model: Model): Set<string> {\n return new Set(model.fields.map((f) => normalizeFieldName(f.name)));\n}\n\n/**\n * Build a set of normalized field names from an SDK interface.\n */\nfunction sdkInterfaceFieldSignature(iface: ApiInterface): Set<string> {\n return new Set(Object.keys(iface.fields).map(normalizeFieldName));\n}\n\n/**\n * Populate the modelNameByIR map using two strategies:\n *\n * 1. Operation-based matching (high confidence):\n * When a manifest maps an HTTP operation to an SDK method, extract the\n * method's return type and parameter types. Match them against the IR\n * operation's response model and request body model.\n *\n * 2. Field-structure matching (fallback):\n * For IR models not matched by operations, compare their field names\n * against all SDK interfaces using Jaccard similarity. A match requires\n * ≥60% field overlap with ≥3 fields in common.\n */\nfunction buildModelNameMap(\n surface: ApiSurface,\n spec: ApiSpec,\n lookup: OverlayLookup,\n hints: LanguageHints,\n options?: { strictModelMatch?: boolean },\n): void {\n const mapped = new Set<string>(); // IR model names already mapped\n const usedSdkNames = new Set<string>(); // SDK names already claimed\n\n // --- Strategy 1: Operation-based matching ---\n if (lookup.methodByOperation.size > 0) {\n for (const service of spec.services) {\n for (const op of service.operations) {\n const httpKey = `${op.httpMethod.toUpperCase()} ${op.path}`;\n const methodOverlay = lookup.methodByOperation.get(httpKey);\n if (!methodOverlay) continue;\n\n // Match response model → SDK return type\n if (op.response.kind === 'model' && !mapped.has(op.response.name)) {\n const sdkTypeName = hints.extractReturnTypeName(methodOverlay.returnType);\n if (sdkTypeName && surface.interfaces[sdkTypeName]) {\n lookup.modelNameByIR.set(op.response.name, sdkTypeName);\n mapped.add(op.response.name);\n usedSdkNames.add(sdkTypeName);\n }\n }\n\n // Match request body model → SDK param type\n if (op.requestBody?.kind === 'model' && !mapped.has(op.requestBody.name)) {\n for (const param of methodOverlay.params) {\n const sdkTypeName = hints.extractParamTypeName(param.type);\n if (sdkTypeName && surface.interfaces[sdkTypeName]) {\n lookup.modelNameByIR.set(op.requestBody.name, sdkTypeName);\n mapped.add(op.requestBody.name);\n usedSdkNames.add(sdkTypeName);\n break;\n }\n }\n }\n }\n }\n }\n\n // --- Strategy 2: Field-structure matching ---\n // Pre-compute SDK interface field signatures\n const sdkSignatures: { name: string; fields: Set<string>; fieldCount: number }[] = [];\n for (const [name, iface] of Object.entries(surface.interfaces)) {\n if (usedSdkNames.has(name)) continue;\n const fields = sdkInterfaceFieldSignature(iface);\n if (fields.size >= 2) {\n sdkSignatures.push({ name, fields, fieldCount: fields.size });\n }\n }\n\n const sdkSignatureNames = new Set(sdkSignatures.map((s) => s.name));\n\n for (const model of spec.models) {\n if (mapped.has(model.name)) continue;\n if (model.fields.length < 2) continue;\n\n // Strategy 2a: Prefer exact name match — if the IR model name matches an SDK\n // interface name exactly, use it without Jaccard scoring. This prevents\n // false positives when a superset interface (e.g., DirectoryUserWithGroups)\n // scores higher than the exact match (DirectoryUser).\n if (sdkSignatureNames.has(model.name) && !usedSdkNames.has(model.name)) {\n lookup.modelNameByIR.set(model.name, model.name);\n mapped.add(model.name);\n usedSdkNames.add(model.name);\n continue;\n }\n\n // Strategy 2a+: Try derived model names before falling back to Jaccard\n const derivedNames = hints.derivedModelNames(model.name);\n for (const derived of derivedNames) {\n if (sdkSignatureNames.has(derived) && !usedSdkNames.has(derived)) {\n lookup.modelNameByIR.set(model.name, derived);\n mapped.add(model.name);\n usedSdkNames.add(derived);\n break;\n }\n }\n if (mapped.has(model.name)) continue;\n\n // In strict mode, skip Jaccard entirely\n if (options?.strictModelMatch) continue;\n\n // Strategy 2b: Fall back to Jaccard field-similarity matching\n const irFields = irModelFieldSignature(model);\n let bestMatch: string | null = null;\n let bestScore = 0;\n\n for (const sdk of sdkSignatures) {\n if (usedSdkNames.has(sdk.name)) continue;\n\n const { score, intersection } = jaccardSimilarity(irFields, sdk.fields);\n\n // Require ≥60% Jaccard AND enough fields in common (scaled by model size)\n const minIntersection = Math.max(3, Math.ceil(irFields.size * 0.5));\n if (score > bestScore && score >= 0.6 && intersection >= minIntersection) {\n bestScore = score;\n bestMatch = sdk.name;\n }\n }\n\n if (bestMatch) {\n lookup.modelNameByIR.set(model.name, bestMatch);\n mapped.add(model.name);\n usedSdkNames.add(bestMatch);\n }\n }\n}\n\n/** Categories that can be patched by the overlay retry loop. */\nconst PATCHABLE_CATEGORIES = new Set(['symbol_removed', 'symbol_renamed']);\n\n/** Check if a classified change is patchable by the overlay loop. */\nexport function isPatchableChange(change: ClassifiedChange): boolean {\n return PATCHABLE_CATEGORIES.has(change.category);\n}\n\n/**\n * Patch overlay with classified changes from a failed verification.\n * Adds explicit name mappings for symbols that were generated with wrong names.\n * Returns a new OverlayLookup (immutable).\n */\nexport function patchOverlay(overlay: OverlayLookup, changes: ClassifiedChange[], baseline: ApiSurface): OverlayLookup {\n const patched: OverlayLookup = {\n methodByOperation: new Map(overlay.methodByOperation),\n httpKeyByMethod: new Map(overlay.httpKeyByMethod),\n interfaceByName: new Map(overlay.interfaceByName),\n typeAliasByName: new Map(overlay.typeAliasByName),\n requiredExports: new Map(Array.from(overlay.requiredExports.entries()).map(([k, v]) => [k, new Set(v)])),\n modelNameByIR: new Map(overlay.modelNameByIR),\n fileBySymbol: new Map(overlay.fileBySymbol),\n };\n\n let warnedManifest = false;\n\n for (const c of changes) {\n if (!isPatchableChange(c)) continue;\n\n // symbol is the fqName, e.g. \"ClassName.methodName\" or \"ClassName\"\n const parts = c.symbol.split('.');\n if (parts.length === 2) {\n const [className, methodName] = parts;\n const baseClass = baseline.classes[className];\n if (baseClass && baseClass.methods[methodName]?.length > 0) {\n const httpKey = overlay.httpKeyByMethod.get(`${className}.${methodName}`);\n if (!httpKey && overlay.httpKeyByMethod.size === 0 && !warnedManifest) {\n console.warn(\n 'Warning: No operations map in .oagen-manifest.json. Method-level violations cannot be auto-patched. ' +\n 'Implement buildOperationsMap in your emitter for the self-correcting loop to resolve these.',\n );\n warnedManifest = true;\n }\n if (httpKey) {\n const method = baseClass.methods[methodName][0];\n patched.methodByOperation.set(httpKey, {\n className,\n methodName,\n params: method.params,\n returnType: method.returnType,\n });\n }\n }\n const baseIface = baseline.interfaces[className];\n if (baseIface) {\n patched.interfaceByName.set(className, className);\n }\n } else if (parts.length === 1) {\n const name = parts[0];\n if (baseline.interfaces[name]) {\n patched.interfaceByName.set(name, name);\n }\n if (baseline.typeAliases[name]) {\n patched.typeAliasByName.set(name, name);\n }\n }\n }\n\n return patched;\n}\n","import { RegistryError } from '../errors.js';\nimport type { Extractor } from './types.js';\n\nconst extractors = new Map<string, Extractor>();\n\nexport function registerExtractor(extractor: Extractor): void {\n extractors.set(extractor.language, extractor);\n}\n\nexport function getExtractor(language: string): Extractor {\n const extractor = extractors.get(language);\n if (!extractor) {\n const available = [...extractors.keys()].join(', ') || '(none)';\n throw new RegistryError(\n `No extractor registered for language: ${language}. Available: ${available}`,\n `Register an extractor for \"${language}\" via registerExtractor() or add one in your oagen.config.ts plugin.`,\n );\n }\n return extractor;\n}\n","import { readFileSync, existsSync } from 'node:fs';\nimport * as path from 'node:path';\nimport { MANIFEST_FILENAME } from './manifest.js';\n\n/** Minimal shape matching compat/overlay.ts ManifestEntry for cross-layer use. */\ninterface ManifestEntry {\n operationId: string;\n sdkResourceProperty: string;\n sdkMethodName: string;\n httpMethod: string;\n path: string;\n pathParams: string[];\n bodyFields: string[];\n queryFields: string[];\n}\n\n/**\n * Read the operations map from `.oagen-manifest.json` in the given directory\n * and convert it to `ManifestEntry[]` for the overlay builder.\n *\n * Returns undefined if the manifest is absent or has no operations field.\n */\nexport function readManifestSync(dir: string): ManifestEntry[] | undefined {\n const manifestPath = path.join(dir, MANIFEST_FILENAME);\n if (!existsSync(manifestPath)) return undefined;\n try {\n const parsed = JSON.parse(readFileSync(manifestPath, 'utf-8'));\n const operations = parsed?.operations;\n if (!operations || typeof operations !== 'object') return undefined;\n return convertOperationsToManifestEntries(operations);\n } catch {\n return undefined;\n }\n}\n\n/** Convert the operations map from .oagen-manifest.json into ManifestEntry[]. */\nfunction convertOperationsToManifestEntries(operations: Record<string, unknown>): ManifestEntry[] {\n const entries: ManifestEntry[] = [];\n for (const [httpKey, value] of Object.entries(operations)) {\n const spaceIdx = httpKey.indexOf(' ');\n const httpMethod = httpKey.slice(0, spaceIdx);\n const httpPath = httpKey.slice(spaceIdx + 1);\n\n const values = Array.isArray(value) ? value : [value];\n for (const v of values) {\n const entry = v as { sdkMethod?: string; service?: string };\n entries.push({\n operationId: '',\n sdkResourceProperty: entry.service ?? '',\n sdkMethodName: entry.sdkMethod ?? '',\n httpMethod,\n path: httpPath,\n pathParams: [],\n bodyFields: [],\n queryFields: [],\n });\n }\n }\n return entries;\n}\n","import { readFileSync } from 'node:fs';\nimport { ConfigError } from '../errors.js';\nimport { buildOverlayLookup } from '../compat/overlay.js';\nimport type { ApiSurface, LanguageHints, OverlayLookup } from '../compat/types.js';\nimport type { ApiSpec } from '../ir/types.js';\nimport { nodeHints } from '../compat/language-hints.js';\nimport { getExtractor } from '../compat/extractor-registry.js';\nimport { readManifestSync } from '../engine/manifest-reader.js';\n\nexport interface OverlayContext {\n apiSurface: ApiSurface;\n overlayLookup: OverlayLookup;\n}\n\n/**\n * Load an API surface from disk, discover/load the manifest, resolve\n * language hints, and build the overlay lookup. Shared by diff and generate.\n */\nexport function loadOverlayContext(opts: {\n apiSurfacePath: string;\n outputDir: string;\n lang: string;\n spec?: ApiSpec;\n}): OverlayContext {\n let raw: string;\n try {\n raw = readFileSync(opts.apiSurfacePath, 'utf-8');\n } catch {\n throw new ConfigError(\n `API surface file not found: ${opts.apiSurfacePath}. Run \\`oagen extract\\` first.`,\n `Generate the API surface file by running \\`oagen extract --lang ${opts.lang} --sdk-path <path-to-sdk>\\` before running this command.`,\n );\n }\n let apiSurface: ApiSurface;\n try {\n apiSurface = JSON.parse(raw) as ApiSurface;\n } catch (err) {\n throw new ConfigError(\n `Failed to parse API surface JSON: ${err instanceof Error ? err.message : String(err)}`,\n `Ensure \"${opts.apiSurfacePath}\" contains valid JSON. Re-run \\`oagen extract\\` to regenerate it.`,\n );\n }\n\n // Load operations from .oagen-manifest.json in output directory\n const manifest = readManifestSync(opts.outputDir);\n\n let hints: LanguageHints = nodeHints;\n try {\n hints = getExtractor(opts.lang).hints;\n } catch {\n // no extractor registered — use nodeHints fallback\n }\n\n const overlayLookup = buildOverlayLookup(apiSurface, manifest, opts.spec, hints);\n return { apiSurface, overlayLookup };\n}\n","import type { ApiSpec } from '../ir/types.js';\n\n/**\n * Walk all description fields in the IR and expand relative URL paths\n * (e.g. `/reference/authkit/user`) into full URLs using the given base.\n *\n * Matches markdown-style links: `[text](/path)` → `[text](https://example.com/path)`\n * and bare parenthetical refs: `(/path)` → `(https://example.com/path)`\n */\nexport function expandDocUrls(spec: ApiSpec, docUrl: string): ApiSpec {\n // Normalize: strip trailing slash so joins are clean\n const base = docUrl.replace(/\\/+$/, '');\n\n function expand(description: string | undefined): string | undefined {\n if (!description) return description;\n // Match markdown links and bare parenthetical paths with a leading slash\n return description.replace(/\\(\\/([^)]*)\\)/g, `(${base}/$1)`);\n }\n\n return {\n ...spec,\n description: expand(spec.description),\n services: spec.services.map((service) => ({\n ...service,\n description: expand(service.description),\n operations: service.operations.map((op) => ({\n ...op,\n description: expand(op.description),\n pathParams: op.pathParams.map((p) => ({ ...p, description: expand(p.description) })),\n queryParams: op.queryParams.map((p) => ({ ...p, description: expand(p.description) })),\n headerParams: op.headerParams.map((p) => ({ ...p, description: expand(p.description) })),\n })),\n })),\n models: spec.models.map((model) => ({\n ...model,\n description: expand(model.description),\n fields: model.fields.map((f) => ({ ...f, description: expand(f.description) })),\n })),\n enums: spec.enums.map((e) => ({\n ...e,\n values: e.values.map((v) => ({ ...v, description: expand(v.description) })),\n })),\n };\n}\n","import { parseSpec } from '../parser/parse.js';\nimport { generate } from '../engine/orchestrator.js';\nimport { getEmitter } from '../engine/registry.js';\nimport { loadOverlayContext } from './overlay-loader.js';\nimport { expandDocUrls } from '../utils/expand-doc-urls.js';\nimport type { OperationHint } from '../ir/operation-hints.js';\n\nexport async function generateCommand(opts: {\n spec: string;\n lang: string;\n output: string;\n target?: string;\n namespace?: string;\n dryRun?: boolean;\n apiSurface?: string;\n compatCheck?: boolean;\n /** From `--no-prune`. When false, manifest-driven stale-file pruning is skipped. */\n prune?: boolean;\n operationIdTransform?: (id: string) => string;\n schemaNameTransform?: (name: string) => string;\n docUrl?: string;\n operationHints?: Record<string, OperationHint>;\n mountRules?: Record<string, string>;\n}): Promise<void> {\n let ir = await parseSpec(opts.spec, {\n operationIdTransform: opts.operationIdTransform,\n schemaNameTransform: opts.schemaNameTransform,\n });\n if (opts.docUrl) {\n ir = expandDocUrls(ir, opts.docUrl);\n }\n const emitter = getEmitter(opts.lang);\n const namespace = opts.namespace ?? ir.name;\n\n // Build overlay from API surface if provided and not disabled\n let apiSurface;\n let overlayLookup;\n if (opts.apiSurface && opts.compatCheck !== false) {\n const ctx = loadOverlayContext({\n apiSurfacePath: opts.apiSurface,\n outputDir: opts.output,\n lang: opts.lang,\n spec: ir,\n });\n apiSurface = ctx.apiSurface;\n overlayLookup = ctx.overlayLookup;\n }\n\n const files = await generate(ir, emitter, {\n namespace,\n dryRun: opts.dryRun,\n outputDir: opts.output,\n target: opts.target,\n apiSurface,\n overlayLookup,\n operationHints: opts.operationHints,\n mountRules: opts.mountRules,\n noPrune: opts.prune === false,\n });\n\n if (opts.dryRun) {\n for (const f of files) {\n console.log(f.path);\n }\n } else {\n console.log(`Generated ${files.length} files in ${opts.output}`);\n if (opts.target) {\n console.log(`Integrated into ${opts.target}`);\n }\n }\n}\n","import type { FieldChange, ParamChange } from './types.js';\n\nexport function classifyFieldChange(kind: FieldChange['kind'], fieldName: string, isRequired?: boolean): FieldChange {\n switch (kind) {\n case 'field-added':\n return {\n kind,\n fieldName,\n classification: isRequired ? 'breaking' : 'additive',\n };\n case 'field-removed':\n return { kind, fieldName, classification: 'breaking' };\n case 'field-type-changed':\n return { kind, fieldName, classification: 'breaking' };\n case 'field-required-changed':\n return {\n kind,\n fieldName,\n classification: isRequired ? 'breaking' : 'additive',\n details: isRequired ? 'optional → required' : 'required → optional',\n };\n case 'field-access-changed':\n return { kind, fieldName, classification: 'breaking' };\n }\n}\n\nexport function classifyParamChange(kind: ParamChange['kind'], paramName: string, isRequired?: boolean): ParamChange {\n switch (kind) {\n case 'param-added':\n return {\n kind,\n paramName,\n classification: isRequired ? 'breaking' : 'additive',\n };\n case 'param-removed':\n return { kind, paramName, classification: 'breaking' };\n case 'param-type-changed':\n return { kind, paramName, classification: 'breaking' };\n case 'param-required-changed':\n return {\n kind,\n paramName,\n classification: isRequired ? 'breaking' : 'additive',\n };\n }\n}\n","import type { Model, TypeRef } from '../ir/types.js';\nimport { assertNever } from '../ir/types.js';\nimport type { Change, FieldChange } from './types.js';\nimport { classifyFieldChange } from './classify.js';\n\nexport function diffModels(oldModels: Model[], newModels: Model[]): Change[] {\n const changes: Change[] = [];\n const oldByName = new Map(oldModels.map((m) => [m.name, m]));\n const newByName = new Map(newModels.map((m) => [m.name, m]));\n\n for (const [name] of newByName) {\n if (!oldByName.has(name)) {\n changes.push({ kind: 'model-added', name, classification: 'additive' });\n }\n }\n\n for (const [name] of oldByName) {\n if (!newByName.has(name)) {\n changes.push({ kind: 'model-removed', name, classification: 'breaking' });\n }\n }\n\n for (const [name, newModel] of newByName) {\n const oldModel = oldByName.get(name);\n if (!oldModel) continue;\n\n const fieldChanges = diffFields(oldModel, newModel);\n if (fieldChanges.length > 0) {\n const hasBreaking = fieldChanges.some((fc) => fc.classification === 'breaking');\n changes.push({\n kind: 'model-modified',\n name,\n fieldChanges,\n classification: hasBreaking ? 'breaking' : 'additive',\n });\n }\n }\n\n return changes;\n}\n\nfunction diffFields(oldModel: Model, newModel: Model): FieldChange[] {\n const changes: FieldChange[] = [];\n const oldByName = new Map(oldModel.fields.map((f) => [f.name, f]));\n const newByName = new Map(newModel.fields.map((f) => [f.name, f]));\n\n for (const [name, field] of newByName) {\n if (!oldByName.has(name)) {\n changes.push(classifyFieldChange('field-added', name, field.required));\n }\n }\n\n for (const [name] of oldByName) {\n if (!newByName.has(name)) {\n changes.push(classifyFieldChange('field-removed', name));\n }\n }\n\n for (const [name, newField] of newByName) {\n const oldField = oldByName.get(name);\n if (!oldField) continue;\n\n if (!typeRefsEqual(oldField.type, newField.type)) {\n changes.push({\n kind: 'field-type-changed',\n fieldName: name,\n classification: 'breaking',\n details: `type changed`,\n });\n }\n\n if (oldField.required !== newField.required) {\n changes.push(classifyFieldChange('field-required-changed', name, newField.required));\n }\n\n if (!!oldField.readOnly !== !!newField.readOnly || !!oldField.writeOnly !== !!newField.writeOnly) {\n changes.push(classifyFieldChange('field-access-changed', name));\n }\n }\n\n return changes;\n}\n\nexport function typeRefsEqual(a: TypeRef, b: TypeRef): boolean {\n if (a.kind !== b.kind) return false;\n\n switch (a.kind) {\n case 'primitive':\n return b.kind === 'primitive' && a.type === b.type && (a.format ?? '') === ((b as typeof a).format ?? '');\n case 'array':\n return b.kind === 'array' && typeRefsEqual(a.items, b.items);\n case 'model':\n return b.kind === 'model' && a.name === b.name;\n case 'enum':\n return b.kind === 'enum' && a.name === b.name;\n case 'literal':\n return b.kind === 'literal' && a.value === b.value;\n case 'nullable':\n return b.kind === 'nullable' && typeRefsEqual(a.inner, b.inner);\n case 'union': {\n if (b.kind !== 'union') return false;\n if (a.variants.length !== b.variants.length) return false;\n if (!a.variants.every((v, i) => typeRefsEqual(v, b.variants[i]))) return false;\n // Compare discriminator\n if (!a.discriminator && !b.discriminator) return true;\n if (!a.discriminator || !b.discriminator) return false;\n if (a.discriminator.property !== b.discriminator.property) return false;\n const aKeys = Object.keys(a.discriminator.mapping).sort();\n const bKeys = Object.keys(b.discriminator.mapping).sort();\n if (aKeys.length !== bKeys.length) return false;\n return aKeys.every((k, i) => k === bKeys[i] && a.discriminator!.mapping[k] === b.discriminator!.mapping[k]);\n }\n case 'map':\n return b.kind === 'map' && typeRefsEqual(a.valueType, b.valueType);\n }\n return assertNever(a);\n}\n","import type { ErrorResponse, Operation } from '../ir/types.js';\nimport type { Change, ParamChange } from './types.js';\nimport { classifyParamChange } from './classify.js';\nimport { typeRefsEqual } from './models.js';\n\nexport function diffOperations(serviceName: string, oldOps: Operation[], newOps: Operation[]): Change[] {\n const changes: Change[] = [];\n const oldByName = new Map(oldOps.map((o) => [o.name, o]));\n const newByName = new Map(newOps.map((o) => [o.name, o]));\n\n for (const [name] of newByName) {\n if (!oldByName.has(name)) {\n changes.push({\n kind: 'operation-added',\n serviceName,\n operationName: name,\n classification: 'additive',\n });\n }\n }\n\n for (const [name] of oldByName) {\n if (!newByName.has(name)) {\n changes.push({\n kind: 'operation-removed',\n serviceName,\n operationName: name,\n classification: 'breaking',\n });\n }\n }\n\n for (const [name, newOp] of newByName) {\n const oldOp = oldByName.get(name);\n if (!oldOp) continue;\n\n const paramChanges = diffParams(oldOp, newOp);\n const responseChanged = !typeRefsEqual(oldOp.response, newOp.response);\n const requestBodyChanged = !requestBodiesEqual(oldOp.requestBody, newOp.requestBody);\n const httpMethodChanged = oldOp.httpMethod !== newOp.httpMethod;\n const pathChanged = oldOp.path !== newOp.path;\n const paginatedChanged = !!oldOp.pagination !== !!newOp.pagination;\n const injectIdempotencyKeyChanged = oldOp.injectIdempotencyKey !== newOp.injectIdempotencyKey;\n const errorsDiff = classifyErrorsChange(oldOp.errors, newOp.errors);\n const errorsChanged = errorsDiff !== 'none';\n\n const hasChanges =\n paramChanges.length > 0 ||\n responseChanged ||\n requestBodyChanged ||\n httpMethodChanged ||\n pathChanged ||\n paginatedChanged ||\n injectIdempotencyKeyChanged ||\n errorsChanged;\n\n if (hasChanges) {\n // paginated: false→true is additive (SDK gains pagination helper)\n // paginated: true→false is breaking (SDK loses pagination helper)\n const paginatedBreaking = paginatedChanged && !newOp.pagination;\n // injectIdempotencyKey: false→true is additive (SDK gains idempotency key)\n // injectIdempotencyKey: true→false is breaking (SDK loses idempotency key)\n const injectIdempotencyKeyBreaking = injectIdempotencyKeyChanged && !newOp.injectIdempotencyKey;\n const errorsBreaking = errorsDiff === 'breaking';\n\n const hasBreaking =\n responseChanged ||\n requestBodyChanged ||\n httpMethodChanged ||\n pathChanged ||\n paginatedBreaking ||\n injectIdempotencyKeyBreaking ||\n errorsBreaking ||\n paramChanges.some((pc) => pc.classification === 'breaking');\n changes.push({\n kind: 'operation-modified',\n serviceName,\n operationName: name,\n paramChanges,\n responseChanged,\n requestBodyChanged,\n httpMethodChanged,\n pathChanged,\n paginatedChanged,\n injectIdempotencyKeyChanged,\n errorsChanged,\n classification: hasBreaking ? 'breaking' : 'additive',\n });\n }\n }\n\n return changes;\n}\n\nfunction requestBodiesEqual(a: Operation['requestBody'], b: Operation['requestBody']): boolean {\n if (!a && !b) return true;\n if (!a || !b) return false;\n return typeRefsEqual(a, b);\n}\n\nfunction classifyErrorsChange(\n oldErrors: ErrorResponse[],\n newErrors: ErrorResponse[],\n): 'none' | 'additive' | 'breaking' {\n const oldByCode = new Map(oldErrors.map((e) => [e.statusCode, e]));\n const newByCode = new Map(newErrors.map((e) => [e.statusCode, e]));\n\n let hasAdditive = false;\n let hasBreaking = false;\n\n // New error codes added → additive (SDK gains new error classes)\n for (const code of newByCode.keys()) {\n if (!oldByCode.has(code)) hasAdditive = true;\n }\n\n // Old error codes removed → breaking (SDK loses error classes)\n for (const code of oldByCode.keys()) {\n if (!newByCode.has(code)) hasBreaking = true;\n }\n\n // Shared error codes with changed types → breaking\n for (const [code, newErr] of newByCode) {\n const oldErr = oldByCode.get(code);\n if (!oldErr) continue;\n if (!oldErr.type && !newErr.type) continue;\n if (!oldErr.type || !newErr.type || !typeRefsEqual(oldErr.type, newErr.type)) {\n hasBreaking = true;\n }\n }\n\n if (hasBreaking) return 'breaking';\n if (hasAdditive) return 'additive';\n return 'none';\n}\n\nfunction diffParams(oldOp: Operation, newOp: Operation): ParamChange[] {\n const changes: ParamChange[] = [];\n const allOldParams = [...oldOp.pathParams, ...oldOp.queryParams, ...oldOp.headerParams];\n const allNewParams = [...newOp.pathParams, ...newOp.queryParams, ...newOp.headerParams];\n const oldByName = new Map(allOldParams.map((p) => [p.name, p]));\n const newByName = new Map(allNewParams.map((p) => [p.name, p]));\n\n for (const [name, param] of newByName) {\n if (!oldByName.has(name)) {\n changes.push(classifyParamChange('param-added', name, param.required));\n }\n }\n\n for (const [name] of oldByName) {\n if (!newByName.has(name)) {\n changes.push(classifyParamChange('param-removed', name));\n }\n }\n\n for (const [name, newParam] of newByName) {\n const oldParam = oldByName.get(name);\n if (!oldParam) continue;\n\n if (!typeRefsEqual(oldParam.type, newParam.type)) {\n changes.push(classifyParamChange('param-type-changed', name));\n }\n\n if (oldParam.required !== newParam.required) {\n changes.push(classifyParamChange('param-required-changed', name, newParam.required));\n }\n }\n\n return changes;\n}\n","import type { Service } from '../ir/types.js';\nimport type { Change } from './types.js';\nimport { diffOperations } from './operations.js';\n\nexport function diffServices(oldServices: Service[], newServices: Service[]): Change[] {\n const changes: Change[] = [];\n const oldByName = new Map(oldServices.map((s) => [s.name, s]));\n const newByName = new Map(newServices.map((s) => [s.name, s]));\n\n for (const [name] of newByName) {\n if (!oldByName.has(name)) {\n changes.push({ kind: 'service-added', name, classification: 'additive' });\n }\n }\n\n for (const [name] of oldByName) {\n if (!newByName.has(name)) {\n changes.push({ kind: 'service-removed', name, classification: 'breaking' });\n }\n }\n\n for (const [name, newService] of newByName) {\n const oldService = oldByName.get(name);\n if (!oldService) continue;\n\n changes.push(...diffOperations(name, oldService.operations, newService.operations));\n }\n\n return changes;\n}\n","import type { ApiSpec, Enum } from '../ir/types.js';\nimport type { Change, DiffReport, EnumValueChange } from './types.js';\nimport { diffModels } from './models.js';\nimport { diffServices } from './services.js';\n\nexport function diffSpecs(oldSpec: ApiSpec, newSpec: ApiSpec): DiffReport {\n const changes: Change[] = [\n ...diffModels(oldSpec.models, newSpec.models),\n ...diffEnums(oldSpec.enums, newSpec.enums),\n ...diffServices(oldSpec.services, newSpec.services),\n ];\n\n return {\n oldVersion: oldSpec.version,\n newVersion: newSpec.version,\n changes,\n summary: summarize(changes),\n };\n}\n\nfunction diffEnums(oldEnums: Enum[], newEnums: Enum[]): Change[] {\n const changes: Change[] = [];\n const oldByName = new Map(oldEnums.map((e) => [e.name, e]));\n const newByName = new Map(newEnums.map((e) => [e.name, e]));\n\n for (const [name] of newByName) {\n if (!oldByName.has(name)) {\n changes.push({ kind: 'enum-added', name, classification: 'additive' });\n }\n }\n\n for (const [name] of oldByName) {\n if (!newByName.has(name)) {\n changes.push({ kind: 'enum-removed', name, classification: 'breaking' });\n }\n }\n\n for (const [name, newEnum] of newByName) {\n const oldEnum = oldByName.get(name);\n if (!oldEnum) continue;\n\n const valueChanges = diffEnumValues(oldEnum, newEnum);\n if (valueChanges.length > 0) {\n const hasBreaking = valueChanges.some((vc) => vc.classification === 'breaking');\n changes.push({\n kind: 'enum-modified',\n name,\n valueChanges,\n classification: hasBreaking ? 'breaking' : 'additive',\n });\n }\n }\n\n return changes;\n}\n\nfunction diffEnumValues(oldEnum: Enum, newEnum: Enum): EnumValueChange[] {\n const changes: EnumValueChange[] = [];\n const oldByName = new Map(oldEnum.values.map((v) => [v.name, v]));\n const newByName = new Map(newEnum.values.map((v) => [v.name, v]));\n\n for (const [name] of newByName) {\n if (!oldByName.has(name)) {\n changes.push({ kind: 'value-added', valueName: name, classification: 'additive' });\n }\n }\n\n for (const [name] of oldByName) {\n if (!newByName.has(name)) {\n changes.push({ kind: 'value-removed', valueName: name, classification: 'breaking' });\n }\n }\n\n for (const [name, newVal] of newByName) {\n const oldVal = oldByName.get(name);\n if (!oldVal) continue;\n\n if (oldVal.value !== newVal.value) {\n changes.push({\n kind: 'value-changed',\n valueName: name,\n classification: 'breaking',\n details: `value changed from '${oldVal.value}' to '${newVal.value}'`,\n });\n }\n }\n\n return changes;\n}\n\nfunction summarize(changes: Change[]) {\n let added = 0;\n let removed = 0;\n let modified = 0;\n let breaking = 0;\n let additive = 0;\n\n for (const c of changes) {\n if (c.kind.endsWith('-added')) added++;\n else if (c.kind.endsWith('-removed')) removed++;\n else if (c.kind.endsWith('-modified')) modified++;\n\n if (c.classification === 'breaking') breaking++;\n else additive++;\n }\n\n return { added, removed, modified, breaking, additive };\n}\n","import { parseSpec } from '../parser/parse.js';\nimport { diffSpecs } from '../differ/diff.js';\nimport { CommandError } from '../errors.js';\nimport { expandDocUrls } from '../utils/expand-doc-urls.js';\n\nexport async function diffCommand(opts: {\n old: string;\n new: string;\n operationIdTransform?: (id: string) => string;\n schemaNameTransform?: (name: string) => string;\n docUrl?: string;\n}): Promise<void> {\n const parseOptions = {\n operationIdTransform: opts.operationIdTransform,\n schemaNameTransform: opts.schemaNameTransform,\n };\n let [oldSpec, newSpec] = await Promise.all([parseSpec(opts.old, parseOptions), parseSpec(opts.new, parseOptions)]);\n if (opts.docUrl) {\n oldSpec = expandDocUrls(oldSpec, opts.docUrl);\n newSpec = expandDocUrls(newSpec, opts.docUrl);\n }\n\n const diff = diffSpecs(oldSpec, newSpec);\n console.log(JSON.stringify(diff, null, 2));\n throw new CommandError(\n '',\n '',\n diff.summary.breaking > 0\n ? 2\n : diff.summary.modified > 0 || diff.summary.removed > 0\n ? 1\n : diff.summary.added > 0\n ? 1\n : 0,\n );\n}\n","import { writeFileSync } from 'node:fs';\nimport { getExtractor } from '../compat/extractor-registry.js';\n\nexport async function extractCommand(opts: { sdkPath: string; lang: string; output: string }): Promise<void> {\n const extractor = getExtractor(opts.lang);\n console.log(`Extracting ${opts.lang} API surface from ${opts.sdkPath}...`);\n const surface = await extractor.extract(opts.sdkPath);\n writeFileSync(opts.output, JSON.stringify(surface, null, 2));\n const symbolCount =\n Object.keys(surface.classes).length +\n Object.keys(surface.interfaces).length +\n Object.keys(surface.typeAliases).length +\n Object.keys(surface.enums).length;\n console.log(`Extracted ${symbolCount} symbols → ${opts.output}`);\n}\n","/**\n * Language-aware compatibility policy.\n *\n * Defines which aspects of the public API surface are breaking in each\n * language. Built-in defaults capture language semantics (e.g., PHP has\n * named arguments, Go does not). Config overrides allow per-SDK divergence.\n */\n\nimport type { LanguageId } from './ir.js';\n\n/** Policy hints that determine what constitutes a breaking change. */\nexport interface CompatPolicyHints {\n /** Callers reference parameter names at the call site (PHP named args, Python/Ruby keyword args, Kotlin/C# named args). */\n callerUsesParamNames: boolean;\n /** Constructor positional order is part of the public API. */\n constructorOrderMatters: boolean;\n /** Method parameter names are visible to callers. */\n methodParameterNamesArePublicApi: boolean;\n /** Constructor parameter names are visible to callers. */\n constructorParameterNamesArePublicApi: boolean;\n /** Method overload sets are part of the public API (Kotlin, C#). */\n overloadsArePublicApi: boolean;\n /** Function arity is part of the public API (Elixir, Go). */\n arityIsPublicApi: boolean;\n}\n\n/** Built-in language defaults. */\nconst LANGUAGE_DEFAULTS: Record<LanguageId, CompatPolicyHints> = {\n php: {\n callerUsesParamNames: true,\n constructorOrderMatters: true,\n methodParameterNamesArePublicApi: true,\n constructorParameterNamesArePublicApi: true,\n overloadsArePublicApi: false,\n arityIsPublicApi: false,\n },\n python: {\n callerUsesParamNames: true,\n constructorOrderMatters: true,\n methodParameterNamesArePublicApi: true,\n constructorParameterNamesArePublicApi: true,\n overloadsArePublicApi: false,\n arityIsPublicApi: false,\n },\n ruby: {\n callerUsesParamNames: true,\n constructorOrderMatters: true,\n methodParameterNamesArePublicApi: true,\n constructorParameterNamesArePublicApi: true,\n overloadsArePublicApi: false,\n arityIsPublicApi: false,\n },\n go: {\n callerUsesParamNames: false,\n constructorOrderMatters: true,\n methodParameterNamesArePublicApi: false,\n constructorParameterNamesArePublicApi: false,\n overloadsArePublicApi: false,\n arityIsPublicApi: true,\n },\n kotlin: {\n callerUsesParamNames: true,\n constructorOrderMatters: false,\n methodParameterNamesArePublicApi: true,\n constructorParameterNamesArePublicApi: true,\n overloadsArePublicApi: true,\n arityIsPublicApi: false,\n },\n dotnet: {\n callerUsesParamNames: true,\n constructorOrderMatters: false,\n methodParameterNamesArePublicApi: true,\n constructorParameterNamesArePublicApi: true,\n overloadsArePublicApi: true,\n arityIsPublicApi: false,\n },\n elixir: {\n callerUsesParamNames: true,\n constructorOrderMatters: false,\n methodParameterNamesArePublicApi: true,\n constructorParameterNamesArePublicApi: false,\n overloadsArePublicApi: false,\n arityIsPublicApi: true,\n },\n rust: {\n callerUsesParamNames: false,\n constructorOrderMatters: true,\n methodParameterNamesArePublicApi: false,\n constructorParameterNamesArePublicApi: false,\n overloadsArePublicApi: false,\n arityIsPublicApi: true,\n },\n node: {\n callerUsesParamNames: false,\n constructorOrderMatters: false,\n methodParameterNamesArePublicApi: false,\n constructorParameterNamesArePublicApi: false,\n overloadsArePublicApi: false,\n arityIsPublicApi: false,\n },\n};\n\n/** Get the built-in default policy for a language. */\nexport function getDefaultPolicy(language: LanguageId): CompatPolicyHints {\n return { ...LANGUAGE_DEFAULTS[language] };\n}\n\n/** Merge user overrides onto language defaults. Only provided keys are overridden. */\nexport function mergePolicy(defaults: CompatPolicyHints, overrides: Partial<CompatPolicyHints>): CompatPolicyHints {\n return { ...defaults, ...overrides };\n}\n\n/** All supported language IDs. */\nexport const ALL_LANGUAGE_IDS: readonly LanguageId[] = Object.keys(LANGUAGE_DEFAULTS) as LanguageId[];\n","/**\n * Schema versioning for compatibility snapshots.\n *\n * Snapshots are versioned so consumers can detect format changes and\n * apply migration logic if needed.\n */\n\nimport type { CompatSnapshot } from './ir.js';\n\n/** Current schema version for compatibility snapshots. */\nexport const COMPAT_SCHEMA_VERSION = '1';\n\n/** Validate that a parsed snapshot has a compatible schema version. */\nexport function isCompatibleSchemaVersion(snapshot: { schemaVersion?: string }): boolean {\n return snapshot.schemaVersion === COMPAT_SCHEMA_VERSION;\n}\n\n/** Validate the basic structure of a parsed compat snapshot. */\nexport function validateSnapshot(data: unknown): data is CompatSnapshot {\n if (typeof data !== 'object' || data === null) return false;\n const obj = data as Record<string, unknown>;\n return (\n typeof obj.schemaVersion === 'string' &&\n typeof obj.source === 'object' &&\n obj.source !== null &&\n typeof obj.policies === 'object' &&\n obj.policies !== null &&\n Array.isArray(obj.symbols)\n );\n}\n","/**\n * Rich compatibility IR for cross-language compatibility verification.\n *\n * These types represent the public API surface of an SDK in a language-aware,\n * machine-readable format. They extend the basic ApiSurface with richer\n * parameter semantics, sensitivity flags, and provenance metadata.\n */\n\nimport type { CompatPolicyHints } from './policy.js';\n\n/** Language identifier for emitter targets. */\nexport type LanguageId = 'node' | 'php' | 'python' | 'ruby' | 'go' | 'kotlin' | 'dotnet' | 'elixir' | 'rust';\n\n/** A full compatibility snapshot of an SDK's public API surface. */\nexport interface CompatSnapshot {\n schemaVersion: string;\n source: {\n specSha?: string;\n extractedAt: string;\n };\n policies: CompatPolicyHints;\n symbols: CompatSymbol[];\n}\n\n/** Kind of public API symbol. */\nexport type CompatSymbolKind =\n | 'service_accessor'\n | 'callable'\n | 'constructor'\n | 'field'\n | 'property'\n | 'enum'\n | 'enum_member'\n | 'alias';\n\n/** Visibility level of a symbol. */\nexport type CompatVisibility = 'public' | 'protected' | 'internal';\n\n/** Stability classification of a symbol. */\nexport type CompatStability = 'stable' | 'unstable' | 'deprecated';\n\n/** How the symbol was generated. */\nexport type CompatSourceKind =\n | 'generated_service_wrapper'\n | 'generated_model_constructor'\n | 'generated_resource_constructor'\n | 'generated_enum'\n | 'compat_alias';\n\n/** A single public API symbol with its full metadata. */\nexport interface CompatSymbol {\n id: string;\n kind: CompatSymbolKind;\n fqName: string;\n ownerFqName?: string;\n displayName: string;\n visibility: CompatVisibility;\n stability: CompatStability;\n sourceKind: CompatSourceKind;\n operationId?: string;\n schemaName?: string;\n route?: {\n method: string;\n path: string;\n };\n parameters?: CompatParameter[];\n returns?: CompatTypeRef;\n /** Type reference for field/property symbols. */\n typeRef?: CompatTypeRef;\n /** Value for enum member symbols. */\n value?: string | number;\n}\n\n/** How a parameter is passed at the call site. */\nexport type CompatPassingStyle =\n | 'positional'\n | 'keyword'\n | 'named'\n | 'keyword_or_positional'\n | 'options_object'\n | 'builder';\n\n/** A parameter on a callable or constructor symbol. */\nexport interface CompatParameter {\n publicName: string;\n wireName?: string;\n position: number;\n required: boolean;\n nullable: boolean;\n hasDefault: boolean;\n passing: CompatPassingStyle;\n type: CompatTypeRef;\n sensitivity: ParameterSensitivity;\n}\n\n/** Which aspects of this parameter are part of the public API contract. */\nexport interface ParameterSensitivity {\n order: boolean;\n publicName: boolean;\n requiredness: boolean;\n type: boolean;\n}\n\n/** A type reference — either a named type or an inline description. */\nexport interface CompatTypeRef {\n name: string;\n nullable?: boolean;\n array?: boolean;\n generic?: string[];\n}\n\n// ---------------------------------------------------------------------------\n// Bridge: ApiSurface → CompatSnapshot\n// ---------------------------------------------------------------------------\n\nimport type { ApiSurface, ApiParam } from './types.js';\nimport { getDefaultPolicy } from './policy.js';\nimport { COMPAT_SCHEMA_VERSION } from './schema.js';\n\n/**\n * Convert a legacy ApiSurface to a CompatSnapshot.\n *\n * This bridge allows existing extractors (which produce ApiSurface) to feed\n * into the new classified diff engine without requiring immediate migration.\n */\nexport function apiSurfaceToSnapshot(surface: ApiSurface): CompatSnapshot {\n const language = (surface.language || 'node') as LanguageId;\n const symbols: CompatSymbol[] = [];\n\n // Convert classes → service_accessor symbols + callable/constructor children\n for (const [className, cls] of Object.entries(surface.classes)) {\n symbols.push({\n id: `class:${className}`,\n kind: 'service_accessor',\n fqName: className,\n displayName: className,\n visibility: 'public',\n stability: cls.deprecationMessage ? 'deprecated' : 'stable',\n sourceKind: 'generated_service_wrapper',\n });\n\n // Constructor\n if (cls.constructorParams.length > 0) {\n symbols.push({\n id: `ctor:${className}`,\n kind: 'constructor',\n fqName: `${className}.constructor`,\n ownerFqName: className,\n displayName: `new ${className}`,\n visibility: 'public',\n stability: 'stable',\n sourceKind: 'generated_resource_constructor',\n parameters: cls.constructorParams.map((p, i) => apiParamToCompatParam(p, i, language)),\n });\n }\n\n // Methods\n for (const [methodName, overloads] of Object.entries(cls.methods)) {\n for (let oi = 0; oi < overloads.length; oi++) {\n const method = overloads[oi];\n const suffix = overloads.length > 1 ? `#${oi}` : '';\n symbols.push({\n id: `method:${className}.${methodName}${suffix}`,\n kind: 'callable',\n fqName: `${className}.${methodName}`,\n ownerFqName: className,\n displayName: `${className}.${methodName}`,\n visibility: 'public',\n stability: 'stable',\n sourceKind: 'generated_service_wrapper',\n parameters: method.params.map((p, i) => apiParamToCompatParam(p, i, language)),\n returns: { name: method.returnType },\n });\n }\n }\n\n // Properties\n for (const [propName, prop] of Object.entries(cls.properties)) {\n symbols.push({\n id: `prop:${className}.${propName}`,\n kind: 'property',\n fqName: `${className}.${propName}`,\n ownerFqName: className,\n displayName: `${className}.${propName}`,\n visibility: 'public',\n stability: 'stable',\n sourceKind: 'generated_service_wrapper',\n typeRef: { name: prop.type },\n });\n }\n }\n\n // Convert interfaces → field symbols\n for (const [ifaceName, iface] of Object.entries(surface.interfaces)) {\n symbols.push({\n id: `iface:${ifaceName}`,\n kind: 'alias',\n fqName: ifaceName,\n displayName: ifaceName,\n visibility: 'public',\n stability: 'stable',\n sourceKind: 'generated_resource_constructor',\n });\n\n for (const [fieldName, field] of Object.entries(iface.fields)) {\n symbols.push({\n id: `field:${ifaceName}.${fieldName}`,\n kind: 'field',\n fqName: `${ifaceName}.${fieldName}`,\n ownerFqName: ifaceName,\n displayName: `${ifaceName}.${fieldName}`,\n visibility: 'public',\n stability: 'stable',\n sourceKind: 'generated_resource_constructor',\n typeRef: { name: field.type },\n });\n }\n\n // Constructor if interface has one\n if (iface.hasCustomConstructor) {\n symbols.push({\n id: `ctor:${ifaceName}`,\n kind: 'constructor',\n fqName: `${ifaceName}.constructor`,\n ownerFqName: ifaceName,\n displayName: `new ${ifaceName}`,\n visibility: 'public',\n stability: 'stable',\n sourceKind: 'generated_resource_constructor',\n });\n }\n }\n\n // Convert type aliases\n for (const [aliasName] of Object.entries(surface.typeAliases)) {\n symbols.push({\n id: `alias:${aliasName}`,\n kind: 'alias',\n fqName: aliasName,\n displayName: aliasName,\n visibility: 'public',\n stability: 'stable',\n sourceKind: 'generated_resource_constructor',\n });\n }\n\n // Convert enums\n for (const [enumName, enumDef] of Object.entries(surface.enums)) {\n symbols.push({\n id: `enum:${enumName}`,\n kind: 'enum',\n fqName: enumName,\n displayName: enumName,\n visibility: 'public',\n stability: 'stable',\n sourceKind: 'generated_enum',\n });\n\n for (const [memberName, memberValue] of Object.entries(enumDef.members)) {\n symbols.push({\n id: `enum_member:${enumName}.${memberName}`,\n kind: 'enum_member',\n fqName: `${enumName}.${memberName}`,\n ownerFqName: enumName,\n displayName: `${enumName}.${memberName}`,\n visibility: 'public',\n stability: 'stable',\n sourceKind: 'generated_enum',\n value: memberValue,\n });\n }\n }\n\n return {\n schemaVersion: COMPAT_SCHEMA_VERSION,\n source: { extractedAt: surface.extractedAt },\n policies: getDefaultPolicy(language),\n symbols,\n };\n}\n\n/** Convert a legacy ApiParam to a CompatParameter. */\nfunction apiParamToCompatParam(param: ApiParam, position: number, language: LanguageId): CompatParameter {\n const policy = getDefaultPolicy(language);\n return {\n publicName: param.name,\n position,\n required: !param.optional,\n nullable: false,\n hasDefault: param.optional,\n passing: param.passingStyle ?? inferPassingStyle(language),\n type: { name: param.type },\n sensitivity: {\n order: policy.constructorOrderMatters,\n publicName: policy.methodParameterNamesArePublicApi,\n requiredness: true,\n type: true,\n },\n };\n}\n\n/** Infer the default parameter passing style for a language. */\nfunction inferPassingStyle(language: LanguageId): CompatPassingStyle {\n switch (language) {\n case 'python':\n case 'ruby':\n case 'elixir':\n return 'keyword';\n case 'php':\n case 'kotlin':\n case 'dotnet':\n return 'named';\n case 'node':\n return 'options_object';\n default:\n return 'positional';\n }\n}\n","import { readFileSync, writeFileSync } from 'node:fs';\nimport { createHash } from 'node:crypto';\nimport { resolve } from 'node:path';\nimport { getExtractor } from '../compat/extractor-registry.js';\nimport { parseSpec } from '../parser/parse.js';\nimport { apiSurfaceToSnapshot } from '../compat/ir.js';\nimport { readManifest } from '../engine/manifest.js';\nimport type { Manifest } from '../engine/manifest.js';\nimport type { CompatSnapshot } from '../compat/ir.js';\nimport type { ApiSurface, ApiClass } from '../compat/types.js';\nimport type { ApiSpec } from '../ir/types.js';\n\nconst SNAPSHOT_FILENAME = '.oagen-compat-snapshot.json';\n\n/** Normalize a name for case-insensitive matching: strip underscores and lowercase. */\nfunction normalize(name: string): string {\n return name.replace(/_/g, '').toLowerCase();\n}\n\n/**\n * Build a map of normalized service name → Set of generated method names\n * from the manifest's operations record.\n */\nfunction buildServiceMethodMap(operations: Record<string, unknown>): Map<string, Set<string>> {\n const result = new Map<string, Set<string>>();\n for (const value of Object.values(operations)) {\n if (typeof value !== 'object' || value === null) continue;\n const { sdkMethod, service } = value as { sdkMethod?: string; service?: string };\n if (typeof sdkMethod !== 'string' || typeof service !== 'string') continue;\n const key = normalize(service);\n if (!result.has(key)) result.set(key, new Set());\n result.get(key)!.add(sdkMethod);\n }\n return result;\n}\n\n/**\n * Filter an ApiSurface to only include generated symbols based on the manifest.\n *\n * Two levels of filtering:\n * 1. File-level: classes/interfaces/enums from files not in the manifest are\n * dropped entirely (they are wholly hand-written).\n * 2. Method-level: for service classes (those whose name matches a manifest\n * service), only methods listed in the manifest operations are kept.\n * Constructors and properties are always preserved since they are structural.\n * Non-service classes (models, enums, etc.) keep all their symbols.\n */\nfunction filterSurfaceByManifest(\n surface: ApiSurface,\n manifest: Manifest,\n): {\n filtered: ApiSurface;\n filesExcluded: number;\n methodsExcluded: number;\n} {\n const manifestFiles = new Set(manifest.files);\n const serviceMethodMap = manifest.operations\n ? buildServiceMethodMap(manifest.operations)\n : new Map<string, Set<string>>();\n\n let filesExcluded = 0;\n let methodsExcluded = 0;\n\n // Filter a record by manifest files, counting exclusions\n const filterByFile = <T extends { sourceFile?: string }>(record: Record<string, T>): Record<string, T> => {\n const result: Record<string, T> = {};\n for (const [name, entry] of Object.entries(record)) {\n if (entry.sourceFile && manifestFiles.has(entry.sourceFile)) {\n result[name] = entry;\n } else {\n filesExcluded++;\n }\n }\n return result;\n };\n\n // Filter classes: file-level first, then method-level for service classes\n const filteredClasses: Record<string, ApiClass> = {};\n for (const [name, cls] of Object.entries(surface.classes)) {\n if (cls.sourceFile && !manifestFiles.has(cls.sourceFile)) {\n filesExcluded++;\n continue;\n }\n\n // Check if this class is a service with known operations\n const generatedMethods = serviceMethodMap.get(normalize(name));\n if (generatedMethods) {\n // Service class — keep only methods that appear in manifest operations\n const methods: typeof cls.methods = {};\n for (const [methodName, overloads] of Object.entries(cls.methods)) {\n if (generatedMethods.has(methodName)) {\n methods[methodName] = overloads;\n } else {\n methodsExcluded++;\n }\n }\n filteredClasses[name] = { ...cls, methods };\n } else {\n // Model / utility class — keep all symbols\n filteredClasses[name] = cls;\n }\n }\n\n // Filter exports to only include files in the manifest\n const filteredExports: Record<string, string[]> = {};\n for (const [filePath, symbols] of Object.entries(surface.exports)) {\n if (manifestFiles.has(filePath)) {\n filteredExports[filePath] = symbols;\n }\n }\n\n return {\n filtered: {\n ...surface,\n classes: filteredClasses,\n interfaces: filterByFile(surface.interfaces),\n typeAliases: filterByFile(surface.typeAliases),\n enums: filterByFile(surface.enums),\n exports: filteredExports,\n },\n filesExcluded,\n methodsExcluded,\n };\n}\n\nexport async function compatExtractCommand(opts: {\n sdkPath: string;\n lang: string;\n output: string;\n spec?: string;\n}): Promise<void> {\n const extractor = getExtractor(opts.lang);\n console.log(`Extracting ${opts.lang} compat snapshot from ${opts.sdkPath}...`);\n\n let surface = await extractor.extract(opts.sdkPath);\n\n // If the SDK has a manifest, scope extraction to only generated symbols.\n // File-level: excludes wholly hand-written files.\n // Method-level: excludes hand-written methods on service classes.\n const manifest = await readManifest(opts.sdkPath);\n if (manifest) {\n const { filtered, filesExcluded, methodsExcluded } = filterSurfaceByManifest(surface, manifest);\n surface = filtered;\n if (filesExcluded > 0 || methodsExcluded > 0) {\n console.log(\n `Manifest filter: excluded ${filesExcluded} hand-written file(s), ${methodsExcluded} hand-written method(s)`,\n );\n }\n }\n\n const snapshot = apiSurfaceToSnapshot(surface);\n\n // Enrich with spec context if provided\n if (opts.spec) {\n const specContent = readFileSync(opts.spec, 'utf-8');\n snapshot.source.specSha = createHash('sha256').update(specContent).digest('hex');\n\n const parsedSpec = await parseSpec(opts.spec);\n enrichWithSpecContext(snapshot, parsedSpec);\n }\n\n const outputPath = resolve(opts.output, SNAPSHOT_FILENAME);\n writeFileSync(outputPath, JSON.stringify(snapshot, null, 2));\n console.log(`Extracted ${snapshot.symbols.length} symbols → ${outputPath}`);\n}\n\n/**\n * Enrich snapshot symbols with operationId and route from the parsed spec.\n *\n * Matches callable symbols to spec operations by comparing method names\n * derived from the spec against the symbol's fqName.\n */\nfunction enrichWithSpecContext(snapshot: CompatSnapshot, spec: ApiSpec): void {\n // Build lookup: \"ServiceName.methodName\" → { operationId, method, path }\n const opLookup = new Map<string, { operationId: string; method: string; path: string }>();\n for (const service of spec.services) {\n for (const op of service.operations) {\n // The symbol fqName is \"ClassName.methodName\" — match against service + operation name\n const key = `${service.name}.${op.name}`;\n opLookup.set(key, {\n operationId: op.name,\n method: op.httpMethod,\n path: op.path,\n });\n }\n }\n\n for (const sym of snapshot.symbols) {\n if (sym.kind !== 'callable') continue;\n const match = opLookup.get(sym.fqName);\n if (match) {\n sym.operationId = match.operationId;\n sym.route = { method: match.method, path: match.path };\n }\n }\n}\n","/**\n * Compat configuration types for `oagen.config.ts`.\n *\n * The `compat` section of the config holds human-authored policy:\n * fail thresholds, language overrides, and intentional break approvals.\n * Generated state (manifests, snapshots, reports) lives elsewhere.\n */\n\nimport type { LanguageId } from './ir.js';\nimport type { CompatPolicyHints } from './policy.js';\n\n// ---------------------------------------------------------------------------\n// Change categories\n// ---------------------------------------------------------------------------\n\n/** Breaking change categories — changes that break callers. */\nexport type BreakingChangeCategory =\n | 'symbol_removed'\n | 'symbol_renamed'\n | 'parameter_removed'\n | 'parameter_renamed'\n | 'parameter_requiredness_increased'\n | 'parameter_type_narrowed'\n | 'parameter_position_changed_order_sensitive'\n | 'constructor_position_changed_order_sensitive'\n | 'named_arg_name_removed'\n | 'keyword_name_removed'\n | 'overload_removed'\n | 'union_wrapper_migration_without_compat_alias'\n | 'field_type_changed'\n | 'return_type_changed'\n | 'enum_member_value_changed';\n\n/** Soft-risk change categories — may affect callers depending on usage. */\nexport type SoftRiskChangeCategory =\n | 'parameter_added_non_terminal_optional'\n | 'constructor_reordered_named_friendly'\n | 'default_value_changed'\n | 'wrapper_stricter_than_previous_sdk_but_matches_spec'\n | 'doc_surface_drift';\n\n/** Additive change categories — safe to ship. */\nexport type AdditiveChangeCategory =\n | 'symbol_added'\n | 'parameter_added_optional_terminal'\n | 'new_constructor_overload_added'\n | 'new_wrapper_alias_added';\n\n/** All change categories. */\nexport type CompatChangeCategory = BreakingChangeCategory | SoftRiskChangeCategory | AdditiveChangeCategory;\n\n/** Change severity levels. */\nexport type CompatChangeSeverity = 'breaking' | 'soft-risk' | 'additive';\n\n/** Provenance bucket — where the drift originated. */\nexport type CompatProvenance =\n | 'spec_shape_change'\n | 'spec_ordering_change'\n | 'emitter_template_change'\n | 'compat_extractor_change'\n | 'operation_hint_change'\n | 'manual_override_change'\n | 'normalization_change'\n | 'unknown';\n\n// ---------------------------------------------------------------------------\n// Fail threshold\n// ---------------------------------------------------------------------------\n\n/** Level at which `verify` should fail. */\nexport type CompatFailLevel = 'none' | 'breaking' | 'soft-risk';\n\n// ---------------------------------------------------------------------------\n// Approvals\n// ---------------------------------------------------------------------------\n\n/** A single intentional-break approval in `oagen.config.ts`. */\nexport interface CompatApproval {\n /** Fully-qualified symbol (e.g., \"WorkOS\\\\Service\\\\UserManagement::createUser\"). */\n symbol: string;\n /** The kind of change being approved. */\n category: CompatChangeCategory;\n /** Languages this approval applies to. Omit for all impacted languages. */\n appliesTo?: LanguageId[] | 'all-impacted-languages';\n /** Optional narrowing criteria. */\n match?: {\n parameter?: string;\n member?: string;\n oldName?: string;\n newName?: string;\n };\n /** Minimum release level required for this break. */\n allowedReleaseLevel?: 'major' | 'minor' | 'patch';\n /** Human-readable reason for this approval. */\n reason: string;\n /** Issue tracker reference (e.g., \"SDK-1234\"). */\n issue?: string;\n /** Auto-expire this approval after a version is released. */\n expiresAfterVersion?: string;\n /** Whether this approval is currently active. */\n approved?: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// Config section\n// ---------------------------------------------------------------------------\n\n/** The `compat` section of `oagen.config.ts`. */\nexport interface CompatConfig {\n /** Level at which `oagen verify` should fail. Default: 'breaking'. */\n failOn?: CompatFailLevel;\n /** Path to write the machine-readable compat report. */\n reportPath?: string;\n /** Include provenance explanations in reports. */\n explain?: boolean;\n /** Path to the baseline compatibility snapshot. */\n baselinePath?: string;\n /** Per-language policy overrides. Sparse — only override what diverges. */\n languagePolicy?: Partial<Record<LanguageId, Partial<CompatPolicyHints>>>;\n /** Intentional break approvals. */\n allow?: CompatApproval[];\n}\n\n// ---------------------------------------------------------------------------\n// Category → severity mapping\n// ---------------------------------------------------------------------------\n\nconst BREAKING_CATEGORIES: ReadonlySet<BreakingChangeCategory> = new Set<BreakingChangeCategory>([\n 'symbol_removed',\n 'symbol_renamed',\n 'parameter_removed',\n 'parameter_renamed',\n 'parameter_requiredness_increased',\n 'parameter_type_narrowed',\n 'parameter_position_changed_order_sensitive',\n 'constructor_position_changed_order_sensitive',\n 'named_arg_name_removed',\n 'keyword_name_removed',\n 'overload_removed',\n 'union_wrapper_migration_without_compat_alias',\n 'field_type_changed',\n 'return_type_changed',\n 'enum_member_value_changed',\n]);\n\nconst SOFT_RISK_CATEGORIES: ReadonlySet<SoftRiskChangeCategory> = new Set<SoftRiskChangeCategory>([\n 'parameter_added_non_terminal_optional',\n 'constructor_reordered_named_friendly',\n 'default_value_changed',\n 'wrapper_stricter_than_previous_sdk_but_matches_spec',\n 'doc_surface_drift',\n]);\n\n/** Get the default severity for a change category. */\nexport function defaultSeverityForCategory(category: CompatChangeCategory): CompatChangeSeverity {\n if (BREAKING_CATEGORIES.has(category as BreakingChangeCategory)) return 'breaking';\n if (SOFT_RISK_CATEGORIES.has(category as SoftRiskChangeCategory)) return 'soft-risk';\n return 'additive';\n}\n\n/** Check whether a severity meets or exceeds a fail threshold. */\nexport function severityMeetsThreshold(severity: CompatChangeSeverity, threshold: CompatFailLevel): boolean {\n if (threshold === 'none') return false;\n if (threshold === 'soft-risk') return severity === 'breaking' || severity === 'soft-risk';\n return severity === 'breaking';\n}\n","/**\n * Change classifier for compatibility verification.\n *\n * Takes raw diffs between baseline and candidate compat snapshots and\n * classifies each change into a specific category with policy-aware severity.\n */\n\nimport type { CompatSymbol, CompatParameter } from './ir.js';\nimport type { CompatPolicyHints } from './policy.js';\nimport type { CompatChangeCategory, CompatChangeSeverity, CompatProvenance } from './config.js';\nimport { defaultSeverityForCategory } from './config.js';\n\n/** A single classified compatibility change. */\nexport interface ClassifiedChange {\n /** Specific change category. */\n category: CompatChangeCategory;\n /** Policy-aware severity (may differ from defaultSeverityForCategory). */\n severity: CompatChangeSeverity;\n /** Fully-qualified symbol path. */\n symbol: string;\n /** Deterministic ID for grouping related changes across languages. */\n conceptualChangeId: string;\n /** Where the drift originated. */\n provenance: CompatProvenance;\n /** Description of the old state. */\n old: Record<string, string>;\n /** Description of the new state. */\n new: Record<string, string>;\n /** Human-readable explanation. */\n message: string;\n}\n\n/** Result of classifying all changes between two snapshots. */\nexport interface ClassificationResult {\n changes: ClassifiedChange[];\n summary: {\n breaking: number;\n softRisk: number;\n additive: number;\n };\n}\n\n// ---------------------------------------------------------------------------\n// Classification engine\n// ---------------------------------------------------------------------------\n\n/**\n * Classify changes between a baseline and candidate symbol.\n * Returns one or more classified changes for the diff.\n */\nexport function classifySymbolChanges(\n baseline: CompatSymbol,\n candidate: CompatSymbol | undefined,\n policy: CompatPolicyHints,\n): ClassifiedChange[] {\n const changes: ClassifiedChange[] = [];\n\n // Symbol removed\n if (!candidate) {\n changes.push(\n makeChange({\n category: 'symbol_removed',\n symbol: baseline.fqName,\n old: { symbol: baseline.fqName },\n new: { symbol: '(removed)' },\n message: `Symbol \"${baseline.displayName}\" was removed`,\n policy,\n }),\n );\n return changes;\n }\n\n // Symbol renamed\n if (baseline.fqName !== candidate.fqName && baseline.id === candidate.id) {\n changes.push(\n makeChange({\n category: 'symbol_renamed',\n symbol: baseline.fqName,\n old: { name: baseline.fqName },\n new: { name: candidate.fqName },\n message: `Symbol renamed from \"${baseline.displayName}\" to \"${candidate.displayName}\"`,\n policy,\n }),\n );\n }\n\n // Parameter-level changes (for callables and constructors)\n if (baseline.parameters && candidate.parameters) {\n changes.push(...classifyParameterChanges(baseline, candidate, policy));\n }\n\n // Return type changes (for callables)\n if (baseline.returns && candidate.returns && baseline.returns.name !== candidate.returns.name) {\n changes.push(\n makeChange({\n category: 'return_type_changed',\n symbol: baseline.fqName,\n old: { returnType: baseline.returns.name },\n new: { returnType: candidate.returns.name },\n message: `Return type changed for \"${baseline.displayName}\" from \"${baseline.returns.name}\" to \"${candidate.returns.name}\"`,\n policy,\n }),\n );\n }\n\n // Field/property type changes\n if (baseline.typeRef && candidate.typeRef && baseline.typeRef.name !== candidate.typeRef.name) {\n changes.push(\n makeChange({\n category: 'field_type_changed',\n symbol: baseline.fqName,\n old: { type: baseline.typeRef.name },\n new: { type: candidate.typeRef.name },\n message: `Type changed for \"${baseline.displayName}\" from \"${baseline.typeRef.name}\" to \"${candidate.typeRef.name}\"`,\n policy,\n }),\n );\n }\n\n // Enum member value changes\n if (\n baseline.kind === 'enum_member' &&\n candidate.kind === 'enum_member' &&\n baseline.value !== undefined &&\n candidate.value !== undefined &&\n baseline.value !== candidate.value\n ) {\n changes.push(\n makeChange({\n category: 'enum_member_value_changed',\n symbol: baseline.fqName,\n old: { value: String(baseline.value) },\n new: { value: String(candidate.value) },\n message: `Enum value changed for \"${baseline.displayName}\" from \"${baseline.value}\" to \"${candidate.value}\"`,\n policy,\n }),\n );\n }\n\n return changes;\n}\n\n/**\n * Classify parameter-level changes between two symbol versions.\n */\nfunction classifyParameterChanges(\n baseline: CompatSymbol,\n candidate: CompatSymbol,\n policy: CompatPolicyHints,\n): ClassifiedChange[] {\n const changes: ClassifiedChange[] = [];\n const baseParams = baseline.parameters ?? [];\n const candParams = candidate.parameters ?? [];\n\n const baseByName = new Map(baseParams.map((p) => [p.publicName, p]));\n const candByName = new Map(candParams.map((p) => [p.publicName, p]));\n const isConstructor = baseline.kind === 'constructor';\n\n // Check each baseline parameter\n for (const baseParam of baseParams) {\n const candParam = candByName.get(baseParam.publicName);\n\n if (!candParam) {\n // Parameter removed — check if it was renamed\n const positionalMatch = candParams[baseParam.position];\n if (positionalMatch && !baseByName.has(positionalMatch.publicName)) {\n // Position preserved but name changed → rename\n const isBreakingRename = parameterNameIsPublicApi(baseParam, policy, isConstructor);\n changes.push(\n makeChange({\n category: 'parameter_renamed',\n symbol: baseline.fqName,\n old: { parameter: baseParam.publicName },\n new: { parameter: positionalMatch.publicName },\n message: `Parameter \"${baseParam.publicName}\" renamed to \"${positionalMatch.publicName}\" on \"${baseline.displayName}\"`,\n policy,\n severityOverride: isBreakingRename ? undefined : 'soft-risk',\n }),\n );\n } else {\n // Truly removed\n changes.push(\n makeChange({\n category: 'parameter_removed',\n symbol: baseline.fqName,\n old: { parameter: baseParam.publicName },\n new: { parameter: '(removed)' },\n message: `Parameter \"${baseParam.publicName}\" removed from \"${baseline.displayName}\"`,\n policy,\n }),\n );\n }\n continue;\n }\n\n // Requiredness increased (optional → required)\n if (!baseParam.required && candParam.required) {\n changes.push(\n makeChange({\n category: 'parameter_requiredness_increased',\n symbol: baseline.fqName,\n old: { parameter: baseParam.publicName, required: 'false' },\n new: { parameter: candParam.publicName, required: 'true' },\n message: `Parameter \"${baseParam.publicName}\" became required on \"${baseline.displayName}\"`,\n policy,\n }),\n );\n }\n\n // Type narrowed\n if (baseParam.type.name !== candParam.type.name) {\n changes.push(\n makeChange({\n category: 'parameter_type_narrowed',\n symbol: baseline.fqName,\n old: { parameter: baseParam.publicName, type: baseParam.type.name },\n new: { parameter: candParam.publicName, type: candParam.type.name },\n message: `Parameter type changed for \"${baseParam.publicName}\" on \"${baseline.displayName}\"`,\n policy,\n }),\n );\n }\n\n // Position changed (order-sensitive)\n if (baseParam.position !== candParam.position) {\n const orderMatters = isConstructor ? policy.constructorOrderMatters : baseParam.sensitivity.order;\n\n if (orderMatters) {\n const category: CompatChangeCategory = isConstructor\n ? 'constructor_position_changed_order_sensitive'\n : 'parameter_position_changed_order_sensitive';\n changes.push(\n makeChange({\n category,\n symbol: baseline.fqName,\n old: { parameter: baseParam.publicName, position: String(baseParam.position) },\n new: { parameter: candParam.publicName, position: String(candParam.position) },\n message: `Parameter \"${baseParam.publicName}\" moved from position ${baseParam.position} to ${candParam.position} on \"${baseline.displayName}\"`,\n policy,\n }),\n );\n } else {\n // Reordered but in a named-friendly language → soft-risk\n changes.push(\n makeChange({\n category: 'constructor_reordered_named_friendly',\n symbol: baseline.fqName,\n old: { parameter: baseParam.publicName, position: String(baseParam.position) },\n new: { parameter: candParam.publicName, position: String(candParam.position) },\n message: `Parameter \"${baseParam.publicName}\" reordered on \"${baseline.displayName}\" (named-friendly language)`,\n policy,\n }),\n );\n }\n }\n }\n\n // Check for new parameters in candidate\n for (const candParam of candParams) {\n if (!baseByName.has(candParam.publicName)) {\n // Check if this was already captured as a rename\n const isRename = changes.some(\n (c) => c.category === 'parameter_renamed' && c.new.parameter === candParam.publicName,\n );\n if (isRename) continue;\n\n const isTerminal = candParam.position === candParams.length - 1;\n const category: CompatChangeCategory = candParam.required\n ? 'parameter_requiredness_increased'\n : isTerminal\n ? 'parameter_added_optional_terminal'\n : 'parameter_added_non_terminal_optional';\n\n if (candParam.required) {\n changes.push(\n makeChange({\n category,\n symbol: baseline.fqName,\n old: { parameter: '(absent)' },\n new: { parameter: candParam.publicName, required: 'true' },\n message: `Required parameter \"${candParam.publicName}\" added to \"${baseline.displayName}\"`,\n policy,\n }),\n );\n } else {\n changes.push(\n makeChange({\n category,\n symbol: baseline.fqName,\n old: { parameter: '(absent)' },\n new: { parameter: candParam.publicName },\n message: `Optional parameter \"${candParam.publicName}\" added to \"${baseline.displayName}\"`,\n policy,\n }),\n );\n }\n }\n }\n\n return changes;\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction parameterNameIsPublicApi(param: CompatParameter, policy: CompatPolicyHints, isConstructor: boolean): boolean {\n if (param.sensitivity.publicName) return true;\n if (isConstructor) return policy.constructorParameterNamesArePublicApi;\n return policy.methodParameterNamesArePublicApi;\n}\n\n/** Build a deterministic conceptual change ID. */\nfunction buildConceptualChangeId(\n category: CompatChangeCategory,\n symbol: string,\n match: Record<string, string>,\n): string {\n const parts = ['chg', category, symbol.replace(/[^a-zA-Z0-9_.]/g, '_')];\n if (match.parameter) parts.push(match.parameter);\n if (match.member) parts.push(match.member);\n return parts.join('_').toLowerCase();\n}\n\nfunction makeChange(opts: {\n category: CompatChangeCategory;\n symbol: string;\n old: Record<string, string>;\n new: Record<string, string>;\n message: string;\n policy: CompatPolicyHints;\n provenance?: CompatProvenance;\n severityOverride?: CompatChangeSeverity;\n}): ClassifiedChange {\n return {\n category: opts.category,\n severity: opts.severityOverride ?? defaultSeverityForCategory(opts.category),\n symbol: opts.symbol,\n conceptualChangeId: buildConceptualChangeId(opts.category, opts.symbol, opts.old),\n provenance: opts.provenance ?? 'unknown',\n old: opts.old,\n new: opts.new,\n message: opts.message,\n };\n}\n\n/**\n * Classify a new symbol as additive.\n */\nexport function classifyAddedSymbol(symbol: CompatSymbol): ClassifiedChange {\n return {\n category: 'symbol_added',\n severity: 'additive',\n symbol: symbol.fqName,\n conceptualChangeId: buildConceptualChangeId('symbol_added', symbol.fqName, {}),\n provenance: 'unknown',\n old: { symbol: '(absent)' },\n new: { symbol: symbol.fqName },\n message: `Symbol \"${symbol.displayName}\" was added`,\n };\n}\n\n/** Summarize a list of classified changes by severity. */\nexport function summarizeChanges(changes: ClassifiedChange[]): ClassificationResult['summary'] {\n let breaking = 0;\n let softRisk = 0;\n let additive = 0;\n for (const c of changes) {\n if (c.severity === 'breaking') breaking++;\n else if (c.severity === 'soft-risk') softRisk++;\n else additive++;\n }\n return { breaking, softRisk, additive };\n}\n","import type { ApiSpec, TypeRef } from '../ir/types.js';\nimport { walkTypeRef } from '../ir/types.js';\nimport type { ApiSurface, LanguageHints } from './types.js';\n\n/**\n * Compute the set of symbol names that are derivable from the OpenAPI spec.\n * Only these names should be compared during compat verification — everything\n * else in the baseline is hand-written and out of scope for generation.\n */\nexport function specDerivedNames(spec: ApiSpec, hints: LanguageHints): Set<string> {\n const names = new Set<string>();\n\n // Build set of top-level enum names for filtering inline enums\n const topLevelEnumNames = new Set(spec.enums.map((e) => e.name));\n\n // Service classes\n for (const service of spec.services) {\n names.add(service.name);\n for (const op of service.operations) {\n // Operation methods are matched by the class diff, not by name here\n collectTypeRefNames(op.response, names, hints, topLevelEnumNames);\n if (op.requestBody) collectTypeRefNames(op.requestBody, names, hints, topLevelEnumNames);\n for (const p of [...op.pathParams, ...op.queryParams, ...op.headerParams, ...(op.cookieParams ?? [])]) {\n collectTypeRefNames(p.type, names, hints, topLevelEnumNames);\n }\n }\n }\n\n // Models → domain interface + language-specific derived names\n for (const model of spec.models) {\n names.add(model.name);\n for (const derived of hints.derivedModelNames(model.name)) {\n names.add(derived);\n }\n for (const field of model.fields) {\n collectTypeRefNames(field.type, names, hints, topLevelEnumNames);\n }\n }\n\n // Enums → type aliases\n for (const e of spec.enums) {\n names.add(e.name);\n }\n\n return names;\n}\n\n/**\n * Compute a map of enum name → set of wire values that appear in the spec.\n * Used by filterSurface to exclude hand-added enum members that aren't in the spec.\n */\nexport function specDerivedEnumValues(spec: ApiSpec): Map<string, Set<string | number>> {\n const result = new Map<string, Set<string | number>>();\n for (const e of spec.enums) {\n result.set(e.name, new Set(e.values.map((v) => v.value)));\n }\n return result;\n}\n\n/**\n * Compute the set of field paths (e.g., \"Organization.name\") that are defined\n * in the OpenAPI spec's model schemas. Used by filterSurface to exclude\n * hand-added SDK fields that reference spec-derived types.\n */\nexport function specDerivedFieldPaths(spec: ApiSpec, hints: LanguageHints): Set<string> {\n const paths = new Set<string>();\n for (const model of spec.models) {\n for (const field of model.fields) {\n paths.add(`${model.name}.${field.name}`);\n }\n // Also add field paths for derived model names (e.g., OrganizationResponse.name)\n for (const derived of hints.derivedModelNames(model.name)) {\n for (const field of model.fields) {\n paths.add(`${derived}.${field.name}`);\n }\n }\n }\n return paths;\n}\n\n/**\n * Compute the set of method paths (e.g., \"SSO.authorize\") that are defined\n * as operations in the OpenAPI spec's services. Used by filterSurface to\n * exclude hand-written SDK methods that don't correspond to spec operations.\n */\nexport function specDerivedMethodPaths(spec: ApiSpec): Set<string> {\n const paths = new Set<string>();\n for (const service of spec.services) {\n for (const op of service.operations) {\n paths.add(`${service.name}.${op.name}`);\n }\n }\n return paths;\n}\n\n/**\n * Compute the set of HTTP operation keys (e.g., \"GET /sso/authorize\") that\n * exist in the spec. Used for overlay-based method matching.\n */\nexport function specDerivedHttpKeys(spec: ApiSpec): Set<string> {\n const keys = new Set<string>();\n for (const service of spec.services) {\n for (const op of service.operations) {\n keys.add(`${op.httpMethod.toUpperCase()} ${op.path}`);\n }\n }\n return keys;\n}\n\nfunction collectTypeRefNames(ref: TypeRef, out: Set<string>, hints: LanguageHints, topLevelEnums?: Set<string>): void {\n walkTypeRef(ref, {\n model: (r) => {\n out.add(r.name);\n for (const derived of hints.derivedModelNames(r.name)) {\n out.add(derived);\n }\n },\n enum: (r) => {\n // Only include enums that are top-level (in spec.enums). Inline enums\n // embedded in TypeRefs (e.g., query parameter enums) may not be emitted\n // by all emitters, so they should not create false-positive violations.\n if (!topLevelEnums || topLevelEnums.has(r.name)) {\n out.add(r.name);\n }\n },\n });\n}\n\nfunction filterRecord<T>(record: Record<string, T>, allowed: Set<string>): Record<string, T> {\n const result: Record<string, T> = {};\n for (const [name, value] of Object.entries(record)) {\n if (allowed.has(name)) result[name] = value;\n }\n return result;\n}\n\n/**\n * Filter an ApiSurface to only include symbols whose names appear in the\n * allowed set. Symbols not in the set are dropped entirely — they won't\n * count toward the total or produce violations.\n *\n * For interfaces: when fieldPaths is provided, only keeps fields that appear\n * in the spec-derived field paths. This prevents false positives from hand-added\n * SDK fields that reference spec-derived types but aren't defined in the spec.\n *\n * For classes: when methodPaths is provided, only keeps methods whose names\n * appear in the spec-derived method paths. This prevents false positives from\n * hand-written SDK methods (e.g., SSO.authorization_url, Webhooks.construct_event)\n * that don't correspond to spec operations. Properties on service classes are\n * also filtered: only UPPER_CASE constants that are spec-derivable are kept.\n */\nexport function filterSurface(\n surface: ApiSurface,\n allowedNames: Set<string>,\n opts?: {\n fieldPaths?: Set<string>;\n methodPaths?: Set<string>;\n enumValues?: Map<string, Set<string | number>>;\n },\n): ApiSurface {\n const { fieldPaths, methodPaths, enumValues } = opts ?? {};\n const filteredInterfaces = filterRecord(surface.interfaces, allowedNames);\n\n // Filter interface fields by spec-derived field paths if provided\n if (fieldPaths) {\n for (const [name, iface] of Object.entries(filteredInterfaces)) {\n const filteredFields: Record<string, (typeof iface.fields)[string]> = {};\n for (const [fieldName, field] of Object.entries(iface.fields)) {\n // Keep the field if its path is spec-derived\n if (fieldPaths.has(`${name}.${fieldName}`)) {\n filteredFields[fieldName] = field;\n }\n }\n filteredInterfaces[name] = { ...iface, fields: filteredFields };\n }\n }\n\n let filteredClasses = filterRecord(surface.classes, allowedNames);\n\n // Filter class methods and properties by spec-derived method paths if provided\n if (methodPaths) {\n // Build a set of service-class names that have spec-derived methods.\n // Only filter methods on these classes; non-service model classes keep all members.\n const serviceClassNames = new Set<string>();\n for (const path of methodPaths) {\n const dot = path.indexOf('.');\n if (dot !== -1) serviceClassNames.add(path.slice(0, dot));\n }\n\n const newClasses: Record<string, (typeof filteredClasses)[string]> = {};\n for (const [name, cls] of Object.entries(filteredClasses)) {\n if (serviceClassNames.has(name)) {\n // Service class — filter methods and properties by spec-derived method paths\n const filteredMethods: typeof cls.methods = {};\n for (const [methodName, overloads] of Object.entries(cls.methods)) {\n if (methodPaths.has(`${name}.${methodName}`)) {\n filteredMethods[methodName] = overloads;\n }\n }\n\n // Filter properties: only keep properties that are spec-derivable.\n // Hand-written constants (PROVIDERS, DEFAULT_TOLERANCE, WIDGET_SCOPES)\n // are not derivable from the spec and should be excluded.\n const filteredProperties: typeof cls.properties = {};\n for (const [propName, prop] of Object.entries(cls.properties)) {\n if (methodPaths.has(`${name}.${propName}`)) {\n filteredProperties[propName] = prop;\n }\n }\n\n newClasses[name] = {\n ...cls,\n methods: filteredMethods,\n properties: filteredProperties,\n };\n } else if (fieldPaths) {\n // Non-service (model) class — filter properties by spec-derived field paths.\n // In some languages (Ruby, PHP), models are represented as classes with\n // properties rather than interfaces with fields. Apply the same field-level\n // filtering used for interfaces to exclude hand-added SDK fields.\n const filteredProperties: typeof cls.properties = {};\n for (const [propName, prop] of Object.entries(cls.properties)) {\n if (fieldPaths.has(`${name}.${propName}`)) {\n filteredProperties[propName] = prop;\n }\n }\n\n // Also filter methods on model classes: convenience methods like\n // `primary_email` are hand-written and not spec-derivable.\n // Keep utility methods (from_json, to_json, etc.) if they appear in fieldPaths,\n // otherwise drop non-spec methods.\n const filteredMethods: typeof cls.methods = {};\n for (const [methodName, overloads] of Object.entries(cls.methods)) {\n if (fieldPaths.has(`${name}.${methodName}`) || methodPaths.has(`${name}.${methodName}`)) {\n filteredMethods[methodName] = overloads;\n }\n }\n\n newClasses[name] = {\n ...cls,\n methods: filteredMethods,\n properties: filteredProperties,\n };\n } else {\n // No filtering available — keep as-is\n newClasses[name] = cls;\n }\n }\n filteredClasses = newClasses;\n }\n\n // Filter enum members by spec-derived values if provided\n let filteredEnums = filterRecord(surface.enums, allowedNames);\n if (enumValues) {\n const newEnums: Record<string, (typeof filteredEnums)[string]> = {};\n for (const [name, enumDef] of Object.entries(filteredEnums)) {\n const specValues = enumValues.get(name);\n if (!specValues) {\n // Enum not in spec values map — keep as-is\n newEnums[name] = enumDef;\n continue;\n }\n // Filter members: keep only those whose wire value is in the spec.\n // Use case-insensitive comparison since some extractors produce\n // PascalCase values (e.g., \"Pending\") while the spec has lowercase.\n const specValuesLower = new Set([...specValues].map((v) => String(v).toLowerCase()));\n const filteredMembers: typeof enumDef.members = {};\n for (const [member, value] of Object.entries(enumDef.members)) {\n if (specValues.has(value) || specValuesLower.has(String(value).toLowerCase())) {\n filteredMembers[member] = value;\n }\n }\n newEnums[name] = { ...enumDef, members: filteredMembers };\n }\n filteredEnums = newEnums;\n }\n\n return {\n ...surface,\n classes: filteredClasses,\n interfaces: filteredInterfaces,\n typeAliases: filterRecord(surface.typeAliases, allowedNames),\n enums: filteredEnums,\n exports: {}, // exports are structural, not symbol-level — skip for scoped comparison\n };\n}\n","/**\n * Compatibility diff engine.\n *\n * Compares two API surfaces (or compat snapshots) and produces classified\n * changes with policy-aware severity, provenance, and conceptual change IDs.\n *\n * This replaces the previous unclassified diff engine with a richer model\n * that supports cross-language severity analysis and approval matching.\n */\n\nimport type { ApiSurface, ApiMethod, LanguageHints, DiffResult, Violation, Addition } from './types.js';\nimport type { CompatSnapshot, CompatSymbol } from './ir.js';\nimport type { CompatPolicyHints } from './policy.js';\nimport type { ClassifiedChange, ClassificationResult } from './classify.js';\nimport { classifySymbolChanges, classifyAddedSymbol, summarizeChanges } from './classify.js';\nimport { NAMED_TYPE_RE, typeExistsInSurface } from './language-hints.js';\n\nexport {\n specDerivedNames,\n specDerivedFieldPaths,\n specDerivedMethodPaths,\n specDerivedHttpKeys,\n specDerivedEnumValues,\n filterSurface,\n} from './spec-filter.js';\n\n// ---------------------------------------------------------------------------\n// New: CompatSnapshot-based diff\n// ---------------------------------------------------------------------------\n\n/** Result of diffing two compat snapshots. */\nexport interface CompatDiffResult {\n changes: ClassifiedChange[];\n summary: ClassificationResult['summary'];\n}\n\n/**\n * Diff two compat snapshots, producing classified changes with\n * policy-aware severity.\n */\nexport function diffSnapshots(\n baseline: CompatSnapshot,\n candidate: CompatSnapshot,\n policy?: CompatPolicyHints,\n): CompatDiffResult {\n const effectivePolicy = policy ?? baseline.policies;\n const changes: ClassifiedChange[] = [];\n\n // Index candidate symbols by ID and fqName for lookup\n const candById = new Map<string, CompatSymbol>();\n const candByFqName = new Map<string, CompatSymbol>();\n for (const sym of candidate.symbols) {\n candById.set(sym.id, sym);\n candByFqName.set(sym.fqName, sym);\n }\n\n // Index baseline symbols by fqName\n const baseByFqName = new Set<string>();\n for (const sym of baseline.symbols) {\n baseByFqName.add(sym.fqName);\n }\n\n // Compare each baseline symbol against candidate\n for (const baseSym of baseline.symbols) {\n const candSym = candById.get(baseSym.id) ?? candByFqName.get(baseSym.fqName);\n changes.push(...classifySymbolChanges(baseSym, candSym, effectivePolicy));\n }\n\n // Detect added symbols\n for (const candSym of candidate.symbols) {\n if (!baseByFqName.has(candSym.fqName)) {\n changes.push(classifyAddedSymbol(candSym));\n }\n }\n\n return {\n changes,\n summary: summarizeChanges(changes),\n };\n}\n\n// ---------------------------------------------------------------------------\n// Legacy: ApiSurface-based diff (delegates to existing logic)\n// ---------------------------------------------------------------------------\n\n/**\n * Compare two ApiSurface objects and return a DiffResult.\n *\n * This preserves the existing diffing behavior used by the overlay retry loop,\n * compat check, and all existing tests. The internal implementation uses the\n * same algorithms as before to maintain full backward compatibility with\n * overlay patching and verification workflows.\n */\nexport function diffSurfaces(baseline: ApiSurface, candidate: ApiSurface, hints: LanguageHints): DiffResult {\n const violations: Violation[] = [];\n const additions: Addition[] = [];\n let totalBaseline = 0;\n let preserved = 0;\n\n // Diff classes\n for (const [name, baseClass] of Object.entries(baseline.classes)) {\n totalBaseline++;\n const candClass = candidate.classes[name];\n if (!candClass) {\n violations.push({\n category: 'public-api',\n severity: 'breaking',\n symbolPath: name,\n baseline: name,\n candidate: '(missing)',\n message: `Class \"${name}\" exists in baseline but not in generated output`,\n });\n totalBaseline += Object.values(baseClass.methods).reduce((sum, overloads) => sum + overloads.length, 0);\n totalBaseline += Object.keys(baseClass.properties).length;\n continue;\n }\n preserved++;\n\n // Diff methods (each method name maps to an array of overloads)\n for (const [methodName, baseOverloads] of Object.entries(baseClass.methods)) {\n const candOverloads = candClass.methods[methodName];\n for (const baseMethod of baseOverloads) {\n totalBaseline++;\n if (!candOverloads || candOverloads.length === 0) {\n violations.push({\n category: 'public-api',\n severity: 'breaking',\n symbolPath: `${name}.${methodName}`,\n baseline: methodName,\n candidate: '(missing)',\n message: `Method \"${name}.${methodName}\" exists in baseline but not in generated output`,\n });\n continue;\n }\n const candMethod = candOverloads.find((c) => signaturesMatch(baseMethod, c));\n if (!candMethod) {\n // Fallback: check language-specific signature equivalence\n const equivalentMethod = hints.isSignatureEquivalent\n ? candOverloads.find((c) => hints.isSignatureEquivalent!(baseMethod, c, candidate))\n : undefined;\n if (equivalentMethod) {\n preserved++;\n continue;\n }\n violations.push({\n category: 'signature',\n severity: 'breaking',\n symbolPath: `${name}.${methodName}`,\n baseline: formatSignature(baseMethod),\n candidate: formatSignature(candOverloads[0]),\n message: `Signature mismatch for \"${name}.${methodName}\"`,\n });\n continue;\n }\n preserved++;\n }\n }\n\n // Check for new methods (additions)\n for (const methodName of Object.keys(candClass.methods)) {\n if (!baseClass.methods[methodName]) {\n additions.push({ symbolPath: `${name}.${methodName}`, symbolType: 'method' });\n }\n }\n\n // Diff properties\n for (const [propName, baseProp] of Object.entries(baseClass.properties)) {\n totalBaseline++;\n const candProp = candClass.properties[propName];\n if (!candProp) {\n violations.push({\n category: 'public-api',\n severity: 'breaking',\n symbolPath: `${name}.${propName}`,\n baseline: baseProp.type,\n candidate: '(missing)',\n message: `Property \"${name}.${propName}\" exists in baseline but not in generated output`,\n });\n continue;\n }\n if (baseProp.type !== candProp.type) {\n const nullableOnly = hints.isNullableOnlyDifference(baseProp.type, candProp.type);\n violations.push({\n category: 'signature',\n severity: nullableOnly ? 'warning' : 'breaking',\n symbolPath: `${name}.${propName}`,\n baseline: baseProp.type,\n candidate: candProp.type,\n message: `Property type mismatch for \"${name}.${propName}\"`,\n });\n if (nullableOnly) preserved++;\n continue;\n }\n preserved++;\n }\n\n // Check for new properties (additions)\n for (const propName of Object.keys(candClass.properties)) {\n if (!baseClass.properties[propName]) {\n additions.push({ symbolPath: `${name}.${propName}`, symbolType: 'property' });\n }\n }\n }\n\n // Check for new classes (additions)\n for (const name of Object.keys(candidate.classes)) {\n if (!baseline.classes[name]) {\n additions.push({ symbolPath: name, symbolType: 'class' });\n }\n }\n\n // Precompute lowercased field/property name sets for field-structure matching\n const candIfaceFieldSets = new Map<string, Set<string>>();\n for (const [n, iface] of Object.entries(candidate.interfaces)) {\n candIfaceFieldSets.set(n, new Set(Object.keys(iface.fields).map((f) => f.toLowerCase())));\n }\n const candClassPropSets = new Map<string, Set<string>>();\n for (const [n, cls] of Object.entries(candidate.classes)) {\n candClassPropSets.set(n, new Set(Object.keys(cls.properties).map((f) => f.toLowerCase())));\n }\n\n // Diff interfaces\n for (const [name, baseIface] of Object.entries(baseline.interfaces)) {\n totalBaseline++;\n const candIface = candidate.interfaces[name];\n if (!candIface) {\n let tolerated = false;\n if (hints.tolerateCategoryMismatch && name.startsWith('Serialized')) {\n const baseName = name.slice('Serialized'.length);\n if (candidate.interfaces[baseName] || candidate.classes[baseName]) {\n tolerated = true;\n }\n }\n if (tolerated) {\n preserved++;\n totalBaseline += Object.keys(baseIface.fields).length;\n preserved += Object.keys(baseIface.fields).length;\n continue;\n }\n if (!tolerated) {\n const baseFieldNamesLower = new Set(Object.keys(baseIface.fields).map((f) => f.toLowerCase()));\n if (baseFieldNamesLower.size > 0) {\n for (const [, candFieldNamesLower] of candIfaceFieldSets) {\n if (\n candFieldNamesLower.size === baseFieldNamesLower.size &&\n [...baseFieldNamesLower].every((f) => candFieldNamesLower.has(f))\n ) {\n tolerated = true;\n break;\n }\n }\n if (!tolerated) {\n for (const [, candPropNamesLower] of candClassPropSets) {\n if (\n candPropNamesLower.size === baseFieldNamesLower.size &&\n [...baseFieldNamesLower].every((f) => candPropNamesLower.has(f))\n ) {\n tolerated = true;\n break;\n }\n }\n }\n } else {\n tolerated = true;\n }\n }\n if (tolerated) {\n preserved++;\n totalBaseline += Object.keys(baseIface.fields).length;\n preserved += Object.keys(baseIface.fields).length;\n continue;\n }\n violations.push({\n category: 'public-api',\n severity: 'breaking',\n symbolPath: name,\n baseline: name,\n candidate: '(missing)',\n message: `Interface \"${name}\" exists in baseline but not in generated output`,\n });\n totalBaseline += Object.keys(baseIface.fields).length;\n continue;\n }\n preserved++;\n\n for (const [fieldName, baseField] of Object.entries(baseIface.fields)) {\n totalBaseline++;\n const candField = candIface.fields[fieldName];\n if (!candField) {\n const baseTypeClean = baseField.type.replace(/\\[\\]$/, '').replace(/ \\| null$/, '');\n const typeIsUnresolvable = NAMED_TYPE_RE.test(baseTypeClean) && !typeExistsInSurface(baseTypeClean, candidate);\n violations.push({\n category: 'public-api',\n severity: typeIsUnresolvable ? 'warning' : 'breaking',\n symbolPath: `${name}.${fieldName}`,\n baseline: baseField.type,\n candidate: '(missing)',\n message: `Field \"${name}.${fieldName}\" exists in baseline but not in generated output`,\n });\n if (typeIsUnresolvable) preserved++;\n continue;\n }\n if (baseField.type !== candField.type) {\n if (hints.isUnionReorder(baseField.type, candField.type)) {\n preserved++;\n continue;\n }\n if (hints.isTypeEquivalent?.(baseField.type, candField.type, candidate)) {\n preserved++;\n continue;\n }\n const nullableOnly = hints.isNullableOnlyDifference(baseField.type, candField.type);\n const genericParam = hints.isGenericTypeParam(baseField.type);\n const extractionArtifact = hints.isExtractionArtifact(candField.type);\n const isWarning = nullableOnly || genericParam || extractionArtifact;\n violations.push({\n category: 'signature',\n severity: isWarning ? 'warning' : 'breaking',\n symbolPath: `${name}.${fieldName}`,\n baseline: baseField.type,\n candidate: candField.type,\n message: `Field type mismatch for \"${name}.${fieldName}\"`,\n });\n if (isWarning) preserved++;\n continue;\n }\n preserved++;\n }\n\n for (const fieldName of Object.keys(candIface.fields)) {\n if (!baseIface.fields[fieldName]) {\n additions.push({ symbolPath: `${name}.${fieldName}`, symbolType: 'property' });\n }\n }\n }\n\n // Check for new interfaces (additions)\n for (const name of Object.keys(candidate.interfaces)) {\n if (!baseline.interfaces[name]) {\n additions.push({ symbolPath: name, symbolType: 'interface' });\n }\n }\n\n // Diff type aliases\n for (const [name, baseAlias] of Object.entries(baseline.typeAliases)) {\n totalBaseline++;\n const candAlias = candidate.typeAliases[name];\n if (!candAlias) {\n if (hints.tolerateCategoryMismatch && typeExistsInSurface(name, candidate)) {\n preserved++;\n continue;\n }\n violations.push({\n category: 'public-api',\n severity: 'breaking',\n symbolPath: name,\n baseline: baseAlias.value,\n candidate: '(missing)',\n message: `Type alias \"${name}\" exists in baseline but not in generated output`,\n });\n continue;\n }\n if (baseAlias.value !== candAlias.value) {\n if (hints.isUnionReorder(baseAlias.value, candAlias.value)) {\n preserved++;\n continue;\n }\n const nullableOnly = hints.isNullableOnlyDifference(baseAlias.value, candAlias.value);\n violations.push({\n category: 'signature',\n severity: nullableOnly ? 'warning' : 'breaking',\n symbolPath: name,\n baseline: baseAlias.value,\n candidate: candAlias.value,\n message: `Type alias value mismatch for \"${name}\"`,\n });\n if (nullableOnly) preserved++;\n continue;\n }\n preserved++;\n }\n\n // Check for new type aliases (additions)\n for (const name of Object.keys(candidate.typeAliases)) {\n if (!baseline.typeAliases[name]) {\n additions.push({ symbolPath: name, symbolType: 'type-alias' });\n }\n }\n\n // Diff enums\n for (const [name, baseEnum] of Object.entries(baseline.enums)) {\n totalBaseline++;\n const candEnum = candidate.enums[name];\n if (!candEnum) {\n violations.push({\n category: 'public-api',\n severity: 'breaking',\n symbolPath: name,\n baseline: name,\n candidate: '(missing)',\n message: `Enum \"${name}\" exists in baseline but not in generated output`,\n });\n continue;\n }\n\n const candValueToMembers = new Map<string | number, string[]>();\n for (const [candMember, candValue] of Object.entries(candEnum.members)) {\n const existing = candValueToMembers.get(candValue);\n if (existing) {\n existing.push(candMember);\n } else {\n candValueToMembers.set(candValue, [candMember]);\n }\n }\n\n let enumMatch = true;\n for (const [member, value] of Object.entries(baseEnum.members)) {\n if (candEnum.members[member] === value) {\n continue;\n }\n\n const valueMatches = candValueToMembers.get(value);\n if (valueMatches && valueMatches.length > 0) {\n violations.push({\n category: 'signature',\n severity: 'warning',\n symbolPath: `${name}.${member}`,\n baseline: `${member}=${String(value)}`,\n candidate: `${valueMatches[0]}=${String(value)}`,\n message: `Enum member name differs for \"${name}.${member}\" (value \"${value}\" preserved as \"${valueMatches[0]}\")`,\n });\n continue;\n }\n\n const lowerValue = String(value).toLowerCase();\n const caseInsensitiveMatch = [...candValueToMembers.entries()].find(\n ([candVal]) => String(candVal).toLowerCase() === lowerValue,\n );\n if (caseInsensitiveMatch) {\n violations.push({\n category: 'signature',\n severity: 'warning',\n symbolPath: `${name}.${member}`,\n baseline: `${member}=${String(value)}`,\n candidate: `${caseInsensitiveMatch[1][0]}=${String(caseInsensitiveMatch[0])}`,\n message: `Enum member value case differs for \"${name}.${member}\" (baseline \"${value}\" vs candidate \"${caseInsensitiveMatch[0]}\")`,\n });\n continue;\n }\n\n const isExtractionArtifact =\n String(value) === member || member === 'JsonEnumDefaultValue' || member === 'JsonProperty';\n if (isExtractionArtifact) {\n violations.push({\n category: 'signature',\n severity: 'warning',\n symbolPath: `${name}.${member}`,\n baseline: String(value),\n candidate: '(extraction artifact)',\n message: `Enum member \"${name}.${member}\" appears to be an extraction artifact`,\n });\n continue;\n }\n\n violations.push({\n category: 'signature',\n severity: 'breaking',\n symbolPath: `${name}.${member}`,\n baseline: String(value),\n candidate: member in candEnum.members ? String(candEnum.members[member]) : '(missing)',\n message: `Enum member mismatch for \"${name}.${member}\"`,\n });\n enumMatch = false;\n }\n if (enumMatch) {\n preserved++;\n }\n }\n\n // Check for new enums (additions)\n for (const name of Object.keys(candidate.enums)) {\n if (!baseline.enums[name]) {\n additions.push({ symbolPath: name, symbolType: 'enum' });\n }\n }\n\n // Diff barrel exports\n for (const [path, baseExports] of Object.entries(baseline.exports)) {\n const candExports = candidate.exports[path];\n if (!candExports) {\n for (const exp of baseExports) {\n violations.push({\n category: 'export-structure',\n severity: 'warning',\n symbolPath: `exports[${path}].${exp}`,\n baseline: exp,\n candidate: '(missing)',\n message: `Export \"${exp}\" from \"${path}\" not found in generated output`,\n });\n }\n continue;\n }\n const candSet = new Set(candExports);\n for (const exp of baseExports) {\n if (!candSet.has(exp)) {\n violations.push({\n category: 'export-structure',\n severity: 'warning',\n symbolPath: `exports[${path}].${exp}`,\n baseline: exp,\n candidate: '(missing)',\n message: `Export \"${exp}\" from \"${path}\" not found in generated output`,\n });\n }\n }\n }\n\n return {\n preservationScore: totalBaseline > 0 ? Math.round((preserved / totalBaseline) * 100) : 100,\n totalBaselineSymbols: totalBaseline,\n preservedSymbols: preserved,\n violations,\n additions,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Internal helpers (legacy)\n// ---------------------------------------------------------------------------\n\nfunction signaturesMatch(baseline: ApiMethod, candidate: ApiMethod): boolean {\n if (baseline.returnType !== candidate.returnType) return false;\n for (let i = 0; i < baseline.params.length; i++) {\n const baseParam = baseline.params[i];\n const candParam = candidate.params[i];\n if (!candParam) return false;\n if (baseParam.type !== candParam.type) return false;\n if (baseParam.name !== candParam.name) return false;\n }\n for (let i = baseline.params.length; i < candidate.params.length; i++) {\n if (!candidate.params[i].optional) return false;\n }\n return true;\n}\n\nfunction formatSignature(method: ApiMethod): string {\n const params = method.params.map((p) => `${p.name}${p.optional ? '?' : ''}: ${p.type}`).join(', ');\n return `(${params}) => ${method.returnType}`;\n}\n","/**\n * Conceptual change grouping for cross-language compatibility analysis.\n *\n * Groups related changes across languages into a single conceptual change\n * with per-language severity. This allows reports to say \"parameter rename\n * on Authorization.check is breaking in PHP, Python, Kotlin, and .NET but\n * soft-risk in Go\" rather than treating these as unrelated per-language findings.\n */\n\nimport type { LanguageId } from './ir.js';\nimport type { CompatChangeSeverity, CompatChangeCategory } from './config.js';\nimport type { CompatDiffResult } from './differ.js';\n\n/** A conceptual change with per-language severity. */\nexport interface ConceptualChange {\n /** Deterministic ID from symbol + category + match details. */\n id: string;\n /** IR-level symbol path (language-neutral). */\n symbol: string;\n /** The kind of change. */\n category: CompatChangeCategory;\n /** Per-language severity mapping. */\n impact: Partial<Record<LanguageId, CompatChangeSeverity>>;\n /** Human-readable description (from first language that reported it). */\n message: string;\n /** Old state details. */\n old: Record<string, string>;\n /** New state details. */\n new: Record<string, string>;\n}\n\n/** Cross-language conceptual rollup. */\nexport interface ConceptualRollup {\n conceptualChanges: ConceptualChange[];\n}\n\n/**\n * Group classified changes from multiple languages into conceptual changes.\n *\n * Changes are grouped by their `conceptualChangeId` — a deterministic ID\n * derived from the symbol, category, and match details. Changes with the\n * same ID across different languages represent the same conceptual change.\n */\nexport function buildConceptualRollup(\n perLanguageResults: Array<{ diff: CompatDiffResult; language: LanguageId }>,\n): ConceptualRollup {\n const grouped = new Map<string, ConceptualChange>();\n\n for (const { diff: result, language } of perLanguageResults) {\n for (const change of result.changes) {\n const existing = grouped.get(change.conceptualChangeId);\n if (existing) {\n existing.impact[language] = change.severity;\n } else {\n grouped.set(change.conceptualChangeId, {\n id: change.conceptualChangeId,\n symbol: change.symbol,\n category: change.category,\n impact: { [language]: change.severity },\n message: change.message,\n old: change.old,\n new: change.new,\n });\n }\n }\n }\n\n return {\n conceptualChanges: [...grouped.values()],\n };\n}\n\n/** Get the highest severity across all languages for a conceptual change. */\nexport function highestSeverity(change: ConceptualChange): CompatChangeSeverity {\n const severities = Object.values(change.impact);\n if (severities.includes('breaking')) return 'breaking';\n if (severities.includes('soft-risk')) return 'soft-risk';\n return 'additive';\n}\n\n/** Count conceptual changes by highest severity. */\nexport function summarizeConceptualChanges(rollup: ConceptualRollup): {\n breaking: number;\n softRisk: number;\n additive: number;\n} {\n let breaking = 0;\n let softRisk = 0;\n let additive = 0;\n for (const change of rollup.conceptualChanges) {\n const sev = highestSeverity(change);\n if (sev === 'breaking') breaking++;\n else if (sev === 'soft-risk') softRisk++;\n else additive++;\n }\n return { breaking, softRisk, additive };\n}\n","/**\n * Report generation for compatibility verification.\n *\n * Produces machine-readable JSON reports, human-readable terminal summaries,\n * and conceptual cross-language summaries.\n */\n\nimport type { LanguageId } from './ir.js';\nimport type { CompatChangeSeverity, CompatChangeCategory, CompatProvenance } from './config.js';\nimport type { CompatDiffResult } from './differ.js';\nimport { buildConceptualRollup, highestSeverity, summarizeConceptualChanges } from './concepts.js';\n\n// ---------------------------------------------------------------------------\n// Machine-readable report\n// ---------------------------------------------------------------------------\n\n/** Machine-readable compat report for a single language. */\nexport interface CompatReport {\n schemaVersion: string;\n language: string;\n summary: {\n breaking: number;\n softRisk: number;\n additive: number;\n };\n changes: CompatReportChange[];\n}\n\n/** A single change entry in the machine-readable report. */\nexport interface CompatReportChange {\n severity: CompatChangeSeverity;\n category: CompatChangeCategory;\n symbol: string;\n conceptualChangeId: string;\n provenance: CompatProvenance;\n old: Record<string, string>;\n new: Record<string, string>;\n message?: string;\n}\n\n/** Generate a machine-readable compat report from a diff result. */\nexport function generateReport(diff: CompatDiffResult, language?: string): CompatReport {\n return {\n schemaVersion: '1',\n language: language ?? 'unknown',\n summary: diff.summary,\n changes: diff.changes.map((c) => ({\n severity: c.severity,\n category: c.category,\n symbol: c.symbol,\n conceptualChangeId: c.conceptualChangeId,\n provenance: c.provenance,\n old: c.old,\n new: c.new,\n ...(c.message ? { message: c.message } : {}),\n })),\n };\n}\n\n// ---------------------------------------------------------------------------\n// Human-readable terminal summary\n// ---------------------------------------------------------------------------\n\n/** Generate a human-readable summary string for terminal output. */\nexport function formatHumanSummary(diff: CompatDiffResult, opts?: { explain?: boolean; language?: string }): string {\n const lines: string[] = [];\n\n lines.push(`Compat report${opts?.language ? ` for ${opts.language}` : ''}:`);\n lines.push(\n ` ${diff.summary.breaking} breaking, ${diff.summary.softRisk} soft-risk, ${diff.summary.additive} additive`,\n );\n\n if (diff.changes.length === 0) {\n lines.push(' No compatibility changes detected.');\n return lines.join('\\n');\n }\n\n // Group by severity for display\n const breaking = diff.changes.filter((c) => c.severity === 'breaking');\n const softRisk = diff.changes.filter((c) => c.severity === 'soft-risk');\n const additive = diff.changes.filter((c) => c.severity === 'additive');\n\n if (breaking.length > 0) {\n lines.push('');\n lines.push(' Breaking:');\n for (const c of breaking) {\n lines.push(` [${c.category}] ${c.symbol} — ${c.message}`);\n if (opts?.explain && c.provenance !== 'unknown') {\n lines.push(` provenance: ${c.provenance}`);\n }\n }\n }\n\n if (softRisk.length > 0) {\n lines.push('');\n lines.push(' Soft-risk:');\n for (const c of softRisk) {\n lines.push(` [${c.category}] ${c.symbol} — ${c.message}`);\n if (opts?.explain && c.provenance !== 'unknown') {\n lines.push(` provenance: ${c.provenance}`);\n }\n }\n }\n\n if (additive.length > 0) {\n lines.push('');\n lines.push(` Additive: ${additive.length} new symbol(s)`);\n }\n\n return lines.join('\\n');\n}\n\n// ---------------------------------------------------------------------------\n// Conceptual cross-language summary\n// ---------------------------------------------------------------------------\n\n/** Conceptual cross-language report. */\nexport interface ConceptualReport {\n conceptualChanges: {\n id: string;\n symbol: string;\n category: CompatChangeCategory;\n impact: Partial<Record<LanguageId, CompatChangeSeverity>>;\n }[];\n}\n\n/** Generate a conceptual cross-language report from multiple per-language results. */\nexport function generateConceptualReport(\n perLanguageResults: Array<{ diff: CompatDiffResult; language: LanguageId }>,\n): ConceptualReport {\n const rollup = buildConceptualRollup(perLanguageResults);\n return {\n conceptualChanges: rollup.conceptualChanges.map((c) => ({\n id: c.id,\n symbol: c.symbol,\n category: c.category,\n impact: c.impact,\n })),\n };\n}\n\n/** Format a conceptual cross-language summary for terminal output. */\nexport function formatConceptualSummary(\n perLanguageResults: Array<{ diff: CompatDiffResult; language: LanguageId }>,\n): string {\n const rollup = buildConceptualRollup(perLanguageResults);\n const summary = summarizeConceptualChanges(rollup);\n const lines: string[] = [];\n\n lines.push('Cross-language conceptual summary:');\n lines.push(` ${summary.breaking} breaking, ${summary.softRisk} soft-risk, ${summary.additive} additive`);\n\n if (rollup.conceptualChanges.length === 0) {\n lines.push(' No cross-language changes.');\n return lines.join('\\n');\n }\n\n for (const change of rollup.conceptualChanges) {\n const sev = highestSeverity(change);\n const impactStr = Object.entries(change.impact)\n .map(([lang, s]) => `${lang}: ${s}`)\n .join(', ');\n lines.push(` [${sev}] ${change.category}: ${change.symbol}`);\n lines.push(` impact: ${impactStr}`);\n }\n\n return lines.join('\\n');\n}\n","import { readFileSync, writeFileSync } from 'node:fs';\nimport { validateSnapshot } from '../compat/schema.js';\nimport { diffSnapshots } from '../compat/differ.js';\nimport { generateReport, formatHumanSummary } from '../compat/report.js';\nimport { severityMeetsThreshold } from '../compat/config.js';\nimport type { CompatFailLevel } from '../compat/config.js';\nimport type { CompatSnapshot } from '../compat/ir.js';\n\nexport async function compatDiffCommand(opts: {\n baseline: string;\n candidate: string;\n output?: string;\n failOn?: string;\n explain?: boolean;\n}): Promise<void> {\n const baselineData = JSON.parse(readFileSync(opts.baseline, 'utf-8'));\n const candidateData = JSON.parse(readFileSync(opts.candidate, 'utf-8'));\n\n if (!validateSnapshot(baselineData)) {\n throw new Error(`Invalid baseline snapshot: ${opts.baseline}`);\n }\n if (!validateSnapshot(candidateData)) {\n throw new Error(`Invalid candidate snapshot: ${opts.candidate}`);\n }\n\n const baseline = baselineData as CompatSnapshot;\n const candidate = candidateData as CompatSnapshot;\n\n const diff = diffSnapshots(baseline, candidate);\n\n // Human-readable output to terminal\n console.log(formatHumanSummary(diff, { explain: opts.explain }));\n\n // Machine-readable output to file\n if (opts.output) {\n const report = generateReport(diff);\n writeFileSync(opts.output, JSON.stringify(report, null, 2));\n console.log(`Report written to ${opts.output}`);\n }\n\n // Fail if threshold exceeded\n const failOn = (opts.failOn ?? 'breaking') as CompatFailLevel;\n const hasFailure = diff.changes.some((c) => severityMeetsThreshold(c.severity, failOn));\n if (hasFailure) {\n process.exitCode = 1;\n }\n}\n","import { readFileSync, writeFileSync } from 'node:fs';\nimport type { CompatReport, CompatReportChange } from '../compat/report.js';\nimport type { CompatDiffResult } from '../compat/differ.js';\nimport type { LanguageId } from '../compat/ir.js';\nimport type { CompatChangeSeverity } from '../compat/config.js';\nimport { buildConceptualRollup, highestSeverity, summarizeConceptualChanges } from '../compat/concepts.js';\n\n/**\n * Format compat report(s) as a markdown PR comment.\n *\n * Single report:\n * oagen compat-summary --report node-report.json | gh pr comment --body-file -\n *\n * Multiple reports (cross-language rollup):\n * oagen compat-summary --report php.json --report python.json --report go.json\n */\nexport async function compatSummaryCommand(opts: { report: string | string[]; output?: string }): Promise<void> {\n const paths = Array.isArray(opts.report) ? opts.report : [opts.report];\n const reports = paths.map((p) => JSON.parse(readFileSync(p, 'utf-8')) as CompatReport);\n\n const md = reports.length === 1 ? formatSingleReport(reports[0]) : formatCrossLanguageRollup(reports);\n\n if (opts.output) {\n writeFileSync(opts.output, md);\n console.log(`Summary written to ${opts.output}`);\n } else {\n process.stdout.write(md);\n }\n}\n\n// ---------------------------------------------------------------------------\n// Single-language report\n// ---------------------------------------------------------------------------\n\nfunction formatSingleReport(report: CompatReport): string {\n const lines: string[] = [];\n const { breaking, softRisk, additive } = report.summary;\n const total = breaking + softRisk + additive;\n\n if (breaking > 0) {\n lines.push(`## :x: Compat check failed — ${report.language}`);\n } else if (softRisk > 0) {\n lines.push(`## :warning: Compat check has warnings — ${report.language}`);\n } else {\n lines.push(`## :white_check_mark: Compat check passed — ${report.language}`);\n }\n\n lines.push('');\n lines.push('| Severity | Count |');\n lines.push('| --- | --- |');\n lines.push(`| Breaking | ${breaking} |`);\n lines.push(`| Soft-risk | ${softRisk} |`);\n lines.push(`| Additive | ${additive} |`);\n lines.push(`| **Total** | **${total}** |`);\n\n if (total === 0) {\n lines.push('');\n lines.push('No compatibility changes detected.');\n return lines.join('\\n') + '\\n';\n }\n\n const breakingChanges = report.changes.filter((c) => c.severity === 'breaking');\n if (breakingChanges.length > 0) {\n lines.push('');\n lines.push('### Breaking changes');\n lines.push('');\n lines.push(formatChangesTable(breakingChanges));\n }\n\n const softRiskChanges = report.changes.filter((c) => c.severity === 'soft-risk');\n if (softRiskChanges.length > 0) {\n lines.push('');\n lines.push('<details>');\n lines.push(`<summary>Soft-risk changes (${softRiskChanges.length})</summary>`);\n lines.push('');\n lines.push(formatChangesTable(softRiskChanges));\n lines.push('</details>');\n }\n\n const additiveChanges = report.changes.filter((c) => c.severity === 'additive');\n if (additiveChanges.length > 0) {\n lines.push('');\n lines.push('<details>');\n lines.push(`<summary>Additive changes (${additiveChanges.length})</summary>`);\n lines.push('');\n lines.push(formatChangesTable(additiveChanges));\n lines.push('</details>');\n }\n\n return lines.join('\\n') + '\\n';\n}\n\n// ---------------------------------------------------------------------------\n// Cross-language rollup\n// ---------------------------------------------------------------------------\n\nfunction formatCrossLanguageRollup(reports: CompatReport[]): string {\n const languages = reports.map((r) => r.language);\n\n // Convert reports to the shape buildConceptualRollup expects\n const perLanguage = reports.map((r) => ({\n diff: { changes: r.changes, summary: r.summary } as CompatDiffResult,\n language: r.language as LanguageId,\n }));\n const rollup = buildConceptualRollup(perLanguage);\n const summary = summarizeConceptualChanges(rollup);\n\n const lines: string[] = [];\n\n // Header\n if (summary.breaking > 0) {\n lines.push(`## :x: Compat check failed — ${summary.breaking} breaking across ${languages.length} languages`);\n } else if (summary.softRisk > 0) {\n lines.push(\n `## :warning: Compat check has warnings — ${summary.softRisk} soft-risk across ${languages.length} languages`,\n );\n } else {\n lines.push(`## :white_check_mark: Compat check passed — ${languages.length} languages`);\n }\n\n lines.push('');\n\n // Per-language summary table\n lines.push('| Language | Breaking | Soft-risk | Additive |');\n lines.push('| --- | --- | --- | --- |');\n for (const r of reports) {\n lines.push(`| ${r.language} | ${r.summary.breaking} | ${r.summary.softRisk} | ${r.summary.additive} |`);\n }\n\n if (rollup.conceptualChanges.length === 0) {\n lines.push('');\n lines.push('No compatibility changes detected.');\n return lines.join('\\n') + '\\n';\n }\n\n // Conceptual changes table with per-language severity\n const breakingConcepts = rollup.conceptualChanges.filter((c) => highestSeverity(c) === 'breaking');\n if (breakingConcepts.length > 0) {\n lines.push('');\n lines.push('### Breaking changes');\n lines.push('');\n lines.push(formatConceptualTable(breakingConcepts, languages));\n }\n\n const softRiskConcepts = rollup.conceptualChanges.filter((c) => highestSeverity(c) === 'soft-risk');\n if (softRiskConcepts.length > 0) {\n lines.push('');\n lines.push('<details>');\n lines.push(`<summary>Soft-risk changes (${softRiskConcepts.length})</summary>`);\n lines.push('');\n lines.push(formatConceptualTable(softRiskConcepts, languages));\n lines.push('</details>');\n }\n\n const additiveConcepts = rollup.conceptualChanges.filter((c) => highestSeverity(c) === 'additive');\n if (additiveConcepts.length > 0) {\n lines.push('');\n lines.push('<details>');\n lines.push(`<summary>Additive changes (${additiveConcepts.length})</summary>`);\n lines.push('');\n lines.push(formatConceptualTable(additiveConcepts, languages));\n lines.push('</details>');\n }\n\n return lines.join('\\n') + '\\n';\n}\n\nfunction formatConceptualTable(\n concepts: Array<{ symbol: string; category: string; impact: Partial<Record<string, CompatChangeSeverity>> }>,\n languages: string[],\n): string {\n const lines: string[] = [];\n const langHeaders = languages.map((l) => l).join(' | ');\n lines.push(`| Symbol | Category | ${langHeaders} |`);\n lines.push(`| --- | --- | ${languages.map(() => '---').join(' | ')} |`);\n for (const c of concepts) {\n const severities = languages.map((l) => severityIcon(c.impact[l])).join(' | ');\n lines.push(`| \\`${c.symbol}\\` | \\`${c.category}\\` | ${severities} |`);\n }\n return lines.join('\\n');\n}\n\nfunction severityIcon(severity: CompatChangeSeverity | undefined): string {\n if (!severity) return '—';\n switch (severity) {\n case 'breaking':\n return ':x: breaking';\n case 'soft-risk':\n return ':warning: soft-risk';\n case 'additive':\n return ':white_check_mark: additive';\n }\n}\n\n// ---------------------------------------------------------------------------\n// Shared helpers\n// ---------------------------------------------------------------------------\n\nfunction formatChangesTable(changes: CompatReportChange[]): string {\n const lines: string[] = [];\n lines.push('| Category | Symbol | Detail |');\n lines.push('| --- | --- | --- |');\n for (const c of changes) {\n const detail = c.message ?? formatOldNew(c.old, c.new);\n lines.push(`| \\`${c.category}\\` | \\`${c.symbol}\\` | ${escapeMarkdown(detail)} |`);\n }\n return lines.join('\\n');\n}\n\nfunction formatOldNew(old: Record<string, string>, updated: Record<string, string>): string {\n const parts: string[] = [];\n for (const key of Object.keys(old)) {\n if (updated[key] && old[key] !== updated[key]) {\n parts.push(`${key}: \\`${old[key]}\\` → \\`${updated[key]}\\``);\n }\n }\n return parts.length > 0 ? parts.join(', ') : '';\n}\n\nfunction escapeMarkdown(text: string): string {\n return text.replace(/\\|/g, '\\\\|').replace(/\\n/g, ' ');\n}\n","/**\n * Approval matching engine for compatibility verification.\n *\n * Matches CompatApproval entries from oagen.config.ts against classified\n * changes. Approved changes are excluded from failure thresholds.\n *\n * Approvals must be narrow (one symbol, one category, one conceptual change).\n * Overly broad approvals are rejected at validation time.\n */\n\nimport type { LanguageId } from './ir.js';\nimport type { CompatApproval } from './config.js';\nimport type { ClassifiedChange } from './classify.js';\n\n/** Result of matching a change against approvals. */\nexport interface ApprovalMatch {\n /** The change that was matched. */\n change: ClassifiedChange;\n /** The approval that matched. null if no approval covers this change. */\n approval: CompatApproval | null;\n /** Whether the change is covered by an approval. */\n approved: boolean;\n}\n\n/** Result of validating an approval for broadness. */\nexport interface ApprovalValidation {\n valid: boolean;\n errors: string[];\n}\n\n// ---------------------------------------------------------------------------\n// Validation\n// ---------------------------------------------------------------------------\n\n/** Validate that an approval is narrow enough to be accepted. */\nexport function validateApproval(approval: CompatApproval): ApprovalValidation {\n const errors: string[] = [];\n\n if (!approval.symbol || approval.symbol.trim() === '') {\n errors.push('Approval must target a specific symbol');\n }\n\n if (!approval.category) {\n errors.push('Approval must specify a change category');\n }\n\n if (!approval.reason || approval.reason.trim() === '') {\n errors.push('Approval must include a reason');\n }\n\n // Wildcard symbols are too broad\n if (approval.symbol === '*' || approval.symbol.endsWith('.*') || approval.symbol.endsWith('::*')) {\n errors.push(`Approval symbol \"${approval.symbol}\" is too broad — must target a specific symbol`);\n }\n\n return {\n valid: errors.length === 0,\n errors,\n };\n}\n\n/** Validate all approvals in a config. Returns errors keyed by index. */\nexport function validateApprovals(approvals: CompatApproval[]): Map<number, string[]> {\n const result = new Map<number, string[]>();\n for (let i = 0; i < approvals.length; i++) {\n const validation = validateApproval(approvals[i]);\n if (!validation.valid) {\n result.set(i, validation.errors);\n }\n }\n return result;\n}\n\n// ---------------------------------------------------------------------------\n// Matching\n// ---------------------------------------------------------------------------\n\n/**\n * Match a classified change against a list of approvals.\n * Returns the first matching approval, or null if none match.\n */\nexport function matchApproval(\n change: ClassifiedChange,\n approvals: CompatApproval[],\n language: LanguageId,\n): CompatApproval | null {\n for (const approval of approvals) {\n if (approvalMatchesChange(approval, change, language)) {\n return approval;\n }\n }\n return null;\n}\n\n/**\n * Apply approvals to a list of changes.\n * Returns matches for every change (approved or not).\n */\nexport function applyApprovals(\n changes: ClassifiedChange[],\n approvals: CompatApproval[],\n language: LanguageId,\n): ApprovalMatch[] {\n return changes.map((change) => {\n const approval = matchApproval(change, approvals, language);\n return {\n change,\n approval,\n approved: approval !== null,\n };\n });\n}\n\n/**\n * Filter changes to only those NOT covered by approvals.\n * These are the remaining unapproved changes that may cause failure.\n */\nexport function unapprovedChanges(\n changes: ClassifiedChange[],\n approvals: CompatApproval[],\n language: LanguageId,\n): ClassifiedChange[] {\n return changes.filter((change) => !matchApproval(change, approvals, language));\n}\n\n// ---------------------------------------------------------------------------\n// Internal matching logic\n// ---------------------------------------------------------------------------\n\nfunction approvalMatchesChange(approval: CompatApproval, change: ClassifiedChange, language: LanguageId): boolean {\n // Skip inactive approvals\n if (approval.approved === false) return false;\n\n // Category must match exactly\n if (approval.category !== change.category) return false;\n\n // Symbol must match\n if (!symbolMatches(approval.symbol, change.symbol)) return false;\n\n // Language scoping\n if (!languageMatches(approval.appliesTo, language)) return false;\n\n // Narrowing match (optional)\n if (approval.match && !narrowingMatches(approval.match, change)) return false;\n\n return true;\n}\n\nfunction symbolMatches(approvalSymbol: string, changeSymbol: string): boolean {\n // Exact match\n if (approvalSymbol === changeSymbol) return true;\n\n // Normalize common separators for cross-language matching\n // PHP uses :: and \\, others use . — normalize to dots for comparison\n const normalizedApproval = approvalSymbol.replace(/::/g, '.').replace(/\\\\/g, '.');\n const normalizedChange = changeSymbol.replace(/::/g, '.').replace(/\\\\/g, '.');\n return normalizedApproval === normalizedChange;\n}\n\nfunction languageMatches(appliesTo: CompatApproval['appliesTo'], language: LanguageId): boolean {\n if (!appliesTo || appliesTo === 'all-impacted-languages') return true;\n return appliesTo.includes(language);\n}\n\nfunction narrowingMatches(match: NonNullable<CompatApproval['match']>, change: ClassifiedChange): boolean {\n if (match.parameter) {\n // Check if the change involves this parameter\n const paramInOld = change.old.parameter === match.parameter;\n const paramInNew = change.new.parameter === match.parameter;\n if (!paramInOld && !paramInNew) return false;\n }\n if (match.member) {\n const memberInOld = change.old.member === match.member;\n const memberInNew = change.new.member === match.member;\n if (!memberInOld && !memberInNew) return false;\n }\n if (match.oldName) {\n const nameMatch = Object.values(change.old).some((v) => v === match.oldName);\n if (!nameMatch) return false;\n }\n if (match.newName) {\n const nameMatch = Object.values(change.new).some((v) => v === match.newName);\n if (!nameMatch) return false;\n }\n return true;\n}\n","import { getExtractor } from '../compat/extractor-registry.js';\nimport {\n diffSnapshots,\n specDerivedNames,\n specDerivedFieldPaths,\n specDerivedMethodPaths,\n specDerivedEnumValues,\n filterSurface,\n} from '../compat/differ.js';\nimport { apiSurfaceToSnapshot } from '../compat/ir.js';\nimport type { LanguageId } from '../compat/ir.js';\nimport { getDefaultPolicy, mergePolicy } from '../compat/policy.js';\nimport type { CompatPolicyHints } from '../compat/policy.js';\nimport type { ApiSpec } from '../ir/types.js';\nimport type { ApiSurface } from '../compat/types.js';\nimport type { CompatCheckResult } from './types.js';\n\nexport async function runCompatCheck(\n baseline: ApiSurface,\n outputDir: string,\n lang: string,\n spec?: ApiSpec,\n policyOverrides?: Partial<CompatPolicyHints>,\n): Promise<CompatCheckResult> {\n const extractor = getExtractor(lang);\n const candidate = await extractor.extract(outputDir);\n\n let scopedBaseline = baseline;\n let scopedToSpec = false;\n let scopedSymbolCount: number | undefined;\n if (spec) {\n const allowed = specDerivedNames(spec, extractor.hints);\n const fieldPaths = specDerivedFieldPaths(spec, extractor.hints);\n const methodPaths = specDerivedMethodPaths(spec);\n const enumVals = specDerivedEnumValues(spec);\n scopedBaseline = filterSurface(baseline, allowed, { fieldPaths, methodPaths, enumValues: enumVals });\n scopedToSpec = true;\n scopedSymbolCount =\n Object.keys(scopedBaseline.interfaces).length +\n Object.keys(scopedBaseline.classes).length +\n Object.keys(scopedBaseline.typeAliases).length +\n Object.keys(scopedBaseline.enums).length;\n }\n\n const baseSnap = apiSurfaceToSnapshot(scopedBaseline);\n const candSnap = apiSurfaceToSnapshot(candidate);\n\n const langId = lang as LanguageId;\n const policy = policyOverrides ? mergePolicy(getDefaultPolicy(langId), policyOverrides) : getDefaultPolicy(langId);\n\n const diff = diffSnapshots(baseSnap, candSnap, policy);\n const passed = diff.changes.every((c) => c.severity !== 'breaking');\n\n return { passed, diff, scopedToSpec, scopedSymbolCount };\n}\n","import { readdirSync, unlinkSync, statSync, openSync, readSync, closeSync } from 'node:fs';\nimport * as path from 'node:path';\nimport { buildOverlayLookup, patchOverlay, isPatchableChange } from '../compat/overlay.js';\nimport { getExtractor } from '../compat/extractor-registry.js';\nimport type { ApiSurface } from '../compat/types.js';\nimport type { ApiSpec } from '../ir/types.js';\nimport { getEmitter } from '../engine/registry.js';\nimport { generate } from '../engine/orchestrator.js';\nimport { runCompatCheck } from './run-compat-check.js';\nimport type { OverlayRetryResult } from './types.js';\nimport { readManifestSync } from '../engine/manifest-reader.js';\n\n/** Generated file header markers used by various emitters. */\nconst GENERATED_MARKERS = ['Code generated by oagen', 'auto-generated by oagen', 'This file is auto-generated'];\n\n/**\n * Delete oagen-generated source files so the retry loop can regenerate them\n * with overlay-corrected names. Only deletes files that contain an oagen\n * generation marker, preserving hand-written files.\n */\nfunction cleanGeneratedFiles(dir: string): void {\n let entries: string[];\n try {\n entries = readdirSync(dir);\n } catch {\n return;\n }\n for (const entry of entries) {\n const full = path.join(dir, entry);\n let stat;\n try {\n stat = statSync(full);\n } catch {\n continue;\n }\n if (stat.isDirectory()) {\n cleanGeneratedFiles(full);\n continue;\n }\n // Skip non-source files and manifests\n if (entry.endsWith('.json') || entry.endsWith('.lock')) continue;\n // Read only the first 200 bytes to check for generation marker\n try {\n const buf = Buffer.alloc(200);\n const fd = openSync(full, 'r');\n try {\n readSync(fd, buf, 0, 200, 0);\n } finally {\n closeSync(fd);\n }\n const header = buf.toString('utf-8');\n if (GENERATED_MARKERS.some((m) => header.includes(m))) {\n unlinkSync(full);\n }\n } catch {\n // ignore read/delete errors\n }\n }\n}\n\nexport async function runOverlayRetryLoop(opts: {\n baseline: ApiSurface;\n parsedSpec: ApiSpec;\n outputDir: string;\n lang: string;\n maxRetries: number;\n namespace?: string;\n onRetry?: (attemptNumber: number, maxRetries: number, patchableCount: number) => void;\n}): Promise<OverlayRetryResult> {\n const { baseline, parsedSpec, outputDir, lang, maxRetries, namespace, onRetry } = opts;\n\n const manifest = readManifestSync(outputDir);\n // Pass language-specific hints so property-to-class matching works correctly\n // (e.g., Ruby snake_case \"api_keys\" → PascalCase \"ApiKeys\").\n const extractor = getExtractor(lang);\n let overlay = buildOverlayLookup(baseline, manifest, parsedSpec, extractor.hints);\n let prevPreserved = -1;\n const patchedPerIteration: number[] = [];\n\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n const compatResult = await runCompatCheck(baseline, outputDir, lang, parsedSpec);\n if (compatResult.passed) {\n return {\n status: 'passed',\n attempts: attempt,\n patchedPerIteration,\n compatResult,\n };\n }\n\n if (attempt === maxRetries) {\n return {\n status: 'max-retries',\n attempts: attempt,\n patchedPerIteration,\n compatResult,\n };\n }\n\n const patchable = compatResult.diff.changes.filter(isPatchableChange);\n if (patchable.length === 0) {\n return {\n status: 'no-patchable',\n attempts: attempt,\n patchedPerIteration,\n compatResult,\n };\n }\n\n const currentBreaking = compatResult.diff.summary.breaking;\n // Stall detection: if breaking count hasn't decreased, we're not making progress\n if (attempt > 0 && currentBreaking >= prevPreserved) {\n return {\n status: 'stalled',\n attempts: attempt,\n patchedPerIteration,\n compatResult,\n };\n }\n prevPreserved = currentBreaking;\n patchedPerIteration.push(patchable.length);\n onRetry?.(attempt + 1, maxRetries, patchable.length);\n\n overlay = patchOverlay(overlay, patchable, baseline);\n\n // Pre-delete generated source files so the writer creates them fresh\n // with overlay-corrected names. Without this, the AST merger would preserve\n // old method/class names from the existing files.\n // Only delete files that look like oagen-generated source files (have the header).\n cleanGeneratedFiles(outputDir);\n\n const emitter = getEmitter(lang);\n await generate(parsedSpec, emitter, {\n namespace: namespace ?? parsedSpec.name,\n outputDir,\n overlayLookup: overlay,\n apiSurface: baseline,\n });\n }\n\n const compatResult = await runCompatCheck(baseline, outputDir, lang, parsedSpec);\n return {\n status: 'max-retries',\n attempts: maxRetries,\n patchedPerIteration,\n compatResult,\n };\n}\n","import type { ApiSurface, LanguageHints, Violation } from './types.js';\nimport type { ApiSpec } from '../ir/types.js';\nimport { specDerivedNames, specDerivedFieldPaths } from './spec-filter.js';\nimport { diffSpecs } from '../differ/diff.js';\n\n/**\n * Detect symbols that exist in the live SDK surface but are no longer defined\n * in the current OpenAPI spec. These are \"stale\" — they compile and run but\n * represent dead code from a previous spec version.\n *\n * Requires both the old and new spec so we can distinguish hand-written SDK\n * symbols (never in any spec) from genuinely removed spec symbols.\n */\nexport function detectStaleSymbols(\n liveSurface: ApiSurface,\n oldSpec: ApiSpec,\n newSpec: ApiSpec,\n hints: LanguageHints,\n): Violation[] {\n const violations: Violation[] = [];\n\n // Step 1-3: Name-set difference for top-level symbols\n const oldNames = specDerivedNames(oldSpec, hints);\n const newNames = specDerivedNames(newSpec, hints);\n\n const removedNames = new Set<string>();\n for (const name of oldNames) {\n if (!newNames.has(name)) removedNames.add(name);\n }\n\n for (const name of removedNames) {\n if (liveSurface.classes[name]) {\n violations.push({\n category: 'staleness',\n severity: 'warning',\n symbolPath: name,\n baseline: name,\n candidate: '(removed from spec)',\n message: `Class \"${name}\" is no longer defined in the OpenAPI spec`,\n });\n }\n if (liveSurface.interfaces[name]) {\n violations.push({\n category: 'staleness',\n severity: 'warning',\n symbolPath: name,\n baseline: name,\n candidate: '(removed from spec)',\n message: `Interface \"${name}\" is no longer defined in the OpenAPI spec`,\n });\n }\n if (liveSurface.typeAliases[name]) {\n violations.push({\n category: 'staleness',\n severity: 'warning',\n symbolPath: name,\n baseline: name,\n candidate: '(removed from spec)',\n message: `Type alias \"${name}\" is no longer defined in the OpenAPI spec`,\n });\n }\n if (liveSurface.enums[name]) {\n violations.push({\n category: 'staleness',\n severity: 'warning',\n symbolPath: name,\n baseline: name,\n candidate: '(removed from spec)',\n message: `Enum \"${name}\" is no longer defined in the OpenAPI spec`,\n });\n }\n }\n\n // Step 4-6: Field-level staleness for models that still exist in new spec\n const oldFieldPaths = specDerivedFieldPaths(oldSpec, hints);\n const newFieldPaths = specDerivedFieldPaths(newSpec, hints);\n\n for (const fieldPath of oldFieldPaths) {\n if (newFieldPaths.has(fieldPath)) continue;\n\n const [modelName, fieldName] = fieldPath.split('.');\n // Only flag field-level staleness for models that still exist in the new spec\n // (fully removed models are already caught above)\n if (removedNames.has(modelName)) continue;\n\n const iface = liveSurface.interfaces[modelName];\n if (iface?.fields[fieldName]) {\n violations.push({\n category: 'staleness',\n severity: 'warning',\n symbolPath: fieldPath,\n baseline: fieldName,\n candidate: '(removed from spec)',\n message: `Field \"${fieldPath}\" is no longer defined in the OpenAPI spec`,\n });\n }\n }\n\n // Step 7: Operation-level staleness via diffSpecs\n const diff = diffSpecs(oldSpec, newSpec);\n for (const change of diff.changes) {\n if (change.kind === 'operation-removed') {\n const cls = liveSurface.classes[change.serviceName];\n if (cls?.methods[change.operationName]) {\n violations.push({\n category: 'staleness',\n severity: 'warning',\n symbolPath: `${change.serviceName}.${change.operationName}`,\n baseline: change.operationName,\n candidate: '(removed from spec)',\n message: `Method \"${change.serviceName}.${change.operationName}\" is no longer defined in the OpenAPI spec`,\n });\n }\n }\n }\n\n return violations;\n}\n","import { getExtractor } from '../compat/extractor-registry.js';\nimport { detectStaleSymbols } from '../compat/staleness.js';\nimport type { ApiSpec } from '../ir/types.js';\nimport type { ApiSurface } from '../compat/types.js';\nimport type { StalenessCheckResult } from './types.js';\n\nexport function runStalenessCheck(\n baseline: ApiSurface,\n oldSpec: ApiSpec,\n newSpec: ApiSpec,\n lang: string,\n): StalenessCheckResult {\n const extractor = getExtractor(lang);\n const violations = detectStaleSymbols(baseline, oldSpec, newSpec, extractor.hints);\n return { violations };\n}\n","import { execFileSync } from 'node:child_process';\nimport { existsSync, readFileSync } from 'node:fs';\nimport { fileURLToPath } from 'node:url';\nimport * as path from 'node:path';\nimport { CommandError } from '../errors.js';\nimport type { SmokeCheckResult } from './types.js';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = path.dirname(__filename);\n\nfunction resolveScript(scriptRelPath: string): { bin: string; script: string } {\n const distScript = path.resolve(__dirname, '..', '..', 'dist', 'scripts', scriptRelPath.replace(/\\.ts$/, '.mjs'));\n if (existsSync(distScript)) {\n return { bin: 'node', script: distScript };\n }\n const srcScript = path.resolve(__dirname, '..', '..', 'scripts', scriptRelPath);\n return { bin: 'npx', script: srcScript };\n}\n\nfunction runPackagedScript(scriptRelPath: string, args: string[]): void {\n const { bin, script } = resolveScript(scriptRelPath);\n const fullArgs = bin === 'npx' ? ['tsx', script, ...args] : [script, ...args];\n execFileSync(bin, fullArgs, { stdio: 'inherit', env: process.env });\n}\n\nexport function runSmokeCheck(opts: {\n spec?: string;\n lang: string;\n output: string;\n rawResults?: string;\n smokeConfig?: string;\n smokeRunner?: string;\n}): SmokeCheckResult {\n const { spec, lang, output, rawResults, smokeConfig, smokeRunner } = opts;\n\n let baselinePath = rawResults ?? 'smoke-results-raw.json';\n let generatedBaseline = false;\n\n if (!rawResults && !existsSync('smoke-results-raw.json')) {\n if (!spec) {\n throw new CommandError(\n 'error: --spec <path> or OPENAPI_SPEC_PATH env var is required when no raw baseline exists',\n '',\n 1,\n );\n }\n\n try {\n runPackagedScript('smoke/baseline.ts', ['--spec', spec]);\n } catch {\n throw new CommandError('Baseline generation failed', '', 1);\n }\n baselinePath = 'smoke-results-spec-baseline.json';\n generatedBaseline = true;\n }\n\n const smokeArgs = ['--lang', lang, '--sdk-path', output, '--raw-results', baselinePath];\n if (spec) smokeArgs.push('--spec', spec);\n if (smokeConfig) smokeArgs.push('--smoke-config', smokeConfig);\n\n try {\n if (smokeRunner) {\n const bin = smokeRunner.endsWith('.ts') ? 'npx' : 'node';\n const fullArgs = bin === 'npx' ? ['tsx', smokeRunner, ...smokeArgs] : [smokeRunner, ...smokeArgs];\n execFileSync(bin, fullArgs, { stdio: 'inherit', env: process.env });\n } else {\n runPackagedScript('smoke/sdk-test.ts', smokeArgs);\n }\n\n return { passed: true, baselinePath, generatedBaseline };\n } catch {\n if (existsSync('smoke-compile-errors.json')) {\n return { passed: false, compileErrors: true, baselinePath, generatedBaseline };\n }\n\n const findingsCount = existsSync('smoke-diff-findings.json')\n ? (JSON.parse(readFileSync('smoke-diff-findings.json', 'utf-8')) as unknown[]).length\n : undefined;\n\n return { passed: false, findingsCount, baselinePath, generatedBaseline };\n }\n}\n","import { writeFileSync } from 'node:fs';\nimport type { VerifyDiagnostics, CompatCheckResult } from './types.js';\n\nexport function summarizeCompatCheck(result: CompatCheckResult): NonNullable<VerifyDiagnostics['compatCheck']> {\n const violationsByCategory: Record<string, number> = {};\n const violationsBySeverity: Record<string, number> = {};\n for (const c of result.diff.changes) {\n violationsByCategory[c.category] = (violationsByCategory[c.category] ?? 0) + 1;\n violationsBySeverity[c.severity] = (violationsBySeverity[c.severity] ?? 0) + 1;\n }\n\n const { breaking, softRisk, additive } = result.diff.summary;\n const totalChanges = breaking + softRisk + additive;\n const totalBaselineSymbols = totalChanges + additive; // approximate; additive are new\n const preservedSymbols = totalBaselineSymbols - breaking - softRisk;\n const preservationScore =\n totalBaselineSymbols > 0 ? Math.round((preservedSymbols / totalBaselineSymbols) * 100) : 100;\n\n return {\n totalBaselineSymbols,\n preservedSymbols,\n preservationScore,\n violationsByCategory,\n violationsBySeverity,\n additions: additive,\n scopedToSpec: result.scopedToSpec,\n ...(result.scopedSymbolCount !== undefined ? { scopedSymbolCount: result.scopedSymbolCount } : {}),\n };\n}\n\nexport function setRetryDiagnostics(\n diagData: VerifyDiagnostics,\n attempt: number,\n converged: boolean,\n finalScore: number,\n patchedPerIteration: number[],\n): void {\n diagData.retryLoop = { attempts: attempt, converged, finalScore, patchedPerIteration };\n}\n\nexport function writeDiagnostics(data: VerifyDiagnostics, filePath: string = 'verify-diagnostics.json'): void {\n writeFileSync(filePath, JSON.stringify(data, null, 2) + '\\n');\n}\n","import { existsSync, readFileSync, writeFileSync } from 'node:fs';\nimport { CommandError } from '../errors.js';\nimport { parseSpec } from '../parser/parse.js';\nimport type { ApiSurface } from '../compat/types.js';\nimport type { CompatConfig, CompatFailLevel } from '../compat/config.js';\nimport { severityMeetsThreshold } from '../compat/config.js';\nimport { generateReport, formatHumanSummary } from '../compat/report.js';\nimport { unapprovedChanges } from '../compat/approvals.js';\nimport type { LanguageId } from '../compat/ir.js';\nimport { runCompatCheck } from '../verify/run-compat-check.js';\nimport { runOverlayRetryLoop } from '../verify/run-overlay-retry-loop.js';\nimport { runStalenessCheck } from '../verify/run-staleness-check.js';\nimport { runSmokeCheck } from '../verify/run-smoke-check.js';\nimport { summarizeCompatCheck, setRetryDiagnostics, writeDiagnostics } from '../verify/write-diagnostics.js';\nimport type { VerifyDiagnostics } from '../verify/types.js';\n\nexport type { VerifyDiagnostics } from '../verify/types.js';\n\nconst separator = '='.repeat(60);\n\nfunction printCompatResult(result: ReturnType<typeof summarizeCompatCheck>, baseline: ApiSurface): void {\n if (result.scopedToSpec) {\n const totalBefore =\n Object.keys(baseline.interfaces).length +\n Object.keys(baseline.classes).length +\n Object.keys(baseline.typeAliases).length +\n Object.keys(baseline.enums).length;\n console.log(`(scoped to spec: ${result.scopedSymbolCount}/${totalBefore} baseline symbols in scope)`);\n }\n\n console.log(\n `compat: ${result.preservationScore}% (${result.preservedSymbols}/${result.totalBaselineSymbols} symbols preserved)`,\n );\n}\n\nexport async function verifyCommand(opts: {\n spec?: string;\n oldSpec?: string;\n lang: string;\n output: string;\n apiSurface?: string;\n rawResults?: string;\n smokeConfig?: string;\n smokeRunner?: string;\n scope?: 'full' | 'spec-only';\n diagnostics?: boolean;\n maxRetries?: number;\n operationIdTransform?: (id: string) => string;\n schemaNameTransform?: (name: string) => string;\n namespace?: string;\n compatConfig?: CompatConfig;\n compatReport?: string;\n compatFailOn?: string;\n compatBaseline?: string;\n compatExplain?: boolean;\n}): Promise<void> {\n const {\n spec,\n oldSpec,\n lang,\n output,\n apiSurface,\n rawResults,\n smokeConfig,\n smokeRunner,\n scope,\n diagnostics,\n operationIdTransform,\n schemaNameTransform,\n compatConfig,\n compatReport,\n compatExplain,\n } = opts;\n const maxRetries = opts.maxRetries ?? 3;\n const diagData: VerifyDiagnostics = {};\n\n // Resolve compat options: CLI flags take precedence over config\n const effectiveFailOn: CompatFailLevel =\n (opts.compatFailOn as CompatFailLevel | undefined) ?? compatConfig?.failOn ?? 'breaking';\n const effectiveReportPath = compatReport ?? compatConfig?.reportPath;\n const effectiveExplain = compatExplain ?? compatConfig?.explain ?? false;\n\n let stepNum = 1;\n const baseline: ApiSurface | undefined = apiSurface\n ? (JSON.parse(readFileSync(apiSurface, 'utf-8')) as ApiSurface)\n : undefined;\n\n if (apiSurface && baseline) {\n console.log(`\\n${separator}`);\n console.log(`Step ${stepNum}: Compat verification`);\n console.log(separator);\n\n const effectiveScope = scope ?? (spec ? 'spec-only' : 'full');\n let parsedSpec;\n if (effectiveScope === 'spec-only' && spec) {\n parsedSpec = await parseSpec(spec, { operationIdTransform, schemaNameTransform });\n } else if (effectiveScope === 'spec-only') {\n throw new CommandError('error: --scope spec-only requires --spec <path>', '', 1);\n }\n\n const compatFlow =\n parsedSpec && maxRetries > 0\n ? await runOverlayRetryLoop({\n baseline,\n parsedSpec,\n outputDir: output,\n lang,\n maxRetries,\n namespace: opts.namespace,\n onRetry: (attemptNumber, retryLimit, patchableCount) => {\n console.log(`\\nRetry ${attemptNumber}/${retryLimit}: patching ${patchableCount} violation(s)...`);\n },\n })\n : {\n status: 'passed' as const,\n attempts: 0,\n patchedPerIteration: [],\n compatResult: await runCompatCheck(baseline, output, lang, parsedSpec),\n };\n\n const compatSummary = summarizeCompatCheck(compatFlow.compatResult);\n printCompatResult(compatSummary, baseline);\n const classifiedDiff = compatFlow.compatResult.diff;\n for (const c of classifiedDiff.changes) {\n if (c.severity !== 'additive') {\n console.log(` [${c.category}] ${c.severity}: ${c.symbol} — ${c.message}`);\n }\n }\n const additiveCount = classifiedDiff.summary.additive;\n if (additiveCount > 0) {\n console.log(` + ${additiveCount} new symbols added`);\n }\n\n if (diagnostics) {\n diagData.compatCheck = compatSummary;\n if (parsedSpec && maxRetries > 0) {\n setRetryDiagnostics(\n diagData,\n compatFlow.attempts,\n compatFlow.status === 'passed',\n compatSummary.preservationScore,\n compatFlow.patchedPerIteration,\n );\n }\n }\n\n if (compatFlow.status === 'passed' && compatFlow.compatResult.passed) {\n if (compatFlow.attempts > 0) {\n console.log(`Compat: converged after ${compatFlow.attempts} retry iteration(s)`);\n } else {\n console.log('Compat: passed');\n }\n } else {\n if (diagnostics) {\n writeDiagnostics(diagData);\n console.log('Diagnostics written to verify-diagnostics.json');\n }\n\n if (compatFlow.status === 'no-patchable') {\n console.log(\n 'No patchable violations — cannot self-correct. Remaining violations require emitter code changes.',\n );\n } else if (compatFlow.status === 'stalled') {\n console.log(`Stalled — overlay patching is not making progress.`);\n }\n\n throw new CommandError('\\nCompat violations found — fix the emitter and re-run `oagen verify`.', '', 1);\n }\n\n // Classified compat analysis — approvals, reports, and explanations\n // The diff is already classified from runCompatCheck/runOverlayRetryLoop\n if (effectiveReportPath || effectiveExplain || (compatConfig?.allow?.length ?? 0) > 0) {\n const langId = lang as LanguageId;\n const approvals = compatConfig?.allow ?? [];\n const remaining = unapprovedChanges(classifiedDiff.changes, approvals, langId);\n const hasFailure = remaining.some((c) => severityMeetsThreshold(c.severity, effectiveFailOn));\n\n if (effectiveExplain) {\n console.log('');\n console.log(formatHumanSummary(classifiedDiff, { explain: true }));\n }\n\n if (effectiveReportPath) {\n const report = generateReport(classifiedDiff);\n writeFileSync(effectiveReportPath, JSON.stringify(report, null, 2) + '\\n');\n console.log(`Compat report written to ${effectiveReportPath}`);\n }\n\n if (hasFailure && effectiveFailOn !== 'none') {\n const unapprovedBreaking = remaining.filter((c) => severityMeetsThreshold(c.severity, effectiveFailOn));\n console.log(`\\n${unapprovedBreaking.length} unapproved change(s) at or above '${effectiveFailOn}' threshold`);\n }\n }\n\n stepNum++;\n }\n\n if (oldSpec && spec && apiSurface && baseline) {\n console.log(`\\n${separator}`);\n console.log(`Step ${stepNum}: Staleness detection`);\n console.log(separator);\n\n const oldParsedSpec = await parseSpec(oldSpec, { operationIdTransform, schemaNameTransform });\n const newParsedSpec = await parseSpec(spec, { operationIdTransform, schemaNameTransform });\n const stalenessResult = runStalenessCheck(baseline, oldParsedSpec, newParsedSpec, lang);\n\n if (stalenessResult.violations.length > 0) {\n console.log(`Found ${stalenessResult.violations.length} stale symbol(s):`);\n for (const v of stalenessResult.violations) {\n console.log(` [${v.category}] ${v.severity}: ${v.symbolPath} — ${v.message}`);\n }\n } else {\n console.log('No stale symbols detected.');\n }\n\n if (diagnostics) {\n diagData.stalenessCheck = {\n staleSymbolCount: stalenessResult.violations.length,\n staleSymbols: stalenessResult.violations.map((v) => v.symbolPath),\n };\n }\n\n stepNum++;\n }\n\n const needsBaselineStep = !rawResults && !existsSync('smoke-results-raw.json');\n if (needsBaselineStep) {\n console.log(`\\n${separator}`);\n console.log(`Step ${stepNum}: Generating spec-only baseline (no raw baseline found)`);\n console.log(separator);\n stepNum++;\n }\n\n console.log(`\\n${separator}`);\n console.log(`Step ${stepNum}: Smoke test + diff`);\n console.log(separator);\n\n const smokeResult = runSmokeCheck({\n spec,\n lang,\n output,\n rawResults,\n smokeConfig,\n smokeRunner,\n });\n\n if (diagnostics) {\n diagData.smokeCheck = {\n passed: smokeResult.passed,\n ...(smokeResult.findingsCount !== undefined ? { findingsCount: smokeResult.findingsCount } : {}),\n ...(smokeResult.compileErrors ? { compileErrors: true } : {}),\n };\n writeDiagnostics(diagData);\n console.log('Diagnostics written to verify-diagnostics.json');\n }\n\n if (!smokeResult.passed) {\n if (smokeResult.compileErrors) {\n throw new CommandError('\\nSDK compile errors — read smoke-compile-errors.json for details', '', 2);\n }\n\n throw new CommandError(\n '\\nSmoke test findings — read smoke-diff-findings.json for details\\n\\n' +\n `Remediation guide (by finding type):\n \"HTTP method differs\" → fix ${lang} emitter resources.ts (in emitter project)\n \"Request path structure differs\" → fix ${lang} emitter resources.ts (in emitter project)\n \"Query parameters differ\" → fix ${lang} emitter resources.ts (in emitter project)\n \"Request body key sets differ\" → fix ${lang} emitter models.ts or resources.ts (in emitter project)\n \"Skipped in SDK\" → fix smoke/sdk-${lang}.ts (in emitter project)\n \"Missing from SDK\" → fix smoke/sdk-${lang}.ts (in emitter project)`,\n '',\n 1,\n );\n }\n\n console.log('\\nVerify: all checks passed');\n}\n","import { toCamelCase } from '../../utils/naming.js';\n\nexport function oagenScripts(lang: string): Record<string, string> {\n return {\n [`sdk:generate:${lang}`]: `oagen generate --lang ${lang} --output ./sdk --namespace my-api --spec open-api-spec.yaml --api-surface ./sdk-${lang}-surface.json --target ../your-${lang}-sdk`,\n [`sdk:diff:${lang}`]: `oagen diff --old ./sdk/spec-snapshot.yaml --new open-api-spec.yaml --lang ${lang} --output ./sdk --target ../your-${lang}-sdk --api-surface ./sdk-${lang}-surface.json`,\n [`sdk:verify:${lang}`]: `oagen verify --lang ${lang} --output ./sdk --spec open-api-spec.yaml --api-surface ./sdk-${lang}-surface.json`,\n [`sdk:extract:${lang}`]: `oagen extract --lang ${lang} --sdk-path ../your-${lang}-sdk --output ./sdk-${lang}-surface.json`,\n };\n}\n\nexport function packageJson(lang: string): string {\n return JSON.stringify(\n {\n name: `custom-oagen-emitters`,\n version: '0.0.1',\n type: 'module',\n main: 'dist/index.js',\n types: 'dist/index.d.ts',\n exports: {\n '.': { types: './dist/index.d.ts', import: './dist/index.js' },\n './plugin': { types: './dist/plugin.d.ts', import: './dist/plugin.js' },\n },\n scripts: {\n build: 'tsup',\n test: 'vitest run',\n 'test:watch': 'vitest',\n typecheck: 'tsc --noEmit',\n ...oagenScripts(lang),\n },\n dependencies: {\n '@workos/oagen': '^0.0.1',\n },\n devDependencies: {\n tsup: '^8.4.0',\n tsx: '^4.19.0',\n vitest: '^3.0.0',\n '@types/node': '^25.3.3',\n },\n },\n null,\n 2,\n );\n}\n\nexport function tsconfigJson(): string {\n return JSON.stringify(\n {\n compilerOptions: {\n target: 'ES2022',\n module: 'ESNext',\n moduleResolution: 'bundler',\n strict: true,\n declaration: true,\n declarationMap: true,\n sourceMap: true,\n outDir: 'dist',\n rootDir: '.',\n esModuleInterop: true,\n skipLibCheck: true,\n forceConsistentCasingInFileNames: true,\n resolveJsonModule: true,\n isolatedModules: true,\n },\n include: ['src', 'test'],\n exclude: ['node_modules', 'dist'],\n },\n null,\n 2,\n );\n}\n\nexport function vitestConfig(): string {\n return `import { defineConfig } from 'vitest/config';\nexport default defineConfig({\n test: { globals: true, include: ['test/**/*.test.ts'] },\n});\n`;\n}\n\nexport function tsupConfig(): string {\n return `import { defineConfig } from 'tsup';\nexport default defineConfig({\n entry: { index: 'src/index.ts', plugin: 'src/plugin.ts' },\n format: ['esm'],\n dts: true,\n clean: true,\n target: 'node20',\n});\n`;\n}\n\nexport function oagenConfig(): string {\n return `import type { OagenConfig } from '@workos/oagen';\nimport { plugin } from './src/plugin.js';\n\n// Minimal config for local emitter development.\n// The canonical consumer config lives in the consumer project's oagen.config.ts,\n// which imports the plugin bundle from this package.\nconst config: OagenConfig = {\n ...plugin,\n};\nexport default config;\n`;\n}\n\nexport function srcPlugin(lang: string): string {\n const varName = `${toCamelCase(lang)}Emitter`;\n return `import type { OagenConfig } from '@workos/oagen';\nimport { ${varName} } from './${lang}/index.js';\n\nexport const plugin: Pick<OagenConfig, 'emitters' | 'extractors' | 'smokeRunners'> = {\n emitters: [${varName}],\n extractors: [],\n smokeRunners: {},\n};\n`;\n}\n\nexport function srcIndex(lang: string): string {\n const varName = `${toCamelCase(lang)}Emitter`;\n return `export { ${varName} } from './${lang}/index.js';\nexport { plugin } from './plugin.js';\n`;\n}\n\nexport function gitignore(): string {\n return `node_modules/\ndist/\n.env\nsdk-*-surface.json\nsmoke-*.json\nsdk/\n`;\n}\n\nexport function stubEmitter(lang: string): string {\n const varName = `${toCamelCase(lang)}Emitter`;\n return `import type { Emitter, EmitterContext, GeneratedFile, ApiSpec, Model, Enum, Service } from '@workos/oagen';\n\nexport const ${varName}: Emitter = {\n language: '${lang}',\n\n generateModels(_models: Model[], _ctx: EmitterContext): GeneratedFile[] {\n return [];\n },\n\n generateEnums(_enums: Enum[], _ctx: EmitterContext): GeneratedFile[] {\n return [];\n },\n\n generateResources(_services: Service[], _ctx: EmitterContext): GeneratedFile[] {\n return [];\n },\n\n generateClient(_spec: ApiSpec, _ctx: EmitterContext): GeneratedFile[] {\n return [];\n },\n\n generateErrors(_ctx: EmitterContext): GeneratedFile[] {\n return [];\n },\n\n generateTypeSignatures(_spec: ApiSpec, _ctx: EmitterContext): GeneratedFile[] {\n return [];\n },\n\n generateTests(_spec: ApiSpec, _ctx: EmitterContext): GeneratedFile[] {\n return [];\n },\n\n buildOperationsMap(_spec: ApiSpec, _ctx: EmitterContext) {\n return {};\n },\n\n fileHeader(): string {\n return '// Auto-generated by oagen. Do not edit.';\n },\n};\n`;\n}\n","import { resolve, relative } from 'node:path';\nimport { existsSync, mkdirSync, writeFileSync, readFileSync } from 'node:fs';\nimport {\n packageJson,\n tsconfigJson,\n vitestConfig,\n tsupConfig,\n oagenConfig,\n srcPlugin,\n srcIndex,\n gitignore,\n stubEmitter,\n} from './templates/init.js';\n\nexport async function initCommand(opts: { lang: string; project?: string }): Promise<void> {\n const projectDir = resolve(opts.project ?? '.');\n const lang = opts.lang;\n\n if (existsSync(resolve(projectDir, 'oagen.config.ts'))) {\n throw new Error('Project already initialized — oagen.config.ts exists');\n }\n\n // Create directories\n const dirs = [`src/${lang}`, 'test', 'smoke', 'docs/sdk-architecture'];\n for (const dir of dirs) {\n mkdirSync(resolve(projectDir, dir), { recursive: true });\n }\n\n // Write template files\n const files: Array<[string, string]> = [\n ['tsconfig.json', tsconfigJson()],\n ['vitest.config.ts', vitestConfig()],\n ['tsup.config.ts', tsupConfig()],\n ['oagen.config.ts', oagenConfig()],\n ['src/plugin.ts', srcPlugin(lang)],\n ['src/index.ts', srcIndex(lang)],\n [`src/${lang}/index.ts`, stubEmitter(lang)],\n ];\n\n // Handle package.json specially - merge if it exists\n const packageJsonPath = resolve(projectDir, 'package.json');\n let packageJsonContent: string;\n if (existsSync(packageJsonPath)) {\n const existingContent = readFileSync(packageJsonPath, 'utf-8');\n const existingPkg = JSON.parse(existingContent);\n const newPkg = JSON.parse(packageJson(lang));\n // Merge: existing values take precedence, but append new scripts/devDependencies\n existingPkg.scripts = { ...newPkg.scripts, ...existingPkg.scripts };\n existingPkg.devDependencies = { ...newPkg.devDependencies, ...existingPkg.devDependencies };\n existingPkg.dependencies = { ...newPkg.dependencies, ...existingPkg.dependencies };\n // Only set exports if not already defined\n if (!existingPkg.exports) {\n existingPkg.exports = newPkg.exports;\n }\n // Only set type if not already defined\n if (!existingPkg.type) {\n existingPkg.type = newPkg.type;\n }\n // Only set main if not already defined\n if (!existingPkg.main) {\n existingPkg.main = newPkg.main;\n }\n // Only set types if not already defined\n if (!existingPkg.types) {\n existingPkg.types = newPkg.types;\n }\n packageJsonContent = JSON.stringify(existingPkg, null, 2);\n } else {\n packageJsonContent = packageJson(lang);\n }\n\n // Handle .gitignore specially - append if it exists\n const gitignorePath = resolve(projectDir, '.gitignore');\n let gitignoreContent: string;\n if (existsSync(gitignorePath)) {\n const existingContent = readFileSync(gitignorePath, 'utf-8');\n const newContent = gitignore();\n // Append new entries that don't already exist (filter out comments and empty lines for comparison)\n const existingLines = new Set(\n existingContent\n .split('\\n')\n .map((line) => line.trim())\n .filter((line) => line && !line.startsWith('#')),\n );\n const newLines = newContent.split('\\n').filter((line) => {\n const trimmed = line.trim();\n return trimmed && !existingLines.has(trimmed);\n });\n gitignoreContent = existingContent + (existingContent.endsWith('\\n') ? '' : '\\n') + newLines.join('\\n');\n } else {\n gitignoreContent = gitignore();\n }\n\n for (const [filePath, content] of files) {\n const fullPath = resolve(projectDir, filePath);\n mkdirSync(resolve(fullPath, '..'), { recursive: true });\n writeFileSync(fullPath, content, 'utf-8');\n }\n\n // Write package.json\n writeFileSync(packageJsonPath, packageJsonContent, 'utf-8');\n\n // Write .gitignore\n writeFileSync(gitignorePath, gitignoreContent, 'utf-8');\n\n // Print summary\n console.log(`Initialized emitter project for \"${lang}\" in ${relative(process.cwd(), projectDir) || '.'}`);\n console.log('');\n console.log('Created:');\n for (const [filePath] of files) {\n console.log(` ${filePath}`);\n }\n for (const dir of dirs) {\n console.log(` ${dir}/`);\n }\n\n // Print next steps\n console.log('');\n console.log('Next steps:');\n console.log(` - Implement your emitter in src/${lang}/index.ts`);\n console.log(' - npm run sdk:generate -- --spec <path-to-spec> --namespace <Name>');\n console.log(' - npm run sdk:verify -- --spec <path-to-spec>');\n}\n","import { parseSpec } from '../parser/parse.js';\nimport { resolveOperations } from '../ir/operation-hints.js';\nimport { expandDocUrls } from '../utils/expand-doc-urls.js';\nimport type { OperationHint, ResolvedOperation } from '../ir/operation-hints.js';\n\nexport async function resolveCommand(opts: {\n spec: string;\n format?: 'table' | 'json';\n operationIdTransform?: (id: string) => string;\n schemaNameTransform?: (name: string) => string;\n docUrl?: string;\n operationHints?: Record<string, OperationHint>;\n mountRules?: Record<string, string>;\n}): Promise<void> {\n let ir = await parseSpec(opts.spec, {\n operationIdTransform: opts.operationIdTransform,\n schemaNameTransform: opts.schemaNameTransform,\n });\n if (opts.docUrl) {\n ir = expandDocUrls(ir, opts.docUrl);\n }\n\n const resolved = resolveOperations(ir, opts.operationHints, opts.mountRules);\n const format = opts.format ?? 'table';\n\n if (format === 'json') {\n const output = resolved.map(toJsonRow);\n console.log(JSON.stringify(output, null, 2));\n return;\n }\n\n // Table format\n printTable(resolved, opts.operationHints);\n}\n\ninterface JsonRow {\n service: string;\n method: string;\n path: string;\n derivedName: string;\n hintApplied: boolean;\n mountOn: string;\n wrappers?: string[];\n}\n\nfunction toJsonRow(r: ResolvedOperation): JsonRow {\n return {\n service: r.service.name,\n method: r.operation.httpMethod.toUpperCase(),\n path: r.operation.path,\n derivedName: r.methodName,\n hintApplied: r.methodName !== r.operation.name,\n mountOn: r.mountOn,\n wrappers: r.wrappers?.map((w) => w.name),\n };\n}\n\nfunction printTable(resolved: ResolvedOperation[], hints?: Record<string, OperationHint>): void {\n const hintMap = hints ?? {};\n\n // Header\n console.log('| Service | Method | Path | Resolved Name | Hint | Mount On |');\n console.log('|---|---|---|---|---|---|');\n\n const unhinted: ResolvedOperation[] = [];\n\n for (const r of resolved) {\n const key = `${r.operation.httpMethod.toUpperCase()} ${r.operation.path}`;\n const hasHint = key in hintMap;\n const hintMarker = hasHint ? 'yes' : '';\n const mountChanged = r.mountOn !== r.service.name;\n const mountCol = mountChanged ? r.mountOn : '';\n\n console.log(\n `| ${r.service.name} | ${r.operation.httpMethod.toUpperCase()} | ${r.operation.path} | \\`${r.methodName}\\` | ${hintMarker} | ${mountCol} |`,\n );\n\n // Track wrappers\n if (r.wrappers) {\n for (const w of r.wrappers) {\n console.log(`| | | | \\`${w.name}\\` (wrapper) | yes | ${mountCol} |`);\n }\n }\n\n if (!hasHint && !mountChanged) {\n unhinted.push(r);\n }\n }\n\n console.log('');\n console.log(\n `Total: ${resolved.length} operations, ${resolved.length - unhinted.length} with hints/mounts, ${unhinted.length} algorithm-only`,\n );\n}\n","import * as path from 'node:path';\nimport { existsSync } from 'node:fs';\nimport { pathToFileURL } from 'node:url';\nimport type { Emitter } from '../engine/types.js';\nimport type { OperationHint } from '../ir/operation-hints.js';\nimport type { Extractor } from '../compat/types.js';\nimport type { CompatConfig } from '../compat/config.js';\nimport { ConfigLoadError } from '../errors.js';\n\nexport interface OagenConfig {\n emitters?: Emitter[];\n extractors?: Extractor[];\n /** Compatibility verification policy. See docs/core/compatibility-policy.md. */\n compat?: CompatConfig;\n /** Path to the emitter project (where skills scaffold new emitters, tests, smoke runners). */\n emitterProject?: string;\n /** Map from language key to custom smoke runner script path. */\n smokeRunners?: Record<string, string>;\n /**\n * Custom transform for operation IDs. When provided, replaces the default\n * camelCase pass-through. Receives the raw operationId string; return the\n * desired operation name (no additional conversion is applied).\n *\n */\n operationIdTransform?: (id: string) => string;\n /**\n * Custom transform for schema (model/enum) names. Applied after the built-in\n * cleanSchemaName normalization. Receives the cleaned PascalCase name; return\n * the desired name. Collisions are detected automatically -- if a transform\n * would produce a duplicate name, the original is kept.\n */\n schemaNameTransform?: (name: string) => string;\n /** Base URL for documentation links. When set, relative paths in descriptions\n * (e.g. `/reference/authkit/user`) are expanded to full URLs. */\n docUrl?: string;\n /**\n * Per-operation overrides keyed by \"METHOD /path\" (e.g. \"POST /sso/token\").\n * Used by the operation resolver to override derived method names, mount\n * targets, and to split union-body operations into typed wrappers.\n */\n operationHints?: Record<string, OperationHint>;\n /**\n * Service-level mount rules: maps an IR service name to a target\n * service/namespace (PascalCase). All operations in the source service\n * are mounted on the target. Per-operation mountOn in operationHints\n * takes priority.\n */\n mountRules?: Record<string, string>;\n}\n\nconst CONFIG_NAMES = ['oagen.config.ts', 'oagen.config.js', 'oagen.config.mjs'];\n\n/**\n * Load an oagen config file.\n *\n * @param configPath - Explicit path to a config file. When provided, only that\n * file is attempted (no fallback search).\n * @param cwd - Directory to search when `configPath` is omitted. Defaults to\n * `process.cwd()`. The loader tries each name in `CONFIG_NAMES` in order.\n */\nexport async function loadConfig(configPath?: string, cwd: string = process.cwd()): Promise<OagenConfig | null> {\n if (configPath) {\n const resolved = path.resolve(cwd, configPath);\n if (!existsSync(resolved)) {\n throw new ConfigLoadError(`Config file not found: ${resolved}`, 'Check that the path passed to --config exists.');\n }\n try {\n const mod = await import(pathToFileURL(resolved).href);\n return (mod.default ?? mod) as OagenConfig;\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n throw new ConfigLoadError(\n `Failed to load ${resolved}: ${message}`,\n resolved.endsWith('.ts')\n ? 'TypeScript config files require tsx or ts-node. Use .mjs instead, or run via `npx tsx`.'\n : 'Check that the config file is valid ESM.',\n );\n }\n }\n\n for (const name of CONFIG_NAMES) {\n const resolved = path.resolve(cwd, name);\n if (!existsSync(resolved)) continue;\n try {\n const mod = await import(pathToFileURL(resolved).href);\n const config = (mod.default ?? mod) as OagenConfig;\n return config;\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n throw new ConfigLoadError(\n `Failed to load ${name}: ${message}`,\n name.endsWith('.ts')\n ? 'TypeScript config files require tsx or ts-node. Use .mjs instead, or run via `npx tsx`.'\n : 'Check that the config file is valid ESM.',\n );\n }\n }\n return null;\n}\n","import { registerEmitter } from '../engine/registry.js';\nimport { registerExtractor } from '../compat/extractor-registry.js';\nimport type { OagenConfig } from './config-loader.js';\n\nexport function applyConfig(config: OagenConfig): void {\n for (const emitter of config.emitters ?? []) {\n registerEmitter(emitter);\n }\n for (const extractor of config.extractors ?? []) {\n registerExtractor(extractor);\n }\n}\n","import 'dotenv/config';\nimport { Command } from 'commander';\nimport { parseCommand } from './parse.js';\nimport { generateCommand } from './generate.js';\nimport { diffCommand } from './diff.js';\nimport { extractCommand } from './extract.js';\nimport { compatExtractCommand } from './compat-extract.js';\nimport { compatDiffCommand } from './compat-diff.js';\nimport { compatSummaryCommand } from './compat-summary.js';\nimport { verifyCommand } from './verify.js';\nimport { initCommand } from './init.js';\nimport { resolveCommand } from './resolve.js';\nimport { loadConfig } from './config-loader.js';\nimport { applyConfig } from './plugin-loader.js';\nimport { CommandError } from '../errors.js';\n\nfunction handleError(err: unknown): never {\n const exitCode = err instanceof CommandError ? err.exitCode : 1;\n const message = err instanceof Error ? err.message : String(err);\n if (message) console.error(message);\n process.exit(exitCode);\n}\n\n// Parse --config before Commander runs so we can load the right config file\n// at startup. Commander's parseOptions isn't available before .parse(), so we\n// do a simple argv scan.\nconst configArgIdx = process.argv.indexOf('--config');\nconst explicitConfigPath = configArgIdx !== -1 ? process.argv[configArgIdx + 1] : undefined;\n\n// Load config at startup so user-provided emitters/extractors are registered\n// before any command runs. loadConfig is async (dynamic import), so we use\n// top-level await.\nlet configSmokeRunners: Record<string, string> | undefined;\nlet configOperationIdTransform: ((id: string) => string) | undefined;\nlet configSchemaNameTransform: ((name: string) => string) | undefined;\nlet configDocUrl: string | undefined;\nlet configOperationHints: Record<string, import('../ir/operation-hints.js').OperationHint> | undefined;\nlet configMountRules: Record<string, string> | undefined;\nlet configCompat: import('../compat/config.js').CompatConfig | undefined;\ntry {\n const config = await loadConfig(explicitConfigPath);\n if (config) {\n applyConfig(config);\n configSmokeRunners = config.smokeRunners;\n configOperationIdTransform = config.operationIdTransform;\n configSchemaNameTransform = config.schemaNameTransform;\n configDocUrl = config.docUrl;\n configOperationHints = config.operationHints;\n configMountRules = config.mountRules;\n configCompat = config.compat;\n }\n} catch (err) {\n handleError(err);\n}\n\nconst program = new Command()\n .name('oagen')\n .description('Framework for building OpenAPI SDK emitters')\n .version('0.0.1')\n .option('--config <path>', 'Path to oagen config file (default: oagen.config.ts in cwd)');\n\nprogram\n .command('parse')\n .description('Parse an OpenAPI spec and output IR as JSON')\n .option('--spec <path>', 'Path to OpenAPI spec file (or set OPENAPI_SPEC_PATH)')\n .action((opts) => {\n opts.spec ??= process.env.OPENAPI_SPEC_PATH;\n if (!opts.spec) {\n console.error('error: --spec <path> or OPENAPI_SPEC_PATH env var is required');\n process.exit(1);\n }\n return parseCommand(opts);\n });\n\nprogram\n .command('generate')\n .description('Run a registered emitter against an OpenAPI spec')\n .option('--spec <path>', 'Path to OpenAPI spec file (or set OPENAPI_SPEC_PATH)')\n .requiredOption('--lang <language>', 'Target language')\n .requiredOption('--output <dir>', 'Output directory')\n .option('--target <dir>', 'Target directory for live SDK integration (merged output)')\n .option('--namespace <name>', 'SDK namespace/package name')\n .option('--dry-run', 'Preview files without writing')\n .option('--api-surface <path>', 'Path to baseline API surface JSON for compat overlay')\n .option('--no-compat-check', 'Skip compat overlay even if --api-surface is provided')\n .option('--no-prune', 'Skip deletion of stale files recorded in the previous .oagen-manifest.json')\n .action((opts) => {\n opts.spec ??= process.env.OPENAPI_SPEC_PATH;\n if (!opts.spec) {\n console.error('error: --spec <path> or OPENAPI_SPEC_PATH env var is required');\n process.exit(1);\n }\n generateCommand({\n ...opts,\n operationIdTransform: configOperationIdTransform,\n schemaNameTransform: configSchemaNameTransform,\n docUrl: configDocUrl,\n operationHints: configOperationHints,\n mountRules: configMountRules,\n }).catch(handleError);\n });\n\nprogram\n .command('diff')\n .description('Compare two OpenAPI specs and output a diff report')\n .requiredOption('--old <path>', 'Path to old spec')\n .requiredOption('--new <path>', 'Path to new spec')\n .action((opts) => {\n diffCommand({\n ...opts,\n operationIdTransform: configOperationIdTransform,\n schemaNameTransform: configSchemaNameTransform,\n docUrl: configDocUrl,\n }).catch(handleError);\n });\n\nprogram\n .command('extract')\n .description('Extract public API surface from a live SDK')\n .requiredOption('--sdk-path <path>', 'Path to the live SDK')\n .requiredOption('--lang <language>', 'Target language')\n .option('--output <path>', 'Output file path')\n .action((opts) => {\n opts.output ??= `sdk-${opts.lang}-surface.json`;\n extractCommand(opts).catch(handleError);\n });\n\nprogram\n .command('compat-extract')\n .description('Extract a compat snapshot from a live SDK and write .oagen-compat-snapshot.json')\n .requiredOption('--sdk-path <path>', 'Path to the live SDK')\n .requiredOption('--lang <language>', 'Target language')\n .requiredOption('--output <dir>', 'Directory to write .oagen-compat-snapshot.json into')\n .option('--spec <path>', 'Path to OpenAPI spec — enriches symbols with operationId, route, and specSha')\n .action((opts) => {\n opts.spec ??= process.env.OPENAPI_SPEC_PATH;\n compatExtractCommand(opts).catch(handleError);\n });\n\nprogram\n .command('compat-diff')\n .description('Diff two compat snapshot files and produce a classified change report')\n .requiredOption('--baseline <path>', 'Path to the baseline compat snapshot JSON')\n .requiredOption('--candidate <path>', 'Path to the candidate compat snapshot JSON')\n .option('--output <path>', 'Write machine-readable report to this path')\n .option('--fail-on <level>', 'Fail threshold: none, breaking, or soft-risk', 'breaking')\n .option('--explain', 'Include provenance explanations in output')\n .action((opts) => {\n compatDiffCommand(opts).catch(handleError);\n });\n\nprogram\n .command('compat-summary')\n .description('Format compat report(s) as a markdown PR comment')\n .requiredOption('--report <path...>', 'Path(s) to compat report JSON(s) — pass multiple for cross-language rollup')\n .option('--output <path>', 'Write markdown to this file instead of stdout')\n .action((opts) => {\n compatSummaryCommand(opts).catch(handleError);\n });\n\nprogram\n .command('verify')\n .description('Run smoke tests (and optional compat check) against an already-generated SDK')\n .option('--spec <path>', 'Path to OpenAPI spec file (or set OPENAPI_SPEC_PATH)')\n .requiredOption('--lang <language>', 'Target language')\n .requiredOption('--output <dir>', 'Path to the generated SDK')\n .option('--api-surface <path>', 'Baseline API surface JSON — enables compat verification')\n .option('--raw-results <path>', 'Path to an existing smoke baseline file to diff against')\n .option('--smoke-config <path>', 'Path to smoke config JSON for skip lists and service mappings')\n .option('--smoke-runner <path>', 'Path to a custom smoke runner script (overrides built-in sdk-test.ts)')\n .option(\n '--scope <mode>',\n 'Compat scope: \"full\" compares all baseline symbols, \"spec-only\" compares only symbols derivable from the OpenAPI spec (default: spec-only when --spec is provided)',\n )\n .option('--old-spec <path>', 'Previous OpenAPI spec — enables staleness detection for removed/renamed symbols')\n .option('--namespace <name>', 'SDK namespace/package name (used by retry loop for regeneration)')\n .option('--diagnostics', 'Output verify-diagnostics.json with structured violation breakdown')\n .option('--max-retries <n>', 'Max retry iterations for self-correcting overlay loop (default: 3)', '3')\n .option('--compat-report <path>', 'Write machine-readable compat report to this path')\n .option('--compat-fail-on <level>', 'Fail threshold: none, breaking, or soft-risk')\n .option('--compat-baseline <path>', 'Path to baseline compatibility snapshot')\n .option('--compat-explain', 'Include provenance explanations in compat output')\n .action((opts) => {\n opts.spec ??= process.env.OPENAPI_SPEC_PATH;\n // --spec is only required when we need to generate a baseline (no --raw-results\n // and no existing smoke-results-raw.json). Defer the check to verifyCommand.\n // CLI --smoke-runner takes precedence, then per-language smokeRunners map from config\n opts.smokeRunner ??= configSmokeRunners?.[opts.lang];\n verifyCommand({\n ...opts,\n maxRetries: parseInt(opts.maxRetries, 10),\n operationIdTransform: configOperationIdTransform,\n schemaNameTransform: configSchemaNameTransform,\n compatConfig: configCompat,\n compatReport: opts.compatReport,\n compatFailOn: opts.compatFailOn,\n compatBaseline: opts.compatBaseline,\n compatExplain: opts.compatExplain,\n }).catch(handleError);\n });\n\nprogram\n .command('resolve')\n .description('Resolve operation names from spec and output a review table')\n .option('--spec <path>', 'Path to OpenAPI spec file (or set OPENAPI_SPEC_PATH)')\n .option('--format <format>', 'Output format: table or json', 'table')\n .action((opts) => {\n opts.spec ??= process.env.OPENAPI_SPEC_PATH;\n if (!opts.spec) {\n console.error('error: --spec <path> or OPENAPI_SPEC_PATH env var is required');\n process.exit(1);\n }\n resolveCommand({\n ...opts,\n operationIdTransform: configOperationIdTransform,\n schemaNameTransform: configSchemaNameTransform,\n docUrl: configDocUrl,\n operationHints: configOperationHints,\n mountRules: configMountRules,\n }).catch(handleError);\n });\n\nprogram\n .command('init')\n .description('Scaffold a new emitter project')\n .requiredOption('--lang <language>', 'Target language')\n .option('--project <dir>', 'Project directory', '.')\n .action((opts) => {\n initCommand(opts).catch(handleError);\n });\n\nprogram.parse();\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":["singularize","singularize","singularize","singularize","extractDeclarationName","declarationKey","path","path","path","defaultNodeHints","path","path","path","path"],"sources":["../../src/ir/sdk-behavior.ts","../../src/errors.ts","../../src/parser/refs.ts","../../src/ir/types.ts","../../src/utils/naming.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","../../src/cli/parse.ts","../../src/engine/merge-adapters/url-fingerprint.ts","../../src/engine/merge-adapters/dotnet.ts","../../src/engine/merge-adapters/elixir.ts","../../src/engine/merge-adapters/go.ts","../../src/engine/merge-adapters/kotlin.ts","../../src/engine/merge-adapters/node.ts","../../src/engine/merge-adapters/php.ts","../../src/engine/merge-adapters/python.ts","../../src/engine/merge-adapters/ruby.ts","../../src/engine/merge-adapters/rust.ts","../../src/engine/merge-adapters/index.ts","../../src/utils/tree-sitter.ts","../../src/engine/merger.ts","../../src/engine/json-merge.ts","../../src/engine/writer.ts","../../src/ir/operation-hints.ts","../../src/engine/generate-files.ts","../../src/engine/integrate.ts","../../src/engine/formatter.ts","../../src/engine/manifest.ts","../../src/engine/orchestrator.ts","../../src/engine/registry.ts","../../src/compat/language-hints.ts","../../src/compat/overlay.ts","../../src/compat/extractor-registry.ts","../../src/engine/manifest-reader.ts","../../src/cli/overlay-loader.ts","../../src/utils/expand-doc-urls.ts","../../src/cli/generate.ts","../../src/differ/classify.ts","../../src/differ/models.ts","../../src/differ/operations.ts","../../src/differ/services.ts","../../src/differ/diff.ts","../../src/cli/diff.ts","../../src/cli/extract.ts","../../src/compat/policy.ts","../../src/compat/schema.ts","../../src/compat/ir.ts","../../src/cli/compat-extract.ts","../../src/compat/config.ts","../../src/compat/classify.ts","../../src/compat/spec-filter.ts","../../src/compat/differ.ts","../../src/compat/concepts.ts","../../src/compat/report.ts","../../src/cli/compat-diff.ts","../../src/cli/compat-summary.ts","../../src/compat/approvals.ts","../../src/verify/run-compat-check.ts","../../src/verify/run-overlay-retry-loop.ts","../../src/compat/staleness.ts","../../src/verify/run-staleness-check.ts","../../src/verify/run-smoke-check.ts","../../src/verify/write-diagnostics.ts","../../src/cli/verify.ts","../../src/cli/templates/init.ts","../../src/cli/init.ts","../../src/cli/resolve.ts","../../src/cli/config-loader.ts","../../src/cli/plugin-loader.ts","../../src/cli/index.ts"],"sourcesContent":["/**\n * SDK Behavior IR — language-agnostic runtime policies for generated SDKs.\n *\n * These types capture the \"what\" of SDK behavior (retry, telemetry, errors, etc.)\n * while emitters provide the \"how\" (language-specific mechanism).\n *\n * Emitters access these via `ctx.spec.sdk` — always populated, never undefined.\n */\n\n// ── Retry ──────────────────────────────────────────────────────────\n\n/** Retry policy — when and how to retry failed requests. */\nexport interface RetryPolicy {\n /** HTTP status codes that trigger a retry. */\n retryableStatusCodes: number[];\n /** Maximum number of retry attempts (0 = no retries). */\n maxRetries: number;\n /** Whether to retry on connection errors (DNS failure, TCP reset). */\n retryOnConnectionError: boolean;\n /** Whether to retry on timeout errors. */\n retryOnTimeout: boolean;\n /** Backoff strategy between retries. */\n backoff: BackoffStrategy;\n}\n\n/** Exponential backoff configuration.\n *\n * Formula: `delay = min(initialDelay * multiplier^attempt, maxDelay)`\n * With jitter: `delay += delay * jitterFactor * random(0, 1)`\n */\nexport interface BackoffStrategy {\n /** Initial delay in seconds before the first retry. */\n initialDelay: number;\n /** Multiplier applied to the delay on each subsequent retry. */\n multiplier: number;\n /** Maximum delay in seconds (cap). */\n maxDelay: number;\n /** Jitter factor (0..1). 0.5 means up to 50% random jitter added. */\n jitterFactor: number;\n}\n\n// ── Errors ─────────────────────────────────────────────────────────\n\n/** Error mapping — status codes to named exception kinds. */\nexport interface ErrorPolicy {\n /** Map from HTTP status code to a logical error kind name (e.g. 400 → 'BadRequest').\n * Emitters append language-specific suffixes (e.g. 'BadRequestException'). */\n statusCodeMap: Record<number, string>;\n /** Catch-all error kind for 5xx status codes not in the map. */\n serverErrorKind: string;\n /** Catch-all error kind for unrecognized status codes. */\n clientErrorKind: string;\n /** URL template for error documentation. Use {code} as placeholder for the API error code.\n * Example: 'https://workos.com/docs/errors/{code}' */\n errorDocUrlTemplate?: string;\n}\n\n// ── Telemetry ──────────────────────────────────────────────────────\n\n/** Telemetry — what request metrics to track and send. */\nexport interface TelemetryPolicy {\n /** Whether telemetry is enabled by default. Users can opt out via constructor param. */\n enabledByDefault: boolean;\n /** Header name for client telemetry data (previous request's ID + latency). */\n headerName: string;\n /** Response header name for the request ID. */\n requestIdHeader: string;\n}\n\n// ── Pagination ─────────────────────────────────────────────────────\n\n/** Pagination behavior defaults. */\nexport interface PaginationPolicy {\n /** Delay in milliseconds between pages during auto-pagination. 0 = no delay. */\n autoPageDelayMs: number;\n}\n\n// ── Idempotency ────────────────────────────────────────────────────\n\n/** Idempotency auto-generation rules. */\nexport interface IdempotencyPolicy {\n /** Header name for the idempotency key. */\n headerName: string;\n /** Whether to auto-generate a UUID v4 idempotency key for POST requests when retries > 0. */\n autoGenerateForPost: boolean;\n}\n\n// ── Logging ────────────────────────────────────────────────────────\n\n/** Logging contract — what to log at which level. */\nexport interface LoggingPolicy {\n /** Whether structured logging hooks are generated. */\n enabled: boolean;\n /** Log events that the generated client emits. */\n events: LogEvent[];\n}\n\n/** A discrete loggable event in the request lifecycle. */\nexport type LogEvent =\n | 'request.start'\n | 'request.success'\n | 'request.retry'\n | 'request.rate_limited'\n | 'request.error'\n | 'request.connection_error';\n\n// ── User-Agent ─────────────────────────────────────────────────────\n\n/** User-Agent construction rules. */\nexport interface UserAgentPolicy {\n /** Template for the SDK identifier string.\n * Placeholders: {name} = spec name, {lang} = emitter language, {version} = SDK version.\n * Each emitter interpolates with its own language string and casing conventions.\n * Example: '{name} {lang}/{version}' → 'WorkOS PHP/4.32.0' */\n sdkIdentifierTemplate: string;\n /** Whether to append the runtime/language version (e.g. PHP 8.2, Python 3.12). */\n includeRuntimeVersion: boolean;\n /** Whether to allow app info enrichment via setAppInfo(name, version, url). */\n allowAppInfo: boolean;\n /** AI agent environment variable detection entries. */\n aiAgentEnvVars: AiAgentEnvVar[];\n}\n\n/** Maps an environment variable to an AI agent slug for User-Agent enrichment. */\nexport interface AiAgentEnvVar {\n /** Environment variable to check (e.g. 'CLAUDE_CODE'). */\n envVar: string;\n /** Agent name to append to User-Agent (e.g. 'ClaudeCode'). */\n agentName: string;\n}\n\n// ── Request Guards ─────────────────────────────────────────────────\n\n/** Guards that validate request params before sending. */\nexport interface RequestGuardPolicy {\n /** Keys that should be in RequestOptions, not in params.\n * If detected in the body or query params, the SDK throws an error. */\n optionKeys: string[];\n}\n\n// ── Timeouts ───────────────────────────────────────────────────────\n\n/** Timeout configuration. */\nexport interface TimeoutPolicy {\n /** Default HTTP request timeout in seconds. */\n defaultTimeoutSeconds: number;\n /** Environment variable name to override the timeout (e.g. 'WORKOS_REQUEST_TIMEOUT'). */\n timeoutEnvVar?: string;\n}\n\n// ── Root ───────────────────────────────────────────────────────────\n\n/** Language-agnostic runtime policies for generated SDKs.\n * Attached to `ApiSpec.sdk` and consumed by emitters via `ctx.spec.sdk`. */\nexport interface SdkBehavior {\n retry: RetryPolicy;\n errors: ErrorPolicy;\n telemetry: TelemetryPolicy;\n pagination: PaginationPolicy;\n idempotency: IdempotencyPolicy;\n logging: LoggingPolicy;\n userAgent: UserAgentPolicy;\n requestGuard: RequestGuardPolicy;\n timeout: TimeoutPolicy;\n}\n\n// ── Defaults ───────────────────────────────────────────────────────\n\n/**\n * Canonical SDK behavior defaults. These match the PHP emitter's current\n * implementation (the most complete). Per-language overrides can be applied\n * via `mergeSdkBehavior()` in each SDK's `oagen.config.ts`.\n *\n * - Retry: exponential backoff with jitter, retries on 429/5xx\n * - Errors: standard HTTP status → exception kind mapping\n * - Telemetry: enabled by default, tracks request ID + latency\n * - Pagination: no inter-page delay (Node overrides to 350ms)\n * - Idempotency: auto-generate UUID v4 for retryable POSTs\n * - Logging: all lifecycle events enabled\n * - User-Agent: SDK identifier + runtime version + app info + AI agent detection\n * - Request guards: detect misplaced RequestOptions keys in params\n * - Timeout: 60s default (Python overrides to 30s)\n */\nexport function defaultSdkBehavior(): SdkBehavior {\n return {\n retry: {\n retryableStatusCodes: [429, 500, 502, 503, 504],\n maxRetries: 3,\n retryOnConnectionError: true,\n retryOnTimeout: true,\n backoff: {\n initialDelay: 1.0,\n multiplier: 2.0,\n maxDelay: 30.0,\n jitterFactor: 0.5,\n },\n },\n errors: {\n statusCodeMap: {\n 400: 'BadRequest',\n 401: 'Authentication',\n 403: 'Authorization',\n 404: 'NotFound',\n 409: 'Conflict',\n 422: 'UnprocessableEntity',\n 429: 'RateLimitExceeded',\n },\n serverErrorKind: 'Server',\n clientErrorKind: 'Api',\n errorDocUrlTemplate: 'https://workos.com/docs/errors/{code}',\n },\n telemetry: {\n enabledByDefault: true,\n headerName: 'X-WorkOS-Client-Telemetry',\n requestIdHeader: 'X-Request-ID',\n },\n pagination: {\n autoPageDelayMs: 0,\n },\n idempotency: {\n headerName: 'Idempotency-Key',\n autoGenerateForPost: true,\n },\n logging: {\n enabled: true,\n events: [\n 'request.start',\n 'request.success',\n 'request.retry',\n 'request.rate_limited',\n 'request.error',\n 'request.connection_error',\n ],\n },\n userAgent: {\n sdkIdentifierTemplate: '{name} {lang}/{version}',\n includeRuntimeVersion: true,\n allowAppInfo: true,\n aiAgentEnvVars: [\n { envVar: 'CLAUDE_CODE', agentName: 'ClaudeCode' },\n { envVar: 'CURSOR_AGENT', agentName: 'Cursor' },\n { envVar: 'CLINE_ACTIVE', agentName: 'Cline' },\n { envVar: 'WINDSURF_ACTIVE', agentName: 'Windsurf' },\n { envVar: 'COPILOT_AGENT', agentName: 'Copilot' },\n ],\n },\n requestGuard: {\n optionKeys: [\n 'api_key',\n 'apiKey',\n 'idempotency_key',\n 'idempotencyKey',\n 'extra_headers',\n 'extraHeaders',\n 'max_retries',\n 'maxRetries',\n 'base_url',\n 'baseUrl',\n ],\n },\n timeout: {\n defaultTimeoutSeconds: 60,\n },\n };\n}\n\n// ── Merge ──────────────────────────────────────────────────────────\n\n/** Recursive partial type for deep overrides. */\nexport type DeepPartial<T> = {\n [K in keyof T]?: T[K] extends (infer U)[]\n ? U[] // Arrays replace entirely (don't concat)\n : T[K] extends object\n ? DeepPartial<T[K]>\n : T[K];\n};\n\n/**\n * Deep-merge partial overrides into the canonical defaults.\n * Arrays replace entirely (so `retryableStatusCodes: [429]` replaces the full list,\n * rather than appending). Object properties are merged recursively.\n */\nexport function mergeSdkBehavior(overrides: DeepPartial<SdkBehavior>): SdkBehavior {\n return deepMerge(\n defaultSdkBehavior() as unknown as Record<string, unknown>,\n overrides as unknown as Record<string, unknown>,\n ) as unknown as SdkBehavior;\n}\n\n/**\n * Self-contained deep merge (no external imports — ir/ is layer 0).\n * Arrays and primitives from `source` replace those in `target`.\n * Objects are merged recursively.\n */\nfunction deepMerge(target: Record<string, unknown>, source: Record<string, unknown>): Record<string, unknown> {\n const result: Record<string, unknown> = { ...target };\n for (const key of Object.keys(source)) {\n const sourceVal = source[key];\n const targetVal = target[key];\n if (sourceVal === undefined) continue;\n if (\n sourceVal !== null &&\n typeof sourceVal === 'object' &&\n !Array.isArray(sourceVal) &&\n targetVal !== null &&\n typeof targetVal === 'object' &&\n !Array.isArray(targetVal)\n ) {\n result[key] = deepMerge(targetVal as Record<string, unknown>, sourceVal as Record<string, unknown>);\n } else {\n result[key] = sourceVal;\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, Oas3_1Types } 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,\n types: Oas3_1Types,\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","import type { SdkBehavior } from './sdk-behavior.js';\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 /** Language-agnostic runtime policies (retry, errors, telemetry, etc.). */\n sdk: SdkBehavior;\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) */\n/** Per-operation security requirement: scheme name → scope list. */\nexport interface SecurityRequirement {\n schemeName: string;\n scopes: string[];\n}\n\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 /** Per-operation security overrides. When present, overrides the global spec-level security. */\n security?: SecurityRequirement[];\n /**\n * Mutually-exclusive parameter groups parsed from `x-mutually-exclusive-parameter-groups`.\n * Each group represents a logical choice the caller must (or may) make between\n * several subsets of query/path/header parameters. The grouped parameters remain\n * in their original arrays (queryParams, pathParams, etc.) for wire-format purposes;\n * this field adds the grouping metadata so emitters can render sum types.\n */\n parameterGroups?: ParameterGroup[];\n}\n\n/**\n * A mutually-exclusive parameter group. The caller must supply exactly one\n * variant (when `optional` is false) or may omit the group entirely (when true).\n */\nexport interface ParameterGroup {\n /** Group name from the extension (e.g. \"parent_resource\"). */\n name: string;\n /** True when the whole group may be omitted. */\n optional: boolean;\n /** Ordered variants (insertion order matches the spec). */\n variants: ParameterGroupVariant[];\n}\n\n/**\n * One variant within a mutually-exclusive parameter group.\n */\nexport interface ParameterGroupVariant {\n /** Variant name from the extension (e.g. \"by_id\", \"by_external_id\"). */\n name: string;\n /**\n * References to the actual parameter IR nodes. These are the same\n * objects that live in operation.queryParams / .pathParams / .headerParams --\n * shared by identity, not duplicated.\n */\n parameters: Parameter[];\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 style?: 'form' | 'simple' | 'label' | 'matrix';\n explode?: boolean;\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 * When set, this model is a discriminated union over allOf+oneOf variants.\n * Emitters should generate a dispatcher (factory) instead of a regular dataclass.\n * The `property` field is the discriminator key (e.g. \"event\"), and `mapping`\n * maps each discriminator value to the concrete variant model name.\n */\n discriminator?: {\n property: string;\n mapping: Record<string, string>;\n };\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","/**\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 = ['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 'Species',\n 'Series',\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","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, singularize, stripListItemMarkers } from '../utils/naming.js';\n\n/**\n * Module-level transform set during extractSchemas(). Used by schemaToTypeRef()\n * to apply the same name transform to $ref model/enum references.\n */\nlet activeSchemaNameTransform: ((name: string) => string) | null = null;\n\n/** Apply cleanSchemaName + the active transform (if any) to a raw schema name. */\nfunction resolveSchemaName(rawName: string): string {\n let name = cleanSchemaName(toPascalCase(rawName));\n if (activeSchemaNameTransform) name = activeSchemaNameTransform(name);\n return name;\n}\n\nexport interface SchemaExtractionOptions {\n schemaNameTransform?: (name: string) => string;\n}\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(\n schemas: Record<string, SchemaObject> | undefined,\n options?: SchemaExtractionOptions,\n): ExtractedSchemas {\n const enums: Enum[] = [];\n\n if (!schemas) return { models: [], enums };\n\n // Build collision-safe transform if provided\n if (options?.schemaNameTransform) {\n const transform = options.schemaNameTransform;\n const rawNames = Object.keys(schemas);\n const cleanedNames = rawNames.map((n) => cleanSchemaName(toPascalCase(n)));\n const transformedToOriginals = new Map<string, string[]>();\n for (const cleaned of cleanedNames) {\n const transformed = transform(cleaned);\n if (!transformedToOriginals.has(transformed)) transformedToOriginals.set(transformed, []);\n transformedToOriginals.get(transformed)!.push(cleaned);\n }\n const unsafeToTransform = new Set<string>();\n for (const [, originals] of transformedToOriginals) {\n if (originals.length > 1) {\n for (const n of originals) unsafeToTransform.add(n);\n }\n }\n activeSchemaNameTransform = (name: string) => (unsafeToTransform.has(name) ? name : transform(name));\n } else {\n activeSchemaNameTransform = null;\n }\n\n const modelsByCleanName = new Map<string, Model>();\n\n for (const [name, schema] of Object.entries(schemas)) {\n const pascalName = resolveSchemaName(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 for (const inlineModel of extractDiscriminatedAllOfVariantModels(schema, pascalName)) {\n const existingInline = modelsByCleanName.get(inlineModel.name);\n if (existingInline) {\n if (inlineModel.fields.length > existingInline.fields.length) {\n modelsByCleanName.set(inlineModel.name, inlineModel);\n }\n } else {\n modelsByCleanName.set(inlineModel.name, inlineModel);\n }\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 // NOTE: activeSchemaNameTransform is intentionally NOT cleared here.\n // extractOperations() calls schemaToTypeRef() for $ref resolution and\n // needs the same transform active. parseSpec() calls clearSchemaNameTransform()\n // after all extraction is complete.\n return { models, enums };\n}\n\n/** Clear the module-level schemaNameTransform. Called by parseSpec() after all extraction phases. */\nexport function clearSchemaNameTransform(): void {\n activeSchemaNameTransform = null;\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) => resolveSchemaName(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 (resolveSchemaName(k) === pascalName) return v;\n }\n return null;\n}\n\n/** Walk into a schema to find a field's sub-schema, resolving allOf and oneOf/anyOf. */\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 // Also check inside oneOf/anyOf variants (pure oneOf schemas flatten variant\n // properties into the model, so the field may live inside a variant).\n for (const variant of [...(parentSchema.oneOf ?? []), ...(parentSchema.anyOf ?? [])]) {\n let resolved = variant;\n if (variant.$ref) {\n const segments = variant.$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 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\n/**\n * If every non-null oneOf/anyOf variant is a string-valued const, return the\n * list of those const values so the union can collapse into a single enum.\n * Returns null when any variant isn't a pure string-const (model ref,\n * number const, nullable, etc.).\n */\nfunction collectLiteralStringConsts(variants: SchemaObject[]): string[] | null {\n if (variants.length === 0) return null;\n const values: string[] = [];\n for (const v of variants) {\n // A single-element enum is semantically identical to const.\n if (typeof v.const === 'string') {\n values.push(v.const);\n continue;\n }\n if (Array.isArray(v.enum) && v.enum.length === 1 && typeof v.enum[0] === 'string') {\n values.push(v.enum[0]);\n continue;\n }\n return null;\n }\n return values;\n}\n\n/** Build an EnumRef the same way the regular enum path does for naming. */\nfunction buildSyntheticEnumRef(\n values: string[],\n contextName: string | undefined,\n parentModelName: string | undefined,\n): TypeRef {\n const baseName = toPascalCase(contextName ?? 'UnknownEnum');\n const cleanParent = parentModelName ? stripListItemMarkers(parentModelName) : undefined;\n const qualifiedName = cleanParent && !baseName.startsWith(cleanParent) ? `${cleanParent}${baseName}` : baseName;\n return { kind: 'enum', name: qualifiedName, values };\n}\n\n/**\n * Detect an implicit discriminator on an oneOf where every variant is an\n * object schema that pins the same property to a const value. Returns\n * { property, mapping } so the IR can represent the union as discriminated\n * without needing an explicit `discriminator:` key in the spec.\n *\n * Both shapes are supported:\n * { properties: { event: { const: \"x\" } }, required: [\"event\"] }\n * { properties: { event: { type: \"string\", enum: [\"x\"] } } }\n *\n * Returns null when any variant doesn't fit the pattern or when variants\n * disagree on which property carries the discriminator.\n */\nfunction detectConstPropertyDiscriminator(\n variants: SchemaObject[],\n): { property: string; mapping: Record<string, string> } | null {\n if (variants.length < 2) return null;\n\n // Find properties whose const value is present on every variant.\n let candidateProperty: string | null = null;\n const candidates = Object.keys(variants[0]?.properties ?? {});\n for (const propName of candidates) {\n if (variants.every((v) => getConstPropertyValue(v, propName) !== null)) {\n candidateProperty = propName;\n break;\n }\n }\n\n if (!candidateProperty) return null;\n\n const mapping: Record<string, string> = {};\n for (const v of variants) {\n const value = getConstPropertyValue(v, candidateProperty);\n if (value === null) return null;\n // Require a $ref or title so we have a concrete model name to map to.\n const variantName = resolveVariantModelName(v);\n if (!variantName) return null;\n mapping[value] = variantName;\n }\n\n return { property: candidateProperty, mapping };\n}\n\nfunction getConstPropertyValue(schema: SchemaObject, property: string): string | null {\n const prop = schema.properties?.[property];\n if (!prop) return null;\n if (typeof prop.const === 'string') return prop.const;\n if (Array.isArray(prop.enum) && prop.enum.length === 1 && typeof prop.enum[0] === 'string') {\n return prop.enum[0];\n }\n return null;\n}\n\nfunction resolveVariantModelName(schema: SchemaObject): string | null {\n if (schema.$ref) {\n return resolveSchemaName(schema.$ref.replace(/^#\\/components\\/schemas\\//, ''));\n }\n const title = typeof schema['title'] === 'string' ? (schema['title'] as string) : null;\n if (title) return resolveSchemaName(title);\n return null;\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 // Pure oneOf/anyOf schemas (no allOf, no properties): merge variant fields\n // as optional. This handles schemas like UpdateOrganizationMembership which\n // is a oneOf with mutually exclusive field groups (role_slug vs role_slugs).\n if (fields.length === 0 && (schema.oneOf || schema.anyOf)) {\n const variants = schema.oneOf ?? schema.anyOf ?? [];\n const emptyRequired = new Set<string>();\n const seenFieldNames = new Set<string>();\n for (const variant of variants) {\n if (!variant.properties) continue;\n for (const [fieldName, fieldSchema] of Object.entries(variant.properties)) {\n if (!fieldSchema || seenFieldNames.has(fieldName)) continue;\n seenFieldNames.add(fieldName);\n fields.push(buildFieldFromSchema(fieldName, fieldSchema as SchemaObject, name, emptyRequired));\n }\n }\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 let resultDiscriminator: { property: string; mapping: Record<string, string> } | undefined;\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 if (resolved.oneOf || resolved.anyOf) {\n const variants = resolved.oneOf ?? resolved.anyOf ?? [];\n // Detect discriminated union: every variant pins the same property to a\n // distinct const value (e.g. EventSchema where each variant has event: const).\n // When detected, store the discriminator instead of flattening variant fields —\n // the base allOf schema already captures the common fields.\n const discriminatorInfo = detectAllOfVariantDiscriminator(variants, name);\n if (discriminatorInfo) {\n resultDiscriminator = discriminatorInfo;\n } else {\n // Flatten oneOf/anyOf variant fields into the parent model as optional\n // fields. This handles the common allOf + oneOf pattern where the spec\n // uses mutually exclusive variant groups (e.g. password vs password_hash).\n const emptyRequired = new Set<string>();\n const seenFieldNames = new Set(fields.map((f) => f.name));\n for (const variant of variants) {\n if (!variant.properties) continue;\n for (const [fieldName, fieldSchema] of Object.entries(variant.properties)) {\n if (!fieldSchema || seenFieldNames.has(fieldName)) continue;\n seenFieldNames.add(fieldName);\n fields.push(buildFieldFromSchema(fieldName, fieldSchema as SchemaObject, name, emptyRequired));\n }\n }\n // Do NOT add variant-level required to the requiredSet — these fields\n // are optional at the parent level because they come from mutually\n // exclusive branches.\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 {\n name,\n description: schema.description,\n fields,\n ...(resultDiscriminator ? { discriminator: resultDiscriminator } : {}),\n };\n}\n\n/**\n * Detect an implicit discriminator on an allOf+oneOf where every variant is an\n * object that pins the same property to a distinct const value. Unlike\n * detectConstPropertyDiscriminator (which requires $ref or title for variant\n * model names), this version derives model names from the const value itself\n * using deriveDiscriminatedVariantName — matching how extractDiscriminatedAllOfVariantModels\n * names those models.\n *\n * Returns null when no discriminator can be reliably detected.\n */\nfunction detectAllOfVariantDiscriminator(\n variants: SchemaObject[],\n fallbackName: string,\n): { property: string; mapping: Record<string, string> } | null {\n if (variants.length < 2) return null;\n\n // Find a property whose const value is present on every variant\n const candidates = Object.keys(variants[0]?.properties ?? {});\n let candidateProperty: string | null = null;\n for (const propName of candidates) {\n if (variants.every((v) => getConstPropertyValue(v, propName) !== null)) {\n candidateProperty = propName;\n break;\n }\n }\n if (!candidateProperty) return null;\n\n const mapping: Record<string, string> = {};\n const seenModelNames = new Set<string>();\n for (const v of variants) {\n const value = getConstPropertyValue(v, candidateProperty);\n if (value === null) return null;\n const modelName = deriveDiscriminatedVariantName(v, fallbackName);\n // If two variants map to the same model name, the discriminator is ambiguous\n if (seenModelNames.has(modelName)) return null;\n seenModelNames.add(modelName);\n mapping[value] = modelName;\n }\n\n return { property: candidateProperty, mapping };\n}\n\nfunction extractDiscriminatedAllOfVariantModels(schema: SchemaObject, fallbackName: string): Model[] {\n const models: Model[] = [];\n const seenNames = new Set<string>();\n\n for (const subSchema of schema.allOf ?? []) {\n for (const variant of subSchema.oneOf ?? []) {\n if (!variant.properties || (variant.type !== undefined && variant.type !== 'object')) continue;\n\n const variantName = deriveDiscriminatedVariantName(variant, fallbackName);\n for (const model of extractInlineModelDeep(variantName, variant)) {\n if (seenNames.has(model.name)) continue;\n seenNames.add(model.name);\n models.push(model);\n }\n }\n }\n\n return models;\n}\n\nfunction deriveDiscriminatedVariantName(schema: SchemaObject, fallbackName: string): string {\n if (!schema.properties) return fallbackName;\n\n const preferred = ['event', 'type', 'object'];\n for (const name of preferred) {\n const field = schema.properties[name];\n if (!field) continue;\n if (typeof field.const === 'string') {\n return toPascalCase(field.const);\n }\n if (field.enum && field.enum.length === 1 && typeof field.enum[0] === 'string') {\n return toPascalCase(field.enum[0]);\n }\n }\n\n for (const field of Object.values(schema.properties)) {\n if (!field) continue;\n if (typeof field.const === 'string') {\n return toPascalCase(field.const);\n }\n if (field.enum && field.enum.length === 1 && typeof field.enum[0] === 'string') {\n return toPascalCase(field.enum[0]);\n }\n }\n\n return fallbackName;\n}\n\nfunction extractInlineModelDeep(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 if (fieldSchema.type === 'object' && fieldSchema.properties) {\n nestedModels.push(...extractInlineModelDeep(qualifyNestedInlineName(name, fieldName), fieldSchema));\n }\n\n if (fieldSchema.type === 'array' && fieldSchema.items?.properties) {\n nestedModels.push(...extractInlineModelDeep(qualifyNestedInlineName(name, fieldName), fieldSchema.items));\n }\n\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 nestedModels.push(\n ...extractInlineModelDeep(qualifyNestedInlineName(name, fieldName), {\n type: 'object',\n properties: mergedProperties,\n required: mergedRequired,\n }),\n );\n }\n }\n\n if (fieldSchema.oneOf) {\n const objectVariant = fieldSchema.oneOf.find((v) => v.properties && (v.type === 'object' || !v.type));\n if (objectVariant) {\n nestedModels.push(...extractInlineModelDeep(qualifyNestedInlineName(name, fieldName), objectVariant));\n }\n }\n }\n\n return [{ name, description: schema.description, fields }, ...nestedModels];\n}\n\nfunction qualifyNestedInlineName(parentName: string, fieldName: string): string {\n const pascalField = toPascalCase(fieldName);\n if (pascalField.startsWith(parentName)) return pascalField;\n\n const cleanParent = stripListItemMarkers(parentName);\n const qualified = `${cleanParent}${pascalField}`;\n const match = qualified.match(/^(.+?)([A-Z][a-z]+s?)$/);\n if (match && match[2]) {\n return match[1] + singularize(match[2]);\n }\n return qualified;\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: resolveSchemaName(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 // Collapse an oneOf/anyOf whose non-null variants are all string-const\n // schemas into a single enum. This turns patterns like\n // provider: { oneOf: [{ const: \"AppleOAuth\" }, { const: \"GitHubOAuth\" }, ...] }\n // into a proper enum type with one member per variant instead of a\n // structurally-opaque union of literal refs.\n const literalStrings = collectLiteralStringConsts(nonNullVariants);\n if (literalStrings !== null && literalStrings.length >= 2) {\n const enumRef = buildSyntheticEnumRef(literalStrings, contextName, parentModelName);\n return nullVariant ? { kind: 'nullable', inner: enumRef } : enumRef;\n }\n\n // Synthesize a discriminator when all non-null variants are objects that\n // share a property whose schema carries a `const` value. Covers the\n // EventSchema-style pattern where each oneOf variant pins `event:\n // const: \"...\"` instead of the spec using an explicit `discriminator:`.\n const syntheticDiscriminator =\n !schema.discriminator && compositionKind === 'oneOf' ? detectConstPropertyDiscriminator(nonNullVariants) : null;\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 : syntheticDiscriminator\n ? { discriminator: syntheticDiscriminator }\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 'meta',\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 // that looks like pagination metadata. A `data` array alone (e.g. with only an\n // `object` discriminant companion) is NOT sufficient — the companion must indicate\n // actual pagination (cursor, metadata, total, etc.).\n if (arrayProps.length === 1 && nonArrayKeys.length >= 1) {\n const arrayPropName = arrayProps[0];\n\n const hasPaginationCompanion = nonArrayKeys.some((key) =>\n PAGINATION_METADATA_PATTERNS.some((pattern) => key.toLowerCase().includes(pattern)),\n );\n\n if (KNOWN_DATA_PATHS.has(arrayPropName) && hasPaginationCompanion) {\n return { isEnvelope: true, dataPath: arrayPropName };\n }\n\n // Non-standard array property name — still treat as envelope if pagination companion exists\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 ParameterGroup,\n TypeRef,\n ErrorResponse,\n SuccessResponse,\n SecurityRequirement,\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 ParameterGroupExtension {\n optional: boolean;\n variants: Record<string, string[]>;\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 security?: Array<Record<string, string[]>>;\n 'x-mutually-exclusive-parameter-groups'?: Record<string, ParameterGroupExtension>;\n 'x-mutually-exclusive-body-groups'?: Record<string, ParameterGroupExtension>;\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 style?: string;\n explode?: boolean;\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 serviceName,\n );\n inlineModels.push(...opModels);\n const ops = serviceMap.get(serviceName) ?? [];\n ops.push(operation);\n serviceMap.set(serviceName, ops);\n }\n }\n\n // Split services when a single tag groups operations from multiple path prefixes.\n // Example: /organizations and /organization_domains both tagged \"organizations\"\n // should become separate services based on their first path segment.\n for (const [serviceName, operations] of serviceMap) {\n const pathGroups = new Map<string, Operation[]>();\n for (const op of operations) {\n const firstSeg = op.path.split('/').filter(Boolean)[0] ?? '';\n const groupKey = firstSeg.startsWith('{') ? serviceName : toPascalCase(firstSeg);\n const group = pathGroups.get(groupKey) ?? [];\n group.push(op);\n pathGroups.set(groupKey, group);\n }\n // Only split if there are multiple distinct path-prefix groups AND\n // at least one group name differs from the current service name\n if (pathGroups.size > 1) {\n const needsSplit = [...pathGroups.keys()].some((k) => k !== serviceName);\n if (needsSplit) {\n serviceMap.delete(serviceName);\n for (const [groupName, groupOps] of pathGroups) {\n const existing = serviceMap.get(groupName) ?? [];\n existing.push(...groupOps);\n serviceMap.set(groupName, existing);\n }\n }\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\n/**\n * Extract mutually-exclusive parameter groups from the `x-mutually-exclusive-parameter-groups`\n * operation extension. Cross-references grouped parameter names against the already-extracted\n * IR parameter arrays so emitters get object-identity references.\n */\nfunction extractParameterGroups(\n op: OperationObject,\n allIRParams: Parameter[],\n operationContext: string,\n): ParameterGroup[] | undefined {\n const raw = op['x-mutually-exclusive-parameter-groups'];\n if (!raw || typeof raw !== 'object') return undefined;\n\n const paramByName = new Map<string, Parameter>();\n for (const p of allIRParams) {\n paramByName.set(p.name, p);\n }\n\n const groups: ParameterGroup[] = [];\n\n for (const [groupName, groupDef] of Object.entries(raw)) {\n if (!groupDef || typeof groupDef !== 'object') {\n throw new Error(\n `Malformed x-mutually-exclusive-parameter-groups.${groupName} in ${operationContext}: expected an object with \"optional\" and \"variants\".`,\n );\n }\n\n if (typeof groupDef.optional !== 'boolean') {\n throw new Error(\n `Malformed x-mutually-exclusive-parameter-groups.${groupName}.optional in ${operationContext}: expected a boolean.`,\n );\n }\n\n if (!groupDef.variants || typeof groupDef.variants !== 'object') {\n throw new Error(\n `Malformed x-mutually-exclusive-parameter-groups.${groupName}.variants in ${operationContext}: expected an object mapping variant names to parameter name arrays.`,\n );\n }\n\n if (Object.keys(groupDef.variants).length === 0) {\n throw new Error(\n `Malformed x-mutually-exclusive-parameter-groups.${groupName} in ${operationContext}: group has zero variants.`,\n );\n }\n\n const variants = Object.entries(groupDef.variants).map(([variantName, paramNames]) => {\n if (!Array.isArray(paramNames) || paramNames.length === 0) {\n throw new Error(\n `Malformed x-mutually-exclusive-parameter-groups.${groupName}.variants.${variantName} in ${operationContext}: expected a non-empty array of parameter names.`,\n );\n }\n const parameters: Parameter[] = paramNames.map((pName) => {\n const irParam = paramByName.get(pName);\n if (!irParam) {\n throw new Error(\n `x-mutually-exclusive-parameter-groups.${groupName}.variants.${variantName} references parameter \"${pName}\" which does not exist in the operation's parameters[] (${operationContext}).`,\n );\n }\n return irParam;\n });\n return { name: variantName, parameters };\n });\n\n groups.push({\n name: groupName,\n optional: groupDef.optional,\n variants,\n });\n }\n\n return groups.length > 0 ? groups : undefined;\n}\n\n/**\n * Extract mutually-exclusive body parameter groups from the\n * `x-mutually-exclusive-body-groups` operation extension. Unlike query\n * parameter groups (whose parameters live in operation.queryParams), body\n * group parameters are synthetic — built from the oneOf variant schemas in\n * the request body. Emitters use the group's presence to generate sum-type\n * interfaces and custom JSON marshalling instead of flat optional fields.\n */\nfunction extractBodyParameterGroups(op: OperationObject, operationContext: string): ParameterGroup[] | undefined {\n const raw = op['x-mutually-exclusive-body-groups'];\n if (!raw || typeof raw !== 'object') return undefined;\n\n // Collect the body schema's oneOf variant fields so we can resolve types.\n // The body schema has been structurally rewritten to allOf: [base, { oneOf: [...] }]\n // by the spec generator; the variant properties live inside oneOf branches.\n const bodySchema = op.requestBody?.content?.['application/json']?.schema;\n const variantFieldSchemas = new Map<string, SchemaObject>();\n\n if (bodySchema) {\n // Walk allOf → oneOf → variant.properties to find all variant fields\n for (const sub of bodySchema.allOf ?? []) {\n for (const variant of sub.oneOf ?? []) {\n if (variant.properties) {\n for (const [name, fieldSchema] of Object.entries(variant.properties)) {\n if (fieldSchema) variantFieldSchemas.set(name, fieldSchema);\n }\n }\n }\n }\n // Also check top-level oneOf (for inline schemas that aren't wrapped in allOf)\n for (const variant of bodySchema.oneOf ?? []) {\n if (variant.properties) {\n for (const [name, fieldSchema] of Object.entries(variant.properties)) {\n if (fieldSchema) variantFieldSchemas.set(name, fieldSchema);\n }\n }\n }\n }\n\n const groups: ParameterGroup[] = [];\n\n for (const [groupName, groupDef] of Object.entries(raw)) {\n if (!groupDef || typeof groupDef !== 'object') continue;\n if (typeof groupDef.optional !== 'boolean') continue;\n if (!groupDef.variants || typeof groupDef.variants !== 'object') continue;\n if (Object.keys(groupDef.variants).length === 0) continue;\n\n const variants = Object.entries(groupDef.variants).map(([variantName, paramNames]) => {\n if (!Array.isArray(paramNames) || paramNames.length === 0) {\n throw new Error(\n `Malformed x-mutually-exclusive-body-groups.${groupName}.variants.${variantName} in ${operationContext}: expected a non-empty array of parameter names.`,\n );\n }\n const parameters: Parameter[] = paramNames.map((pName) => {\n const fieldSchema = variantFieldSchemas.get(pName);\n const fieldType: TypeRef = fieldSchema\n ? schemaToTypeRef(fieldSchema, toPascalCase(pName))\n : { kind: 'primitive', type: 'string' };\n return {\n name: pName,\n type: fieldType,\n required: false, // group variant fields are always optional at the struct level\n description: fieldSchema?.description,\n };\n });\n return { name: variantName, parameters };\n });\n\n groups.push({\n name: groupName,\n optional: groupDef.optional,\n variants,\n });\n }\n\n return groups.length > 0 ? groups : undefined;\n}\n\nfunction buildOperation(\n method: HttpMethod,\n path: string,\n op: OperationObject,\n pathLevelParams: ParameterObject[],\n operationIdTransform?: (id: string) => string,\n serviceName?: 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 // Use the service name as context so inline parameter enums get qualified\n // names. e.g., service \"SSO\" + param \"provider\" → \"SSOProvider\".\n const opContext = serviceName;\n const pathParams = extractParams(allParams, 'path', opContext);\n const queryParams = extractParams(allParams, 'query', opContext);\n const headerParams = extractParams(allParams, 'header', opContext).filter(\n (p) => p.name.toLowerCase() !== 'idempotency-key',\n );\n const cookieParams = extractParams(allParams, 'cookie', opContext);\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 // Extract per-operation security overrides\n const security = extractOperationSecurity(op.security);\n\n // Extract mutually-exclusive parameter groups (query/path/header/cookie)\n const allIRParams = [...pathParams, ...queryParams, ...headerParams, ...cookieParams];\n const opLabel = op.operationId ?? `${method.toUpperCase()} ${path}`;\n const queryParamGroups = extractParameterGroups(op, allIRParams, opLabel);\n\n // Extract mutually-exclusive body parameter groups\n const bodyParamGroups = extractBodyParameterGroups(op, opLabel);\n\n // Merge both sources into a single parameterGroups array\n const parameterGroups =\n queryParamGroups || bodyParamGroups ? [...(queryParamGroups ?? []), ...(bodyParamGroups ?? [])] : undefined;\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 security,\n parameterGroups,\n },\n inlineModels,\n };\n}\n\n/**\n * Extract per-operation security requirements from an OpenAPI security directive.\n * Returns undefined when the operation uses the spec-level default security.\n *\n * OpenAPI security format: `security: [{ schemeName: [scope1, scope2] }]`\n */\nfunction extractOperationSecurity(\n security: Array<Record<string, string[]>> | undefined,\n): SecurityRequirement[] | undefined {\n if (!security || security.length === 0) return undefined;\n\n const requirements: SecurityRequirement[] = [];\n for (const entry of security) {\n for (const [schemeName, scopes] of Object.entries(entry)) {\n requirements.push({ schemeName, scopes: scopes ?? [] });\n }\n }\n return requirements.length > 0 ? requirements : undefined;\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(\n params: ParameterObject[],\n location: 'path' | 'query' | 'header' | 'cookie',\n operationContext?: string,\n): Parameter[] {\n return params\n .filter((p) => p.in === location)\n .map((p) => ({\n name: p.name,\n type: p.schema\n ? schemaToTypeRef(p.schema, p.name, operationContext ? toPascalCase(operationContext) : undefined)\n : ({ 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 style: p.style as Parameter['style'],\n explode: p.explode,\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 >= 300 && code < 400) {\n // 3xx redirects — include so emitter can detect redirect endpoints\n allSuccessResponses.push({ statusCode: code, type: { kind: 'primitive', type: 'unknown' } });\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, Service } 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\n/**\n * Collect inline enum definitions from operation parameters (query, path, header)\n * and promote them to top-level enums so emitters can generate typed enum files.\n */\nexport function collectInlineEnumsFromOperations(services: Service[], enums: Enum[]): void {\n const enumNames = new Set(enums.map((e) => e.name));\n for (const service of services) {\n for (const op of service.operations) {\n for (const param of [...op.pathParams, ...op.queryParams, ...op.headerParams, ...(op.cookieParams ?? [])]) {\n collectInlineEnumFromRef(param.type, enums, enumNames);\n }\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 { defaultSdkBehavior } from '../ir/sdk-behavior.js';\nimport { SpecParseError } from '../errors.js';\nimport { loadAndBundleSpec } from './refs.js';\nimport { extractSchemas, extractInlineModelsFromSchemas, clearSchemaNameTransform } from './schemas.js';\nimport { extractOperations } from './operations.js';\nimport {\n mergeInlineResponseModels,\n collapseJsonSuffixModels,\n mergeFieldInlineModels,\n} from './normalize-inline-models.js';\nimport { collectInlineEnumsFromModels, collectInlineEnumsFromOperations } from './collect-inline-enums.js';\nimport { validateModelRefs } from './normalize-model-refs.js';\n\nexport interface ParseOptions {\n operationIdTransform?: (id: string) => string;\n schemaNameTransform?: (name: 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 { schemaNameTransform: options?.schemaNameTransform },\n );\n\n const { services, inlineModels } = extractOperations(\n spec.paths as Record<string, Record<string, unknown>> | undefined,\n options?.operationIdTransform,\n );\n\n // schemaNameTransform is kept active through extractOperations so that\n // $ref-based TypeRefs in operations resolve to the same transformed names.\n // Now that all extraction is done, clear it.\n clearSchemaNameTransform();\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 collectInlineEnumsFromOperations(services, 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 sdk: defaultSdkBehavior(),\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","import { parseSpec } from '../parser/parse.js';\n\nexport async function parseCommand(opts: { spec: string }): Promise<void> {\n const ir = await parseSpec(opts.spec);\n console.log(JSON.stringify(ir, null, 2));\n}\n","import type Parser from 'tree-sitter';\nimport type { UrlFingerprintConfig } from './types.js';\n\n/**\n * Extract a URL path fingerprint from a method body using tree-sitter AST traversal.\n *\n * Walks the AST subtree of the member node looking for the first string literal\n * that starts with '/'. Normalizes interpolation expressions to '{}' and format\n * specifiers (%s, %d, etc.) to '{}' for cross-language comparison.\n *\n * @returns A normalized URL fingerprint like \"/organizations/{}\" or undefined if none found.\n */\nexport function extractUrlFingerprint(memberNode: Parser.SyntaxNode, config: UrlFingerprintConfig): string | undefined {\n const stringTypes = new Set(config.stringNodeTypes);\n const contentTypes = new Set(config.contentNodeTypes);\n const interpolationTypes = new Set(config.interpolationNodeTypes);\n const formatFns = config.formatFunctionNames ? new Set(config.formatFunctionNames) : null;\n\n // Iterative DFS through the method's AST subtree\n const stack: Parser.SyntaxNode[] = [memberNode];\n\n while (stack.length > 0) {\n const node = stack.pop()!;\n\n if (stringTypes.has(node.type)) {\n const fp = resolveFingerprint(node, contentTypes, interpolationTypes);\n if (fp?.startsWith('/')) return fp;\n }\n\n // For format functions (Go's Sprintf, Rust's format!): check if this call\n // matches and extract the first string argument.\n if (formatFns && isFormatCall(node, formatFns)) {\n const fp = extractFromFormatCall(node, stringTypes, contentTypes, interpolationTypes);\n if (fp?.startsWith('/')) return fp;\n }\n\n // Push children in reverse order so leftmost child is processed first\n for (let i = node.childCount - 1; i >= 0; i--) {\n const child = node.child(i);\n if (child) stack.push(child);\n }\n }\n\n return undefined;\n}\n\n/**\n * Resolve the text content of a string node, normalizing interpolations to '{}'.\n */\nfunction resolveFingerprint(\n stringNode: Parser.SyntaxNode,\n contentTypes: Set<string>,\n interpolationTypes: Set<string>,\n): string | undefined {\n // Leaf string node (no children besides quotes) — strip quotes\n if (stringNode.namedChildCount === 0) {\n return normalizeFormatSpecifiers(stripQuotes(stringNode.text));\n }\n\n // Composite string (has content fragments + interpolation children)\n let result = '';\n for (let i = 0; i < stringNode.childCount; i++) {\n const child = stringNode.child(i)!;\n if (contentTypes.has(child.type)) {\n result += child.text;\n } else if (interpolationTypes.has(child.type)) {\n result += '{}';\n }\n // Skip quote delimiters, interpolation markers, etc.\n }\n\n return result ? normalizeFormatSpecifiers(result) : normalizeFormatSpecifiers(stripQuotes(stringNode.text));\n}\n\n/** Check if a node is a call to one of the format functions (e.g., fmt.Sprintf, format!). */\nfunction isFormatCall(node: Parser.SyntaxNode, formatFns: Set<string>): boolean {\n // Rust macro: format!(...) — tree-sitter may parse as macro_invocation\n if (node.type === 'macro_invocation') {\n const macroName = node.childForFieldName('macro')?.text;\n return !!(macroName && formatFns.has(macroName.replace(/!$/, '')));\n }\n\n if (node.type !== 'call_expression') return false;\n const fnNode = node.childForFieldName('function');\n if (!fnNode) return false;\n\n // Direct call: Sprintf(...) or format!(...)\n if (formatFns.has(fnNode.text)) return true;\n\n // Member call: fmt.Sprintf(...)\n if (fnNode.type === 'selector_expression' || fnNode.type === 'member_expression') {\n const prop = fnNode.childForFieldName('field') ?? fnNode.childForFieldName('property');\n if (prop && formatFns.has(prop.text)) return true;\n }\n return false;\n}\n\n/** Extract the first string argument from a format function call. */\nfunction extractFromFormatCall(\n callNode: Parser.SyntaxNode,\n stringTypes: Set<string>,\n contentTypes: Set<string>,\n interpolationTypes: Set<string>,\n): string | undefined {\n const args = callNode.childForFieldName('arguments');\n if (!args) return undefined;\n\n for (let i = 0; i < args.childCount; i++) {\n const arg = args.child(i)!;\n if (stringTypes.has(arg.type)) {\n return resolveFingerprint(arg, contentTypes, interpolationTypes);\n }\n }\n return undefined;\n}\n\n/** Strip surrounding quote characters from a string literal. */\nfunction stripQuotes(text: string): string {\n // Handle various quote styles: \"...\", '...', `...`, f\"...\", $\"...\", @\"...\"\n const match = text.match(/^(?:f|r|b|@|\\$)?(?:\"\"\"([\\s\\S]*)\"\"\"|'''([\\s\\S]*)'''|\"(.*)\"|'(.*)'|`(.*)`)$/s);\n if (match) return match[1] ?? match[2] ?? match[3] ?? match[4] ?? match[5] ?? text;\n return text;\n}\n\n/** Replace printf-style format specifiers (%s, %d, %v, %f) with {}. */\nfunction normalizeFormatSpecifiers(s: string): string {\n return s.replace(/%[sdvf]/g, '{}');\n}\n","import type Parser from 'tree-sitter';\nimport type {\n MergeAdapter,\n MergeStatement,\n MergeImport,\n DocstringInfo,\n SymbolDocstrings,\n MemberDocstrings,\n} from './types.js';\nimport { extractUrlFingerprint } from './url-fingerprint.js';\n\nconst DOTNET_URL_FINGERPRINT_CONFIG = {\n stringNodeTypes: ['string_literal', 'interpolated_string_expression'],\n contentNodeTypes: ['string_content', 'string_literal_content'],\n interpolationNodeTypes: ['interpolation'],\n};\n\nconst DECLARATION_TYPES = new Set([\n 'class_declaration',\n 'struct_declaration',\n 'interface_declaration',\n 'enum_declaration',\n 'record_declaration',\n]);\n\nfunction extractDeclarationName(node: Parser.SyntaxNode): string | null {\n if (DECLARATION_TYPES.has(node.type)) {\n const nameNode = node.childForFieldName('name') ?? node.children.find((c) => c.type === 'identifier');\n return nameNode?.text ?? null;\n }\n if (node.type === 'namespace_declaration' || node.type === 'file_scoped_namespace_declaration') {\n const nameNode =\n node.children.find((c) => c.type === 'qualified_name') ?? node.children.find((c) => c.type === 'identifier');\n return nameNode ? `__namespace:${nameNode.text}` : null;\n }\n return null;\n}\n\nfunction collectPrecedingXmlDocComments(\n children: Parser.SyntaxNode[],\n index: number,\n source: string,\n): DocstringInfo | null {\n let lastIdx = -1;\n let firstIdx = -1;\n for (let k = index - 1; k >= 0; k--) {\n const prev = children[k];\n if (prev.type === 'comment') {\n const text = source.slice(prev.startIndex, prev.endIndex);\n if (text.startsWith('///')) {\n if (lastIdx === -1) lastIdx = k;\n firstIdx = k;\n } else {\n break;\n }\n } else {\n break;\n }\n }\n if (firstIdx === -1) return null;\n const first = children[firstIdx];\n const last = children[lastIdx];\n return { text: source.slice(first.startIndex, last.endIndex), startIndex: first.startIndex, endIndex: last.endIndex };\n}\n\n/**\n * Collect declarations from a list of sibling nodes (root level or namespace body).\n */\nfunction collectDeclarations(\n children: Parser.SyntaxNode[],\n source: string,\n statements: MergeStatement[],\n imports: MergeImport[],\n importAnchors: string[],\n importInsertionAnchor: { value?: string },\n): void {\n for (const child of children) {\n if (child.type === 'comment') continue;\n\n if (child.type === 'using_directive') {\n const text = source.slice(child.startIndex, child.endIndex);\n imports.push({ key: text.trim(), text });\n importAnchors.push(text);\n continue;\n }\n\n if (child.type === 'file_scoped_namespace_declaration') {\n importInsertionAnchor.value = source.slice(child.startIndex, child.endIndex);\n // File-scoped namespace: subsequent declarations are siblings at root\n continue;\n }\n\n if (child.type === 'namespace_declaration') {\n importInsertionAnchor.value = source.slice(child.startIndex, child.endIndex);\n // Block namespace: recurse into declaration_list\n const body = child.children.find((c) => c.type === 'declaration_list');\n if (body) {\n collectDeclarations(body.namedChildren, source, statements, imports, importAnchors, importInsertionAnchor);\n }\n continue;\n }\n\n const name = extractDeclarationName(child);\n statements.push({\n key: name,\n kind: name ? 'declaration' : 'other',\n text: source.slice(child.startIndex, child.endIndex),\n });\n }\n}\n\nexport const dotnetMergeAdapter: MergeAdapter = {\n language: 'dotnet',\n grammarModule: 'tree-sitter-c-sharp',\n testFilePatterns: [/Tests?\\.cs$/],\n urlFingerprintConfig: DOTNET_URL_FINGERPRINT_CONFIG,\n parseStatements(tree, source) {\n const imports: MergeImport[] = [];\n const importAnchors: string[] = [];\n const statements: MergeStatement[] = [];\n const importInsertionAnchor: { value?: string } = {};\n\n collectDeclarations(tree.rootNode.children, source, statements, imports, importAnchors, importInsertionAnchor);\n\n return {\n imports,\n importAnchors,\n importInsertionAnchor: importInsertionAnchor.value,\n statements,\n };\n },\n renderImports(imports) {\n return imports.map((entry) => entry.text);\n },\n extractDocstrings(tree, source) {\n const result = new Map<string, SymbolDocstrings>();\n\n function processChildren(children: Parser.SyntaxNode[]): void {\n for (let i = 0; i < children.length; i++) {\n const child = children[i];\n\n // Recurse into namespaces\n if (child.type === 'namespace_declaration') {\n const body = child.children.find((c) => c.type === 'declaration_list');\n if (body) processChildren(body.children);\n continue;\n }\n\n const name = extractDeclarationName(child);\n if (!name || name.startsWith('__namespace:')) continue;\n\n const docstring = collectPrecedingXmlDocComments(children, i, source);\n const members = new Map<string, MemberDocstrings>();\n\n // Extract member docstrings\n const body = child.children.find((c) => c.type === 'declaration_list');\n if (body) {\n const bodyChildren = body.children;\n for (let j = 0; j < bodyChildren.length; j++) {\n const member = bodyChildren[j];\n if (member.type !== 'method_declaration' && member.type !== 'property_declaration') continue;\n // For methods, the second identifier is the name (first is return type)\n const identifiers = member.children.filter((c) => c.type === 'identifier');\n const memberName =\n member.type === 'method_declaration'\n ? identifiers.length >= 2\n ? identifiers[1]!.text\n : identifiers[0]?.text\n : identifiers[0]?.text;\n if (!memberName) continue;\n const memberDoc = collectPrecedingXmlDocComments(bodyChildren, j, source);\n members.set(memberName, {\n docstring: memberDoc,\n declStartIndex: member.startIndex,\n declColumn: member.startPosition.column,\n urlFingerprint: extractUrlFingerprint(member, DOTNET_URL_FINGERPRINT_CONFIG),\n });\n }\n }\n\n result.set(name, {\n docstring,\n declStartIndex: child.startIndex,\n declColumn: child.startPosition.column,\n members,\n });\n }\n }\n\n processChildren(tree.rootNode.children);\n return result;\n },\n};\n","import type Parser from 'tree-sitter';\nimport type {\n MergeAdapter,\n MergeStatement,\n MergeImport,\n DocstringInfo,\n SymbolDocstrings,\n MemberDocstrings,\n} from './types.js';\nimport { extractUrlFingerprint } from './url-fingerprint.js';\n\nconst ELIXIR_URL_FINGERPRINT_CONFIG = {\n stringNodeTypes: ['string'],\n contentNodeTypes: ['quoted_content'],\n interpolationNodeTypes: ['interpolation'],\n};\n\nfunction isDefmodule(node: Parser.SyntaxNode): boolean {\n return node.type === 'call' && node.children[0]?.text === 'defmodule';\n}\n\nfunction getModuleName(node: Parser.SyntaxNode): string | null {\n if (!isDefmodule(node)) return null;\n const args = node.children.find((c) => c.type === 'arguments');\n if (!args) return null;\n const alias = args.children.find((c) => c.type === 'alias');\n return alias?.text ?? null;\n}\n\nfunction getDoBlock(node: Parser.SyntaxNode): Parser.SyntaxNode | null {\n return node.children.find((c) => c.type === 'do_block') ?? null;\n}\n\n/** Check if a node is an @moduledoc or @doc attribute. */\nfunction isDocAttribute(node: Parser.SyntaxNode): string | null {\n if (node.type !== 'unary_operator') return null;\n const call = node.children.find((c) => c.type === 'call');\n if (!call) return null;\n const id = call.children.find((c) => c.type === 'identifier');\n if (id?.text === 'moduledoc' || id?.text === 'doc') return id.text;\n return null;\n}\n\n/** Check if a node is a def/defp call. */\nfunction getDefName(node: Parser.SyntaxNode): string | null {\n if (node.type !== 'call') return null;\n const id = node.children[0];\n if (!id || (id.text !== 'def' && id.text !== 'defp')) return null;\n const args = node.children.find((c) => c.type === 'arguments');\n if (!args) return null;\n // The function name is either a simple identifier or a call (for functions with params)\n for (const arg of args.namedChildren) {\n if (arg.type === 'identifier') return arg.text;\n if (arg.type === 'call') {\n const nameNode = arg.children.find((c) => c.type === 'identifier');\n return nameNode?.text ?? null;\n }\n }\n return null;\n}\n\n/** Check if a node is an alias/import/require/use call. */\nfunction isImportLike(node: Parser.SyntaxNode): boolean {\n if (node.type !== 'call') return false;\n const id = node.children[0];\n return id?.type === 'identifier' && ['alias', 'import', 'require', 'use'].includes(id.text);\n}\n\nexport const elixirMergeAdapter: MergeAdapter = {\n language: 'elixir',\n grammarModule: 'tree-sitter-elixir',\n testFilePatterns: [/_test\\.exs$/],\n urlFingerprintConfig: ELIXIR_URL_FINGERPRINT_CONFIG,\n parseStatements(tree, source) {\n const imports: MergeImport[] = [];\n const importAnchors: string[] = [];\n const statements: MergeStatement[] = [];\n\n for (const child of tree.rootNode.children) {\n if (child.type === 'comment') continue;\n\n // Top-level alias/import/require/use (rare but possible outside modules)\n if (isImportLike(child)) {\n const text = source.slice(child.startIndex, child.endIndex);\n imports.push({ key: text.trim(), text });\n importAnchors.push(text);\n continue;\n }\n\n const moduleName = getModuleName(child);\n statements.push({\n key: moduleName,\n kind: moduleName ? 'declaration' : 'other',\n text: source.slice(child.startIndex, child.endIndex),\n });\n }\n\n return { imports, importAnchors, statements };\n },\n renderImports(imports) {\n return imports.map((entry) => entry.text);\n },\n extractDocstrings(tree, source) {\n const result = new Map<string, SymbolDocstrings>();\n const rootChildren = tree.rootNode.children;\n\n for (let i = 0; i < rootChildren.length; i++) {\n const child = rootChildren[i];\n const moduleName = getModuleName(child);\n if (!moduleName) continue;\n\n // Look for @moduledoc inside the do_block\n let docstring: DocstringInfo | null = null;\n const doBlock = getDoBlock(child);\n const members = new Map<string, MemberDocstrings>();\n\n if (doBlock) {\n const bodyChildren = doBlock.children;\n\n // Find @moduledoc\n for (const bodyChild of bodyChildren) {\n if (isDocAttribute(bodyChild) === 'moduledoc') {\n docstring = {\n text: source.slice(bodyChild.startIndex, bodyChild.endIndex),\n startIndex: bodyChild.startIndex,\n endIndex: bodyChild.endIndex,\n };\n break;\n }\n }\n\n // Find @doc + def pairs for member docstrings\n for (let j = 0; j < bodyChildren.length; j++) {\n const bodyChild = bodyChildren[j];\n const defName = getDefName(bodyChild);\n if (!defName) continue;\n\n // Look for preceding @doc attribute\n let memberDoc: DocstringInfo | null = null;\n for (let k = j - 1; k >= 0; k--) {\n const prev = bodyChildren[k];\n if (isDocAttribute(prev) === 'doc') {\n memberDoc = {\n text: source.slice(prev.startIndex, prev.endIndex),\n startIndex: prev.startIndex,\n endIndex: prev.endIndex,\n };\n break;\n }\n if (prev.type === 'comment') continue;\n break;\n }\n\n members.set(defName, {\n docstring: memberDoc,\n declStartIndex: bodyChild.startIndex,\n declColumn: bodyChild.startPosition.column,\n urlFingerprint: extractUrlFingerprint(bodyChild, ELIXIR_URL_FINGERPRINT_CONFIG),\n });\n }\n }\n\n result.set(moduleName, {\n docstring,\n declStartIndex: child.startIndex,\n declColumn: child.startPosition.column,\n members,\n });\n }\n\n return result;\n },\n};\n","import type Parser from 'tree-sitter';\nimport type { MergeAdapter, MergeStatement, MergeImport, DocstringInfo, SymbolDocstrings } from './types.js';\n\nconst GO_URL_FINGERPRINT_CONFIG = {\n stringNodeTypes: ['interpreted_string_literal'],\n contentNodeTypes: ['interpreted_string_literal_content'],\n interpolationNodeTypes: [],\n formatFunctionNames: ['Sprintf'],\n};\n\nfunction lastIdentifier(text: string): string | null {\n const matches = [...text.matchAll(/[A-Za-z_][A-Za-z0-9_]*/g)];\n return matches.length > 0 ? matches[matches.length - 1]![0] : null;\n}\n\nfunction receiverKey(node: Parser.SyntaxNode): string | null {\n const receiver = node.childForFieldName('receiver');\n if (!receiver) return null;\n return lastIdentifier(receiver.text);\n}\n\nfunction declarationKey(node: Parser.SyntaxNode): string | null {\n switch (node.type) {\n case 'package_clause': {\n const pkg = lastIdentifier(node.text);\n return pkg ? `__package:${pkg}` : '__package:';\n }\n case 'type_declaration': {\n const spec = node.firstNamedChild?.type === 'type_spec' ? node.firstNamedChild : node.namedChildren[0];\n const nameNode = spec?.childForFieldName('name');\n return nameNode?.text ?? null;\n }\n case 'function_declaration': {\n return node.childForFieldName('name')?.text ?? null;\n }\n case 'method_declaration': {\n const name = node.childForFieldName('name')?.text ?? null;\n const receiver = receiverKey(node);\n return name && receiver ? `method:${receiver}.${name}` : name;\n }\n case 'const_declaration':\n case 'var_declaration': {\n return node.text.split(/\\s+/).slice(0, 3).join(' ');\n }\n default:\n return null;\n }\n}\n\nfunction importEntries(node: Parser.SyntaxNode, source: string): MergeImport[] {\n const entries: MergeImport[] = [];\n\n const collect = (spec: Parser.SyntaxNode): void => {\n const path = spec.childForFieldName('path')?.text ?? spec.text;\n const name = spec.childForFieldName('name')?.text ?? '';\n const text = source.slice(spec.startIndex, spec.endIndex);\n entries.push({\n key: `${name}:${path.replace(/^\"|\"$/g, '')}`,\n text,\n });\n };\n\n for (const child of node.namedChildren) {\n if (child.type === 'import_spec') {\n collect(child);\n continue;\n }\n if (child.type === 'import_spec_list') {\n for (const spec of child.namedChildren) {\n if (spec.type === 'import_spec') collect(spec);\n }\n }\n }\n\n return entries;\n}\n\nfunction collectPrecedingGoComments(\n children: Parser.SyntaxNode[],\n index: number,\n source: string,\n): DocstringInfo | null {\n let lastIdx = -1;\n let firstIdx = -1;\n for (let k = index - 1; k >= 0; k--) {\n const prev = children[k];\n if (prev.type === 'comment') {\n const text = source.slice(prev.startIndex, prev.endIndex);\n if (text.startsWith('//')) {\n if (lastIdx === -1) lastIdx = k;\n firstIdx = k;\n } else {\n break;\n }\n } else {\n break;\n }\n }\n if (firstIdx === -1) return null;\n const first = children[firstIdx];\n const last = children[lastIdx];\n return { text: source.slice(first.startIndex, last.endIndex), startIndex: first.startIndex, endIndex: last.endIndex };\n}\n\nexport const goMergeAdapter: MergeAdapter = {\n language: 'go',\n grammarModule: 'tree-sitter-go',\n testFilePatterns: [/_test\\.go$/],\n urlFingerprintConfig: GO_URL_FINGERPRINT_CONFIG,\n parseStatements(tree, source) {\n const imports: MergeImport[] = [];\n const importAnchors: string[] = [];\n let importInsertionAnchor: string | undefined;\n const statements: MergeStatement[] = [];\n\n for (const child of tree.rootNode.children) {\n if (child.type === 'comment') continue;\n\n if (child.type === 'package_clause') {\n importInsertionAnchor = source.slice(child.startIndex, child.endIndex);\n }\n\n if (child.type === 'import_declaration') {\n imports.push(...importEntries(child, source));\n importAnchors.push(source.slice(child.startIndex, child.endIndex));\n continue;\n }\n\n const key = declarationKey(child);\n statements.push({\n key,\n kind: key ? 'declaration' : 'other',\n text: source.slice(child.startIndex, child.endIndex),\n });\n }\n\n return { imports, importAnchors, importInsertionAnchor, statements };\n },\n renderImports(imports) {\n if (imports.length === 0) return [];\n if (imports.length === 1) return [`import ${imports[0]!.text}`];\n return [`import (\\n${imports.map((entry) => ` ${entry.text}`).join('\\n')}\\n)`];\n },\n extractDocstrings(tree, source) {\n const result = new Map<string, SymbolDocstrings>();\n const rootChildren = tree.rootNode.children;\n\n for (let i = 0; i < rootChildren.length; i++) {\n const child = rootChildren[i];\n const key = declarationKey(child);\n if (!key || key.startsWith('__package:')) continue;\n\n const docstring = collectPrecedingGoComments(rootChildren, i, source);\n result.set(key, {\n docstring,\n declStartIndex: child.startIndex,\n declColumn: child.startPosition.column,\n members: new Map(),\n });\n }\n\n return result;\n },\n};\n","import type Parser from 'tree-sitter';\nimport type {\n MergeAdapter,\n MergeStatement,\n MergeImport,\n MergeMember,\n DeepMergeSymbol,\n DocstringInfo,\n SymbolDocstrings,\n MemberDocstrings,\n} from './types.js';\nimport { extractUrlFingerprint } from './url-fingerprint.js';\n\nconst KOTLIN_URL_FINGERPRINT_CONFIG = {\n stringNodeTypes: ['string_literal'],\n contentNodeTypes: ['string_content'],\n interpolationNodeTypes: ['interpolated_expression'],\n};\n\nfunction extractDeclarationName(node: Parser.SyntaxNode): string | null {\n if (node.type === 'class_declaration') {\n // Handles class, data class, enum class, etc.\n const nameNode = node.children.find((c) => c.type === 'type_identifier');\n return nameNode?.text ?? null;\n }\n if (node.type === 'function_declaration') {\n const nameNode = node.children.find((c) => c.type === 'simple_identifier');\n return nameNode?.text ?? null;\n }\n if (node.type === 'object_declaration') {\n const nameNode = node.children.find((c) => c.type === 'type_identifier');\n return nameNode?.text ?? null;\n }\n if (node.type === 'type_alias') {\n const nameNode = node.children.find((c) => c.type === 'type_identifier');\n return nameNode?.text ?? null;\n }\n if (node.type === 'property_declaration') {\n const nameNode = node.children.find((c) => c.type === 'variable_declaration');\n if (nameNode) {\n const id = nameNode.children.find((c) => c.type === 'simple_identifier');\n return id?.text ?? null;\n }\n }\n return null;\n}\n\nfunction findPrecedingKdoc(children: Parser.SyntaxNode[], index: number, source: string): DocstringInfo | null {\n for (let k = index - 1; k >= 0; k--) {\n const prev = children[k];\n if (prev.type === 'multiline_comment') {\n const text = source.slice(prev.startIndex, prev.endIndex);\n if (text.startsWith('/**')) {\n return { text, startIndex: prev.startIndex, endIndex: prev.endIndex };\n }\n return null;\n }\n if (prev.type === 'line_comment') continue;\n return null;\n }\n return null;\n}\n\nfunction extractKotlinClassMembers(classBody: Parser.SyntaxNode, source: string): MergeMember[] {\n const members: MergeMember[] = [];\n const children = classBody.namedChildren;\n\n for (let i = 0; i < children.length; i++) {\n const child = children[i];\n let memberName: string | null = null;\n\n if (child.type === 'property_declaration') {\n const varDecl = child.children.find((c) => c.type === 'variable_declaration');\n memberName = varDecl?.children.find((c) => c.type === 'simple_identifier')?.text ?? null;\n } else if (child.type === 'function_declaration') {\n memberName = child.children.find((c) => c.type === 'simple_identifier')?.text ?? null;\n } else if (child.type === 'companion_object') {\n memberName = 'companion';\n }\n\n if (!memberName) continue;\n\n // Fold trailing getter/setter into the property's text span\n let endIdx = child.endIndex;\n if (child.type === 'property_declaration') {\n while (i + 1 < children.length) {\n const next = children[i + 1];\n if (next.type === 'getter' || next.type === 'setter') {\n endIdx = next.endIndex;\n i++;\n } else {\n break;\n }\n }\n }\n\n // Include preceding KDoc comment in the text span so deep merge\n // inserts the member with its documentation intact.\n let startIdx = child.startIndex;\n for (let k = i - 1; k >= 0; k--) {\n const prev = children[k];\n if (prev.type === 'multiline_comment') {\n const text = source.slice(prev.startIndex, prev.endIndex);\n if (text.startsWith('/**')) startIdx = prev.startIndex;\n break;\n }\n if (prev.type === 'line_comment') continue;\n break;\n }\n\n members.push({ key: memberName, text: source.slice(startIdx, endIdx) });\n }\n\n return members;\n}\n\nexport const kotlinMergeAdapter: MergeAdapter = {\n language: 'kotlin',\n grammarModule: 'tree-sitter-kotlin',\n testFilePatterns: [/Test\\.kt$/],\n urlFingerprintConfig: KOTLIN_URL_FINGERPRINT_CONFIG,\n parseStatements(tree, source) {\n const imports: MergeImport[] = [];\n const importAnchors: string[] = [];\n const statements: MergeStatement[] = [];\n\n for (const child of tree.rootNode.children) {\n if (child.type === 'multiline_comment' || child.type === 'line_comment') continue;\n\n if (child.type === 'import_list') {\n const fullText = source.slice(child.startIndex, child.endIndex);\n importAnchors.push(fullText);\n for (const imp of child.namedChildren) {\n if (imp.type === 'import_header') {\n const text = source.slice(imp.startIndex, imp.endIndex).trim();\n // Key on the full import path\n const idNode = imp.children.find((c) => c.type === 'identifier');\n const key = idNode?.text ?? text;\n imports.push({ key, text });\n }\n }\n continue;\n }\n\n const name = extractDeclarationName(child);\n statements.push({\n key: name,\n kind: name ? 'declaration' : 'other',\n text: source.slice(child.startIndex, child.endIndex),\n });\n }\n\n return { imports, importAnchors, statements };\n },\n renderImports(imports) {\n return imports.map((entry) => entry.text);\n },\n shouldSkipDeepMerge(_symbolName, existingMemberKeys, newMembers) {\n // Skip if new members reference instance properties that don't exist in the target\n const newText = newMembers.map((m) => m.text).join('\\n');\n for (const match of newText.matchAll(/this\\.(\\w+)/g)) {\n const propName = match[1];\n if (propName && !existingMemberKeys.has(propName)) return true;\n }\n return false;\n },\n extractMembers(tree, source) {\n const result = new Map<string, DeepMergeSymbol>();\n\n for (const child of tree.rootNode.children) {\n if (child.type !== 'class_declaration') continue;\n const nameNode = child.children.find((c) => c.type === 'type_identifier');\n if (!nameNode) continue;\n const body = child.children.find((c) => c.type === 'class_body');\n if (!body) continue;\n\n const members = extractKotlinClassMembers(body, source);\n const firstMember = body.firstNamedChild;\n const memberIndent = firstMember ? ' '.repeat(firstMember.startPosition.column) : undefined;\n result.set(nameNode.text, { members, bodyEndLine: body.endPosition.row, memberIndent });\n }\n\n return result;\n },\n extractDocstrings(tree, source) {\n const result = new Map<string, SymbolDocstrings>();\n const rootChildren = tree.rootNode.children;\n\n for (let i = 0; i < rootChildren.length; i++) {\n const child = rootChildren[i];\n const name = extractDeclarationName(child);\n if (!name) continue;\n\n const docstring = findPrecedingKdoc(rootChildren, i, source);\n const members = new Map<string, MemberDocstrings>();\n\n // Extract member docstrings for classes\n if (child.type === 'class_declaration') {\n const body = child.children.find((c) => c.type === 'class_body' || c.type === 'enum_class_body');\n if (body) {\n const bodyChildren = body.children;\n for (let j = 0; j < bodyChildren.length; j++) {\n const member = bodyChildren[j];\n const memberName = extractDeclarationName(member);\n if (!memberName) continue;\n const memberDoc = findPrecedingKdoc(bodyChildren, j, source);\n members.set(memberName, {\n docstring: memberDoc,\n declStartIndex: member.startIndex,\n declColumn: member.startPosition.column,\n urlFingerprint: extractUrlFingerprint(member, KOTLIN_URL_FINGERPRINT_CONFIG),\n });\n }\n }\n }\n\n result.set(name, {\n docstring,\n declStartIndex: child.startIndex,\n declColumn: child.startPosition.column,\n members,\n });\n }\n\n return result;\n },\n};\n","import type Parser from 'tree-sitter';\nimport { normalizeJsExtension } from '../../utils/naming.js';\nimport type {\n MergeAdapter,\n MergeStatement,\n MergeImport,\n DeepMergeSymbol,\n MergeMember,\n DocstringInfo,\n SymbolDocstrings,\n} from './types.js';\nimport { extractUrlFingerprint } from './url-fingerprint.js';\n\nconst REEXPORT_PREFIX = '__export:';\n\nfunction extractDeclName(node: Parser.SyntaxNode): string | null {\n const nameNode = node.childForFieldName('name');\n if (nameNode) return nameNode.text;\n\n if (node.type === 'lexical_declaration') {\n const declarator = node.firstNamedChild;\n if (declarator?.type === 'variable_declarator') {\n const name = declarator.childForFieldName('name');\n if (name) return name.text;\n }\n }\n\n return null;\n}\n\nfunction extractNodeKey(node: Parser.SyntaxNode): { key: string | null; kind: MergeStatement['kind'] } {\n if (node.type === 'export_statement') {\n const decl = node.childForFieldName('declaration');\n if (decl) {\n return { key: extractDeclName(decl), kind: 'declaration' };\n }\n\n const source = node.childForFieldName('source');\n if (source) {\n return { key: `${REEXPORT_PREFIX}${normalizeJsExtension(source.text)}`, kind: 'reexport' };\n }\n\n return { key: null, kind: 'other' };\n }\n return { key: extractDeclName(node), kind: extractDeclName(node) ? 'declaration' : 'other' };\n}\n\nfunction extractClassMembers(classBody: Parser.SyntaxNode, source: string): MergeMember[] {\n const members: MergeMember[] = [];\n for (const child of classBody.namedChildren) {\n if (child.type === 'method_definition') {\n const nameNode = child.childForFieldName('name');\n if (nameNode && nameNode.text !== 'constructor') {\n members.push({ key: nameNode.text, text: source.slice(child.startIndex, child.endIndex) });\n }\n } else if (child.type === 'public_field_definition') {\n const nameNode = child.childForFieldName('name');\n if (nameNode) {\n // tree-sitter may exclude the trailing semicolon from\n // public_field_definition nodes — include it if present\n let endIdx = child.endIndex;\n if (source[endIdx] === ';') {\n endIdx += 1;\n }\n members.push({ key: nameNode.text, text: source.slice(child.startIndex, endIdx) });\n }\n }\n }\n return members;\n}\n\nfunction extractInterfaceMembers(body: Parser.SyntaxNode, source: string): MergeMember[] {\n const members: MergeMember[] = [];\n for (const child of body.namedChildren) {\n if (child.type === 'property_signature' || child.type === 'method_signature') {\n const nameNode = child.childForFieldName('name');\n if (nameNode) {\n members.push({ key: nameNode.text, text: source.slice(child.startIndex, child.endIndex) });\n }\n }\n }\n return members;\n}\n\nfunction extractEnumMembers(body: Parser.SyntaxNode, source: string): MergeMember[] {\n const members: MergeMember[] = [];\n for (const child of body.namedChildren) {\n if (child.type === 'enum_assignment') {\n const nameNode = child.childForFieldName('name');\n if (nameNode) {\n members.push({ key: nameNode.text, text: source.slice(child.startIndex, child.endIndex) });\n }\n } else if (child.type === 'property_identifier') {\n members.push({ key: child.text, text: source.slice(child.startIndex, child.endIndex) });\n }\n }\n return members;\n}\n\nfunction isCommentNode(node: Parser.SyntaxNode): boolean {\n // tree-sitter extras (comments) may report the parent node's type\n // instead of 'comment' — check grammarType as fallback\n return node.type === 'comment' || (node as any).grammarType === 'comment';\n}\n\nfunction findPrecedingDocstring(children: Parser.SyntaxNode[], index: number, source: string): DocstringInfo | null {\n for (let k = index - 1; k >= 0; k--) {\n const prev = children[k];\n if (isCommentNode(prev)) {\n const text = source.slice(prev.startIndex, prev.endIndex);\n if (text.startsWith('/**')) {\n return { text, startIndex: prev.startIndex, endIndex: prev.endIndex };\n }\n return null;\n }\n if (prev.type === ',' || prev.type === ';' || prev.type === '{') continue;\n return null;\n }\n return null;\n}\n\nconst CLASS_MEMBER_TYPES = new Set(['method_definition', 'public_field_definition']);\nconst INTERFACE_MEMBER_TYPES = new Set(['property_signature', 'method_signature']);\nconst ENUM_MEMBER_TYPES = new Set(['enum_assignment', 'property_identifier']);\n\nconst NODE_URL_FINGERPRINT_CONFIG = {\n stringNodeTypes: ['string', 'template_string'],\n contentNodeTypes: ['string_fragment'],\n interpolationNodeTypes: ['template_substitution'],\n};\n\nfunction extractBodyMemberDocstrings(\n body: Parser.SyntaxNode,\n source: string,\n memberTypes: Set<string>,\n): Map<\n string,\n { docstring: DocstringInfo | null; declStartIndex: number; declColumn: number; urlFingerprint?: string }\n> {\n const result = new Map<\n string,\n { docstring: DocstringInfo | null; declStartIndex: number; declColumn: number; urlFingerprint?: string }\n >();\n const allChildren = body.children;\n for (let i = 0; i < allChildren.length; i++) {\n const child = allChildren[i];\n if (!memberTypes.has(child.type)) continue;\n let memberName: string | null = null;\n if (child.type === 'property_identifier') {\n memberName = child.text;\n } else {\n const nameNode = child.childForFieldName('name');\n if (nameNode) memberName = nameNode.text;\n }\n if (!memberName || memberName === 'constructor') continue;\n const docstring = findPrecedingDocstring(allChildren, i, source);\n const fp = extractUrlFingerprint(child, NODE_URL_FINGERPRINT_CONFIG);\n result.set(memberName, {\n docstring,\n declStartIndex: child.startIndex,\n declColumn: child.startPosition.column,\n urlFingerprint: fp,\n });\n }\n return result;\n}\n\nexport const nodeMergeAdapter: MergeAdapter = {\n language: 'node',\n grammarModule: 'tree-sitter-typescript/bindings/node/typescript.js',\n normalizeReexport: normalizeJsExtension,\n testFilePatterns: [/\\.(spec|test)\\.[jt]sx?$/],\n urlFingerprintConfig: NODE_URL_FINGERPRINT_CONFIG,\n shouldSkipDeepMerge(_symbolName, existingMemberKeys, newMembers) {\n // If new members reference instance properties (this.X) that don't exist\n // in the target class, the merged code would be broken.\n // Exception: `this.workos` is always valid — it's the constructor-injected\n // WorkOS client instance that every generated resource class uses.\n const newText = newMembers.map((m) => m.text).join('\\n');\n for (const match of newText.matchAll(/this\\.(\\w+)/g)) {\n const propName = match[1];\n if (propName === 'workos') continue;\n if (propName && !existingMemberKeys.has(propName)) {\n return true;\n }\n }\n return false;\n },\n parseStatements(tree, source) {\n const imports: MergeImport[] = [];\n const importAnchors: string[] = [];\n const statements: MergeStatement[] = [];\n\n for (const child of tree.rootNode.children) {\n if (child.type === 'comment') continue;\n\n if (child.type === 'import_statement') {\n const text = source.slice(child.startIndex, child.endIndex);\n // Key on module path so `import { X }` and `import type { X }` from\n // the same module are treated as duplicates\n const sourceNode = child.childForFieldName('source');\n const modulePath = sourceNode ? normalizeJsExtension(sourceNode.text) : normalizeJsExtension(text.trim());\n imports.push({ key: modulePath, text });\n importAnchors.push(text);\n continue;\n }\n\n const { key, kind } = extractNodeKey(child);\n statements.push({\n key,\n kind,\n text: source.slice(child.startIndex, child.endIndex),\n });\n }\n\n return { imports, importAnchors, statements };\n },\n renderImports(imports) {\n return imports.map((entry) => entry.text);\n },\n extractMembers(tree, source) {\n const result = new Map<string, DeepMergeSymbol>();\n\n for (const child of tree.rootNode.children) {\n if (child.type !== 'export_statement') continue;\n const decl = child.childForFieldName('declaration');\n if (!decl) continue;\n\n const nameNode = decl.childForFieldName('name');\n if (!nameNode) continue;\n const symbolName = nameNode.text;\n\n if (decl.type === 'class_declaration') {\n const body = decl.childForFieldName('body');\n if (!body) continue;\n const members = extractClassMembers(body, source);\n const firstMember = body.firstNamedChild;\n const memberIndent = firstMember ? ' '.repeat(firstMember.startPosition.column) : undefined;\n result.set(symbolName, { members, bodyEndLine: body.endPosition.row, memberIndent });\n } else if (decl.type === 'interface_declaration') {\n const body = decl.childForFieldName('body');\n if (!body) continue;\n const members = extractInterfaceMembers(body, source);\n const firstMember = body.firstNamedChild;\n const memberIndent = firstMember ? ' '.repeat(firstMember.startPosition.column) : undefined;\n result.set(symbolName, { members, bodyEndLine: body.endPosition.row, memberIndent });\n } else if (decl.type === 'enum_declaration') {\n const body = decl.childForFieldName('body');\n if (!body) continue;\n const members = extractEnumMembers(body, source);\n const firstMember = body.firstNamedChild;\n const memberIndent = firstMember ? ' '.repeat(firstMember.startPosition.column) : undefined;\n result.set(symbolName, { members, bodyEndLine: body.endPosition.row, memberIndent });\n }\n }\n\n return result;\n },\n extractDocstrings(tree, source) {\n const result = new Map<string, SymbolDocstrings>();\n const rootChildren = tree.rootNode.children;\n\n for (let i = 0; i < rootChildren.length; i++) {\n const child = rootChildren[i];\n if (child.type !== 'export_statement') continue;\n const decl = child.childForFieldName('declaration');\n if (!decl) continue;\n const nameNode = decl.childForFieldName('name');\n if (!nameNode) continue;\n\n // Find preceding JSDoc for this top-level symbol\n const docstring = findPrecedingDocstring(rootChildren, i, source);\n\n // Extract member-level docstrings\n let members = new Map<string, { docstring: DocstringInfo | null; declStartIndex: number; declColumn: number }>();\n const body = decl.childForFieldName('body');\n if (body) {\n if (decl.type === 'class_declaration') {\n members = extractBodyMemberDocstrings(body, source, CLASS_MEMBER_TYPES);\n } else if (decl.type === 'interface_declaration') {\n members = extractBodyMemberDocstrings(body, source, INTERFACE_MEMBER_TYPES);\n } else if (decl.type === 'enum_declaration') {\n members = extractBodyMemberDocstrings(body, source, ENUM_MEMBER_TYPES);\n }\n }\n\n result.set(nameNode.text, {\n docstring,\n declStartIndex: child.startIndex,\n declColumn: child.startPosition.column,\n members,\n });\n }\n\n return result;\n },\n};\n","import type Parser from 'tree-sitter';\nimport type {\n MergeAdapter,\n MergeStatement,\n MergeImport,\n DocstringInfo,\n SymbolDocstrings,\n MemberDocstrings,\n} from './types.js';\nimport { extractUrlFingerprint } from './url-fingerprint.js';\n\nconst PHP_URL_FINGERPRINT_CONFIG = {\n stringNodeTypes: ['encapsed_string', 'string'],\n contentNodeTypes: ['string_content'],\n interpolationNodeTypes: ['variable_name'],\n};\n\nfunction extractPhpDeclarationName(node: Parser.SyntaxNode): string | null {\n switch (node.type) {\n case 'class_declaration':\n case 'interface_declaration':\n case 'trait_declaration':\n case 'enum_declaration':\n case 'function_definition': {\n const nameNode = node.childForFieldName('name');\n return nameNode?.text ?? null;\n }\n case 'namespace_definition': {\n const nameNode = node.childForFieldName('name');\n return nameNode ? `__namespace:${nameNode.text}` : '__namespace:';\n }\n default:\n return null;\n }\n}\n\nfunction findPhpDocstring(children: Parser.SyntaxNode[], index: number, source: string): DocstringInfo | null {\n for (let k = index - 1; k >= 0; k--) {\n const prev = children[k];\n if (prev.type === 'comment') {\n const text = source.slice(prev.startIndex, prev.endIndex);\n if (text.startsWith('/**')) {\n return { text, startIndex: prev.startIndex, endIndex: prev.endIndex };\n }\n return null;\n }\n if (prev.type === ';' || prev.type === '{') continue;\n return null;\n }\n return null;\n}\n\nexport const phpMergeAdapter: MergeAdapter = {\n language: 'php',\n grammarModule: 'tree-sitter-php',\n testFilePatterns: [/Test\\.php$/],\n urlFingerprintConfig: PHP_URL_FINGERPRINT_CONFIG,\n resolveGrammar: (mod) => {\n // ESM import wraps in { default: { php, php_only } }\n const m = (mod as Record<string, unknown>)?.default ?? mod;\n if (typeof m === 'object' && m !== null && 'php' in (m as Record<string, unknown>))\n return (m as { php: unknown }).php;\n return m;\n },\n parseStatements(tree, source) {\n const imports: MergeImport[] = [];\n const importAnchors: string[] = [];\n let importInsertionAnchor: string | undefined;\n const statements: MergeStatement[] = [];\n\n for (const child of tree.rootNode.children) {\n if (child.type === 'comment') continue;\n\n if (child.type === 'namespace_definition') {\n importInsertionAnchor = source.slice(child.startIndex, child.endIndex);\n }\n\n if (child.type === 'namespace_use_declaration') {\n const text = source.slice(child.startIndex, child.endIndex);\n imports.push({ key: text.trim(), text });\n importAnchors.push(text);\n continue;\n }\n\n const declarationName = extractPhpDeclarationName(child);\n const kind: MergeStatement['kind'] = declarationName ? 'declaration' : 'other';\n\n statements.push({\n key: declarationName,\n kind,\n text: source.slice(child.startIndex, child.endIndex),\n });\n }\n\n return { imports, importAnchors, importInsertionAnchor, statements };\n },\n renderImports(imports) {\n return imports.map((entry) => entry.text);\n },\n extractDocstrings(tree, source) {\n const result = new Map<string, SymbolDocstrings>();\n const rootChildren = tree.rootNode.children;\n\n for (let i = 0; i < rootChildren.length; i++) {\n const child = rootChildren[i];\n const name = extractPhpDeclarationName(child);\n if (!name || name.startsWith('__namespace:')) continue;\n\n const docstring = findPhpDocstring(rootChildren, i, source);\n const members = new Map<string, MemberDocstrings>();\n\n const body = child.childForFieldName('body');\n if (body) {\n const bodyChildren = body.children;\n for (let j = 0; j < bodyChildren.length; j++) {\n const member = bodyChildren[j];\n if (member.type !== 'method_declaration') continue;\n const memberName = member.childForFieldName('name')?.text;\n if (!memberName) continue;\n const memberDoc = findPhpDocstring(bodyChildren, j, source);\n members.set(memberName, {\n docstring: memberDoc,\n declStartIndex: member.startIndex,\n declColumn: member.startPosition.column,\n urlFingerprint: extractUrlFingerprint(member, PHP_URL_FINGERPRINT_CONFIG),\n });\n }\n }\n\n result.set(name, {\n docstring,\n declStartIndex: child.startIndex,\n declColumn: child.startPosition.column,\n members,\n });\n }\n\n return result;\n },\n};\n","import type Parser from 'tree-sitter';\nimport type {\n MergeAdapter,\n MergeStatement,\n MergeImport,\n DocstringInfo,\n SymbolDocstrings,\n MemberDocstrings,\n} from './types.js';\nimport { extractUrlFingerprint } from './url-fingerprint.js';\n\nconst PYTHON_URL_FINGERPRINT_CONFIG = {\n stringNodeTypes: ['string'],\n contentNodeTypes: ['string_content'],\n interpolationNodeTypes: ['interpolation'],\n};\n\nfunction extractPythonDeclarationName(node: Parser.SyntaxNode): string | null {\n if (node.type === 'class_definition' || node.type === 'function_definition') {\n const nameNode = node.childForFieldName('name');\n return nameNode?.text ?? null;\n }\n\n // Detect `__all__ = [...]` assignments so they get a key and can be deduplicated\n if (node.type === 'expression_statement') {\n const firstChild = node.firstNamedChild;\n if (firstChild?.type === 'assignment') {\n const left = firstChild.childForFieldName('left');\n if (left?.type === 'identifier' && left.text === '__all__') {\n return '__all__';\n }\n }\n }\n\n return null;\n}\n\nfunction extractPythonDocstring(bodyNode: Parser.SyntaxNode, source: string): DocstringInfo | null {\n // Python docstrings are the first expression_statement in a body block\n // where the expression is a string literal\n for (const child of bodyNode.namedChildren) {\n if (child.type === 'expression_statement') {\n const expr = child.firstNamedChild;\n if (expr?.type === 'string') {\n const text = source.slice(child.startIndex, child.endIndex);\n return { text, startIndex: child.startIndex, endIndex: child.endIndex };\n }\n }\n // Only the FIRST statement can be a docstring\n break;\n }\n return null;\n}\n\nfunction collectPrecedingPythonComments(\n children: Parser.SyntaxNode[],\n index: number,\n source: string,\n): DocstringInfo | null {\n let lastIdx = -1;\n let firstIdx = -1;\n for (let k = index - 1; k >= 0; k--) {\n const prev = children[k];\n if (prev.type === 'comment') {\n if (lastIdx === -1) lastIdx = k;\n firstIdx = k;\n } else {\n break;\n }\n }\n if (firstIdx === -1) return null;\n const first = children[firstIdx];\n const last = children[lastIdx];\n return { text: source.slice(first.startIndex, last.endIndex), startIndex: first.startIndex, endIndex: last.endIndex };\n}\n\nexport const pythonMergeAdapter: MergeAdapter = {\n language: 'python',\n grammarModule: 'tree-sitter-python',\n testFilePatterns: [/(?:^|\\/)test_.*\\.py$/, /_test\\.py$/],\n urlFingerprintConfig: PYTHON_URL_FINGERPRINT_CONFIG,\n parseStatements(tree, source) {\n const imports: MergeImport[] = [];\n const importAnchors: string[] = [];\n const statements: MergeStatement[] = [];\n\n for (const child of tree.rootNode.children) {\n if (child.type === 'comment') continue;\n\n if (child.type === 'import_statement' || child.type === 'import_from_statement') {\n const text = source.slice(child.startIndex, child.endIndex);\n imports.push({ key: text.trim(), text });\n importAnchors.push(text);\n continue;\n }\n\n const declarationName = extractPythonDeclarationName(child);\n const kind: MergeStatement['kind'] = declarationName ? 'declaration' : 'other';\n\n statements.push({\n key: declarationName,\n kind,\n text: source.slice(child.startIndex, child.endIndex),\n });\n }\n\n return { imports, importAnchors, statements };\n },\n renderImports(imports) {\n return imports.map((entry) => entry.text);\n },\n extractDocstrings(tree, source) {\n const result = new Map<string, SymbolDocstrings>();\n const rootChildren = tree.rootNode.children;\n\n for (let i = 0; i < rootChildren.length; i++) {\n const child = rootChildren[i];\n const name = extractPythonDeclarationName(child);\n if (!name) continue;\n\n // Python: class/function docstrings are inside the body, OR use # comments before\n let docstring: DocstringInfo | null = null;\n const body = child.childForFieldName('body');\n if (body) {\n docstring = extractPythonDocstring(body, source);\n }\n // Fallback: check for # comments before the declaration\n if (!docstring) {\n docstring = collectPrecedingPythonComments(rootChildren, i, source);\n }\n\n const members = new Map<string, MemberDocstrings>();\n\n // Extract method docstrings for classes\n if (child.type === 'class_definition' && body) {\n for (const member of body.namedChildren) {\n if (member.type !== 'function_definition') continue;\n const memberName = member.childForFieldName('name')?.text;\n if (!memberName) continue;\n\n let memberDoc: DocstringInfo | null = null;\n const memberBody = member.childForFieldName('body');\n if (memberBody) {\n memberDoc = extractPythonDocstring(memberBody, source);\n }\n\n members.set(memberName, {\n docstring: memberDoc,\n declStartIndex: member.startIndex,\n declColumn: member.startPosition.column,\n urlFingerprint: extractUrlFingerprint(member, PYTHON_URL_FINGERPRINT_CONFIG),\n });\n }\n }\n\n result.set(name, {\n docstring,\n declStartIndex: child.startIndex,\n declColumn: child.startPosition.column,\n members,\n });\n }\n\n return result;\n },\n};\n","import type Parser from 'tree-sitter';\nimport type {\n MergeAdapter,\n MergeStatement,\n MergeImport,\n DocstringInfo,\n SymbolDocstrings,\n MemberDocstrings,\n} from './types.js';\nimport { extractUrlFingerprint } from './url-fingerprint.js';\n\nconst RUBY_URL_FINGERPRINT_CONFIG = {\n stringNodeTypes: ['string'],\n contentNodeTypes: ['string_content'],\n interpolationNodeTypes: ['interpolation'],\n};\n\nfunction isRequireCall(node: Parser.SyntaxNode): boolean {\n if (node.type !== 'call') return false;\n const method = node.childForFieldName('method');\n if (!method) return false;\n return method.text === 'require' || method.text === 'require_relative';\n}\n\nfunction extractRubyDeclarationName(node: Parser.SyntaxNode): string | null {\n if (node.type !== 'class' && node.type !== 'module') return null;\n const nameNode = node.childForFieldName('name');\n return nameNode?.text ?? null;\n}\n\nfunction collectPrecedingRubyComments(\n children: Parser.SyntaxNode[],\n index: number,\n source: string,\n): DocstringInfo | null {\n let lastIdx = -1;\n let firstIdx = -1;\n for (let k = index - 1; k >= 0; k--) {\n const prev = children[k];\n const nodeType = (prev as any).grammarType ?? prev.type;\n if (nodeType === 'comment') {\n const text = source.slice(prev.startIndex, prev.endIndex);\n if (text.startsWith('#')) {\n if (lastIdx === -1) lastIdx = k;\n firstIdx = k;\n } else {\n break;\n }\n } else {\n break;\n }\n }\n if (firstIdx === -1) return null;\n const first = children[firstIdx];\n const last = children[lastIdx];\n return { text: source.slice(first.startIndex, last.endIndex), startIndex: first.startIndex, endIndex: last.endIndex };\n}\n\nexport const rubyMergeAdapter: MergeAdapter = {\n language: 'ruby',\n grammarModule: 'tree-sitter-ruby',\n testFilePatterns: [/_test\\.rb$/, /_spec\\.rb$/],\n urlFingerprintConfig: RUBY_URL_FINGERPRINT_CONFIG,\n parseStatements(tree, source) {\n const imports: MergeImport[] = [];\n const importAnchors: string[] = [];\n const statements: MergeStatement[] = [];\n\n for (const child of tree.rootNode.children) {\n if (child.type === 'comment') continue;\n\n const declarationName = extractRubyDeclarationName(child);\n if (isRequireCall(child)) {\n const text = source.slice(child.startIndex, child.endIndex);\n imports.push({ key: text.trim(), text });\n importAnchors.push(text);\n continue;\n }\n\n const kind: MergeStatement['kind'] = declarationName ? 'declaration' : 'other';\n\n statements.push({\n key: declarationName,\n kind,\n text: source.slice(child.startIndex, child.endIndex),\n });\n }\n\n return { imports, importAnchors, statements };\n },\n renderImports(imports) {\n return imports.map((entry) => entry.text);\n },\n extractDocstrings(tree, source) {\n const result = new Map<string, SymbolDocstrings>();\n const rootChildren = tree.rootNode.children;\n\n for (let i = 0; i < rootChildren.length; i++) {\n const child = rootChildren[i];\n const name = extractRubyDeclarationName(child);\n if (!name) continue;\n\n const docstring = collectPrecedingRubyComments(rootChildren, i, source);\n const members = new Map<string, MemberDocstrings>();\n\n // Ruby class/module bodies: comments may appear in class children\n // (before body_statement) or in body_statement children (between methods)\n if (child.type === 'class' || child.type === 'module') {\n const allClassChildren = child.children;\n const body = child.childForFieldName('body');\n\n // Check for comment before body_statement in class children\n // (docstring for the first method)\n let firstMethodDocFromClass: DocstringInfo | null = null;\n for (let j = 0; j < allClassChildren.length; j++) {\n if (allClassChildren[j] === body || allClassChildren[j].type === 'body_statement') {\n firstMethodDocFromClass = collectPrecedingRubyComments(allClassChildren, j, source);\n break;\n }\n }\n\n if (body) {\n const bodyChildren = body.children;\n let firstMethodHandled = false;\n for (let j = 0; j < bodyChildren.length; j++) {\n const member = bodyChildren[j];\n if (member.type !== 'method') continue;\n const memberName = member.childForFieldName('name')?.text;\n if (!memberName) continue;\n\n let memberDoc: DocstringInfo | null;\n if (!firstMethodHandled && firstMethodDocFromClass) {\n memberDoc = firstMethodDocFromClass;\n firstMethodHandled = true;\n } else {\n memberDoc = collectPrecedingRubyComments(bodyChildren, j, source);\n firstMethodHandled = true;\n }\n\n members.set(memberName, {\n docstring: memberDoc,\n declStartIndex: member.startIndex,\n declColumn: member.startPosition.column,\n urlFingerprint: extractUrlFingerprint(member, RUBY_URL_FINGERPRINT_CONFIG),\n });\n }\n }\n }\n\n result.set(name, {\n docstring,\n declStartIndex: child.startIndex,\n declColumn: child.startPosition.column,\n members,\n });\n }\n\n return result;\n },\n};\n","import type Parser from 'tree-sitter';\nimport type { MergeAdapter, MergeStatement, MergeImport, DocstringInfo, SymbolDocstrings } from './types.js';\n\nconst RUST_URL_FINGERPRINT_CONFIG = {\n stringNodeTypes: ['string_literal'],\n contentNodeTypes: ['string_content'],\n interpolationNodeTypes: [],\n};\n\nfunction declarationKey(node: Parser.SyntaxNode): string | null {\n switch (node.type) {\n case 'struct_item':\n case 'enum_item':\n case 'function_item':\n case 'trait_item':\n case 'type_item':\n case 'const_item': {\n return node.childForFieldName('name')?.text ?? null;\n }\n case 'impl_item': {\n const typeName = node.childForFieldName('type')?.text ?? 'unknown';\n const traitName = node.childForFieldName('trait')?.text;\n return traitName ? `impl:${traitName}->${typeName}` : `impl:${typeName}`;\n }\n default:\n return null;\n }\n}\n\nfunction collectPrecedingRustDocComments(\n children: Parser.SyntaxNode[],\n index: number,\n source: string,\n): DocstringInfo | null {\n let lastIdx = -1;\n let firstIdx = -1;\n for (let k = index - 1; k >= 0; k--) {\n const prev = children[k];\n if (prev.type === 'line_comment') {\n const text = source.slice(prev.startIndex, prev.endIndex);\n if (text.startsWith('///')) {\n if (lastIdx === -1) lastIdx = k;\n firstIdx = k;\n } else {\n break;\n }\n } else {\n break;\n }\n }\n if (firstIdx === -1) return null;\n const first = children[firstIdx];\n const last = children[lastIdx];\n return { text: source.slice(first.startIndex, last.endIndex), startIndex: first.startIndex, endIndex: last.endIndex };\n}\n\nexport const rustMergeAdapter: MergeAdapter = {\n language: 'rust',\n grammarModule: 'tree-sitter-rust',\n testFilePatterns: [/_test\\.rs$/, /(?:^|\\/)tests\\/.*\\.rs$/],\n urlFingerprintConfig: RUST_URL_FINGERPRINT_CONFIG,\n parseStatements(tree, source) {\n const imports: MergeImport[] = [];\n const importAnchors: string[] = [];\n const statements: MergeStatement[] = [];\n\n for (const child of tree.rootNode.children) {\n if (child.type === 'comment') continue;\n\n if (child.type === 'use_declaration') {\n const text = source.slice(child.startIndex, child.endIndex);\n imports.push({ key: text.trim(), text });\n importAnchors.push(text);\n continue;\n }\n\n const key = declarationKey(child);\n statements.push({\n key,\n kind: key ? 'declaration' : 'other',\n text: source.slice(child.startIndex, child.endIndex),\n });\n }\n\n return { imports, importAnchors, statements };\n },\n renderImports(imports) {\n return imports.map((entry) => entry.text);\n },\n extractDocstrings(tree, source) {\n const result = new Map<string, SymbolDocstrings>();\n const rootChildren = tree.rootNode.children;\n\n for (let i = 0; i < rootChildren.length; i++) {\n const child = rootChildren[i];\n const key = declarationKey(child);\n if (!key) continue;\n\n const docstring = collectPrecedingRustDocComments(rootChildren, i, source);\n result.set(key, {\n docstring,\n declStartIndex: child.startIndex,\n declColumn: child.startPosition.column,\n members: new Map(),\n });\n }\n\n return result;\n },\n};\n","import type { MergeAdapter } from './types.js';\nimport { dotnetMergeAdapter } from './dotnet.js';\nimport { elixirMergeAdapter } from './elixir.js';\nimport { goMergeAdapter } from './go.js';\nimport { kotlinMergeAdapter } from './kotlin.js';\nimport { nodeMergeAdapter } from './node.js';\nimport { phpMergeAdapter } from './php.js';\nimport { pythonMergeAdapter } from './python.js';\nimport { rubyMergeAdapter } from './ruby.js';\nimport { rustMergeAdapter } from './rust.js';\n\nconst adapters = new Map<string, MergeAdapter>([\n ['dotnet', dotnetMergeAdapter],\n ['elixir', elixirMergeAdapter],\n ['go', goMergeAdapter],\n ['kotlin', kotlinMergeAdapter],\n ['node', nodeMergeAdapter],\n ['php', phpMergeAdapter],\n ['python', pythonMergeAdapter],\n ['ruby', rubyMergeAdapter],\n ['rust', rustMergeAdapter],\n]);\n\nexport function getMergeAdapter(language: string): MergeAdapter | undefined {\n return adapters.get(language);\n}\n","/**\n * Shared tree-sitter utilities.\n *\n * tree-sitter 0.21.x has a native binding bug: its internal UTF-16 buffer is\n * 32 768 uint16 units (32 768 characters for BMP text). When the JS input\n * callback returns a string >= 32 768 chars, `napi_get_value_string_utf16`\n * overflows and the C layer throws \"Invalid argument\". Work around this by\n * supplying a chunked callback for large sources instead of a raw string.\n */\n\nimport type Parser from 'tree-sitter';\n\nconst TS_SAFE_CHUNK = 32_767;\n\nexport function safeParse(parser: Parser, source: string): Parser.Tree {\n if (source.length < TS_SAFE_CHUNK) {\n return parser.parse(source);\n }\n return parser.parse((offset: number) => source.slice(offset, offset + TS_SAFE_CHUNK));\n}\n","/**\n * AST-level file merger using tree-sitter.\n *\n * When generating into a directory that already contains files, the merger\n * parses both the existing and generated content, detects top-level symbols,\n * and only appends symbols that don't already exist. Hand-written code is\n * never modified or removed.\n *\n * Supports any language with a tree-sitter grammar package.\n */\n\nimport Parser from 'tree-sitter';\nimport { getMergeAdapter } from './merge-adapters/index.js';\nimport type { MergeImport, ParsedMergeFile, SymbolDocstrings } from './merge-adapters/types.js';\n\n// Cache parser instances per language\nconst parserCache = new Map<string, Parser>();\n\nimport { safeParse } from '../utils/tree-sitter.js';\n\n// --- @deprecated preservation ---\n\n/**\n * When replacing an existing docstring with a generated one, carry over any\n * `@deprecated` lines from the existing doc that aren't present in the\n * generated doc. This prevents hand-written deprecation notices from being\n * silently dropped during docstring refresh.\n */\nfunction preserveDeprecatedTags(existingDoc: string, generatedDoc: string): string {\n // Check if the existing docstring contains @deprecated anywhere\n if (!existingDoc.includes('@deprecated')) return generatedDoc;\n\n // If generated doc already has @deprecated, no need to merge\n if (generatedDoc.includes('@deprecated')) return generatedDoc;\n\n // Extract the @deprecated content from the existing doc.\n // Handle both multi-line (`* @deprecated ...`) and one-liner (`/** @deprecated ... */`) formats.\n const deprecatedParts: string[] = [];\n for (const line of existingDoc.split('\\n')) {\n if (/@deprecated\\b/.test(line)) {\n // Normalize to JSDoc member format: ` * @deprecated ...`\n const match = line.match(/@deprecated\\b.*/);\n if (match) {\n // Strip trailing */ and whitespace (from one-liner JSDoc like `/** @deprecated ... */`)\n const cleaned = match[0].replace(/\\s*\\*\\/\\s*$/, '');\n deprecatedParts.push(` * ${cleaned}`);\n }\n }\n }\n if (deprecatedParts.length === 0) return generatedDoc;\n\n // Insert @deprecated lines before the closing */ of the generated doc\n const closingIdx = generatedDoc.lastIndexOf('*/');\n if (closingIdx === -1) return generatedDoc;\n const before = generatedDoc.slice(0, closingIdx);\n const after = generatedDoc.slice(closingIdx);\n return before + deprecatedParts.join('\\n') + '\\n ' + after;\n}\n\n// --- @oagen-ignore region helpers ---\n\ninterface IgnoredRegion {\n startIndex: number;\n endIndex: number;\n}\n\nfunction findIgnoredRegions(source: string): IgnoredRegion[] {\n const regions: IgnoredRegion[] = [];\n const startTag = '@oagen-ignore-start';\n const endTag = '@oagen-ignore-end';\n let searchFrom = 0;\n\n while (true) {\n const startIdx = source.indexOf(startTag, searchFrom);\n if (startIdx === -1) break;\n const endIdx = source.indexOf(endTag, startIdx + startTag.length);\n if (endIdx === -1) break; // Unclosed — silently ignore\n regions.push({ startIndex: startIdx, endIndex: endIdx + endTag.length });\n searchFrom = endIdx + endTag.length;\n }\n\n return regions;\n}\n\nfunction buildIgnoredSymbolNames(docstrings: Map<string, SymbolDocstrings>, regions: IgnoredRegion[]): Set<string> {\n if (regions.length === 0) return new Set();\n const ignored = new Set<string>();\n for (const [name, info] of docstrings) {\n if (regions.some((r) => info.declStartIndex >= r.startIndex && info.declStartIndex <= r.endIndex)) {\n ignored.add(name);\n }\n }\n return ignored;\n}\n\nfunction clampIndex(value: number, contentLength: number): number {\n if (!Number.isFinite(value)) return 0;\n if (value < 0) return 0;\n if (value > contentLength) return contentLength;\n return value;\n}\n\n/**\n * Resolve the declaration line start for insertion using the current content,\n * instead of relying on parser column arithmetic. This avoids misplaced inserts\n * when parser columns/offsets drift.\n */\nfunction declarationLineStart(content: string, declStartIndex: number): number {\n const idx = clampIndex(declStartIndex, content.length);\n const prevNewline = content.lastIndexOf('\\n', Math.max(0, idx - 1));\n return prevNewline === -1 ? 0 : prevNewline + 1;\n}\n\n/**\n * Resolve a docstring range by searching for the nearest matching text before\n * the declaration start. Falls back to parser-provided offsets when search fails.\n */\nfunction resolveDocRange(\n content: string,\n docText: string,\n declStartIndex: number,\n fallbackStart: number,\n fallbackEnd: number,\n): { start: number; end: number } {\n const safeDecl = clampIndex(declStartIndex, content.length);\n const safeFallbackStart = clampIndex(fallbackStart, content.length);\n const safeFallbackEnd = clampIndex(fallbackEnd, content.length);\n const found = content.lastIndexOf(docText, safeDecl);\n if (found !== -1) {\n return { start: found, end: found + docText.length };\n }\n return { start: safeFallbackStart, end: safeFallbackEnd };\n}\n\n/**\n * Check if a tree-sitter grammar is configured for the given language.\n */\nexport function hasGrammar(language: string): boolean {\n return getMergeAdapter(language) !== undefined;\n}\n\nasync function getParser(language: string): Promise<Parser> {\n const cached = parserCache.get(language);\n if (cached) return cached;\n\n const adapter = getMergeAdapter(language);\n if (!adapter) {\n throw new Error(\n `No tree-sitter grammar configured for language \"${language}\". ` +\n `Add a merge adapter and install the corresponding tree-sitter grammar package.`,\n );\n }\n\n const mod = await import(adapter.grammarModule);\n const exported = adapter.resolveGrammar ? adapter.resolveGrammar(mod) : mod;\n const grammar = (exported as { default?: unknown }).default ?? exported;\n const parser = new Parser();\n parser.setLanguage(grammar);\n parserCache.set(language, parser);\n return parser;\n}\n\ninterface ParsedSymbols {\n names: Set<string>;\n /** Trimmed text of unnamed top-level statements (for text-based dedup) */\n unnamedTexts: Set<string>;\n}\n\n/**\n * Extract all top-level symbol names (and unnamed statement texts) from source code.\n */\nexport async function extractTopLevelSymbols(source: string, language: string): Promise<ParsedSymbols> {\n const parser = await getParser(language);\n const adapter = getMergeAdapter(language);\n if (!adapter) {\n throw new Error(`No merge adapter configured for language \"${language}\"`);\n }\n if (typeof source !== 'string') {\n throw new Error(`extractTopLevelSymbols: expected string source, got ${typeof source}`);\n }\n const tree = safeParse(parser, source);\n const names = new Set<string>();\n const unnamedTexts = new Set<string>();\n const parsed = adapter.parseStatements(tree, source);\n\n for (const imp of parsed.imports) {\n names.add(imp.key);\n }\n for (const statement of parsed.statements) {\n if (statement.key) {\n names.add(statement.key);\n } else {\n unnamedTexts.add(statement.text.trim());\n }\n }\n\n return { names, unnamedTexts };\n}\n\n/** Convenience wrapper that returns only the name set. */\nexport async function extractTopLevelNames(source: string, language: string): Promise<Set<string>> {\n return (await extractTopLevelSymbols(source, language)).names;\n}\n\n/**\n * Extract top-level statements from generated source with their names\n * and exact text span.\n */\nexport async function extractStatements(source: string, language: string): Promise<ParsedMergeFile> {\n const parser = await getParser(language);\n const adapter = getMergeAdapter(language);\n if (!adapter) {\n throw new Error(`No merge adapter configured for language \"${language}\"`);\n }\n const tree = safeParse(parser, source);\n return adapter.parseStatements(tree, source);\n}\n\n/**\n * Return a map of top-level class name → { bodyEndLine, bodyEndCol } using\n * tree-sitter. `bodyEndLine` is 0-based. For brace-delimited classes the\n * end points at the closing brace line; for indentation-delimited classes\n * it points one past the last line of the class body.\n */\nexport async function extractClassEndLines(\n source: string,\n language: string,\n): Promise<Map<string, { bodyEndLine: number }>> {\n const parser = await getParser(language);\n const tree = safeParse(parser, source);\n const map = new Map<string, { bodyEndLine: number }>();\n\n function processClassNode(node: Parser.SyntaxNode): void {\n const nameNode = node.childForFieldName('name');\n if (!nameNode) return;\n const name = nameNode.text;\n\n const body = node.childForFieldName('body');\n const endRow = body ? body.endPosition.row : node.endPosition.row;\n const lastChar = source[body ? body.endIndex - 1 : node.endIndex - 1];\n\n if (lastChar === '}') {\n map.set(name, { bodyEndLine: endRow });\n } else {\n map.set(name, { bodyEndLine: endRow + 1 });\n }\n }\n\n // Walk the tree recursively. Ruby (and Python) often nest target classes\n // inside `module Foo` / `class Outer:` containers, so a flat iteration over\n // root children would miss them.\n function walk(node: Parser.SyntaxNode): void {\n if (node.type === 'class' || node.type === 'class_definition' || node.type === 'class_declaration') {\n processClassNode(node);\n }\n if (node.type === 'decorated_definition') {\n for (const inner of node.namedChildren) {\n if (inner.type === 'class_definition') processClassNode(inner);\n }\n }\n if (node.type === 'export_statement') {\n for (const inner of node.namedChildren) {\n if (inner.type === 'class_declaration') processClassNode(inner);\n }\n }\n for (const child of node.namedChildren) walk(child);\n }\n for (const child of tree.rootNode.children) {\n walk(child);\n }\n\n return map;\n}\n\nexport interface MergeResult {\n content: string;\n added: number;\n preserved: number;\n changed: boolean;\n}\n\n/**\n * Merge generated content into an existing file.\n *\n * - Parses both files with tree-sitter\n * - Detects which top-level symbols already exist\n * - Appends only new symbols\n * - Never modifies or removes existing code\n * - Adds auto-generated header if not present\n */\nexport async function mergeIntoExisting(\n existingContent: string,\n generatedContent: string,\n language: string,\n header: string,\n): Promise<MergeResult> {\n const adapter = getMergeAdapter(language);\n if (!adapter) {\n throw new Error(`No merge adapter configured for language \"${language}\"`);\n }\n\n // Parse existing file once — extract both symbols and statements from the same AST pass\n const existingStatements = await extractStatements(existingContent, language);\n const generatedStatements = await extractStatements(generatedContent, language);\n\n const existingKeys = new Set<string>();\n const existingUnnamedTexts = new Set<string>();\n const existingImportKeys = new Set<string>();\n const existingReexports = new Set<string>();\n let lastImportEndIndex = -1;\n\n // Collect import keys AND imported identifiers (to prevent adding declarations\n // that clash with already-imported names)\n const existingImportedNames = new Set<string>();\n for (const imp of existingStatements.imports) {\n existingImportKeys.add(imp.key);\n // Extract identifiers from import text: import { Foo, Bar } from '...'\n const braceMatch = imp.text.match(/\\{([^}]+)\\}/);\n if (braceMatch) {\n for (const name of braceMatch[1].split(',')) {\n const trimmed = name.replace(/\\btype\\b/, '').trim();\n if (trimmed) existingImportedNames.add(trimmed);\n }\n }\n }\n for (const anchor of existingStatements.importAnchors) {\n const linesBefore = existingContent.slice(0, existingContent.indexOf(anchor)).split('\\n').length - 1;\n const stmtLines = anchor.split('\\n').length;\n lastImportEndIndex = linesBefore + stmtLines - 1;\n }\n if (lastImportEndIndex === -1 && existingStatements.importInsertionAnchor) {\n const linesBefore =\n existingContent.slice(0, existingContent.indexOf(existingStatements.importInsertionAnchor)).split('\\n').length -\n 1;\n const stmtLines = existingStatements.importInsertionAnchor.split('\\n').length;\n lastImportEndIndex = linesBefore + stmtLines - 1;\n }\n\n // Track all names exported by existing statements (both direct exports and\n // re-export aliases like `export { X as Y }`). Used to prevent the merger\n // from appending a re-export that introduces a duplicate exported name.\n const existingExportedNames = new Set<string>();\n\n for (const stmt of existingStatements.statements) {\n if (stmt.kind === 'reexport') {\n existingReexports.add(adapter.normalizeReexport ? adapter.normalizeReexport(stmt.text.trim()) : stmt.text.trim());\n // Collect aliased export names from re-exports\n const braceMatch = stmt.text.match(/\\{([^}]+)\\}/);\n if (braceMatch) {\n for (const part of braceMatch[1].split(',')) {\n const segments = part.trim().split(/\\s+as\\s+/);\n const exportedName = (segments[1] ?? segments[0]).trim();\n if (exportedName) existingExportedNames.add(exportedName);\n }\n }\n }\n if (stmt.key) {\n existingKeys.add(stmt.key);\n existingExportedNames.add(stmt.key);\n } else {\n existingUnnamedTexts.add(stmt.text.trim());\n }\n }\n\n const headerLine = header.trim();\n\n const newImports: MergeImport[] = [];\n const toAppend: string[] = [];\n let preserved = 0;\n\n for (const imp of generatedStatements.imports) {\n if (imp.text.trim() === headerLine) continue;\n if (existingImportKeys.has(imp.key)) {\n // The existing file already imports from this module path.\n // Check if the generated import adds identifiers not present in\n // the existing import — if so, create a supplemental import with\n // only the new identifiers. The supplemental participates in the\n // usage-based filter (below) so unused identifiers are dropped.\n const braceMatch = imp.text.match(/\\{([^}]+)\\}/);\n if (braceMatch) {\n const names = braceMatch[1]\n .split(',')\n .map((n) => n.replace(/\\btype\\b/, '').trim())\n .filter(Boolean);\n const newNames = names.filter((n) => !existingImportedNames.has(n) && !existingKeys.has(n));\n if (newNames.length > 0) {\n const isTypeImport = imp.text.trimStart().startsWith('import type');\n const prefix = isTypeImport ? 'import type' : 'import';\n const sourceMatch = imp.text.match(/from\\s+(['\"][^'\"]+['\"]);?/);\n if (sourceMatch) {\n newImports.push({\n key: imp.key + '#supplemental',\n text: `${prefix} { ${newNames.join(', ')} } from ${sourceMatch[1]};`,\n });\n }\n }\n }\n preserved++;\n continue;\n }\n // Strip out identifiers that are already imported from another path.\n // This prevents duplicates when the generated file uses a specific path\n // (e.g., '../interfaces/organization.interface') while the existing file\n // imports the same names from a barrel (e.g., '../interfaces').\n const braceMatch = imp.text.match(/\\{([^}]+)\\}/);\n if (braceMatch) {\n const names = braceMatch[1]\n .split(',')\n .map((n) => n.replace(/\\btype\\b/, '').trim())\n .filter(Boolean);\n // Check against both existing imports AND existing top-level declarations\n const isAlreadyDefined = (n: string) => existingImportedNames.has(n) || existingKeys.has(n);\n if (names.length > 0 && names.every(isAlreadyDefined)) {\n preserved++;\n continue;\n }\n // If only SOME identifiers are already defined, strip them out and keep only new ones\n if (names.some(isAlreadyDefined)) {\n const newNames = names.filter((n) => !isAlreadyDefined(n));\n if (newNames.length === 0) {\n preserved++;\n continue;\n }\n // Rebuild the import with only new identifiers\n const isTypeImport = imp.text.trimStart().startsWith('import type');\n const prefix = isTypeImport ? 'import type' : 'import';\n const sourceMatch = imp.text.match(/from\\s+(['\"][^'\"]+['\"]);?/);\n if (sourceMatch) {\n const newText = `${prefix} { ${newNames.join(', ')} } from ${sourceMatch[1]};`;\n newImports.push({ key: imp.key, text: newText });\n continue;\n }\n }\n }\n newImports.push(imp);\n }\n\n for (const stmt of generatedStatements.statements) {\n // Skip the header comment\n if (stmt.text.trim() === headerLine) continue;\n\n // Skip re-export statements that duplicate existing re-exports\n // (e.g., generated uses .js extension but existing doesn't).\n // Allow genuinely new re-exports through.\n if (stmt.kind === 'reexport') {\n const normalizedText = adapter.normalizeReexport ? adapter.normalizeReexport(stmt.text.trim()) : stmt.text.trim();\n if (existingReexports.has(normalizedText) || (stmt.key !== null && existingKeys.has(stmt.key))) {\n preserved++;\n continue;\n }\n // Also skip re-exports whose aliased names are already defined as\n // top-level exports in the existing file (e.g., generated file has\n // `export { X as deserializeFoo } from '...'` but existing file\n // already has `export const deserializeFoo = ...`).\n const braceMatch = stmt.text.match(/\\{([^}]+)\\}/);\n if (braceMatch) {\n const exportedNames = braceMatch[1]\n .split(',')\n .map((n) => {\n const parts = n.trim().split(/\\s+as\\s+/);\n return (parts[1] ?? parts[0]).trim();\n })\n .filter(Boolean);\n if (exportedNames.length > 0 && exportedNames.every((n) => existingExportedNames.has(n))) {\n preserved++;\n continue;\n }\n }\n }\n\n if (stmt.key && (existingKeys.has(stmt.key) || existingImportedNames.has(stmt.key))) {\n preserved++;\n continue;\n }\n\n if (!stmt.key) {\n if (existingUnnamedTexts.has(stmt.text.trim())) {\n preserved++;\n continue;\n }\n }\n\n toAppend.push(stmt.text);\n }\n\n if (newImports.length === 0 && toAppend.length === 0) {\n // No top-level changes — check for deep merge before returning\n if (!adapter.extractMembers) {\n // Still need to check docstring refresh below\n }\n }\n\n let result = existingContent;\n\n // Append new top-level symbols first (so deep merge can see them)\n if (toAppend.length > 0) {\n result = result.trimEnd() + '\\n\\n' + toAppend.join('\\n\\n') + '\\n';\n }\n\n // Deep merge pass: add new members to existing symbols\n // Runs after import/symbol merge so line numbers are based on the updated content\n let deepAdded = 0;\n const insertions: { line: number; text: string }[] = [];\n if (adapter.extractMembers) {\n const parser = await getParser(language);\n const resultTree = safeParse(parser, result);\n const generatedTree = safeParse(parser, generatedContent);\n const resultSymbols = adapter.extractMembers(resultTree, result);\n const generatedSymbols = adapter.extractMembers(generatedTree, generatedContent);\n\n // Build ignored symbol set from @oagen-ignore-start/@oagen-ignore-end regions\n const existingTree = safeParse(parser, existingContent);\n const existingDocs = adapter.extractDocstrings(existingTree, existingContent);\n const deepIgnoredRegions = findIgnoredRegions(existingContent);\n const deepIgnoredSymbols = buildIgnoredSymbolNames(existingDocs, deepIgnoredRegions);\n\n for (const [symbolName, genSymbol] of generatedSymbols) {\n if (deepIgnoredSymbols.has(symbolName)) continue;\n const existSymbol = resultSymbols.get(symbolName);\n if (!existSymbol) continue; // New symbol — handled by top-level append\n\n const existingMemberKeys = new Set(existSymbol.members.map((m) => m.key));\n const newMembers = genSymbol.members.filter((m) => !existingMemberKeys.has(m.key));\n\n if (newMembers.length > 0) {\n // Let the adapter decide whether to skip deep merge (e.g., when new members\n // reference dependencies the existing symbol doesn't provide)\n if (adapter.shouldSkipDeepMerge?.(symbolName, existingMemberKeys, newMembers)) {\n continue;\n }\n\n const indent = existSymbol.memberIndent ?? ' ';\n const insertText = newMembers.map((m) => indent + m.text).join('\\n\\n');\n // Leading blank line separates inserted members from existing ones.\n insertions.push({ line: existSymbol.bodyEndLine, text: '\\n' + insertText });\n deepAdded += newMembers.length;\n }\n }\n\n if (insertions.length > 0) {\n // Apply bottom-up to avoid offset shifting\n insertions.sort((a, b) => b.line - a.line);\n const resultLines = result.split('\\n');\n for (const ins of insertions) {\n resultLines.splice(ins.line, 0, ins.text);\n }\n result = resultLines.join('\\n');\n }\n }\n\n // Insert new imports only when new symbols or members were actually added.\n // This prevents orphaned imports for generated code that wasn't merged in.\n // Additionally, filter imports to only include identifiers actually used in the\n // appended/inserted code — prevents orphaned imports for generated code that\n // referenced types used in other (non-appended) generated functions.\n if (newImports.length > 0 && (toAppend.length > 0 || deepAdded > 0)) {\n // Build text of all new code that was actually added (appended + deep-merged members)\n const addedParts: string[] = [...toAppend];\n if (insertions) {\n for (const ins of insertions) {\n addedParts.push(ins.text);\n }\n }\n const addedCodeText = addedParts.join('\\n');\n\n // Filter imports to only identifiers that appear in the added code.\n // Strip individual unused identifiers from each import rather than\n // keeping/dropping the entire import — prevents orphaned imports when\n // a generated import line contains both used and unused identifiers\n // (e.g., `import { deserializeFoo, serializeFoo }` where only\n // serializeFoo is used in the appended code).\n const filteredImports: MergeImport[] = [];\n for (const imp of newImports) {\n const braceMatch = imp.text.match(/\\{([^}]+)\\}/);\n if (!braceMatch) {\n // Non-destructured import (e.g., default import) — keep as-is\n filteredImports.push(imp);\n continue;\n }\n const names = braceMatch[1]\n .split(',')\n .map((n) => n.replace(/\\btype\\b/, '').trim())\n .filter(Boolean);\n const usedNames = names.filter((name) => addedCodeText.includes(name));\n if (usedNames.length === 0) continue; // Drop entirely\n if (usedNames.length === names.length) {\n // All identifiers used — keep original import\n filteredImports.push(imp);\n } else {\n // Rebuild import with only used identifiers\n const isTypeImport = imp.text.trimStart().startsWith('import type');\n const prefix = isTypeImport ? 'import type' : 'import';\n const sourceMatch = imp.text.match(/from\\s+(['\"][^'\"]+['\"]);?/);\n if (sourceMatch) {\n filteredImports.push({\n key: imp.key,\n text: `${prefix} { ${usedNames.join(', ')} } from ${sourceMatch[1]};`,\n });\n } else {\n filteredImports.push(imp);\n }\n }\n }\n\n if (filteredImports.length > 0) {\n const renderedImports = adapter.renderImports\n ? adapter.renderImports(filteredImports)\n : filteredImports.map((entry) => entry.text);\n const lines = result.split('\\n');\n const insertIdx = lastImportEndIndex + 1;\n lines.splice(insertIdx, 0, ...renderedImports);\n result = lines.join('\\n');\n }\n }\n\n // Docstring refresh pass: update existing docstrings to match generated content\n let docstringUpdates = 0;\n {\n const parser = await getParser(language);\n const resultTree = safeParse(parser, result);\n const generatedTree = safeParse(parser, generatedContent);\n const resultDocs = adapter.extractDocstrings(resultTree, result);\n const generatedDocs = adapter.extractDocstrings(generatedTree, generatedContent);\n const docIgnoredRegions = findIgnoredRegions(result);\n const docIgnoredSymbols = buildIgnoredSymbolNames(resultDocs, docIgnoredRegions);\n\n const edits: { start: number; end: number; newText: string }[] = [];\n\n for (const [symbolName, genInfo] of generatedDocs) {\n const existInfo = resultDocs.get(symbolName);\n if (!existInfo) continue;\n if (docIgnoredSymbols.has(symbolName)) continue;\n\n // Skip header comments being treated as docstrings\n const genDoc = genInfo.docstring && genInfo.docstring.text.trim() !== headerLine ? genInfo.docstring : null;\n\n // Top-level docstring\n if (genDoc) {\n if (existInfo.docstring) {\n const isPreserved = existInfo.docstring.text.includes('@oagen-ignore');\n if (!isPreserved && existInfo.docstring.text !== genDoc.text) {\n const newText = preserveDeprecatedTags(existInfo.docstring.text, genDoc.text);\n const range = resolveDocRange(\n result,\n existInfo.docstring.text,\n existInfo.declStartIndex,\n existInfo.docstring.startIndex,\n existInfo.docstring.endIndex,\n );\n edits.push({\n start: range.start,\n end: range.end,\n newText,\n });\n docstringUpdates++;\n }\n } else {\n const lineStart = declarationLineStart(result, existInfo.declStartIndex);\n const indent = ' '.repeat(existInfo.declColumn);\n edits.push({\n start: lineStart,\n end: lineStart,\n newText: indent + genDoc.text + '\\n',\n });\n docstringUpdates++;\n }\n }\n\n // Member-level docstrings — first pass: match by name\n const matchedExistMembers = new Set<string>();\n for (const [memberName, genMember] of genInfo.members) {\n const existMember = existInfo.members.get(memberName);\n if (!existMember) continue;\n matchedExistMembers.add(memberName);\n if (!genMember.docstring) continue;\n\n if (existMember.docstring) {\n const isPreserved = existMember.docstring.text.includes('@oagen-ignore');\n if (!isPreserved && existMember.docstring.text !== genMember.docstring.text) {\n const newText = preserveDeprecatedTags(existMember.docstring.text, genMember.docstring.text);\n const range = resolveDocRange(\n result,\n existMember.docstring.text,\n existMember.declStartIndex,\n existMember.docstring.startIndex,\n existMember.docstring.endIndex,\n );\n edits.push({\n start: range.start,\n end: range.end,\n newText,\n });\n docstringUpdates++;\n }\n } else {\n const lineStart = declarationLineStart(result, existMember.declStartIndex);\n const indent = ' '.repeat(existMember.declColumn);\n edits.push({\n start: lineStart,\n end: lineStart,\n newText: indent + genMember.docstring.text + '\\n',\n });\n docstringUpdates++;\n }\n }\n\n // Member-level docstrings — second pass: URL fingerprint fallback\n // Match generated members to existing members by URL pattern when\n // name-based matching fails (e.g., generated \"find\" vs existing \"getOrganization\"\n // both call this.workos.get('/organizations/${id}')).\n //\n // Safety: only attempt fingerprint matching when there is exactly ONE\n // unmatched generated member and ONE unmatched existing member for a\n // given fingerprint. When multiple members share the same URL path\n // (e.g., POST and GET on /authorization/roles), fingerprint matching\n // is ambiguous and would swap docstrings between methods.\n const unmatchedGenByFp = new Map<\n string,\n { name: string; member: typeof genInfo.members extends Map<string, infer V> ? V : never }[]\n >();\n for (const [genName, genMember] of genInfo.members) {\n if (matchedExistMembers.has(genName)) continue; // name-matched in pass 1 (as an exist member) — skip\n if (!genMember.docstring || !genMember.urlFingerprint) continue;\n // Skip if this generated member was already name-matched\n if (existInfo.members.has(genName)) continue;\n const bucket = unmatchedGenByFp.get(genMember.urlFingerprint) ?? [];\n bucket.push({ name: genName, member: genMember });\n unmatchedGenByFp.set(genMember.urlFingerprint, bucket);\n }\n const unmatchedExistByFp = new Map<\n string,\n { name: string; member: typeof existInfo.members extends Map<string, infer V> ? V : never }[]\n >();\n for (const [existName, existMember] of existInfo.members) {\n if (matchedExistMembers.has(existName)) continue;\n if (!existMember.urlFingerprint) continue;\n const bucket = unmatchedExistByFp.get(existMember.urlFingerprint) ?? [];\n bucket.push({ name: existName, member: existMember });\n unmatchedExistByFp.set(existMember.urlFingerprint, bucket);\n }\n for (const [fp, genBucket] of unmatchedGenByFp) {\n if (genBucket.length !== 1) continue; // ambiguous — skip\n const existBucket = unmatchedExistByFp.get(fp);\n if (!existBucket || existBucket.length !== 1) continue; // ambiguous — skip\n const genMember = genBucket[0].member;\n const existEntry = existBucket[0];\n const existMember = existEntry.member;\n if (!genMember.docstring) continue;\n\n if (existMember.docstring) {\n const isPreserved = existMember.docstring.text.includes('@oagen-ignore');\n if (isPreserved) continue;\n if (existMember.docstring.text !== genMember.docstring.text) {\n const newText = preserveDeprecatedTags(existMember.docstring.text, genMember.docstring.text);\n const range = resolveDocRange(\n result,\n existMember.docstring.text,\n existMember.declStartIndex,\n existMember.docstring.startIndex,\n existMember.docstring.endIndex,\n );\n edits.push({\n start: range.start,\n end: range.end,\n newText,\n });\n docstringUpdates++;\n }\n } else {\n const lineStart = declarationLineStart(result, existMember.declStartIndex);\n const indent = ' '.repeat(existMember.declColumn);\n edits.push({\n start: lineStart,\n end: lineStart,\n newText: indent + genMember.docstring.text + '\\n',\n });\n docstringUpdates++;\n }\n matchedExistMembers.add(existEntry.name);\n }\n }\n\n if (edits.length > 0) {\n edits.sort((a, b) => b.start - a.start);\n for (const edit of edits) {\n result = result.slice(0, edit.start) + edit.newText + result.slice(edit.end);\n }\n }\n }\n\n const importsActuallyAdded =\n toAppend.length > 0 || deepAdded > 0\n ? adapter.renderImports\n ? adapter.renderImports(newImports).length\n : newImports.length\n : 0;\n const topLevelAdded = importsActuallyAdded + toAppend.length;\n const totalAdded = topLevelAdded + deepAdded;\n\n if (totalAdded === 0 && docstringUpdates === 0) {\n return { content: existingContent, added: 0, preserved, changed: false };\n }\n\n return {\n content: result,\n added: totalAdded,\n preserved,\n changed: true,\n };\n}\n","/**\n * Deep merge two parsed JSON values.\n *\n * - Objects: recursively merge, preserving existing keys not in generated\n * - Arrays: generated replaces existing entirely (generated owns array contents)\n * - Primitives: generated wins\n */\nexport function deepMergeJson(existing: unknown, generated: unknown): unknown {\n if (\n typeof existing === 'object' &&\n existing !== null &&\n !Array.isArray(existing) &&\n typeof generated === 'object' &&\n generated !== null &&\n !Array.isArray(generated)\n ) {\n const merged: Record<string, unknown> = { ...(existing as Record<string, unknown>) };\n for (const [key, value] of Object.entries(generated as Record<string, unknown>)) {\n if (key in merged) {\n merged[key] = deepMergeJson(merged[key], value);\n } else {\n merged[key] = value;\n }\n }\n return merged;\n }\n\n // Arrays and primitives: generated wins\n return generated;\n}\n","import * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport type { GeneratedFile } from './types.js';\nimport { mergeIntoExisting, hasGrammar, extractClassEndLines } from './merger.js';\nimport { deepMergeJson } from './json-merge.js';\nimport { getMergeAdapter } from './merge-adapters/index.js';\n\nexport interface WriteOptions {\n /** The emitter language (e.g., \"node\", \"ruby\"). Used to select the\n * tree-sitter grammar for AST-level merging. */\n language?: string;\n /** The auto-generated file header string. */\n header?: string;\n}\n\nexport interface WriteResult {\n written: string[];\n merged: string[];\n skipped: string[];\n identical: string[];\n ignored: string[];\n}\n\n/**\n * Write generated files to disk with AST-level merging.\n *\n * When a file already exists:\n * - skipIfExists → leave it alone entirely\n * - AST merge available → parse both, append only new symbols\n * - No grammar → skip (never clobber hand-written code)\n *\n * New files are always written in full.\n */\nexport async function writeFiles(\n files: GeneratedFile[],\n outputDir: string,\n options?: WriteOptions,\n): Promise<WriteResult> {\n const result: WriteResult = { written: [], merged: [], skipped: [], identical: [], ignored: [] };\n const sorted = [...files].sort((a, b) => a.path.localeCompare(b.path));\n const language = options?.language;\n const header = options?.header ?? '';\n\n for (const file of sorted) {\n const fullPath = path.join(outputDir, file.path);\n\n // Check if file already exists\n let existingContent: string | null = null;\n try {\n existingContent = await fs.readFile(fullPath, 'utf-8');\n } catch {\n // File doesn't exist\n }\n\n // New file → write in full\n if (existingContent === null) {\n await fs.mkdir(path.dirname(fullPath), { recursive: true });\n await fs.writeFile(fullPath, file.content, 'utf-8');\n result.written.push(file.path);\n continue;\n }\n\n // skipIfExists → hard skip, no merge (but ensure header is present)\n if (file.skipIfExists) {\n if (header && !existingContent.startsWith(header)) {\n await fs.writeFile(fullPath, header + '\\n\\n' + existingContent, 'utf-8');\n }\n result.skipped.push(file.path);\n continue;\n }\n\n // @oagen-ignore-file → skip entirely (existing file opts out of all generation)\n if (existingContent.includes('@oagen-ignore-file')) {\n result.ignored.push(file.path);\n continue;\n }\n\n // Don't merge test files into hand-written test files — generated tests are\n // designed for the standalone generated SDK and will have wrong\n // signatures/fixtures when merged into hand-written tests.\n // However, if the existing test file is itself auto-generated (has the oagen\n // header), allow overwriteExisting to take effect so new methods get coverage.\n const adapter = language ? getMergeAdapter(language) : undefined;\n const isTestFile = adapter?.testFilePatterns\n ? adapter.testFilePatterns.some((p) => p.test(file.path))\n : isDefaultTestFile(file.path);\n if (isTestFile) {\n const isExistingAutoGenerated = header && existingContent.startsWith(header);\n if (!isExistingAutoGenerated) {\n result.skipped.push(file.path);\n continue;\n }\n // Auto-generated test file — fall through to overwriteExisting / identical checks\n }\n\n // Identical content → no-op\n if (existingContent === file.content) {\n result.identical.push(file.path);\n continue;\n }\n\n // Force overwrite — but preserve any @oagen-ignore regions from existing content\n if (file.overwriteExisting) {\n const content =\n existingContent.includes('@oagen-ignore-start') && language && hasGrammar(language)\n ? await overwriteWithPreservedRegions(existingContent, file.content, language)\n : file.content;\n await fs.writeFile(fullPath, content, 'utf-8');\n result.written.push(file.path);\n continue;\n }\n\n // JSON files → deep merge preserving existing keys\n if (file.path.endsWith('.json')) {\n try {\n const existingJson = JSON.parse(existingContent);\n const generatedJson = JSON.parse(file.content);\n const merged = deepMergeJson(existingJson, generatedJson);\n const mergedContent = JSON.stringify(merged, null, 2) + '\\n';\n if (mergedContent === existingContent) {\n result.identical.push(file.path);\n } else {\n await fs.writeFile(fullPath, mergedContent, 'utf-8');\n result.merged.push(file.path);\n }\n } catch {\n // Parse failed — fall back to overwrite\n await fs.writeFile(fullPath, file.content, 'utf-8');\n result.written.push(file.path);\n }\n continue;\n }\n\n // Source files with grammar → AST-level merge\n if (language && hasGrammar(language)) {\n try {\n const mergeResult = await mergeIntoExisting(existingContent, file.content, language, header);\n\n // Ensure header is present on merged content\n let finalContent = mergeResult.content;\n if (header && !finalContent.startsWith(header)) {\n finalContent = header + '\\n\\n' + finalContent;\n }\n\n if (!mergeResult.changed && finalContent === existingContent) {\n result.identical.push(file.path);\n continue;\n }\n\n await fs.writeFile(fullPath, finalContent, 'utf-8');\n result.merged.push(file.path);\n continue;\n } catch (err) {\n // AST merge failed (e.g. tree-sitter grammar ABI issue) — fall back to overwrite\n console.warn(\n `[oagen] AST merge failed for ${file.path}, falling back to overwrite.${err instanceof Error ? ` ${err.message}` : ''}`,\n );\n await fs.writeFile(fullPath, file.content, 'utf-8');\n result.written.push(file.path);\n continue;\n }\n }\n\n // No grammar available → skip to avoid clobbering\n result.skipped.push(file.path);\n }\n\n return result;\n}\n\n/** Comprehensive fallback when no adapter is available. */\nfunction isDefaultTestFile(filePath: string): boolean {\n return (\n /\\.(spec|test)\\.[jt]sx?$/.test(filePath) ||\n filePath.endsWith('_test.go') ||\n filePath.endsWith('_test.rb') ||\n filePath.endsWith('_spec.rb') ||\n /(?:^|\\/)test_.*\\.py$/.test(filePath) ||\n filePath.endsWith('_test.py') ||\n filePath.endsWith('Test.php') ||\n filePath.endsWith('_test.rs') ||\n /(?:^|\\/)tests\\/.*\\.rs$/.test(filePath)\n );\n}\n\n// --- @oagen-ignore region preservation for overwriteExisting ---\n\n/**\n * Overwrite a file with generated content while preserving\n * `@oagen-ignore-start` / `@oagen-ignore-end` regions (and their\n * required imports) from the existing file.\n *\n * Uses tree-sitter via `extractClassEndLines` to find accurate class\n * boundaries so ignore blocks are inserted at the correct position even\n * when docstrings contain unindented text.\n */\nexport async function overwriteWithPreservedRegions(\n existingContent: string,\n generatedContent: string,\n language: string,\n): Promise<string> {\n const existingLines = existingContent.split('\\n');\n const generatedLines = generatedContent.split('\\n');\n\n // 1. Extract ignore blocks and their containing class from existing content.\n const blocks: { containingClass: string; lines: string[] }[] = [];\n for (let i = 0; i < existingLines.length; i++) {\n if (!existingLines[i].includes('@oagen-ignore-start')) continue;\n const startIdx = i;\n while (i < existingLines.length && !existingLines[i].includes('@oagen-ignore-end')) i++;\n blocks.push({\n containingClass: findContainingClass(existingLines, startIdx),\n lines: existingLines.slice(startIdx, i + 1),\n });\n }\n if (blocks.length === 0) return generatedContent;\n\n // 2. Splice extra imports from existing into generated.\n // First strip any `@oagen-ignore-start`..`@oagen-ignore-end` regions the\n // generator itself emitted: we are about to re-insert the on-disk versions,\n // and if we left the generator's seed blocks in place we'd end up with two\n // copies of every ignore block per regeneration (monotonically growing).\n const result = stripIgnoreRegions(generatedLines);\n spliceExtraImports(existingLines, result);\n\n // 3. Build class-end map from the generated content (after import splicing)\n // via tree-sitter for accurate boundary detection.\n const genSource = result.join('\\n');\n const classEndLines = await extractClassEndLines(genSource, language);\n\n // 4. Group ignore blocks by class and determine insertion points\n const blocksByClass = new Map<string, string[][]>();\n for (const b of blocks) {\n if (!blocksByClass.has(b.containingClass)) blocksByClass.set(b.containingClass, []);\n blocksByClass.get(b.containingClass)!.push(b.lines);\n }\n\n // 4a. Handle replacement blocks: ignore blocks that redefine their\n // containing class replace the generated class entirely.\n // Also handles top-level blocks (no containing class) that define\n // a class matching one in the generated content.\n const replacedClasses = new Set<string>();\n const handledBlockKeys = new Set<string>();\n const replacements: { startLine: number; endLine: number; content: string[] }[] = [];\n for (const [className, classBlocks] of blocksByClass) {\n // Determine the target class for replacement. When the block has a\n // containing class, we check if the block redefines that class. When\n // there is no containing class (top-level ignore block), we look for a\n // class definition inside the block that matches a generated class.\n let targetClass = className;\n if (!targetClass) {\n for (const blockLines of classBlocks) {\n for (const l of blockLines) {\n const m = l.match(/^(?:export\\s+)?class\\s+(\\w+)/);\n if (m && classEndLines.has(m[1])) {\n targetClass = m[1];\n break;\n }\n }\n if (targetClass) break;\n }\n }\n if (!targetClass) continue;\n const isReplacement = classBlocks.some((blockLines) =>\n blockLines.some((l) => {\n const m = l.match(/^(?:export\\s+)?class\\s+(\\w+)/);\n return m?.[1] === targetClass;\n }),\n );\n if (!isReplacement) continue;\n const info = classEndLines.get(targetClass);\n if (!info) continue;\n const startLine = findClassDeclarationStart(result, targetClass, info.bodyEndLine);\n if (startLine < 0) continue;\n const content: string[] = [];\n for (const block of classBlocks) {\n content.push('');\n content.push(...block);\n }\n replacements.push({ startLine, endLine: info.bodyEndLine, content });\n replacedClasses.add(targetClass);\n handledBlockKeys.add(className);\n }\n // Apply replacements bottom-up to preserve line indices\n replacements.sort((a, b) => b.startLine - a.startLine);\n for (const rep of replacements) {\n result.splice(rep.startLine, rep.endLine - rep.startLine, ...rep.content);\n }\n\n // 4b. Standard insertions for non-replacement blocks\n // Rebuild class end lines if replacements shifted line numbers.\n let effectiveClassEndLines = classEndLines;\n if (replacedClasses.size > 0) {\n effectiveClassEndLines = await extractClassEndLines(result.join('\\n'), language);\n }\n\n const insertions: { line: number; content: string[] }[] = [];\n for (const [className, classBlocks] of blocksByClass) {\n if (handledBlockKeys.has(className) || replacedClasses.has(className)) continue;\n const info = className ? effectiveClassEndLines.get(className) : undefined;\n const insertLine = info ? info.bodyEndLine : result.length;\n const content: string[] = [];\n for (const block of classBlocks) {\n content.push('');\n content.push(...block);\n }\n insertions.push({ line: insertLine, content });\n }\n\n // Apply bottom-up to preserve line indices\n insertions.sort((a, b) => b.line - a.line);\n for (const ins of insertions) {\n result.splice(ins.line, 0, ...ins.content);\n }\n\n return result.join('\\n');\n}\n\n/**\n * Remove every `@oagen-ignore-start`..`@oagen-ignore-end` region from the\n * supplied lines, collapsing stretches of blank lines that get left behind.\n * Used to drop generator-emitted seed blocks before splicing the on-disk\n * versions back in — otherwise every regen doubles up.\n */\nfunction stripIgnoreRegions(lines: string[]): string[] {\n const out: string[] = [];\n let skipping = false;\n for (const line of lines) {\n if (!skipping && line.includes('@oagen-ignore-start')) {\n skipping = true;\n // Drop a preceding blank line if we have one queued up — otherwise\n // regen leaves a stray blank line above the spliced-in block.\n while (out.length > 0 && out[out.length - 1].trim() === '') out.pop();\n continue;\n }\n if (skipping) {\n if (line.includes('@oagen-ignore-end')) skipping = false;\n continue;\n }\n out.push(line);\n }\n return out;\n}\n\n/** Scan backwards from `lineIdx` to find the nearest class declaration name. */\nfunction findContainingClass(lines: string[], lineIdx: number): string {\n // Allow leading whitespace so indented declarations (e.g. Ruby classes\n // nested inside `module Foo`, Python nested classes) are recognized.\n for (let j = lineIdx - 1; j >= 0; j--) {\n const m = lines[j].match(/^\\s*(?:export\\s+)?class\\s+(\\w+)/);\n if (m) return m[1];\n }\n return '';\n}\n\n/**\n * Find the start line of a class declaration (including decorators above it)\n * by scanning backwards from `beforeLine`.\n */\nfunction findClassDeclarationStart(lines: string[], className: string, beforeLine: number): number {\n // Match optional indentation so Ruby/Python nested classes are found.\n const classPattern = new RegExp(`^\\\\s*(?:export\\\\s+)?class\\\\s+${className}\\\\b`);\n for (let i = beforeLine - 1; i >= 0; i--) {\n if (!classPattern.test(lines[i])) continue;\n // Scan backward past decorators\n let start = i;\n while (start > 0 && /^\\s*@\\w+/.test(lines[start - 1])) {\n start--;\n }\n return start;\n }\n return -1;\n}\n\n/**\n * Collect `from X import Y, Z` identifiers grouped by module, handling\n * both single-line and multiline (parenthesized) forms.\n */\nfunction collectFromImports(lines: string[]): Map<string, Set<string>> {\n const byModule = new Map<string, Set<string>>();\n for (let i = 0; i < lines.length; i++) {\n if (!/^from\\s+/.test(lines[i])) continue;\n\n let fullText = lines[i];\n if (fullText.includes('(') && !fullText.includes(')')) {\n while (i + 1 < lines.length) {\n i++;\n fullText += ' ' + lines[i].trim();\n if (lines[i].includes(')')) break;\n }\n }\n\n const normalized = fullText.replace(/[()]/g, '').replace(/\\s+/g, ' ').trim();\n const match = normalized.match(/^from\\s+(\\S+)\\s+import\\s+(.+)$/);\n if (!match) continue;\n\n const mod = match[1];\n if (!byModule.has(mod)) byModule.set(mod, new Set());\n for (const id of match[2]\n .split(',')\n .map((s) => s.trim())\n .filter(Boolean)) {\n byModule.get(mod)!.add(id);\n }\n }\n return byModule;\n}\n\n/**\n * Add imports from the existing file that are absent from the generated\n * result. Handles both `import X` and `from X import Y` forms.\n * Mutates `resultLines` in place.\n */\nfunction spliceExtraImports(existingLines: string[], resultLines: string[]): void {\n const isSimpleImport = (l: string) => /^import\\s+\\w/.test(l);\n\n // Simple imports (import hashlib, import json, …)\n const existingSimple = new Set(existingLines.filter(isSimpleImport).map((l) => l.trim()));\n const generatedSimple = new Set(resultLines.filter(isSimpleImport).map((l) => l.trim()));\n const extraSimple = [...existingSimple].filter((l) => !generatedSimple.has(l));\n\n // From-imports — compare by module and find extra identifiers\n const existingFrom = collectFromImports(existingLines);\n const generatedFrom = collectFromImports(resultLines);\n\n // Build a set of all identifiers imported by the generated file (across all modules)\n // so we can detect when an existing barrel import's identifiers are covered by\n // more-specific generated imports (e.g., `from x.y import Z` covers `from x import Z`).\n const allGeneratedIds = new Set<string>();\n for (const ids of generatedFrom.values()) {\n for (const id of ids) allGeneratedIds.add(id);\n }\n\n const extraFromLines: string[] = [];\n for (const [mod, existIds] of existingFrom) {\n const genIds = generatedFrom.get(mod);\n if (!genIds) {\n // The exact module isn't in the generated file — but check whether every\n // identifier is already imported from a different (e.g., more-specific) module.\n const extra = [...existIds].filter((id) => !allGeneratedIds.has(id));\n if (extra.length > 0) {\n extraFromLines.push(`from ${mod} import ${extra.join(', ')}`);\n }\n } else {\n const extra = [...existIds].filter((id) => !genIds.has(id) && !allGeneratedIds.has(id));\n if (extra.length > 0) {\n extraFromLines.push(`from ${mod} import ${extra.join(', ')}`);\n }\n }\n }\n\n const allExtra = [...extraSimple, ...extraFromLines];\n if (allExtra.length === 0) return;\n\n // Find last import line in resultLines (accounting for multiline imports)\n let lastImportIdx = -1;\n for (let i = 0; i < resultLines.length; i++) {\n if (isSimpleImport(resultLines[i]) || /^from\\s+/.test(resultLines[i])) {\n lastImportIdx = i;\n if (resultLines[i].includes('(') && !resultLines[i].includes(')')) {\n while (i + 1 < resultLines.length) {\n i++;\n lastImportIdx = i;\n if (resultLines[i].includes(')')) break;\n }\n }\n }\n }\n\n if (lastImportIdx >= 0) {\n resultLines.splice(lastImportIdx + 1, 0, ...allExtra);\n }\n}\n","import type { ApiSpec, Service, Operation, HttpMethod } from './types.js';\n\n/** Minimal snake_case converter for path segments (avoids cross-layer import). */\nfunction toSnake(s: string): string {\n return s\n .replace(/([a-z])([A-Z])/g, '$1_$2')\n .replace(/[-\\s.]+/g, '_')\n .toLowerCase();\n}\n\n// ---------------------------------------------------------------------------\n// Hint types — consumer-provided overrides for operation resolution\n// ---------------------------------------------------------------------------\n\n/** Per-operation override keyed by \"METHOD /path\" (e.g. \"POST /sso/token\"). */\nexport interface OperationHint {\n /** Override the algorithm-derived method name. */\n name?: string;\n /** Remount this operation to a different service/namespace (PascalCase). */\n mountOn?: string;\n /** Split a union-body operation into N typed wrapper methods. */\n split?: SplitHint[];\n /** Inject constant body defaults (e.g. { grant_type: 'password' }). */\n defaults?: Record<string, string | number | boolean>;\n /** Fields the SDK reads from client config at runtime (e.g. ['client_id']). */\n inferFromClient?: string[];\n /**\n * Marks this operation as a URL builder rather than a real HTTP call. Emitters\n * should generate a method that returns the constructed URL (typically as a\n * string) without performing any I/O. Used for OAuth-style redirect endpoints\n * such as /sso/authorize and /user_management/sessions/logout.\n */\n urlBuilder?: boolean;\n}\n\nexport interface SplitHint {\n /** Wrapper method name (snake_case). */\n name: string;\n /** The discriminated union variant model name (e.g. 'PasswordSessionAuthenticateRequest'). */\n targetVariant: string;\n /** Constant body fields injected by the wrapper. */\n defaults?: Record<string, string | number | boolean>;\n /** Fields the SDK reads from client config at runtime. */\n inferFromClient?: string[];\n /** Only these body fields are exposed as method params. If omitted, all non-default/non-inferred fields are exposed. */\n exposedParams?: string[];\n /**\n * Subset of exposedParams that should be emitted as optional even when the\n * variant model would otherwise mark them required (or when the variant has\n * no addressable model, as happens for inline oneOf branches).\n */\n optionalParams?: string[];\n}\n\n// ---------------------------------------------------------------------------\n// Resolved output — consumed by emitters\n// ---------------------------------------------------------------------------\n\nexport interface ResolvedOperation {\n /** The original IR operation (preserves description, params, types, etc.). */\n operation: Operation;\n /** The original IR service that owns this operation. */\n service: Service;\n /** Resolved snake_case method name (emitters convert to their convention). */\n methodName: string;\n /** Resolved target service/namespace (PascalCase). */\n mountOn: string;\n /** For split operations: one wrapper per union variant. */\n wrappers?: ResolvedWrapper[];\n /** Constant defaults injected into query/body at runtime (from operation-level hint). */\n defaults: Record<string, string | number | boolean>;\n /** Fields the SDK reads from client config at runtime (from operation-level hint). */\n inferFromClient: string[];\n /** Marks this operation as a URL builder; emitters should not generate an HTTP call. */\n urlBuilder: boolean;\n}\n\nexport interface ResolvedWrapper {\n /** Wrapper method name (snake_case). */\n name: string;\n /** The discriminated union variant model name. */\n targetVariant: string;\n /** Constant body defaults injected by the wrapper. */\n defaults: Record<string, string | number | boolean>;\n /** Fields read from client config at runtime. */\n inferFromClient: string[];\n /** Body fields exposed as method params. */\n exposedParams: string[];\n /** Optional body fields (not required in the variant). */\n optionalParams: string[];\n /** Response model name (if any). */\n responseModelName: string | null;\n}\n\n// ---------------------------------------------------------------------------\n// Algorithm\n// ---------------------------------------------------------------------------\n\n/**\n * Action verbs recognised at the terminal path segment.\n * When a path ends with one of these, we use it as the verb instead of\n * deriving a CRUD verb from the HTTP method.\n */\nconst ACTION_VERBS = new Set([\n 'accept',\n 'activate',\n 'authorize',\n 'challenge',\n 'check',\n 'complete',\n 'confirm',\n 'deactivate',\n 'disable',\n 'enable',\n 'enroll',\n 'generate',\n 'reactivate',\n 'resend',\n 'revoke',\n 'send',\n 'verify',\n]);\n\n/** Map HTTP method → default CRUD verb. */\nconst CRUD_VERB: Record<HttpMethod, string> = {\n get: 'list',\n post: 'create',\n put: 'update',\n patch: 'update',\n delete: 'delete',\n head: 'get',\n options: 'list',\n trace: 'list',\n};\n\n/**\n * Naive singularization: strips trailing \"s\" with common-sense exceptions.\n * Good enough for API resource nouns; not a general-purpose English stemmer.\n */\nfunction singularize(word: string): string {\n if (word.length <= 2) return word;\n if (word.endsWith('ies')) return word.slice(0, -3) + 'y';\n if (\n word.endsWith('ses') ||\n word.endsWith('zes') ||\n word.endsWith('xes') ||\n word.endsWith('ches') ||\n word.endsWith('shes')\n ) {\n return word.slice(0, -2);\n }\n if (word.endsWith('ss') || word.endsWith('us') || word.endsWith('is')) return word;\n if (word.endsWith('s')) return word.slice(0, -1);\n return word;\n}\n\n/**\n * Derive a snake_case method name from an operation's HTTP method and path.\n *\n * Rules:\n * 1. Strip path-param segments (`{id}`, `{slug}`, etc.)\n * 2. If the terminal segment is an action verb, use it as the verb\n * 3. Otherwise, use the CRUD verb for the HTTP method\n * 4. For GET on a collection (no trailing {id}), use \"list\"; with {id}, use \"get\"\n * 5. For POST on a resource path, if only one path param, use \"create\" singular\n * 6. Singularize the resource noun for single-resource operations\n */\nexport function deriveMethodName(op: Operation, _service: Service): string {\n const segments = op.path.split('/').filter(Boolean);\n\n // Separate static segments from param segments\n const staticSegments: string[] = [];\n let trailingParam = false;\n for (const seg of segments) {\n if (seg.startsWith('{') && seg.endsWith('}')) {\n trailingParam = true;\n } else {\n staticSegments.push(seg);\n trailingParam = false;\n }\n }\n\n if (staticSegments.length === 0) {\n return `${CRUD_VERB[op.httpMethod] ?? 'get'}_root`;\n }\n\n const terminal = toSnake(staticSegments[staticSegments.length - 1]);\n\n // Check if terminal is an action verb\n if (ACTION_VERBS.has(terminal)) {\n // Resource context from preceding segments\n const context = staticSegments.slice(0, -1).filter((s) => !s.startsWith('{'));\n const resource = context.length > 0 ? toSnake(singularize(context[context.length - 1])) : '';\n if (resource) {\n return `${terminal}_${resource}`;\n }\n return terminal;\n }\n\n // Determine verb from HTTP method\n let verb = CRUD_VERB[op.httpMethod] ?? 'get';\n\n // GET with trailing {id} → \"get\" instead of \"list\"\n if (op.httpMethod === 'get' && trailingParam) {\n verb = 'get';\n }\n\n // Build resource name from static segments.\n // When path params separate static segments, include the penultimate static\n // segment (singularized) as a parent-context prefix to disambiguate nested paths.\n // e.g. /authorization/organizations/{id}/roles → \"organization_roles\"\n let resource = toSnake(terminal);\n if (staticSegments.length >= 2) {\n const penultimate = staticSegments[staticSegments.length - 2];\n // Check if a path param appears between the penultimate and terminal segments\n // in the original path by finding both positions and looking for {…} between them.\n const penIdx = segments.lastIndexOf(penultimate);\n const termIdx = segments.lastIndexOf(staticSegments[staticSegments.length - 1]);\n const hasParamBetween = segments.slice(penIdx + 1, termIdx).some((s) => s.startsWith('{'));\n if (hasParamBetween) {\n const prefix = toSnake(singularize(penultimate));\n resource = `${prefix}_${resource}`;\n }\n }\n\n // Singularize when:\n // * there's a trailing path param (single-resource read/update/delete), or\n // * the verb itself implies a single-resource operation (e.g. POST → create\n // always creates one item even when posted to a collection endpoint).\n const isSingleResource = trailingParam || verb === 'create';\n const noun = isSingleResource ? singularize(resource) : resource;\n\n // For \"list\" verb, keep plural\n const finalNoun = verb === 'list' ? resource : noun;\n\n return `${verb}_${finalNoun}`;\n}\n\n/**\n * Resolve all operations in the spec, applying hints and mount rules.\n *\n * @param spec - The parsed API spec\n * @param hints - Per-operation overrides keyed by \"METHOD /path\"\n * @param mountRules - Service name → target service mappings\n * @returns Resolved operations ready for emitter consumption\n */\nexport function resolveOperations(\n spec: ApiSpec,\n hints?: Record<string, OperationHint>,\n mountRules?: Record<string, string>,\n): ResolvedOperation[] {\n const resolved: ResolvedOperation[] = [];\n const hintMap = hints ?? {};\n const mounts = mountRules ?? {};\n\n for (const service of spec.services) {\n for (const op of service.operations) {\n const key = `${op.httpMethod.toUpperCase()} ${op.path}`;\n const hint = hintMap[key];\n\n // Resolve method name: hint > algorithm\n const methodName = hint?.name ?? deriveMethodName(op, service);\n\n // Resolve mount target: per-op hint > service mount rule > original service\n const mountOn = hint?.mountOn ?? mounts[service.name] ?? service.name;\n\n // Build wrappers for split operations\n let wrappers: ResolvedWrapper[] | undefined;\n if (hint?.split) {\n wrappers = hint.split.map((sh) => ({\n name: sh.name,\n targetVariant: sh.targetVariant,\n defaults: sh.defaults ?? {},\n inferFromClient: sh.inferFromClient ?? [],\n exposedParams: sh.exposedParams ?? [],\n optionalParams: sh.optionalParams ?? [],\n responseModelName: resolveResponseModelName(op),\n }));\n }\n\n resolved.push({\n operation: op,\n service,\n methodName,\n mountOn,\n wrappers,\n defaults: hint?.defaults ?? {},\n inferFromClient: hint?.inferFromClient ?? [],\n urlBuilder: hint?.urlBuilder ?? false,\n });\n }\n }\n\n return resolved;\n}\n\n/** Extract the response model name from an operation (for wrapper metadata). */\nfunction resolveResponseModelName(op: Operation): string | null {\n if (op.httpMethod === 'delete') return null;\n const ref = op.response;\n if (ref.kind === 'model') return ref.name;\n if (ref.kind === 'nullable' && ref.inner.kind === 'model') return ref.inner.name;\n return null;\n}\n","import type { ApiSpec, Model, TypeRef, Service } from '../ir/types.js';\nimport { walkTypeRef } from '../ir/types.js';\nimport type { OperationHint } from '../ir/operation-hints.js';\nimport { resolveOperations } from '../ir/operation-hints.js';\nimport type { Emitter, EmitterContext, GeneratedFile, OperationsMap } from './types.js';\nimport type { ApiSurface, OverlayLookup } from '../compat/types.js';\nimport { toSnakeCase } from '../utils/naming.js';\n\nexport function buildEmitterContext(\n spec: ApiSpec,\n options: {\n namespace: string;\n outputDir: string;\n apiSurface?: ApiSurface;\n overlayLookup?: OverlayLookup;\n operationHints?: Record<string, OperationHint>;\n mountRules?: Record<string, string>;\n target?: string;\n priorTargetManifestPaths?: Set<string>;\n },\n): EmitterContext {\n return {\n namespace: toSnakeCase(options.namespace),\n namespacePascal: options.namespace,\n spec,\n outputDir: options.outputDir,\n apiSurface: options.apiSurface,\n overlayLookup: options.overlayLookup,\n resolvedOperations: resolveOperations(spec, options.operationHints, options.mountRules),\n targetDir: options.target,\n priorTargetManifestPaths: options.priorTargetManifestPaths,\n };\n}\n\n/**\n * Collect model and enum names transitively referenced by service operations.\n * Walks operation parameters, request bodies, responses, and pagination item\n * types, then chases model field references until the set stabilizes.\n */\nexport function collectReferencedNames(\n services: Service[],\n models: Model[],\n): { models: Set<string>; enums: Set<string> } {\n const referencedModels = new Set<string>();\n const referencedEnums = new Set<string>();\n\n const collectFromTypeRef = (ref: TypeRef): void => {\n walkTypeRef(ref, {\n model: (r) => referencedModels.add(r.name),\n enum: (r) => referencedEnums.add(r.name),\n });\n };\n\n // Seed: walk every operation's params, request body, response, errors, and pagination\n for (const service of services) {\n for (const op of service.operations) {\n for (const p of [...op.pathParams, ...op.queryParams, ...op.headerParams, ...(op.cookieParams ?? [])]) {\n collectFromTypeRef(p.type);\n }\n if (op.requestBody) collectFromTypeRef(op.requestBody);\n collectFromTypeRef(op.response);\n if (op.pagination) collectFromTypeRef(op.pagination.itemType);\n for (const err of op.errors) {\n if (err.type) collectFromTypeRef(err.type);\n }\n if (op.successResponses) {\n for (const sr of op.successResponses) {\n collectFromTypeRef(sr.type);\n }\n }\n }\n }\n\n // Preserve discriminated models as public SDK types even when no operation\n // returns them directly. This matters for event/webhook unions where the base\n // operation references a generic envelope but the variant structs are still\n // useful public surface.\n for (const model of models) {\n if (isDiscriminatedModel(model)) {\n referencedModels.add(model.name);\n }\n }\n\n // Chase: transitively resolve model field references until stable\n const modelsByName = new Map(models.map((m) => [m.name, m]));\n const visited = new Set<string>();\n const queue = [...referencedModels];\n while (queue.length > 0) {\n const name = queue.pop()!;\n if (visited.has(name)) continue;\n visited.add(name);\n const model = modelsByName.get(name);\n if (!model) continue;\n for (const field of model.fields) {\n collectFromTypeRef(field.type);\n // If new models were discovered, enqueue them\n for (const m of referencedModels) {\n if (!visited.has(m)) queue.push(m);\n }\n }\n }\n\n return { models: referencedModels, enums: referencedEnums };\n}\n\nfunction isDiscriminatedModel(model: Model): boolean {\n return model.fields.some(\n (field) =>\n (field.name === 'event' || field.name === 'type' || field.name === 'object') && field.type.kind === 'literal',\n );\n}\n\n/** Collect all generated files from an emitter (no headers, no path prefixes). */\nexport function generateAllFiles(spec: ApiSpec, emitter: Emitter, ctx: EmitterContext): GeneratedFile[] {\n const referenced = collectReferencedNames(spec.services, spec.models);\n const reachableModels = spec.models.filter((m) => referenced.models.has(m.name));\n const reachableEnums = spec.enums.filter((e) => referenced.enums.has(e.name));\n const reachableSpec: ApiSpec = { ...spec, models: reachableModels, enums: reachableEnums };\n\n return [\n ...emitter.generateModels(reachableModels, ctx),\n ...emitter.generateEnums(reachableEnums, ctx),\n ...emitter.generateResources(spec.services, ctx),\n ...emitter.generateClient(spec, ctx),\n ...emitter.generateErrors(ctx),\n ...(emitter.generateTypeSignatures?.(reachableSpec, ctx) ?? []),\n ...emitter.generateTests(reachableSpec, ctx),\n ];\n}\n\n/** Apply file header to generated files, respecting headerPlacement and JSON files. */\nexport function applyFileHeaders(files: GeneratedFile[], header: string): GeneratedFile[] {\n return files.map((f) => ({\n ...f,\n content:\n !header || f.path.endsWith('.json') || f.headerPlacement === 'skip' ? f.content : header + '\\n\\n' + f.content,\n skipIfExists: f.skipIfExists ?? false,\n }));\n}\n\nexport function generateFiles(\n spec: ApiSpec,\n emitter: Emitter,\n options: {\n namespace: string;\n outputDir: string;\n apiSurface?: ApiSurface;\n overlayLookup?: OverlayLookup;\n operationHints?: Record<string, OperationHint>;\n mountRules?: Record<string, string>;\n target?: string;\n priorTargetManifestPaths?: Set<string>;\n },\n): { files: GeneratedFile[]; ctx: EmitterContext; header: string; operations?: OperationsMap } {\n const ctx = buildEmitterContext(spec, options);\n const files = generateAllFiles(spec, emitter, ctx);\n const operations = emitter.buildOperationsMap?.(spec, ctx);\n const header = emitter.fileHeader();\n return { files: applyFileHeaders(files, header), ctx, header, operations };\n}\n","import * as fs from 'node:fs/promises';\nimport path from 'node:path';\nimport type { GeneratedFile } from './types.js';\nimport { writeFiles, type WriteResult } from './writer.js';\nimport { extractStatements } from './merger.js';\nimport { hasGrammar } from './merger.js';\n\n/**\n * Resolve a relative import path against a source file path to get the\n * target file path. Handles implicit .ts extensions and /index.ts.\n */\nfunction resolveImportPath(\n fromFilePath: string,\n importModulePath: string,\n knownPaths: Set<string>,\n): string | undefined {\n // Strip quotes from module path key (tree-sitter keeps them)\n const cleaned = importModulePath.replace(/^['\"]|['\"]$/g, '');\n // Skip non-relative imports (node_modules, bare specifiers)\n if (!cleaned.startsWith('.')) return undefined;\n\n const dir = path.dirname(fromFilePath);\n const resolved = path.normalize(path.join(dir, cleaned));\n\n // Try exact match, .ts, /index.ts\n for (const candidate of [resolved, `${resolved}.ts`, `${resolved}/index.ts`]) {\n if (knownPaths.has(candidate)) return candidate;\n }\n return undefined;\n}\n\n/**\n * Determine whether a generated file is a \"root\" — a file that should always\n * be integrated into the target. Roots are entry points from which we trace\n * the import graph. Everything else must be reachable from a root.\n *\n * Roots: resource classes, client, config, errors, enums, barrel index files.\n * Non-roots: serializers, fixtures, standalone interfaces, test files.\n */\nfunction isRootFile(filePath: string): boolean {\n // Fixtures are never roots (and should be filtered by integrateTarget already)\n if (filePath.includes('/fixtures/')) return false;\n // Test files are roots — they are standalone entry points that belong in the\n // target repo even though nothing imports them.\n if (filePath.endsWith('.spec.ts') || filePath.endsWith('.test.ts')) return true;\n // Serializer files\n if (filePath.includes('/serializers/')) return false;\n // Standalone interface files (not barrel/index)\n if (filePath.includes('/interfaces/') && !filePath.endsWith('/index.ts')) return false;\n // Everything else is a root: resource classes, client, config, errors, enums, barrel files\n return true;\n}\n\n/**\n * Build a file-level dependency graph from generated files and return only\n * files reachable from root entry points. Uses tree-sitter to parse imports.\n */\nexport async function treeShakeFiles(files: GeneratedFile[], language: string): Promise<GeneratedFile[]> {\n if (!hasGrammar(language)) return files;\n\n const knownPaths = new Set(files.map((f) => f.path));\n\n // Build dependency graph: file → set of files it imports\n const deps = new Map<string, Set<string>>();\n for (const file of files) {\n // Only parse .ts/.js files (skip JSON, etc.)\n if (!file.path.endsWith('.ts') && !file.path.endsWith('.js')) {\n deps.set(file.path, new Set());\n continue;\n }\n const parsed = await extractStatements(file.content, language);\n const fileDeps = new Set<string>();\n for (const imp of parsed.imports) {\n const resolved = resolveImportPath(file.path, imp.key, knownPaths);\n if (resolved) fileDeps.add(resolved);\n }\n // Also check re-export statements (export * from './foo')\n for (const stmt of parsed.statements) {\n if (stmt.kind === 'reexport') {\n // Extract module path from \"export * from './foo'\" or \"export { X } from './foo'\"\n const match = stmt.text.match(/from\\s+['\"]([^'\"]+)['\"]/);\n if (match) {\n const resolved = resolveImportPath(file.path, match[1], knownPaths);\n if (resolved) fileDeps.add(resolved);\n }\n }\n }\n deps.set(file.path, fileDeps);\n }\n\n // Determine which file extensions are source code for this language\n const codeExtensions = new Set([\n '.ts',\n '.js',\n '.tsx',\n '.jsx',\n '.py',\n '.rb',\n '.go',\n '.rs',\n '.kt',\n '.cs',\n '.ex',\n '.exs',\n '.php',\n ]);\n\n // BFS from roots\n const reachable = new Set<string>();\n const queue: string[] = [];\n for (const file of files) {\n const ext = file.path.slice(file.path.lastIndexOf('.'));\n // Non-code files (JSON, etc.) are always reachable — they can't participate\n // in the import graph and are loaded at runtime (e.g. test fixtures).\n if (!codeExtensions.has(ext)) {\n reachable.add(file.path);\n continue;\n }\n if (isRootFile(file.path)) {\n reachable.add(file.path);\n queue.push(file.path);\n }\n }\n while (queue.length > 0) {\n const current = queue.pop()!;\n const fileDeps = deps.get(current);\n if (!fileDeps) continue;\n for (const dep of fileDeps) {\n if (!reachable.has(dep)) {\n reachable.add(dep);\n queue.push(dep);\n }\n }\n }\n\n return files.filter((f) => reachable.has(f.path));\n}\n\nexport function mapFilesForTargetIntegration(files: GeneratedFile[], language: string): GeneratedFile[] {\n const langPrefix = `${language}/`;\n return files\n .filter((f) => f.integrateTarget !== false) // integrateTarget: false files are standalone-only\n .map((f) => {\n const stripped = f.path.startsWith(langPrefix) ? f.path.replace(langPrefix, '') : f.path;\n return {\n ...f,\n skipIfExists: false, // Always merge in target — never hard-skip\n path: stripped,\n };\n });\n}\n\n/**\n * Resolve file-to-directory conflicts in the target.\n *\n * When a generated file creates a package directory (e.g., `api_keys/__init__.py`)\n * that would shadow an existing module file (e.g., `api_keys.py`), move the\n * module file's content into `_compat.py` inside the package and add a\n * re-export from `__init__.py`. This preserves backward-compatible imports\n * (e.g., `from workos.api_keys import ApiKeysModule`) while the package directory\n * provides the generated models and resource classes.\n */\nasync function resolveFileToDirectoryConflicts(\n files: GeneratedFile[],\n targetDir: string,\n): Promise<{ files: GeneratedFile[]; removals: string[] }> {\n const result = [...files];\n const removals: string[] = [];\n\n for (let i = 0; i < result.length; i++) {\n const file = result[i];\n // Match package init files: e.g., src/workos/api_keys/__init__.py\n const match = file.path.match(/^(.+)\\/__init__\\.py$/);\n if (!match) continue;\n\n const dirPath = match[1]; // e.g., src/workos/api_keys\n const moduleFilePath = `${dirPath}.py`; // e.g., src/workos/api_keys.py\n const fullModulePath = path.join(targetDir, moduleFilePath);\n\n let moduleContent: string;\n try {\n moduleContent = await fs.readFile(fullModulePath, 'utf-8');\n } catch {\n continue; // Module file doesn't exist — no conflict\n }\n\n // Create a compat shim inside the package with the old module's content\n const compatPath = `${dirPath}/_compat.py`;\n result.push({\n path: compatPath,\n content: moduleContent,\n overwriteExisting: true,\n });\n\n // Append re-export from _compat to __init__.py so existing imports work.\n // Compat must come AFTER generated models so hand-written types take\n // precedence over generated types with the same name.\n const compatImport = 'from ._compat import * # noqa: F401,F403 # pyright: ignore[reportUnusedImport]';\n const existingContent = file.content.endsWith('\\n') ? file.content : file.content + '\\n';\n result[i] = {\n ...file,\n content: existingContent + compatImport + '\\n',\n };\n\n // Schedule the shadowed module file for removal\n removals.push(fullModulePath);\n }\n\n return { files: result, removals };\n}\n\nexport interface IntegrateResult extends WriteResult {\n /** Final set of paths this run claims ownership of in the target (post tree-shake + conflict resolution). */\n emittedPaths: string[];\n}\n\nexport async function integrateGeneratedFiles(opts: {\n files: GeneratedFile[];\n language: string;\n targetDir: string;\n header: string;\n}): Promise<IntegrateResult> {\n const mapped = mapFilesForTargetIntegration(opts.files, opts.language);\n const shaken = await treeShakeFiles(mapped, opts.language);\n\n // Handle file-to-directory conflicts before writing\n const { files: resolved, removals } = await resolveFileToDirectoryConflicts(shaken, opts.targetDir);\n\n const result = await writeFiles(resolved, opts.targetDir, {\n language: opts.language,\n header: opts.header,\n });\n\n // Remove shadowed module files after integration\n for (const filePath of removals) {\n try {\n await fs.unlink(filePath);\n } catch {\n // File may already be gone\n }\n }\n\n // The manifest tracks ALL files oagen owns, including tree-shaken ones.\n // Tree-shaking decides what to write, but shaken files are still oagen-managed\n // and must not be pruned from the target on subsequent runs.\n return { ...result, emittedPaths: mapped.map((f) => f.path) };\n}\n","/**\n * Post-integration formatter.\n *\n * After generating and merging files into a target directory, runs the\n * emitter-provided format command on all written/merged files so that\n * generated code matches the target project's style conventions.\n */\n\nimport { execFile } from 'node:child_process';\nimport { promisify } from 'node:util';\nimport * as path from 'node:path';\nimport type { Emitter } from './types.js';\n\nconst execFileAsync = promisify(execFile);\n\n/**\n * Run the emitter's format command on the given target files.\n * Silently skips if the emitter has no formatCommand or returns null.\n */\nexport async function formatTargetFiles(emitter: Emitter, targetDir: string, filePaths: string[]): Promise<void> {\n if (filePaths.length === 0) return;\n if (!emitter.formatCommand) return;\n\n const formatCmd = emitter.formatCommand(targetDir);\n if (!formatCmd) return;\n\n const absolutePaths = filePaths.map((f) => path.resolve(targetDir, f));\n const batchSize = formatCmd.batchSize ?? 100;\n\n process.stderr.write(\n `[oagen] formatting ${absolutePaths.length} file(s) with ${formatCmd.cmd} (batch ${batchSize})\\n`,\n );\n\n for (let i = 0; i < absolutePaths.length; i += batchSize) {\n const batch = absolutePaths.slice(i, i + batchSize);\n try {\n await execFileAsync(formatCmd.cmd, [...formatCmd.args, ...batch], {\n cwd: targetDir,\n maxBuffer: 10 * 1024 * 1024,\n timeout: 120_000,\n });\n } catch (err) {\n // Formatter failed on this batch — continue with remaining batches.\n // Surface the failure on stderr so misconfigured commands don't silently\n // leave generated code unformatted every regen.\n const msg = err instanceof Error ? err.message : String(err);\n process.stderr.write(`[oagen] formatter batch failed: ${msg}\\n`);\n }\n }\n}\n","import * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\n\n/**\n * Prune-manifest support for `oagen generate`.\n *\n * The manifest records every auto-generated file emitted on the previous run,\n * relative to the directory it lives in (either the `--output` standalone dir\n * or the `--target` integration dir). On the next run we diff the previous\n * list against the current emission set and delete anything that's no longer\n * produced — preventing stale-file accumulation across regens.\n *\n * Design notes:\n * - The manifest is versioned so future format changes can be handled safely.\n * - Paths are stored sorted for deterministic diffs in git.\n * - Deletion is gated on a header guard when one is available: we only remove\n * files whose contents start with the auto-generated header. This protects\n * a hand-maintained file that happens to share a name with a previously\n * generated one (extremely rare, but worth catching).\n * - On first adoption (no previous manifest), pruning is skipped and a\n * one-line notice is printed — no surprise deletions.\n */\n\nexport const MANIFEST_FILENAME = '.oagen-manifest.json';\nconst MANIFEST_VERSION = 2;\n\nexport interface Manifest {\n /** Schema version. Bump when the format changes incompatibly. */\n version: number;\n /** Emitter language (e.g. \"python\"). Used only as a consistency hint. */\n language: string;\n /** Human-readable or package-level SDK identity (e.g. \"workos-php\"). */\n sdkName?: string;\n /** ISO-8601 timestamp of the run that produced this manifest. */\n generatedAt: string;\n /** SHA-256 hash of the source OpenAPI spec used for generation. */\n specSha?: string;\n /** Path or reference to the source spec. */\n specPath?: string;\n /** Git SHA or version of the emitter code used. */\n emitterSha?: string;\n /** Emitter version string if available. */\n emitterVersion?: string;\n /** SHA-256 hash of the effective oagen.config.ts after resolution. */\n configSha?: string;\n /** Version of the compat snapshot/report schema expected by this generation. */\n compatSchemaVersion?: string;\n /** Sorted list of paths, relative to the manifest's containing directory. */\n files: string[];\n /** Maps \"METHOD /path\" to SDK method + service property name. */\n operations?: Record<string, unknown>;\n}\n\nexport interface PruneResult {\n /** Paths actually deleted. */\n pruned: string[];\n /** Paths skipped because the header guard didn't match (preserved). */\n preserved: string[];\n /** Paths already absent on disk (nothing to do). */\n missing: string[];\n}\n\n/** Read `.oagen-manifest.json` from a directory. Returns null if absent or malformed. */\nexport async function readManifest(dir: string): Promise<Manifest | null> {\n const manifestPath = path.join(dir, MANIFEST_FILENAME);\n let raw: string;\n try {\n raw = await fs.readFile(manifestPath, 'utf-8');\n } catch {\n return null;\n }\n try {\n const parsed = JSON.parse(raw) as Partial<Manifest>;\n if (\n typeof parsed.version !== 'number' ||\n typeof parsed.language !== 'string' ||\n typeof parsed.generatedAt !== 'string' ||\n !Array.isArray(parsed.files) ||\n !parsed.files.every((p): p is string => typeof p === 'string')\n ) {\n return null;\n }\n if (parsed.version > MANIFEST_VERSION) {\n console.warn(\n `[oagen] ${MANIFEST_FILENAME} schema version ${parsed.version} is newer than supported (${MANIFEST_VERSION}); ignoring for pruning.`,\n );\n return null;\n }\n // v1 manifests are forward-compatible — new fields are simply absent\n return parsed as Manifest;\n } catch {\n return null;\n }\n}\n\n/** Options for writing a manifest. */\nexport interface WriteManifestOpts {\n language: string;\n files: Iterable<string>;\n sdkName?: string;\n specSha?: string;\n specPath?: string;\n emitterSha?: string;\n emitterVersion?: string;\n configSha?: string;\n compatSchemaVersion?: string;\n operations?: Record<string, unknown>;\n}\n\n/** Write `.oagen-manifest.json` to a directory with sorted paths. */\nexport async function writeManifest(dir: string, opts: WriteManifestOpts): Promise<void> {\n const manifest: Manifest = {\n version: MANIFEST_VERSION,\n language: opts.language,\n ...(opts.sdkName !== undefined ? { sdkName: opts.sdkName } : {}),\n generatedAt: new Date().toISOString(),\n ...(opts.specSha !== undefined ? { specSha: opts.specSha } : {}),\n ...(opts.specPath !== undefined ? { specPath: opts.specPath } : {}),\n ...(opts.emitterSha !== undefined ? { emitterSha: opts.emitterSha } : {}),\n ...(opts.emitterVersion !== undefined ? { emitterVersion: opts.emitterVersion } : {}),\n ...(opts.configSha !== undefined ? { configSha: opts.configSha } : {}),\n ...(opts.compatSchemaVersion !== undefined ? { compatSchemaVersion: opts.compatSchemaVersion } : {}),\n files: [...new Set(opts.files)].sort(),\n ...(opts.operations !== undefined ? { operations: opts.operations } : {}),\n };\n const manifestPath = path.join(dir, MANIFEST_FILENAME);\n await fs.mkdir(dir, { recursive: true });\n await fs.writeFile(manifestPath, JSON.stringify(manifest, null, 2) + '\\n', 'utf-8');\n}\n\n/** Return the set of previous paths no longer present in the current emission. */\nexport function computeStalePaths(prev: Manifest, currentPaths: Iterable<string>): string[] {\n const current = new Set(currentPaths);\n return prev.files.filter((p) => !current.has(p)).sort();\n}\n\n/**\n * Delete stale files from `dir`.\n *\n * When `header` is provided, a file is only deleted if its contents start with\n * that header — so hand-maintained files that somehow collide with a previously\n * generated path can't be clobbered. When `header` is omitted, the guard is\n * skipped (useful for non-source artifacts like fixture JSON).\n *\n * Returns lists for reporting. Empty parent directories are removed after\n * deletion, up to (but not including) `dir` itself.\n */\nexport async function pruneStaleFiles(\n dir: string,\n paths: string[],\n opts: { header?: string } = {},\n): Promise<PruneResult> {\n const pruned: string[] = [];\n const preserved: string[] = [];\n const missing: string[] = [];\n\n for (const relPath of paths) {\n const fullPath = path.join(dir, relPath);\n let content: string;\n try {\n content = await fs.readFile(fullPath, 'utf-8');\n } catch {\n missing.push(relPath);\n continue;\n }\n if (opts.header && !content.startsWith(opts.header)) {\n preserved.push(relPath);\n continue;\n }\n try {\n await fs.unlink(fullPath);\n pruned.push(relPath);\n } catch {\n // Racing deletion or permission issue — treat as missing rather than fatal.\n missing.push(relPath);\n continue;\n }\n await removeEmptyParents(path.dirname(fullPath), dir);\n }\n\n return { pruned, preserved, missing };\n}\n\n/**\n * Walk up from `startDir` removing empty directories until we hit `stopDir`\n * (exclusive) or a non-empty directory. Silently ignores errors.\n */\nasync function removeEmptyParents(startDir: string, stopDir: string): Promise<void> {\n let current = path.resolve(startDir);\n const stop = path.resolve(stopDir);\n while (current.startsWith(stop + path.sep) && current !== stop) {\n let entries: string[];\n try {\n entries = await fs.readdir(current);\n } catch {\n return;\n }\n if (entries.length > 0) return;\n try {\n await fs.rmdir(current);\n } catch {\n return;\n }\n current = path.dirname(current);\n }\n}\n","import type { ApiSpec } from '../ir/types.js';\nimport type { OperationHint } from '../ir/operation-hints.js';\nimport type { Emitter, GeneratedFile } from './types.js';\nimport type { ApiSurface, OverlayLookup } from '../compat/types.js';\nimport { writeFiles } from './writer.js';\nimport { generateFiles } from './generate-files.js';\nimport { integrateGeneratedFiles } from './integrate.js';\nimport { formatTargetFiles } from './formatter.js';\nimport { computeStalePaths, MANIFEST_FILENAME, pruneStaleFiles, readManifest, writeManifest } from './manifest.js';\n\nexport async function generate(\n spec: ApiSpec,\n emitter: Emitter,\n options: {\n namespace: string;\n dryRun?: boolean;\n outputDir: string;\n target?: string;\n apiSurface?: ApiSurface;\n overlayLookup?: OverlayLookup;\n operationHints?: Record<string, OperationHint>;\n mountRules?: Record<string, string>;\n /** When true, skip deletion of files recorded in the previous manifest but not in the current emission. */\n noPrune?: boolean;\n },\n): Promise<GeneratedFile[]> {\n // Read the target's previous manifest up front so emitters can mark files\n // the prior run wrote as safe-to-overwrite (vs files a human hand-maintains).\n // Skipped when --no-prune is set so users opting out of lifecycle tracking\n // also opt out of overwrite-on-regen behavior.\n const targetManifestForCtx = options.target && !options.noPrune ? await readManifest(options.target) : null;\n const priorTargetManifestPaths = targetManifestForCtx ? new Set(targetManifestForCtx.files) : undefined;\n\n const {\n files: withHeaders,\n header,\n operations,\n } = generateFiles(spec, emitter, {\n ...options,\n priorTargetManifestPaths,\n });\n\n if (options.dryRun) {\n if (options.target) {\n console.log(`\\nTarget integration (${options.target}):`);\n for (const f of withHeaders) {\n console.log(` ${f.path}`);\n }\n }\n return withHeaders;\n }\n\n // Read previous manifest BEFORE writing so a manifest overwrite can't alter the diff.\n const outputPrevManifest = options.noPrune ? null : await readManifest(options.outputDir);\n\n const writeResult = await writeFiles(withHeaders, options.outputDir, {\n language: emitter.language,\n header,\n });\n\n if (writeResult.merged.length > 0) {\n console.log(`Merged into ${writeResult.merged.length} existing files (additive only)`);\n }\n if (writeResult.ignored.length > 0) {\n console.log(`Ignored ${writeResult.ignored.length} files (@oagen-ignore-file)`);\n }\n\n const outputEmittedPaths = withHeaders.map((f) => f.path);\n await applyManifestPrune({\n dir: options.outputDir,\n label: 'Output',\n prevManifest: outputPrevManifest,\n currentPaths: outputEmittedPaths,\n language: emitter.language,\n header,\n noPrune: options.noPrune,\n operations,\n });\n\n // Format output files so the emitter's formatter runs even without --target.\n const allOutputFiles = [...writeResult.written, ...writeResult.merged];\n if (allOutputFiles.length > 0) {\n await formatTargetFiles(emitter, options.outputDir, allOutputFiles);\n }\n\n // Target integration pass\n if (options.target) {\n // Reuse the manifest we already read to build the emitter context. This\n // is correct because nothing between the two reads writes the manifest.\n const targetPrevManifest = targetManifestForCtx;\n\n const targetResult = await integrateGeneratedFiles({\n files: withHeaders,\n language: emitter.language,\n targetDir: options.target,\n header,\n });\n\n if (targetResult.written.length > 0) {\n console.log(`Target: created ${targetResult.written.length} new files`);\n }\n if (targetResult.merged.length > 0) {\n console.log(`Target: merged into ${targetResult.merged.length} existing files (additive only)`);\n }\n if (targetResult.skipped.length > 0) {\n console.log(`Target: skipped ${targetResult.skipped.length} files (excluded or no grammar)`);\n }\n\n await applyManifestPrune({\n dir: options.target,\n label: 'Target',\n prevManifest: targetPrevManifest,\n currentPaths: targetResult.emittedPaths,\n language: emitter.language,\n header,\n noPrune: options.noPrune,\n operations,\n });\n\n // Run the emitter's formatter on all written/merged/identical files\n const allTargetFiles = [...targetResult.written, ...targetResult.merged, ...targetResult.identical];\n if (allTargetFiles.length > 0) {\n await formatTargetFiles(emitter, options.target, allTargetFiles);\n }\n }\n\n return withHeaders;\n}\n\n/**\n * Prune files recorded in the previous manifest but absent from the current emission,\n * then write the fresh manifest. Safe on first adoption (no previous manifest).\n */\nasync function applyManifestPrune(opts: {\n dir: string;\n label: string;\n prevManifest: Awaited<ReturnType<typeof readManifest>>;\n currentPaths: string[];\n language: string;\n header: string;\n noPrune?: boolean;\n operations?: Record<string, unknown>;\n}): Promise<void> {\n const manifestOpts = { language: opts.language, files: opts.currentPaths, operations: opts.operations };\n if (opts.noPrune) {\n // Still refresh the manifest so future runs with pruning enabled have a baseline.\n await writeManifest(opts.dir, manifestOpts);\n return;\n }\n\n if (!opts.prevManifest) {\n console.log(\n `${opts.label}: no ${MANIFEST_FILENAME} found — skipping prune (this baseline manifest will be written now).`,\n );\n await writeManifest(opts.dir, manifestOpts);\n return;\n }\n\n const stale = computeStalePaths(opts.prevManifest, opts.currentPaths);\n if (stale.length > 0) {\n const { pruned, preserved } = await pruneStaleFiles(opts.dir, stale, { header: opts.header });\n if (pruned.length > 0) {\n console.log(`${opts.label}: pruned ${pruned.length} stale file${pruned.length === 1 ? '' : 's'}`);\n }\n if (preserved.length > 0) {\n console.log(\n `${opts.label}: preserved ${preserved.length} file${preserved.length === 1 ? '' : 's'} in previous manifest but lacking the auto-generated header (possibly hand-edited).`,\n );\n for (const p of preserved) console.log(` ${p}`);\n }\n }\n\n await writeManifest(opts.dir, manifestOpts);\n}\n","import { RegistryError } from '../errors.js';\nimport type { Emitter } from './types.js';\n\nconst emitters = new Map<string, Emitter>();\n\nexport function registerEmitter(emitter: Emitter): void {\n emitters.set(emitter.language, emitter);\n}\n\nexport function getEmitter(language: string): Emitter {\n const emitter = emitters.get(language);\n if (!emitter) {\n const available = [...emitters.keys()].join(', ') || '(none)';\n throw new RegistryError(\n `Unknown language: ${language}. Available: ${available}`,\n `Register an emitter for \"${language}\" via registerEmitter() or check your oagen.config.ts plugin configuration.`,\n );\n }\n return emitter;\n}\n","import type { ApiSurface, LanguageHints } from './types.js';\nimport { splitWords } from '../utils/naming.js';\n\n/** Untyped map patterns — hoisted to avoid allocation on every isTypeEquivalent call. */\nconst UNTYPED_MAP_PATTERNS = new Set([\n 'Record<string, unknown>',\n 'Record<string, any>',\n '{ [key: string]: any; }',\n '{ [key: string]: unknown; }',\n 'any',\n]);\n\nexport const NAMED_TYPE_RE = /^[A-Z][a-zA-Z0-9]*$/;\n\n/** Check whether a type name exists as an interface, class, or enum in a surface. */\nexport function typeExistsInSurface(name: string, surface: ApiSurface): boolean {\n return !!(surface.interfaces[name] || surface.classes[name] || surface.enums[name]);\n}\n\n/** Split a PascalCase string into words, keeping only words > 2 chars. */\nfunction splitPascalWords(s: string): string[] {\n return splitWords(s).filter((w) => w.length > 2);\n}\n\n/**\n * Check whether two named types share enough PascalCase word components to\n * be considered equivalent (handles name reordering from Json merges, etc.).\n * Both names have `Response$` stripped before comparison.\n */\nexport function namedTypeWordsOverlap(a: string, b: string, minOverlap = 1): boolean {\n const aNoResp = a.replace(/Response$/, '');\n const bNoResp = b.replace(/Response$/, '');\n const aWords = new Set(splitPascalWords(aNoResp).map((w) => w.toLowerCase()));\n const bWords = new Set(splitPascalWords(bNoResp).map((w) => w.toLowerCase()));\n const overlap = [...aWords].filter((w) => bWords.has(w));\n return overlap.length >= minOverlap && overlap.length >= Math.min(aWords.size, bWords.size) - 1;\n}\n\n/** Split a pipe-delimited union string into trimmed, non-empty members. */\nfunction parseUnionMembers(s: string): string[] {\n return s\n .split('|')\n .map((p) => p.trim())\n .filter(Boolean);\n}\n\n/**\n * Default implementation of isNullableOnlyDifference — shared across extractors.\n * Returns true when stripping nullable wrappers from both sides yields the same\n * type, but the original types differ (i.e., the only difference is nullability).\n */\nexport function defaultIsNullableOnlyDifference(\n hints: Pick<LanguageHints, 'stripNullable'>,\n a: string,\n b: string,\n): boolean {\n return (hints.stripNullable(a) ?? a) === (hints.stripNullable(b) ?? b) && a !== b;\n}\n\n/**\n * Node/TypeScript language hints — reference implementation.\n * Extracted from the hardcoded logic previously in differ.ts and overlay.ts.\n */\nexport const nodeHints: LanguageHints = {\n stripNullable(type: string): string | null {\n const members = parseUnionMembers(type);\n const stripped = members.filter((p) => p !== 'null');\n if (stripped.length === members.length) {\n return null; // no null member found\n }\n return stripped.join(' | ');\n },\n\n isNullableOnlyDifference(a: string, b: string): boolean {\n return (nodeHints.stripNullable(a) ?? a) === (nodeHints.stripNullable(b) ?? b) && a !== b;\n },\n\n isUnionReorder(a: string, b: string): boolean {\n const membersA = parseUnionMembers(a).sort();\n const membersB = parseUnionMembers(b).sort();\n if (membersA.length !== membersB.length || membersA.length < 2) return false;\n return membersA.every((m, i) => m === membersB[i]);\n },\n\n isGenericTypeParam(type: string): boolean {\n if (/^[A-Z]$/.test(type)) return true;\n if (/^T[A-Z][a-zA-Z]*$/.test(type)) return true;\n if (/^[A-Z]\\[\\]$/.test(type) || /^T[A-Z][a-zA-Z]*\\[\\]$/.test(type)) return true;\n return false;\n },\n\n isExtractionArtifact(type: string): boolean {\n return type === 'any' || type === 'Record<string, unknown>';\n },\n\n tolerateCategoryMismatch: true,\n\n extractReturnTypeName(returnType: string): string | null {\n let inner = returnType;\n while (inner.startsWith('Promise<') && inner.endsWith('>')) {\n inner = inner.slice(8, -1);\n }\n const genericMatch = inner.match(/^[A-Za-z]+<(.+)>$/);\n if (genericMatch) {\n inner = genericMatch[1];\n }\n inner = inner.replace(/\\[\\]$/, '');\n if (['void', 'string', 'number', 'boolean', 'any', 'unknown', 'null', 'undefined'].includes(inner)) {\n return null;\n }\n return inner;\n },\n\n extractParamTypeName(paramType: string): string | null {\n if (['string', 'number', 'boolean', 'any', 'unknown'].includes(paramType)) {\n return null;\n }\n return paramType;\n },\n\n propertyMatchesClass(propertyName: string, className: string): boolean {\n // Support both camelCase and snake_case properties matching PascalCase classes\n // e.g., \"organizations\" ≡ \"Organizations\", \"api_keys\" ≡ \"ApiKeys\"\n const normalizedProp = propertyName.replace(/[-_]/g, '').toLowerCase();\n return normalizedProp === className.toLowerCase();\n },\n\n derivedModelNames(modelName: string): string[] {\n return [`${modelName}Response`, `Serialized${modelName}`];\n },\n\n isTypeEquivalent(baselineType: string, candidateType: string, candidateSurface: ApiSurface): boolean {\n // Check if one side is a named enum and the other is an inline union\n // of that enum's string literal values.\n // e.g., baseline: '\"active\" | \"inactive\"', candidate: 'ConnectionState'\n // or baseline: 'ConnectionState', candidate: '\"active\" | \"inactive\"'\n\n // Try: candidate is enum name, baseline is inline union of string literals.\n // The generated enum may have MORE members than the baseline (new spec values),\n // so check that all baseline members exist in the enum (subset match).\n const candEnum = candidateSurface.enums[candidateType];\n if (candEnum) {\n const enumValuesSet = new Set(Object.values(candEnum.members).flatMap((v) => [`\"${v}\"`, `'${v}'`]));\n const baseMembers = parseUnionMembers(baselineType);\n if (baseMembers.length > 0 && baseMembers.every((m) => enumValuesSet.has(m))) {\n return true;\n }\n }\n\n // Tolerate untyped-map equivalences:\n // { [key: string]: any; } ≡ Record<string, unknown> ≡ Record<string, any>\n if (UNTYPED_MAP_PATTERNS.has(baselineType) && UNTYPED_MAP_PATTERNS.has(candidateType)) {\n return true;\n }\n\n // Tolerate inline object literal vs named model in candidate.\n // e.g., baseline: '{ type: \"organization\"; id: string; }', candidate: 'ApiKeyOwner'\n // The named model is more structured but semantically equivalent.\n if (baselineType.startsWith('{') && baselineType.endsWith('}')) {\n if (typeExistsInSurface(candidateType, candidateSurface)) {\n return true;\n }\n }\n\n // Tolerate named-type-to-named-type mismatches when both types exist\n // as models/interfaces/enums in their respective surfaces. This handles\n // cases where the parser qualifies inline types with parent names while\n // the live SDK uses shared types:\n // baseline: RoleResponse, candidate: OrganizationMembershipRole\n // baseline: ConnectionType, candidate: ProfileConnectionType\n // baseline: AuditLogTargetSchema[], candidate: AuditLogSchemaJsonTarget[]\n const baseClean = baselineType.replace(/\\[\\]$/, '');\n const candClean = candidateType.replace(/\\[\\]$/, '');\n const sameArrayness = baselineType.endsWith('[]') === candidateType.endsWith('[]');\n\n // Response suffix equivalence (both directions)\n if (sameArrayness) {\n if (candClean === baseClean + 'Response' || baseClean === candClean + 'Response') {\n return true;\n }\n }\n\n // Both are named types (PascalCase, no operators) — check if candidate\n // is a known model/interface/enum, and baseline looks like a named type too.\n // This tolerates the parser's qualified naming vs the live SDK's shared naming.\n if (sameArrayness && NAMED_TYPE_RE.test(baseClean) && NAMED_TYPE_RE.test(candClean)) {\n if (typeExistsInSurface(candClean, candidateSurface)) {\n // One name contains the other (e.g., ProfileConnectionType contains ConnectionType)\n if (candClean.includes(baseClean) || baseClean.includes(candClean)) {\n return true;\n }\n // Strip Response suffix and check containment\n const baseNoResp = baseClean.replace(/Response$/, '');\n const candNoResp = candClean.replace(/Response$/, '');\n if (candNoResp.includes(baseNoResp) || baseNoResp.includes(candNoResp)) {\n return true;\n }\n // Word-component overlap: split PascalCase into words and check\n // if they share enough meaningful words (handles name reordering\n // from Json merges: AuditLogTargetSchema vs AuditLogSchemaJsonTarget)\n if (namedTypeWordsOverlap(baseClean, candClean, 2)) {\n return true;\n }\n }\n }\n\n return false;\n },\n};\n\n/**\n * Merge partial language hint overrides over nodeHints defaults.\n * Any hint not provided falls back to the Node/TypeScript implementation.\n */\nexport function resolveHints(overrides: Partial<LanguageHints>): LanguageHints {\n return { ...nodeHints, ...overrides };\n}\n","import type { ApiSurface, ApiInterface, ApiMethod, OverlayLookup, LanguageHints } from './types.js';\nimport type { ClassifiedChange } from './classify.js';\nimport type { ApiSpec, Model } from '../ir/types.js';\nimport { toSnakeCase, splitWords } from '../utils/naming.js';\nimport { nodeHints as defaultNodeHints } from './language-hints.js';\n\nexport type { MethodOverlay, OverlayLookup } from './types.js';\n\nexport interface ManifestEntry {\n operationId: string;\n sdkResourceProperty: string;\n sdkMethodName: string;\n httpMethod: string;\n path: string;\n pathParams: string[];\n bodyFields: string[];\n queryFields: string[];\n}\n\n/**\n * Find the class name that owns a given SDK resource property.\n * E.g. if the surface has a class \"Organizations\" with property \"organizations\",\n * and sdkResourceProperty is \"organizations\", return \"Organizations\".\n */\nfunction findClassForProperty(\n surface: ApiSurface,\n sdkResourceProperty: string,\n hints: LanguageHints,\n): string | undefined {\n for (const [className, cls] of Object.entries(surface.classes)) {\n // Check if the class itself maps to this property (language-specific match)\n if (hints.propertyMatchesClass(sdkResourceProperty, className)) {\n return className;\n }\n // Check properties — resolve to the property's type class, not the parent.\n // This prevents generic parent classes (e.g., WorkOS) from being returned\n // when the actual resource class (e.g., ApiKeys) should be used.\n for (const [propName, prop] of Object.entries(cls.properties)) {\n if (propName === sdkResourceProperty) {\n const propType = (prop as { type?: string }).type;\n if (propType && surface.classes[propType]) {\n return propType;\n }\n // Property type not in surface — skip rather than return the parent\n return undefined;\n }\n }\n }\n\n // Strategy 3: Word-suffix fallback\n // \"adminPortal\" → [\"admin\",\"portal\"]; class \"Portal\" → [\"portal\"]\n // [\"portal\"] is a suffix of [\"admin\",\"portal\"] → match\n const propWords = splitWords(sdkResourceProperty).map((w) => w.toLowerCase());\n if (propWords.length > 1) {\n for (const [className] of Object.entries(surface.classes)) {\n const classWords = splitWords(className).map((w) => w.toLowerCase());\n if (classWords.length > 0 && classWords.length < propWords.length) {\n const suffix = propWords.slice(propWords.length - classWords.length);\n if (classWords.every((w, i) => w === suffix[i])) {\n return className;\n }\n }\n }\n }\n\n return undefined;\n}\n\nexport function buildOverlayLookup(\n surface: ApiSurface,\n manifest?: ManifestEntry[],\n spec?: ApiSpec,\n hints?: LanguageHints,\n options?: { strictModelMatch?: boolean },\n): OverlayLookup {\n const resolvedHints = hints ?? defaultNodeHints;\n const lookup: OverlayLookup = {\n methodByOperation: new Map(),\n httpKeyByMethod: new Map(),\n interfaceByName: new Map(),\n typeAliasByName: new Map(),\n requiredExports: new Map(),\n modelNameByIR: new Map(),\n fileBySymbol: new Map(),\n };\n\n // If manifest available, map operationId → HTTP method + path → existing method\n if (manifest) {\n for (const entry of manifest) {\n const key = `${entry.httpMethod.toUpperCase()} ${entry.path}`;\n const className = findClassForProperty(surface, entry.sdkResourceProperty, resolvedHints);\n if (className) {\n let resolvedMethodName = entry.sdkMethodName;\n let methods = surface.classes[className]?.methods[resolvedMethodName];\n\n // Exact match failed — try prefix match on the resolved class.\n // Handles cases where the generated name is shorter than the existing name\n // (e.g., manifest says \"delete\" but existing SDK has \"deleteApiKey\").\n // Only accept when exactly one candidate matches — ambiguous matches are worse than no match.\n if (!methods) {\n const classMethods = surface.classes[className]?.methods ?? {};\n const prefix = resolvedMethodName.toLowerCase();\n const candidates: [string, ApiMethod[]][] = [];\n for (const [name, overloads] of Object.entries(classMethods)) {\n if (name.toLowerCase().startsWith(prefix) && name !== resolvedMethodName) {\n candidates.push([name, overloads]);\n }\n }\n if (candidates.length === 1) {\n methods = candidates[0][1];\n resolvedMethodName = candidates[0][0];\n } else if (candidates.length > 1) {\n // Disambiguate: prefer the candidate whose name is <prefix><pathSegment>\n // derived from the FIRST segment of the operation path. This avoids\n // mismatching when a class combines operations from multiple path groups\n // (e.g., /organizations and /organization_domains both in Organizations).\n const firstSegment =\n entry.path\n .split('/')\n .filter(Boolean)[0]\n ?.replace(/[{}_-]/g, '') ?? '';\n if (firstSegment) {\n const segLower = firstSegment.toLowerCase();\n // Try the path segment as-is and as singular\n const segSingular = segLower.endsWith('s') ? segLower.slice(0, -1) : segLower;\n const best = candidates.find(([name]) => {\n const lower = name.toLowerCase();\n return lower === prefix + segLower || lower === prefix + segSingular;\n });\n if (best) {\n methods = best[1];\n resolvedMethodName = best[0];\n }\n }\n\n // HTTP verb disambiguation: when path disambiguation fails, use the\n // HTTP method to prefer method names that match the verb semantics.\n // E.g., GET → list/get, POST → create, PUT → set/update, DELETE → delete/remove.\n if (!methods) {\n const verbMatch = disambiguateByHttpVerb(candidates, entry.httpMethod);\n if (verbMatch) {\n methods = verbMatch[1];\n resolvedMethodName = verbMatch[0];\n }\n }\n }\n }\n\n // Suffix match: the existing SDK may use a longer controller-prefixed\n // method name that ends with the transformed name.\n // (e.g., manifest says \"validate_api_key\" but existing SDK has\n // \"api_keys_controller_validate_api_key\").\n // Only accept when exactly one candidate matches — ambiguous matches are worse than no match.\n if (!methods) {\n const classMethods = surface.classes[className]?.methods ?? {};\n const suffix = resolvedMethodName.toLowerCase();\n const candidates: [string, ApiMethod[]][] = [];\n for (const [name, overloads] of Object.entries(classMethods)) {\n if (name.toLowerCase().endsWith(suffix) && name !== resolvedMethodName) {\n candidates.push([name, overloads]);\n }\n }\n if (candidates.length === 1) {\n methods = candidates[0][1];\n resolvedMethodName = candidates[0][0];\n }\n }\n\n // Word-part subsequence match: the surface method may have extra words\n // inserted into the manifest method name. For example:\n // \"disableFlag\" → \"disableFeatureFlag\" ([\"disable\",\"Flag\"] ⊂ [\"disable\",\"Feature\",\"Flag\"])\n // \"getByExternalId\" → \"getOrganizationByExternalId\"\n // Only accept when exactly one candidate matches, or use HTTP verb disambiguation.\n if (!methods) {\n const manifestWords = splitCamelCase(resolvedMethodName);\n if (manifestWords.length >= 2) {\n const classMethods = surface.classes[className]?.methods ?? {};\n const candidates: [string, ApiMethod[]][] = [];\n for (const [name, overloads] of Object.entries(classMethods)) {\n if (name === resolvedMethodName) continue;\n const surfaceWords = splitCamelCase(name);\n if (surfaceWords.length > manifestWords.length && isSubsequence(manifestWords, surfaceWords)) {\n candidates.push([name, overloads]);\n }\n }\n if (candidates.length === 1) {\n methods = candidates[0][1];\n resolvedMethodName = candidates[0][0];\n } else if (candidates.length > 1) {\n const verbMatch = disambiguateByHttpVerb(candidates, entry.httpMethod);\n if (verbMatch) {\n methods = verbMatch[1];\n resolvedMethodName = verbMatch[0];\n }\n }\n }\n }\n\n // Reverse prefix match: the manifest name may be LONGER than the surface\n // name (e.g., \"createResources\" → \"createResource\", \"removeRoleByCriteria\" → \"removeRole\").\n // Check if the manifest name starts with a surface name. Only accept unique matches.\n if (!methods) {\n const classMethods = surface.classes[className]?.methods ?? {};\n const manifestLower = resolvedMethodName.toLowerCase();\n const candidates: [string, ApiMethod[]][] = [];\n for (const [name, overloads] of Object.entries(classMethods)) {\n if (name === resolvedMethodName) continue;\n if (manifestLower.startsWith(name.toLowerCase()) && name.length >= 3) {\n candidates.push([name, overloads]);\n }\n }\n if (candidates.length === 1) {\n methods = candidates[0][1];\n resolvedMethodName = candidates[0][0];\n } else if (candidates.length > 1) {\n const verbMatch = disambiguateByHttpVerb(candidates, entry.httpMethod);\n if (verbMatch) {\n methods = verbMatch[1];\n resolvedMethodName = verbMatch[0];\n }\n }\n }\n\n const method = methods?.[0];\n if (method) {\n lookup.methodByOperation.set(key, {\n className,\n methodName: resolvedMethodName,\n params: method.params,\n returnType: method.returnType,\n });\n lookup.httpKeyByMethod.set(`${className}.${resolvedMethodName}`, key);\n }\n }\n }\n }\n\n // Map interface and type alias names\n for (const name of Object.keys(surface.interfaces)) {\n lookup.interfaceByName.set(name, name);\n }\n for (const name of Object.keys(surface.typeAliases)) {\n lookup.typeAliasByName.set(name, name);\n }\n\n // Map barrel exports\n for (const [path, symbols] of Object.entries(surface.exports)) {\n lookup.requiredExports.set(path, new Set(symbols));\n }\n\n // Populate fileBySymbol from enriched surface\n for (const record of [surface.classes, surface.interfaces, surface.typeAliases, surface.enums] as Record<\n string,\n { sourceFile?: string }\n >[]) {\n for (const [name, item] of Object.entries(record)) {\n if (item.sourceFile) lookup.fileBySymbol.set(name, item.sourceFile);\n }\n }\n\n // Auto-infer IR model name → SDK interface name mappings\n if (spec) {\n buildModelNameMap(surface, spec, lookup, resolvedHints, options);\n\n // Remap fileBySymbol so IR model names point to the SDK symbol's file\n for (const [irName, sdkName] of lookup.modelNameByIR) {\n const filePath = lookup.fileBySymbol.get(sdkName);\n if (filePath) {\n lookup.fileBySymbol.set(irName, filePath);\n }\n }\n }\n\n return lookup;\n}\n\n// ---------------------------------------------------------------------------\n// HTTP verb disambiguation\n// ---------------------------------------------------------------------------\n\n/** Map HTTP methods to preferred method name prefixes for disambiguation. */\nconst HTTP_VERB_PREFIXES: Record<string, string[]> = {\n GET: ['list', 'get', 'fetch', 'retrieve', 'find'],\n POST: ['create', 'add', 'insert', 'send'],\n PUT: ['set', 'update', 'replace', 'put'],\n PATCH: ['update', 'patch', 'modify'],\n DELETE: ['delete', 'remove', 'revoke'],\n};\n\n/**\n * Disambiguate multiple method candidates using HTTP verb semantics.\n * Returns the best match or undefined if no unique match is found.\n */\nfunction disambiguateByHttpVerb<T>(candidates: [string, T][], httpMethod: string): [string, T] | undefined {\n const prefixes = HTTP_VERB_PREFIXES[httpMethod.toUpperCase()];\n if (!prefixes) return undefined;\n\n const verbCandidates = candidates.filter(([name]) => {\n const lower = name.toLowerCase();\n return prefixes.some((p) => lower.startsWith(p));\n });\n\n if (verbCandidates.length === 1) return verbCandidates[0];\n return undefined;\n}\n\n// ---------------------------------------------------------------------------\n// Word-part matching helpers\n// ---------------------------------------------------------------------------\n\n/** Split a camelCase identifier into its word parts (e.g., \"getByExternalId\" → [\"get\",\"By\",\"External\",\"Id\"]). */\nfunction splitCamelCase(name: string): string[] {\n const parts: string[] = [];\n let start = 0;\n for (let i = 1; i < name.length; i++) {\n if (name[i] >= 'A' && name[i] <= 'Z') {\n parts.push(name.slice(start, i));\n start = i;\n }\n }\n parts.push(name.slice(start));\n return parts;\n}\n\n/** Check if `needle` words form a subsequence of `haystack` words (case-insensitive). */\nfunction isSubsequence(needle: string[], haystack: string[]): boolean {\n let ni = 0;\n for (let hi = 0; hi < haystack.length && ni < needle.length; hi++) {\n if (needle[ni].toLowerCase() === haystack[hi].toLowerCase()) ni++;\n }\n return ni === needle.length;\n}\n\n// ---------------------------------------------------------------------------\n// Automatic model name inference\n// ---------------------------------------------------------------------------\n\n/**\n * Normalize a field name to a canonical form for comparison.\n * Handles camelCase → snake_case so \"createdAt\" and \"created_at\" match.\n */\nfunction normalizeFieldName(name: string): string {\n return toSnakeCase(name);\n}\n\n/**\n * Compute the Jaccard similarity between two sets of normalized field names.\n * Returns score (0–1) and raw intersection count.\n */\nfunction jaccardSimilarity(a: Set<string>, b: Set<string>): { score: number; intersection: number } {\n if (a.size === 0 && b.size === 0) return { score: 0, intersection: 0 };\n let intersection = 0;\n for (const item of a) {\n if (b.has(item)) intersection++;\n }\n const union = a.size + b.size - intersection;\n return { score: union === 0 ? 0 : intersection / union, intersection };\n}\n\n/**\n * Build a set of normalized field names from an IR model.\n */\nfunction irModelFieldSignature(model: Model): Set<string> {\n return new Set(model.fields.map((f) => normalizeFieldName(f.name)));\n}\n\n/**\n * Build a set of normalized field names from an SDK interface.\n */\nfunction sdkInterfaceFieldSignature(iface: ApiInterface): Set<string> {\n return new Set(Object.keys(iface.fields).map(normalizeFieldName));\n}\n\n/**\n * Populate the modelNameByIR map using two strategies:\n *\n * 1. Operation-based matching (high confidence):\n * When a manifest maps an HTTP operation to an SDK method, extract the\n * method's return type and parameter types. Match them against the IR\n * operation's response model and request body model.\n *\n * 2. Field-structure matching (fallback):\n * For IR models not matched by operations, compare their field names\n * against all SDK interfaces using Jaccard similarity. A match requires\n * ≥60% field overlap with ≥3 fields in common.\n */\nfunction buildModelNameMap(\n surface: ApiSurface,\n spec: ApiSpec,\n lookup: OverlayLookup,\n hints: LanguageHints,\n options?: { strictModelMatch?: boolean },\n): void {\n const mapped = new Set<string>(); // IR model names already mapped\n const usedSdkNames = new Set<string>(); // SDK names already claimed\n\n // --- Strategy 1: Operation-based matching ---\n if (lookup.methodByOperation.size > 0) {\n for (const service of spec.services) {\n for (const op of service.operations) {\n const httpKey = `${op.httpMethod.toUpperCase()} ${op.path}`;\n const methodOverlay = lookup.methodByOperation.get(httpKey);\n if (!methodOverlay) continue;\n\n // Match response model → SDK return type\n if (op.response.kind === 'model' && !mapped.has(op.response.name)) {\n const sdkTypeName = hints.extractReturnTypeName(methodOverlay.returnType);\n if (sdkTypeName && surface.interfaces[sdkTypeName]) {\n lookup.modelNameByIR.set(op.response.name, sdkTypeName);\n mapped.add(op.response.name);\n usedSdkNames.add(sdkTypeName);\n }\n }\n\n // Match request body model → SDK param type\n if (op.requestBody?.kind === 'model' && !mapped.has(op.requestBody.name)) {\n for (const param of methodOverlay.params) {\n const sdkTypeName = hints.extractParamTypeName(param.type);\n if (sdkTypeName && surface.interfaces[sdkTypeName]) {\n lookup.modelNameByIR.set(op.requestBody.name, sdkTypeName);\n mapped.add(op.requestBody.name);\n usedSdkNames.add(sdkTypeName);\n break;\n }\n }\n }\n }\n }\n }\n\n // --- Strategy 2: Field-structure matching ---\n // Pre-compute SDK interface field signatures\n const sdkSignatures: { name: string; fields: Set<string>; fieldCount: number }[] = [];\n for (const [name, iface] of Object.entries(surface.interfaces)) {\n if (usedSdkNames.has(name)) continue;\n const fields = sdkInterfaceFieldSignature(iface);\n if (fields.size >= 2) {\n sdkSignatures.push({ name, fields, fieldCount: fields.size });\n }\n }\n\n const sdkSignatureNames = new Set(sdkSignatures.map((s) => s.name));\n\n for (const model of spec.models) {\n if (mapped.has(model.name)) continue;\n if (model.fields.length < 2) continue;\n\n // Strategy 2a: Prefer exact name match — if the IR model name matches an SDK\n // interface name exactly, use it without Jaccard scoring. This prevents\n // false positives when a superset interface (e.g., DirectoryUserWithGroups)\n // scores higher than the exact match (DirectoryUser).\n if (sdkSignatureNames.has(model.name) && !usedSdkNames.has(model.name)) {\n lookup.modelNameByIR.set(model.name, model.name);\n mapped.add(model.name);\n usedSdkNames.add(model.name);\n continue;\n }\n\n // Strategy 2a+: Try derived model names before falling back to Jaccard\n const derivedNames = hints.derivedModelNames(model.name);\n for (const derived of derivedNames) {\n if (sdkSignatureNames.has(derived) && !usedSdkNames.has(derived)) {\n lookup.modelNameByIR.set(model.name, derived);\n mapped.add(model.name);\n usedSdkNames.add(derived);\n break;\n }\n }\n if (mapped.has(model.name)) continue;\n\n // In strict mode, skip Jaccard entirely\n if (options?.strictModelMatch) continue;\n\n // Strategy 2b: Fall back to Jaccard field-similarity matching\n const irFields = irModelFieldSignature(model);\n let bestMatch: string | null = null;\n let bestScore = 0;\n\n for (const sdk of sdkSignatures) {\n if (usedSdkNames.has(sdk.name)) continue;\n\n const { score, intersection } = jaccardSimilarity(irFields, sdk.fields);\n\n // Require ≥60% Jaccard AND enough fields in common (scaled by model size)\n const minIntersection = Math.max(3, Math.ceil(irFields.size * 0.5));\n if (score > bestScore && score >= 0.6 && intersection >= minIntersection) {\n bestScore = score;\n bestMatch = sdk.name;\n }\n }\n\n if (bestMatch) {\n lookup.modelNameByIR.set(model.name, bestMatch);\n mapped.add(model.name);\n usedSdkNames.add(bestMatch);\n }\n }\n}\n\n/** Categories that can be patched by the overlay retry loop. */\nconst PATCHABLE_CATEGORIES = new Set(['symbol_removed', 'symbol_renamed']);\n\n/** Check if a classified change is patchable by the overlay loop. */\nexport function isPatchableChange(change: ClassifiedChange): boolean {\n return PATCHABLE_CATEGORIES.has(change.category);\n}\n\n/**\n * Patch overlay with classified changes from a failed verification.\n * Adds explicit name mappings for symbols that were generated with wrong names.\n * Returns a new OverlayLookup (immutable).\n */\nexport function patchOverlay(overlay: OverlayLookup, changes: ClassifiedChange[], baseline: ApiSurface): OverlayLookup {\n const patched: OverlayLookup = {\n methodByOperation: new Map(overlay.methodByOperation),\n httpKeyByMethod: new Map(overlay.httpKeyByMethod),\n interfaceByName: new Map(overlay.interfaceByName),\n typeAliasByName: new Map(overlay.typeAliasByName),\n requiredExports: new Map(Array.from(overlay.requiredExports.entries()).map(([k, v]) => [k, new Set(v)])),\n modelNameByIR: new Map(overlay.modelNameByIR),\n fileBySymbol: new Map(overlay.fileBySymbol),\n };\n\n let warnedManifest = false;\n\n for (const c of changes) {\n if (!isPatchableChange(c)) continue;\n\n // symbol is the fqName, e.g. \"ClassName.methodName\" or \"ClassName\"\n const parts = c.symbol.split('.');\n if (parts.length === 2) {\n const [className, methodName] = parts;\n const baseClass = baseline.classes[className];\n if (baseClass && baseClass.methods[methodName]?.length > 0) {\n const httpKey = overlay.httpKeyByMethod.get(`${className}.${methodName}`);\n if (!httpKey && overlay.httpKeyByMethod.size === 0 && !warnedManifest) {\n console.warn(\n 'Warning: No operations map in .oagen-manifest.json. Method-level violations cannot be auto-patched. ' +\n 'Implement buildOperationsMap in your emitter for the self-correcting loop to resolve these.',\n );\n warnedManifest = true;\n }\n if (httpKey) {\n const method = baseClass.methods[methodName][0];\n patched.methodByOperation.set(httpKey, {\n className,\n methodName,\n params: method.params,\n returnType: method.returnType,\n });\n }\n }\n const baseIface = baseline.interfaces[className];\n if (baseIface) {\n patched.interfaceByName.set(className, className);\n }\n } else if (parts.length === 1) {\n const name = parts[0];\n if (baseline.interfaces[name]) {\n patched.interfaceByName.set(name, name);\n }\n if (baseline.typeAliases[name]) {\n patched.typeAliasByName.set(name, name);\n }\n }\n }\n\n return patched;\n}\n","import { RegistryError } from '../errors.js';\nimport type { Extractor } from './types.js';\n\nconst extractors = new Map<string, Extractor>();\n\nexport function registerExtractor(extractor: Extractor): void {\n extractors.set(extractor.language, extractor);\n}\n\nexport function getExtractor(language: string): Extractor {\n const extractor = extractors.get(language);\n if (!extractor) {\n const available = [...extractors.keys()].join(', ') || '(none)';\n throw new RegistryError(\n `No extractor registered for language: ${language}. Available: ${available}`,\n `Register an extractor for \"${language}\" via registerExtractor() or add one in your oagen.config.ts plugin.`,\n );\n }\n return extractor;\n}\n","import { readFileSync, existsSync } from 'node:fs';\nimport * as path from 'node:path';\nimport { MANIFEST_FILENAME } from './manifest.js';\n\n/** Minimal shape matching compat/overlay.ts ManifestEntry for cross-layer use. */\ninterface ManifestEntry {\n operationId: string;\n sdkResourceProperty: string;\n sdkMethodName: string;\n httpMethod: string;\n path: string;\n pathParams: string[];\n bodyFields: string[];\n queryFields: string[];\n}\n\n/**\n * Read the operations map from `.oagen-manifest.json` in the given directory\n * and convert it to `ManifestEntry[]` for the overlay builder.\n *\n * Returns undefined if the manifest is absent or has no operations field.\n */\nexport function readManifestSync(dir: string): ManifestEntry[] | undefined {\n const manifestPath = path.join(dir, MANIFEST_FILENAME);\n if (!existsSync(manifestPath)) return undefined;\n try {\n const parsed = JSON.parse(readFileSync(manifestPath, 'utf-8'));\n const operations = parsed?.operations;\n if (!operations || typeof operations !== 'object') return undefined;\n return convertOperationsToManifestEntries(operations);\n } catch {\n return undefined;\n }\n}\n\n/** Convert the operations map from .oagen-manifest.json into ManifestEntry[]. */\nfunction convertOperationsToManifestEntries(operations: Record<string, unknown>): ManifestEntry[] {\n const entries: ManifestEntry[] = [];\n for (const [httpKey, value] of Object.entries(operations)) {\n const spaceIdx = httpKey.indexOf(' ');\n const httpMethod = httpKey.slice(0, spaceIdx);\n const httpPath = httpKey.slice(spaceIdx + 1);\n\n const values = Array.isArray(value) ? value : [value];\n for (const v of values) {\n const entry = v as { sdkMethod?: string; service?: string };\n entries.push({\n operationId: '',\n sdkResourceProperty: entry.service ?? '',\n sdkMethodName: entry.sdkMethod ?? '',\n httpMethod,\n path: httpPath,\n pathParams: [],\n bodyFields: [],\n queryFields: [],\n });\n }\n }\n return entries;\n}\n","import { readFileSync } from 'node:fs';\nimport { ConfigError } from '../errors.js';\nimport { buildOverlayLookup } from '../compat/overlay.js';\nimport type { ApiSurface, LanguageHints, OverlayLookup } from '../compat/types.js';\nimport type { ApiSpec } from '../ir/types.js';\nimport { nodeHints } from '../compat/language-hints.js';\nimport { getExtractor } from '../compat/extractor-registry.js';\nimport { readManifestSync } from '../engine/manifest-reader.js';\n\nexport interface OverlayContext {\n apiSurface: ApiSurface;\n overlayLookup: OverlayLookup;\n}\n\n/**\n * Load an API surface from disk, discover/load the manifest, resolve\n * language hints, and build the overlay lookup. Shared by diff and generate.\n */\nexport function loadOverlayContext(opts: {\n apiSurfacePath: string;\n outputDir: string;\n lang: string;\n spec?: ApiSpec;\n}): OverlayContext {\n let raw: string;\n try {\n raw = readFileSync(opts.apiSurfacePath, 'utf-8');\n } catch {\n throw new ConfigError(\n `API surface file not found: ${opts.apiSurfacePath}. Run \\`oagen extract\\` first.`,\n `Generate the API surface file by running \\`oagen extract --lang ${opts.lang} --sdk-path <path-to-sdk>\\` before running this command.`,\n );\n }\n let apiSurface: ApiSurface;\n try {\n apiSurface = JSON.parse(raw) as ApiSurface;\n } catch (err) {\n throw new ConfigError(\n `Failed to parse API surface JSON: ${err instanceof Error ? err.message : String(err)}`,\n `Ensure \"${opts.apiSurfacePath}\" contains valid JSON. Re-run \\`oagen extract\\` to regenerate it.`,\n );\n }\n\n // Load operations from .oagen-manifest.json in output directory\n const manifest = readManifestSync(opts.outputDir);\n\n let hints: LanguageHints = nodeHints;\n try {\n hints = getExtractor(opts.lang).hints;\n } catch {\n // no extractor registered — use nodeHints fallback\n }\n\n const overlayLookup = buildOverlayLookup(apiSurface, manifest, opts.spec, hints);\n return { apiSurface, overlayLookup };\n}\n","import type { ApiSpec } from '../ir/types.js';\n\n/**\n * Walk all description fields in the IR and expand relative URL paths\n * (e.g. `/reference/authkit/user`) into full URLs using the given base.\n *\n * Matches markdown-style links: `[text](/path)` → `[text](https://example.com/path)`\n * and bare parenthetical refs: `(/path)` → `(https://example.com/path)`\n */\nexport function expandDocUrls(spec: ApiSpec, docUrl: string): ApiSpec {\n // Normalize: strip trailing slash so joins are clean\n const base = docUrl.replace(/\\/+$/, '');\n\n function expand(description: string | undefined): string | undefined {\n if (!description) return description;\n // Match markdown links and bare parenthetical paths with a leading slash\n return description.replace(/\\(\\/([^)]*)\\)/g, `(${base}/$1)`);\n }\n\n return {\n ...spec,\n description: expand(spec.description),\n services: spec.services.map((service) => ({\n ...service,\n description: expand(service.description),\n operations: service.operations.map((op) => ({\n ...op,\n description: expand(op.description),\n pathParams: op.pathParams.map((p) => ({ ...p, description: expand(p.description) })),\n queryParams: op.queryParams.map((p) => ({ ...p, description: expand(p.description) })),\n headerParams: op.headerParams.map((p) => ({ ...p, description: expand(p.description) })),\n })),\n })),\n models: spec.models.map((model) => ({\n ...model,\n description: expand(model.description),\n fields: model.fields.map((f) => ({ ...f, description: expand(f.description) })),\n })),\n enums: spec.enums.map((e) => ({\n ...e,\n values: e.values.map((v) => ({ ...v, description: expand(v.description) })),\n })),\n };\n}\n","import { parseSpec } from '../parser/parse.js';\nimport { generate } from '../engine/orchestrator.js';\nimport { getEmitter } from '../engine/registry.js';\nimport { loadOverlayContext } from './overlay-loader.js';\nimport { expandDocUrls } from '../utils/expand-doc-urls.js';\nimport type { OperationHint } from '../ir/operation-hints.js';\n\nexport async function generateCommand(opts: {\n spec: string;\n lang: string;\n output: string;\n target?: string;\n namespace?: string;\n dryRun?: boolean;\n apiSurface?: string;\n compatCheck?: boolean;\n /** From `--no-prune`. When false, manifest-driven stale-file pruning is skipped. */\n prune?: boolean;\n operationIdTransform?: (id: string) => string;\n schemaNameTransform?: (name: string) => string;\n docUrl?: string;\n operationHints?: Record<string, OperationHint>;\n mountRules?: Record<string, string>;\n}): Promise<void> {\n let ir = await parseSpec(opts.spec, {\n operationIdTransform: opts.operationIdTransform,\n schemaNameTransform: opts.schemaNameTransform,\n });\n if (opts.docUrl) {\n ir = expandDocUrls(ir, opts.docUrl);\n }\n const emitter = getEmitter(opts.lang);\n const namespace = opts.namespace ?? ir.name;\n\n // Build overlay from API surface if provided and not disabled\n let apiSurface;\n let overlayLookup;\n if (opts.apiSurface && opts.compatCheck !== false) {\n const ctx = loadOverlayContext({\n apiSurfacePath: opts.apiSurface,\n outputDir: opts.output,\n lang: opts.lang,\n spec: ir,\n });\n apiSurface = ctx.apiSurface;\n overlayLookup = ctx.overlayLookup;\n }\n\n const files = await generate(ir, emitter, {\n namespace,\n dryRun: opts.dryRun,\n outputDir: opts.output,\n target: opts.target,\n apiSurface,\n overlayLookup,\n operationHints: opts.operationHints,\n mountRules: opts.mountRules,\n noPrune: opts.prune === false,\n });\n\n if (opts.dryRun) {\n for (const f of files) {\n console.log(f.path);\n }\n } else {\n console.log(`Generated ${files.length} files in ${opts.output}`);\n if (opts.target) {\n console.log(`Integrated into ${opts.target}`);\n }\n }\n}\n","import type { FieldChange, ParamChange } from './types.js';\n\nexport function classifyFieldChange(kind: FieldChange['kind'], fieldName: string, isRequired?: boolean): FieldChange {\n switch (kind) {\n case 'field-added':\n return {\n kind,\n fieldName,\n classification: isRequired ? 'breaking' : 'additive',\n };\n case 'field-removed':\n return { kind, fieldName, classification: 'breaking' };\n case 'field-type-changed':\n return { kind, fieldName, classification: 'breaking' };\n case 'field-required-changed':\n return {\n kind,\n fieldName,\n classification: isRequired ? 'breaking' : 'additive',\n details: isRequired ? 'optional → required' : 'required → optional',\n };\n case 'field-access-changed':\n return { kind, fieldName, classification: 'breaking' };\n }\n}\n\nexport function classifyParamChange(kind: ParamChange['kind'], paramName: string, isRequired?: boolean): ParamChange {\n switch (kind) {\n case 'param-added':\n return {\n kind,\n paramName,\n classification: isRequired ? 'breaking' : 'additive',\n };\n case 'param-removed':\n return { kind, paramName, classification: 'breaking' };\n case 'param-type-changed':\n return { kind, paramName, classification: 'breaking' };\n case 'param-required-changed':\n return {\n kind,\n paramName,\n classification: isRequired ? 'breaking' : 'additive',\n };\n }\n}\n","import type { Model, TypeRef } from '../ir/types.js';\nimport { assertNever } from '../ir/types.js';\nimport type { Change, FieldChange } from './types.js';\nimport { classifyFieldChange } from './classify.js';\n\nexport function diffModels(oldModels: Model[], newModels: Model[]): Change[] {\n const changes: Change[] = [];\n const oldByName = new Map(oldModels.map((m) => [m.name, m]));\n const newByName = new Map(newModels.map((m) => [m.name, m]));\n\n for (const [name] of newByName) {\n if (!oldByName.has(name)) {\n changes.push({ kind: 'model-added', name, classification: 'additive' });\n }\n }\n\n for (const [name] of oldByName) {\n if (!newByName.has(name)) {\n changes.push({ kind: 'model-removed', name, classification: 'breaking' });\n }\n }\n\n for (const [name, newModel] of newByName) {\n const oldModel = oldByName.get(name);\n if (!oldModel) continue;\n\n const fieldChanges = diffFields(oldModel, newModel);\n if (fieldChanges.length > 0) {\n const hasBreaking = fieldChanges.some((fc) => fc.classification === 'breaking');\n changes.push({\n kind: 'model-modified',\n name,\n fieldChanges,\n classification: hasBreaking ? 'breaking' : 'additive',\n });\n }\n }\n\n return changes;\n}\n\nfunction diffFields(oldModel: Model, newModel: Model): FieldChange[] {\n const changes: FieldChange[] = [];\n const oldByName = new Map(oldModel.fields.map((f) => [f.name, f]));\n const newByName = new Map(newModel.fields.map((f) => [f.name, f]));\n\n for (const [name, field] of newByName) {\n if (!oldByName.has(name)) {\n changes.push(classifyFieldChange('field-added', name, field.required));\n }\n }\n\n for (const [name] of oldByName) {\n if (!newByName.has(name)) {\n changes.push(classifyFieldChange('field-removed', name));\n }\n }\n\n for (const [name, newField] of newByName) {\n const oldField = oldByName.get(name);\n if (!oldField) continue;\n\n if (!typeRefsEqual(oldField.type, newField.type)) {\n changes.push({\n kind: 'field-type-changed',\n fieldName: name,\n classification: 'breaking',\n details: `type changed`,\n });\n }\n\n if (oldField.required !== newField.required) {\n changes.push(classifyFieldChange('field-required-changed', name, newField.required));\n }\n\n if (!!oldField.readOnly !== !!newField.readOnly || !!oldField.writeOnly !== !!newField.writeOnly) {\n changes.push(classifyFieldChange('field-access-changed', name));\n }\n }\n\n return changes;\n}\n\nexport function typeRefsEqual(a: TypeRef, b: TypeRef): boolean {\n if (a.kind !== b.kind) return false;\n\n switch (a.kind) {\n case 'primitive':\n return b.kind === 'primitive' && a.type === b.type && (a.format ?? '') === ((b as typeof a).format ?? '');\n case 'array':\n return b.kind === 'array' && typeRefsEqual(a.items, b.items);\n case 'model':\n return b.kind === 'model' && a.name === b.name;\n case 'enum':\n return b.kind === 'enum' && a.name === b.name;\n case 'literal':\n return b.kind === 'literal' && a.value === b.value;\n case 'nullable':\n return b.kind === 'nullable' && typeRefsEqual(a.inner, b.inner);\n case 'union': {\n if (b.kind !== 'union') return false;\n if (a.variants.length !== b.variants.length) return false;\n if (!a.variants.every((v, i) => typeRefsEqual(v, b.variants[i]))) return false;\n // Compare discriminator\n if (!a.discriminator && !b.discriminator) return true;\n if (!a.discriminator || !b.discriminator) return false;\n if (a.discriminator.property !== b.discriminator.property) return false;\n const aKeys = Object.keys(a.discriminator.mapping).sort();\n const bKeys = Object.keys(b.discriminator.mapping).sort();\n if (aKeys.length !== bKeys.length) return false;\n return aKeys.every((k, i) => k === bKeys[i] && a.discriminator!.mapping[k] === b.discriminator!.mapping[k]);\n }\n case 'map':\n return b.kind === 'map' && typeRefsEqual(a.valueType, b.valueType);\n }\n return assertNever(a);\n}\n","import type { ErrorResponse, Operation } from '../ir/types.js';\nimport type { Change, ParamChange } from './types.js';\nimport { classifyParamChange } from './classify.js';\nimport { typeRefsEqual } from './models.js';\n\nexport function diffOperations(serviceName: string, oldOps: Operation[], newOps: Operation[]): Change[] {\n const changes: Change[] = [];\n const oldByName = new Map(oldOps.map((o) => [o.name, o]));\n const newByName = new Map(newOps.map((o) => [o.name, o]));\n\n for (const [name] of newByName) {\n if (!oldByName.has(name)) {\n changes.push({\n kind: 'operation-added',\n serviceName,\n operationName: name,\n classification: 'additive',\n });\n }\n }\n\n for (const [name] of oldByName) {\n if (!newByName.has(name)) {\n changes.push({\n kind: 'operation-removed',\n serviceName,\n operationName: name,\n classification: 'breaking',\n });\n }\n }\n\n for (const [name, newOp] of newByName) {\n const oldOp = oldByName.get(name);\n if (!oldOp) continue;\n\n const paramChanges = diffParams(oldOp, newOp);\n const responseChanged = !typeRefsEqual(oldOp.response, newOp.response);\n const requestBodyChanged = !requestBodiesEqual(oldOp.requestBody, newOp.requestBody);\n const httpMethodChanged = oldOp.httpMethod !== newOp.httpMethod;\n const pathChanged = oldOp.path !== newOp.path;\n const paginatedChanged = !!oldOp.pagination !== !!newOp.pagination;\n const injectIdempotencyKeyChanged = oldOp.injectIdempotencyKey !== newOp.injectIdempotencyKey;\n const errorsDiff = classifyErrorsChange(oldOp.errors, newOp.errors);\n const errorsChanged = errorsDiff !== 'none';\n\n const hasChanges =\n paramChanges.length > 0 ||\n responseChanged ||\n requestBodyChanged ||\n httpMethodChanged ||\n pathChanged ||\n paginatedChanged ||\n injectIdempotencyKeyChanged ||\n errorsChanged;\n\n if (hasChanges) {\n // paginated: false→true is additive (SDK gains pagination helper)\n // paginated: true→false is breaking (SDK loses pagination helper)\n const paginatedBreaking = paginatedChanged && !newOp.pagination;\n // injectIdempotencyKey: false→true is additive (SDK gains idempotency key)\n // injectIdempotencyKey: true→false is breaking (SDK loses idempotency key)\n const injectIdempotencyKeyBreaking = injectIdempotencyKeyChanged && !newOp.injectIdempotencyKey;\n const errorsBreaking = errorsDiff === 'breaking';\n\n const hasBreaking =\n responseChanged ||\n requestBodyChanged ||\n httpMethodChanged ||\n pathChanged ||\n paginatedBreaking ||\n injectIdempotencyKeyBreaking ||\n errorsBreaking ||\n paramChanges.some((pc) => pc.classification === 'breaking');\n changes.push({\n kind: 'operation-modified',\n serviceName,\n operationName: name,\n paramChanges,\n responseChanged,\n requestBodyChanged,\n httpMethodChanged,\n pathChanged,\n paginatedChanged,\n injectIdempotencyKeyChanged,\n errorsChanged,\n classification: hasBreaking ? 'breaking' : 'additive',\n });\n }\n }\n\n return changes;\n}\n\nfunction requestBodiesEqual(a: Operation['requestBody'], b: Operation['requestBody']): boolean {\n if (!a && !b) return true;\n if (!a || !b) return false;\n return typeRefsEqual(a, b);\n}\n\nfunction classifyErrorsChange(\n oldErrors: ErrorResponse[],\n newErrors: ErrorResponse[],\n): 'none' | 'additive' | 'breaking' {\n const oldByCode = new Map(oldErrors.map((e) => [e.statusCode, e]));\n const newByCode = new Map(newErrors.map((e) => [e.statusCode, e]));\n\n let hasAdditive = false;\n let hasBreaking = false;\n\n // New error codes added → additive (SDK gains new error classes)\n for (const code of newByCode.keys()) {\n if (!oldByCode.has(code)) hasAdditive = true;\n }\n\n // Old error codes removed → breaking (SDK loses error classes)\n for (const code of oldByCode.keys()) {\n if (!newByCode.has(code)) hasBreaking = true;\n }\n\n // Shared error codes with changed types → breaking\n for (const [code, newErr] of newByCode) {\n const oldErr = oldByCode.get(code);\n if (!oldErr) continue;\n if (!oldErr.type && !newErr.type) continue;\n if (!oldErr.type || !newErr.type || !typeRefsEqual(oldErr.type, newErr.type)) {\n hasBreaking = true;\n }\n }\n\n if (hasBreaking) return 'breaking';\n if (hasAdditive) return 'additive';\n return 'none';\n}\n\nfunction diffParams(oldOp: Operation, newOp: Operation): ParamChange[] {\n const changes: ParamChange[] = [];\n const allOldParams = [...oldOp.pathParams, ...oldOp.queryParams, ...oldOp.headerParams];\n const allNewParams = [...newOp.pathParams, ...newOp.queryParams, ...newOp.headerParams];\n const oldByName = new Map(allOldParams.map((p) => [p.name, p]));\n const newByName = new Map(allNewParams.map((p) => [p.name, p]));\n\n for (const [name, param] of newByName) {\n if (!oldByName.has(name)) {\n changes.push(classifyParamChange('param-added', name, param.required));\n }\n }\n\n for (const [name] of oldByName) {\n if (!newByName.has(name)) {\n changes.push(classifyParamChange('param-removed', name));\n }\n }\n\n for (const [name, newParam] of newByName) {\n const oldParam = oldByName.get(name);\n if (!oldParam) continue;\n\n if (!typeRefsEqual(oldParam.type, newParam.type)) {\n changes.push(classifyParamChange('param-type-changed', name));\n }\n\n if (oldParam.required !== newParam.required) {\n changes.push(classifyParamChange('param-required-changed', name, newParam.required));\n }\n }\n\n return changes;\n}\n","import type { Service } from '../ir/types.js';\nimport type { Change } from './types.js';\nimport { diffOperations } from './operations.js';\n\nexport function diffServices(oldServices: Service[], newServices: Service[]): Change[] {\n const changes: Change[] = [];\n const oldByName = new Map(oldServices.map((s) => [s.name, s]));\n const newByName = new Map(newServices.map((s) => [s.name, s]));\n\n for (const [name] of newByName) {\n if (!oldByName.has(name)) {\n changes.push({ kind: 'service-added', name, classification: 'additive' });\n }\n }\n\n for (const [name] of oldByName) {\n if (!newByName.has(name)) {\n changes.push({ kind: 'service-removed', name, classification: 'breaking' });\n }\n }\n\n for (const [name, newService] of newByName) {\n const oldService = oldByName.get(name);\n if (!oldService) continue;\n\n changes.push(...diffOperations(name, oldService.operations, newService.operations));\n }\n\n return changes;\n}\n","import type { ApiSpec, Enum } from '../ir/types.js';\nimport type { Change, DiffReport, EnumValueChange } from './types.js';\nimport { diffModels } from './models.js';\nimport { diffServices } from './services.js';\n\nexport function diffSpecs(oldSpec: ApiSpec, newSpec: ApiSpec): DiffReport {\n const changes: Change[] = [\n ...diffModels(oldSpec.models, newSpec.models),\n ...diffEnums(oldSpec.enums, newSpec.enums),\n ...diffServices(oldSpec.services, newSpec.services),\n ];\n\n return {\n oldVersion: oldSpec.version,\n newVersion: newSpec.version,\n changes,\n summary: summarize(changes),\n };\n}\n\nfunction diffEnums(oldEnums: Enum[], newEnums: Enum[]): Change[] {\n const changes: Change[] = [];\n const oldByName = new Map(oldEnums.map((e) => [e.name, e]));\n const newByName = new Map(newEnums.map((e) => [e.name, e]));\n\n for (const [name] of newByName) {\n if (!oldByName.has(name)) {\n changes.push({ kind: 'enum-added', name, classification: 'additive' });\n }\n }\n\n for (const [name] of oldByName) {\n if (!newByName.has(name)) {\n changes.push({ kind: 'enum-removed', name, classification: 'breaking' });\n }\n }\n\n for (const [name, newEnum] of newByName) {\n const oldEnum = oldByName.get(name);\n if (!oldEnum) continue;\n\n const valueChanges = diffEnumValues(oldEnum, newEnum);\n if (valueChanges.length > 0) {\n const hasBreaking = valueChanges.some((vc) => vc.classification === 'breaking');\n changes.push({\n kind: 'enum-modified',\n name,\n valueChanges,\n classification: hasBreaking ? 'breaking' : 'additive',\n });\n }\n }\n\n return changes;\n}\n\nfunction diffEnumValues(oldEnum: Enum, newEnum: Enum): EnumValueChange[] {\n const changes: EnumValueChange[] = [];\n const oldByName = new Map(oldEnum.values.map((v) => [v.name, v]));\n const newByName = new Map(newEnum.values.map((v) => [v.name, v]));\n\n for (const [name] of newByName) {\n if (!oldByName.has(name)) {\n changes.push({ kind: 'value-added', valueName: name, classification: 'additive' });\n }\n }\n\n for (const [name] of oldByName) {\n if (!newByName.has(name)) {\n changes.push({ kind: 'value-removed', valueName: name, classification: 'breaking' });\n }\n }\n\n for (const [name, newVal] of newByName) {\n const oldVal = oldByName.get(name);\n if (!oldVal) continue;\n\n if (oldVal.value !== newVal.value) {\n changes.push({\n kind: 'value-changed',\n valueName: name,\n classification: 'breaking',\n details: `value changed from '${oldVal.value}' to '${newVal.value}'`,\n });\n }\n }\n\n return changes;\n}\n\nfunction summarize(changes: Change[]) {\n let added = 0;\n let removed = 0;\n let modified = 0;\n let breaking = 0;\n let additive = 0;\n\n for (const c of changes) {\n if (c.kind.endsWith('-added')) added++;\n else if (c.kind.endsWith('-removed')) removed++;\n else if (c.kind.endsWith('-modified')) modified++;\n\n if (c.classification === 'breaking') breaking++;\n else additive++;\n }\n\n return { added, removed, modified, breaking, additive };\n}\n","import { parseSpec } from '../parser/parse.js';\nimport { diffSpecs } from '../differ/diff.js';\nimport { CommandError } from '../errors.js';\nimport { expandDocUrls } from '../utils/expand-doc-urls.js';\n\nexport async function diffCommand(opts: {\n old: string;\n new: string;\n operationIdTransform?: (id: string) => string;\n schemaNameTransform?: (name: string) => string;\n docUrl?: string;\n}): Promise<void> {\n const parseOptions = {\n operationIdTransform: opts.operationIdTransform,\n schemaNameTransform: opts.schemaNameTransform,\n };\n let [oldSpec, newSpec] = await Promise.all([parseSpec(opts.old, parseOptions), parseSpec(opts.new, parseOptions)]);\n if (opts.docUrl) {\n oldSpec = expandDocUrls(oldSpec, opts.docUrl);\n newSpec = expandDocUrls(newSpec, opts.docUrl);\n }\n\n const diff = diffSpecs(oldSpec, newSpec);\n console.log(JSON.stringify(diff, null, 2));\n throw new CommandError(\n '',\n '',\n diff.summary.breaking > 0\n ? 2\n : diff.summary.modified > 0 || diff.summary.removed > 0\n ? 1\n : diff.summary.added > 0\n ? 1\n : 0,\n );\n}\n","import { writeFileSync } from 'node:fs';\nimport { getExtractor } from '../compat/extractor-registry.js';\n\nexport async function extractCommand(opts: { sdkPath: string; lang: string; output: string }): Promise<void> {\n const extractor = getExtractor(opts.lang);\n console.log(`Extracting ${opts.lang} API surface from ${opts.sdkPath}...`);\n const surface = await extractor.extract(opts.sdkPath);\n writeFileSync(opts.output, JSON.stringify(surface, null, 2));\n const symbolCount =\n Object.keys(surface.classes).length +\n Object.keys(surface.interfaces).length +\n Object.keys(surface.typeAliases).length +\n Object.keys(surface.enums).length;\n console.log(`Extracted ${symbolCount} symbols → ${opts.output}`);\n}\n","/**\n * Language-aware compatibility policy.\n *\n * Defines which aspects of the public API surface are breaking in each\n * language. Built-in defaults capture language semantics (e.g., PHP has\n * named arguments, Go does not). Config overrides allow per-SDK divergence.\n */\n\nimport type { LanguageId } from './ir.js';\n\n/** Policy hints that determine what constitutes a breaking change. */\nexport interface CompatPolicyHints {\n /** Callers reference parameter names at the call site (PHP named args, Python/Ruby keyword args, Kotlin/C# named args). */\n callerUsesParamNames: boolean;\n /** Constructor positional order is part of the public API. */\n constructorOrderMatters: boolean;\n /** Method parameter names are visible to callers. */\n methodParameterNamesArePublicApi: boolean;\n /** Constructor parameter names are visible to callers. */\n constructorParameterNamesArePublicApi: boolean;\n /** Method overload sets are part of the public API (Kotlin, C#). */\n overloadsArePublicApi: boolean;\n /** Function arity is part of the public API (Elixir, Go). */\n arityIsPublicApi: boolean;\n}\n\n/** Built-in language defaults. */\nconst LANGUAGE_DEFAULTS: Record<LanguageId, CompatPolicyHints> = {\n php: {\n callerUsesParamNames: true,\n constructorOrderMatters: true,\n methodParameterNamesArePublicApi: true,\n constructorParameterNamesArePublicApi: true,\n overloadsArePublicApi: false,\n arityIsPublicApi: false,\n },\n python: {\n callerUsesParamNames: true,\n constructorOrderMatters: true,\n methodParameterNamesArePublicApi: true,\n constructorParameterNamesArePublicApi: true,\n overloadsArePublicApi: false,\n arityIsPublicApi: false,\n },\n ruby: {\n callerUsesParamNames: true,\n constructorOrderMatters: true,\n methodParameterNamesArePublicApi: true,\n constructorParameterNamesArePublicApi: true,\n overloadsArePublicApi: false,\n arityIsPublicApi: false,\n },\n go: {\n callerUsesParamNames: false,\n constructorOrderMatters: true,\n methodParameterNamesArePublicApi: false,\n constructorParameterNamesArePublicApi: false,\n overloadsArePublicApi: false,\n arityIsPublicApi: true,\n },\n kotlin: {\n callerUsesParamNames: true,\n constructorOrderMatters: false,\n methodParameterNamesArePublicApi: true,\n constructorParameterNamesArePublicApi: true,\n overloadsArePublicApi: true,\n arityIsPublicApi: false,\n },\n dotnet: {\n callerUsesParamNames: true,\n constructorOrderMatters: false,\n methodParameterNamesArePublicApi: true,\n constructorParameterNamesArePublicApi: true,\n overloadsArePublicApi: true,\n arityIsPublicApi: false,\n },\n elixir: {\n callerUsesParamNames: true,\n constructorOrderMatters: false,\n methodParameterNamesArePublicApi: true,\n constructorParameterNamesArePublicApi: false,\n overloadsArePublicApi: false,\n arityIsPublicApi: true,\n },\n rust: {\n callerUsesParamNames: false,\n constructorOrderMatters: true,\n methodParameterNamesArePublicApi: false,\n constructorParameterNamesArePublicApi: false,\n overloadsArePublicApi: false,\n arityIsPublicApi: true,\n },\n node: {\n callerUsesParamNames: false,\n constructorOrderMatters: false,\n methodParameterNamesArePublicApi: false,\n constructorParameterNamesArePublicApi: false,\n overloadsArePublicApi: false,\n arityIsPublicApi: false,\n },\n};\n\n/** Get the built-in default policy for a language. */\nexport function getDefaultPolicy(language: LanguageId): CompatPolicyHints {\n return { ...LANGUAGE_DEFAULTS[language] };\n}\n\n/** Merge user overrides onto language defaults. Only provided keys are overridden. */\nexport function mergePolicy(defaults: CompatPolicyHints, overrides: Partial<CompatPolicyHints>): CompatPolicyHints {\n return { ...defaults, ...overrides };\n}\n\n/** All supported language IDs. */\nexport const ALL_LANGUAGE_IDS: readonly LanguageId[] = Object.keys(LANGUAGE_DEFAULTS) as LanguageId[];\n","/**\n * Schema versioning for compatibility snapshots.\n *\n * Snapshots are versioned so consumers can detect format changes and\n * apply migration logic if needed.\n */\n\nimport type { CompatSnapshot } from './ir.js';\n\n/** Current schema version for compatibility snapshots. */\nexport const COMPAT_SCHEMA_VERSION = '1';\n\n/** Validate that a parsed snapshot has a compatible schema version. */\nexport function isCompatibleSchemaVersion(snapshot: { schemaVersion?: string }): boolean {\n return snapshot.schemaVersion === COMPAT_SCHEMA_VERSION;\n}\n\n/** Validate the basic structure of a parsed compat snapshot. */\nexport function validateSnapshot(data: unknown): data is CompatSnapshot {\n if (typeof data !== 'object' || data === null) return false;\n const obj = data as Record<string, unknown>;\n return (\n typeof obj.schemaVersion === 'string' &&\n typeof obj.source === 'object' &&\n obj.source !== null &&\n typeof obj.policies === 'object' &&\n obj.policies !== null &&\n Array.isArray(obj.symbols)\n );\n}\n","/**\n * Rich compatibility IR for cross-language compatibility verification.\n *\n * These types represent the public API surface of an SDK in a language-aware,\n * machine-readable format. They extend the basic ApiSurface with richer\n * parameter semantics, sensitivity flags, and provenance metadata.\n */\n\nimport type { CompatPolicyHints } from './policy.js';\n\n/** Language identifier for emitter targets. */\nexport type LanguageId = 'node' | 'php' | 'python' | 'ruby' | 'go' | 'kotlin' | 'dotnet' | 'elixir' | 'rust';\n\n/** A full compatibility snapshot of an SDK's public API surface. */\nexport interface CompatSnapshot {\n schemaVersion: string;\n source: {\n specSha?: string;\n extractedAt: string;\n };\n policies: CompatPolicyHints;\n symbols: CompatSymbol[];\n}\n\n/** Kind of public API symbol. */\nexport type CompatSymbolKind =\n | 'service_accessor'\n | 'callable'\n | 'constructor'\n | 'field'\n | 'property'\n | 'enum'\n | 'enum_member'\n | 'alias';\n\n/** Visibility level of a symbol. */\nexport type CompatVisibility = 'public' | 'protected' | 'internal';\n\n/** Stability classification of a symbol. */\nexport type CompatStability = 'stable' | 'unstable' | 'deprecated';\n\n/** How the symbol was generated. */\nexport type CompatSourceKind =\n | 'generated_service_wrapper'\n | 'generated_model_constructor'\n | 'generated_resource_constructor'\n | 'generated_enum'\n | 'compat_alias';\n\n/** A single public API symbol with its full metadata. */\nexport interface CompatSymbol {\n id: string;\n kind: CompatSymbolKind;\n fqName: string;\n ownerFqName?: string;\n displayName: string;\n visibility: CompatVisibility;\n stability: CompatStability;\n sourceKind: CompatSourceKind;\n operationId?: string;\n schemaName?: string;\n route?: {\n method: string;\n path: string;\n };\n parameters?: CompatParameter[];\n returns?: CompatTypeRef;\n /** Type reference for field/property symbols. */\n typeRef?: CompatTypeRef;\n /** Value for enum member symbols. */\n value?: string | number;\n}\n\n/** How a parameter is passed at the call site. */\nexport type CompatPassingStyle =\n | 'positional'\n | 'keyword'\n | 'named'\n | 'keyword_or_positional'\n | 'options_object'\n | 'builder';\n\n/** A parameter on a callable or constructor symbol. */\nexport interface CompatParameter {\n publicName: string;\n wireName?: string;\n position: number;\n required: boolean;\n nullable: boolean;\n hasDefault: boolean;\n passing: CompatPassingStyle;\n type: CompatTypeRef;\n sensitivity: ParameterSensitivity;\n}\n\n/** Which aspects of this parameter are part of the public API contract. */\nexport interface ParameterSensitivity {\n order: boolean;\n publicName: boolean;\n requiredness: boolean;\n type: boolean;\n}\n\n/** A type reference — either a named type or an inline description. */\nexport interface CompatTypeRef {\n name: string;\n nullable?: boolean;\n array?: boolean;\n generic?: string[];\n}\n\n// ---------------------------------------------------------------------------\n// Bridge: ApiSurface → CompatSnapshot\n// ---------------------------------------------------------------------------\n\nimport type { ApiSurface, ApiParam } from './types.js';\nimport { getDefaultPolicy } from './policy.js';\nimport { COMPAT_SCHEMA_VERSION } from './schema.js';\n\n/**\n * Convert a legacy ApiSurface to a CompatSnapshot.\n *\n * This bridge allows existing extractors (which produce ApiSurface) to feed\n * into the new classified diff engine without requiring immediate migration.\n */\nexport function apiSurfaceToSnapshot(surface: ApiSurface): CompatSnapshot {\n const language = (surface.language || 'node') as LanguageId;\n const symbols: CompatSymbol[] = [];\n\n // Convert classes → service_accessor symbols + callable/constructor children\n for (const [className, cls] of Object.entries(surface.classes)) {\n symbols.push({\n id: `class:${className}`,\n kind: 'service_accessor',\n fqName: className,\n displayName: className,\n visibility: 'public',\n stability: cls.deprecationMessage ? 'deprecated' : 'stable',\n sourceKind: 'generated_service_wrapper',\n });\n\n // Constructor\n if (cls.constructorParams.length > 0) {\n symbols.push({\n id: `ctor:${className}`,\n kind: 'constructor',\n fqName: `${className}.constructor`,\n ownerFqName: className,\n displayName: `new ${className}`,\n visibility: 'public',\n stability: 'stable',\n sourceKind: 'generated_resource_constructor',\n parameters: cls.constructorParams.map((p, i) => apiParamToCompatParam(p, i, language)),\n });\n }\n\n // Methods\n for (const [methodName, overloads] of Object.entries(cls.methods)) {\n for (let oi = 0; oi < overloads.length; oi++) {\n const method = overloads[oi];\n const suffix = overloads.length > 1 ? `#${oi}` : '';\n symbols.push({\n id: `method:${className}.${methodName}${suffix}`,\n kind: 'callable',\n fqName: `${className}.${methodName}`,\n ownerFqName: className,\n displayName: `${className}.${methodName}`,\n visibility: 'public',\n stability: 'stable',\n sourceKind: 'generated_service_wrapper',\n parameters: method.params.map((p, i) => apiParamToCompatParam(p, i, language)),\n returns: { name: method.returnType },\n });\n }\n }\n\n // Properties\n for (const [propName, prop] of Object.entries(cls.properties)) {\n symbols.push({\n id: `prop:${className}.${propName}`,\n kind: 'property',\n fqName: `${className}.${propName}`,\n ownerFqName: className,\n displayName: `${className}.${propName}`,\n visibility: 'public',\n stability: 'stable',\n sourceKind: 'generated_service_wrapper',\n typeRef: { name: prop.type },\n });\n }\n }\n\n // Convert interfaces → field symbols\n for (const [ifaceName, iface] of Object.entries(surface.interfaces)) {\n symbols.push({\n id: `iface:${ifaceName}`,\n kind: 'alias',\n fqName: ifaceName,\n displayName: ifaceName,\n visibility: 'public',\n stability: 'stable',\n sourceKind: 'generated_resource_constructor',\n });\n\n for (const [fieldName, field] of Object.entries(iface.fields)) {\n symbols.push({\n id: `field:${ifaceName}.${fieldName}`,\n kind: 'field',\n fqName: `${ifaceName}.${fieldName}`,\n ownerFqName: ifaceName,\n displayName: `${ifaceName}.${fieldName}`,\n visibility: 'public',\n stability: 'stable',\n sourceKind: 'generated_resource_constructor',\n typeRef: { name: field.type },\n });\n }\n\n // Constructor if interface has one\n if (iface.hasCustomConstructor) {\n symbols.push({\n id: `ctor:${ifaceName}`,\n kind: 'constructor',\n fqName: `${ifaceName}.constructor`,\n ownerFqName: ifaceName,\n displayName: `new ${ifaceName}`,\n visibility: 'public',\n stability: 'stable',\n sourceKind: 'generated_resource_constructor',\n });\n }\n }\n\n // Convert type aliases\n for (const [aliasName] of Object.entries(surface.typeAliases)) {\n symbols.push({\n id: `alias:${aliasName}`,\n kind: 'alias',\n fqName: aliasName,\n displayName: aliasName,\n visibility: 'public',\n stability: 'stable',\n sourceKind: 'generated_resource_constructor',\n });\n }\n\n // Convert enums\n for (const [enumName, enumDef] of Object.entries(surface.enums)) {\n symbols.push({\n id: `enum:${enumName}`,\n kind: 'enum',\n fqName: enumName,\n displayName: enumName,\n visibility: 'public',\n stability: 'stable',\n sourceKind: 'generated_enum',\n });\n\n for (const [memberName, memberValue] of Object.entries(enumDef.members)) {\n symbols.push({\n id: `enum_member:${enumName}.${memberName}`,\n kind: 'enum_member',\n fqName: `${enumName}.${memberName}`,\n ownerFqName: enumName,\n displayName: `${enumName}.${memberName}`,\n visibility: 'public',\n stability: 'stable',\n sourceKind: 'generated_enum',\n value: memberValue,\n });\n }\n }\n\n return {\n schemaVersion: COMPAT_SCHEMA_VERSION,\n source: { extractedAt: surface.extractedAt },\n policies: getDefaultPolicy(language),\n symbols,\n };\n}\n\n/** Convert a legacy ApiParam to a CompatParameter. */\nfunction apiParamToCompatParam(param: ApiParam, position: number, language: LanguageId): CompatParameter {\n const policy = getDefaultPolicy(language);\n return {\n publicName: param.name,\n position,\n required: !param.optional,\n nullable: false,\n hasDefault: param.optional,\n passing: param.passingStyle ?? inferPassingStyle(language),\n type: { name: param.type },\n sensitivity: {\n order: policy.constructorOrderMatters,\n publicName: policy.methodParameterNamesArePublicApi,\n requiredness: true,\n type: true,\n },\n };\n}\n\n/** Infer the default parameter passing style for a language. */\nfunction inferPassingStyle(language: LanguageId): CompatPassingStyle {\n switch (language) {\n case 'python':\n case 'ruby':\n case 'elixir':\n return 'keyword';\n case 'php':\n case 'kotlin':\n case 'dotnet':\n return 'named';\n case 'node':\n return 'options_object';\n default:\n return 'positional';\n }\n}\n","import { readFileSync, writeFileSync } from 'node:fs';\nimport { createHash } from 'node:crypto';\nimport { resolve } from 'node:path';\nimport { getExtractor } from '../compat/extractor-registry.js';\nimport { parseSpec } from '../parser/parse.js';\nimport { apiSurfaceToSnapshot } from '../compat/ir.js';\nimport { readManifest } from '../engine/manifest.js';\nimport type { Manifest } from '../engine/manifest.js';\nimport type { CompatSnapshot } from '../compat/ir.js';\nimport type { ApiSurface, ApiClass } from '../compat/types.js';\nimport type { ApiSpec } from '../ir/types.js';\n\nconst SNAPSHOT_FILENAME = '.oagen-compat-snapshot.json';\n\n/** Normalize a name for case-insensitive matching: strip underscores and lowercase. */\nfunction normalize(name: string): string {\n return name.replace(/_/g, '').toLowerCase();\n}\n\n/**\n * Build a map of normalized service name → Set of generated method names\n * from the manifest's operations record.\n */\nfunction buildServiceMethodMap(operations: Record<string, unknown>): Map<string, Set<string>> {\n const result = new Map<string, Set<string>>();\n for (const value of Object.values(operations)) {\n if (typeof value !== 'object' || value === null) continue;\n const { sdkMethod, service } = value as { sdkMethod?: string; service?: string };\n if (typeof sdkMethod !== 'string' || typeof service !== 'string') continue;\n const key = normalize(service);\n if (!result.has(key)) result.set(key, new Set());\n result.get(key)!.add(sdkMethod);\n }\n return result;\n}\n\n/**\n * Filter an ApiSurface to only include generated symbols based on the manifest.\n *\n * Two levels of filtering:\n * 1. File-level: classes/interfaces/enums from files not in the manifest are\n * dropped entirely (they are wholly hand-written).\n * 2. Method-level: for service classes (those whose name matches a manifest\n * service), only methods listed in the manifest operations are kept.\n * Constructors and properties are always preserved since they are structural.\n * Non-service classes (models, enums, etc.) keep all their symbols.\n */\nfunction filterSurfaceByManifest(\n surface: ApiSurface,\n manifest: Manifest,\n): {\n filtered: ApiSurface;\n filesExcluded: number;\n methodsExcluded: number;\n} {\n const manifestFiles = new Set(manifest.files);\n const serviceMethodMap = manifest.operations\n ? buildServiceMethodMap(manifest.operations)\n : new Map<string, Set<string>>();\n\n let filesExcluded = 0;\n let methodsExcluded = 0;\n\n // Filter a record by manifest files, counting exclusions\n const filterByFile = <T extends { sourceFile?: string }>(record: Record<string, T>): Record<string, T> => {\n const result: Record<string, T> = {};\n for (const [name, entry] of Object.entries(record)) {\n if (entry.sourceFile && manifestFiles.has(entry.sourceFile)) {\n result[name] = entry;\n } else {\n filesExcluded++;\n }\n }\n return result;\n };\n\n // Filter classes: file-level first, then method-level for service classes\n const filteredClasses: Record<string, ApiClass> = {};\n for (const [name, cls] of Object.entries(surface.classes)) {\n if (cls.sourceFile && !manifestFiles.has(cls.sourceFile)) {\n filesExcluded++;\n continue;\n }\n\n // Check if this class is a service with known operations\n const generatedMethods = serviceMethodMap.get(normalize(name));\n if (generatedMethods) {\n // Service class — keep only methods that appear in manifest operations\n const methods: typeof cls.methods = {};\n for (const [methodName, overloads] of Object.entries(cls.methods)) {\n if (generatedMethods.has(methodName)) {\n methods[methodName] = overloads;\n } else {\n methodsExcluded++;\n }\n }\n filteredClasses[name] = { ...cls, methods };\n } else {\n // Model / utility class — keep all symbols\n filteredClasses[name] = cls;\n }\n }\n\n // Filter exports to only include files in the manifest\n const filteredExports: Record<string, string[]> = {};\n for (const [filePath, symbols] of Object.entries(surface.exports)) {\n if (manifestFiles.has(filePath)) {\n filteredExports[filePath] = symbols;\n }\n }\n\n return {\n filtered: {\n ...surface,\n classes: filteredClasses,\n interfaces: filterByFile(surface.interfaces),\n typeAliases: filterByFile(surface.typeAliases),\n enums: filterByFile(surface.enums),\n exports: filteredExports,\n },\n filesExcluded,\n methodsExcluded,\n };\n}\n\nexport async function compatExtractCommand(opts: {\n sdkPath: string;\n lang: string;\n output: string;\n spec?: string;\n schemaNameTransform?: (name: string) => string;\n}): Promise<void> {\n const extractor = getExtractor(opts.lang);\n console.log(`Extracting ${opts.lang} compat snapshot from ${opts.sdkPath}...`);\n\n let surface = await extractor.extract(opts.sdkPath);\n\n // If the SDK has a manifest, scope extraction to only generated symbols.\n // File-level: excludes wholly hand-written files.\n // Method-level: excludes hand-written methods on service classes.\n const manifest = await readManifest(opts.sdkPath);\n if (manifest) {\n const { filtered, filesExcluded, methodsExcluded } = filterSurfaceByManifest(surface, manifest);\n surface = filtered;\n if (filesExcluded > 0 || methodsExcluded > 0) {\n console.log(\n `Manifest filter: excluded ${filesExcluded} hand-written file(s), ${methodsExcluded} hand-written method(s)`,\n );\n }\n }\n\n const snapshot = apiSurfaceToSnapshot(surface);\n\n // Enrich with spec context if provided\n if (opts.spec) {\n const specContent = readFileSync(opts.spec, 'utf-8');\n snapshot.source.specSha = createHash('sha256').update(specContent).digest('hex');\n\n const parsedSpec = await parseSpec(opts.spec, {\n schemaNameTransform: opts.schemaNameTransform,\n });\n enrichWithSpecContext(snapshot, parsedSpec);\n }\n\n const outputPath = resolve(opts.output, SNAPSHOT_FILENAME);\n writeFileSync(outputPath, JSON.stringify(snapshot, null, 2));\n console.log(`Extracted ${snapshot.symbols.length} symbols → ${outputPath}`);\n}\n\n/**\n * Enrich snapshot symbols with spec-level identity.\n *\n * - Callable symbols get `operationId` and `route` from spec operations.\n * - Property/field/constructor/service_accessor symbols get `schemaName`\n * from spec models, enabling cross-language grouping in reports.\n *\n * The `schemaName` uses the spec-level identity (e.g. \"GenerateLinkBody.admin_emails\")\n * which is the same regardless of the language's naming conventions.\n */\nfunction enrichWithSpecContext(snapshot: CompatSnapshot, spec: ApiSpec): void {\n // Build lookup: \"ServiceName.methodName\" → { operationId, method, path }\n const opLookup = new Map<string, { operationId: string; method: string; path: string }>();\n for (const service of spec.services) {\n for (const op of service.operations) {\n const key = `${service.name}.${op.name}`;\n opLookup.set(key, {\n operationId: op.name,\n method: op.httpMethod,\n path: op.path,\n });\n }\n }\n\n // Build model field lookup for schema-level identity.\n // Normalized class name → { specModelName, fields: Map<normalizedFieldName, specFieldName> }\n const norm = (s: string) => s.replace(/_/g, '').toLowerCase();\n const modelLookup = new Map<string, { specName: string; fields: Map<string, string> }>();\n for (const model of spec.models) {\n const fieldMap = new Map<string, string>();\n for (const field of model.fields) {\n fieldMap.set(norm(field.name), field.name);\n }\n modelLookup.set(norm(model.name), { specName: model.name, fields: fieldMap });\n }\n\n for (const sym of snapshot.symbols) {\n // Enrich callables with operation identity\n if (sym.kind === 'callable') {\n const match = opLookup.get(sym.fqName);\n if (match) {\n sym.operationId = match.operationId;\n sym.route = { method: match.method, path: match.path };\n }\n }\n\n // Enrich all symbols with schema-level identity\n if (sym.ownerFqName) {\n // This symbol belongs to a class — try to match the class to a spec model\n const modelMatch = modelLookup.get(norm(sym.ownerFqName));\n if (modelMatch) {\n // Extract the local name (part after the dot)\n const localName = sym.fqName.includes('.') ? sym.fqName.split('.').pop()! : sym.fqName;\n const fieldMatch = modelMatch.fields.get(norm(localName));\n if (fieldMatch) {\n sym.schemaName = `${modelMatch.specName}.${fieldMatch}`;\n } else {\n // Class-level symbol (constructor, etc.) — use just the model name\n sym.schemaName = modelMatch.specName;\n }\n }\n } else {\n // Top-level symbol (class itself) — try to match to a spec model\n const modelMatch = modelLookup.get(norm(sym.fqName));\n if (modelMatch) {\n sym.schemaName = modelMatch.specName;\n }\n }\n }\n}\n","/**\n * Compat configuration types for `oagen.config.ts`.\n *\n * The `compat` section of the config holds human-authored policy:\n * fail thresholds, language overrides, and intentional break approvals.\n * Generated state (manifests, snapshots, reports) lives elsewhere.\n */\n\nimport type { LanguageId } from './ir.js';\nimport type { CompatPolicyHints } from './policy.js';\n\n// ---------------------------------------------------------------------------\n// Change categories\n// ---------------------------------------------------------------------------\n\n/** Breaking change categories — changes that break callers. */\nexport type BreakingChangeCategory =\n | 'symbol_removed'\n | 'symbol_renamed'\n | 'parameter_removed'\n | 'parameter_renamed'\n | 'parameter_requiredness_increased'\n | 'parameter_type_narrowed'\n | 'parameter_position_changed_order_sensitive'\n | 'constructor_position_changed_order_sensitive'\n | 'named_arg_name_removed'\n | 'keyword_name_removed'\n | 'overload_removed'\n | 'union_wrapper_migration_without_compat_alias'\n | 'field_type_changed'\n | 'return_type_changed'\n | 'enum_member_value_changed';\n\n/** Soft-risk change categories — may affect callers depending on usage. */\nexport type SoftRiskChangeCategory =\n | 'parameter_added_non_terminal_optional'\n | 'constructor_reordered_named_friendly'\n | 'default_value_changed'\n | 'wrapper_stricter_than_previous_sdk_but_matches_spec'\n | 'doc_surface_drift';\n\n/** Additive change categories — safe to ship. */\nexport type AdditiveChangeCategory =\n | 'symbol_added'\n | 'parameter_added_optional_terminal'\n | 'new_constructor_overload_added'\n | 'new_wrapper_alias_added';\n\n/** All change categories. */\nexport type CompatChangeCategory = BreakingChangeCategory | SoftRiskChangeCategory | AdditiveChangeCategory;\n\n/** Change severity levels. */\nexport type CompatChangeSeverity = 'breaking' | 'soft-risk' | 'additive';\n\n/** Provenance bucket — where the drift originated. */\nexport type CompatProvenance =\n | 'spec_shape_change'\n | 'spec_ordering_change'\n | 'emitter_template_change'\n | 'compat_extractor_change'\n | 'operation_hint_change'\n | 'manual_override_change'\n | 'normalization_change'\n | 'unknown';\n\n// ---------------------------------------------------------------------------\n// Fail threshold\n// ---------------------------------------------------------------------------\n\n/** Level at which `verify` should fail. */\nexport type CompatFailLevel = 'none' | 'breaking' | 'soft-risk';\n\n// ---------------------------------------------------------------------------\n// Approvals\n// ---------------------------------------------------------------------------\n\n/** A single intentional-break approval in `oagen.config.ts`. */\nexport interface CompatApproval {\n /** Fully-qualified symbol (e.g., \"WorkOS\\\\Service\\\\UserManagement::createUser\"). */\n symbol: string;\n /** The kind of change being approved. */\n category: CompatChangeCategory;\n /** Languages this approval applies to. Omit for all impacted languages. */\n appliesTo?: LanguageId[] | 'all-impacted-languages';\n /** Optional narrowing criteria. */\n match?: {\n parameter?: string;\n member?: string;\n oldName?: string;\n newName?: string;\n };\n /** Minimum release level required for this break. */\n allowedReleaseLevel?: 'major' | 'minor' | 'patch';\n /** Human-readable reason for this approval. */\n reason: string;\n /** Issue tracker reference (e.g., \"SDK-1234\"). */\n issue?: string;\n /** Auto-expire this approval after a version is released. */\n expiresAfterVersion?: string;\n /** Whether this approval is currently active. */\n approved?: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// Config section\n// ---------------------------------------------------------------------------\n\n/** The `compat` section of `oagen.config.ts`. */\nexport interface CompatConfig {\n /** Level at which `oagen verify` should fail. Default: 'breaking'. */\n failOn?: CompatFailLevel;\n /** Path to write the machine-readable compat report. */\n reportPath?: string;\n /** Include provenance explanations in reports. */\n explain?: boolean;\n /** Path to the baseline compatibility snapshot. */\n baselinePath?: string;\n /** Per-language policy overrides. Sparse — only override what diverges. */\n languagePolicy?: Partial<Record<LanguageId, Partial<CompatPolicyHints>>>;\n /** Intentional break approvals. */\n allow?: CompatApproval[];\n}\n\n// ---------------------------------------------------------------------------\n// Category → severity mapping\n// ---------------------------------------------------------------------------\n\nconst BREAKING_CATEGORIES: ReadonlySet<BreakingChangeCategory> = new Set<BreakingChangeCategory>([\n 'symbol_removed',\n 'symbol_renamed',\n 'parameter_removed',\n 'parameter_renamed',\n 'parameter_requiredness_increased',\n 'parameter_type_narrowed',\n 'parameter_position_changed_order_sensitive',\n 'constructor_position_changed_order_sensitive',\n 'named_arg_name_removed',\n 'keyword_name_removed',\n 'overload_removed',\n 'union_wrapper_migration_without_compat_alias',\n 'field_type_changed',\n 'return_type_changed',\n 'enum_member_value_changed',\n]);\n\nconst SOFT_RISK_CATEGORIES: ReadonlySet<SoftRiskChangeCategory> = new Set<SoftRiskChangeCategory>([\n 'parameter_added_non_terminal_optional',\n 'constructor_reordered_named_friendly',\n 'default_value_changed',\n 'wrapper_stricter_than_previous_sdk_but_matches_spec',\n 'doc_surface_drift',\n]);\n\n/** Get the default severity for a change category. */\nexport function defaultSeverityForCategory(category: CompatChangeCategory): CompatChangeSeverity {\n if (BREAKING_CATEGORIES.has(category as BreakingChangeCategory)) return 'breaking';\n if (SOFT_RISK_CATEGORIES.has(category as SoftRiskChangeCategory)) return 'soft-risk';\n return 'additive';\n}\n\n/** Check whether a severity meets or exceeds a fail threshold. */\nexport function severityMeetsThreshold(severity: CompatChangeSeverity, threshold: CompatFailLevel): boolean {\n if (threshold === 'none') return false;\n if (threshold === 'soft-risk') return severity === 'breaking' || severity === 'soft-risk';\n return severity === 'breaking';\n}\n","/**\n * Change classifier for compatibility verification.\n *\n * Takes raw diffs between baseline and candidate compat snapshots and\n * classifies each change into a specific category with policy-aware severity.\n */\n\nimport type { CompatSymbol, CompatParameter } from './ir.js';\nimport type { CompatPolicyHints } from './policy.js';\nimport type { CompatChangeCategory, CompatChangeSeverity, CompatProvenance } from './config.js';\nimport { defaultSeverityForCategory } from './config.js';\n\n/** A single classified compatibility change. */\nexport interface ClassifiedChange {\n /** Specific change category. */\n category: CompatChangeCategory;\n /** Policy-aware severity (may differ from defaultSeverityForCategory). */\n severity: CompatChangeSeverity;\n /** Fully-qualified symbol path. */\n symbol: string;\n /** Deterministic ID for grouping related changes across languages. */\n conceptualChangeId: string;\n /** Where the drift originated. */\n provenance: CompatProvenance;\n /** Description of the old state. */\n old: Record<string, string>;\n /** Description of the new state. */\n new: Record<string, string>;\n /** Human-readable explanation. */\n message: string;\n}\n\n/** Result of classifying all changes between two snapshots. */\nexport interface ClassificationResult {\n changes: ClassifiedChange[];\n summary: {\n breaking: number;\n softRisk: number;\n additive: number;\n };\n}\n\n// ---------------------------------------------------------------------------\n// Classification engine\n// ---------------------------------------------------------------------------\n\n/**\n * Classify changes between a baseline and candidate symbol.\n * Returns one or more classified changes for the diff.\n */\nexport function classifySymbolChanges(\n baseline: CompatSymbol,\n candidate: CompatSymbol | undefined,\n policy: CompatPolicyHints,\n): ClassifiedChange[] {\n const changes: ClassifiedChange[] = [];\n\n // Build spec-level ref for cross-language grouping.\n // Prefer schemaName from either symbol (baseline for removals, candidate for adds).\n const specRef = baseline.schemaName ?? candidate?.schemaName;\n\n // Symbol removed\n if (!candidate) {\n changes.push(\n makeChange({\n category: 'symbol_removed',\n symbol: baseline.fqName,\n old: { symbol: baseline.fqName },\n new: { symbol: '(removed)' },\n message: `Symbol \"${baseline.displayName}\" was removed`,\n policy,\n specRef,\n }),\n );\n return changes;\n }\n\n // Symbol renamed\n if (baseline.fqName !== candidate.fqName && baseline.id === candidate.id) {\n changes.push(\n makeChange({\n category: 'symbol_renamed',\n symbol: baseline.fqName,\n old: { name: baseline.fqName },\n new: { name: candidate.fqName },\n message: `Symbol renamed from \"${baseline.displayName}\" to \"${candidate.displayName}\"`,\n policy,\n specRef,\n }),\n );\n }\n\n // Parameter-level changes (for callables and constructors)\n if (baseline.parameters && candidate.parameters) {\n changes.push(...classifyParameterChanges(baseline, candidate, policy, specRef));\n }\n\n // Return type changes (for callables)\n if (baseline.returns && candidate.returns && baseline.returns.name !== candidate.returns.name) {\n changes.push(\n makeChange({\n category: 'return_type_changed',\n symbol: baseline.fqName,\n old: { returnType: baseline.returns.name },\n new: { returnType: candidate.returns.name },\n message: `Return type changed for \"${baseline.displayName}\" from \"${baseline.returns.name}\" to \"${candidate.returns.name}\"`,\n policy,\n specRef,\n }),\n );\n }\n\n // Field/property type changes\n if (baseline.typeRef && candidate.typeRef && baseline.typeRef.name !== candidate.typeRef.name) {\n changes.push(\n makeChange({\n category: 'field_type_changed',\n symbol: baseline.fqName,\n old: { type: baseline.typeRef.name },\n new: { type: candidate.typeRef.name },\n message: `Type changed for \"${baseline.displayName}\" from \"${baseline.typeRef.name}\" to \"${candidate.typeRef.name}\"`,\n policy,\n specRef,\n }),\n );\n }\n\n // Enum member value changes\n if (\n baseline.kind === 'enum_member' &&\n candidate.kind === 'enum_member' &&\n baseline.value !== undefined &&\n candidate.value !== undefined &&\n baseline.value !== candidate.value\n ) {\n changes.push(\n makeChange({\n category: 'enum_member_value_changed',\n symbol: baseline.fqName,\n old: { value: String(baseline.value) },\n new: { value: String(candidate.value) },\n message: `Enum value changed for \"${baseline.displayName}\" from \"${baseline.value}\" to \"${candidate.value}\"`,\n policy,\n }),\n );\n }\n\n return changes;\n}\n\n/**\n * Classify parameter-level changes between two symbol versions.\n */\nfunction classifyParameterChanges(\n baseline: CompatSymbol,\n candidate: CompatSymbol,\n policy: CompatPolicyHints,\n specRef?: string,\n): ClassifiedChange[] {\n const changes: ClassifiedChange[] = [];\n const baseParams = baseline.parameters ?? [];\n const candParams = candidate.parameters ?? [];\n\n const baseByName = new Map(baseParams.map((p) => [p.publicName, p]));\n const candByName = new Map(candParams.map((p) => [p.publicName, p]));\n const isConstructor = baseline.kind === 'constructor';\n\n // Check each baseline parameter\n for (const baseParam of baseParams) {\n const candParam = candByName.get(baseParam.publicName);\n\n if (!candParam) {\n // Parameter removed — check if it was renamed\n const positionalMatch = candParams[baseParam.position];\n if (positionalMatch && !baseByName.has(positionalMatch.publicName)) {\n // Position preserved but name changed → rename\n const isBreakingRename = parameterNameIsPublicApi(baseParam, policy, isConstructor);\n changes.push(\n makeChange({\n category: 'parameter_renamed',\n symbol: baseline.fqName,\n old: { parameter: baseParam.publicName },\n new: { parameter: positionalMatch.publicName },\n message: `Parameter \"${baseParam.publicName}\" renamed to \"${positionalMatch.publicName}\" on \"${baseline.displayName}\"`,\n policy,\n specRef,\n severityOverride: isBreakingRename ? undefined : 'soft-risk',\n }),\n );\n } else {\n // Truly removed\n changes.push(\n makeChange({\n category: 'parameter_removed',\n symbol: baseline.fqName,\n old: { parameter: baseParam.publicName },\n new: { parameter: '(removed)' },\n message: `Parameter \"${baseParam.publicName}\" removed from \"${baseline.displayName}\"`,\n policy,\n specRef,\n }),\n );\n }\n continue;\n }\n\n // Requiredness increased (optional → required)\n if (!baseParam.required && candParam.required) {\n changes.push(\n makeChange({\n category: 'parameter_requiredness_increased',\n symbol: baseline.fqName,\n old: { parameter: baseParam.publicName, required: 'false' },\n new: { parameter: candParam.publicName, required: 'true' },\n message: `Parameter \"${baseParam.publicName}\" became required on \"${baseline.displayName}\"`,\n policy,\n specRef,\n }),\n );\n }\n\n // Type narrowed\n if (baseParam.type.name !== candParam.type.name) {\n changes.push(\n makeChange({\n category: 'parameter_type_narrowed',\n symbol: baseline.fqName,\n old: { parameter: baseParam.publicName, type: baseParam.type.name },\n new: { parameter: candParam.publicName, type: candParam.type.name },\n message: `Parameter type changed for \"${baseParam.publicName}\" on \"${baseline.displayName}\"`,\n policy,\n specRef,\n }),\n );\n }\n\n // Position changed (order-sensitive)\n if (baseParam.position !== candParam.position) {\n const orderMatters = isConstructor ? policy.constructorOrderMatters : baseParam.sensitivity.order;\n\n if (orderMatters) {\n const category: CompatChangeCategory = isConstructor\n ? 'constructor_position_changed_order_sensitive'\n : 'parameter_position_changed_order_sensitive';\n changes.push(\n makeChange({\n category,\n symbol: baseline.fqName,\n old: { parameter: baseParam.publicName, position: String(baseParam.position) },\n new: { parameter: candParam.publicName, position: String(candParam.position) },\n message: `Parameter \"${baseParam.publicName}\" moved from position ${baseParam.position} to ${candParam.position} on \"${baseline.displayName}\"`,\n policy,\n specRef,\n }),\n );\n } else {\n // Reordered but in a named-friendly language → soft-risk\n changes.push(\n makeChange({\n category: 'constructor_reordered_named_friendly',\n symbol: baseline.fqName,\n old: { parameter: baseParam.publicName, position: String(baseParam.position) },\n new: { parameter: candParam.publicName, position: String(candParam.position) },\n message: `Parameter \"${baseParam.publicName}\" reordered on \"${baseline.displayName}\" (named-friendly language)`,\n policy,\n specRef,\n }),\n );\n }\n }\n }\n\n // Check for new parameters in candidate\n for (const candParam of candParams) {\n if (!baseByName.has(candParam.publicName)) {\n // Check if this was already captured as a rename\n const isRename = changes.some(\n (c) => c.category === 'parameter_renamed' && c.new.parameter === candParam.publicName,\n );\n if (isRename) continue;\n\n const isTerminal = candParam.position === candParams.length - 1;\n const category: CompatChangeCategory = candParam.required\n ? 'parameter_requiredness_increased'\n : isTerminal\n ? 'parameter_added_optional_terminal'\n : 'parameter_added_non_terminal_optional';\n\n if (candParam.required) {\n changes.push(\n makeChange({\n category,\n symbol: baseline.fqName,\n old: { parameter: '(absent)' },\n new: { parameter: candParam.publicName, required: 'true' },\n message: `Required parameter \"${candParam.publicName}\" added to \"${baseline.displayName}\"`,\n policy,\n specRef,\n }),\n );\n } else {\n changes.push(\n makeChange({\n category,\n symbol: baseline.fqName,\n old: { parameter: '(absent)' },\n new: { parameter: candParam.publicName },\n message: `Optional parameter \"${candParam.publicName}\" added to \"${baseline.displayName}\"`,\n policy,\n specRef,\n }),\n );\n }\n }\n }\n\n return changes;\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction parameterNameIsPublicApi(param: CompatParameter, policy: CompatPolicyHints, isConstructor: boolean): boolean {\n if (param.sensitivity.publicName) return true;\n if (isConstructor) return policy.constructorParameterNamesArePublicApi;\n return policy.methodParameterNamesArePublicApi;\n}\n\n/**\n * Build a deterministic conceptual change ID.\n *\n * When `specRef` is provided (e.g. \"GenerateLinkBody.admin_emails\"), it is\n * used instead of the language-specific symbol name. This ensures the same\n * spec entity produces the same ID across all languages, enabling cross-\n * language rollup in reports.\n */\nfunction buildConceptualChangeId(\n category: CompatChangeCategory,\n symbol: string,\n match: Record<string, string>,\n specRef?: string,\n): string {\n const identity = specRef ?? symbol;\n const parts = ['chg', category, identity.replace(/[^a-zA-Z0-9_.]/g, '_')];\n if (match.parameter) parts.push(match.parameter);\n if (match.member) parts.push(match.member);\n return parts.join('_').toLowerCase();\n}\n\nfunction makeChange(opts: {\n category: CompatChangeCategory;\n symbol: string;\n old: Record<string, string>;\n new: Record<string, string>;\n message: string;\n policy: CompatPolicyHints;\n provenance?: CompatProvenance;\n severityOverride?: CompatChangeSeverity;\n specRef?: string;\n}): ClassifiedChange {\n return {\n category: opts.category,\n severity: opts.severityOverride ?? defaultSeverityForCategory(opts.category),\n symbol: opts.symbol,\n conceptualChangeId: buildConceptualChangeId(opts.category, opts.symbol, opts.old, opts.specRef),\n provenance: opts.provenance ?? 'unknown',\n old: opts.old,\n new: opts.new,\n message: opts.message,\n };\n}\n\n/**\n * Classify a new symbol as additive.\n */\nexport function classifyAddedSymbol(symbol: CompatSymbol): ClassifiedChange {\n return {\n category: 'symbol_added',\n severity: 'additive',\n symbol: symbol.fqName,\n conceptualChangeId: buildConceptualChangeId('symbol_added', symbol.fqName, {}, symbol.schemaName),\n provenance: 'unknown',\n old: { symbol: '(absent)' },\n new: { symbol: symbol.fqName },\n message: `Symbol \"${symbol.displayName}\" was added`,\n };\n}\n\n/** Summarize a list of classified changes by severity. */\nexport function summarizeChanges(changes: ClassifiedChange[]): ClassificationResult['summary'] {\n let breaking = 0;\n let softRisk = 0;\n let additive = 0;\n for (const c of changes) {\n if (c.severity === 'breaking') breaking++;\n else if (c.severity === 'soft-risk') softRisk++;\n else additive++;\n }\n return { breaking, softRisk, additive };\n}\n","import type { ApiSpec, TypeRef } from '../ir/types.js';\nimport { walkTypeRef } from '../ir/types.js';\nimport type { ApiSurface, LanguageHints } from './types.js';\n\n/**\n * Compute the set of symbol names that are derivable from the OpenAPI spec.\n * Only these names should be compared during compat verification — everything\n * else in the baseline is hand-written and out of scope for generation.\n */\nexport function specDerivedNames(spec: ApiSpec, hints: LanguageHints): Set<string> {\n const names = new Set<string>();\n\n // Build set of top-level enum names for filtering inline enums\n const topLevelEnumNames = new Set(spec.enums.map((e) => e.name));\n\n // Service classes\n for (const service of spec.services) {\n names.add(service.name);\n for (const op of service.operations) {\n // Operation methods are matched by the class diff, not by name here\n collectTypeRefNames(op.response, names, hints, topLevelEnumNames);\n if (op.requestBody) collectTypeRefNames(op.requestBody, names, hints, topLevelEnumNames);\n for (const p of [...op.pathParams, ...op.queryParams, ...op.headerParams, ...(op.cookieParams ?? [])]) {\n collectTypeRefNames(p.type, names, hints, topLevelEnumNames);\n }\n }\n }\n\n // Models → domain interface + language-specific derived names\n for (const model of spec.models) {\n names.add(model.name);\n for (const derived of hints.derivedModelNames(model.name)) {\n names.add(derived);\n }\n for (const field of model.fields) {\n collectTypeRefNames(field.type, names, hints, topLevelEnumNames);\n }\n }\n\n // Enums → type aliases\n for (const e of spec.enums) {\n names.add(e.name);\n }\n\n return names;\n}\n\n/**\n * Compute a map of enum name → set of wire values that appear in the spec.\n * Used by filterSurface to exclude hand-added enum members that aren't in the spec.\n */\nexport function specDerivedEnumValues(spec: ApiSpec): Map<string, Set<string | number>> {\n const result = new Map<string, Set<string | number>>();\n for (const e of spec.enums) {\n result.set(e.name, new Set(e.values.map((v) => v.value)));\n }\n return result;\n}\n\n/**\n * Compute the set of field paths (e.g., \"Organization.name\") that are defined\n * in the OpenAPI spec's model schemas. Used by filterSurface to exclude\n * hand-added SDK fields that reference spec-derived types.\n */\nexport function specDerivedFieldPaths(spec: ApiSpec, hints: LanguageHints): Set<string> {\n const paths = new Set<string>();\n for (const model of spec.models) {\n for (const field of model.fields) {\n paths.add(`${model.name}.${field.name}`);\n }\n // Also add field paths for derived model names (e.g., OrganizationResponse.name)\n for (const derived of hints.derivedModelNames(model.name)) {\n for (const field of model.fields) {\n paths.add(`${derived}.${field.name}`);\n }\n }\n }\n return paths;\n}\n\n/**\n * Compute the set of method paths (e.g., \"SSO.authorize\") that are defined\n * as operations in the OpenAPI spec's services. Used by filterSurface to\n * exclude hand-written SDK methods that don't correspond to spec operations.\n */\nexport function specDerivedMethodPaths(spec: ApiSpec): Set<string> {\n const paths = new Set<string>();\n for (const service of spec.services) {\n for (const op of service.operations) {\n paths.add(`${service.name}.${op.name}`);\n }\n }\n return paths;\n}\n\n/**\n * Compute the set of HTTP operation keys (e.g., \"GET /sso/authorize\") that\n * exist in the spec. Used for overlay-based method matching.\n */\nexport function specDerivedHttpKeys(spec: ApiSpec): Set<string> {\n const keys = new Set<string>();\n for (const service of spec.services) {\n for (const op of service.operations) {\n keys.add(`${op.httpMethod.toUpperCase()} ${op.path}`);\n }\n }\n return keys;\n}\n\nfunction collectTypeRefNames(ref: TypeRef, out: Set<string>, hints: LanguageHints, topLevelEnums?: Set<string>): void {\n walkTypeRef(ref, {\n model: (r) => {\n out.add(r.name);\n for (const derived of hints.derivedModelNames(r.name)) {\n out.add(derived);\n }\n },\n enum: (r) => {\n // Only include enums that are top-level (in spec.enums). Inline enums\n // embedded in TypeRefs (e.g., query parameter enums) may not be emitted\n // by all emitters, so they should not create false-positive violations.\n if (!topLevelEnums || topLevelEnums.has(r.name)) {\n out.add(r.name);\n }\n },\n });\n}\n\nfunction filterRecord<T>(record: Record<string, T>, allowed: Set<string>): Record<string, T> {\n const result: Record<string, T> = {};\n for (const [name, value] of Object.entries(record)) {\n if (allowed.has(name)) result[name] = value;\n }\n return result;\n}\n\n/**\n * Filter an ApiSurface to only include symbols whose names appear in the\n * allowed set. Symbols not in the set are dropped entirely — they won't\n * count toward the total or produce violations.\n *\n * For interfaces: when fieldPaths is provided, only keeps fields that appear\n * in the spec-derived field paths. This prevents false positives from hand-added\n * SDK fields that reference spec-derived types but aren't defined in the spec.\n *\n * For classes: when methodPaths is provided, only keeps methods whose names\n * appear in the spec-derived method paths. This prevents false positives from\n * hand-written SDK methods (e.g., SSO.authorization_url, Webhooks.construct_event)\n * that don't correspond to spec operations. Properties on service classes are\n * also filtered: only UPPER_CASE constants that are spec-derivable are kept.\n */\nexport function filterSurface(\n surface: ApiSurface,\n allowedNames: Set<string>,\n opts?: {\n fieldPaths?: Set<string>;\n methodPaths?: Set<string>;\n enumValues?: Map<string, Set<string | number>>;\n },\n): ApiSurface {\n const { fieldPaths, methodPaths, enumValues } = opts ?? {};\n const filteredInterfaces = filterRecord(surface.interfaces, allowedNames);\n\n // Filter interface fields by spec-derived field paths if provided\n if (fieldPaths) {\n for (const [name, iface] of Object.entries(filteredInterfaces)) {\n const filteredFields: Record<string, (typeof iface.fields)[string]> = {};\n for (const [fieldName, field] of Object.entries(iface.fields)) {\n // Keep the field if its path is spec-derived\n if (fieldPaths.has(`${name}.${fieldName}`)) {\n filteredFields[fieldName] = field;\n }\n }\n filteredInterfaces[name] = { ...iface, fields: filteredFields };\n }\n }\n\n let filteredClasses = filterRecord(surface.classes, allowedNames);\n\n // Filter class methods and properties by spec-derived method paths if provided\n if (methodPaths) {\n // Build a set of service-class names that have spec-derived methods.\n // Only filter methods on these classes; non-service model classes keep all members.\n const serviceClassNames = new Set<string>();\n for (const path of methodPaths) {\n const dot = path.indexOf('.');\n if (dot !== -1) serviceClassNames.add(path.slice(0, dot));\n }\n\n const newClasses: Record<string, (typeof filteredClasses)[string]> = {};\n for (const [name, cls] of Object.entries(filteredClasses)) {\n if (serviceClassNames.has(name)) {\n // Service class — filter methods and properties by spec-derived method paths\n const filteredMethods: typeof cls.methods = {};\n for (const [methodName, overloads] of Object.entries(cls.methods)) {\n if (methodPaths.has(`${name}.${methodName}`)) {\n filteredMethods[methodName] = overloads;\n }\n }\n\n // Filter properties: only keep properties that are spec-derivable.\n // Hand-written constants (PROVIDERS, DEFAULT_TOLERANCE, WIDGET_SCOPES)\n // are not derivable from the spec and should be excluded.\n const filteredProperties: typeof cls.properties = {};\n for (const [propName, prop] of Object.entries(cls.properties)) {\n if (methodPaths.has(`${name}.${propName}`)) {\n filteredProperties[propName] = prop;\n }\n }\n\n newClasses[name] = {\n ...cls,\n methods: filteredMethods,\n properties: filteredProperties,\n };\n } else if (fieldPaths) {\n // Non-service (model) class — filter properties by spec-derived field paths.\n // In some languages (Ruby, PHP), models are represented as classes with\n // properties rather than interfaces with fields. Apply the same field-level\n // filtering used for interfaces to exclude hand-added SDK fields.\n const filteredProperties: typeof cls.properties = {};\n for (const [propName, prop] of Object.entries(cls.properties)) {\n if (fieldPaths.has(`${name}.${propName}`)) {\n filteredProperties[propName] = prop;\n }\n }\n\n // Also filter methods on model classes: convenience methods like\n // `primary_email` are hand-written and not spec-derivable.\n // Keep utility methods (from_json, to_json, etc.) if they appear in fieldPaths,\n // otherwise drop non-spec methods.\n const filteredMethods: typeof cls.methods = {};\n for (const [methodName, overloads] of Object.entries(cls.methods)) {\n if (fieldPaths.has(`${name}.${methodName}`) || methodPaths.has(`${name}.${methodName}`)) {\n filteredMethods[methodName] = overloads;\n }\n }\n\n newClasses[name] = {\n ...cls,\n methods: filteredMethods,\n properties: filteredProperties,\n };\n } else {\n // No filtering available — keep as-is\n newClasses[name] = cls;\n }\n }\n filteredClasses = newClasses;\n }\n\n // Filter enum members by spec-derived values if provided\n let filteredEnums = filterRecord(surface.enums, allowedNames);\n if (enumValues) {\n const newEnums: Record<string, (typeof filteredEnums)[string]> = {};\n for (const [name, enumDef] of Object.entries(filteredEnums)) {\n const specValues = enumValues.get(name);\n if (!specValues) {\n // Enum not in spec values map — keep as-is\n newEnums[name] = enumDef;\n continue;\n }\n // Filter members: keep only those whose wire value is in the spec.\n // Use case-insensitive comparison since some extractors produce\n // PascalCase values (e.g., \"Pending\") while the spec has lowercase.\n const specValuesLower = new Set([...specValues].map((v) => String(v).toLowerCase()));\n const filteredMembers: typeof enumDef.members = {};\n for (const [member, value] of Object.entries(enumDef.members)) {\n if (specValues.has(value) || specValuesLower.has(String(value).toLowerCase())) {\n filteredMembers[member] = value;\n }\n }\n newEnums[name] = { ...enumDef, members: filteredMembers };\n }\n filteredEnums = newEnums;\n }\n\n return {\n ...surface,\n classes: filteredClasses,\n interfaces: filteredInterfaces,\n typeAliases: filterRecord(surface.typeAliases, allowedNames),\n enums: filteredEnums,\n exports: {}, // exports are structural, not symbol-level — skip for scoped comparison\n };\n}\n","/**\n * Compatibility diff engine.\n *\n * Compares two API surfaces (or compat snapshots) and produces classified\n * changes with policy-aware severity, provenance, and conceptual change IDs.\n *\n * This replaces the previous unclassified diff engine with a richer model\n * that supports cross-language severity analysis and approval matching.\n */\n\nimport type { ApiSurface, ApiMethod, LanguageHints, DiffResult, Violation, Addition } from './types.js';\nimport type { CompatSnapshot, CompatSymbol } from './ir.js';\nimport type { CompatPolicyHints } from './policy.js';\nimport type { ClassifiedChange, ClassificationResult } from './classify.js';\nimport { classifySymbolChanges, classifyAddedSymbol, summarizeChanges } from './classify.js';\nimport { NAMED_TYPE_RE, typeExistsInSurface } from './language-hints.js';\n\nexport {\n specDerivedNames,\n specDerivedFieldPaths,\n specDerivedMethodPaths,\n specDerivedHttpKeys,\n specDerivedEnumValues,\n filterSurface,\n} from './spec-filter.js';\n\n// ---------------------------------------------------------------------------\n// New: CompatSnapshot-based diff\n// ---------------------------------------------------------------------------\n\n/** Result of diffing two compat snapshots. */\nexport interface CompatDiffResult {\n changes: ClassifiedChange[];\n summary: ClassificationResult['summary'];\n}\n\n/**\n * Diff two compat snapshots, producing classified changes with\n * policy-aware severity.\n */\nexport function diffSnapshots(\n baseline: CompatSnapshot,\n candidate: CompatSnapshot,\n policy?: CompatPolicyHints,\n): CompatDiffResult {\n const effectivePolicy = policy ?? baseline.policies;\n const changes: ClassifiedChange[] = [];\n\n // Index candidate symbols by ID and fqName for lookup\n const candById = new Map<string, CompatSymbol>();\n const candByFqName = new Map<string, CompatSymbol>();\n for (const sym of candidate.symbols) {\n candById.set(sym.id, sym);\n candByFqName.set(sym.fqName, sym);\n }\n\n // Index baseline symbols by fqName\n const baseByFqName = new Set<string>();\n for (const sym of baseline.symbols) {\n baseByFqName.add(sym.fqName);\n }\n\n // Compare each baseline symbol against candidate\n for (const baseSym of baseline.symbols) {\n const candSym = candById.get(baseSym.id) ?? candByFqName.get(baseSym.fqName);\n changes.push(...classifySymbolChanges(baseSym, candSym, effectivePolicy));\n }\n\n // Detect added symbols\n for (const candSym of candidate.symbols) {\n if (!baseByFqName.has(candSym.fqName)) {\n changes.push(classifyAddedSymbol(candSym));\n }\n }\n\n return {\n changes,\n summary: summarizeChanges(changes),\n };\n}\n\n// ---------------------------------------------------------------------------\n// Legacy: ApiSurface-based diff (delegates to existing logic)\n// ---------------------------------------------------------------------------\n\n/**\n * Compare two ApiSurface objects and return a DiffResult.\n *\n * This preserves the existing diffing behavior used by the overlay retry loop,\n * compat check, and all existing tests. The internal implementation uses the\n * same algorithms as before to maintain full backward compatibility with\n * overlay patching and verification workflows.\n */\nexport function diffSurfaces(baseline: ApiSurface, candidate: ApiSurface, hints: LanguageHints): DiffResult {\n const violations: Violation[] = [];\n const additions: Addition[] = [];\n let totalBaseline = 0;\n let preserved = 0;\n\n // Diff classes\n for (const [name, baseClass] of Object.entries(baseline.classes)) {\n totalBaseline++;\n const candClass = candidate.classes[name];\n if (!candClass) {\n violations.push({\n category: 'public-api',\n severity: 'breaking',\n symbolPath: name,\n baseline: name,\n candidate: '(missing)',\n message: `Class \"${name}\" exists in baseline but not in generated output`,\n });\n totalBaseline += Object.values(baseClass.methods).reduce((sum, overloads) => sum + overloads.length, 0);\n totalBaseline += Object.keys(baseClass.properties).length;\n continue;\n }\n preserved++;\n\n // Diff methods (each method name maps to an array of overloads)\n for (const [methodName, baseOverloads] of Object.entries(baseClass.methods)) {\n const candOverloads = candClass.methods[methodName];\n for (const baseMethod of baseOverloads) {\n totalBaseline++;\n if (!candOverloads || candOverloads.length === 0) {\n violations.push({\n category: 'public-api',\n severity: 'breaking',\n symbolPath: `${name}.${methodName}`,\n baseline: methodName,\n candidate: '(missing)',\n message: `Method \"${name}.${methodName}\" exists in baseline but not in generated output`,\n });\n continue;\n }\n const candMethod = candOverloads.find((c) => signaturesMatch(baseMethod, c));\n if (!candMethod) {\n // Fallback: check language-specific signature equivalence\n const equivalentMethod = hints.isSignatureEquivalent\n ? candOverloads.find((c) => hints.isSignatureEquivalent!(baseMethod, c, candidate))\n : undefined;\n if (equivalentMethod) {\n preserved++;\n continue;\n }\n violations.push({\n category: 'signature',\n severity: 'breaking',\n symbolPath: `${name}.${methodName}`,\n baseline: formatSignature(baseMethod),\n candidate: formatSignature(candOverloads[0]),\n message: `Signature mismatch for \"${name}.${methodName}\"`,\n });\n continue;\n }\n preserved++;\n }\n }\n\n // Check for new methods (additions)\n for (const methodName of Object.keys(candClass.methods)) {\n if (!baseClass.methods[methodName]) {\n additions.push({ symbolPath: `${name}.${methodName}`, symbolType: 'method' });\n }\n }\n\n // Diff properties\n for (const [propName, baseProp] of Object.entries(baseClass.properties)) {\n totalBaseline++;\n const candProp = candClass.properties[propName];\n if (!candProp) {\n violations.push({\n category: 'public-api',\n severity: 'breaking',\n symbolPath: `${name}.${propName}`,\n baseline: baseProp.type,\n candidate: '(missing)',\n message: `Property \"${name}.${propName}\" exists in baseline but not in generated output`,\n });\n continue;\n }\n if (baseProp.type !== candProp.type) {\n const nullableOnly = hints.isNullableOnlyDifference(baseProp.type, candProp.type);\n violations.push({\n category: 'signature',\n severity: nullableOnly ? 'warning' : 'breaking',\n symbolPath: `${name}.${propName}`,\n baseline: baseProp.type,\n candidate: candProp.type,\n message: `Property type mismatch for \"${name}.${propName}\"`,\n });\n if (nullableOnly) preserved++;\n continue;\n }\n preserved++;\n }\n\n // Check for new properties (additions)\n for (const propName of Object.keys(candClass.properties)) {\n if (!baseClass.properties[propName]) {\n additions.push({ symbolPath: `${name}.${propName}`, symbolType: 'property' });\n }\n }\n }\n\n // Check for new classes (additions)\n for (const name of Object.keys(candidate.classes)) {\n if (!baseline.classes[name]) {\n additions.push({ symbolPath: name, symbolType: 'class' });\n }\n }\n\n // Precompute lowercased field/property name sets for field-structure matching\n const candIfaceFieldSets = new Map<string, Set<string>>();\n for (const [n, iface] of Object.entries(candidate.interfaces)) {\n candIfaceFieldSets.set(n, new Set(Object.keys(iface.fields).map((f) => f.toLowerCase())));\n }\n const candClassPropSets = new Map<string, Set<string>>();\n for (const [n, cls] of Object.entries(candidate.classes)) {\n candClassPropSets.set(n, new Set(Object.keys(cls.properties).map((f) => f.toLowerCase())));\n }\n\n // Diff interfaces\n for (const [name, baseIface] of Object.entries(baseline.interfaces)) {\n totalBaseline++;\n const candIface = candidate.interfaces[name];\n if (!candIface) {\n let tolerated = false;\n if (hints.tolerateCategoryMismatch && name.startsWith('Serialized')) {\n const baseName = name.slice('Serialized'.length);\n if (candidate.interfaces[baseName] || candidate.classes[baseName]) {\n tolerated = true;\n }\n }\n if (tolerated) {\n preserved++;\n totalBaseline += Object.keys(baseIface.fields).length;\n preserved += Object.keys(baseIface.fields).length;\n continue;\n }\n if (!tolerated) {\n const baseFieldNamesLower = new Set(Object.keys(baseIface.fields).map((f) => f.toLowerCase()));\n if (baseFieldNamesLower.size > 0) {\n for (const [, candFieldNamesLower] of candIfaceFieldSets) {\n if (\n candFieldNamesLower.size === baseFieldNamesLower.size &&\n [...baseFieldNamesLower].every((f) => candFieldNamesLower.has(f))\n ) {\n tolerated = true;\n break;\n }\n }\n if (!tolerated) {\n for (const [, candPropNamesLower] of candClassPropSets) {\n if (\n candPropNamesLower.size === baseFieldNamesLower.size &&\n [...baseFieldNamesLower].every((f) => candPropNamesLower.has(f))\n ) {\n tolerated = true;\n break;\n }\n }\n }\n } else {\n tolerated = true;\n }\n }\n if (tolerated) {\n preserved++;\n totalBaseline += Object.keys(baseIface.fields).length;\n preserved += Object.keys(baseIface.fields).length;\n continue;\n }\n violations.push({\n category: 'public-api',\n severity: 'breaking',\n symbolPath: name,\n baseline: name,\n candidate: '(missing)',\n message: `Interface \"${name}\" exists in baseline but not in generated output`,\n });\n totalBaseline += Object.keys(baseIface.fields).length;\n continue;\n }\n preserved++;\n\n for (const [fieldName, baseField] of Object.entries(baseIface.fields)) {\n totalBaseline++;\n const candField = candIface.fields[fieldName];\n if (!candField) {\n const baseTypeClean = baseField.type.replace(/\\[\\]$/, '').replace(/ \\| null$/, '');\n const typeIsUnresolvable = NAMED_TYPE_RE.test(baseTypeClean) && !typeExistsInSurface(baseTypeClean, candidate);\n violations.push({\n category: 'public-api',\n severity: typeIsUnresolvable ? 'warning' : 'breaking',\n symbolPath: `${name}.${fieldName}`,\n baseline: baseField.type,\n candidate: '(missing)',\n message: `Field \"${name}.${fieldName}\" exists in baseline but not in generated output`,\n });\n if (typeIsUnresolvable) preserved++;\n continue;\n }\n if (baseField.type !== candField.type) {\n if (hints.isUnionReorder(baseField.type, candField.type)) {\n preserved++;\n continue;\n }\n if (hints.isTypeEquivalent?.(baseField.type, candField.type, candidate)) {\n preserved++;\n continue;\n }\n const nullableOnly = hints.isNullableOnlyDifference(baseField.type, candField.type);\n const genericParam = hints.isGenericTypeParam(baseField.type);\n const extractionArtifact = hints.isExtractionArtifact(candField.type);\n const isWarning = nullableOnly || genericParam || extractionArtifact;\n violations.push({\n category: 'signature',\n severity: isWarning ? 'warning' : 'breaking',\n symbolPath: `${name}.${fieldName}`,\n baseline: baseField.type,\n candidate: candField.type,\n message: `Field type mismatch for \"${name}.${fieldName}\"`,\n });\n if (isWarning) preserved++;\n continue;\n }\n preserved++;\n }\n\n for (const fieldName of Object.keys(candIface.fields)) {\n if (!baseIface.fields[fieldName]) {\n additions.push({ symbolPath: `${name}.${fieldName}`, symbolType: 'property' });\n }\n }\n }\n\n // Check for new interfaces (additions)\n for (const name of Object.keys(candidate.interfaces)) {\n if (!baseline.interfaces[name]) {\n additions.push({ symbolPath: name, symbolType: 'interface' });\n }\n }\n\n // Diff type aliases\n for (const [name, baseAlias] of Object.entries(baseline.typeAliases)) {\n totalBaseline++;\n const candAlias = candidate.typeAliases[name];\n if (!candAlias) {\n if (hints.tolerateCategoryMismatch && typeExistsInSurface(name, candidate)) {\n preserved++;\n continue;\n }\n violations.push({\n category: 'public-api',\n severity: 'breaking',\n symbolPath: name,\n baseline: baseAlias.value,\n candidate: '(missing)',\n message: `Type alias \"${name}\" exists in baseline but not in generated output`,\n });\n continue;\n }\n if (baseAlias.value !== candAlias.value) {\n if (hints.isUnionReorder(baseAlias.value, candAlias.value)) {\n preserved++;\n continue;\n }\n const nullableOnly = hints.isNullableOnlyDifference(baseAlias.value, candAlias.value);\n violations.push({\n category: 'signature',\n severity: nullableOnly ? 'warning' : 'breaking',\n symbolPath: name,\n baseline: baseAlias.value,\n candidate: candAlias.value,\n message: `Type alias value mismatch for \"${name}\"`,\n });\n if (nullableOnly) preserved++;\n continue;\n }\n preserved++;\n }\n\n // Check for new type aliases (additions)\n for (const name of Object.keys(candidate.typeAliases)) {\n if (!baseline.typeAliases[name]) {\n additions.push({ symbolPath: name, symbolType: 'type-alias' });\n }\n }\n\n // Diff enums\n for (const [name, baseEnum] of Object.entries(baseline.enums)) {\n totalBaseline++;\n const candEnum = candidate.enums[name];\n if (!candEnum) {\n violations.push({\n category: 'public-api',\n severity: 'breaking',\n symbolPath: name,\n baseline: name,\n candidate: '(missing)',\n message: `Enum \"${name}\" exists in baseline but not in generated output`,\n });\n continue;\n }\n\n const candValueToMembers = new Map<string | number, string[]>();\n for (const [candMember, candValue] of Object.entries(candEnum.members)) {\n const existing = candValueToMembers.get(candValue);\n if (existing) {\n existing.push(candMember);\n } else {\n candValueToMembers.set(candValue, [candMember]);\n }\n }\n\n let enumMatch = true;\n for (const [member, value] of Object.entries(baseEnum.members)) {\n if (candEnum.members[member] === value) {\n continue;\n }\n\n const valueMatches = candValueToMembers.get(value);\n if (valueMatches && valueMatches.length > 0) {\n violations.push({\n category: 'signature',\n severity: 'warning',\n symbolPath: `${name}.${member}`,\n baseline: `${member}=${String(value)}`,\n candidate: `${valueMatches[0]}=${String(value)}`,\n message: `Enum member name differs for \"${name}.${member}\" (value \"${value}\" preserved as \"${valueMatches[0]}\")`,\n });\n continue;\n }\n\n const lowerValue = String(value).toLowerCase();\n const caseInsensitiveMatch = [...candValueToMembers.entries()].find(\n ([candVal]) => String(candVal).toLowerCase() === lowerValue,\n );\n if (caseInsensitiveMatch) {\n violations.push({\n category: 'signature',\n severity: 'warning',\n symbolPath: `${name}.${member}`,\n baseline: `${member}=${String(value)}`,\n candidate: `${caseInsensitiveMatch[1][0]}=${String(caseInsensitiveMatch[0])}`,\n message: `Enum member value case differs for \"${name}.${member}\" (baseline \"${value}\" vs candidate \"${caseInsensitiveMatch[0]}\")`,\n });\n continue;\n }\n\n const isExtractionArtifact =\n String(value) === member || member === 'JsonEnumDefaultValue' || member === 'JsonProperty';\n if (isExtractionArtifact) {\n violations.push({\n category: 'signature',\n severity: 'warning',\n symbolPath: `${name}.${member}`,\n baseline: String(value),\n candidate: '(extraction artifact)',\n message: `Enum member \"${name}.${member}\" appears to be an extraction artifact`,\n });\n continue;\n }\n\n violations.push({\n category: 'signature',\n severity: 'breaking',\n symbolPath: `${name}.${member}`,\n baseline: String(value),\n candidate: member in candEnum.members ? String(candEnum.members[member]) : '(missing)',\n message: `Enum member mismatch for \"${name}.${member}\"`,\n });\n enumMatch = false;\n }\n if (enumMatch) {\n preserved++;\n }\n }\n\n // Check for new enums (additions)\n for (const name of Object.keys(candidate.enums)) {\n if (!baseline.enums[name]) {\n additions.push({ symbolPath: name, symbolType: 'enum' });\n }\n }\n\n // Diff barrel exports\n for (const [path, baseExports] of Object.entries(baseline.exports)) {\n const candExports = candidate.exports[path];\n if (!candExports) {\n for (const exp of baseExports) {\n violations.push({\n category: 'export-structure',\n severity: 'warning',\n symbolPath: `exports[${path}].${exp}`,\n baseline: exp,\n candidate: '(missing)',\n message: `Export \"${exp}\" from \"${path}\" not found in generated output`,\n });\n }\n continue;\n }\n const candSet = new Set(candExports);\n for (const exp of baseExports) {\n if (!candSet.has(exp)) {\n violations.push({\n category: 'export-structure',\n severity: 'warning',\n symbolPath: `exports[${path}].${exp}`,\n baseline: exp,\n candidate: '(missing)',\n message: `Export \"${exp}\" from \"${path}\" not found in generated output`,\n });\n }\n }\n }\n\n return {\n preservationScore: totalBaseline > 0 ? Math.round((preserved / totalBaseline) * 100) : 100,\n totalBaselineSymbols: totalBaseline,\n preservedSymbols: preserved,\n violations,\n additions,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Internal helpers (legacy)\n// ---------------------------------------------------------------------------\n\nfunction signaturesMatch(baseline: ApiMethod, candidate: ApiMethod): boolean {\n if (baseline.returnType !== candidate.returnType) return false;\n for (let i = 0; i < baseline.params.length; i++) {\n const baseParam = baseline.params[i];\n const candParam = candidate.params[i];\n if (!candParam) return false;\n if (baseParam.type !== candParam.type) return false;\n if (baseParam.name !== candParam.name) return false;\n }\n for (let i = baseline.params.length; i < candidate.params.length; i++) {\n if (!candidate.params[i].optional) return false;\n }\n return true;\n}\n\nfunction formatSignature(method: ApiMethod): string {\n const params = method.params.map((p) => `${p.name}${p.optional ? '?' : ''}: ${p.type}`).join(', ');\n return `(${params}) => ${method.returnType}`;\n}\n","/**\n * Conceptual change grouping for cross-language compatibility analysis.\n *\n * Groups related changes across languages into a single conceptual change\n * with per-language severity. This allows reports to say \"parameter rename\n * on Authorization.check is breaking in PHP, Python, Kotlin, and .NET but\n * soft-risk in Go\" rather than treating these as unrelated per-language findings.\n */\n\nimport type { LanguageId } from './ir.js';\nimport type { CompatChangeSeverity, CompatChangeCategory } from './config.js';\nimport type { CompatDiffResult } from './differ.js';\n\n/** A conceptual change with per-language severity. */\nexport interface ConceptualChange {\n /** Deterministic ID from symbol + category + match details. */\n id: string;\n /** IR-level symbol path (language-neutral). */\n symbol: string;\n /** The kind of change. */\n category: CompatChangeCategory;\n /** Per-language severity mapping. */\n impact: Partial<Record<LanguageId, CompatChangeSeverity>>;\n /** Human-readable description (from first language that reported it). */\n message: string;\n /** Old state details. */\n old: Record<string, string>;\n /** New state details. */\n new: Record<string, string>;\n}\n\n/** Cross-language conceptual rollup. */\nexport interface ConceptualRollup {\n conceptualChanges: ConceptualChange[];\n}\n\n/**\n * Group classified changes from multiple languages into conceptual changes.\n *\n * Changes are grouped by their `conceptualChangeId` — a deterministic ID\n * derived from the symbol, category, and match details. Changes with the\n * same ID across different languages represent the same conceptual change.\n */\nexport function buildConceptualRollup(\n perLanguageResults: Array<{ diff: CompatDiffResult; language: LanguageId }>,\n): ConceptualRollup {\n const grouped = new Map<string, ConceptualChange>();\n\n for (const { diff: result, language } of perLanguageResults) {\n for (const change of result.changes) {\n const existing = grouped.get(change.conceptualChangeId);\n if (existing) {\n existing.impact[language] = change.severity;\n } else {\n grouped.set(change.conceptualChangeId, {\n id: change.conceptualChangeId,\n symbol: change.symbol,\n category: change.category,\n impact: { [language]: change.severity },\n message: change.message,\n old: change.old,\n new: change.new,\n });\n }\n }\n }\n\n return {\n conceptualChanges: [...grouped.values()],\n };\n}\n\n/** Get the highest severity across all languages for a conceptual change. */\nexport function highestSeverity(change: ConceptualChange): CompatChangeSeverity {\n const severities = Object.values(change.impact);\n if (severities.includes('breaking')) return 'breaking';\n if (severities.includes('soft-risk')) return 'soft-risk';\n return 'additive';\n}\n\n/** Count conceptual changes by highest severity. */\nexport function summarizeConceptualChanges(rollup: ConceptualRollup): {\n breaking: number;\n softRisk: number;\n additive: number;\n} {\n let breaking = 0;\n let softRisk = 0;\n let additive = 0;\n for (const change of rollup.conceptualChanges) {\n const sev = highestSeverity(change);\n if (sev === 'breaking') breaking++;\n else if (sev === 'soft-risk') softRisk++;\n else additive++;\n }\n return { breaking, softRisk, additive };\n}\n","/**\n * Report generation for compatibility verification.\n *\n * Produces machine-readable JSON reports, human-readable terminal summaries,\n * and conceptual cross-language summaries.\n */\n\nimport type { LanguageId } from './ir.js';\nimport type { CompatChangeSeverity, CompatChangeCategory, CompatProvenance } from './config.js';\nimport type { CompatDiffResult } from './differ.js';\nimport { buildConceptualRollup, highestSeverity, summarizeConceptualChanges } from './concepts.js';\n\n// ---------------------------------------------------------------------------\n// Machine-readable report\n// ---------------------------------------------------------------------------\n\n/** Machine-readable compat report for a single language. */\nexport interface CompatReport {\n schemaVersion: string;\n language: string;\n summary: {\n breaking: number;\n softRisk: number;\n additive: number;\n };\n changes: CompatReportChange[];\n}\n\n/** A single change entry in the machine-readable report. */\nexport interface CompatReportChange {\n severity: CompatChangeSeverity;\n category: CompatChangeCategory;\n symbol: string;\n conceptualChangeId: string;\n provenance: CompatProvenance;\n old: Record<string, string>;\n new: Record<string, string>;\n message?: string;\n}\n\n/** Generate a machine-readable compat report from a diff result. */\nexport function generateReport(diff: CompatDiffResult, language?: string): CompatReport {\n return {\n schemaVersion: '1',\n language: language ?? 'unknown',\n summary: diff.summary,\n changes: diff.changes.map((c) => ({\n severity: c.severity,\n category: c.category,\n symbol: c.symbol,\n conceptualChangeId: c.conceptualChangeId,\n provenance: c.provenance,\n old: c.old,\n new: c.new,\n ...(c.message ? { message: c.message } : {}),\n })),\n };\n}\n\n// ---------------------------------------------------------------------------\n// Human-readable terminal summary\n// ---------------------------------------------------------------------------\n\n/** Generate a human-readable summary string for terminal output. */\nexport function formatHumanSummary(diff: CompatDiffResult, opts?: { explain?: boolean; language?: string }): string {\n const lines: string[] = [];\n\n lines.push(`Compat report${opts?.language ? ` for ${opts.language}` : ''}:`);\n lines.push(\n ` ${diff.summary.breaking} breaking, ${diff.summary.softRisk} soft-risk, ${diff.summary.additive} additive`,\n );\n\n if (diff.changes.length === 0) {\n lines.push(' No compatibility changes detected.');\n return lines.join('\\n');\n }\n\n // Group by severity for display\n const breaking = diff.changes.filter((c) => c.severity === 'breaking');\n const softRisk = diff.changes.filter((c) => c.severity === 'soft-risk');\n const additive = diff.changes.filter((c) => c.severity === 'additive');\n\n if (breaking.length > 0) {\n lines.push('');\n lines.push(' Breaking:');\n for (const c of breaking) {\n lines.push(` [${c.category}] ${c.symbol} — ${c.message}`);\n if (opts?.explain && c.provenance !== 'unknown') {\n lines.push(` provenance: ${c.provenance}`);\n }\n }\n }\n\n if (softRisk.length > 0) {\n lines.push('');\n lines.push(' Soft-risk:');\n for (const c of softRisk) {\n lines.push(` [${c.category}] ${c.symbol} — ${c.message}`);\n if (opts?.explain && c.provenance !== 'unknown') {\n lines.push(` provenance: ${c.provenance}`);\n }\n }\n }\n\n if (additive.length > 0) {\n lines.push('');\n lines.push(` Additive: ${additive.length} new symbol(s)`);\n }\n\n return lines.join('\\n');\n}\n\n// ---------------------------------------------------------------------------\n// Conceptual cross-language summary\n// ---------------------------------------------------------------------------\n\n/** Conceptual cross-language report. */\nexport interface ConceptualReport {\n conceptualChanges: {\n id: string;\n symbol: string;\n category: CompatChangeCategory;\n impact: Partial<Record<LanguageId, CompatChangeSeverity>>;\n }[];\n}\n\n/** Generate a conceptual cross-language report from multiple per-language results. */\nexport function generateConceptualReport(\n perLanguageResults: Array<{ diff: CompatDiffResult; language: LanguageId }>,\n): ConceptualReport {\n const rollup = buildConceptualRollup(perLanguageResults);\n return {\n conceptualChanges: rollup.conceptualChanges.map((c) => ({\n id: c.id,\n symbol: c.symbol,\n category: c.category,\n impact: c.impact,\n })),\n };\n}\n\n/** Format a conceptual cross-language summary for terminal output. */\nexport function formatConceptualSummary(\n perLanguageResults: Array<{ diff: CompatDiffResult; language: LanguageId }>,\n): string {\n const rollup = buildConceptualRollup(perLanguageResults);\n const summary = summarizeConceptualChanges(rollup);\n const lines: string[] = [];\n\n lines.push('Cross-language conceptual summary:');\n lines.push(` ${summary.breaking} breaking, ${summary.softRisk} soft-risk, ${summary.additive} additive`);\n\n if (rollup.conceptualChanges.length === 0) {\n lines.push(' No cross-language changes.');\n return lines.join('\\n');\n }\n\n for (const change of rollup.conceptualChanges) {\n const sev = highestSeverity(change);\n const impactStr = Object.entries(change.impact)\n .map(([lang, s]) => `${lang}: ${s}`)\n .join(', ');\n lines.push(` [${sev}] ${change.category}: ${change.symbol}`);\n lines.push(` impact: ${impactStr}`);\n }\n\n return lines.join('\\n');\n}\n","import { readFileSync, writeFileSync } from 'node:fs';\nimport { validateSnapshot } from '../compat/schema.js';\nimport { diffSnapshots } from '../compat/differ.js';\nimport { generateReport, formatHumanSummary } from '../compat/report.js';\nimport { severityMeetsThreshold } from '../compat/config.js';\nimport type { CompatFailLevel } from '../compat/config.js';\nimport type { CompatSnapshot } from '../compat/ir.js';\n\nexport async function compatDiffCommand(opts: {\n baseline: string;\n candidate: string;\n output?: string;\n failOn?: string;\n explain?: boolean;\n}): Promise<void> {\n const baselineData = JSON.parse(readFileSync(opts.baseline, 'utf-8'));\n const candidateData = JSON.parse(readFileSync(opts.candidate, 'utf-8'));\n\n if (!validateSnapshot(baselineData)) {\n throw new Error(`Invalid baseline snapshot: ${opts.baseline}`);\n }\n if (!validateSnapshot(candidateData)) {\n throw new Error(`Invalid candidate snapshot: ${opts.candidate}`);\n }\n\n const baseline = baselineData as CompatSnapshot;\n const candidate = candidateData as CompatSnapshot;\n\n const diff = diffSnapshots(baseline, candidate);\n\n // Human-readable output to terminal\n console.log(formatHumanSummary(diff, { explain: opts.explain }));\n\n // Machine-readable output to file\n if (opts.output) {\n const report = generateReport(diff);\n writeFileSync(opts.output, JSON.stringify(report, null, 2));\n console.log(`Report written to ${opts.output}`);\n }\n\n // Fail if threshold exceeded\n const failOn = (opts.failOn ?? 'breaking') as CompatFailLevel;\n const hasFailure = diff.changes.some((c) => severityMeetsThreshold(c.severity, failOn));\n if (hasFailure) {\n process.exitCode = 1;\n }\n}\n","import { readFileSync, writeFileSync } from 'node:fs';\nimport type { CompatReport, CompatReportChange } from '../compat/report.js';\nimport type { CompatDiffResult } from '../compat/differ.js';\nimport type { LanguageId } from '../compat/ir.js';\nimport type { CompatChangeSeverity } from '../compat/config.js';\nimport { buildConceptualRollup, highestSeverity, summarizeConceptualChanges } from '../compat/concepts.js';\n\n/**\n * Format compat report(s) as a markdown PR comment.\n *\n * Single report:\n * oagen compat-summary --report node-report.json | gh pr comment --body-file -\n *\n * Multiple reports (cross-language rollup):\n * oagen compat-summary --report php.json --report python.json --report go.json\n */\nexport async function compatSummaryCommand(opts: { report: string | string[]; output?: string }): Promise<void> {\n const paths = Array.isArray(opts.report) ? opts.report : [opts.report];\n const reports = paths.map((p) => JSON.parse(readFileSync(p, 'utf-8')) as CompatReport);\n\n const md = reports.length === 1 ? formatSingleReport(reports[0]) : formatCrossLanguageRollup(reports);\n\n if (opts.output) {\n writeFileSync(opts.output, md);\n console.log(`Summary written to ${opts.output}`);\n } else {\n process.stdout.write(md);\n }\n}\n\n// ---------------------------------------------------------------------------\n// Single-language report\n// ---------------------------------------------------------------------------\n\nfunction formatSingleReport(report: CompatReport): string {\n const lines: string[] = [];\n const { breaking, softRisk, additive } = report.summary;\n const total = breaking + softRisk + additive;\n\n if (breaking > 0) {\n lines.push(`## :x: Compat check failed — ${report.language}`);\n } else if (softRisk > 0) {\n lines.push(`## :warning: Compat check has warnings — ${report.language}`);\n } else {\n lines.push(`## :white_check_mark: Compat check passed — ${report.language}`);\n }\n\n lines.push('');\n lines.push('| Severity | Count |');\n lines.push('| --- | --- |');\n lines.push(`| Breaking | ${breaking} |`);\n lines.push(`| Soft-risk | ${softRisk} |`);\n lines.push(`| Additive | ${additive} |`);\n lines.push(`| **Total** | **${total}** |`);\n\n if (total === 0) {\n lines.push('');\n lines.push('No compatibility changes detected.');\n return lines.join('\\n') + '\\n';\n }\n\n const breakingChanges = report.changes.filter((c) => c.severity === 'breaking');\n if (breakingChanges.length > 0) {\n lines.push('');\n lines.push('### Breaking changes');\n lines.push('');\n lines.push(formatChangesTable(breakingChanges));\n }\n\n const softRiskChanges = report.changes.filter((c) => c.severity === 'soft-risk');\n if (softRiskChanges.length > 0) {\n lines.push('');\n lines.push('<details>');\n lines.push(`<summary>Soft-risk changes (${softRiskChanges.length})</summary>`);\n lines.push('');\n lines.push(formatChangesTable(softRiskChanges));\n lines.push('</details>');\n }\n\n const additiveChanges = report.changes.filter((c) => c.severity === 'additive');\n if (additiveChanges.length > 0) {\n lines.push('');\n lines.push('<details>');\n lines.push(`<summary>Additive changes (${additiveChanges.length})</summary>`);\n lines.push('');\n lines.push(formatChangesTable(additiveChanges));\n lines.push('</details>');\n }\n\n return lines.join('\\n') + '\\n';\n}\n\n// ---------------------------------------------------------------------------\n// Cross-language rollup\n// ---------------------------------------------------------------------------\n\nfunction formatCrossLanguageRollup(reports: CompatReport[]): string {\n const languages = reports.map((r) => r.language);\n\n // Convert reports to the shape buildConceptualRollup expects\n const perLanguage = reports.map((r) => ({\n diff: { changes: r.changes, summary: r.summary } as CompatDiffResult,\n language: r.language as LanguageId,\n }));\n const rollup = buildConceptualRollup(perLanguage);\n const summary = summarizeConceptualChanges(rollup);\n\n const lines: string[] = [];\n\n // Header\n if (summary.breaking > 0) {\n lines.push(`## :x: Compat check failed — ${summary.breaking} breaking across ${languages.length} languages`);\n } else if (summary.softRisk > 0) {\n lines.push(\n `## :warning: Compat check has warnings — ${summary.softRisk} soft-risk across ${languages.length} languages`,\n );\n } else {\n lines.push(`## :white_check_mark: Compat check passed — ${languages.length} languages`);\n }\n\n lines.push('');\n\n // Per-language summary table\n lines.push('| Language | Breaking | Soft-risk | Additive |');\n lines.push('| --- | --- | --- | --- |');\n for (const r of reports) {\n lines.push(`| ${r.language} | ${r.summary.breaking} | ${r.summary.softRisk} | ${r.summary.additive} |`);\n }\n\n if (rollup.conceptualChanges.length === 0) {\n lines.push('');\n lines.push('No compatibility changes detected.');\n return lines.join('\\n') + '\\n';\n }\n\n // Conceptual changes table with per-language severity\n const breakingConcepts = rollup.conceptualChanges.filter((c) => highestSeverity(c) === 'breaking');\n if (breakingConcepts.length > 0) {\n lines.push('');\n lines.push('### Breaking changes');\n lines.push('');\n lines.push(formatConceptualTable(breakingConcepts, languages));\n }\n\n const softRiskConcepts = rollup.conceptualChanges.filter((c) => highestSeverity(c) === 'soft-risk');\n if (softRiskConcepts.length > 0) {\n lines.push('');\n lines.push('<details>');\n lines.push(`<summary>Soft-risk changes (${softRiskConcepts.length})</summary>`);\n lines.push('');\n lines.push(formatConceptualTable(softRiskConcepts, languages));\n lines.push('</details>');\n }\n\n const additiveConcepts = rollup.conceptualChanges.filter((c) => highestSeverity(c) === 'additive');\n if (additiveConcepts.length > 0) {\n lines.push('');\n lines.push('<details>');\n lines.push(`<summary>Additive changes (${additiveConcepts.length})</summary>`);\n lines.push('');\n lines.push(formatConceptualTable(additiveConcepts, languages));\n lines.push('</details>');\n }\n\n return lines.join('\\n') + '\\n';\n}\n\nfunction formatConceptualTable(\n concepts: Array<{ symbol: string; category: string; impact: Partial<Record<string, CompatChangeSeverity>> }>,\n languages: string[],\n): string {\n const lines: string[] = [];\n const langHeaders = languages.map((l) => l).join(' | ');\n lines.push(`| Symbol | Category | ${langHeaders} |`);\n lines.push(`| --- | --- | ${languages.map(() => '---').join(' | ')} |`);\n for (const c of concepts) {\n const severities = languages.map((l) => severityIcon(c.impact[l])).join(' | ');\n lines.push(`| \\`${c.symbol}\\` | \\`${c.category}\\` | ${severities} |`);\n }\n return lines.join('\\n');\n}\n\nfunction severityIcon(severity: CompatChangeSeverity | undefined): string {\n if (!severity) return '—';\n switch (severity) {\n case 'breaking':\n return ':x: breaking';\n case 'soft-risk':\n return ':warning: soft-risk';\n case 'additive':\n return ':white_check_mark: additive';\n }\n}\n\n// ---------------------------------------------------------------------------\n// Shared helpers\n// ---------------------------------------------------------------------------\n\nfunction formatChangesTable(changes: CompatReportChange[]): string {\n const lines: string[] = [];\n lines.push('| Category | Symbol | Detail |');\n lines.push('| --- | --- | --- |');\n for (const c of changes) {\n const detail = c.message ?? formatOldNew(c.old, c.new);\n lines.push(`| \\`${c.category}\\` | \\`${c.symbol}\\` | ${escapeMarkdown(detail)} |`);\n }\n return lines.join('\\n');\n}\n\nfunction formatOldNew(old: Record<string, string>, updated: Record<string, string>): string {\n const parts: string[] = [];\n for (const key of Object.keys(old)) {\n if (updated[key] && old[key] !== updated[key]) {\n parts.push(`${key}: \\`${old[key]}\\` → \\`${updated[key]}\\``);\n }\n }\n return parts.length > 0 ? parts.join(', ') : '';\n}\n\nfunction escapeMarkdown(text: string): string {\n return text.replace(/\\|/g, '\\\\|').replace(/\\n/g, ' ');\n}\n","/**\n * Approval matching engine for compatibility verification.\n *\n * Matches CompatApproval entries from oagen.config.ts against classified\n * changes. Approved changes are excluded from failure thresholds.\n *\n * Approvals must be narrow (one symbol, one category, one conceptual change).\n * Overly broad approvals are rejected at validation time.\n */\n\nimport type { LanguageId } from './ir.js';\nimport type { CompatApproval } from './config.js';\nimport type { ClassifiedChange } from './classify.js';\n\n/** Result of matching a change against approvals. */\nexport interface ApprovalMatch {\n /** The change that was matched. */\n change: ClassifiedChange;\n /** The approval that matched. null if no approval covers this change. */\n approval: CompatApproval | null;\n /** Whether the change is covered by an approval. */\n approved: boolean;\n}\n\n/** Result of validating an approval for broadness. */\nexport interface ApprovalValidation {\n valid: boolean;\n errors: string[];\n}\n\n// ---------------------------------------------------------------------------\n// Validation\n// ---------------------------------------------------------------------------\n\n/** Validate that an approval is narrow enough to be accepted. */\nexport function validateApproval(approval: CompatApproval): ApprovalValidation {\n const errors: string[] = [];\n\n if (!approval.symbol || approval.symbol.trim() === '') {\n errors.push('Approval must target a specific symbol');\n }\n\n if (!approval.category) {\n errors.push('Approval must specify a change category');\n }\n\n if (!approval.reason || approval.reason.trim() === '') {\n errors.push('Approval must include a reason');\n }\n\n // Wildcard symbols are too broad\n if (approval.symbol === '*' || approval.symbol.endsWith('.*') || approval.symbol.endsWith('::*')) {\n errors.push(`Approval symbol \"${approval.symbol}\" is too broad — must target a specific symbol`);\n }\n\n return {\n valid: errors.length === 0,\n errors,\n };\n}\n\n/** Validate all approvals in a config. Returns errors keyed by index. */\nexport function validateApprovals(approvals: CompatApproval[]): Map<number, string[]> {\n const result = new Map<number, string[]>();\n for (let i = 0; i < approvals.length; i++) {\n const validation = validateApproval(approvals[i]);\n if (!validation.valid) {\n result.set(i, validation.errors);\n }\n }\n return result;\n}\n\n// ---------------------------------------------------------------------------\n// Matching\n// ---------------------------------------------------------------------------\n\n/**\n * Match a classified change against a list of approvals.\n * Returns the first matching approval, or null if none match.\n */\nexport function matchApproval(\n change: ClassifiedChange,\n approvals: CompatApproval[],\n language: LanguageId,\n): CompatApproval | null {\n for (const approval of approvals) {\n if (approvalMatchesChange(approval, change, language)) {\n return approval;\n }\n }\n return null;\n}\n\n/**\n * Apply approvals to a list of changes.\n * Returns matches for every change (approved or not).\n */\nexport function applyApprovals(\n changes: ClassifiedChange[],\n approvals: CompatApproval[],\n language: LanguageId,\n): ApprovalMatch[] {\n return changes.map((change) => {\n const approval = matchApproval(change, approvals, language);\n return {\n change,\n approval,\n approved: approval !== null,\n };\n });\n}\n\n/**\n * Filter changes to only those NOT covered by approvals.\n * These are the remaining unapproved changes that may cause failure.\n */\nexport function unapprovedChanges(\n changes: ClassifiedChange[],\n approvals: CompatApproval[],\n language: LanguageId,\n): ClassifiedChange[] {\n return changes.filter((change) => !matchApproval(change, approvals, language));\n}\n\n// ---------------------------------------------------------------------------\n// Internal matching logic\n// ---------------------------------------------------------------------------\n\nfunction approvalMatchesChange(approval: CompatApproval, change: ClassifiedChange, language: LanguageId): boolean {\n // Skip inactive approvals\n if (approval.approved === false) return false;\n\n // Category must match exactly\n if (approval.category !== change.category) return false;\n\n // Symbol must match\n if (!symbolMatches(approval.symbol, change.symbol)) return false;\n\n // Language scoping\n if (!languageMatches(approval.appliesTo, language)) return false;\n\n // Narrowing match (optional)\n if (approval.match && !narrowingMatches(approval.match, change)) return false;\n\n return true;\n}\n\nfunction symbolMatches(approvalSymbol: string, changeSymbol: string): boolean {\n // Exact match\n if (approvalSymbol === changeSymbol) return true;\n\n // Normalize common separators for cross-language matching\n // PHP uses :: and \\, others use . — normalize to dots for comparison\n const normalizedApproval = approvalSymbol.replace(/::/g, '.').replace(/\\\\/g, '.');\n const normalizedChange = changeSymbol.replace(/::/g, '.').replace(/\\\\/g, '.');\n return normalizedApproval === normalizedChange;\n}\n\nfunction languageMatches(appliesTo: CompatApproval['appliesTo'], language: LanguageId): boolean {\n if (!appliesTo || appliesTo === 'all-impacted-languages') return true;\n return appliesTo.includes(language);\n}\n\nfunction narrowingMatches(match: NonNullable<CompatApproval['match']>, change: ClassifiedChange): boolean {\n if (match.parameter) {\n // Check if the change involves this parameter\n const paramInOld = change.old.parameter === match.parameter;\n const paramInNew = change.new.parameter === match.parameter;\n if (!paramInOld && !paramInNew) return false;\n }\n if (match.member) {\n const memberInOld = change.old.member === match.member;\n const memberInNew = change.new.member === match.member;\n if (!memberInOld && !memberInNew) return false;\n }\n if (match.oldName) {\n const nameMatch = Object.values(change.old).some((v) => v === match.oldName);\n if (!nameMatch) return false;\n }\n if (match.newName) {\n const nameMatch = Object.values(change.new).some((v) => v === match.newName);\n if (!nameMatch) return false;\n }\n return true;\n}\n","import { getExtractor } from '../compat/extractor-registry.js';\nimport {\n diffSnapshots,\n specDerivedNames,\n specDerivedFieldPaths,\n specDerivedMethodPaths,\n specDerivedEnumValues,\n filterSurface,\n} from '../compat/differ.js';\nimport { apiSurfaceToSnapshot } from '../compat/ir.js';\nimport type { LanguageId } from '../compat/ir.js';\nimport { getDefaultPolicy, mergePolicy } from '../compat/policy.js';\nimport type { CompatPolicyHints } from '../compat/policy.js';\nimport type { ApiSpec } from '../ir/types.js';\nimport type { ApiSurface } from '../compat/types.js';\nimport type { CompatCheckResult } from './types.js';\n\nexport async function runCompatCheck(\n baseline: ApiSurface,\n outputDir: string,\n lang: string,\n spec?: ApiSpec,\n policyOverrides?: Partial<CompatPolicyHints>,\n): Promise<CompatCheckResult> {\n const extractor = getExtractor(lang);\n const candidate = await extractor.extract(outputDir);\n\n let scopedBaseline = baseline;\n let scopedToSpec = false;\n let scopedSymbolCount: number | undefined;\n if (spec) {\n const allowed = specDerivedNames(spec, extractor.hints);\n const fieldPaths = specDerivedFieldPaths(spec, extractor.hints);\n const methodPaths = specDerivedMethodPaths(spec);\n const enumVals = specDerivedEnumValues(spec);\n scopedBaseline = filterSurface(baseline, allowed, { fieldPaths, methodPaths, enumValues: enumVals });\n scopedToSpec = true;\n scopedSymbolCount =\n Object.keys(scopedBaseline.interfaces).length +\n Object.keys(scopedBaseline.classes).length +\n Object.keys(scopedBaseline.typeAliases).length +\n Object.keys(scopedBaseline.enums).length;\n }\n\n const baseSnap = apiSurfaceToSnapshot(scopedBaseline);\n const candSnap = apiSurfaceToSnapshot(candidate);\n\n const langId = lang as LanguageId;\n const policy = policyOverrides ? mergePolicy(getDefaultPolicy(langId), policyOverrides) : getDefaultPolicy(langId);\n\n const diff = diffSnapshots(baseSnap, candSnap, policy);\n const passed = diff.changes.every((c) => c.severity !== 'breaking');\n\n return { passed, diff, scopedToSpec, scopedSymbolCount };\n}\n","import { readdirSync, unlinkSync, statSync, openSync, readSync, closeSync } from 'node:fs';\nimport * as path from 'node:path';\nimport { buildOverlayLookup, patchOverlay, isPatchableChange } from '../compat/overlay.js';\nimport { getExtractor } from '../compat/extractor-registry.js';\nimport type { ApiSurface } from '../compat/types.js';\nimport type { ApiSpec } from '../ir/types.js';\nimport { getEmitter } from '../engine/registry.js';\nimport { generate } from '../engine/orchestrator.js';\nimport { runCompatCheck } from './run-compat-check.js';\nimport type { OverlayRetryResult } from './types.js';\nimport { readManifestSync } from '../engine/manifest-reader.js';\n\n/** Generated file header markers used by various emitters. */\nconst GENERATED_MARKERS = ['Code generated by oagen', 'auto-generated by oagen', 'This file is auto-generated'];\n\n/**\n * Delete oagen-generated source files so the retry loop can regenerate them\n * with overlay-corrected names. Only deletes files that contain an oagen\n * generation marker, preserving hand-written files.\n */\nfunction cleanGeneratedFiles(dir: string): void {\n let entries: string[];\n try {\n entries = readdirSync(dir);\n } catch {\n return;\n }\n for (const entry of entries) {\n const full = path.join(dir, entry);\n let stat;\n try {\n stat = statSync(full);\n } catch {\n continue;\n }\n if (stat.isDirectory()) {\n cleanGeneratedFiles(full);\n continue;\n }\n // Skip non-source files and manifests\n if (entry.endsWith('.json') || entry.endsWith('.lock')) continue;\n // Read only the first 200 bytes to check for generation marker\n try {\n const buf = Buffer.alloc(200);\n const fd = openSync(full, 'r');\n try {\n readSync(fd, buf, 0, 200, 0);\n } finally {\n closeSync(fd);\n }\n const header = buf.toString('utf-8');\n if (GENERATED_MARKERS.some((m) => header.includes(m))) {\n unlinkSync(full);\n }\n } catch {\n // ignore read/delete errors\n }\n }\n}\n\nexport async function runOverlayRetryLoop(opts: {\n baseline: ApiSurface;\n parsedSpec: ApiSpec;\n outputDir: string;\n lang: string;\n maxRetries: number;\n namespace?: string;\n onRetry?: (attemptNumber: number, maxRetries: number, patchableCount: number) => void;\n}): Promise<OverlayRetryResult> {\n const { baseline, parsedSpec, outputDir, lang, maxRetries, namespace, onRetry } = opts;\n\n const manifest = readManifestSync(outputDir);\n // Pass language-specific hints so property-to-class matching works correctly\n // (e.g., Ruby snake_case \"api_keys\" → PascalCase \"ApiKeys\").\n const extractor = getExtractor(lang);\n let overlay = buildOverlayLookup(baseline, manifest, parsedSpec, extractor.hints);\n let prevPreserved = -1;\n const patchedPerIteration: number[] = [];\n\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n const compatResult = await runCompatCheck(baseline, outputDir, lang, parsedSpec);\n if (compatResult.passed) {\n return {\n status: 'passed',\n attempts: attempt,\n patchedPerIteration,\n compatResult,\n };\n }\n\n if (attempt === maxRetries) {\n return {\n status: 'max-retries',\n attempts: attempt,\n patchedPerIteration,\n compatResult,\n };\n }\n\n const patchable = compatResult.diff.changes.filter(isPatchableChange);\n if (patchable.length === 0) {\n return {\n status: 'no-patchable',\n attempts: attempt,\n patchedPerIteration,\n compatResult,\n };\n }\n\n const currentBreaking = compatResult.diff.summary.breaking;\n // Stall detection: if breaking count hasn't decreased, we're not making progress\n if (attempt > 0 && currentBreaking >= prevPreserved) {\n return {\n status: 'stalled',\n attempts: attempt,\n patchedPerIteration,\n compatResult,\n };\n }\n prevPreserved = currentBreaking;\n patchedPerIteration.push(patchable.length);\n onRetry?.(attempt + 1, maxRetries, patchable.length);\n\n overlay = patchOverlay(overlay, patchable, baseline);\n\n // Pre-delete generated source files so the writer creates them fresh\n // with overlay-corrected names. Without this, the AST merger would preserve\n // old method/class names from the existing files.\n // Only delete files that look like oagen-generated source files (have the header).\n cleanGeneratedFiles(outputDir);\n\n const emitter = getEmitter(lang);\n await generate(parsedSpec, emitter, {\n namespace: namespace ?? parsedSpec.name,\n outputDir,\n overlayLookup: overlay,\n apiSurface: baseline,\n });\n }\n\n const compatResult = await runCompatCheck(baseline, outputDir, lang, parsedSpec);\n return {\n status: 'max-retries',\n attempts: maxRetries,\n patchedPerIteration,\n compatResult,\n };\n}\n","import type { ApiSurface, LanguageHints, Violation } from './types.js';\nimport type { ApiSpec } from '../ir/types.js';\nimport { specDerivedNames, specDerivedFieldPaths } from './spec-filter.js';\nimport { diffSpecs } from '../differ/diff.js';\n\n/**\n * Detect symbols that exist in the live SDK surface but are no longer defined\n * in the current OpenAPI spec. These are \"stale\" — they compile and run but\n * represent dead code from a previous spec version.\n *\n * Requires both the old and new spec so we can distinguish hand-written SDK\n * symbols (never in any spec) from genuinely removed spec symbols.\n */\nexport function detectStaleSymbols(\n liveSurface: ApiSurface,\n oldSpec: ApiSpec,\n newSpec: ApiSpec,\n hints: LanguageHints,\n): Violation[] {\n const violations: Violation[] = [];\n\n // Step 1-3: Name-set difference for top-level symbols\n const oldNames = specDerivedNames(oldSpec, hints);\n const newNames = specDerivedNames(newSpec, hints);\n\n const removedNames = new Set<string>();\n for (const name of oldNames) {\n if (!newNames.has(name)) removedNames.add(name);\n }\n\n for (const name of removedNames) {\n if (liveSurface.classes[name]) {\n violations.push({\n category: 'staleness',\n severity: 'warning',\n symbolPath: name,\n baseline: name,\n candidate: '(removed from spec)',\n message: `Class \"${name}\" is no longer defined in the OpenAPI spec`,\n });\n }\n if (liveSurface.interfaces[name]) {\n violations.push({\n category: 'staleness',\n severity: 'warning',\n symbolPath: name,\n baseline: name,\n candidate: '(removed from spec)',\n message: `Interface \"${name}\" is no longer defined in the OpenAPI spec`,\n });\n }\n if (liveSurface.typeAliases[name]) {\n violations.push({\n category: 'staleness',\n severity: 'warning',\n symbolPath: name,\n baseline: name,\n candidate: '(removed from spec)',\n message: `Type alias \"${name}\" is no longer defined in the OpenAPI spec`,\n });\n }\n if (liveSurface.enums[name]) {\n violations.push({\n category: 'staleness',\n severity: 'warning',\n symbolPath: name,\n baseline: name,\n candidate: '(removed from spec)',\n message: `Enum \"${name}\" is no longer defined in the OpenAPI spec`,\n });\n }\n }\n\n // Step 4-6: Field-level staleness for models that still exist in new spec\n const oldFieldPaths = specDerivedFieldPaths(oldSpec, hints);\n const newFieldPaths = specDerivedFieldPaths(newSpec, hints);\n\n for (const fieldPath of oldFieldPaths) {\n if (newFieldPaths.has(fieldPath)) continue;\n\n const [modelName, fieldName] = fieldPath.split('.');\n // Only flag field-level staleness for models that still exist in the new spec\n // (fully removed models are already caught above)\n if (removedNames.has(modelName)) continue;\n\n const iface = liveSurface.interfaces[modelName];\n if (iface?.fields[fieldName]) {\n violations.push({\n category: 'staleness',\n severity: 'warning',\n symbolPath: fieldPath,\n baseline: fieldName,\n candidate: '(removed from spec)',\n message: `Field \"${fieldPath}\" is no longer defined in the OpenAPI spec`,\n });\n }\n }\n\n // Step 7: Operation-level staleness via diffSpecs\n const diff = diffSpecs(oldSpec, newSpec);\n for (const change of diff.changes) {\n if (change.kind === 'operation-removed') {\n const cls = liveSurface.classes[change.serviceName];\n if (cls?.methods[change.operationName]) {\n violations.push({\n category: 'staleness',\n severity: 'warning',\n symbolPath: `${change.serviceName}.${change.operationName}`,\n baseline: change.operationName,\n candidate: '(removed from spec)',\n message: `Method \"${change.serviceName}.${change.operationName}\" is no longer defined in the OpenAPI spec`,\n });\n }\n }\n }\n\n return violations;\n}\n","import { getExtractor } from '../compat/extractor-registry.js';\nimport { detectStaleSymbols } from '../compat/staleness.js';\nimport type { ApiSpec } from '../ir/types.js';\nimport type { ApiSurface } from '../compat/types.js';\nimport type { StalenessCheckResult } from './types.js';\n\nexport function runStalenessCheck(\n baseline: ApiSurface,\n oldSpec: ApiSpec,\n newSpec: ApiSpec,\n lang: string,\n): StalenessCheckResult {\n const extractor = getExtractor(lang);\n const violations = detectStaleSymbols(baseline, oldSpec, newSpec, extractor.hints);\n return { violations };\n}\n","import { execFileSync } from 'node:child_process';\nimport { existsSync, readFileSync } from 'node:fs';\nimport { fileURLToPath } from 'node:url';\nimport * as path from 'node:path';\nimport { CommandError } from '../errors.js';\nimport type { SmokeCheckResult } from './types.js';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = path.dirname(__filename);\n\nfunction resolveScript(scriptRelPath: string): { bin: string; script: string } {\n const distScript = path.resolve(__dirname, '..', '..', 'dist', 'scripts', scriptRelPath.replace(/\\.ts$/, '.mjs'));\n if (existsSync(distScript)) {\n return { bin: 'node', script: distScript };\n }\n const srcScript = path.resolve(__dirname, '..', '..', 'scripts', scriptRelPath);\n return { bin: 'npx', script: srcScript };\n}\n\nfunction runPackagedScript(scriptRelPath: string, args: string[]): void {\n const { bin, script } = resolveScript(scriptRelPath);\n const fullArgs = bin === 'npx' ? ['tsx', script, ...args] : [script, ...args];\n execFileSync(bin, fullArgs, { stdio: 'inherit', env: process.env });\n}\n\nexport function runSmokeCheck(opts: {\n spec?: string;\n lang: string;\n output: string;\n rawResults?: string;\n smokeConfig?: string;\n smokeRunner?: string;\n}): SmokeCheckResult {\n const { spec, lang, output, rawResults, smokeConfig, smokeRunner } = opts;\n\n let baselinePath = rawResults ?? 'smoke-results-raw.json';\n let generatedBaseline = false;\n\n if (!rawResults && !existsSync('smoke-results-raw.json')) {\n if (!spec) {\n throw new CommandError(\n 'error: --spec <path> or OPENAPI_SPEC_PATH env var is required when no raw baseline exists',\n '',\n 1,\n );\n }\n\n try {\n runPackagedScript('smoke/baseline.ts', ['--spec', spec]);\n } catch {\n throw new CommandError('Baseline generation failed', '', 1);\n }\n baselinePath = 'smoke-results-spec-baseline.json';\n generatedBaseline = true;\n }\n\n const smokeArgs = ['--lang', lang, '--sdk-path', output, '--raw-results', baselinePath];\n if (spec) smokeArgs.push('--spec', spec);\n if (smokeConfig) smokeArgs.push('--smoke-config', smokeConfig);\n\n try {\n if (smokeRunner) {\n const bin = smokeRunner.endsWith('.ts') ? 'npx' : 'node';\n const fullArgs = bin === 'npx' ? ['tsx', smokeRunner, ...smokeArgs] : [smokeRunner, ...smokeArgs];\n execFileSync(bin, fullArgs, { stdio: 'inherit', env: process.env });\n } else {\n runPackagedScript('smoke/sdk-test.ts', smokeArgs);\n }\n\n return { passed: true, baselinePath, generatedBaseline };\n } catch {\n if (existsSync('smoke-compile-errors.json')) {\n return { passed: false, compileErrors: true, baselinePath, generatedBaseline };\n }\n\n const findingsCount = existsSync('smoke-diff-findings.json')\n ? (JSON.parse(readFileSync('smoke-diff-findings.json', 'utf-8')) as unknown[]).length\n : undefined;\n\n return { passed: false, findingsCount, baselinePath, generatedBaseline };\n }\n}\n","import { writeFileSync } from 'node:fs';\nimport type { VerifyDiagnostics, CompatCheckResult } from './types.js';\n\nexport function summarizeCompatCheck(result: CompatCheckResult): NonNullable<VerifyDiagnostics['compatCheck']> {\n const violationsByCategory: Record<string, number> = {};\n const violationsBySeverity: Record<string, number> = {};\n for (const c of result.diff.changes) {\n violationsByCategory[c.category] = (violationsByCategory[c.category] ?? 0) + 1;\n violationsBySeverity[c.severity] = (violationsBySeverity[c.severity] ?? 0) + 1;\n }\n\n const { breaking, softRisk, additive } = result.diff.summary;\n const totalChanges = breaking + softRisk + additive;\n const totalBaselineSymbols = totalChanges + additive; // approximate; additive are new\n const preservedSymbols = totalBaselineSymbols - breaking - softRisk;\n const preservationScore =\n totalBaselineSymbols > 0 ? Math.round((preservedSymbols / totalBaselineSymbols) * 100) : 100;\n\n return {\n totalBaselineSymbols,\n preservedSymbols,\n preservationScore,\n violationsByCategory,\n violationsBySeverity,\n additions: additive,\n scopedToSpec: result.scopedToSpec,\n ...(result.scopedSymbolCount !== undefined ? { scopedSymbolCount: result.scopedSymbolCount } : {}),\n };\n}\n\nexport function setRetryDiagnostics(\n diagData: VerifyDiagnostics,\n attempt: number,\n converged: boolean,\n finalScore: number,\n patchedPerIteration: number[],\n): void {\n diagData.retryLoop = { attempts: attempt, converged, finalScore, patchedPerIteration };\n}\n\nexport function writeDiagnostics(data: VerifyDiagnostics, filePath: string = 'verify-diagnostics.json'): void {\n writeFileSync(filePath, JSON.stringify(data, null, 2) + '\\n');\n}\n","import { existsSync, readFileSync, writeFileSync } from 'node:fs';\nimport { CommandError } from '../errors.js';\nimport { parseSpec } from '../parser/parse.js';\nimport type { ApiSurface } from '../compat/types.js';\nimport type { CompatConfig, CompatFailLevel } from '../compat/config.js';\nimport { severityMeetsThreshold } from '../compat/config.js';\nimport { generateReport, formatHumanSummary } from '../compat/report.js';\nimport { unapprovedChanges } from '../compat/approvals.js';\nimport type { LanguageId } from '../compat/ir.js';\nimport { runCompatCheck } from '../verify/run-compat-check.js';\nimport { runOverlayRetryLoop } from '../verify/run-overlay-retry-loop.js';\nimport { runStalenessCheck } from '../verify/run-staleness-check.js';\nimport { runSmokeCheck } from '../verify/run-smoke-check.js';\nimport { summarizeCompatCheck, setRetryDiagnostics, writeDiagnostics } from '../verify/write-diagnostics.js';\nimport type { VerifyDiagnostics } from '../verify/types.js';\n\nexport type { VerifyDiagnostics } from '../verify/types.js';\n\nconst separator = '='.repeat(60);\n\nfunction printCompatResult(result: ReturnType<typeof summarizeCompatCheck>, baseline: ApiSurface): void {\n if (result.scopedToSpec) {\n const totalBefore =\n Object.keys(baseline.interfaces).length +\n Object.keys(baseline.classes).length +\n Object.keys(baseline.typeAliases).length +\n Object.keys(baseline.enums).length;\n console.log(`(scoped to spec: ${result.scopedSymbolCount}/${totalBefore} baseline symbols in scope)`);\n }\n\n console.log(\n `compat: ${result.preservationScore}% (${result.preservedSymbols}/${result.totalBaselineSymbols} symbols preserved)`,\n );\n}\n\nexport async function verifyCommand(opts: {\n spec?: string;\n oldSpec?: string;\n lang: string;\n output: string;\n apiSurface?: string;\n rawResults?: string;\n smokeConfig?: string;\n smokeRunner?: string;\n scope?: 'full' | 'spec-only';\n diagnostics?: boolean;\n maxRetries?: number;\n operationIdTransform?: (id: string) => string;\n schemaNameTransform?: (name: string) => string;\n namespace?: string;\n compatConfig?: CompatConfig;\n compatReport?: string;\n compatFailOn?: string;\n compatBaseline?: string;\n compatExplain?: boolean;\n}): Promise<void> {\n const {\n spec,\n oldSpec,\n lang,\n output,\n apiSurface,\n rawResults,\n smokeConfig,\n smokeRunner,\n scope,\n diagnostics,\n operationIdTransform,\n schemaNameTransform,\n compatConfig,\n compatReport,\n compatExplain,\n } = opts;\n const maxRetries = opts.maxRetries ?? 3;\n const diagData: VerifyDiagnostics = {};\n\n // Resolve compat options: CLI flags take precedence over config\n const effectiveFailOn: CompatFailLevel =\n (opts.compatFailOn as CompatFailLevel | undefined) ?? compatConfig?.failOn ?? 'breaking';\n const effectiveReportPath = compatReport ?? compatConfig?.reportPath;\n const effectiveExplain = compatExplain ?? compatConfig?.explain ?? false;\n\n let stepNum = 1;\n const baseline: ApiSurface | undefined = apiSurface\n ? (JSON.parse(readFileSync(apiSurface, 'utf-8')) as ApiSurface)\n : undefined;\n\n if (apiSurface && baseline) {\n console.log(`\\n${separator}`);\n console.log(`Step ${stepNum}: Compat verification`);\n console.log(separator);\n\n const effectiveScope = scope ?? (spec ? 'spec-only' : 'full');\n let parsedSpec;\n if (effectiveScope === 'spec-only' && spec) {\n parsedSpec = await parseSpec(spec, { operationIdTransform, schemaNameTransform });\n } else if (effectiveScope === 'spec-only') {\n throw new CommandError('error: --scope spec-only requires --spec <path>', '', 1);\n }\n\n const compatFlow =\n parsedSpec && maxRetries > 0\n ? await runOverlayRetryLoop({\n baseline,\n parsedSpec,\n outputDir: output,\n lang,\n maxRetries,\n namespace: opts.namespace,\n onRetry: (attemptNumber, retryLimit, patchableCount) => {\n console.log(`\\nRetry ${attemptNumber}/${retryLimit}: patching ${patchableCount} violation(s)...`);\n },\n })\n : {\n status: 'passed' as const,\n attempts: 0,\n patchedPerIteration: [],\n compatResult: await runCompatCheck(baseline, output, lang, parsedSpec),\n };\n\n const compatSummary = summarizeCompatCheck(compatFlow.compatResult);\n printCompatResult(compatSummary, baseline);\n const classifiedDiff = compatFlow.compatResult.diff;\n for (const c of classifiedDiff.changes) {\n if (c.severity !== 'additive') {\n console.log(` [${c.category}] ${c.severity}: ${c.symbol} — ${c.message}`);\n }\n }\n const additiveCount = classifiedDiff.summary.additive;\n if (additiveCount > 0) {\n console.log(` + ${additiveCount} new symbols added`);\n }\n\n if (diagnostics) {\n diagData.compatCheck = compatSummary;\n if (parsedSpec && maxRetries > 0) {\n setRetryDiagnostics(\n diagData,\n compatFlow.attempts,\n compatFlow.status === 'passed',\n compatSummary.preservationScore,\n compatFlow.patchedPerIteration,\n );\n }\n }\n\n if (compatFlow.status === 'passed' && compatFlow.compatResult.passed) {\n if (compatFlow.attempts > 0) {\n console.log(`Compat: converged after ${compatFlow.attempts} retry iteration(s)`);\n } else {\n console.log('Compat: passed');\n }\n } else {\n if (diagnostics) {\n writeDiagnostics(diagData);\n console.log('Diagnostics written to verify-diagnostics.json');\n }\n\n if (compatFlow.status === 'no-patchable') {\n console.log(\n 'No patchable violations — cannot self-correct. Remaining violations require emitter code changes.',\n );\n } else if (compatFlow.status === 'stalled') {\n console.log(`Stalled — overlay patching is not making progress.`);\n }\n\n throw new CommandError('\\nCompat violations found — fix the emitter and re-run `oagen verify`.', '', 1);\n }\n\n // Classified compat analysis — approvals, reports, and explanations\n // The diff is already classified from runCompatCheck/runOverlayRetryLoop\n if (effectiveReportPath || effectiveExplain || (compatConfig?.allow?.length ?? 0) > 0) {\n const langId = lang as LanguageId;\n const approvals = compatConfig?.allow ?? [];\n const remaining = unapprovedChanges(classifiedDiff.changes, approvals, langId);\n const hasFailure = remaining.some((c) => severityMeetsThreshold(c.severity, effectiveFailOn));\n\n if (effectiveExplain) {\n console.log('');\n console.log(formatHumanSummary(classifiedDiff, { explain: true }));\n }\n\n if (effectiveReportPath) {\n const report = generateReport(classifiedDiff);\n writeFileSync(effectiveReportPath, JSON.stringify(report, null, 2) + '\\n');\n console.log(`Compat report written to ${effectiveReportPath}`);\n }\n\n if (hasFailure && effectiveFailOn !== 'none') {\n const unapprovedBreaking = remaining.filter((c) => severityMeetsThreshold(c.severity, effectiveFailOn));\n console.log(`\\n${unapprovedBreaking.length} unapproved change(s) at or above '${effectiveFailOn}' threshold`);\n }\n }\n\n stepNum++;\n }\n\n if (oldSpec && spec && apiSurface && baseline) {\n console.log(`\\n${separator}`);\n console.log(`Step ${stepNum}: Staleness detection`);\n console.log(separator);\n\n const oldParsedSpec = await parseSpec(oldSpec, { operationIdTransform, schemaNameTransform });\n const newParsedSpec = await parseSpec(spec, { operationIdTransform, schemaNameTransform });\n const stalenessResult = runStalenessCheck(baseline, oldParsedSpec, newParsedSpec, lang);\n\n if (stalenessResult.violations.length > 0) {\n console.log(`Found ${stalenessResult.violations.length} stale symbol(s):`);\n for (const v of stalenessResult.violations) {\n console.log(` [${v.category}] ${v.severity}: ${v.symbolPath} — ${v.message}`);\n }\n } else {\n console.log('No stale symbols detected.');\n }\n\n if (diagnostics) {\n diagData.stalenessCheck = {\n staleSymbolCount: stalenessResult.violations.length,\n staleSymbols: stalenessResult.violations.map((v) => v.symbolPath),\n };\n }\n\n stepNum++;\n }\n\n const needsBaselineStep = !rawResults && !existsSync('smoke-results-raw.json');\n if (needsBaselineStep) {\n console.log(`\\n${separator}`);\n console.log(`Step ${stepNum}: Generating spec-only baseline (no raw baseline found)`);\n console.log(separator);\n stepNum++;\n }\n\n console.log(`\\n${separator}`);\n console.log(`Step ${stepNum}: Smoke test + diff`);\n console.log(separator);\n\n const smokeResult = runSmokeCheck({\n spec,\n lang,\n output,\n rawResults,\n smokeConfig,\n smokeRunner,\n });\n\n if (diagnostics) {\n diagData.smokeCheck = {\n passed: smokeResult.passed,\n ...(smokeResult.findingsCount !== undefined ? { findingsCount: smokeResult.findingsCount } : {}),\n ...(smokeResult.compileErrors ? { compileErrors: true } : {}),\n };\n writeDiagnostics(diagData);\n console.log('Diagnostics written to verify-diagnostics.json');\n }\n\n if (!smokeResult.passed) {\n if (smokeResult.compileErrors) {\n throw new CommandError('\\nSDK compile errors — read smoke-compile-errors.json for details', '', 2);\n }\n\n throw new CommandError(\n '\\nSmoke test findings — read smoke-diff-findings.json for details\\n\\n' +\n `Remediation guide (by finding type):\n \"HTTP method differs\" → fix ${lang} emitter resources.ts (in emitter project)\n \"Request path structure differs\" → fix ${lang} emitter resources.ts (in emitter project)\n \"Query parameters differ\" → fix ${lang} emitter resources.ts (in emitter project)\n \"Request body key sets differ\" → fix ${lang} emitter models.ts or resources.ts (in emitter project)\n \"Skipped in SDK\" → fix smoke/sdk-${lang}.ts (in emitter project)\n \"Missing from SDK\" → fix smoke/sdk-${lang}.ts (in emitter project)`,\n '',\n 1,\n );\n }\n\n console.log('\\nVerify: all checks passed');\n}\n","import { toCamelCase } from '../../utils/naming.js';\n\nexport function oagenScripts(lang: string): Record<string, string> {\n return {\n [`sdk:generate:${lang}`]: `oagen generate --lang ${lang} --output ./sdk --namespace my-api --spec open-api-spec.yaml --api-surface ./sdk-${lang}-surface.json --target ../your-${lang}-sdk`,\n [`sdk:diff:${lang}`]: `oagen diff --old ./sdk/spec-snapshot.yaml --new open-api-spec.yaml --lang ${lang} --output ./sdk --target ../your-${lang}-sdk --api-surface ./sdk-${lang}-surface.json`,\n [`sdk:verify:${lang}`]: `oagen verify --lang ${lang} --output ./sdk --spec open-api-spec.yaml --api-surface ./sdk-${lang}-surface.json`,\n [`sdk:extract:${lang}`]: `oagen extract --lang ${lang} --sdk-path ../your-${lang}-sdk --output ./sdk-${lang}-surface.json`,\n };\n}\n\nexport function packageJson(lang: string): string {\n return JSON.stringify(\n {\n name: `custom-oagen-emitters`,\n version: '0.0.1',\n type: 'module',\n main: 'dist/index.js',\n types: 'dist/index.d.ts',\n exports: {\n '.': { types: './dist/index.d.ts', import: './dist/index.js' },\n './plugin': { types: './dist/plugin.d.ts', import: './dist/plugin.js' },\n },\n scripts: {\n build: 'tsup',\n test: 'vitest run',\n 'test:watch': 'vitest',\n typecheck: 'tsc --noEmit',\n ...oagenScripts(lang),\n },\n dependencies: {\n '@workos/oagen': '^0.0.1',\n },\n devDependencies: {\n tsup: '^8.4.0',\n tsx: '^4.19.0',\n vitest: '^3.0.0',\n '@types/node': '^25.3.3',\n },\n },\n null,\n 2,\n );\n}\n\nexport function tsconfigJson(): string {\n return JSON.stringify(\n {\n compilerOptions: {\n target: 'ES2022',\n module: 'ESNext',\n moduleResolution: 'bundler',\n strict: true,\n declaration: true,\n declarationMap: true,\n sourceMap: true,\n outDir: 'dist',\n rootDir: '.',\n esModuleInterop: true,\n skipLibCheck: true,\n forceConsistentCasingInFileNames: true,\n resolveJsonModule: true,\n isolatedModules: true,\n },\n include: ['src', 'test'],\n exclude: ['node_modules', 'dist'],\n },\n null,\n 2,\n );\n}\n\nexport function vitestConfig(): string {\n return `import { defineConfig } from 'vitest/config';\nexport default defineConfig({\n test: { globals: true, include: ['test/**/*.test.ts'] },\n});\n`;\n}\n\nexport function tsupConfig(): string {\n return `import { defineConfig } from 'tsup';\nexport default defineConfig({\n entry: { index: 'src/index.ts', plugin: 'src/plugin.ts' },\n format: ['esm'],\n dts: true,\n clean: true,\n target: 'node20',\n});\n`;\n}\n\nexport function oagenConfig(): string {\n return `import type { OagenConfig } from '@workos/oagen';\nimport { plugin } from './src/plugin.js';\n\n// Minimal config for local emitter development.\n// The canonical consumer config lives in the consumer project's oagen.config.ts,\n// which imports the plugin bundle from this package.\nconst config: OagenConfig = {\n ...plugin,\n};\nexport default config;\n`;\n}\n\nexport function srcPlugin(lang: string): string {\n const varName = `${toCamelCase(lang)}Emitter`;\n return `import type { OagenConfig } from '@workos/oagen';\nimport { ${varName} } from './${lang}/index.js';\n\nexport const plugin: Pick<OagenConfig, 'emitters' | 'extractors' | 'smokeRunners'> = {\n emitters: [${varName}],\n extractors: [],\n smokeRunners: {},\n};\n`;\n}\n\nexport function srcIndex(lang: string): string {\n const varName = `${toCamelCase(lang)}Emitter`;\n return `export { ${varName} } from './${lang}/index.js';\nexport { plugin } from './plugin.js';\n`;\n}\n\nexport function gitignore(): string {\n return `node_modules/\ndist/\n.env\nsdk-*-surface.json\nsmoke-*.json\nsdk/\n`;\n}\n\nexport function stubEmitter(lang: string): string {\n const varName = `${toCamelCase(lang)}Emitter`;\n return `import type { Emitter, EmitterContext, GeneratedFile, ApiSpec, Model, Enum, Service } from '@workos/oagen';\n\nexport const ${varName}: Emitter = {\n language: '${lang}',\n\n generateModels(_models: Model[], _ctx: EmitterContext): GeneratedFile[] {\n return [];\n },\n\n generateEnums(_enums: Enum[], _ctx: EmitterContext): GeneratedFile[] {\n return [];\n },\n\n generateResources(_services: Service[], _ctx: EmitterContext): GeneratedFile[] {\n return [];\n },\n\n generateClient(_spec: ApiSpec, _ctx: EmitterContext): GeneratedFile[] {\n return [];\n },\n\n generateErrors(_ctx: EmitterContext): GeneratedFile[] {\n return [];\n },\n\n generateTypeSignatures(_spec: ApiSpec, _ctx: EmitterContext): GeneratedFile[] {\n return [];\n },\n\n generateTests(_spec: ApiSpec, _ctx: EmitterContext): GeneratedFile[] {\n return [];\n },\n\n buildOperationsMap(_spec: ApiSpec, _ctx: EmitterContext) {\n return {};\n },\n\n fileHeader(): string {\n return '// Auto-generated by oagen. Do not edit.';\n },\n};\n`;\n}\n","import { resolve, relative } from 'node:path';\nimport { existsSync, mkdirSync, writeFileSync, readFileSync } from 'node:fs';\nimport {\n packageJson,\n tsconfigJson,\n vitestConfig,\n tsupConfig,\n oagenConfig,\n srcPlugin,\n srcIndex,\n gitignore,\n stubEmitter,\n} from './templates/init.js';\n\nexport async function initCommand(opts: { lang: string; project?: string }): Promise<void> {\n const projectDir = resolve(opts.project ?? '.');\n const lang = opts.lang;\n\n if (existsSync(resolve(projectDir, 'oagen.config.ts'))) {\n throw new Error('Project already initialized — oagen.config.ts exists');\n }\n\n // Create directories\n const dirs = [`src/${lang}`, 'test', 'smoke', 'docs/sdk-architecture'];\n for (const dir of dirs) {\n mkdirSync(resolve(projectDir, dir), { recursive: true });\n }\n\n // Write template files\n const files: Array<[string, string]> = [\n ['tsconfig.json', tsconfigJson()],\n ['vitest.config.ts', vitestConfig()],\n ['tsup.config.ts', tsupConfig()],\n ['oagen.config.ts', oagenConfig()],\n ['src/plugin.ts', srcPlugin(lang)],\n ['src/index.ts', srcIndex(lang)],\n [`src/${lang}/index.ts`, stubEmitter(lang)],\n ];\n\n // Handle package.json specially - merge if it exists\n const packageJsonPath = resolve(projectDir, 'package.json');\n let packageJsonContent: string;\n if (existsSync(packageJsonPath)) {\n const existingContent = readFileSync(packageJsonPath, 'utf-8');\n const existingPkg = JSON.parse(existingContent);\n const newPkg = JSON.parse(packageJson(lang));\n // Merge: existing values take precedence, but append new scripts/devDependencies\n existingPkg.scripts = { ...newPkg.scripts, ...existingPkg.scripts };\n existingPkg.devDependencies = { ...newPkg.devDependencies, ...existingPkg.devDependencies };\n existingPkg.dependencies = { ...newPkg.dependencies, ...existingPkg.dependencies };\n // Only set exports if not already defined\n if (!existingPkg.exports) {\n existingPkg.exports = newPkg.exports;\n }\n // Only set type if not already defined\n if (!existingPkg.type) {\n existingPkg.type = newPkg.type;\n }\n // Only set main if not already defined\n if (!existingPkg.main) {\n existingPkg.main = newPkg.main;\n }\n // Only set types if not already defined\n if (!existingPkg.types) {\n existingPkg.types = newPkg.types;\n }\n packageJsonContent = JSON.stringify(existingPkg, null, 2);\n } else {\n packageJsonContent = packageJson(lang);\n }\n\n // Handle .gitignore specially - append if it exists\n const gitignorePath = resolve(projectDir, '.gitignore');\n let gitignoreContent: string;\n if (existsSync(gitignorePath)) {\n const existingContent = readFileSync(gitignorePath, 'utf-8');\n const newContent = gitignore();\n // Append new entries that don't already exist (filter out comments and empty lines for comparison)\n const existingLines = new Set(\n existingContent\n .split('\\n')\n .map((line) => line.trim())\n .filter((line) => line && !line.startsWith('#')),\n );\n const newLines = newContent.split('\\n').filter((line) => {\n const trimmed = line.trim();\n return trimmed && !existingLines.has(trimmed);\n });\n gitignoreContent = existingContent + (existingContent.endsWith('\\n') ? '' : '\\n') + newLines.join('\\n');\n } else {\n gitignoreContent = gitignore();\n }\n\n for (const [filePath, content] of files) {\n const fullPath = resolve(projectDir, filePath);\n mkdirSync(resolve(fullPath, '..'), { recursive: true });\n writeFileSync(fullPath, content, 'utf-8');\n }\n\n // Write package.json\n writeFileSync(packageJsonPath, packageJsonContent, 'utf-8');\n\n // Write .gitignore\n writeFileSync(gitignorePath, gitignoreContent, 'utf-8');\n\n // Print summary\n console.log(`Initialized emitter project for \"${lang}\" in ${relative(process.cwd(), projectDir) || '.'}`);\n console.log('');\n console.log('Created:');\n for (const [filePath] of files) {\n console.log(` ${filePath}`);\n }\n for (const dir of dirs) {\n console.log(` ${dir}/`);\n }\n\n // Print next steps\n console.log('');\n console.log('Next steps:');\n console.log(` - Implement your emitter in src/${lang}/index.ts`);\n console.log(' - npm run sdk:generate -- --spec <path-to-spec> --namespace <Name>');\n console.log(' - npm run sdk:verify -- --spec <path-to-spec>');\n}\n","import { parseSpec } from '../parser/parse.js';\nimport { resolveOperations } from '../ir/operation-hints.js';\nimport { expandDocUrls } from '../utils/expand-doc-urls.js';\nimport type { OperationHint, ResolvedOperation } from '../ir/operation-hints.js';\n\nexport async function resolveCommand(opts: {\n spec: string;\n format?: 'table' | 'json';\n operationIdTransform?: (id: string) => string;\n schemaNameTransform?: (name: string) => string;\n docUrl?: string;\n operationHints?: Record<string, OperationHint>;\n mountRules?: Record<string, string>;\n}): Promise<void> {\n let ir = await parseSpec(opts.spec, {\n operationIdTransform: opts.operationIdTransform,\n schemaNameTransform: opts.schemaNameTransform,\n });\n if (opts.docUrl) {\n ir = expandDocUrls(ir, opts.docUrl);\n }\n\n const resolved = resolveOperations(ir, opts.operationHints, opts.mountRules);\n const format = opts.format ?? 'table';\n\n if (format === 'json') {\n const output = resolved.map(toJsonRow);\n console.log(JSON.stringify(output, null, 2));\n return;\n }\n\n // Table format\n printTable(resolved, opts.operationHints);\n}\n\ninterface JsonRow {\n service: string;\n method: string;\n path: string;\n derivedName: string;\n hintApplied: boolean;\n mountOn: string;\n wrappers?: string[];\n}\n\nfunction toJsonRow(r: ResolvedOperation): JsonRow {\n return {\n service: r.service.name,\n method: r.operation.httpMethod.toUpperCase(),\n path: r.operation.path,\n derivedName: r.methodName,\n hintApplied: r.methodName !== r.operation.name,\n mountOn: r.mountOn,\n wrappers: r.wrappers?.map((w) => w.name),\n };\n}\n\nfunction printTable(resolved: ResolvedOperation[], hints?: Record<string, OperationHint>): void {\n const hintMap = hints ?? {};\n\n // Header\n console.log('| Service | Method | Path | Resolved Name | Hint | Mount On |');\n console.log('|---|---|---|---|---|---|');\n\n const unhinted: ResolvedOperation[] = [];\n\n for (const r of resolved) {\n const key = `${r.operation.httpMethod.toUpperCase()} ${r.operation.path}`;\n const hasHint = key in hintMap;\n const hintMarker = hasHint ? 'yes' : '';\n const mountChanged = r.mountOn !== r.service.name;\n const mountCol = mountChanged ? r.mountOn : '';\n\n console.log(\n `| ${r.service.name} | ${r.operation.httpMethod.toUpperCase()} | ${r.operation.path} | \\`${r.methodName}\\` | ${hintMarker} | ${mountCol} |`,\n );\n\n // Track wrappers\n if (r.wrappers) {\n for (const w of r.wrappers) {\n console.log(`| | | | \\`${w.name}\\` (wrapper) | yes | ${mountCol} |`);\n }\n }\n\n if (!hasHint && !mountChanged) {\n unhinted.push(r);\n }\n }\n\n console.log('');\n console.log(\n `Total: ${resolved.length} operations, ${resolved.length - unhinted.length} with hints/mounts, ${unhinted.length} algorithm-only`,\n );\n}\n","import * as path from 'node:path';\nimport { existsSync } from 'node:fs';\nimport { pathToFileURL } from 'node:url';\nimport type { Emitter } from '../engine/types.js';\nimport type { OperationHint } from '../ir/operation-hints.js';\nimport type { Extractor } from '../compat/types.js';\nimport type { CompatConfig } from '../compat/config.js';\nimport { ConfigLoadError } from '../errors.js';\n\nexport interface OagenConfig {\n emitters?: Emitter[];\n extractors?: Extractor[];\n /** Compatibility verification policy. See docs/core/compatibility-policy.md. */\n compat?: CompatConfig;\n /** Path to the emitter project (where skills scaffold new emitters, tests, smoke runners). */\n emitterProject?: string;\n /** Map from language key to custom smoke runner script path. */\n smokeRunners?: Record<string, string>;\n /**\n * Custom transform for operation IDs. When provided, replaces the default\n * camelCase pass-through. Receives the raw operationId string; return the\n * desired operation name (no additional conversion is applied).\n *\n */\n operationIdTransform?: (id: string) => string;\n /**\n * Custom transform for schema (model/enum) names. Applied after the built-in\n * cleanSchemaName normalization. Receives the cleaned PascalCase name; return\n * the desired name. Collisions are detected automatically -- if a transform\n * would produce a duplicate name, the original is kept.\n */\n schemaNameTransform?: (name: string) => string;\n /** Base URL for documentation links. When set, relative paths in descriptions\n * (e.g. `/reference/authkit/user`) are expanded to full URLs. */\n docUrl?: string;\n /**\n * Per-operation overrides keyed by \"METHOD /path\" (e.g. \"POST /sso/token\").\n * Used by the operation resolver to override derived method names, mount\n * targets, and to split union-body operations into typed wrappers.\n */\n operationHints?: Record<string, OperationHint>;\n /**\n * Service-level mount rules: maps an IR service name to a target\n * service/namespace (PascalCase). All operations in the source service\n * are mounted on the target. Per-operation mountOn in operationHints\n * takes priority.\n */\n mountRules?: Record<string, string>;\n}\n\nconst CONFIG_NAMES = ['oagen.config.ts', 'oagen.config.js', 'oagen.config.mjs'];\n\n/**\n * Load an oagen config file.\n *\n * @param configPath - Explicit path to a config file. When provided, only that\n * file is attempted (no fallback search).\n * @param cwd - Directory to search when `configPath` is omitted. Defaults to\n * `process.cwd()`. The loader tries each name in `CONFIG_NAMES` in order.\n */\nexport async function loadConfig(configPath?: string, cwd: string = process.cwd()): Promise<OagenConfig | null> {\n if (configPath) {\n const resolved = path.resolve(cwd, configPath);\n if (!existsSync(resolved)) {\n throw new ConfigLoadError(`Config file not found: ${resolved}`, 'Check that the path passed to --config exists.');\n }\n try {\n const mod = await import(pathToFileURL(resolved).href);\n return (mod.default ?? mod) as OagenConfig;\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n throw new ConfigLoadError(\n `Failed to load ${resolved}: ${message}`,\n resolved.endsWith('.ts')\n ? 'TypeScript config files require tsx or ts-node. Use .mjs instead, or run via `npx tsx`.'\n : 'Check that the config file is valid ESM.',\n );\n }\n }\n\n for (const name of CONFIG_NAMES) {\n const resolved = path.resolve(cwd, name);\n if (!existsSync(resolved)) continue;\n try {\n const mod = await import(pathToFileURL(resolved).href);\n const config = (mod.default ?? mod) as OagenConfig;\n return config;\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n throw new ConfigLoadError(\n `Failed to load ${name}: ${message}`,\n name.endsWith('.ts')\n ? 'TypeScript config files require tsx or ts-node. Use .mjs instead, or run via `npx tsx`.'\n : 'Check that the config file is valid ESM.',\n );\n }\n }\n return null;\n}\n","import { registerEmitter } from '../engine/registry.js';\nimport { registerExtractor } from '../compat/extractor-registry.js';\nimport type { OagenConfig } from './config-loader.js';\n\nexport function applyConfig(config: OagenConfig): void {\n for (const emitter of config.emitters ?? []) {\n registerEmitter(emitter);\n }\n for (const extractor of config.extractors ?? []) {\n registerExtractor(extractor);\n }\n}\n","import 'dotenv/config';\nimport { Command } from 'commander';\nimport { parseCommand } from './parse.js';\nimport { generateCommand } from './generate.js';\nimport { diffCommand } from './diff.js';\nimport { extractCommand } from './extract.js';\nimport { compatExtractCommand } from './compat-extract.js';\nimport { compatDiffCommand } from './compat-diff.js';\nimport { compatSummaryCommand } from './compat-summary.js';\nimport { verifyCommand } from './verify.js';\nimport { initCommand } from './init.js';\nimport { resolveCommand } from './resolve.js';\nimport { loadConfig } from './config-loader.js';\nimport { applyConfig } from './plugin-loader.js';\nimport { CommandError } from '../errors.js';\n\nfunction handleError(err: unknown): never {\n const exitCode = err instanceof CommandError ? err.exitCode : 1;\n const message = err instanceof Error ? err.message : String(err);\n if (message) console.error(message);\n process.exit(exitCode);\n}\n\n// Parse --config before Commander runs so we can load the right config file\n// at startup. Commander's parseOptions isn't available before .parse(), so we\n// do a simple argv scan.\nconst configArgIdx = process.argv.indexOf('--config');\nconst explicitConfigPath = configArgIdx !== -1 ? process.argv[configArgIdx + 1] : undefined;\n\n// Load config at startup so user-provided emitters/extractors are registered\n// before any command runs. loadConfig is async (dynamic import), so we use\n// top-level await.\nlet configSmokeRunners: Record<string, string> | undefined;\nlet configOperationIdTransform: ((id: string) => string) | undefined;\nlet configSchemaNameTransform: ((name: string) => string) | undefined;\nlet configDocUrl: string | undefined;\nlet configOperationHints: Record<string, import('../ir/operation-hints.js').OperationHint> | undefined;\nlet configMountRules: Record<string, string> | undefined;\nlet configCompat: import('../compat/config.js').CompatConfig | undefined;\ntry {\n const config = await loadConfig(explicitConfigPath);\n if (config) {\n applyConfig(config);\n configSmokeRunners = config.smokeRunners;\n configOperationIdTransform = config.operationIdTransform;\n configSchemaNameTransform = config.schemaNameTransform;\n configDocUrl = config.docUrl;\n configOperationHints = config.operationHints;\n configMountRules = config.mountRules;\n configCompat = config.compat;\n }\n} catch (err) {\n handleError(err);\n}\n\nconst program = new Command()\n .name('oagen')\n .description('Framework for building OpenAPI SDK emitters')\n .version('0.0.1')\n .option('--config <path>', 'Path to oagen config file (default: oagen.config.ts in cwd)');\n\nprogram\n .command('parse')\n .description('Parse an OpenAPI spec and output IR as JSON')\n .option('--spec <path>', 'Path to OpenAPI spec file (or set OPENAPI_SPEC_PATH)')\n .action((opts) => {\n opts.spec ??= process.env.OPENAPI_SPEC_PATH;\n if (!opts.spec) {\n console.error('error: --spec <path> or OPENAPI_SPEC_PATH env var is required');\n process.exit(1);\n }\n return parseCommand(opts);\n });\n\nprogram\n .command('generate')\n .description('Run a registered emitter against an OpenAPI spec')\n .option('--spec <path>', 'Path to OpenAPI spec file (or set OPENAPI_SPEC_PATH)')\n .requiredOption('--lang <language>', 'Target language')\n .requiredOption('--output <dir>', 'Output directory')\n .option('--target <dir>', 'Target directory for live SDK integration (merged output)')\n .option('--namespace <name>', 'SDK namespace/package name')\n .option('--dry-run', 'Preview files without writing')\n .option('--api-surface <path>', 'Path to baseline API surface JSON for compat overlay')\n .option('--no-compat-check', 'Skip compat overlay even if --api-surface is provided')\n .option('--no-prune', 'Skip deletion of stale files recorded in the previous .oagen-manifest.json')\n .action((opts) => {\n opts.spec ??= process.env.OPENAPI_SPEC_PATH;\n if (!opts.spec) {\n console.error('error: --spec <path> or OPENAPI_SPEC_PATH env var is required');\n process.exit(1);\n }\n generateCommand({\n ...opts,\n operationIdTransform: configOperationIdTransform,\n schemaNameTransform: configSchemaNameTransform,\n docUrl: configDocUrl,\n operationHints: configOperationHints,\n mountRules: configMountRules,\n }).catch(handleError);\n });\n\nprogram\n .command('diff')\n .description('Compare two OpenAPI specs and output a diff report')\n .requiredOption('--old <path>', 'Path to old spec')\n .requiredOption('--new <path>', 'Path to new spec')\n .action((opts) => {\n diffCommand({\n ...opts,\n operationIdTransform: configOperationIdTransform,\n schemaNameTransform: configSchemaNameTransform,\n docUrl: configDocUrl,\n }).catch(handleError);\n });\n\nprogram\n .command('extract')\n .description('Extract public API surface from a live SDK')\n .requiredOption('--sdk-path <path>', 'Path to the live SDK')\n .requiredOption('--lang <language>', 'Target language')\n .option('--output <path>', 'Output file path')\n .action((opts) => {\n opts.output ??= `sdk-${opts.lang}-surface.json`;\n extractCommand(opts).catch(handleError);\n });\n\nprogram\n .command('compat-extract')\n .description('Extract a compat snapshot from a live SDK and write .oagen-compat-snapshot.json')\n .requiredOption('--sdk-path <path>', 'Path to the live SDK')\n .requiredOption('--lang <language>', 'Target language')\n .requiredOption('--output <dir>', 'Directory to write .oagen-compat-snapshot.json into')\n .option('--spec <path>', 'Path to OpenAPI spec — enriches symbols with operationId, route, and specSha')\n .action((opts) => {\n opts.spec ??= process.env.OPENAPI_SPEC_PATH;\n compatExtractCommand({\n ...opts,\n schemaNameTransform: configSchemaNameTransform,\n }).catch(handleError);\n });\n\nprogram\n .command('compat-diff')\n .description('Diff two compat snapshot files and produce a classified change report')\n .requiredOption('--baseline <path>', 'Path to the baseline compat snapshot JSON')\n .requiredOption('--candidate <path>', 'Path to the candidate compat snapshot JSON')\n .option('--output <path>', 'Write machine-readable report to this path')\n .option('--fail-on <level>', 'Fail threshold: none, breaking, or soft-risk', 'breaking')\n .option('--explain', 'Include provenance explanations in output')\n .action((opts) => {\n compatDiffCommand(opts).catch(handleError);\n });\n\nprogram\n .command('compat-summary')\n .description('Format compat report(s) as a markdown PR comment')\n .requiredOption('--report <path...>', 'Path(s) to compat report JSON(s) — pass multiple for cross-language rollup')\n .option('--output <path>', 'Write markdown to this file instead of stdout')\n .action((opts) => {\n compatSummaryCommand(opts).catch(handleError);\n });\n\nprogram\n .command('verify')\n .description('Run smoke tests (and optional compat check) against an already-generated SDK')\n .option('--spec <path>', 'Path to OpenAPI spec file (or set OPENAPI_SPEC_PATH)')\n .requiredOption('--lang <language>', 'Target language')\n .requiredOption('--output <dir>', 'Path to the generated SDK')\n .option('--api-surface <path>', 'Baseline API surface JSON — enables compat verification')\n .option('--raw-results <path>', 'Path to an existing smoke baseline file to diff against')\n .option('--smoke-config <path>', 'Path to smoke config JSON for skip lists and service mappings')\n .option('--smoke-runner <path>', 'Path to a custom smoke runner script (overrides built-in sdk-test.ts)')\n .option(\n '--scope <mode>',\n 'Compat scope: \"full\" compares all baseline symbols, \"spec-only\" compares only symbols derivable from the OpenAPI spec (default: spec-only when --spec is provided)',\n )\n .option('--old-spec <path>', 'Previous OpenAPI spec — enables staleness detection for removed/renamed symbols')\n .option('--namespace <name>', 'SDK namespace/package name (used by retry loop for regeneration)')\n .option('--diagnostics', 'Output verify-diagnostics.json with structured violation breakdown')\n .option('--max-retries <n>', 'Max retry iterations for self-correcting overlay loop (default: 3)', '3')\n .option('--compat-report <path>', 'Write machine-readable compat report to this path')\n .option('--compat-fail-on <level>', 'Fail threshold: none, breaking, or soft-risk')\n .option('--compat-baseline <path>', 'Path to baseline compatibility snapshot')\n .option('--compat-explain', 'Include provenance explanations in compat output')\n .action((opts) => {\n opts.spec ??= process.env.OPENAPI_SPEC_PATH;\n // --spec is only required when we need to generate a baseline (no --raw-results\n // and no existing smoke-results-raw.json). Defer the check to verifyCommand.\n // CLI --smoke-runner takes precedence, then per-language smokeRunners map from config\n opts.smokeRunner ??= configSmokeRunners?.[opts.lang];\n verifyCommand({\n ...opts,\n maxRetries: parseInt(opts.maxRetries, 10),\n operationIdTransform: configOperationIdTransform,\n schemaNameTransform: configSchemaNameTransform,\n compatConfig: configCompat,\n compatReport: opts.compatReport,\n compatFailOn: opts.compatFailOn,\n compatBaseline: opts.compatBaseline,\n compatExplain: opts.compatExplain,\n }).catch(handleError);\n });\n\nprogram\n .command('resolve')\n .description('Resolve operation names from spec and output a review table')\n .option('--spec <path>', 'Path to OpenAPI spec file (or set OPENAPI_SPEC_PATH)')\n .option('--format <format>', 'Output format: table or json', 'table')\n .action((opts) => {\n opts.spec ??= process.env.OPENAPI_SPEC_PATH;\n if (!opts.spec) {\n console.error('error: --spec <path> or OPENAPI_SPEC_PATH env var is required');\n process.exit(1);\n }\n resolveCommand({\n ...opts,\n operationIdTransform: configOperationIdTransform,\n schemaNameTransform: configSchemaNameTransform,\n docUrl: configDocUrl,\n operationHints: configOperationHints,\n mountRules: configMountRules,\n }).catch(handleError);\n });\n\nprogram\n .command('init')\n .description('Scaffold a new emitter project')\n .requiredOption('--lang <language>', 'Target language')\n .option('--project <dir>', 'Project directory', '.')\n .action((opts) => {\n initCommand(opts).catch(handleError);\n });\n\nprogram.parse();\n"],"mappings":"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"}
|