2018-01-28 23:16:50 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								"use strict" ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-01-29 18:34:59 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								const  Entity  =  require ( './entity' ) ;  
						 
					
						
							
								
									
										
										
										
											2018-08-13 10:59:31 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								const  Attribute  =  require ( './attribute' ) ;  
						 
					
						
							
								
									
										
										
										
											2018-04-20 00:12:01 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								const  protectedSessionService  =  require ( '../services/protected_session' ) ;  
						 
					
						
							
								
									
										
										
										
											2018-03-31 10:51:37 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								const  repository  =  require ( '../services/repository' ) ;  
						 
					
						
							
								
									
										
										
										
											2018-11-25 22:09:52 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								const  sql  =  require ( '../services/sql' ) ;  
						 
					
						
							
								
									
										
										
										
											2019-03-26 22:24:04 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								const  utils  =  require ( '../services/utils' ) ;  
						 
					
						
							
								
									
										
										
										
											2018-04-02 20:46:46 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								const  dateUtils  =  require ( '../services/date_utils' ) ;  
						 
					
						
							
								
									
										
										
										
											2019-03-26 22:24:04 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								const  syncTableService  =  require ( '../services/sync_table' ) ;  
						 
					
						
							
								
									
										
										
										
											2018-01-28 23:16:50 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-08-15 22:06:49 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								const  LABEL  =  'label' ;  
						 
					
						
							
								
									
										
										
										
											2018-11-13 12:50:08 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								const  LABEL _DEFINITION  =  'label-definition' ;  
						 
					
						
							
								
									
										
										
										
											2018-08-15 22:06:49 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								const  RELATION  =  'relation' ;  
						 
					
						
							
								
									
										
										
										
											2018-11-13 12:50:08 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								const  RELATION _DEFINITION  =  'relation-definition' ;  
						 
					
						
							
								
									
										
										
										
											2018-08-15 22:06:49 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-02-23 20:33:27 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								const  STRING _MIME _TYPES  =  [ "application/x-javascript" ] ;  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-08-22 23:37:06 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								/ * *  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  This  represents  a  Note  which  is  a  central  object  in  the  Trilium  Notes  project . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  @ property  { string }  noteId  -  primary  key 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  @ property  { string }  type  -  one  of  "text" ,  "code" ,  "file"  or  "render" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  @ property  { string }  mime  -  MIME  type ,  e . g .  "text/html" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  @ property  { string }  title  -  note  title 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  @ property  { boolean }  isProtected  -  true  if  note  is  protected 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  @ property  { boolean }  isDeleted  -  true  if  note  is  deleted 
							 
						 
					
						
							
								
									
										
										
										
											2019-03-13 22:43:59 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  @ property  { string }  dateCreated  -  local  date  time  ( with  offset ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  @ property  { string }  dateModified  -  local  date  time  ( with  offset ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-03-12 20:58:31 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 *  @ property  { string }  utcDateCreated 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  @ property  { string }  utcDateModified 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-22 23:37:06 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								 * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 *  @ extends  Entity 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								 * / 
							 
						 
					
						
							
								
									
										
										
										
											2018-01-29 18:34:59 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								class  Note  extends  Entity  {  
						 
					
						
							
								
									
										
										
										
											2018-08-16 23:00:04 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    static  get  entityName ( )  {  return  "notes" ;  } 
							 
						 
					
						
							
								
									
										
										
										
											2018-01-30 20:12:19 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    static  get  primaryKeyName ( )  {  return  "noteId" ;  } 
							 
						 
					
						
							
								
									
										
										
										
											2019-02-06 20:19:25 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    static  get  hashedProperties ( )  {  return  [ "noteId" ,  "title" ,  "type" ,  "isProtected" ,  "isDeleted" ] ;  } 
							 
						 
					
						
							
								
									
										
										
										
											2018-01-29 23:35:36 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-08-22 23:37:06 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    / * * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  @ param  row  -  object  containing  database  row  from  "notes"  table 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * / 
							 
						 
					
						
							
								
									
										
										
										
											2018-03-31 10:51:37 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    constructor ( row )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        super ( row ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2018-01-29 20:57:55 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-08-07 11:38:00 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        this . isProtected  =  ! ! this . isProtected ; 
							 
						 
					
						
							
								
									
										
										
										
											2018-10-30 22:18:20 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        / *   t r u e   i f   c o n t e n t   ( m e a n i n g   a n y   k i n d   o f   p o t e n t i a l l y   e n c r y p t e d   c o n t e n t )   i s   e i t h e r   n o t   e n c r y p t e d 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								         *  or  encrypted ,  but  with  available  protected  session  ( so  effectively  decrypted )  * / 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        this . isContentAvailable  =  true ; 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-07 11:38:00 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-04-08 12:27:10 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        // check if there's noteId, otherwise this is a new entity which wasn't encrypted yet
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  ( this . isProtected  &&  this . noteId )  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-10-30 22:18:20 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            this . isContentAvailable  =  protectedSessionService . isProtectedSessionAvailable ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-01-13 00:24:51 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            if  ( this . isContentAvailable )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                protectedSessionService . decryptNote ( this ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                this . title  =  "[protected]" ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            } 
							 
						 
					
						
							
								
									
										
										
										
											2018-01-29 23:35:36 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
									
										
										
										
											2018-01-29 20:57:55 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-03-27 21:16:13 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    / * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  Note  content  has  quite  special  handling  -  it ' s  not  a  separate  entity ,  but  a  lazily  loaded 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  part  of  Note  entity  with  it ' s  own  sync .  Reasons  behind  this  hybrid  design  has  been : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  -  content  can  be  quite  large  and  it 's not necessary to load it / fill memory for any note access even if we don' t  need  a  content ,  especially  for  bulk  operations  like  search 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  -  changes  in  the  note  metadata  or  title  should  not  trigger  note  content  sync  ( so  we  keep  separate  utcDateModified  and  sync  rows ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  -  but  to  the  user  note  content  and  title  changes  are  one  and  the  same  -  single  dateModified  ( so  all  changes  must  go  through  Note  and  content  is  not  a  separate  entity ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * / 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-03-26 22:24:04 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    /** @returns {Promise<*>} */ 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-13 19:34:19 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    async  getContent ( silentNotFoundError  =  false )  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-03-26 22:24:04 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        if  ( this . content  ===  undefined )  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-03-27 21:27:29 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            const  res  =  await  sql . getRow ( ` SELECT content, hash FROM note_contents WHERE noteId = ? ` ,  [ this . noteId ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-04-13 19:34:19 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            if  ( ! res )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                if  ( silentNotFoundError )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    return  undefined ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    throw  new  Error ( "Cannot find note content for noteId="  +  this . noteId ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-03-27 21:27:29 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            this . content  =  res . content ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-02-08 21:01:26 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-03-26 22:24:04 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            if  ( this . isProtected )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                if  ( this . isContentAvailable )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    protectedSessionService . decryptNoteContent ( this ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    this . content  =  "" ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                } 
							 
						 
					
						
							
								
									
										
										
										
											2019-02-08 21:01:26 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            } 
							 
						 
					
						
							
								
									
										
										
										
											2019-02-10 22:45:44 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  ( this . isStringNote ( ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-03-26 22:24:04 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                this . content  =  this . content  ===  null 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    ?  "" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    :  this . content . toString ( "UTF-8" ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-02-10 22:45:44 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            } 
							 
						 
					
						
							
								
									
										
										
										
											2018-04-08 08:31:19 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
									
										
										
										
											2019-02-06 20:19:25 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-03-26 22:24:04 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        return  this . content ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-02-06 21:29:23 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-02-07 22:16:40 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    /** @returns {Promise<*>} */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    async  getJsonContent ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        const  content  =  await  this . getContent ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  JSON . parse ( content ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-02-08 21:01:26 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    /** @returns {Promise} */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    async  setContent ( content )  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-11 21:44:35 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        // force updating note itself so that dateChanged is represented correctly even for the content
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        this . forcedChange  =  true ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        await  this . save ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-03-26 22:24:04 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        this . content  =  content ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        const  pojo  =  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            noteId :  this . noteId , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            content :  content , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            utcDateModified :  dateUtils . utcNowDateTime ( ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            hash :  utils . hash ( this . noteId  +  "|"  +  content ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  ( this . isProtected )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  ( this . isContentAvailable )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                protectedSessionService . encryptNoteContent ( pojo ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                throw  new  Error ( ` Cannot update content of noteId= ${ this . noteId }  since we're out of protected session. ` ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            } 
							 
						 
					
						
							
								
									
										
										
										
											2019-02-08 21:01:26 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-03-26 22:24:04 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        await  sql . upsert ( "note_contents" ,  "noteId" ,  pojo ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        await  syncTableService . addNoteContentSync ( this . noteId ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-02-08 21:01:26 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    /** @returns {Promise} */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    async  setJsonContent ( content )  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-03-05 20:44:50 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        await  this . setContent ( JSON . stringify ( content ,  null ,  '\t' ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-02-08 21:01:26 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-08-22 23:37:06 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    /** @returns {boolean} true if this note is the root of the note tree. Root note has "root" noteId */ 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-01 09:26:02 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    isRoot ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  this . noteId  ===  'root' ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-08-22 23:37:06 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    /** @returns {boolean} true if this note is of application/json content type */ 
							 
						 
					
						
							
								
									
										
										
										
											2018-01-29 23:17:44 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    isJson ( )  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-03-25 23:25:17 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        return  this . mime  ===  "application/json" ; 
							 
						 
					
						
							
								
									
										
										
										
											2018-01-29 23:17:44 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-08-22 23:37:06 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    /** @returns {boolean} true if this note is JavaScript (code or attachment) */ 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-18 10:47:02 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    isJavaScript ( )  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-03-01 22:30:06 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        return  ( this . type  ===  "code"  ||  this . type  ===  "file" ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-11-30 22:28:30 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            &&  ( this . mime . startsWith ( "application/javascript" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                ||  this . mime  ===  "application/x-javascript" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                ||  this . mime  ===  "text/javascript" ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-18 10:47:02 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-08-22 23:37:06 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    /** @returns {boolean} true if this note is HTML */ 
							 
						 
					
						
							
								
									
										
										
										
											2018-03-04 21:05:14 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    isHtml ( )  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-05-26 19:27:47 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        return  ( this . type  ===  "code"  ||  this . type  ===  "file"  ||  this . type  ===  "render" )  &&  this . mime  ===  "text/html" ; 
							 
						 
					
						
							
								
									
										
										
										
											2018-03-04 21:05:14 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-02-10 22:45:44 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    /** @returns {boolean} true if the note has string content (not binary) */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    isStringNote ( )  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-02-23 20:33:27 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        return  [ "text" ,  "code" ,  "relation-map" ,  "search" ] . includes ( this . type ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            ||  this . mime . startsWith ( 'text/' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            ||  STRING _MIME _TYPES . includes ( this . mime ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-02-10 22:45:44 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-08-22 23:37:06 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    /** @returns {string} JS script environment - either "frontend" or "backend" */ 
							 
						 
					
						
							
								
									
										
										
										
											2018-03-05 23:09:36 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    getScriptEnv ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  ( this . isHtml ( )  ||  ( this . isJavaScript ( )  &&  this . mime . endsWith ( 'env=frontend' ) ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            return  "frontend" ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-03-07 00:17:18 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        if  ( this . type  ===  'render' )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            return  "frontend" ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-03-05 23:09:36 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        if  ( this . isJavaScript ( )  &&  this . mime . endsWith ( 'env=backend' ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            return  "backend" ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  null ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-08-22 23:37:06 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    / * * 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-23 15:33:19 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								     *  @ returns  { Promise < Attribute [ ] > }  attributes  belonging  to  this  specific  note  ( excludes  inherited  attributes ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-22 23:37:06 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								     * / 
							 
						 
					
						
							
								
									
										
										
										
											2019-09-07 20:43:59 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    async  getOwnedAttributes ( type ,  name )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        let  query  =  ` SELECT * FROM attributes WHERE isDeleted = 0 AND noteId = ? ` ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        const  params  =  [ this . noteId ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  ( type )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            query  +=  `  AND type = ? ` ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            params . push ( type ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  ( name )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            query  +=  `  AND name = ? ` ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            params . push ( name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  await  repository . getEntities ( query ,  params ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    / * * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  @ returns  { Promise < Attribute > }  attribute  belonging  to  this  specific  note  ( excludes  inherited  attributes ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * / 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    async  getOwnedAttribute ( type ,  name )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        const  attrs  =  await  this . getOwnedAttributes ( type ,  name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  attrs . length  >  0  ?  attrs [ 0 ]  :  null ; 
							 
						 
					
						
							
								
									
										
										
										
											2018-01-28 23:16:50 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-11-01 10:23:21 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    / * * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  @ returns  { Promise < Attribute [ ] > }  relations  targetting  this  specific  note 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * / 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    async  getTargetRelations ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  await  repository . getEntities ( "SELECT * FROM attributes WHERE type = 'relation' AND isDeleted = 0 AND value = ?" ,  [ this . noteId ] ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-09-01 13:18:55 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    / * * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  @ param  { string }  [ name ]  -  attribute  name  to  filter 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  @ returns  { Promise < Attribute [ ] > }  all  note ' s  attributes ,  including  inherited  ones 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * / 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    async  getAttributes ( name )  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-13 17:16:06 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        if  ( ! this . _ _attributeCache )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            await  this . loadAttributesToCache ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-09-01 13:18:55 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        if  ( name )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            return  this . _ _attributeCache . filter ( attr  =>  attr . name  ===  name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            return  this . _ _attributeCache ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-13 17:16:06 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-09-01 13:18:55 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    / * * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  @ param  { string }  [ name ]  -  label  name  to  filter 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  @ returns  { Promise < Attribute [ ] > }  all  note ' s  labels  ( attributes  with  type  label ) ,  including  inherited  ones 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * / 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    async  getLabels ( name )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  ( await  this . getAttributes ( name ) ) . filter ( attr  =>  attr . type  ===  LABEL ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-15 22:06:49 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-11-13 12:50:08 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    / * * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  @ param  { string }  [ name ]  -  label  name  to  filter 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  @ returns  { Promise < Attribute [ ] > }  all  note ' s  label  definitions ,  including  inherited  ones 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * / 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    async  getLabelDefinitions ( name )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  ( await  this . getAttributes ( name ) ) . filter ( attr  =>  attr . type  ===  LABEL _DEFINITION ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-09-01 13:18:55 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    / * * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  @ param  { string }  [ name ]  -  relation  name  to  filter 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  @ returns  { Promise < Attribute [ ] > }  all  note ' s  relations  ( attributes  with  type  relation ) ,  including  inherited  ones 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * / 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    async  getRelations ( name )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  ( await  this . getAttributes ( name ) ) . filter ( attr  =>  attr . type  ===  RELATION ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-15 22:06:49 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-08-17 11:28:36 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    / * * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  @ param  { string }  [ name ]  -  relation  name  to  filter 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  @ returns  { Promise < Note [ ] > } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * / 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    async  getRelationTargets ( name )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        const  relations  =  await  this . getRelations ( name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        const  targets  =  [ ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        for  ( const  relation  of  relations )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            targets . push ( await  relation . getTargetNote ( ) ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  targets ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-11-13 12:50:08 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    / * * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  @ param  { string }  [ name ]  -  relation  name  to  filter 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  @ returns  { Promise < Attribute [ ] > }  all  note ' s  relation  definitions  including  inherited  ones 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * / 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    async  getRelationDefinitions ( name )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  ( await  this . getAttributes ( name ) ) . filter ( attr  =>  attr . type  ===  RELATION _DEFINITION ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-08-22 23:37:06 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    / * * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  Clear  note ' s  attributes  cache  to  force  fresh  reload  for  next  attribute  request . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  Cache  is  note  instance  scoped . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * / 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-13 17:16:06 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    invalidateAttributeCache ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        this . _ _attributeCache  =  null ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-08-22 23:37:06 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    /** @returns {Promise<void>} */ 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-13 17:16:06 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    async  loadAttributesToCache ( )  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-07 13:33:10 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        const  attributes  =  await  repository . getEntities ( ` 
 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-13 17:05:16 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            WITH  RECURSIVE 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            tree ( noteId ,  level )  AS  ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                SELECT  ? ,  0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                UNION 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                SELECT  branches . parentNoteId ,  tree . level  +  1  FROM  branches 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    JOIN  tree  ON  branches . noteId  =  tree . noteId 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    JOIN  notes  ON  notes . noteId  =  branches . parentNoteId 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                WHERE  notes . isDeleted  =  0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                  AND  branches . isDeleted  =  0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            treeWithAttrs ( noteId ,  level )  AS  ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                SELECT  *  FROM  tree 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                UNION 
							 
						 
					
						
							
								
									
										
										
										
											2019-09-07 11:00:15 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                SELECT  attributes . value ,  treeWithAttrs . level  FROM  attributes 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-13 17:05:16 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                     JOIN  treeWithAttrs  ON  treeWithAttrs . noteId  =  attributes . noteId 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                WHERE  attributes . isDeleted  =  0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                  AND  attributes . type  =  'relation' 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-21 12:52:11 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                  AND  attributes . name  =  'template' 
							 
						 
					
						
							
								
									
										
										
										
											2019-09-07 11:00:15 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                  AND  ( treeWithAttrs . level  =  0  OR  attributes . isInheritable  =  1 ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-13 17:05:16 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            SELECT  attributes . *  FROM  attributes  JOIN  treeWithAttrs  ON  attributes . noteId  =  treeWithAttrs . noteId 
							 
						 
					
						
							
								
									
										
										
										
											2019-09-07 11:00:15 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            WHERE  attributes . isDeleted  =  0  AND  ( attributes . isInheritable  =  1  OR  treeWithAttrs . level  =  0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            ORDER  BY  level ,  noteId ,  position ` , [this.noteId]);
 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-07 13:33:10 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        // attributes are ordered so that "closest" attributes are first
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        // we order by noteId so that attributes from same note stay together. Actual noteId ordering doesn't matter.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        const  filteredAttributes  =  attributes . filter ( ( attr ,  index )  =>  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  ( attr . isDefinition ( ) )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                const  firstDefinitionIndex  =  attributes . findIndex ( el  =>  el . type  ===  attr . type  &&  el . name  ===  attr . name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                // keep only if this element is the first definition for this type & name
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                return  firstDefinitionIndex  ===  index ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                const  definitionAttr  =  attributes . find ( el  =>  el . type  ===  attr . type  +  '-definition'  &&  el . name  ===  attr . name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                if  ( ! definitionAttr )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    return  true ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                const  definition  =  definitionAttr . value ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                if  ( definition . multiplicityType  ===  'multivalue' )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    return  true ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    const  firstAttrIndex  =  attributes . findIndex ( el  =>  el . type  ===  attr . type  &&  el . name  ===  attr . name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    // in case of single-valued attribute we'll keep it only if it's first (closest)
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    return  firstAttrIndex  ===  index ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        for  ( const  attr  of  filteredAttributes )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            attr . isOwned  =  attr . noteId  ===  this . noteId ; 
							 
						 
					
						
							
								
									
										
										
										
											2018-03-03 09:11:41 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-08-13 17:16:06 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        this . _ _attributeCache  =  filteredAttributes ; 
							 
						 
					
						
							
								
									
										
										
										
											2018-03-03 09:11:41 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-08-22 23:37:06 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    / * * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  @ param  { string }  type  -  attribute  type  ( label ,  relation ,  etc . ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  @ param  { string }  name  -  attribute  name 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  @ returns  { Promise < boolean > }  true  if  note  has  an  attribute  with  given  type  and  name  ( including  inherited ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * / 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-15 22:06:49 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    async  hasAttribute ( type ,  name )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  ! ! await  this . getAttribute ( type ,  name ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2018-03-04 22:09:51 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-08-22 23:37:06 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    / * * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  @ param  { string }  type  -  attribute  type  ( label ,  relation ,  etc . ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  @ param  { string }  name  -  attribute  name 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  @ returns  { Promise < Attribute > }  attribute  of  given  type  and  name .  If  there 's more such attributes, first is  returned. Returns null if there' s  no  such  attribute  belonging  to  this  note . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * / 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-15 22:06:49 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    async  getAttribute ( type ,  name )  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-07 13:33:10 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        const  attributes  =  await  this . getAttributes ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-08-15 22:06:49 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        return  attributes . find ( attr  =>  attr . type  ===  type  &&  attr . name  ===  name ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2018-01-29 17:41:59 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-08-22 23:37:06 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    / * * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  @ param  { string }  type  -  attribute  type  ( label ,  relation ,  etc . ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  @ param  { string }  name  -  attribute  name 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  @ returns  { Promise < string > }  attribute  value  of  given  type  and  name  or  null  if  no  such  attribute  exists . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * / 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-15 22:06:49 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    async  getAttributeValue ( type ,  name )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        const  attr  =  await  this . getAttribute ( type ,  name ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-13 10:59:31 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-08-15 22:06:49 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        return  attr  ?  attr . value  :  null ; 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-13 10:59:31 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-08-22 23:37:06 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    / * * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  Based  on  enabled ,  attribute  is  either  set  or  removed . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  @ param  { string }  type  -  attribute  type  ( 'relation' ,  'label'  etc . ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  @ param  { boolean }  enabled  -  toggle  On  or  Off 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  @ param  { string }  name  -  attribute  name 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  @ param  { string }  [ value ]  -  attribute  value  ( optional ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  @ returns  { Promise < void > } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * / 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    async  toggleAttribute ( type ,  enabled ,  name ,  value )  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-13 13:53:08 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        if  ( enabled )  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-15 22:06:49 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            await  this . setAttribute ( type ,  name ,  value ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-13 13:53:08 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        else  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-15 22:06:49 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            await  this . removeAttribute ( type ,  name ,  value ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-13 13:53:08 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-08-22 23:37:06 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    / * * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  Creates  given  attribute  name - value  pair  if  it  doesn ' t  exist . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  @ param  { string }  type  -  attribute  type  ( label ,  relation ,  etc . ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  @ param  { string }  name  -  attribute  name 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  @ param  { string }  [ value ]  -  attribute  value  ( optional ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  @ returns  { Promise < void > } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * / 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    async  setAttribute ( type ,  name ,  value )  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-13 13:53:08 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        const  attributes  =  await  this . getOwnedAttributes ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-22 23:37:06 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        let  attr  =  attributes . find ( attr  =>  attr . type  ===  type  &&  ( value  ===  undefined  ||  attr . value  ===  value ) ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-13 10:59:31 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-08-15 22:06:49 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        if  ( ! attr )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            attr  =  new  Attribute ( { 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-13 10:59:31 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                noteId :  this . noteId , 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-15 22:06:49 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                type :  type , 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-13 13:53:08 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                name :  name , 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-22 23:37:06 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                value :  value  !==  undefined  ?  value  :  "" 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-13 10:59:31 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            } ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-08-15 22:06:49 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            await  attr . save ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-13 17:16:06 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            this . invalidateAttributeCache ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-13 13:53:08 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-13 10:59:31 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-08-22 23:37:06 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    / * * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  Removes  given  attribute  name - value  pair  if  it  exists . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  @ param  { string }  type  -  attribute  type  ( label ,  relation ,  etc . ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  @ param  { string }  name  -  attribute  name 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  @ param  { string }  [ value ]  -  attribute  value  ( optional ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  @ returns  { Promise < void > } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * / 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    async  removeAttribute ( type ,  name ,  value )  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-13 13:53:08 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        const  attributes  =  await  this . getOwnedAttributes ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-13 10:59:31 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-08-13 13:53:08 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        for  ( const  attribute  of  attributes )  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-22 23:37:06 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            if  ( attribute . type  ===  type  &&  ( value  ===  undefined  ||  value  ===  attribute . value ) )  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-13 13:53:08 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                attribute . isDeleted  =  true ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                await  attribute . save ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-13 17:16:06 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                this . invalidateAttributeCache ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-13 13:53:08 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            } 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-13 10:59:31 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-08-22 23:37:06 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    / * * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  @ param  { string }  name  -  label  name 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  @ returns  { Promise < boolean > }  true  if  label  exists  ( including  inherited ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * / 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-15 22:06:49 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    async  hasLabel ( name )  {  return  await  this . hasAttribute ( LABEL ,  name ) ;  } 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-22 23:37:06 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    / * * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  @ param  { string }  name  -  relation  name 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  @ returns  { Promise < boolean > }  true  if  relation  exists  ( including  inherited ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * / 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-15 22:06:49 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    async  hasRelation ( name )  {  return  await  this . hasAttribute ( RELATION ,  name ) ;  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-08-22 23:37:06 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    / * * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  @ param  { string }  name  -  label  name 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  @ returns  { Promise < Attribute > }  label  if  it  exists ,  null  otherwise 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * / 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-15 22:06:49 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    async  getLabel ( name )  {  return  await  this . getAttribute ( LABEL ,  name ) ;  } 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-22 23:37:06 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    / * * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  @ param  { string }  name  -  relation  name 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  @ returns  { Promise < Attribute > }  relation  if  it  exists ,  null  otherwise 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * / 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-15 22:06:49 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    async  getRelation ( name )  {  return  await  this . getAttribute ( RELATION ,  name ) ;  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-08-22 23:37:06 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    / * * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  @ param  { string }  name  -  label  name 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  @ returns  { Promise < string > }  label  value  if  label  exists ,  null  otherwise 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * / 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-15 22:06:49 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    async  getLabelValue ( name )  {  return  await  this . getAttributeValue ( LABEL ,  name ) ;  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-08-22 23:37:06 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    / * * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  @ param  { string }  name  -  relation  name 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  @ returns  { Promise < string > }  relation  value  if  relation  exists ,  null  otherwise 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * / 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    async  getRelationValue ( name )  {  return  await  this . getAttributeValue ( RELATION ,  name ) ;  } 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-15 22:06:49 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-12-22 22:16:32 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    / * * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  @ param  { string }  name 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  @ returns  { Promise < Note > | null }  target  note  of  the  relation  or  null  ( if  target  is  empty  or  note  was  not  found ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * / 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    async  getRelationTarget ( name )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        const  relation  =  await  this . getRelation ( name ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  relation  ?  await  repository . getNote ( relation . value )  :  null ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-08-22 23:37:06 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    / * * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  Based  on  enabled ,  label  is  either  set  or  removed . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  @ param  { boolean }  enabled  -  toggle  On  or  Off 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  @ param  { string }  name  -  label  name 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  @ param  { string }  [ value ]  -  label  value  ( optional ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  @ returns  { Promise < void > } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * / 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    async  toggleLabel ( enabled ,  name ,  value )  {  return  await  this . toggleAttribute ( LABEL ,  enabled ,  name ,  value ) ;  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    / * * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  Based  on  enabled ,  relation  is  either  set  or  removed . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  @ param  { boolean }  enabled  -  toggle  On  or  Off 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  @ param  { string }  name  -  relation  name 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  @ param  { string }  [ value ]  -  relation  value  ( noteId ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  @ returns  { Promise < void > } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * / 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    async  toggleRelation ( enabled ,  name ,  value )  {  return  await  this . toggleAttribute ( RELATION ,  enabled ,  name ,  value ) ;  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    / * * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  Create  label  name - value  pair  if  it  doesn ' t  exist  yet . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  @ param  { string }  name  -  label  name 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  @ param  { string }  [ value ]  -  label  value 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  @ returns  { Promise < void > } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * / 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    async  setLabel ( name ,  value )  {  return  await  this . setAttribute ( LABEL ,  name ,  value ) ;  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    / * * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  Create  relation  name - value  pair  if  it  doesn ' t  exist  yet . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  @ param  { string }  name  -  relation  name 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  @ param  { string }  [ value ]  -  relation  value  ( noteId ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  @ returns  { Promise < void > } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * / 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    async  setRelation ( name ,  value )  {  return  await  this . setAttribute ( RELATION ,  name ,  value ) ;  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    / * * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  Remove  label  name - value  pair ,  if  it  exists . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  @ param  { string }  name  -  label  name 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  @ param  { string }  [ value ]  -  label  value 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  @ returns  { Promise < void > } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * / 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    async  removeLabel ( name ,  value )  {  return  await  this . removeAttribute ( LABEL ,  name ,  value ) ;  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    / * * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  Remove  relation  name - value  pair ,  if  it  exists . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  @ param  { string }  name  -  relation  name 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  @ param  { string }  [ value ]  -  relation  value  ( noteId ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  @ returns  { Promise < void > } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * / 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    async  removeRelation ( name ,  value )  {  return  await  this . removeAttribute ( RELATION ,  name ,  value ) ;  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    / * * 
							 
						 
					
						
							
								
									
										
										
										
											2018-11-25 22:09:52 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								     *  @ return  { Promise < string [ ] > }  return  list  of  all  descendant  noteIds  of  this  note .  Returning  just  noteIds  because  number  of  notes  can  be  huge .  Includes  also  this  note ' s  noteId 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * / 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    async  getDescendantNoteIds ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  await  sql . getColumn ( ` 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            WITH  RECURSIVE 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            tree ( noteId )  AS  ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                SELECT  ? 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                UNION 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                SELECT  branches . noteId  FROM  branches 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    JOIN  tree  ON  branches . parentNoteId  =  tree . noteId 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    JOIN  notes  ON  notes . noteId  =  branches . noteId 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                WHERE  notes . isDeleted  =  0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                  AND  branches . isDeleted  =  0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            SELECT  noteId  FROM  tree ` , [this.noteId]);
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    / * * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  Finds  descendant  notes  with  given  attribute  name  and  value .  Only  own  attributes  are  considered ,  not  inherited  ones 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-22 23:37:06 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								     * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  @ param  { string }  type  -  attribute  type  ( label ,  relation ,  etc . ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  @ param  { string }  name  -  attribute  name 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  @ param  { string }  [ value ]  -  attribute  value 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-23 15:33:19 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								     *  @ returns  { Promise < Note [ ] > } 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-22 23:37:06 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								     * / 
							 
						 
					
						
							
								
									
										
										
										
											2018-11-25 22:09:52 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    async  getDescendantNotesWithAttribute ( type ,  name ,  value )  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-21 12:50:43 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        const  params  =  [ this . noteId ,  name ] ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        let  valueCondition  =  "" ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  ( value  !==  undefined )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            params . push ( value ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            valueCondition  =  " AND attributes.value = ?" ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        const  notes  =  await  repository . getEntities ( ` 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            WITH  RECURSIVE 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            tree ( noteId )  AS  ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                SELECT  ? 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                UNION 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                SELECT  branches . noteId  FROM  branches 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    JOIN  tree  ON  branches . parentNoteId  =  tree . noteId 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    JOIN  notes  ON  notes . noteId  =  branches . noteId 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                WHERE  notes . isDeleted  =  0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                  AND  branches . isDeleted  =  0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            SELECT  notes . *  FROM  notes  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            JOIN  tree  ON  tree . noteId  =  notes . noteId 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            JOIN  attributes  ON  attributes . noteId  =  notes . noteId 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            WHERE  attributes . isDeleted  =  0  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              AND  attributes . name  =  ? 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								              $ { valueCondition }  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            ORDER  BY  noteId ,  position ` , params);
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  notes ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-08-22 23:37:06 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    / * * 
							 
						 
					
						
							
								
									
										
										
										
											2018-11-25 22:09:52 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								     *  Finds  descendant  notes  with  given  label  name  and  value .  Only  own  labels  are  considered ,  not  inherited  ones 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-22 23:37:06 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								     * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  @ param  { string }  name  -  label  name 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  @ param  { string }  [ value ]  -  label  value 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-23 15:33:19 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								     *  @ returns  { Promise < Note [ ] > } 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-22 23:37:06 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								     * / 
							 
						 
					
						
							
								
									
										
										
										
											2018-11-25 22:09:52 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    async  getDescendantNotesWithLabel ( name ,  value )  {  return  await  this . getDescendantNotesWithAttribute ( LABEL ,  name ,  value ) ;  } 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-22 23:37:06 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    / * * 
							 
						 
					
						
							
								
									
										
										
										
											2018-11-25 22:09:52 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								     *  Finds  descendant  notes  with  given  relation  name  and  value .  Only  own  relations  are  considered ,  not  inherited  ones 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-22 23:37:06 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								     * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  @ param  { string }  name  -  relation  name 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  @ param  { string }  [ value ]  -  relation  value 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-23 15:33:19 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								     *  @ returns  { Promise < Note [ ] > } 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-22 23:37:06 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								     * / 
							 
						 
					
						
							
								
									
										
										
										
											2018-11-25 22:09:52 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    async  getDescendantNotesWithRelation ( name ,  value )  {  return  await  this . getDescendantNotesWithAttribute ( RELATION ,  name ,  value ) ;  } 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-21 12:50:43 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-08-22 23:37:06 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    / * * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  Returns  note  revisions  of  this  note . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-23 15:33:19 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								     *  @ returns  { Promise < NoteRevision [ ] > } 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-22 23:37:06 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								     * / 
							 
						 
					
						
							
								
									
										
										
										
											2018-01-29 18:34:59 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    async  getRevisions ( )  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-03-31 10:51:37 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        return  await  repository . getEntities ( "SELECT * FROM note_revisions WHERE noteId = ?" ,  [ this . noteId ] ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2018-01-29 18:34:59 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-08-22 23:37:06 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    / * * 
							 
						 
					
						
							
								
									
										
										
										
											2018-11-15 13:58:14 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								     *  Get  list  of  links  coming  out  of  this  note . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * 
							 
						 
					
						
							
								
									
										
										
										
											2019-08-19 20:12:00 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								     *  @ deprecated  -  not  intended  for  general  use 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  @ returns  { Promise < Attribute [ ] > } 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-22 23:37:06 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								     * / 
							 
						 
					
						
							
								
									
										
										
										
											2018-11-08 11:08:16 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    async  getLinks ( )  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-08-19 20:12:00 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        return  await  repository . getEntities ( ` 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            SELECT  *  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            FROM  attributes  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            WHERE  noteId  =  ?  AND  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                  isDeleted  =  0  AND  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                  type  =  'relation'  AND  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                  name  IN  ( 'internal-link' ,  'image-link' ,  'relation-map-link' ) ` , [this.noteId]);
 
							 
						 
					
						
							
								
									
										
										
										
											2018-03-31 22:15:06 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-08-22 23:37:06 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    / * * 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-23 15:33:19 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								     *  @ returns  { Promise < Branch [ ] > } 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-22 23:37:06 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								     * / 
							 
						 
					
						
							
								
									
										
										
										
											2018-03-31 23:08:22 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    async  getBranches ( )  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-03-31 10:51:37 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        return  await  repository . getEntities ( "SELECT * FROM branches WHERE isDeleted = 0 AND noteId = ?" ,  [ this . noteId ] ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2018-01-28 23:16:50 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
									
										
										
										
											2018-01-29 23:35:36 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-09-03 09:40:22 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    / * * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     *  @ returns  { boolean }  -  true  if  note  has  children 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     * / 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    async  hasChildren ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  ( await  this . getChildNotes ( ) ) . length  >  0 ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-08-22 23:37:06 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    / * * 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-23 15:33:19 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								     *  @ returns  { Promise < Note [ ] > }  child  notes  of  this  note 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-22 23:37:06 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								     * / 
							 
						 
					
						
							
								
									
										
										
										
											2018-03-31 23:08:22 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    async  getChildNotes ( )  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-03-31 10:51:37 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        return  await  repository . getEntities ( ` 
 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-24 14:42:52 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								          SELECT  notes . *  
							 
						 
					
						
							
								
									
										
										
										
											2018-03-24 21:39:15 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								          FROM  branches  
							 
						 
					
						
							
								
									
										
										
										
											2018-02-24 14:42:52 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            JOIN  notes  USING ( noteId )  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          WHERE  notes . isDeleted  =  0 
							 
						 
					
						
							
								
									
										
										
										
											2018-03-24 21:39:15 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                AND  branches . isDeleted  =  0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                AND  branches . parentNoteId  =  ? 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          ORDER  BY  branches . notePosition ` , [this.noteId]);
 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-24 14:42:52 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-08-22 23:37:06 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    / * * 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-23 15:33:19 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								     *  @ returns  { Promise < Branch [ ] > }  child  branches  of  this  note 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-22 23:37:06 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								     * / 
							 
						 
					
						
							
								
									
										
										
										
											2018-03-31 23:08:22 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    async  getChildBranches ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  await  repository . getEntities ( ` 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          SELECT  branches . *  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          FROM  branches  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          WHERE  branches . isDeleted  =  0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                AND  branches . parentNoteId  =  ? 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          ORDER  BY  branches . notePosition ` , [this.noteId]);
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-08-22 23:37:06 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    / * * 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-23 15:33:19 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								     *  @ returns  { Promise < Note [ ] > }  parent  notes  of  this  note  ( note  can  have  multiple  parents  because  of  cloning ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-22 23:37:06 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								     * / 
							 
						 
					
						
							
								
									
										
										
										
											2018-03-31 23:08:22 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    async  getParentNotes ( )  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-03-31 10:51:37 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        return  await  repository . getEntities ( ` 
 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-24 14:42:52 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								          SELECT  parent _notes . *  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          FROM  
							 
						 
					
						
							
								
									
										
										
										
											2018-03-24 21:39:15 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            branches  AS  child _tree  
							 
						 
					
						
							
								
									
										
										
										
											2018-02-24 14:42:52 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            JOIN  notes  AS  parent _notes  ON  parent _notes . noteId  =  child _tree . parentNoteId  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								          WHERE  child _tree . noteId  =  ? 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                AND  child _tree . isDeleted  =  0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                AND  parent _notes . isDeleted  =  0 ` , [this.noteId]);
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-01-29 23:35:36 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    beforeSaving ( )  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-04-01 17:38:24 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        if  ( ! this . isDeleted )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            this . isDeleted  =  false ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-03-13 22:43:59 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        if  ( ! this . dateCreated )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            this . dateCreated  =  dateUtils . localNowDateTime ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-03-12 20:58:31 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        if  ( ! this . utcDateCreated )  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-03-13 22:43:59 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            this . utcDateCreated  =  dateUtils . utcNowDateTime ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2018-03-31 22:15:06 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-08-12 20:04:48 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        super . beforeSaving ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  ( this . isChanged )  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-03-13 22:43:59 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            this . dateModified  =  dateUtils . localNowDateTime ( ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            this . utcDateModified  =  dateUtils . utcNowDateTime ( ) ; 
							 
						 
					
						
							
								
									
										
										
										
											2018-08-12 20:04:48 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
									
										
										
										
											2018-01-29 23:35:36 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
									
										
										
										
											2018-11-30 10:20:03 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    // cannot be static!
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    updatePojo ( pojo )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  ( pojo . isProtected )  { 
							 
						 
					
						
							
								
									
										
										
										
											2019-01-13 00:24:51 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            if  ( this . isContentAvailable )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                protectedSessionService . encryptNote ( pojo ) ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            else  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                // updating protected note outside of protected session means we will keep original ciphertexts
 
							 
						 
					
						
							
								
									
										
										
										
											2019-03-26 22:24:04 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                delete  pojo . title ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-01-13 00:24:51 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            } 
							 
						 
					
						
							
								
									
										
										
										
											2018-11-30 10:20:03 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        delete  pojo . isContentAvailable ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        delete  pojo . _ _attributeCache ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-03-26 22:24:04 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        delete  pojo . content ; 
							 
						 
					
						
							
								
									
										
										
										
											2019-03-28 21:17:40 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        delete  pojo . contentHash ; 
							 
						 
					
						
							
								
									
										
										
										
											2018-11-30 10:20:03 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
									
										
										
										
											2018-01-28 23:16:50 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								module . exports  =  Note ;