@@ -113,6 +113,19 @@ function _UnsafeRestQuery(
113113  this . response  =  null ; 
114114  this . findOptions  =  { } ; 
115115  this . context  =  context  ||  { } ; 
116+   const  hasIgnoreIncludeErrors  =  Object . prototype . hasOwnProperty . call ( 
117+     restOptions , 
118+     'ignoreIncludeErrors' 
119+   ) ; 
120+   this . ignoreIncludeErrors  =  hasIgnoreIncludeErrors 
121+     ? ! ! restOptions . ignoreIncludeErrors 
122+     : false ; 
123+   if  ( hasIgnoreIncludeErrors )  { 
124+     this . restOptions . ignoreIncludeErrors  =  this . ignoreIncludeErrors ; 
125+     if  ( this . ignoreIncludeErrors )  { 
126+       this . findOptions . ignoreIncludeErrors  =  true ; 
127+     } 
128+   } 
116129  if  ( ! this . auth . isMaster )  { 
117130    if  ( this . className  ==  '_Session' )  { 
118131      if  ( ! this . auth . user )  { 
@@ -215,6 +228,8 @@ function _UnsafeRestQuery(
215228      case  'comment' :
216229        this . findOptions [ option ]  =  restOptions [ option ] ; 
217230        break ; 
231+       case  'ignoreIncludeErrors' :
232+         break ; 
218233      case  'order' :
219234        var  fields  =  restOptions . order . split ( ',' ) ; 
220235        this . findOptions . sort  =  fields . reduce ( ( sortMap ,  field )  =>  { 
@@ -741,6 +756,9 @@ _UnsafeRestQuery.prototype.runFind = async function (options = {}) {
741756    return  Promise . resolve ( ) ; 
742757  } 
743758  const  findOptions  =  Object . assign ( { } ,  this . findOptions ) ; 
759+   if  ( this . ignoreIncludeErrors )  { 
760+     findOptions . ignoreIncludeErrors  =  true ; 
761+   } 
744762  if  ( this . keys )  { 
745763    findOptions . keys  =  this . keys . map ( key  =>  { 
746764      return  key . split ( '.' ) [ 0 ] ; 
@@ -1013,6 +1031,13 @@ function includePath(config, auth, response, path, context, restOptions = {}) {
10131031  }  else  if  ( restOptions . readPreference )  { 
10141032    includeRestOptions . readPreference  =  restOptions . readPreference ; 
10151033  } 
1034+   // Flag for replacePointers if missing pointers should be preserved without throwing errors 
1035+   // defaults to false to continue previous behaviour 
1036+   let  preserveMissing  =  false ; 
1037+   if  ( restOptions . ignoreIncludeErrors )  { 
1038+     includeRestOptions . ignoreIncludeErrors  =  restOptions . ignoreIncludeErrors ; 
1039+     preserveMissing  =  true ; 
1040+   } 
10161041
10171042  const  queryPromises  =  Object . keys ( pointersHash ) . map ( async  className  =>  { 
10181043    const  objectIds  =  Array . from ( pointersHash [ className ] ) ; 
@@ -1054,7 +1079,9 @@ function includePath(config, auth, response, path, context, restOptions = {}) {
10541079    } ,  { } ) ; 
10551080
10561081    var  resp  =  { 
1057-       results : replacePointers ( response . results ,  path ,  replace ) , 
1082+       results : replacePointers ( response . results ,  path ,  replace ,  { 
1083+         preserveMissing, 
1084+       } ) , 
10581085    } ; 
10591086    if  ( response . count )  { 
10601087      resp . count  =  response . count ; 
@@ -1095,13 +1122,17 @@ function findPointers(object, path) {
10951122// in, or it may be a single object. 
10961123// Path is a list of fields to search into. 
10971124// replace is a map from object id -> object. 
1125+ // `options` is an optional options object; options currently include 
1126+ // `preserveMissing?: boolean` where if it is true 
10981127// Returns something analogous to object, but with the appropriate 
10991128// pointers inflated. 
1100- function  replacePointers ( object ,  path ,  replace )  { 
1129+ function  replacePointers ( object ,  path ,  replace ,  options  =  { } )  { 
1130+   const  preserveMissing  =  ! ! options . preserveMissing ; 
11011131  if  ( object  instanceof  Array )  { 
1102-     return  object 
1103-       . map ( obj  =>  replacePointers ( obj ,  path ,  replace ) ) 
1104-       . filter ( obj  =>  typeof  obj  !==  'undefined' ) ; 
1132+     const  mapped  =  object . map ( obj  =>  replacePointers ( obj ,  path ,  replace ,  options ) ) ; 
1133+     // TODO: Is this change really correct? If we do this then preserveMissing will essentially  
1134+     // cause the array to have undefined values inside? 
1135+     return  preserveMissing  ? mapped  : mapped . filter ( obj  =>  typeof  obj  !==  'undefined' ) ; 
11051136  } 
11061137
11071138  if  ( typeof  object  !==  'object'  ||  ! object )  { 
@@ -1110,7 +1141,11 @@ function replacePointers(object, path, replace) {
11101141
11111142  if  ( path . length  ===  0 )  { 
11121143    if  ( object  &&  object . __type  ===  'Pointer' )  { 
1113-       return  replace [ object . objectId ] ; 
1144+       const  replacement  =  replace [ object . objectId ] ; 
1145+       if  ( typeof  replacement  ===  'undefined' )  { 
1146+         return  preserveMissing  ? object  : undefined ; 
1147+       } 
1148+       return  replacement ; 
11141149    } 
11151150    return  object ; 
11161151  } 
@@ -1119,7 +1154,7 @@ function replacePointers(object, path, replace) {
11191154  if  ( ! subobject )  { 
11201155    return  object ; 
11211156  } 
1122-   var  newsub  =  replacePointers ( subobject ,  path . slice ( 1 ) ,  replace ) ; 
1157+   var  newsub  =  replacePointers ( subobject ,  path . slice ( 1 ) ,  replace ,   options ) ; 
11231158  var  answer  =  { } ; 
11241159  for  ( var  key  in  object )  { 
11251160    if  ( key  ==  path [ 0 ] )  { 
0 commit comments