@workos/oagen 0.7.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/index.mjs +1123 -436
- package/dist/cli/index.mjs.map +1 -1
- package/dist/compat/index.d.mts +144 -57
- package/dist/compat/index.d.mts.map +1 -1
- package/dist/compat/index.mjs +362 -41
- package/dist/compat/index.mjs.map +1 -1
- package/dist/{diff-BYadQQV7.mjs → diff-BaH9qa8k.mjs} +11 -2
- package/dist/{diff-BYadQQV7.mjs.map → diff-BaH9qa8k.mjs.map} +1 -1
- package/dist/differ-CTl98yoS.d.mts +116 -0
- package/dist/differ-CTl98yoS.d.mts.map +1 -0
- package/dist/index.d.mts +3 -1
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +50 -10
- package/dist/index.mjs.map +1 -1
- package/dist/{differ-CG5ZErKl.mjs → overlay-TYxHOCow.mjs} +1112 -553
- package/dist/overlay-TYxHOCow.mjs.map +1 -0
- package/dist/scripts/smoke/baseline.mjs +49 -9
- package/dist/scripts/smoke/baseline.mjs.map +1 -1
- package/dist/smoke.d.mts +10 -0
- package/dist/smoke.d.mts.map +1 -1
- package/dist/smoke.mjs +49 -9
- package/dist/smoke.mjs.map +1 -1
- package/dist/tree-sitter-C53w_0WE.mjs.map +1 -1
- package/dist/{types-DJMbCtIO.d.mts → types-mTtkgy_h.d.mts} +180 -2
- package/dist/types-mTtkgy_h.d.mts.map +1 -0
- package/dist/verify/index.d.mts +4 -3
- package/dist/verify/index.d.mts.map +1 -1
- package/dist/verify/index.mjs +12 -10
- package/dist/verify/index.mjs.map +1 -1
- package/docs/architecture/emitter-contract.md +2 -2
- package/docs/architecture/extractor-contract.md +6 -5
- package/docs/architecture/pipeline.md +4 -3
- package/docs/architecture/workflows.md +5 -3
- package/docs/cli.md +148 -6
- package/docs/contributor/public-api.md +1 -1
- package/docs/core/compatibility-ir.md +200 -0
- package/docs/core/compatibility-policy.md +170 -0
- package/docs/core/compatibility.md +83 -0
- package/docs/core/index.md +5 -0
- package/docs/core/manifest-schema.md +76 -0
- package/docs/core/quickstart.md +9 -2
- package/docs/core/verify-compat.md +235 -0
- package/package.json +1 -1
- package/skills/generate-emitter/SKILL.md +12 -7
- package/skills/generate-emitter/references/project-scaffold.md +27 -6
- package/skills/generate-extractor/SKILL.md +14 -8
- package/skills/generate-sdk/SKILL.md +2 -2
- package/skills/generate-smoke-test/SKILL.md +9 -5
- package/skills/review-operations/SKILL.md +2 -2
- package/skills/verify-compat/SKILL.md +1 -1
- package/dist/differ-CG5ZErKl.mjs.map +0 -1
- package/dist/types-DJMbCtIO.d.mts.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tree-sitter-C53w_0WE.mjs","names":[],"sources":["../src/ir/types.ts","../src/errors.ts","../src/utils/naming.ts","../src/utils/tree-sitter.ts"],"sourcesContent":["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\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 * 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","/**\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","/**\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"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"tree-sitter-C53w_0WE.mjs","names":[],"sources":["../src/ir/types.ts","../src/errors.ts","../src/utils/naming.ts","../src/utils/tree-sitter.ts"],"sourcesContent":["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 * 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","/**\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","/**\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"],"mappings":"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"}
|
|
@@ -1,3 +1,106 @@
|
|
|
1
|
+
//#region src/compat/policy.d.ts
|
|
2
|
+
/** Policy hints that determine what constitutes a breaking change. */
|
|
3
|
+
interface CompatPolicyHints {
|
|
4
|
+
/** Callers reference parameter names at the call site (PHP named args, Python/Ruby keyword args, Kotlin/C# named args). */
|
|
5
|
+
callerUsesParamNames: boolean;
|
|
6
|
+
/** Constructor positional order is part of the public API. */
|
|
7
|
+
constructorOrderMatters: boolean;
|
|
8
|
+
/** Method parameter names are visible to callers. */
|
|
9
|
+
methodParameterNamesArePublicApi: boolean;
|
|
10
|
+
/** Constructor parameter names are visible to callers. */
|
|
11
|
+
constructorParameterNamesArePublicApi: boolean;
|
|
12
|
+
/** Method overload sets are part of the public API (Kotlin, C#). */
|
|
13
|
+
overloadsArePublicApi: boolean;
|
|
14
|
+
/** Function arity is part of the public API (Elixir, Go). */
|
|
15
|
+
arityIsPublicApi: boolean;
|
|
16
|
+
}
|
|
17
|
+
/** Get the built-in default policy for a language. */
|
|
18
|
+
declare function getDefaultPolicy(language: LanguageId): CompatPolicyHints;
|
|
19
|
+
/** Merge user overrides onto language defaults. Only provided keys are overridden. */
|
|
20
|
+
declare function mergePolicy(defaults: CompatPolicyHints, overrides: Partial<CompatPolicyHints>): CompatPolicyHints;
|
|
21
|
+
/** All supported language IDs. */
|
|
22
|
+
declare const ALL_LANGUAGE_IDS: readonly LanguageId[];
|
|
23
|
+
//#endregion
|
|
24
|
+
//#region src/compat/ir.d.ts
|
|
25
|
+
/** Language identifier for emitter targets. */
|
|
26
|
+
type LanguageId = 'node' | 'php' | 'python' | 'ruby' | 'go' | 'kotlin' | 'dotnet' | 'elixir' | 'rust';
|
|
27
|
+
/** A full compatibility snapshot of an SDK's public API surface. */
|
|
28
|
+
interface CompatSnapshot {
|
|
29
|
+
schemaVersion: string;
|
|
30
|
+
source: {
|
|
31
|
+
specSha?: string;
|
|
32
|
+
extractedAt: string;
|
|
33
|
+
};
|
|
34
|
+
policies: CompatPolicyHints;
|
|
35
|
+
symbols: CompatSymbol[];
|
|
36
|
+
}
|
|
37
|
+
/** Kind of public API symbol. */
|
|
38
|
+
type CompatSymbolKind = 'service_accessor' | 'callable' | 'constructor' | 'field' | 'property' | 'enum' | 'enum_member' | 'alias';
|
|
39
|
+
/** Visibility level of a symbol. */
|
|
40
|
+
type CompatVisibility = 'public' | 'protected' | 'internal';
|
|
41
|
+
/** Stability classification of a symbol. */
|
|
42
|
+
type CompatStability = 'stable' | 'unstable' | 'deprecated';
|
|
43
|
+
/** How the symbol was generated. */
|
|
44
|
+
type CompatSourceKind = 'generated_service_wrapper' | 'generated_model_constructor' | 'generated_resource_constructor' | 'generated_enum' | 'compat_alias';
|
|
45
|
+
/** A single public API symbol with its full metadata. */
|
|
46
|
+
interface CompatSymbol {
|
|
47
|
+
id: string;
|
|
48
|
+
kind: CompatSymbolKind;
|
|
49
|
+
fqName: string;
|
|
50
|
+
ownerFqName?: string;
|
|
51
|
+
displayName: string;
|
|
52
|
+
visibility: CompatVisibility;
|
|
53
|
+
stability: CompatStability;
|
|
54
|
+
sourceKind: CompatSourceKind;
|
|
55
|
+
operationId?: string;
|
|
56
|
+
schemaName?: string;
|
|
57
|
+
route?: {
|
|
58
|
+
method: string;
|
|
59
|
+
path: string;
|
|
60
|
+
};
|
|
61
|
+
parameters?: CompatParameter[];
|
|
62
|
+
returns?: CompatTypeRef;
|
|
63
|
+
/** Type reference for field/property symbols. */
|
|
64
|
+
typeRef?: CompatTypeRef;
|
|
65
|
+
/** Value for enum member symbols. */
|
|
66
|
+
value?: string | number;
|
|
67
|
+
}
|
|
68
|
+
/** How a parameter is passed at the call site. */
|
|
69
|
+
type CompatPassingStyle = 'positional' | 'keyword' | 'named' | 'keyword_or_positional' | 'options_object' | 'builder';
|
|
70
|
+
/** A parameter on a callable or constructor symbol. */
|
|
71
|
+
interface CompatParameter {
|
|
72
|
+
publicName: string;
|
|
73
|
+
wireName?: string;
|
|
74
|
+
position: number;
|
|
75
|
+
required: boolean;
|
|
76
|
+
nullable: boolean;
|
|
77
|
+
hasDefault: boolean;
|
|
78
|
+
passing: CompatPassingStyle;
|
|
79
|
+
type: CompatTypeRef;
|
|
80
|
+
sensitivity: ParameterSensitivity;
|
|
81
|
+
}
|
|
82
|
+
/** Which aspects of this parameter are part of the public API contract. */
|
|
83
|
+
interface ParameterSensitivity {
|
|
84
|
+
order: boolean;
|
|
85
|
+
publicName: boolean;
|
|
86
|
+
requiredness: boolean;
|
|
87
|
+
type: boolean;
|
|
88
|
+
}
|
|
89
|
+
/** A type reference — either a named type or an inline description. */
|
|
90
|
+
interface CompatTypeRef {
|
|
91
|
+
name: string;
|
|
92
|
+
nullable?: boolean;
|
|
93
|
+
array?: boolean;
|
|
94
|
+
generic?: string[];
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Convert a legacy ApiSurface to a CompatSnapshot.
|
|
98
|
+
*
|
|
99
|
+
* This bridge allows existing extractors (which produce ApiSurface) to feed
|
|
100
|
+
* into the new classified diff engine without requiring immediate migration.
|
|
101
|
+
*/
|
|
102
|
+
declare function apiSurfaceToSnapshot(surface: ApiSurface): CompatSnapshot;
|
|
103
|
+
//#endregion
|
|
1
104
|
//#region src/compat/types.d.ts
|
|
2
105
|
interface ApiSurface {
|
|
3
106
|
language: string;
|
|
@@ -31,6 +134,9 @@ interface ApiParam {
|
|
|
31
134
|
name: string;
|
|
32
135
|
type: string;
|
|
33
136
|
optional: boolean;
|
|
137
|
+
/** Per-parameter passing style, populated by extractors.
|
|
138
|
+
* When absent, the bridge infers from language defaults. */
|
|
139
|
+
passingStyle?: CompatPassingStyle;
|
|
34
140
|
}
|
|
35
141
|
interface ApiProperty {
|
|
36
142
|
name: string;
|
|
@@ -118,6 +224,7 @@ interface LanguageHints {
|
|
|
118
224
|
interface Extractor {
|
|
119
225
|
language: string;
|
|
120
226
|
extract(sdkPath: string): Promise<ApiSurface>;
|
|
227
|
+
extractSnapshot(sdkPath: string): Promise<CompatSnapshot>;
|
|
121
228
|
hints: LanguageHints;
|
|
122
229
|
}
|
|
123
230
|
interface MethodOverlay {
|
|
@@ -164,6 +271,67 @@ interface DiffResult {
|
|
|
164
271
|
additions: Addition[];
|
|
165
272
|
}
|
|
166
273
|
//#endregion
|
|
274
|
+
//#region src/compat/config.d.ts
|
|
275
|
+
/** Breaking change categories — changes that break callers. */
|
|
276
|
+
type BreakingChangeCategory = 'symbol_removed' | 'symbol_renamed' | 'parameter_removed' | 'parameter_renamed' | 'parameter_requiredness_increased' | 'parameter_type_narrowed' | 'parameter_position_changed_order_sensitive' | 'constructor_position_changed_order_sensitive' | 'named_arg_name_removed' | 'keyword_name_removed' | 'overload_removed' | 'union_wrapper_migration_without_compat_alias' | 'field_type_changed' | 'return_type_changed' | 'enum_member_value_changed';
|
|
277
|
+
/** Soft-risk change categories — may affect callers depending on usage. */
|
|
278
|
+
type SoftRiskChangeCategory = 'parameter_added_non_terminal_optional' | 'constructor_reordered_named_friendly' | 'default_value_changed' | 'wrapper_stricter_than_previous_sdk_but_matches_spec' | 'doc_surface_drift';
|
|
279
|
+
/** Additive change categories — safe to ship. */
|
|
280
|
+
type AdditiveChangeCategory = 'symbol_added' | 'parameter_added_optional_terminal' | 'new_constructor_overload_added' | 'new_wrapper_alias_added';
|
|
281
|
+
/** All change categories. */
|
|
282
|
+
type CompatChangeCategory = BreakingChangeCategory | SoftRiskChangeCategory | AdditiveChangeCategory;
|
|
283
|
+
/** Change severity levels. */
|
|
284
|
+
type CompatChangeSeverity = 'breaking' | 'soft-risk' | 'additive';
|
|
285
|
+
/** Provenance bucket — where the drift originated. */
|
|
286
|
+
type CompatProvenance = 'spec_shape_change' | 'spec_ordering_change' | 'emitter_template_change' | 'compat_extractor_change' | 'operation_hint_change' | 'manual_override_change' | 'normalization_change' | 'unknown';
|
|
287
|
+
/** Level at which `verify` should fail. */
|
|
288
|
+
type CompatFailLevel = 'none' | 'breaking' | 'soft-risk';
|
|
289
|
+
/** A single intentional-break approval in `oagen.config.ts`. */
|
|
290
|
+
interface CompatApproval {
|
|
291
|
+
/** Fully-qualified symbol (e.g., "WorkOS\\Service\\UserManagement::createUser"). */
|
|
292
|
+
symbol: string;
|
|
293
|
+
/** The kind of change being approved. */
|
|
294
|
+
category: CompatChangeCategory;
|
|
295
|
+
/** Languages this approval applies to. Omit for all impacted languages. */
|
|
296
|
+
appliesTo?: LanguageId[] | 'all-impacted-languages';
|
|
297
|
+
/** Optional narrowing criteria. */
|
|
298
|
+
match?: {
|
|
299
|
+
parameter?: string;
|
|
300
|
+
member?: string;
|
|
301
|
+
oldName?: string;
|
|
302
|
+
newName?: string;
|
|
303
|
+
};
|
|
304
|
+
/** Minimum release level required for this break. */
|
|
305
|
+
allowedReleaseLevel?: 'major' | 'minor' | 'patch';
|
|
306
|
+
/** Human-readable reason for this approval. */
|
|
307
|
+
reason: string;
|
|
308
|
+
/** Issue tracker reference (e.g., "SDK-1234"). */
|
|
309
|
+
issue?: string;
|
|
310
|
+
/** Auto-expire this approval after a version is released. */
|
|
311
|
+
expiresAfterVersion?: string;
|
|
312
|
+
/** Whether this approval is currently active. */
|
|
313
|
+
approved?: boolean;
|
|
314
|
+
}
|
|
315
|
+
/** The `compat` section of `oagen.config.ts`. */
|
|
316
|
+
interface CompatConfig {
|
|
317
|
+
/** Level at which `oagen verify` should fail. Default: 'breaking'. */
|
|
318
|
+
failOn?: CompatFailLevel;
|
|
319
|
+
/** Path to write the machine-readable compat report. */
|
|
320
|
+
reportPath?: string;
|
|
321
|
+
/** Include provenance explanations in reports. */
|
|
322
|
+
explain?: boolean;
|
|
323
|
+
/** Path to the baseline compatibility snapshot. */
|
|
324
|
+
baselinePath?: string;
|
|
325
|
+
/** Per-language policy overrides. Sparse — only override what diverges. */
|
|
326
|
+
languagePolicy?: Partial<Record<LanguageId, Partial<CompatPolicyHints>>>;
|
|
327
|
+
/** Intentional break approvals. */
|
|
328
|
+
allow?: CompatApproval[];
|
|
329
|
+
}
|
|
330
|
+
/** Get the default severity for a change category. */
|
|
331
|
+
declare function defaultSeverityForCategory(category: CompatChangeCategory): CompatChangeSeverity;
|
|
332
|
+
/** Check whether a severity meets or exceeds a fail threshold. */
|
|
333
|
+
declare function severityMeetsThreshold(severity: CompatChangeSeverity, threshold: CompatFailLevel): boolean;
|
|
334
|
+
//#endregion
|
|
167
335
|
//#region src/ir/sdk-behavior.d.ts
|
|
168
336
|
/**
|
|
169
337
|
* SDK Behavior IR — language-agnostic runtime policies for generated SDKs.
|
|
@@ -495,6 +663,16 @@ interface Model {
|
|
|
495
663
|
fields: Field[];
|
|
496
664
|
/** Generic type parameters. Empty/undefined for non-generic models. */
|
|
497
665
|
typeParams?: TypeParam[];
|
|
666
|
+
/**
|
|
667
|
+
* When set, this model is a discriminated union over allOf+oneOf variants.
|
|
668
|
+
* Emitters should generate a dispatcher (factory) instead of a regular dataclass.
|
|
669
|
+
* The `property` field is the discriminator key (e.g. "event"), and `mapping`
|
|
670
|
+
* maps each discriminator value to the concrete variant model name.
|
|
671
|
+
*/
|
|
672
|
+
discriminator?: {
|
|
673
|
+
property: string;
|
|
674
|
+
mapping: Record<string, string>;
|
|
675
|
+
};
|
|
498
676
|
}
|
|
499
677
|
interface Field {
|
|
500
678
|
name: string;
|
|
@@ -596,5 +774,5 @@ interface SuccessResponse {
|
|
|
596
774
|
type: TypeRef;
|
|
597
775
|
}
|
|
598
776
|
//#endregion
|
|
599
|
-
export {
|
|
600
|
-
//# sourceMappingURL=types-
|
|
777
|
+
export { BreakingChangeCategory as $, collectEnumRefs as A, CompatSourceKind as At, IdempotencyPolicy as B, CompatPolicyHints as Bt, Service as C, OverlayLookup as Ct, UnionType as D, CompatParameter as Dt, TypeRef as E, ViolationSeverity as Et, walkTypeRef as F, CompatVisibility as Ft, RetryPolicy as G, LoggingPolicy as H, mergePolicy as Ht, AiAgentEnvVar as I, LanguageId as It, TimeoutPolicy as J, SdkBehavior as K, BackoffStrategy as L, ParameterSensitivity as Lt, collectModelRefs as M, CompatSymbol as Mt, collectRequestBodyModels as N, CompatSymbolKind as Nt, assertNever as O, CompatPassingStyle as Ot, mapTypeRef as P, CompatTypeRef as Pt, AdditiveChangeCategory as Q, DeepPartial as R, apiSurfaceToSnapshot as Rt, ServerEntry as S, MethodOverlay as St, TypeParam as T, ViolationCategory as Tt, PaginationPolicy as U, LogEvent as V, getDefaultPolicy as Vt, RequestGuardPolicy as W, defaultSdkBehavior as X, UserAgentPolicy as Y, mergeSdkBehavior as Z, Parameter as _, ApiSurface as _t, EnumRef as a, CompatProvenance as at, PrimitiveType as b, Extractor as bt, Field as c, severityMeetsThreshold as ct, MapType as d, ApiEnum as dt, CompatApproval as et, Model as f, ApiField as ft, PaginationMeta as g, ApiProperty as gt, Operation as h, ApiParam as ht, Enum as i, CompatFailLevel as it, collectFieldDependencies as j, CompatStability as jt, assignModelsToServices as k, CompatSnapshot as kt, HttpMethod as l, Addition as lt, NullableType as m, ApiMethod as mt, ArrayType as n, CompatChangeSeverity as nt, EnumValue as o, SoftRiskChangeCategory as ot, ModelRef as p, ApiInterface as pt, TelemetryPolicy as q, AuthScheme as r, CompatConfig as rt, ErrorResponse as s, defaultSeverityForCategory as st, ApiSpec as t, CompatChangeCategory as tt, LiteralType as u, ApiClass as ut, ParameterGroup as v, ApiTypeAlias as vt, SuccessResponse as w, Violation as wt, SecurityRequirement as x, LanguageHints as xt, ParameterGroupVariant as y, DiffResult as yt, ErrorPolicy as z, ALL_LANGUAGE_IDS as zt };
|
|
778
|
+
//# sourceMappingURL=types-mTtkgy_h.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types-mTtkgy_h.d.mts","names":[],"sources":["../src/compat/policy.ts","../src/compat/ir.ts","../src/compat/types.ts","../src/compat/config.ts","../src/ir/sdk-behavior.ts","../src/ir/types.ts"],"mappings":"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"}
|
package/dist/verify/index.d.mts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Bt as CompatPolicyHints, _t as ApiSurface, t as ApiSpec, wt as Violation } from "../types-mTtkgy_h.mjs";
|
|
2
|
+
import { t as CompatDiffResult } from "../differ-CTl98yoS.mjs";
|
|
2
3
|
|
|
3
4
|
//#region src/verify/types.d.ts
|
|
4
5
|
interface VerifyDiagnostics {
|
|
@@ -30,7 +31,7 @@ interface VerifyDiagnostics {
|
|
|
30
31
|
}
|
|
31
32
|
interface CompatCheckResult {
|
|
32
33
|
passed: boolean;
|
|
33
|
-
diff:
|
|
34
|
+
diff: CompatDiffResult;
|
|
34
35
|
scopedToSpec: boolean;
|
|
35
36
|
scopedSymbolCount?: number;
|
|
36
37
|
}
|
|
@@ -52,7 +53,7 @@ interface StalenessCheckResult {
|
|
|
52
53
|
}
|
|
53
54
|
//#endregion
|
|
54
55
|
//#region src/verify/run-compat-check.d.ts
|
|
55
|
-
declare function runCompatCheck(baseline: ApiSurface, outputDir: string, lang: string, spec?: ApiSpec): Promise<CompatCheckResult>;
|
|
56
|
+
declare function runCompatCheck(baseline: ApiSurface, outputDir: string, lang: string, spec?: ApiSpec, policyOverrides?: Partial<CompatPolicyHints>): Promise<CompatCheckResult>;
|
|
56
57
|
//#endregion
|
|
57
58
|
//#region src/verify/run-overlay-retry-loop.d.ts
|
|
58
59
|
declare function runOverlayRetryLoop(opts: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../../src/verify/types.ts","../../src/verify/run-compat-check.ts","../../src/verify/run-overlay-retry-loop.ts","../../src/verify/run-staleness-check.ts","../../src/verify/run-smoke-check.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../../src/verify/types.ts","../../src/verify/run-compat-check.ts","../../src/verify/run-overlay-retry-loop.ts","../../src/verify/run-staleness-check.ts","../../src/verify/run-smoke-check.ts"],"mappings":";;;;UAGiB,iBAAA;EACf,WAAA;IACE,oBAAA;IACA,gBAAA;IACA,iBAAA;IACA,oBAAA,EAAsB,MAAA;IACtB,oBAAA,EAAsB,MAAA;IACtB,SAAA;IACA,YAAA;IACA,iBAAA;EAAA;EAEF,cAAA;IACE,gBAAA;IACA,YAAA;EAAA;EAEF,UAAA;IACE,MAAA;IACA,aAAA;IACA,aAAA;EAAA;EAEF,SAAA;IACE,QAAA;IACA,SAAA;IACA,UAAA;IACA,mBAAA;EAAA;AAAA;AAAA,UAIa,iBAAA;EACf,MAAA;EACA,IAAA,EAAM,gBAAA;EACN,YAAA;EACA,iBAAA;AAAA;AAAA,UAGe,kBAAA;EACf,MAAA;EACA,QAAA;EACA,mBAAA;EACA,YAAA,EAAc,iBAAA;AAAA;AAAA,UAGC,gBAAA;EACf,MAAA;EACA,aAAA;EACA,aAAA;EACA,YAAA;EACA,iBAAA;AAAA;AAAA,UAGe,oBAAA;EACf,UAAA,EAAY,SAAA;AAAA;;;iBCrCQ,cAAA,CACpB,QAAA,EAAU,UAAA,EACV,SAAA,UACA,IAAA,UACA,IAAA,GAAO,OAAA,EACP,eAAA,GAAkB,OAAA,CAAQ,iBAAA,IACzB,OAAA,CAAQ,iBAAA;;;iBCuEW,mBAAA,CAAoB,IAAA;EACxC,QAAA,EAAU,UAAA;EACV,UAAA,EAAY,OAAA;EACZ,SAAA;EACA,IAAA;EACA,UAAA;EACA,SAAA;EACA,OAAA,IAAW,aAAA,UAAuB,UAAA,UAAoB,cAAA;AAAA,IACpD,OAAA,CAAQ,kBAAA;;;iBChGI,iBAAA,CACd,QAAA,EAAU,UAAA,EACV,OAAA,EAAS,OAAA,EACT,OAAA,EAAS,OAAA,EACT,IAAA,WACC,oBAAA;;;iBCca,aAAA,CAAc,IAAA;EAC5B,IAAA;EACA,IAAA;EACA,MAAA;EACA,UAAA;EACA,WAAA;EACA,WAAA;AAAA,IACE,gBAAA"}
|
package/dist/verify/index.mjs
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { m as CommandError } from "../tree-sitter-C53w_0WE.mjs";
|
|
2
|
-
import { i as generate, n as getEmitter, t as diffSpecs } from "../diff-
|
|
3
|
-
import { c as
|
|
2
|
+
import { i as generate, n as getEmitter, t as diffSpecs } from "../diff-BaH9qa8k.mjs";
|
|
3
|
+
import { A as getDefaultPolicy, T as apiSurfaceToSnapshot, c as filterSurface, f as specDerivedMethodPaths, i as getExtractor, j as mergePolicy, l as specDerivedEnumValues, n as isPatchableChange, o as diffSnapshots, p as specDerivedNames, r as patchOverlay, t as buildOverlayLookup, u as specDerivedFieldPaths } from "../overlay-TYxHOCow.mjs";
|
|
4
4
|
import * as path$1 from "node:path";
|
|
5
5
|
import { fileURLToPath } from "node:url";
|
|
6
6
|
import { execFileSync } from "node:child_process";
|
|
7
7
|
import { closeSync, existsSync, openSync, readFileSync, readSync, readdirSync, statSync, unlinkSync } from "node:fs";
|
|
8
8
|
//#region src/verify/run-compat-check.ts
|
|
9
|
-
async function runCompatCheck(baseline, outputDir, lang, spec) {
|
|
9
|
+
async function runCompatCheck(baseline, outputDir, lang, spec, policyOverrides) {
|
|
10
10
|
const extractor = getExtractor(lang);
|
|
11
11
|
const candidate = await extractor.extract(outputDir);
|
|
12
12
|
let scopedBaseline = baseline;
|
|
@@ -21,9 +21,12 @@ async function runCompatCheck(baseline, outputDir, lang, spec) {
|
|
|
21
21
|
scopedToSpec = true;
|
|
22
22
|
scopedSymbolCount = Object.keys(scopedBaseline.interfaces).length + Object.keys(scopedBaseline.classes).length + Object.keys(scopedBaseline.typeAliases).length + Object.keys(scopedBaseline.enums).length;
|
|
23
23
|
}
|
|
24
|
-
const
|
|
24
|
+
const baseSnap = apiSurfaceToSnapshot(scopedBaseline);
|
|
25
|
+
const candSnap = apiSurfaceToSnapshot(candidate);
|
|
26
|
+
const langId = lang;
|
|
27
|
+
const diff = diffSnapshots(baseSnap, candSnap, policyOverrides ? mergePolicy(getDefaultPolicy(langId), policyOverrides) : getDefaultPolicy(langId));
|
|
25
28
|
return {
|
|
26
|
-
passed: diff.
|
|
29
|
+
passed: diff.changes.every((c) => c.severity !== "breaking"),
|
|
27
30
|
diff,
|
|
28
31
|
scopedToSpec,
|
|
29
32
|
scopedSymbolCount
|
|
@@ -31,7 +34,6 @@ async function runCompatCheck(baseline, outputDir, lang, spec) {
|
|
|
31
34
|
}
|
|
32
35
|
//#endregion
|
|
33
36
|
//#region src/verify/run-overlay-retry-loop.ts
|
|
34
|
-
const PATCHABLE_CATEGORIES = new Set(["public-api", "export-structure"]);
|
|
35
37
|
/** Generated file header markers used by various emitters. */
|
|
36
38
|
const GENERATED_MARKERS = [
|
|
37
39
|
"Code generated by oagen",
|
|
@@ -123,21 +125,21 @@ async function runOverlayRetryLoop(opts) {
|
|
|
123
125
|
patchedPerIteration,
|
|
124
126
|
compatResult
|
|
125
127
|
};
|
|
126
|
-
const patchable = compatResult.diff.
|
|
128
|
+
const patchable = compatResult.diff.changes.filter(isPatchableChange);
|
|
127
129
|
if (patchable.length === 0) return {
|
|
128
130
|
status: "no-patchable",
|
|
129
131
|
attempts: attempt,
|
|
130
132
|
patchedPerIteration,
|
|
131
133
|
compatResult
|
|
132
134
|
};
|
|
133
|
-
const
|
|
134
|
-
if (attempt > 0 &&
|
|
135
|
+
const currentBreaking = compatResult.diff.summary.breaking;
|
|
136
|
+
if (attempt > 0 && currentBreaking >= prevPreserved) return {
|
|
135
137
|
status: "stalled",
|
|
136
138
|
attempts: attempt,
|
|
137
139
|
patchedPerIteration,
|
|
138
140
|
compatResult
|
|
139
141
|
};
|
|
140
|
-
prevPreserved =
|
|
142
|
+
prevPreserved = currentBreaking;
|
|
141
143
|
patchedPerIteration.push(patchable.length);
|
|
142
144
|
onRetry?.(attempt + 1, maxRetries, patchable.length);
|
|
143
145
|
overlay = patchOverlay(overlay, patchable, baseline);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":["path","path"],"sources":["../../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"],"sourcesContent":["import { getExtractor } from '../compat/extractor-registry.js';\nimport {\n diffSurfaces,\n specDerivedNames,\n specDerivedFieldPaths,\n specDerivedMethodPaths,\n specDerivedEnumValues,\n filterSurface,\n} from '../compat/differ.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): 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 diff = diffSurfaces(scopedBaseline, candidate, extractor.hints);\n const passed = diff.violations.every((v) => v.severity !== 'breaking');\n\n return { passed, diff, scopedToSpec, scopedSymbolCount };\n}\n","import { existsSync, readFileSync, readdirSync, unlinkSync, statSync, openSync, readSync, closeSync } from 'node:fs';\nimport * as path from 'node:path';\nimport { buildOverlayLookup, patchOverlay } from '../compat/overlay.js';\nimport type { ManifestEntry } from '../compat/overlay.js';\nimport { getExtractor } from '../compat/extractor-registry.js';\nimport type { ApiSurface, ViolationCategory } 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';\n\nconst PATCHABLE_CATEGORIES: Set<ViolationCategory> = new Set(['public-api', 'export-structure']);\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\n/**\n * Load a smoke-manifest.json from the generated SDK directory and convert\n * it to ManifestEntry[] for the overlay builder.\n */\nfunction loadManifestFromDir(outputDir: string): ManifestEntry[] | undefined {\n const manifestPath = path.join(outputDir, 'smoke-manifest.json');\n if (!existsSync(manifestPath)) return undefined;\n try {\n const parsed = JSON.parse(readFileSync(manifestPath, 'utf-8'));\n if (Array.isArray(parsed)) return parsed as ManifestEntry[];\n if (typeof parsed === 'object' && parsed !== null) {\n return Object.entries(parsed).map(([httpKey, value]) => {\n const spaceIdx = httpKey.indexOf(' ');\n const httpMethod = httpKey.slice(0, spaceIdx);\n const httpPath = httpKey.slice(spaceIdx + 1);\n const v = value as { sdkMethod?: string; service?: string };\n return {\n operationId: '',\n sdkResourceProperty: v.service ?? '',\n sdkMethodName: v.sdkMethod ?? '',\n httpMethod,\n path: httpPath,\n pathParams: [],\n bodyFields: [],\n queryFields: [],\n };\n });\n }\n } catch {\n // ignore parse errors\n }\n return undefined;\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 = loadManifestFromDir(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.violations.filter((v) => PATCHABLE_CATEGORIES.has(v.category));\n if (patchable.length === 0) {\n return {\n status: 'no-patchable',\n attempts: attempt,\n patchedPerIteration,\n compatResult,\n };\n }\n\n const currentPreserved = compatResult.diff.preservedSymbols;\n if (attempt > 0 && currentPreserved <= prevPreserved) {\n return {\n status: 'stalled',\n attempts: attempt,\n patchedPerIteration,\n compatResult,\n };\n }\n prevPreserved = currentPreserved;\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"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":["path","path"],"sources":["../../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"],"sourcesContent":["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 { existsSync, readFileSync, readdirSync, unlinkSync, statSync, openSync, readSync, closeSync } from 'node:fs';\nimport * as path from 'node:path';\nimport { buildOverlayLookup, patchOverlay, isPatchableChange } from '../compat/overlay.js';\nimport type { ManifestEntry } 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';\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\n/**\n * Load a smoke-manifest.json from the generated SDK directory and convert\n * it to ManifestEntry[] for the overlay builder.\n */\nfunction loadManifestFromDir(outputDir: string): ManifestEntry[] | undefined {\n const manifestPath = path.join(outputDir, 'smoke-manifest.json');\n if (!existsSync(manifestPath)) return undefined;\n try {\n const parsed = JSON.parse(readFileSync(manifestPath, 'utf-8'));\n if (Array.isArray(parsed)) return parsed as ManifestEntry[];\n if (typeof parsed === 'object' && parsed !== null) {\n return Object.entries(parsed).map(([httpKey, value]) => {\n const spaceIdx = httpKey.indexOf(' ');\n const httpMethod = httpKey.slice(0, spaceIdx);\n const httpPath = httpKey.slice(spaceIdx + 1);\n const v = value as { sdkMethod?: string; service?: string };\n return {\n operationId: '',\n sdkResourceProperty: v.service ?? '',\n sdkMethodName: v.sdkMethod ?? '',\n httpMethod,\n path: httpPath,\n pathParams: [],\n bodyFields: [],\n queryFields: [],\n };\n });\n }\n } catch {\n // ignore parse errors\n }\n return undefined;\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 = loadManifestFromDir(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"],"mappings":"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"}
|