diff --git a/samples/react-msal-msgraph/.editorconfig b/samples/react-msal-msgraph/.editorconfig new file mode 100644 index 000000000..985fb1ffd --- /dev/null +++ b/samples/react-msal-msgraph/.editorconfig @@ -0,0 +1,25 @@ +# EditorConfig helps developers define and maintain consistent +# coding styles between different editors and IDEs +# editorconfig.org + +root = true + + +[*] + +# change these settings to your own preference +indent_style = space +indent_size = 4 + +# we recommend you to keep these unchanged +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.md] +trim_trailing_whitespace = false + +[{package,bower}.json] +indent_style = space +indent_size = 4 diff --git a/samples/react-msal-msgraph/.gitattributes b/samples/react-msal-msgraph/.gitattributes new file mode 100644 index 000000000..212566614 --- /dev/null +++ b/samples/react-msal-msgraph/.gitattributes @@ -0,0 +1 @@ +* text=auto \ No newline at end of file diff --git a/samples/react-msal-msgraph/.gitignore b/samples/react-msal-msgraph/.gitignore new file mode 100644 index 000000000..b19bbe123 --- /dev/null +++ b/samples/react-msal-msgraph/.gitignore @@ -0,0 +1,32 @@ +# Logs +logs +*.log +npm-debug.log* + +# Dependency directories +node_modules + +# Build generated files +dist +lib +solution +temp +*.sppkg + +# Coverage directory used by tools like istanbul +coverage + +# OSX +.DS_Store + +# Visual Studio files +.ntvs_analysis.dat +.vs +bin +obj + +# Resx Generated Code +*.resx.ts + +# Styles Generated Code +*.scss.ts diff --git a/samples/react-msal-msgraph/.npmignore b/samples/react-msal-msgraph/.npmignore new file mode 100644 index 000000000..2c93a9384 --- /dev/null +++ b/samples/react-msal-msgraph/.npmignore @@ -0,0 +1,14 @@ +# Folders +.vscode +coverage +node_modules +sharepoint +src +temp + +# Files +*.csproj +.git* +.yo-rc.json +gulpfile.js +tsconfig.json diff --git a/samples/react-msal-msgraph/.yo-rc.json b/samples/react-msal-msgraph/.yo-rc.json new file mode 100644 index 000000000..12a426f5a --- /dev/null +++ b/samples/react-msal-msgraph/.yo-rc.json @@ -0,0 +1,8 @@ +{ + "@microsoft/generator-sharepoint": { + "version": "1.1.1", + "libraryName": "react-msal-msgraph", + "libraryId": "169d1e68-4272-4d99-ac26-e4acd43d62fd", + "environment": "spo" + } +} \ No newline at end of file diff --git a/samples/react-msal-msgraph/README.md b/samples/react-msal-msgraph/README.md new file mode 100644 index 000000000..050ce7012 --- /dev/null +++ b/samples/react-msal-msgraph/README.md @@ -0,0 +1,73 @@ +# Microsoft Authentication Library (MSAL JS) authentication sample + +## Summary + +Sample SharePoint Framework web part which makes use of the [Microsoft Authentication Library (MSAL JS)](https://github.com/AzureAD/microsoft-authentication-library-for-js) to call the Microsoft Graph. + +### MSAL WP + +The sample web part will retrieve an access token with the `User.Read` and `Mail.Read` scope. Once an access token is retrieved, it will do a call to receive the current user and its mail messages. + +![Permission scopes](./assets/permission-scopes.png) + +After you gave permissions, the following will information will get displayed: + +![The MSAL web part displayed in SharePoint workbench](./assets/msal-wp-output.png) + +## Used SharePoint Framework Version +![drop](https://img.shields.io/badge/drop-GA-green.svg) + +## Applies to + +* [SharePoint Framework](http://dev.office.com/sharepoint/docs/spfx/sharepoint-framework-overview) +* [Office 365 developer tenant](http://dev.office.com/sharepoint/docs/spfx/set-up-your-developer-tenant) + +## Solution + +Solution|Author(s) +--------|--------- +react-msal-msgraph|Elio Struyf (MVP, [U2U](https://www.u2u.be), [@eliostruyf](https://www.twitter.com/eliostruyf)) + +## Version history + +Version|Date|Comments +-------|----|-------- +1.0.0|March 17, 2017|Initial release + +## Disclaimer +**THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.** + +--- + +## Prerequisites + +- Office 365 subscription with SharePoint Online and Exchange + +## Minimal Path to Awesome + +- Clone this repo +- Go and register a new application on [https://apps.dev.microsoft.com](https://apps.dev.microsoft.com) + - Once logged in, click on **add an app** + - Specify the application name, and click create + - Click on **add platform**, and choose **web** + - Specify the workbench URL and be sure that **allow implicit flow** is enabled + - Click on save to store these changes + +![Web URL configuration and implicit flow](./assets/redirect-url.png) + +- Copy the **application id** and change add this to the [MsalWP.tsx file on line 20](./src/webparts/msalWp/components/MsalWp.tsx#20) +- Run `npm i` +- Run `gulp serve --nobrowser` +- Test out your web part in the local or hosted workbench + +## Features + +Sample web part in this solution illustrates the following concepts on top of the SharePoint Framework: + +- using React for building SharePoint Framework client-side web parts +- using Office UI Fabric React styles for building user experience consistent with SharePoint and Office +- on-demand authentication with the Azure Active Directory using the MSAL JS library +- communicating with the Microsoft Graph using its REST API +- using the MSAL JS library with SharePoint Framework web parts built using React + +![](https://telemetry.sharepointpnp.com/sp-dev-fx-webparts/samples/react-msal-msgraph) diff --git a/samples/react-msal-msgraph/assets/msal-wp-output.png b/samples/react-msal-msgraph/assets/msal-wp-output.png new file mode 100644 index 000000000..ea60e33cc Binary files /dev/null and b/samples/react-msal-msgraph/assets/msal-wp-output.png differ diff --git a/samples/react-msal-msgraph/assets/permission-scopes.png b/samples/react-msal-msgraph/assets/permission-scopes.png new file mode 100644 index 000000000..94197b3df Binary files /dev/null and b/samples/react-msal-msgraph/assets/permission-scopes.png differ diff --git a/samples/react-msal-msgraph/assets/redirect-url.png b/samples/react-msal-msgraph/assets/redirect-url.png new file mode 100644 index 000000000..b30e013e2 Binary files /dev/null and b/samples/react-msal-msgraph/assets/redirect-url.png differ diff --git a/samples/react-msal-msgraph/config/config.json b/samples/react-msal-msgraph/config/config.json new file mode 100644 index 000000000..19515aa0f --- /dev/null +++ b/samples/react-msal-msgraph/config/config.json @@ -0,0 +1,16 @@ +{ + "entries": [{ + "entry": "./lib/webparts/msalWp/MsalWpWebPart.js", + "manifest": "./src/webparts/msalWp/MsalWpWebPart.manifest.json", + "outputPath": "./dist/msal-wp.bundle.js" + }], + "externals": { + "Msal": { + "path": "https://secure.aadcdn.microsoftonline-p.com/lib/0.1.1/js/msal.min.js", + "globalName": "Msal" + } + }, + "localizedResources": { + "msalWpStrings": "webparts/msalWp/loc/{locale}.js" + } +} diff --git a/samples/react-msal-msgraph/config/copy-assets.json b/samples/react-msal-msgraph/config/copy-assets.json new file mode 100644 index 000000000..6aca63656 --- /dev/null +++ b/samples/react-msal-msgraph/config/copy-assets.json @@ -0,0 +1,3 @@ +{ + "deployCdnPath": "temp/deploy" +} diff --git a/samples/react-msal-msgraph/config/deploy-azure-storage.json b/samples/react-msal-msgraph/config/deploy-azure-storage.json new file mode 100644 index 000000000..2732c291f --- /dev/null +++ b/samples/react-msal-msgraph/config/deploy-azure-storage.json @@ -0,0 +1,6 @@ +{ + "workingDir": "./temp/deploy/", + "account": "", + "container": "react-msal-msgraph", + "accessKey": "" +} \ No newline at end of file diff --git a/samples/react-msal-msgraph/config/package-solution.json b/samples/react-msal-msgraph/config/package-solution.json new file mode 100644 index 000000000..559dc848f --- /dev/null +++ b/samples/react-msal-msgraph/config/package-solution.json @@ -0,0 +1,10 @@ +{ + "solution": { + "name": "react-msal-msgraph-client-side-solution", + "id": "169d1e68-4272-4d99-ac26-e4acd43d62fd", + "version": "1.0.0.0" + }, + "paths": { + "zippedPackage": "solution/react-msal-msgraph.sppkg" + } +} diff --git a/samples/react-msal-msgraph/config/serve.json b/samples/react-msal-msgraph/config/serve.json new file mode 100644 index 000000000..087899637 --- /dev/null +++ b/samples/react-msal-msgraph/config/serve.json @@ -0,0 +1,9 @@ +{ + "port": 4321, + "initialPage": "https://localhost:5432/workbench", + "https": true, + "api": { + "port": 5432, + "entryPath": "node_modules/@microsoft/sp-webpart-workbench/lib/api/" + } +} diff --git a/samples/react-msal-msgraph/config/tslint.json b/samples/react-msal-msgraph/config/tslint.json new file mode 100644 index 000000000..1e8687a2b --- /dev/null +++ b/samples/react-msal-msgraph/config/tslint.json @@ -0,0 +1,45 @@ +{ + // Display errors as warnings + "displayAsWarning": true, + // The TSLint task may have been configured with several custom lint rules + // before this config file is read (for example lint rules from the tslint-microsoft-contrib + // project). If true, this flag will deactivate any of these rules. + "removeExistingRules": true, + // When true, the TSLint task is configured with some default TSLint "rules.": + "useDefaultConfigAsBase": false, + // Since removeExistingRules=true and useDefaultConfigAsBase=false, there will be no lint rules + // which are active, other than the list of rules below. + "lintConfig": { + // Opt-in to Lint rules which help to eliminate bugs in JavaScript + "rules": { + "class-name": false, + "export-name": false, + "forin": false, + "label-position": false, + "member-access": true, + "no-arg": false, + "no-console": false, + "no-construct": false, + "no-duplicate-case": true, + "no-duplicate-variable": true, + "no-eval": false, + "no-function-expression": true, + "no-internal-module": true, + "no-shadowed-variable": true, + "no-switch-case-fall-through": true, + "no-unnecessary-semicolons": true, + "no-unused-expression": true, + "no-unused-imports": true, + "no-use-before-declare": true, + "no-with-statement": true, + "semicolon": true, + "trailing-comma": false, + "typedef": false, + "typedef-whitespace": false, + "use-named-parameter": true, + "valid-typeof": true, + "variable-name": false, + "whitespace": false + } + } +} \ No newline at end of file diff --git a/samples/react-msal-msgraph/config/write-manifests.json b/samples/react-msal-msgraph/config/write-manifests.json new file mode 100644 index 000000000..0a4bafb06 --- /dev/null +++ b/samples/react-msal-msgraph/config/write-manifests.json @@ -0,0 +1,3 @@ +{ + "cdnBasePath": "" +} \ No newline at end of file diff --git a/samples/react-msal-msgraph/gulpfile.js b/samples/react-msal-msgraph/gulpfile.js new file mode 100644 index 000000000..7d36ddb1c --- /dev/null +++ b/samples/react-msal-msgraph/gulpfile.js @@ -0,0 +1,6 @@ +'use strict'; + +const gulp = require('gulp'); +const build = require('@microsoft/sp-build-web'); + +build.initialize(gulp); diff --git a/samples/react-msal-msgraph/package.json b/samples/react-msal-msgraph/package.json new file mode 100644 index 000000000..60cf8aac2 --- /dev/null +++ b/samples/react-msal-msgraph/package.json @@ -0,0 +1,34 @@ +{ + "name": "react-msal-msgraph", + "version": "0.0.1", + "private": true, + "engines": { + "node": ">=0.10.0" + }, + "dependencies": { + "@microsoft/sp-core-library": "~1.1.0", + "@microsoft/sp-webpart-base": "~1.1.1", + "@types/react": "0.14.46", + "@types/react-addons-shallow-compare": "0.14.17", + "@types/react-addons-test-utils": "0.14.15", + "@types/react-addons-update": "0.14.14", + "@types/react-dom": "0.14.18", + "@types/webpack-env": ">=1.12.1 <1.14.0", + "msal": "0.1.1", + "react": "15.4.2", + "react-dom": "15.4.2" + }, + "devDependencies": { + "@microsoft/sp-build-web": "~1.1.0", + "@microsoft/sp-module-interfaces": "~1.1.0", + "@microsoft/sp-webpart-workbench": "~1.1.0", + "@types/chai": ">=3.4.34 <3.6.0", + "@types/mocha": ">=2.2.33 <2.6.0", + "gulp": "~3.9.1" + }, + "scripts": { + "build": "gulp bundle", + "clean": "gulp clean", + "test": "gulp test" + } +} diff --git a/samples/react-msal-msgraph/src/webparts/msalWp/IMsalWpWebPartProps.ts b/samples/react-msal-msgraph/src/webparts/msalWp/IMsalWpWebPartProps.ts new file mode 100644 index 000000000..3f5393da5 --- /dev/null +++ b/samples/react-msal-msgraph/src/webparts/msalWp/IMsalWpWebPartProps.ts @@ -0,0 +1,3 @@ +export interface IMsalWpWebPartProps { + description: string; +} diff --git a/samples/react-msal-msgraph/src/webparts/msalWp/MsalWpWebPart.manifest.json b/samples/react-msal-msgraph/src/webparts/msalWp/MsalWpWebPart.manifest.json new file mode 100644 index 000000000..06c54c65f --- /dev/null +++ b/samples/react-msal-msgraph/src/webparts/msalWp/MsalWpWebPart.manifest.json @@ -0,0 +1,26 @@ +{ + "$schema": "../../../node_modules/@microsoft/sp-module-interfaces/lib/manifestSchemas/jsonSchemas/clientSideComponentManifestSchema.json", + + "id": "5ff21af8-04ea-478a-a640-919b29ba5ff4", + "alias": "MsalWpWebPart", + "componentType": "WebPart", + "version": "*", // The "*" signifies that the version should be taken from the package.json + "manifestVersion": 2, + + /** + * This property should only be set to true if it is certain that the webpart does not + * allow arbitrary scripts to be called + */ + "safeWithCustomScriptDisabled": false, + + "preconfiguredEntries": [{ + "groupId": "5ff21af8-04ea-478a-a640-919b29ba5ff4", + "group": { "default": "Under Development" }, + "title": { "default": "MSAL WP" }, + "description": { "default": "MSAL WP description" }, + "officeFabricIconFontName": "Page", + "properties": { + "description": "MSAL WP" + } + }] +} diff --git a/samples/react-msal-msgraph/src/webparts/msalWp/MsalWpWebPart.ts b/samples/react-msal-msgraph/src/webparts/msalWp/MsalWpWebPart.ts new file mode 100644 index 000000000..0012bc5cd --- /dev/null +++ b/samples/react-msal-msgraph/src/webparts/msalWp/MsalWpWebPart.ts @@ -0,0 +1,54 @@ +import * as React from 'react'; +import * as ReactDom from 'react-dom'; +import { Version } from '@microsoft/sp-core-library'; +import { + BaseClientSideWebPart, + IPropertyPaneConfiguration, + PropertyPaneTextField +} from '@microsoft/sp-webpart-base'; + +import * as strings from 'msalWpStrings'; +import MsalWp from './components/MsalWp'; +import { IMsalWpProps } from './components/IMsalWpProps'; +import { IMsalWpWebPartProps } from './IMsalWpWebPartProps'; + +export default class MsalWpWebPart extends BaseClientSideWebPart { + + public render(): void { + const element: React.ReactElement = React.createElement( + MsalWp, + { + description: this.properties.description, + context: this.context + } + ); + + ReactDom.render(element, this.domElement); + } + + protected get dataVersion(): Version { + return Version.parse('1.0'); + } + + protected getPropertyPaneConfiguration(): IPropertyPaneConfiguration { + return { + pages: [ + { + header: { + description: strings.PropertyPaneDescription + }, + groups: [ + { + groupName: strings.BasicGroupName, + groupFields: [ + PropertyPaneTextField('description', { + label: strings.DescriptionFieldLabel + }) + ] + } + ] + } + ] + }; + } +} diff --git a/samples/react-msal-msgraph/src/webparts/msalWp/components/IMsalWpProps.ts b/samples/react-msal-msgraph/src/webparts/msalWp/components/IMsalWpProps.ts new file mode 100644 index 000000000..f7f08ced3 --- /dev/null +++ b/samples/react-msal-msgraph/src/webparts/msalWp/components/IMsalWpProps.ts @@ -0,0 +1,35 @@ +import { IWebPartContext } from "@microsoft/sp-webpart-base"; + +export interface IMsalWpProps { + description: string; + context: IWebPartContext; +} + +export interface IMsalWpState { + loading?: boolean; + loggedIn?: boolean; + person?: IPerson; + mails?: IMail[]; +} + +export interface IPerson { + id: string; + businessPhones?: any[]; + displayName?: string; + givenName?: string; + jobTitle?: string; + mail?: string; + mobilePhone?: any; + officeLocation?: any; + preferredLanguage?: string; + surname?: string; + userPrincipalName?: string; +} + +export interface IMails { + value: IMail[]; +} + +export interface IMail { + subject: string; +} diff --git a/samples/react-msal-msgraph/src/webparts/msalWp/components/MsalWp.module.scss b/samples/react-msal-msgraph/src/webparts/msalWp/components/MsalWp.module.scss new file mode 100644 index 000000000..92279d009 --- /dev/null +++ b/samples/react-msal-msgraph/src/webparts/msalWp/components/MsalWp.module.scss @@ -0,0 +1,11 @@ +.msalWp { + .container { + max-width: 700px; + margin: 0px auto; + box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2), 0 25px 50px 0 rgba(0, 0, 0, 0.1); + } + + .row { + padding: 20px; + } +} diff --git a/samples/react-msal-msgraph/src/webparts/msalWp/components/MsalWp.tsx b/samples/react-msal-msgraph/src/webparts/msalWp/components/MsalWp.tsx new file mode 100644 index 000000000..74daa8a11 --- /dev/null +++ b/samples/react-msal-msgraph/src/webparts/msalWp/components/MsalWp.tsx @@ -0,0 +1,190 @@ +/// + +import * as React from 'react'; +import styles from './MsalWp.module.scss'; +import { IMsalWpProps, IMsalWpState, IPerson, IMails, IMail } from './IMsalWpProps'; +import { HttpClient } from "@microsoft/sp-http"; +import { PrimaryButton, Persona, PersonaSize, PersonaInitialsColor, List, Spinner, SpinnerType } from 'office-ui-fabric-react'; + +/** + * Load the MSAL library + */ +require('Msal'); +declare const Msal; + +/** + * MSAL Config + * Register your app here: https://apps.dev.microsoft.com/ + */ +const msalconfig = { + clientID: "00000000-0000-0000-0000-000000000000", // Azure AD Application + redirectUri: location.origin +}; + +const scopes = ["User.Read", "Mail.Read"]; + +export default class MsalWp extends React.Component { + private clientApplication: Msal.UserAgentApplication; + + constructor(props: IMsalWpProps) { + super(props); + + // Set the initial state of the component + this.state = { + loading: false, + loggedIn: false, + person: null, + mails: [] + }; + + // Initialize the user agent application for MSAL + if (!this.clientApplication) { + this.clientApplication = new Msal.UserAgentApplication(msalconfig.clientID, null, (errorDesc, token, error, tokenType) => { + // Called after loginRedirect or acquireTokenPopup + }); + } + + // Check if the user can be retrieved and automatically get your data + if (this.clientApplication.getUser()) { + this._getAccessToken(); + } + + this._login = this._login.bind(this); + this._getAccessToken = this._getAccessToken.bind(this); + this._getCrntUser = this._getCrntUser.bind(this); + this._getMessages = this._getMessages.bind(this); + } + + /** + * Function that will login the user and call the Microsoft Graph + */ + private _login(): void { + // Login the user + if (this.clientApplication.getUser()) { + this._getAccessToken(); + } else { + this.clientApplication.loginPopup(scopes).then((idToken: string) => { + this._getAccessToken(); + }); + } + } + + /** + * Retrieve an accessToken for the Microsoft Graph + */ + private _getAccessToken(): void { + this.state = { + loading: true + }; + // Retrieve a accessToken to call the Microsoft Graph + this.clientApplication.acquireTokenSilent(scopes).then((token: string) => { + this._getCrntUser(token); + this._getMessages(token); + }, (error) => { + // Interaction required + if (error) { + this.clientApplication.acquireTokenPopup(scopes).then((token: string) => { + this._getCrntUser(token); + this._getMessages(token); + }, (err: string) => { + // Something went wrong + console.log('Error:', err); + this.setState({ + loading: false + }); + }); + } + }); + } + + /** + * Call the current user via the Microsoft Graph + */ + private _getCrntUser(token: string): void { + // Call the Microsoft Graph + this.props.context.httpClient.get('https://graph.microsoft.com/v1.0/me', HttpClient.configurations.v1, { + headers: { + "authorization": `Bearer ${token}` + } + }).then(response => { + return response.json(); + }).then((data: IPerson) => { + this.setState({ + loggedIn: true, + person: data, + loading: false + }); + }); + } + + /** + * Get the mails of the current user + */ + private _getMessages(token: string): void { + // Call the Microsoft Graph + this.props.context.httpClient.get('https://graph.microsoft.com/v1.0/me/messages', HttpClient.configurations.v1, { + headers: { + "authorization": `Bearer ${token}` + } + }).then(response => { + return response.json(); + }).then((data: IMails) => { + this.setState({ + mails: data.value, + loading: false + }); + }); + } + + /** + * Component render + */ + public render(): React.ReactElement { + if (this.state.loading) { + return ; + } + + const loginBtn: JSX.Element = this.state.loggedIn ?
: ; + + let userInfo: JSX.Element =
; + if (this.state.loggedIn && this.state.person) { + userInfo = ; + } + + let mails: JSX.Element =
; + if (this.state.mails.length > 0) { + mails =

Your mails

; + } + + return ( +
+
+
+
+

SPFx WP sample with the MSAL library

+ + {loginBtn} + + {userInfo} + + {mails} + + ( +
{index++}: {item.subject}
+ )} /> +
+
+
+
+ ); + } +} diff --git a/samples/react-msal-msgraph/src/webparts/msalWp/loc/en-us.js b/samples/react-msal-msgraph/src/webparts/msalWp/loc/en-us.js new file mode 100644 index 000000000..89f98bc1e --- /dev/null +++ b/samples/react-msal-msgraph/src/webparts/msalWp/loc/en-us.js @@ -0,0 +1,7 @@ +define([], function() { + return { + "PropertyPaneDescription": "Description", + "BasicGroupName": "Group Name", + "DescriptionFieldLabel": "Description Field" + } +}); \ No newline at end of file diff --git a/samples/react-msal-msgraph/src/webparts/msalWp/loc/mystrings.d.ts b/samples/react-msal-msgraph/src/webparts/msalWp/loc/mystrings.d.ts new file mode 100644 index 000000000..8542ee09a --- /dev/null +++ b/samples/react-msal-msgraph/src/webparts/msalWp/loc/mystrings.d.ts @@ -0,0 +1,10 @@ +declare interface IMsalWpStrings { + PropertyPaneDescription: string; + BasicGroupName: string; + DescriptionFieldLabel: string; +} + +declare module 'msalWpStrings' { + const strings: IMsalWpStrings; + export = strings; +} diff --git a/samples/react-msal-msgraph/src/webparts/msalWp/tests/MsalWp.test.ts b/samples/react-msal-msgraph/src/webparts/msalWp/tests/MsalWp.test.ts new file mode 100644 index 000000000..0bd4ecadf --- /dev/null +++ b/samples/react-msal-msgraph/src/webparts/msalWp/tests/MsalWp.test.ts @@ -0,0 +1,9 @@ +/// + +import { assert } from 'chai'; + +describe('MsalWpWebPart', () => { + it('should do something', () => { + assert.ok(true); + }); +}); diff --git a/samples/react-msal-msgraph/tsconfig.json b/samples/react-msal-msgraph/tsconfig.json new file mode 100644 index 000000000..20a531bae --- /dev/null +++ b/samples/react-msal-msgraph/tsconfig.json @@ -0,0 +1,16 @@ +{ + "compilerOptions": { + "target": "es5", + "forceConsistentCasingInFileNames": true, + "module": "commonjs", + "jsx": "react", + "declaration": true, + "sourceMap": true, + "experimentalDecorators": true, + "types": [ + "es6-promise", + "es6-collections", + "webpack-env" + ] + } +} diff --git a/samples/react-msal-msgraph/typings/@ms/odsp.d.ts b/samples/react-msal-msgraph/typings/@ms/odsp.d.ts new file mode 100644 index 000000000..5a2404000 --- /dev/null +++ b/samples/react-msal-msgraph/typings/@ms/odsp.d.ts @@ -0,0 +1,11 @@ +// Type definitions for Microsoft ODSP projects +// Project: ODSP + +/* Global definition for UNIT_TEST builds + Code that is wrapped inside an if(UNIT_TEST) {...} + block will not be included in the final bundle when the + --ship flag is specified */ +declare const UNIT_TEST: boolean; + +/* Global defintion for SPO builds */ +declare const DATACENTER: boolean; \ No newline at end of file diff --git a/samples/react-msal-msgraph/typings/tsd.d.ts b/samples/react-msal-msgraph/typings/tsd.d.ts new file mode 100644 index 000000000..e7efdd728 --- /dev/null +++ b/samples/react-msal-msgraph/typings/tsd.d.ts @@ -0,0 +1 @@ +///