@workos/oagen-emitters 0.0.1 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/release-please.yml +9 -1
- package/.husky/commit-msg +0 -0
- package/.husky/pre-commit +1 -0
- package/.husky/pre-push +1 -0
- package/.oxfmtrc.json +8 -1
- package/.prettierignore +1 -0
- package/.release-please-manifest.json +3 -0
- package/.vscode/settings.json +3 -0
- package/CHANGELOG.md +61 -0
- package/README.md +2 -2
- package/dist/index.d.mts +7 -0
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +4070 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +14 -18
- package/release-please-config.json +11 -0
- package/smoke/sdk-dotnet.ts +17 -3
- package/smoke/sdk-elixir.ts +17 -3
- package/smoke/sdk-go.ts +21 -4
- package/smoke/sdk-kotlin.ts +23 -4
- package/smoke/sdk-node.ts +15 -3
- package/smoke/sdk-ruby.ts +17 -3
- package/smoke/sdk-rust.ts +16 -3
- package/src/node/client.ts +521 -206
- package/src/node/common.ts +74 -4
- package/src/node/config.ts +1 -0
- package/src/node/enums.ts +53 -9
- package/src/node/errors.ts +82 -3
- package/src/node/fixtures.ts +87 -16
- package/src/node/index.ts +66 -10
- package/src/node/manifest.ts +4 -2
- package/src/node/models.ts +251 -124
- package/src/node/naming.ts +107 -3
- package/src/node/resources.ts +1162 -108
- package/src/node/serializers.ts +512 -52
- package/src/node/tests.ts +650 -110
- package/src/node/type-map.ts +89 -11
- package/src/node/utils.ts +426 -113
- package/test/node/client.test.ts +1083 -20
- package/test/node/enums.test.ts +73 -4
- package/test/node/errors.test.ts +4 -21
- package/test/node/models.test.ts +499 -5
- package/test/node/naming.test.ts +14 -7
- package/test/node/resources.test.ts +1568 -9
- package/test/node/serializers.test.ts +241 -5
- package/tsconfig.json +2 -3
- package/{tsup.config.ts → tsdown.config.ts} +1 -1
- package/dist/index.d.ts +0 -5
- package/dist/index.js +0 -2158
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","names":["mapTypeRef","irMapTypeRef","mapTypeRef","mapTypeRef","tsMapTypeRef","assignModelsToServices","mapTypeRef","assignModelsToServices"],"sources":["../src/node/naming.ts","../src/node/type-map.ts","../src/node/utils.ts","../src/node/enums.ts","../src/node/models.ts","../src/node/serializers.ts","../src/node/fixtures.ts","../src/node/resources.ts","../src/node/client.ts","../src/node/errors.ts","../src/node/config.ts","../src/node/common.ts","../src/node/tests.ts","../src/node/manifest.ts","../src/node/index.ts"],"sourcesContent":["import type { Operation, Service, EmitterContext } from '@workos/oagen';\nimport { toPascalCase, toCamelCase, toKebabCase, toSnakeCase } from '@workos/oagen';\n\n/** PascalCase class/interface name. */\nexport function className(name: string): string {\n return toPascalCase(name);\n}\n\n/** kebab-case file name (without extension). */\nexport function fileName(name: string): string {\n return toKebabCase(name);\n}\n\n/** camelCase method name. */\nexport function methodName(name: string): string {\n return toCamelCase(name);\n}\n\n/** camelCase field name for domain interfaces. */\nexport function fieldName(name: string): string {\n return toCamelCase(name);\n}\n\n/** snake_case field name for wire/response interfaces. */\nexport function wireFieldName(name: string): string {\n return toSnakeCase(name);\n}\n\n/**\n * Wire/response interface name. Uses \"Wire\" suffix when the domain name\n * already ends in \"Response\" to avoid stuttering (e.g., FooResponseResponse).\n */\nexport function wireInterfaceName(domainName: string): string {\n return domainName.endsWith('Response') ? `${domainName}Wire` : `${domainName}Response`;\n}\n\n/** kebab-case service directory name. */\nexport function serviceDirName(name: string): string {\n return toKebabCase(name);\n}\n\n/** camelCase property name for service accessors on the client. */\nexport function servicePropertyName(name: string): string {\n return toCamelCase(name);\n}\n\n/**\n * Resolve the effective service name, using the overlay-resolved class name\n * when available. This ensures directory names, file names, and property names\n * all derive from the same resolved name (e.g., \"Mfa\" instead of \"MultiFactorAuth\").\n */\nexport function resolveServiceName(service: Service, ctx: EmitterContext): string {\n return resolveClassName(service, ctx);\n}\n\n/**\n * Build a map from IR service name → resolved service name.\n * Used to translate modelToService/enumToService map values to overlay-resolved\n * directory names when the code only has the IR service name string.\n */\nexport function buildServiceNameMap(services: Service[], ctx: EmitterContext): Map<string, string> {\n const map = new Map<string, string>();\n for (const service of services) {\n map.set(service.name, resolveServiceName(service, ctx));\n }\n return map;\n}\n\n/**\n * Explicit method name overrides for operations where the spec's operationId\n * does not match the desired SDK method name and the spec cannot be changed.\n * Key: \"HTTP_METHOD /path\", Value: camelCase method name.\n */\nconst METHOD_NAME_OVERRIDES: Record<string, string> = {\n 'POST /portal/generate_link': 'generatePortalLink',\n};\n\n/**\n * Explicit service directory overrides. Maps a resolved PascalCase service name\n * to a target directory (kebab-case). Use this when the spec's tag grouping\n * does not match the desired SDK directory layout and the spec cannot be changed.\n */\nconst SERVICE_DIR_OVERRIDES: Record<string, string> = {\n ApplicationClientSecrets: 'workos-connect',\n Applications: 'workos-connect',\n Connections: 'sso',\n Directories: 'directory-sync',\n DirectoryGroups: 'directory-sync',\n DirectoryUsers: 'directory-sync',\n FeatureFlagsTargets: 'feature-flags',\n MultiFactorAuth: 'mfa',\n MultiFactorAuthChallenges: 'mfa',\n OrganizationsApiKeys: 'organizations',\n WebhooksEndpoints: 'webhooks',\n UserManagementAuthentication: 'user-management',\n UserManagementCorsOrigins: 'user-management',\n UserManagementDataProviders: 'user-management',\n UserManagementInvitations: 'user-management',\n UserManagementJWTTemplate: 'user-management',\n UserManagementMagicAuth: 'user-management',\n UserManagementMultiFactorAuthentication: 'user-management',\n UserManagementOrganizationMembership: 'user-management',\n UserManagementRedirectUris: 'user-management',\n UserManagementSessionTokens: 'user-management',\n UserManagementUsers: 'user-management',\n UserManagementUsersAuthorizedApplications: 'user-management',\n WorkOSConnect: 'workos-connect',\n};\n\n/**\n * Maps a service (by PascalCase name) to the existing hand-written class that\n * already covers its endpoints. When a service appears here:\n * - `resolveClassName` returns the target class (so generated code merges in)\n * - `isServiceCoveredByExisting` returns true\n * - `hasMethodsAbsentFromBaseline` checks the target class for missing methods,\n * so new endpoints are added to the existing class rather than silently dropped\n */\nexport const SERVICE_COVERED_BY: Record<string, string> = {\n Connections: 'SSO',\n Directories: 'DirectorySync',\n DirectoryGroups: 'DirectorySync',\n DirectoryUsers: 'DirectorySync',\n FeatureFlagsTargets: 'FeatureFlags',\n MultiFactorAuth: 'Mfa',\n MultiFactorAuthChallenges: 'Mfa',\n OrganizationsApiKeys: 'Organizations',\n UserManagementAuthentication: 'UserManagement',\n UserManagementInvitations: 'UserManagement',\n UserManagementMagicAuth: 'UserManagement',\n UserManagementMultiFactorAuthentication: 'UserManagement',\n UserManagementOrganizationMembership: 'UserManagement',\n UserManagementUsers: 'UserManagement',\n};\n\n/**\n * Explicit class name overrides. Maps the default PascalCase service name\n * to the desired SDK class name when toPascalCase produces the wrong casing.\n */\nconst CLASS_NAME_OVERRIDES: Record<string, string> = {\n WorkosConnect: 'WorkOSConnect',\n};\n\n/**\n * Resolve the output directory for a service, checking overrides first.\n * Falls back to the standard kebab-case conversion.\n */\nexport function resolveServiceDir(resolvedServiceName: string): string {\n return SERVICE_DIR_OVERRIDES[resolvedServiceName] ?? serviceDirName(resolvedServiceName);\n}\n\n/** Resolve the SDK method name for an operation, checking overlay first. */\nexport function resolveMethodName(op: Operation, _service: Service, ctx: EmitterContext): string {\n const httpKey = `${op.httpMethod.toUpperCase()} ${op.path}`;\n const override = METHOD_NAME_OVERRIDES[httpKey];\n if (override) return override;\n const existing = ctx.overlayLookup?.methodByOperation?.get(httpKey);\n if (existing) {\n // Fix: when the path ends with a path parameter (single-resource operation)\n // and the overlay method name is plural, prefer the singular form.\n // E.g., getUsers → getUser when path is /user_management/users/{id}\n const isSingleResource = /\\/\\{[^}]+\\}$/.test(op.path);\n if (isSingleResource && existing.methodName.endsWith('s') && !existing.methodName.endsWith('ss')) {\n const singular = existing.methodName.slice(0, -1);\n // Only singularize if it looks like a typical pluralization (ends in 's')\n // and the spec-derived name agrees it should be singular\n const specDerived = toCamelCase(op.name);\n if (specDerived === singular || specDerived.endsWith(singular.slice(singular.length - 4))) {\n return singular;\n }\n }\n return existing.methodName;\n }\n return toCamelCase(op.name);\n}\n\n/** Resolve the SDK class name for a service, checking overlay for existing names. */\nexport function resolveClassName(service: Service, ctx: EmitterContext): string {\n // Explicit coverage: this service's endpoints belong to an existing class\n const coveredBy = SERVICE_COVERED_BY[toPascalCase(service.name)];\n if (coveredBy) return coveredBy;\n\n // Check overlay's methodByOperation for any operation in this service\n // to find the existing class name\n if (ctx.overlayLookup?.methodByOperation) {\n for (const op of service.operations) {\n const httpKey = `${op.httpMethod.toUpperCase()} ${op.path}`;\n const existing = ctx.overlayLookup.methodByOperation.get(httpKey);\n if (existing) return CLASS_NAME_OVERRIDES[existing.className] ?? existing.className;\n }\n }\n const defaultName = toPascalCase(service.name);\n return CLASS_NAME_OVERRIDES[defaultName] ?? defaultName;\n}\n\n/** Resolve the interface name for a model, checking overlay first. */\nexport function resolveInterfaceName(name: string, ctx: EmitterContext): string {\n const existing = ctx.overlayLookup?.interfaceByName?.get(name);\n if (existing) return existing;\n return toPascalCase(name);\n}\n","import type { TypeRef, PrimitiveType, UnionType } from '@workos/oagen';\nimport { mapTypeRef as irMapTypeRef } from '@workos/oagen';\nimport { wireInterfaceName } from './naming.js';\n\nexport interface MapTypeRefOpts {\n stringDates?: boolean;\n /** Map from model name → default type args (e.g., `'<Record<string, unknown>>'`).\n * When present, model refs for generic models get their defaults appended. */\n genericDefaults?: Map<string, string>;\n}\n\n/**\n * Map an IR TypeRef to a TypeScript domain type string.\n * Domain types use PascalCase model names (e.g., `Organization`).\n *\n * @param opts.stringDates - When true, map `date-time` to `string` instead of `Date`.\n * Use this when integrating into an existing SDK that represents timestamps as\n * ISO 8601 strings rather than Date objects.\n * @param opts.genericDefaults - When present, appends default type args to generic model refs.\n */\nexport function mapTypeRef(ref: TypeRef, opts?: MapTypeRefOpts): string {\n const primMapper = opts?.stringDates ? mapPrimitiveStringDates : mapPrimitive;\n const genericDefaults = opts?.genericDefaults;\n return irMapTypeRef<string>(ref, {\n primitive: primMapper,\n array: (_r, items) => `${parenthesizeUnion(items)}[]`,\n model: (r) => r.name + (genericDefaults?.get(r.name) ?? ''),\n enum: (r) => r.name,\n union: (r, variants) => joinUnionVariants(r, variants),\n nullable: (_r, inner) => `${inner} | null`,\n literal: (r) => (typeof r.value === 'string' ? `'${r.value}'` : String(r.value)),\n map: (_r, value) => `Record<string, ${value}>`,\n });\n}\n\n/**\n * Map an IR TypeRef to a TypeScript wire/response type string.\n * Model references get the `Response` suffix (e.g., `OrganizationResponse`).\n * Wire types use JSON-native types (string for date-time, number/string for int64).\n */\nexport function mapWireTypeRef(ref: TypeRef, opts?: { genericDefaults?: Map<string, string> }): string {\n const genericDefaults = opts?.genericDefaults;\n return irMapTypeRef<string>(ref, {\n primitive: mapWirePrimitive,\n array: (_r, items) => `${parenthesizeUnion(items)}[]`,\n model: (r) => wireInterfaceName(r.name) + (genericDefaults?.get(r.name) ?? ''),\n enum: (r) => r.name,\n union: (r, variants) => joinUnionVariants(r, variants),\n nullable: (_r, inner) => `${inner} | null`,\n literal: (r) => (typeof r.value === 'string' ? `'${r.value}'` : String(r.value)),\n map: (_r, value) => `Record<string, ${value}>`,\n });\n}\n\nfunction mapPrimitive(ref: PrimitiveType): string {\n if (ref.format) {\n switch (ref.format) {\n case 'date-time':\n return 'Date';\n case 'int64':\n return 'bigint';\n }\n }\n switch (ref.type) {\n case 'string':\n return 'string';\n case 'integer':\n case 'number':\n return 'number';\n case 'boolean':\n return 'boolean';\n case 'unknown':\n return 'any';\n }\n}\n\n/**\n * Map a primitive type using string representation for dates.\n * Used when the existing SDK represents timestamps as ISO 8601 strings.\n */\nfunction mapPrimitiveStringDates(ref: PrimitiveType): string {\n if (ref.format) {\n switch (ref.format) {\n case 'int64':\n return 'bigint';\n // date-time intentionally falls through to the string case\n }\n }\n switch (ref.type) {\n case 'string':\n return 'string';\n case 'integer':\n case 'number':\n return 'number';\n case 'boolean':\n return 'boolean';\n case 'unknown':\n return 'any';\n }\n}\n\n/**\n * Map an IR PrimitiveType to a TypeScript wire/JSON type string.\n * Wire types match JSON encoding: date-time stays string, int64 stays string/number.\n */\nfunction mapWirePrimitive(ref: PrimitiveType): string {\n switch (ref.type) {\n case 'string':\n return 'string';\n case 'integer':\n case 'number':\n return 'number';\n case 'boolean':\n return 'boolean';\n case 'unknown':\n return 'any';\n }\n}\n\n/**\n * Join union variant type strings using the appropriate operator.\n * allOf unions use `&` (intersection), oneOf/anyOf/unspecified use `|` (union).\n */\nfunction joinUnionVariants(ref: UnionType, variants: string[]): string {\n if (ref.compositionKind === 'allOf') {\n return variants.join(' & ');\n }\n return variants.join(' | ');\n}\n\n/** Wrap union/intersection types in parentheses when used as array item type. */\nfunction parenthesizeUnion(type: string): string {\n return type.includes(' | ') || type.includes(' & ') ? `(${type})` : type;\n}\n","import type { Model, EmitterContext, Service, Operation, Field } from '@workos/oagen';\nimport { toPascalCase } from '@workos/oagen';\nexport {\n collectModelRefs,\n collectEnumRefs,\n assignModelsToServices,\n collectFieldDependencies,\n collectRequestBodyModels,\n} from '@workos/oagen';\nimport { mapTypeRef } from './type-map.js';\nimport {\n resolveInterfaceName,\n fieldName,\n resolveServiceDir,\n resolveMethodName,\n buildServiceNameMap,\n SERVICE_COVERED_BY,\n} from './naming.js';\nimport { assignModelsToServices } from '@workos/oagen';\n\n/**\n * Compute a relative import path between two files within the generated SDK.\n * Strips .ts extension from the result.\n */\nexport function relativeImport(fromFile: string, toFile: string): string {\n const fromDir = fromFile.split('/').slice(0, -1);\n const toFileParts = toFile.split('/');\n const toDir = toFileParts.slice(0, -1);\n const toFileName = toFileParts[toFileParts.length - 1];\n\n let common = 0;\n while (common < fromDir.length && common < toDir.length && fromDir[common] === toDir[common]) {\n common++;\n }\n\n const ups = fromDir.length - common;\n const downs = toDir.slice(common);\n const parts = [...Array(ups).fill('..'), ...downs, toFileName];\n let result = parts.join('/');\n result = result.replace(/\\.ts$/, '');\n if (!result.startsWith('.')) result = './' + result;\n return result;\n}\n\n/**\n * Render a JSDoc comment block from a description string.\n * Handles multiline descriptions by prefixing each line with ` * `.\n * Returns the lines with the given indent (default 0 spaces).\n */\nexport function docComment(description: string, indent = 0): string[] {\n const pad = ' '.repeat(indent);\n const descLines = description.split('\\n');\n if (descLines.length === 1) {\n return [`${pad}/** ${descLines[0]} */`];\n }\n const lines: string[] = [`${pad}/**`];\n for (const line of descLines) {\n lines.push(line === '' ? `${pad} *` : `${pad} * ${line}`);\n }\n lines.push(`${pad} */`);\n return lines;\n}\n\n/**\n * Build a map from model name → default type args string for generic models.\n * E.g., Profile<CustomAttributesType = Record<string, unknown>>\n * → Map { 'Profile' → '<Record<string, unknown>>' }\n *\n * Non-generic models are not included in the map.\n */\nexport function buildGenericModelDefaults(models: Model[]): Map<string, string> {\n const result = new Map<string, string>();\n for (const model of models) {\n if (!model.typeParams?.length) continue;\n const defaults = model.typeParams.map((tp) => (tp.default ? mapTypeRef(tp.default) : 'unknown'));\n result.set(model.name, `<${defaults.join(', ')}>`);\n }\n return result;\n}\n\n/**\n * Remove unused imports from generated source code.\n * Scans the non-import body for each imported identifier and drops\n * individual names that are never referenced. Removes entire import\n * statements when no names are used.\n */\nexport function pruneUnusedImports(lines: string[]): string[] {\n // Split lines into imports and body\n const importLines: string[] = [];\n const bodyLines: string[] = [];\n let inBody = false;\n for (const line of lines) {\n if (!inBody && (line.startsWith('import ') || line === '')) {\n importLines.push(line);\n } else {\n inBody = true;\n bodyLines.push(line);\n }\n }\n\n const body = bodyLines.join('\\n');\n const kept: string[] = [];\n\n for (const line of importLines) {\n if (line === '') {\n kept.push(line);\n continue;\n }\n // Extract imported names from the import statement\n const match = line.match(/\\{([^}]+)\\}/);\n if (!match) {\n // Non-destructured import (e.g., import X from '...') — keep\n kept.push(line);\n continue;\n }\n const names = match[1]\n .split(',')\n .map((n) => n.trim())\n .filter(Boolean);\n // Filter to only names that appear in the body\n const usedNames = names.filter((name) => {\n const re = new RegExp(`\\\\b${name.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')}\\\\b`);\n return re.test(body);\n });\n if (usedNames.length === 0) {\n // No names used — drop entire import\n continue;\n }\n if (usedNames.length === names.length) {\n // All names used — keep original line\n kept.push(line);\n } else {\n // Some names unused — reconstruct import with only used names\n const isTypeImport = line.startsWith('import type');\n const fromMatch = line.match(/from\\s+['\"]([^'\"]+)['\"]/);\n if (fromMatch) {\n const prefix = isTypeImport ? 'import type' : 'import';\n kept.push(`${prefix} { ${usedNames.join(', ')} } from '${fromMatch[1]}';`);\n } else {\n kept.push(line);\n }\n }\n }\n\n return [...kept, ...bodyLines];\n}\n\n/** Built-in TypeScript types that are always available (no import needed). */\nexport const TS_BUILTINS = new Set([\n 'Record',\n 'Promise',\n 'Array',\n 'Map',\n 'Set',\n 'Date',\n 'string',\n 'number',\n 'boolean',\n 'void',\n 'null',\n 'undefined',\n 'any',\n 'never',\n 'unknown',\n 'true',\n 'false',\n]);\n\n/**\n * Detect whether the existing SDK uses string (ISO 8601) representation for\n * date-time fields. Checks if any baseline interface has a date-time IR field\n * typed as plain `string` (not `Date`).\n */\nexport function detectStringDateConvention(models: Model[], ctx: EmitterContext): boolean {\n if (!ctx.apiSurface?.interfaces) return false;\n for (const model of models) {\n const domainName = resolveInterfaceName(model.name, ctx);\n const baseline = ctx.apiSurface.interfaces[domainName];\n if (!baseline?.fields) continue;\n for (const field of model.fields) {\n if (field.type.kind !== 'primitive' || field.type.format !== 'date-time') continue;\n const baselineField = baseline.fields[fieldName(field.name)];\n if (baselineField && !baselineField.type.includes('Date')) {\n return true;\n }\n }\n }\n return false;\n}\n\n/**\n * Build a comprehensive set of all known type names from the IR and baseline.\n * Used to identify type parameters by elimination — any PascalCase name not in\n * this set is likely a generic type parameter.\n */\nexport function buildKnownTypeNames(models: Model[], ctx: EmitterContext): Set<string> {\n const knownNames = new Set<string>();\n for (const m of models) knownNames.add(resolveInterfaceName(m.name, ctx));\n for (const e of ctx.spec.enums) knownNames.add(e.name);\n if (ctx.apiSurface?.interfaces) {\n for (const name of Object.keys(ctx.apiSurface.interfaces)) knownNames.add(name);\n }\n if (ctx.apiSurface?.typeAliases) {\n for (const name of Object.keys(ctx.apiSurface.typeAliases)) knownNames.add(name);\n }\n if (ctx.apiSurface?.enums) {\n for (const name of Object.keys(ctx.apiSurface.enums)) knownNames.add(name);\n }\n return knownNames;\n}\n\n/**\n * Create a service directory resolver bundle.\n * Encapsulates the common pattern of mapping models to services and resolving\n * the output directory for a given IR service name.\n */\nexport function createServiceDirResolver(\n models: Model[],\n services: Service[],\n ctx: EmitterContext,\n): {\n modelToService: Map<string, string>;\n serviceNameMap: Map<string, string>;\n resolveDir: (irService: string | undefined) => string;\n} {\n const modelToService = assignModelsToServices(models, services);\n const serviceNameMap = buildServiceNameMap(services, ctx);\n const resolveDir = (irService: string | undefined) =>\n irService ? resolveServiceDir(serviceNameMap.get(irService) ?? irService) : 'common';\n return { modelToService, serviceNameMap, resolveDir };\n}\n\n/**\n * Check if a set of baseline interface fields appears to contain generic type\n * parameters — PascalCase names that aren't known models, enums, or builtins.\n */\nexport function isBaselineGeneric(fields: Record<string, unknown>, knownNames: Set<string>): boolean {\n for (const [, bf] of Object.entries(fields)) {\n const fieldType = (bf as { type: string }).type;\n const typeNames = fieldType.match(/\\b[A-Z][a-zA-Z0-9]*\\b/g);\n if (!typeNames) continue;\n for (const tn of typeNames) {\n if (TS_BUILTINS.has(tn)) continue;\n if (knownNames.has(tn)) continue;\n return true;\n }\n }\n return false;\n}\n\n/**\n * Detect whether a model matches the standard list-metadata shape:\n * exactly 2 fields named `before` and `after`, both nullable string.\n *\n * These models are redundant because the SDK already has a shared\n * `ListMetadata` type in `src/common/utils/pagination.ts`.\n */\nexport function isListMetadataModel(model: Model): boolean {\n if (model.fields.length !== 2) return false;\n\n const fieldsByName = new Map(model.fields.map((f) => [f.name, f]));\n const before = fieldsByName.get('before');\n const after = fieldsByName.get('after');\n\n if (!before || !after) return false;\n\n return isNullableString(before) && isNullableString(after);\n}\n\n/**\n * Detect whether a model is a list wrapper — the standard paginated\n * list envelope with `data` (array), `list_metadata`, and `object: 'list'`.\n *\n * These models are redundant because the SDK already has `List<T>` and\n * `ListResponse<T>` in `src/common/utils/pagination.ts`, and the shared\n * `deserializeList` handles deserialization.\n */\nexport function isListWrapperModel(model: Model): boolean {\n const fieldsByName = new Map(model.fields.map((f) => [f.name, f]));\n\n // Must have a `data` field that is an array type\n const dataField = fieldsByName.get('data');\n if (!dataField) return false;\n if (dataField.type.kind !== 'array') return false;\n\n // Must have a `list_metadata` field (the IR uses snake_case names)\n const listMetadataField = fieldsByName.get('list_metadata');\n if (!listMetadataField) return false;\n\n // Optionally has an `object` field with literal value 'list'\n const objectField = fieldsByName.get('object');\n if (objectField) {\n if (objectField.type.kind !== 'literal' || objectField.type.value !== 'list') {\n return false;\n }\n }\n\n return true;\n}\n\n/** Check if a field type is nullable string (nullable<string> or just string). */\nfunction isNullableString(field: Field): boolean {\n const { type } = field;\n if (type.kind === 'nullable') {\n return type.inner.kind === 'primitive' && type.inner.type === 'string';\n }\n if (type.kind === 'primitive') {\n return type.type === 'string';\n }\n return false;\n}\n\n/**\n * Compute a structural fingerprint for a model based on its fields.\n * Two models with identical fingerprints are structurally equivalent.\n */\nfunction modelFingerprint(model: Model): string {\n const fields = model.fields.map((f) => `${f.name}:${JSON.stringify(f.type)}:${f.required}`).sort();\n return fields.join('|');\n}\n\n/**\n * Find structurally identical models and build a deduplication map.\n * Also deduplicates models that resolve to the same interface name across\n * services — when a `$ref` schema is used by multiple tags, the IR may\n * produce per-tag copies that diverge slightly. The version with the most\n * fields is chosen as canonical.\n *\n * Returns a Map from duplicate model name → canonical model name.\n */\nexport function buildDeduplicationMap(models: Model[], ctx?: EmitterContext): Map<string, string> {\n const dedup = new Map<string, string>();\n\n // Pass 1: structural fingerprint dedup (exact match)\n const fingerprints = new Map<string, string>();\n for (const model of models) {\n if (model.fields.length === 0) continue;\n const fp = modelFingerprint(model);\n const existing = fingerprints.get(fp);\n if (existing) {\n dedup.set(model.name, existing);\n } else {\n fingerprints.set(fp, model.name);\n }\n }\n\n // Pass 2: name-based dedup for models that resolve to the same interface\n // name across services. Only applies when context with name resolution is\n // available. Picks the model with the most fields as canonical.\n if (ctx) {\n const byDomainName = new Map<string, Model[]>();\n for (const model of models) {\n if (model.fields.length === 0) continue;\n if (dedup.has(model.name)) continue; // already deduped in pass 1\n const domainName = resolveInterfaceName(model.name, ctx);\n const group = byDomainName.get(domainName);\n if (group) {\n group.push(model);\n } else {\n byDomainName.set(domainName, [model]);\n }\n }\n for (const [, group] of byDomainName) {\n if (group.length < 2) continue;\n // Choose canonical: most fields, then alphabetically by name\n group.sort((a, b) => b.fields.length - a.fields.length || a.name.localeCompare(b.name));\n const canonical = group[0];\n for (let i = 1; i < group.length; i++) {\n dedup.set(group[i].name, canonical.name);\n }\n }\n }\n\n return dedup;\n}\n\n/**\n * Check whether a service's endpoints are already fully covered by existing\n * hand-written service classes.\n *\n * A service is considered \"covered\" when:\n * 1. **Every** operation in it appears in `overlayLookup.methodByOperation`\n * 2. The overlay maps those operations to a class that exists in the baseline\n * `apiSurface` (confirming the hand-written class is actually present)\n *\n * Services with zero operations are never considered covered (nothing to\n * deduplicate). When no `apiSurface` is available, the overlay alone is\n * used as the coverage signal (the overlay is only built from existing code).\n *\n * This prevents the emitter from generating resource classes like `Connections`\n * that would duplicate hand-written modules like `SSO` for the same API\n * endpoints (e.g., `GET /connections`).\n */\nexport function isServiceCoveredByExisting(service: Service, ctx: EmitterContext): boolean {\n // Explicit override: services known to be covered by existing hand-written classes\n if (SERVICE_COVERED_BY[toPascalCase(service.name)]) return true;\n\n const overlay = ctx.overlayLookup?.methodByOperation;\n if (!overlay || overlay.size === 0) return false;\n if (service.operations.length === 0) return false;\n\n // Collect the set of existing class names from the baseline surface.\n // When no apiSurface is available, the overlay alone cannot confirm that\n // a hand-written class exists — it may only carry naming hints.\n const baselineClasses = ctx.apiSurface?.classes;\n if (!baselineClasses) return false;\n const existingClassNames = new Set(Object.keys(baselineClasses));\n\n // Check that every operation is in the overlay AND the overlay's target class\n // exists in the baseline.\n return service.operations.every((op: Operation) => {\n const httpKey = `${op.httpMethod.toUpperCase()} ${op.path}`;\n const match = overlay.get(httpKey);\n if (!match) return false;\n return existingClassNames.has(match.className);\n });\n}\n\n/**\n * Check whether a fully-covered service has operations whose overlay-mapped\n * methods are missing from the baseline class. Returns true when at least\n * one operation maps to a method name that the baseline class does not have,\n * meaning the merger needs to add new methods (skipIfExists must be removed).\n */\nexport function hasMethodsAbsentFromBaseline(service: Service, ctx: EmitterContext): boolean {\n const baselineClasses = ctx.apiSurface?.classes;\n if (!baselineClasses) return false;\n\n // For services explicitly mapped to an existing class via SERVICE_COVERED_BY,\n // check each operation's resolved method name against the target class directly.\n // This avoids the overlay gap where new endpoints are silently skipped.\n const targetClassName = SERVICE_COVERED_BY[toPascalCase(service.name)];\n if (targetClassName) {\n const cls = baselineClasses[targetClassName];\n if (!cls) return true; // Target class missing from baseline — treat as absent\n for (const op of service.operations) {\n const method = resolveMethodName(op, service, ctx);\n if (!cls.methods?.[method]) return true;\n }\n return false;\n }\n\n // Default overlay-based detection\n const overlay = ctx.overlayLookup?.methodByOperation;\n if (!overlay) return false;\n\n for (const op of service.operations) {\n const httpKey = `${op.httpMethod.toUpperCase()} ${op.path}`;\n const match = overlay.get(httpKey);\n if (!match) continue;\n const cls = baselineClasses[match.className];\n if (!cls) continue;\n if (!cls.methods?.[match.methodName]) return true;\n }\n return false;\n}\n\n/**\n * Return operations in a service that are NOT covered by existing hand-written\n * service classes. For fully uncovered services, returns all operations.\n * For partially covered services, returns only the uncovered operations.\n */\nexport function uncoveredOperations(service: Service, ctx: EmitterContext): Operation[] {\n const overlay = ctx.overlayLookup?.methodByOperation;\n if (!overlay || overlay.size === 0) return service.operations;\n\n const baselineClasses = ctx.apiSurface?.classes;\n if (!baselineClasses) return service.operations;\n const existingClassNames = new Set(Object.keys(baselineClasses));\n\n return service.operations.filter((op: Operation) => {\n const httpKey = `${op.httpMethod.toUpperCase()} ${op.path}`;\n const match = overlay.get(httpKey);\n if (!match) return true; // Not in overlay → uncovered\n return !existingClassNames.has(match.className); // Class doesn't exist → uncovered\n });\n}\n","import type { Enum, EmitterContext, GeneratedFile, Service } from '@workos/oagen';\nimport { toPascalCase, walkTypeRef } from '@workos/oagen';\nimport { fileName, resolveServiceDir, buildServiceNameMap } from './naming.js';\nimport { docComment } from './utils.js';\n\nexport function generateEnums(enums: Enum[], ctx: EmitterContext): GeneratedFile[] {\n if (enums.length === 0) return [];\n\n const enumToService = assignEnumsToServices(enums, ctx.spec.services);\n const serviceNameMap = buildServiceNameMap(ctx.spec.services, ctx);\n const resolveDir = (irService: string | undefined) =>\n irService ? resolveServiceDir(serviceNameMap.get(irService) ?? irService) : 'common';\n const files: GeneratedFile[] = [];\n\n for (const enumDef of enums) {\n const service = enumToService.get(enumDef.name);\n const dirName = resolveDir(service);\n\n // Check baseline surface for representation and values\n const baselineEnum = ctx.apiSurface?.enums?.[enumDef.name];\n const baselineAlias = ctx.apiSurface?.typeAliases?.[enumDef.name];\n const lines: string[] = [];\n\n // Track whether the generated content has new values not in the baseline.\n // When it does, skipIfExists must be false so the file gets updated.\n let hasNewValues = false;\n\n if (baselineEnum?.members) {\n // Generate TS `enum` using baseline member names and values, merging\n // any new IR values that the baseline is missing.\n const existingValues = new Set(Object.values(baselineEnum.members).map(String));\n const irValues = enumDef.values.map((v) => String(v.value));\n const missingValues = irValues.filter((v) => !existingValues.has(v));\n hasNewValues = missingValues.length > 0;\n\n lines.push(`export enum ${enumDef.name} {`);\n for (const [memberName, memberValue] of Object.entries(baselineEnum.members)) {\n const valueStr = typeof memberValue === 'string' ? `'${memberValue}'` : String(memberValue);\n lines.push(` ${memberName} = ${valueStr},`);\n }\n // Append new values from the spec that the baseline is missing\n for (const val of missingValues) {\n // Derive a PascalCase member name from the value\n const memberName = toPascalCase(val);\n lines.push(` ${memberName} = '${val}',`);\n }\n lines.push('}');\n } else if (baselineAlias?.value) {\n // Use the baseline type alias value, but merge in any new IR values the baseline is missing.\n const baselineValues = extractLiteralUnionValues(baselineAlias.value);\n const irValues = enumDef.values.map((v) => String(v.value));\n const missing = irValues.filter((v) => !baselineValues.has(v));\n hasNewValues = missing.length > 0;\n if (missing.length > 0) {\n // Baseline is missing values from the spec — regenerate with all values merged\n const allValues = [...baselineValues, ...missing];\n const parts = allValues.map((v) => `'${v}'`);\n lines.push(`export type ${enumDef.name} = ${parts.join(' | ')};`);\n } else {\n lines.push(`export type ${enumDef.name} = ${baselineAlias.value};`);\n }\n } else {\n // No baseline — generate string literal union from IR values\n const values = enumDef.values;\n lines.push(`export type ${enumDef.name} =`);\n for (let i = 0; i < values.length; i++) {\n const v = values[i];\n const valueStr = typeof v.value === 'string' ? `'${v.value}'` : String(v.value);\n if (v.description || v.deprecated) {\n const parts: string[] = [];\n if (v.description) parts.push(v.description);\n if (v.deprecated) parts.push('@deprecated');\n lines.push(...docComment(parts.join('\\n'), 2));\n }\n const suffix = i === values.length - 1 ? ';' : '';\n lines.push(` | ${valueStr}${suffix}`);\n }\n }\n\n files.push({\n path: `src/${dirName}/interfaces/${fileName(enumDef.name)}.interface.ts`,\n content: lines.join('\\n'),\n // When the spec has new values the baseline is missing, allow the file\n // to be updated so the SDK picks up the full set of enum values.\n skipIfExists: !hasNewValues,\n });\n }\n\n return files;\n}\n\n/**\n * Parse a TypeScript string literal union type alias value (e.g., \"'a' | 'b' | 'c'\")\n * into a set of its string values.\n */\nfunction extractLiteralUnionValues(aliasValue: string): Set<string> {\n const values = new Set<string>();\n // Match all single-quoted string literals in the union\n const regex = /'([^']+)'/g;\n let match;\n while ((match = regex.exec(aliasValue)) !== null) {\n values.add(match[1]);\n }\n return values;\n}\n\nexport function assignEnumsToServices(enums: Enum[], services: Service[]): Map<string, string> {\n const enumToService = new Map<string, string>();\n const enumNames = new Set(enums.map((e) => e.name));\n\n for (const service of services) {\n for (const op of service.operations) {\n const refs = new Set<string>();\n const collect = (ref: any) => {\n walkTypeRef(ref, { enum: (r: any) => refs.add(r.name) });\n };\n if (op.requestBody) collect(op.requestBody);\n collect(op.response);\n for (const p of [...op.pathParams, ...op.queryParams, ...op.headerParams, ...(op.cookieParams ?? [])]) {\n collect(p.type);\n }\n for (const name of refs) {\n if (enumNames.has(name) && !enumToService.has(name)) {\n enumToService.set(name, service.name);\n }\n }\n }\n }\n\n return enumToService;\n}\n","import type { Model, Field, TypeRef, EmitterContext, GeneratedFile } from '@workos/oagen';\nimport { mapTypeRef, mapWireTypeRef } from './type-map.js';\nimport { fieldName, wireFieldName, fileName, resolveInterfaceName, wireInterfaceName } from './naming.js';\nimport {\n collectFieldDependencies,\n docComment,\n buildGenericModelDefaults,\n pruneUnusedImports,\n TS_BUILTINS,\n detectStringDateConvention,\n buildKnownTypeNames,\n isBaselineGeneric,\n createServiceDirResolver,\n isListMetadataModel,\n isListWrapperModel,\n buildDeduplicationMap,\n} from './utils.js';\nimport { assignEnumsToServices } from './enums.js';\n\n/**\n * Detect baseline interfaces that are generic (have type parameters) even though\n * the IR model has no typeParams (OpenAPI doesn't support generics).\n *\n * Heuristic: if any field type in the baseline interface contains a PascalCase\n * name that isn't a known model, enum, or builtin, it's likely a type parameter\n * (e.g., `CustomAttributesType`), indicating the interface is generic.\n *\n * When detected, adds a default generic type arg so references like `Profile`\n * become `Profile<Record<string, unknown>>`.\n */\nfunction enrichGenericDefaultsFromBaseline(\n genericDefaults: Map<string, string>,\n models: Model[],\n ctx: EmitterContext,\n resolveDir: (irService: string | undefined) => string,\n modelToService: Map<string, string>,\n): void {\n if (!ctx.apiSurface?.interfaces) return;\n const knownNames = buildKnownTypeNames(models, ctx);\n\n for (const model of models) {\n if (genericDefaults.has(model.name)) continue; // IR already handles it\n const domainName = resolveInterfaceName(model.name, ctx);\n const baseline = ctx.apiSurface.interfaces[domainName];\n if (!baseline?.fields) continue;\n\n // Only enrich generic defaults for models whose baseline file will be\n // preserved via skipIfExists (paths match). If the file is generated\n // fresh in a new directory, it won't have generics, so references\n // to it don't need type args.\n const generatedPath = `src/${resolveDir(modelToService.get(model.name))}/interfaces/${fileName(model.name)}.interface.ts`;\n const baselineSourceFile = (baseline as any).sourceFile as string | undefined;\n if (baselineSourceFile && baselineSourceFile !== generatedPath) continue;\n\n if (isBaselineGeneric(baseline.fields, knownNames)) {\n genericDefaults.set(model.name, '<Record<string, unknown>>');\n }\n }\n}\n\nexport function generateModels(models: Model[], ctx: EmitterContext): GeneratedFile[] {\n if (models.length === 0) return [];\n\n const { modelToService, resolveDir } = createServiceDirResolver(models, ctx.spec.services, ctx);\n // Detect whether the existing SDK uses string dates (ISO 8601) rather than Date objects.\n // When detected, newly generated models also use string to maintain consistency.\n const useStringDates = detectStringDateConvention(models, ctx);\n const genericDefaults = buildGenericModelDefaults(ctx.spec.models);\n // Enrich genericDefaults from baseline interfaces that appear to be generic.\n // The IR doesn't carry typeParams for models parsed from OpenAPI (which has no\n // generics), but the existing SDK may have hand-written generic interfaces\n // (e.g., Profile<CustomAttributesType>). Detect these by checking if any\n // field type contains a PascalCase name that isn't a known model, enum, or builtin.\n enrichGenericDefaultsFromBaseline(genericDefaults, models, ctx, resolveDir, modelToService);\n const typeRefOpts = useStringDates ? { stringDates: true, genericDefaults } : { genericDefaults };\n const wireTypeRefOpts = { genericDefaults };\n const files: GeneratedFile[] = [];\n\n // Detect structurally identical or same-name models — emit type aliases for duplicates\n const dedup = buildDeduplicationMap(models, ctx);\n\n for (const model of models) {\n // Fix #4: Skip per-domain ListMetadata interfaces — the shared ListMetadata type covers these\n if (isListMetadataModel(model)) continue;\n\n // Fix #6: Skip per-domain list wrapper interfaces — the shared List<T>/ListResponse<T> covers these\n if (isListWrapperModel(model)) continue;\n\n // Deduplication: if this model is structurally identical to a canonical model,\n // emit a type alias instead of a full interface.\n const canonicalName = dedup.get(model.name);\n if (canonicalName) {\n const domainName = resolveInterfaceName(model.name, ctx);\n const responseName = wireInterfaceName(domainName);\n const canonDomainName = resolveInterfaceName(canonicalName, ctx);\n const canonResponseName = wireInterfaceName(canonDomainName);\n const service = modelToService.get(model.name);\n const dirName = resolveDir(service);\n const canonService = modelToService.get(canonicalName);\n const canonDir = resolveDir(canonService);\n const canonRelPath =\n canonDir === dirName\n ? `./${fileName(canonicalName)}.interface`\n : `../../${canonDir}/interfaces/${fileName(canonicalName)}.interface`;\n const aliasLines = [\n `import type { ${canonDomainName}, ${canonResponseName} } from '${canonRelPath}';`,\n '',\n `export type ${domainName} = ${canonDomainName};`,\n `export type ${responseName} = ${canonResponseName};`,\n ];\n files.push({\n path: `src/${dirName}/interfaces/${fileName(model.name)}.interface.ts`,\n content: aliasLines.join('\\n'),\n skipIfExists: true,\n });\n continue;\n }\n\n const service = modelToService.get(model.name);\n const dirName = resolveDir(service);\n const domainName = resolveInterfaceName(model.name, ctx);\n const responseName = wireInterfaceName(domainName);\n const deps = collectFieldDependencies(model);\n const lines: string[] = [];\n\n // Exclude the current model from generic defaults to avoid self-referencing\n // (e.g., Profile's own fields should use TCustom, not Profile<Record<...>>)\n let modelTypeRefOpts = typeRefOpts;\n let modelWireTypeRefOpts = wireTypeRefOpts;\n if (genericDefaults.has(model.name)) {\n const filteredDefaults = new Map(genericDefaults);\n filteredDefaults.delete(model.name);\n modelTypeRefOpts = { ...typeRefOpts, genericDefaults: filteredDefaults };\n modelWireTypeRefOpts = { genericDefaults: filteredDefaults };\n }\n\n // Baseline interface data (for compat field type matching)\n const baselineDomain = ctx.apiSurface?.interfaces?.[domainName];\n const baselineResponse = ctx.apiSurface?.interfaces?.[responseName];\n\n // Build set of importable type names for this file:\n // the model itself, its Response variant, all IR-dep model names + Response variants, and all IR-dep enum names\n const importableNames = new Set<string>();\n importableNames.add(domainName);\n importableNames.add(responseName);\n for (const dep of deps.models) {\n const depName = resolveInterfaceName(dep, ctx);\n importableNames.add(depName);\n importableNames.add(wireInterfaceName(depName));\n }\n for (const dep of deps.enums) {\n importableNames.add(dep);\n }\n\n // Pre-pass: discover baseline type names that aren't directly importable.\n // For each unresolvable name we either:\n // 1. Import the real type from another service (if it exists as an enum/model there)\n // 2. Create a local type alias from a suffix match\n // 3. Mark as unresolvable — the field will fall back to the IR-generated type\n const typeDecls = new Map<string, string>(); // aliasName → type expression\n const crossServiceImports = new Map<string, { name: string; relPath: string }>(); // extra imports\n const unresolvableNames = new Set<string>(); // names that can't be resolved — forces IR fallback\n const enumToService = assignEnumsToServices(ctx.spec.enums, ctx.spec.services);\n // Build a lookup: resolved enum name → IR enum name\n const resolvedEnumNames = new Map<string, string>();\n for (const e of ctx.spec.enums) {\n resolvedEnumNames.set(resolveInterfaceName(e.name, ctx), e.name);\n }\n\n for (const field of model.fields) {\n const baselineFields = [\n baselineDomain?.fields?.[fieldName(field.name)],\n baselineResponse?.fields?.[wireFieldName(field.name)],\n ].filter(Boolean) as { type: string; optional: boolean }[];\n\n for (const bf of baselineFields) {\n const names = bf.type.match(/\\b[A-Z][a-zA-Z0-9]*\\b/g);\n if (!names) continue;\n\n for (const name of names) {\n if (TS_BUILTINS.has(name)) continue;\n if (importableNames.has(name)) continue;\n if (typeDecls.has(name)) continue;\n if (crossServiceImports.has(name)) continue;\n if (unresolvableNames.has(name)) continue;\n\n // Check if this name exists as an enum in another service —\n // import the actual type so the extractor sees the real name\n const irEnumName = resolvedEnumNames.get(name);\n if (irEnumName && !deps.enums.has(irEnumName)) {\n const eService = enumToService.get(irEnumName);\n const eDir = resolveDir(eService);\n const relPath =\n eDir === dirName\n ? `./${fileName(irEnumName)}.interface`\n : `../../${eDir}/interfaces/${fileName(irEnumName)}.interface`;\n crossServiceImports.set(name, { name, relPath });\n importableNames.add(name);\n continue;\n }\n\n // Try suffix match: find an importable name ending with this name\n const candidates = [...importableNames].filter((n) => n.endsWith(name) && n !== name);\n if (candidates.length === 1) {\n // Create local type alias (e.g., type RoleResponse = ProfileRoleResponse)\n typeDecls.set(name, candidates[0]);\n importableNames.add(name);\n } else {\n // Cannot resolve this baseline type name — mark it so the field\n // falls back to the IR-generated type instead of the baseline.\n // This avoids creating type aliases that reference undefined types.\n unresolvableNames.add(name);\n }\n }\n }\n }\n\n // Import referenced models (domain + response) and enums with correct cross-service paths\n for (const dep of deps.models) {\n const depName = resolveInterfaceName(dep, ctx);\n const depService = modelToService.get(dep);\n const depDir = resolveDir(depService);\n const relPath =\n depDir === dirName ? `./${fileName(dep)}.interface` : `../../${depDir}/interfaces/${fileName(dep)}.interface`;\n lines.push(`import type { ${depName}, ${wireInterfaceName(depName)} } from '${relPath}';`);\n }\n for (const dep of deps.enums) {\n const depService = enumToService.get(dep);\n const depDir = resolveDir(depService);\n const relPath =\n depDir === dirName ? `./${fileName(dep)}.interface` : `../../${depDir}/interfaces/${fileName(dep)}.interface`;\n lines.push(`import type { ${dep} } from '${relPath}';`);\n }\n for (const [, imp] of crossServiceImports) {\n lines.push(`import type { ${imp.name} } from '${imp.relPath}';`);\n }\n\n if (lines.length > 0) lines.push('');\n\n // Add local type declarations for unresolvable baseline type names\n for (const [alias, typeExpr] of typeDecls) {\n lines.push(`type ${alias} = ${typeExpr};`);\n }\n if (typeDecls.size > 0) lines.push('');\n\n // Type params (generics) — pass genericDefaults so baseline-detected generics\n // also get type parameter declarations on the interface itself.\n const typeParams = renderTypeParams(model, genericDefaults);\n\n // Domain interface (camelCase fields) — deduplicate by camelCase name\n const seenDomainFields = new Set<string>();\n if (model.description) {\n lines.push(...docComment(model.description));\n }\n if (model.fields.length === 0) {\n lines.push(`export type ${domainName}${typeParams} = object;`);\n } else {\n lines.push(`export interface ${domainName}${typeParams} {`);\n for (const field of model.fields) {\n const domainFieldName = fieldName(field.name);\n if (seenDomainFields.has(domainFieldName)) continue;\n seenDomainFields.add(domainFieldName);\n if (field.description || field.deprecated || field.readOnly || field.writeOnly || field.default !== undefined) {\n const parts: string[] = [];\n if (field.description) parts.push(field.description);\n if (field.readOnly) parts.push('@readonly');\n if (field.writeOnly) parts.push('@writeonly');\n if (field.default !== undefined) parts.push(`@default ${JSON.stringify(field.default)}`);\n if (field.deprecated) parts.push('@deprecated');\n lines.push(...docComment(parts.join('\\n'), 2));\n }\n const baselineField = baselineDomain?.fields?.[domainFieldName];\n // For the domain interface, also check that the response baseline's optionality\n // is compatible — the serializer reads from the response type and assigns to the domain type.\n // If the domain baseline says required but the response baseline says optional,\n // the serializer would produce T | undefined for a field expecting T.\n const domainWireField = wireFieldName(field.name);\n const responseBaselineField = baselineResponse?.fields?.[domainWireField];\n const domainResponseOptionalMismatch =\n baselineField && !baselineField.optional && responseBaselineField && responseBaselineField.optional;\n const readonlyPrefix = field.readOnly ? 'readonly ' : '';\n if (\n baselineField &&\n !domainResponseOptionalMismatch &&\n baselineTypeResolvable(baselineField.type, importableNames) &&\n baselineFieldCompatible(baselineField, field)\n ) {\n const opt = baselineField.optional ? '?' : '';\n lines.push(` ${readonlyPrefix}${domainFieldName}${opt}: ${baselineField.type};`);\n } else {\n // When a baseline exists for this model, new fields (not present in the\n // baseline) are generated as optional. The merger can deep-merge new\n // fields into existing interfaces, but it cannot update existing\n // deserializer function bodies. Making the field optional prevents a\n // type error where the interface requires a field that the preserved\n // deserializer never populates.\n const isNewFieldOnExistingModel = baselineDomain && !baselineField;\n // Also make the field optional when the response baseline has it as optional\n // but the domain baseline has it as required — the deserializer reads from\n // the response type, so if the response field is optional, the domain value\n // may be undefined.\n // Additionally, when a baseline exists for the RESPONSE interface but NOT the\n // domain interface, fields that are new on the response baseline become optional\n // in the wire type. The domain type must also be optional to match, otherwise\n // the deserializer produces T | undefined for a field typed as T.\n const isNewFieldOnExistingResponse = !baselineDomain && baselineResponse && !responseBaselineField;\n const opt =\n !field.required ||\n isNewFieldOnExistingModel ||\n domainResponseOptionalMismatch ||\n isNewFieldOnExistingResponse\n ? '?'\n : '';\n lines.push(` ${readonlyPrefix}${domainFieldName}${opt}: ${mapTypeRef(field.type, modelTypeRefOpts)};`);\n }\n }\n lines.push('}');\n } // close else for non-empty domain interface\n lines.push('');\n\n // Wire/response interface (snake_case fields) — deduplicate by snake_case name\n const seenWireFields = new Set<string>();\n if (model.fields.length === 0) {\n lines.push(`export type ${responseName}${typeParams} = object;`);\n } else {\n lines.push(`export interface ${responseName}${typeParams} {`);\n for (const field of model.fields) {\n const wireField = wireFieldName(field.name);\n if (seenWireFields.has(wireField)) continue;\n seenWireFields.add(wireField);\n const baselineField = baselineResponse?.fields?.[wireField];\n if (\n baselineField &&\n baselineTypeResolvable(baselineField.type, importableNames) &&\n baselineFieldCompatible(baselineField, field)\n ) {\n const opt = baselineField.optional ? '?' : '';\n lines.push(` ${wireField}${opt}: ${baselineField.type};`);\n } else {\n const isNewFieldOnExistingModel = baselineResponse && !baselineField;\n const opt = !field.required || isNewFieldOnExistingModel ? '?' : '';\n lines.push(` ${wireField}${opt}: ${mapWireTypeRef(field.type, modelWireTypeRefOpts)};`);\n }\n }\n lines.push('}');\n } // close else for non-empty wire interface\n\n files.push({\n path: `src/${dirName}/interfaces/${fileName(model.name)}.interface.ts`,\n content: pruneUnusedImports(lines).join('\\n'),\n skipIfExists: true,\n });\n }\n\n return files;\n}\n\n/**\n * Check if all PascalCase type references in a baseline type string\n * can be resolved to types that are actually importable in the generated file.\n * A type is importable if it's a builtin, or if it's among the set of names\n * that will be imported (the model's own name/response, or its IR deps).\n * Returns false if any reference is unresolvable (e.g., hand-written types\n * from the live SDK, or spec types from other services not in IR deps).\n */\nfunction baselineTypeResolvable(typeStr: string, importableNames: Set<string>): boolean {\n const matches = typeStr.match(/\\b[A-Z][a-zA-Z0-9]*\\b/g);\n if (!matches) return true;\n\n for (const name of matches) {\n if (TS_BUILTINS.has(name)) continue;\n if (importableNames.has(name)) continue;\n return false;\n }\n return true;\n}\n\n/**\n * Check if a baseline field type is compatible with the IR field for use\n * in the generated interface. The serializer generates expressions based on\n * the IR type, so the interface type must be assignable from the serializer output.\n *\n * Rejects baseline types when:\n * - IR field is nullable but baseline type doesn't include `null`\n * - IR field is optional but baseline says required (and vice versa)\n * - IR field is required but baseline says optional\n */\nfunction baselineFieldCompatible(baselineField: { type: string; optional: boolean }, irField: Field): boolean {\n const irNullable = irField.type.kind === 'nullable';\n const baselineHasNull = baselineField.type.includes('null');\n\n // If the IR field is nullable, the serializer produces `expr ?? null`,\n // so the baseline type must include null to be assignable.\n // Exception: for optional fields, the serializer's null guard converts\n // null to undefined (`wireAccess != null ? expr : undefined`), so the\n // result type is `T | undefined` which is compatible with `field?: T`.\n if (irNullable && !baselineHasNull && irField.required) {\n return false;\n }\n\n // If the IR field is optional, the serializer may produce undefined,\n // so the baseline should also be optional (or include undefined)\n if (!irField.required && !baselineField.optional && !baselineField.type.includes('undefined')) {\n return false;\n }\n\n // If the IR field is required but the baseline says optional,\n // the serializer produces a definite value but the interface is looser — that's OK\n // (the domain type is wider than the serializer output)\n\n // If the baseline type is Record<string, unknown> but the IR field has a more specific\n // type (model, enum, or union with named variants), prefer the IR type for better type safety\n if (baselineField.type === 'Record<string, unknown>' && hasSpecificIRType(irField.type)) {\n return false;\n }\n\n return true;\n}\n\n/** Check if an IR type is more specific than Record<string, unknown>. */\nfunction hasSpecificIRType(ref: TypeRef): boolean {\n switch (ref.kind) {\n case 'model':\n case 'enum':\n return true;\n case 'union':\n // A union with named model/enum variants is more specific\n return ref.variants.some((v) => v.kind === 'model' || v.kind === 'enum');\n case 'nullable':\n return hasSpecificIRType(ref.inner);\n default:\n return false;\n }\n}\n\nfunction renderTypeParams(model: Model, genericDefaults?: Map<string, string>): string {\n if (!model.typeParams?.length) {\n // Fallback: if genericDefaults indicates this model is generic (detected\n // from the baseline), generate a default generic type parameter declaration.\n if (genericDefaults?.has(model.name)) {\n return '<GenericType extends Record<string, unknown> = Record<string, unknown>>';\n }\n return '';\n }\n const params = model.typeParams.map((tp) => {\n const def = tp.default ? ` = ${mapTypeRef(tp.default)}` : '';\n return `${tp.name}${def}`;\n });\n return `<${params.join(', ')}>`;\n}\n","import type { Model, EmitterContext, GeneratedFile, TypeRef, UnionType, PrimitiveType } from '@workos/oagen';\nimport { mapTypeRef as tsMapTypeRef } from './type-map.js';\nimport { fieldName, wireFieldName, fileName, resolveInterfaceName, wireInterfaceName } from './naming.js';\nimport {\n relativeImport,\n pruneUnusedImports,\n detectStringDateConvention,\n buildKnownTypeNames,\n isBaselineGeneric,\n createServiceDirResolver,\n isListMetadataModel,\n isListWrapperModel,\n buildDeduplicationMap,\n} from './utils.js';\n\n/**\n * Render generic type parameter declarations for a model.\n * E.g., `<CustomAttributesType = Record<string, unknown>>`.\n * Returns empty string for non-generic models.\n */\nfunction renderSerializerTypeParams(model: Model, ctx?: EmitterContext): { decl: string; usage: string } {\n if (model.typeParams?.length) {\n const params = model.typeParams.map((tp) => {\n const def = tp.default ? ` = ${tsMapTypeRef(tp.default)}` : '';\n return `${tp.name}${def}`;\n });\n const names = model.typeParams.map((tp) => tp.name);\n return { decl: `<${params.join(', ')}>`, usage: `<${names.join(', ')}>` };\n }\n // Fallback: check if the baseline interface is generic (hand-written generics\n // not captured in the IR). Only apply if the baseline file path matches the\n // generated path — meaning the existing generic file will be preserved via\n // skipIfExists. If paths differ, the interface is newly generated and non-generic.\n if (ctx?.apiSurface?.interfaces) {\n const domainName = resolveInterfaceName(model.name, ctx);\n const baseline = ctx.apiSurface.interfaces[domainName];\n if (baseline?.fields) {\n const baselineSourceFile = (baseline as any).sourceFile as string | undefined;\n const { modelToService, resolveDir } = createServiceDirResolver(ctx.spec.models, ctx.spec.services, ctx);\n const generatedPath = `src/${resolveDir(modelToService.get(model.name))}/interfaces/${fileName(model.name)}.interface.ts`;\n const pathMatches = !baselineSourceFile || baselineSourceFile === generatedPath;\n const knownNames = buildKnownTypeNames(ctx.spec.models, ctx);\n if (pathMatches && isBaselineGeneric(baseline.fields, knownNames)) {\n return {\n decl: '<GenericType extends Record<string, unknown> = Record<string, unknown>>',\n usage: '<GenericType>',\n };\n }\n }\n }\n return { decl: '', usage: '' };\n}\n\nexport function generateSerializers(models: Model[], ctx: EmitterContext): GeneratedFile[] {\n if (models.length === 0) return [];\n\n const { modelToService, resolveDir } = createServiceDirResolver(models, ctx.spec.services, ctx);\n const useStringDates = detectStringDateConvention(models, ctx);\n const files: GeneratedFile[] = [];\n const dedup = buildDeduplicationMap(models, ctx);\n // Track model names whose serialize function was skipped due to baseline incompatibility.\n // Dependent serializers that import a skipped serialize function must also skip.\n const skippedSerializeModels = new Set<string>();\n\n for (const model of models) {\n // Fix #5: Skip per-domain ListMetadata serializers — the shared deserializeListMetadata covers these\n if (isListMetadataModel(model)) continue;\n\n // Fix #7: Skip per-domain list wrapper serializers — the shared deserializeList covers these\n if (isListWrapperModel(model)) continue;\n\n // Deduplication: for structurally identical models, re-export the canonical serializer\n const canonicalName = dedup.get(model.name);\n if (canonicalName) {\n const domainName = resolveInterfaceName(model.name, ctx);\n const canonDomainName = resolveInterfaceName(canonicalName, ctx);\n const service = modelToService.get(model.name);\n const dirName = resolveDir(service);\n const canonService = modelToService.get(canonicalName);\n const canonDir = resolveDir(canonService);\n const serializerPath = `src/${dirName}/serializers/${fileName(model.name)}.serializer.ts`;\n const canonSerializerPath = `src/${canonDir}/serializers/${fileName(canonicalName)}.serializer.ts`;\n const rel = relativeImport(serializerPath, canonSerializerPath);\n const aliasLines = [\n `export { deserialize${canonDomainName} as deserialize${domainName}, serialize${canonDomainName} as serialize${domainName} } from '${rel}';`,\n ];\n files.push({\n path: serializerPath,\n content: aliasLines.join('\\n'),\n });\n continue;\n }\n\n const service = modelToService.get(model.name);\n const dirName = resolveDir(service);\n const domainName = resolveInterfaceName(model.name, ctx);\n const responseName = wireInterfaceName(domainName);\n const serializerPath = `src/${dirName}/serializers/${fileName(model.name)}.serializer.ts`;\n const typeParams = renderSerializerTypeParams(model, ctx);\n const baselineResponse = ctx.apiSurface?.interfaces?.[responseName];\n\n // Build a set of field names where format conversion (new Date / BigInt) should\n // be skipped. When the SDK-wide convention is string dates, ALL date-time fields\n // in ALL models skip conversion — not just those with a baseline interface.\n const skipFormatFields = new Set<string>();\n const baselineDomain = ctx.apiSurface?.interfaces?.[domainName];\n\n // Check if the serialize function would produce type errors against the baseline\n // wire interface. Skip serialize generation when the baseline has required fields\n // that aren't in the IR model — the generated serialize body would be missing those\n // fields, causing TS2741 / TS2322 errors. The merger will preserve any existing\n // hand-written serialize function.\n let shouldSkipSerialize = serializerHasBaselineIncompatibility(model, baselineResponse, baselineDomain, ctx);\n // Also skip if any nested model dependency had its serialize skipped — the generated\n // serialize function would reference a non-existent serialize export.\n if (!shouldSkipSerialize) {\n for (const field of model.fields) {\n for (const ref of collectSerializedModelRefs(field.type)) {\n // Check both the original model name and its dedup canonical name\n if (skippedSerializeModels.has(ref)) {\n shouldSkipSerialize = true;\n break;\n }\n const canon = dedup.get(ref);\n if (canon && skippedSerializeModels.has(canon)) {\n shouldSkipSerialize = true;\n break;\n }\n }\n if (shouldSkipSerialize) break;\n }\n }\n if (shouldSkipSerialize) {\n skippedSerializeModels.add(model.name);\n }\n if (useStringDates) {\n // Global convention: skip date-time conversion for every date field\n for (const field of model.fields) {\n if (hasDateTimeConversion(field.type)) {\n skipFormatFields.add(field.name);\n }\n }\n }\n if (baselineDomain) {\n // Per-field baseline check: also skip any other format conversions\n // (e.g., int64 → BigInt) when the baseline uses a simpler type\n for (const field of model.fields) {\n if (skipFormatFields.has(field.name)) continue;\n const baselineField = baselineDomain.fields?.[fieldName(field.name)];\n if (baselineField && !baselineField.type.includes('Date') && hasFormatConversion(field.type)) {\n skipFormatFields.add(field.name);\n }\n }\n }\n\n // Find nested model refs that need their own serializer imports.\n // Only collect models that will actually be called in serialize/deserialize expressions\n // (direct model refs, array-of-model items, nullable-wrapped models, single-model-variant unions).\n const nestedModelRefs = new Set<string>();\n for (const field of model.fields) {\n for (const ref of collectSerializedModelRefs(field.type)) {\n if (ref !== model.name) nestedModelRefs.add(ref);\n }\n }\n\n const lines: string[] = [];\n\n // Import model interfaces\n const interfacePath = `src/${dirName}/interfaces/${fileName(model.name)}.interface.ts`;\n lines.push(\n `import type { ${domainName}, ${responseName} } from '${relativeImport(serializerPath, interfacePath)}';`,\n );\n\n // Import nested model deserializers/serializers as a single merged import.\n // pruneUnusedImports will strip any unused identifiers (e.g., serialize*\n // when shouldSkipSerialize is true).\n for (const dep of nestedModelRefs) {\n const depService = modelToService.get(dep);\n const depDir = resolveDir(depService);\n const depSerializerPath = `src/${depDir}/serializers/${fileName(dep)}.serializer.ts`;\n const depName = resolveInterfaceName(dep, ctx);\n const rel = relativeImport(serializerPath, depSerializerPath);\n lines.push(`import { deserialize${depName}, serialize${depName} } from '${rel}';`);\n }\n lines.push('');\n\n // Deserialize function (wire → domain) — deduplicate by camelCase name\n const seenDeserFields = new Set<string>();\n // Prefix param with _ when model has no fields to avoid unused-param warnings\n const deserParamPrefix = model.fields.length === 0 ? '_' : '';\n lines.push(`export const deserialize${domainName} = ${typeParams.decl}(`);\n lines.push(` ${deserParamPrefix}response: ${responseName}${typeParams.usage},`);\n lines.push(`): ${domainName}${typeParams.usage} => ({`);\n for (const field of model.fields) {\n const domain = fieldName(field.name);\n if (seenDeserFields.has(domain)) continue;\n seenDeserFields.add(domain);\n const wire = wireFieldName(field.name);\n const wireAccess = `response.${wire}`;\n const skip = skipFormatFields.has(field.name);\n const expr = skip ? wireAccess : deserializeExpression(field.type, wireAccess, ctx);\n // Treat new fields (not in baseline) as effectively optional: the merger\n // can deep-merge them into existing interfaces but cannot update existing\n // deserializer bodies, so the wire response may not contain them.\n const isNewField = baselineDomain && !baselineDomain.fields?.[domain];\n const effectivelyOptional = !field.required || isNewField;\n // If the field is optional and the expression involves a function call,\n // wrap with a null check to avoid passing undefined to the deserializer.\n // When the field type is nullable, preserve null on the wire instead of\n // converting it to undefined (APIs distinguish null from absent).\n if (effectivelyOptional && expr !== wireAccess && needsNullGuard(field.type)) {\n const fallback = field.type.kind === 'nullable' ? 'null' : 'undefined';\n // If the expression already starts with a null guard from nullable handling,\n // don't wrap it again — just replace the inner null fallback\n if (expr.startsWith(`${wireAccess} != null ?`)) {\n lines.push(` ${domain}: ${expr.replace(/: null$/, `: ${fallback}`)},`);\n } else {\n lines.push(` ${domain}: ${wireAccess} != null ? ${expr} : ${fallback},`);\n }\n } else if (field.required && expr === wireAccess) {\n // Required field with direct assignment — only add a fallback when the\n // response interface makes the field optional (baseline override mismatch)\n // or the field is newly added. When the field is required on BOTH\n // interfaces, the response always contains it — no fallback is needed.\n // This prevents incorrect fallbacks like ?? '' on string|null fields\n // and invalid enum fallbacks like ?? 'Pending'.\n const responseFieldInfo = baselineResponse?.fields?.[wire];\n const responseFieldOptional = responseFieldInfo?.optional ?? false;\n const needsFallback = responseFieldOptional || isNewField;\n const fallback = needsFallback ? defaultForType(field.type) : null;\n if (fallback) {\n lines.push(` ${domain}: ${expr} ?? ${fallback},`);\n } else {\n lines.push(` ${domain}: ${expr},`);\n }\n } else {\n lines.push(` ${domain}: ${expr},`);\n }\n }\n // NOTE: Previously we added passthrough assignments for baseline-required fields\n // missing from the IR model. This was removed because it creates type errors:\n // the serializer would output fields that don't exist on the generated interface\n // (e.g., Connection.type, AuditLogSchema.createdAt). If a baseline field is\n // truly needed, the merger will preserve the existing serializer for that field.\n lines.push('});');\n\n // Serialize function (domain → wire) — skip when the baseline wire interface\n // has required fields not covered by the IR model (the merger will preserve\n // any existing hand-written serialize function).\n if (!shouldSkipSerialize) {\n const serParamPrefix = model.fields.length === 0 ? '_' : '';\n lines.push('');\n lines.push(`export const serialize${domainName} = ${typeParams.decl}(`);\n lines.push(` ${serParamPrefix}model: ${domainName}${typeParams.usage},`);\n lines.push(`): ${responseName}${typeParams.usage} => ({`);\n const seenSerFields = new Set<string>();\n for (const field of model.fields) {\n const wire = wireFieldName(field.name);\n if (seenSerFields.has(wire)) continue;\n seenSerFields.add(wire);\n const domain = fieldName(field.name);\n const domainAccess = `model.${domain}`;\n const skip = skipFormatFields.has(field.name);\n const expr = skip ? domainAccess : serializeExpression(field.type, domainAccess, ctx);\n // Treat new fields (not in baseline) as effectively optional — see deserializer comment above.\n const isNewSerField = baselineDomain && !baselineDomain.fields?.[domain];\n const effectivelyOptionalSer = !field.required || isNewSerField;\n\n // Check if the domain field is optional but the baseline wire field is required.\n // The serializer assigns `T | undefined` to the wire field, but the wire interface\n // expects `T`. Add `?? null` coalesce to strip undefined and satisfy the wire type.\n const baselineWireField = baselineResponse?.fields?.[wire];\n const baselineDomainField = baselineDomain?.fields?.[domain];\n // The domain field is optional if: (a) the IR says it's optional, (b) the baseline says it's optional,\n // or (c) the baseline domain exists but doesn't have this field name (it's a \"new field on existing model\"\n // and the generated interface makes it optional). Case (c) covers renamed fields (e.g., baseline\n // uses `type` but the generated interface uses `connectionType`).\n const isNewFieldOnExistingDomain = baselineDomain && !baselineDomainField;\n const domainFieldIsOptional =\n !field.required || (baselineDomainField?.optional ?? false) || !!isNewFieldOnExistingDomain;\n const wireFieldIsRequired = baselineWireField ? !baselineWireField.optional : field.required;\n const needsUndefinedCoalesce = domainFieldIsOptional && wireFieldIsRequired && expr === domainAccess;\n\n // If the expression involves a function call (nested model/array serializer),\n // wrap with a null check to prevent crashes when callers pass partial objects\n // (e.g., `{} as any` in tests).\n // When the field type is nullable, preserve null instead of undefined.\n // Guard nullable and optional nested model/array-of-model fields.\n // Required non-nullable fields are not guarded — the caller must provide them.\n const shouldGuardSer = effectivelyOptionalSer || field.type.kind === 'nullable';\n if (expr !== domainAccess && needsNullGuard(field.type) && shouldGuardSer) {\n // For nullable fields, fallback to null. For optional fields, fallback to undefined.\n const fallback = field.type.kind === 'nullable' ? 'null' : 'undefined';\n if (expr.startsWith(`${domainAccess} != null ?`)) {\n lines.push(` ${wire}: ${expr.replace(/: null$/, `: ${fallback}`)},`);\n } else {\n lines.push(` ${wire}: ${domainAccess} != null ? ${expr} : ${fallback},`);\n }\n } else if (needsUndefinedCoalesce) {\n // Domain field is optional (T | undefined) but wire field is required (T or T | null).\n // When the wire type includes null, coalesce undefined → null.\n // Otherwise, use a non-null assertion — the consumer is responsible for\n // providing required fields when calling serialize, so undefined at runtime\n // indicates a programming error on the caller's side.\n const wireHasNull = baselineWireField?.type?.includes('null') || field.type.kind === 'nullable';\n if (wireHasNull) {\n lines.push(` ${wire}: ${expr} ?? null,`);\n } else {\n lines.push(` ${wire}: ${expr}!,`);\n }\n } else if (field.type.kind === 'nullable' && expr === domainAccess) {\n // Check if the domain interface makes this field optional (T | null | undefined).\n // This can happen when: (a) the IR says not required, (b) the field is new on\n // an existing model, or (c) the baseline domain is required but the baseline\n // response is optional (domainResponseOptionalMismatch in models.ts).\n // In all these cases, the domain type includes `undefined` but the wire type\n // may only accept `T | null`, so coalesce undefined → null.\n const domainWireField2 = wireFieldName(field.name);\n const responseBaselineField2 = baselineResponse?.fields?.[domainWireField2];\n const baselineDomainField2 = baselineDomain?.fields?.[domain];\n const domainResponseMismatch =\n baselineDomainField2 &&\n !baselineDomainField2.optional &&\n responseBaselineField2 &&\n responseBaselineField2.optional;\n const fieldEffectivelyOptional = !field.required || isNewSerField || !!domainResponseMismatch;\n if (fieldEffectivelyOptional) {\n lines.push(` ${wire}: ${expr} ?? null,`);\n } else {\n lines.push(` ${wire}: ${expr},`);\n }\n } else {\n lines.push(` ${wire}: ${expr},`);\n }\n }\n lines.push('});');\n }\n\n files.push({\n path: serializerPath,\n content: pruneUnusedImports(lines).join('\\n'),\n });\n }\n\n return files;\n}\n\n/**\n * Collect model names that will actually be called in serialize/deserialize expressions.\n * Unlike collectModelRefs (which walks all union variants), this only includes models\n * that the expression functions will actually invoke a serializer/deserializer for.\n */\nfunction collectSerializedModelRefs(ref: TypeRef): string[] {\n switch (ref.kind) {\n case 'model':\n return [ref.name];\n case 'array':\n if (ref.items.kind === 'model') return [ref.items.name];\n return collectSerializedModelRefs(ref.items);\n case 'nullable':\n return collectSerializedModelRefs(ref.inner);\n case 'union': {\n const models = uniqueModelVariants(ref);\n // Discriminated unions and allOf unions need serializers for all model variants\n if (ref.discriminator && models.length > 0) return models;\n if (ref.compositionKind === 'allOf' && models.length > 0) return models;\n // Only if exactly one unique model variant — that's when we call its serializer\n if (models.length === 1) return models;\n return [];\n }\n case 'map':\n case 'primitive':\n case 'literal':\n case 'enum':\n return [];\n }\n}\n\nfunction deserializeExpression(ref: TypeRef, wireExpr: string, ctx: EmitterContext): string {\n switch (ref.kind) {\n case 'primitive':\n return deserializePrimitive(ref, wireExpr);\n case 'literal':\n case 'enum':\n return wireExpr;\n case 'model': {\n const name = resolveInterfaceName(ref.name, ctx);\n return `deserialize${name}(${wireExpr})`;\n }\n case 'array':\n if (ref.items.kind === 'model') {\n const name = resolveInterfaceName(ref.items.name, ctx);\n return `${wireExpr}.map(deserialize${name})`;\n }\n return wireExpr;\n case 'nullable': {\n const innerExpr = deserializeExpression(ref.inner, wireExpr, ctx);\n // If the inner type involves a function call (model or array-of-model),\n // wrap with a null check to avoid passing null to the deserializer\n if (innerExpr !== wireExpr) {\n return `${wireExpr} != null ? ${innerExpr} : null`;\n }\n return `${wireExpr} ?? null`;\n }\n case 'union': {\n // Discriminated union: switch on the discriminator property\n if (ref.discriminator) {\n return renderDiscriminatorSwitch(ref, wireExpr, 'deserialize', ctx);\n }\n // allOf union: merge all model variant fields via spread\n if (ref.compositionKind === 'allOf') {\n return renderAllOfMerge(ref, wireExpr, 'deserialize', ctx);\n }\n // If the union has exactly one unique model variant, deserialize using that model's deserializer\n const deserModelVariants = uniqueModelVariants(ref);\n if (deserModelVariants.length === 1) {\n const name = resolveInterfaceName(deserModelVariants[0], ctx);\n return `deserialize${name}(${wireExpr})`;\n }\n return wireExpr;\n }\n case 'map':\n return wireExpr;\n }\n}\n\nfunction serializeExpression(ref: TypeRef, domainExpr: string, ctx: EmitterContext): string {\n switch (ref.kind) {\n case 'primitive':\n return serializePrimitive(ref, domainExpr);\n case 'literal':\n case 'enum':\n return domainExpr;\n case 'model': {\n const name = resolveInterfaceName(ref.name, ctx);\n return `serialize${name}(${domainExpr})`;\n }\n case 'array':\n if (ref.items.kind === 'model') {\n const name = resolveInterfaceName(ref.items.name, ctx);\n return `${domainExpr}.map(serialize${name})`;\n }\n return domainExpr;\n case 'nullable': {\n const innerExpr = serializeExpression(ref.inner, domainExpr, ctx);\n // If the inner type involves a function call (model or array-of-model),\n // wrap with a null check to avoid passing null to the serializer\n if (innerExpr !== domainExpr) {\n return `${domainExpr} != null ? ${innerExpr} : null`;\n }\n return domainExpr;\n }\n case 'union': {\n // Discriminated union: switch on the discriminator property\n if (ref.discriminator) {\n return renderDiscriminatorSwitch(ref, domainExpr, 'serialize', ctx);\n }\n // allOf union: merge all model variant fields via spread\n if (ref.compositionKind === 'allOf') {\n return renderAllOfMerge(ref, domainExpr, 'serialize', ctx);\n }\n // If the union has exactly one unique model variant, serialize using that model's serializer\n const serModelVariants = uniqueModelVariants(ref);\n if (serModelVariants.length === 1) {\n const name = resolveInterfaceName(serModelVariants[0], ctx);\n return `serialize${name}(${domainExpr})`;\n }\n return domainExpr;\n }\n case 'map':\n return domainExpr;\n }\n}\n\n/**\n * Extract unique model names from a union's variants.\n * Used to determine if a union can be deserialized/serialized as a single model.\n */\nfunction uniqueModelVariants(ref: UnionType): string[] {\n const modelNames = new Set<string>();\n for (const v of ref.variants) {\n if (v.kind === 'model') modelNames.add(v.name);\n }\n return [...modelNames];\n}\n\n/**\n * Check whether a TypeRef involves a model reference or format conversion\n * that would produce a function call in serialization/deserialization.\n * Used to determine whether optional fields need a null guard wrapper.\n */\nfunction needsNullGuard(ref: TypeRef): boolean {\n switch (ref.kind) {\n case 'model':\n return true;\n case 'primitive':\n return hasFormatConversion(ref);\n case 'array':\n return ref.items.kind === 'model';\n case 'nullable':\n return needsNullGuard(ref.inner);\n case 'union':\n if (ref.discriminator) return true;\n if (ref.compositionKind === 'allOf' && uniqueModelVariants(ref).length > 0) return true;\n return uniqueModelVariants(ref).length === 1;\n default:\n return false;\n }\n}\n\n/** Check if a type has a format that requires conversion. */\nfunction hasFormatConversion(ref: TypeRef): boolean {\n switch (ref.kind) {\n case 'primitive':\n return ref.format === 'date-time' || ref.format === 'int64';\n case 'nullable':\n return hasFormatConversion(ref.inner);\n default:\n return false;\n }\n}\n\n/** Check if a type specifically has a date-time format conversion. */\nfunction hasDateTimeConversion(ref: TypeRef): boolean {\n switch (ref.kind) {\n case 'primitive':\n return ref.format === 'date-time';\n case 'nullable':\n return hasDateTimeConversion(ref.inner);\n default:\n return false;\n }\n}\n\n/** Deserialize a primitive value, applying format conversions when needed. */\nfunction deserializePrimitive(ref: PrimitiveType, wireExpr: string): string {\n if (ref.format === 'date-time') return `new Date(${wireExpr})`;\n if (ref.format === 'int64') return `BigInt(${wireExpr})`;\n return wireExpr;\n}\n\n/** Serialize a primitive value, applying format conversions when needed. */\nfunction serializePrimitive(ref: PrimitiveType, domainExpr: string): string {\n if (ref.format === 'date-time') return `${domainExpr}.toISOString()`;\n if (ref.format === 'int64') return `String(${domainExpr})`;\n return domainExpr;\n}\n\n/**\n * Render a discriminated union switch expression.\n * Produces an IIFE that switches on the discriminator property and calls\n * the appropriate serializer/deserializer for each mapped model.\n */\nfunction renderDiscriminatorSwitch(\n ref: UnionType,\n expr: string,\n direction: 'deserialize' | 'serialize',\n ctx: EmitterContext,\n): string {\n const disc = ref.discriminator!;\n const cases: string[] = [];\n for (const [value, modelName] of Object.entries(disc.mapping)) {\n const resolved = resolveInterfaceName(modelName, ctx);\n const fn = `${direction}${resolved}`;\n cases.push(`case '${value}': return ${fn}(${expr} as any)`);\n }\n return `(() => { switch ((${expr} as any).${disc.property}) { ${cases.join('; ')}; default: return ${expr} } })()`;\n}\n\n/**\n * Render an allOf merge expression.\n * Spreads the serialized/deserialized result of each model variant.\n */\nfunction renderAllOfMerge(\n ref: UnionType,\n expr: string,\n direction: 'deserialize' | 'serialize',\n ctx: EmitterContext,\n): string {\n const models = uniqueModelVariants(ref);\n if (models.length === 0) return expr;\n const spreads = models.map((name) => {\n const resolved = resolveInterfaceName(name, ctx);\n return `...${direction}${resolved}(${expr} as any)`;\n });\n return `({ ${spreads.join(', ')} })`;\n}\n\n/**\n * Return a TypeScript default value expression for a type, used as a null\n * coalesce fallback when a required domain field may be optional in the\n * response interface (baseline override mismatch).\n */\nfunction defaultForType(ref: TypeRef): string | null {\n switch (ref.kind) {\n case 'literal':\n // Use the literal value itself as the fallback (e.g., 'role' for object: 'role')\n return typeof ref.value === 'string' ? `'${ref.value}'` : String(ref.value);\n case 'enum':\n // Don't provide enum fallbacks — the first enum value may not be a valid\n // member of the target type (e.g., 'Pending' is not a member of ConnectionType).\n // If the field is required, the API always sends it; if the response baseline\n // says optional, null/undefined is safer than guessing a value.\n return null;\n case 'map':\n return '{}';\n case 'nullable':\n // Nullable fields should fall back to null, not the inner type's default.\n // This prevents incorrect conversions like nullable<string> → '' instead of null.\n return 'null';\n case 'primitive':\n switch (ref.type) {\n case 'boolean':\n return 'false';\n case 'string':\n return \"''\";\n case 'integer':\n case 'number':\n return '0';\n default:\n return null;\n }\n case 'array':\n return '[]';\n default:\n return null;\n }\n}\n\n/**\n * Check if the generated serialize function would produce type errors\n * against the baseline wire (response) interface. Returns true when:\n * - The baseline response interface has required fields whose wire name\n * doesn't match any IR model field → TS2741 missing property.\n * - The baseline domain interface has required fields whose camelCase name\n * doesn't match any IR model field → the serializer would produce\n * expressions referencing domain fields that don't exist on the baseline.\n * - The baseline response has a required array field whose type references\n * a different module than where the serializer imports its nested serializer.\n */\nfunction serializerHasBaselineIncompatibility(\n model: Model,\n baselineResponse: { fields?: Record<string, { type: string; optional: boolean }> } | undefined,\n baselineDomain?: {\n fields?: Record<string, { type: string; optional: boolean }>;\n },\n ctx?: EmitterContext,\n): boolean {\n if (!baselineResponse?.fields) return false;\n\n // Collect all wire-format field names the IR model will produce\n const irWireFields = new Set<string>();\n const irDomainFields = new Set<string>();\n for (const field of model.fields) {\n irWireFields.add(wireFieldName(field.name));\n irDomainFields.add(fieldName(field.name));\n }\n\n // Check if the baseline response has required fields not in the IR model\n for (const [wireField2, fieldDef] of Object.entries(baselineResponse.fields)) {\n if (fieldDef.optional) continue; // Optional fields won't cause TS errors\n if (!irWireFields.has(wireField2)) {\n // Baseline requires a field the IR doesn't produce → type error\n return true;\n }\n }\n\n // Check if the baseline domain has required fields whose names differ from\n // what the IR would generate (e.g., baseline uses `type` but IR maps\n // `connection_type` → `connectionType`). If there are required fields in\n // the baseline domain that the IR doesn't produce, the serializer would read\n // from domain fields that may have incompatible types.\n if (baselineDomain?.fields) {\n const baselineRequiredFields = Object.entries(baselineDomain.fields)\n .filter(([, f]) => !f.optional)\n .map(([name]) => name);\n // Count how many baseline required fields are NOT in the IR domain fields.\n // If more than 1/3 of required fields are unrecognized, assume significant\n // structural differences → skip serialize to avoid type mismatches.\n const unmatchedCount = baselineRequiredFields.filter((n) => !irDomainFields.has(n)).length;\n if (unmatchedCount > 0 && baselineRequiredFields.length > 0) {\n const unmatchedRatio = unmatchedCount / baselineRequiredFields.length;\n if (unmatchedRatio > 0.3) {\n return true;\n }\n }\n }\n\n // Check for nested model type mismatches: when the baseline response interface\n // references a nested model type whose source file is in a DIFFERENT directory\n // than the serializer's parent directory. The generated serializer creates local\n // copies of nested model interfaces (via the model generator), and these local\n // copies are structurally similar but TypeScript treats them as different types.\n // Example: OrganizationDomainResponse from organization-domains/interfaces/ vs\n // the generated copy in organizations/interfaces/ — same structure, different modules.\n if (ctx?.apiSurface?.interfaces) {\n // Determine the serializer's parent directory from the model name\n const modelSourceFile = (baselineResponse as any)?.sourceFile as string | undefined;\n const responseDir = modelSourceFile ? modelSourceFile.split('/').slice(0, 2).join('/') : null;\n\n for (const field of model.fields) {\n // Unwrap nullable to get the inner model type\n let fieldType = field.type;\n if (fieldType.kind === 'nullable') fieldType = fieldType.inner;\n if (fieldType.kind !== 'array' && fieldType.kind !== 'model') continue;\n const innerType = fieldType.kind === 'array' ? fieldType.items : fieldType;\n if (innerType.kind !== 'model') continue;\n\n const nestedWireName = wireInterfaceName(resolveInterfaceName(innerType.name, ctx));\n const wireField3 = wireFieldName(field.name);\n const baselineWireField2 = baselineResponse.fields[wireField3];\n if (!baselineWireField2) continue;\n\n // Check for type name mismatch: the baseline wire field references a type\n // that is different from what the generated serializer would produce.\n // e.g., baseline has `role: RoleResponse` but the deduped serializer returns\n // `AddRolePermissionResponse`.\n const baselineTypeNames: string[] = baselineWireField2.type.match(/\\b[A-Z][a-zA-Z0-9]*Response\\b/g) || [];\n if (baselineTypeNames.length > 0 && !baselineTypeNames.includes(nestedWireName)) {\n // The baseline expects a different Response type than the serializer produces\n return true;\n }\n\n // Check if the baseline wire field type includes the nested wire type name\n if (baselineWireField2.type.includes(nestedWireName) || baselineWireField2.type.match(/\\b[A-Z]\\w*Response\\b/)) {\n // Extract type names from the baseline field type\n const typeNames: string[] = baselineWireField2.type.match(/\\b[A-Z][a-zA-Z0-9]*\\b/g) || [];\n for (const typeName of typeNames) {\n if (typeName === 'Record' || typeName === 'Array') continue;\n const nestedIface = ctx.apiSurface.interfaces[typeName];\n if (!nestedIface) continue;\n const nestedSrc = (nestedIface as any).sourceFile as string | undefined;\n if (!nestedSrc || !responseDir) continue;\n const nestedDir = nestedSrc.split('/').slice(0, 2).join('/');\n if (nestedDir !== responseDir) {\n // The baseline response uses a type from a different directory than\n // where the response itself lives → cross-module type incompatibility\n return true;\n }\n }\n }\n }\n }\n\n return false;\n}\n","import type { Model, TypeRef, Enum, EmitterContext } from '@workos/oagen';\nimport { wireFieldName, fileName, resolveServiceDir } from './naming.js';\nimport { resolveResourceClassName } from './resources.js';\nimport { createServiceDirResolver, assignModelsToServices, isListMetadataModel, isListWrapperModel } from './utils.js';\n\n/**\n * Prefix mapping for generating realistic ID fixture values.\n * When a field named \"id\" belongs to a model whose name matches a key here,\n * the generated ID will be prefixed accordingly (e.g. \"conn_01234\").\n */\nexport const ID_PREFIXES: Record<string, string> = {\n Connection: 'conn_',\n Organization: 'org_',\n OrganizationMembership: 'om_',\n User: 'user_',\n Directory: 'directory_',\n DirectoryGroup: 'dir_grp_',\n DirectoryUser: 'dir_usr_',\n Invitation: 'inv_',\n Session: 'session_',\n AuthenticationFactor: 'auth_factor_',\n EmailVerification: 'email_verification_',\n MagicAuth: 'magic_auth_',\n PasswordReset: 'password_reset_',\n};\n\n/**\n * Generate JSON fixture files for test data.\n * Each model that appears as a response gets a fixture in wire format (snake_case).\n */\nexport function generateFixtures(\n spec: {\n models: Model[];\n enums: Enum[];\n services: any[];\n },\n ctx?: EmitterContext,\n): { path: string; content: string }[] {\n if (spec.models.length === 0) return [];\n\n const { modelToService, resolveDir } = ctx\n ? createServiceDirResolver(spec.models, ctx.spec.services, ctx)\n : {\n modelToService: assignModelsToServices(spec.models, spec.services),\n resolveDir: (irService: string | undefined) => (irService ? resolveServiceDir(irService) : 'common'),\n };\n const modelMap = new Map(spec.models.map((m) => [m.name, m]));\n const enumMap = new Map(spec.enums.map((e) => [e.name, e]));\n const files: { path: string; content: string }[] = [];\n\n for (const model of spec.models) {\n // Skip redundant list-metadata and list-wrapper models (handled by shared types)\n if (isListMetadataModel(model)) continue;\n if (isListWrapperModel(model)) continue;\n\n const service = modelToService.get(model.name);\n const dirName = resolveDir(service);\n const fixture = generateModelFixture(model, modelMap, enumMap);\n\n files.push({\n path: `src/${dirName}/fixtures/${fileName(model.name)}.fixture.json`,\n content: JSON.stringify(fixture, null, 2),\n });\n }\n\n // Generate list fixtures for models that appear in paginated responses\n for (const service of spec.services) {\n const resolvedName = ctx ? resolveResourceClassName(service, ctx) : service.name;\n const serviceDir = resolveServiceDir(resolvedName);\n for (const op of service.operations) {\n if (op.pagination) {\n let itemModel = op.pagination.itemType.kind === 'model' ? modelMap.get(op.pagination.itemType.name) : null;\n if (itemModel) {\n // Detect if the \"item\" model is actually a list wrapper (has `data` array + `list_metadata`).\n // If so, unwrap to the actual item type to avoid double-nesting in fixtures.\n const unwrapped = unwrapListModel(itemModel, modelMap);\n if (unwrapped) {\n itemModel = unwrapped;\n }\n const fixture = generateModelFixture(itemModel, modelMap, enumMap);\n const listFixture = {\n data: [fixture],\n list_metadata: {\n before: null,\n after: null,\n },\n };\n files.push({\n path: `src/${serviceDir}/fixtures/list-${fileName(itemModel.name)}.fixture.json`,\n content: JSON.stringify(listFixture, null, 2),\n });\n }\n }\n }\n }\n\n return files;\n}\n\n/**\n * Detect if a model is a list wrapper (has a `data` array field and a `list_metadata` field).\n * If so, return the inner item model from the `data` array. Otherwise return null.\n * This prevents double-nesting when the pagination itemType points to a list wrapper\n * instead of the actual item model.\n */\nexport function unwrapListModel(model: Model, modelMap: Map<string, Model>): Model | null {\n const dataField = model.fields.find((f) => f.name === 'data');\n const hasListMetadata = model.fields.some((f) => f.name === 'list_metadata' || f.name === 'listMetadata');\n if (dataField && hasListMetadata && dataField.type.kind === 'array') {\n const itemType = dataField.type.items;\n if (itemType.kind === 'model') {\n return modelMap.get(itemType.name) ?? null;\n }\n }\n return null;\n}\n\nfunction generateModelFixture(\n model: Model,\n modelMap: Map<string, Model>,\n enumMap: Map<string, Enum>,\n): Record<string, any> {\n const fixture: Record<string, any> = {};\n\n for (const field of model.fields) {\n const wireName = wireFieldName(field.name);\n // Prefer the OpenAPI example value when available on the field\n if (field.example !== undefined) {\n fixture[wireName] = field.example;\n } else {\n fixture[wireName] = generateFieldValue(field.type, field.name, model.name, modelMap, enumMap);\n }\n }\n\n return fixture;\n}\n\nfunction generateFieldValue(\n ref: TypeRef,\n fieldName: string,\n modelName: string,\n modelMap: Map<string, Model>,\n enumMap: Map<string, Enum>,\n): any {\n switch (ref.kind) {\n case 'primitive':\n return generatePrimitiveValue(ref.type, ref.format, fieldName, modelName);\n case 'literal':\n return ref.value;\n case 'enum': {\n const e = enumMap.get(ref.name);\n return e?.values[0]?.value ?? 'unknown';\n }\n case 'model': {\n const nested = modelMap.get(ref.name);\n if (nested) return generateModelFixture(nested, modelMap, enumMap);\n return {};\n }\n case 'array': {\n // For array<enum>, use actual enum values instead of a single generated item\n if (ref.items.kind === 'enum') {\n const e = enumMap.get(ref.items.name);\n if (e && e.values.length > 0) {\n return e.values.map((v) => v.value);\n }\n }\n const item = generateFieldValue(ref.items, fieldName, modelName, modelMap, enumMap);\n return [item];\n }\n case 'nullable':\n return generateFieldValue(ref.inner, fieldName, modelName, modelMap, enumMap);\n case 'union':\n if (ref.variants.length > 0) {\n return generateFieldValue(ref.variants[0], fieldName, modelName, modelMap, enumMap);\n }\n return null;\n case 'map':\n return {\n key: generateFieldValue(ref.valueType, 'value', modelName, modelMap, enumMap),\n };\n }\n}\n\nfunction generatePrimitiveValue(type: string, format: string | undefined, name: string, modelName: string): any {\n switch (type) {\n case 'string':\n if (format === 'date-time') return '2023-01-01T00:00:00.000Z';\n if (format === 'date') return '2023-01-01';\n if (format === 'uuid') return '00000000-0000-0000-0000-000000000000';\n if (name === 'id') {\n const prefix = ID_PREFIXES[modelName] ?? '';\n return `${prefix}01234`;\n }\n if (name.includes('id')) return `${name}_01234`;\n if (name.includes('email')) return 'test@example.com';\n if (name.includes('url') || name.includes('uri')) return 'https://example.com';\n if (name.includes('name')) return 'Test';\n return `test_${name}`;\n case 'integer':\n return 1;\n case 'number':\n return 1.0;\n case 'boolean':\n return true;\n case 'unknown':\n return {};\n default:\n return null;\n }\n}\n","// @oagen-ignore: Operation.async — all TypeScript SDK methods are async by nature\n\nimport type { Service, Operation, EmitterContext, GeneratedFile, TypeRef, Model } from '@workos/oagen';\nimport { planOperation, toPascalCase, toCamelCase } from '@workos/oagen';\nimport type { OperationPlan } from '@workos/oagen';\nimport { mapTypeRef } from './type-map.js';\nimport {\n fieldName,\n wireFieldName,\n fileName,\n resolveServiceDir,\n resolveMethodName,\n resolveInterfaceName,\n resolveServiceName,\n wireInterfaceName,\n} from './naming.js';\nimport {\n docComment,\n createServiceDirResolver,\n isServiceCoveredByExisting,\n hasMethodsAbsentFromBaseline,\n uncoveredOperations,\n} from './utils.js';\nimport { assignEnumsToServices } from './enums.js';\nimport { unwrapListModel } from './fixtures.js';\n\n/**\n * Check whether the baseline (hand-written) class has a constructor compatible\n * with the generated pattern `constructor(private readonly workos: WorkOS)`.\n * Returns true when no baseline exists (fresh generation) or when compatible.\n */\nexport function hasCompatibleConstructor(className: string, ctx: EmitterContext): boolean {\n const baselineClass = ctx.apiSurface?.classes?.[className];\n if (!baselineClass) return true; // No baseline — fresh generation\n const params = baselineClass.constructorParams;\n if (!params || params.length === 0) return true; // No-arg constructor is compatible\n // Compatible if there is a single `workos` param whose type contains \"WorkOS\"\n return params.some((p) => p.name === 'workos' && p.type.includes('WorkOS'));\n}\n\n/**\n * Resolve the resource class name for a service, accounting for constructor\n * compatibility with the baseline class.\n *\n * When the overlay-resolved class has an incompatible constructor (e.g., a\n * hand-written `Webhooks` class that takes `CryptoProvider` instead of `WorkOS`),\n * falls back to the IR name (`toPascalCase(service.name)`). If the IR name\n * collides with the overlay name, appends an `Endpoints` suffix.\n */\nexport function resolveResourceClassName(service: Service, ctx: EmitterContext): string {\n const overlayName = resolveServiceName(service, ctx);\n if (hasCompatibleConstructor(overlayName, ctx)) {\n return overlayName;\n }\n // Incompatible constructor — fall back to IR name\n const irName = toPascalCase(service.name);\n if (irName === overlayName) {\n return irName + 'Endpoints';\n }\n return irName;\n}\n\n/** Standard pagination query params handled by PaginationOptions — not imported individually. */\nconst PAGINATION_PARAM_NAMES = new Set(['limit', 'before', 'after', 'order']);\n\n/** Map HTTP status codes to their corresponding exception class names for @throws docs. */\nconst STATUS_TO_EXCEPTION_NAME: Record<number, string> = {\n 400: 'BadRequestException',\n 401: 'UnauthorizedException',\n 404: 'NotFoundException',\n 409: 'ConflictException',\n 422: 'UnprocessableEntityException',\n 429: 'RateLimitExceededException',\n};\n\n/**\n * Compute the options interface name for a paginated method.\n * When the method name is simply \"list\", prefix with the service name to avoid\n * naming collisions at barrel-export level (e.g. \"ConnectionsListOptions\"\n * instead of the generic \"ListOptions\").\n */\nfunction paginatedOptionsName(method: string, resolvedServiceName: string): string {\n if (method === 'list') {\n return `${toPascalCase(resolvedServiceName)}ListOptions`;\n }\n return toPascalCase(method) + 'Options';\n}\n\n/** HTTP methods that require a body argument even when the spec has no request body. */\nfunction httpMethodNeedsBody(method: string): boolean {\n return method === 'post' || method === 'put' || method === 'patch';\n}\n\n// ---------------------------------------------------------------------------\n// Method-name reconciliation helpers\n// ---------------------------------------------------------------------------\n\n/** Map HTTP methods to expected CRUD verb prefixes for method name matching. */\nconst HTTP_VERB_PREFIXES: Record<string, string[]> = {\n get: ['list', 'get', 'fetch', 'retrieve', 'find'],\n post: ['create', 'add', 'insert', 'send'],\n put: ['set', 'update', 'replace', 'put'],\n patch: ['update', 'patch', 'modify'],\n delete: ['delete', 'remove', 'revoke'],\n};\n\n/** Split a camelCase/PascalCase name into lowercase word parts. */\nfunction splitCamelWords(name: string): string[] {\n const parts: string[] = [];\n let start = 0;\n for (let i = 1; i < name.length; i++) {\n if (name[i] >= 'A' && name[i] <= 'Z') {\n parts.push(name.slice(start, i).toLowerCase());\n start = i;\n }\n }\n parts.push(name.slice(start).toLowerCase());\n return parts;\n}\n\n/** Naive singularize: strip trailing 's' unless it ends in 'ss'. */\nfunction singularize(word: string): string {\n return word.endsWith('s') && !word.endsWith('ss') ? word.slice(0, -1) : word;\n}\n\n/**\n * Batch-reconcile generated method names against the api-surface class methods.\n *\n * When the overlay doesn't map an operation (missing from previous manifest or\n * fuzzy-matching failed), the emitter falls back to the spec-derived name which\n * often doesn't match the hand-written SDK. This function uses three passes\n * with progressive exclusion to find the best surface match:\n *\n * 1. **Overlay-resolved** — already correct, mark as taken.\n * 2. **Word-set match** — same content words regardless of order (handles\n * `listRolesOrganizations` ↔ `listOrganizationRoles`).\n * 3. **Path-context match** — all surface-method content words appear in the\n * operation's URL path segments (handles `findById` ↔ `getResource`).\n *\n * After each pass, matched surface methods are removed from the pool so that\n * ambiguous cases (e.g., `listEnvironmentRoles` vs `listOrganizationRoles`)\n * resolve by elimination.\n */\nfunction reconcileMethodNames(\n plans: Array<{ op: Operation; plan: OperationPlan; method: string }>,\n service: Service,\n ctx: EmitterContext,\n): void {\n const className = resolveResourceClassName(service, ctx);\n const classMethods = ctx.apiSurface?.classes?.[className]?.methods;\n if (!classMethods) return;\n\n const available = new Set(Object.keys(classMethods));\n const resolved = new Map<(typeof plans)[number], string>();\n\n // Exclude surface methods that are overlay-mapped by OTHER services'\n // operations. This prevents the reconciliation from stealing methods\n // that belong to a different service (e.g., `createPermission` belongs\n // to the Permissions service, not the Authorization service).\n const thisServicePaths = new Set(service.operations.map((op) => op.path));\n if (ctx.overlayLookup?.methodByOperation) {\n for (const [httpKey, info] of ctx.overlayLookup.methodByOperation) {\n if (info.className !== className) continue; // different class\n const path = httpKey.split(' ')[1];\n if (thisServicePaths.has(path)) continue; // same service\n // This method is mapped to an operation in a different service\n available.delete(info.methodName);\n }\n }\n\n // Determine which plans are already overlay-resolved\n const overlayResolved = new Set<(typeof plans)[number]>();\n for (const plan of plans) {\n const httpKey = `${plan.op.httpMethod.toUpperCase()} ${plan.op.path}`;\n if (ctx.overlayLookup?.methodByOperation?.get(httpKey)) {\n overlayResolved.add(plan);\n if (available.has(plan.method)) {\n resolved.set(plan, plan.method);\n available.delete(plan.method);\n }\n }\n }\n\n // Helper: check verb compatibility.\n // When specVerb is provided, require the surface method to use the same verb\n // subgroup (e.g., \"list\" operations only match \"list\" methods, not \"get\").\n const verbMatches = (methodName: string, httpMethod: string, specVerb?: string): boolean => {\n const prefixes = HTTP_VERB_PREFIXES[httpMethod] ?? [];\n const lower = methodName.toLowerCase();\n if (!prefixes.some((p) => lower.startsWith(p))) return false;\n if (specVerb) {\n const surfaceVerb = splitCamelWords(methodName)[0];\n // \"list\" is a distinct verb subgroup from \"get/find/fetch/retrieve\"\n if (specVerb === 'list' && surfaceVerb !== 'list') return false;\n if (specVerb !== 'list' && surfaceVerb === 'list') return false;\n }\n return true;\n };\n\n // Pass 1: Word-set matching (handles word-order differences)\n for (const plan of plans) {\n if (resolved.has(plan)) continue;\n const specVerb = splitCamelWords(plan.method)[0];\n const specWords = splitCamelWords(plan.method).slice(1).map(singularize); // skip verb\n const specSet = new Set(specWords);\n if (specSet.size === 0) continue;\n\n let match: string | null = null;\n for (const name of available) {\n if (!verbMatches(name, plan.op.httpMethod, specVerb)) continue;\n const methodWords = splitCamelWords(name).slice(1).map(singularize);\n if (methodWords.length !== specWords.length) continue;\n const methodSet = new Set(methodWords);\n if (specSet.size === methodSet.size && [...specSet].every((w) => methodSet.has(w))) {\n if (match !== null) {\n match = null; // ambiguous — more than one match\n break;\n }\n match = name;\n }\n }\n if (match) {\n resolved.set(plan, match);\n available.delete(match);\n }\n }\n\n // Pass 2: Path-context matching (handles different naming e.g., findById → getResource)\n // To avoid false matches (e.g., `createPermission` matching a role-permission path\n // just because \"permission\" appears somewhere in the URL), require that the method's\n // content words reference the LEAF resource of the path, not just any segment.\n for (const plan of plans) {\n if (resolved.has(plan)) continue;\n const specVerb = splitCamelWords(plan.method)[0];\n const pathSegments = plan.op.path.split('/').filter((s) => s && !s.startsWith('{'));\n const pathWords = new Set(pathSegments.flatMap((s) => s.split('_')).map(singularize));\n // The \"leaf\" words come from the last non-param segment — the most specific resource.\n let bestMatch: string | null = null;\n let bestLen = 0;\n let ambiguous = false;\n for (const name of available) {\n if (!verbMatches(name, plan.op.httpMethod, specVerb)) continue;\n const methodWords = splitCamelWords(name).slice(1).map(singularize);\n if (methodWords.length === 0) continue;\n // All method content words must appear in path context\n if (!methodWords.every((w) => pathWords.has(w))) continue;\n // For paths with 3+ non-param segments (nested sub-resources like\n // /authorization/roles/{slug}/permissions), require at least 2 content\n // words. A single-word method like `createPermission` should only match\n // a top-level path like /authorization/permissions, not a nested one.\n if (methodWords.length < 2 && pathSegments.length > 2) continue;\n if (methodWords.length > bestLen) {\n bestMatch = name;\n bestLen = methodWords.length;\n ambiguous = false;\n } else if (methodWords.length === bestLen) {\n ambiguous = true;\n }\n }\n if (bestMatch && !ambiguous) {\n resolved.set(plan, bestMatch);\n available.delete(bestMatch);\n }\n }\n\n // Pass 3: Retry word-set and path-context for still-unresolved plans\n // (earlier passes may have eliminated ambiguous candidates)\n for (const plan of plans) {\n if (resolved.has(plan)) continue;\n const specVerb = splitCamelWords(plan.method)[0];\n\n // Retry word-set\n const specWords = splitCamelWords(plan.method).slice(1).map(singularize);\n const specSet = new Set(specWords);\n let match: string | null = null;\n for (const name of available) {\n if (!verbMatches(name, plan.op.httpMethod, specVerb)) continue;\n const methodWords = splitCamelWords(name).slice(1).map(singularize);\n if (methodWords.length !== specWords.length) continue;\n const methodSet = new Set(methodWords);\n if (specSet.size === methodSet.size && [...specSet].every((w) => methodSet.has(w))) {\n if (match !== null) {\n match = null;\n break;\n }\n match = name;\n }\n }\n if (match) {\n resolved.set(plan, match);\n available.delete(match);\n continue;\n }\n\n // Retry path-context (with leaf-word check)\n const pathSegments = plan.op.path.split('/').filter((s) => s && !s.startsWith('{'));\n const pathWords = new Set(pathSegments.flatMap((s) => s.split('_')).map(singularize));\n let bestMatch: string | null = null;\n let bestLen = 0;\n let ambiguous = false;\n for (const name of available) {\n if (!verbMatches(name, plan.op.httpMethod, specVerb)) continue;\n const methodWords = splitCamelWords(name).slice(1).map(singularize);\n if (methodWords.length === 0) continue;\n if (!methodWords.every((w) => pathWords.has(w))) continue;\n if (methodWords.length < 2 && pathSegments.length > 2) continue;\n if (methodWords.length > bestLen) {\n bestMatch = name;\n bestLen = methodWords.length;\n ambiguous = false;\n } else if (methodWords.length === bestLen) {\n ambiguous = true;\n }\n }\n if (bestMatch && !ambiguous) {\n resolved.set(plan, bestMatch);\n available.delete(bestMatch);\n }\n }\n\n // Apply resolved names (only for non-overlay plans)\n for (const plan of plans) {\n if (overlayResolved.has(plan)) continue;\n const name = resolved.get(plan);\n if (name) plan.method = name;\n }\n}\n\n/**\n * Deduplicate method names within the plans array.\n *\n * When `disambiguateOperationNames()` in `@workos/oagen` fails (e.g., for\n * single-segment paths like `/organizations`), two operations can resolve to\n * the same method name. Disambiguate by appending a path-derived suffix.\n */\nfunction deduplicateMethodNames(\n plans: Array<{ op: Operation; plan: OperationPlan; method: string }>,\n _ctx: EmitterContext,\n): void {\n const nameCount = new Map<string, number>();\n for (const p of plans) {\n nameCount.set(p.method, (nameCount.get(p.method) ?? 0) + 1);\n }\n\n for (const [name, count] of nameCount) {\n if (count <= 1) continue;\n const dupes = plans.filter((p) => p.method === name);\n\n // If all duplicates are on the SAME base path (different HTTP methods),\n // trust the names — they represent the same resource.\n const basePaths = new Set(dupes.map((d) => d.op.path.replace(/\\/\\{[^}]+\\}$/, '')));\n if (basePaths.size <= 1) continue;\n\n // Disambiguate: keep the name for the plan whose path best matches,\n // append path suffix for the others.\n // Score: how many words in the method name appear in the path segments\n const nameWords = new Set(splitCamelWords(name).map(singularize));\n const scored = dupes.map((d) => {\n const pathWords = d.op.path\n .split('/')\n .filter((s) => s && !s.startsWith('{'))\n .flatMap((s) => s.split('_'))\n .map(singularize);\n const overlap = pathWords.filter((w) => nameWords.has(w)).length;\n return { plan: d, score: overlap };\n });\n scored.sort((a, b) => b.score - a.score);\n\n // The best-scoring plan keeps the name; others get disambiguated\n for (let i = 1; i < scored.length; i++) {\n const dupe = scored[i].plan;\n const segments = dupe.op.path.split('/').filter((s) => s && !s.startsWith('{'));\n // Use first segment as suffix (the resource collection name)\n const suffix = segments[0] ?? '';\n if (suffix) {\n dupe.method = toCamelCase(`${name}_${suffix}`);\n }\n }\n\n // If still colliding after suffix, append index\n const stillDuped = new Map<string, typeof dupes>();\n for (const dupe of dupes) {\n const group = stillDuped.get(dupe.method) ?? [];\n group.push(dupe);\n stillDuped.set(dupe.method, group);\n }\n for (const [, group] of stillDuped) {\n if (group.length <= 1) continue;\n for (let i = 1; i < group.length; i++) {\n group[i].method = `${group[i].method}${i + 1}`;\n }\n }\n }\n}\n\nexport function generateResources(services: Service[], ctx: EmitterContext): GeneratedFile[] {\n if (services.length === 0) return [];\n const files: GeneratedFile[] = [];\n\n for (const service of services) {\n if (isServiceCoveredByExisting(service, ctx)) {\n // Fully covered: generate with ALL operations so the merger's docstring\n // refresh pass can update JSDoc on existing methods.\n const file = generateResourceClass(service, ctx);\n // When the baseline class is missing methods for some operations,\n // remove skipIfExists so the merger adds the new methods.\n if (hasMethodsAbsentFromBaseline(service, ctx)) {\n delete file.skipIfExists;\n }\n files.push(file);\n continue;\n }\n\n const ops = uncoveredOperations(service, ctx);\n if (ops.length === 0) continue;\n\n if (ops.length < service.operations.length) {\n // Partial coverage: generate with ALL operations so JSDoc is available\n // for both covered and uncovered methods. Remove skipIfExists so the\n // merger adds new methods AND refreshes existing JSDoc.\n const file = generateResourceClass(service, ctx);\n delete file.skipIfExists;\n files.push(file);\n } else {\n files.push(generateResourceClass(service, ctx));\n }\n }\n\n return files;\n}\n\nfunction generateResourceClass(service: Service, ctx: EmitterContext): GeneratedFile {\n const resolvedName = resolveResourceClassName(service, ctx);\n const serviceDir = resolveServiceDir(resolvedName);\n const serviceClass = resolvedName;\n const resourcePath = `src/${serviceDir}/${fileName(resolvedName)}.ts`;\n\n const plans = service.operations.map((op) => ({\n op,\n plan: planOperation(op),\n method: resolveMethodName(op, service, ctx),\n }));\n\n // Reconcile method names against the api-surface class methods.\n // This fixes cases where the overlay is missing mappings and the\n // spec-derived name doesn't match the hand-written SDK name.\n reconcileMethodNames(plans, service, ctx);\n\n // Deduplicate method names within the class (e.g., two operations both\n // resolving to \"create\" for different paths).\n deduplicateMethodNames(plans, ctx);\n\n // Sort plans to match the existing file's method order.\n // When the merger integrates generated content with existing files, its\n // URL-fingerprint fallback (pass 2) matches by position among methods that\n // share the same endpoint path. If the spec lists POST before GET for a\n // path (common in OpenAPI) but the existing class has them in a different\n // order, JSDoc comments get attached to the wrong methods (list↔create,\n // add↔set swaps). Sorting by the overlay's method order ensures the\n // generated output matches the existing file's method order.\n if (ctx.overlayLookup?.methodByOperation) {\n const methodOrder = new Map<string, number>();\n let pos = 0;\n for (const [, info] of ctx.overlayLookup.methodByOperation) {\n if (!methodOrder.has(info.methodName)) {\n methodOrder.set(info.methodName, pos++);\n }\n }\n if (methodOrder.size > 0) {\n plans.sort((a, b) => {\n const aPos = methodOrder.get(a.method) ?? Number.MAX_SAFE_INTEGER;\n const bPos = methodOrder.get(b.method) ?? Number.MAX_SAFE_INTEGER;\n return aPos - bPos;\n });\n }\n }\n\n const hasPaginated = plans.some((p) => p.plan.isPaginated);\n const modelMap = new Map(ctx.spec.models.map((m) => [m.name, m]));\n\n // Collect models for imports — only include models that are actually used\n // in method signatures (not all union variants from the spec)\n const responseModels = new Set<string>();\n const requestModels = new Set<string>();\n const paramEnums = new Set<string>();\n const paramModels = new Set<string>();\n for (const { op, plan } of plans) {\n if (plan.isPaginated && op.pagination?.itemType.kind === 'model') {\n // For paginated operations, import the item type (e.g., Connection)\n // rather than the list wrapper type (e.g., ConnectionList).\n // fetchAndDeserialize handles the list envelope internally.\n // The IR's itemType may point to a list wrapper model — unwrap to the actual item.\n let itemName = op.pagination.itemType.name;\n const itemModel = modelMap.get(itemName);\n if (itemModel) {\n const unwrapped = unwrapListModel(itemModel, modelMap);\n if (unwrapped) {\n itemName = unwrapped.name;\n }\n }\n responseModels.add(itemName);\n } else if (plan.responseModelName) {\n responseModels.add(plan.responseModelName);\n }\n // Import request body model(s) — handles both single models and union variants.\n const bodyInfo = extractRequestBodyType(op, ctx);\n if (bodyInfo?.kind === 'model') {\n requestModels.add(bodyInfo.name);\n } else if (bodyInfo?.kind === 'union') {\n if (bodyInfo.discriminator) {\n // Discriminated union: import variant models with serializers so we can\n // dispatch to the correct serializer at runtime based on the discriminator.\n for (const name of bodyInfo.modelNames) {\n requestModels.add(name);\n }\n } else {\n // Non-discriminated union: import variant models with serializers so we\n // can dispatch to the correct serializer at runtime via field guards.\n for (const name of bodyInfo.modelNames) {\n requestModels.add(name);\n }\n }\n }\n // Collect types referenced in query and path parameters.\n // For paginated operations, skip standard pagination params (limit, before, after, order)\n // since they're handled by PaginationOptions and don't need explicit imports.\n const queryParams = plan.isPaginated\n ? op.queryParams.filter((p) => !PAGINATION_PARAM_NAMES.has(p.name))\n : op.queryParams;\n for (const param of [...queryParams, ...op.pathParams]) {\n collectParamTypeRefs(param.type, paramEnums, paramModels);\n }\n }\n const allModels = new Set([...responseModels, ...requestModels, ...paramModels]);\n\n const lines: string[] = [];\n\n // Imports\n lines.push(\"import type { WorkOS } from '../workos';\");\n if (hasPaginated) {\n lines.push(\"import type { PaginationOptions } from '../common/interfaces/pagination-options.interface';\");\n lines.push(\"import type { AutoPaginatable } from '../common/utils/pagination';\");\n lines.push(\"import { createPaginatedList } from '../common/utils/fetch-and-deserialize';\");\n }\n\n // Check if any operation needs PostOptions (idempotent POST or custom encoding)\n const hasIdempotentPost = plans.some((p) => p.plan.isIdempotentPost);\n const hasCustomEncoding = plans.some(\n (p) => p.op.requestBodyEncoding && p.op.requestBodyEncoding !== 'json' && p.plan.hasBody,\n );\n if (hasIdempotentPost || hasCustomEncoding) {\n lines.push(\"import type { PostOptions } from '../common/interfaces/post-options.interface';\");\n }\n\n // Compute model-to-service mapping for correct cross-service import paths\n const { modelToService, resolveDir } = createServiceDirResolver(ctx.spec.models, ctx.spec.services, ctx);\n\n // Wire (Response) types are only needed for models used as response types in method signatures.\n // Request models and param models only need the domain type.\n const usedWireTypes = new Set<string>();\n for (const name of responseModels) {\n usedWireTypes.add(resolveInterfaceName(name, ctx));\n }\n\n // Track imported resolved names to prevent duplicate type name collisions\n const importedTypeNames = new Set<string>();\n for (const name of allModels) {\n const resolved = resolveInterfaceName(name, ctx);\n if (importedTypeNames.has(resolved)) continue; // Skip duplicate resolved names\n importedTypeNames.add(resolved);\n const modelDir = modelToService.get(name);\n const modelServiceDir = resolveDir(modelDir);\n const relPath =\n modelServiceDir === serviceDir\n ? `./interfaces/${fileName(name)}.interface`\n : `../${modelServiceDir}/interfaces/${fileName(name)}.interface`;\n if (usedWireTypes.has(resolved)) {\n lines.push(`import type { ${resolved}, ${wireInterfaceName(resolved)} } from '${relPath}';`);\n } else {\n lines.push(`import type { ${resolved} } from '${relPath}';`);\n }\n }\n\n // Collect serializer imports by module path so we can merge deserialize and\n // serialize imports from the same module into a single import statement.\n const serializerImportsByPath = new Map<string, string[]>();\n\n const importedDeserializers = new Set<string>();\n for (const name of responseModels) {\n const resolved = resolveInterfaceName(name, ctx);\n if (importedDeserializers.has(resolved)) continue;\n importedDeserializers.add(resolved);\n const modelDir = modelToService.get(name);\n const modelServiceDir = resolveDir(modelDir);\n const relPath =\n modelServiceDir === serviceDir\n ? `./serializers/${fileName(name)}.serializer`\n : `../${modelServiceDir}/serializers/${fileName(name)}.serializer`;\n const existing = serializerImportsByPath.get(relPath) ?? [];\n existing.push(`deserialize${resolved}`);\n serializerImportsByPath.set(relPath, existing);\n }\n\n const importedSerializers = new Set<string>();\n for (const name of requestModels) {\n const resolved = resolveInterfaceName(name, ctx);\n if (importedSerializers.has(resolved)) continue;\n importedSerializers.add(resolved);\n const modelDir = modelToService.get(name);\n const modelServiceDir = resolveDir(modelDir);\n const relPath =\n modelServiceDir === serviceDir\n ? `./serializers/${fileName(name)}.serializer`\n : `../${modelServiceDir}/serializers/${fileName(name)}.serializer`;\n const existing = serializerImportsByPath.get(relPath) ?? [];\n existing.push(`serialize${resolved}`);\n serializerImportsByPath.set(relPath, existing);\n }\n\n // Emit merged serializer imports\n for (const [relPath, specifiers] of serializerImportsByPath) {\n lines.push(`import { ${specifiers.join(', ')} } from '${relPath}';`);\n }\n\n // Build a set of global enum names — used to distinguish named enums (with files)\n // from inline enums (no file, must be rendered as string literal unions).\n const specEnumNames = new Set(ctx.spec.enums.map((e) => e.name));\n\n // Import enum types referenced in query/path parameters.\n // Only import enums that actually exist in the spec's global enums list —\n // inline string unions may have kind 'enum' but no corresponding file.\n if (paramEnums.size > 0) {\n const enumToService = assignEnumsToServices(ctx.spec.enums, ctx.spec.services);\n for (const name of paramEnums) {\n if (allModels.has(name)) continue; // Already imported as a model\n if (!specEnumNames.has(name)) continue; // No file generated for this enum\n const enumDir = enumToService.get(name);\n const enumServiceDir = resolveDir(enumDir);\n const relPath =\n enumServiceDir === serviceDir\n ? `./interfaces/${fileName(name)}.interface`\n : `../${enumServiceDir}/interfaces/${fileName(name)}.interface`;\n lines.push(`import type { ${name} } from '${relPath}';`);\n }\n }\n\n lines.push('');\n\n // Options interfaces for operations with query params.\n // Paginated operations extend PaginationOptions; non-paginated operations get standalone interfaces.\n for (const { op, plan, method } of plans) {\n if (plan.isPaginated) {\n const extraParams = op.queryParams.filter((p) => !PAGINATION_PARAM_NAMES.has(p.name));\n if (extraParams.length > 0) {\n const optionsName = paginatedOptionsName(method, resolvedName);\n // Always generate the options interface locally in the resource file.\n // Previously we skipped generation when a baseline interface with a matching\n // name existed, but the baseline interface may live in a different module\n // (e.g., `user-management/` vs `user-management-users/`) and would not be\n // available without an import. Generating locally is safe and avoids\n // cross-module import resolution issues.\n lines.push(`export interface ${optionsName} extends PaginationOptions {`);\n for (const param of extraParams) {\n const opt = !param.required ? '?' : '';\n if (param.description || param.deprecated) {\n const parts: string[] = [];\n if (param.description) parts.push(param.description);\n if (param.deprecated) parts.push('@deprecated');\n lines.push(...docComment(parts.join('\\n'), 2));\n }\n lines.push(` ${fieldName(param.name)}${opt}: ${mapParamType(param.type, specEnumNames)};`);\n }\n lines.push('}');\n lines.push('');\n }\n } else if (!plan.isPaginated && !plan.hasBody && !plan.isDelete && op.queryParams.length > 0) {\n // Non-paginated GET or void methods with query params get a typed options interface\n // instead of falling back to Record<string, unknown>.\n const optionsName = toPascalCase(method) + 'Options';\n lines.push(`export interface ${optionsName} {`);\n for (const param of op.queryParams) {\n const opt = !param.required ? '?' : '';\n if (param.description || param.deprecated) {\n const parts: string[] = [];\n if (param.description) parts.push(param.description);\n if (param.deprecated) parts.push('@deprecated');\n lines.push(...docComment(parts.join('\\n'), 2));\n }\n lines.push(` ${fieldName(param.name)}${opt}: ${mapParamType(param.type, specEnumNames)};`);\n }\n lines.push('}');\n lines.push('');\n }\n }\n\n // Resource class\n if (service.description) {\n lines.push(...docComment(service.description));\n }\n lines.push(`export class ${serviceClass} {`);\n lines.push(' constructor(private readonly workos: WorkOS) {}');\n\n for (const { op, plan, method } of plans) {\n lines.push('');\n lines.push(...renderMethod(op, plan, method, service, ctx, modelMap, specEnumNames));\n }\n\n lines.push('}');\n\n return { path: resourcePath, content: lines.join('\\n'), skipIfExists: true };\n}\n\nfunction renderMethod(\n op: Operation,\n plan: OperationPlan,\n method: string,\n service: Service,\n ctx: EmitterContext,\n modelMap: Map<string, Model>,\n specEnumNames?: Set<string>,\n): string[] {\n const lines: string[] = [];\n const responseModel = plan.responseModelName ? resolveInterfaceName(plan.responseModelName, ctx) : null;\n\n const pathStr = buildPathStr(op);\n\n // Build set of valid param names to filter @param tags.\n // Prefer the overlay (existing method signature) if available;\n // otherwise compute from what the render path will actually include.\n const httpKey = `${op.httpMethod.toUpperCase()} ${op.path}`;\n const overlayMethod = ctx.overlayLookup?.methodByOperation?.get(httpKey);\n let validParamNames: Set<string> | null = null;\n if (overlayMethod) {\n validParamNames = new Set(overlayMethod.params.map((p) => p.name));\n } else {\n // Compute actual params based on render path to avoid documenting params\n // that won't appear in the method signature\n const actualParams = new Set<string>();\n for (const p of op.pathParams) actualParams.add(fieldName(p.name));\n if (plan.hasBody) actualParams.add('payload');\n if (plan.isPaginated) actualParams.add('options');\n // renderGetMethod adds options when there are non-paginated query params\n if (!plan.isPaginated && op.queryParams.length > 0 && !plan.isDelete && responseModel) {\n actualParams.add('options');\n }\n validParamNames = actualParams;\n }\n\n const docParts: string[] = [];\n if (op.description) docParts.push(op.description);\n for (const param of op.pathParams) {\n const paramName = fieldName(param.name);\n if (validParamNames && !validParamNames.has(paramName)) continue;\n const deprecatedPrefix = param.deprecated ? '(deprecated) ' : '';\n if (param.description) {\n docParts.push(`@param ${paramName} - ${deprecatedPrefix}${param.description}`);\n } else if (param.deprecated) {\n docParts.push(`@param ${paramName} - (deprecated)`);\n }\n if (param.default !== undefined) docParts.push(`@default ${JSON.stringify(param.default)}`);\n if (param.example !== undefined) docParts.push(`@example ${JSON.stringify(param.example)}`);\n }\n // Document query params for non-paginated operations\n if (!plan.isPaginated) {\n // Only document query params if the method will have an options parameter\n if (validParamNames && (validParamNames.has('options') || overlayMethod)) {\n for (const param of op.queryParams) {\n const paramName = `options.${fieldName(param.name)}`;\n if (validParamNames && !validParamNames.has('options') && !validParamNames.has(fieldName(param.name))) continue;\n const deprecatedPrefix = param.deprecated ? '(deprecated) ' : '';\n if (param.description) {\n docParts.push(`@param ${paramName} - ${deprecatedPrefix}${param.description}`);\n } else if (param.deprecated) {\n docParts.push(`@param ${paramName} - (deprecated)`);\n }\n if (param.default !== undefined) docParts.push(`@default ${JSON.stringify(param.default)}`);\n if (param.example !== undefined) docParts.push(`@example ${JSON.stringify(param.example)}`);\n }\n }\n }\n // Skip header and cookie params in JSDoc — they are not exposed in the method signature.\n // The SDK handles headers and cookies internally, so documenting them would be misleading.\n // Document payload parameter when there is a request body\n if (plan.hasBody) {\n const bodyInfo = extractRequestBodyType(op, ctx);\n if (bodyInfo?.kind === 'model') {\n const bodyModel = ctx.spec.models.find((m) => m.name === bodyInfo.name);\n let payloadDesc: string;\n if (bodyModel?.description) {\n payloadDesc = `@param payload - ${bodyModel.description}`;\n } else if (bodyModel) {\n // When the model lacks a description, list its required fields to help\n // callers understand what must be provided.\n const requiredFieldNames = bodyModel.fields.filter((f) => f.required).map((f) => fieldName(f.name));\n payloadDesc =\n requiredFieldNames.length > 0\n ? `@param payload - Object containing ${requiredFieldNames.join(', ')}.`\n : '@param payload - The request body.';\n } else {\n payloadDesc = '@param payload - The request body.';\n }\n docParts.push(payloadDesc);\n } else {\n docParts.push('@param payload - The request body.');\n }\n }\n // Document options parameter for paginated operations\n if (plan.isPaginated) {\n docParts.push('@param options - Pagination and filter options.');\n } else if (op.queryParams.length > 0) {\n docParts.push('@param options - Additional query options.');\n }\n // @returns for the primary response model (use item type for paginated operations).\n // Unwrap list wrapper models to match the actual return type — the method returns\n // AutoPaginatable<ItemType>, not the list wrapper.\n if (plan.isPaginated && op.pagination?.itemType.kind === 'model') {\n let itemRawName = op.pagination.itemType.name;\n const pModel = modelMap.get(itemRawName);\n if (pModel) {\n const unwrapped = unwrapListModel(pModel, modelMap);\n if (unwrapped) itemRawName = unwrapped.name;\n }\n const itemTypeName = resolveInterfaceName(itemRawName, ctx);\n docParts.push(`@returns {AutoPaginatable<${itemTypeName}>}`);\n } else if (responseModel) {\n docParts.push(`@returns {${responseModel}}`);\n } else {\n docParts.push('@returns {void}');\n }\n // @throws for error responses\n for (const err of op.errors) {\n const exceptionName = STATUS_TO_EXCEPTION_NAME[err.statusCode];\n if (exceptionName) {\n docParts.push(`@throws {${exceptionName}} ${err.statusCode}`);\n }\n }\n if (op.deprecated) docParts.push('@deprecated');\n\n if (docParts.length > 0) {\n // Flatten all parts, splitting multiline descriptions into individual lines\n const allLines: string[] = [];\n for (const part of docParts) {\n for (const line of part.split('\\n')) {\n allLines.push(line);\n }\n }\n if (allLines.length === 1) {\n lines.push(` /** ${allLines[0]} */`);\n } else {\n lines.push(' /**');\n for (const line of allLines) {\n lines.push(line === '' ? ' *' : ` * ${line}`);\n }\n lines.push(' */');\n }\n }\n\n const preDecisionCount = lines.length;\n\n if (plan.isPaginated && op.pagination && op.httpMethod === 'get') {\n // For paginated operations, use the item type from pagination metadata\n // (e.g., Connection) rather than the list wrapper type (e.g., ConnectionList).\n // Unwrap list wrapper models to get the actual item type name.\n let paginatedItemRawName = op.pagination.itemType.kind === 'model' ? op.pagination.itemType.name : null;\n if (paginatedItemRawName) {\n const pModel = modelMap.get(paginatedItemRawName);\n if (pModel) {\n const unwrapped = unwrapListModel(pModel, modelMap);\n if (unwrapped) {\n paginatedItemRawName = unwrapped.name;\n }\n }\n }\n const paginatedItemType = paginatedItemRawName ? resolveInterfaceName(paginatedItemRawName, ctx) : responseModel;\n if (paginatedItemType) {\n const resolvedServiceNameForPaginated = resolveServiceName(service, ctx);\n renderPaginatedMethod(\n lines,\n op,\n plan,\n method,\n paginatedItemType,\n pathStr,\n resolvedServiceNameForPaginated,\n specEnumNames,\n );\n }\n } else if (plan.isPaginated && plan.hasBody && responseModel) {\n // Non-GET paginated operation (e.g., PUT with list response) — treat as body method\n renderBodyMethod(lines, op, plan, method, responseModel, pathStr, ctx, specEnumNames);\n } else if (plan.isDelete && plan.hasBody) {\n renderDeleteWithBodyMethod(lines, op, plan, method, pathStr, ctx, specEnumNames);\n } else if (plan.isDelete) {\n renderDeleteMethod(lines, op, plan, method, pathStr, specEnumNames);\n } else if (plan.hasBody && responseModel) {\n renderBodyMethod(lines, op, plan, method, responseModel, pathStr, ctx, specEnumNames);\n } else if (responseModel) {\n renderGetMethod(lines, op, plan, method, responseModel, pathStr, specEnumNames);\n } else {\n renderVoidMethod(lines, op, plan, method, pathStr, ctx, specEnumNames);\n }\n\n // Defensive: if no render function produced a method body, emit a stub\n if (lines.length === preDecisionCount) {\n const params = buildPathParams(op, specEnumNames);\n lines.push(` async ${method}(${params}): Promise<void> {`);\n lines.push(\n ` await this.workos.${op.httpMethod}(${pathStr}${httpMethodNeedsBody(op.httpMethod) ? ', {}' : ''});`,\n );\n lines.push(' }');\n }\n\n return lines;\n}\n\nfunction renderPaginatedMethod(\n lines: string[],\n op: Operation,\n plan: OperationPlan,\n method: string,\n itemType: string,\n pathStr: string,\n resolvedServiceName: string,\n specEnumNames?: Set<string>,\n): void {\n const extraParams = op.queryParams.filter((p) => !PAGINATION_PARAM_NAMES.has(p.name));\n const optionsType = extraParams.length > 0 ? paginatedOptionsName(method, resolvedServiceName) : 'PaginationOptions';\n\n const pathParams = buildPathParams(op, specEnumNames);\n const allParams = pathParams ? `${pathParams}, options?: ${optionsType}` : `options?: ${optionsType}`;\n\n lines.push(` async ${method}(${allParams}): Promise<AutoPaginatable<${itemType}, ${optionsType}>> {`);\n lines.push(\n ` return createPaginatedList<${wireInterfaceName(itemType)}, ${itemType}, ${optionsType}>(this.workos, ${pathStr}, deserialize${itemType}, options);`,\n );\n lines.push(' }');\n}\n\nfunction renderDeleteMethod(\n lines: string[],\n op: Operation,\n plan: OperationPlan,\n method: string,\n pathStr: string,\n specEnumNames?: Set<string>,\n): void {\n const params = buildPathParams(op, specEnumNames);\n lines.push(` async ${method}(${params}): Promise<void> {`);\n lines.push(` await this.workos.delete(${pathStr});`);\n lines.push(' }');\n}\n\nfunction renderDeleteWithBodyMethod(\n lines: string[],\n op: Operation,\n plan: OperationPlan,\n method: string,\n pathStr: string,\n ctx: EmitterContext,\n specEnumNames?: Set<string>,\n): void {\n const bodyInfo = extractRequestBodyType(op, ctx);\n let requestType: string;\n let bodyExpr: string;\n if (bodyInfo?.kind === 'model') {\n requestType = resolveInterfaceName(bodyInfo.name, ctx);\n bodyExpr = `serialize${requestType}(payload)`;\n } else if (bodyInfo?.kind === 'union') {\n requestType = bodyInfo.typeStr;\n if (bodyInfo.discriminator) {\n bodyExpr = renderUnionBodySerializer(bodyInfo.discriminator, ctx);\n } else {\n bodyExpr = renderNonDiscriminatedUnionBodySerializer(bodyInfo.modelNames, ctx);\n }\n } else {\n requestType = 'Record<string, unknown>';\n bodyExpr = 'payload';\n }\n\n const paramParts: string[] = [];\n for (const param of op.pathParams) {\n paramParts.push(\n `${fieldName(param.name)}: ${specEnumNames ? mapParamType(param.type, specEnumNames) : mapTypeRef(param.type)}`,\n );\n }\n paramParts.push(`payload: ${requestType}`);\n\n lines.push(` async ${method}(${paramParts.join(', ')}): Promise<void> {`);\n lines.push(` await this.workos.deleteWithBody(${pathStr}, ${bodyExpr});`);\n lines.push(' }');\n}\n\nfunction renderBodyMethod(\n lines: string[],\n op: Operation,\n plan: OperationPlan,\n method: string,\n responseModel: string,\n pathStr: string,\n ctx: EmitterContext,\n specEnumNames?: Set<string>,\n): void {\n const bodyInfo = extractRequestBodyType(op, ctx);\n let requestType: string;\n let bodyExpr: string;\n if (bodyInfo?.kind === 'model') {\n requestType = resolveInterfaceName(bodyInfo.name, ctx);\n bodyExpr = `serialize${requestType}(payload)`;\n } else if (bodyInfo?.kind === 'union') {\n requestType = bodyInfo.typeStr;\n if (bodyInfo.discriminator) {\n bodyExpr = renderUnionBodySerializer(bodyInfo.discriminator, ctx);\n } else {\n bodyExpr = renderNonDiscriminatedUnionBodySerializer(bodyInfo.modelNames, ctx);\n }\n } else {\n requestType = 'Record<string, unknown>';\n bodyExpr = 'payload';\n }\n\n const paramParts: string[] = [];\n\n // Always pass path params as individual parameters (matches existing SDK pattern)\n for (const param of op.pathParams) {\n paramParts.push(\n `${fieldName(param.name)}: ${specEnumNames ? mapParamType(param.type, specEnumNames) : mapTypeRef(param.type)}`,\n );\n }\n\n paramParts.push(`payload: ${requestType}`);\n\n if (plan.isIdempotentPost) {\n paramParts.push('requestOptions: PostOptions = {}');\n }\n\n const paramsStr = paramParts.join(', ');\n\n // Fix 2: Pass encoding option when requestBodyEncoding is non-json\n const encoding = op.requestBodyEncoding;\n const encodingOption = encoding && encoding !== 'json' ? `, encoding: '${encoding}' as const` : '';\n const hasCustomEncoding = encodingOption !== '';\n\n lines.push(` async ${method}(${paramsStr}): Promise<${responseModel}> {`);\n if (plan.isIdempotentPost) {\n if (hasCustomEncoding) {\n lines.push(` const { data } = await this.workos.${op.httpMethod}<${wireInterfaceName(responseModel)}>(`);\n lines.push(` ${pathStr},`);\n lines.push(` ${bodyExpr},`);\n lines.push(` { ...requestOptions${encodingOption} },`);\n lines.push(' );');\n } else {\n lines.push(` const { data } = await this.workos.${op.httpMethod}<${wireInterfaceName(responseModel)}>(`);\n lines.push(` ${pathStr},`);\n lines.push(` ${bodyExpr},`);\n lines.push(' requestOptions,');\n lines.push(' );');\n }\n } else {\n if (hasCustomEncoding) {\n lines.push(` const { data } = await this.workos.${op.httpMethod}<${wireInterfaceName(responseModel)}>(`);\n lines.push(` ${pathStr},`);\n lines.push(` ${bodyExpr},`);\n lines.push(` { ${encodingOption.slice(2)} },`);\n lines.push(' );');\n } else {\n lines.push(` const { data } = await this.workos.${op.httpMethod}<${wireInterfaceName(responseModel)}>(`);\n lines.push(` ${pathStr},`);\n lines.push(` ${bodyExpr},`);\n lines.push(' );');\n }\n }\n lines.push(` return deserialize${responseModel}(data);`);\n lines.push(' }');\n}\n\nfunction renderGetMethod(\n lines: string[],\n op: Operation,\n plan: OperationPlan,\n method: string,\n responseModel: string,\n pathStr: string,\n specEnumNames?: Set<string>,\n): void {\n const params = buildPathParams(op, specEnumNames);\n const hasQuery = op.queryParams.length > 0 && !plan.isPaginated;\n const optionsType = hasQuery ? toPascalCase(method) + 'Options' : null;\n\n const allParams = hasQuery ? (params ? `${params}, options?: ${optionsType}` : `options?: ${optionsType}`) : params;\n\n lines.push(` async ${method}(${allParams}): Promise<${responseModel}> {`);\n if (hasQuery) {\n const queryExpr = renderQueryExpr(op.queryParams);\n lines.push(\n ` const { data } = await this.workos.${op.httpMethod}<${wireInterfaceName(responseModel)}>(${pathStr}, {`,\n );\n lines.push(` query: ${queryExpr},`);\n lines.push(' });');\n } else if (httpMethodNeedsBody(op.httpMethod)) {\n // PUT/PATCH/POST require a body argument even when the spec has no request body\n lines.push(\n ` const { data } = await this.workos.${op.httpMethod}<${wireInterfaceName(responseModel)}>(${pathStr}, {});`,\n );\n } else {\n lines.push(\n ` const { data } = await this.workos.${op.httpMethod}<${wireInterfaceName(responseModel)}>(${pathStr});`,\n );\n }\n lines.push(` return deserialize${responseModel}(data);`);\n lines.push(' }');\n}\n\nfunction renderVoidMethod(\n lines: string[],\n op: Operation,\n plan: OperationPlan,\n method: string,\n pathStr: string,\n ctx: EmitterContext,\n specEnumNames?: Set<string>,\n): void {\n const params = buildPathParams(op, specEnumNames);\n const hasQuery = op.queryParams.length > 0 && !plan.hasBody;\n const optionsType = hasQuery ? toPascalCase(method) + 'Options' : null;\n\n let bodyParam = '';\n let bodyExpr = 'payload';\n if (plan.hasBody) {\n const bodyInfo = extractRequestBodyType(op, ctx);\n if (bodyInfo?.kind === 'model') {\n const requestType = resolveInterfaceName(bodyInfo.name, ctx);\n bodyParam = `payload: ${requestType}`;\n bodyExpr = `serialize${requestType}(payload)`;\n } else if (bodyInfo?.kind === 'union') {\n bodyParam = `payload: ${bodyInfo.typeStr}`;\n if (bodyInfo.discriminator) {\n bodyExpr = renderUnionBodySerializer(bodyInfo.discriminator, ctx);\n } else {\n bodyExpr = renderNonDiscriminatedUnionBodySerializer(bodyInfo.modelNames, ctx);\n }\n } else {\n bodyParam = 'payload: Record<string, unknown>';\n bodyExpr = 'payload';\n }\n }\n\n const paramParts: string[] = [];\n if (params) paramParts.push(params);\n if (bodyParam) paramParts.push(bodyParam);\n if (optionsType) paramParts.push(`options?: ${optionsType}`);\n const allParams = paramParts.join(', ');\n\n lines.push(` async ${method}(${allParams}): Promise<void> {`);\n if (plan.hasBody) {\n lines.push(` await this.workos.${op.httpMethod}(${pathStr}, ${bodyExpr});`);\n } else if (hasQuery) {\n const queryExpr = renderQueryExpr(op.queryParams);\n lines.push(` await this.workos.${op.httpMethod}(${pathStr}, {`);\n lines.push(` query: ${queryExpr},`);\n lines.push(' });');\n } else if (httpMethodNeedsBody(op.httpMethod)) {\n lines.push(` await this.workos.${op.httpMethod}(${pathStr}, {});`);\n } else {\n lines.push(` await this.workos.${op.httpMethod}(${pathStr});`);\n }\n lines.push(' }');\n}\n\n/**\n * Generate an inline query serialization expression that maps camelCase option\n * keys to their snake_case wire equivalents. When all keys already match\n * (camel === snake), returns 'options' as-is for brevity.\n */\nfunction renderQueryExpr(queryParams: { name: string; required: boolean }[]): string {\n // Check if any key actually needs conversion\n const needsConversion = queryParams.some((p) => fieldName(p.name) !== wireFieldName(p.name));\n if (!needsConversion) return 'options';\n\n const parts: string[] = [];\n for (const param of queryParams) {\n const camel = fieldName(param.name);\n const snake = wireFieldName(param.name);\n if (param.required) {\n parts.push(`${snake}: options.${camel}`);\n } else {\n parts.push(`...(options.${camel} !== undefined && { ${snake}: options.${camel} })`);\n }\n }\n return `options ? { ${parts.join(', ')} } : undefined`;\n}\n\nfunction buildPathStr(op: Operation): string {\n const interpolated = op.path.replace(/\\{(\\w+)\\}/g, (_, p) => `\\${${fieldName(p)}}`);\n return interpolated.includes('${') ? `\\`${interpolated}\\`` : `'${op.path}'`;\n}\n\nfunction buildPathParams(op: Operation, specEnumNames?: Set<string>): string {\n // Start with declared path params\n const declaredNames = new Set(op.pathParams.map((p) => fieldName(p.name)));\n const params = op.pathParams.map((p) => {\n const type = specEnumNames ? mapParamType(p.type, specEnumNames) : mapTypeRef(p.type);\n return `${fieldName(p.name)}: ${type}`;\n });\n\n // Detect path template variables not in declared pathParams and add them as string params.\n // This handles cases where the spec path has {param} but pathParams is incomplete.\n const templateVars = [...op.path.matchAll(/\\{(\\w+)\\}/g)].map(([, name]) => fieldName(name));\n for (const varName of templateVars) {\n if (!declaredNames.has(varName)) {\n params.push(`${varName}: string`);\n }\n }\n\n return params.join(', ');\n}\n\n/**\n * Walk a parameter's type tree and collect enum/model names for imports.\n * Handles arrays and nullable wrappers that may contain nested enums/models.\n */\nfunction collectParamTypeRefs(type: TypeRef, enums: Set<string>, models: Set<string>): void {\n switch (type.kind) {\n case 'enum':\n enums.add(type.name);\n break;\n case 'model':\n models.add(type.name);\n break;\n case 'array':\n collectParamTypeRefs(type.items, enums, models);\n break;\n case 'nullable':\n collectParamTypeRefs(type.inner, enums, models);\n break;\n }\n}\n\n/**\n * Extract request body type info, supporting both single models and union types.\n * Returns structured info so callers can handle imports and serialization appropriately.\n */\n/**\n * Generate an IIFE expression that dispatches to the correct serializer for a\n * discriminated union request body. Switches on the camelCase discriminator\n * property of the domain object and calls the appropriate serialize function\n * for each mapped model variant.\n */\nfunction renderUnionBodySerializer(\n disc: { property: string; mapping: Record<string, string> },\n ctx: EmitterContext,\n): string {\n const prop = fieldName(disc.property);\n const cases: string[] = [];\n for (const [value, modelName] of Object.entries(disc.mapping)) {\n const resolved = resolveInterfaceName(modelName, ctx);\n cases.push(`case '${value}': return serialize${resolved}(payload as any)`);\n }\n return `(() => { switch ((payload as any).${prop}) { ${cases.join('; ')}; default: return payload } })()`;\n}\n\n/**\n * Generate an IIFE expression that dispatches to the correct serializer for a\n * non-discriminated union request body. Inspects model fields to find a\n * required field unique to each variant and uses `'field' in payload` guards.\n * Falls back to `payload` only when no variant can be distinguished.\n */\nfunction renderNonDiscriminatedUnionBodySerializer(modelNames: string[], ctx: EmitterContext): string {\n const modelMap = new Map(ctx.spec.models.map((m) => [m.name, m]));\n\n // Try to detect an implicit discriminator: a required field present in all\n // variants whose type is `kind: 'literal'` with a distinct value per variant.\n // This covers oneOf unions where each variant has e.g. `grant_type: 'authorization_code'`.\n const implicitDisc = detectImplicitDiscriminator(modelNames, modelMap);\n if (implicitDisc) {\n return renderUnionBodySerializer(implicitDisc, ctx);\n }\n\n // Collect required field names per model (using camelCase domain names).\n const requiredFieldsByModel = new Map<string, Set<string>>();\n for (const name of modelNames) {\n const model = modelMap.get(name);\n if (!model) return 'payload';\n requiredFieldsByModel.set(name, new Set(model.fields.filter((f) => f.required).map((f) => fieldName(f.name))));\n }\n\n // For each model, find a required field that no other model has.\n const guards: Array<{ modelName: string; field: string }> = [];\n let fallbackModel: string | undefined;\n\n for (const name of modelNames) {\n const myFields = requiredFieldsByModel.get(name)!;\n let uniqueField: string | undefined;\n for (const field of myFields) {\n const isUnique = modelNames.every((other) => other === name || !requiredFieldsByModel.get(other)?.has(field));\n if (isUnique) {\n uniqueField = field;\n break;\n }\n }\n if (uniqueField) {\n guards.push({ modelName: name, field: uniqueField });\n } else if (!fallbackModel) {\n fallbackModel = name;\n } else {\n // Multiple models with no unique field — can't dispatch\n return 'payload';\n }\n }\n\n if (guards.length === 0) return 'payload';\n\n const parts: string[] = [];\n for (const { modelName, field } of guards) {\n const resolved = resolveInterfaceName(modelName, ctx);\n parts.push(`if ('${field}' in payload) return serialize${resolved}(payload as any)`);\n }\n if (fallbackModel) {\n const resolved = resolveInterfaceName(fallbackModel, ctx);\n parts.push(`return serialize${resolved}(payload as any)`);\n } else {\n parts.push('return payload');\n }\n\n return `(() => { ${parts.join('; ')} })()`;\n}\n\n/**\n * Detect an implicit discriminator from literal-typed fields.\n * Returns a discriminator descriptor if all variants share a required field\n * whose type is `kind: 'literal'` with a distinct value per variant.\n */\nfunction detectImplicitDiscriminator(\n modelNames: string[],\n modelMap: Map<string, Model>,\n): { property: string; mapping: Record<string, string> } | null {\n if (modelNames.length < 2) return null;\n\n const firstModel = modelMap.get(modelNames[0]);\n if (!firstModel) return null;\n\n // Candidate fields: required fields with literal type in the first model.\n const candidates = firstModel.fields.filter((f) => f.required && f.type.kind === 'literal');\n\n for (const candidate of candidates) {\n const mapping: Record<string, string> = {};\n const values = new Set<string | number | boolean | null>();\n let valid = true;\n\n for (const name of modelNames) {\n const model = modelMap.get(name);\n if (!model) {\n valid = false;\n break;\n }\n const field = model.fields.find((f) => f.name === candidate.name);\n if (!field || !field.required || field.type.kind !== 'literal') {\n valid = false;\n break;\n }\n const val = field.type.value;\n if (values.has(val)) {\n valid = false;\n break;\n } // duplicate value\n values.add(val);\n mapping[String(val)] = name;\n }\n\n if (valid && Object.keys(mapping).length === modelNames.length) {\n return { property: candidate.name, mapping };\n }\n }\n\n return null;\n}\n\n/** Return type for extractRequestBodyType when the body is a union. */\ninterface UnionBodyInfo {\n kind: 'union';\n typeStr: string;\n modelNames: string[];\n discriminator?: { property: string; mapping: Record<string, string> };\n}\n\nfunction extractRequestBodyType(\n op: Operation,\n ctx: EmitterContext,\n): { kind: 'model'; name: string } | UnionBodyInfo | null {\n if (!op.requestBody) return null;\n if (op.requestBody.kind === 'model') return { kind: 'model', name: op.requestBody.name };\n if (op.requestBody.kind === 'union') {\n const modelNames: string[] = [];\n for (const variant of op.requestBody.variants) {\n if (variant.kind === 'model') modelNames.push(variant.name);\n }\n if (modelNames.length > 0) {\n const typeStr = modelNames.map((n) => resolveInterfaceName(n, ctx)).join(' | ');\n return {\n kind: 'union',\n typeStr,\n modelNames,\n discriminator: op.requestBody.discriminator,\n };\n }\n }\n return null;\n}\n\n/**\n * Map a parameter type to a TypeScript type string, handling inline enums\n * that don't have corresponding global enum definitions. These would\n * otherwise emit bare names like `Type` or `Action` that are never imported.\n *\n * Recursively handles container types (arrays, nullable) so that inline\n * enums nested inside e.g. `array<enum>` are also inlined as string literal unions.\n */\nfunction mapParamType(type: TypeRef, specEnumNames: Set<string>): string {\n if (type.kind === 'enum' && !specEnumNames.has(type.name)) {\n // Inline enum with no generated file — render values as string literal union\n if (type.values && type.values.length > 0) {\n return type.values.map((v: string | number) => (typeof v === 'string' ? `'${v}'` : String(v))).join(' | ');\n }\n return 'string';\n }\n if (type.kind === 'array') {\n const inner = mapParamType(type.items, specEnumNames);\n // Parenthesize union types when used as array element type\n return inner.includes(' | ') ? `(${inner})[]` : `${inner}[]`;\n }\n if (type.kind === 'nullable') {\n return `${mapParamType(type.inner, specEnumNames)} | null`;\n }\n return mapTypeRef(type);\n}\n","import type { ApiSpec, AuthScheme, EmitterContext, GeneratedFile, Service } from '@workos/oagen';\nimport { fileName, resolveServiceDir, servicePropertyName, resolveInterfaceName, wireInterfaceName } from './naming.js';\nimport {\n docComment,\n createServiceDirResolver,\n isServiceCoveredByExisting,\n isListMetadataModel,\n isListWrapperModel,\n} from './utils.js';\nimport { resolveResourceClassName } from './resources.js';\n\nexport function generateClient(spec: ApiSpec, ctx: EmitterContext): GeneratedFile[] {\n const files: GeneratedFile[] = [];\n\n files.push(generateWorkOSClient(spec, ctx));\n files.push(...generateServiceBarrels(spec, ctx));\n files.push(generateBarrel(spec, ctx));\n files.push(generateWorkerBarrel(spec, ctx));\n files.push(generatePackageJson(ctx));\n files.push(generateTsConfig());\n\n return files;\n}\n\nfunction generateWorkOSClient(spec: ApiSpec, ctx: EmitterContext): GeneratedFile {\n const lines: string[] = [];\n\n // Only import WorkOSBase for fresh generation (no existing WorkOS class).\n // When integrating into an existing SDK, the existing WorkOS already has its\n // own base class and the WorkOSBase file may not exist.\n const hasExistingWorkOS = !!ctx.apiSurface?.classes?.['WorkOS'];\n if (!hasExistingWorkOS) {\n lines.push(\"import { WorkOSBase } from './common/workos-base';\");\n }\n\n // Filter out services whose endpoints are already covered by existing\n // hand-written service classes (e.g., Connections covered by SSO).\n const coveredServices = new Set<string>();\n for (const service of spec.services) {\n if (isServiceCoveredByExisting(service, ctx)) {\n coveredServices.add(service.name);\n }\n }\n\n // Service imports — skip covered services\n for (const service of spec.services) {\n if (coveredServices.has(service.name)) continue;\n const resolvedName = resolveResourceClassName(service, ctx);\n const serviceDir = resolveServiceDir(resolvedName);\n lines.push(`import { ${resolvedName} } from './${serviceDir}/${fileName(resolvedName)}';`);\n }\n\n lines.push('');\n if (spec.description) {\n lines.push(...docComment(spec.description));\n }\n const extendsClause = hasExistingWorkOS ? '' : ' extends WorkOSBase';\n lines.push(`export class WorkOS${extendsClause} {`);\n\n // Server URL constants from spec.servers\n if (spec.servers && spec.servers.length > 0) {\n for (const server of spec.servers) {\n const constName = serverConstName(server.description ?? server.url);\n if (server.description) {\n lines.push(...docComment(server.description, 2));\n }\n lines.push(` static readonly ${constName} = '${server.url}';`);\n }\n lines.push('');\n }\n\n // Resource accessors — skip services whose property already exists\n // in the baseline WorkOS class (e.g., `portal` covers AdminPortal,\n // `mfa` covers MultiFactorAuth).\n const existingProps = new Set<string>();\n const baselineWorkOS = ctx.apiSurface?.classes?.['WorkOS'] ?? ctx.apiSurface?.classes?.['WorkOSNode'];\n if (baselineWorkOS?.properties) {\n for (const name of Object.keys(baselineWorkOS.properties)) {\n existingProps.add(name);\n }\n }\n // Resource accessors — skip services whose endpoints are fully covered\n // by existing hand-written services.\n for (const service of spec.services) {\n if (coveredServices.has(service.name)) continue;\n const resolvedName = resolveResourceClassName(service, ctx);\n const propName = servicePropertyName(resolvedName);\n if (existingProps.has(propName)) continue;\n lines.push(` readonly ${propName} = new ${resolvedName}(this);`);\n }\n\n // Auth override — only emit when auth is non-default (not bearer)\n if (needsAuthOverride(spec.auth)) {\n lines.push('');\n lines.push(' protected override setAuthHeaders(headers: Record<string, string>): void {');\n renderAuthOverride(lines, spec.auth!);\n lines.push(' }');\n }\n\n lines.push('}');\n\n return {\n path: 'src/workos.ts',\n content: lines.join('\\n'),\n skipIfExists: true,\n };\n}\n\n/**\n * Generate per-service barrel files (interfaces/index.ts) that re-export\n * all interface and enum files for each service directory. This reduces\n * the root barrel from ~200+ individual type exports to one wildcard\n * re-export per service.\n */\nfunction generateServiceBarrels(spec: ApiSpec, ctx: EmitterContext): GeneratedFile[] {\n const files: GeneratedFile[] = [];\n const { modelToService, resolveDir } = createServiceDirResolver(spec.models, spec.services, ctx);\n\n // Group interface files by directory, tracking exported symbol names\n // to prevent TS2308 duplicate export errors when two files in the same\n // directory export the same symbol (e.g., FooResponse as a wire type\n // from one file and a domain type from another).\n const dirExports = new Map<string, string[]>();\n const dirSymbols = new Map<string, Set<string>>();\n\n // Pre-seed dirSymbols with names already exported by existing interface files.\n // When the existing SDK has an interface file in a directory that already\n // exports a name (e.g., AuditLogSchema from create-audit-log-schema-options),\n // the generated model with the same name must be skipped to prevent the\n // merger from adding a duplicate `export *` that causes TS2308.\n if (ctx.apiSurface?.interfaces) {\n for (const [name, iface] of Object.entries(ctx.apiSurface.interfaces)) {\n const sourceFile = (iface as any).sourceFile as string | undefined;\n if (!sourceFile) continue;\n // Match paths like \"src/audit-logs/interfaces/foo.interface.ts\" to directory \"audit-logs\"\n const match = sourceFile.match(/^src\\/([^/]+)\\/interfaces\\//);\n if (match) {\n const dirName = match[1];\n if (!dirSymbols.has(dirName)) {\n dirSymbols.set(dirName, new Set());\n }\n dirSymbols.get(dirName)!.add(name);\n }\n }\n }\n if (ctx.apiSurface?.enums) {\n for (const [name, enumDef] of Object.entries(ctx.apiSurface.enums)) {\n const sourceFile = (enumDef as any).sourceFile as string | undefined;\n if (!sourceFile) continue;\n const match = sourceFile.match(/^src\\/([^/]+)\\/interfaces\\//);\n if (match) {\n const dirName = match[1];\n if (!dirSymbols.has(dirName)) {\n dirSymbols.set(dirName, new Set());\n }\n dirSymbols.get(dirName)!.add(name);\n }\n }\n }\n if (ctx.apiSurface?.typeAliases) {\n for (const [name, alias] of Object.entries(ctx.apiSurface.typeAliases)) {\n const sourceFile = (alias as any).sourceFile as string | undefined;\n if (!sourceFile) continue;\n const match = sourceFile.match(/^src\\/([^/]+)\\/interfaces\\//);\n if (match) {\n const dirName = match[1];\n if (!dirSymbols.has(dirName)) {\n dirSymbols.set(dirName, new Set());\n }\n dirSymbols.get(dirName)!.add(name);\n }\n }\n }\n\n // Build a global set of all symbols across all directories for\n // cross-directory deduplication. This prevents adding a model to one\n // directory's barrel when the same symbol already exists in another\n // directory's barrel (e.g., Event in common vs events, DirectoryState\n // in directory-sync vs common).\n const globalExistingSymbols = new Set<string>();\n for (const symbols of dirSymbols.values()) {\n for (const sym of symbols) {\n globalExistingSymbols.add(sym);\n }\n }\n\n // Models -> service directories\n // Skip list wrapper and list metadata models — they use shared List<T>/ListMetadata\n // from common utils, so no per-resource interface file is generated.\n for (const model of spec.models) {\n if (isListMetadataModel(model) || isListWrapperModel(model)) continue;\n const service = modelToService.get(model.name);\n const dirName = resolveDir(service);\n if (!dirExports.has(dirName)) {\n dirExports.set(dirName, []);\n // Only initialize dirSymbols if not already pre-seeded from baseline\n if (!dirSymbols.has(dirName)) {\n dirSymbols.set(dirName, new Set());\n }\n }\n\n // Each model file exports a domain interface and a wire interface.\n // Track these symbols to detect cross-file collisions.\n const domainName = resolveInterfaceName(model.name, ctx);\n const wireName = wireInterfaceName(domainName);\n const symbols = dirSymbols.get(dirName)!;\n\n if (globalExistingSymbols.has(domainName) || globalExistingSymbols.has(wireName)) {\n // Skip this model's export to avoid duplicate symbol in the barrel\n // (checks across ALL directories, not just the target one)\n continue;\n }\n\n symbols.add(domainName);\n symbols.add(wireName);\n // Also track in the global set so subsequent models in other directories\n // don't re-export the same symbol (intra-generation cross-directory dedup).\n globalExistingSymbols.add(domainName);\n globalExistingSymbols.add(wireName);\n dirExports.get(dirName)!.push(`export * from './${fileName(model.name)}.interface';`);\n }\n\n // Enums -> service directories\n for (const enumDef of spec.enums) {\n const enumService = findEnumService(enumDef.name, spec.services);\n const dirName = resolveDir(enumService);\n if (!dirExports.has(dirName)) {\n dirExports.set(dirName, []);\n if (!dirSymbols.has(dirName)) {\n dirSymbols.set(dirName, new Set());\n }\n }\n\n const symbols = dirSymbols.get(dirName)!;\n if (globalExistingSymbols.has(enumDef.name)) continue;\n\n symbols.add(enumDef.name);\n globalExistingSymbols.add(enumDef.name);\n dirExports.get(dirName)!.push(`export * from './${fileName(enumDef.name)}.interface';`);\n }\n\n for (const [dirName, exports] of dirExports) {\n // Deduplicate (an enum and model could theoretically share a file name)\n const uniqueExports = [...new Set(exports)];\n uniqueExports.sort();\n files.push({\n path: `src/${dirName}/interfaces/index.ts`,\n content: uniqueExports.join('\\n'),\n skipIfExists: true,\n });\n }\n\n return files;\n}\n\nfunction generateBarrel(spec: ApiSpec, ctx: EmitterContext): GeneratedFile {\n const lines: string[] = [];\n const { modelToService, resolveDir } = createServiceDirResolver(spec.models, spec.services, ctx);\n\n // Track all exported names to prevent duplicates.\n // Pre-seed with names already exported by the existing SDK to avoid generating\n // duplicate exports that would conflict with existing `export *` statements.\n const exportedNames = new Set<string>();\n if (ctx.apiSurface?.interfaces) {\n for (const name of Object.keys(ctx.apiSurface.interfaces)) {\n exportedNames.add(name);\n }\n }\n if (ctx.apiSurface?.classes) {\n for (const name of Object.keys(ctx.apiSurface.classes)) {\n exportedNames.add(name);\n }\n }\n\n // Collect names already exported by the existing SDK (via export * or named exports).\n // When an explicit `export type { Foo }` would shadow a wildcard re-export that\n // already provides a hand-written version of Foo (e.g., a discriminated union),\n // we must skip the explicit export so the wildcard wins.\n const existingSdkExports = new Set<string>();\n if (ctx.apiSurface?.exports) {\n for (const names of Object.values(ctx.apiSurface.exports)) {\n for (const name of names) {\n existingSdkExports.add(name);\n }\n }\n }\n\n // Common exports\n lines.push(\"export * from './common/exceptions';\");\n lines.push(\"export { AutoPaginatable } from './common/utils/pagination';\");\n lines.push(\"export type { List, ListMetadata, ListResponse } from './common/utils/pagination';\");\n lines.push(\"export type { PaginationOptions } from './common/interfaces/pagination-options.interface';\");\n lines.push(\"export type { WorkOSOptions } from './common/interfaces/workos-options.interface';\");\n lines.push(\"export type { PostOptions } from './common/interfaces/post-options.interface';\");\n lines.push(\"export type { GetOptions } from './common/interfaces/get-options.interface';\");\n lines.push('');\n for (const name of [\n 'AutoPaginatable',\n 'List',\n 'ListMetadata',\n 'ListResponse',\n 'PaginationOptions',\n 'WorkOSOptions',\n 'PostOptions',\n 'GetOptions',\n ]) {\n exportedNames.add(name);\n }\n\n // Identify services whose endpoints are fully covered by existing hand-written\n // classes — their resource class should not be re-exported from the barrel.\n const coveredServicesBarrel = new Set<string>();\n for (const service of spec.services) {\n if (isServiceCoveredByExisting(service, ctx)) {\n coveredServicesBarrel.add(service.name);\n }\n }\n\n // Track directories that have already been wildcard-exported\n const exportedDirs = new Set<string>();\n\n // Pre-compute all names per interfaces directory (generated + baseline) to detect\n // cross-directory conflicts before emitting any star exports. A star export is\n // unsafe when two different directories export the same name (e.g., Factor in\n // both mfa/interfaces and user-management/interfaces).\n const dirAllNames = new Map<string, Set<string>>();\n for (const service of spec.services) {\n const iDir = resolveDir(service.name);\n if (!dirAllNames.has(iDir)) dirAllNames.set(iDir, new Set());\n const names = dirAllNames.get(iDir)!;\n for (const model of spec.models) {\n if (modelToService.get(model.name) !== service.name) continue;\n if (isListMetadataModel(model) || isListWrapperModel(model)) continue;\n names.add(resolveInterfaceName(model.name, ctx));\n names.add(wireInterfaceName(resolveInterfaceName(model.name, ctx)));\n }\n }\n // Add baseline names per directory\n if (ctx.apiSurface?.interfaces) {\n for (const [name, iface] of Object.entries(ctx.apiSurface.interfaces)) {\n const sourceFile = (iface as any).sourceFile as string | undefined;\n if (!sourceFile) continue;\n const match = sourceFile.match(/^src\\/([^/]+)\\/interfaces\\//);\n if (match) {\n const dirName = match[1];\n if (!dirAllNames.has(dirName)) dirAllNames.set(dirName, new Set());\n dirAllNames.get(dirName)!.add(name);\n }\n }\n }\n if (ctx.apiSurface?.typeAliases) {\n for (const [name, alias] of Object.entries(ctx.apiSurface.typeAliases)) {\n const sourceFile = (alias as any).sourceFile as string | undefined;\n if (!sourceFile) continue;\n const match = sourceFile.match(/^src\\/([^/]+)\\/interfaces\\//);\n if (match) {\n const dirName = match[1];\n if (!dirAllNames.has(dirName)) dirAllNames.set(dirName, new Set());\n dirAllNames.get(dirName)!.add(name);\n }\n }\n }\n // Detect directories with cross-directory name conflicts\n const unsafeStarDirs = new Set<string>();\n const allDirEntries = [...dirAllNames.entries()];\n for (let i = 0; i < allDirEntries.length; i++) {\n for (let j = i + 1; j < allDirEntries.length; j++) {\n const [dirA, namesA] = allDirEntries[i];\n const [dirB, namesB] = allDirEntries[j];\n for (const name of namesA) {\n if (namesB.has(name)) {\n unsafeStarDirs.add(dirA);\n unsafeStarDirs.add(dirB);\n break;\n }\n }\n }\n }\n\n // Per-service exports: service barrel + resource class\n for (const service of spec.services) {\n const resolvedName = resolveResourceClassName(service, ctx);\n const serviceDir = resolveServiceDir(resolvedName);\n // The interfaces directory may differ from the resource class directory when\n // a service's class name is remapped (e.g., WebhooksEndpoints class lives in\n // webhooks-endpoints/ but its model interfaces live in webhooks/).\n const interfacesDir = resolveDir(service.name);\n\n // Check if this service has any models or enums (i.e., a barrel was generated).\n // Exclude list wrapper and list metadata models — these are skipped during\n // interface generation (they use shared List<T>/ListMetadata), so they don't\n // have corresponding .interface.ts files in the output.\n const serviceModels = spec.models.filter((m) => {\n if (modelToService.get(m.name) !== service.name) return false;\n if (isListMetadataModel(m) || isListWrapperModel(m)) return false;\n return true;\n });\n const serviceEnums = spec.enums.filter((e) => {\n const enumService = findEnumService(e.name, spec.services);\n return enumService === service.name;\n });\n\n // Check whether any model or enum in this service conflicts with names already\n // exported (from earlier star exports or the existing SDK baseline). If so, fall\n // back to individual named exports to avoid duplicate-export TS2308 errors.\n const hasConflict =\n serviceModels.some((m) => {\n const name = resolveInterfaceName(m.name, ctx);\n return existingSdkExports.has(name) || exportedNames.has(name) || exportedNames.has(wireInterfaceName(name));\n }) || serviceEnums.some((e) => existingSdkExports.has(e.name) || exportedNames.has(e.name));\n\n // Skip star export for covered services — their directory may have hand-written types\n // (e.g., Factor in mfa/) that conflict with types in the covering service's directory.\n const isCovered = coveredServicesBarrel.has(service.name);\n if (\n (serviceModels.length > 0 || serviceEnums.length > 0) &&\n !exportedDirs.has(interfacesDir) &&\n !hasConflict &&\n !unsafeStarDirs.has(interfacesDir) &&\n !isCovered\n ) {\n exportedDirs.add(interfacesDir);\n lines.push(`export * from './${interfacesDir}/interfaces';`);\n // Track the individual names so they don't get re-exported below\n for (const model of serviceModels) {\n exportedNames.add(resolveInterfaceName(model.name, ctx));\n exportedNames.add(wireInterfaceName(resolveInterfaceName(model.name, ctx)));\n }\n for (const enumDef of serviceEnums) {\n exportedNames.add(enumDef.name);\n }\n } else if (!hasConflict) {\n // Fallback: emit individual model exports (e.g., when no models/enums exist)\n for (const model of serviceModels) {\n const name = resolveInterfaceName(model.name, ctx);\n const wireName = wireInterfaceName(name);\n if (exportedNames.has(name) || exportedNames.has(wireName)) continue;\n if (existingSdkExports.has(name)) continue;\n exportedNames.add(name);\n exportedNames.add(wireName);\n lines.push(\n `export type { ${name}, ${wireName} } from './${interfacesDir}/interfaces/${fileName(model.name)}.interface';`,\n );\n }\n }\n\n // Resource class — skip if already exported or if service is fully covered\n // by existing hand-written classes\n if (coveredServicesBarrel.has(service.name)) {\n // Emit a comment indicating this service is covered by an existing class\n lines.push(`// ${resolvedName} is covered by an existing hand-written class — not re-exported.`);\n } else if (!exportedNames.has(resolvedName)) {\n exportedNames.add(resolvedName);\n lines.push(`export { ${resolvedName} } from './${serviceDir}/${fileName(resolvedName)}';`);\n }\n lines.push('');\n }\n\n // Unassigned models (common) — use barrel if any exist\n const unassignedModels = spec.models.filter((m) => !modelToService.has(m.name));\n const commonEnums = spec.enums.filter((e) => {\n const enumService = findEnumService(e.name, spec.services);\n return !enumService;\n });\n\n const commonHasConflict =\n unassignedModels.some((m) => existingSdkExports.has(resolveInterfaceName(m.name, ctx))) ||\n commonEnums.some((e) => existingSdkExports.has(e.name));\n\n if ((unassignedModels.length > 0 || commonEnums.length > 0) && !exportedDirs.has('common') && !commonHasConflict) {\n exportedDirs.add('common');\n lines.push(\"export * from './common/interfaces';\");\n for (const model of unassignedModels) {\n exportedNames.add(resolveInterfaceName(model.name, ctx));\n exportedNames.add(wireInterfaceName(resolveInterfaceName(model.name, ctx)));\n }\n for (const enumDef of commonEnums) {\n exportedNames.add(enumDef.name);\n }\n } else {\n // Fallback: individual model exports\n for (const model of unassignedModels) {\n const name = resolveInterfaceName(model.name, ctx);\n const wireName = wireInterfaceName(name);\n if (exportedNames.has(name) || exportedNames.has(wireName)) continue;\n if (existingSdkExports.has(name)) continue;\n exportedNames.add(name);\n exportedNames.add(wireName);\n lines.push(`export type { ${name}, ${wireName} } from './common/interfaces/${fileName(model.name)}.interface';`);\n }\n }\n\n // Enum exports — only for enums not already covered by a service/common barrel.\n // Skip duplicates and names already covered by existing SDK wildcards.\n // Use value export (`export { ... }`) for actual TS enums so consumers\n // can use them as runtime values (e.g., ConnectionType.GoogleOAuth).\n // Use type-only export (`export type { ... }`) for string literal unions.\n for (const enumDef of spec.enums) {\n if (exportedNames.has(enumDef.name)) continue;\n if (existingSdkExports.has(enumDef.name)) continue;\n exportedNames.add(enumDef.name);\n const enumService = findEnumService(enumDef.name, spec.services);\n const dir = resolveDir(enumService);\n if (!exportedDirs.has(dir)) {\n const baselineEnum = ctx.apiSurface?.enums?.[enumDef.name];\n const exportKeyword = baselineEnum?.members ? 'export' : 'export type';\n lines.push(\n `${exportKeyword} { ${enumDef.name} } from './${dir}/interfaces/${fileName(enumDef.name)}.interface';`,\n );\n }\n }\n\n lines.push('');\n // Only emit the WorkOS re-export for standalone generation (no existing SDK).\n // When integrating into an existing SDK, the existing barrel already exports\n // WorkOS (often as a subclass alias like `export { WorkOSNode as WorkOS }`),\n // and adding a second export with the same name causes a duplicate identifier error.\n if (!ctx.apiSurface && !exportedNames.has('WorkOS')) {\n exportedNames.add('WorkOS');\n lines.push(\"export { WorkOS } from './workos';\");\n }\n\n return {\n path: 'src/index.ts',\n content: lines.join('\\n'),\n skipIfExists: true,\n };\n}\n\n/**\n * Generate a worker-compatible barrel file that re-exports everything from\n * the main barrel. This keeps type exports in sync automatically.\n */\nfunction generateWorkerBarrel(_spec: ApiSpec, _ctx: EmitterContext): GeneratedFile {\n const lines: string[] = [];\n\n // Re-export everything from the main index — keeps type exports in sync\n lines.push(\"export * from './index';\");\n\n return {\n path: 'src/index.worker.ts',\n content: lines.join('\\n'),\n skipIfExists: true,\n };\n}\n\nfunction findEnumService(enumName: string, services: Service[]): string | undefined {\n for (const service of services) {\n for (const op of service.operations) {\n const refs: string[] = [];\n const collect = (ref: any) => {\n if (ref?.kind === 'enum' && ref.name === enumName) refs.push(ref.name);\n if (ref?.items) collect(ref.items);\n if (ref?.inner) collect(ref.inner);\n if (ref?.variants) ref.variants.forEach(collect);\n if (ref?.valueType) collect(ref.valueType);\n };\n if (op.requestBody) collect(op.requestBody);\n collect(op.response);\n for (const p of [...op.pathParams, ...op.queryParams]) {\n collect(p.type);\n }\n if (refs.length > 0) return service.name;\n }\n }\n return undefined;\n}\n\n/**\n * Determine whether the spec's auth scheme requires overriding the\n * default bearer auth in WorkOSBase.setAuthHeaders().\n */\nfunction needsAuthOverride(auth?: AuthScheme[]): boolean {\n if (!auth || auth.length === 0) return false;\n const scheme = auth[0];\n // bearer and oauth2 match the base class default — no override needed\n return scheme.kind === 'apiKey';\n}\n\n/**\n * Render the body of a setAuthHeaders override for non-default auth schemes.\n * Only called when needsAuthOverride() returns true.\n */\nfunction renderAuthOverride(lines: string[], auth: AuthScheme[]): void {\n const scheme = auth[0];\n if (scheme.kind !== 'apiKey') return;\n switch (scheme.in) {\n case 'header':\n lines.push(` headers['${scheme.name}'] = this.key;`);\n break;\n case 'query':\n lines.push(` // Auth key sent as query parameter '${scheme.name}' (see buildUrl)`);\n break;\n case 'cookie':\n lines.push(` headers['Cookie'] = \\`${scheme.name}=\\${this.key}\\`;`);\n break;\n }\n}\n\n/**\n * Convert a server description or URL into a SCREAMING_SNAKE_CASE constant name.\n */\nfunction serverConstName(description: string): string {\n return (\n 'SERVER_' +\n description\n .replace(/https?:\\/\\//g, '')\n .replace(/[^a-zA-Z0-9]+/g, '_')\n .replace(/^_|_$/g, '')\n .toUpperCase()\n );\n}\n\nfunction generatePackageJson(ctx: EmitterContext): GeneratedFile {\n const pkg = {\n name: `@${ctx.namespace}/sdk`,\n version: '0.0.0',\n type: 'module',\n main: 'src/index.ts',\n types: 'src/index.ts',\n exports: {\n '.': './src/index.ts',\n },\n scripts: {\n test: 'jest',\n build: 'tsc',\n },\n devDependencies: {\n typescript: '^5.0.0',\n jest: '^29.0.0',\n 'jest-fetch-mock': '^3.0.0',\n '@types/jest': '^29.0.0',\n 'ts-jest': '^29.0.0',\n },\n };\n\n return {\n path: 'package.json',\n content: JSON.stringify(pkg, null, 2),\n skipIfExists: true,\n integrateTarget: false,\n };\n}\n\nfunction generateTsConfig(): GeneratedFile {\n const config = {\n compilerOptions: {\n target: 'ES2020',\n module: 'CommonJS',\n lib: ['ES2020'],\n declaration: true,\n strict: true,\n exactOptionalPropertyTypes: true,\n esModuleInterop: true,\n skipLibCheck: true,\n forceConsistentCasingInFileNames: true,\n resolveJsonModule: true,\n outDir: './lib',\n rootDir: './src',\n },\n include: ['src/**/*'],\n exclude: ['node_modules', 'lib', '**/*.spec.ts'],\n };\n\n return {\n path: 'tsconfig.json',\n content: JSON.stringify(config, null, 2),\n skipIfExists: true,\n integrateTarget: false,\n };\n}\n","import type { EmitterContext, GeneratedFile } from '@workos/oagen';\nimport { fileName } from './naming.js';\n\nexport function generateErrors(ctx?: EmitterContext): GeneratedFile[] {\n const files: GeneratedFile[] = [\n {\n path: 'src/common/exceptions/bad-request.exception.ts',\n content: `export class BadRequestException extends Error {\n readonly status = 400;\n readonly name = 'BadRequestException';\n readonly requestID: string;\n readonly code?: string;\n\n constructor({\n code,\n message,\n requestID,\n }: {\n code?: string;\n message?: string;\n requestID: string;\n }) {\n super();\n this.message = message ?? 'Bad request';\n this.requestID = requestID;\n if (code) this.code = code;\n }\n}`,\n skipIfExists: true,\n integrateTarget: false,\n },\n {\n path: 'src/common/exceptions/unauthorized.exception.ts',\n content: `export class UnauthorizedException extends Error {\n readonly status = 401;\n readonly name = 'UnauthorizedException';\n readonly requestID: string;\n\n constructor(requestID: string) {\n super();\n this.message = 'Unauthorized';\n this.requestID = requestID;\n }\n}`,\n skipIfExists: true,\n integrateTarget: false,\n },\n {\n path: 'src/common/exceptions/not-found.exception.ts',\n content: `export class NotFoundException extends Error {\n readonly status = 404;\n readonly name = 'NotFoundException';\n readonly requestID: string;\n readonly code?: string;\n\n constructor({\n code,\n message,\n path,\n requestID,\n }: {\n code?: string;\n message?: string;\n path: string;\n requestID: string;\n }) {\n super();\n this.message =\n message ?? \\`The requested path '\\${path}' could not be found.\\`;\n this.requestID = requestID;\n if (code) this.code = code;\n }\n}`,\n skipIfExists: true,\n integrateTarget: false,\n },\n {\n path: 'src/common/exceptions/conflict.exception.ts',\n content: `export class ConflictException extends Error {\n readonly status = 409;\n readonly name = 'ConflictException';\n readonly requestID: string;\n\n constructor({\n message,\n requestID,\n }: {\n message?: string;\n error?: string;\n requestID: string;\n }) {\n super();\n this.message = message ?? 'Conflict';\n this.requestID = requestID;\n }\n}`,\n skipIfExists: true,\n integrateTarget: false,\n },\n {\n path: 'src/common/exceptions/unprocessable-entity.exception.ts',\n content: `export interface UnprocessableEntityError {\n code: string;\n}\n\nexport class UnprocessableEntityException extends Error {\n readonly status = 422;\n readonly name = 'UnprocessableEntityException';\n readonly requestID: string;\n readonly code?: string;\n\n constructor({\n code,\n errors,\n message,\n requestID,\n }: {\n code?: string;\n errors?: UnprocessableEntityError[];\n message?: string;\n requestID: string;\n }) {\n super();\n this.requestID = requestID;\n this.message = message ?? 'Unprocessable entity';\n if (code) this.code = code;\n if (errors) {\n const requirement =\n errors.length === 1 ? 'requirement' : 'requirements';\n this.message = \\`The following \\${requirement} must be met:\\\\n\\`;\n for (const { code: errCode } of errors) {\n this.message = this.message.concat(\\`\\\\t\\${errCode}\\\\n\\`);\n }\n }\n }\n}`,\n skipIfExists: true,\n integrateTarget: false,\n },\n {\n path: 'src/common/exceptions/rate-limit-exceeded.exception.ts',\n content: `export class RateLimitExceededException extends Error {\n readonly status = 429;\n readonly name = 'RateLimitExceededException';\n readonly requestID: string;\n readonly retryAfter?: number;\n\n constructor(message: string, requestID: string, retryAfter?: number) {\n super();\n this.message = message ?? 'Too many requests';\n this.requestID = requestID;\n this.retryAfter = retryAfter;\n }\n}`,\n skipIfExists: true,\n integrateTarget: false,\n },\n {\n path: 'src/common/exceptions/generic-server.exception.ts',\n content: `export class GenericServerException extends Error {\n readonly status: number;\n readonly name = 'GenericServerException';\n readonly requestID: string;\n\n constructor(status: number, message: string, requestID: string) {\n super();\n this.status = status;\n this.message = message ?? 'Server error';\n this.requestID = requestID;\n }\n}`,\n skipIfExists: true,\n integrateTarget: false,\n },\n {\n path: 'src/common/exceptions/no-api-key-provided.exception.ts',\n content: `export class NoApiKeyProvidedException extends Error {\n readonly name = 'NoApiKeyProvidedException';\n\n constructor() {\n super();\n this.message =\n 'No API key provided. Pass it to the WorkOS constructor or set the WORKOS_API_KEY environment variable.';\n }\n}`,\n skipIfExists: true,\n integrateTarget: false,\n },\n {\n path: 'src/common/exceptions/index.ts',\n content: `export { BadRequestException } from './bad-request.exception';\nexport { UnauthorizedException } from './unauthorized.exception';\nexport { NotFoundException } from './not-found.exception';\nexport { ConflictException } from './conflict.exception';\nexport {\n UnprocessableEntityException,\n type UnprocessableEntityError,\n} from './unprocessable-entity.exception';\nexport { RateLimitExceededException } from './rate-limit-exceeded.exception';\nexport { GenericServerException } from './generic-server.exception';\nexport { NoApiKeyProvidedException } from './no-api-key-provided.exception';`,\n skipIfExists: true,\n integrateTarget: false,\n },\n ];\n\n // Fix 6: Generate typed exception classes from ErrorResponse.type\n if (ctx?.spec) {\n const typedErrors = collectTypedErrors(ctx);\n for (const { modelName, statusCode, baseException } of typedErrors) {\n const exceptionClassName = `${modelName}Exception`;\n const filePath = `src/common/exceptions/${fileName(modelName)}.exception.ts`;\n const baseImport = baseException\n ? `import { ${baseException} } from './${fileName(baseException.replace(/Exception$/, '')).replace(/^/, '')}.exception';\\n\\n`\n : '';\n const baseClass = baseException ?? 'Error';\n\n files.push({\n path: filePath,\n content: `${baseImport}export class ${exceptionClassName} extends ${baseClass} {\n readonly status = ${statusCode};\n readonly name = '${exceptionClassName}';\n readonly requestID: string;\n readonly data?: any;\n\n constructor({ message, requestID, data }: { message?: string; requestID: string; data?: any }) {\n ${baseException ? `super(${baseException === 'UnauthorizedException' ? 'requestID' : `{ message: message ?? '${modelName} error', requestID }`});` : 'super();'}\n this.message = message ?? '${modelName} error';\n this.requestID = requestID;\n if (data) this.data = data;\n }\n}`,\n skipIfExists: true,\n integrateTarget: false,\n });\n\n // Update the barrel index to export the new exception\n const existingIndex = files.find((f) => f.path === 'src/common/exceptions/index.ts');\n if (existingIndex) {\n existingIndex.content += `\\nexport { ${exceptionClassName} } from './${fileName(modelName)}.exception';`;\n }\n }\n }\n\n return files;\n}\n\nconst STATUS_TO_BASE_EXCEPTION: Record<number, string> = {\n 400: 'BadRequestException',\n 401: 'UnauthorizedException',\n 404: 'NotFoundException',\n 409: 'ConflictException',\n 422: 'UnprocessableEntityException',\n 429: 'RateLimitExceededException',\n};\n\nfunction collectTypedErrors(\n ctx: EmitterContext,\n): { modelName: string; statusCode: number; baseException: string | null }[] {\n const seen = new Set<string>();\n const results: {\n modelName: string;\n statusCode: number;\n baseException: string | null;\n }[] = [];\n\n for (const service of ctx.spec.services) {\n for (const op of service.operations) {\n for (const err of op.errors) {\n if (err.type?.kind === 'model' && !seen.has(err.type.name)) {\n seen.add(err.type.name);\n results.push({\n modelName: err.type.name,\n statusCode: err.statusCode,\n baseException:\n STATUS_TO_BASE_EXCEPTION[err.statusCode] ?? (err.statusCode >= 500 ? 'GenericServerException' : null),\n });\n }\n }\n }\n }\n\n return results;\n}\n","import type { GeneratedFile } from '@workos/oagen';\n\nexport function generateConfig(): GeneratedFile[] {\n return [\n {\n path: 'src/common/interfaces/workos-options.interface.ts',\n content: `export interface WorkOSOptions {\n apiKey?: string;\n apiHostname?: string;\n https?: boolean;\n port?: number;\n config?: RequestInit;\n fetchFn?: typeof fetch;\n clientId?: string;\n timeout?: number;\n}\n\nexport interface AppInfo {\n name: string;\n version?: string;\n}`,\n skipIfExists: true,\n integrateTarget: false,\n },\n {\n path: 'src/common/interfaces/post-options.interface.ts',\n content: `export interface PostOptions {\n query?: Record<string, any>;\n idempotencyKey?: string;\n warrantToken?: string;\n skipApiKeyCheck?: boolean;\n encoding?: 'json' | 'form-data' | 'form-urlencoded' | 'binary' | 'text';\n}`,\n skipIfExists: true,\n integrateTarget: false,\n },\n {\n path: 'src/common/interfaces/get-options.interface.ts',\n content: `export interface GetOptions {\n query?: Record<string, any>;\n accessToken?: string;\n warrantToken?: string;\n skipApiKeyCheck?: boolean;\n}`,\n skipIfExists: true,\n integrateTarget: false,\n },\n {\n path: 'src/common/interfaces/pagination-options.interface.ts',\n content: `export interface PaginationOptions {\n limit?: number;\n before?: string | null;\n after?: string | null;\n order?: 'asc' | 'desc';\n}`,\n skipIfExists: true,\n integrateTarget: false,\n },\n {\n path: 'src/common/interfaces/request-exception.interface.ts',\n content: `export interface RequestException {\n readonly status: number;\n readonly name: string;\n readonly requestID: string;\n readonly code?: string;\n}`,\n skipIfExists: true,\n integrateTarget: false,\n },\n ];\n}\n","import type { GeneratedFile } from '@workos/oagen';\n\nexport function generateCommon(): GeneratedFile[] {\n return [\n {\n path: 'src/common/utils/pagination.ts',\n content: paginationContent(),\n skipIfExists: true,\n integrateTarget: false,\n },\n {\n path: 'src/common/utils/fetch-and-deserialize.ts',\n content: fetchAndDeserializeContent(),\n skipIfExists: true,\n integrateTarget: true,\n },\n {\n path: 'src/common/serializers/list.serializer.ts',\n content: listSerializerContent(),\n skipIfExists: true,\n integrateTarget: false,\n },\n {\n path: 'src/common/utils/test-utils.ts',\n content: testUtilsContent(),\n skipIfExists: true,\n integrateTarget: true,\n },\n ];\n}\n\nfunction paginationContent(): string {\n return `import type { PaginationOptions } from '../interfaces/pagination-options.interface';\n\nexport interface ListMetadata {\n before: string | null;\n after: string | null;\n}\n\nexport interface List<T> {\n object: 'list';\n data: T[];\n listMetadata: ListMetadata;\n}\n\nexport interface ListResponse<T> {\n object: 'list';\n data: T[];\n list_metadata: {\n before: string | null;\n after: string | null;\n };\n}\n\nexport class AutoPaginatable<\n ResourceType,\n ParametersType extends PaginationOptions = PaginationOptions,\n> {\n readonly object = 'list' as const;\n readonly options: ParametersType;\n\n constructor(\n protected list: List<ResourceType>,\n private apiCall: (params: PaginationOptions) => Promise<List<ResourceType>>,\n options?: ParametersType,\n ) {\n this.options = options ?? ({} as ParametersType);\n }\n\n get data(): ResourceType[] {\n return this.list.data;\n }\n\n get listMetadata() {\n return this.list.listMetadata;\n }\n\n private async *generatePages(\n params: PaginationOptions,\n ): AsyncGenerator<ResourceType[]> {\n const result = await this.apiCall({\n ...this.options,\n limit: 100,\n after: params.after,\n });\n yield result.data;\n if (result.listMetadata.after) {\n await new Promise((resolve) => setTimeout(resolve, 350));\n yield* this.generatePages({ after: result.listMetadata.after });\n }\n }\n\n async autoPagination(): Promise<ResourceType[]> {\n if (this.options.limit) {\n return this.data;\n }\n const results: ResourceType[] = [];\n for await (const page of this.generatePages({\n after: this.options.after,\n })) {\n results.push(...page);\n }\n return results;\n }\n}`;\n}\n\nfunction fetchAndDeserializeContent(): string {\n return `import type { WorkOS } from '../../workos';\nimport type { PaginationOptions } from '../interfaces/pagination-options.interface';\nimport { AutoPaginatable, type List, type ListResponse } from './pagination';\n\nfunction setDefaultOptions(\n options?: PaginationOptions,\n): Record<string, any> {\n return {\n order: 'desc',\n ...options,\n };\n}\n\nfunction deserializeList<T, U>(\n data: ListResponse<T>,\n deserializeFn: (item: T) => U,\n): List<U> {\n return {\n data: data.data.map(deserializeFn),\n listMetadata: {\n before: data.list_metadata.before,\n after: data.list_metadata.after,\n },\n };\n}\n\nexport const fetchAndDeserialize = async <T, U>(\n workos: WorkOS,\n endpoint: string,\n deserializeFn: (data: T) => U,\n options?: PaginationOptions,\n): Promise<List<U>> => {\n const { data } = await workos.get<ListResponse<T>>(endpoint, {\n query: setDefaultOptions(options),\n });\n return deserializeList(data, deserializeFn);\n};\n\nexport async function createPaginatedList<TResponse, TModel, TOptions extends PaginationOptions>(\n workos: WorkOS,\n endpoint: string,\n deserializeFn: (r: TResponse) => TModel,\n options?: TOptions,\n): Promise<AutoPaginatable<TModel, TOptions>> {\n return new AutoPaginatable(\n await fetchAndDeserialize<TResponse, TModel>(workos, endpoint, deserializeFn, options),\n (params) => fetchAndDeserialize<TResponse, TModel>(workos, endpoint, deserializeFn, params),\n options,\n );\n}`;\n}\n\nfunction listSerializerContent(): string {\n return `import type { ListMetadata, ListResponse } from '../utils/pagination';\n\nexport function deserializeListMetadata(\n metadata: ListResponse<any>['list_metadata'],\n): ListMetadata {\n return {\n before: metadata.before,\n after: metadata.after,\n };\n}`;\n}\n\nfunction testUtilsContent(): string {\n return `import fetch from 'jest-fetch-mock';\n\ninterface MockParams {\n status?: number;\n headers?: Record<string, string>;\n [key: string]: any;\n}\n\nexport function fetchOnce(\n response: any = {},\n { status = 200, headers, ...rest }: MockParams = {},\n) {\n return fetch.once(JSON.stringify(response), {\n status,\n headers: {\n 'content-type': 'application/json;charset=UTF-8',\n ...headers,\n },\n ...rest,\n });\n}\n\nexport function fetchURL(): string {\n return String(fetch.mock.calls[0][0]);\n}\n\nexport function fetchMethod(): string {\n return String(fetch.mock.calls[0][1]?.method ?? 'GET');\n}\n\nexport function fetchSearchParams(): Record<string, string> {\n return Object.fromEntries(new URL(fetchURL()).searchParams);\n}\n\nexport function fetchHeaders(): Record<string, string> {\n const headers = fetch.mock.calls[0][1]?.headers ?? {};\n return headers as Record<string, string>;\n}\n\nexport function fetchBody({ raw = false } = {}): any {\n const body = fetch.mock.calls[0][1]?.body;\n if (body instanceof URLSearchParams) return body.toString();\n if (raw) return body;\n return JSON.parse(String(body));\n}\n\n/**\n * Shared test helper: asserts that the given async function throws when the\n * server responds with 401 Unauthorized.\n */\nexport function testUnauthorized(fn: () => Promise<any>) {\n it('throws on unauthorized', async () => {\n fetchOnce({ message: 'Unauthorized' }, { status: 401 });\n await expect(fn()).rejects.toThrow('Could not authorize the request');\n });\n}\n\n/**\n * Shared test helper: asserts that a paginated list call returns the expected\n * shape (data array + listMetadata) and hits the correct endpoint.\n */\nexport function testPaginatedList(\n fn: () => Promise<any>,\n pathContains: string,\n) {\n it('returns paginated results', async () => {\n // Caller must have called fetchOnce with the list fixture before invoking fn\n const { data, listMetadata } = await fn();\n expect(fetchURL()).toContain(pathContains);\n expect(fetchSearchParams()).toHaveProperty('order');\n expect(Array.isArray(data)).toBe(true);\n expect(listMetadata).toBeDefined();\n });\n}\n\n/**\n * Shared test helper: asserts that a paginated list call returns empty data\n * when the server responds with an empty list.\n */\nexport function testEmptyResults(fn: () => Promise<any>) {\n it('handles empty results', async () => {\n fetchOnce({ data: [], list_metadata: { before: null, after: null } });\n const { data } = await fn();\n expect(data).toEqual([]);\n });\n}\n\n/**\n * Shared test helper: asserts that pagination params are forwarded correctly.\n */\nexport function testPaginationParams(fn: (opts: any) => Promise<any>, fixture: any) {\n it('forwards pagination params', async () => {\n fetchOnce(fixture);\n await fn({ limit: 10, after: 'cursor_abc' });\n expect(fetchSearchParams()['limit']).toBe('10');\n expect(fetchSearchParams()['after']).toBe('cursor_abc');\n });\n}`;\n}\n","import type { ApiSpec, Service, Operation, Model, TypeRef, EmitterContext, GeneratedFile } from '@workos/oagen';\nimport { planOperation, toCamelCase } from '@workos/oagen';\nimport { unwrapListModel, ID_PREFIXES } from './fixtures.js';\nimport {\n fieldName,\n wireFieldName,\n fileName,\n resolveServiceDir,\n servicePropertyName,\n resolveMethodName,\n resolveInterfaceName,\n} from './naming.js';\nimport { generateFixtures } from './fixtures.js';\nimport { resolveResourceClassName } from './resources.js';\nimport {\n assignModelsToServices,\n createServiceDirResolver,\n isServiceCoveredByExisting,\n uncoveredOperations,\n relativeImport,\n isListMetadataModel,\n isListWrapperModel,\n} from './utils.js';\n\nexport function generateTests(spec: ApiSpec, ctx: EmitterContext): GeneratedFile[] {\n const files: GeneratedFile[] = [];\n\n // Generate fixture JSON files\n const fixtures = generateFixtures(spec, ctx);\n for (const f of fixtures) {\n files.push({ path: f.path, content: f.content, headerPlacement: 'skip', integrateTarget: false });\n }\n\n // Build model lookup for response field assertions\n const modelMap = new Map(spec.models.map((m) => [m.name, m]));\n\n // Generate test files per service — skip services whose endpoints are fully\n // covered by existing hand-written service classes. For partially covered\n // services, generate tests only for uncovered operations.\n for (const service of spec.services) {\n if (isServiceCoveredByExisting(service, ctx)) continue;\n const ops = uncoveredOperations(service, ctx);\n if (ops.length === 0) continue;\n const testService = ops.length < service.operations.length ? { ...service, operations: ops } : service;\n files.push(generateServiceTest(testService, spec, ctx, modelMap));\n }\n\n // Generate serializer round-trip tests\n const serializerTests = generateSerializerTests(spec, ctx);\n for (const f of serializerTests) {\n files.push(f);\n }\n\n return files;\n}\n\nfunction generateServiceTest(\n service: Service,\n spec: ApiSpec,\n ctx: EmitterContext,\n modelMap: Map<string, Model>,\n): GeneratedFile {\n const resolvedName = resolveResourceClassName(service, ctx);\n const serviceDir = resolveServiceDir(resolvedName);\n const serviceClass = resolvedName;\n const serviceProp = servicePropertyName(resolvedName);\n const testPath = `src/${serviceDir}/${fileName(resolvedName)}.spec.ts`;\n\n const plans = service.operations.map((op) => ({\n op,\n plan: planOperation(op),\n method: resolveMethodName(op, service, ctx),\n }));\n\n // Sort plans to match the existing file's method order (same as resources.ts).\n if (ctx.overlayLookup?.methodByOperation) {\n const methodOrder = new Map<string, number>();\n let pos = 0;\n for (const [, info] of ctx.overlayLookup.methodByOperation) {\n if (!methodOrder.has(info.methodName)) {\n methodOrder.set(info.methodName, pos++);\n }\n }\n if (methodOrder.size > 0) {\n plans.sort((a, b) => {\n const aPos = methodOrder.get(a.method) ?? Number.MAX_SAFE_INTEGER;\n const bPos = methodOrder.get(b.method) ?? Number.MAX_SAFE_INTEGER;\n return aPos - bPos;\n });\n }\n }\n\n // Compute model-to-service mapping so fixture imports use the correct cross-service path.\n // A test for service A may reference a response model owned by service B — the fixture\n // lives in service B's fixtures directory, not service A's.\n const { modelToService, resolveDir } = createServiceDirResolver(spec.models, spec.services, ctx);\n\n const lines: string[] = [];\n\n lines.push(\"import fetch from 'jest-fetch-mock';\");\n\n // Conditionally import test utilities based on what test types exist\n const hasPaginated = plans.some((p) => p.plan.isPaginated);\n const hasBody = plans.some((p) => p.plan.hasBody);\n const testUtils = ['fetchOnce', 'fetchURL', 'fetchMethod'];\n if (hasPaginated) testUtils.push('fetchSearchParams');\n if (hasBody) testUtils.push('fetchBody');\n // Import shared test helpers for error and pagination tests\n if (hasPaginated) testUtils.push('testEmptyResults', 'testPaginationParams');\n // Only import testUnauthorized when at least one operation has a response model or is paginated\n const hasErrorTests = plans.some((p) => p.plan.responseModelName || p.plan.isPaginated);\n if (hasErrorTests) testUtils.push('testUnauthorized');\n lines.push('import {');\n for (const util of testUtils) {\n lines.push(` ${util},`);\n }\n lines.push(\"} from '../common/utils/test-utils';\");\n lines.push(\"import { WorkOS } from '../workos';\");\n lines.push('');\n\n // Import fixtures — use correct cross-service paths when the response model\n // is owned by a different service than the current test file.\n const fixtureImports = new Set<string>();\n for (const { op, plan } of plans) {\n if (plan.isPaginated && op.pagination) {\n let itemModelName = op.pagination.itemType.kind === 'model' ? op.pagination.itemType.name : null;\n if (itemModelName) {\n // Unwrap list wrapper models to match the fixture file naming in fixtures.ts\n const rawModel = modelMap.get(itemModelName);\n if (rawModel) {\n const unwrapped = unwrapListModel(rawModel, modelMap);\n if (unwrapped) {\n itemModelName = unwrapped.name;\n }\n }\n // List fixtures are always generated in the current service's directory\n // (the service owning the list operation), not in the model's home service.\n // Always use a local import path.\n const fixturePath = `./fixtures/list-${fileName(itemModelName)}.fixture.json`;\n fixtureImports.add(`import list${itemModelName}Fixture from '${fixturePath}';`);\n }\n } else if (plan.responseModelName) {\n const respService = modelToService.get(plan.responseModelName);\n const respDir = resolveDir(respService);\n const fixturePath =\n respDir === serviceDir\n ? `./fixtures/${fileName(plan.responseModelName)}.fixture.json`\n : `../${respDir}/fixtures/${fileName(plan.responseModelName)}.fixture.json`;\n fixtureImports.add(`import ${toCamelCase(plan.responseModelName)}Fixture from '${fixturePath}';`);\n }\n // NOTE: Request body fixtures are not imported for body tests because\n // fixtures use wire format (snake_case) but methods expect domain types\n // (camelCase). Body tests use `{} as any` instead.\n }\n for (const imp of fixtureImports) {\n lines.push(imp);\n }\n\n lines.push('');\n lines.push(\"const workos = new WorkOS('sk_test_Sz3IQjepeSWaI4cMS4ms4sMuU');\");\n lines.push('');\n\n // Generate per-entity assertion helpers for models used in 2+ tests.\n // This deduplicates the field assertion blocks that would otherwise be\n // copy-pasted across list/find/create/update test cases.\n const { lines: helperLines, helpers: entityHelperNames } = generateEntityHelpers(plans, modelMap, ctx);\n for (const line of helperLines) {\n lines.push(line);\n }\n\n lines.push(`describe('${serviceClass}', () => {`);\n lines.push(' beforeEach(() => fetch.resetMocks());');\n\n for (const { op, plan, method } of plans) {\n lines.push('');\n lines.push(` describe('${method}', () => {`);\n\n if (plan.isPaginated) {\n renderPaginatedTest(lines, op, plan, method, serviceProp, modelMap, ctx, entityHelperNames);\n } else if (plan.isDelete) {\n renderDeleteTest(lines, op, plan, method, serviceProp, modelMap);\n } else if (plan.hasBody && plan.responseModelName) {\n renderBodyTest(lines, op, plan, method, serviceProp, modelMap, ctx, entityHelperNames);\n } else if (plan.responseModelName) {\n renderGetTest(lines, op, plan, method, serviceProp, modelMap, ctx, entityHelperNames);\n } else {\n renderVoidTest(lines, op, plan, method, serviceProp, modelMap);\n }\n\n // Error case test for all non-void operations\n if (plan.responseModelName || plan.isPaginated) {\n renderErrorTest(lines, op, plan, method, serviceProp, modelMap);\n }\n\n lines.push(' });');\n }\n\n lines.push('});');\n\n return { path: testPath, content: lines.join('\\n'), skipIfExists: true };\n}\n\n/** Compute the test value for a single path parameter.\n * Uses distinct values per param name so multi-param paths don't all get 'test_id'.\n */\nfunction pathParamTestValue(param: { type: TypeRef; name?: string } | undefined, paramName?: string): string {\n if (param?.type.kind === 'enum' && param.type.values?.length) {\n const first = param.type.values[0];\n return typeof first === 'string' ? first : String(first);\n }\n // Use distinct values for different path params to detect ordering bugs\n const name = paramName ?? (param as any)?.name;\n if (name) return `test_${fieldName(name)}`;\n return 'test_id';\n}\n\n/** Build test arguments for all path params (handles multiple path params). */\nfunction buildTestPathArgs(op: Operation): string {\n // Detect path template variables (may be more than op.pathParams if spec is incomplete)\n const templateVars = [...op.path.matchAll(/\\{(\\w+)\\}/g)].map(([, name]) => fieldName(name));\n const declaredNames = new Set(op.pathParams.map((p) => fieldName(p.name)));\n const paramByName = new Map(op.pathParams.map((p) => [fieldName(p.name), p]));\n // Merge declared + template vars, deduplicate, preserve order\n const allVars: string[] = [];\n for (const p of op.pathParams) allVars.push(fieldName(p.name));\n for (const v of templateVars) {\n if (!declaredNames.has(v)) allVars.push(v);\n }\n return allVars.map((varName) => `'${pathParamTestValue(paramByName.get(varName), varName)}'`).join(', ');\n}\n\nfunction renderPaginatedTest(\n lines: string[],\n op: Operation,\n plan: any,\n method: string,\n serviceProp: string,\n modelMap: Map<string, Model>,\n ctx?: EmitterContext,\n entityHelpers?: Set<string>,\n): void {\n let itemModelName = op.pagination?.itemType.kind === 'model' ? op.pagination.itemType.name : 'Item';\n // Unwrap list wrapper models to match the fixture file naming in fixtures.ts\n const rawModel = itemModelName !== 'Item' ? modelMap.get(itemModelName) : null;\n if (rawModel) {\n const unwrapped = unwrapListModel(rawModel, modelMap);\n if (unwrapped) {\n itemModelName = unwrapped.name;\n }\n }\n const pathArgs = buildTestPathArgs(op);\n\n lines.push(\" it('returns paginated results', async () => {\");\n lines.push(` fetchOnce(list${itemModelName}Fixture);`);\n lines.push('');\n lines.push(` const { data, listMetadata } = await workos.${serviceProp}.${method}(${pathArgs});`);\n lines.push('');\n lines.push(\" expect(fetchMethod()).toBe('GET');\");\n // Fix #12: Full URL path assertion instead of toContain()\n const expectedPath = buildExpectedPath(op);\n lines.push(` expect(new URL(String(fetchURL())).pathname).toBe('${expectedPath}');`);\n lines.push(\" expect(fetchSearchParams()).toHaveProperty('order');\");\n lines.push(' expect(Array.isArray(data)).toBe(true);');\n lines.push(' expect(listMetadata).toBeDefined();');\n\n // Assert on first item fields — use entity helper if available\n const paginatedHelperName = ctx ? `expect${resolveInterfaceName(itemModelName, ctx)}` : null;\n if (paginatedHelperName && entityHelpers?.has(paginatedHelperName)) {\n lines.push(' expect(data.length).toBeGreaterThan(0);');\n lines.push(` ${paginatedHelperName}(data[0]);`);\n } else {\n const itemModel = modelMap.get(itemModelName);\n if (itemModel) {\n const assertions = buildFieldAssertions(itemModel, 'data[0]', modelMap);\n if (assertions.length > 0) {\n lines.push(' expect(data.length).toBeGreaterThan(0);');\n for (const assertion of assertions) {\n lines.push(` ${assertion}`);\n }\n }\n }\n }\n\n lines.push(' });');\n\n // Edge case: handles empty results — use shared helper\n lines.push('');\n lines.push(` testEmptyResults(() => workos.${serviceProp}.${method}(${pathArgs}));`);\n\n // Edge case: forwards pagination params — use shared helper\n lines.push('');\n lines.push(` testPaginationParams(`);\n lines.push(` (opts) => workos.${serviceProp}.${method}(${pathArgs ? pathArgs + ', ' : ''}opts),`);\n lines.push(` list${itemModelName}Fixture,`);\n lines.push(' );');\n}\n\nfunction renderDeleteTest(\n lines: string[],\n op: Operation,\n plan: any,\n method: string,\n serviceProp: string,\n modelMap: Map<string, Model>,\n): void {\n const pathArgs = buildTestPathArgs(op);\n // Build realistic payload for body-bearing delete operations\n const payload = plan.hasBody ? buildTestPayload(op, modelMap) : null;\n const bodyArg = plan.hasBody ? (payload ? payload.camelCaseObj : fallbackBodyArg(op, modelMap)) : '';\n const args = plan.hasBody ? (pathArgs ? `${pathArgs}, ${bodyArg}` : bodyArg) : pathArgs;\n\n lines.push(\" it('sends a DELETE request', async () => {\");\n lines.push(' fetchOnce({}, { status: 204 });');\n lines.push('');\n lines.push(` await workos.${serviceProp}.${method}(${args});`);\n lines.push('');\n lines.push(\" expect(fetchMethod()).toBe('DELETE');\");\n // Fix #12: Full URL path assertion instead of toContain()\n const expectedPathDel = buildExpectedPath(op);\n lines.push(` expect(new URL(String(fetchURL())).pathname).toBe('${expectedPathDel}');`);\n if (plan.hasBody) {\n if (payload) {\n lines.push(` expect(fetchBody()).toEqual(expect.objectContaining(${payload.snakeCaseObj}));`);\n } else {\n lines.push(' expect(fetchBody()).toBeDefined();');\n }\n }\n lines.push(' });');\n}\n\nfunction renderBodyTest(\n lines: string[],\n op: Operation,\n plan: any,\n method: string,\n serviceProp: string,\n modelMap: Map<string, Model>,\n ctx?: EmitterContext,\n entityHelpers?: Set<string>,\n): void {\n const responseModelName = plan.responseModelName!;\n const fixture = `${toCamelCase(responseModelName)}Fixture`;\n const pathArgs = buildTestPathArgs(op);\n\n // Build realistic payload from request body model fields\n const payload = buildTestPayload(op, modelMap);\n const payloadArg = payload ? payload.camelCaseObj : fallbackBodyArg(op, modelMap);\n const allArgs = pathArgs ? `${pathArgs}, ${payloadArg}` : payloadArg;\n\n lines.push(\" it('sends the correct request and returns result', async () => {\");\n lines.push(` fetchOnce(${fixture});`);\n lines.push('');\n lines.push(` const result = await workos.${serviceProp}.${method}(${allArgs});`);\n lines.push('');\n lines.push(` expect(fetchMethod()).toBe('${op.httpMethod.toUpperCase()}');`);\n\n // Fix #12: Full URL path assertion instead of toContain()\n const expectedPath = buildExpectedPath(op);\n lines.push(` expect(new URL(String(fetchURL())).pathname).toBe('${expectedPath}');`);\n\n // Fix #10: Assert serialized wire format of request body\n if (payload) {\n lines.push(` expect(fetchBody()).toEqual(expect.objectContaining(${payload.snakeCaseObj}));`);\n } else {\n lines.push(' expect(fetchBody()).toBeDefined();');\n }\n\n // Use entity helper if available, otherwise inline assertions\n const bodyHelperName = ctx ? `expect${resolveInterfaceName(responseModelName, ctx)}` : null;\n if (bodyHelperName && entityHelpers?.has(bodyHelperName)) {\n lines.push(` ${bodyHelperName}(result);`);\n } else {\n const responseModel = modelMap.get(responseModelName);\n if (responseModel) {\n const assertions = buildFieldAssertions(responseModel, 'result', modelMap);\n if (assertions.length > 0) {\n for (const assertion of assertions) {\n lines.push(` ${assertion}`);\n }\n } else {\n lines.push(' expect(result).toBeDefined();');\n }\n } else {\n lines.push(' expect(result).toBeDefined();');\n }\n }\n\n lines.push(' });');\n}\n\nfunction renderGetTest(\n lines: string[],\n op: Operation,\n plan: any,\n method: string,\n serviceProp: string,\n modelMap: Map<string, Model>,\n ctx?: EmitterContext,\n entityHelpers?: Set<string>,\n): void {\n const responseModelName = plan.responseModelName!;\n const fixture = `${toCamelCase(responseModelName)}Fixture`;\n const pathArgs = buildTestPathArgs(op);\n\n lines.push(\" it('returns the expected result', async () => {\");\n lines.push(` fetchOnce(${fixture});`);\n lines.push('');\n lines.push(` const result = await workos.${serviceProp}.${method}(${pathArgs});`);\n lines.push('');\n lines.push(` expect(fetchMethod()).toBe('${op.httpMethod.toUpperCase()}');`);\n // Fix #12: Full URL path assertion instead of toContain()\n const expectedPathGet = buildExpectedPath(op);\n lines.push(` expect(new URL(String(fetchURL())).pathname).toBe('${expectedPathGet}');`);\n\n // Use entity helper if available, otherwise inline assertions\n const helperName = ctx ? `expect${resolveInterfaceName(responseModelName, ctx)}` : null;\n if (helperName && entityHelpers?.has(helperName)) {\n lines.push(` ${helperName}(result);`);\n } else {\n const responseModel = modelMap.get(responseModelName);\n if (responseModel) {\n const assertions = buildFieldAssertions(responseModel, 'result', modelMap);\n if (assertions.length > 0) {\n for (const assertion of assertions) {\n lines.push(` ${assertion}`);\n }\n } else {\n lines.push(' expect(result).toBeDefined();');\n }\n } else {\n lines.push(' expect(result).toBeDefined();');\n }\n }\n\n lines.push(' });');\n}\n\nfunction renderVoidTest(\n lines: string[],\n op: Operation,\n plan: any,\n method: string,\n serviceProp: string,\n modelMap: Map<string, Model>,\n): void {\n const pathArgs = buildTestPathArgs(op);\n // Build realistic payload for body-bearing void operations\n const payload = plan.hasBody ? buildTestPayload(op, modelMap) : null;\n const bodyArg = plan.hasBody ? (payload ? payload.camelCaseObj : fallbackBodyArg(op, modelMap)) : '';\n const args = plan.hasBody ? (pathArgs ? `${pathArgs}, ${bodyArg}` : bodyArg) : pathArgs;\n\n lines.push(\" it('sends the request', async () => {\");\n lines.push(' fetchOnce({});');\n lines.push('');\n lines.push(` await workos.${serviceProp}.${method}(${args});`);\n lines.push('');\n lines.push(` expect(fetchMethod()).toBe('${op.httpMethod.toUpperCase()}');`);\n // Fix #12: Full URL path assertion instead of toContain()\n const expectedPathVoid = buildExpectedPath(op);\n lines.push(` expect(new URL(String(fetchURL())).pathname).toBe('${expectedPathVoid}');`);\n if (plan.hasBody && payload) {\n lines.push(` expect(fetchBody()).toEqual(expect.objectContaining(${payload.snakeCaseObj}));`);\n }\n lines.push(' });');\n}\n\nfunction renderErrorTest(\n lines: string[],\n op: Operation,\n plan: any,\n method: string,\n serviceProp: string,\n modelMap: Map<string, Model>,\n): void {\n const args = buildCallArgs(op, plan, modelMap);\n\n lines.push('');\n lines.push(` testUnauthorized(() => workos.${serviceProp}.${method}(${args}));`);\n\n // Add error-status tests based on the operation's error responses\n const errorStatuses = new Set(op.errors.map((e) => e.statusCode));\n\n // 404 test for find/get methods\n if (errorStatuses.has(404) && (method.startsWith('get') || method.startsWith('find'))) {\n lines.push('');\n lines.push(\" it('throws NotFoundException on 404', async () => {\");\n lines.push(\" fetchOnce('', { status: 404 });\");\n lines.push(` await expect(workos.${serviceProp}.${method}(${args})).rejects.toThrow();`);\n lines.push(' });');\n }\n\n // 422 test for create/update methods\n if (errorStatuses.has(422) && (method.startsWith('create') || method.startsWith('update'))) {\n lines.push('');\n lines.push(\" it('throws UnprocessableEntityException on 422', async () => {\");\n lines.push(\" fetchOnce('', { status: 422 });\");\n lines.push(` await expect(workos.${serviceProp}.${method}(${args})).rejects.toThrow();`);\n lines.push(' });');\n }\n}\n\n/**\n * Build the argument string for a method call in tests.\n * Shared by renderErrorTest and other test renderers.\n */\nfunction buildCallArgs(op: Operation, plan: any, modelMap: Map<string, Model>): string {\n const pathArgs = buildTestPathArgs(op);\n const isPaginated = plan.isPaginated;\n const hasBody = plan.hasBody;\n\n if (isPaginated) return pathArgs || '';\n if (hasBody) {\n const payload = buildTestPayload(op, modelMap);\n const bodyArg = payload ? payload.camelCaseObj : fallbackBodyArg(op, modelMap);\n return pathArgs ? `${pathArgs}, ${bodyArg}` : bodyArg;\n }\n return pathArgs || '';\n}\n\n/**\n * Generate per-entity assertion helper functions for models used in 2+ tests.\n * Returns lines like: function expectConnection(result: any) { expect(...) }\n */\n/**\n * Generate per-entity assertion helper functions for models used in 2+ tests.\n * Returns { lines, helpers } where helpers is a Set of helper function names.\n */\nfunction generateEntityHelpers(\n plans: { op: Operation; plan: any; method: string }[],\n modelMap: Map<string, Model>,\n ctx: EmitterContext,\n): { lines: string[]; helpers: Set<string> } {\n // Count how many tests reference each response model\n const modelUsage = new Map<string, number>();\n for (const { op, plan } of plans) {\n let modelName: string | null = null;\n if (plan.isPaginated && op.pagination?.itemType.kind === 'model') {\n modelName = op.pagination.itemType.name;\n const rawModel = modelMap.get(modelName);\n if (rawModel) {\n const unwrapped = unwrapListModel(rawModel, modelMap);\n if (unwrapped) modelName = unwrapped.name;\n }\n } else if (plan.responseModelName) {\n modelName = plan.responseModelName;\n }\n if (modelName) {\n modelUsage.set(modelName, (modelUsage.get(modelName) ?? 0) + 1);\n }\n }\n\n const lines: string[] = [];\n const helpers = new Set<string>();\n for (const [modelName, count] of modelUsage) {\n if (count < 2) continue;\n const model = modelMap.get(modelName);\n if (!model) continue;\n const assertions = buildFieldAssertions(model, 'result', modelMap);\n if (assertions.length === 0) continue;\n\n const domainName = resolveInterfaceName(modelName, ctx);\n const helperName = `expect${domainName}`;\n if (helpers.has(helperName)) continue;\n helpers.add(helperName);\n\n lines.push(`function ${helperName}(result: any) {`);\n for (const assertion of assertions) {\n lines.push(` ${assertion}`);\n }\n lines.push('}');\n lines.push('');\n }\n return { lines, helpers };\n}\n\n/**\n * Build field-level assertions for top-level primitive fields of a response model.\n * Returns lines like: expect(result.fieldName).toBe(fixtureValue);\n *\n * When the top level has no assertable primitive fields (e.g. wrapper types\n * whose only required fields are nested models), recurse one level into those\n * nested models so we still get meaningful assertions instead of a bare\n * `toBeDefined()`.\n */\nfunction buildFieldAssertions(model: Model, accessor: string, modelMap?: Map<string, Model>): string[] {\n const assertions: string[] = [];\n\n for (const field of model.fields) {\n if (!field.required) continue;\n // When a field has an example value, use it as the expected assertion value\n if (field.example !== undefined) {\n const domainField = fieldName(field.name);\n if (typeof field.example === 'object' && field.example !== null) {\n // Objects and arrays need toEqual with JSON serialization\n assertions.push(`expect(${accessor}.${domainField}).toEqual(${JSON.stringify(field.example)});`);\n } else {\n const exampleLiteral = typeof field.example === 'string' ? `'${field.example}'` : String(field.example);\n assertions.push(`expect(${accessor}.${domainField}).toBe(${exampleLiteral});`);\n }\n continue;\n }\n const value = fixtureValueForType(field.type, field.name, model.name);\n if (value === null) continue;\n const domainField = fieldName(field.name);\n assertions.push(`expect(${accessor}.${domainField}).toBe(${value});`);\n }\n\n // When no primitive assertions were found (e.g. wrapper types like\n // ResetPasswordResponse { user: User }), recurse one level into nested\n // model-type fields to generate assertions on their primitive fields.\n if (assertions.length === 0 && modelMap) {\n for (const field of model.fields) {\n if (!field.required) continue;\n if (field.type.kind === 'model') {\n const nestedModel = modelMap.get(field.type.name);\n if (nestedModel) {\n const nestedAccessor = `${accessor}.${fieldName(field.name)}`;\n // Recurse without modelMap to limit depth to one level\n const nested = buildFieldAssertions(nestedModel, nestedAccessor);\n assertions.push(...nested);\n }\n }\n }\n }\n\n return assertions;\n}\n\n/**\n * Return a JS literal string for the expected fixture value of a field.\n * Returns null for types that cannot be deterministically generated.\n * When a modelMap is provided, recursively builds object literals for nested model types.\n * When wire is true, uses snake_case keys for nested model objects (wire format).\n */\nfunction fixtureValueForType(\n ref: TypeRef,\n name: string,\n modelName: string,\n modelMap?: Map<string, Model>,\n wire?: boolean,\n): string | null {\n switch (ref.kind) {\n case 'primitive':\n return fixtureValueForPrimitive(ref.type, ref.format, name, modelName);\n case 'literal':\n return typeof ref.value === 'string' ? `'${ref.value}'` : String(ref.value);\n case 'enum':\n // Use the first enum value as a realistic fixture value\n if (ref.values?.length) {\n const first = ref.values[0];\n return typeof first === 'string' ? `'${first}'` : String(first);\n }\n return null;\n case 'array': {\n // For arrays of primitives/enums, generate a single-element array assertion.\n // For arrays of models/complex types, return null to skip the assertion —\n // the fixture will have populated items that we can't predict here.\n const itemValue = fixtureValueForType(ref.items, name, modelName, modelMap, wire);\n if (itemValue !== null) return `[${itemValue}]`;\n return null;\n }\n case 'model': {\n if (!modelMap) return null;\n const nested = modelMap.get(ref.name);\n if (!nested) return null;\n const requiredFields = nested.fields.filter((f) => f.required);\n const entries: string[] = [];\n for (const field of requiredFields) {\n const value = fixtureValueForType(field.type, field.name, nested.name, modelMap, wire);\n if (value === null) return null; // Can't build a complete object\n const key = wire ? wireFieldName(field.name) : fieldName(field.name);\n entries.push(`${key}: ${value}`);\n }\n return `{ ${entries.join(', ')} }`;\n }\n default:\n return null;\n }\n}\n\nfunction fixtureValueForPrimitive(\n type: string,\n format: string | undefined,\n name: string,\n modelName: string,\n): string | null {\n switch (type) {\n case 'string':\n if (format === 'date-time') return \"'2023-01-01T00:00:00.000Z'\";\n if (format === 'date') return \"'2023-01-01'\";\n if (format === 'uuid') return \"'00000000-0000-0000-0000-000000000000'\";\n if (name === 'id') {\n const prefix = ID_PREFIXES[modelName] ?? '';\n return `'${prefix}01234'`;\n }\n if (name.includes('id')) return `'${wireFieldName(name)}_01234'`;\n if (name.includes('email')) return \"'test@example.com'\";\n if (name.includes('url') || name.includes('uri')) return \"'https://example.com'\";\n if (name.includes('name')) return \"'Test'\";\n return `'test_${wireFieldName(name)}'`;\n case 'integer':\n return '1';\n case 'number':\n return '1';\n case 'boolean':\n return 'true';\n default:\n return null;\n }\n}\n\n/**\n * Build the expected full URL path for an operation, substituting path params\n * with their test values. Returns a string like '/organizations/test_id'.\n */\nfunction buildExpectedPath(op: Operation): string {\n let path = op.path;\n for (const param of op.pathParams) {\n path = path.replace(`{${param.name}}`, pathParamTestValue(param, fieldName(param.name)));\n }\n return path;\n}\n\n/**\n * Build a realistic test payload for a request body model.\n * Returns { camelCaseObj, snakeCaseObj } as inline JS object literal strings,\n * or null if the request body is not a named model.\n *\n * camelCaseObj is what the SDK consumer passes (e.g. { organizationName: 'Test' })\n * snakeCaseObj is the expected wire format (e.g. { organization_name: 'Test' })\n */\nfunction buildTestPayload(\n op: Operation,\n modelMap: Map<string, Model>,\n): { camelCaseObj: string; snakeCaseObj: string } | null {\n if (!op.requestBody || op.requestBody.kind !== 'model') return null;\n\n const model = modelMap.get(op.requestBody.name);\n if (!model) return null;\n\n const fields = model.fields.filter((f) => f.required);\n // Only use fields that we can generate deterministic values for (primitives, enums, and nested models)\n const usableFields = fields.filter((f) => fixtureValueForType(f.type, f.name, model.name, modelMap) !== null);\n\n // Only generate a typed payload when ALL required fields have fixture values.\n // A partial payload missing required fields would fail TypeScript type checking.\n if (usableFields.length === 0 || usableFields.length < fields.length) return null;\n\n const camelEntries: string[] = [];\n const snakeEntries: string[] = [];\n\n for (const field of usableFields) {\n const camelValue = fixtureValueForType(field.type, field.name, model.name, modelMap)!;\n const wireValue = fixtureValueForType(field.type, field.name, model.name, modelMap, true)!;\n const camelKey = fieldName(field.name);\n const snakeKey = wireFieldName(field.name);\n camelEntries.push(`${camelKey}: ${camelValue}`);\n snakeEntries.push(`${snakeKey}: ${wireValue}`);\n }\n\n return {\n camelCaseObj: `{ ${camelEntries.join(', ')} }`,\n snakeCaseObj: `{ ${snakeEntries.join(', ')} }`,\n };\n}\n\n/**\n * Compute a fallback body argument when buildTestPayload returns null.\n * If the request body model has no required fields (all optional), an empty\n * object `{}` is a valid value and doesn't need a type assertion. Otherwise,\n * fall back to `{} as any` to bypass type checking for complex required fields.\n */\nfunction fallbackBodyArg(op: Operation, modelMap: Map<string, Model>): string {\n if (!op.requestBody || op.requestBody.kind !== 'model') return '{} as any';\n const model = modelMap.get(op.requestBody.name);\n if (!model) return '{} as any';\n const hasRequiredFields = model.fields.some((f) => f.required);\n return hasRequiredFields ? '{} as any' : '{}';\n}\n\n/**\n * Determine whether a model should get a round-trip serializer test.\n * Includes all models with at least one field — every model gets both\n * serialize and deserialize functions, so all benefit from round-trip testing.\n */\nfunction modelNeedsRoundTripTest(model: Model): boolean {\n return model.fields.length > 0;\n}\n\n/**\n * Generate serializer round-trip tests for models that have both serialize and\n * deserialize functions and have nested types requiring non-trivial serialization.\n */\nfunction generateSerializerTests(spec: ApiSpec, ctx: EmitterContext): GeneratedFile[] {\n const files: GeneratedFile[] = [];\n const modelToService = assignModelsToServices(spec.models, spec.services);\n const serviceNameMap = new Map<string, string>();\n for (const service of spec.services) {\n serviceNameMap.set(service.name, resolveResourceClassName(service, ctx));\n }\n const resolveDir = (irService: string | undefined) =>\n irService ? resolveServiceDir(serviceNameMap.get(irService) ?? irService) : 'common';\n\n // Only generate round-trip tests for models with fields that have serializers generated.\n // Skip list metadata and list wrapper models since their serializers are not emitted.\n const eligibleModels = spec.models.filter(\n (m) => modelNeedsRoundTripTest(m) && !isListMetadataModel(m) && !isListWrapperModel(m),\n );\n\n if (eligibleModels.length === 0) return files;\n\n // Group eligible models by service directory for one test file per service\n const modelsByDir = new Map<string, Model[]>();\n for (const model of eligibleModels) {\n const service = modelToService.get(model.name);\n const dirName = resolveDir(service);\n if (!modelsByDir.has(dirName)) {\n modelsByDir.set(dirName, []);\n }\n modelsByDir.get(dirName)!.push(model);\n }\n\n for (const [dirName, models] of modelsByDir) {\n const testPath = `src/${dirName}/serializers.spec.ts`;\n const lines: string[] = [];\n\n // Collect imports\n const serializerImports: string[] = [];\n const fixtureImports: string[] = [];\n\n for (const model of models) {\n const domainName = resolveInterfaceName(model.name, ctx);\n const service = modelToService.get(model.name);\n const modelDir = resolveDir(service);\n const serializerPath = `src/${modelDir}/serializers/${fileName(model.name)}.serializer.ts`;\n const fixturePath = `src/${modelDir}/fixtures/${fileName(model.name)}.fixture.json`;\n\n serializerImports.push(\n `import { deserialize${domainName}, serialize${domainName} } from '${relativeImport(testPath, serializerPath)}';`,\n );\n fixtureImports.push(`import ${toCamelCase(model.name)}Fixture from '${relativeImport(testPath, fixturePath)}';`);\n }\n\n for (const imp of serializerImports) {\n lines.push(imp);\n }\n for (const imp of fixtureImports) {\n lines.push(imp);\n }\n lines.push('');\n\n for (const model of models) {\n const domainName = resolveInterfaceName(model.name, ctx);\n const fixtureName = `${toCamelCase(model.name)}Fixture`;\n\n lines.push(`describe('${domainName}Serializer', () => {`);\n lines.push(\" it('round-trips through serialize/deserialize', () => {\");\n lines.push(` const fixture = ${fixtureName};`);\n lines.push(` const deserialized = deserialize${domainName}(fixture);`);\n lines.push(` const reserialized = serialize${domainName}(deserialized);`);\n lines.push(' expect(reserialized).toEqual(expect.objectContaining(fixture));');\n lines.push(' });');\n lines.push('});');\n lines.push('');\n }\n\n files.push({\n path: testPath,\n content: lines.join('\\n'),\n skipIfExists: true,\n integrateTarget: false,\n });\n }\n\n return files;\n}\n","import type { ApiSpec, EmitterContext, GeneratedFile } from '@workos/oagen';\nimport { resolveMethodName, servicePropertyName } from './naming.js';\nimport { resolveResourceClassName } from './resources.js';\n\nexport function generateManifest(spec: ApiSpec, ctx: EmitterContext): GeneratedFile[] {\n const manifest: Record<string, { sdkMethod: string; service: string }> = {};\n\n for (const service of spec.services) {\n const propName = servicePropertyName(resolveResourceClassName(service, ctx));\n for (const op of service.operations) {\n const httpKey = `${op.httpMethod.toUpperCase()} ${op.path}`;\n const method = resolveMethodName(op, service, ctx);\n manifest[httpKey] = { sdkMethod: method, service: propName };\n }\n }\n\n return [\n {\n path: 'smoke-manifest.json',\n content: JSON.stringify(manifest, null, 2),\n integrateTarget: false,\n overwriteExisting: true,\n },\n ];\n}\n","import type {\n Emitter,\n EmitterContext,\n FormatCommand,\n GeneratedFile,\n ApiSpec,\n Model,\n Enum,\n Service,\n} from '@workos/oagen';\nimport * as fs from 'node:fs';\nimport * as path from 'node:path';\n\nimport { generateModels } from './models.js';\nimport { generateEnums } from './enums.js';\nimport { generateSerializers } from './serializers.js';\nimport { generateResources } from './resources.js';\nimport { generateClient } from './client.js';\nimport { generateErrors } from './errors.js';\nimport { generateConfig } from './config.js';\nimport { generateCommon } from './common.js';\nimport { generateTests } from './tests.js';\nimport { generateManifest } from './manifest.js';\n\n/** Ensure every generated file's content ends with a trailing newline. */\nfunction ensureTrailingNewlines(files: GeneratedFile[]): GeneratedFile[] {\n for (const f of files) {\n if (f.content && !f.content.endsWith('\\n')) {\n f.content += '\\n';\n }\n }\n return files;\n}\n\nexport const nodeEmitter: Emitter = {\n language: 'node',\n\n generateModels(models: Model[], ctx: EmitterContext): GeneratedFile[] {\n return ensureTrailingNewlines([...generateModels(models, ctx), ...generateSerializers(models, ctx)]);\n },\n\n generateEnums(enums: Enum[], ctx: EmitterContext): GeneratedFile[] {\n return ensureTrailingNewlines(generateEnums(enums, ctx));\n },\n\n generateResources(services: Service[], ctx: EmitterContext): GeneratedFile[] {\n return ensureTrailingNewlines(generateResources(services, ctx));\n },\n\n generateClient(spec: ApiSpec, ctx: EmitterContext): GeneratedFile[] {\n return ensureTrailingNewlines(generateClient(spec, ctx));\n },\n\n generateErrors(ctx: EmitterContext): GeneratedFile[] {\n return ensureTrailingNewlines(generateErrors(ctx));\n },\n\n generateConfig(_ctx: EmitterContext): GeneratedFile[] {\n return ensureTrailingNewlines([...generateConfig(), ...generateCommon()]);\n },\n\n generateTypeSignatures(_spec: ApiSpec, _ctx: EmitterContext): GeneratedFile[] {\n // TypeScript uses inline types — no separate type signature files needed\n return [];\n },\n\n generateTests(spec: ApiSpec, ctx: EmitterContext): GeneratedFile[] {\n return ensureTrailingNewlines(generateTests(spec, ctx));\n },\n\n generateManifest(spec: ApiSpec, ctx: EmitterContext): GeneratedFile[] {\n return ensureTrailingNewlines(generateManifest(spec, ctx));\n },\n\n fileHeader(): string {\n return '// This file is auto-generated by oagen. Do not edit.';\n },\n\n formatCommand(targetDir: string): FormatCommand | null {\n const hasPrettier = fs.existsSync(path.join(targetDir, '.prettierrc'));\n const hasEslint =\n fs.existsSync(path.join(targetDir, 'eslint.config.mjs')) ||\n fs.existsSync(path.join(targetDir, 'eslint.config.js')) ||\n fs.existsSync(path.join(targetDir, '.eslintrc.json')) ||\n fs.existsSync(path.join(targetDir, '.eslintrc.js'));\n\n if (hasPrettier && hasEslint) {\n // Chain ESLint autofix (e.g. unused-import removal) then prettier.\n // ESLint errors are suppressed so formatting still runs on lint failure.\n return {\n cmd: 'bash',\n args: [\n '-c',\n 'npx eslint --fix --no-error-on-unmatched-pattern \"$@\" 2>/dev/null; npx prettier --write --log-level silent \"$@\"',\n '--',\n ],\n };\n }\n if (hasPrettier) {\n return {\n cmd: 'npx',\n args: ['prettier', '--write', '--log-level', 'silent'],\n };\n }\n if (hasEslint) {\n return {\n cmd: 'npx',\n args: ['eslint', '--fix', '--no-error-on-unmatched-pattern'],\n };\n }\n return null;\n },\n};\n"],"mappings":"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"}
|