@workos/oagen 0.5.0 → 0.6.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/smoke.mjs CHANGED
@@ -629,6 +629,86 @@ function buildFieldFromSchema(fieldName, fieldSchema, contextName, requiredSet)
629
629
  example: fieldSchema.example
630
630
  };
631
631
  }
632
+ /**
633
+ * If every non-null oneOf/anyOf variant is a string-valued const, return the
634
+ * list of those const values so the union can collapse into a single enum.
635
+ * Returns null when any variant isn't a pure string-const (model ref,
636
+ * number const, nullable, etc.).
637
+ */
638
+ function collectLiteralStringConsts(variants) {
639
+ if (variants.length === 0) return null;
640
+ const values = [];
641
+ for (const v of variants) {
642
+ if (typeof v.const === "string") {
643
+ values.push(v.const);
644
+ continue;
645
+ }
646
+ if (Array.isArray(v.enum) && v.enum.length === 1 && typeof v.enum[0] === "string") {
647
+ values.push(v.enum[0]);
648
+ continue;
649
+ }
650
+ return null;
651
+ }
652
+ return values;
653
+ }
654
+ /** Build an EnumRef the same way the regular enum path does for naming. */
655
+ function buildSyntheticEnumRef(values, contextName, parentModelName) {
656
+ const baseName = toPascalCase(contextName ?? "UnknownEnum");
657
+ const cleanParent = parentModelName ? stripListItemMarkers(parentModelName) : void 0;
658
+ return {
659
+ kind: "enum",
660
+ name: cleanParent && !baseName.startsWith(cleanParent) ? `${cleanParent}${baseName}` : baseName,
661
+ values
662
+ };
663
+ }
664
+ /**
665
+ * Detect an implicit discriminator on an oneOf where every variant is an
666
+ * object schema that pins the same property to a const value. Returns
667
+ * { property, mapping } so the IR can represent the union as discriminated
668
+ * without needing an explicit `discriminator:` key in the spec.
669
+ *
670
+ * Both shapes are supported:
671
+ * { properties: { event: { const: "x" } }, required: ["event"] }
672
+ * { properties: { event: { type: "string", enum: ["x"] } } }
673
+ *
674
+ * Returns null when any variant doesn't fit the pattern or when variants
675
+ * disagree on which property carries the discriminator.
676
+ */
677
+ function detectConstPropertyDiscriminator(variants) {
678
+ if (variants.length < 2) return null;
679
+ let candidateProperty = null;
680
+ const candidates = Object.keys(variants[0]?.properties ?? {});
681
+ for (const propName of candidates) if (variants.every((v) => getConstPropertyValue(v, propName) !== null)) {
682
+ candidateProperty = propName;
683
+ break;
684
+ }
685
+ if (!candidateProperty) return null;
686
+ const mapping = {};
687
+ for (const v of variants) {
688
+ const value = getConstPropertyValue(v, candidateProperty);
689
+ if (value === null) return null;
690
+ const variantName = resolveVariantModelName(v);
691
+ if (!variantName) return null;
692
+ mapping[value] = variantName;
693
+ }
694
+ return {
695
+ property: candidateProperty,
696
+ mapping
697
+ };
698
+ }
699
+ function getConstPropertyValue(schema, property) {
700
+ const prop = schema.properties?.[property];
701
+ if (!prop) return null;
702
+ if (typeof prop.const === "string") return prop.const;
703
+ if (Array.isArray(prop.enum) && prop.enum.length === 1 && typeof prop.enum[0] === "string") return prop.enum[0];
704
+ return null;
705
+ }
706
+ function resolveVariantModelName(schema) {
707
+ if (schema.$ref) return resolveSchemaName(schema.$ref.replace(/^#\/components\/schemas\//, ""));
708
+ const title = typeof schema["title"] === "string" ? schema["title"] : null;
709
+ if (title) return resolveSchemaName(title);
710
+ return null;
711
+ }
632
712
  function extractEnum(name, schema) {
633
713
  return {
634
714
  name,
@@ -852,6 +932,15 @@ function schemaToTypeRef(schema, contextName, parentModelName) {
852
932
  kind: "nullable",
853
933
  inner: schemaToTypeRef(nonNullVariants[0], contextName, parentModelName)
854
934
  };
935
+ const literalStrings = collectLiteralStringConsts(nonNullVariants);
936
+ if (literalStrings !== null && literalStrings.length >= 2) {
937
+ const enumRef = buildSyntheticEnumRef(literalStrings, contextName, parentModelName);
938
+ return nullVariant ? {
939
+ kind: "nullable",
940
+ inner: enumRef
941
+ } : enumRef;
942
+ }
943
+ const syntheticDiscriminator = !schema.discriminator && compositionKind === "oneOf" ? detectConstPropertyDiscriminator(nonNullVariants) : null;
855
944
  const variants = rawVariants.filter((v) => v.type !== "null").map((v) => schemaToTypeRef(v, contextName, parentModelName));
856
945
  const hasNull = !!nullVariant;
857
946
  const union = {
@@ -861,7 +950,7 @@ function schemaToTypeRef(schema, contextName, parentModelName) {
861
950
  ...schema.discriminator ? { discriminator: {
862
951
  property: schema.discriminator.propertyName,
863
952
  mapping: Object.fromEntries(Object.entries(schema.discriminator.mapping ?? {}).map(([k, v]) => [k, v.replace(/^#\/components\/schemas\//, "")]))
864
- } } : {}
953
+ } } : syntheticDiscriminator ? { discriminator: syntheticDiscriminator } : {}
865
954
  };
866
955
  return hasNull ? {
867
956
  kind: "nullable",