import { Entity , EntityReference , EntitySchema , EntitySchemaResolver , EntityStatus , EntityValues , GeoPoint , Properties , PropertiesOrBuilder , Property , ResolvedEntitySchema } from "../models" ; import { buildPropertyFrom } from "./util/property_builder" ; export function isReadOnly ( property ) { if ( property . readOnly ) return true ; if ( property . dataType === "timestamp" ) { if ( property . autoValue ) return true ; } return false ; } export function isHidden ( property ) { return typeof property . disabled === "object" && Boolean ( property . disabled . hidden ) ; } param schema param values param path param entityId ignore export function computeSchema < M extends { [ Key ] : any ; } > ( { schemaOrResolver , path , entityId , values } ) { if ( typeof schemaOrResolver === "function" ) { return schemaOrResolver ( { entityId , values } ) ; } else { if ( "originalSchema" in schemaOrResolver ) { return schemaOrResolver ; } const properties = computeProperties ( { propertiesOrBuilder : schemaOrResolver . properties , path , entityId , values } ) ; return { ... schemaOrResolver , properties , originalSchema : schemaOrResolver } ; } } param propertiesOrBuilder param values param path param entityId ignore export function computeProperties < M extends { [ Key ] : any ; } > ( { propertiesOrBuilder , path , entityId , values } ) { return Object . entries ( propertiesOrBuilder ) . map ( ( [ key , propertyOrBuilder ] ) => { return { [ key ] : buildPropertyFrom ( { propertyOrBuilder , values : values ?? { } , path , entityId } ) } ; } ) . reduce ( ( a , b ) => ( { ... a , ... b } ) , { } ) as Properties < M > ; } export function initWithProperties < M extends { [ Key ] : any ; } > ( properties , defaultValues ? ) { return Object . entries ( properties ) . map ( ( [ key , property ] ) => { const propertyDefaultValue = defaultValues && key in defaultValues ? ( defaultValues as any ) [ key ] : undefined ; const value = initPropertyValue ( key , property as Property , propertyDefaultValue ) ; return value === undefined ? { } : { [ key ] : value } ; } ) . reduce ( ( a , b ) => ( { ... a , ... b } ) , { } ) as EntityValues < M > ; } function initPropertyValue ( key , property , defaultValue ) { let value ; if ( property . dataType === "map" && property . properties ) { value = initWithProperties ( property . properties as Properties , defaultValue ) ; } else if ( defaultValue !== undefined ) { value = defaultValue ; } else { value = undefined ; } return value ; } category export function updateAutoValues < M extends { [ Key ] : any ; } > ( { inputValues , properties , status , timestampNowValue , referenceConverter , geopointConverter } ) { return traverseValues ( inputValues , properties , ( inputValue , property ) => { if ( property . dataType === "timestamp" ) { if ( status === "existing" && property . autoValue === "on_update" ) { return timestampNowValue ; } else if ( ( status === "new" || status === "copy" ) && ( property . autoValue === "on_update" || property . autoValue === "on_create" ) ) { return timestampNowValue ; } else { return inputValue ; } } else if ( referenceConverter && property . dataType === "reference" ) { if ( inputValue instanceof EntityReference ) { return referenceConverter ( inputValue ) ; } } else if ( geopointConverter && property . dataType === "geopoint" ) { if ( inputValue instanceof GeoPoint ) { return geopointConverter ( inputValue ) ; } } else { return inputValue ; } } ) ; } param values param properties param path category export function sanitizeData < M extends { [ Key ] : any ; } > ( values , properties , path ) { const result = values ; Object . entries ( properties ) . forEach ( ( [ key , property ] ) => { if ( values && values [ key ] !== undefined ) result [ key ] = values [ key ] ; else if ( ( property as Property ) . validation ?. required ) result [ key ] = null ; } ) ; return result ; } export function getReferenceFrom ( entity ) { return new EntityReference ( entity . id , entity . path ) ; } export function traverseValues < M extends { [ Key ] : any ; } > ( inputValues , properties , operation ) { const updatedValues = Object . entries ( properties ) . map ( ( [ key , property ] ) => { const inputValue = inputValues && ( inputValues as any ) [ key ] ; const updatedValue = traverseValue ( inputValue , property as Property , operation ) ; if ( updatedValue === undefined ) return { } ; return ( { [ key ] : updatedValue } ) ; } ) . reduce ( ( a , b ) => ( { ... a , ... b } ) , { } ) as EntityValues < M > ; return { ... inputValues , ... updatedValues } ; } export function traverseValue ( inputValue , property , operation ) { let value ; if ( property . dataType === "map" && property . properties ) { value = traverseValues ( inputValue , property . properties as Properties , operation ) ; } else if ( property . dataType === "array" ) { if ( property . of && Array . isArray ( inputValue ) ) { value = inputValue . map ( ( e ) => traverseValue ( e , property . of as Property , operation ) ) ; } else if ( property . oneOf && Array . isArray ( inputValue ) ) { const typeField = property . oneOf ! . typeField ?? "type" ; const valueField = property . oneOf ! . valueField ?? "value" ; value = inputValue . map ( ( e ) => { if ( e === null ) return null ; if ( typeof e !== "object" ) return e ; const type = e [ typeField ] ; const childProperty = property . oneOf ! . properties [ type ] ; if ( ! type || ! childProperty ) return e ; return { [ typeField ] : type , [ valueField ] : traverseValue ( e [ valueField ] , childProperty , operation ) } ; } ) ; } else { value = inputValue ; } } else { value = operation ( inputValue , property ) ; } return value ; }