@workos/oagen 0.22.6 → 0.23.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/README.md +1 -1
- package/dist/cli/index.mjs +271 -42
- package/dist/cli/index.mjs.map +1 -1
- package/dist/compat/index.d.mts +2 -2
- package/dist/compat/index.mjs +9 -8
- package/dist/compat/index.mjs.map +1 -1
- package/dist/{diff-CQzcGuFJ.mjs → diff-B7dMUCoJ.mjs} +235 -27
- package/dist/diff-B7dMUCoJ.mjs.map +1 -0
- package/dist/{differ-CC65Efzt.d.mts → differ-DMmw0tbA.d.mts} +5 -5
- package/dist/{differ-CC65Efzt.d.mts.map → differ-DMmw0tbA.d.mts.map} +1 -1
- package/dist/index.d.mts +64 -9
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +26 -11
- package/dist/index.mjs.map +1 -1
- package/dist/{overlay-cb32jDBS.mjs → overlay-sQHQoN0I.mjs} +4 -4
- package/dist/overlay-sQHQoN0I.mjs.map +1 -0
- package/dist/scripts/smoke/baseline.mjs +25 -10
- package/dist/scripts/smoke/baseline.mjs.map +1 -1
- package/dist/scripts/smoke/sdk-test.mjs +3 -3
- package/dist/scripts/smoke/sdk-test.mjs.map +1 -1
- package/dist/smoke.d.mts +19 -4
- package/dist/smoke.d.mts.map +1 -1
- package/dist/smoke.mjs +25 -10
- package/dist/smoke.mjs.map +1 -1
- package/dist/tree-sitter-DcUvm0KA.mjs.map +1 -1
- package/dist/{types-Cjh39AGQ.d.mts → types-nM5Kp7UP.d.mts} +16 -9
- package/dist/types-nM5Kp7UP.d.mts.map +1 -0
- package/dist/verify/index.d.mts +2 -2
- package/dist/verify/index.mjs +2 -2
- package/docs/architecture/extractor-contract.md +2 -2
- package/docs/architecture/pipeline.md +2 -2
- package/docs/cli.md +19 -19
- package/docs/core/compatibility-policy.md +1 -1
- package/docs/core/manifest-schema.md +2 -2
- package/package.json +1 -1
- package/skills/generate-emitter/SKILL.md +2 -2
- package/skills/generate-emitter/references/common-pitfalls.md +1 -1
- package/skills/generate-emitter/references/project-scaffold.md +3 -3
- package/skills/generate-extractor/SKILL.md +2 -2
- package/skills/generate-smoke-test/SKILL.md +1 -1
- package/skills/verify-smoke-test/SKILL.md +1 -1
- package/dist/diff-CQzcGuFJ.mjs.map +0 -1
- package/dist/overlay-cb32jDBS.mjs.map +0 -1
- package/dist/types-Cjh39AGQ.d.mts.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tree-sitter-DcUvm0KA.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 /** Spec-level default value (the value of `default:` on the schema). Optional. */\n default?: string | number;\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 *\n * @param hints - Optional pin overrides keyed by IR model name → IR service\n * name. Applied after the natural assignment loop. Both names must exist in\n * the spec; unknown keys/values throw a config-style error so typos fail\n * loud at generation time.\n */\nexport function assignModelsToServices(\n models: Model[],\n services: Service[],\n hints?: Record<string, string>,\n): 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 if (hints) {\n const serviceNames = new Set(services.map((s) => s.name));\n for (const [modelName, serviceName] of Object.entries(hints)) {\n if (!modelNames.has(modelName)) {\n const err = new Error(\n `modelHints: unknown model \"${modelName}\". Hint keys must match an IR model name (post-cleanSchemaName/schemaNameTransform).`,\n );\n err.name = 'ConfigError';\n throw err;\n }\n if (!serviceNames.has(serviceName)) {\n const err = new Error(\n `modelHints: unknown service \"${serviceName}\" for model \"${modelName}\". Hint values must match an IR service name (PascalCase, derived from the operation's first tag).`,\n );\n err.name = 'ConfigError';\n throw err;\n }\n modelToService.set(modelName, serviceName);\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-DcUvm0KA.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 /**\n * Optional domain-facing name override. When set, emitters derive the\n * domain-side identifier (in their own casing) from this instead of `name`,\n * while serialization still uses `name` for the wire key. Lets an SDK expose\n * a wire field under a friendlier name (e.g. `connection_type` → `type`)\n * without changing the API contract. Set via the `fieldHints` config and\n * honored by any emitter that reads it.\n */\n domainName?: 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 /** Spec-level default value (the value of `default:` on the schema). Optional. */\n default?: string | number;\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 *\n * @param hints - Optional pin overrides keyed by IR model name → IR service\n * name. Applied after the natural assignment loop. Both names must exist in\n * the spec; unknown keys/values throw a config-style error so typos fail\n * loud at generation time.\n */\nexport function assignModelsToServices(\n models: Model[],\n services: Service[],\n hints?: Record<string, string>,\n): 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 if (hints) {\n const serviceNames = new Set(services.map((s) => s.name));\n for (const [modelName, serviceName] of Object.entries(hints)) {\n if (!modelNames.has(modelName)) {\n const err = new Error(\n `modelHints: unknown model \"${modelName}\". Hint keys must match an IR model name (post-cleanSchemaName/schemaNameTransform).`,\n );\n err.name = 'ConfigError';\n throw err;\n }\n if (!serviceNames.has(serviceName)) {\n const err = new Error(\n `modelHints: unknown service \"${serviceName}\" for model \"${modelName}\". Hint values must match an IR service name (PascalCase, derived from the operation's first tag).`,\n );\n err.name = 'ConfigError';\n throw err;\n }\n modelToService.set(modelName, serviceName);\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":";;;;;;;;;;;;;;AA6PA,SAAgB,YAAY,GAAiB;CAE3C,MAAM,OAAQ,EAAc;CAC5B,MAAM,sBAAM,IAAI,MACd,4BAA4B,KAAK,oGAClC;AACD,KAAI,OAAO;AACX,OAAM;;;;;;;;AASR,SAAgB,YACd,KACA,SAMM;AACN,SAAQ,IAAI,MAAZ;EACE,KAAK;AACH,WAAQ,QAAQ,IAAI;AACpB;EACF,KAAK;AACH,WAAQ,OAAO,IAAI;AACnB;EACF,KAAK;AACH,eAAY,IAAI,OAAO,QAAQ;AAC/B;EACF,KAAK;AACH,eAAY,IAAI,OAAO,QAAQ;AAC/B;EACF,KAAK;AACH,QAAK,MAAM,KAAK,IAAI,SAAU,aAAY,GAAG,QAAQ;AACrD;EACF,KAAK;AACH,OAAI,IAAI,QAAS,aAAY,IAAI,SAAS,QAAQ;AAClD,eAAY,IAAI,WAAW,QAAQ;AACnC;EACF,KAAK;AACH,WAAQ,UAAU,IAAI;AACtB;EACF,KAAK;AACH,WAAQ,YAAY,IAAI;AACxB;EACF,QACE,aAAY,IAAI;;;;;;;;;AAUtB,SAAgB,WACd,KACA,QAUG;AACH,SAAQ,IAAI,MAAZ;EACE,KAAK,YACH,QAAO,OAAO,UAAU,IAAI;EAC9B,KAAK,QACH,QAAO,OAAO,MAAM,KAAK,WAAW,IAAI,OAAO,OAAO,CAAC;EACzD,KAAK,QACH,QAAO,OAAO,MAAM,IAAI;EAC1B,KAAK,OACH,QAAO,OAAO,KAAK,IAAI;EACzB,KAAK,QACH,QAAO,OAAO,MACZ,KACA,IAAI,SAAS,KAAK,MAAM,WAAW,GAAG,OAAO,CAAC,CAC/C;EACH,KAAK,WACH,QAAO,OAAO,SAAS,KAAK,WAAW,IAAI,OAAO,OAAO,CAAC;EAC5D,KAAK,UACH,QAAO,OAAO,QAAQ,IAAI;EAC5B,KAAK,MACH,QAAO,OAAO,IACZ,KACA,WAAW,IAAI,WAAW,OAAO,EACjC,IAAI,UAAU,WAAW,IAAI,SAAS,OAAO,GAAG,KAAA,EACjD;EACH,QACE,QAAO,YAAY,IAAI;;;;;;AAS7B,SAAgB,iBAAiB,KAAwB;CACvD,MAAM,QAAkB,EAAE;AAC1B,aAAY,KAAK,EAAE,QAAQ,MAAM,MAAM,KAAK,EAAE,KAAK,EAAE,CAAC;AACtD,QAAO;;;;;AAMT,SAAgB,gBAAgB,KAAwB;CACtD,MAAM,QAAkB,EAAE;AAC1B,aAAY,KAAK,EAAE,OAAO,MAAM,MAAM,KAAK,EAAE,KAAK,EAAE,CAAC;AACrD,QAAO;;;;;;AAOT,SAAgB,yBAAyB,OAGvC;CACA,MAAM,yBAAS,IAAI,KAAa;CAChC,MAAM,wBAAQ,IAAI,KAAa;AAE/B,MAAK,MAAM,SAAS,MAAM,QAAQ;AAChC,OAAK,MAAM,QAAQ,iBAAiB,MAAM,KAAK,CAC7C,KAAI,SAAS,MAAM,KAAM,QAAO,IAAI,KAAK;AAE3C,OAAK,MAAM,QAAQ,gBAAgB,MAAM,KAAK,CAC5C,OAAM,IAAI,KAAK;;AAInB,QAAO;EAAE;EAAQ;EAAO;;;;;;;;;;;;AAa1B,SAAgB,uBACd,QACA,UACA,OACqB;CACrB,MAAM,iCAAiB,IAAI,KAAqB;CAChD,MAAM,aAAa,IAAI,IAAI,OAAO,KAAK,MAAM,EAAE,KAAK,CAAC;AAErD,MAAK,MAAM,WAAW,UAAU;EAC9B,MAAM,mCAAmB,IAAI,KAAa;AAE1C,OAAK,MAAM,MAAM,QAAQ,YAAY;AACnC,OAAI,GAAG,YACL,MAAK,MAAM,QAAQ,iBAAiB,GAAG,YAAY,CACjD,kBAAiB,IAAI,KAAK;AAG9B,QAAK,MAAM,QAAQ,iBAAiB,GAAG,SAAS,CAC9C,kBAAiB,IAAI,KAAK;AAE5B,QAAK,MAAM,SAAS;IAAC,GAAG,GAAG;IAAY,GAAG,GAAG;IAAa,GAAG,GAAG;IAAc,GAAI,GAAG,gBAAgB,EAAE;IAAE,CACvG,MAAK,MAAM,QAAQ,iBAAiB,MAAM,KAAK,CAC7C,kBAAiB,IAAI,KAAK;AAG9B,OAAI,GAAG,WACL,MAAK,MAAM,QAAQ,iBAAiB,GAAG,WAAW,SAAS,CACzD,kBAAiB,IAAI,KAAK;;EAMhC,MAAM,UAAU,CAAC,GAAG,iBAAiB;AACrC,SAAO,QAAQ,SAAS,GAAG;GACzB,MAAM,OAAO,QAAQ,KAAK;GAC1B,MAAM,QAAQ,OAAO,MAAM,MAAM,EAAE,SAAS,KAAK;AACjD,OAAI,CAAC,MAAO;AACZ,QAAK,MAAM,SAAS,MAAM,OACxB,MAAK,MAAM,OAAO,iBAAiB,MAAM,KAAK,CAC5C,KAAI,CAAC,iBAAiB,IAAI,IAAI,IAAI,WAAW,IAAI,IAAI,EAAE;AACrD,qBAAiB,IAAI,IAAI;AACzB,YAAQ,KAAK,IAAI;;;AAMzB,OAAK,MAAM,QAAQ,iBACjB,KAAI,CAAC,eAAe,IAAI,KAAK,CAC3B,gBAAe,IAAI,MAAM,QAAQ,KAAK;;AAK5C,KAAI,OAAO;EACT,MAAM,eAAe,IAAI,IAAI,SAAS,KAAK,MAAM,EAAE,KAAK,CAAC;AACzD,OAAK,MAAM,CAAC,WAAW,gBAAgB,OAAO,QAAQ,MAAM,EAAE;AAC5D,OAAI,CAAC,WAAW,IAAI,UAAU,EAAE;IAC9B,MAAM,sBAAM,IAAI,MACd,8BAA8B,UAAU,sFACzC;AACD,QAAI,OAAO;AACX,UAAM;;AAER,OAAI,CAAC,aAAa,IAAI,YAAY,EAAE;IAClC,MAAM,sBAAM,IAAI,MACd,gCAAgC,YAAY,eAAe,UAAU,oGACtE;AACD,QAAI,OAAO;AACX,UAAM;;AAER,kBAAe,IAAI,WAAW,YAAY;;;AAI9C,QAAO;;;;;AAMT,SAAgB,yBAAyB,UAAkC;CACzE,MAAM,yBAAS,IAAI,KAAa;AAChC,MAAK,MAAM,WAAW,SACpB,MAAK,MAAM,MAAM,QAAQ,WACvB,KAAI,GAAG,YACL,MAAK,MAAM,QAAQ,iBAAiB,GAAG,YAAY,CACjD,QAAO,IAAI,KAAK;AAKxB,QAAO;;;;;;;;;;;AC/eT,IAAa,aAAb,cAAgC,MAAM;CACpC;CAEA,YAAY,SAAiB,MAAc;EACzC,MAAM,cAAc,OAAO,GAAG,QAAQ,UAAU,SAAS;AACzD,QAAM,YAAY;AAClB,OAAK,OAAO;AACZ,OAAK,OAAO;;;;AAKhB,IAAa,eAAb,cAAkC,WAAW;CAC3C;CAEA,YAAY,SAAiB,MAAc,UAAkB;AAC3D,QAAM,SAAS,KAAK;AACpB,OAAK,OAAO;AACZ,OAAK,WAAW;;;;AAKpB,IAAa,iBAAb,cAAoC,WAAW;CAC7C,YAAY,SAAiB,MAAc;AACzC,QAAM,SAAS,KAAK;AACpB,OAAK,OAAO;;;;AAKhB,IAAa,cAAb,cAAiC,WAAW;CAC1C,YAAY,SAAiB,MAAc;AACzC,QAAM,SAAS,KAAK;AACpB,OAAK,OAAO;;;;AAKhB,IAAa,kBAAb,cAAqC,YAAY;CAC/C,YAAY,SAAiB,MAAc;AACzC,QAAM,SAAS,KAAK;AACpB,OAAK,OAAO;;;;AAKhB,IAAa,6BAAb,cAAgD,YAAY;CAC1D,YAAY,SAAiB,MAAc;AACzC,QAAM,SAAS,KAAK;AACpB,OAAK,OAAO;;;;AAKhB,IAAa,iBAAb,cAAoC,WAAW;CAC7C,YAAY,SAAiB,MAAc;AACzC,QAAM,SAAS,KAAK;AACpB,OAAK,OAAO;;;;AAKhB,IAAa,gBAAb,cAAmC,WAAW;CAC5C,YAAY,SAAiB,MAAc;AACzC,QAAM,SAAS,KAAK;AACpB,OAAK,OAAO;;;;AAKhB,IAAa,gBAAb,cAAmC,WAAW;CAC5C,YAAY,SAAiB,MAAc;AACzC,QAAM,SAAS,KAAK;AACpB,OAAK,OAAO;;;;;;;;;;AC7EhB,MAAM,iBAAuC,CAC3C,CAAC;CAAC;CAAK;CAAK;CAAI,EAAE,MAAM,EACxB,CAAC,CAAC,KAAK,OAAO,EAAE,QAAQ,CACzB;;;;AAKD,SAAS,mBAAmB,OAA2B;CACrD,MAAM,SAAmB,EAAE;CAC3B,IAAI,IAAI;AACR,QAAO,IAAI,MAAM,QAAQ;EACvB,IAAI,UAAU;AACd,OAAK,MAAM,CAAC,SAAS,cAAc,eACjC,KAAI,IAAI,QAAQ,UAAU,MAAM;OACd,QAAQ,OAAO,GAAG,MAAM,MAAM,IAAI,GAAG,aAAa,KAAK,EAAE,EAC5D;AACX,WAAO,KAAK,UAAU;AACtB,SAAK,QAAQ;AACb,cAAU;AACV;;;AAIN,MAAI,CAAC,SAAS;AACZ,UAAO,KAAK,MAAM,GAAG;AACrB;;;AAGJ,QAAO;;;;;;;;;;AAWT,SAAgB,WAAW,GAAqB;AAC9C,KAAI,CAAC,EAAG,QAAO,EAAE;AAWjB,QAAO,mBATO,EACX,QAAQ,uBAAuB,IAAI,CACnC,QAAQ,mBAAmB,SAAS,CACpC,QAAQ,yBAAyB,SAAS,CAC1C,QAAQ,mBAAmB,SAAS,CACpC,QAAQ,mBAAmB,SAAS,CACpC,MAAM,cAAc,CACpB,QAAQ,MAAM,EAAE,SAAS,EAAE,CAEE;;AAGlC,MAAa,cAAc,IAAI,IAAI;CAAC;CAAO;CAAO;CAAQ;CAAQ;CAAO;CAAQ;CAAM,CAAC;AAExF,SAAgB,aAAa,GAAW,UAAgC;CACtE,MAAM,SAAS,WAAW,IAAI,IAAI,CAAC,GAAG,aAAa,GAAG,SAAS,CAAC,GAAG;AACnE,QAAO,WAAW,EAAE,CACjB,KAAK,MAAM;EACV,MAAM,QAAQ,EAAE,aAAa;AAC7B,MAAI,OAAO,IAAI,MAAM,CAAE,QAAO;AAE9B,MAAI,UAAU,QAAS,QAAO;AAC9B,SAAO,EAAE,OAAO,EAAE,CAAC,aAAa,GAAG,EAAE,MAAM,EAAE,CAAC,aAAa;GAC3D,CACD,KAAK,GAAG;;AAGb,SAAgB,YAAY,GAAW,UAAgC;CACrE,MAAM,SAAS,WAAW,IAAI,IAAI,CAAC,GAAG,aAAa,GAAG,SAAS,CAAC,GAAG;CACnE,MAAM,QAAQ,WAAW,EAAE;AAC3B,KAAI,MAAM,WAAW,EAAG,QAAO;AAC/B,QAAO,MACJ,KAAK,GAAG,MAAM;AACb,MAAI,MAAM,EAAG,QAAO,EAAE,aAAa;EACnC,MAAM,QAAQ,EAAE,aAAa;AAC7B,MAAI,OAAO,IAAI,MAAM,CAAE,QAAO;AAC9B,MAAI,UAAU,QAAS,QAAO;AAC9B,SAAO,EAAE,OAAO,EAAE,CAAC,aAAa,GAAG,EAAE,MAAM,EAAE,CAAC,aAAa;GAC3D,CACD,KAAK,GAAG;;AAGb,SAAgB,YAAY,GAAmB;AAC7C,QAAO,WAAW,EAAE,CACjB,KAAK,MAAM,EAAE,aAAa,CAAC,CAC3B,KAAK,IAAI;;AAGd,SAAgB,YAAY,GAAmB;AAC7C,QAAO,WAAW,EAAE,CACjB,KAAK,MAAM,EAAE,aAAa,CAAC,CAC3B,KAAK,IAAI;;AAGd,SAAgB,iBAAiB,GAAmB;AAClD,QAAO,WAAW,EAAE,CACjB,KAAK,MAAM,EAAE,aAAa,CAAC,CAC3B,KAAK,IAAI;;AAGd,MAAM,mBAAmB,CAAC,aAAa;AAEvC,SAAgB,qBAAqB,MAAsB;AACzD,MAAK,MAAM,UAAU,iBACnB,KAAI,KAAK,SAAS,OAAO,IAAI,KAAK,SAAS,OAAO,OAChD,QAAO,KAAK,MAAM,GAAG,CAAC,OAAO,OAAO;AAGxC,QAAO;;AAGT,SAAgB,qBAAqB,MAAsB;AACzD,QAAO,KAAK,QAAQ,aAAa,GAAG,CAAC,QAAQ,eAAe,GAAG;;;;;;AAOjE,SAAgB,qBAAqB,MAAsB;AACzD,QAAO,KACJ,QAAQ,aAAa,GAAG,CACxB,QAAQ,iBAAiB,GAAG,CAC5B,QAAQ,iBAAiB,GAAG,CAC5B,QAAQ,gBAAgB,GAAG;;;AAIhC,MAAM,qBAAqB,IAAI,IAAI;CACjC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD,CAAC;;;;;;;;AASF,SAAgB,YAAY,MAAsB;AAChD,KAAI,mBAAmB,IAAI,KAAK,CAAE,QAAO;AACzC,KAAI,KAAK,SAAS,MAAM,IAAI,KAAK,SAAS,EACxC,QAAO,KAAK,MAAM,GAAG,GAAG,GAAG;AAE7B,KAAI,KAAK,SAAS,MAAM,IAAI,KAAK,SAAS,EAExC,QAAO,KAAK,MAAM,GAAG,GAAG;AAE1B,KAAI,KAAK,SAAS,IAAI,IAAI,CAAC,KAAK,SAAS,KAAK,IAAI,KAAK,SAAS,EAC9D,QAAO,KAAK,MAAM,GAAG,GAAG;AAE1B,QAAO;;;;;;;;;;;;AAaT,SAAgB,qBAAqB,MAAsB;AACzD,QAAO,KAAK,QAAQ,eAAe,KAAK;;AAG1C,SAAgB,gBAAgB,MAAsB;CACpD,IAAI,SAAS,qBAAqB,qBAAqB,KAAK,CAAC;AAC7D,UAAS,qBAAqB,OAAO;CAGrC,MAAM,QAAQ,OAAO,MAAM,iBAAiB;AAC5C,KAAI,OAAO;EACT,MAAM,WAAW,MAAM;EACvB,MAAM,WAAW,YAAY,SAAS;AACtC,MAAI,aAAa,SACf,UAAS,WAAW,OAAO,MAAM,SAAS,OAAO;;AAIrD,QAAO;;;;AC9LT,MAAM,gBAAgB;AAEtB,SAAgB,UAAU,QAAgB,QAA6B;AACrE,KAAI,OAAO,SAAS,cAClB,QAAO,OAAO,MAAM,OAAO;AAE7B,QAAO,OAAO,OAAO,WAAmB,OAAO,MAAM,QAAQ,SAAS,cAAc,CAAC"}
|
|
@@ -290,7 +290,7 @@ type CompatProvenance = 'spec_shape_change' | 'spec_ordering_change' | 'emitter_
|
|
|
290
290
|
type CompatFailLevel = 'none' | 'breaking' | 'soft-risk';
|
|
291
291
|
/** A single intentional-break approval in `oagen.config.ts`. */
|
|
292
292
|
interface CompatApproval {
|
|
293
|
-
/** Fully-qualified symbol (e.g., "
|
|
293
|
+
/** Fully-qualified symbol (e.g., "Acme\\Service\\Users::createUser"). */
|
|
294
294
|
symbol: string;
|
|
295
295
|
/** The kind of change being approved. */
|
|
296
296
|
category: CompatChangeCategory;
|
|
@@ -380,8 +380,7 @@ interface ErrorPolicy {
|
|
|
380
380
|
serverErrorKind: string;
|
|
381
381
|
/** Catch-all error kind for unrecognized status codes. */
|
|
382
382
|
clientErrorKind: string;
|
|
383
|
-
/** URL template for error documentation. Use {code} as placeholder for the API error code.
|
|
384
|
-
* Example: 'https://workos.com/docs/errors/{code}' */
|
|
383
|
+
/** URL template for error documentation. Use {code} as placeholder for the API error code. */
|
|
385
384
|
errorDocUrlTemplate?: string;
|
|
386
385
|
}
|
|
387
386
|
/** Telemetry — what request metrics to track and send. */
|
|
@@ -419,7 +418,7 @@ interface UserAgentPolicy {
|
|
|
419
418
|
/** Template for the SDK identifier string.
|
|
420
419
|
* Placeholders: {name} = spec name, {lang} = emitter language, {version} = SDK version.
|
|
421
420
|
* Each emitter interpolates with its own language string and casing conventions.
|
|
422
|
-
* Example: '{name} {lang}/{version}' → '
|
|
421
|
+
* Example: '{name} {lang}/{version}' → 'Acme PHP/4.32.0' */
|
|
423
422
|
sdkIdentifierTemplate: string;
|
|
424
423
|
/** Whether to append the runtime/language version (e.g. PHP 8.2, Python 3.12). */
|
|
425
424
|
includeRuntimeVersion: boolean;
|
|
@@ -445,7 +444,7 @@ interface RequestGuardPolicy {
|
|
|
445
444
|
interface TimeoutPolicy {
|
|
446
445
|
/** Default HTTP request timeout in seconds. */
|
|
447
446
|
defaultTimeoutSeconds: number;
|
|
448
|
-
/** Environment variable name to override the timeout (e.g. '
|
|
447
|
+
/** Environment variable name to override the timeout (e.g. 'SDK_REQUEST_TIMEOUT'). */
|
|
449
448
|
timeoutEnvVar?: string;
|
|
450
449
|
}
|
|
451
450
|
/** Language-agnostic runtime policies for generated SDKs.
|
|
@@ -462,9 +461,8 @@ interface SdkBehavior {
|
|
|
462
461
|
timeout: TimeoutPolicy;
|
|
463
462
|
}
|
|
464
463
|
/**
|
|
465
|
-
* Canonical SDK behavior defaults.
|
|
466
|
-
*
|
|
467
|
-
* via `mergeSdkBehavior()` in each SDK's `oagen.config.ts`.
|
|
464
|
+
* Canonical SDK behavior defaults. Per-language or per-project overrides can
|
|
465
|
+
* be applied via `mergeSdkBehavior()` in each SDK's `oagen.config.ts`.
|
|
468
466
|
*
|
|
469
467
|
* - Retry: exponential backoff with jitter, retries on 429/5xx
|
|
470
468
|
* - Errors: standard HTTP status → exception kind mapping
|
|
@@ -678,6 +676,15 @@ interface Model {
|
|
|
678
676
|
}
|
|
679
677
|
interface Field {
|
|
680
678
|
name: string;
|
|
679
|
+
/**
|
|
680
|
+
* Optional domain-facing name override. When set, emitters derive the
|
|
681
|
+
* domain-side identifier (in their own casing) from this instead of `name`,
|
|
682
|
+
* while serialization still uses `name` for the wire key. Lets an SDK expose
|
|
683
|
+
* a wire field under a friendlier name (e.g. `connection_type` → `type`)
|
|
684
|
+
* without changing the API contract. Set via the `fieldHints` config and
|
|
685
|
+
* honored by any emitter that reads it.
|
|
686
|
+
*/
|
|
687
|
+
domainName?: string;
|
|
681
688
|
type: TypeRef;
|
|
682
689
|
required: boolean;
|
|
683
690
|
description?: string;
|
|
@@ -784,4 +791,4 @@ interface SuccessResponse {
|
|
|
784
791
|
}
|
|
785
792
|
//#endregion
|
|
786
793
|
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 };
|
|
787
|
-
//# sourceMappingURL=types-
|
|
794
|
+
//# sourceMappingURL=types-nM5Kp7UP.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types-nM5Kp7UP.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,5 +1,5 @@
|
|
|
1
|
-
import { Bt as CompatPolicyHints, _t as ApiSurface, t as ApiSpec, wt as Violation } from "../types-
|
|
2
|
-
import { t as CompatDiffResult } from "../differ-
|
|
1
|
+
import { Bt as CompatPolicyHints, _t as ApiSurface, t as ApiSpec, wt as Violation } from "../types-nM5Kp7UP.mjs";
|
|
2
|
+
import { t as CompatDiffResult } from "../differ-DMmw0tbA.mjs";
|
|
3
3
|
|
|
4
4
|
//#region src/verify/types.d.ts
|
|
5
5
|
interface VerifyDiagnostics {
|
package/dist/verify/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { m as CommandError } from "../tree-sitter-DcUvm0KA.mjs";
|
|
2
|
-
import { a as MANIFEST_FILENAME, i as generate, n as getEmitter, t as diffSpecs } from "../diff-
|
|
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-
|
|
2
|
+
import { a as MANIFEST_FILENAME, i as generate, n as getEmitter, t as diffSpecs } from "../diff-B7dMUCoJ.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-sQHQoN0I.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";
|
|
@@ -99,11 +99,11 @@ Extractors are registered via `oagen.config.ts` in the consumer project. The CLI
|
|
|
99
99
|
|
|
100
100
|
```typescript
|
|
101
101
|
// oagen.config.ts (consumer project)
|
|
102
|
-
import {
|
|
102
|
+
import { acmeEmittersPlugin } from "@acme/oagen-emitters";
|
|
103
103
|
import type { OagenConfig } from "@workos/oagen";
|
|
104
104
|
|
|
105
105
|
const config: OagenConfig = {
|
|
106
|
-
...
|
|
106
|
+
...acmeEmittersPlugin, // includes all extractors
|
|
107
107
|
// spec interpretation policy...
|
|
108
108
|
};
|
|
109
109
|
export default config;
|
|
@@ -97,10 +97,10 @@ Simple map from language name → `Emitter` instance. Emitters are registered at
|
|
|
97
97
|
|
|
98
98
|
```typescript
|
|
99
99
|
// In oagen.config.ts (consumer project)
|
|
100
|
-
import {
|
|
100
|
+
import { acmeEmittersPlugin } from "@acme/oagen-emitters";
|
|
101
101
|
|
|
102
102
|
export default {
|
|
103
|
-
...
|
|
103
|
+
...acmeEmittersPlugin,
|
|
104
104
|
// spec interpretation policy...
|
|
105
105
|
};
|
|
106
106
|
```
|
package/docs/cli.md
CHANGED
|
@@ -7,19 +7,19 @@ All commands support `--help` for full usage details.
|
|
|
7
7
|
Generate SDK code from an OpenAPI spec.
|
|
8
8
|
|
|
9
9
|
```bash
|
|
10
|
-
oagen generate --spec openapi.yml --lang node --output ./sdk --namespace
|
|
10
|
+
oagen generate --spec openapi.yml --lang node --output ./sdk --namespace Acme
|
|
11
11
|
```
|
|
12
12
|
|
|
13
|
-
| Argument | Required | Default | Description
|
|
14
|
-
| ---------------------- | -------- | ----------------------- |
|
|
15
|
-
| `--spec <path>` | No | `OPENAPI_SPEC_PATH` env | Path to an OpenAPI 3.x spec file.
|
|
16
|
-
| `--lang <language>` | Yes | | Target language — must have a registered emitter (via `oagen.config.ts`)
|
|
17
|
-
| `--output <dir>` | Yes | | Directory to write generated files into
|
|
18
|
-
| `--namespace <name>` | No | Spec's `info.title` | SDK namespace in PascalCase — used directly for code identifiers (e.g., `
|
|
19
|
-
| `--dry-run` | No | `false` | Print the list of file paths that would be generated, without writing anything to disk
|
|
20
|
-
| `--api-surface <path>` | No | | Path to baseline API surface JSON for compat overlay
|
|
21
|
-
| `--target <dir>` | No | | Target directory for live SDK integration — generated files are merged into this directory instead of `--output`
|
|
22
|
-
| `--no-compat-check` | No | `false` | Skip compat overlay even if `--api-surface` is provided
|
|
13
|
+
| Argument | Required | Default | Description |
|
|
14
|
+
| ---------------------- | -------- | ----------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
15
|
+
| `--spec <path>` | No | `OPENAPI_SPEC_PATH` env | Path to an OpenAPI 3.x spec file. |
|
|
16
|
+
| `--lang <language>` | Yes | | Target language — must have a registered emitter (via `oagen.config.ts`) |
|
|
17
|
+
| `--output <dir>` | Yes | | Directory to write generated files into |
|
|
18
|
+
| `--namespace <name>` | No | Spec's `info.title` | SDK namespace in PascalCase — used directly for code identifiers (e.g., `Acme::Client`) and converted to `snake_case` for file paths (e.g., `lib/acme/`). Use PascalCase with the exact casing you want. |
|
|
19
|
+
| `--dry-run` | No | `false` | Print the list of file paths that would be generated, without writing anything to disk |
|
|
20
|
+
| `--api-surface <path>` | No | | Path to baseline API surface JSON for compat overlay |
|
|
21
|
+
| `--target <dir>` | No | | Target directory for live SDK integration — generated files are merged into this directory instead of `--output` |
|
|
22
|
+
| `--no-compat-check` | No | `false` | Skip compat overlay even if `--api-surface` is provided |
|
|
23
23
|
|
|
24
24
|
## `oagen diff`
|
|
25
25
|
|
|
@@ -244,11 +244,11 @@ The config file belongs to the **consumer project** (the project that owns spec
|
|
|
244
244
|
|
|
245
245
|
```ts
|
|
246
246
|
import type { OagenConfig } from "@workos/oagen";
|
|
247
|
-
import {
|
|
247
|
+
import { acmeEmittersPlugin } from "@acme/oagen-emitters";
|
|
248
248
|
|
|
249
249
|
const config: OagenConfig = {
|
|
250
|
-
...
|
|
251
|
-
docUrl: "https://
|
|
250
|
+
...acmeEmittersPlugin,
|
|
251
|
+
docUrl: "https://docs.example.com",
|
|
252
252
|
operationIdTransform: (id) => id.replace(/Controller_/, ""),
|
|
253
253
|
operationHints,
|
|
254
254
|
mountRules,
|
|
@@ -276,20 +276,20 @@ export default config;
|
|
|
276
276
|
|
|
277
277
|
```ts
|
|
278
278
|
import type { OagenConfig } from "@workos/oagen";
|
|
279
|
-
import {
|
|
279
|
+
import { acmeEmittersPlugin } from "@acme/oagen-emitters";
|
|
280
280
|
import { experimentalPlugin } from "@workos/oagen-experimental";
|
|
281
281
|
|
|
282
282
|
const config: OagenConfig = {
|
|
283
283
|
emitters: [
|
|
284
|
-
...(
|
|
284
|
+
...(acmeEmittersPlugin.emitters ?? []),
|
|
285
285
|
...(experimentalPlugin.emitters ?? []),
|
|
286
286
|
],
|
|
287
287
|
extractors: [
|
|
288
|
-
...(
|
|
288
|
+
...(acmeEmittersPlugin.extractors ?? []),
|
|
289
289
|
...(experimentalPlugin.extractors ?? []),
|
|
290
290
|
],
|
|
291
291
|
smokeRunners: {
|
|
292
|
-
...(
|
|
292
|
+
...(acmeEmittersPlugin.smokeRunners ?? {}),
|
|
293
293
|
...(experimentalPlugin.smokeRunners ?? {}),
|
|
294
294
|
},
|
|
295
295
|
operationHints,
|
|
@@ -310,7 +310,7 @@ export default config;
|
|
|
310
310
|
| `operationIdTransform` | `(id: string) => string` | Custom transform for operation IDs. Receives the raw `operationId` from the spec; return the desired operation name. No additional casing conversion is applied. When omitted, `operationId` values are converted to `camelCase`. |
|
|
311
311
|
| `schemaNameTransform` | `(name: string) => string` | Custom transform for schema (model/enum) names. Applied after the built-in `cleanSchemaName` normalization. Receives the cleaned PascalCase name; return the desired name. |
|
|
312
312
|
| `transformSpec` | `(spec: OpenApiDocument) => OpenApiDocument` | Pre-IR overlay applied to the bundled OpenAPI document before any IR extraction. Use to patch around upstream spec quirks that would otherwise emit a breaking SDK change. See [`transformSpec` — Pre-IR Spec Overlay](advanced/transform-spec.md). |
|
|
313
|
-
| `docUrl` | `string` | Base URL for documentation links. When set, relative markdown paths in descriptions (e.g. `[User](/reference/
|
|
313
|
+
| `docUrl` | `string` | Base URL for documentation links. When set, relative markdown paths in descriptions (e.g. `[User](/reference/users/user)`) are expanded to full URLs (e.g. `[User](https://docs.example.com/reference/users/user)`). |
|
|
314
314
|
| `operationHints` | `Record<string, OperationHint>` | Per-operation overrides keyed by `"METHOD /path"`. Override derived method names, remount to a different service, or split union-body operations into typed wrappers. See [Operation Resolution](architecture/ir-types.md#operation-resolution). |
|
|
315
315
|
| `mountRules` | `Record<string, string>` | Service-level remounting. Maps IR service name to target service/namespace (PascalCase). All operations in the source service are mounted on the target unless overridden per-operation in `operationHints`. |
|
|
316
316
|
| `modelHints` | `Record<string, string>` | Pin specific models to a specific IR service for placement. Maps IR model name (post-`cleanSchemaName`/`schemaNameTransform`) → IR service name (PascalCase). Overrides the default "first service to reference the model wins" assignment. Both names must exist in the parsed spec; unknown names throw at generation time. |
|
|
@@ -113,7 +113,7 @@ When `approved` is `false`, the matching engine skips the approval entirely. Whe
|
|
|
113
113
|
compat: {
|
|
114
114
|
allow: [
|
|
115
115
|
{
|
|
116
|
-
symbol: '
|
|
116
|
+
symbol: 'Acme\\Service\\Users::createUser',
|
|
117
117
|
category: 'parameter_removed',
|
|
118
118
|
match: { parameter: 'passwordHashType' },
|
|
119
119
|
appliesTo: ['php', 'python', 'kotlin', 'dotnet'],
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
{
|
|
15
15
|
"version": 2,
|
|
16
16
|
"language": "php",
|
|
17
|
-
"sdkName": "
|
|
17
|
+
"sdkName": "acme-php",
|
|
18
18
|
"generatedAt": "2026-04-18T22:02:14.077Z",
|
|
19
19
|
"specSha": "sha256:abc123...",
|
|
20
20
|
"specPath": "../openapi-spec/spec/open-api-spec.yaml",
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
| --------------------- | ---------- | -------- | -------------------------------------------------------------------- |
|
|
33
33
|
| `version` | `number` | yes | Manifest schema version (currently `2`) |
|
|
34
34
|
| `language` | `string` | yes | Emitter target language (e.g., `"php"`) |
|
|
35
|
-
| `sdkName` | `string` | no | Human-readable SDK identity (e.g., `"
|
|
35
|
+
| `sdkName` | `string` | no | Human-readable SDK identity (e.g., `"acme-php"`) |
|
|
36
36
|
| `generatedAt` | `string` | yes | ISO-8601 timestamp of the generation run |
|
|
37
37
|
| `specSha` | `string` | no | SHA-256 hash of the source OpenAPI spec |
|
|
38
38
|
| `specPath` | `string` | no | Path or reference to the source spec |
|
package/package.json
CHANGED
|
@@ -11,7 +11,7 @@ Scaffold a complete language emitter for oagen that translates the intermediate
|
|
|
11
11
|
|
|
12
12
|
oagen has a plugin architecture for code generation. Each target language is an **emitter** — a TypeScript module that implements the `Emitter` interface. An emitter receives parsed IR nodes (models, enums, services, etc.) and returns `GeneratedFile[]` — arrays of `{ path, content }` pairs. The engine orchestrator calls each emitter method, prepends a file header, and writes the results to disk.
|
|
13
13
|
|
|
14
|
-
Emitters live in **external projects** (not inside the oagen core repo). They import all oagen types from `@workos/oagen` and are exported through the emitter project's plugin bundle (e.g., `
|
|
14
|
+
Emitters live in **external projects** (not inside the oagen core repo). They import all oagen types from `@workos/oagen` and are exported through the emitter project's plugin bundle (e.g., `acmeEmittersPlugin`), which the consumer project's `oagen.config.ts` imports.
|
|
15
15
|
|
|
16
16
|
## Reference Docs
|
|
17
17
|
|
|
@@ -232,7 +232,7 @@ Add the emitter to the plugin bundle export (e.g., `src/plugin.ts`) and re-expor
|
|
|
232
232
|
```typescript
|
|
233
233
|
// src/plugin.ts
|
|
234
234
|
import { {language}Emitter } from './{language}/index.js';
|
|
235
|
-
export const
|
|
235
|
+
export const acmeEmittersPlugin = {
|
|
236
236
|
emitters: [/* existing, */ {language}Emitter],
|
|
237
237
|
// ...
|
|
238
238
|
};
|
|
@@ -20,4 +20,4 @@ Review this checklist before finalizing the emitter, and when debugging failures
|
|
|
20
20
|
|
|
21
21
|
9. **Wrong test framework** — If the existing SDK uses Jest, generate Jest tests. If it uses pytest, generate pytest tests. Never substitute a different framework because it seems "better."
|
|
22
22
|
|
|
23
|
-
10. **Acronym handling in naming** — `toPascalCase('
|
|
23
|
+
10. **Acronym handling in naming** — `toPascalCase('XMLAPI')` may produce `Xmlapi` instead of `XMLAPI`. If the SDK preserves acronym casing, create an `ensurePascal()` wrapper that only capitalizes the first letter without disturbing the rest.
|
|
@@ -138,7 +138,7 @@ The `sdk:*` scripts bake in `--lang` and `--output` so you only need to pass the
|
|
|
138
138
|
|
|
139
139
|
```bash
|
|
140
140
|
# Fresh generation
|
|
141
|
-
npm run sdk:generate -- --spec ../openapi.yaml --namespace
|
|
141
|
+
npm run sdk:generate -- --spec ../openapi.yaml --namespace acme
|
|
142
142
|
|
|
143
143
|
# Verify generated output
|
|
144
144
|
npm run sdk:verify -- --spec ../openapi.yaml
|
|
@@ -147,13 +147,13 @@ npm run sdk:verify -- --spec ../openapi.yaml
|
|
|
147
147
|
npm run sdk:extract -- --sdk-path ../path-to-live-sdk
|
|
148
148
|
|
|
149
149
|
# Generate with compat overlay (Scenario A)
|
|
150
|
-
npm run sdk:generate -- --spec ../openapi.yaml --namespace
|
|
150
|
+
npm run sdk:generate -- --spec ../openapi.yaml --namespace acme --api-surface ./sdk-{language}-surface.json
|
|
151
151
|
|
|
152
152
|
# Verify with compat check (Scenario A)
|
|
153
153
|
npm run sdk:verify -- --spec ../openapi.yaml --api-surface ./sdk-{language}-surface.json
|
|
154
154
|
|
|
155
155
|
# Integrate into live SDK (Scenario A)
|
|
156
|
-
npm run sdk:generate -- --spec ../openapi.yaml --namespace
|
|
156
|
+
npm run sdk:generate -- --spec ../openapi.yaml --namespace acme --api-surface ./sdk-{language}-surface.json --target ../path-to-live-sdk
|
|
157
157
|
```
|
|
158
158
|
|
|
159
159
|
The `--spec` flag can be replaced by setting `OPENAPI_SPEC_PATH` in the environment.
|
|
@@ -13,7 +13,7 @@ Scaffold a language extractor for oagen's compat verification system. An extract
|
|
|
13
13
|
Live SDK → Extractor → ApiSurface JSON → Differ ← Generated SDK → Violations
|
|
14
14
|
```
|
|
15
15
|
|
|
16
|
-
Each language needs its own extractor because public surface detection is language-specific (e.g., TypeScript exports vs. Ruby public methods vs. Python `__all__` vs. Go capitalized identifiers). An extractor implements the `Extractor` interface and is exported through the emitter project's plugin bundle (e.g., `
|
|
16
|
+
Each language needs its own extractor because public surface detection is language-specific (e.g., TypeScript exports vs. Ruby public methods vs. Python `__all__` vs. Go capitalized identifiers). An extractor implements the `Extractor` interface and is exported through the emitter project's plugin bundle (e.g., `acmeEmittersPlugin`), which the consumer project's `oagen.config.ts` imports.
|
|
17
17
|
|
|
18
18
|
## Reference Docs
|
|
19
19
|
|
|
@@ -120,7 +120,7 @@ Add the extractor to the plugin bundle export (e.g., `src/plugin.ts`) and re-exp
|
|
|
120
120
|
```typescript
|
|
121
121
|
// src/plugin.ts
|
|
122
122
|
import { {language}Extractor } from './compat/extractors/{language}.js';
|
|
123
|
-
export const
|
|
123
|
+
export const acmeEmittersPlugin = {
|
|
124
124
|
extractors: [/* existing, */ {language}Extractor],
|
|
125
125
|
// ...
|
|
126
126
|
};
|
|
@@ -119,7 +119,7 @@ Add the smoke runner path to the plugin bundle export (e.g., `src/plugin.ts`):
|
|
|
119
119
|
|
|
120
120
|
```typescript
|
|
121
121
|
// src/plugin.ts
|
|
122
|
-
export const
|
|
122
|
+
export const acmeEmittersPlugin = {
|
|
123
123
|
smokeRunners: {
|
|
124
124
|
// existing runners...
|
|
125
125
|
{language}: path.join(smokeDir, 'sdk-{language}.ts'),
|
|
@@ -42,7 +42,7 @@ Collect these values. Use arguments if provided, otherwise ask:
|
|
|
42
42
|
2. **`spec`** — path to the OpenAPI spec (e.g., `../openapi.yaml`)
|
|
43
43
|
3. **`output`** — path to the generated SDK output directory
|
|
44
44
|
4. **`project`** — path to the emitter project (often the parent of `output`)
|
|
45
|
-
5. **`namespace`** — SDK namespace/package name (e.g., `
|
|
45
|
+
5. **`namespace`** — SDK namespace/package name (e.g., `Acme`)
|
|
46
46
|
|
|
47
47
|
Optional (Scenario A only):
|
|
48
48
|
|