UNPKG

instantdb-react-ui

Version:

Customizable react components for InstantDB (forms/lists/etc.)

168 lines (167 loc) 5.69 kB
import { z } from 'zod'; import { generateZodEntitySchema } from '../utils/utils'; /** * Maps InstantDB types to Zod types. * Used when a instant field does not have a zod validator. Handles required/optional fields. */ function getDefaultSchema(attr) { let baseSchema; switch (attr.valueType) { case 'string': baseSchema = z.string(); break; case 'number': baseSchema = z.number(); break; case 'boolean': baseSchema = z.boolean(); break; case 'date': baseSchema = z.number(); // instantdb uses number for dates break; case 'json': baseSchema = z.any(); break; default: baseSchema = z.string(); } return attr.required ? baseSchema : baseSchema.optional(); } /** The default value map used by getDefaultValueByType */ const DEFAULT_VALUES_BY_TYPE = { boolean: false, string: '', number: 0, date: () => Date.now(), }; /** * Creates default values for useForm's initialValues parameter * Used when an instant field does not have a zod default */ function getDefaultValueByType(valueType) { const defaultValue = DEFAULT_VALUES_BY_TYPE[valueType]; // Use empty string for for unknown types if (defaultValue === undefined) return ''; return typeof defaultValue === 'function' ? defaultValue() : defaultValue; } export function createIDBEntityZodSchema(schema, entityName) { const entity = schema.entities[entityName]; const entityAttrs = entity.attrs; const schemaObj = {}; const defaults = {}; // Handle attributes Object.entries(entityAttrs).forEach(([key, attr]) => { const attrSchema = attr.zodSchema; let fieldSchema; if (attrSchema) { try { fieldSchema = attrSchema; // Extract default if it exists from Zod schema if ('_def' in fieldSchema && 'defaultValue' in fieldSchema._def) { const defaultValue = fieldSchema._def.defaultValue; defaults[key] = typeof defaultValue === 'function' ? defaultValue() : defaultValue; } else { defaults[key] = getDefaultValueByType(attr.valueType); } } catch (e) { fieldSchema = getDefaultSchema(attr); defaults[key] = getDefaultValueByType(attr.valueType); } } else { fieldSchema = getDefaultSchema(attr); defaults[key] = getDefaultValueByType(attr.valueType); } schemaObj[key] = fieldSchema; }); // Handle links Object.entries(entity.links).forEach(([key, link]) => { const linkSchema = link.zodSchema; if (link.cardinality === 'one') { defaults[key] = null; if (linkSchema) { schemaObj[key] = linkSchema; } else { schemaObj[key] = generateZodEntitySchema().nullable(); } } else { defaults[key] = []; if (linkSchema) { schemaObj[key] = linkSchema; } else { schemaObj[key] = z.array(generateZodEntitySchema().nullable()); } } }); return { zodSchema: z.object(schemaObj), defaults: defaults, }; } /** Creates a zod schema and default values for useForm's initialValues parameter */ export function internalCreateIDBEntityZodSchema(entity, links) { const entityAttrs = entity.attrs; const schemaObj = {}; const defaults = {}; Object.entries(entityAttrs).forEach(([key, attr]) => { const attrSchema = attr.zodSchema; let fieldSchema; if (attrSchema) { try { fieldSchema = attrSchema; // Extract default if it exists from Zod schema if ('_def' in fieldSchema && 'defaultValue' in fieldSchema._def) { const defaultValue = fieldSchema._def.defaultValue; defaults[key] = typeof defaultValue === 'function' ? defaultValue() : defaultValue; } else { // If no Zod default, use valueType default defaults[key] = getDefaultValueByType(attr.valueType); } } catch (e) { // fallback to default schema fieldSchema = getDefaultSchema(attr.valueType); defaults[key] = getDefaultValueByType(attr.valueType); } } else { // fallback to default schema fieldSchema = getDefaultSchema(attr.valueType); defaults[key] = getDefaultValueByType(attr.valueType); } schemaObj[key] = fieldSchema; }); // Add zod schema for links Object.entries(links).forEach(([key, link]) => { const linkSchema = link.zodSchema; if (link.cardinality === 'one') { defaults[key] = null; if (linkSchema) { schemaObj[key] = linkSchema; } else { schemaObj[key] = generateZodEntitySchema().nullable(); } } else { defaults[key] = []; if (linkSchema) { schemaObj[key] = linkSchema; } else { schemaObj[key] = z.array(generateZodEntitySchema().nullable()); } } }); return { zodSchema: z.object(schemaObj), defaults, }; }