@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.
- package/dist/cli/index.mjs +158 -21
- package/dist/cli/index.mjs.map +1 -1
- package/dist/{diff-C8mjApjv.mjs → diff-CBFCoTCw.mjs} +6 -2
- package/dist/{diff-C8mjApjv.mjs.map → diff-CBFCoTCw.mjs.map} +1 -1
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +155 -22
- package/dist/index.mjs.map +1 -1
- package/dist/scripts/smoke/baseline.mjs +153 -20
- package/dist/scripts/smoke/baseline.mjs.map +1 -1
- package/dist/smoke.mjs +153 -20
- package/dist/smoke.mjs.map +1 -1
- package/dist/verify/index.mjs +1 -1
- package/package.json +1 -1
- package/skills/generate-smoke-test/SKILL.md +19 -41
- package/skills/generate-smoke-test/references/implementation-patterns.md +87 -0
package/dist/smoke.mjs
CHANGED
|
@@ -786,9 +786,10 @@ function collectLiteralStringConsts(variants) {
|
|
|
786
786
|
function buildSyntheticEnumRef(values, contextName, parentModelName) {
|
|
787
787
|
const baseName = toPascalCase(contextName ?? "UnknownEnum");
|
|
788
788
|
const cleanParent = parentModelName ? stripListItemMarkers(parentModelName) : void 0;
|
|
789
|
+
const qualifiedName = cleanParent && !baseName.startsWith(cleanParent) ? `${cleanParent}${baseName}` : baseName;
|
|
789
790
|
return {
|
|
790
791
|
kind: "enum",
|
|
791
|
-
name:
|
|
792
|
+
name: activeSchemaNameTransform ? activeSchemaNameTransform(qualifiedName) : qualifiedName,
|
|
792
793
|
values
|
|
793
794
|
};
|
|
794
795
|
}
|
|
@@ -996,6 +997,36 @@ function extractAllOfModel(name, schema, schemas) {
|
|
|
996
997
|
};
|
|
997
998
|
}
|
|
998
999
|
/**
|
|
1000
|
+
* Walk through `allOf` wrappers to collect the effective top-level properties
|
|
1001
|
+
* of a schema. Stops at `oneOf` / `anyOf` boundaries — those are different
|
|
1002
|
+
* variant axes, not part of the same flat object.
|
|
1003
|
+
*
|
|
1004
|
+
* Used by `detectAllOfVariantDiscriminator` and `deriveDiscriminatedVariantName`
|
|
1005
|
+
* so a oneOf variant of the form `{ allOf: [{ properties: { … } }, { oneOf: […] }] }`
|
|
1006
|
+
* still surfaces its top-level `properties` (in particular its discriminator
|
|
1007
|
+
* `const`) instead of being treated as having none.
|
|
1008
|
+
*/
|
|
1009
|
+
function getEffectiveProperties(schema) {
|
|
1010
|
+
const props = {};
|
|
1011
|
+
const visit = (s) => {
|
|
1012
|
+
if (s.properties) {
|
|
1013
|
+
for (const [k, v] of Object.entries(s.properties)) if (!(k in props) && v) props[k] = v;
|
|
1014
|
+
}
|
|
1015
|
+
if (s.allOf) for (const sub of s.allOf) visit(sub);
|
|
1016
|
+
};
|
|
1017
|
+
visit(schema);
|
|
1018
|
+
return props;
|
|
1019
|
+
}
|
|
1020
|
+
function getEffectiveConstPropertyValue(schema, property) {
|
|
1021
|
+
const direct = getConstPropertyValue(schema, property);
|
|
1022
|
+
if (direct !== null) return direct;
|
|
1023
|
+
const effective = getEffectiveProperties(schema)[property];
|
|
1024
|
+
if (!effective) return null;
|
|
1025
|
+
if (typeof effective.const === "string") return effective.const;
|
|
1026
|
+
if (Array.isArray(effective.enum) && effective.enum.length === 1 && typeof effective.enum[0] === "string") return effective.enum[0];
|
|
1027
|
+
return null;
|
|
1028
|
+
}
|
|
1029
|
+
/**
|
|
999
1030
|
* Detect an implicit discriminator on an allOf+oneOf where every variant is an
|
|
1000
1031
|
* object that pins the same property to a distinct const value. Unlike
|
|
1001
1032
|
* detectConstPropertyDiscriminator (which requires $ref or title for variant
|
|
@@ -1003,13 +1034,17 @@ function extractAllOfModel(name, schema, schemas) {
|
|
|
1003
1034
|
* using deriveDiscriminatedVariantName — matching how extractDiscriminatedAllOfVariantModels
|
|
1004
1035
|
* names those models.
|
|
1005
1036
|
*
|
|
1037
|
+
* Walks through allOf wrappers on each variant so a oneOf branch like
|
|
1038
|
+
* { allOf: [{ properties: { type: { const: 'oauth' } } }, { oneOf: […] }] }
|
|
1039
|
+
* still surfaces `type` as a candidate discriminator.
|
|
1040
|
+
*
|
|
1006
1041
|
* Returns null when no discriminator can be reliably detected.
|
|
1007
1042
|
*/
|
|
1008
1043
|
function detectAllOfVariantDiscriminator(variants, fallbackName) {
|
|
1009
1044
|
if (variants.length < 2) return null;
|
|
1010
|
-
const
|
|
1045
|
+
const firstProps = getEffectiveProperties(variants[0] ?? {});
|
|
1011
1046
|
let candidateProperty = null;
|
|
1012
|
-
for (const propName of
|
|
1047
|
+
for (const propName of Object.keys(firstProps)) if (variants.every((v) => getEffectiveConstPropertyValue(v, propName) !== null)) {
|
|
1013
1048
|
candidateProperty = propName;
|
|
1014
1049
|
break;
|
|
1015
1050
|
}
|
|
@@ -1017,7 +1052,7 @@ function detectAllOfVariantDiscriminator(variants, fallbackName) {
|
|
|
1017
1052
|
const mapping = {};
|
|
1018
1053
|
const seenModelNames = /* @__PURE__ */ new Set();
|
|
1019
1054
|
for (const v of variants) {
|
|
1020
|
-
const value =
|
|
1055
|
+
const value = getEffectiveConstPropertyValue(v, candidateProperty);
|
|
1021
1056
|
if (value === null) return null;
|
|
1022
1057
|
const modelName = deriveDiscriminatedVariantName(v, fallbackName);
|
|
1023
1058
|
if (seenModelNames.has(modelName)) return null;
|
|
@@ -1032,10 +1067,28 @@ function detectAllOfVariantDiscriminator(variants, fallbackName) {
|
|
|
1032
1067
|
function extractDiscriminatedAllOfVariantModels(schema, fallbackName) {
|
|
1033
1068
|
const models = [];
|
|
1034
1069
|
const seenNames = /* @__PURE__ */ new Set();
|
|
1070
|
+
const baseProperties = {};
|
|
1071
|
+
const baseRequired = /* @__PURE__ */ new Set();
|
|
1072
|
+
for (const subSchema of schema.allOf ?? []) {
|
|
1073
|
+
if (subSchema.oneOf) continue;
|
|
1074
|
+
const flat = subSchema.allOf ? flattenVariantForExtraction(subSchema) : subSchema;
|
|
1075
|
+
if (flat.properties) {
|
|
1076
|
+
for (const [k, v] of Object.entries(flat.properties)) if (!(k in baseProperties) && v) baseProperties[k] = v;
|
|
1077
|
+
}
|
|
1078
|
+
if (flat.required) for (const r of flat.required) baseRequired.add(r);
|
|
1079
|
+
}
|
|
1035
1080
|
for (const subSchema of schema.allOf ?? []) for (const variant of subSchema.oneOf ?? []) {
|
|
1036
|
-
|
|
1081
|
+
const flat = flattenVariantForExtraction(variant);
|
|
1082
|
+
if (!flat.properties || flat.type !== void 0 && flat.type !== "object") continue;
|
|
1083
|
+
const mergedProperties = { ...baseProperties };
|
|
1084
|
+
for (const [k, v] of Object.entries(flat.properties)) if (v) mergedProperties[k] = v;
|
|
1085
|
+
const merged = {
|
|
1086
|
+
type: "object",
|
|
1087
|
+
properties: mergedProperties,
|
|
1088
|
+
required: [...new Set([...baseRequired, ...flat.required ?? []])]
|
|
1089
|
+
};
|
|
1037
1090
|
const variantName = deriveDiscriminatedVariantName(variant, fallbackName);
|
|
1038
|
-
for (const model of extractInlineModelDeep(variantName,
|
|
1091
|
+
for (const model of extractInlineModelDeep(variantName, merged)) {
|
|
1039
1092
|
if (seenNames.has(model.name)) continue;
|
|
1040
1093
|
seenNames.add(model.name);
|
|
1041
1094
|
models.push(model);
|
|
@@ -1043,24 +1096,103 @@ function extractDiscriminatedAllOfVariantModels(schema, fallbackName) {
|
|
|
1043
1096
|
}
|
|
1044
1097
|
return models;
|
|
1045
1098
|
}
|
|
1099
|
+
/**
|
|
1100
|
+
* Flatten a oneOf variant schema into a single object-shaped schema for
|
|
1101
|
+
* variant-model extraction. Recursively merges `allOf` members and folds
|
|
1102
|
+
* any nested `oneOf` into an inline-oneOf field group whose properties are
|
|
1103
|
+
* the union across sub-branches (required only when present in every
|
|
1104
|
+
* sub-branch). Returns the schema unchanged when no flattening is needed.
|
|
1105
|
+
*/
|
|
1106
|
+
function flattenVariantForExtraction(variant) {
|
|
1107
|
+
if (!variant.allOf) return variant;
|
|
1108
|
+
const mergedProperties = {};
|
|
1109
|
+
const mergedRequired = /* @__PURE__ */ new Set();
|
|
1110
|
+
const nestedOneOfs = [];
|
|
1111
|
+
const collect = (s) => {
|
|
1112
|
+
if (s.properties) {
|
|
1113
|
+
for (const [k, v] of Object.entries(s.properties)) if (!(k in mergedProperties) && v) mergedProperties[k] = v;
|
|
1114
|
+
}
|
|
1115
|
+
if (s.required) for (const r of s.required) mergedRequired.add(r);
|
|
1116
|
+
if (s.allOf) for (const sub of s.allOf) collect(sub);
|
|
1117
|
+
if (s.oneOf) nestedOneOfs.push(s.oneOf);
|
|
1118
|
+
};
|
|
1119
|
+
collect(variant);
|
|
1120
|
+
for (const branches of nestedOneOfs) {
|
|
1121
|
+
const flatBranches = branches.map(flattenVariantForExtraction);
|
|
1122
|
+
const branchKeys = /* @__PURE__ */ new Set();
|
|
1123
|
+
for (const b of flatBranches) for (const k of Object.keys(b.properties ?? {})) branchKeys.add(k);
|
|
1124
|
+
for (const key of branchKeys) {
|
|
1125
|
+
const schemas = [];
|
|
1126
|
+
for (const b of flatBranches) {
|
|
1127
|
+
const s = b.properties?.[key];
|
|
1128
|
+
if (s) schemas.push(s);
|
|
1129
|
+
}
|
|
1130
|
+
const merged = mergeBranchPropertySchemas(schemas);
|
|
1131
|
+
if (!(key in mergedProperties)) mergedProperties[key] = merged;
|
|
1132
|
+
if (flatBranches.every((b) => b.properties && key in b.properties) && flatBranches.every((b) => (b.required ?? []).includes(key))) mergedRequired.add(key);
|
|
1133
|
+
}
|
|
1134
|
+
}
|
|
1135
|
+
return {
|
|
1136
|
+
type: "object",
|
|
1137
|
+
properties: mergedProperties,
|
|
1138
|
+
required: [...mergedRequired]
|
|
1139
|
+
};
|
|
1140
|
+
}
|
|
1141
|
+
/**
|
|
1142
|
+
* Merge same-named property schemas from across sub-variants. If every
|
|
1143
|
+
* occurrence is a boolean const, widen to plain boolean; if every occurrence
|
|
1144
|
+
* is a distinct string const, widen to plain string. Otherwise return the
|
|
1145
|
+
* first occurrence — emitters that build their own widened types (e.g. the
|
|
1146
|
+
* Node discriminated-models module) re-derive from the raw spec.
|
|
1147
|
+
*/
|
|
1148
|
+
function mergeBranchPropertySchemas(schemas) {
|
|
1149
|
+
if (schemas.length === 0) return {};
|
|
1150
|
+
if (schemas.length === 1) return schemas[0];
|
|
1151
|
+
if (schemas.every((s) => s.type === "boolean" && typeof s.const === "boolean")) return {
|
|
1152
|
+
type: "boolean",
|
|
1153
|
+
description: schemas[0].description
|
|
1154
|
+
};
|
|
1155
|
+
if (schemas.every((s) => s.type === "string" && typeof s.const === "string")) {
|
|
1156
|
+
const values = schemas.map((s) => s.const);
|
|
1157
|
+
if (new Set(values).size === 1) return schemas[0];
|
|
1158
|
+
return {
|
|
1159
|
+
type: "string",
|
|
1160
|
+
description: schemas[0].description
|
|
1161
|
+
};
|
|
1162
|
+
}
|
|
1163
|
+
return schemas[0];
|
|
1164
|
+
}
|
|
1046
1165
|
function deriveDiscriminatedVariantName(schema, fallbackName) {
|
|
1047
|
-
|
|
1048
|
-
|
|
1166
|
+
const effective = getEffectiveProperties(schema);
|
|
1167
|
+
if (Object.keys(effective).length === 0) return fallbackName;
|
|
1168
|
+
const pickConst = (name) => {
|
|
1169
|
+
const field = effective[name];
|
|
1170
|
+
if (!field) return null;
|
|
1171
|
+
if (typeof field.const === "string") return field.const;
|
|
1172
|
+
if (field.enum && field.enum.length === 1 && typeof field.enum[0] === "string") return field.enum[0];
|
|
1173
|
+
return null;
|
|
1174
|
+
};
|
|
1175
|
+
let constValue = null;
|
|
1176
|
+
for (const preferred of [
|
|
1049
1177
|
"event",
|
|
1050
1178
|
"type",
|
|
1051
1179
|
"object"
|
|
1052
1180
|
]) {
|
|
1053
|
-
|
|
1054
|
-
if (
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
return
|
|
1181
|
+
constValue = pickConst(preferred);
|
|
1182
|
+
if (constValue) break;
|
|
1183
|
+
}
|
|
1184
|
+
if (constValue === null) for (const name of Object.keys(effective)) {
|
|
1185
|
+
constValue = pickConst(name);
|
|
1186
|
+
if (constValue) break;
|
|
1187
|
+
}
|
|
1188
|
+
if (constValue === null) return fallbackName;
|
|
1189
|
+
const pascal = toPascalCase(constValue);
|
|
1190
|
+
if (!pascal) return fallbackName;
|
|
1191
|
+
if (splitWords(constValue).length >= 2) return pascal;
|
|
1192
|
+
if (pascal === fallbackName) return pascal;
|
|
1193
|
+
if (fallbackName.startsWith(pascal)) return fallbackName;
|
|
1194
|
+
if (pascal.endsWith(fallbackName)) return pascal;
|
|
1195
|
+
return `${fallbackName}${pascal}`;
|
|
1064
1196
|
}
|
|
1065
1197
|
function extractInlineModelDeep(name, schema) {
|
|
1066
1198
|
const requiredSet = new Set(schema.required ?? []);
|
|
@@ -1289,9 +1421,10 @@ function schemaToTypeRef(schema, contextName, parentModelName) {
|
|
|
1289
1421
|
if (schema.enum) {
|
|
1290
1422
|
const baseName = toPascalCase(contextName ?? "UnknownEnum");
|
|
1291
1423
|
const cleanParent = parentModelName ? stripListItemMarkers(parentModelName) : void 0;
|
|
1424
|
+
const qualifiedName = cleanParent && !baseName.startsWith(cleanParent) ? `${cleanParent}${baseName}` : baseName;
|
|
1292
1425
|
return {
|
|
1293
1426
|
kind: "enum",
|
|
1294
|
-
name:
|
|
1427
|
+
name: activeSchemaNameTransform ? activeSchemaNameTransform(qualifiedName) : qualifiedName,
|
|
1295
1428
|
values: schema.enum.map((v) => typeof v === "number" ? v : String(v))
|
|
1296
1429
|
};
|
|
1297
1430
|
}
|