@@ -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