@mastra/schema-compat 1.3.4-alpha.2 → 1.3.5-alpha.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/CHANGELOG.md +34 -0
- package/dist/_types/@internal_ai-sdk-v5/dist/index.d.ts +4 -4
- package/dist/_types/@internal_ai-v6/dist/index.d.ts +10 -6
- package/dist/index.cjs +5455 -5998
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +5467 -5988
- package/dist/index.js.map +1 -1
- package/dist/json-schema-BstKYbJi.js +6797 -0
- package/dist/json-schema-BstKYbJi.js.map +1 -0
- package/dist/json-schema-pcL1TeZs.cjs +6809 -0
- package/dist/json-schema-pcL1TeZs.cjs.map +1 -0
- package/dist/json-schema-traverse-B35mHRM8.js +101 -0
- package/dist/json-schema-traverse-B35mHRM8.js.map +1 -0
- package/dist/json-schema-traverse-CSNSaf0y.cjs +83 -0
- package/dist/json-schema-traverse-CSNSaf0y.cjs.map +1 -0
- package/dist/json-to-zod.cjs +185 -245
- package/dist/json-to-zod.cjs.map +1 -1
- package/dist/json-to-zod.js +176 -235
- package/dist/json-to-zod.js.map +1 -1
- package/dist/provider-compats/anthropic.d.ts +1 -0
- package/dist/provider-compats/anthropic.d.ts.map +1 -1
- package/dist/rolldown-runtime-emK7D4bc.cjs +35 -0
- package/dist/schema-Bv9OdW1f.js +258 -0
- package/dist/schema-Bv9OdW1f.js.map +1 -0
- package/dist/schema-Cjk6OMG9.cjs +295 -0
- package/dist/schema-Cjk6OMG9.cjs.map +1 -0
- package/dist/schema.cjs +8 -32
- package/dist/schema.js +2 -3
- package/dist/standard-schema/adapters/ai-sdk.cjs +156 -14
- package/dist/standard-schema/adapters/ai-sdk.cjs.map +1 -1
- package/dist/standard-schema/adapters/ai-sdk.js +155 -2
- package/dist/standard-schema/adapters/ai-sdk.js.map +1 -1
- package/dist/standard-schema/adapters/json-schema.cjs +4 -16
- package/dist/standard-schema/adapters/json-schema.js +2 -3
- package/dist/standard-schema/adapters/zod-v3.cjs +101 -10
- package/dist/standard-schema/adapters/zod-v3.cjs.map +1 -1
- package/dist/standard-schema/adapters/zod-v3.js +99 -2
- package/dist/standard-schema/adapters/zod-v3.js.map +1 -1
- package/dist/zod-to-json.cjs +165 -22
- package/dist/zod-to-json.cjs.map +1 -1
- package/dist/zod-to-json.js +160 -2
- package/dist/zod-to-json.js.map +1 -1
- package/package.json +18 -17
- package/dist/chunk-23HDOZLF.js +0 -105
- package/dist/chunk-23HDOZLF.js.map +0 -1
- package/dist/chunk-5WRI5ZAA.js +0 -29
- package/dist/chunk-5WRI5ZAA.js.map +0 -1
- package/dist/chunk-77T2HV4Q.cjs +0 -7352
- package/dist/chunk-77T2HV4Q.cjs.map +0 -1
- package/dist/chunk-BQ3VTMIR.cjs +0 -76
- package/dist/chunk-BQ3VTMIR.cjs.map +0 -1
- package/dist/chunk-DZUJEN5N.cjs +0 -32
- package/dist/chunk-DZUJEN5N.cjs.map +0 -1
- package/dist/chunk-FJGZKUBH.cjs +0 -208
- package/dist/chunk-FJGZKUBH.cjs.map +0 -1
- package/dist/chunk-FS3P4V5M.cjs +0 -108
- package/dist/chunk-FS3P4V5M.cjs.map +0 -1
- package/dist/chunk-QEM5W7OR.js +0 -199
- package/dist/chunk-QEM5W7OR.js.map +0 -1
- package/dist/chunk-QFEMCRFS.js +0 -70
- package/dist/chunk-QFEMCRFS.js.map +0 -1
- package/dist/chunk-RMMKMUYK.js +0 -7349
- package/dist/chunk-RMMKMUYK.js.map +0 -1
- package/dist/chunk-SKPYVQBT.cjs +0 -94
- package/dist/chunk-SKPYVQBT.cjs.map +0 -1
- package/dist/chunk-VNIPWNNH.js +0 -170
- package/dist/chunk-VNIPWNNH.js.map +0 -1
- package/dist/chunk-Y4VRRNL5.js +0 -92
- package/dist/chunk-Y4VRRNL5.js.map +0 -1
- package/dist/chunk-ZTO66ALH.cjs +0 -181
- package/dist/chunk-ZTO66ALH.cjs.map +0 -1
- package/dist/schema.cjs.map +0 -1
- package/dist/schema.js.map +0 -1
- package/dist/standard-schema/adapters/json-schema.cjs.map +0 -1
- package/dist/standard-schema/adapters/json-schema.js.map +0 -1
|
@@ -1,3 +1,100 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import { r as __toESM, t as require_json_schema_traverse } from "../../json-schema-traverse-B35mHRM8.js";
|
|
2
|
+
import zodToJsonSchemaOriginal, { ignoreOverride } from "zod-to-json-schema";
|
|
3
|
+
//#region src/standard-schema/adapters/zod-v3.ts
|
|
4
|
+
var import_json_schema_traverse = /* @__PURE__ */ __toESM(require_json_schema_traverse(), 1);
|
|
5
|
+
/**
|
|
6
|
+
* Target mapping from Standard Schema targets to zod-to-json-schema targets.
|
|
7
|
+
*/
|
|
8
|
+
const TARGET_MAP = {
|
|
9
|
+
"draft-04": "jsonSchema7",
|
|
10
|
+
"draft-07": "jsonSchema7",
|
|
11
|
+
"draft-2020-12": "jsonSchema2019-09",
|
|
12
|
+
"openapi-3.0": "openApi3"
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Converts a Zod schema to JSON Schema using the specified target format.
|
|
16
|
+
*
|
|
17
|
+
* @param zodSchema - The Zod schema to convert
|
|
18
|
+
* @param options - Standard Schema JSON options including the target format
|
|
19
|
+
* @returns The JSON Schema representation
|
|
20
|
+
* @throws Error if the target format is not supported
|
|
21
|
+
*
|
|
22
|
+
* @internal
|
|
23
|
+
*/
|
|
24
|
+
function convertToJsonSchema(zodSchema, options) {
|
|
25
|
+
const target = TARGET_MAP[options.target];
|
|
26
|
+
if (!target) {
|
|
27
|
+
const supportedTargets = Object.keys(TARGET_MAP);
|
|
28
|
+
throw new Error(`Unsupported JSON Schema target: "${options.target}". Supported targets are: ${supportedTargets.join(", ")}`);
|
|
29
|
+
}
|
|
30
|
+
const jsonSchema = zodToJsonSchemaOriginal(zodSchema, {
|
|
31
|
+
$refStrategy: "none",
|
|
32
|
+
target,
|
|
33
|
+
override: (def) => {
|
|
34
|
+
if (def.typeName === "ZodDate") return {
|
|
35
|
+
type: "string",
|
|
36
|
+
format: "date-time",
|
|
37
|
+
"x-date": true
|
|
38
|
+
};
|
|
39
|
+
return ignoreOverride;
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
(0, import_json_schema_traverse.default)(jsonSchema, { cb: { pre: (schema) => {
|
|
43
|
+
if (schema.type === "string" && schema.format === "email") schema.pattern = `^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$`;
|
|
44
|
+
} } });
|
|
45
|
+
return jsonSchema;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Wraps a Zod v3 schema to implement the full @standard-schema/spec interface.
|
|
49
|
+
*
|
|
50
|
+
* While Zod v3 natively implements `StandardSchemaV1` (validation), it does not
|
|
51
|
+
* implement `StandardJSONSchemaV1` (JSON Schema conversion). This adapter adds
|
|
52
|
+
* the `jsonSchema` property to provide JSON Schema conversion capabilities.
|
|
53
|
+
*
|
|
54
|
+
* @typeParam T - The Zod schema type
|
|
55
|
+
*
|
|
56
|
+
* @example
|
|
57
|
+
* ```typescript
|
|
58
|
+
* import { z } from 'zod';
|
|
59
|
+
* import { toStandardSchema } from '@mastra/schema-compat/adapters/zod-v3';
|
|
60
|
+
*
|
|
61
|
+
* const userSchema = z.object({
|
|
62
|
+
* name: z.string(),
|
|
63
|
+
* age: z.number().min(0),
|
|
64
|
+
* });
|
|
65
|
+
*
|
|
66
|
+
* const standardSchema = toStandardSchema(userSchema);
|
|
67
|
+
*
|
|
68
|
+
* // Use validation (from StandardSchemaV1)
|
|
69
|
+
* const result = standardSchema['~standard'].validate({ name: 'John', age: 30 });
|
|
70
|
+
*
|
|
71
|
+
* // Get JSON Schema (from StandardJSONSchemaV1)
|
|
72
|
+
* const jsonSchema = standardSchema['~standard'].jsonSchema.output({ target: 'draft-07' });
|
|
73
|
+
* ```
|
|
74
|
+
*/
|
|
75
|
+
function toStandardSchema(zodSchema) {
|
|
76
|
+
const wrapper = Object.create(zodSchema);
|
|
77
|
+
const existingStandard = zodSchema["~standard"];
|
|
78
|
+
const jsonSchemaConverter = {
|
|
79
|
+
input: (options) => {
|
|
80
|
+
return convertToJsonSchema(zodSchema, options);
|
|
81
|
+
},
|
|
82
|
+
output: (options) => {
|
|
83
|
+
return convertToJsonSchema(zodSchema, options);
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
Object.defineProperty(wrapper, "~standard", {
|
|
87
|
+
value: {
|
|
88
|
+
...existingStandard,
|
|
89
|
+
jsonSchema: jsonSchemaConverter
|
|
90
|
+
},
|
|
91
|
+
writable: false,
|
|
92
|
+
enumerable: true,
|
|
93
|
+
configurable: false
|
|
94
|
+
});
|
|
95
|
+
return wrapper;
|
|
96
|
+
}
|
|
97
|
+
//#endregion
|
|
98
|
+
export { toStandardSchema };
|
|
99
|
+
|
|
3
100
|
//# sourceMappingURL=zod-v3.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"
|
|
1
|
+
{"version":3,"file":"zod-v3.js","names":[],"sources":["../../../src/standard-schema/adapters/zod-v3.ts"],"sourcesContent":["import type { StandardSchemaV1, StandardJSONSchemaV1 } from '@standard-schema/spec';\nimport traverse from 'json-schema-traverse';\n// Use zod/v3 types for v3 compatibility (v4's v3-compat layer)\nimport type { ZodType, ZodTypeDef } from 'zod/v3';\nimport zodToJsonSchemaOriginal, { ignoreOverride } from 'zod-to-json-schema';\nimport type {\n StandardSchemaWithJSON,\n StandardSchemaWithJSONProps,\n ZodToJsonSchemaTarget,\n} from '../standard-schema.types';\n/**\n * Target mapping from Standard Schema targets to zod-to-json-schema targets.\n */\nconst TARGET_MAP: Record<string, ZodToJsonSchemaTarget> = {\n 'draft-04': 'jsonSchema7',\n 'draft-07': 'jsonSchema7',\n 'draft-2020-12': 'jsonSchema2019-09',\n 'openapi-3.0': 'openApi3',\n};\n\n/**\n * Converts a Zod schema to JSON Schema using the specified target format.\n *\n * @param zodSchema - The Zod schema to convert\n * @param options - Standard Schema JSON options including the target format\n * @returns The JSON Schema representation\n * @throws Error if the target format is not supported\n *\n * @internal\n */\nfunction convertToJsonSchema<T extends ZodType<any, ZodTypeDef, any>>(\n zodSchema: T,\n options: StandardJSONSchemaV1.Options,\n): Record<string, unknown> {\n const target = TARGET_MAP[options.target];\n\n if (!target) {\n // For unknown targets, try to use jsonSchema7 as fallback or throw\n const supportedTargets = Object.keys(TARGET_MAP);\n throw new Error(\n `Unsupported JSON Schema target: \"${options.target}\". ` + `Supported targets are: ${supportedTargets.join(', ')}`,\n );\n }\n\n const jsonSchema = zodToJsonSchemaOriginal(zodSchema, {\n $refStrategy: 'none',\n target,\n override: (def: any) => {\n // Mark z.date() with x-date for downstream string→Date conversion.\n // Zod v3 has no z.coerce.date(), so all dates are strict.\n if (def.typeName === 'ZodDate') {\n return { type: 'string', format: 'date-time', 'x-date': true };\n }\n return ignoreOverride;\n },\n });\n\n traverse(jsonSchema, {\n cb: {\n pre: schema => {\n if (schema.type === 'string' && schema.format === 'email') {\n schema.pattern = `^(?!\\\\.)(?!.*\\\\.\\\\.)([A-Za-z0-9_'+\\\\-\\\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\\\-]*\\\\.)+[A-Za-z]{2,}$`;\n }\n },\n // post: (schema, jsonPtr, rootSchema, parentJsonPtr, parentKeyword, parentSchema) => {\n // this.postProcessJSONNode(schema, parentSchema);\n // },\n },\n });\n\n return jsonSchema as Record<string, unknown>;\n}\n\n/**\n * Wraps a Zod v3 schema to implement the full @standard-schema/spec interface.\n *\n * While Zod v3 natively implements `StandardSchemaV1` (validation), it does not\n * implement `StandardJSONSchemaV1` (JSON Schema conversion). This adapter adds\n * the `jsonSchema` property to provide JSON Schema conversion capabilities.\n *\n * @typeParam T - The Zod schema type\n *\n * @example\n * ```typescript\n * import { z } from 'zod';\n * import { toStandardSchema } from '@mastra/schema-compat/adapters/zod-v3';\n *\n * const userSchema = z.object({\n * name: z.string(),\n * age: z.number().min(0),\n * });\n *\n * const standardSchema = toStandardSchema(userSchema);\n *\n * // Use validation (from StandardSchemaV1)\n * const result = standardSchema['~standard'].validate({ name: 'John', age: 30 });\n *\n * // Get JSON Schema (from StandardJSONSchemaV1)\n * const jsonSchema = standardSchema['~standard'].jsonSchema.output({ target: 'draft-07' });\n * ```\n */\nexport function toStandardSchema<T>(zodSchema: ZodType<T, ZodTypeDef, T>): T & StandardSchemaWithJSON<T, T> {\n // Create a wrapper object that includes the jsonSchema converter\n const wrapper = Object.create(zodSchema) as T & StandardSchemaWithJSON<T, T>;\n\n // Get the existing ~standard property from Zod\n const existingStandard = zodSchema['~standard'] as StandardSchemaV1.Props<T, T>;\n\n // Create the JSON Schema converter\n const jsonSchemaConverter: StandardJSONSchemaV1.Converter = {\n input: (options: StandardJSONSchemaV1.Options): Record<string, unknown> => {\n return convertToJsonSchema(zodSchema, options);\n },\n output: (options: StandardJSONSchemaV1.Options): Record<string, unknown> => {\n // For Zod schemas, input and output JSON Schema are typically the same\n // unless using transforms, which would need special handling\n return convertToJsonSchema(zodSchema, options);\n },\n };\n\n // Define the enhanced ~standard property\n Object.defineProperty(wrapper, '~standard', {\n value: {\n ...existingStandard,\n jsonSchema: jsonSchemaConverter,\n } satisfies StandardSchemaWithJSONProps<T, T>,\n writable: false,\n enumerable: true,\n configurable: false,\n });\n\n return wrapper;\n}\n"],"mappings":";;;;;;;AAaA,MAAM,aAAoD;CACxD,YAAY;CACZ,YAAY;CACZ,iBAAiB;CACjB,eAAe;AACjB;;;;;;;;;;;AAYA,SAAS,oBACP,WACA,SACyB;CACzB,MAAM,SAAS,WAAW,QAAQ;CAElC,IAAI,CAAC,QAAQ;EAEX,MAAM,mBAAmB,OAAO,KAAK,UAAU;EAC/C,MAAM,IAAI,MACR,oCAAoC,QAAQ,OAAO,4BAAiC,iBAAiB,KAAK,IAAI,GAChH;CACF;CAEA,MAAM,aAAa,wBAAwB,WAAW;EACpD,cAAc;EACd;EACA,WAAW,QAAa;GAGtB,IAAI,IAAI,aAAa,WACnB,OAAO;IAAE,MAAM;IAAU,QAAQ;IAAa,UAAU;GAAK;GAE/D,OAAO;EACT;CACF,CAAC;CAED,CAAA,GAAA,4BAAA,QAAA,CAAS,YAAY,EACnB,IAAI,EACF,MAAK,WAAU;EACb,IAAI,OAAO,SAAS,YAAY,OAAO,WAAW,SAChD,OAAO,UAAU;CAErB,EAIF,EACF,CAAC;CAED,OAAO;AACT;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8BA,SAAgB,iBAAoB,WAAwE;CAE1G,MAAM,UAAU,OAAO,OAAO,SAAS;CAGvC,MAAM,mBAAmB,UAAU;CAGnC,MAAM,sBAAsD;EAC1D,QAAQ,YAAmE;GACzE,OAAO,oBAAoB,WAAW,OAAO;EAC/C;EACA,SAAS,YAAmE;GAG1E,OAAO,oBAAoB,WAAW,OAAO;EAC/C;CACF;CAGA,OAAO,eAAe,SAAS,aAAa;EAC1C,OAAO;GACL,GAAG;GACH,YAAY;EACd;EACA,UAAU;EACV,YAAY;EACZ,cAAc;CAChB,CAAC;CAED,OAAO;AACT"}
|
package/dist/zod-to-json.cjs
CHANGED
|
@@ -1,24 +1,167 @@
|
|
|
1
|
-
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
const require_rolldown_runtime = require("./rolldown-runtime-emK7D4bc.cjs");
|
|
3
|
+
let zod_v4 = require("zod/v4");
|
|
4
|
+
let zod_to_json_schema = require("zod-to-json-schema");
|
|
5
|
+
zod_to_json_schema = require_rolldown_runtime.__toESM(zod_to_json_schema, 1);
|
|
6
|
+
//#region src/zod-to-json.ts
|
|
7
|
+
const PATCHED = Symbol("__mastra_patched__");
|
|
8
|
+
/**
|
|
9
|
+
* Recursively patch Zod v4 record schemas that are missing valueType.
|
|
10
|
+
* This fixes a bug in Zod v4 where z.record(valueSchema) doesn't set def.valueType.
|
|
11
|
+
* The single-arg form should set valueType but instead only sets keyType.
|
|
12
|
+
*
|
|
13
|
+
* Idempotent — marks patched schemas with a Symbol so repeat calls no-op.
|
|
14
|
+
*
|
|
15
|
+
* @internal Exported so the Zod v4 standard-schema adapter can apply the
|
|
16
|
+
* same patch before its native `toJSONSchema` call (the legacy `zodToJsonSchema`
|
|
17
|
+
* entry already calls it; the `applyCompatLayer` path otherwise wouldn't).
|
|
18
|
+
* Not part of the public API.
|
|
19
|
+
*/
|
|
20
|
+
function patchRecordSchemas(schema) {
|
|
21
|
+
if (!schema || typeof schema !== "object") return schema;
|
|
22
|
+
if (schema[PATCHED]) return schema;
|
|
23
|
+
schema[PATCHED] = true;
|
|
24
|
+
const def = schema._zod?.def;
|
|
25
|
+
if (def?.type === "record" && def.keyType && !def.valueType) {
|
|
26
|
+
def.valueType = def.keyType;
|
|
27
|
+
def.keyType = zod_v4.z.string();
|
|
28
|
+
}
|
|
29
|
+
if (!def) return schema;
|
|
30
|
+
if (def.type === "object" && def.shape) {
|
|
31
|
+
const shape = typeof def.shape === "function" ? def.shape() : def.shape;
|
|
32
|
+
for (const key of Object.keys(shape)) patchRecordSchemas(shape[key]);
|
|
33
|
+
}
|
|
34
|
+
if (def.type === "array" && def.element) patchRecordSchemas(def.element);
|
|
35
|
+
if (def.type === "union" && def.options) def.options.forEach(patchRecordSchemas);
|
|
36
|
+
if (def.type === "record") {
|
|
37
|
+
if (def.keyType) patchRecordSchemas(def.keyType);
|
|
38
|
+
if (def.valueType) patchRecordSchemas(def.valueType);
|
|
39
|
+
}
|
|
40
|
+
if (def.type === "intersection") {
|
|
41
|
+
if (def.left) patchRecordSchemas(def.left);
|
|
42
|
+
if (def.right) patchRecordSchemas(def.right);
|
|
43
|
+
}
|
|
44
|
+
if (def.type === "lazy") {
|
|
45
|
+
if (def.getter && typeof def.getter === "function") {
|
|
46
|
+
const originalGetter = def.getter;
|
|
47
|
+
def.getter = function() {
|
|
48
|
+
const innerSchema = originalGetter();
|
|
49
|
+
if (innerSchema) patchRecordSchemas(innerSchema);
|
|
50
|
+
return innerSchema;
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
if (def.innerType) patchRecordSchemas(def.innerType);
|
|
55
|
+
return schema;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Recursively fixes anyOf patterns that some providers (like OpenAI) don't accept.
|
|
59
|
+
* Converts anyOf: [{type: X}, {type: "null"}] to type: [X, "null"]
|
|
60
|
+
* Also fixes empty {} property schemas by converting to a union of primitive types.
|
|
61
|
+
*/
|
|
62
|
+
function fixAnyOfNullable(schema) {
|
|
63
|
+
if (typeof schema !== "object" || schema === null) return schema;
|
|
64
|
+
const result = { ...schema };
|
|
65
|
+
if (result.anyOf && Array.isArray(result.anyOf) && result.anyOf.length === 2) {
|
|
66
|
+
const nullSchema = result.anyOf.find((s) => typeof s === "object" && s !== null && s.type === "null");
|
|
67
|
+
const otherSchema = result.anyOf.find((s) => typeof s === "object" && s !== null && s.type !== "null");
|
|
68
|
+
if (nullSchema && otherSchema && typeof otherSchema === "object" && otherSchema.type) {
|
|
69
|
+
const { anyOf, ...rest } = result;
|
|
70
|
+
const fixedRest = fixAnyOfNullable(rest);
|
|
71
|
+
const fixedOther = fixAnyOfNullable(otherSchema);
|
|
72
|
+
return {
|
|
73
|
+
...fixedRest,
|
|
74
|
+
...fixedOther,
|
|
75
|
+
type: Array.isArray(fixedOther.type) ? [...fixedOther.type, "null"] : [fixedOther.type, "null"]
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
if (result.properties && typeof result.properties === "object" && !Array.isArray(result.properties)) result.properties = Object.fromEntries(Object.entries(result.properties).map(([key, value]) => {
|
|
80
|
+
const propSchema = value;
|
|
81
|
+
if (typeof propSchema === "object" && propSchema !== null && !Array.isArray(propSchema) && Object.keys(propSchema).length === 0) return [key, { type: [
|
|
82
|
+
"string",
|
|
83
|
+
"number",
|
|
84
|
+
"boolean",
|
|
85
|
+
"null"
|
|
86
|
+
] }];
|
|
87
|
+
return [key, fixAnyOfNullable(propSchema)];
|
|
88
|
+
}));
|
|
89
|
+
if (result.items) if (Array.isArray(result.items)) result.items = result.items.map((item) => fixAnyOfNullable(item));
|
|
90
|
+
else result.items = fixAnyOfNullable(result.items);
|
|
91
|
+
if (result.anyOf && Array.isArray(result.anyOf)) result.anyOf = result.anyOf.map((s) => fixAnyOfNullable(s));
|
|
92
|
+
if (result.oneOf && Array.isArray(result.oneOf)) result.oneOf = result.oneOf.map((s) => fixAnyOfNullable(s));
|
|
93
|
+
if (result.allOf && Array.isArray(result.allOf)) result.allOf = result.allOf.map((s) => fixAnyOfNullable(s));
|
|
94
|
+
return result;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Recursively ensures all properties in an object schema are included in the `required` array.
|
|
98
|
+
* OpenAI's strict structured output mode requires every key in `properties` to also appear in `required`.
|
|
99
|
+
*
|
|
100
|
+
* @param schema - The JSON Schema to process
|
|
101
|
+
* @returns A new schema with all properties marked as required
|
|
102
|
+
*/
|
|
103
|
+
function ensureAllPropertiesRequired(schema) {
|
|
104
|
+
if (typeof schema !== "object" || schema === null) return schema;
|
|
105
|
+
const result = { ...schema };
|
|
106
|
+
if (result.type === "object" && result.properties) {
|
|
107
|
+
result.required = Object.keys(result.properties);
|
|
108
|
+
result.properties = Object.fromEntries(Object.entries(result.properties).map(([key, value]) => [key, ensureAllPropertiesRequired(value)]));
|
|
109
|
+
}
|
|
110
|
+
if (result.items) {
|
|
111
|
+
if (Array.isArray(result.items)) result.items = result.items.map((item) => ensureAllPropertiesRequired(item));
|
|
112
|
+
else if (typeof result.items === "object") result.items = ensureAllPropertiesRequired(result.items);
|
|
113
|
+
}
|
|
114
|
+
if (result.additionalProperties && typeof result.additionalProperties === "object") result.additionalProperties = ensureAllPropertiesRequired(result.additionalProperties);
|
|
115
|
+
if (result.anyOf && Array.isArray(result.anyOf)) result.anyOf = result.anyOf.map((s) => ensureAllPropertiesRequired(s));
|
|
116
|
+
if (result.oneOf && Array.isArray(result.oneOf)) result.oneOf = result.oneOf.map((s) => ensureAllPropertiesRequired(s));
|
|
117
|
+
if (result.allOf && Array.isArray(result.allOf)) result.allOf = result.allOf.map((s) => ensureAllPropertiesRequired(s));
|
|
118
|
+
return result;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Prepare a JSON Schema for OpenAI strict mode by ensuring all object properties
|
|
122
|
+
* are required and all objects have additionalProperties: false.
|
|
123
|
+
*/
|
|
124
|
+
function prepareJsonSchemaForOpenAIStrictMode(schema) {
|
|
125
|
+
return ensureAdditionalPropertiesFalse(ensureAllPropertiesRequired(schema));
|
|
126
|
+
}
|
|
127
|
+
function ensureAdditionalPropertiesFalse(schema) {
|
|
128
|
+
if (typeof schema !== "object" || schema === null) return schema;
|
|
129
|
+
const result = { ...schema };
|
|
130
|
+
if (result.type === "object" || result.properties) result.additionalProperties = false;
|
|
131
|
+
if (result.properties) result.properties = Object.fromEntries(Object.entries(result.properties).map(([key, value]) => [key, ensureAdditionalPropertiesFalse(value)]));
|
|
132
|
+
if (result.items) {
|
|
133
|
+
if (Array.isArray(result.items)) result.items = result.items.map((item) => ensureAdditionalPropertiesFalse(item));
|
|
134
|
+
else if (typeof result.items === "object") result.items = ensureAdditionalPropertiesFalse(result.items);
|
|
135
|
+
}
|
|
136
|
+
if (result.anyOf && Array.isArray(result.anyOf)) result.anyOf = result.anyOf.map((s) => ensureAdditionalPropertiesFalse(s));
|
|
137
|
+
if (result.oneOf && Array.isArray(result.oneOf)) result.oneOf = result.oneOf.map((s) => ensureAdditionalPropertiesFalse(s));
|
|
138
|
+
if (result.allOf && Array.isArray(result.allOf)) result.allOf = result.allOf.map((s) => ensureAdditionalPropertiesFalse(s));
|
|
139
|
+
return result;
|
|
140
|
+
}
|
|
141
|
+
function zodToJsonSchema(zodSchema, target = "jsonSchema7", strategy = "relative") {
|
|
142
|
+
if (zodSchema?._zod) {
|
|
143
|
+
patchRecordSchemas(zodSchema);
|
|
144
|
+
return fixAnyOfNullable(zod_v4.z.toJSONSchema(zodSchema, {
|
|
145
|
+
unrepresentable: "any",
|
|
146
|
+
io: "input",
|
|
147
|
+
override: (ctx) => {
|
|
148
|
+
const def = ctx.zodSchema?._def || ctx.zodSchema?._zod?.def;
|
|
149
|
+
if (def && (def.typeName === "ZodDate" || def.type === "date")) {
|
|
150
|
+
ctx.jsonSchema.type = "string";
|
|
151
|
+
ctx.jsonSchema.format = "date-time";
|
|
152
|
+
}
|
|
153
|
+
if (def && (def.typeName === "ZodObject" || def.type === "object")) ctx.jsonSchema.additionalProperties = false;
|
|
154
|
+
}
|
|
155
|
+
}));
|
|
156
|
+
} else return (0, zod_to_json_schema.default)(zodSchema, {
|
|
157
|
+
$refStrategy: strategy,
|
|
158
|
+
target
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
//#endregion
|
|
162
|
+
exports.ensureAllPropertiesRequired = ensureAllPropertiesRequired;
|
|
163
|
+
exports.patchRecordSchemas = patchRecordSchemas;
|
|
164
|
+
exports.prepareJsonSchemaForOpenAIStrictMode = prepareJsonSchemaForOpenAIStrictMode;
|
|
165
|
+
exports.zodToJsonSchema = zodToJsonSchema;
|
|
2
166
|
|
|
3
|
-
var chunkFJGZKUBH_cjs = require('./chunk-FJGZKUBH.cjs');
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
Object.defineProperty(exports, "ensureAllPropertiesRequired", {
|
|
8
|
-
enumerable: true,
|
|
9
|
-
get: function () { return chunkFJGZKUBH_cjs.ensureAllPropertiesRequired; }
|
|
10
|
-
});
|
|
11
|
-
Object.defineProperty(exports, "patchRecordSchemas", {
|
|
12
|
-
enumerable: true,
|
|
13
|
-
get: function () { return chunkFJGZKUBH_cjs.patchRecordSchemas; }
|
|
14
|
-
});
|
|
15
|
-
Object.defineProperty(exports, "prepareJsonSchemaForOpenAIStrictMode", {
|
|
16
|
-
enumerable: true,
|
|
17
|
-
get: function () { return chunkFJGZKUBH_cjs.prepareJsonSchemaForOpenAIStrictMode; }
|
|
18
|
-
});
|
|
19
|
-
Object.defineProperty(exports, "zodToJsonSchema", {
|
|
20
|
-
enumerable: true,
|
|
21
|
-
get: function () { return chunkFJGZKUBH_cjs.zodToJsonSchema; }
|
|
22
|
-
});
|
|
23
|
-
//# sourceMappingURL=zod-to-json.cjs.map
|
|
24
167
|
//# sourceMappingURL=zod-to-json.cjs.map
|
package/dist/zod-to-json.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":[],"names":[],"mappings":"","file":"zod-to-json.cjs"}
|
|
1
|
+
{"version":3,"file":"zod-to-json.cjs","names":["zV4"],"sources":["../src/zod-to-json.ts"],"sourcesContent":["import type { JSONSchema7 } from 'json-schema';\nimport type { ZodSchema as ZodSchemaV3 } from 'zod/v3';\nimport { z as zV4 } from 'zod/v4';\nimport type { Targets } from 'zod-to-json-schema';\nimport zodToJsonSchemaOriginal from 'zod-to-json-schema';\n\n// Symbol to mark schemas as already patched (for idempotency)\nconst PATCHED = Symbol('__mastra_patched__');\n\n/**\n * Recursively patch Zod v4 record schemas that are missing valueType.\n * This fixes a bug in Zod v4 where z.record(valueSchema) doesn't set def.valueType.\n * The single-arg form should set valueType but instead only sets keyType.\n *\n * Idempotent — marks patched schemas with a Symbol so repeat calls no-op.\n *\n * @internal Exported so the Zod v4 standard-schema adapter can apply the\n * same patch before its native `toJSONSchema` call (the legacy `zodToJsonSchema`\n * entry already calls it; the `applyCompatLayer` path otherwise wouldn't).\n * Not part of the public API.\n */\nexport function patchRecordSchemas(schema: any): any {\n if (!schema || typeof schema !== 'object') return schema;\n\n // Skip if already patched (idempotency check)\n if ((schema as any)[PATCHED]) return schema;\n (schema as any)[PATCHED] = true;\n\n // Check the _zod.def location (v4 structure)\n const def = schema._zod?.def;\n\n // Fix record schemas with missing valueType\n if (def?.type === 'record' && def.keyType && !def.valueType) {\n // The bug: z.record(valueSchema) puts the value in keyType instead of valueType\n // Fix: move it to valueType and set keyType to string (the default)\n def.valueType = def.keyType;\n def.keyType = zV4.string();\n }\n\n // Recursively patch nested schemas\n if (!def) return schema;\n\n if (def.type === 'object' && def.shape) {\n const shape = typeof def.shape === 'function' ? def.shape() : def.shape;\n for (const key of Object.keys(shape)) {\n patchRecordSchemas(shape[key]);\n }\n }\n\n if (def.type === 'array' && def.element) {\n patchRecordSchemas(def.element);\n }\n\n if (def.type === 'union' && def.options) {\n def.options.forEach(patchRecordSchemas);\n }\n\n if (def.type === 'record') {\n if (def.keyType) patchRecordSchemas(def.keyType);\n if (def.valueType) patchRecordSchemas(def.valueType);\n }\n\n // Handle intersection types\n if (def.type === 'intersection') {\n if (def.left) patchRecordSchemas(def.left);\n if (def.right) patchRecordSchemas(def.right);\n }\n\n // Handle lazy types - patch the schema returned by the getter\n if (def.type === 'lazy') {\n // For lazy schemas, we need to patch the schema when it's accessed\n // Store the original getter and wrap it\n if (def.getter && typeof def.getter === 'function') {\n const originalGetter = def.getter;\n def.getter = function () {\n const innerSchema = originalGetter();\n if (innerSchema) {\n patchRecordSchemas(innerSchema);\n }\n return innerSchema;\n };\n }\n }\n\n // Handle wrapper types that have innerType\n // This covers: optional, nullable, default, catch, nullish, and any other wrappers\n if (def.innerType) {\n patchRecordSchemas(def.innerType);\n }\n\n return schema;\n}\n\n/**\n * Recursively fixes anyOf patterns that some providers (like OpenAI) don't accept.\n * Converts anyOf: [{type: X}, {type: \"null\"}] to type: [X, \"null\"]\n * Also fixes empty {} property schemas by converting to a union of primitive types.\n */\nfunction fixAnyOfNullable(schema: JSONSchema7): JSONSchema7 {\n if (typeof schema !== 'object' || schema === null) {\n return schema;\n }\n\n const result = { ...schema };\n\n // Fix anyOf pattern: [{type: X}, {type: \"null\"}] or [{type: \"null\"}, {type: X}]\n if (result.anyOf && Array.isArray(result.anyOf) && result.anyOf.length === 2) {\n const nullSchema = result.anyOf.find((s: any) => typeof s === 'object' && s !== null && s.type === 'null');\n const otherSchema = result.anyOf.find((s: any) => typeof s === 'object' && s !== null && s.type !== 'null');\n\n if (nullSchema && otherSchema && typeof otherSchema === 'object' && otherSchema.type) {\n // Convert anyOf to type array format\n // Normalize sibling fields (like properties/items) before returning\n const { anyOf, ...rest } = result;\n const fixedRest = fixAnyOfNullable(rest as JSONSchema7);\n const fixedOther = fixAnyOfNullable(otherSchema as JSONSchema7);\n return {\n ...fixedRest,\n ...fixedOther,\n type: (Array.isArray(fixedOther.type)\n ? [...fixedOther.type, 'null']\n : [fixedOther.type, 'null']) as JSONSchema7['type'],\n };\n }\n }\n\n // Fix empty property schemas {} - OpenAI requires a type key\n if (result.properties && typeof result.properties === 'object' && !Array.isArray(result.properties)) {\n result.properties = Object.fromEntries(\n Object.entries(result.properties).map(([key, value]) => {\n const propSchema = value as JSONSchema7;\n\n // If property is an empty object {}, convert to allow primitive types\n // Note: We exclude 'object' (requires additionalProperties) and 'array' (requires items) for OpenAI\n if (\n typeof propSchema === 'object' &&\n propSchema !== null &&\n !Array.isArray(propSchema) &&\n Object.keys(propSchema).length === 0\n ) {\n return [key, { type: ['string', 'number', 'boolean', 'null'] as JSONSchema7['type'] }];\n }\n\n // Recursively fix nested schemas\n return [key, fixAnyOfNullable(propSchema)];\n }),\n );\n }\n\n // Recursively fix items in arrays\n if (result.items) {\n if (Array.isArray(result.items)) {\n result.items = result.items.map(item => fixAnyOfNullable(item as JSONSchema7));\n } else {\n result.items = fixAnyOfNullable(result.items as JSONSchema7);\n }\n }\n\n // Recursively fix anyOf/oneOf/allOf schemas\n if (result.anyOf && Array.isArray(result.anyOf)) {\n result.anyOf = result.anyOf.map(s => fixAnyOfNullable(s as JSONSchema7));\n }\n if (result.oneOf && Array.isArray(result.oneOf)) {\n result.oneOf = result.oneOf.map(s => fixAnyOfNullable(s as JSONSchema7));\n }\n if (result.allOf && Array.isArray(result.allOf)) {\n result.allOf = result.allOf.map(s => fixAnyOfNullable(s as JSONSchema7));\n }\n\n return result;\n}\n\n/**\n * Recursively ensures all properties in an object schema are included in the `required` array.\n * OpenAI's strict structured output mode requires every key in `properties` to also appear in `required`.\n *\n * @param schema - The JSON Schema to process\n * @returns A new schema with all properties marked as required\n */\nexport function ensureAllPropertiesRequired(schema: JSONSchema7): JSONSchema7 {\n if (typeof schema !== 'object' || schema === null) {\n return schema;\n }\n\n const result = { ...schema };\n\n if (result.type === 'object' && result.properties) {\n result.required = Object.keys(result.properties);\n result.properties = Object.fromEntries(\n Object.entries(result.properties).map(([key, value]) => [key, ensureAllPropertiesRequired(value as JSONSchema7)]),\n );\n }\n\n if (result.items) {\n if (Array.isArray(result.items)) {\n result.items = result.items.map(item => ensureAllPropertiesRequired(item as JSONSchema7));\n } else if (typeof result.items === 'object') {\n result.items = ensureAllPropertiesRequired(result.items as JSONSchema7);\n }\n }\n\n if (result.additionalProperties && typeof result.additionalProperties === 'object') {\n result.additionalProperties = ensureAllPropertiesRequired(result.additionalProperties as JSONSchema7);\n }\n\n if (result.anyOf && Array.isArray(result.anyOf)) {\n result.anyOf = result.anyOf.map(s => ensureAllPropertiesRequired(s as JSONSchema7));\n }\n if (result.oneOf && Array.isArray(result.oneOf)) {\n result.oneOf = result.oneOf.map(s => ensureAllPropertiesRequired(s as JSONSchema7));\n }\n if (result.allOf && Array.isArray(result.allOf)) {\n result.allOf = result.allOf.map(s => ensureAllPropertiesRequired(s as JSONSchema7));\n }\n\n return result;\n}\n\n/**\n * Prepare a JSON Schema for OpenAI strict mode by ensuring all object properties\n * are required and all objects have additionalProperties: false.\n */\nexport function prepareJsonSchemaForOpenAIStrictMode(schema: JSONSchema7): JSONSchema7 {\n const withRequired = ensureAllPropertiesRequired(schema);\n return ensureAdditionalPropertiesFalse(withRequired);\n}\n\nfunction ensureAdditionalPropertiesFalse(schema: JSONSchema7): JSONSchema7 {\n if (typeof schema !== 'object' || schema === null) {\n return schema;\n }\n\n const result = { ...schema };\n\n if (result.type === 'object' || result.properties) {\n result.additionalProperties = false;\n }\n\n if (result.properties) {\n result.properties = Object.fromEntries(\n Object.entries(result.properties).map(([key, value]) => [\n key,\n ensureAdditionalPropertiesFalse(value as JSONSchema7),\n ]),\n );\n }\n\n if (result.items) {\n if (Array.isArray(result.items)) {\n result.items = result.items.map(item => ensureAdditionalPropertiesFalse(item as JSONSchema7));\n } else if (typeof result.items === 'object') {\n result.items = ensureAdditionalPropertiesFalse(result.items as JSONSchema7);\n }\n }\n\n if (result.anyOf && Array.isArray(result.anyOf)) {\n result.anyOf = result.anyOf.map(s => ensureAdditionalPropertiesFalse(s as JSONSchema7));\n }\n if (result.oneOf && Array.isArray(result.oneOf)) {\n result.oneOf = result.oneOf.map(s => ensureAdditionalPropertiesFalse(s as JSONSchema7));\n }\n if (result.allOf && Array.isArray(result.allOf)) {\n result.allOf = result.allOf.map(s => ensureAdditionalPropertiesFalse(s as JSONSchema7));\n }\n\n return result;\n}\n\n// export function zotToJsonSchema(zodSchema: ZodSchemaV3 | ZodSchemaV4, target: Targets = 'jsonSchema7', strategy: 'none' | 'seen' | 'root' | 'relative' = 'relative'): JSONSchema7 {\n// const target = 'draft-07' as StandardJSONSchemaV1.Target;\n// const standardSchema = toStandardSchema(zodSchema);\n// const jsonSchema = standardSchemaToJSONSchema(standardSchema, {\n// target,\n// });\n\n// traverse(jsonSchema, {\n// cb: {\n// pre: (schema, jsonPtr, rootSchema, parentJsonPtr, parentKeyword, parentSchema) => {\n// this.preProcessJSONNode(schema, parentSchema);\n// },\n// post: (schema, jsonPtr, rootSchema, parentJsonPtr, parentKeyword, parentSchema) => {\n// this.postProcessJSONNode(schema, parentSchema);\n// },\n// },\n// });\n\n// }\n\nexport function zodToJsonSchema(\n zodSchema: any,\n target: Targets = 'jsonSchema7',\n strategy: 'none' | 'seen' | 'root' | 'relative' = 'relative',\n): JSONSchema7 {\n // Route based on whether the schema is v4 (has _zod) or v3 (only has _def).\n // We use zV4.toJSONSchema (imported from 'zod/v4') for v4 schemas, since the\n // default 'zod' import may resolve to v3 depending on the environment.\n // Without this check, v3 schemas passed to v4's toJSONSchema would throw\n // \"Cannot read properties of undefined (reading 'def')\".\n if (zodSchema?._zod) {\n // Zod v4 path - patch record schemas before converting\n patchRecordSchemas(zodSchema);\n\n const jsonSchema = zV4.toJSONSchema(zodSchema, {\n unrepresentable: 'any',\n io: 'input',\n override: (ctx: any) => {\n // Handle both Zod v4 structures: _def directly or nested in _zod\n const def = ctx.zodSchema?._def || ctx.zodSchema?._zod?.def;\n // Check for date type using both possible property names\n if (def && (def.typeName === 'ZodDate' || def.type === 'date')) {\n ctx.jsonSchema.type = 'string';\n ctx.jsonSchema.format = 'date-time';\n }\n // Add additionalProperties: false for object types to match Zod v3 behavior\n // This is required for OpenAI strict mode function calling\n if (def && (def.typeName === 'ZodObject' || def.type === 'object')) {\n ctx.jsonSchema.additionalProperties = false;\n }\n },\n }) as JSONSchema7;\n\n // Fix anyOf patterns for nullable fields - required for OpenAI compatibility\n return fixAnyOfNullable(jsonSchema);\n } else {\n // Zod v3 path - use the original converter\n return zodToJsonSchemaOriginal(zodSchema as ZodSchemaV3, {\n $refStrategy: strategy,\n target,\n }) as JSONSchema7;\n }\n}\n"],"mappings":"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"}
|
package/dist/zod-to-json.js
CHANGED
|
@@ -1,3 +1,161 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import { z } from "zod/v4";
|
|
2
|
+
import zodToJsonSchemaOriginal from "zod-to-json-schema";
|
|
3
|
+
//#region src/zod-to-json.ts
|
|
4
|
+
const PATCHED = Symbol("__mastra_patched__");
|
|
5
|
+
/**
|
|
6
|
+
* Recursively patch Zod v4 record schemas that are missing valueType.
|
|
7
|
+
* This fixes a bug in Zod v4 where z.record(valueSchema) doesn't set def.valueType.
|
|
8
|
+
* The single-arg form should set valueType but instead only sets keyType.
|
|
9
|
+
*
|
|
10
|
+
* Idempotent — marks patched schemas with a Symbol so repeat calls no-op.
|
|
11
|
+
*
|
|
12
|
+
* @internal Exported so the Zod v4 standard-schema adapter can apply the
|
|
13
|
+
* same patch before its native `toJSONSchema` call (the legacy `zodToJsonSchema`
|
|
14
|
+
* entry already calls it; the `applyCompatLayer` path otherwise wouldn't).
|
|
15
|
+
* Not part of the public API.
|
|
16
|
+
*/
|
|
17
|
+
function patchRecordSchemas(schema) {
|
|
18
|
+
if (!schema || typeof schema !== "object") return schema;
|
|
19
|
+
if (schema[PATCHED]) return schema;
|
|
20
|
+
schema[PATCHED] = true;
|
|
21
|
+
const def = schema._zod?.def;
|
|
22
|
+
if (def?.type === "record" && def.keyType && !def.valueType) {
|
|
23
|
+
def.valueType = def.keyType;
|
|
24
|
+
def.keyType = z.string();
|
|
25
|
+
}
|
|
26
|
+
if (!def) return schema;
|
|
27
|
+
if (def.type === "object" && def.shape) {
|
|
28
|
+
const shape = typeof def.shape === "function" ? def.shape() : def.shape;
|
|
29
|
+
for (const key of Object.keys(shape)) patchRecordSchemas(shape[key]);
|
|
30
|
+
}
|
|
31
|
+
if (def.type === "array" && def.element) patchRecordSchemas(def.element);
|
|
32
|
+
if (def.type === "union" && def.options) def.options.forEach(patchRecordSchemas);
|
|
33
|
+
if (def.type === "record") {
|
|
34
|
+
if (def.keyType) patchRecordSchemas(def.keyType);
|
|
35
|
+
if (def.valueType) patchRecordSchemas(def.valueType);
|
|
36
|
+
}
|
|
37
|
+
if (def.type === "intersection") {
|
|
38
|
+
if (def.left) patchRecordSchemas(def.left);
|
|
39
|
+
if (def.right) patchRecordSchemas(def.right);
|
|
40
|
+
}
|
|
41
|
+
if (def.type === "lazy") {
|
|
42
|
+
if (def.getter && typeof def.getter === "function") {
|
|
43
|
+
const originalGetter = def.getter;
|
|
44
|
+
def.getter = function() {
|
|
45
|
+
const innerSchema = originalGetter();
|
|
46
|
+
if (innerSchema) patchRecordSchemas(innerSchema);
|
|
47
|
+
return innerSchema;
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
if (def.innerType) patchRecordSchemas(def.innerType);
|
|
52
|
+
return schema;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Recursively fixes anyOf patterns that some providers (like OpenAI) don't accept.
|
|
56
|
+
* Converts anyOf: [{type: X}, {type: "null"}] to type: [X, "null"]
|
|
57
|
+
* Also fixes empty {} property schemas by converting to a union of primitive types.
|
|
58
|
+
*/
|
|
59
|
+
function fixAnyOfNullable(schema) {
|
|
60
|
+
if (typeof schema !== "object" || schema === null) return schema;
|
|
61
|
+
const result = { ...schema };
|
|
62
|
+
if (result.anyOf && Array.isArray(result.anyOf) && result.anyOf.length === 2) {
|
|
63
|
+
const nullSchema = result.anyOf.find((s) => typeof s === "object" && s !== null && s.type === "null");
|
|
64
|
+
const otherSchema = result.anyOf.find((s) => typeof s === "object" && s !== null && s.type !== "null");
|
|
65
|
+
if (nullSchema && otherSchema && typeof otherSchema === "object" && otherSchema.type) {
|
|
66
|
+
const { anyOf, ...rest } = result;
|
|
67
|
+
const fixedRest = fixAnyOfNullable(rest);
|
|
68
|
+
const fixedOther = fixAnyOfNullable(otherSchema);
|
|
69
|
+
return {
|
|
70
|
+
...fixedRest,
|
|
71
|
+
...fixedOther,
|
|
72
|
+
type: Array.isArray(fixedOther.type) ? [...fixedOther.type, "null"] : [fixedOther.type, "null"]
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
if (result.properties && typeof result.properties === "object" && !Array.isArray(result.properties)) result.properties = Object.fromEntries(Object.entries(result.properties).map(([key, value]) => {
|
|
77
|
+
const propSchema = value;
|
|
78
|
+
if (typeof propSchema === "object" && propSchema !== null && !Array.isArray(propSchema) && Object.keys(propSchema).length === 0) return [key, { type: [
|
|
79
|
+
"string",
|
|
80
|
+
"number",
|
|
81
|
+
"boolean",
|
|
82
|
+
"null"
|
|
83
|
+
] }];
|
|
84
|
+
return [key, fixAnyOfNullable(propSchema)];
|
|
85
|
+
}));
|
|
86
|
+
if (result.items) if (Array.isArray(result.items)) result.items = result.items.map((item) => fixAnyOfNullable(item));
|
|
87
|
+
else result.items = fixAnyOfNullable(result.items);
|
|
88
|
+
if (result.anyOf && Array.isArray(result.anyOf)) result.anyOf = result.anyOf.map((s) => fixAnyOfNullable(s));
|
|
89
|
+
if (result.oneOf && Array.isArray(result.oneOf)) result.oneOf = result.oneOf.map((s) => fixAnyOfNullable(s));
|
|
90
|
+
if (result.allOf && Array.isArray(result.allOf)) result.allOf = result.allOf.map((s) => fixAnyOfNullable(s));
|
|
91
|
+
return result;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Recursively ensures all properties in an object schema are included in the `required` array.
|
|
95
|
+
* OpenAI's strict structured output mode requires every key in `properties` to also appear in `required`.
|
|
96
|
+
*
|
|
97
|
+
* @param schema - The JSON Schema to process
|
|
98
|
+
* @returns A new schema with all properties marked as required
|
|
99
|
+
*/
|
|
100
|
+
function ensureAllPropertiesRequired(schema) {
|
|
101
|
+
if (typeof schema !== "object" || schema === null) return schema;
|
|
102
|
+
const result = { ...schema };
|
|
103
|
+
if (result.type === "object" && result.properties) {
|
|
104
|
+
result.required = Object.keys(result.properties);
|
|
105
|
+
result.properties = Object.fromEntries(Object.entries(result.properties).map(([key, value]) => [key, ensureAllPropertiesRequired(value)]));
|
|
106
|
+
}
|
|
107
|
+
if (result.items) {
|
|
108
|
+
if (Array.isArray(result.items)) result.items = result.items.map((item) => ensureAllPropertiesRequired(item));
|
|
109
|
+
else if (typeof result.items === "object") result.items = ensureAllPropertiesRequired(result.items);
|
|
110
|
+
}
|
|
111
|
+
if (result.additionalProperties && typeof result.additionalProperties === "object") result.additionalProperties = ensureAllPropertiesRequired(result.additionalProperties);
|
|
112
|
+
if (result.anyOf && Array.isArray(result.anyOf)) result.anyOf = result.anyOf.map((s) => ensureAllPropertiesRequired(s));
|
|
113
|
+
if (result.oneOf && Array.isArray(result.oneOf)) result.oneOf = result.oneOf.map((s) => ensureAllPropertiesRequired(s));
|
|
114
|
+
if (result.allOf && Array.isArray(result.allOf)) result.allOf = result.allOf.map((s) => ensureAllPropertiesRequired(s));
|
|
115
|
+
return result;
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Prepare a JSON Schema for OpenAI strict mode by ensuring all object properties
|
|
119
|
+
* are required and all objects have additionalProperties: false.
|
|
120
|
+
*/
|
|
121
|
+
function prepareJsonSchemaForOpenAIStrictMode(schema) {
|
|
122
|
+
return ensureAdditionalPropertiesFalse(ensureAllPropertiesRequired(schema));
|
|
123
|
+
}
|
|
124
|
+
function ensureAdditionalPropertiesFalse(schema) {
|
|
125
|
+
if (typeof schema !== "object" || schema === null) return schema;
|
|
126
|
+
const result = { ...schema };
|
|
127
|
+
if (result.type === "object" || result.properties) result.additionalProperties = false;
|
|
128
|
+
if (result.properties) result.properties = Object.fromEntries(Object.entries(result.properties).map(([key, value]) => [key, ensureAdditionalPropertiesFalse(value)]));
|
|
129
|
+
if (result.items) {
|
|
130
|
+
if (Array.isArray(result.items)) result.items = result.items.map((item) => ensureAdditionalPropertiesFalse(item));
|
|
131
|
+
else if (typeof result.items === "object") result.items = ensureAdditionalPropertiesFalse(result.items);
|
|
132
|
+
}
|
|
133
|
+
if (result.anyOf && Array.isArray(result.anyOf)) result.anyOf = result.anyOf.map((s) => ensureAdditionalPropertiesFalse(s));
|
|
134
|
+
if (result.oneOf && Array.isArray(result.oneOf)) result.oneOf = result.oneOf.map((s) => ensureAdditionalPropertiesFalse(s));
|
|
135
|
+
if (result.allOf && Array.isArray(result.allOf)) result.allOf = result.allOf.map((s) => ensureAdditionalPropertiesFalse(s));
|
|
136
|
+
return result;
|
|
137
|
+
}
|
|
138
|
+
function zodToJsonSchema(zodSchema, target = "jsonSchema7", strategy = "relative") {
|
|
139
|
+
if (zodSchema?._zod) {
|
|
140
|
+
patchRecordSchemas(zodSchema);
|
|
141
|
+
return fixAnyOfNullable(z.toJSONSchema(zodSchema, {
|
|
142
|
+
unrepresentable: "any",
|
|
143
|
+
io: "input",
|
|
144
|
+
override: (ctx) => {
|
|
145
|
+
const def = ctx.zodSchema?._def || ctx.zodSchema?._zod?.def;
|
|
146
|
+
if (def && (def.typeName === "ZodDate" || def.type === "date")) {
|
|
147
|
+
ctx.jsonSchema.type = "string";
|
|
148
|
+
ctx.jsonSchema.format = "date-time";
|
|
149
|
+
}
|
|
150
|
+
if (def && (def.typeName === "ZodObject" || def.type === "object")) ctx.jsonSchema.additionalProperties = false;
|
|
151
|
+
}
|
|
152
|
+
}));
|
|
153
|
+
} else return zodToJsonSchemaOriginal(zodSchema, {
|
|
154
|
+
$refStrategy: strategy,
|
|
155
|
+
target
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
//#endregion
|
|
159
|
+
export { ensureAllPropertiesRequired, patchRecordSchemas, prepareJsonSchemaForOpenAIStrictMode, zodToJsonSchema };
|
|
160
|
+
|
|
3
161
|
//# sourceMappingURL=zod-to-json.js.map
|
package/dist/zod-to-json.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":[],"names":[],"mappings":"","file":"zod-to-json.js"}
|
|
1
|
+
{"version":3,"file":"zod-to-json.js","names":["zV4"],"sources":["../src/zod-to-json.ts"],"sourcesContent":["import type { JSONSchema7 } from 'json-schema';\nimport type { ZodSchema as ZodSchemaV3 } from 'zod/v3';\nimport { z as zV4 } from 'zod/v4';\nimport type { Targets } from 'zod-to-json-schema';\nimport zodToJsonSchemaOriginal from 'zod-to-json-schema';\n\n// Symbol to mark schemas as already patched (for idempotency)\nconst PATCHED = Symbol('__mastra_patched__');\n\n/**\n * Recursively patch Zod v4 record schemas that are missing valueType.\n * This fixes a bug in Zod v4 where z.record(valueSchema) doesn't set def.valueType.\n * The single-arg form should set valueType but instead only sets keyType.\n *\n * Idempotent — marks patched schemas with a Symbol so repeat calls no-op.\n *\n * @internal Exported so the Zod v4 standard-schema adapter can apply the\n * same patch before its native `toJSONSchema` call (the legacy `zodToJsonSchema`\n * entry already calls it; the `applyCompatLayer` path otherwise wouldn't).\n * Not part of the public API.\n */\nexport function patchRecordSchemas(schema: any): any {\n if (!schema || typeof schema !== 'object') return schema;\n\n // Skip if already patched (idempotency check)\n if ((schema as any)[PATCHED]) return schema;\n (schema as any)[PATCHED] = true;\n\n // Check the _zod.def location (v4 structure)\n const def = schema._zod?.def;\n\n // Fix record schemas with missing valueType\n if (def?.type === 'record' && def.keyType && !def.valueType) {\n // The bug: z.record(valueSchema) puts the value in keyType instead of valueType\n // Fix: move it to valueType and set keyType to string (the default)\n def.valueType = def.keyType;\n def.keyType = zV4.string();\n }\n\n // Recursively patch nested schemas\n if (!def) return schema;\n\n if (def.type === 'object' && def.shape) {\n const shape = typeof def.shape === 'function' ? def.shape() : def.shape;\n for (const key of Object.keys(shape)) {\n patchRecordSchemas(shape[key]);\n }\n }\n\n if (def.type === 'array' && def.element) {\n patchRecordSchemas(def.element);\n }\n\n if (def.type === 'union' && def.options) {\n def.options.forEach(patchRecordSchemas);\n }\n\n if (def.type === 'record') {\n if (def.keyType) patchRecordSchemas(def.keyType);\n if (def.valueType) patchRecordSchemas(def.valueType);\n }\n\n // Handle intersection types\n if (def.type === 'intersection') {\n if (def.left) patchRecordSchemas(def.left);\n if (def.right) patchRecordSchemas(def.right);\n }\n\n // Handle lazy types - patch the schema returned by the getter\n if (def.type === 'lazy') {\n // For lazy schemas, we need to patch the schema when it's accessed\n // Store the original getter and wrap it\n if (def.getter && typeof def.getter === 'function') {\n const originalGetter = def.getter;\n def.getter = function () {\n const innerSchema = originalGetter();\n if (innerSchema) {\n patchRecordSchemas(innerSchema);\n }\n return innerSchema;\n };\n }\n }\n\n // Handle wrapper types that have innerType\n // This covers: optional, nullable, default, catch, nullish, and any other wrappers\n if (def.innerType) {\n patchRecordSchemas(def.innerType);\n }\n\n return schema;\n}\n\n/**\n * Recursively fixes anyOf patterns that some providers (like OpenAI) don't accept.\n * Converts anyOf: [{type: X}, {type: \"null\"}] to type: [X, \"null\"]\n * Also fixes empty {} property schemas by converting to a union of primitive types.\n */\nfunction fixAnyOfNullable(schema: JSONSchema7): JSONSchema7 {\n if (typeof schema !== 'object' || schema === null) {\n return schema;\n }\n\n const result = { ...schema };\n\n // Fix anyOf pattern: [{type: X}, {type: \"null\"}] or [{type: \"null\"}, {type: X}]\n if (result.anyOf && Array.isArray(result.anyOf) && result.anyOf.length === 2) {\n const nullSchema = result.anyOf.find((s: any) => typeof s === 'object' && s !== null && s.type === 'null');\n const otherSchema = result.anyOf.find((s: any) => typeof s === 'object' && s !== null && s.type !== 'null');\n\n if (nullSchema && otherSchema && typeof otherSchema === 'object' && otherSchema.type) {\n // Convert anyOf to type array format\n // Normalize sibling fields (like properties/items) before returning\n const { anyOf, ...rest } = result;\n const fixedRest = fixAnyOfNullable(rest as JSONSchema7);\n const fixedOther = fixAnyOfNullable(otherSchema as JSONSchema7);\n return {\n ...fixedRest,\n ...fixedOther,\n type: (Array.isArray(fixedOther.type)\n ? [...fixedOther.type, 'null']\n : [fixedOther.type, 'null']) as JSONSchema7['type'],\n };\n }\n }\n\n // Fix empty property schemas {} - OpenAI requires a type key\n if (result.properties && typeof result.properties === 'object' && !Array.isArray(result.properties)) {\n result.properties = Object.fromEntries(\n Object.entries(result.properties).map(([key, value]) => {\n const propSchema = value as JSONSchema7;\n\n // If property is an empty object {}, convert to allow primitive types\n // Note: We exclude 'object' (requires additionalProperties) and 'array' (requires items) for OpenAI\n if (\n typeof propSchema === 'object' &&\n propSchema !== null &&\n !Array.isArray(propSchema) &&\n Object.keys(propSchema).length === 0\n ) {\n return [key, { type: ['string', 'number', 'boolean', 'null'] as JSONSchema7['type'] }];\n }\n\n // Recursively fix nested schemas\n return [key, fixAnyOfNullable(propSchema)];\n }),\n );\n }\n\n // Recursively fix items in arrays\n if (result.items) {\n if (Array.isArray(result.items)) {\n result.items = result.items.map(item => fixAnyOfNullable(item as JSONSchema7));\n } else {\n result.items = fixAnyOfNullable(result.items as JSONSchema7);\n }\n }\n\n // Recursively fix anyOf/oneOf/allOf schemas\n if (result.anyOf && Array.isArray(result.anyOf)) {\n result.anyOf = result.anyOf.map(s => fixAnyOfNullable(s as JSONSchema7));\n }\n if (result.oneOf && Array.isArray(result.oneOf)) {\n result.oneOf = result.oneOf.map(s => fixAnyOfNullable(s as JSONSchema7));\n }\n if (result.allOf && Array.isArray(result.allOf)) {\n result.allOf = result.allOf.map(s => fixAnyOfNullable(s as JSONSchema7));\n }\n\n return result;\n}\n\n/**\n * Recursively ensures all properties in an object schema are included in the `required` array.\n * OpenAI's strict structured output mode requires every key in `properties` to also appear in `required`.\n *\n * @param schema - The JSON Schema to process\n * @returns A new schema with all properties marked as required\n */\nexport function ensureAllPropertiesRequired(schema: JSONSchema7): JSONSchema7 {\n if (typeof schema !== 'object' || schema === null) {\n return schema;\n }\n\n const result = { ...schema };\n\n if (result.type === 'object' && result.properties) {\n result.required = Object.keys(result.properties);\n result.properties = Object.fromEntries(\n Object.entries(result.properties).map(([key, value]) => [key, ensureAllPropertiesRequired(value as JSONSchema7)]),\n );\n }\n\n if (result.items) {\n if (Array.isArray(result.items)) {\n result.items = result.items.map(item => ensureAllPropertiesRequired(item as JSONSchema7));\n } else if (typeof result.items === 'object') {\n result.items = ensureAllPropertiesRequired(result.items as JSONSchema7);\n }\n }\n\n if (result.additionalProperties && typeof result.additionalProperties === 'object') {\n result.additionalProperties = ensureAllPropertiesRequired(result.additionalProperties as JSONSchema7);\n }\n\n if (result.anyOf && Array.isArray(result.anyOf)) {\n result.anyOf = result.anyOf.map(s => ensureAllPropertiesRequired(s as JSONSchema7));\n }\n if (result.oneOf && Array.isArray(result.oneOf)) {\n result.oneOf = result.oneOf.map(s => ensureAllPropertiesRequired(s as JSONSchema7));\n }\n if (result.allOf && Array.isArray(result.allOf)) {\n result.allOf = result.allOf.map(s => ensureAllPropertiesRequired(s as JSONSchema7));\n }\n\n return result;\n}\n\n/**\n * Prepare a JSON Schema for OpenAI strict mode by ensuring all object properties\n * are required and all objects have additionalProperties: false.\n */\nexport function prepareJsonSchemaForOpenAIStrictMode(schema: JSONSchema7): JSONSchema7 {\n const withRequired = ensureAllPropertiesRequired(schema);\n return ensureAdditionalPropertiesFalse(withRequired);\n}\n\nfunction ensureAdditionalPropertiesFalse(schema: JSONSchema7): JSONSchema7 {\n if (typeof schema !== 'object' || schema === null) {\n return schema;\n }\n\n const result = { ...schema };\n\n if (result.type === 'object' || result.properties) {\n result.additionalProperties = false;\n }\n\n if (result.properties) {\n result.properties = Object.fromEntries(\n Object.entries(result.properties).map(([key, value]) => [\n key,\n ensureAdditionalPropertiesFalse(value as JSONSchema7),\n ]),\n );\n }\n\n if (result.items) {\n if (Array.isArray(result.items)) {\n result.items = result.items.map(item => ensureAdditionalPropertiesFalse(item as JSONSchema7));\n } else if (typeof result.items === 'object') {\n result.items = ensureAdditionalPropertiesFalse(result.items as JSONSchema7);\n }\n }\n\n if (result.anyOf && Array.isArray(result.anyOf)) {\n result.anyOf = result.anyOf.map(s => ensureAdditionalPropertiesFalse(s as JSONSchema7));\n }\n if (result.oneOf && Array.isArray(result.oneOf)) {\n result.oneOf = result.oneOf.map(s => ensureAdditionalPropertiesFalse(s as JSONSchema7));\n }\n if (result.allOf && Array.isArray(result.allOf)) {\n result.allOf = result.allOf.map(s => ensureAdditionalPropertiesFalse(s as JSONSchema7));\n }\n\n return result;\n}\n\n// export function zotToJsonSchema(zodSchema: ZodSchemaV3 | ZodSchemaV4, target: Targets = 'jsonSchema7', strategy: 'none' | 'seen' | 'root' | 'relative' = 'relative'): JSONSchema7 {\n// const target = 'draft-07' as StandardJSONSchemaV1.Target;\n// const standardSchema = toStandardSchema(zodSchema);\n// const jsonSchema = standardSchemaToJSONSchema(standardSchema, {\n// target,\n// });\n\n// traverse(jsonSchema, {\n// cb: {\n// pre: (schema, jsonPtr, rootSchema, parentJsonPtr, parentKeyword, parentSchema) => {\n// this.preProcessJSONNode(schema, parentSchema);\n// },\n// post: (schema, jsonPtr, rootSchema, parentJsonPtr, parentKeyword, parentSchema) => {\n// this.postProcessJSONNode(schema, parentSchema);\n// },\n// },\n// });\n\n// }\n\nexport function zodToJsonSchema(\n zodSchema: any,\n target: Targets = 'jsonSchema7',\n strategy: 'none' | 'seen' | 'root' | 'relative' = 'relative',\n): JSONSchema7 {\n // Route based on whether the schema is v4 (has _zod) or v3 (only has _def).\n // We use zV4.toJSONSchema (imported from 'zod/v4') for v4 schemas, since the\n // default 'zod' import may resolve to v3 depending on the environment.\n // Without this check, v3 schemas passed to v4's toJSONSchema would throw\n // \"Cannot read properties of undefined (reading 'def')\".\n if (zodSchema?._zod) {\n // Zod v4 path - patch record schemas before converting\n patchRecordSchemas(zodSchema);\n\n const jsonSchema = zV4.toJSONSchema(zodSchema, {\n unrepresentable: 'any',\n io: 'input',\n override: (ctx: any) => {\n // Handle both Zod v4 structures: _def directly or nested in _zod\n const def = ctx.zodSchema?._def || ctx.zodSchema?._zod?.def;\n // Check for date type using both possible property names\n if (def && (def.typeName === 'ZodDate' || def.type === 'date')) {\n ctx.jsonSchema.type = 'string';\n ctx.jsonSchema.format = 'date-time';\n }\n // Add additionalProperties: false for object types to match Zod v3 behavior\n // This is required for OpenAI strict mode function calling\n if (def && (def.typeName === 'ZodObject' || def.type === 'object')) {\n ctx.jsonSchema.additionalProperties = false;\n }\n },\n }) as JSONSchema7;\n\n // Fix anyOf patterns for nullable fields - required for OpenAI compatibility\n return fixAnyOfNullable(jsonSchema);\n } else {\n // Zod v3 path - use the original converter\n return zodToJsonSchemaOriginal(zodSchema as ZodSchemaV3, {\n $refStrategy: strategy,\n target,\n }) as JSONSchema7;\n }\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mastra/schema-compat",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.5-alpha.0",
|
|
4
4
|
"description": "Tool schema compatibility layer for Mastra.ai",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -101,30 +101,30 @@
|
|
|
101
101
|
"zod": "^3.25.0 || ^4.0.0"
|
|
102
102
|
},
|
|
103
103
|
"devDependencies": {
|
|
104
|
-
"@ai-sdk/anthropic": "^3.0.
|
|
105
|
-
"@ai-sdk/google": "^3.0.
|
|
106
|
-
"@ai-sdk/openai": "^3.0.
|
|
104
|
+
"@ai-sdk/anthropic": "^3.0.98",
|
|
105
|
+
"@ai-sdk/google": "^3.0.95",
|
|
106
|
+
"@ai-sdk/openai": "^3.0.86",
|
|
107
107
|
"@standard-schema/spec": "^1.1.0",
|
|
108
108
|
"@types/json-schema": "^7.0.15",
|
|
109
|
-
"@types/node": "22.
|
|
109
|
+
"@types/node": "22.20.1",
|
|
110
110
|
"@vitest/coverage-v8": "4.1.10",
|
|
111
111
|
"@vitest/ui": "4.1.10",
|
|
112
112
|
"ajv": "^8.20.0",
|
|
113
113
|
"arktype": "^2.2.0",
|
|
114
|
-
"eslint": "^10.
|
|
114
|
+
"eslint": "^10.7.0",
|
|
115
115
|
"json-schema-traverse": "^1.0.0",
|
|
116
|
-
"
|
|
116
|
+
"tsdown": "0.22.9",
|
|
117
117
|
"typescript": "^6.0.3",
|
|
118
118
|
"vitest": "4.1.10",
|
|
119
119
|
"zod": "^4.4.3",
|
|
120
120
|
"zod-v3": "npm:zod@^3.25.76",
|
|
121
|
-
"@internal/ai-sdk-v4": "0.0.
|
|
122
|
-
"@internal/
|
|
123
|
-
"@internal/ai-v6": "0.0.
|
|
124
|
-
"@internal/
|
|
125
|
-
"@internal/
|
|
126
|
-
"@internal/
|
|
127
|
-
"@internal/
|
|
121
|
+
"@internal/ai-sdk-v4": "0.0.67",
|
|
122
|
+
"@internal/lint": "0.0.120",
|
|
123
|
+
"@internal/ai-v6": "0.0.67",
|
|
124
|
+
"@internal/llm-recorder": "0.0.56",
|
|
125
|
+
"@internal/ai-sdk-v5": "0.0.67",
|
|
126
|
+
"@internal/test-utils": "0.0.56",
|
|
127
|
+
"@internal/types-builder": "0.0.95"
|
|
128
128
|
},
|
|
129
129
|
"homepage": "https://mastra.ai",
|
|
130
130
|
"repository": {
|
|
@@ -139,9 +139,10 @@
|
|
|
139
139
|
"node": ">=22.13.0"
|
|
140
140
|
},
|
|
141
141
|
"scripts": {
|
|
142
|
-
"build": "
|
|
143
|
-
"build:watch": "
|
|
142
|
+
"build": "tsdown --silent --config tsdown.config.ts",
|
|
143
|
+
"build:watch": "tsdown --watch --silent --config tsdown.config.ts",
|
|
144
144
|
"test": "vitest run",
|
|
145
|
-
"lint": "eslint ."
|
|
145
|
+
"lint": "oxlint . && eslint .",
|
|
146
|
+
"lint:fix": "oxlint --fix . && eslint --fix ."
|
|
146
147
|
}
|
|
147
148
|
}
|