55 * -------------------------------------------------------------------------------------------
66 */
77
8- import { Client , ResponseType } from '@microsoft/microsoft-graph-client' ;
8+ import { Client , GraphRequest , Middleware , MiddlewareOptions , ResponseType } from '@microsoft/microsoft-graph-client' ;
99import * as MicrosoftGraph from '@microsoft/microsoft-graph-types' ;
1010import * as MicrosoftGraphBeta from '@microsoft/microsoft-graph-types-beta' ;
11- import { IProvider , prepScopes } from '.' ;
1211import { MgtBaseComponent } from './components/baseComponent' ;
1312import { Batch } from './utils/Batch' ;
13+ import { ComponentMiddlewareOptions } from './utils/ComponentMiddlewareOptions' ;
14+ import { prepScopes } from './utils/GraphHelpers' ;
1415
1516/**
1617 * The base Graph implementation.
@@ -29,36 +30,54 @@ export abstract class BaseGraph {
2930 public client : Client ;
3031
3132 /**
32- * a provider used for making calls
33+ * name of a component for analytics
3334 *
3435 * @protected
35- * @type {IProvider }
36+ * @type {string }
3637 * @memberof BaseGraph
3738 */
38- protected _provider : IProvider ;
39-
40- constructor ( provider : IProvider ) {
41- this . _provider = provider ;
42- }
39+ protected componentName : string ;
4340
4441 /**
4542 * Returns a new instance of the Graph using the same
46- * provider and the provided component .
43+ * client within the context of the provider .
4744 *
4845 * @param {MgtBaseComponent } component
4946 * @returns
5047 * @memberof BaseGraph
5148 */
5249 public abstract forComponent ( component : MgtBaseComponent ) : BaseGraph ;
5350
51+ /**
52+ * Returns a new graph request for a specific component
53+ * Used internally for analytics purposes
54+ *
55+ * @param {string } path
56+ * @param {MgtBaseComponent } [component=null]
57+ * @memberof Graph
58+ */
59+ public api ( path : string ) : GraphRequest {
60+ let request = this . client . api ( path ) ;
61+ if ( this . componentName ) {
62+ request . middlewareOptions = ( options : MiddlewareOptions [ ] ) : GraphRequest => {
63+ const requestObj = request as any ;
64+ requestObj . _middlewareOptions = requestObj . _middlewareOptions . concat ( options ) ;
65+ return request ;
66+ } ;
67+ request = request . middlewareOptions ( [ new ComponentMiddlewareOptions ( this . componentName ) ] ) ;
68+ }
69+
70+ return request ;
71+ }
72+
5473 /**
5574 * creates batch request
5675 *
5776 * @returns
5877 * @memberof BaseGraph
5978 */
6079 public createBatch ( ) {
61- return new Batch ( this . client ) ;
80+ return new Batch ( this . client , this . componentName ) ;
6281 }
6382
6483 /**
@@ -68,8 +87,7 @@ export abstract class BaseGraph {
6887 * @memberof BaseGraph
6988 */
7089 public async getMe ( ) : Promise < MicrosoftGraph . User > {
71- return this . client
72- . api ( 'me' )
90+ return this . api ( 'me' )
7391 . middlewareOptions ( prepScopes ( 'user.read' ) )
7492 . get ( ) ;
7593 }
@@ -83,8 +101,7 @@ export abstract class BaseGraph {
83101 */
84102 public async getUser ( userPrincipleName : string ) : Promise < MicrosoftGraph . User > {
85103 const scopes = 'user.readbasic.all' ;
86- return this . client
87- . api ( `/users/${ userPrincipleName } ` )
104+ return this . api ( `/users/${ userPrincipleName } ` )
88105 . middlewareOptions ( prepScopes ( scopes ) )
89106 . get ( ) ;
90107 }
@@ -98,8 +115,7 @@ export abstract class BaseGraph {
98115 */
99116 public async findPerson ( query : string ) : Promise < MicrosoftGraph . Person [ ] > {
100117 const scopes = 'people.read' ;
101- const result = await this . client
102- . api ( '/me/people' )
118+ const result = await this . api ( '/me/people' )
103119 . search ( '"' + query + '"' )
104120 . middlewareOptions ( prepScopes ( scopes ) )
105121 . get ( ) ;
@@ -115,8 +131,7 @@ export abstract class BaseGraph {
115131 */
116132 public async findContactByEmail ( email : string ) : Promise < MicrosoftGraph . Contact [ ] > {
117133 const scopes = 'contacts.read' ;
118- const result = await this . client
119- . api ( '/me/contacts' )
134+ const result = await this . api ( '/me/contacts' )
120135 . filter ( `emailAddresses/any(a:a/address eq '${ email } ')` )
121136 . middlewareOptions ( prepScopes ( scopes ) )
122137 . get ( ) ;
@@ -194,8 +209,7 @@ export abstract class BaseGraph {
194209
195210 uri += `/calendarview?${ sdt } &${ edt } ` ;
196211
197- const calendarView = await this . client
198- . api ( uri )
212+ const calendarView = await this . api ( uri )
199213 . middlewareOptions ( prepScopes ( scopes ) )
200214 . orderby ( 'start/dateTime' )
201215 . get ( ) ;
@@ -212,8 +226,7 @@ export abstract class BaseGraph {
212226 const scopes = 'people.read' ;
213227
214228 const uri = '/me/people' ;
215- const people = await this . client
216- . api ( uri )
229+ const people = await this . api ( uri )
217230 . middlewareOptions ( prepScopes ( scopes ) )
218231 . filter ( "personType/class eq 'Person'" )
219232 . get ( ) ;
@@ -231,8 +244,7 @@ export abstract class BaseGraph {
231244 const scopes = 'people.read' ;
232245
233246 const uri = `/groups/${ groupId } /members` ;
234- const people = await this . client
235- . api ( uri )
247+ const people = await this . api ( uri )
236248 . middlewareOptions ( prepScopes ( scopes ) )
237249 . get ( ) ;
238250 return people ? people . value : null ;
@@ -249,8 +261,7 @@ export abstract class BaseGraph {
249261 const scopes = 'Group.Read.All' ;
250262
251263 const uri = `/groups/${ groupId } /planner/plans` ;
252- const plans = await this . client
253- . api ( uri )
264+ const plans = await this . api ( uri )
254265 . header ( 'Cache-Control' , 'no-store' )
255266 . middlewareOptions ( prepScopes ( scopes ) )
256267 . get ( ) ;
@@ -264,8 +275,7 @@ export abstract class BaseGraph {
264275 * @memberof BaseGraph
265276 */
266277 public async getAllMyPlannerPlans ( ) : Promise < MicrosoftGraph . PlannerPlan [ ] > {
267- const plans = await this . client
268- . api ( '/me/planner/plans' )
278+ const plans = await this . api ( '/me/planner/plans' )
269279 . header ( 'Cache-Control' , 'no-store' )
270280 . middlewareOptions ( prepScopes ( 'Group.Read.All' ) )
271281 . get ( ) ;
@@ -281,8 +291,7 @@ export abstract class BaseGraph {
281291 * @memberof BaseGraph
282292 */
283293 public async getSinglePlannerPlan ( planId : string ) : Promise < MicrosoftGraph . PlannerPlan > {
284- const plan = await this . client
285- . api ( `/planner/plans/${ planId } ` )
294+ const plan = await this . api ( `/planner/plans/${ planId } ` )
286295 . header ( 'Cache-Control' , 'no-store' )
287296 . middlewareOptions ( prepScopes ( 'Group.Read.All' ) )
288297 . get ( ) ;
@@ -298,8 +307,7 @@ export abstract class BaseGraph {
298307 * @memberof BaseGraph
299308 */
300309 public async getBucketsForPlannerPlan ( planId : string ) : Promise < MicrosoftGraph . PlannerBucket [ ] > {
301- const buckets = await this . client
302- . api ( `/planner/plans/${ planId } /buckets` )
310+ const buckets = await this . api ( `/planner/plans/${ planId } /buckets` )
303311 . header ( 'Cache-Control' , 'no-store' )
304312 . middlewareOptions ( prepScopes ( 'Group.Read.All' ) )
305313 . get ( ) ;
@@ -315,8 +323,7 @@ export abstract class BaseGraph {
315323 * @memberof BaseGraph
316324 */
317325 public async getTasksForPlannerBucket ( bucketId : string ) : Promise < MicrosoftGraph . PlannerTask [ ] > {
318- const tasks = await this . client
319- . api ( `/planner/buckets/${ bucketId } /tasks` )
326+ const tasks = await this . api ( `/planner/buckets/${ bucketId } /tasks` )
320327 . header ( 'Cache-Control' , 'no-store' )
321328 . middlewareOptions ( prepScopes ( 'Group.Read.All' ) )
322329 . get ( ) ;
@@ -334,8 +341,7 @@ export abstract class BaseGraph {
334341 * @memberof BaseGraph
335342 */
336343 public async setPlannerTaskDetails ( taskId : string , details : MicrosoftGraph . PlannerTask , eTag : string ) : Promise < any > {
337- return await this . client
338- . api ( `/planner/tasks/${ taskId } ` )
344+ return await this . api ( `/planner/tasks/${ taskId } ` )
339345 . header ( 'Cache-Control' , 'no-store' )
340346 . middlewareOptions ( prepScopes ( 'Group.ReadWrite.All' ) )
341347 . header ( 'If-Match' , eTag )
@@ -405,8 +411,7 @@ export abstract class BaseGraph {
405411 * @memberof BaseGraph
406412 */
407413 public async addPlannerTask ( newTask : MicrosoftGraph . PlannerTask ) : Promise < any > {
408- return this . client
409- . api ( '/planner/tasks' )
414+ return this . api ( '/planner/tasks' )
410415 . header ( 'Cache-Control' , 'no-store' )
411416 . middlewareOptions ( prepScopes ( 'Group.ReadWrite.All' ) )
412417 . post ( newTask ) ;
@@ -421,8 +426,7 @@ export abstract class BaseGraph {
421426 * @memberof BaseGraph
422427 */
423428 public async removePlannerTask ( taskId : string , eTag : string ) : Promise < any > {
424- return this . client
425- . api ( `/planner/tasks/${ taskId } ` )
429+ return this . api ( `/planner/tasks/${ taskId } ` )
426430 . header ( 'Cache-Control' , 'no-store' )
427431 . header ( 'If-Match' , eTag )
428432 . middlewareOptions ( prepScopes ( 'Group.ReadWrite.All' ) )
@@ -438,8 +442,7 @@ export abstract class BaseGraph {
438442 * @memberof BaseGraph
439443 */
440444 public async getAllMyTodoGroups ( ) : Promise < MicrosoftGraphBeta . OutlookTaskGroup [ ] > {
441- const groups = await this . client
442- . api ( '/me/outlook/taskGroups' )
445+ const groups = await this . api ( '/me/outlook/taskGroups' )
443446 . header ( 'Cache-Control' , 'no-store' )
444447 . version ( 'beta' )
445448 . middlewareOptions ( prepScopes ( 'Tasks.Read' ) )
@@ -456,8 +459,7 @@ export abstract class BaseGraph {
456459 * @memberof BaseGraph
457460 */
458461 public async getSingleTodoGroup ( groupId : string ) : Promise < MicrosoftGraphBeta . OutlookTaskGroup > {
459- const group = await this . client
460- . api ( `/me/outlook/taskGroups/${ groupId } ` )
462+ const group = await this . api ( `/me/outlook/taskGroups/${ groupId } ` )
461463 . header ( 'Cache-Control' , 'no-store' )
462464 . version ( 'beta' )
463465 . middlewareOptions ( prepScopes ( 'Tasks.Read' ) )
@@ -474,8 +476,7 @@ export abstract class BaseGraph {
474476 * @memberof BaseGraph
475477 */
476478 public async getFoldersForTodoGroup ( groupId : string ) : Promise < MicrosoftGraphBeta . OutlookTaskFolder [ ] > {
477- const folders = await this . client
478- . api ( `/me/outlook/taskGroups/${ groupId } /taskFolders` )
479+ const folders = await this . api ( `/me/outlook/taskGroups/${ groupId } /taskFolders` )
479480 . header ( 'Cache-Control' , 'no-store' )
480481 . version ( 'beta' )
481482 . middlewareOptions ( prepScopes ( 'Tasks.Read' ) )
@@ -492,8 +493,7 @@ export abstract class BaseGraph {
492493 * @memberof BaseGraph
493494 */
494495 public async getAllTodoTasksForFolder ( folderId : string ) : Promise < MicrosoftGraphBeta . OutlookTask [ ] > {
495- const tasks = await this . client
496- . api ( `/me/outlook/taskFolders/${ folderId } /tasks` )
496+ const tasks = await this . api ( `/me/outlook/taskFolders/${ folderId } /tasks` )
497497 . header ( 'Cache-Control' , 'no-store' )
498498 . version ( 'beta' )
499499 . middlewareOptions ( prepScopes ( 'Tasks.Read' ) )
@@ -512,8 +512,7 @@ export abstract class BaseGraph {
512512 * @memberof BaseGraph
513513 */
514514 public async setTodoTaskDetails ( taskId : string , task : any , eTag : string ) : Promise < MicrosoftGraphBeta . OutlookTask > {
515- return await this . client
516- . api ( `/me/outlook/tasks/${ taskId } ` )
515+ return await this . api ( `/me/outlook/tasks/${ taskId } ` )
517516 . header ( 'Cache-Control' , 'no-store' )
518517 . version ( 'beta' )
519518 . header ( 'If-Match' , eTag )
@@ -570,15 +569,13 @@ export abstract class BaseGraph {
570569 const { parentFolderId = null } = newTask ;
571570
572571 if ( parentFolderId ) {
573- return await this . client
574- . api ( `/me/outlook/taskFolders/${ parentFolderId } /tasks` )
572+ return await this . api ( `/me/outlook/taskFolders/${ parentFolderId } /tasks` )
575573 . header ( 'Cache-Control' , 'no-store' )
576574 . version ( 'beta' )
577575 . middlewareOptions ( prepScopes ( 'Tasks.ReadWrite' ) )
578576 . post ( newTask ) ;
579577 } else {
580- return await this . client
581- . api ( '/me/outlook/tasks' )
578+ return await this . api ( '/me/outlook/tasks' )
582579 . header ( 'Cache-Control' , 'no-store' )
583580 . version ( 'beta' )
584581 . middlewareOptions ( prepScopes ( 'Tasks.ReadWrite' ) )
@@ -595,15 +592,35 @@ export abstract class BaseGraph {
595592 * @memberof BaseGraph
596593 */
597594 public async removeTodoTask ( taskId : string , eTag : string ) : Promise < any > {
598- return await this . client
599- . api ( `/me/outlook/tasks/${ taskId } ` )
595+ return await this . api ( `/me/outlook/tasks/${ taskId } ` )
600596 . header ( 'Cache-Control' , 'no-store' )
601597 . version ( 'beta' )
602598 . header ( 'If-Match' , eTag )
603599 . middlewareOptions ( prepScopes ( 'Tasks.ReadWrite' ) )
604600 . delete ( ) ;
605601 }
606602
603+ /**
604+ * Helper method to chain Middleware when instantiating new Client
605+ *
606+ * @protected
607+ * @param {...Middleware[] } middleware
608+ * @returns {Middleware }
609+ * @memberof BaseGraph
610+ */
611+ protected chainMiddleware ( ...middleware : Middleware [ ] ) : Middleware {
612+ const rootMiddleware = middleware [ 0 ] ;
613+ let current = rootMiddleware ;
614+ for ( let i = 1 ; i < middleware . length ; ++ i ) {
615+ const next = middleware [ i ] ;
616+ if ( current . setNext ) {
617+ current . setNext ( next ) ;
618+ }
619+ current = next ;
620+ }
621+ return rootMiddleware ;
622+ }
623+
607624 private blobToBase64 ( blob : Blob ) : Promise < string > {
608625 return new Promise ( ( resolve , reject ) => {
609626 const reader = new FileReader ( ) ;
@@ -617,8 +634,7 @@ export abstract class BaseGraph {
617634
618635 private async getPhotoForResource ( resource : string , scopes : string [ ] ) : Promise < string > {
619636 try {
620- const blob = await this . client
621- . api ( `${ resource } /photo/$value` )
637+ const blob = await this . api ( `${ resource } /photo/$value` )
622638 . version ( 'beta' )
623639 . responseType ( ResponseType . BLOB )
624640 . middlewareOptions ( prepScopes ( ...scopes ) )
0 commit comments