@techery/zod-to-vertex-schema
Version:
Convert Zod schemas to Vertex AI/Gemini compatible schemas
159 lines • 5.62 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.vertexSchemaToZod = vertexSchemaToZod;
const zod_1 = require("zod");
const vertex_schema_1 = require("./vertex-schema");
function vertexSchemaToZod(schema) {
// 1) If `anyOf` is present, treat it as a union of possibilities.
if (schema.anyOf && schema.anyOf.length > 0) {
const unionVariants = schema.anyOf.map((sub) => vertexSchemaToZod(sub));
// Attach description or other metadata on the union if needed
let unionSchema = zod_1.z.union(unionVariants);
if (schema.description) {
unionSchema = unionSchema.describe(schema.description);
}
return applyNullable(unionSchema, schema);
}
// 2) Otherwise, dispatch on the schema.type
switch (schema.type) {
case vertex_schema_1.SchemaType.STRING:
return makeStringZod(schema);
case vertex_schema_1.SchemaType.NUMBER:
case vertex_schema_1.SchemaType.INTEGER:
return makeNumberZod(schema);
case vertex_schema_1.SchemaType.BOOLEAN:
return makeBooleanZod(schema);
case vertex_schema_1.SchemaType.ARRAY:
return makeArrayZod(schema);
case vertex_schema_1.SchemaType.OBJECT:
return makeObjectZod(schema);
default:
// If no type is given or it's an unknown type, fall back to an "unknown" Zod type.
// Or you could throw an error, depending on your needs.
throw new Error(`Unsupported or missing schema.type: ${schema.type}`);
}
}
/**
* STRING handling:
* - If `enum` is present with more than one value, use z.enum.
* - If `enum` is present with exactly one value, use z.literal.
* - Otherwise plain z.string(), plus `.datetime()` if format==='date-time', etc.
*/
function makeStringZod(schema) {
const { format, description, enum: maybeEnum } = schema;
if (maybeEnum && maybeEnum.length > 1) {
// multiple enumerated string values => z.enum([...])
let out = zod_1.z.enum(maybeEnum);
if (description)
out = out.describe(description);
return applyNullable(out, schema);
}
else if (maybeEnum && maybeEnum.length === 1) {
// single enumerated value => z.literal(...)
let out = zod_1.z.literal(maybeEnum[0]);
if (description)
out = out.describe(description);
return applyNullable(out, schema);
}
// Otherwise, a basic string
let strZod = zod_1.z.string();
if (format === 'date-time') {
// Zod v3 has `z.string().datetime()`
strZod = strZod.datetime();
}
// If you want to handle `date` or other custom formats:
// - you might do a refine, or skip it, depending on your needs
if (description) {
strZod = strZod.describe(description);
}
return applyNullable(strZod, schema);
}
/**
* NUMBER or INTEGER handling:
* - Use z.number(), plus .int() if type=INTEGER
* - Apply .min(schema.minimum), .max(schema.maximum)
*/
function makeNumberZod(schema) {
let numZod = zod_1.z.number();
if (schema.type === vertex_schema_1.SchemaType.INTEGER) {
numZod = numZod.int();
}
if (typeof schema.minimum === 'number') {
numZod = numZod.min(schema.minimum);
}
if (typeof schema.maximum === 'number') {
numZod = numZod.max(schema.maximum);
}
if (schema.description) {
numZod = numZod.describe(schema.description);
}
return applyNullable(numZod, schema);
}
/**
* BOOLEAN handling:
* - Just z.boolean(), with optional `.describe(...)`
*/
function makeBooleanZod(schema) {
let boolZod = zod_1.z.boolean();
if (schema.description) {
boolZod = boolZod.describe(schema.description);
}
return applyNullable(boolZod, schema);
}
/**
* ARRAY handling:
* - Must have `items`
* - Use z.array(itemsZod)
* - Apply .min(schema.minItems), .max(schema.maxItems)
*/
function makeArrayZod(schema) {
if (!schema.items) {
throw new Error(`ARRAY type schema must have 'items'`);
}
const elementZod = vertexSchemaToZod(schema.items);
let arrZod = zod_1.z.array(elementZod);
if (typeof schema.minItems === 'number') {
arrZod = arrZod.min(schema.minItems);
}
if (typeof schema.maxItems === 'number') {
arrZod = arrZod.max(schema.maxItems);
}
if (schema.description) {
arrZod = arrZod.describe(schema.description);
}
return applyNullable(arrZod, schema);
}
/**
* OBJECT handling:
* - Each key in `properties` => shape entry
* - If key not in `required`, mark as .optional()
*/
function makeObjectZod(schema) {
const { properties = {}, required = [], description } = schema;
const shape = {};
for (const key of Object.keys(properties)) {
const propertySchema = properties[key];
let zodField = vertexSchemaToZod(propertySchema);
if (!required.includes(key)) {
zodField = zodField.optional();
}
shape[key] = zodField;
}
let objectZod = zod_1.z.object(shape);
if (description) {
objectZod = objectZod.describe(description);
}
return applyNullable(objectZod, schema);
}
/**
* If schema.nullable = true, attach .nullable().
* (This does NOT handle the difference between "nullable" vs. "optional";
* typically you'll handle "optional" if the property is NOT in `required`.)
*/
function applyNullable(zodSchema, schema) {
if (schema.nullable) {
return zodSchema.nullable();
}
return zodSchema;
}
//# sourceMappingURL=vertex-schema-to-zod.js.map