@@ -49,6 +49,7 @@ export interface URLComponents {
4949 path ?: string ;
5050 oDataQueryParams : KeyValuePairObjectStringNumber ;
5151 otherURLQueryParams : KeyValuePairObjectStringNumber ;
52+ otherURLQueryStrings : string [ ] ;
5253}
5354
5455/**
@@ -118,6 +119,7 @@ export class GraphRequest {
118119 version : this . config . defaultVersion ,
119120 oDataQueryParams : { } ,
120121 otherURLQueryParams : { } ,
122+ otherURLQueryStrings : [ ] ,
121123 } ;
122124 this . _headers = { } ;
123125 this . _options = { } ;
@@ -170,7 +172,7 @@ export class GraphRequest {
170172 // Capture query string into oDataQueryParams and otherURLQueryParams
171173 const queryParams = path . substring ( queryStrPos + 1 , path . length ) . split ( "&" ) ;
172174 for ( const queryParam of queryParams ) {
173- this . query ( queryParam ) ;
175+ this . parseQueryParameter ( queryParam ) ;
174176 }
175177 }
176178 } ;
@@ -237,9 +239,87 @@ export class GraphRequest {
237239 }
238240 }
239241 }
242+
243+ if ( urlComponents . otherURLQueryStrings . length !== 0 ) {
244+ for ( const str of urlComponents . otherURLQueryStrings ) {
245+ query . push ( str ) ;
246+ }
247+ }
240248 return query . length > 0 ? "?" + query . join ( "&" ) : "" ;
241249 }
242250
251+ /**
252+ * @private
253+ * @param queryDictionaryOrString
254+ */
255+ private parseQueryParameter ( queryDictionaryOrString : string | KeyValuePairObjectStringNumber ) : GraphRequest {
256+ if ( typeof queryDictionaryOrString === "string" ) {
257+ if ( queryDictionaryOrString . charAt ( 0 ) === "?" ) {
258+ queryDictionaryOrString = queryDictionaryOrString . substring ( 1 , queryDictionaryOrString . length ) ;
259+ }
260+
261+ if ( queryDictionaryOrString . indexOf ( "&" ) !== - 1 ) {
262+ const queryParams = queryDictionaryOrString . split ( "&" ) ;
263+ for ( const str of queryParams ) {
264+ this . parseQueryParamenterString ( str ) ;
265+ }
266+ } else {
267+ this . parseQueryParamenterString ( queryDictionaryOrString ) ;
268+ }
269+ } else {
270+ for ( const key in queryDictionaryOrString ) {
271+ if ( queryDictionaryOrString . hasOwnProperty ( key ) ) {
272+ this . setURLComponentsQueryParamater ( key , queryDictionaryOrString [ key ] ) ;
273+ }
274+ }
275+ }
276+
277+ return this ;
278+ }
279+
280+ /**
281+ * @private
282+ * @param query
283+ */
284+ private parseQueryParamenterString ( queryParameter : string ) : void {
285+ /* The query key-value pair must be split on the first equals sign to avoid errors in parsing nested query parameters.
286+ Example-> "/me?$expand=home($select=city)" */
287+ if ( this . isValidQueryKeyValuePair ( queryParameter ) ) {
288+ const indexOfFirstEquals = queryParameter . indexOf ( "=" ) ;
289+ const paramKey = queryParameter . substring ( 0 , indexOfFirstEquals ) ;
290+ const paramValue = queryParameter . substring ( indexOfFirstEquals + 1 , queryParameter . length ) ;
291+ this . setURLComponentsQueryParamater ( paramKey , paramValue ) ;
292+ } else {
293+ this . urlComponents . otherURLQueryStrings . push ( queryParameter ) ;
294+ }
295+ }
296+
297+ /**
298+ * @private
299+ * @param query
300+ */
301+ private setURLComponentsQueryParamater ( paramKey : string , paramValue : string | number ) : void {
302+ if ( oDataQueryNames . indexOf ( paramKey ) !== - 1 ) {
303+ const currentValue = this . urlComponents . oDataQueryParams [ paramKey ] ;
304+ const isValueAppendable = currentValue && ( paramKey === "$expand" || paramKey === "$select" || paramKey === "$orderby" ) ;
305+ this . urlComponents . oDataQueryParams [ paramKey ] = isValueAppendable ? currentValue + "," + paramValue : paramValue ;
306+ } else {
307+ this . urlComponents . otherURLQueryParams [ paramKey ] = paramValue ;
308+ }
309+ }
310+
311+ private isValidQueryKeyValuePair ( queryDictionaryOrString : string ) : boolean {
312+ const indexofFirstEquals = queryDictionaryOrString . indexOf ( "=" ) ;
313+ if ( indexofFirstEquals === - 1 ) {
314+ return false ;
315+ } else {
316+ const indexofOpeningParanthesis = queryDictionaryOrString . indexOf ( "(" ) ;
317+ if ( indexofOpeningParanthesis !== - 1 && queryDictionaryOrString . indexOf ( "(" ) < indexofFirstEquals ) {
318+ return false ;
319+ }
320+ }
321+ return true ;
322+ }
243323 /**
244324 * @private
245325 * Updates the custom headers and options for a request
@@ -494,30 +574,7 @@ export class GraphRequest {
494574 * @returns The same GraphRequest instance that is being called with
495575 */
496576 public query ( queryDictionaryOrString : string | KeyValuePairObjectStringNumber ) : GraphRequest {
497- let paramKey : string ;
498- let paramValue : string | number ;
499- if ( typeof queryDictionaryOrString === "string" ) {
500- /* The query key-value pair must be split on the first equals sign to avoid errors in parsing nested query parameters.
501- Example-> "/me?$expand=home($select=city)" */
502- const indexOfFirstEquals = queryDictionaryOrString . indexOf ( "=" ) ;
503- paramKey = queryDictionaryOrString . substring ( 0 , indexOfFirstEquals ) ;
504- paramValue = queryDictionaryOrString . substring ( indexOfFirstEquals + 1 , queryDictionaryOrString . length ) ;
505- } else {
506- for ( const key in queryDictionaryOrString ) {
507- if ( queryDictionaryOrString . hasOwnProperty ( key ) ) {
508- paramKey = key ;
509- paramValue = queryDictionaryOrString [ key ] ;
510- }
511- }
512- }
513- if ( oDataQueryNames . indexOf ( paramKey ) !== - 1 ) {
514- const currentValue = this . urlComponents . oDataQueryParams [ paramKey ] ;
515- const isValueAppendable = currentValue && ( paramKey === "$expand" || paramKey === "$select" || paramKey === "$orderby" ) ;
516- this . urlComponents . oDataQueryParams [ paramKey ] = isValueAppendable ? currentValue + "," + paramValue : paramValue ;
517- } else {
518- this . urlComponents . otherURLQueryParams [ paramKey ] = paramValue ;
519- }
520- return this ;
577+ return this . parseQueryParameter ( queryDictionaryOrString ) ;
521578 }
522579
523580 /**
0 commit comments