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