UNPKG

27.3 kBPlain TextView Raw
1/**
2 * -------------------------------------------------------------------------------------------
3 * Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License.
4 * See License in the project root for license information.
5 * -------------------------------------------------------------------------------------------
6 */
7
8/**
9 * @module GraphRequest
10 */
11import { GraphClientError } from "./GraphClientError";
12import { GraphError } from "./GraphError";
13import { GraphErrorHandler } from "./GraphErrorHandler";
14import { oDataQueryNames, serializeContent, urlJoin } from "./GraphRequestUtil";
15import { GraphResponseHandler } from "./GraphResponseHandler";
16import { HTTPClient } from "./HTTPClient";
17import { ClientOptions } from "./IClientOptions";
18import { Context } from "./IContext";
19import { FetchOptions } from "./IFetchOptions";
20import { GraphRequestCallback } from "./IGraphRequestCallback";
21import { MiddlewareControl } from "./middleware/MiddlewareControl";
22import { MiddlewareOptions } from "./middleware/options/IMiddlewareOptions";
23import { RequestMethod } from "./RequestMethod";
24import { ResponseType } from "./ResponseType";
25/**
26 * @interface
27 * Signature to representing key value pairs
28 * @property {[key: string] : string | number} - The Key value pair
29 */
30interface KeyValuePairObjectStringNumber {
31 [key: string]: string | number;
32}
33
34/**
35 * @interface
36 * Signature to define URL components
37 * @template http://graph.microsoft.com/VERSION/PATH?QUERYSTRING&OTHER_QUERY_PARAMS
38 *
39 * @property {string} host - The host to which the request needs to be made
40 * @property {string} version - Version of the graph endpoint
41 * @property {string} [path] - The path of the resource request
42 * @property {KeyValuePairObjectStringNumber} oDataQueryParams - The oData Query Params
43 * @property {KeyValuePairObjectStringNumber} otherURLQueryParams - The other query params for a request
44 * @property {string[]} otherURLQueryOptions - The non key-value query parameters. Example- '/me?$whatif'
45 */
46export interface URLComponents {
47 host: string;
48 version: string;
49 path?: string;
50 oDataQueryParams: KeyValuePairObjectStringNumber;
51 otherURLQueryParams: KeyValuePairObjectStringNumber;
52 otherURLQueryOptions?: string[];
53}
54
55/**
56 * @class
57 * A Class representing GraphRequest
58 */
59export class GraphRequest {
60 /**
61 * @private
62 * A member variable to hold HTTPClient instance
63 */
64 private httpClient: HTTPClient;
65
66 /**
67 * @private
68 * A member variable to hold client options
69 */
70 private config: ClientOptions;
71
72 /**
73 * @private
74 * A member to hold URL Components data
75 */
76 private urlComponents: URLComponents;
77
78 /**
79 * @private
80 * A member to hold custom header options for a request
81 */
82 private _headers: HeadersInit;
83
84 /**
85 * @private
86 * A member to hold custom options for a request
87 */
88 private _options: FetchOptions;
89
90 /**
91 * @private
92 * A member to hold the array of middleware options for a request
93 */
94 private _middlewareOptions: MiddlewareOptions[];
95
96 /**
97 * @private
98 * A member to hold custom response type for a request
99 */
100 private _responseType: ResponseType;
101
102 /**
103 * @public
104 * @constructor
105 * Creates an instance of GraphRequest
106 * @param {HTTPClient} httpClient - The HTTPClient instance
107 * @param {ClientOptions} config - The options for making request
108 * @param {string} path - A path string
109 */
110 public constructor(httpClient: HTTPClient, config: ClientOptions, path: string) {
111 this.httpClient = httpClient;
112 this.config = config;
113 this.urlComponents = {
114 host: this.config.baseUrl,
115 version: this.config.defaultVersion,
116 oDataQueryParams: {},
117 otherURLQueryParams: {},
118 otherURLQueryOptions: [],
119 };
120 this._headers = {};
121 this._options = {};
122 this._middlewareOptions = [];
123 this.parsePath(path);
124 }
125
126 /**
127 * @private
128 * Parses the path string and creates URLComponents out of it
129 * @param {string} path - The request path string
130 * @returns Nothing
131 */
132 private parsePath = (path: string): void => {
133 // Strips out the base of the url if they passed in
134 if (path.indexOf("https://") !== -1) {
135 path = path.replace("https://", "");
136
137 // Find where the host ends
138 const endOfHostStrPos = path.indexOf("/");
139 if (endOfHostStrPos !== -1) {
140 // Parse out the host
141 this.urlComponents.host = "https://" + path.substring(0, endOfHostStrPos);
142 // Strip the host from path
143 path = path.substring(endOfHostStrPos + 1, path.length);
144 }
145
146 // Remove the following version
147 const endOfVersionStrPos = path.indexOf("/");
148 if (endOfVersionStrPos !== -1) {
149 // Parse out the version
150 this.urlComponents.version = path.substring(0, endOfVersionStrPos);
151 // Strip version from path
152 path = path.substring(endOfVersionStrPos + 1, path.length);
153 }
154 }
155
156 // Strip out any leading "/"
157 if (path.charAt(0) === "/") {
158 path = path.substr(1);
159 }
160
161 const queryStrPos = path.indexOf("?");
162 if (queryStrPos === -1) {
163 // No query string
164 this.urlComponents.path = path;
165 } else {
166 this.urlComponents.path = path.substr(0, queryStrPos);
167
168 // Capture query string into oDataQueryParams and otherURLQueryParams
169 const queryParams = path.substring(queryStrPos + 1, path.length).split("&");
170 for (const queryParam of queryParams) {
171 this.parseQueryParameter(queryParam);
172 }
173 }
174 };
175
176 /**
177 * @private
178 * Adds the query parameter as comma separated values
179 * @param {string} propertyName - The name of a property
180 * @param {string|string[]} propertyValue - The vale of a property
181 * @param {IArguments} additionalProperties - The additional properties
182 * @returns Nothing
183 */
184 private addCsvQueryParameter(propertyName: string, propertyValue: string | string[], additionalProperties: IArguments): void {
185 // If there are already $propertyName value there, append a ","
186 this.urlComponents.oDataQueryParams[propertyName] = this.urlComponents.oDataQueryParams[propertyName] ? this.urlComponents.oDataQueryParams[propertyName] + "," : "";
187
188 let allValues: string[] = [];
189
190 if (additionalProperties.length > 1 && typeof propertyValue === "string") {
191 allValues = Array.prototype.slice.call(additionalProperties);
192 } else if (typeof propertyValue === "string") {
193 allValues.push(propertyValue);
194 } else {
195 allValues = allValues.concat(propertyValue);
196 }
197
198 this.urlComponents.oDataQueryParams[propertyName] += allValues.join(",");
199 }
200
201 /**
202 * @private
203 * Builds the full url from the URLComponents to make a request
204 * @returns The URL string that is qualified to make a request to graph endpoint
205 */
206 private buildFullUrl(): string {
207 const url = urlJoin([this.urlComponents.host, this.urlComponents.version, this.urlComponents.path]) + this.createQueryString();
208
209 if (this.config.debugLogging) {
210 console.log(url);
211 }
212 return url;
213 }
214
215 /**
216 * @private
217 * Builds the query string from the URLComponents
218 * @returns The Constructed query string
219 */
220 private createQueryString(): string {
221 // Combining query params from oDataQueryParams and otherURLQueryParams
222 const urlComponents = this.urlComponents;
223 const query: string[] = [];
224 if (Object.keys(urlComponents.oDataQueryParams).length !== 0) {
225 for (const property in urlComponents.oDataQueryParams) {
226 if (Object.prototype.hasOwnProperty.call(urlComponents.oDataQueryParams, property)) {
227 query.push(property + "=" + urlComponents.oDataQueryParams[property]);
228 }
229 }
230 }
231 if (Object.keys(urlComponents.otherURLQueryParams).length !== 0) {
232 for (const property in urlComponents.otherURLQueryParams) {
233 if (Object.prototype.hasOwnProperty.call(urlComponents.otherURLQueryParams, property)) {
234 query.push(property + "=" + urlComponents.otherURLQueryParams[property]);
235 }
236 }
237 }
238
239 if (urlComponents.otherURLQueryOptions.length !== 0) {
240 for (const str of urlComponents.otherURLQueryOptions) {
241 query.push(str);
242 }
243 }
244 return query.length > 0 ? "?" + query.join("&") : "";
245 }
246
247 /**
248 * @private
249 * Parses the query parameters to set the urlComponents property of the GraphRequest object
250 * @param {string|KeyValuePairObjectStringNumber} queryDictionaryOrString - The query parameter
251 * @returns The same GraphRequest instance that is being called with
252 */
253 private parseQueryParameter(queryDictionaryOrString: string | KeyValuePairObjectStringNumber): GraphRequest {
254 if (typeof queryDictionaryOrString === "string") {
255 if (queryDictionaryOrString.charAt(0) === "?") {
256 queryDictionaryOrString = queryDictionaryOrString.substring(1);
257 }
258
259 if (queryDictionaryOrString.indexOf("&") !== -1) {
260 const queryParams = queryDictionaryOrString.split("&");
261 for (const str of queryParams) {
262 this.parseQueryParamenterString(str);
263 }
264 } else {
265 this.parseQueryParamenterString(queryDictionaryOrString);
266 }
267 } else if (queryDictionaryOrString.constructor === Object) {
268 for (const key in queryDictionaryOrString) {
269 if (Object.prototype.hasOwnProperty.call(queryDictionaryOrString, key)) {
270 this.setURLComponentsQueryParamater(key, queryDictionaryOrString[key]);
271 }
272 }
273 }
274
275 return this;
276 }
277
278 /**
279 * @private
280 * Parses the query parameter of string type to set the urlComponents property of the GraphRequest object
281 * @param {string} queryParameter - the query parameters
282 * returns nothing
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);
291 this.setURLComponentsQueryParamater(paramKey, paramValue);
292 } else {
293 /* Push values which are not of key-value structure.
294 Example-> Handle an invalid input->.query(test), .query($select($select=name)) and let the Graph API respond with the error in the URL*/
295 this.urlComponents.otherURLQueryOptions.push(queryParameter);
296 }
297 }
298
299 /**
300 * @private
301 * Sets values into the urlComponents property of GraphRequest object.
302 * @param {string} paramKey - the query parameter key
303 * @param {string} paramValue - the query paramter value
304 * @returns nothing
305 */
306 private setURLComponentsQueryParamater(paramKey: string, paramValue: string | number): void {
307 if (oDataQueryNames.indexOf(paramKey) !== -1) {
308 const currentValue = this.urlComponents.oDataQueryParams[paramKey];
309 const isValueAppendable = currentValue && (paramKey === "$expand" || paramKey === "$select" || paramKey === "$orderby");
310 this.urlComponents.oDataQueryParams[paramKey] = isValueAppendable ? currentValue + "," + paramValue : paramValue;
311 } else {
312 this.urlComponents.otherURLQueryParams[paramKey] = paramValue;
313 }
314 }
315 /**
316 * @private
317 * Check if the query parameter string has a valid key-value structure
318 * @param {string} queryString - the query parameter string. Example -> "name=value"
319 * #returns true if the query string has a valid key-value structure else false
320 */
321 private isValidQueryKeyValuePair(queryString: string): boolean {
322 const indexofFirstEquals = queryString.indexOf("=");
323 if (indexofFirstEquals === -1) {
324 return false;
325 }
326 const indexofOpeningParanthesis = queryString.indexOf("(");
327 if (indexofOpeningParanthesis !== -1 && queryString.indexOf("(") < indexofFirstEquals) {
328 // Example -> .query($select($expand=true));
329 return false;
330 }
331 return true;
332 }
333
334 /**
335 * @private
336 * Updates the custom headers and options for a request
337 * @param {FetchOptions} options - The request options object
338 * @returns Nothing
339 */
340 private updateRequestOptions(options: FetchOptions): void {
341 const optionsHeaders: HeadersInit = { ...options.headers };
342 if (this.config.fetchOptions !== undefined) {
343 const fetchOptions: FetchOptions = { ...this.config.fetchOptions };
344 Object.assign(options, fetchOptions);
345 if (typeof this.config.fetchOptions.headers !== undefined) {
346 options.headers = { ...this.config.fetchOptions.headers };
347 }
348 }
349 Object.assign(options, this._options);
350 if (options.headers !== undefined) {
351 Object.assign(optionsHeaders, options.headers);
352 }
353 Object.assign(optionsHeaders, this._headers);
354 options.headers = optionsHeaders;
355 }
356
357 /**
358 * @private
359 * @async
360 * Adds the custom headers and options to the request and makes the HTTPClient send request call
361 * @param {RequestInfo} request - The request url string or the Request object value
362 * @param {FetchOptions} options - The options to make a request
363 * @param {GraphRequestCallback} [callback] - The callback function to be called in response with async call
364 * @returns A promise that resolves to the response content
365 */
366 private async send(request: RequestInfo, options: FetchOptions, callback?: GraphRequestCallback): Promise<any> {
367 let rawResponse: Response;
368 const middlewareControl = new MiddlewareControl(this._middlewareOptions);
369 this.updateRequestOptions(options);
370 const customHosts = this.config?.customHosts;
371 try {
372 const context: Context = await this.httpClient.sendRequest({
373 request,
374 options,
375 middlewareControl,
376 customHosts,
377 });
378
379 rawResponse = context.response;
380 const response: any = await GraphResponseHandler.getResponse(rawResponse, this._responseType, callback);
381 return response;
382 } catch (error) {
383 if (error instanceof GraphClientError) {
384 throw error;
385 }
386 let statusCode: number;
387
388 if (rawResponse) {
389 statusCode = rawResponse.status;
390 }
391 const gError: GraphError = await GraphErrorHandler.getError(error, statusCode, callback);
392 throw gError;
393 }
394 }
395
396 /**
397 * @private
398 * Checks if the content-type is present in the _headers property. If not present, defaults the content-type to application/json
399 * @param none
400 * @returns nothing
401 */
402 private setHeaderContentType(): void {
403 if (!this._headers) {
404 this.header("Content-Type", "application/json");
405 return;
406 }
407 const headerKeys = Object.keys(this._headers);
408 for (const headerKey of headerKeys) {
409 if (headerKey.toLowerCase() === "content-type") {
410 return;
411 }
412 }
413 // Default the content-type to application/json in case the content-type is not present in the header
414 this.header("Content-Type", "application/json");
415 }
416
417 /**
418 * @public
419 * Sets the custom header for a request
420 * @param {string} headerKey - A header key
421 * @param {string} headerValue - A header value
422 * @returns The same GraphRequest instance that is being called with
423 */
424 public header(headerKey: string, headerValue: string): GraphRequest {
425 this._headers[headerKey] = headerValue;
426 return this;
427 }
428
429 /**
430 * @public
431 * Sets the custom headers for a request
432 * @param {KeyValuePairObjectStringNumber | HeadersInit} headers - The request headers
433 * @returns The same GraphRequest instance that is being called with
434 */
435 public headers(headers: KeyValuePairObjectStringNumber | HeadersInit): GraphRequest {
436 for (const key in headers) {
437 if (Object.prototype.hasOwnProperty.call(headers, key)) {
438 this._headers[key] = headers[key] as string;
439 }
440 }
441 return this;
442 }
443
444 /**
445 * @public
446 * Sets the option for making a request
447 * @param {string} key - The key value
448 * @param {any} value - The value
449 * @returns The same GraphRequest instance that is being called with
450 */
451 public option(key: string, value: any): GraphRequest {
452 this._options[key] = value;
453 return this;
454 }
455
456 /**
457 * @public
458 * Sets the options for making a request
459 * @param {{ [key: string]: any }} options - The options key value pair
460 * @returns The same GraphRequest instance that is being called with
461 */
462 public options(options: { [key: string]: any }): GraphRequest {
463 for (const key in options) {
464 if (Object.prototype.hasOwnProperty.call(options, key)) {
465 this._options[key] = options[key];
466 }
467 }
468 return this;
469 }
470
471 /**
472 * @public
473 * Sets the middleware options for a request
474 * @param {MiddlewareOptions[]} options - The array of middleware options
475 * @returns The same GraphRequest instance that is being called with
476 */
477 public middlewareOptions(options: MiddlewareOptions[]): GraphRequest {
478 this._middlewareOptions = options;
479 return this;
480 }
481
482 /**
483 * @public
484 * Sets the api endpoint version for a request
485 * @param {string} version - The version value
486 * @returns The same GraphRequest instance that is being called with
487 */
488 public version(version: string): GraphRequest {
489 this.urlComponents.version = version;
490 return this;
491 }
492
493 /**
494 * @public
495 * Sets the api endpoint version for a request
496 * @param {ResponseType} responseType - The response type value
497 * @returns The same GraphRequest instance that is being called with
498 */
499 public responseType(responseType: ResponseType): GraphRequest {
500 this._responseType = responseType;
501 return this;
502 }
503
504 /**
505 * @public
506 * To add properties for select OData Query param
507 * @param {string|string[]} properties - The Properties value
508 * @returns The same GraphRequest instance that is being called with, after adding the properties for $select query
509 */
510 /*
511 * Accepts .select("displayName,birthday")
512 * and .select(["displayName", "birthday"])
513 * and .select("displayName", "birthday")
514 *
515 */
516 public select(properties: string | string[]): GraphRequest {
517 this.addCsvQueryParameter("$select", properties, arguments);
518 return this;
519 }
520
521 /**
522 * @public
523 * To add properties for expand OData Query param
524 * @param {string|string[]} properties - The Properties value
525 * @returns The same GraphRequest instance that is being called with, after adding the properties for $expand query
526 */
527 public expand(properties: string | string[]): GraphRequest {
528 this.addCsvQueryParameter("$expand", properties, arguments);
529 return this;
530 }
531
532 /**
533 * @public
534 * To add properties for orderby OData Query param
535 * @param {string|string[]} properties - The Properties value
536 * @returns The same GraphRequest instance that is being called with, after adding the properties for $orderby query
537 */
538 public orderby(properties: string | string[]): GraphRequest {
539 this.addCsvQueryParameter("$orderby", properties, arguments);
540 return this;
541 }
542
543 /**
544 * @public
545 * To add query string for filter OData Query param. The request URL accepts only one $filter Odata Query option and its value is set to the most recently passed filter query string.
546 * @param {string} filterStr - The filter query string
547 * @returns The same GraphRequest instance that is being called with, after adding the $filter query
548 */
549 public filter(filterStr: string): GraphRequest {
550 this.urlComponents.oDataQueryParams.$filter = filterStr;
551 return this;
552 }
553
554 /**
555 * @public
556 * To add criterion for search OData Query param. The request URL accepts only one $search Odata Query option and its value is set to the most recently passed search criterion string.
557 * @param {string} searchStr - The search criterion string
558 * @returns The same GraphRequest instance that is being called with, after adding the $search query criteria
559 */
560 public search(searchStr: string): GraphRequest {
561 this.urlComponents.oDataQueryParams.$search = searchStr;
562 return this;
563 }
564
565 /**
566 * @public
567 * To add number for top OData Query param. The request URL accepts only one $top Odata Query option and its value is set to the most recently passed number value.
568 * @param {number} n - The number value
569 * @returns The same GraphRequest instance that is being called with, after adding the number for $top query
570 */
571 public top(n: number): GraphRequest {
572 this.urlComponents.oDataQueryParams.$top = n;
573 return this;
574 }
575
576 /**
577 * @public
578 * To add number for skip OData Query param. The request URL accepts only one $skip Odata Query option and its value is set to the most recently passed number value.
579 * @param {number} n - The number value
580 * @returns The same GraphRequest instance that is being called with, after adding the number for the $skip query
581 */
582 public skip(n: number): GraphRequest {
583 this.urlComponents.oDataQueryParams.$skip = n;
584 return this;
585 }
586
587 /**
588 * @public
589 * To add token string for skipToken OData Query param. The request URL accepts only one $skipToken Odata Query option and its value is set to the most recently passed token value.
590 * @param {string} token - The token value
591 * @returns The same GraphRequest instance that is being called with, after adding the token string for $skipToken query option
592 */
593 public skipToken(token: string): GraphRequest {
594 this.urlComponents.oDataQueryParams.$skipToken = token;
595 return this;
596 }
597
598 /**
599 * @public
600 * To add boolean for count OData Query param. The URL accepts only one $count Odata Query option and its value is set to the most recently passed boolean value.
601 * @param {boolean} isCount - The count boolean
602 * @returns The same GraphRequest instance that is being called with, after adding the boolean value for the $count query option
603 */
604 public count(isCount = true): GraphRequest {
605 this.urlComponents.oDataQueryParams.$count = isCount.toString();
606 return this;
607 }
608
609 /**
610 * @public
611 * Appends query string to the urlComponent
612 * @param {string|KeyValuePairObjectStringNumber} queryDictionaryOrString - The query value
613 * @returns The same GraphRequest instance that is being called with, after appending the query string to the url component
614 */
615 /*
616 * Accepts .query("displayName=xyz")
617 * and .select({ name: "value" })
618 */
619 public query(queryDictionaryOrString: string | KeyValuePairObjectStringNumber): GraphRequest {
620 return this.parseQueryParameter(queryDictionaryOrString);
621 }
622
623 /**
624 * @public
625 * @async
626 * Makes a http request with GET method
627 * @param {GraphRequestCallback} [callback] - The callback function to be called in response with async call
628 * @returns A promise that resolves to the get response
629 */
630 public async get(callback?: GraphRequestCallback): Promise<any> {
631 const url = this.buildFullUrl();
632 const options: FetchOptions = {
633 method: RequestMethod.GET,
634 };
635 const response = await this.send(url, options, callback);
636 return response;
637 }
638
639 /**
640 * @public
641 * @async
642 * Makes a http request with POST method
643 * @param {any} content - The content that needs to be sent with the request
644 * @param {GraphRequestCallback} [callback] - The callback function to be called in response with async call
645 * @returns A promise that resolves to the post response
646 */
647 public async post(content: any, callback?: GraphRequestCallback): Promise<any> {
648 const url = this.buildFullUrl();
649 const options: FetchOptions = {
650 method: RequestMethod.POST,
651 body: serializeContent(content),
652 };
653 const className: string = content && content.constructor && content.constructor.name;
654 if (className === "FormData") {
655 // Content-Type headers should not be specified in case the of FormData type content
656 options.headers = {};
657 } else {
658 this.setHeaderContentType();
659 options.headers = this._headers;
660 }
661 return await this.send(url, options, callback);
662 }
663
664 /**
665 * @public
666 * @async
667 * Alias for Post request call
668 * @param {any} content - The content that needs to be sent with the request
669 * @param {GraphRequestCallback} [callback] - The callback function to be called in response with async call
670 * @returns A promise that resolves to the post response
671 */
672 public async create(content: any, callback?: GraphRequestCallback): Promise<any> {
673 return await this.post(content, callback);
674 }
675
676 /**
677 * @public
678 * @async
679 * Makes http request with PUT method
680 * @param {any} content - The content that needs to be sent with the request
681 * @param {GraphRequestCallback} [callback] - The callback function to be called in response with async call
682 * @returns A promise that resolves to the put response
683 */
684 public async put(content: any, callback?: GraphRequestCallback): Promise<any> {
685 const url = this.buildFullUrl();
686 this.setHeaderContentType();
687 const options: FetchOptions = {
688 method: RequestMethod.PUT,
689 body: serializeContent(content),
690 };
691 return await this.send(url, options, callback);
692 }
693
694 /**
695 * @public
696 * @async
697 * Makes http request with PATCH method
698 * @param {any} content - The content that needs to be sent with the request
699 * @param {GraphRequestCallback} [callback] - The callback function to be called in response with async call
700 * @returns A promise that resolves to the patch response
701 */
702 public async patch(content: any, callback?: GraphRequestCallback): Promise<any> {
703 const url = this.buildFullUrl();
704 this.setHeaderContentType();
705 const options: FetchOptions = {
706 method: RequestMethod.PATCH,
707 body: serializeContent(content),
708 };
709 return await this.send(url, options, callback);
710 }
711
712 /**
713 * @public
714 * @async
715 * Alias for PATCH request
716 * @param {any} content - The content that needs to be sent with the request
717 * @param {GraphRequestCallback} [callback] - The callback function to be called in response with async call
718 * @returns A promise that resolves to the patch response
719 */
720 public async update(content: any, callback?: GraphRequestCallback): Promise<any> {
721 return await this.patch(content, callback);
722 }
723
724 /**
725 * @public
726 * @async
727 * Makes http request with DELETE method
728 * @param {GraphRequestCallback} [callback] - The callback function to be called in response with async call
729 * @returns A promise that resolves to the delete response
730 */
731 public async delete(callback?: GraphRequestCallback): Promise<any> {
732 const url = this.buildFullUrl();
733 const options: FetchOptions = {
734 method: RequestMethod.DELETE,
735 };
736 return await this.send(url, options, callback);
737 }
738
739 /**
740 * @public
741 * @async
742 * Alias for delete request call
743 * @param {GraphRequestCallback} [callback] - The callback function to be called in response with async call
744 * @returns A promise that resolves to the delete response
745 */
746 public async del(callback?: GraphRequestCallback): Promise<any> {
747 return await this.delete(callback);
748 }
749
750 /**
751 * @public
752 * @async
753 * Makes a http request with GET method to read response as a stream.
754 * @param {GraphRequestCallback} [callback] - The callback function to be called in response with async call
755 * @returns A promise that resolves to the getStream response
756 */
757 public async getStream(callback?: GraphRequestCallback): Promise<any> {
758 const url = this.buildFullUrl();
759 const options = {
760 method: RequestMethod.GET,
761 };
762 this.responseType(ResponseType.STREAM);
763 return await this.send(url, options, callback);
764 }
765
766 /**
767 * @public
768 * @async
769 * Makes a http request with GET method to read response as a stream.
770 * @param {any} stream - The stream instance
771 * @param {GraphRequestCallback} [callback] - The callback function to be called in response with async call
772 * @returns A promise that resolves to the putStream response
773 */
774 public async putStream(stream: any, callback?: GraphRequestCallback): Promise<any> {
775 const url = this.buildFullUrl();
776 const options = {
777 method: RequestMethod.PUT,
778 headers: {
779 "Content-Type": "application/octet-stream",
780 },
781 body: stream,
782 };
783 return await this.send(url, options, callback);
784 }
785}