1
0
Fork 0
mirror of https://codeberg.org/MarkusThielker/next-ory.git synced 2025-04-10 11:58:41 +00:00

NORY-47: refactor dynamic zodSchema generation

This commit is contained in:
Markus Thielker 2024-12-28 23:41:05 +01:00
parent bc30c83dcb
commit 9170454ae2
No known key found for this signature in database

View file

@ -1,22 +1,39 @@
'use client';
import { z } from 'zod'; import { z } from 'zod';
// interface for a list of properties export const literalSchema = z.union([z.string(), z.number(), z.boolean(), z.null()]);
type Literal = z.infer<typeof literalSchema>;
type Json = Literal | { [key: string]: Json } | Json[];
export const jsonSchema: z.ZodType<Json> = z.lazy(() =>
z.union([literalSchema, z.array(jsonSchema), z.record(jsonSchema)]),
);
// Interface for a list of properties
export interface KratosSchemaProperties { export interface KratosSchemaProperties {
[key: string]: { [key: string]: {
type: string; type: 'string' | 'number' | 'integer' | 'boolean' | 'object' | 'array' | 'null';
format?: string; format?: string;
title: string; title: string;
minLength?: number; minLength?: number;
maxLength?: number; maxLength?: number;
minimum?: number; minimum?: number;
maximum?: number; maximum?: number;
required?: boolean; required: boolean;
description?: string; description?: string;
properties?: KratosSchemaProperties properties?: KratosSchemaProperties;
enum?: any[];
pattern?: string;
items?: KratosSchemaProperties;
oneOf?: KratosSchemaProperties[];
anyOf?: KratosSchemaProperties[];
allOf?: KratosSchemaProperties[];
dependencies?: { [key: string]: string[] | KratosSchemaProperties };
additionalProperties?: boolean;
}; };
} }
// interface for the kratos identity schema // Interface for the Kratos identity schema
export interface KratosSchema { export interface KratosSchema {
$id: string; $id: string;
$schema: string; $schema: string;
@ -32,53 +49,50 @@ export interface KratosSchema {
}; };
} }
export function generateZodSchema(properties: KratosSchemaProperties) { export function kratosSchemaToZod(schema: KratosSchema): z.ZodObject<any> {
const zodSchema = z.object({}); // Function to recursively convert Kratos properties to Zod types
function convertProperties(properties: KratosSchemaProperties): { [key: string]: z.ZodTypeAny } {
const zodProps: { [key: string]: z.ZodTypeAny } = {};
for (const key in properties) {
const prop = properties[key];
for (const [key, value] of Object.entries(properties)) { let zodType;
let zodType; switch (prop.type) {
switch (value.type) { case 'string':
case 'string': zodType = z.string();
zodType = z.string(); if (prop.format === 'email') zodType = zodType.email();
if (value.format === 'email') { if (prop.minLength) zodType = zodType.min(prop.minLength);
zodType = z.string().email(); if (prop.maxLength) zodType = zodType.max(prop.maxLength);
} if (prop.pattern) zodType = zodType.regex(new RegExp(prop.pattern));
if (value.minLength) { break;
zodType = zodType.min(value.minLength); case 'number':
} case 'integer':
if (value.maxLength) { zodType = z.number();
zodType = zodType.max(value.maxLength); if (prop.minimum) zodType = zodType.min(prop.minimum);
} if (prop.maximum) zodType = zodType.max(prop.maximum);
break; break;
case 'integer': case 'boolean':
case 'number': zodType = z.boolean();
zodType = z.number(); break;
if (value.minimum) { case 'object':
zodType = zodType.min(value.minimum); zodType = z.object(convertProperties(prop.properties || {}));
} break;
if (value.maximum) { case 'array':
zodType = zodType.max(value.maximum); zodType = z.array(
} prop.items ? kratosSchemaToZod({ properties: { item: prop.items } } as any).shape.item : z.any(),
break; );
case 'boolean': break;
zodType = z.boolean(); default:
break; zodType = z.any(); // Fallback to any for unknown types
case 'object': }
const schemaCopy = structuredClone(schema);
schemaCopy.properties.traits.properties = value.properties!; if (prop.enum) zodType = zodType.refine((val) => prop.enum!.includes(val));
zodType = generateZodSchema(schemaCopy);
break; zodProps[key] = zodType;
default:
zodType = z.any();
} }
return zodProps;
if (!value.required) {
zodType = zodType.nullable();
}
zodSchema.extend({ [key]: zodType });
} }
return zodSchema; return z.object(convertProperties(schema.properties.traits.properties));
} }