@workos/oagen 0.20.0 → 0.21.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.
@@ -837,9 +837,10 @@ function collectLiteralStringConsts(variants) {
837
837
  function buildSyntheticEnumRef(values, contextName, parentModelName) {
838
838
  const baseName = toPascalCase(contextName ?? "UnknownEnum");
839
839
  const cleanParent = parentModelName ? stripListItemMarkers(parentModelName) : void 0;
840
+ const qualifiedName = cleanParent && !baseName.startsWith(cleanParent) ? `${cleanParent}${baseName}` : baseName;
840
841
  return {
841
842
  kind: "enum",
842
- name: cleanParent && !baseName.startsWith(cleanParent) ? `${cleanParent}${baseName}` : baseName,
843
+ name: activeSchemaNameTransform ? activeSchemaNameTransform(qualifiedName) : qualifiedName,
843
844
  values
844
845
  };
845
846
  }
@@ -1047,6 +1048,36 @@ function extractAllOfModel(name, schema, schemas) {
1047
1048
  };
1048
1049
  }
1049
1050
  /**
1051
+ * Walk through `allOf` wrappers to collect the effective top-level properties
1052
+ * of a schema. Stops at `oneOf` / `anyOf` boundaries — those are different
1053
+ * variant axes, not part of the same flat object.
1054
+ *
1055
+ * Used by `detectAllOfVariantDiscriminator` and `deriveDiscriminatedVariantName`
1056
+ * so a oneOf variant of the form `{ allOf: [{ properties: { … } }, { oneOf: […] }] }`
1057
+ * still surfaces its top-level `properties` (in particular its discriminator
1058
+ * `const`) instead of being treated as having none.
1059
+ */
1060
+ function getEffectiveProperties(schema) {
1061
+ const props = {};
1062
+ const visit = (s) => {
1063
+ if (s.properties) {
1064
+ for (const [k, v] of Object.entries(s.properties)) if (!(k in props) && v) props[k] = v;
1065
+ }
1066
+ if (s.allOf) for (const sub of s.allOf) visit(sub);
1067
+ };
1068
+ visit(schema);
1069
+ return props;
1070
+ }
1071
+ function getEffectiveConstPropertyValue(schema, property) {
1072
+ const direct = getConstPropertyValue(schema, property);
1073
+ if (direct !== null) return direct;
1074
+ const effective = getEffectiveProperties(schema)[property];
1075
+ if (!effective) return null;
1076
+ if (typeof effective.const === "string") return effective.const;
1077
+ if (Array.isArray(effective.enum) && effective.enum.length === 1 && typeof effective.enum[0] === "string") return effective.enum[0];
1078
+ return null;
1079
+ }
1080
+ /**
1050
1081
  * Detect an implicit discriminator on an allOf+oneOf where every variant is an
1051
1082
  * object that pins the same property to a distinct const value. Unlike
1052
1083
  * detectConstPropertyDiscriminator (which requires $ref or title for variant
@@ -1054,13 +1085,17 @@ function extractAllOfModel(name, schema, schemas) {
1054
1085
  * using deriveDiscriminatedVariantName — matching how extractDiscriminatedAllOfVariantModels
1055
1086
  * names those models.
1056
1087
  *
1088
+ * Walks through allOf wrappers on each variant so a oneOf branch like
1089
+ * { allOf: [{ properties: { type: { const: 'oauth' } } }, { oneOf: […] }] }
1090
+ * still surfaces `type` as a candidate discriminator.
1091
+ *
1057
1092
  * Returns null when no discriminator can be reliably detected.
1058
1093
  */
1059
1094
  function detectAllOfVariantDiscriminator(variants, fallbackName) {
1060
1095
  if (variants.length < 2) return null;
1061
- const candidates = Object.keys(variants[0]?.properties ?? {});
1096
+ const firstProps = getEffectiveProperties(variants[0] ?? {});
1062
1097
  let candidateProperty = null;
1063
- for (const propName of candidates) if (variants.every((v) => getConstPropertyValue(v, propName) !== null)) {
1098
+ for (const propName of Object.keys(firstProps)) if (variants.every((v) => getEffectiveConstPropertyValue(v, propName) !== null)) {
1064
1099
  candidateProperty = propName;
1065
1100
  break;
1066
1101
  }
@@ -1068,7 +1103,7 @@ function detectAllOfVariantDiscriminator(variants, fallbackName) {
1068
1103
  const mapping = {};
1069
1104
  const seenModelNames = /* @__PURE__ */ new Set();
1070
1105
  for (const v of variants) {
1071
- const value = getConstPropertyValue(v, candidateProperty);
1106
+ const value = getEffectiveConstPropertyValue(v, candidateProperty);
1072
1107
  if (value === null) return null;
1073
1108
  const modelName = deriveDiscriminatedVariantName(v, fallbackName);
1074
1109
  if (seenModelNames.has(modelName)) return null;
@@ -1083,10 +1118,28 @@ function detectAllOfVariantDiscriminator(variants, fallbackName) {
1083
1118
  function extractDiscriminatedAllOfVariantModels(schema, fallbackName) {
1084
1119
  const models = [];
1085
1120
  const seenNames = /* @__PURE__ */ new Set();
1121
+ const baseProperties = {};
1122
+ const baseRequired = /* @__PURE__ */ new Set();
1123
+ for (const subSchema of schema.allOf ?? []) {
1124
+ if (subSchema.oneOf) continue;
1125
+ const flat = subSchema.allOf ? flattenVariantForExtraction(subSchema) : subSchema;
1126
+ if (flat.properties) {
1127
+ for (const [k, v] of Object.entries(flat.properties)) if (!(k in baseProperties) && v) baseProperties[k] = v;
1128
+ }
1129
+ if (flat.required) for (const r of flat.required) baseRequired.add(r);
1130
+ }
1086
1131
  for (const subSchema of schema.allOf ?? []) for (const variant of subSchema.oneOf ?? []) {
1087
- if (!variant.properties || variant.type !== void 0 && variant.type !== "object") continue;
1132
+ const flat = flattenVariantForExtraction(variant);
1133
+ if (!flat.properties || flat.type !== void 0 && flat.type !== "object") continue;
1134
+ const mergedProperties = { ...baseProperties };
1135
+ for (const [k, v] of Object.entries(flat.properties)) if (v) mergedProperties[k] = v;
1136
+ const merged = {
1137
+ type: "object",
1138
+ properties: mergedProperties,
1139
+ required: [...new Set([...baseRequired, ...flat.required ?? []])]
1140
+ };
1088
1141
  const variantName = deriveDiscriminatedVariantName(variant, fallbackName);
1089
- for (const model of extractInlineModelDeep(variantName, variant)) {
1142
+ for (const model of extractInlineModelDeep(variantName, merged)) {
1090
1143
  if (seenNames.has(model.name)) continue;
1091
1144
  seenNames.add(model.name);
1092
1145
  models.push(model);
@@ -1094,24 +1147,103 @@ function extractDiscriminatedAllOfVariantModels(schema, fallbackName) {
1094
1147
  }
1095
1148
  return models;
1096
1149
  }
1150
+ /**
1151
+ * Flatten a oneOf variant schema into a single object-shaped schema for
1152
+ * variant-model extraction. Recursively merges `allOf` members and folds
1153
+ * any nested `oneOf` into an inline-oneOf field group whose properties are
1154
+ * the union across sub-branches (required only when present in every
1155
+ * sub-branch). Returns the schema unchanged when no flattening is needed.
1156
+ */
1157
+ function flattenVariantForExtraction(variant) {
1158
+ if (!variant.allOf) return variant;
1159
+ const mergedProperties = {};
1160
+ const mergedRequired = /* @__PURE__ */ new Set();
1161
+ const nestedOneOfs = [];
1162
+ const collect = (s) => {
1163
+ if (s.properties) {
1164
+ for (const [k, v] of Object.entries(s.properties)) if (!(k in mergedProperties) && v) mergedProperties[k] = v;
1165
+ }
1166
+ if (s.required) for (const r of s.required) mergedRequired.add(r);
1167
+ if (s.allOf) for (const sub of s.allOf) collect(sub);
1168
+ if (s.oneOf) nestedOneOfs.push(s.oneOf);
1169
+ };
1170
+ collect(variant);
1171
+ for (const branches of nestedOneOfs) {
1172
+ const flatBranches = branches.map(flattenVariantForExtraction);
1173
+ const branchKeys = /* @__PURE__ */ new Set();
1174
+ for (const b of flatBranches) for (const k of Object.keys(b.properties ?? {})) branchKeys.add(k);
1175
+ for (const key of branchKeys) {
1176
+ const schemas = [];
1177
+ for (const b of flatBranches) {
1178
+ const s = b.properties?.[key];
1179
+ if (s) schemas.push(s);
1180
+ }
1181
+ const merged = mergeBranchPropertySchemas(schemas);
1182
+ if (!(key in mergedProperties)) mergedProperties[key] = merged;
1183
+ if (flatBranches.every((b) => b.properties && key in b.properties) && flatBranches.every((b) => (b.required ?? []).includes(key))) mergedRequired.add(key);
1184
+ }
1185
+ }
1186
+ return {
1187
+ type: "object",
1188
+ properties: mergedProperties,
1189
+ required: [...mergedRequired]
1190
+ };
1191
+ }
1192
+ /**
1193
+ * Merge same-named property schemas from across sub-variants. If every
1194
+ * occurrence is a boolean const, widen to plain boolean; if every occurrence
1195
+ * is a distinct string const, widen to plain string. Otherwise return the
1196
+ * first occurrence — emitters that build their own widened types (e.g. the
1197
+ * Node discriminated-models module) re-derive from the raw spec.
1198
+ */
1199
+ function mergeBranchPropertySchemas(schemas) {
1200
+ if (schemas.length === 0) return {};
1201
+ if (schemas.length === 1) return schemas[0];
1202
+ if (schemas.every((s) => s.type === "boolean" && typeof s.const === "boolean")) return {
1203
+ type: "boolean",
1204
+ description: schemas[0].description
1205
+ };
1206
+ if (schemas.every((s) => s.type === "string" && typeof s.const === "string")) {
1207
+ const values = schemas.map((s) => s.const);
1208
+ if (new Set(values).size === 1) return schemas[0];
1209
+ return {
1210
+ type: "string",
1211
+ description: schemas[0].description
1212
+ };
1213
+ }
1214
+ return schemas[0];
1215
+ }
1097
1216
  function deriveDiscriminatedVariantName(schema, fallbackName) {
1098
- if (!schema.properties) return fallbackName;
1099
- for (const name of [
1217
+ const effective = getEffectiveProperties(schema);
1218
+ if (Object.keys(effective).length === 0) return fallbackName;
1219
+ const pickConst = (name) => {
1220
+ const field = effective[name];
1221
+ if (!field) return null;
1222
+ if (typeof field.const === "string") return field.const;
1223
+ if (field.enum && field.enum.length === 1 && typeof field.enum[0] === "string") return field.enum[0];
1224
+ return null;
1225
+ };
1226
+ let constValue = null;
1227
+ for (const preferred of [
1100
1228
  "event",
1101
1229
  "type",
1102
1230
  "object"
1103
1231
  ]) {
1104
- const field = schema.properties[name];
1105
- if (!field) continue;
1106
- if (typeof field.const === "string") return toPascalCase(field.const);
1107
- if (field.enum && field.enum.length === 1 && typeof field.enum[0] === "string") return toPascalCase(field.enum[0]);
1108
- }
1109
- for (const field of Object.values(schema.properties)) {
1110
- if (!field) continue;
1111
- if (typeof field.const === "string") return toPascalCase(field.const);
1112
- if (field.enum && field.enum.length === 1 && typeof field.enum[0] === "string") return toPascalCase(field.enum[0]);
1113
- }
1114
- return fallbackName;
1232
+ constValue = pickConst(preferred);
1233
+ if (constValue) break;
1234
+ }
1235
+ if (constValue === null) for (const name of Object.keys(effective)) {
1236
+ constValue = pickConst(name);
1237
+ if (constValue) break;
1238
+ }
1239
+ if (constValue === null) return fallbackName;
1240
+ const pascal = toPascalCase(constValue);
1241
+ if (!pascal) return fallbackName;
1242
+ if (splitWords(constValue).length >= 2) return pascal;
1243
+ if (pascal === fallbackName) return pascal;
1244
+ if (fallbackName.startsWith(pascal)) return fallbackName;
1245
+ if (pascal.endsWith(fallbackName)) return pascal;
1246
+ return `${fallbackName}${pascal}`;
1115
1247
  }
1116
1248
  function extractInlineModelDeep(name, schema) {
1117
1249
  const requiredSet = new Set(schema.required ?? []);
@@ -1340,9 +1472,10 @@ function schemaToTypeRef(schema, contextName, parentModelName) {
1340
1472
  if (schema.enum) {
1341
1473
  const baseName = toPascalCase(contextName ?? "UnknownEnum");
1342
1474
  const cleanParent = parentModelName ? stripListItemMarkers(parentModelName) : void 0;
1475
+ const qualifiedName = cleanParent && !baseName.startsWith(cleanParent) ? `${cleanParent}${baseName}` : baseName;
1343
1476
  return {
1344
1477
  kind: "enum",
1345
- name: cleanParent && !baseName.startsWith(cleanParent) ? `${cleanParent}${baseName}` : baseName,
1478
+ name: activeSchemaNameTransform ? activeSchemaNameTransform(qualifiedName) : qualifiedName,
1346
1479
  values: schema.enum.map((v) => typeof v === "number" ? v : String(v))
1347
1480
  };
1348
1481
  }
@@ -5174,7 +5307,11 @@ function collectReferencedNames(services, models) {
5174
5307
  for (const err of op.errors) if (err.type) collectFromTypeRef(err.type);
5175
5308
  if (op.successResponses) for (const sr of op.successResponses) collectFromTypeRef(sr.type);
5176
5309
  }
5177
- for (const model of models) if (isDiscriminatedModel(model)) referencedModels.add(model.name);
5310
+ for (const model of models) {
5311
+ if (isDiscriminatedModel(model)) referencedModels.add(model.name);
5312
+ const disc = model.discriminator;
5313
+ if (disc?.mapping) for (const variantName of Object.values(disc.mapping)) referencedModels.add(variantName);
5314
+ }
5178
5315
  const modelsByName = new Map(models.map((m) => [m.name, m]));
5179
5316
  const visited = /* @__PURE__ */ new Set();
5180
5317
  const queue = [...referencedModels];