@mastra/schema-compat 1.3.8 → 1.3.9

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
@@ -5058,6 +5058,39 @@ const allowedStringFormats = [
5058
5058
  "ipv6",
5059
5059
  "uuid"
5060
5060
  ];
5061
+ function unorderedArraysEqual(left, right, itemEquals) {
5062
+ if (left.length !== right.length) return false;
5063
+ const matched = /* @__PURE__ */ new Set();
5064
+ return left.every((leftItem) => {
5065
+ const matchIndex = right.findIndex((rightItem, index) => !matched.has(index) && itemEquals(leftItem, rightItem));
5066
+ if (matchIndex === -1) return false;
5067
+ matched.add(matchIndex);
5068
+ return true;
5069
+ });
5070
+ }
5071
+ function jsonValuesEqual(left, right) {
5072
+ if (Object.is(left, right)) return true;
5073
+ if (Array.isArray(left) || Array.isArray(right)) return Array.isArray(left) && Array.isArray(right) && left.length === right.length && left.every((value, index) => jsonValuesEqual(value, right[index]));
5074
+ if (!left || !right || typeof left !== "object" || typeof right !== "object") return false;
5075
+ const leftEntries = Object.entries(left);
5076
+ const rightRecord = right;
5077
+ return leftEntries.length === Object.keys(rightRecord).length && leftEntries.every(([key, value]) => Object.prototype.hasOwnProperty.call(rightRecord, key) && jsonValuesEqual(value, rightRecord[key]));
5078
+ }
5079
+ function schemaValuesEqual(left, right, keyword) {
5080
+ if (keyword === "const" || keyword === "default" || keyword === "example" || keyword === "examples") return jsonValuesEqual(left, right);
5081
+ if (Object.is(left, right)) return true;
5082
+ if (Array.isArray(left) || Array.isArray(right)) {
5083
+ if (!Array.isArray(left) || !Array.isArray(right)) return false;
5084
+ if (keyword === "required" || keyword === "type") return unorderedArraysEqual(left, right, Object.is);
5085
+ if (keyword === "enum") return unorderedArraysEqual(left, right, jsonValuesEqual);
5086
+ if (keyword === "allOf" || keyword === "anyOf" || keyword === "oneOf") return unorderedArraysEqual(left, right, (leftItem, rightItem) => schemaValuesEqual(leftItem, rightItem));
5087
+ return left.length === right.length && left.every((value, index) => schemaValuesEqual(value, right[index]));
5088
+ }
5089
+ if (!left || !right || typeof left !== "object" || typeof right !== "object") return false;
5090
+ const leftEntries = Object.entries(left);
5091
+ const rightRecord = right;
5092
+ return leftEntries.length === Object.keys(rightRecord).length && leftEntries.every(([key, value]) => Object.prototype.hasOwnProperty.call(rightRecord, key) && schemaValuesEqual(value, rightRecord[key], key));
5093
+ }
5061
5094
  var OpenAISchemaCompatLayer = class extends SchemaCompatLayer {
5062
5095
  getSchemaTarget() {
5063
5096
  return `jsonSchema7`;
@@ -5187,41 +5220,89 @@ var OpenAISchemaCompatLayer = class extends SchemaCompatLayer {
5187
5220
  if (!schema.required?.includes(key)) {
5188
5221
  schema["x-optional"] = [...schema["x-optional"] || [], key];
5189
5222
  schema.required?.push(key);
5223
+ const objectKeywords = [
5224
+ "properties",
5225
+ "required",
5226
+ "additionalProperties",
5227
+ "x-optional"
5228
+ ];
5229
+ const arrayKeywords = ["items"];
5230
+ const genericConstraintKeywords = [
5231
+ "const",
5232
+ "enum",
5233
+ "oneOf",
5234
+ "not",
5235
+ "if",
5236
+ "then",
5237
+ "else"
5238
+ ];
5239
+ const branchConstraintKeywords = [
5240
+ "anyOf",
5241
+ "oneOf",
5242
+ "not",
5243
+ "if",
5244
+ "then",
5245
+ "else"
5246
+ ];
5247
+ const typeSpecificKeywords = (type) => type === "object" ? objectKeywords : type === "array" ? arrayKeywords : [];
5248
+ const isRedundantNullableUnion = (type) => {
5249
+ if (!prop.anyOf || prop.anyOf.length !== 2) return false;
5250
+ const nullBranches = prop.anyOf.filter((branch) => typeof branch !== "boolean" && branch.type === "null");
5251
+ const valueBranches = prop.anyOf.filter((branch) => typeof branch !== "boolean" && branch.type !== "null");
5252
+ if (nullBranches.length !== 1 || valueBranches.length !== 1) return false;
5253
+ const valueBranch = valueBranches[0];
5254
+ if (valueBranch.type !== type) return false;
5255
+ return Object.entries(valueBranch).every(([keyword, value]) => {
5256
+ if (keyword === "type") return true;
5257
+ return keyword in prop && schemaValuesEqual(prop[keyword], value, keyword);
5258
+ });
5259
+ };
5190
5260
  if (Array.isArray(prop.type)) {
5191
5261
  const types = [...prop.type];
5192
5262
  if (!types.includes("null")) types.push("null");
5193
- delete prop.anyOf;
5263
+ const branchConstraints = {};
5264
+ const propRecord = prop;
5265
+ const branchConstraintRecord = branchConstraints;
5266
+ for (const keyword of branchConstraintKeywords) if (keyword in prop) {
5267
+ branchConstraintRecord[keyword] = propRecord[keyword];
5268
+ delete propRecord[keyword];
5269
+ }
5194
5270
  delete prop.type;
5195
5271
  if ("const" in prop) {
5196
5272
  const constValue = prop.const;
5197
- prop.enum = !prop.enum || prop.enum.some((value) => JSON.stringify(value) === JSON.stringify(constValue)) ? [constValue, null] : [null];
5273
+ prop.enum = !prop.enum || prop.enum.some((value) => jsonValuesEqual(value, constValue)) ? [constValue, null] : [null];
5198
5274
  delete prop.const;
5199
5275
  } else if (prop.enum && !prop.enum.includes(null)) prop.enum = [...prop.enum, null];
5200
- const objectKeywords = [
5201
- "properties",
5202
- "required",
5203
- "additionalProperties",
5204
- "x-optional"
5205
- ];
5206
- const arrayKeywords = ["items"];
5207
5276
  prop.anyOf = types.map((type) => {
5208
5277
  if (type === "null") return { type: "null" };
5209
5278
  const branch = { type };
5210
- const keywords = type === "object" ? objectKeywords : type === "array" ? arrayKeywords : [];
5211
- for (const keyword of keywords) if (keyword in prop) branch[keyword] = prop[keyword];
5212
- return branch;
5279
+ for (const keyword of typeSpecificKeywords(type)) if (keyword in prop) branch[keyword] = prop[keyword];
5280
+ return Object.assign(branch, branchConstraints);
5213
5281
  });
5214
5282
  for (const keyword of [...objectKeywords, ...arrayKeywords]) delete prop[keyword];
5215
5283
  } else if (prop.type && prop.type !== "null") {
5216
5284
  const originalType = prop.type;
5217
- const propSchema = { ...prop };
5218
- delete propSchema.anyOf;
5219
- delete propSchema.type;
5220
- delete prop.type;
5221
- prop.anyOf = [{
5222
- ...propSchema,
5223
- type: originalType
5224
- }, { type: "null" }];
5285
+ const keywords = typeSpecificKeywords(originalType);
5286
+ if (keywords.length > 0) {
5287
+ const branch = { type: originalType };
5288
+ const preserveAnyOf = prop.anyOf && !isRedundantNullableUnion(originalType) ? prop.anyOf : void 0;
5289
+ for (const keyword of [...keywords, ...genericConstraintKeywords]) if (keyword in prop) {
5290
+ branch[keyword] = prop[keyword];
5291
+ delete prop[keyword];
5292
+ }
5293
+ if (preserveAnyOf) branch.anyOf = preserveAnyOf;
5294
+ delete prop.type;
5295
+ prop.anyOf = [branch, { type: "null" }];
5296
+ } else {
5297
+ const propSchema = {
5298
+ ...prop,
5299
+ type: originalType
5300
+ };
5301
+ if (isRedundantNullableUnion(originalType)) delete propSchema.anyOf;
5302
+ for (const keyword of [...genericConstraintKeywords, "anyOf"]) delete prop[keyword];
5303
+ delete prop.type;
5304
+ prop.anyOf = [propSchema, { type: "null" }];
5305
+ }
5225
5306
  }
5226
5307
  }
5227
5308
  }