import { Result , Ok , Err , Some , Option , None } from 'ts-results' ; import type { TypedMessage } from './base' ; import z_schema from 'z-schema' ; import draft , { enableMapSet , Draft } from 'immer' ; enableMapSet ( ) ; const metadataSchemaStore = new Map < string , object > ( ) ; export function getKnownMetadataKeys ( ) { return [ ... metadataSchemaStore . keys ( ) ] ; } export function getMetadataSchema ( key ) { return metadataSchemaStore . has ( key ) ? Some ( metadataSchemaStore . get ( key ) ! ) : None ; } param key param jsonSchema export function registerMetadataSchema ( key , jsonSchema ) { metadataSchemaStore . set ( key , jsonSchema ) ; } param key param jsonSchema example export function createTypedMessageMetadataReader < T > ( key , jsonSchema ? ) { if ( jsonSchema ) registerMetadataSchema ( key , jsonSchema ) ; return ( meta ) => readTypedMessageMetadataUntyped < T > ( meta , key ) ; } param meta param key param jsonSchema export function readTypedMessageMetadataUntyped < T > ( meta , key , jsonSchema ? ) { if ( ! meta ) return Err . EMPTY ; if ( ! meta . has ( key ) ) return Err . EMPTY ; if ( metadataSchemaStore . has ( key ) && ! jsonSchema ) jsonSchema = metadataSchemaStore . get ( key ) ! ; const data = meta . get ( key ) ! as T ; if ( ! jsonSchema ) console . warn ( 'You should add a JSON Schema to verify the metadata in the TypedMessage' ) ; else { const match = isDataMatchJSONSchema ( data , jsonSchema ) ; if ( match . err ) { console . warn ( 'The problematic metadata is dropped' , data , 'errors:' , match . val ) ; return Err . EMPTY ; } } return Ok ( data ) ; } export function isDataMatchJSONSchema ( data , jsonSchema ) { const validator = new z_schema ( { } ) ; if ( ! validator . validate ( data , jsonSchema ) ) return Err ( validator . getLastErrors ( ) ) ; return Ok . EMPTY ; } param metadataReader export function createRenderWithMetadata < T > ( metadataReader ) { return ( metadata , render ) : React . ReactElement | null => { const message = metadataReader ( metadata ) ; if ( message . ok ) return render ( message . val ) ; return null ; } ; } export function editMetadata ( metadata , edit ) { return draft ( metadata || new Map ( ) , ( e ) => void edit ( e ) ) ; } export function editTypedMessageMeta < T extends TypedMessage > ( typedMessage , edit ) { const meta = editMetadata ( typedMessage . meta , edit ) ; return { ... typedMessage , meta : meta . size === 0 ? undefined : meta } ; } param metadata param key param render param jsonSchema export function renderWithMetadataUntyped ( metadata , key , render , jsonSchema ? ) { const message = readTypedMessageMetadataUntyped ( metadata , key , jsonSchema ) ; if ( message . ok ) return render ( message . val ) ; return null ; }