@workos/oagen 0.5.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { A as collectModelRefs, B as LoggingPolicy, C as TypeParam, D as assignModelsToServices, E as assertNever, F as BackoffStrategy, G as TelemetryPolicy, H as RequestGuardPolicy, I as DeepPartial, J as defaultSdkBehavior, K as TimeoutPolicy, L as ErrorPolicy, M as mapTypeRef, N as walkTypeRef, O as collectEnumRefs, P as AiAgentEnvVar, R as IdempotencyPolicy, S as SuccessResponse, T as UnionType, U as RetryPolicy, V as PaginationPolicy, W as SdkBehavior, Y as mergeSdkBehavior, _ as Parameter, a as EnumRef, b as ServerEntry, c as Field, d as MapType, f as Model, g as PaginationMeta, h as Operation, i as Enum, it as ApiSurface, j as collectRequestBodyModels, k as collectFieldDependencies, l as HttpMethod, m as NullableType, n as ArrayType, o as EnumValue, p as ModelRef, q as UserAgentPolicy, r as AuthScheme, s as ErrorResponse, st as Extractor, t as ApiSpec, u as LiteralType, ut as OverlayLookup, v as PrimitiveType, w as TypeRef, x as Service, y as SecurityRequirement, z as LogEvent } from "./types-D84LjrVG.mjs";
1
+ import { A as collectEnumRefs, B as IdempotencyPolicy, C as Service, D as UnionType, E as TypeRef, F as walkTypeRef, G as RetryPolicy, H as LoggingPolicy, I as AiAgentEnvVar, J as TimeoutPolicy, K as SdkBehavior, L as BackoffStrategy, M as collectModelRefs, N as collectRequestBodyModels, O as assertNever, P as mapTypeRef, R as DeepPartial, S as ServerEntry, T as TypeParam, U as PaginationPolicy, V as LogEvent, W as RequestGuardPolicy, X as defaultSdkBehavior, Y as UserAgentPolicy, Z as mergeSdkBehavior, _ as Parameter, a as EnumRef, b as PrimitiveType, c as Field, d as MapType, f as Model, ft as OverlayLookup, g as PaginationMeta, h as Operation, i as Enum, j as collectFieldDependencies, k as assignModelsToServices, l as HttpMethod, lt as Extractor, m as NullableType, n as ArrayType, o as EnumValue, ot as ApiSurface, p as ModelRef, q as TelemetryPolicy, r as AuthScheme, s as ErrorResponse, t as ApiSpec, u as LiteralType, v as ParameterGroup, w as SuccessResponse, x as SecurityRequirement, y as ParameterGroupVariant, z as ErrorPolicy } from "./types-DJMbCtIO.mjs";
2
2
 
3
3
  //#region src/ir/operation-hints.d.ts
4
4
  /** Per-operation override keyed by "METHOD /path" (e.g. "POST /sso/token"). */
@@ -13,6 +13,13 @@ interface OperationHint {
13
13
  defaults?: Record<string, string | number | boolean>;
14
14
  /** Fields the SDK reads from client config at runtime (e.g. ['client_id']). */
15
15
  inferFromClient?: string[];
16
+ /**
17
+ * Marks this operation as a URL builder rather than a real HTTP call. Emitters
18
+ * should generate a method that returns the constructed URL (typically as a
19
+ * string) without performing any I/O. Used for OAuth-style redirect endpoints
20
+ * such as /sso/authorize and /user_management/sessions/logout.
21
+ */
22
+ urlBuilder?: boolean;
16
23
  }
17
24
  interface SplitHint {
18
25
  /** Wrapper method name (snake_case). */
@@ -25,6 +32,12 @@ interface SplitHint {
25
32
  inferFromClient?: string[];
26
33
  /** Only these body fields are exposed as method params. If omitted, all non-default/non-inferred fields are exposed. */
27
34
  exposedParams?: string[];
35
+ /**
36
+ * Subset of exposedParams that should be emitted as optional even when the
37
+ * variant model would otherwise mark them required (or when the variant has
38
+ * no addressable model, as happens for inline oneOf branches).
39
+ */
40
+ optionalParams?: string[];
28
41
  }
29
42
  interface ResolvedOperation {
30
43
  /** The original IR operation (preserves description, params, types, etc.). */
@@ -41,6 +54,8 @@ interface ResolvedOperation {
41
54
  defaults: Record<string, string | number | boolean>;
42
55
  /** Fields the SDK reads from client config at runtime (from operation-level hint). */
43
56
  inferFromClient: string[];
57
+ /** Marks this operation as a URL builder; emitters should not generate an HTTP call. */
58
+ urlBuilder: boolean;
44
59
  }
45
60
  interface ResolvedWrapper {
46
61
  /** Wrapper method name (snake_case). */
@@ -146,6 +161,16 @@ interface EmitterContext {
146
161
  overlayLookup?: OverlayLookup;
147
162
  /** Resolved operations from the hint-aware resolver. Populated by buildEmitterContext(). */
148
163
  resolvedOperations?: ResolvedOperation[];
164
+ /** Absolute path to the integration target directory (when --target is used). */
165
+ targetDir?: string;
166
+ /**
167
+ * Paths (relative to the target dir) that the previous run wrote into
168
+ * `--target`, loaded from that directory's `.oagen-manifest.json`. Emitters
169
+ * can use this to distinguish "file exists because oagen wrote it last time"
170
+ * from "file exists because a human wrote it" — the former is safe to
171
+ * overwrite, the latter should be merged.
172
+ */
173
+ priorTargetManifestPaths?: Set<string>;
149
174
  }
150
175
  interface FormatCommand {
151
176
  /** The executable to run (e.g., "npx", "gofmt", "bundle"). */
@@ -292,7 +317,8 @@ declare function generate(spec: ApiSpec, emitter: Emitter, options: {
292
317
  apiSurface?: ApiSurface;
293
318
  overlayLookup?: OverlayLookup;
294
319
  operationHints?: Record<string, OperationHint>;
295
- mountRules?: Record<string, string>;
320
+ mountRules?: Record<string, string>; /** When true, skip deletion of files recorded in the previous manifest but not in the current emission. */
321
+ noPrune?: boolean;
296
322
  }): Promise<GeneratedFile[]>;
297
323
  //#endregion
298
324
  //#region src/engine/generate-files.d.ts
@@ -303,6 +329,8 @@ declare function buildEmitterContext(spec: ApiSpec, options: {
303
329
  overlayLookup?: OverlayLookup;
304
330
  operationHints?: Record<string, OperationHint>;
305
331
  mountRules?: Record<string, string>;
332
+ target?: string;
333
+ priorTargetManifestPaths?: Set<string>;
306
334
  }): EmitterContext;
307
335
  /**
308
336
  * Collect model and enum names transitively referenced by service operations.
@@ -324,6 +352,8 @@ declare function generateFiles(spec: ApiSpec, emitter: Emitter, options: {
324
352
  overlayLookup?: OverlayLookup;
325
353
  operationHints?: Record<string, OperationHint>;
326
354
  mountRules?: Record<string, string>;
355
+ target?: string;
356
+ priorTargetManifestPaths?: Set<string>;
327
357
  }): {
328
358
  files: GeneratedFile[];
329
359
  ctx: EmitterContext;
@@ -346,12 +376,16 @@ interface WriteResult {
346
376
  */
347
377
  declare function treeShakeFiles(files: GeneratedFile[], language: string): Promise<GeneratedFile[]>;
348
378
  declare function mapFilesForTargetIntegration(files: GeneratedFile[], language: string): GeneratedFile[];
379
+ interface IntegrateResult extends WriteResult {
380
+ /** Final set of paths this run claims ownership of in the target (post tree-shake + conflict resolution). */
381
+ emittedPaths: string[];
382
+ }
349
383
  declare function integrateGeneratedFiles(opts: {
350
384
  files: GeneratedFile[];
351
385
  language: string;
352
386
  targetDir: string;
353
387
  header: string;
354
- }): Promise<WriteResult>;
388
+ }): Promise<IntegrateResult>;
355
389
  //#endregion
356
390
  //#region src/engine/registry.d.ts
357
391
  declare function registerEmitter(emitter: Emitter): void;
@@ -383,6 +417,10 @@ interface OperationPlan {
383
417
  * (unwrapped from the list wrapper). Null for non-paginated. */
384
418
  paginatedItemModelName: string | null;
385
419
  isModelResponse: boolean;
420
+ /** True when the response is an unpaginated `type: array` of models.
421
+ * Emitters should use this to return `Model[]` (or the language's list
422
+ * equivalent) and map the deserializer over each element. */
423
+ isArrayResponse: boolean;
386
424
  hasQueryParams: boolean;
387
425
  isAsync: boolean;
388
426
  }
@@ -428,5 +466,5 @@ interface OagenConfig {
428
466
  mountRules?: Record<string, string>;
429
467
  }
430
468
  //#endregion
431
- export { ACRONYM_SET, type AiAgentEnvVar, type ApiSpec, type ArrayType, type AuthScheme, type BackoffStrategy, type Change, CommandError, ConfigError, ConfigLoadError, ConfigVersionMismatchError, type DeepPartial, type DiffReport, type Emitter, type EmitterContext, type Enum, type EnumAdded, type EnumModified, type EnumRef, type EnumRemoved, type EnumValue, type EnumValueChange, type ErrorPolicy, type ErrorResponse, ExtractorError, type Field, type FieldChange, type FormatCommand, type GeneratedFile, type HttpMethod, type IdempotencyPolicy, InternalError, type LiteralType, type LogEvent, type LoggingPolicy, type MapType, type Model, type ModelAdded, type ModelModified, type ModelRef, type ModelRemoved, type NullableType, type OagenConfig, OagenError, type Operation, type OperationAdded, type OperationHint, type OperationModified, type OperationPlan, type OperationRemoved, type PaginationMeta, type PaginationPolicy, type ParamChange, type Parameter, type PrimitiveType, RegistryError, type RequestGuardPolicy, type ResolvedOperation, type ResolvedWrapper, type RetryPolicy, type SdkBehavior, type SecurityRequirement, type ServerEntry, type Service, type ServiceAdded, type ServiceRemoved, SpecParseError, type SplitHint, type SuccessResponse, type TelemetryPolicy, type TimeoutPolicy, type TypeParam, type TypeRef, type UnionType, type UserAgentPolicy, applyFileHeaders, assertNever, assignModelsToServices, buildEmitterContext, cleanSchemaName, collectEnumRefs, collectFieldDependencies, collectModelRefs, collectReferencedNames, collectRequestBodyModels, defaultSdkBehavior, deriveMethodName, diffSpecs, generate, generateAllFiles, generateFiles, getEmitter, integrateGeneratedFiles, mapFilesForTargetIntegration, mapTypeRef, mergeSdkBehavior, parseSpec, planOperation, registerEmitter, resolveOperations, stripBackendPrefixes, toCamelCase, toKebabCase, toPascalCase, toSnakeCase, toUpperSnakeCase, treeShakeFiles, walkTypeRef };
469
+ export { ACRONYM_SET, type AiAgentEnvVar, type ApiSpec, type ArrayType, type AuthScheme, type BackoffStrategy, type Change, CommandError, ConfigError, ConfigLoadError, ConfigVersionMismatchError, type DeepPartial, type DiffReport, type Emitter, type EmitterContext, type Enum, type EnumAdded, type EnumModified, type EnumRef, type EnumRemoved, type EnumValue, type EnumValueChange, type ErrorPolicy, type ErrorResponse, ExtractorError, type Field, type FieldChange, type FormatCommand, type GeneratedFile, type HttpMethod, type IdempotencyPolicy, InternalError, type LiteralType, type LogEvent, type LoggingPolicy, type MapType, type Model, type ModelAdded, type ModelModified, type ModelRef, type ModelRemoved, type NullableType, type OagenConfig, OagenError, type Operation, type OperationAdded, type OperationHint, type OperationModified, type OperationPlan, type OperationRemoved, type PaginationMeta, type PaginationPolicy, type ParamChange, type Parameter, type ParameterGroup, type ParameterGroupVariant, type PrimitiveType, RegistryError, type RequestGuardPolicy, type ResolvedOperation, type ResolvedWrapper, type RetryPolicy, type SdkBehavior, type SecurityRequirement, type ServerEntry, type Service, type ServiceAdded, type ServiceRemoved, SpecParseError, type SplitHint, type SuccessResponse, type TelemetryPolicy, type TimeoutPolicy, type TypeParam, type TypeRef, type UnionType, type UserAgentPolicy, applyFileHeaders, assertNever, assignModelsToServices, buildEmitterContext, cleanSchemaName, collectEnumRefs, collectFieldDependencies, collectModelRefs, collectReferencedNames, collectRequestBodyModels, defaultSdkBehavior, deriveMethodName, diffSpecs, generate, generateAllFiles, generateFiles, getEmitter, integrateGeneratedFiles, mapFilesForTargetIntegration, mapTypeRef, mergeSdkBehavior, parseSpec, planOperation, registerEmitter, resolveOperations, stripBackendPrefixes, toCamelCase, toKebabCase, toPascalCase, toSnakeCase, toUpperSnakeCase, treeShakeFiles, walkTypeRef };
432
470
  //# sourceMappingURL=index.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../src/ir/operation-hints.ts","../src/errors.ts","../src/engine/types.ts","../src/differ/types.ts","../src/parser/parse.ts","../src/engine/orchestrator.ts","../src/engine/generate-files.ts","../src/engine/writer.ts","../src/engine/integrate.ts","../src/engine/registry.ts","../src/differ/diff.ts","../src/utils/naming.ts","../src/engine/operation-plan.ts","../src/cli/config-loader.ts"],"mappings":"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"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../src/ir/operation-hints.ts","../src/errors.ts","../src/engine/types.ts","../src/differ/types.ts","../src/parser/parse.ts","../src/engine/orchestrator.ts","../src/engine/generate-files.ts","../src/engine/writer.ts","../src/engine/integrate.ts","../src/engine/registry.ts","../src/differ/diff.ts","../src/utils/naming.ts","../src/engine/operation-plan.ts","../src/cli/config-loader.ts"],"mappings":"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"}
package/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  import { A as walkTypeRef, C as assertNever, D as collectModelRefs, E as collectFieldDependencies, O as collectRequestBodyModels, S as SpecParseError, T as collectEnumRefs, _ as ConfigVersionMismatchError, a as singularize, b as OagenError, c as stripListItemMarkers, d as toPascalCase, f as toSnakeCase, g as ConfigLoadError, h as ConfigError, k as mapTypeRef, l as toCamelCase, m as CommandError, n as ACRONYM_SET, p as toUpperSnakeCase, r as cleanSchemaName, s as stripBackendPrefixes, u as toKebabCase, v as ExtractorError, w as assignModelsToServices, x as RegistryError, y as InternalError } from "./tree-sitter-C53w_0WE.mjs";
2
- import { a as integrateGeneratedFiles, c as applyFileHeaders, d as generateAllFiles, f as generateFiles, i as generate, l as buildEmitterContext, m as resolveOperations, n as getEmitter, o as mapFilesForTargetIntegration, p as deriveMethodName, r as registerEmitter, s as treeShakeFiles, t as diffSpecs, u as collectReferencedNames } from "./diff-CSy3g-Bq.mjs";
2
+ import { a as integrateGeneratedFiles, c as applyFileHeaders, d as generateAllFiles, f as generateFiles, i as generate, l as buildEmitterContext, m as resolveOperations, n as getEmitter, o as mapFilesForTargetIntegration, p as deriveMethodName, r as registerEmitter, s as treeShakeFiles, t as diffSpecs, u as collectReferencedNames } from "./diff-BYadQQV7.mjs";
3
3
  import { readFile } from "node:fs/promises";
4
4
  import { resolve } from "node:path";
5
5
  import { pathToFileURL } from "node:url";
@@ -353,7 +353,7 @@ function findSchemaByName(pascalName, schemas) {
353
353
  for (const [k, v] of Object.entries(schemas)) if (resolveSchemaName(k) === pascalName) return v;
354
354
  return null;
355
355
  }
356
- /** Walk into a schema to find a field's sub-schema, resolving allOf. */
356
+ /** Walk into a schema to find a field's sub-schema, resolving allOf and oneOf/anyOf. */
357
357
  function findNestedFieldSchema(fieldName, parentSchema, schemas) {
358
358
  if (parentSchema.properties?.[fieldName]) return parentSchema.properties[fieldName];
359
359
  if (parentSchema.allOf) for (const sub of parentSchema.allOf) {
@@ -365,6 +365,15 @@ function findNestedFieldSchema(fieldName, parentSchema, schemas) {
365
365
  }
366
366
  if (resolved.properties?.[fieldName]) return resolved.properties[fieldName];
367
367
  }
368
+ for (const variant of [...parentSchema.oneOf ?? [], ...parentSchema.anyOf ?? []]) {
369
+ let resolved = variant;
370
+ if (variant.$ref) {
371
+ const segments = variant.$ref.split("/");
372
+ const refName = segments[segments.length - 1];
373
+ if (refName && schemas[refName]) resolved = schemas[refName];
374
+ }
375
+ if (resolved.properties?.[fieldName]) return resolved.properties[fieldName];
376
+ }
368
377
  return null;
369
378
  }
370
379
  /** Extract a model (and nested models) from an inline field schema. */
@@ -432,6 +441,86 @@ function buildFieldFromSchema(fieldName, fieldSchema, contextName, requiredSet)
432
441
  example: fieldSchema.example
433
442
  };
434
443
  }
444
+ /**
445
+ * If every non-null oneOf/anyOf variant is a string-valued const, return the
446
+ * list of those const values so the union can collapse into a single enum.
447
+ * Returns null when any variant isn't a pure string-const (model ref,
448
+ * number const, nullable, etc.).
449
+ */
450
+ function collectLiteralStringConsts(variants) {
451
+ if (variants.length === 0) return null;
452
+ const values = [];
453
+ for (const v of variants) {
454
+ if (typeof v.const === "string") {
455
+ values.push(v.const);
456
+ continue;
457
+ }
458
+ if (Array.isArray(v.enum) && v.enum.length === 1 && typeof v.enum[0] === "string") {
459
+ values.push(v.enum[0]);
460
+ continue;
461
+ }
462
+ return null;
463
+ }
464
+ return values;
465
+ }
466
+ /** Build an EnumRef the same way the regular enum path does for naming. */
467
+ function buildSyntheticEnumRef(values, contextName, parentModelName) {
468
+ const baseName = toPascalCase(contextName ?? "UnknownEnum");
469
+ const cleanParent = parentModelName ? stripListItemMarkers(parentModelName) : void 0;
470
+ return {
471
+ kind: "enum",
472
+ name: cleanParent && !baseName.startsWith(cleanParent) ? `${cleanParent}${baseName}` : baseName,
473
+ values
474
+ };
475
+ }
476
+ /**
477
+ * Detect an implicit discriminator on an oneOf where every variant is an
478
+ * object schema that pins the same property to a const value. Returns
479
+ * { property, mapping } so the IR can represent the union as discriminated
480
+ * without needing an explicit `discriminator:` key in the spec.
481
+ *
482
+ * Both shapes are supported:
483
+ * { properties: { event: { const: "x" } }, required: ["event"] }
484
+ * { properties: { event: { type: "string", enum: ["x"] } } }
485
+ *
486
+ * Returns null when any variant doesn't fit the pattern or when variants
487
+ * disagree on which property carries the discriminator.
488
+ */
489
+ function detectConstPropertyDiscriminator(variants) {
490
+ if (variants.length < 2) return null;
491
+ let candidateProperty = null;
492
+ const candidates = Object.keys(variants[0]?.properties ?? {});
493
+ for (const propName of candidates) if (variants.every((v) => getConstPropertyValue(v, propName) !== null)) {
494
+ candidateProperty = propName;
495
+ break;
496
+ }
497
+ if (!candidateProperty) return null;
498
+ const mapping = {};
499
+ for (const v of variants) {
500
+ const value = getConstPropertyValue(v, candidateProperty);
501
+ if (value === null) return null;
502
+ const variantName = resolveVariantModelName(v);
503
+ if (!variantName) return null;
504
+ mapping[value] = variantName;
505
+ }
506
+ return {
507
+ property: candidateProperty,
508
+ mapping
509
+ };
510
+ }
511
+ function getConstPropertyValue(schema, property) {
512
+ const prop = schema.properties?.[property];
513
+ if (!prop) return null;
514
+ if (typeof prop.const === "string") return prop.const;
515
+ if (Array.isArray(prop.enum) && prop.enum.length === 1 && typeof prop.enum[0] === "string") return prop.enum[0];
516
+ return null;
517
+ }
518
+ function resolveVariantModelName(schema) {
519
+ if (schema.$ref) return resolveSchemaName(schema.$ref.replace(/^#\/components\/schemas\//, ""));
520
+ const title = typeof schema["title"] === "string" ? schema["title"] : null;
521
+ if (title) return resolveSchemaName(title);
522
+ return null;
523
+ }
435
524
  function extractEnum(name, schema) {
436
525
  return {
437
526
  name,
@@ -450,6 +539,19 @@ function extractModel(name, schema, schemas) {
450
539
  if (!fieldSchema) continue;
451
540
  fields.push(buildFieldFromSchema(fieldName, fieldSchema, name, requiredSet));
452
541
  }
542
+ if (fields.length === 0 && (schema.oneOf || schema.anyOf)) {
543
+ const variants = schema.oneOf ?? schema.anyOf ?? [];
544
+ const emptyRequired = /* @__PURE__ */ new Set();
545
+ const seenFieldNames = /* @__PURE__ */ new Set();
546
+ for (const variant of variants) {
547
+ if (!variant.properties) continue;
548
+ for (const [fieldName, fieldSchema] of Object.entries(variant.properties)) {
549
+ if (!fieldSchema || seenFieldNames.has(fieldName)) continue;
550
+ seenFieldNames.add(fieldName);
551
+ fields.push(buildFieldFromSchema(fieldName, fieldSchema, name, emptyRequired));
552
+ }
553
+ }
554
+ }
453
555
  if (schema.additionalProperties && typeof schema.additionalProperties === "object" && schema.properties) {
454
556
  if (Object.keys(schema.additionalProperties).length > 0) {
455
557
  const valueType = schemaToTypeRef(schema.additionalProperties, "additionalProperties", name);
@@ -489,6 +591,18 @@ function extractAllOfModel(name, schema, schemas) {
489
591
  });
490
592
  if (f.required) requiredSet.add(f.name);
491
593
  }
594
+ } else if (resolved.oneOf || resolved.anyOf) {
595
+ const variants = resolved.oneOf ?? resolved.anyOf ?? [];
596
+ const emptyRequired = /* @__PURE__ */ new Set();
597
+ const seenFieldNames = new Set(fields.map((f) => f.name));
598
+ for (const variant of variants) {
599
+ if (!variant.properties) continue;
600
+ for (const [fieldName, fieldSchema] of Object.entries(variant.properties)) {
601
+ if (!fieldSchema || seenFieldNames.has(fieldName)) continue;
602
+ seenFieldNames.add(fieldName);
603
+ fields.push(buildFieldFromSchema(fieldName, fieldSchema, name, emptyRequired));
604
+ }
605
+ }
492
606
  } else {
493
607
  if (resolved.required) for (const r of resolved.required) requiredSet.add(r);
494
608
  if (resolved.properties) {
@@ -655,6 +769,15 @@ function schemaToTypeRef(schema, contextName, parentModelName) {
655
769
  kind: "nullable",
656
770
  inner: schemaToTypeRef(nonNullVariants[0], contextName, parentModelName)
657
771
  };
772
+ const literalStrings = collectLiteralStringConsts(nonNullVariants);
773
+ if (literalStrings !== null && literalStrings.length >= 2) {
774
+ const enumRef = buildSyntheticEnumRef(literalStrings, contextName, parentModelName);
775
+ return nullVariant ? {
776
+ kind: "nullable",
777
+ inner: enumRef
778
+ } : enumRef;
779
+ }
780
+ const syntheticDiscriminator = !schema.discriminator && compositionKind === "oneOf" ? detectConstPropertyDiscriminator(nonNullVariants) : null;
658
781
  const variants = rawVariants.filter((v) => v.type !== "null").map((v) => schemaToTypeRef(v, contextName, parentModelName));
659
782
  const hasNull = !!nullVariant;
660
783
  const union = {
@@ -664,7 +787,7 @@ function schemaToTypeRef(schema, contextName, parentModelName) {
664
787
  ...schema.discriminator ? { discriminator: {
665
788
  property: schema.discriminator.propertyName,
666
789
  mapping: Object.fromEntries(Object.entries(schema.discriminator.mapping ?? {}).map(([k, v]) => [k, v.replace(/^#\/components\/schemas\//, "")]))
667
- } } : {}
790
+ } } : syntheticDiscriminator ? { discriminator: syntheticDiscriminator } : {}
668
791
  };
669
792
  return hasNull ? {
670
793
  kind: "nullable",
@@ -1336,6 +1459,94 @@ function inferDeeperContext(path) {
1336
1459
  if (nonParams.length >= 3) return toPascalCase(nonParams.slice(1, -1).join("_"));
1337
1460
  return null;
1338
1461
  }
1462
+ /**
1463
+ * Extract mutually-exclusive parameter groups from the `x-mutually-exclusive-parameter-groups`
1464
+ * operation extension. Cross-references grouped parameter names against the already-extracted
1465
+ * IR parameter arrays so emitters get object-identity references.
1466
+ */
1467
+ function extractParameterGroups(op, allIRParams, operationContext) {
1468
+ const raw = op["x-mutually-exclusive-parameter-groups"];
1469
+ if (!raw || typeof raw !== "object") return void 0;
1470
+ const paramByName = /* @__PURE__ */ new Map();
1471
+ for (const p of allIRParams) paramByName.set(p.name, p);
1472
+ const groups = [];
1473
+ for (const [groupName, groupDef] of Object.entries(raw)) {
1474
+ if (!groupDef || typeof groupDef !== "object") throw new Error(`Malformed x-mutually-exclusive-parameter-groups.${groupName} in ${operationContext}: expected an object with "optional" and "variants".`);
1475
+ if (typeof groupDef.optional !== "boolean") throw new Error(`Malformed x-mutually-exclusive-parameter-groups.${groupName}.optional in ${operationContext}: expected a boolean.`);
1476
+ if (!groupDef.variants || typeof groupDef.variants !== "object") throw new Error(`Malformed x-mutually-exclusive-parameter-groups.${groupName}.variants in ${operationContext}: expected an object mapping variant names to parameter name arrays.`);
1477
+ if (Object.keys(groupDef.variants).length === 0) throw new Error(`Malformed x-mutually-exclusive-parameter-groups.${groupName} in ${operationContext}: group has zero variants.`);
1478
+ const variants = Object.entries(groupDef.variants).map(([variantName, paramNames]) => {
1479
+ if (!Array.isArray(paramNames) || paramNames.length === 0) throw new Error(`Malformed x-mutually-exclusive-parameter-groups.${groupName}.variants.${variantName} in ${operationContext}: expected a non-empty array of parameter names.`);
1480
+ return {
1481
+ name: variantName,
1482
+ parameters: paramNames.map((pName) => {
1483
+ const irParam = paramByName.get(pName);
1484
+ if (!irParam) throw new Error(`x-mutually-exclusive-parameter-groups.${groupName}.variants.${variantName} references parameter "${pName}" which does not exist in the operation's parameters[] (${operationContext}).`);
1485
+ return irParam;
1486
+ })
1487
+ };
1488
+ });
1489
+ groups.push({
1490
+ name: groupName,
1491
+ optional: groupDef.optional,
1492
+ variants
1493
+ });
1494
+ }
1495
+ return groups.length > 0 ? groups : void 0;
1496
+ }
1497
+ /**
1498
+ * Extract mutually-exclusive body parameter groups from the
1499
+ * `x-mutually-exclusive-body-groups` operation extension. Unlike query
1500
+ * parameter groups (whose parameters live in operation.queryParams), body
1501
+ * group parameters are synthetic — built from the oneOf variant schemas in
1502
+ * the request body. Emitters use the group's presence to generate sum-type
1503
+ * interfaces and custom JSON marshalling instead of flat optional fields.
1504
+ */
1505
+ function extractBodyParameterGroups(op, operationContext) {
1506
+ const raw = op["x-mutually-exclusive-body-groups"];
1507
+ if (!raw || typeof raw !== "object") return void 0;
1508
+ const bodySchema = op.requestBody?.content?.["application/json"]?.schema;
1509
+ const variantFieldSchemas = /* @__PURE__ */ new Map();
1510
+ if (bodySchema) {
1511
+ for (const sub of bodySchema.allOf ?? []) for (const variant of sub.oneOf ?? []) if (variant.properties) {
1512
+ for (const [name, fieldSchema] of Object.entries(variant.properties)) if (fieldSchema) variantFieldSchemas.set(name, fieldSchema);
1513
+ }
1514
+ for (const variant of bodySchema.oneOf ?? []) if (variant.properties) {
1515
+ for (const [name, fieldSchema] of Object.entries(variant.properties)) if (fieldSchema) variantFieldSchemas.set(name, fieldSchema);
1516
+ }
1517
+ }
1518
+ const groups = [];
1519
+ for (const [groupName, groupDef] of Object.entries(raw)) {
1520
+ if (!groupDef || typeof groupDef !== "object") continue;
1521
+ if (typeof groupDef.optional !== "boolean") continue;
1522
+ if (!groupDef.variants || typeof groupDef.variants !== "object") continue;
1523
+ if (Object.keys(groupDef.variants).length === 0) continue;
1524
+ const variants = Object.entries(groupDef.variants).map(([variantName, paramNames]) => {
1525
+ if (!Array.isArray(paramNames) || paramNames.length === 0) throw new Error(`Malformed x-mutually-exclusive-body-groups.${groupName}.variants.${variantName} in ${operationContext}: expected a non-empty array of parameter names.`);
1526
+ return {
1527
+ name: variantName,
1528
+ parameters: paramNames.map((pName) => {
1529
+ const fieldSchema = variantFieldSchemas.get(pName);
1530
+ return {
1531
+ name: pName,
1532
+ type: fieldSchema ? schemaToTypeRef(fieldSchema, toPascalCase(pName)) : {
1533
+ kind: "primitive",
1534
+ type: "string"
1535
+ },
1536
+ required: false,
1537
+ description: fieldSchema?.description
1538
+ };
1539
+ })
1540
+ };
1541
+ });
1542
+ groups.push({
1543
+ name: groupName,
1544
+ optional: groupDef.optional,
1545
+ variants
1546
+ });
1547
+ }
1548
+ return groups.length > 0 ? groups : void 0;
1549
+ }
1339
1550
  function buildOperation(method, path, op, pathLevelParams, operationIdTransform, serviceName) {
1340
1551
  const allParams = [...pathLevelParams, ...op.parameters ?? []];
1341
1552
  const hasIdempotencyHeader = allParams.some((p) => p.in === "header" && p.name.toLowerCase() === "idempotency-key");
@@ -1361,6 +1572,16 @@ function buildOperation(method, path, op, pathLevelParams, operationIdTransform,
1361
1572
  };
1362
1573
  } else if (paginationFromParams) pagination = paginationFromParams;
1363
1574
  const security = extractOperationSecurity(op.security);
1575
+ const allIRParams = [
1576
+ ...pathParams,
1577
+ ...queryParams,
1578
+ ...headerParams,
1579
+ ...cookieParams
1580
+ ];
1581
+ const opLabel = op.operationId ?? `${method.toUpperCase()} ${path}`;
1582
+ const queryParamGroups = extractParameterGroups(op, allIRParams, opLabel);
1583
+ const bodyParamGroups = extractBodyParameterGroups(op, opLabel);
1584
+ const parameterGroups = queryParamGroups || bodyParamGroups ? [...queryParamGroups ?? [], ...bodyParamGroups ?? []] : void 0;
1364
1585
  return {
1365
1586
  operation: {
1366
1587
  name: inferOperationName(method, path, op.operationId, operationIdTransform),
@@ -1380,7 +1601,8 @@ function buildOperation(method, path, op, pathLevelParams, operationIdTransform,
1380
1601
  injectIdempotencyKey: hasIdempotencyHeader,
1381
1602
  deprecated: op.deprecated || void 0,
1382
1603
  async: op["x-oagen-async"],
1383
- security
1604
+ security,
1605
+ parameterGroups
1384
1606
  },
1385
1607
  inlineModels
1386
1608
  };
@@ -1833,6 +2055,7 @@ function planOperation(op) {
1833
2055
  responseModelName,
1834
2056
  paginatedItemModelName: isPaginated && op.pagination?.itemType.kind === "model" ? op.pagination.itemType.name : null,
1835
2057
  isModelResponse: responseModelName !== null,
2058
+ isArrayResponse: !isPaginated && op.response.kind === "array" && op.response.items.kind === "model",
1836
2059
  hasQueryParams,
1837
2060
  isAsync: op.async ?? true
1838
2061
  };