From b15a400560425fecbf9d13b5be297a366535c924 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Levert?= Date: Wed, 14 Dec 2022 16:42:34 -0500 Subject: [PATCH 1/8] Initial push of selective imports --- design/kiota-e2e.md | 229 -------------------------------------- design/service-library.md | 160 ++++++++++++++++++++++++++ 2 files changed, 160 insertions(+), 229 deletions(-) delete mode 100644 design/kiota-e2e.md create mode 100644 design/service-library.md diff --git a/design/kiota-e2e.md b/design/kiota-e2e.md deleted file mode 100644 index 31e776c5a..000000000 --- a/design/kiota-e2e.md +++ /dev/null @@ -1,229 +0,0 @@ -# End-to-end usage of kiota-generated SDKs in Javascript - -While working with the Kiota + Javascript teams, it became clear that we needed more context and provide a better vision on how we should be using a kiota-generated SDK. This design document aims at providing clarity and a better understanding on how developers will be using our SDKs and the underlying kiota packages. - -## Status - -| Date | Version | Author | Status | -| ------------------- | ------- | ---------------- | ------ | -| February 15th, 2022 | v0.2 | Sébastien Levert | Draft | -| January 17th, 2022 | v0.1 | Sébastien Levert | Draft | - -## Constraints - -Before we jump into the end-to-end walk-through, it's important to set some constraints. - -| Type | Environment | Description | -| --------- | ----------- | ------------------------------------------------------------------------------------------------- | -| Platforms | Node | Current and Previous LTS (14 / 16) | -| Platforms | Web | Edge, Chrome, Firefox and Safari (Latest released version + immediate previous version) | -| Modules | Node | ESM + CJS | -| Modules | Web | ESM | -| Types | All | Typings / Models should be available for both the core and the service libraries for Graph models | - -## Table of Contents - -- [NodeJS e2e using the Service library](#node-service-library) -- [NodeJS e2e using the Core library](#node-core-library) - -## NodeJS e2e using the Service library - -### Concept - -This example is utilizing both the core and the service library. That means that as a developer, we want the full fluent API, allowing me discover APIs via the intellisence. Because the service library leverages the core library, we also want to highlight that we can leverage the core components directly (like the `.api()` method). - -### Install the Microsoft Graph Javascript Service Library - -There will be two versions of the service library for the Graph Javascript SDK. The default one will bring the representation of the v1.0 of Microsoft Graph. The second one will bring the representation of the beta of Microsoft Graph. This will be the only difference between these two libraries, as all the handcrafted code (delivering authentication, middlewares, tasks, etc.) will happen in the core library. - -The Microsoft Graph Javascript Service Library includes the following packages: - -- `@microsoft/msgraph-sdk-javascript` ([npm](https://www.npmjs.com/package/@microsoft/msgraph-sdk-javascript-core)) - The service library for making fluent calls to Microsoft Graph v1.0. -- `@microsoft/msgraph-sdk-javascript-beta` ([npm](https://www.npmjs.com/package/@microsoft/msgraph-sdk-javascript-type)) - The service library for making fluent calls to Microsoft Graph beta. - -You can use [npm](https://www.npmjs.com) to install the Microsoft Graph Javascript Service Library : - -```shell -npm install @microsoft/msgraph-sdk-javascript --save -``` - -### Importing the right functionalities from the Graph Javascript Service Library - -```typescript -// App.ts - -import { Client } from "@microsoft/msgraph-sdk-javascript"; -import { User, Message, BodyType } from "@microsoft/msgraph-sdk-javascript/models"; - -// The authentication providers would get re-exported from @microsoft/msgraph-sdk-javascript-core/authentication -import { AzureIdentityAuthenticationProvider } from "@microsoft/msgraph-sdk-javascript/authentication"; -import { DeviceCodeCredential } from "@azure/identity"; -``` - -### Setting up the app to work with the Graph Javascript Service Library - -```typescript -const deviceCodeCredentials = new DeviceCodeCredential({ - tenantId: "b61f9af1-d6cf-4cc0-a6f6-befb38bc00ed", - clientId: "bde251a6-0ef9-42a8-a40b-9ad9bb594b2c", -}); - -const scopes = ["User.Read", "Mail.Send"]; - -const graphClient = Client.init({ - authenticationTokenProvider: new AzureIdentityAuthenticationProvider(deviceCodeCredentials, scopes), -}); -``` - -### Calling Microsoft Graph via the Graph Javascript Service Library - -The core value of the Microsoft Graph Javascript Service Library is the availability of the Fluent API. This provides developers with typechecking and discoverability when building on Microsoft Graph. This Fluent API is made available via the Request Builder concept and highlights the full spectrum of capabilities on Microsoft Graph. - -Models are also available in this package and should reflect the underlying version of Graph we are targeting. Developers using our types should do it in a way that will be familiar to how they are used to with other SDKs and APIs. We should provide an easy-to-use model that feels natural in the Javascript world. This means we should not be forcing developers to use Classes and / or other structures that will make their code less natural to them. - -We have an open issue about the above topic that can be followed here : [TypeScript - Use of interface models instead of class models](https://github.com/microsoft/kiota/issues/1013) - -```typescript -const me: User | undefined = await getMe(); -const meRaw: User | undefined = await getMeRaw(); -await sendMail(); -await sendMailRaw(); - -// The types returned by the fluent API should be the same as the .api() area. It should also be the same (or at least very similar) as the current @microsoft/microsoft-graph-types to offer seamless migration. -async function getMe(): Promise { - return await graphClient.me.get(); -} - -// Allowing raw calls (using the .api() method instead of the full fluent API) is important for migration purposes and cases we don't know the resource beforehands (thinking Graph Explorer, mgt-get, etc.) -async function getMeRaw(): Promise { - return await graphClient.api("/me").get(); -} - -// Sending an email via the fluent API -async function sendMail(): Promise { - const message: Message = { - subject: "Hello Graph TypeScript SDK!", - body: { - contentType: BodyType.Html, - content: "Hello Graph TypeScript SDK!", - }, - toRecipients: [ - { - emailAddress: { - address: "admin@m365x263716.onmicrosoft.com", - }, - }, - ], - }; - - return await client.me.sendMail.post(message); -} - -// Sending the email via the .api() method -async function sendMailRaw(): Promise { - const message: Message = { - subject: "Hello Graph TypeScript SDK!", - body: { - contentType: BodyType.Html, - content: "Hello Graph TypeScript SDK!", - }, - toRecipients: [ - { - emailAddress: { - address: "admin@m365x263716.onmicrosoft.com", - }, - }, - ], - }; - - return await client.api("/me/sendMail").post({ - message: message, - }); -} -``` - -## NodeJS e2e using the Core library - -### Concept - -This example brings very similar concepts, but utilizing only the core library. That means that as a developer, we only care about the core capabilities (authentication, serialization, etc.) but we don't need / want the fluent API. This also highlights that types are still important in this case (similarly to how they were important with the v3 of the SDK using our Typings). - -### Install the Microsoft Graph Javascript Core SDK - -The Microsoft Graph Javascript Core SDK includes the following packages: - -- `@microsoft/msgraph-sdk-javascript-core` ([npm](https://www.npmjs.com/package/@microsoft/msgraph-sdk-javascript))- The core library for making calls to Microsoft Graph. -- `@microsoft/msgraph-sdk-javascript-type` ([npm](https://www.npmjs.com/package/@microsoft/msgraph-sdk-javascript-type)) - The Typescript types for the Microsoft Graph entities. - -You can use [npm](https://www.npmjs.com) to install the Microsoft Graph Javascript SDK: - -```Shell -npm install @microsoft/msgraph-sdk-javascript-core --save -npm install @microsoft/msgraph-sdk-javascript-types --save-dev -``` - -As a developer, the only package you really need is the `@microsoft/msgraph-sdk-javascript-core` one. This will deliver the expected capabilities (authentication, middlewares, tasks, etc.) and should be used in a comprehensive way for existing NodeJS developers. The types are recommended but optional. - -### Importing the right functionalities from the Graph Javascript Core SDK - -```typescript -import { Client } from "@microsoft/msgraph-sdk-javascript-core"; -import { User, Message, BodyType } from "@microsoft/msgraph-sdk-javascript-core-types"; -import { AzureIdentityAuthenticationProvider } from "@microsoft/msgraph-sdk-javascript-core/authentication"; -import { DeviceCodeCredential } from "@azure/identity"; -``` - -### Setting up the app to work with the Graph Javascript Core SDK - -There should not be a difference between using the core library and the service library. The setup code should remain the same to deliver a simplified developer experience. - -```typescript -const deviceCodeCredentials = new DeviceCodeCredential({ - tenantId: "b61f9af1-d6cf-4cc0-a6f6-befb38bc00ed", - clientId: "bde251a6-0ef9-42a8-a40b-9ad9bb594b2c", -}); - -const scopes = ["User.Read", "Mail.Send"]; - -const graphClient = Client.init({ - authenticationTokenProvider: new AzureIdentityAuthenticationProvider(deviceCodeCredentials, scopes), -}); -``` - -### Calling Microsoft Graph via the Graph Javascript Core SDK - -Calling the API should be done in a familiar way and should most importantly return the same models that the service library returns. That means that I can build on top of either modules without the need to redefine the types that I'll be receiving back from the API. - -Developers using our types should do it in a way that will be familiar to how they are used to with other SDKs and APIs. We should provide an easy-to-use model that feels natural in the Javascript world. This means we should not be forcing developers to use Classes and / or other structures that will make their code less natural to them. - -We have an open issue about the above topic that can be followed here : [TypeScript - Use of interface models instead of class models](https://github.com/microsoft/kiota/issues/1013) - -```typescript -const me: User = await getMe(); -await sendMail(); - -async function getMe(): Promise { - return await graphClient.api("/me").get(); -} - -async function sendMail(): Promise { - const message: Message = { - subject: "Hello Graph TypeScript SDK!", - body: { - contentType: BodyType.Html, - content: "Hello Graph TypeScript SDK!", - }, - toRecipients: [ - { - emailAddress: { - address: "admin@m365x263716.onmicrosoft.com", - }, - }, - ], - }; - - return await client.api("/me/sendMail").post({ - message: message, - }); -} -``` diff --git a/design/service-library.md b/design/service-library.md new file mode 100644 index 000000000..9deaf05e1 --- /dev/null +++ b/design/service-library.md @@ -0,0 +1,160 @@ +# End-to-end usage of kiota-generated API Clients in JavaScript + +While working with the Kiota + JavaScript teams, it became clear that we needed more context and provide a better vision on how we should be using a kiota-generated SDK. This design document aims at providing clarity and a better understanding on how developers will be using our SDKs and the underlying kiota packages. + +## Status + +| Date | Version | Author | Status | +| ------------------- | ------- | ---------------- | ------ | +| December 14th, 2022 | v0.3 | Sébastien Levert | Draft | +| February 15th, 2022 | v0.2 | Sébastien Levert | Draft | +| January 17th, 2022 | v0.1 | Sébastien Levert | Draft | + +## Constraints + +Before we jump into the end-to-end walk-through, it's important to set some constraints. + +| Type | Environment | Description | +| --------- | ----------- | ------------------------------------------------------------------------------------------------- | +| Platforms | Node | Current and 2 Previous LTS (14 / 16 / 18) | +| Platforms | Web | Edge, Chrome, Firefox and Safari (Latest released version + immediate previous version) | +| Modules | Node | ESM2019 + CJS | +| Modules | Web | ESM2019 | +| Types | All | Typings / Models should be available for both the core and the service libraries for Graph models | + +## NodeJS end-to-end using the Service library + +### Concept + +This example is utilizing both the core and the service library. That means that as a developer, we want the full fluent API, allowing me discover APIs via the intellisence. Because the service library leverages the core library, we also want to highlight that we can leverage the core components directly (like the `.api()` method). + +### Install the Microsoft Graph JavaScript Service Library + +There will be two versions of the service library for the Graph JavaScript SDK. The default one will bring the representation of the v1.0 of Microsoft Graph. The second one will bring the representation of the beta of Microsoft Graph. This will be the only difference between these two libraries, as all the handcrafted code (delivering authentication, middlewares, tasks, etc.) will happen in the core library. + +The Microsoft Graph JavaScript Service Library includes the following packages: + +- `@microsoft/microsoft-graph-client` ([npm](https://www.npmjs.com/package/@microsoft/microsoft-graph-client)) - The service library for making fluent calls to Microsoft Graph v1.0. +- `@microsoft/microsoft-graph-client-beta` ([npm](https://www.npmjs.com/package/@microsoft/microsoft-graph-client-beta)) - The service library for making fluent calls to Microsoft Graph beta. + +You can use [npm](https://www.npmjs.com) to install the Microsoft Graph JavaScript Service Library: + +```shell +npm install @microsoft/msgraph-sdk-javascript --save +``` + +### Importing the right functionalities from the Graph JavaScript Service Library + +```typescript +import { Client } from "@microsoft/microsoft-graph-client"; +import { User, Message, BodyType } from "@microsoft/microsoft-graph-client/models"; +import { AzureIdentityAuthenticationProvider } from "@microsoft/kiota-authentication-azure"; +import { DeviceCodeCredential } from "@azure/identity"; +``` + +### Setting up the app to work with the Graph JavaScript Service Library + +```typescript +const deviceCodeCredentials = new DeviceCodeCredential({ + tenantId: "b61f9af1-d6cf-4cc0-a6f6-befb38bc00ed", + clientId: "bde251a6-0ef9-42a8-a40b-9ad9bb594b2c", +}); + +const scopes = ["User.Read", "Mail.Send"]; + +const graphClient = Client.init({ + authenticationTokenProvider: new AzureIdentityAuthenticationProvider(deviceCodeCredentials, scopes), +}); +``` + +### Calling Microsoft Graph via the Graph JavaScript Service Library + +The core value of the Microsoft Graph JavaScript Service Library is the availability of the chaned request builder pattern (fluent API). This provides developers with typechecking and discoverability when building on Microsoft Graph. This would highlight the full spectrum of capabilities on Microsoft Graph directly in the SDK. + +Models are also available in this package and should reflect the underlying version of Graph we are targeting. Developers using our types should do it in a way that will be familiar to how they are used to with other SDKs and APIs. We should provide an easy-to-use model that feels natural in the JavaScript world. This means we should not be forcing developers to use Classes and / or other structures that will make their code less natural to them. + +Because of the richness of the Graph APIs, we are making a decision to allow developers to selectively import the areas of Graph they care about. This will provide a lightweight bundle size while still offering a good developer experience. + +### Selective Imports of the Graph area needed + +To offer a bundle size that fair to the developer, we are using a selective imports strategy. This strategy enables developers to bring only the endpoints they need from Graph. Developers would only see the root paths of Graph when using the API Client by default, and would need to import additional path with selective imports. + +
+ Using the service library without any selective imports +

+ +> **Note** +> This example works because `me` is at the root of the Graph Client + +```typescript +const me = await graphClient.me.get(); +``` +> **Note** +> This example works because `users` is at the root of the Graph Client + +```typescript +const users = await graphClient.users.get(); +``` +> **Warning** +> This example does not work because `usersById().directReports` is not available at the root of the Graph Client + +```typescript +const directReports = await graphClient.usersById("ab677c1b-50c6-4013-aa9f-792ed42c59c8").directReports.get(); +``` + +

+
+ +
+ Using the service library with selective imports +

+ +> **Note** +> This example works because `/users` is imported, making it available at the root of the Graph Client + +```typescript +import "@microsoft/microsoft-graph-client/users"; +const directReports = await graphClient.usersById("ab677c1b-50c6-4013-aa9f-792ed42c59c8").directReports.get(); +``` + +> **Note** +> This example does not work because `/me` is imported, making it available at the root of the Graph Client + +```typescript +import "@microsoft/microsoft-graph-client/me"; +const joinedTeams = await graphClient.me.joinedTeams.get(); +``` + +

+
+ + +```typescript +import "@microsoft/msgraph-sdk-javascript/me"; + +const me: User | undefined = await getMe(); +await sendMail(); + +async function getMe(): Promise { + return await graphClient.me.get(); +} + +async function sendMail(): Promise { + const message: Message = { + subject: "Hello Graph TypeScript SDK!", + body: { + contentType: BodyType.Html, + content: "Hello Graph TypeScript SDK!", + }, + toRecipients: [ + { + emailAddress: { + address: "admin@m365x263716.onmicrosoft.com", + }, + }, + ], + }; + + return await client.me.sendMail.post(message); +} +``` \ No newline at end of file From 1a515b9a1f0e5c5bc7e2024492b20fffe7525f78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Levert?= Date: Wed, 14 Dec 2022 20:05:07 -0500 Subject: [PATCH 2/8] Adding more selective imports scenarios --- design/service-library.md | 81 ++++++++++++++------------------------- 1 file changed, 29 insertions(+), 52 deletions(-) diff --git a/design/service-library.md b/design/service-library.md index 9deaf05e1..bfefe0ffa 100644 --- a/design/service-library.md +++ b/design/service-library.md @@ -75,86 +75,63 @@ Models are also available in this package and should reflect the underlying vers Because of the richness of the Graph APIs, we are making a decision to allow developers to selectively import the areas of Graph they care about. This will provide a lightweight bundle size while still offering a good developer experience. -### Selective Imports of the Graph area needed +### Selective Imports of the Graph areas needed To offer a bundle size that fair to the developer, we are using a selective imports strategy. This strategy enables developers to bring only the endpoints they need from Graph. Developers would only see the root paths of Graph when using the API Client by default, and would need to import additional path with selective imports. -
- Using the service library without any selective imports -

+#### Using the service library without any selective imports -> **Note** -> This example works because `me` is at the root of the Graph Client +> ❌ **Fails**
+> This example does not work because `usersById().directReports` is not available at the root of the Graph Client + +```typescript +const directReports = await graphClient.usersById("ab677c1b-50c6-4013-aa9f-792ed42c59c8").directReports.get(); +``` + +> ✅ **Succeeds**
+> This example succeeds because `me` is at the root of the Graph Client ```typescript const me = await graphClient.me.get(); ``` -> **Note** -> This example works because `users` is at the root of the Graph Client +> ✅ **Succeeds**
+> This example succeeds because `users` is at the root of the Graph Client ```typescript const users = await graphClient.users.get(); ``` -> **Warning** -> This example does not work because `usersById().directReports` is not available at the root of the Graph Client + +#### Using the service library with selective imports + +> ❌ **Fails**
+> This example fails because `@microsoft/microsoft-graph-client/users/item` is not imported and therefore not available on the Graph Client ```typescript +import "@microsoft/microsoft-graph-client/users"; const directReports = await graphClient.usersById("ab677c1b-50c6-4013-aa9f-792ed42c59c8").directReports.get(); ``` -

-
- -
- Using the service library with selective imports -

- -> **Note** -> This example works because `/users` is imported, making it available at the root of the Graph Client +> ✅ **Succeeds**
+> This example succeeds because `/users/item` is imported, making it available on the Graph Client ```typescript -import "@microsoft/microsoft-graph-client/users"; +import "@microsoft/microsoft-graph-client/users/item"; const directReports = await graphClient.usersById("ab677c1b-50c6-4013-aa9f-792ed42c59c8").directReports.get(); +const extensions = await graphClient.usersById("ab677c1b-50c6-4013-aa9f-792ed42c59c8").extensions.get(); ``` -> **Note** -> This example does not work because `/me` is imported, making it available at the root of the Graph Client +> ✅ **Succeeds**
+> This example succeeds because `/me` is imported, making it available at the root of the Graph Client ```typescript import "@microsoft/microsoft-graph-client/me"; const joinedTeams = await graphClient.me.joinedTeams.get(); ``` -

-
- +> ✅ **Succeeds**
+> This example succeeds because `/me` is imported, making it available at the root of the Graph Client ```typescript -import "@microsoft/msgraph-sdk-javascript/me"; - -const me: User | undefined = await getMe(); -await sendMail(); - -async function getMe(): Promise { - return await graphClient.me.get(); -} - -async function sendMail(): Promise { - const message: Message = { - subject: "Hello Graph TypeScript SDK!", - body: { - contentType: BodyType.Html, - content: "Hello Graph TypeScript SDK!", - }, - toRecipients: [ - { - emailAddress: { - address: "admin@m365x263716.onmicrosoft.com", - }, - }, - ], - }; - - return await client.me.sendMail.post(message); -} +import "@microsoft/microsoft-graph-client/me/insights"; +const trending = await graphClient.me.insights.trending.get(); ``` \ No newline at end of file From a62a360c3e03d000e305b4e40656ead0777064f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Levert?= Date: Wed, 14 Dec 2022 21:22:19 -0500 Subject: [PATCH 3/8] Completed first pass for the service library --- .../child-resources-remarks.png | Bin 0 -> 12726 bytes design/service-library.md | 64 ++++++++++++++++-- 2 files changed, 57 insertions(+), 7 deletions(-) create mode 100644 design/assets/service-library/child-resources-remarks.png diff --git a/design/assets/service-library/child-resources-remarks.png b/design/assets/service-library/child-resources-remarks.png new file mode 100644 index 0000000000000000000000000000000000000000..5d94510df26dc67462b126dc27576ecbdc1c6c9c GIT binary patch literal 12726 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
6x$f{AE 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 ✅ **Succeeds**
-> This example succeeds because `/me` is imported, making it available at the root of the Graph Client +> This example succeeds because `/users` is imported, making it available at the root of the Graph Client ```typescript import "@microsoft/microsoft-graph-client/me"; @@ -134,4 +138,50 @@ const joinedTeams = await graphClient.me.joinedTeams.get(); ```typescript import "@microsoft/microsoft-graph-client/me/insights"; const trending = await graphClient.me.insights.trending.get(); +``` + +#### In-Context Help + +To provide as much context as possible, all modules that are augmented should provide remarks on how to obtain the child resources they contain. This would be added as part of the attached comment block and visible in the developers IDEs. + +![Child resources remarks](assets/service-library/child-resources-remarks.png) + +### Use Request Configuration + +Using request configuration allows developers to personalize their requests with different configuration options. The following snippets demonstrate how developers should be using the API Client. + +```typescript +// Specifying only Query Parameters +const users = await graphClient.users.get({ + queryParameters: { + count: true + } +}); +``` + +```typescript +// Specifying Query Parameters and Headers +const users = await graphClient.users.get({ + queryParameters: { + count: true, + filter: "endsWith(mail, 'microsoft.com')", + orderby: "displayName", + select: "id,displayName,email", + search: 'displayName:room' + }, + headers: { + ConsistencyLevel: "Eventual" + } +}); +``` + +```typescript +// Specifying Middleware Options +graphClient.usersById("ab677c1b-50c6-4013-aa9f-792ed42c59c8").patch({ + displayName: "Megan Bowen" +}, { + options: [ + new RetryHandlerOptions({ maxRetries: 10 }) + ] +}); ``` \ No newline at end of file From 218bdac0342d09aa138025ba6aaf9786dcf1194c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Levert?= Date: Wed, 25 Jan 2023 16:22:09 -0500 Subject: [PATCH 4/8] Update design/service-library.md Co-authored-by: Vincent Biret --- design/service-library.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/design/service-library.md b/design/service-library.md index 264d86805..554bbf88d 100644 --- a/design/service-library.md +++ b/design/service-library.md @@ -71,7 +71,7 @@ const graphClient = Client.init({ ### Calling Microsoft Graph via the Graph JavaScript Service Library -The core value of the Microsoft Graph JavaScript Service Library is the availability of the chaned request builder pattern (fluent API). This provides developers with typechecking and discoverability when building on Microsoft Graph. This would highlight the full spectrum of capabilities on Microsoft Graph directly in the API Client. +The core value of the Microsoft Graph JavaScript Service Library is the availability of the chained request builder pattern (fluent API). This provides developers with typechecking and discoverability when building on Microsoft Graph. This would highlight the full spectrum of capabilities on Microsoft Graph directly in the API Client. Models are also available in this package and should reflect the underlying version of Graph we are targeting. Developers using our types should do it in a way that will be familiar to how they are used to with other API Clients and APIs. We should provide an easy-to-use model that feels natural in the JavaScript world. This means we should not be forcing developers to use Classes and / or other structures that will make their code less natural to them. From 403273f2c20d6ceb68be6d5781bcf3606f22cf0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Levert?= Date: Wed, 25 Jan 2023 16:23:09 -0500 Subject: [PATCH 5/8] Update design/service-library.md Co-authored-by: Vincent Biret --- design/service-library.md | 1 + 1 file changed, 1 insertion(+) diff --git a/design/service-library.md b/design/service-library.md index 554bbf88d..0be90acd1 100644 --- a/design/service-library.md +++ b/design/service-library.md @@ -129,6 +129,7 @@ const joinedTeams = await graphClient.me.joinedTeams.get(); ```typescript import "@microsoft/microsoft-graph-client/me"; +import "@microsoft/microsoft-graph-client/me/joinedTeams"; const joinedTeams = await graphClient.me.joinedTeams.get(); ``` From 2b80f74ea780984d1d54de9840b8ae4afec42bc2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Levert?= Date: Wed, 25 Jan 2023 16:23:19 -0500 Subject: [PATCH 6/8] Update design/service-library.md Co-authored-by: Vincent Biret --- design/service-library.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/design/service-library.md b/design/service-library.md index 0be90acd1..f60e1ec09 100644 --- a/design/service-library.md +++ b/design/service-library.md @@ -137,7 +137,9 @@ const joinedTeams = await graphClient.me.joinedTeams.get(); > This example succeeds because `/me` is imported, making it available at the root of the Graph Client ```typescript +import "@microsoft/microsoft-graph-client/me"; import "@microsoft/microsoft-graph-client/me/insights"; +import "@microsoft/microsoft-graph-client/me/insights/trending"; const trending = await graphClient.me.insights.trending.get(); ``` From 5ed7f713ab5570d7c4fee571a2ad496fb0a18273 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Levert?= Date: Wed, 25 Jan 2023 16:23:29 -0500 Subject: [PATCH 7/8] Update design/service-library.md Co-authored-by: Vincent Biret --- design/service-library.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/design/service-library.md b/design/service-library.md index f60e1ec09..5a0ba2490 100644 --- a/design/service-library.md +++ b/design/service-library.md @@ -173,7 +173,7 @@ const users = await graphClient.users.get({ search: 'displayName:room' }, headers: { - ConsistencyLevel: "Eventual" + ConsistencyLevel: ["Eventual"] } }); ``` From 25be3b3fbd07968595bc86a4c6cb025071478baf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Levert?= Date: Wed, 25 Jan 2023 16:25:33 -0500 Subject: [PATCH 8/8] Update design/service-library.md --- design/service-library.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/design/service-library.md b/design/service-library.md index 5a0ba2490..72e783ddf 100644 --- a/design/service-library.md +++ b/design/service-library.md @@ -16,7 +16,7 @@ Before we jump into the end-to-end walk-through, it's important to set some cons | Type | Environment | Description | | --------- | ----------- | ------------------------------------------------------------------------------------------------- | -| Platforms | Node | Current and 2 Previous LTS (14 / 16 / 18) | +| Platforms | Node | Current and 2 Previous LTS (16 / 18) | | Platforms | Web | Edge, Chrome, Firefox and Safari (Latest released version + immediate previous version) | | Modules | Node | ESM2019 + CJS | | Modules | Web | ESM2019 |