@kubb/adapter-oas 5.0.2 → 5.0.3

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.js CHANGED
@@ -162,11 +162,11 @@ function buildDiscriminatorChildMap(schemas) {
162
162
  if (!existing) {
163
163
  childMap.set(refNode.name, {
164
164
  propertyName: discriminatorPropertyName,
165
- enumValues: [...enumValues]
165
+ enumValues: [...new Set(enumValues)]
166
166
  });
167
167
  continue;
168
168
  }
169
- existing.enumValues.push(...enumValues);
169
+ existing.enumValues = [.../* @__PURE__ */ new Set([...existing.enumValues, ...enumValues])];
170
170
  }
171
171
  }
172
172
  return childMap;
@@ -174,10 +174,11 @@ function buildDiscriminatorChildMap(schemas) {
174
174
  /**
175
175
  * Patches a single top-level `SchemaNode` with its discriminator entry (adds or replaces
176
176
  * the discriminant property).
177
+ *
178
+ * A child declared with `allOf` parses to an intersection rather than an object, so the
179
+ * discriminant is intersected on as an extra member instead.
177
180
  */
178
181
  function patchDiscriminatorNode(node, entry) {
179
- const objectNode = ast.narrowSchema(node, "object");
180
- if (!objectNode) return node;
181
182
  const { propertyName, enumValues } = entry;
182
183
  const enumSchema = ast.factory.createSchema({
183
184
  type: "enum",
@@ -188,11 +189,27 @@ function patchDiscriminatorNode(node, entry) {
188
189
  required: true,
189
190
  schema: enumSchema
190
191
  });
191
- const existingIdx = objectNode.properties.findIndex((p) => p.name === propertyName);
192
- const newProperties = existingIdx >= 0 ? objectNode.properties.map((p, i) => i === existingIdx ? newProp : p) : [...objectNode.properties, newProp];
192
+ const objectNode = ast.narrowSchema(node, "object");
193
+ if (objectNode) {
194
+ const existingIdx = objectNode.properties.findIndex((p) => p.name === propertyName);
195
+ const newProperties = existingIdx >= 0 ? objectNode.properties.map((p, i) => i === existingIdx ? newProp : p) : [...objectNode.properties, newProp];
196
+ return {
197
+ ...objectNode,
198
+ properties: newProperties
199
+ };
200
+ }
201
+ const intersectionNode = ast.narrowSchema(node, "intersection");
202
+ if (!intersectionNode?.members) return node;
203
+ const discriminantNode = ast.factory.createSchema({
204
+ type: "object",
205
+ primitive: "object",
206
+ properties: [newProp]
207
+ });
208
+ const patchedIdx = intersectionNode.members.findIndex((member) => ast.narrowSchema(member, "object")?.properties.some((p) => p.name === propertyName));
209
+ const newMembers = patchedIdx >= 0 ? intersectionNode.members.map((member, i) => i === patchedIdx ? patchDiscriminatorNode(member, entry) : member) : [...intersectionNode.members, discriminantNode];
193
210
  return {
194
- ...objectNode,
195
- properties: newProperties
211
+ ...intersectionNode,
212
+ members: newMembers
196
213
  };
197
214
  }
198
215
  //#endregion
@@ -1079,11 +1096,11 @@ function createNode({ schema, name, nullable, defaultValue }, extras) {
1079
1096
  *
1080
1097
  * @example
1081
1098
  * ```ts
1082
- * createDiscriminantNode({ propertyName: 'type', value: 'dog' })
1099
+ * createDiscriminantNode({ propertyName: 'type', values: ['dog'] })
1083
1100
  * // -> { type: 'object', properties: [{ name: 'type', required: true, schema: enum('dog') }] }
1084
1101
  * ```
1085
1102
  */
1086
- function createDiscriminantNode({ propertyName, value }) {
1103
+ function createDiscriminantNode({ propertyName, values }) {
1087
1104
  return ast.factory.createSchema({
1088
1105
  type: "object",
1089
1106
  primitive: "object",
@@ -1092,23 +1109,26 @@ function createDiscriminantNode({ propertyName, value }) {
1092
1109
  schema: ast.factory.createSchema({
1093
1110
  type: "enum",
1094
1111
  primitive: "string",
1095
- enumValues: [value]
1112
+ enumValues: values
1096
1113
  }),
1097
1114
  required: true
1098
1115
  })]
1099
1116
  });
1100
1117
  }
1101
1118
  /**
1102
- * Returns the discriminator key whose mapping value matches `ref`, or `null` when there is no match.
1119
+ * Returns every discriminator key whose mapping value matches `ref`, in mapping order.
1120
+ *
1121
+ * A mapping may point several keys at the same schema, in which case the member has to be
1122
+ * narrowed to all of them — keeping only the first would drop the rest from the union.
1103
1123
  *
1104
1124
  * @example
1105
1125
  * ```ts
1106
- * findDiscriminator({ dog: '#/components/schemas/Dog' }, '#/components/schemas/Dog') // 'dog'
1126
+ * findDiscriminators({ dog: '#/components/schemas/Dog', hound: '#/components/schemas/Dog' }, '#/components/schemas/Dog') // ['dog', 'hound']
1107
1127
  * ```
1108
1128
  */
1109
- function findDiscriminator(mapping, ref) {
1110
- if (!mapping || !ref) return null;
1111
- return Object.entries(mapping).find(([, value]) => value === ref)?.[0] ?? null;
1129
+ function findDiscriminators(mapping, ref) {
1130
+ if (!mapping || !ref) return [];
1131
+ return Object.entries(mapping).filter(([, value]) => value === ref).map(([key]) => key);
1112
1132
  }
1113
1133
  /**
1114
1134
  * Narrows each `oneOf`/`anyOf` member with its discriminant value, intersecting the member's own
@@ -1153,21 +1173,23 @@ function narrowUnionMembers({ unionMembers, discriminator, sharedPropertiesNode,
1153
1173
  }
1154
1174
  return unionMembers.map((s) => {
1155
1175
  const ref = isReference(s) ? s.$ref : void 0;
1156
- const discriminatorValue = findDiscriminator(discriminator?.mapping, ref) ?? implicitDiscriminantValue(s);
1176
+ const mappedValues = findDiscriminators(discriminator?.mapping, ref);
1177
+ const implicitValue = mappedValues.length ? null : implicitDiscriminantValue(s);
1178
+ const discriminatorValues = mappedValues.length ? mappedValues : implicitValue ? [implicitValue] : [];
1157
1179
  const memberNode = parse({
1158
1180
  schema: s,
1159
1181
  name
1160
1182
  }, rawOptions);
1161
- if (!discriminatorValue || !discriminator) return memberNode;
1183
+ if (!discriminatorValues.length || !discriminator) return memberNode;
1162
1184
  const narrowedDiscriminatorNode = sharedPropertiesNode ? pickDiscriminatorPropertyNode(ast.applyMacros(sharedPropertiesNode, [macroDiscriminatorEnum({
1163
1185
  propertyName: discriminator.propertyName,
1164
- values: [discriminatorValue]
1186
+ values: discriminatorValues
1165
1187
  })], { depth: "shallow" }), discriminator.propertyName) : void 0;
1166
1188
  return ast.factory.createSchema({
1167
1189
  type: "intersection",
1168
1190
  members: [memberNode, narrowedDiscriminatorNode ?? createDiscriminantNode({
1169
1191
  propertyName: discriminator.propertyName,
1170
- value: discriminatorValue
1192
+ values: discriminatorValues
1171
1193
  })]
1172
1194
  });
1173
1195
  });
@@ -1192,10 +1214,10 @@ function extractDiscriminatedAllOfMembers({ allOfMembers, name, refs }) {
1192
1214
  const inOneOf = parentUnion.some((oneOfItem) => isReference(oneOfItem) && oneOfItem.$ref === childRef);
1193
1215
  const inMapping = Object.values(deref.discriminator.mapping ?? {}).some((v) => v === childRef);
1194
1216
  if (inOneOf || inMapping) {
1195
- const discriminatorValue = findDiscriminator(deref.discriminator.mapping, childRef);
1196
- if (discriminatorValue) discriminantValues.push({
1217
+ const values = findDiscriminators(deref.discriminator.mapping, childRef);
1218
+ if (values.length) discriminantValues.push({
1197
1219
  propertyName: deref.discriminator.propertyName,
1198
- value: discriminatorValue
1220
+ values
1199
1221
  });
1200
1222
  return false;
1201
1223
  }
@@ -1300,9 +1322,9 @@ function convertAllOf({ schema, name, nullable, defaultValue, rawOptions, parse,
1300
1322
  const { allOf: _allOf, ...schemaWithoutAllOf } = schema;
1301
1323
  allOfMembers.push(parse({ schema: schemaWithoutAllOf }, rawOptions));
1302
1324
  }
1303
- for (const { propertyName, value } of discriminantValues) allOfMembers.push(createDiscriminantNode({
1325
+ for (const { propertyName, values } of discriminantValues) allOfMembers.push(createDiscriminantNode({
1304
1326
  propertyName,
1305
- value
1327
+ values
1306
1328
  }));
1307
1329
  return createNode({
1308
1330
  schema,