import { EvalCallback, Schema, SchemaContextModel, VevProps } from '@vev/utils'; import { isFunction } from 'lodash'; import { useEffect, useState } from 'react'; import { safeEvalFunction } from './safe-eval'; import { useSchemaContext } from './silke-schema-context'; export function isEvalCallback(value: any): value is EvalCallback { return value && value.type === '__eval__'; } type InitialValue = { [key: string]: any }; export async function getSchemaInitialValue( schema: Schema, context: Omit, ): Promise { const res: InitialValue = {}; for (const field of schema) { if (field.name && field.type) { if (field.type === 'object') { res[field.name] = await getSchemaInitialValue(field.fields, context); continue; } if (field.initialValue) { if (isEvalCallback(field.initialValue)) { res[field.name] = await safeEvalFunction(field.initialValue.value, context); } else if (isFunction(field.initialValue)) { res[field.name] = (await field.initialValue(context)) as any; } else { res[field.name] = field.initialValue as any; } } } } return res; } /** * Synchronously compute default/initial values from a schema. * Handles static initialValue only (skips eval callbacks and functions). */ export function getSchemaDefaultValue(schema: VevProps | VevProps[]): InitialValue { const fields = Array.isArray(schema) ? schema : [schema]; const res: InitialValue = {}; for (const field of fields) { if (field.name && field.type) { if (field.type === 'object') { res[field.name] = getSchemaDefaultValue(field.fields); continue; } if ( field.initialValue && !isEvalCallback(field.initialValue) && !isFunction(field.initialValue) ) { res[field.name] = field.initialValue as any; } } } return res; } export function useStorageField( name: string, storageScope: 'project' | 'workspace' | 'account', ): { value: T | undefined; onChange: (value: T) => Promise } { const { storage } = useSchemaContext(); const [value, setValue] = useState(); useEffect(() => { storage?.getItem(name, storageScope).then(setValue); }, [storageScope, name, storage]); return { value, async onChange(value) { setValue(value); storage?.setItem(name, value, storageScope); }, }; }