-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
React sample integrating with Azure SDKs (#12924)
## What Adds a React sample that integrates with multiple Azure services ## Why As part of our investigation into how well our SDKs integrate into existing frameworks we created a few sample apps that showcase how to use the various SDKs. Adding a sample here would ensure that we have something to reference and provide to folks who are interested in using our SDKs in React.
- Loading branch information
Showing
19 changed files
with
894 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,154 @@ | ||
{ | ||
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", | ||
"contentVersion": "1.0.0.0", | ||
"parameters": { | ||
"baseName": { | ||
"type": "string", | ||
"defaultValue": "[resourceGroup().name]", | ||
"metadata": { | ||
"description": "The base resource name." | ||
} | ||
}, | ||
"origin": { | ||
"type": "string", | ||
"defaultValue": "http://localhost:3000", | ||
"metadata": { | ||
"description": "The application origin for configuring CORS policies. By default it'll be set to http://localhost:3000 locally." | ||
} | ||
} | ||
}, | ||
"variables": { | ||
"eventHubsName": "events", | ||
"eventHubsNamespace": "[concat(parameters('baseName'), 'reactevents')]", | ||
"storageAccount": "[concat(parameters('baseName'), 'reactstorage')]", | ||
"storageContainer": "[concat(parameters('baseName'), 'reactstorage', '/default/blobs')]", | ||
"location": "[resourceGroup().location]" | ||
}, | ||
"resources": [ | ||
{ | ||
"type": "Microsoft.EventHub/namespaces", | ||
"apiVersion": "2018-01-01-preview", | ||
"name": "[variables('eventHubsNamespace')]", | ||
"location": "[variables('location')]", | ||
"sku": { | ||
"name": "Basic", | ||
"tier": "Basic", | ||
"capacity": 1 | ||
}, | ||
"properties": { | ||
"zoneRedundant": false, | ||
"isAutoInflateEnabled": false, | ||
"maximumThroughputUnits": 0, | ||
"kafkaEnabled": false | ||
} | ||
}, | ||
{ | ||
"type": "Microsoft.Storage/storageAccounts", | ||
"apiVersion": "2020-08-01-preview", | ||
"name": "[variables('storageAccount')]", | ||
"location": "[variables('location')]", | ||
"sku": { | ||
"name": "Standard_RAGRS", | ||
"tier": "Standard" | ||
}, | ||
"kind": "StorageV2", | ||
"properties": { | ||
"networkAcls": { | ||
"bypass": "AzureServices", | ||
"virtualNetworkRules": [], | ||
"ipRules": [], | ||
"defaultAction": "Allow" | ||
}, | ||
"supportsHttpsTrafficOnly": true, | ||
"encryption": { | ||
"services": { | ||
"file": { | ||
"keyType": "Account", | ||
"enabled": true | ||
}, | ||
"blob": { | ||
"keyType": "Account", | ||
"enabled": true | ||
} | ||
}, | ||
"keySource": "Microsoft.Storage" | ||
}, | ||
"accessTier": "Hot" | ||
} | ||
}, | ||
{ | ||
"type": "Microsoft.EventHub/namespaces/eventhubs", | ||
"apiVersion": "2017-04-01", | ||
"name": "[concat(variables('eventHubsNamespace'), '/', variables('eventHubsName'))]", | ||
"location": "[variables('location')]", | ||
"dependsOn": [ | ||
"[resourceId('Microsoft.EventHub/namespaces', variables('eventHubsNamespace'))]" | ||
], | ||
"properties": { | ||
"messageRetentionInDays": 1, | ||
"partitionCount": 2, | ||
"status": "Active" | ||
} | ||
}, | ||
{ | ||
"type": "Microsoft.Storage/storageAccounts/blobServices", | ||
"apiVersion": "2020-08-01-preview", | ||
"name": "[concat(variables('storageAccount'), '/default')]", | ||
"dependsOn": [ | ||
"[resourceId('Microsoft.Storage/storageAccounts', variables('storageAccount'))]" | ||
], | ||
"sku": { | ||
"name": "Standard_RAGRS", | ||
"tier": "Standard" | ||
}, | ||
"properties": { | ||
"cors": { | ||
"corsRules": [ | ||
{ | ||
"allowedOrigins": ["[parameters('origin')]"], | ||
"allowedMethods": ["GET", "OPTIONS", "PUT", "POST"], | ||
"maxAgeInSeconds": 0, | ||
"exposedHeaders": ["*"], | ||
"allowedHeaders": ["*"] | ||
} | ||
] | ||
}, | ||
"deleteRetentionPolicy": { | ||
"enabled": false | ||
} | ||
} | ||
}, | ||
{ | ||
"type": "Microsoft.Storage/storageAccounts/blobServices/containers", | ||
"apiVersion": "2020-08-01-preview", | ||
"name": "[variables('storageContainer')]", | ||
"dependsOn": [ | ||
"[resourceId('Microsoft.Storage/storageAccounts/blobServices', variables('storageAccount'), 'default')]", | ||
"[resourceId('Microsoft.Storage/storageAccounts', variables('storageAccount'))]" | ||
], | ||
"properties": { | ||
"defaultEncryptionScope": "$account-encryption-key", | ||
"denyEncryptionScopeOverride": false, | ||
"publicAccess": "None" | ||
} | ||
} | ||
], | ||
"outputs": { | ||
"react_app_event_hubs_namespace": { | ||
"type": "string", | ||
"value": "[concat(variables('eventHubsNamespace'), '.servicebus.windows.net')]" | ||
}, | ||
"react_app_event_hubs_name": { | ||
"type": "string", | ||
"value": "[variables('eventHubsName')]" | ||
}, | ||
"react_app_blob_uri": { | ||
"type": "string", | ||
"value": "[reference(variables('storageAccount')).primaryEndpoints.blob]" | ||
}, | ||
"react_app_blob_container": { | ||
"type": "string", | ||
"value": "[last(split(variables('storageContainer'), '/'))]" | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
{ | ||
"parser": "@typescript-eslint/parser", | ||
"parserOptions": { | ||
"ecmaVersion": 2020, | ||
"sourceType": "module", | ||
"ecmaFeatures": { | ||
"jsx": true | ||
} | ||
}, | ||
"rules": { | ||
"react/prop-types": 0 | ||
}, | ||
"settings": { | ||
"react": { | ||
"version": "detect" | ||
} | ||
}, | ||
"extends": [ | ||
"plugin:react/recommended", | ||
"plugin:@typescript-eslint/recommended", | ||
"prettier/@typescript-eslint", | ||
"plugin:prettier/recommended" | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
# Azure SDK samples for React (TypeScript) | ||
|
||
This sample application shows how to use the TypeScript client libraries for Azure in some common scenarios. | ||
|
||
In this sample, we build a simple Todo application in React using [create-react-app][react] and integrating with various Azure services. | ||
|
||
- Integration with Azure Event Hubs to support real-time updates across multiple instances of the application. | ||
- Integration with Azure Storage Blob for persisting ToDo items. | ||
|
||
## Prerequisites | ||
|
||
The samples are compatible with Node.js >= 8.0.0. | ||
|
||
Before running the samples in Node, they must be compiled to JavaScript using the TypeScript compiler. For more information on TypeScript, see the [TypeScript documentation][typescript]. | ||
|
||
You need [an Azure subscription][freesub] and the following resources created to run this sample: | ||
|
||
- An Azure Event Hubs namespace. Please refer to the [Event Hubs documentation][eventhubs] for additional information on Event Hubs. | ||
- An Azure Storage Blob container. Please refer to the [Storage Blob documentation][storageblob] for additional information on Azure Storage Blob. This file will be fetched from Azure Storage Blob and displayed on the screen. | ||
- Finally, you'll need a way to authenticate the application with Azure. Please refer to the [@azure/identity][identity] package for information on authentication. The instructions below will walk you through the necessary steps. | ||
|
||
To quickly create the needed resources in Azure and to receive the necessary environment variables for them, you can deploy our sample template by clicking: | ||
|
||
[![](http://azuredeploy.net/deploybutton.png)](https://portal.azure.com/#create/Microsoft.Template/uri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2Fazure-sdk-for-js%2F6e519929f154b919e8a47245715076e73cd7915c%2Fsamples%2Fframeworks%2Freact%2Farm-template.json) | ||
|
||
The above template will create the necessary resources for you and the output tab will contain the exact environment variables that you'll need as soon as deployment succeeds. When the deployment is finished, head over to the "outputs" tab and copy the outputs to a local file - you'll need them in the next step. | ||
|
||
### Register a new application in AAD and assign the "Azure Event Hubs Data Owner" and "Azure Storage Blob Data Contributor" role to it. | ||
|
||
Authentication will still need to be set-up manually using the following instructions: | ||
|
||
- See https://docs.microsoft.com/azure/active-directory/develop/quickstart-register-app | ||
to register a new application in the Azure Active Directory. | ||
- Note down the client id and tenant id from the above step. | ||
You will need to set these in the .env file below. | ||
|
||
Ensure your app registration has been configured properly to allow the [implicit grant flow][implicitgrantflow] | ||
and allow both `Access tokens` and `ID tokens` to be issued by the authorization endpoint. | ||
In your app registration, you will also need to add a permission for the `Microsoft.EventHubs` and `Azure Storage` apps. | ||
When adding permission for `Microsoft.EventHubs` and `Azure Storage`, the type should be `delegated permissions` and the permission should be `user_impersonation`. | ||
|
||
## Running the sample | ||
|
||
Once the above created you'll want to ensure React has the necessary environment variables. To do this, copy `sample.env` as `.env` and provide the necessary environment variables to configure the application. You can get most values from the output tab of the deployment, and the client and tenant ID from the App registration step. Please note that environment variables should be upper case. For example: REACT_APP_TENANT_ID and REACT_APP_EVENT_HUBS_NAME. | ||
|
||
Install the various packages as well as the TypeScript compiler using: | ||
|
||
```bash | ||
npm install | ||
``` | ||
|
||
Run the sample app: | ||
|
||
```bash | ||
npm start | ||
``` | ||
|
||
Since this is a contrived example, you can only create new Todos and complete existing Todos. As you interact with the application, you'll notice EventHubs messages get written out to the console in the browser's developer tools. You may attach a note which will get uploaded as Blobs or fetch an existing note to display it on the screen. | ||
|
||
Additionally, you may open multiple instances of this sample application and watch as Todos synchronize in real-time. | ||
|
||
## Next Steps | ||
|
||
Take a look at our [API Documentation][apiref] for more information about the APIs that are avaiable. | ||
|
||
[react]: https://create-react-app.dev/ | ||
[typescript]: https://www.typescriptlang.org/docs/home.html | ||
[freesub]: https://azure.microsoft.com/free | ||
[eventhubs]: https://docs.microsoft.com/javascript/api/@azure/event-hubs | ||
[servicebus]: https://docs.microsoft.com/javascript/api/@azure/service-bus | ||
[storageblob]: https://docs.microsoft.com/javascript/api/@azure/storage-blob | ||
[identity]: https://docs.microsoft.com/javascript/api/@azure/identity | ||
[apiref]: https://docs.microsoft.com/javascript/api/ | ||
[implicitgrantflow]: https://docs.microsoft.com/azure/active-directory/develop/v2-oauth2-implicit-grant-flow |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
{ | ||
"name": "typescript-react-sample", | ||
"version": "0.1.0", | ||
"private": true, | ||
"dependencies": { | ||
"@azure/event-hubs": "^5.3.1", | ||
"@azure/identity": "^1.2.0", | ||
"@azure/storage-blob": "^12.3.0", | ||
"react": "^17.0.1", | ||
"react-dom": "^17.0.1", | ||
"react-scripts": "4.0.1", | ||
"uuid": "^8.3.1" | ||
}, | ||
"scripts": { | ||
"start": "react-scripts start", | ||
"build": "react-scripts build", | ||
"eject": "react-scripts eject" | ||
}, | ||
"eslintConfig": { | ||
"extends": [ | ||
"react-app" | ||
] | ||
}, | ||
"browserslist": { | ||
"production": [ | ||
">0.2%", | ||
"not dead", | ||
"not op_mini all" | ||
], | ||
"development": [ | ||
"last 1 chrome version", | ||
"last 1 firefox version", | ||
"last 1 safari version" | ||
] | ||
}, | ||
"devDependencies": { | ||
"@types/node": "^12.0.0", | ||
"@types/react": "^16.9.53", | ||
"@types/react-dom": "^16.9.8", | ||
"@types/uuid": "^8.3.0", | ||
"@typescript-eslint/eslint-plugin": "^4.9.0", | ||
"@typescript-eslint/parser": "^4.9.0", | ||
"eslint-config-prettier": "^6.15.0", | ||
"eslint-plugin-prettier": "^3.1.4", | ||
"typescript": "^4.0.3", | ||
"prettier": "^1.16.4" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
<!DOCTYPE html> | ||
<html lang="en"> | ||
<head> | ||
<meta charset="utf-8" /> | ||
<link rel="icon" href="https://c.s-microsoft.com/favicon.ico?v2" type="image/x-icon" /> | ||
<meta name="viewport" content="width=device-width, initial-scale=1" /> | ||
<meta name="theme-color" content="#000000" /> | ||
<meta name="description" content="Web site created using create-react-app" /> | ||
<!-- | ||
manifest.json provides metadata used when your web app is installed on a | ||
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/ | ||
--> | ||
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" /> | ||
<!-- | ||
Notice the use of %PUBLIC_URL% in the tags above. | ||
It will be replaced with the URL of the `public` folder during the build. | ||
Only files inside the `public` folder can be referenced from the HTML. | ||
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will | ||
work correctly both with client-side routing and a non-root public URL. | ||
Learn how to configure a non-root public URL by running `npm run build`. | ||
--> | ||
<title>Todos React Sample</title> | ||
<!-- | ||
Adding basic styling with Bootstrap | ||
--> | ||
<link | ||
rel="stylesheet" | ||
href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" | ||
integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" | ||
crossorigin="anonymous" | ||
/> | ||
</head> | ||
<body> | ||
<noscript>You need to enable JavaScript to run this app.</noscript> | ||
<div id="root"></div> | ||
<!-- | ||
This HTML file is a template. | ||
If you open it directly in the browser, you will see an empty page. | ||
You can add webfonts, meta tags, or analytics to this file. | ||
The build step will place the bundled scripts into the <body> tag. | ||
To begin the development, run `npm start` or `yarn start`. | ||
To create a production bundle, use `npm run build` or `yarn build`. | ||
--> | ||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
{ | ||
"short_name": "React App", | ||
"name": "Create React App Sample", | ||
"start_url": ".", | ||
"display": "standalone", | ||
"theme_color": "#000000", | ||
"background_color": "#ffffff" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
# https://www.robotstxt.org/robotstxt.html | ||
User-agent: * | ||
Disallow: |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
# Rename this to .env in order to have React automatically | ||
# pull in all these variables (anything that starts with REACT_APP_ will be | ||
# made available. See the documentation for adding custom environment variables | ||
# at the following link: https://create-react-app.dev/docs/adding-custom-environment-variables/) | ||
|
||
# fully qualified namespace for event hubs, typically: <namespace>.servicebus.windows.net | ||
REACT_APP_EVENT_HUBS_NAMESPACE="" | ||
# The name of the Event Hubs hub | ||
REACT_APP_EVENT_HUBS_NAME="" | ||
|
||
# URI for the Azure Blob Storage, typically https://<name>.blob.core.windows.net/ | ||
REACT_APP_BLOB_URI="" | ||
# the name of the Azure Blob Storage container | ||
REACT_APP_BLOB_CONTAINER="" | ||
|
||
# Used to authenticate using Azure AD as a service principal for role-based authentication. | ||
# | ||
# See the documentation for `InteractiveBrowserCredential` at the following link: | ||
# https://docs.microsoft.com/javascript/api/@azure/identity/interactivebrowsercredential | ||
REACT_APP_CLIENT_ID="" | ||
REACT_APP_TENANT_ID="" |
Oops, something went wrong.