UNPKG

@type-r/models

Version:

The serializable type system for JS and TypeScript

67 lines (51 loc) 2.02 kB
/** * Traversable objects and symbolic references */ export interface Traversable { getStore() : Traversable getOwner() : Traversable get( key : string ) : any } const referenceMask = /\^|(store\.[^.]+)|([^.]+)/g; // Compile reference to function export type ResolveReference = ( root : Traversable ) => any; export class CompiledReference { resolve : ResolveReference tail : string local : boolean constructor( reference : string, splitTail : boolean = false ){ const path = reference .match( referenceMask ) .map( key => { if( key === '^' || key === 'owner' ) return 'getOwner()'; if( key[ 0 ] === '~' ) return `getStore().get("${ key.substr( 1 ) }")`; if( key.indexOf( 'store.' ) === 0 ) return `getStore().get("${ key.substr( 6 ) }")`; return key; } ); this.tail = splitTail && path.pop(); this.local = !path.length; this.resolve = <any> new Function( 'self', ` var v = self.${ path.shift() }; ${ path.map( x => ` v = v && v.${ x }; `).join('')} return v; ` ); } } export function resolveReference( root : Traversable, reference : string, action : ( object, key : string ) => any ) : any { const path = reference.match( referenceMask ), skip = path.length - 1; let self = root; for( var i = 0; i < skip; i++ ){ const key = path[ i ]; switch( key ){ case '~' : self = self.getStore(); break; case '^' : self = self.getOwner(); break; default : self = self.get( key ); } // Do nothing if object on the path doesn't exist. if( !self ) return; } return action( self, path[ skip ] ); }