license import { Observable } from 'rxjs' ; import { MimeType_ , URL_ , createDataset , createDatasets , Dataset , } from './datasets' ; import { Converter } from './converters' ; import { CachedObservable } from './cachedObservable' ; export const INVALID = Symbol ( 'INVALID' ) ; export abstract class DataType < T , U > { abstract parseMimeType ( mimeType ) ; abstract createMimeType ( typeData ) ; createDataset ( data , typeData ) { return createDataset ( this . createMimeType ( typeData ) , data ) ; } createDatasets ( url , data , typeData ) { return createDatasets ( url , this . createMimeType ( typeData ) , data ) ; } /**
     * Filer dataset for mimetypes of this type.
     */ filterDataset ( dataset ) { const res = new Map < T , U > ( ) ; for ( const [ mimeType , [ , data ] ] of dataset ) { const typeData_ = this . parseMimeType ( mimeType ) ; if ( typeData_ !== INVALID ) { res . set ( typeData_ , data as any ) ; } } return res ; } } /**
 * Dummy mime type data type, that accepts any mimetype.
 */ export class MimeTypeDataType < T > extends DataType < MimeType_ , T > { parseMimeType ( mimeType ) { return mimeType ; } createMimeType ( typeData ) { return typeData ; } } export abstract class TypedURL < T > { abstract parse ( url ) ; abstract create ( args ) ; } export class DefaultTypedURL extends TypedURL < URL > { parse ( url ) { return new URL ( url ) ; } create ( url ) { return url . toString ( ) ; } } /**
 * Create a a new converter, assuming:
 *
 * * returns either a single value or nothing
 * * Cost is one more than the input
 * * if it returns an observable, we should cache this observable
 */ export function createConverter < fromD , toD , fromT = MimeType_ , toT = MimeType_ , urlT = URL > ( { from = new MimeTypeDataType < fromD > ( ) as any , to = new MimeTypeDataType < toD > ( ) as any , url : urlT = new DefaultTypedURL ( ) as any , } , fn ) { return ( { url , mimeType , cost , data } ) => { const type = from . parseMimeType ( mimeType ) ; if ( type === INVALID ) { return [ ] ; } const urlArgs = urlT . parse ( url ) ; if ( urlArgs === null || urlArgs == undefined ) { return [ ] ; } const res = fn ( { url : urlArgs , data , type } ) ; if ( ! res ) { return [ ] ; } const arrayRes = isTypeData ( res ) ? [ res ] : Array . isArray ( res ) ? res : [ { type : ( undefined as any ) as toT , data : res } ] ; return arrayRes . map ( ( { data : newData , type : newType } ) => ( { data : newData instanceof Observable ? ( ( CachedObservable . from ( newData ) as any ) as toD ) : newData , mimeType : to . createMimeType ( newType ) , cost : cost + 1 , } ) ) ; } ; } export function isTypeData ( o ) { return o instanceof Object && 'data' in o && 'type' in o ; }