@mastra/schema-compat 0.10.7 → 0.11.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/.turbo/turbo-build.log +1 -1
- package/CHANGELOG.md +40 -0
- package/README.md +0 -4
- package/dist/chunk-FTKGHMGD.js +27 -0
- package/dist/chunk-FTKGHMGD.js.map +1 -0
- package/dist/chunk-LNR4XKDU.cjs +33 -0
- package/dist/chunk-LNR4XKDU.cjs.map +1 -0
- package/dist/index.cjs +846 -84
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +10 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +845 -85
- package/dist/index.js.map +1 -1
- package/dist/provider-compats/anthropic.d.ts +6 -4
- package/dist/provider-compats/anthropic.d.ts.map +1 -1
- package/dist/provider-compats/deepseek.d.ts +6 -4
- package/dist/provider-compats/deepseek.d.ts.map +1 -1
- package/dist/provider-compats/google.d.ts +6 -4
- package/dist/provider-compats/google.d.ts.map +1 -1
- package/dist/provider-compats/meta.d.ts +6 -4
- package/dist/provider-compats/meta.d.ts.map +1 -1
- package/dist/provider-compats/openai-reasoning.d.ts +6 -4
- package/dist/provider-compats/openai-reasoning.d.ts.map +1 -1
- package/dist/provider-compats/openai.d.ts +6 -4
- package/dist/provider-compats/openai.d.ts.map +1 -1
- package/dist/schema-compatibility-v3.d.ts +319 -0
- package/dist/schema-compatibility-v3.d.ts.map +1 -0
- package/dist/schema-compatibility-v4.d.ts +310 -0
- package/dist/schema-compatibility-v4.d.ts.map +1 -0
- package/dist/schema-compatibility.d.ts +80 -134
- package/dist/schema-compatibility.d.ts.map +1 -1
- package/dist/types.d.ts +6 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/utils-test-suite.d.ts +2 -0
- package/dist/utils-test-suite.d.ts.map +1 -0
- package/dist/utils.d.ts +17 -5
- package/dist/utils.d.ts.map +1 -1
- package/dist/zod-to-json.cjs +12 -0
- package/dist/zod-to-json.cjs.map +1 -0
- package/dist/zod-to-json.d.ts +6 -0
- package/dist/zod-to-json.d.ts.map +1 -0
- package/dist/zod-to-json.js +3 -0
- package/dist/zod-to-json.js.map +1 -0
- package/dist/zodTypes.d.ts +21 -0
- package/dist/zodTypes.d.ts.map +1 -0
- package/package.json +16 -6
- package/src/index.ts +4 -3
- package/src/provider-compats/anthropic.ts +29 -11
- package/src/provider-compats/deepseek.ts +14 -9
- package/src/provider-compats/google.ts +18 -32
- package/src/provider-compats/meta.ts +15 -10
- package/src/provider-compats/openai-reasoning.ts +18 -24
- package/src/provider-compats/openai.ts +22 -12
- package/src/schema-compatibility-v3.ts +664 -0
- package/src/schema-compatibility-v4.test.ts +476 -0
- package/src/schema-compatibility-v4.ts +706 -0
- package/src/schema-compatibility.test.ts +12 -28
- package/src/schema-compatibility.ts +263 -383
- package/src/types.ts +5 -0
- package/src/utils-test-suite.ts +467 -0
- package/src/utils-v3.test.ts +9 -0
- package/src/utils-v4.test.ts +9 -0
- package/src/utils.ts +30 -24
- package/src/zod-to-json.ts +27 -0
- package/src/zodTypes.ts +56 -0
- package/tsup.config.ts +8 -3
- package/src/utils.test.ts +0 -460
package/src/zodTypes.ts
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import type { z as zV3 } from 'zod/v3';
|
|
2
|
+
import type { z as zV4 } from 'zod/v4';
|
|
3
|
+
|
|
4
|
+
export function isOptional<Z extends typeof zV3>(z: Z): (v: any) => v is zV3.ZodOptional<any>;
|
|
5
|
+
export function isOptional<Z extends typeof zV4>(z: Z): (v: any) => v is zV4.ZodOptional<any>;
|
|
6
|
+
export function isOptional<Z extends typeof zV3 | typeof zV4>(z: Z) {
|
|
7
|
+
return (v: any): v is Z['ZodOptional'] => v instanceof z['ZodOptional'];
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export function isObj<Z extends typeof zV3>(z: Z): (v: any) => v is zV3.ZodObject<any>;
|
|
11
|
+
export function isObj<Z extends typeof zV4>(z: Z): (v: any) => v is zV4.ZodObject;
|
|
12
|
+
export function isObj<Z extends typeof zV3 | typeof zV4>(z: Z) {
|
|
13
|
+
return (v: any): v is Z['ZodObject'] => v instanceof z['ZodObject'];
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function isNull<Z extends typeof zV3>(z: Z): (v: any) => v is zV3.ZodNull;
|
|
17
|
+
export function isNull<Z extends typeof zV4>(z: Z): (v: any) => v is zV4.ZodNull;
|
|
18
|
+
export function isNull<Z extends typeof zV3 | typeof zV4>(z: Z) {
|
|
19
|
+
return (v: any): v is Z['ZodNull'] => v instanceof z['ZodNull'];
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function isArr<Z extends typeof zV3>(z: Z): (v: any) => v is zV3.ZodArray<any>;
|
|
23
|
+
export function isArr<Z extends typeof zV4>(z: Z): (v: any) => v is zV4.ZodArray;
|
|
24
|
+
export function isArr<Z extends typeof zV3 | typeof zV4>(z: Z) {
|
|
25
|
+
return (v: any): v is Z['ZodArray'] => v instanceof z['ZodArray'];
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function isUnion<Z extends typeof zV3>(z: Z): (v: any) => v is zV3.ZodUnion<any>;
|
|
29
|
+
export function isUnion<Z extends typeof zV4>(z: Z): (v: any) => v is zV4.ZodUnion;
|
|
30
|
+
export function isUnion<Z extends typeof zV3 | typeof zV4>(z: Z) {
|
|
31
|
+
return (v: any): v is Z['ZodUnion'] => v instanceof z['ZodUnion'];
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function isString<Z extends typeof zV3>(z: Z): (v: any) => v is zV3.ZodString;
|
|
35
|
+
export function isString<Z extends typeof zV4>(z: Z): (v: any) => v is zV4.ZodString;
|
|
36
|
+
export function isString<Z extends typeof zV3 | typeof zV4>(z: Z) {
|
|
37
|
+
return (v: any): v is Z['ZodString'] => v instanceof z['ZodString'];
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export function isNumber<Z extends typeof zV3>(z: Z): (v: any) => v is zV3.ZodNumber;
|
|
41
|
+
export function isNumber<Z extends typeof zV4>(z: Z): (v: any) => v is zV4.ZodNumber;
|
|
42
|
+
export function isNumber<Z extends typeof zV3 | typeof zV4>(z: Z) {
|
|
43
|
+
return (v: any): v is Z['ZodNumber'] => v instanceof z['ZodNumber'];
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export function isDate<Z extends typeof zV3>(z: Z): (v: any) => v is zV3.ZodDate;
|
|
47
|
+
export function isDate<Z extends typeof zV4>(z: Z): (v: any) => v is zV4.ZodDate;
|
|
48
|
+
export function isDate<Z extends typeof zV3 | typeof zV4>(z: Z) {
|
|
49
|
+
return (v: any): v is Z['ZodDate'] => v instanceof z['ZodDate'];
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export function isDefault<Z extends typeof zV3>(z: Z): (v: any) => v is zV3.ZodDefault<any>;
|
|
53
|
+
export function isDefault<Z extends typeof zV4>(z: Z): (v: any) => v is zV4.ZodDefault;
|
|
54
|
+
export function isDefault<Z extends typeof zV3 | typeof zV4>(z: Z) {
|
|
55
|
+
return (v: any): v is Z['ZodDefault'] => v instanceof z['ZodDefault'];
|
|
56
|
+
}
|
package/tsup.config.ts
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { spawn } from 'child_process';
|
|
2
|
+
import { promisify } from 'util';
|
|
2
3
|
import { defineConfig } from 'tsup';
|
|
3
4
|
|
|
5
|
+
const exec = promisify(spawn);
|
|
6
|
+
|
|
4
7
|
export default defineConfig({
|
|
5
|
-
entry: ['src/index.ts'],
|
|
8
|
+
entry: ['src/index.ts', 'src/zod-to-json.ts'],
|
|
6
9
|
format: ['esm', 'cjs'],
|
|
7
10
|
clean: true,
|
|
8
11
|
dts: false,
|
|
@@ -12,6 +15,8 @@ export default defineConfig({
|
|
|
12
15
|
},
|
|
13
16
|
sourcemap: true,
|
|
14
17
|
onSuccess: async () => {
|
|
15
|
-
await
|
|
18
|
+
await exec('pnpm', ['tsc', '-p', 'tsconfig.build.json'], {
|
|
19
|
+
stdio: 'inherit',
|
|
20
|
+
});
|
|
16
21
|
},
|
|
17
22
|
});
|
package/src/utils.test.ts
DELETED
|
@@ -1,460 +0,0 @@
|
|
|
1
|
-
import { jsonSchema } from 'ai';
|
|
2
|
-
import type { Schema } from 'ai';
|
|
3
|
-
import { MockLanguageModelV1 } from 'ai/test';
|
|
4
|
-
import { describe, it, expect, beforeEach, vi } from 'vitest';
|
|
5
|
-
import { z } from 'zod';
|
|
6
|
-
import type { ModelInformation } from './schema-compatibility';
|
|
7
|
-
import { SchemaCompatLayer } from './schema-compatibility';
|
|
8
|
-
import { convertZodSchemaToAISDKSchema, convertSchemaToZod, applyCompatLayer } from './utils';
|
|
9
|
-
|
|
10
|
-
const mockModel = new MockLanguageModelV1({
|
|
11
|
-
modelId: 'test-model',
|
|
12
|
-
defaultObjectGenerationMode: 'json',
|
|
13
|
-
});
|
|
14
|
-
|
|
15
|
-
class MockSchemaCompatibility extends SchemaCompatLayer {
|
|
16
|
-
constructor(
|
|
17
|
-
model: ModelInformation,
|
|
18
|
-
private shouldApplyValue: boolean = true,
|
|
19
|
-
) {
|
|
20
|
-
super(model);
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
shouldApply(): boolean {
|
|
24
|
-
return this.shouldApplyValue;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
getSchemaTarget() {
|
|
28
|
-
return 'jsonSchema7' as const;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
processZodType(value: z.ZodTypeAny): any {
|
|
32
|
-
if (value._def.typeName === 'ZodString') {
|
|
33
|
-
return z.string().describe('processed string');
|
|
34
|
-
}
|
|
35
|
-
if (value instanceof z.ZodObject) {
|
|
36
|
-
return this.defaultZodObjectHandler(value);
|
|
37
|
-
}
|
|
38
|
-
if (value instanceof z.ZodArray) {
|
|
39
|
-
return this.defaultZodArrayHandler(value);
|
|
40
|
-
}
|
|
41
|
-
return value;
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
describe('Builder Functions', () => {
|
|
46
|
-
describe('convertZodSchemaToAISDKSchema', () => {
|
|
47
|
-
it('should convert simple Zod schema to AI SDK schema', () => {
|
|
48
|
-
const zodSchema = z.object({
|
|
49
|
-
name: z.string(),
|
|
50
|
-
age: z.number(),
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
const result = convertZodSchemaToAISDKSchema(zodSchema);
|
|
54
|
-
|
|
55
|
-
expect(result).toHaveProperty('jsonSchema');
|
|
56
|
-
expect(result).toHaveProperty('validate');
|
|
57
|
-
expect(typeof result.validate).toBe('function');
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
it('should create schema with validation function', () => {
|
|
61
|
-
const zodSchema = z.object({
|
|
62
|
-
email: z.string().email(),
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
const result = convertZodSchemaToAISDKSchema(zodSchema);
|
|
66
|
-
|
|
67
|
-
expect(result.validate).toBeDefined();
|
|
68
|
-
|
|
69
|
-
const validResult = result.validate!({ email: 'test@example.com' });
|
|
70
|
-
expect(validResult.success).toBe(true);
|
|
71
|
-
if (validResult.success) {
|
|
72
|
-
expect(validResult.value).toEqual({ email: 'test@example.com' });
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
const invalidResult = result.validate!({ email: 'invalid-email' });
|
|
76
|
-
expect(invalidResult.success).toBe(false);
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
it('should handle custom targets', () => {
|
|
80
|
-
const zodSchema = z.object({
|
|
81
|
-
name: z.string(),
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
const result = convertZodSchemaToAISDKSchema(zodSchema, 'openApi3');
|
|
85
|
-
|
|
86
|
-
expect(result).toHaveProperty('jsonSchema');
|
|
87
|
-
expect(result).toHaveProperty('validate');
|
|
88
|
-
});
|
|
89
|
-
|
|
90
|
-
it('should handle complex nested schemas', () => {
|
|
91
|
-
const zodSchema = z.object({
|
|
92
|
-
user: z.object({
|
|
93
|
-
name: z.string(),
|
|
94
|
-
preferences: z.object({
|
|
95
|
-
theme: z.enum(['light', 'dark']),
|
|
96
|
-
notifications: z.boolean(),
|
|
97
|
-
}),
|
|
98
|
-
}),
|
|
99
|
-
tags: z.array(z.string()),
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
const result = convertZodSchemaToAISDKSchema(zodSchema);
|
|
103
|
-
|
|
104
|
-
expect(result).toHaveProperty('jsonSchema');
|
|
105
|
-
expect(result.jsonSchema).toHaveProperty('properties');
|
|
106
|
-
});
|
|
107
|
-
|
|
108
|
-
it('should handle array schemas', () => {
|
|
109
|
-
const zodSchema = z.array(z.string());
|
|
110
|
-
const result = convertZodSchemaToAISDKSchema(zodSchema);
|
|
111
|
-
expect(result.jsonSchema.type).toBe('array');
|
|
112
|
-
expect((result.jsonSchema.items as any)?.type).toBe('string');
|
|
113
|
-
});
|
|
114
|
-
});
|
|
115
|
-
|
|
116
|
-
describe('convertSchemaToZod', () => {
|
|
117
|
-
it('should return Zod schema unchanged', () => {
|
|
118
|
-
const zodSchema = z.object({
|
|
119
|
-
name: z.string(),
|
|
120
|
-
});
|
|
121
|
-
|
|
122
|
-
const result = convertSchemaToZod(zodSchema);
|
|
123
|
-
|
|
124
|
-
expect(result).toBe(zodSchema);
|
|
125
|
-
});
|
|
126
|
-
|
|
127
|
-
it('should convert AI SDK schema to Zod', () => {
|
|
128
|
-
const aiSchema: Schema = jsonSchema({
|
|
129
|
-
type: 'object',
|
|
130
|
-
properties: {
|
|
131
|
-
name: { type: 'string' },
|
|
132
|
-
age: { type: 'number' },
|
|
133
|
-
},
|
|
134
|
-
required: ['name'],
|
|
135
|
-
});
|
|
136
|
-
|
|
137
|
-
const result = convertSchemaToZod(aiSchema);
|
|
138
|
-
|
|
139
|
-
expect(result).toBeInstanceOf(z.ZodType);
|
|
140
|
-
const parseResult = result.safeParse({ name: 'John', age: 30 });
|
|
141
|
-
expect(parseResult.success).toBe(true);
|
|
142
|
-
});
|
|
143
|
-
|
|
144
|
-
it('should handle complex JSON schema conversion', () => {
|
|
145
|
-
const complexSchema: Schema = jsonSchema({
|
|
146
|
-
type: 'object',
|
|
147
|
-
properties: {
|
|
148
|
-
user: {
|
|
149
|
-
type: 'object',
|
|
150
|
-
properties: {
|
|
151
|
-
name: { type: 'string' },
|
|
152
|
-
email: { type: 'string', format: 'email' },
|
|
153
|
-
},
|
|
154
|
-
required: ['name'],
|
|
155
|
-
},
|
|
156
|
-
tags: {
|
|
157
|
-
type: 'array',
|
|
158
|
-
items: { type: 'string' },
|
|
159
|
-
},
|
|
160
|
-
},
|
|
161
|
-
required: ['user'],
|
|
162
|
-
});
|
|
163
|
-
|
|
164
|
-
const result = convertSchemaToZod(complexSchema);
|
|
165
|
-
|
|
166
|
-
expect(result).toBeInstanceOf(z.ZodType);
|
|
167
|
-
|
|
168
|
-
const validData = {
|
|
169
|
-
user: { name: 'John', email: 'john@example.com' },
|
|
170
|
-
tags: ['tag1', 'tag2'],
|
|
171
|
-
};
|
|
172
|
-
const parseResult = result.safeParse(validData);
|
|
173
|
-
expect(parseResult.success).toBe(true);
|
|
174
|
-
});
|
|
175
|
-
|
|
176
|
-
it('should convert AI SDK array schema to Zod', () => {
|
|
177
|
-
const aiSchema: Schema = jsonSchema({
|
|
178
|
-
type: 'array',
|
|
179
|
-
items: {
|
|
180
|
-
type: 'string',
|
|
181
|
-
},
|
|
182
|
-
});
|
|
183
|
-
|
|
184
|
-
const result = convertSchemaToZod(aiSchema);
|
|
185
|
-
|
|
186
|
-
expect(result).toBeInstanceOf(z.ZodArray);
|
|
187
|
-
expect((result as z.ZodArray<any>).element).toBeInstanceOf(z.ZodString);
|
|
188
|
-
});
|
|
189
|
-
});
|
|
190
|
-
|
|
191
|
-
describe('applyCompatLayer', () => {
|
|
192
|
-
let mockCompatibility: MockSchemaCompatibility;
|
|
193
|
-
|
|
194
|
-
beforeEach(() => {
|
|
195
|
-
mockCompatibility = new MockSchemaCompatibility({
|
|
196
|
-
modelId: mockModel.modelId,
|
|
197
|
-
supportsStructuredOutputs: mockModel.supportsStructuredOutputs ?? false,
|
|
198
|
-
provider: mockModel.provider,
|
|
199
|
-
});
|
|
200
|
-
});
|
|
201
|
-
|
|
202
|
-
it('should process Zod object schema with compatibility', () => {
|
|
203
|
-
const zodSchema = z.object({
|
|
204
|
-
name: z.string(),
|
|
205
|
-
age: z.number(),
|
|
206
|
-
});
|
|
207
|
-
|
|
208
|
-
const result = applyCompatLayer({
|
|
209
|
-
schema: zodSchema,
|
|
210
|
-
compatLayers: [mockCompatibility],
|
|
211
|
-
mode: 'aiSdkSchema',
|
|
212
|
-
});
|
|
213
|
-
|
|
214
|
-
expect(result).toHaveProperty('jsonSchema');
|
|
215
|
-
expect(result).toHaveProperty('validate');
|
|
216
|
-
});
|
|
217
|
-
|
|
218
|
-
it('should process AI SDK schema with compatibility', () => {
|
|
219
|
-
const aiSchema: Schema = jsonSchema({
|
|
220
|
-
type: 'object',
|
|
221
|
-
properties: {
|
|
222
|
-
name: { type: 'string' },
|
|
223
|
-
},
|
|
224
|
-
});
|
|
225
|
-
|
|
226
|
-
const result = applyCompatLayer({
|
|
227
|
-
schema: aiSchema,
|
|
228
|
-
compatLayers: [mockCompatibility],
|
|
229
|
-
mode: 'jsonSchema',
|
|
230
|
-
});
|
|
231
|
-
|
|
232
|
-
expect(typeof result).toBe('object');
|
|
233
|
-
expect(result).toHaveProperty('type');
|
|
234
|
-
});
|
|
235
|
-
|
|
236
|
-
it('should handle object schema with string property', () => {
|
|
237
|
-
const stringSchema = z.object({ value: z.string() });
|
|
238
|
-
|
|
239
|
-
const result = applyCompatLayer({
|
|
240
|
-
schema: stringSchema,
|
|
241
|
-
compatLayers: [mockCompatibility],
|
|
242
|
-
mode: 'aiSdkSchema',
|
|
243
|
-
});
|
|
244
|
-
|
|
245
|
-
expect(result).toHaveProperty('jsonSchema');
|
|
246
|
-
expect(result).toHaveProperty('validate');
|
|
247
|
-
});
|
|
248
|
-
|
|
249
|
-
it('should return processed schema when compatibility applies', () => {
|
|
250
|
-
const zodSchema = z.object({
|
|
251
|
-
name: z.string(),
|
|
252
|
-
});
|
|
253
|
-
|
|
254
|
-
const result = applyCompatLayer({
|
|
255
|
-
schema: zodSchema,
|
|
256
|
-
compatLayers: [mockCompatibility],
|
|
257
|
-
mode: 'aiSdkSchema',
|
|
258
|
-
});
|
|
259
|
-
|
|
260
|
-
expect(result).toHaveProperty('jsonSchema');
|
|
261
|
-
expect(result).toHaveProperty('validate');
|
|
262
|
-
});
|
|
263
|
-
|
|
264
|
-
it('should return fallback when no compatibility applies', () => {
|
|
265
|
-
const nonApplyingCompatibility = new MockSchemaCompatibility(
|
|
266
|
-
{
|
|
267
|
-
modelId: mockModel.modelId,
|
|
268
|
-
supportsStructuredOutputs: mockModel.supportsStructuredOutputs ?? false,
|
|
269
|
-
provider: mockModel.provider,
|
|
270
|
-
},
|
|
271
|
-
false,
|
|
272
|
-
);
|
|
273
|
-
const zodSchema = z.object({
|
|
274
|
-
name: z.string(),
|
|
275
|
-
});
|
|
276
|
-
|
|
277
|
-
const result = applyCompatLayer({
|
|
278
|
-
schema: zodSchema,
|
|
279
|
-
compatLayers: [nonApplyingCompatibility],
|
|
280
|
-
mode: 'aiSdkSchema',
|
|
281
|
-
});
|
|
282
|
-
|
|
283
|
-
expect(result).toHaveProperty('jsonSchema');
|
|
284
|
-
expect(result).toHaveProperty('validate');
|
|
285
|
-
});
|
|
286
|
-
|
|
287
|
-
it('should handle jsonSchema mode', () => {
|
|
288
|
-
const zodSchema = z.object({
|
|
289
|
-
name: z.string(),
|
|
290
|
-
});
|
|
291
|
-
|
|
292
|
-
const result = applyCompatLayer({
|
|
293
|
-
schema: zodSchema,
|
|
294
|
-
compatLayers: [mockCompatibility],
|
|
295
|
-
mode: 'jsonSchema',
|
|
296
|
-
});
|
|
297
|
-
|
|
298
|
-
expect(typeof result).toBe('object');
|
|
299
|
-
expect(result).toHaveProperty('type');
|
|
300
|
-
});
|
|
301
|
-
|
|
302
|
-
it('should handle empty compatLayers array', () => {
|
|
303
|
-
const zodSchema = z.object({
|
|
304
|
-
name: z.string(),
|
|
305
|
-
});
|
|
306
|
-
|
|
307
|
-
const result = applyCompatLayer({
|
|
308
|
-
schema: zodSchema,
|
|
309
|
-
compatLayers: [],
|
|
310
|
-
mode: 'aiSdkSchema',
|
|
311
|
-
});
|
|
312
|
-
|
|
313
|
-
expect(result).toHaveProperty('jsonSchema');
|
|
314
|
-
expect(result).toHaveProperty('validate');
|
|
315
|
-
});
|
|
316
|
-
|
|
317
|
-
it('should handle complex schema with multiple compatLayers', () => {
|
|
318
|
-
const compat1 = new MockSchemaCompatibility(
|
|
319
|
-
{
|
|
320
|
-
modelId: mockModel.modelId,
|
|
321
|
-
supportsStructuredOutputs: mockModel.supportsStructuredOutputs ?? true,
|
|
322
|
-
provider: mockModel.provider,
|
|
323
|
-
},
|
|
324
|
-
false,
|
|
325
|
-
);
|
|
326
|
-
const compat2 = new MockSchemaCompatibility(
|
|
327
|
-
{
|
|
328
|
-
modelId: mockModel.modelId,
|
|
329
|
-
supportsStructuredOutputs: mockModel.supportsStructuredOutputs ?? false,
|
|
330
|
-
provider: mockModel.provider,
|
|
331
|
-
},
|
|
332
|
-
true,
|
|
333
|
-
);
|
|
334
|
-
|
|
335
|
-
vi.spyOn(compat1, 'processZodType');
|
|
336
|
-
vi.spyOn(compat2, 'processZodType');
|
|
337
|
-
|
|
338
|
-
const zodSchema = z.object({
|
|
339
|
-
name: z.string(),
|
|
340
|
-
settings: z.object({
|
|
341
|
-
theme: z.string(),
|
|
342
|
-
notifications: z.boolean(),
|
|
343
|
-
}),
|
|
344
|
-
});
|
|
345
|
-
|
|
346
|
-
const result = applyCompatLayer({
|
|
347
|
-
schema: zodSchema,
|
|
348
|
-
compatLayers: [compat1, compat2],
|
|
349
|
-
mode: 'aiSdkSchema',
|
|
350
|
-
});
|
|
351
|
-
|
|
352
|
-
expect(result).toHaveProperty('jsonSchema');
|
|
353
|
-
expect(result).toHaveProperty('validate');
|
|
354
|
-
expect(compat1.processZodType).not.toHaveBeenCalled();
|
|
355
|
-
expect(compat2.processZodType).toHaveBeenCalled();
|
|
356
|
-
});
|
|
357
|
-
|
|
358
|
-
it('should process Zod array schema with compatibility', () => {
|
|
359
|
-
const arraySchema = z.array(z.string());
|
|
360
|
-
|
|
361
|
-
const result = applyCompatLayer({
|
|
362
|
-
schema: arraySchema,
|
|
363
|
-
compatLayers: [mockCompatibility],
|
|
364
|
-
mode: 'aiSdkSchema',
|
|
365
|
-
});
|
|
366
|
-
|
|
367
|
-
expect(result.jsonSchema.type).toBe('array');
|
|
368
|
-
if (
|
|
369
|
-
result.jsonSchema.items &&
|
|
370
|
-
!Array.isArray(result.jsonSchema.items) &&
|
|
371
|
-
typeof result.jsonSchema.items === 'object'
|
|
372
|
-
) {
|
|
373
|
-
expect(result.jsonSchema.items.type).toBe('string');
|
|
374
|
-
expect(result.jsonSchema.items.description).toBe('processed string');
|
|
375
|
-
} else {
|
|
376
|
-
expect.fail('items is not a single schema object');
|
|
377
|
-
}
|
|
378
|
-
});
|
|
379
|
-
|
|
380
|
-
it('should process AI SDK array schema with compatibility', () => {
|
|
381
|
-
const aiSchema: Schema = jsonSchema({
|
|
382
|
-
type: 'array',
|
|
383
|
-
items: {
|
|
384
|
-
type: 'string',
|
|
385
|
-
},
|
|
386
|
-
});
|
|
387
|
-
|
|
388
|
-
const result = applyCompatLayer({
|
|
389
|
-
schema: aiSchema,
|
|
390
|
-
compatLayers: [mockCompatibility],
|
|
391
|
-
mode: 'aiSdkSchema',
|
|
392
|
-
});
|
|
393
|
-
|
|
394
|
-
expect(result.jsonSchema.type).toBe('array');
|
|
395
|
-
if (
|
|
396
|
-
result.jsonSchema.items &&
|
|
397
|
-
!Array.isArray(result.jsonSchema.items) &&
|
|
398
|
-
typeof result.jsonSchema.items === 'object'
|
|
399
|
-
) {
|
|
400
|
-
expect(result.jsonSchema.items.type).toBe('string');
|
|
401
|
-
expect(result.jsonSchema.items.description).toBe('processed string');
|
|
402
|
-
} else {
|
|
403
|
-
expect.fail('items is not a single schema object');
|
|
404
|
-
}
|
|
405
|
-
});
|
|
406
|
-
|
|
407
|
-
it('should handle a complex array of objects schema', () => {
|
|
408
|
-
const complexArraySchema = z.array(
|
|
409
|
-
z.object({
|
|
410
|
-
id: z.string(),
|
|
411
|
-
user: z.object({
|
|
412
|
-
name: z.string(),
|
|
413
|
-
}),
|
|
414
|
-
}),
|
|
415
|
-
);
|
|
416
|
-
|
|
417
|
-
const result = applyCompatLayer({
|
|
418
|
-
schema: complexArraySchema,
|
|
419
|
-
compatLayers: [mockCompatibility],
|
|
420
|
-
mode: 'aiSdkSchema',
|
|
421
|
-
});
|
|
422
|
-
|
|
423
|
-
const { jsonSchema } = result;
|
|
424
|
-
expect(jsonSchema.type).toBe('array');
|
|
425
|
-
|
|
426
|
-
const items = jsonSchema.items;
|
|
427
|
-
if (items && !Array.isArray(items) && typeof items === 'object') {
|
|
428
|
-
expect(items.type).toBe('object');
|
|
429
|
-
expect(items.properties).toHaveProperty('id');
|
|
430
|
-
expect(items.properties).toHaveProperty('user');
|
|
431
|
-
|
|
432
|
-
const idProperty = items.properties!.id as any;
|
|
433
|
-
expect(idProperty.description).toBe('processed string');
|
|
434
|
-
|
|
435
|
-
const userProperty = items.properties!.user as any;
|
|
436
|
-
expect(userProperty.type).toBe('object');
|
|
437
|
-
expect(userProperty.properties).toHaveProperty('name');
|
|
438
|
-
|
|
439
|
-
const nameProperty = userProperty.properties.name as any;
|
|
440
|
-
expect(nameProperty.description).toBe('processed string');
|
|
441
|
-
} else {
|
|
442
|
-
expect.fail('items is not a single schema object');
|
|
443
|
-
}
|
|
444
|
-
});
|
|
445
|
-
|
|
446
|
-
it('should handle a scalar zod schema', () => {
|
|
447
|
-
const scalarSchema = z.string().email();
|
|
448
|
-
|
|
449
|
-
const result = applyCompatLayer({
|
|
450
|
-
schema: scalarSchema,
|
|
451
|
-
compatLayers: [mockCompatibility],
|
|
452
|
-
mode: 'aiSdkSchema',
|
|
453
|
-
});
|
|
454
|
-
|
|
455
|
-
const { jsonSchema } = result;
|
|
456
|
-
expect(jsonSchema.type).toBe('string');
|
|
457
|
-
expect(jsonSchema.description).toBe('processed string');
|
|
458
|
-
});
|
|
459
|
-
});
|
|
460
|
-
});
|