Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Optimizations for OData Handler and Batching Support #346

Merged
merged 12 commits into from
May 9, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions examples/odata-microsoft/.meshrc.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
sources:
- name: Microsoft Graph
handler:
odata:
baseUrl: https://graph.microsoft.com/v1.0
batch: json
operationHeaders:
Authorization: Bearer {context.accessToken}
74 changes: 74 additions & 0 deletions examples/odata-microsoft/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# GraphQL Mesh for Microsoft Graph

**Note:** This project is based on [Microsoft's GraphQL for Microsoft Graph Demo](https://github.com/microsoftgraph/graphql-demo)

## About
This is a *demo* that enables basic, read-only querying of the [Microsoft Graph API](https://developer.microsoft.com/en-us/graph/) using [GraphQL query syntax](http://graphql.org/learn/queries/). GraphQL enables clients to request exactly the resources and properties that they need instead of making REST requests for each resource and consolidating the responses. To create a GraphQL service, this demo translates the [Microsoft Graph OData $metadata document](https://graph.microsoft.com/v1.0/$metadata) to a GraphQL schema and generates the necessary resolvers. Please note we are providing this demo code for evaluation as-is.

![Animation of sample request](https://user-images.githubusercontent.com/20847995/81301438-b92aeb00-9081-11ea-8bd3-c9e10d73ac8f.gif)

## Installation
1. Clone the repo
2. Install dependencies (`npm install`)
3. Navigate to the [App Registration Portal](https://apps.dev.microsoft.com/), set up a [new web app](https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-v2-app-registration)
4. Configure App Id and redirect URIs in the AppConfiguration of build/index.html
5. Run `npm start` and go to `localhost:4000`

## Sample requests
#### Fetch recent emails

```graphql

{
me {
displayName
officeLocation
skills
messages {
subject
isRead
from {
emailAddress {
address
}
}
}
}
}
```


#### Fetch groups and members
```graphql
{
groups {
displayName
description
members {
id
}
}
}
```

#### Fetch files from OneDrive
```graphql
{
me {
drives {
quota {
used
remaining
}
root {
children {
name
size
lastModifiedDateTime
webUrl
}
}
}
}
}
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
query fetchFilesFromOneDrive {
me {
drives {
quota {
used
remaining
}
root {
children {
name
size
lastModifiedDateTime
webUrl
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
query fetchGroupsAndMembers {
groups {
displayName
description
members {
id
}
}
}
16 changes: 16 additions & 0 deletions examples/odata-microsoft/example-queries/fetchRecentEmails.graphql
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
query fetchRecentEmails {
me {
displayName
officeLocation
skills
messages {
subject
isRead
from {
emailAddress {
address
}
}
}
}
}
111 changes: 111 additions & 0 deletions examples/odata-microsoft/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
<html>

<head>
<title>MSGraphQL Demo</title>
<style>
body {
margin-top: 5%;
margin-left: 5%;
padding: 10px;
font-family: 'HelveticaNeue', 'Arial', sans-serif;
width: 25%;
text-align: left;
}

body>div {
padding: 10px;
}

button {
margin-top: 20px;
padding: 10px;
}

.hidden {
visibility: hidden
}

.visible {
visibility: visible
}

.response {
padding: 0px;
margin: 10px;
}
</style>
</head>

<body>
<script type="text/javascript" src="https://alcdn.msftauth.net/lib/1.3.0/js/msal.js" class='pre'></script>

<div>
<h2>Microsoft Graph GraphQL Demo</h2>
<div id='label'>Sign-in with org or personal account</div>
<button id='auth' onclick='login()'>Login</button>
</div>

<pre class='response'></pre>

<script class='pre'>
const applicationConfig = {
auth: {
clientId: '58503fd3-6d1d-4eb2-a3e7-f2c1a761480b',
// authority: "Enter_the_Cloud_Instance_Id_HereEnter_the_Tenant_Info_Here",
redirectUri: location.href,
},
cache: {
cacheLocation: "localStorage", // This configures where your cache will be stored
storeAuthStateInCookie: true, // Set this to "true" if you are having issues on IE11 or Edge
},
};

const tokenRequest = {
scopes: ['openid', 'profile', 'User.ReadWrite',
'User.Read', 'Sites.ReadWrite.All', 'Contacts.ReadWrite',
'Calendars.Read', 'Mail.Read', 'Device.Read',
'Files.Read.All', 'Mail.Read.Shared', 'People.Read',
'People.Read', 'Notes.Read.All', 'Tasks.Read', 'Mail.ReadWrite'],
};

const clientApplication = new Msal.UserAgentApplication(applicationConfig);
async function login() {
let idToken, tokenResponse;
try {
idToken = await clientApplication.loginPopup(tokenRequest);
} catch(e) {
logMessage('Error during login:\n' + e);
return;
}
try {
tokenResponse = await clientApplication.acquireTokenSilent(tokenRequest);
} catch(e) {
try {
tokenResponse = await clientApplication.acquireTokenPopup(tokenRequest)
}catch(e) {
logMessage('Error acquiring the popup:\n' + e);
return;
}
}

updateUI(tokenResponse);
}
function updateUI(tokenResponse) {
const userName = clientApplication.getAccount().name;
const authButton = document.getElementById('auth');
authButton.innerHTML = 'logout';
authButton.setAttribute('onclick', 'logout();');
const label = document.getElementById('label');
document.cookie = `accessToken=${tokenResponse.accessToken};expires=${tokenResponse.expiresOn.toUTCString()}`;
window.location.href = 'graphql/';
}
function logout() {
clientApplication.logout();
}
function logMessage(s) {
document.body.querySelector('.response').appendChild(document.createTextNode('\n' + s));
}
</script>
</body>

</html>
46 changes: 46 additions & 0 deletions examples/odata-microsoft/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
const express = require('express');
const graphqlHTTP = require('express-graphql');
const path = require('path');
const cookieParser = require('cookie-parser');
const fs = require('fs');

const port = process.env.PORT || 4000;

const { findAndParseConfig, getMesh } = require('@graphql-mesh/runtime');

async function main(){

const app = express();

console.log('Generating Mesh Instance...')
const config = await findAndParseConfig();
const { schema, contextBuilder } = await getMesh(config);

app.use(cookieParser());

app.get('/', function (req, res) {
res.sendFile(path.join(__dirname, '/index.html'));
});

const defaultQuery = fs.readFileSync('./example-queries/fetchRecentEmails.graphql', 'utf8');

app.use(
'/graphql/',
graphqlHTTP(async (req) => ({
schema,
context: await contextBuilder({
accessToken: req.cookies.accessToken,
}),
graphiql: {
defaultQuery
},
}))
);

app.listen(port);

console.log('Listening on ' + port)

}

main().catch(console.error);
17 changes: 17 additions & 0 deletions examples/odata-microsoft/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"name": "odata-microsoft-graph-example",
"version": "0.1.13",
"license": "MIT",
"private": true,
"scripts": {
"start": "node index.js"
},
"dependencies": {
"@graphql-mesh/runtime": "0.1.13",
"@graphql-mesh/odata": "0.1.13",
"graphql": "15.0.0",
"cookie-parser": "1.4.5",
"express": "4.17.1",
"express-graphql": "0.9.0"
}
}
3 changes: 3 additions & 0 deletions examples/odata-microsoft/sandbox.config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"template": "node"
}
3 changes: 2 additions & 1 deletion examples/odata-trippin/.meshrc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ sources:
- name: TripPin
handler:
odata:
baseUrl: https://services.odata.org/TripPinRESTierService/
baseUrl: https://services.odata.org/TripPinRESTierService
batch: multipart
2 changes: 1 addition & 1 deletion examples/odata-trippin/example.query.graphql
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
query GetPeople {
getPeople(queryOptions: { top: 2 }) {
People(queryOptions: { top: 2 }) {
UserName
FirstName
LastName
Expand Down
5 changes: 5 additions & 0 deletions packages/handlers/odata/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,18 @@
},
"devDependencies": {
"@types/graphql-fields": "1.3.2",
"@types/http-string-parser": "0.0.29",
"@types/jsdom": "16.2.1",
"@types/url-join": "4.0.0"
},
"dependencies": {
"@graphql-mesh/types": "0.1.13",
"@graphql-mesh/utils": "0.1.13",
"@graphql-toolkit/schema-merging": "0.10.6",
"http-string-parser": "0.0.6",
"dataloader": "2.0.0",
"fetchache": "0.0.3",
"graphql-compose": "7.14.4",
"graphql-fields": "2.0.3",
"graphql-scalars": "1.1.2",
"jsdom": "16.2.2",
Expand Down
Loading