@mastra/schema-compat 1.3.11 → 1.3.12-alpha.1

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
@@ -1,7 +1,7 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_json_schema_traverse$1 = require("./json-schema-traverse-DbuWNYgg.cjs");
3
3
  const require_zod_to_json = require("./zod-to-json.cjs");
4
- const require_schema = require("./schema-D35TsNfD.cjs");
4
+ const require_schema = require("./schema-IhrnbMI3.cjs");
5
5
  let zod_v3 = require("zod/v3");
6
6
  let zod = require("zod");
7
7
  let zod_from_json_schema = require("zod-from-json-schema");
@@ -4971,6 +4971,13 @@ var SchemaCompatLayer = class {
4971
4971
  */
4972
4972
  function transformNullToUndefined(value, jsonSchema) {
4973
4973
  if (value === null || value === void 0) return value;
4974
+ const branches = jsonSchema.anyOf ?? jsonSchema.oneOf;
4975
+ if (Array.isArray(branches)) {
4976
+ const { anyOf: _anyOf, oneOf: _oneOf, ...parent } = jsonSchema;
4977
+ const branch = findMatchingBranch(value, branches);
4978
+ if (!branch) return "properties" in parent || "items" in parent ? transformNullToUndefined(value, parent) : value;
4979
+ return transformNullToUndefined(value, mergeSchemas(parent, branch));
4980
+ }
4974
4981
  if (typeof value !== "object" || Array.isArray(value)) {
4975
4982
  if (Array.isArray(value) && jsonSchema.items && typeof jsonSchema.items === "object") return value.map((item) => transformNullToUndefined(item, jsonSchema.items));
4976
4983
  return value;
@@ -4985,6 +4992,58 @@ function transformNullToUndefined(value, jsonSchema) {
4985
4992
  return result;
4986
4993
  }
4987
4994
  /**
4995
+ * Picks the non-null union branch (from `anyOf`/`oneOf`) whose shape matches the value,
4996
+ * e.g. the object branch of a `.nullable()` object. For objects, branches whose required
4997
+ * keys are missing or whose `const`/`enum` properties (discriminators) disagree are skipped.
4998
+ */
4999
+ function findMatchingBranch(value, branches) {
5000
+ const isArray = Array.isArray(value);
5001
+ if (typeof value !== "object" && !isArray) return;
5002
+ return branches.find((branch) => {
5003
+ if (!branch || typeof branch !== "object") return false;
5004
+ const types = Array.isArray(branch.type) ? branch.type : [branch.type];
5005
+ if (isArray) {
5006
+ if (!("items" in branch || types.includes("array"))) return false;
5007
+ const items = branch.items;
5008
+ return !items || typeof items !== "object" || value.every((item) => itemMatches(item, items));
5009
+ }
5010
+ if (!("properties" in branch || "anyOf" in branch || "oneOf" in branch || types.includes("object"))) return false;
5011
+ return objectMatchesBranch(value, branch);
5012
+ });
5013
+ }
5014
+ function itemMatches(item, schema) {
5015
+ if (item === null || typeof item !== "object" || Array.isArray(item)) return true;
5016
+ const branches = schema.anyOf ?? schema.oneOf;
5017
+ if (Array.isArray(branches)) return findMatchingBranch(item, branches) !== void 0;
5018
+ return objectMatchesBranch(item, schema);
5019
+ }
5020
+ function objectMatchesBranch(value, branch) {
5021
+ if ((branch.required ?? []).some((key) => !(key in value))) return false;
5022
+ const properties = branch.properties ?? {};
5023
+ return Object.entries(properties).every(([key, prop]) => {
5024
+ if (!prop || typeof prop !== "object" || !(key in value)) return true;
5025
+ if ("const" in prop) return prop.const === value[key];
5026
+ if (Array.isArray(prop.enum)) return prop.enum.includes(value[key]);
5027
+ return true;
5028
+ });
5029
+ }
5030
+ function mergeSchemas(parent, branch) {
5031
+ const merged = {
5032
+ ...parent,
5033
+ ...branch
5034
+ };
5035
+ if (parent.items && !branch.items) merged.items = parent.items;
5036
+ if (!parent.properties) return merged;
5037
+ return {
5038
+ ...merged,
5039
+ properties: {
5040
+ ...parent.properties,
5041
+ ...branch.properties
5042
+ },
5043
+ required: [.../* @__PURE__ */ new Set([...parent.required ?? [], ...branch.required ?? []])]
5044
+ };
5045
+ }
5046
+ /**
4988
5047
  * Wraps a StandardSchemaWithJSON to transform null values to undefined for
4989
5048
  * optional fields before validation. This is a schema-agnostic solution for
4990
5049
  * OpenAI strict mode, which sends null for optional fields.
@@ -5228,6 +5287,15 @@ var OpenAISchemaCompatLayer = class extends SchemaCompatLayer {
5228
5287
  "x-optional"
5229
5288
  ];
5230
5289
  const arrayKeywords = ["items"];
5290
+ const numericKeywords = [
5291
+ "format",
5292
+ "minimum",
5293
+ "maximum",
5294
+ "exclusiveMinimum",
5295
+ "exclusiveMaximum",
5296
+ "multipleOf"
5297
+ ];
5298
+ const isNumericType = (type) => type === "integer" || type === "number";
5231
5299
  const genericConstraintKeywords = [
5232
5300
  "const",
5233
5301
  "enum",
@@ -5277,10 +5345,26 @@ var OpenAISchemaCompatLayer = class extends SchemaCompatLayer {
5277
5345
  prop.anyOf = types.map((type) => {
5278
5346
  if (type === "null") return { type: "null" };
5279
5347
  const branch = { type };
5280
- for (const keyword of typeSpecificKeywords(type)) if (keyword in prop) branch[keyword] = prop[keyword];
5348
+ const numericFormat = typeof prop.format === "string" && [
5349
+ "int32",
5350
+ "int64",
5351
+ "float",
5352
+ "double"
5353
+ ].includes(prop.format);
5354
+ const formatOwner = types.includes("string") && !numericFormat ? type === "string" : isNumericType(type);
5355
+ for (const keyword of [
5356
+ ...typeSpecificKeywords(type),
5357
+ ...isNumericType(type) ? numericKeywords.filter((k) => k !== "format") : [],
5358
+ ...formatOwner ? ["format"] : []
5359
+ ]) if (keyword in prop) branch[keyword] = prop[keyword];
5281
5360
  return Object.assign(branch, branchConstraints);
5282
5361
  });
5283
- for (const keyword of [...objectKeywords, ...arrayKeywords]) delete prop[keyword];
5362
+ const numericBranchExists = types.some(isNumericType);
5363
+ for (const keyword of [
5364
+ ...objectKeywords,
5365
+ ...arrayKeywords,
5366
+ ...numericBranchExists ? numericKeywords : []
5367
+ ]) delete prop[keyword];
5284
5368
  } else if (prop.type && prop.type !== "null") {
5285
5369
  const originalType = prop.type;
5286
5370
  const keywords = typeSpecificKeywords(originalType);
@@ -5301,6 +5385,7 @@ var OpenAISchemaCompatLayer = class extends SchemaCompatLayer {
5301
5385
  };
5302
5386
  if (isRedundantNullableUnion(originalType)) delete propSchema.anyOf;
5303
5387
  for (const keyword of [...genericConstraintKeywords, "anyOf"]) delete prop[keyword];
5388
+ if (isNumericType(originalType)) for (const keyword of numericKeywords) delete prop[keyword];
5304
5389
  delete prop.type;
5305
5390
  prop.anyOf = [propSchema, { type: "null" }];
5306
5391
  }