├── .gitignore ├── .graphqlconfig.yml ├── .vscode └── settings.json ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── amplify.yml ├── amplify.yml.old ├── amplify ├── .config │ └── project-config.json ├── README.md ├── backend │ ├── api │ │ └── AlexaBackend │ │ │ ├── parameters.json │ │ │ ├── schema.graphql │ │ │ ├── stacks │ │ │ └── CustomResources.json │ │ │ └── transform.conf.json │ ├── auth │ │ └── awsalexaui51864c6a │ │ │ ├── awsalexaui51864c6a-cloudformation-template.yml │ │ │ └── parameters.json │ └── backend-config.json ├── cli.json └── hooks │ ├── README.md │ ├── post-push.sh.sample │ └── pre-push.js.sample ├── app ├── .gitignore ├── README.md ├── public │ ├── favicon.ico │ ├── index.html │ ├── logo192.png │ ├── logo512.png │ ├── manifest.json │ └── robots.txt └── src │ ├── App.css │ ├── App.js │ ├── App.test.js │ ├── index.css │ ├── index.js │ ├── logo.svg │ ├── reportWebVitals.js │ └── setupTests.js ├── aws_alexa.png ├── package.json ├── package.json.old ├── public ├── favicon.ico ├── index.html ├── manifest.json └── static │ └── images │ └── lamp.png ├── src ├── App.css ├── App.js ├── App.test.js ├── Device.js ├── graphql │ ├── mutations.js │ ├── queries.js │ ├── schema.json │ └── subscriptions.js ├── index.css ├── index.js ├── logo.svg └── serviceWorker.js └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # Jetbrains 4 | .idea 5 | 6 | # dependencies 7 | /node_modules 8 | /.pnp 9 | .pnp.js 10 | 11 | # testing 12 | /coverage 13 | 14 | # production 15 | /build 16 | 17 | # misc 18 | .DS_Store 19 | .env.local 20 | .env.development.local 21 | .env.test.local 22 | .env.production.local 23 | 24 | npm-debug.log* 25 | yarn-debug.log* 26 | yarn-error.log* 27 | 28 | # for public project 29 | amplify/team-provider-info.json 30 | 31 | #amplify 32 | amplify/\#current-cloud-backend 33 | amplify/.config/local-* 34 | amplify/logs 35 | amplify/mock-data 36 | amplify/backend/amplify-meta.json 37 | amplify/backend/awscloudformation 38 | amplify/backend/.temp 39 | build/ 40 | dist/ 41 | node_modules/ 42 | aws-exports.js 43 | awsconfiguration.json 44 | amplifyconfiguration.json 45 | amplify-build-config.json 46 | amplify-gradle-config.json 47 | amplifytools.xcconfig 48 | .secret-* -------------------------------------------------------------------------------- /.graphqlconfig.yml: -------------------------------------------------------------------------------- 1 | projects: 2 | AlexaBackend: 3 | schemaPath: src/graphql/schema.json 4 | includes: 5 | - src/graphql/**/*.js 6 | excludes: 7 | - ./amplify/** 8 | extensions: 9 | amplify: 10 | codeGenTarget: javascript 11 | generatedFileName: '' 12 | docsFilePath: src/graphql 13 | extensions: 14 | amplify: 15 | version: 3 16 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.exclude": { 3 | "amplify/.config": true, 4 | "amplify/**/*-parameters.json": true, 5 | "amplify/**/amplify.state": true, 6 | "amplify/**/transform.conf.json": true, 7 | "amplify/#current-cloud-backend": true, 8 | "amplify/backend/amplify-meta.json": true, 9 | "amplify/backend/awscloudformation": true 10 | } 11 | } -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | ## Code of Conduct 2 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). 3 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact 4 | opensource-codeofconduct@amazon.com with any additional questions or comments. 5 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing Guidelines 2 | 3 | Thank you for your interest in contributing to our project. Whether it's a bug report, new feature, correction, or additional 4 | documentation, we greatly value feedback and contributions from our community. 5 | 6 | Please read through this document before submitting any issues or pull requests to ensure we have all the necessary 7 | information to effectively respond to your bug report or contribution. 8 | 9 | 10 | ## Reporting Bugs/Feature Requests 11 | 12 | We welcome you to use the GitHub issue tracker to report bugs or suggest features. 13 | 14 | When filing an issue, please check existing open, or recently closed, issues to make sure somebody else hasn't already 15 | reported the issue. Please try to include as much information as you can. Details like these are incredibly useful: 16 | 17 | * A reproducible test case or series of steps 18 | * The version of our code being used 19 | * Any modifications you've made relevant to the bug 20 | * Anything unusual about your environment or deployment 21 | 22 | 23 | ## Contributing via Pull Requests 24 | Contributions via pull requests are much appreciated. Before sending us a pull request, please ensure that: 25 | 26 | 1. You are working against the latest source on the *master* branch. 27 | 2. You check existing open, and recently merged, pull requests to make sure someone else hasn't addressed the problem already. 28 | 3. You open an issue to discuss any significant work - we would hate for your time to be wasted. 29 | 30 | To send us a pull request, please: 31 | 32 | 1. Fork the repository. 33 | 2. Modify the source; please focus on the specific change you are contributing. If you also reformat all the code, it will be hard for us to focus on your change. 34 | 3. Ensure local tests pass. 35 | 4. Commit to your fork using clear commit messages. 36 | 5. Send us a pull request, answering any default questions in the pull request interface. 37 | 6. Pay attention to any automated CI failures reported in the pull request, and stay involved in the conversation. 38 | 39 | GitHub provides additional document on [forking a repository](https://help.github.com/articles/fork-a-repo/) and 40 | [creating a pull request](https://help.github.com/articles/creating-a-pull-request/). 41 | 42 | 43 | ## Finding contributions to work on 44 | Looking at the existing issues is a great way to find something to contribute on. As our projects, by default, use the default GitHub issue labels (enhancement/bug/duplicate/help wanted/invalid/question/wontfix), looking at any 'help wanted' issues is a great place to start. 45 | 46 | 47 | ## Code of Conduct 48 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). 49 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact 50 | opensource-codeofconduct@amazon.com with any additional questions or comments. 51 | 52 | 53 | ## Security issue notifications 54 | If you discover a potential security issue in this project we ask that you notify AWS/Amazon Security via our [vulnerability reporting page](http://aws.amazon.com/security/vulnerability-reporting/). Please do **not** create a public github issue. 55 | 56 | 57 | ## Licensing 58 | 59 | See the [LICENSE](LICENSE) file for our project's licensing. We will ask you to confirm the licensing of your contribution. 60 | 61 | We may ask you to sign a [Contributor License Agreement (CLA)](http://en.wikipedia.org/wiki/Contributor_License_Agreement) for larger changes. 62 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of 4 | this software and associated documentation files (the "Software"), to deal in 5 | the Software without restriction, including without limitation the rights to 6 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 7 | the Software, and to permit persons to whom the Software is furnished to do so. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 10 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 11 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 12 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 13 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 14 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 15 | 16 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Alexa Workshop Smart Home - Device Binding UI 2 | 3 | This is the source code of [Step 1: Build Device Binding UI](https://alexaworkshop.com/smart-home/1.build-device-ui/). 4 | If you are looking for the lab content, please visit the above link. 5 | 6 | If you are looking for the whole lab, please visit [AWS & Alexa Workshop - Smart Home Skills](https://alexaworkshop.com/smart-home/). 7 | 8 | If you have any issues, please create issues in [aws-samples/aws-alexa-workshop](https://github.com/aws-samples/aws-alexa-workshop/issues) repository. 9 | 10 | ![](aws_alexa.png) 11 | 12 | ## License 13 | 14 | This library is licensed under the MIT-0 License. See the LICENSE file. 15 | 16 | -------------------------------------------------------------------------------- /amplify.yml: -------------------------------------------------------------------------------- 1 | version: 0.1 2 | backend: 3 | phases: 4 | build: 5 | commands: 6 | - '# Execute Amplify CLI with the helper script' 7 | - amplifyPush --simple 8 | frontend: 9 | phases: 10 | preBuild: 11 | commands: 12 | - yarn install 13 | build: 14 | commands: 15 | - yarn run build 16 | artifacts: 17 | baseDirectory: build 18 | files: 19 | - '**/*' 20 | cache: 21 | paths: 22 | - node_modules/**/* 23 | -------------------------------------------------------------------------------- /amplify.yml.old: -------------------------------------------------------------------------------- 1 | version: 0.1 2 | backend: 3 | phases: 4 | build: 5 | commands: 6 | - '# Execute Amplify CLI with the helper script' 7 | - amplifyPush --simple 8 | frontend: 9 | phases: 10 | preBuild: 11 | commands: 12 | - yarn install 13 | build: 14 | commands: 15 | - yarn run build 16 | artifacts: 17 | baseDirectory: build 18 | files: 19 | - '**/*' 20 | cache: 21 | paths: 22 | - node_modules/**/* 23 | -------------------------------------------------------------------------------- /amplify/.config/project-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "projectName": "aws-alexa-ui", 3 | "version": "3.0", 4 | "frontend": "javascript", 5 | "javascript": { 6 | "framework": "react", 7 | "config": { 8 | "SourceDir": "src", 9 | "DistributionDir": "build", 10 | "BuildCommand": "npm run-script build", 11 | "StartCommand": "npm run-script start" 12 | } 13 | }, 14 | "providers": [ 15 | "awscloudformation" 16 | ] 17 | } -------------------------------------------------------------------------------- /amplify/README.md: -------------------------------------------------------------------------------- 1 | # Getting Started with Amplify CLI 2 | This directory was generated by [Amplify CLI](https://docs.amplify.aws/cli). 3 | 4 | Helpful resources: 5 | - Amplify documentation: https://docs.amplify.aws 6 | - Amplify CLI documentation: https://docs.amplify.aws/cli 7 | - More details on this folder & generated files: https://docs.amplify.aws/cli/reference/files 8 | - Join Amplify's community: https://amplify.aws/community/ 9 | -------------------------------------------------------------------------------- /amplify/backend/api/AlexaBackend/parameters.json: -------------------------------------------------------------------------------- 1 | { 2 | "AppSyncApiName": "AlexaBackend", 3 | "DynamoDBBillingMode": "PAY_PER_REQUEST", 4 | "DynamoDBEnableServerSideEncryption": "false", 5 | "AuthCognitoUserPoolId": { 6 | "Fn::GetAtt": [ 7 | "authawsalexaui51864c6a", 8 | "Outputs.UserPoolId" 9 | ] 10 | } 11 | } -------------------------------------------------------------------------------- /amplify/backend/api/AlexaBackend/schema.graphql: -------------------------------------------------------------------------------- 1 | type Device @model 2 | @key(fields: ["thingName"]) 3 | @key(name: "ByUsernameThingName", fields: ["username", "thingName"]) 4 | { 5 | thingName: String! 6 | username: String! 7 | description: String 8 | } -------------------------------------------------------------------------------- /amplify/backend/api/AlexaBackend/stacks/CustomResources.json: -------------------------------------------------------------------------------- 1 | { 2 | "AWSTemplateFormatVersion": "2010-09-09", 3 | "Description": "An auto-generated nested stack.", 4 | "Metadata": {}, 5 | "Parameters": { 6 | "AppSyncApiId": { 7 | "Type": "String", 8 | "Description": "The id of the AppSync API associated with this project." 9 | }, 10 | "AppSyncApiName": { 11 | "Type": "String", 12 | "Description": "The name of the AppSync API", 13 | "Default": "AppSyncSimpleTransform" 14 | }, 15 | "env": { 16 | "Type": "String", 17 | "Description": "The environment name. e.g. Dev, Test, or Production", 18 | "Default": "NONE" 19 | }, 20 | "S3DeploymentBucket": { 21 | "Type": "String", 22 | "Description": "The S3 bucket containing all deployment assets for the project." 23 | }, 24 | "S3DeploymentRootKey": { 25 | "Type": "String", 26 | "Description": "An S3 key relative to the S3DeploymentBucket that points to the root\nof the deployment directory." 27 | } 28 | }, 29 | "Resources": { 30 | "EmptyResource": { 31 | "Type": "Custom::EmptyResource", 32 | "Condition": "AlwaysFalse" 33 | } 34 | }, 35 | "Conditions": { 36 | "HasEnvironmentParameter": { 37 | "Fn::Not": [ 38 | { 39 | "Fn::Equals": [ 40 | { 41 | "Ref": "env" 42 | }, 43 | "NONE" 44 | ] 45 | } 46 | ] 47 | }, 48 | "AlwaysFalse": { 49 | "Fn::Equals": [ 50 | "true", 51 | "false" 52 | ] 53 | } 54 | }, 55 | "Outputs": { 56 | "EmptyOutput": { 57 | "Description": "An empty output. You may delete this if you have at least one resource above.", 58 | "Value": "" 59 | } 60 | } 61 | } -------------------------------------------------------------------------------- /amplify/backend/api/AlexaBackend/transform.conf.json: -------------------------------------------------------------------------------- 1 | { 2 | "Version": 5, 3 | "ElasticsearchWarning": true 4 | } -------------------------------------------------------------------------------- /amplify/backend/auth/awsalexaui51864c6a/awsalexaui51864c6a-cloudformation-template.yml: -------------------------------------------------------------------------------- 1 | AWSTemplateFormatVersion: 2010-09-09 2 | 3 | Parameters: 4 | env: 5 | Type: String 6 | authRoleName: 7 | Type: String 8 | unauthRoleName: 9 | Type: String 10 | authRoleArn: 11 | Type: String 12 | unauthRoleArn: 13 | Type: String 14 | 15 | 16 | 17 | 18 | identityPoolName: 19 | Type: String 20 | 21 | allowUnauthenticatedIdentities: 22 | Type: String 23 | 24 | openIdLambdaRoleName: 25 | Type: String 26 | 27 | resourceNameTruncated: 28 | Type: String 29 | 30 | userPoolName: 31 | Type: String 32 | 33 | autoVerifiedAttributes: 34 | Type: CommaDelimitedList 35 | 36 | mfaConfiguration: 37 | Type: String 38 | 39 | mfaTypes: 40 | Type: CommaDelimitedList 41 | 42 | smsAuthenticationMessage: 43 | Type: String 44 | 45 | smsVerificationMessage: 46 | Type: String 47 | 48 | emailVerificationSubject: 49 | Type: String 50 | 51 | emailVerificationMessage: 52 | Type: String 53 | 54 | defaultPasswordPolicy: 55 | Type: String 56 | 57 | passwordPolicyMinLength: 58 | Type: Number 59 | 60 | passwordPolicyCharacters: 61 | Type: CommaDelimitedList 62 | 63 | requiredAttributes: 64 | Type: CommaDelimitedList 65 | 66 | userpoolClientName: 67 | Type: String 68 | 69 | userpoolClientGenerateSecret: 70 | Type: String 71 | 72 | userpoolClientRefreshTokenValidity: 73 | Type: Number 74 | 75 | userpoolClientWriteAttributes: 76 | Type: CommaDelimitedList 77 | 78 | userpoolClientReadAttributes: 79 | Type: CommaDelimitedList 80 | 81 | mfaLambdaRole: 82 | Type: String 83 | 84 | userpoolClientLambdaRole: 85 | Type: String 86 | 87 | userpoolClientSetAttributes: 88 | Type: String 89 | 90 | resourceName: 91 | Type: String 92 | 93 | authSelections: 94 | Type: String 95 | 96 | useDefault: 97 | Type: String 98 | 99 | usernameAttributes: 100 | Type: CommaDelimitedList 101 | 102 | additionalQuestions: 103 | Type: CommaDelimitedList 104 | 105 | dependsOn: 106 | Type: CommaDelimitedList 107 | 108 | Conditions: 109 | ShouldNotCreateEnvResources: !Equals [ !Ref env, NONE ] 110 | 111 | Resources: 112 | 113 | 114 | # BEGIN SNS ROLE RESOURCE 115 | SNSRole: 116 | # Created to allow the UserPool SMS Config to publish via the Simple Notification Service during MFA Process 117 | Type: AWS::IAM::Role 118 | Properties: 119 | RoleName: !If [ShouldNotCreateEnvResources, 'awsale51864c6a_sns-role', !Join ['',['awsale51864c6a_sns-role', '-', !Ref env]]] 120 | AssumeRolePolicyDocument: 121 | Version: "2012-10-17" 122 | Statement: 123 | - Sid: "" 124 | Effect: "Allow" 125 | Principal: 126 | Service: "cognito-idp.amazonaws.com" 127 | Action: 128 | - "sts:AssumeRole" 129 | Condition: 130 | StringEquals: 131 | sts:ExternalId: awsale51864c6a_role_external_id 132 | Policies: 133 | - 134 | PolicyName: awsale51864c6a-sns-policy 135 | PolicyDocument: 136 | Version: "2012-10-17" 137 | Statement: 138 | - 139 | Effect: "Allow" 140 | Action: 141 | - "sns:Publish" 142 | Resource: "*" 143 | # BEGIN USER POOL RESOURCES 144 | UserPool: 145 | # Created upon user selection 146 | # Depends on SNS Role for Arn if MFA is enabled 147 | Type: AWS::Cognito::UserPool 148 | UpdateReplacePolicy: Retain 149 | Properties: 150 | UserPoolName: !If [ShouldNotCreateEnvResources, !Ref userPoolName, !Join ['',[!Ref userPoolName, '-', !Ref env]]] 151 | 152 | Schema: 153 | 154 | - 155 | Name: email 156 | Required: true 157 | Mutable: true 158 | 159 | 160 | 161 | 162 | AutoVerifiedAttributes: !Ref autoVerifiedAttributes 163 | 164 | 165 | EmailVerificationMessage: !Ref emailVerificationMessage 166 | EmailVerificationSubject: !Ref emailVerificationSubject 167 | 168 | Policies: 169 | PasswordPolicy: 170 | MinimumLength: !Ref passwordPolicyMinLength 171 | RequireLowercase: false 172 | RequireNumbers: false 173 | RequireSymbols: false 174 | RequireUppercase: false 175 | 176 | UsernameAttributes: !Ref usernameAttributes 177 | 178 | MfaConfiguration: !Ref mfaConfiguration 179 | SmsVerificationMessage: !Ref smsVerificationMessage 180 | SmsConfiguration: 181 | SnsCallerArn: !GetAtt SNSRole.Arn 182 | ExternalId: awsale51864c6a_role_external_id 183 | 184 | 185 | UserPoolClientWeb: 186 | # Created provide application access to user pool 187 | # Depends on UserPool for ID reference 188 | Type: "AWS::Cognito::UserPoolClient" 189 | Properties: 190 | ClientName: awsale51864c6a_app_clientWeb 191 | 192 | RefreshTokenValidity: !Ref userpoolClientRefreshTokenValidity 193 | UserPoolId: !Ref UserPool 194 | DependsOn: UserPool 195 | UserPoolClient: 196 | # Created provide application access to user pool 197 | # Depends on UserPool for ID reference 198 | Type: "AWS::Cognito::UserPoolClient" 199 | Properties: 200 | ClientName: !Ref userpoolClientName 201 | 202 | GenerateSecret: !Ref userpoolClientGenerateSecret 203 | RefreshTokenValidity: !Ref userpoolClientRefreshTokenValidity 204 | UserPoolId: !Ref UserPool 205 | DependsOn: UserPool 206 | # BEGIN USER POOL LAMBDA RESOURCES 207 | UserPoolClientRole: 208 | # Created to execute Lambda which gets userpool app client config values 209 | Type: 'AWS::IAM::Role' 210 | Properties: 211 | RoleName: !If [ShouldNotCreateEnvResources, !Ref userpoolClientLambdaRole, !Join ['',[!Ref userpoolClientLambdaRole, '-', !Ref env]]] 212 | AssumeRolePolicyDocument: 213 | Version: '2012-10-17' 214 | Statement: 215 | - Effect: Allow 216 | Principal: 217 | Service: 218 | - lambda.amazonaws.com 219 | Action: 220 | - 'sts:AssumeRole' 221 | DependsOn: UserPoolClient 222 | UserPoolClientLambda: 223 | # Lambda which gets userpool app client config values 224 | # Depends on UserPool for id 225 | # Depends on UserPoolClientRole for role ARN 226 | Type: 'AWS::Lambda::Function' 227 | Properties: 228 | Code: 229 | ZipFile: !Join 230 | - |+ 231 | - - 'const response = require(''cfn-response'');' 232 | - 'const aws = require(''aws-sdk'');' 233 | - 'const identity = new aws.CognitoIdentityServiceProvider();' 234 | - 'exports.handler = (event, context, callback) => {' 235 | - ' if (event.RequestType == ''Delete'') { ' 236 | - ' response.send(event, context, response.SUCCESS, {})' 237 | - ' }' 238 | - ' if (event.RequestType == ''Update'' || event.RequestType == ''Create'') {' 239 | - ' const params = {' 240 | - ' ClientId: event.ResourceProperties.clientId,' 241 | - ' UserPoolId: event.ResourceProperties.userpoolId' 242 | - ' };' 243 | - ' identity.describeUserPoolClient(params).promise()' 244 | - ' .then((res) => {' 245 | - ' response.send(event, context, response.SUCCESS, {''appSecret'': res.UserPoolClient.ClientSecret});' 246 | - ' })' 247 | - ' .catch((err) => {' 248 | - ' response.send(event, context, response.FAILED, {err});' 249 | - ' });' 250 | - ' }' 251 | - '};' 252 | Handler: index.handler 253 | Runtime: nodejs14.x 254 | Timeout: '300' 255 | Role: !GetAtt 256 | - UserPoolClientRole 257 | - Arn 258 | DependsOn: UserPoolClientRole 259 | UserPoolClientLambdaPolicy: 260 | # Sets userpool policy for the role that executes the Userpool Client Lambda 261 | # Depends on UserPool for Arn 262 | # Marked as depending on UserPoolClientRole for easier to understand CFN sequencing 263 | Type: 'AWS::IAM::Policy' 264 | Properties: 265 | PolicyName: awsale51864c6a_userpoolclient_lambda_iam_policy 266 | Roles: 267 | - !If [ShouldNotCreateEnvResources, !Ref userpoolClientLambdaRole, !Join ['',[!Ref userpoolClientLambdaRole, '-', !Ref env]]] 268 | PolicyDocument: 269 | Version: '2012-10-17' 270 | Statement: 271 | - Effect: Allow 272 | Action: 273 | - 'cognito-idp:DescribeUserPoolClient' 274 | Resource: !GetAtt UserPool.Arn 275 | DependsOn: UserPoolClientLambda 276 | UserPoolClientLogPolicy: 277 | # Sets log policy for the role that executes the Userpool Client Lambda 278 | # Depends on UserPool for Arn 279 | # Marked as depending on UserPoolClientLambdaPolicy for easier to understand CFN sequencing 280 | Type: 'AWS::IAM::Policy' 281 | Properties: 282 | PolicyName: awsale51864c6a_userpoolclient_lambda_log_policy 283 | Roles: 284 | - !If [ShouldNotCreateEnvResources, !Ref userpoolClientLambdaRole, !Join ['',[!Ref userpoolClientLambdaRole, '-', !Ref env]]] 285 | PolicyDocument: 286 | Version: 2012-10-17 287 | Statement: 288 | - Effect: Allow 289 | Action: 290 | - 'logs:CreateLogGroup' 291 | - 'logs:CreateLogStream' 292 | - 'logs:PutLogEvents' 293 | Resource: !Sub 294 | - arn:aws:logs:${region}:${account}:log-group:/aws/lambda/${lambda}:log-stream:* 295 | - { region: !Ref "AWS::Region", account: !Ref "AWS::AccountId", lambda: !Ref UserPoolClientLambda} 296 | DependsOn: UserPoolClientLambdaPolicy 297 | UserPoolClientInputs: 298 | # Values passed to Userpool client Lambda 299 | # Depends on UserPool for Id 300 | # Depends on UserPoolClient for Id 301 | # Marked as depending on UserPoolClientLambdaPolicy for easier to understand CFN sequencing 302 | Type: 'Custom::LambdaCallout' 303 | Properties: 304 | ServiceToken: !GetAtt UserPoolClientLambda.Arn 305 | clientId: !Ref UserPoolClient 306 | userpoolId: !Ref UserPool 307 | DependsOn: UserPoolClientLogPolicy 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | # BEGIN IDENTITY POOL RESOURCES 316 | 317 | 318 | IdentityPool: 319 | # Always created 320 | Type: AWS::Cognito::IdentityPool 321 | Properties: 322 | IdentityPoolName: !If [ShouldNotCreateEnvResources, 'awsalexaui51864c6a_identitypool_51864c6a', !Join ['',['awsalexaui51864c6a_identitypool_51864c6a', '__', !Ref env]]] 323 | 324 | CognitoIdentityProviders: 325 | - ClientId: !Ref UserPoolClient 326 | ProviderName: !Sub 327 | - cognito-idp.${region}.amazonaws.com/${client} 328 | - { region: !Ref "AWS::Region", client: !Ref UserPool} 329 | - ClientId: !Ref UserPoolClientWeb 330 | ProviderName: !Sub 331 | - cognito-idp.${region}.amazonaws.com/${client} 332 | - { region: !Ref "AWS::Region", client: !Ref UserPool} 333 | 334 | AllowUnauthenticatedIdentities: !Ref allowUnauthenticatedIdentities 335 | 336 | 337 | DependsOn: UserPoolClientInputs 338 | 339 | 340 | IdentityPoolRoleMap: 341 | # Created to map Auth and Unauth roles to the identity pool 342 | # Depends on Identity Pool for ID ref 343 | Type: AWS::Cognito::IdentityPoolRoleAttachment 344 | Properties: 345 | IdentityPoolId: !Ref IdentityPool 346 | Roles: 347 | unauthenticated: !Ref unauthRoleArn 348 | authenticated: !Ref authRoleArn 349 | DependsOn: IdentityPool 350 | 351 | 352 | Outputs : 353 | 354 | IdentityPoolId: 355 | Value: !Ref 'IdentityPool' 356 | Description: Id for the identity pool 357 | IdentityPoolName: 358 | Value: !GetAtt IdentityPool.Name 359 | 360 | 361 | 362 | 363 | UserPoolId: 364 | Value: !Ref 'UserPool' 365 | Description: Id for the user pool 366 | UserPoolName: 367 | Value: !Ref userPoolName 368 | AppClientIDWeb: 369 | Value: !Ref 'UserPoolClientWeb' 370 | Description: The user pool app client id for web 371 | AppClientID: 372 | Value: !Ref 'UserPoolClient' 373 | Description: The user pool app client id 374 | AppClientSecret: 375 | Value: !GetAtt UserPoolClientInputs.appSecret 376 | 377 | 378 | 379 | 380 | 381 | 382 | 383 | -------------------------------------------------------------------------------- /amplify/backend/auth/awsalexaui51864c6a/parameters.json: -------------------------------------------------------------------------------- 1 | { 2 | "identityPoolName": "awsalexaui51864c6a_identitypool_51864c6a", 3 | "allowUnauthenticatedIdentities": false, 4 | "openIdLambdaRoleName": "awsale51864c6a_openid_lambda_role", 5 | "resourceNameTruncated": "awsale51864c6a", 6 | "userPoolName": "awsalexaui51864c6a_userpool_51864c6a", 7 | "autoVerifiedAttributes": [ 8 | "email" 9 | ], 10 | "mfaConfiguration": "OFF", 11 | "mfaTypes": [ 12 | "SMS Text Message" 13 | ], 14 | "smsAuthenticationMessage": "Your authentication code is {####}", 15 | "smsVerificationMessage": "Your verification code is {####}", 16 | "emailVerificationSubject": "Your verification code", 17 | "emailVerificationMessage": "Your verification code is {####}", 18 | "defaultPasswordPolicy": false, 19 | "passwordPolicyMinLength": 8, 20 | "passwordPolicyCharacters": [], 21 | "requiredAttributes": [ 22 | "email" 23 | ], 24 | "userpoolClientName": "awsale51864c6a_app_client", 25 | "userpoolClientGenerateSecret": true, 26 | "userpoolClientRefreshTokenValidity": 30, 27 | "userpoolClientWriteAttributes": [ 28 | "email" 29 | ], 30 | "userpoolClientReadAttributes": [ 31 | "email" 32 | ], 33 | "mfaLambdaRole": "awsale51864c6a_totp_lambda_role", 34 | "userpoolClientLambdaRole": "awsale51864c6a_userpoolclient_lambda_role", 35 | "userpoolClientSetAttributes": false, 36 | "resourceName": "awsalexaui51864c6a", 37 | "authSelections": "identityPoolAndUserPool", 38 | "authRoleName": { 39 | "Ref": "AuthRoleName" 40 | }, 41 | "unauthRoleName": { 42 | "Ref": "UnauthRoleName" 43 | }, 44 | "authRoleArn": { 45 | "Fn::GetAtt": [ 46 | "AuthRole", 47 | "Arn" 48 | ] 49 | }, 50 | "unauthRoleArn": { 51 | "Fn::GetAtt": [ 52 | "UnauthRole", 53 | "Arn" 54 | ] 55 | }, 56 | "useDefault": "default", 57 | "usernameAttributes": [ 58 | "email, phone_number" 59 | ], 60 | "additionalQuestions": [], 61 | "dependsOn": [] 62 | } -------------------------------------------------------------------------------- /amplify/backend/backend-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "auth": { 3 | "awsalexaui51864c6a": { 4 | "service": "Cognito", 5 | "providerPlugin": "awscloudformation", 6 | "dependsOn": [] 7 | } 8 | }, 9 | "api": { 10 | "AlexaBackend": { 11 | "service": "AppSync", 12 | "providerPlugin": "awscloudformation", 13 | "output": { 14 | "securityType": "AMAZON_COGNITO_USER_POOLS" 15 | } 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /amplify/cli.json: -------------------------------------------------------------------------------- 1 | { 2 | "features": { 3 | "graphqltransformer": { 4 | "addmissingownerfields": true, 5 | "validatetypenamereservedwords": true, 6 | "useexperimentalpipelinedtransformer": false, 7 | "enableiterativegsiupdates": false, 8 | "secondarykeyasgsi": true 9 | }, 10 | "frontend-ios": { 11 | "enablexcodeintegration": true 12 | }, 13 | "auth": { 14 | "enablecaseinsensitivity": true 15 | }, 16 | "codegen": { 17 | "useappsyncmodelgenplugin": true, 18 | "usedocsgeneratorplugin": true, 19 | "usetypesgeneratorplugin": true 20 | }, 21 | "appsync": { 22 | "generategraphqlpermissions": true 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /amplify/hooks/README.md: -------------------------------------------------------------------------------- 1 | # Command Hooks 2 | 3 | Command hooks can be used to run custom scripts upon Amplify CLI lifecycle events like pre-push, post-add-function, etc. 4 | 5 | To get started, add your script files based on the expected naming convention in this directory. 6 | 7 | Learn more about the script file naming convention, hook parameters, third party dependencies, and advanced configurations at https://docs.amplify.aws/cli/usage/command-hooks 8 | -------------------------------------------------------------------------------- /amplify/hooks/post-push.sh.sample: -------------------------------------------------------------------------------- 1 | # This is a sample hook script created by Amplify CLI. 2 | # To start using this post-push hook please change the filename: 3 | # post-push.sh.sample -> post-push.sh 4 | # 5 | # learn more: https://docs.amplify.aws/cli/usage/command-hooks 6 | 7 | if [ -z "$(which jq)" ]; then 8 | echo "Please install jq to run the sample script." 9 | exit 0 10 | fi 11 | 12 | parameters=`cat` 13 | error=$(jq -r '.error // empty' <<< "$parameters") 14 | data=$(jq -r '.data' <<< "$parameters") 15 | 16 | # 17 | # Write code here: 18 | # 19 | if [ ! -z "$error" ]; then 20 | echo "Amplify CLI emitted an error:" $(jq -r '.message' <<< "$error") 21 | exit 0 22 | fi 23 | echo "project root path:" $(pwd); 24 | echo "Amplify CLI command:" $(jq -r '.amplify | .command' <<< "$data") -------------------------------------------------------------------------------- /amplify/hooks/pre-push.js.sample: -------------------------------------------------------------------------------- 1 | /** 2 | * This is a sample hook script created by Amplify CLI. 3 | * To start using this pre-push hook please change the filename: 4 | * pre-push.js.sample -> pre-push.js 5 | * 6 | * learn more: https://docs.amplify.aws/cli/usage/command-hooks 7 | */ 8 | 9 | /** 10 | * @param data { { amplify: { environment: string, command: string, subCommand: string, argv: string[] } } } 11 | * @param error { { message: string, stack: string } } 12 | */ 13 | const hookHandler = async (data, error) => { 14 | // TODO write your hook handler here 15 | }; 16 | 17 | const getParameters = async () => { 18 | const fs = require("fs"); 19 | return JSON.parse(fs.readFileSync(0, { encoding: "utf8" })); 20 | }; 21 | 22 | getParameters() 23 | .then((event) => hookHandler(event.data, event.error)) 24 | .catch((err) => { 25 | console.error(err); 26 | process.exitCode = 1; 27 | }); 28 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /app/README.md: -------------------------------------------------------------------------------- 1 | # Getting Started with Create React App 2 | 3 | This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app). 4 | 5 | ## Available Scripts 6 | 7 | In the project directory, you can run: 8 | 9 | ### `yarn start` 10 | 11 | Runs the app in the development mode.\ 12 | Open [http://localhost:3000](http://localhost:3000) to view it in the browser. 13 | 14 | The page will reload if you make edits.\ 15 | You will also see any lint errors in the console. 16 | 17 | ### `yarn test` 18 | 19 | Launches the test runner in the interactive watch mode.\ 20 | See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information. 21 | 22 | ### `yarn build` 23 | 24 | Builds the app for production to the `build` folder.\ 25 | It correctly bundles React in production mode and optimizes the build for the best performance. 26 | 27 | The build is minified and the filenames include the hashes.\ 28 | Your app is ready to be deployed! 29 | 30 | See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information. 31 | 32 | ### `yarn eject` 33 | 34 | **Note: this is a one-way operation. Once you `eject`, you can’t go back!** 35 | 36 | If you aren’t satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project. 37 | 38 | Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own. 39 | 40 | You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it. 41 | 42 | ## Learn More 43 | 44 | You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started). 45 | 46 | To learn React, check out the [React documentation](https://reactjs.org/). 47 | 48 | ### Code Splitting 49 | 50 | This section has moved here: [https://facebook.github.io/create-react-app/docs/code-splitting](https://facebook.github.io/create-react-app/docs/code-splitting) 51 | 52 | ### Analyzing the Bundle Size 53 | 54 | This section has moved here: [https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size](https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size) 55 | 56 | ### Making a Progressive Web App 57 | 58 | This section has moved here: [https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app](https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app) 59 | 60 | ### Advanced Configuration 61 | 62 | This section has moved here: [https://facebook.github.io/create-react-app/docs/advanced-configuration](https://facebook.github.io/create-react-app/docs/advanced-configuration) 63 | 64 | ### Deployment 65 | 66 | This section has moved here: [https://facebook.github.io/create-react-app/docs/deployment](https://facebook.github.io/create-react-app/docs/deployment) 67 | 68 | ### `yarn build` fails to minify 69 | 70 | This section has moved here: [https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify](https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify) 71 | -------------------------------------------------------------------------------- /app/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-alexa-workshop-smarthome-ui/b2c6425a1ae198aa1f5149269ada757bd77b6664/app/public/favicon.ico -------------------------------------------------------------------------------- /app/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 17 | 18 | 27 | React App 28 | 29 | 30 | 31 |
32 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /app/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-alexa-workshop-smarthome-ui/b2c6425a1ae198aa1f5149269ada757bd77b6664/app/public/logo192.png -------------------------------------------------------------------------------- /app/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-alexa-workshop-smarthome-ui/b2c6425a1ae198aa1f5149269ada757bd77b6664/app/public/logo512.png -------------------------------------------------------------------------------- /app/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /app/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /app/src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | height: 40vmin; 7 | pointer-events: none; 8 | } 9 | 10 | @media (prefers-reduced-motion: no-preference) { 11 | .App-logo { 12 | animation: App-logo-spin infinite 20s linear; 13 | } 14 | } 15 | 16 | .App-header { 17 | background-color: #282c34; 18 | min-height: 100vh; 19 | display: flex; 20 | flex-direction: column; 21 | align-items: center; 22 | justify-content: center; 23 | font-size: calc(10px + 2vmin); 24 | color: white; 25 | } 26 | 27 | .App-link { 28 | color: #61dafb; 29 | } 30 | 31 | @keyframes App-logo-spin { 32 | from { 33 | transform: rotate(0deg); 34 | } 35 | to { 36 | transform: rotate(360deg); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /app/src/App.js: -------------------------------------------------------------------------------- 1 | import logo from './logo.svg'; 2 | import './App.css'; 3 | 4 | function App() { 5 | return ( 6 |
7 |
8 | logo 9 |

10 | Edit src/App.js and save to reload. 11 |

12 | 18 | Learn React 19 | 20 |
21 |
22 | ); 23 | } 24 | 25 | export default App; 26 | -------------------------------------------------------------------------------- /app/src/App.test.js: -------------------------------------------------------------------------------- 1 | import { render, screen } from '@testing-library/react'; 2 | import App from './App'; 3 | 4 | test('renders learn react link', () => { 5 | render(); 6 | const linkElement = screen.getByText(/learn react/i); 7 | expect(linkElement).toBeInTheDocument(); 8 | }); 9 | -------------------------------------------------------------------------------- /app/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 12 | monospace; 13 | } 14 | -------------------------------------------------------------------------------- /app/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import './index.css'; 4 | import App from './App'; 5 | import reportWebVitals from './reportWebVitals'; 6 | 7 | ReactDOM.render( 8 | 9 | 10 | , 11 | document.getElementById('root') 12 | ); 13 | 14 | // If you want to start measuring performance in your app, pass a function 15 | // to log results (for example: reportWebVitals(console.log)) 16 | // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals 17 | reportWebVitals(); 18 | -------------------------------------------------------------------------------- /app/src/logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/src/reportWebVitals.js: -------------------------------------------------------------------------------- 1 | const reportWebVitals = onPerfEntry => { 2 | if (onPerfEntry && onPerfEntry instanceof Function) { 3 | import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { 4 | getCLS(onPerfEntry); 5 | getFID(onPerfEntry); 6 | getFCP(onPerfEntry); 7 | getLCP(onPerfEntry); 8 | getTTFB(onPerfEntry); 9 | }); 10 | } 11 | }; 12 | 13 | export default reportWebVitals; 14 | -------------------------------------------------------------------------------- /app/src/setupTests.js: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom'; 6 | -------------------------------------------------------------------------------- /aws_alexa.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-alexa-workshop-smarthome-ui/b2c6425a1ae198aa1f5149269ada757bd77b6664/aws_alexa.png -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "app", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "aws-amplify-react": "^4.2.29", 7 | "@material-ui/core": "^4.11.3", 8 | "@material-ui/icons": "^4.11.2", 9 | "aws-amplify": "^3.3.25", 10 | "react": "^17.0.1", 11 | "react-dom": "^17.0.1", 12 | "web-vitals": "^1.0.1" 13 | }, 14 | "devDependencies": { 15 | "react-scripts": "5.0.0", 16 | "@testing-library/jest-dom": "^5.11.4", 17 | "@testing-library/react": "^11.1.0", 18 | "@testing-library/user-event": "^12.1.10" 19 | }, 20 | "scripts": { 21 | "start": "react-scripts start", 22 | "build": "react-scripts build", 23 | "test": "react-scripts test", 24 | "eject": "react-scripts eject" 25 | }, 26 | "eslintConfig": { 27 | "extends": [ 28 | "react-app", 29 | "react-app/jest" 30 | ] 31 | }, 32 | "browserslist": { 33 | "production": [ 34 | ">0.2%", 35 | "not dead", 36 | "not op_mini all" 37 | ], 38 | "development": [ 39 | "last 1 chrome version", 40 | "last 1 firefox version", 41 | "last 1 safari version" 42 | ] 43 | }, 44 | "resolutions": { 45 | "**/**/immer": "^9.0.6", 46 | "**/**/axios": "^0.21.2", 47 | "**/**/node-fetch": "^2.6.7", 48 | "**/**/ansi-regex": "^5.0.1", 49 | "**/**/browserslist": "^4.16.5", 50 | "react-scripts/**/follow-redirects": "^1.14.7", 51 | "**/**/nth-check": "^2.0.1", 52 | "**/**/async": "^2.6.4" 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /package.json.old: -------------------------------------------------------------------------------- 1 | { 2 | "name": "app", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "aws-amplify-react": "^4.2.29", 7 | "@material-ui/core": "^4.11.3", 8 | "@material-ui/icons": "^4.11.2", 9 | "@testing-library/jest-dom": "^5.11.4", 10 | "@testing-library/react": "^11.1.0", 11 | "@testing-library/user-event": "^12.1.10", 12 | "aws-amplify": "^3.3.25", 13 | "react": "^17.0.1", 14 | "react-dom": "^17.0.1", 15 | "react-scripts": "4.0.3", 16 | "web-vitals": "^1.0.1" 17 | }, 18 | "scripts": { 19 | "start": "react-scripts start", 20 | "build": "react-scripts build", 21 | "test": "react-scripts test", 22 | "eject": "react-scripts eject" 23 | }, 24 | "eslintConfig": { 25 | "extends": [ 26 | "react-app", 27 | "react-app/jest" 28 | ] 29 | }, 30 | "browserslist": { 31 | "production": [ 32 | ">0.2%", 33 | "not dead", 34 | "not op_mini all" 35 | ], 36 | "development": [ 37 | "last 1 chrome version", 38 | "last 1 firefox version", 39 | "last 1 safari version" 40 | ] 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-alexa-workshop-smarthome-ui/b2c6425a1ae198aa1f5149269ada757bd77b6664/public/favicon.ico -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 22 | Alexa Workshop 23 | 24 | 25 | 26 |
27 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | } 10 | ], 11 | "start_url": ".", 12 | "display": "standalone", 13 | "theme_color": "#000000", 14 | "background_color": "#ffffff" 15 | } 16 | -------------------------------------------------------------------------------- /public/static/images/lamp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-alexa-workshop-smarthome-ui/b2c6425a1ae198aa1f5149269ada757bd77b6664/public/static/images/lamp.png -------------------------------------------------------------------------------- /src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | animation: App-logo-spin infinite 20s linear; 7 | height: 40vmin; 8 | pointer-events: none; 9 | } 10 | 11 | .App-header { 12 | background-color: #282c34; 13 | min-height: 100vh; 14 | display: flex; 15 | flex-direction: column; 16 | align-items: center; 17 | justify-content: center; 18 | font-size: calc(10px + 2vmin); 19 | color: white; 20 | } 21 | 22 | .App-link { 23 | color: #61dafb; 24 | } 25 | 26 | @keyframes App-logo-spin { 27 | from { 28 | transform: rotate(0deg); 29 | } 30 | to { 31 | transform: rotate(360deg); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/App.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { makeStyles } from '@material-ui/core/styles'; 3 | import AppBar from '@material-ui/core/AppBar'; 4 | import Toolbar from '@material-ui/core/Toolbar'; 5 | import Typography from '@material-ui/core/Typography'; 6 | import Button from '@material-ui/core/Button'; 7 | import IconButton from '@material-ui/core/IconButton'; 8 | import MenuIcon from '@material-ui/icons/Menu'; 9 | 10 | import Amplify, { Auth } from 'aws-amplify'; 11 | import awsconfig from './aws-exports'; 12 | import { withAuthenticator } from 'aws-amplify-react' 13 | 14 | import Device from './Device'; 15 | 16 | Amplify.configure(awsconfig); 17 | 18 | const useStyles = makeStyles(theme => ({ 19 | root: { 20 | flexGrow: 1, 21 | }, 22 | menuButton: { 23 | marginRight: theme.spacing(2), 24 | }, 25 | title: { 26 | flexGrow: 1, 27 | }, 28 | })); 29 | 30 | function App() { 31 | const classes = useStyles(); 32 | 33 | const logout = async () => { 34 | await Auth.signOut(); 35 | }; 36 | 37 | return ( 38 |
39 | 40 | 41 | 42 | 43 | 44 | 45 | Alexa Workshop 46 | 47 | 48 | 49 | 50 | 51 |
52 | ); 53 | } 54 | 55 | const signUpConfig = { 56 | defaultCountryCode: "86", 57 | usernameAttributes: "email" 58 | }; 59 | 60 | export default withAuthenticator(App, { signUpConfig }); -------------------------------------------------------------------------------- /src/App.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import App from './App'; 4 | 5 | it('renders without crashing', () => { 6 | const div = document.createElement('div'); 7 | ReactDOM.render(, div); 8 | ReactDOM.unmountComponentAtNode(div); 9 | }); 10 | -------------------------------------------------------------------------------- /src/Device.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PropTypes from 'prop-types'; 3 | import clsx from 'clsx'; 4 | import { makeStyles } from '@material-ui/core/styles'; 5 | import Card from '@material-ui/core/Card'; 6 | import CardActions from '@material-ui/core/CardActions'; 7 | import CardContent from '@material-ui/core/CardContent'; 8 | import CardMedia from '@material-ui/core/CardMedia'; 9 | import Button from '@material-ui/core/Button'; 10 | import Typography from '@material-ui/core/Typography'; 11 | import { Grid } from '@material-ui/core'; 12 | import {API, Auth, graphqlOperation} from "aws-amplify"; 13 | import * as queries from "./graphql/queries"; 14 | import * as mutations from "./graphql/mutations"; 15 | import { Connect } from "aws-amplify-react"; 16 | import Snackbar from '@material-ui/core/Snackbar'; 17 | import SnackbarContent from '@material-ui/core/SnackbarContent'; 18 | import {amber, green} from "@material-ui/core/colors" 19 | import CheckCircleIcon from '@material-ui/icons/CheckCircle'; 20 | 21 | const useStyles = makeStyles({ 22 | card: { 23 | maxWidth: 345, 24 | margin: 30 25 | }, 26 | media: { 27 | height: 0, 28 | paddingTop: '56.25%' 29 | }, 30 | }); 31 | 32 | 33 | 34 | export default function Device() { 35 | const classes = useStyles(); 36 | const [open, setOpen] = React.useState(false); 37 | const urlParams = new URLSearchParams(window.location.search); 38 | const thingName = urlParams.get('thingName'); 39 | 40 | const bindDeviceToUser = async () => { 41 | const currentUser = await Auth.currentAuthenticatedUser(); 42 | 43 | const deviceDetails = { 44 | thingName: thingName, 45 | username: currentUser.username, 46 | description: 'Smart Lamp' 47 | }; 48 | 49 | const newDevice = await API.graphql(graphqlOperation(mutations.createDevice, {input: deviceDetails})); 50 | setOpen(true) 51 | 52 | console.log(newDevice) 53 | }; 54 | 55 | const unbindDevice = async () => { 56 | 57 | const oldDevice = await API.graphql(graphqlOperation(mutations.deleteDevice, {input: {thingName: thingName}})); 58 | setOpen(true) 59 | 60 | console.log(oldDevice) 61 | }; 62 | 63 | 64 | const CardView = ({ device }) => ( 65 | 66 | 67 | 71 | 72 | 73 | Smart Lamp 74 | 75 | 76 | Smart lamp controlled to Alexa. 77 | Click the button to bind to your account. 78 | 79 | 80 | 81 | {(() => { 82 | if (device && device.username) { 83 | return ( 84 | 87 | ) 88 | } else { 89 | return ( 90 | 93 | ) 94 | } 95 | })()} 96 | 97 | 98 | 99 | ); 100 | 101 | const useStyles1 = makeStyles(theme => ({ 102 | success: { 103 | backgroundColor: green[600], 104 | }, 105 | error: { 106 | backgroundColor: theme.palette.error.dark, 107 | }, 108 | info: { 109 | backgroundColor: theme.palette.primary.main, 110 | }, 111 | warning: { 112 | backgroundColor: amber[700], 113 | }, 114 | icon: { 115 | fontSize: 20, 116 | }, 117 | iconVariant: { 118 | opacity: 0.9, 119 | marginRight: theme.spacing(1), 120 | }, 121 | message: { 122 | display: 'flex', 123 | alignItems: 'center', 124 | }, 125 | })); 126 | 127 | const variantIcon = { 128 | success: CheckCircleIcon 129 | }; 130 | 131 | function MySnackbarContentWrapper(props) { 132 | const classes = useStyles1(); 133 | const { className, message, onClose, variant, ...other } = props; 134 | const Icon = variantIcon[variant]; 135 | 136 | return ( 137 | 142 | 143 | {message} 144 | 145 | } 146 | {...other} 147 | /> 148 | ); 149 | } 150 | 151 | MySnackbarContentWrapper.propTypes = { 152 | className: PropTypes.string, 153 | message: PropTypes.string, 154 | onClose: PropTypes.func, 155 | variant: PropTypes.oneOf(['error', 'info', 'success', 'warning']).isRequired, 156 | }; 157 | 158 | 159 | function handleClose(event, reason) { 160 | if (reason === 'clickaway') { 161 | return; 162 | } 163 | 164 | setOpen(false); 165 | } 166 | 167 | 168 | return ( 169 |
170 | 179 | 184 | 185 | 186 | {({ data, error }) => { 187 | if (error || data === undefined || data === null) return (

Error

); 188 | return ( ); 189 | }} 190 |
191 |
192 | ); 193 | } 194 | -------------------------------------------------------------------------------- /src/graphql/mutations.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | // this is an auto generated file. This will be overwritten 3 | 4 | export const createDevice = /* GraphQL */ ` 5 | mutation CreateDevice( 6 | $input: CreateDeviceInput! 7 | $condition: ModelDeviceConditionInput 8 | ) { 9 | createDevice(input: $input, condition: $condition) { 10 | thingName 11 | username 12 | description 13 | createdAt 14 | updatedAt 15 | } 16 | } 17 | `; 18 | export const updateDevice = /* GraphQL */ ` 19 | mutation UpdateDevice( 20 | $input: UpdateDeviceInput! 21 | $condition: ModelDeviceConditionInput 22 | ) { 23 | updateDevice(input: $input, condition: $condition) { 24 | thingName 25 | username 26 | description 27 | createdAt 28 | updatedAt 29 | } 30 | } 31 | `; 32 | export const deleteDevice = /* GraphQL */ ` 33 | mutation DeleteDevice( 34 | $input: DeleteDeviceInput! 35 | $condition: ModelDeviceConditionInput 36 | ) { 37 | deleteDevice(input: $input, condition: $condition) { 38 | thingName 39 | username 40 | description 41 | createdAt 42 | updatedAt 43 | } 44 | } 45 | `; 46 | -------------------------------------------------------------------------------- /src/graphql/queries.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | // this is an auto generated file. This will be overwritten 3 | 4 | export const getDevice = /* GraphQL */ ` 5 | query GetDevice($thingName: String!) { 6 | getDevice(thingName: $thingName) { 7 | thingName 8 | username 9 | description 10 | createdAt 11 | updatedAt 12 | } 13 | } 14 | `; 15 | export const listDevices = /* GraphQL */ ` 16 | query ListDevices( 17 | $thingName: String 18 | $filter: ModelDeviceFilterInput 19 | $limit: Int 20 | $nextToken: String 21 | $sortDirection: ModelSortDirection 22 | ) { 23 | listDevices( 24 | thingName: $thingName 25 | filter: $filter 26 | limit: $limit 27 | nextToken: $nextToken 28 | sortDirection: $sortDirection 29 | ) { 30 | items { 31 | thingName 32 | username 33 | description 34 | createdAt 35 | updatedAt 36 | } 37 | nextToken 38 | } 39 | } 40 | `; 41 | -------------------------------------------------------------------------------- /src/graphql/schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "data" : { 3 | "__schema" : { 4 | "queryType" : { 5 | "name" : "Query" 6 | }, 7 | "mutationType" : { 8 | "name" : "Mutation" 9 | }, 10 | "subscriptionType" : { 11 | "name" : "Subscription" 12 | }, 13 | "types" : [ { 14 | "kind" : "OBJECT", 15 | "name" : "Query", 16 | "description" : null, 17 | "fields" : [ { 18 | "name" : "getDevice", 19 | "description" : null, 20 | "args" : [ { 21 | "name" : "thingName", 22 | "description" : null, 23 | "type" : { 24 | "kind" : "NON_NULL", 25 | "name" : null, 26 | "ofType" : { 27 | "kind" : "SCALAR", 28 | "name" : "String", 29 | "ofType" : null 30 | } 31 | }, 32 | "defaultValue" : null 33 | } ], 34 | "type" : { 35 | "kind" : "OBJECT", 36 | "name" : "Device", 37 | "ofType" : null 38 | }, 39 | "isDeprecated" : false, 40 | "deprecationReason" : null 41 | }, { 42 | "name" : "listDevices", 43 | "description" : null, 44 | "args" : [ { 45 | "name" : "thingName", 46 | "description" : null, 47 | "type" : { 48 | "kind" : "SCALAR", 49 | "name" : "String", 50 | "ofType" : null 51 | }, 52 | "defaultValue" : null 53 | }, { 54 | "name" : "filter", 55 | "description" : null, 56 | "type" : { 57 | "kind" : "INPUT_OBJECT", 58 | "name" : "ModelDeviceFilterInput", 59 | "ofType" : null 60 | }, 61 | "defaultValue" : null 62 | }, { 63 | "name" : "limit", 64 | "description" : null, 65 | "type" : { 66 | "kind" : "SCALAR", 67 | "name" : "Int", 68 | "ofType" : null 69 | }, 70 | "defaultValue" : null 71 | }, { 72 | "name" : "nextToken", 73 | "description" : null, 74 | "type" : { 75 | "kind" : "SCALAR", 76 | "name" : "String", 77 | "ofType" : null 78 | }, 79 | "defaultValue" : null 80 | }, { 81 | "name" : "sortDirection", 82 | "description" : null, 83 | "type" : { 84 | "kind" : "ENUM", 85 | "name" : "ModelSortDirection", 86 | "ofType" : null 87 | }, 88 | "defaultValue" : null 89 | } ], 90 | "type" : { 91 | "kind" : "OBJECT", 92 | "name" : "ModelDeviceConnection", 93 | "ofType" : null 94 | }, 95 | "isDeprecated" : false, 96 | "deprecationReason" : null 97 | } ], 98 | "inputFields" : null, 99 | "interfaces" : [ ], 100 | "enumValues" : null, 101 | "possibleTypes" : null 102 | }, { 103 | "kind" : "OBJECT", 104 | "name" : "Device", 105 | "description" : null, 106 | "fields" : [ { 107 | "name" : "thingName", 108 | "description" : null, 109 | "args" : [ ], 110 | "type" : { 111 | "kind" : "NON_NULL", 112 | "name" : null, 113 | "ofType" : { 114 | "kind" : "SCALAR", 115 | "name" : "String", 116 | "ofType" : null 117 | } 118 | }, 119 | "isDeprecated" : false, 120 | "deprecationReason" : null 121 | }, { 122 | "name" : "username", 123 | "description" : null, 124 | "args" : [ ], 125 | "type" : { 126 | "kind" : "NON_NULL", 127 | "name" : null, 128 | "ofType" : { 129 | "kind" : "SCALAR", 130 | "name" : "String", 131 | "ofType" : null 132 | } 133 | }, 134 | "isDeprecated" : false, 135 | "deprecationReason" : null 136 | }, { 137 | "name" : "description", 138 | "description" : null, 139 | "args" : [ ], 140 | "type" : { 141 | "kind" : "SCALAR", 142 | "name" : "String", 143 | "ofType" : null 144 | }, 145 | "isDeprecated" : false, 146 | "deprecationReason" : null 147 | }, { 148 | "name" : "createdAt", 149 | "description" : null, 150 | "args" : [ ], 151 | "type" : { 152 | "kind" : "NON_NULL", 153 | "name" : null, 154 | "ofType" : { 155 | "kind" : "SCALAR", 156 | "name" : "AWSDateTime", 157 | "ofType" : null 158 | } 159 | }, 160 | "isDeprecated" : false, 161 | "deprecationReason" : null 162 | }, { 163 | "name" : "updatedAt", 164 | "description" : null, 165 | "args" : [ ], 166 | "type" : { 167 | "kind" : "NON_NULL", 168 | "name" : null, 169 | "ofType" : { 170 | "kind" : "SCALAR", 171 | "name" : "AWSDateTime", 172 | "ofType" : null 173 | } 174 | }, 175 | "isDeprecated" : false, 176 | "deprecationReason" : null 177 | } ], 178 | "inputFields" : null, 179 | "interfaces" : [ ], 180 | "enumValues" : null, 181 | "possibleTypes" : null 182 | }, { 183 | "kind" : "SCALAR", 184 | "name" : "String", 185 | "description" : "Built-in String", 186 | "fields" : null, 187 | "inputFields" : null, 188 | "interfaces" : null, 189 | "enumValues" : null, 190 | "possibleTypes" : null 191 | }, { 192 | "kind" : "SCALAR", 193 | "name" : "AWSDateTime", 194 | "description" : "The `AWSDateTime` scalar type provided by AWS AppSync, represents a valid ***extended*** [ISO 8601 DateTime](https://en.wikipedia.org/wiki/ISO_8601#Combined_date_and_time_representations) string. In other words, this scalar type accepts datetime strings of the form `YYYY-MM-DDThh:mm:ss.SSSZ`. The scalar can also accept \"negative years\" of the form `-YYYY` which correspond to years before `0000`. For example, \"**-2017-01-01T00:00Z**\" and \"**-9999-01-01T00:00Z**\" are both valid datetime strings. The field after the two digit seconds field is a nanoseconds field. It can accept between 1 and 9 digits. So, for example, \"**1970-01-01T12:00:00.2Z**\", \"**1970-01-01T12:00:00.277Z**\" and \"**1970-01-01T12:00:00.123456789Z**\" are all valid datetime strings. The seconds and nanoseconds fields are optional (the seconds field must be specified if the nanoseconds field is to be used). The [time zone offset](https://en.wikipedia.org/wiki/ISO_8601#Time_zone_designators) is compulsory for this scalar. The time zone offset must either be `Z` (representing the UTC time zone) or be in the format `±hh:mm:ss`. The seconds field in the timezone offset will be considered valid even though it is not part of the ISO 8601 standard.", 195 | "fields" : null, 196 | "inputFields" : null, 197 | "interfaces" : null, 198 | "enumValues" : null, 199 | "possibleTypes" : null 200 | }, { 201 | "kind" : "OBJECT", 202 | "name" : "ModelDeviceConnection", 203 | "description" : null, 204 | "fields" : [ { 205 | "name" : "items", 206 | "description" : null, 207 | "args" : [ ], 208 | "type" : { 209 | "kind" : "LIST", 210 | "name" : null, 211 | "ofType" : { 212 | "kind" : "OBJECT", 213 | "name" : "Device", 214 | "ofType" : null 215 | } 216 | }, 217 | "isDeprecated" : false, 218 | "deprecationReason" : null 219 | }, { 220 | "name" : "nextToken", 221 | "description" : null, 222 | "args" : [ ], 223 | "type" : { 224 | "kind" : "SCALAR", 225 | "name" : "String", 226 | "ofType" : null 227 | }, 228 | "isDeprecated" : false, 229 | "deprecationReason" : null 230 | } ], 231 | "inputFields" : null, 232 | "interfaces" : [ ], 233 | "enumValues" : null, 234 | "possibleTypes" : null 235 | }, { 236 | "kind" : "INPUT_OBJECT", 237 | "name" : "ModelDeviceFilterInput", 238 | "description" : null, 239 | "fields" : null, 240 | "inputFields" : [ { 241 | "name" : "thingName", 242 | "description" : null, 243 | "type" : { 244 | "kind" : "INPUT_OBJECT", 245 | "name" : "ModelStringInput", 246 | "ofType" : null 247 | }, 248 | "defaultValue" : null 249 | }, { 250 | "name" : "username", 251 | "description" : null, 252 | "type" : { 253 | "kind" : "INPUT_OBJECT", 254 | "name" : "ModelStringInput", 255 | "ofType" : null 256 | }, 257 | "defaultValue" : null 258 | }, { 259 | "name" : "description", 260 | "description" : null, 261 | "type" : { 262 | "kind" : "INPUT_OBJECT", 263 | "name" : "ModelStringInput", 264 | "ofType" : null 265 | }, 266 | "defaultValue" : null 267 | }, { 268 | "name" : "and", 269 | "description" : null, 270 | "type" : { 271 | "kind" : "LIST", 272 | "name" : null, 273 | "ofType" : { 274 | "kind" : "INPUT_OBJECT", 275 | "name" : "ModelDeviceFilterInput", 276 | "ofType" : null 277 | } 278 | }, 279 | "defaultValue" : null 280 | }, { 281 | "name" : "or", 282 | "description" : null, 283 | "type" : { 284 | "kind" : "LIST", 285 | "name" : null, 286 | "ofType" : { 287 | "kind" : "INPUT_OBJECT", 288 | "name" : "ModelDeviceFilterInput", 289 | "ofType" : null 290 | } 291 | }, 292 | "defaultValue" : null 293 | }, { 294 | "name" : "not", 295 | "description" : null, 296 | "type" : { 297 | "kind" : "INPUT_OBJECT", 298 | "name" : "ModelDeviceFilterInput", 299 | "ofType" : null 300 | }, 301 | "defaultValue" : null 302 | } ], 303 | "interfaces" : null, 304 | "enumValues" : null, 305 | "possibleTypes" : null 306 | }, { 307 | "kind" : "INPUT_OBJECT", 308 | "name" : "ModelStringInput", 309 | "description" : null, 310 | "fields" : null, 311 | "inputFields" : [ { 312 | "name" : "ne", 313 | "description" : null, 314 | "type" : { 315 | "kind" : "SCALAR", 316 | "name" : "String", 317 | "ofType" : null 318 | }, 319 | "defaultValue" : null 320 | }, { 321 | "name" : "eq", 322 | "description" : null, 323 | "type" : { 324 | "kind" : "SCALAR", 325 | "name" : "String", 326 | "ofType" : null 327 | }, 328 | "defaultValue" : null 329 | }, { 330 | "name" : "le", 331 | "description" : null, 332 | "type" : { 333 | "kind" : "SCALAR", 334 | "name" : "String", 335 | "ofType" : null 336 | }, 337 | "defaultValue" : null 338 | }, { 339 | "name" : "lt", 340 | "description" : null, 341 | "type" : { 342 | "kind" : "SCALAR", 343 | "name" : "String", 344 | "ofType" : null 345 | }, 346 | "defaultValue" : null 347 | }, { 348 | "name" : "ge", 349 | "description" : null, 350 | "type" : { 351 | "kind" : "SCALAR", 352 | "name" : "String", 353 | "ofType" : null 354 | }, 355 | "defaultValue" : null 356 | }, { 357 | "name" : "gt", 358 | "description" : null, 359 | "type" : { 360 | "kind" : "SCALAR", 361 | "name" : "String", 362 | "ofType" : null 363 | }, 364 | "defaultValue" : null 365 | }, { 366 | "name" : "contains", 367 | "description" : null, 368 | "type" : { 369 | "kind" : "SCALAR", 370 | "name" : "String", 371 | "ofType" : null 372 | }, 373 | "defaultValue" : null 374 | }, { 375 | "name" : "notContains", 376 | "description" : null, 377 | "type" : { 378 | "kind" : "SCALAR", 379 | "name" : "String", 380 | "ofType" : null 381 | }, 382 | "defaultValue" : null 383 | }, { 384 | "name" : "between", 385 | "description" : null, 386 | "type" : { 387 | "kind" : "LIST", 388 | "name" : null, 389 | "ofType" : { 390 | "kind" : "SCALAR", 391 | "name" : "String", 392 | "ofType" : null 393 | } 394 | }, 395 | "defaultValue" : null 396 | }, { 397 | "name" : "beginsWith", 398 | "description" : null, 399 | "type" : { 400 | "kind" : "SCALAR", 401 | "name" : "String", 402 | "ofType" : null 403 | }, 404 | "defaultValue" : null 405 | }, { 406 | "name" : "attributeExists", 407 | "description" : null, 408 | "type" : { 409 | "kind" : "SCALAR", 410 | "name" : "Boolean", 411 | "ofType" : null 412 | }, 413 | "defaultValue" : null 414 | }, { 415 | "name" : "attributeType", 416 | "description" : null, 417 | "type" : { 418 | "kind" : "ENUM", 419 | "name" : "ModelAttributeTypes", 420 | "ofType" : null 421 | }, 422 | "defaultValue" : null 423 | }, { 424 | "name" : "size", 425 | "description" : null, 426 | "type" : { 427 | "kind" : "INPUT_OBJECT", 428 | "name" : "ModelSizeInput", 429 | "ofType" : null 430 | }, 431 | "defaultValue" : null 432 | } ], 433 | "interfaces" : null, 434 | "enumValues" : null, 435 | "possibleTypes" : null 436 | }, { 437 | "kind" : "SCALAR", 438 | "name" : "Boolean", 439 | "description" : "Built-in Boolean", 440 | "fields" : null, 441 | "inputFields" : null, 442 | "interfaces" : null, 443 | "enumValues" : null, 444 | "possibleTypes" : null 445 | }, { 446 | "kind" : "ENUM", 447 | "name" : "ModelAttributeTypes", 448 | "description" : null, 449 | "fields" : null, 450 | "inputFields" : null, 451 | "interfaces" : null, 452 | "enumValues" : [ { 453 | "name" : "binary", 454 | "description" : null, 455 | "isDeprecated" : false, 456 | "deprecationReason" : null 457 | }, { 458 | "name" : "binarySet", 459 | "description" : null, 460 | "isDeprecated" : false, 461 | "deprecationReason" : null 462 | }, { 463 | "name" : "bool", 464 | "description" : null, 465 | "isDeprecated" : false, 466 | "deprecationReason" : null 467 | }, { 468 | "name" : "list", 469 | "description" : null, 470 | "isDeprecated" : false, 471 | "deprecationReason" : null 472 | }, { 473 | "name" : "map", 474 | "description" : null, 475 | "isDeprecated" : false, 476 | "deprecationReason" : null 477 | }, { 478 | "name" : "number", 479 | "description" : null, 480 | "isDeprecated" : false, 481 | "deprecationReason" : null 482 | }, { 483 | "name" : "numberSet", 484 | "description" : null, 485 | "isDeprecated" : false, 486 | "deprecationReason" : null 487 | }, { 488 | "name" : "string", 489 | "description" : null, 490 | "isDeprecated" : false, 491 | "deprecationReason" : null 492 | }, { 493 | "name" : "stringSet", 494 | "description" : null, 495 | "isDeprecated" : false, 496 | "deprecationReason" : null 497 | }, { 498 | "name" : "_null", 499 | "description" : null, 500 | "isDeprecated" : false, 501 | "deprecationReason" : null 502 | } ], 503 | "possibleTypes" : null 504 | }, { 505 | "kind" : "INPUT_OBJECT", 506 | "name" : "ModelSizeInput", 507 | "description" : null, 508 | "fields" : null, 509 | "inputFields" : [ { 510 | "name" : "ne", 511 | "description" : null, 512 | "type" : { 513 | "kind" : "SCALAR", 514 | "name" : "Int", 515 | "ofType" : null 516 | }, 517 | "defaultValue" : null 518 | }, { 519 | "name" : "eq", 520 | "description" : null, 521 | "type" : { 522 | "kind" : "SCALAR", 523 | "name" : "Int", 524 | "ofType" : null 525 | }, 526 | "defaultValue" : null 527 | }, { 528 | "name" : "le", 529 | "description" : null, 530 | "type" : { 531 | "kind" : "SCALAR", 532 | "name" : "Int", 533 | "ofType" : null 534 | }, 535 | "defaultValue" : null 536 | }, { 537 | "name" : "lt", 538 | "description" : null, 539 | "type" : { 540 | "kind" : "SCALAR", 541 | "name" : "Int", 542 | "ofType" : null 543 | }, 544 | "defaultValue" : null 545 | }, { 546 | "name" : "ge", 547 | "description" : null, 548 | "type" : { 549 | "kind" : "SCALAR", 550 | "name" : "Int", 551 | "ofType" : null 552 | }, 553 | "defaultValue" : null 554 | }, { 555 | "name" : "gt", 556 | "description" : null, 557 | "type" : { 558 | "kind" : "SCALAR", 559 | "name" : "Int", 560 | "ofType" : null 561 | }, 562 | "defaultValue" : null 563 | }, { 564 | "name" : "between", 565 | "description" : null, 566 | "type" : { 567 | "kind" : "LIST", 568 | "name" : null, 569 | "ofType" : { 570 | "kind" : "SCALAR", 571 | "name" : "Int", 572 | "ofType" : null 573 | } 574 | }, 575 | "defaultValue" : null 576 | } ], 577 | "interfaces" : null, 578 | "enumValues" : null, 579 | "possibleTypes" : null 580 | }, { 581 | "kind" : "SCALAR", 582 | "name" : "Int", 583 | "description" : "Built-in Int", 584 | "fields" : null, 585 | "inputFields" : null, 586 | "interfaces" : null, 587 | "enumValues" : null, 588 | "possibleTypes" : null 589 | }, { 590 | "kind" : "ENUM", 591 | "name" : "ModelSortDirection", 592 | "description" : null, 593 | "fields" : null, 594 | "inputFields" : null, 595 | "interfaces" : null, 596 | "enumValues" : [ { 597 | "name" : "ASC", 598 | "description" : null, 599 | "isDeprecated" : false, 600 | "deprecationReason" : null 601 | }, { 602 | "name" : "DESC", 603 | "description" : null, 604 | "isDeprecated" : false, 605 | "deprecationReason" : null 606 | } ], 607 | "possibleTypes" : null 608 | }, { 609 | "kind" : "OBJECT", 610 | "name" : "Mutation", 611 | "description" : null, 612 | "fields" : [ { 613 | "name" : "createDevice", 614 | "description" : null, 615 | "args" : [ { 616 | "name" : "input", 617 | "description" : null, 618 | "type" : { 619 | "kind" : "NON_NULL", 620 | "name" : null, 621 | "ofType" : { 622 | "kind" : "INPUT_OBJECT", 623 | "name" : "CreateDeviceInput", 624 | "ofType" : null 625 | } 626 | }, 627 | "defaultValue" : null 628 | }, { 629 | "name" : "condition", 630 | "description" : null, 631 | "type" : { 632 | "kind" : "INPUT_OBJECT", 633 | "name" : "ModelDeviceConditionInput", 634 | "ofType" : null 635 | }, 636 | "defaultValue" : null 637 | } ], 638 | "type" : { 639 | "kind" : "OBJECT", 640 | "name" : "Device", 641 | "ofType" : null 642 | }, 643 | "isDeprecated" : false, 644 | "deprecationReason" : null 645 | }, { 646 | "name" : "updateDevice", 647 | "description" : null, 648 | "args" : [ { 649 | "name" : "input", 650 | "description" : null, 651 | "type" : { 652 | "kind" : "NON_NULL", 653 | "name" : null, 654 | "ofType" : { 655 | "kind" : "INPUT_OBJECT", 656 | "name" : "UpdateDeviceInput", 657 | "ofType" : null 658 | } 659 | }, 660 | "defaultValue" : null 661 | }, { 662 | "name" : "condition", 663 | "description" : null, 664 | "type" : { 665 | "kind" : "INPUT_OBJECT", 666 | "name" : "ModelDeviceConditionInput", 667 | "ofType" : null 668 | }, 669 | "defaultValue" : null 670 | } ], 671 | "type" : { 672 | "kind" : "OBJECT", 673 | "name" : "Device", 674 | "ofType" : null 675 | }, 676 | "isDeprecated" : false, 677 | "deprecationReason" : null 678 | }, { 679 | "name" : "deleteDevice", 680 | "description" : null, 681 | "args" : [ { 682 | "name" : "input", 683 | "description" : null, 684 | "type" : { 685 | "kind" : "NON_NULL", 686 | "name" : null, 687 | "ofType" : { 688 | "kind" : "INPUT_OBJECT", 689 | "name" : "DeleteDeviceInput", 690 | "ofType" : null 691 | } 692 | }, 693 | "defaultValue" : null 694 | }, { 695 | "name" : "condition", 696 | "description" : null, 697 | "type" : { 698 | "kind" : "INPUT_OBJECT", 699 | "name" : "ModelDeviceConditionInput", 700 | "ofType" : null 701 | }, 702 | "defaultValue" : null 703 | } ], 704 | "type" : { 705 | "kind" : "OBJECT", 706 | "name" : "Device", 707 | "ofType" : null 708 | }, 709 | "isDeprecated" : false, 710 | "deprecationReason" : null 711 | } ], 712 | "inputFields" : null, 713 | "interfaces" : [ ], 714 | "enumValues" : null, 715 | "possibleTypes" : null 716 | }, { 717 | "kind" : "INPUT_OBJECT", 718 | "name" : "CreateDeviceInput", 719 | "description" : null, 720 | "fields" : null, 721 | "inputFields" : [ { 722 | "name" : "thingName", 723 | "description" : null, 724 | "type" : { 725 | "kind" : "NON_NULL", 726 | "name" : null, 727 | "ofType" : { 728 | "kind" : "SCALAR", 729 | "name" : "String", 730 | "ofType" : null 731 | } 732 | }, 733 | "defaultValue" : null 734 | }, { 735 | "name" : "username", 736 | "description" : null, 737 | "type" : { 738 | "kind" : "NON_NULL", 739 | "name" : null, 740 | "ofType" : { 741 | "kind" : "SCALAR", 742 | "name" : "String", 743 | "ofType" : null 744 | } 745 | }, 746 | "defaultValue" : null 747 | }, { 748 | "name" : "description", 749 | "description" : null, 750 | "type" : { 751 | "kind" : "SCALAR", 752 | "name" : "String", 753 | "ofType" : null 754 | }, 755 | "defaultValue" : null 756 | } ], 757 | "interfaces" : null, 758 | "enumValues" : null, 759 | "possibleTypes" : null 760 | }, { 761 | "kind" : "INPUT_OBJECT", 762 | "name" : "ModelDeviceConditionInput", 763 | "description" : null, 764 | "fields" : null, 765 | "inputFields" : [ { 766 | "name" : "username", 767 | "description" : null, 768 | "type" : { 769 | "kind" : "INPUT_OBJECT", 770 | "name" : "ModelStringInput", 771 | "ofType" : null 772 | }, 773 | "defaultValue" : null 774 | }, { 775 | "name" : "description", 776 | "description" : null, 777 | "type" : { 778 | "kind" : "INPUT_OBJECT", 779 | "name" : "ModelStringInput", 780 | "ofType" : null 781 | }, 782 | "defaultValue" : null 783 | }, { 784 | "name" : "and", 785 | "description" : null, 786 | "type" : { 787 | "kind" : "LIST", 788 | "name" : null, 789 | "ofType" : { 790 | "kind" : "INPUT_OBJECT", 791 | "name" : "ModelDeviceConditionInput", 792 | "ofType" : null 793 | } 794 | }, 795 | "defaultValue" : null 796 | }, { 797 | "name" : "or", 798 | "description" : null, 799 | "type" : { 800 | "kind" : "LIST", 801 | "name" : null, 802 | "ofType" : { 803 | "kind" : "INPUT_OBJECT", 804 | "name" : "ModelDeviceConditionInput", 805 | "ofType" : null 806 | } 807 | }, 808 | "defaultValue" : null 809 | }, { 810 | "name" : "not", 811 | "description" : null, 812 | "type" : { 813 | "kind" : "INPUT_OBJECT", 814 | "name" : "ModelDeviceConditionInput", 815 | "ofType" : null 816 | }, 817 | "defaultValue" : null 818 | } ], 819 | "interfaces" : null, 820 | "enumValues" : null, 821 | "possibleTypes" : null 822 | }, { 823 | "kind" : "INPUT_OBJECT", 824 | "name" : "UpdateDeviceInput", 825 | "description" : null, 826 | "fields" : null, 827 | "inputFields" : [ { 828 | "name" : "thingName", 829 | "description" : null, 830 | "type" : { 831 | "kind" : "NON_NULL", 832 | "name" : null, 833 | "ofType" : { 834 | "kind" : "SCALAR", 835 | "name" : "String", 836 | "ofType" : null 837 | } 838 | }, 839 | "defaultValue" : null 840 | }, { 841 | "name" : "username", 842 | "description" : null, 843 | "type" : { 844 | "kind" : "SCALAR", 845 | "name" : "String", 846 | "ofType" : null 847 | }, 848 | "defaultValue" : null 849 | }, { 850 | "name" : "description", 851 | "description" : null, 852 | "type" : { 853 | "kind" : "SCALAR", 854 | "name" : "String", 855 | "ofType" : null 856 | }, 857 | "defaultValue" : null 858 | } ], 859 | "interfaces" : null, 860 | "enumValues" : null, 861 | "possibleTypes" : null 862 | }, { 863 | "kind" : "INPUT_OBJECT", 864 | "name" : "DeleteDeviceInput", 865 | "description" : null, 866 | "fields" : null, 867 | "inputFields" : [ { 868 | "name" : "thingName", 869 | "description" : null, 870 | "type" : { 871 | "kind" : "NON_NULL", 872 | "name" : null, 873 | "ofType" : { 874 | "kind" : "SCALAR", 875 | "name" : "String", 876 | "ofType" : null 877 | } 878 | }, 879 | "defaultValue" : null 880 | } ], 881 | "interfaces" : null, 882 | "enumValues" : null, 883 | "possibleTypes" : null 884 | }, { 885 | "kind" : "OBJECT", 886 | "name" : "Subscription", 887 | "description" : null, 888 | "fields" : [ { 889 | "name" : "onCreateDevice", 890 | "description" : null, 891 | "args" : [ ], 892 | "type" : { 893 | "kind" : "OBJECT", 894 | "name" : "Device", 895 | "ofType" : null 896 | }, 897 | "isDeprecated" : false, 898 | "deprecationReason" : null 899 | }, { 900 | "name" : "onUpdateDevice", 901 | "description" : null, 902 | "args" : [ ], 903 | "type" : { 904 | "kind" : "OBJECT", 905 | "name" : "Device", 906 | "ofType" : null 907 | }, 908 | "isDeprecated" : false, 909 | "deprecationReason" : null 910 | }, { 911 | "name" : "onDeleteDevice", 912 | "description" : null, 913 | "args" : [ ], 914 | "type" : { 915 | "kind" : "OBJECT", 916 | "name" : "Device", 917 | "ofType" : null 918 | }, 919 | "isDeprecated" : false, 920 | "deprecationReason" : null 921 | } ], 922 | "inputFields" : null, 923 | "interfaces" : [ ], 924 | "enumValues" : null, 925 | "possibleTypes" : null 926 | }, { 927 | "kind" : "INPUT_OBJECT", 928 | "name" : "ModelBooleanInput", 929 | "description" : null, 930 | "fields" : null, 931 | "inputFields" : [ { 932 | "name" : "ne", 933 | "description" : null, 934 | "type" : { 935 | "kind" : "SCALAR", 936 | "name" : "Boolean", 937 | "ofType" : null 938 | }, 939 | "defaultValue" : null 940 | }, { 941 | "name" : "eq", 942 | "description" : null, 943 | "type" : { 944 | "kind" : "SCALAR", 945 | "name" : "Boolean", 946 | "ofType" : null 947 | }, 948 | "defaultValue" : null 949 | }, { 950 | "name" : "attributeExists", 951 | "description" : null, 952 | "type" : { 953 | "kind" : "SCALAR", 954 | "name" : "Boolean", 955 | "ofType" : null 956 | }, 957 | "defaultValue" : null 958 | }, { 959 | "name" : "attributeType", 960 | "description" : null, 961 | "type" : { 962 | "kind" : "ENUM", 963 | "name" : "ModelAttributeTypes", 964 | "ofType" : null 965 | }, 966 | "defaultValue" : null 967 | } ], 968 | "interfaces" : null, 969 | "enumValues" : null, 970 | "possibleTypes" : null 971 | }, { 972 | "kind" : "INPUT_OBJECT", 973 | "name" : "ModelIDInput", 974 | "description" : null, 975 | "fields" : null, 976 | "inputFields" : [ { 977 | "name" : "ne", 978 | "description" : null, 979 | "type" : { 980 | "kind" : "SCALAR", 981 | "name" : "ID", 982 | "ofType" : null 983 | }, 984 | "defaultValue" : null 985 | }, { 986 | "name" : "eq", 987 | "description" : null, 988 | "type" : { 989 | "kind" : "SCALAR", 990 | "name" : "ID", 991 | "ofType" : null 992 | }, 993 | "defaultValue" : null 994 | }, { 995 | "name" : "le", 996 | "description" : null, 997 | "type" : { 998 | "kind" : "SCALAR", 999 | "name" : "ID", 1000 | "ofType" : null 1001 | }, 1002 | "defaultValue" : null 1003 | }, { 1004 | "name" : "lt", 1005 | "description" : null, 1006 | "type" : { 1007 | "kind" : "SCALAR", 1008 | "name" : "ID", 1009 | "ofType" : null 1010 | }, 1011 | "defaultValue" : null 1012 | }, { 1013 | "name" : "ge", 1014 | "description" : null, 1015 | "type" : { 1016 | "kind" : "SCALAR", 1017 | "name" : "ID", 1018 | "ofType" : null 1019 | }, 1020 | "defaultValue" : null 1021 | }, { 1022 | "name" : "gt", 1023 | "description" : null, 1024 | "type" : { 1025 | "kind" : "SCALAR", 1026 | "name" : "ID", 1027 | "ofType" : null 1028 | }, 1029 | "defaultValue" : null 1030 | }, { 1031 | "name" : "contains", 1032 | "description" : null, 1033 | "type" : { 1034 | "kind" : "SCALAR", 1035 | "name" : "ID", 1036 | "ofType" : null 1037 | }, 1038 | "defaultValue" : null 1039 | }, { 1040 | "name" : "notContains", 1041 | "description" : null, 1042 | "type" : { 1043 | "kind" : "SCALAR", 1044 | "name" : "ID", 1045 | "ofType" : null 1046 | }, 1047 | "defaultValue" : null 1048 | }, { 1049 | "name" : "between", 1050 | "description" : null, 1051 | "type" : { 1052 | "kind" : "LIST", 1053 | "name" : null, 1054 | "ofType" : { 1055 | "kind" : "SCALAR", 1056 | "name" : "ID", 1057 | "ofType" : null 1058 | } 1059 | }, 1060 | "defaultValue" : null 1061 | }, { 1062 | "name" : "beginsWith", 1063 | "description" : null, 1064 | "type" : { 1065 | "kind" : "SCALAR", 1066 | "name" : "ID", 1067 | "ofType" : null 1068 | }, 1069 | "defaultValue" : null 1070 | }, { 1071 | "name" : "attributeExists", 1072 | "description" : null, 1073 | "type" : { 1074 | "kind" : "SCALAR", 1075 | "name" : "Boolean", 1076 | "ofType" : null 1077 | }, 1078 | "defaultValue" : null 1079 | }, { 1080 | "name" : "attributeType", 1081 | "description" : null, 1082 | "type" : { 1083 | "kind" : "ENUM", 1084 | "name" : "ModelAttributeTypes", 1085 | "ofType" : null 1086 | }, 1087 | "defaultValue" : null 1088 | }, { 1089 | "name" : "size", 1090 | "description" : null, 1091 | "type" : { 1092 | "kind" : "INPUT_OBJECT", 1093 | "name" : "ModelSizeInput", 1094 | "ofType" : null 1095 | }, 1096 | "defaultValue" : null 1097 | } ], 1098 | "interfaces" : null, 1099 | "enumValues" : null, 1100 | "possibleTypes" : null 1101 | }, { 1102 | "kind" : "SCALAR", 1103 | "name" : "ID", 1104 | "description" : "Built-in ID", 1105 | "fields" : null, 1106 | "inputFields" : null, 1107 | "interfaces" : null, 1108 | "enumValues" : null, 1109 | "possibleTypes" : null 1110 | }, { 1111 | "kind" : "INPUT_OBJECT", 1112 | "name" : "ModelFloatInput", 1113 | "description" : null, 1114 | "fields" : null, 1115 | "inputFields" : [ { 1116 | "name" : "ne", 1117 | "description" : null, 1118 | "type" : { 1119 | "kind" : "SCALAR", 1120 | "name" : "Float", 1121 | "ofType" : null 1122 | }, 1123 | "defaultValue" : null 1124 | }, { 1125 | "name" : "eq", 1126 | "description" : null, 1127 | "type" : { 1128 | "kind" : "SCALAR", 1129 | "name" : "Float", 1130 | "ofType" : null 1131 | }, 1132 | "defaultValue" : null 1133 | }, { 1134 | "name" : "le", 1135 | "description" : null, 1136 | "type" : { 1137 | "kind" : "SCALAR", 1138 | "name" : "Float", 1139 | "ofType" : null 1140 | }, 1141 | "defaultValue" : null 1142 | }, { 1143 | "name" : "lt", 1144 | "description" : null, 1145 | "type" : { 1146 | "kind" : "SCALAR", 1147 | "name" : "Float", 1148 | "ofType" : null 1149 | }, 1150 | "defaultValue" : null 1151 | }, { 1152 | "name" : "ge", 1153 | "description" : null, 1154 | "type" : { 1155 | "kind" : "SCALAR", 1156 | "name" : "Float", 1157 | "ofType" : null 1158 | }, 1159 | "defaultValue" : null 1160 | }, { 1161 | "name" : "gt", 1162 | "description" : null, 1163 | "type" : { 1164 | "kind" : "SCALAR", 1165 | "name" : "Float", 1166 | "ofType" : null 1167 | }, 1168 | "defaultValue" : null 1169 | }, { 1170 | "name" : "between", 1171 | "description" : null, 1172 | "type" : { 1173 | "kind" : "LIST", 1174 | "name" : null, 1175 | "ofType" : { 1176 | "kind" : "SCALAR", 1177 | "name" : "Float", 1178 | "ofType" : null 1179 | } 1180 | }, 1181 | "defaultValue" : null 1182 | }, { 1183 | "name" : "attributeExists", 1184 | "description" : null, 1185 | "type" : { 1186 | "kind" : "SCALAR", 1187 | "name" : "Boolean", 1188 | "ofType" : null 1189 | }, 1190 | "defaultValue" : null 1191 | }, { 1192 | "name" : "attributeType", 1193 | "description" : null, 1194 | "type" : { 1195 | "kind" : "ENUM", 1196 | "name" : "ModelAttributeTypes", 1197 | "ofType" : null 1198 | }, 1199 | "defaultValue" : null 1200 | } ], 1201 | "interfaces" : null, 1202 | "enumValues" : null, 1203 | "possibleTypes" : null 1204 | }, { 1205 | "kind" : "SCALAR", 1206 | "name" : "Float", 1207 | "description" : "Built-in Float", 1208 | "fields" : null, 1209 | "inputFields" : null, 1210 | "interfaces" : null, 1211 | "enumValues" : null, 1212 | "possibleTypes" : null 1213 | }, { 1214 | "kind" : "INPUT_OBJECT", 1215 | "name" : "ModelStringKeyConditionInput", 1216 | "description" : null, 1217 | "fields" : null, 1218 | "inputFields" : [ { 1219 | "name" : "eq", 1220 | "description" : null, 1221 | "type" : { 1222 | "kind" : "SCALAR", 1223 | "name" : "String", 1224 | "ofType" : null 1225 | }, 1226 | "defaultValue" : null 1227 | }, { 1228 | "name" : "le", 1229 | "description" : null, 1230 | "type" : { 1231 | "kind" : "SCALAR", 1232 | "name" : "String", 1233 | "ofType" : null 1234 | }, 1235 | "defaultValue" : null 1236 | }, { 1237 | "name" : "lt", 1238 | "description" : null, 1239 | "type" : { 1240 | "kind" : "SCALAR", 1241 | "name" : "String", 1242 | "ofType" : null 1243 | }, 1244 | "defaultValue" : null 1245 | }, { 1246 | "name" : "ge", 1247 | "description" : null, 1248 | "type" : { 1249 | "kind" : "SCALAR", 1250 | "name" : "String", 1251 | "ofType" : null 1252 | }, 1253 | "defaultValue" : null 1254 | }, { 1255 | "name" : "gt", 1256 | "description" : null, 1257 | "type" : { 1258 | "kind" : "SCALAR", 1259 | "name" : "String", 1260 | "ofType" : null 1261 | }, 1262 | "defaultValue" : null 1263 | }, { 1264 | "name" : "between", 1265 | "description" : null, 1266 | "type" : { 1267 | "kind" : "LIST", 1268 | "name" : null, 1269 | "ofType" : { 1270 | "kind" : "SCALAR", 1271 | "name" : "String", 1272 | "ofType" : null 1273 | } 1274 | }, 1275 | "defaultValue" : null 1276 | }, { 1277 | "name" : "beginsWith", 1278 | "description" : null, 1279 | "type" : { 1280 | "kind" : "SCALAR", 1281 | "name" : "String", 1282 | "ofType" : null 1283 | }, 1284 | "defaultValue" : null 1285 | } ], 1286 | "interfaces" : null, 1287 | "enumValues" : null, 1288 | "possibleTypes" : null 1289 | }, { 1290 | "kind" : "INPUT_OBJECT", 1291 | "name" : "ModelIntInput", 1292 | "description" : null, 1293 | "fields" : null, 1294 | "inputFields" : [ { 1295 | "name" : "ne", 1296 | "description" : null, 1297 | "type" : { 1298 | "kind" : "SCALAR", 1299 | "name" : "Int", 1300 | "ofType" : null 1301 | }, 1302 | "defaultValue" : null 1303 | }, { 1304 | "name" : "eq", 1305 | "description" : null, 1306 | "type" : { 1307 | "kind" : "SCALAR", 1308 | "name" : "Int", 1309 | "ofType" : null 1310 | }, 1311 | "defaultValue" : null 1312 | }, { 1313 | "name" : "le", 1314 | "description" : null, 1315 | "type" : { 1316 | "kind" : "SCALAR", 1317 | "name" : "Int", 1318 | "ofType" : null 1319 | }, 1320 | "defaultValue" : null 1321 | }, { 1322 | "name" : "lt", 1323 | "description" : null, 1324 | "type" : { 1325 | "kind" : "SCALAR", 1326 | "name" : "Int", 1327 | "ofType" : null 1328 | }, 1329 | "defaultValue" : null 1330 | }, { 1331 | "name" : "ge", 1332 | "description" : null, 1333 | "type" : { 1334 | "kind" : "SCALAR", 1335 | "name" : "Int", 1336 | "ofType" : null 1337 | }, 1338 | "defaultValue" : null 1339 | }, { 1340 | "name" : "gt", 1341 | "description" : null, 1342 | "type" : { 1343 | "kind" : "SCALAR", 1344 | "name" : "Int", 1345 | "ofType" : null 1346 | }, 1347 | "defaultValue" : null 1348 | }, { 1349 | "name" : "between", 1350 | "description" : null, 1351 | "type" : { 1352 | "kind" : "LIST", 1353 | "name" : null, 1354 | "ofType" : { 1355 | "kind" : "SCALAR", 1356 | "name" : "Int", 1357 | "ofType" : null 1358 | } 1359 | }, 1360 | "defaultValue" : null 1361 | }, { 1362 | "name" : "attributeExists", 1363 | "description" : null, 1364 | "type" : { 1365 | "kind" : "SCALAR", 1366 | "name" : "Boolean", 1367 | "ofType" : null 1368 | }, 1369 | "defaultValue" : null 1370 | }, { 1371 | "name" : "attributeType", 1372 | "description" : null, 1373 | "type" : { 1374 | "kind" : "ENUM", 1375 | "name" : "ModelAttributeTypes", 1376 | "ofType" : null 1377 | }, 1378 | "defaultValue" : null 1379 | } ], 1380 | "interfaces" : null, 1381 | "enumValues" : null, 1382 | "possibleTypes" : null 1383 | }, { 1384 | "kind" : "OBJECT", 1385 | "name" : "__Schema", 1386 | "description" : "A GraphQL Introspection defines the capabilities of a GraphQL server. It exposes all available types and directives on the server, the entry points for query, mutation, and subscription operations.", 1387 | "fields" : [ { 1388 | "name" : "types", 1389 | "description" : "A list of all types supported by this server.", 1390 | "args" : [ ], 1391 | "type" : { 1392 | "kind" : "NON_NULL", 1393 | "name" : null, 1394 | "ofType" : { 1395 | "kind" : "LIST", 1396 | "name" : null, 1397 | "ofType" : { 1398 | "kind" : "NON_NULL", 1399 | "name" : null, 1400 | "ofType" : { 1401 | "kind" : "OBJECT", 1402 | "name" : "__Type", 1403 | "ofType" : null 1404 | } 1405 | } 1406 | } 1407 | }, 1408 | "isDeprecated" : false, 1409 | "deprecationReason" : null 1410 | }, { 1411 | "name" : "queryType", 1412 | "description" : "The type that query operations will be rooted at.", 1413 | "args" : [ ], 1414 | "type" : { 1415 | "kind" : "NON_NULL", 1416 | "name" : null, 1417 | "ofType" : { 1418 | "kind" : "OBJECT", 1419 | "name" : "__Type", 1420 | "ofType" : null 1421 | } 1422 | }, 1423 | "isDeprecated" : false, 1424 | "deprecationReason" : null 1425 | }, { 1426 | "name" : "mutationType", 1427 | "description" : "If this server supports mutation, the type that mutation operations will be rooted at.", 1428 | "args" : [ ], 1429 | "type" : { 1430 | "kind" : "OBJECT", 1431 | "name" : "__Type", 1432 | "ofType" : null 1433 | }, 1434 | "isDeprecated" : false, 1435 | "deprecationReason" : null 1436 | }, { 1437 | "name" : "directives", 1438 | "description" : "'A list of all directives supported by this server.", 1439 | "args" : [ ], 1440 | "type" : { 1441 | "kind" : "NON_NULL", 1442 | "name" : null, 1443 | "ofType" : { 1444 | "kind" : "LIST", 1445 | "name" : null, 1446 | "ofType" : { 1447 | "kind" : "NON_NULL", 1448 | "name" : null, 1449 | "ofType" : { 1450 | "kind" : "OBJECT", 1451 | "name" : "__Directive", 1452 | "ofType" : null 1453 | } 1454 | } 1455 | } 1456 | }, 1457 | "isDeprecated" : false, 1458 | "deprecationReason" : null 1459 | }, { 1460 | "name" : "subscriptionType", 1461 | "description" : "'If this server support subscription, the type that subscription operations will be rooted at.", 1462 | "args" : [ ], 1463 | "type" : { 1464 | "kind" : "OBJECT", 1465 | "name" : "__Type", 1466 | "ofType" : null 1467 | }, 1468 | "isDeprecated" : false, 1469 | "deprecationReason" : null 1470 | } ], 1471 | "inputFields" : null, 1472 | "interfaces" : [ ], 1473 | "enumValues" : null, 1474 | "possibleTypes" : null 1475 | }, { 1476 | "kind" : "OBJECT", 1477 | "name" : "__Type", 1478 | "description" : null, 1479 | "fields" : [ { 1480 | "name" : "kind", 1481 | "description" : null, 1482 | "args" : [ ], 1483 | "type" : { 1484 | "kind" : "NON_NULL", 1485 | "name" : null, 1486 | "ofType" : { 1487 | "kind" : "ENUM", 1488 | "name" : "__TypeKind", 1489 | "ofType" : null 1490 | } 1491 | }, 1492 | "isDeprecated" : false, 1493 | "deprecationReason" : null 1494 | }, { 1495 | "name" : "name", 1496 | "description" : null, 1497 | "args" : [ ], 1498 | "type" : { 1499 | "kind" : "SCALAR", 1500 | "name" : "String", 1501 | "ofType" : null 1502 | }, 1503 | "isDeprecated" : false, 1504 | "deprecationReason" : null 1505 | }, { 1506 | "name" : "description", 1507 | "description" : null, 1508 | "args" : [ ], 1509 | "type" : { 1510 | "kind" : "SCALAR", 1511 | "name" : "String", 1512 | "ofType" : null 1513 | }, 1514 | "isDeprecated" : false, 1515 | "deprecationReason" : null 1516 | }, { 1517 | "name" : "fields", 1518 | "description" : null, 1519 | "args" : [ { 1520 | "name" : "includeDeprecated", 1521 | "description" : null, 1522 | "type" : { 1523 | "kind" : "SCALAR", 1524 | "name" : "Boolean", 1525 | "ofType" : null 1526 | }, 1527 | "defaultValue" : "false" 1528 | } ], 1529 | "type" : { 1530 | "kind" : "LIST", 1531 | "name" : null, 1532 | "ofType" : { 1533 | "kind" : "NON_NULL", 1534 | "name" : null, 1535 | "ofType" : { 1536 | "kind" : "OBJECT", 1537 | "name" : "__Field", 1538 | "ofType" : null 1539 | } 1540 | } 1541 | }, 1542 | "isDeprecated" : false, 1543 | "deprecationReason" : null 1544 | }, { 1545 | "name" : "interfaces", 1546 | "description" : null, 1547 | "args" : [ ], 1548 | "type" : { 1549 | "kind" : "LIST", 1550 | "name" : null, 1551 | "ofType" : { 1552 | "kind" : "NON_NULL", 1553 | "name" : null, 1554 | "ofType" : { 1555 | "kind" : "OBJECT", 1556 | "name" : "__Type", 1557 | "ofType" : null 1558 | } 1559 | } 1560 | }, 1561 | "isDeprecated" : false, 1562 | "deprecationReason" : null 1563 | }, { 1564 | "name" : "possibleTypes", 1565 | "description" : null, 1566 | "args" : [ ], 1567 | "type" : { 1568 | "kind" : "LIST", 1569 | "name" : null, 1570 | "ofType" : { 1571 | "kind" : "NON_NULL", 1572 | "name" : null, 1573 | "ofType" : { 1574 | "kind" : "OBJECT", 1575 | "name" : "__Type", 1576 | "ofType" : null 1577 | } 1578 | } 1579 | }, 1580 | "isDeprecated" : false, 1581 | "deprecationReason" : null 1582 | }, { 1583 | "name" : "enumValues", 1584 | "description" : null, 1585 | "args" : [ { 1586 | "name" : "includeDeprecated", 1587 | "description" : null, 1588 | "type" : { 1589 | "kind" : "SCALAR", 1590 | "name" : "Boolean", 1591 | "ofType" : null 1592 | }, 1593 | "defaultValue" : "false" 1594 | } ], 1595 | "type" : { 1596 | "kind" : "LIST", 1597 | "name" : null, 1598 | "ofType" : { 1599 | "kind" : "NON_NULL", 1600 | "name" : null, 1601 | "ofType" : { 1602 | "kind" : "OBJECT", 1603 | "name" : "__EnumValue", 1604 | "ofType" : null 1605 | } 1606 | } 1607 | }, 1608 | "isDeprecated" : false, 1609 | "deprecationReason" : null 1610 | }, { 1611 | "name" : "inputFields", 1612 | "description" : null, 1613 | "args" : [ ], 1614 | "type" : { 1615 | "kind" : "LIST", 1616 | "name" : null, 1617 | "ofType" : { 1618 | "kind" : "NON_NULL", 1619 | "name" : null, 1620 | "ofType" : { 1621 | "kind" : "OBJECT", 1622 | "name" : "__InputValue", 1623 | "ofType" : null 1624 | } 1625 | } 1626 | }, 1627 | "isDeprecated" : false, 1628 | "deprecationReason" : null 1629 | }, { 1630 | "name" : "ofType", 1631 | "description" : null, 1632 | "args" : [ ], 1633 | "type" : { 1634 | "kind" : "OBJECT", 1635 | "name" : "__Type", 1636 | "ofType" : null 1637 | }, 1638 | "isDeprecated" : false, 1639 | "deprecationReason" : null 1640 | } ], 1641 | "inputFields" : null, 1642 | "interfaces" : [ ], 1643 | "enumValues" : null, 1644 | "possibleTypes" : null 1645 | }, { 1646 | "kind" : "ENUM", 1647 | "name" : "__TypeKind", 1648 | "description" : "An enum describing what kind of type a given __Type is", 1649 | "fields" : null, 1650 | "inputFields" : null, 1651 | "interfaces" : null, 1652 | "enumValues" : [ { 1653 | "name" : "SCALAR", 1654 | "description" : "Indicates this type is a scalar.", 1655 | "isDeprecated" : false, 1656 | "deprecationReason" : null 1657 | }, { 1658 | "name" : "OBJECT", 1659 | "description" : "Indicates this type is an object. `fields` and `interfaces` are valid fields.", 1660 | "isDeprecated" : false, 1661 | "deprecationReason" : null 1662 | }, { 1663 | "name" : "INTERFACE", 1664 | "description" : "Indicates this type is an interface. `fields` and `possibleTypes` are valid fields.", 1665 | "isDeprecated" : false, 1666 | "deprecationReason" : null 1667 | }, { 1668 | "name" : "UNION", 1669 | "description" : "Indicates this type is a union. `possibleTypes` is a valid field.", 1670 | "isDeprecated" : false, 1671 | "deprecationReason" : null 1672 | }, { 1673 | "name" : "ENUM", 1674 | "description" : "Indicates this type is an enum. `enumValues` is a valid field.", 1675 | "isDeprecated" : false, 1676 | "deprecationReason" : null 1677 | }, { 1678 | "name" : "INPUT_OBJECT", 1679 | "description" : "Indicates this type is an input object. `inputFields` is a valid field.", 1680 | "isDeprecated" : false, 1681 | "deprecationReason" : null 1682 | }, { 1683 | "name" : "LIST", 1684 | "description" : "Indicates this type is a list. `ofType` is a valid field.", 1685 | "isDeprecated" : false, 1686 | "deprecationReason" : null 1687 | }, { 1688 | "name" : "NON_NULL", 1689 | "description" : "Indicates this type is a non-null. `ofType` is a valid field.", 1690 | "isDeprecated" : false, 1691 | "deprecationReason" : null 1692 | } ], 1693 | "possibleTypes" : null 1694 | }, { 1695 | "kind" : "OBJECT", 1696 | "name" : "__Field", 1697 | "description" : null, 1698 | "fields" : [ { 1699 | "name" : "name", 1700 | "description" : null, 1701 | "args" : [ ], 1702 | "type" : { 1703 | "kind" : "NON_NULL", 1704 | "name" : null, 1705 | "ofType" : { 1706 | "kind" : "SCALAR", 1707 | "name" : "String", 1708 | "ofType" : null 1709 | } 1710 | }, 1711 | "isDeprecated" : false, 1712 | "deprecationReason" : null 1713 | }, { 1714 | "name" : "description", 1715 | "description" : null, 1716 | "args" : [ ], 1717 | "type" : { 1718 | "kind" : "SCALAR", 1719 | "name" : "String", 1720 | "ofType" : null 1721 | }, 1722 | "isDeprecated" : false, 1723 | "deprecationReason" : null 1724 | }, { 1725 | "name" : "args", 1726 | "description" : null, 1727 | "args" : [ ], 1728 | "type" : { 1729 | "kind" : "NON_NULL", 1730 | "name" : null, 1731 | "ofType" : { 1732 | "kind" : "LIST", 1733 | "name" : null, 1734 | "ofType" : { 1735 | "kind" : "NON_NULL", 1736 | "name" : null, 1737 | "ofType" : { 1738 | "kind" : "OBJECT", 1739 | "name" : "__InputValue", 1740 | "ofType" : null 1741 | } 1742 | } 1743 | } 1744 | }, 1745 | "isDeprecated" : false, 1746 | "deprecationReason" : null 1747 | }, { 1748 | "name" : "type", 1749 | "description" : null, 1750 | "args" : [ ], 1751 | "type" : { 1752 | "kind" : "NON_NULL", 1753 | "name" : null, 1754 | "ofType" : { 1755 | "kind" : "OBJECT", 1756 | "name" : "__Type", 1757 | "ofType" : null 1758 | } 1759 | }, 1760 | "isDeprecated" : false, 1761 | "deprecationReason" : null 1762 | }, { 1763 | "name" : "isDeprecated", 1764 | "description" : null, 1765 | "args" : [ ], 1766 | "type" : { 1767 | "kind" : "NON_NULL", 1768 | "name" : null, 1769 | "ofType" : { 1770 | "kind" : "SCALAR", 1771 | "name" : "Boolean", 1772 | "ofType" : null 1773 | } 1774 | }, 1775 | "isDeprecated" : false, 1776 | "deprecationReason" : null 1777 | }, { 1778 | "name" : "deprecationReason", 1779 | "description" : null, 1780 | "args" : [ ], 1781 | "type" : { 1782 | "kind" : "SCALAR", 1783 | "name" : "String", 1784 | "ofType" : null 1785 | }, 1786 | "isDeprecated" : false, 1787 | "deprecationReason" : null 1788 | } ], 1789 | "inputFields" : null, 1790 | "interfaces" : [ ], 1791 | "enumValues" : null, 1792 | "possibleTypes" : null 1793 | }, { 1794 | "kind" : "OBJECT", 1795 | "name" : "__InputValue", 1796 | "description" : null, 1797 | "fields" : [ { 1798 | "name" : "name", 1799 | "description" : null, 1800 | "args" : [ ], 1801 | "type" : { 1802 | "kind" : "NON_NULL", 1803 | "name" : null, 1804 | "ofType" : { 1805 | "kind" : "SCALAR", 1806 | "name" : "String", 1807 | "ofType" : null 1808 | } 1809 | }, 1810 | "isDeprecated" : false, 1811 | "deprecationReason" : null 1812 | }, { 1813 | "name" : "description", 1814 | "description" : null, 1815 | "args" : [ ], 1816 | "type" : { 1817 | "kind" : "SCALAR", 1818 | "name" : "String", 1819 | "ofType" : null 1820 | }, 1821 | "isDeprecated" : false, 1822 | "deprecationReason" : null 1823 | }, { 1824 | "name" : "type", 1825 | "description" : null, 1826 | "args" : [ ], 1827 | "type" : { 1828 | "kind" : "NON_NULL", 1829 | "name" : null, 1830 | "ofType" : { 1831 | "kind" : "OBJECT", 1832 | "name" : "__Type", 1833 | "ofType" : null 1834 | } 1835 | }, 1836 | "isDeprecated" : false, 1837 | "deprecationReason" : null 1838 | }, { 1839 | "name" : "defaultValue", 1840 | "description" : null, 1841 | "args" : [ ], 1842 | "type" : { 1843 | "kind" : "SCALAR", 1844 | "name" : "String", 1845 | "ofType" : null 1846 | }, 1847 | "isDeprecated" : false, 1848 | "deprecationReason" : null 1849 | } ], 1850 | "inputFields" : null, 1851 | "interfaces" : [ ], 1852 | "enumValues" : null, 1853 | "possibleTypes" : null 1854 | }, { 1855 | "kind" : "OBJECT", 1856 | "name" : "__EnumValue", 1857 | "description" : null, 1858 | "fields" : [ { 1859 | "name" : "name", 1860 | "description" : null, 1861 | "args" : [ ], 1862 | "type" : { 1863 | "kind" : "NON_NULL", 1864 | "name" : null, 1865 | "ofType" : { 1866 | "kind" : "SCALAR", 1867 | "name" : "String", 1868 | "ofType" : null 1869 | } 1870 | }, 1871 | "isDeprecated" : false, 1872 | "deprecationReason" : null 1873 | }, { 1874 | "name" : "description", 1875 | "description" : null, 1876 | "args" : [ ], 1877 | "type" : { 1878 | "kind" : "SCALAR", 1879 | "name" : "String", 1880 | "ofType" : null 1881 | }, 1882 | "isDeprecated" : false, 1883 | "deprecationReason" : null 1884 | }, { 1885 | "name" : "isDeprecated", 1886 | "description" : null, 1887 | "args" : [ ], 1888 | "type" : { 1889 | "kind" : "NON_NULL", 1890 | "name" : null, 1891 | "ofType" : { 1892 | "kind" : "SCALAR", 1893 | "name" : "Boolean", 1894 | "ofType" : null 1895 | } 1896 | }, 1897 | "isDeprecated" : false, 1898 | "deprecationReason" : null 1899 | }, { 1900 | "name" : "deprecationReason", 1901 | "description" : null, 1902 | "args" : [ ], 1903 | "type" : { 1904 | "kind" : "SCALAR", 1905 | "name" : "String", 1906 | "ofType" : null 1907 | }, 1908 | "isDeprecated" : false, 1909 | "deprecationReason" : null 1910 | } ], 1911 | "inputFields" : null, 1912 | "interfaces" : [ ], 1913 | "enumValues" : null, 1914 | "possibleTypes" : null 1915 | }, { 1916 | "kind" : "OBJECT", 1917 | "name" : "__Directive", 1918 | "description" : null, 1919 | "fields" : [ { 1920 | "name" : "name", 1921 | "description" : null, 1922 | "args" : [ ], 1923 | "type" : { 1924 | "kind" : "SCALAR", 1925 | "name" : "String", 1926 | "ofType" : null 1927 | }, 1928 | "isDeprecated" : false, 1929 | "deprecationReason" : null 1930 | }, { 1931 | "name" : "description", 1932 | "description" : null, 1933 | "args" : [ ], 1934 | "type" : { 1935 | "kind" : "SCALAR", 1936 | "name" : "String", 1937 | "ofType" : null 1938 | }, 1939 | "isDeprecated" : false, 1940 | "deprecationReason" : null 1941 | }, { 1942 | "name" : "locations", 1943 | "description" : null, 1944 | "args" : [ ], 1945 | "type" : { 1946 | "kind" : "LIST", 1947 | "name" : null, 1948 | "ofType" : { 1949 | "kind" : "NON_NULL", 1950 | "name" : null, 1951 | "ofType" : { 1952 | "kind" : "ENUM", 1953 | "name" : "__DirectiveLocation", 1954 | "ofType" : null 1955 | } 1956 | } 1957 | }, 1958 | "isDeprecated" : false, 1959 | "deprecationReason" : null 1960 | }, { 1961 | "name" : "args", 1962 | "description" : null, 1963 | "args" : [ ], 1964 | "type" : { 1965 | "kind" : "NON_NULL", 1966 | "name" : null, 1967 | "ofType" : { 1968 | "kind" : "LIST", 1969 | "name" : null, 1970 | "ofType" : { 1971 | "kind" : "NON_NULL", 1972 | "name" : null, 1973 | "ofType" : { 1974 | "kind" : "OBJECT", 1975 | "name" : "__InputValue", 1976 | "ofType" : null 1977 | } 1978 | } 1979 | } 1980 | }, 1981 | "isDeprecated" : false, 1982 | "deprecationReason" : null 1983 | }, { 1984 | "name" : "onOperation", 1985 | "description" : null, 1986 | "args" : [ ], 1987 | "type" : { 1988 | "kind" : "SCALAR", 1989 | "name" : "Boolean", 1990 | "ofType" : null 1991 | }, 1992 | "isDeprecated" : true, 1993 | "deprecationReason" : "Use `locations`." 1994 | }, { 1995 | "name" : "onFragment", 1996 | "description" : null, 1997 | "args" : [ ], 1998 | "type" : { 1999 | "kind" : "SCALAR", 2000 | "name" : "Boolean", 2001 | "ofType" : null 2002 | }, 2003 | "isDeprecated" : true, 2004 | "deprecationReason" : "Use `locations`." 2005 | }, { 2006 | "name" : "onField", 2007 | "description" : null, 2008 | "args" : [ ], 2009 | "type" : { 2010 | "kind" : "SCALAR", 2011 | "name" : "Boolean", 2012 | "ofType" : null 2013 | }, 2014 | "isDeprecated" : true, 2015 | "deprecationReason" : "Use `locations`." 2016 | } ], 2017 | "inputFields" : null, 2018 | "interfaces" : [ ], 2019 | "enumValues" : null, 2020 | "possibleTypes" : null 2021 | }, { 2022 | "kind" : "ENUM", 2023 | "name" : "__DirectiveLocation", 2024 | "description" : "An enum describing valid locations where a directive can be placed", 2025 | "fields" : null, 2026 | "inputFields" : null, 2027 | "interfaces" : null, 2028 | "enumValues" : [ { 2029 | "name" : "QUERY", 2030 | "description" : "Indicates the directive is valid on queries.", 2031 | "isDeprecated" : false, 2032 | "deprecationReason" : null 2033 | }, { 2034 | "name" : "MUTATION", 2035 | "description" : "Indicates the directive is valid on mutations.", 2036 | "isDeprecated" : false, 2037 | "deprecationReason" : null 2038 | }, { 2039 | "name" : "FIELD", 2040 | "description" : "Indicates the directive is valid on fields.", 2041 | "isDeprecated" : false, 2042 | "deprecationReason" : null 2043 | }, { 2044 | "name" : "FRAGMENT_DEFINITION", 2045 | "description" : "Indicates the directive is valid on fragment definitions.", 2046 | "isDeprecated" : false, 2047 | "deprecationReason" : null 2048 | }, { 2049 | "name" : "FRAGMENT_SPREAD", 2050 | "description" : "Indicates the directive is valid on fragment spreads.", 2051 | "isDeprecated" : false, 2052 | "deprecationReason" : null 2053 | }, { 2054 | "name" : "INLINE_FRAGMENT", 2055 | "description" : "Indicates the directive is valid on inline fragments.", 2056 | "isDeprecated" : false, 2057 | "deprecationReason" : null 2058 | }, { 2059 | "name" : "SCHEMA", 2060 | "description" : "Indicates the directive is valid on a schema SDL definition.", 2061 | "isDeprecated" : false, 2062 | "deprecationReason" : null 2063 | }, { 2064 | "name" : "SCALAR", 2065 | "description" : "Indicates the directive is valid on a scalar SDL definition.", 2066 | "isDeprecated" : false, 2067 | "deprecationReason" : null 2068 | }, { 2069 | "name" : "OBJECT", 2070 | "description" : "Indicates the directive is valid on an object SDL definition.", 2071 | "isDeprecated" : false, 2072 | "deprecationReason" : null 2073 | }, { 2074 | "name" : "FIELD_DEFINITION", 2075 | "description" : "Indicates the directive is valid on a field SDL definition.", 2076 | "isDeprecated" : false, 2077 | "deprecationReason" : null 2078 | }, { 2079 | "name" : "ARGUMENT_DEFINITION", 2080 | "description" : "Indicates the directive is valid on a field argument SDL definition.", 2081 | "isDeprecated" : false, 2082 | "deprecationReason" : null 2083 | }, { 2084 | "name" : "INTERFACE", 2085 | "description" : "Indicates the directive is valid on an interface SDL definition.", 2086 | "isDeprecated" : false, 2087 | "deprecationReason" : null 2088 | }, { 2089 | "name" : "UNION", 2090 | "description" : "Indicates the directive is valid on an union SDL definition.", 2091 | "isDeprecated" : false, 2092 | "deprecationReason" : null 2093 | }, { 2094 | "name" : "ENUM", 2095 | "description" : "Indicates the directive is valid on an enum SDL definition.", 2096 | "isDeprecated" : false, 2097 | "deprecationReason" : null 2098 | }, { 2099 | "name" : "ENUM_VALUE", 2100 | "description" : "Indicates the directive is valid on an enum value SDL definition.", 2101 | "isDeprecated" : false, 2102 | "deprecationReason" : null 2103 | }, { 2104 | "name" : "INPUT_OBJECT", 2105 | "description" : "Indicates the directive is valid on an input object SDL definition.", 2106 | "isDeprecated" : false, 2107 | "deprecationReason" : null 2108 | }, { 2109 | "name" : "INPUT_FIELD_DEFINITION", 2110 | "description" : "Indicates the directive is valid on an input object field SDL definition.", 2111 | "isDeprecated" : false, 2112 | "deprecationReason" : null 2113 | } ], 2114 | "possibleTypes" : null 2115 | } ], 2116 | "directives" : [ { 2117 | "name" : "include", 2118 | "description" : "Directs the executor to include this field or fragment only when the `if` argument is true", 2119 | "locations" : [ "FIELD", "FRAGMENT_SPREAD", "INLINE_FRAGMENT" ], 2120 | "args" : [ { 2121 | "name" : "if", 2122 | "description" : "Included when true.", 2123 | "type" : { 2124 | "kind" : "NON_NULL", 2125 | "name" : null, 2126 | "ofType" : { 2127 | "kind" : "SCALAR", 2128 | "name" : "Boolean", 2129 | "ofType" : null 2130 | } 2131 | }, 2132 | "defaultValue" : null 2133 | } ], 2134 | "onOperation" : false, 2135 | "onFragment" : true, 2136 | "onField" : true 2137 | }, { 2138 | "name" : "skip", 2139 | "description" : "Directs the executor to skip this field or fragment when the `if`'argument is true.", 2140 | "locations" : [ "FIELD", "FRAGMENT_SPREAD", "INLINE_FRAGMENT" ], 2141 | "args" : [ { 2142 | "name" : "if", 2143 | "description" : "Skipped when true.", 2144 | "type" : { 2145 | "kind" : "NON_NULL", 2146 | "name" : null, 2147 | "ofType" : { 2148 | "kind" : "SCALAR", 2149 | "name" : "Boolean", 2150 | "ofType" : null 2151 | } 2152 | }, 2153 | "defaultValue" : null 2154 | } ], 2155 | "onOperation" : false, 2156 | "onFragment" : true, 2157 | "onField" : true 2158 | }, { 2159 | "name" : "defer", 2160 | "description" : "This directive allows results to be deferred during execution", 2161 | "locations" : [ "FIELD" ], 2162 | "args" : [ ], 2163 | "onOperation" : false, 2164 | "onFragment" : false, 2165 | "onField" : true 2166 | }, { 2167 | "name" : "aws_iam", 2168 | "description" : "Tells the service this field/object has access authorized by sigv4 signing.", 2169 | "locations" : [ "OBJECT", "FIELD_DEFINITION" ], 2170 | "args" : [ ], 2171 | "onOperation" : false, 2172 | "onFragment" : false, 2173 | "onField" : false 2174 | }, { 2175 | "name" : "aws_publish", 2176 | "description" : "Tells the service which subscriptions will be published to when this mutation is called. This directive is deprecated use @aws_susbscribe directive instead.", 2177 | "locations" : [ "FIELD_DEFINITION" ], 2178 | "args" : [ { 2179 | "name" : "subscriptions", 2180 | "description" : "List of subscriptions which will be published to when this mutation is called.", 2181 | "type" : { 2182 | "kind" : "LIST", 2183 | "name" : null, 2184 | "ofType" : { 2185 | "kind" : "SCALAR", 2186 | "name" : "String", 2187 | "ofType" : null 2188 | } 2189 | }, 2190 | "defaultValue" : null 2191 | } ], 2192 | "onOperation" : false, 2193 | "onFragment" : false, 2194 | "onField" : false 2195 | }, { 2196 | "name" : "aws_subscribe", 2197 | "description" : "Tells the service which mutation triggers this subscription.", 2198 | "locations" : [ "FIELD_DEFINITION" ], 2199 | "args" : [ { 2200 | "name" : "mutations", 2201 | "description" : "List of mutations which will trigger this subscription when they are called.", 2202 | "type" : { 2203 | "kind" : "LIST", 2204 | "name" : null, 2205 | "ofType" : { 2206 | "kind" : "SCALAR", 2207 | "name" : "String", 2208 | "ofType" : null 2209 | } 2210 | }, 2211 | "defaultValue" : null 2212 | } ], 2213 | "onOperation" : false, 2214 | "onFragment" : false, 2215 | "onField" : false 2216 | }, { 2217 | "name" : "aws_auth", 2218 | "description" : "Directs the schema to enforce authorization on a field", 2219 | "locations" : [ "FIELD_DEFINITION" ], 2220 | "args" : [ { 2221 | "name" : "cognito_groups", 2222 | "description" : "List of cognito user pool groups which have access on this field", 2223 | "type" : { 2224 | "kind" : "LIST", 2225 | "name" : null, 2226 | "ofType" : { 2227 | "kind" : "SCALAR", 2228 | "name" : "String", 2229 | "ofType" : null 2230 | } 2231 | }, 2232 | "defaultValue" : null 2233 | } ], 2234 | "onOperation" : false, 2235 | "onFragment" : false, 2236 | "onField" : false 2237 | }, { 2238 | "name" : "deprecated", 2239 | "description" : null, 2240 | "locations" : [ "FIELD_DEFINITION", "ENUM_VALUE" ], 2241 | "args" : [ { 2242 | "name" : "reason", 2243 | "description" : null, 2244 | "type" : { 2245 | "kind" : "SCALAR", 2246 | "name" : "String", 2247 | "ofType" : null 2248 | }, 2249 | "defaultValue" : "\"No longer supported\"" 2250 | } ], 2251 | "onOperation" : false, 2252 | "onFragment" : false, 2253 | "onField" : false 2254 | }, { 2255 | "name" : "aws_api_key", 2256 | "description" : "Tells the service this field/object has access authorized by an API key.", 2257 | "locations" : [ "OBJECT", "FIELD_DEFINITION" ], 2258 | "args" : [ ], 2259 | "onOperation" : false, 2260 | "onFragment" : false, 2261 | "onField" : false 2262 | }, { 2263 | "name" : "aws_cognito_user_pools", 2264 | "description" : "Tells the service this field/object has access authorized by a Cognito User Pools token.", 2265 | "locations" : [ "OBJECT", "FIELD_DEFINITION" ], 2266 | "args" : [ { 2267 | "name" : "cognito_groups", 2268 | "description" : "List of cognito user pool groups which have access on this field", 2269 | "type" : { 2270 | "kind" : "LIST", 2271 | "name" : null, 2272 | "ofType" : { 2273 | "kind" : "SCALAR", 2274 | "name" : "String", 2275 | "ofType" : null 2276 | } 2277 | }, 2278 | "defaultValue" : null 2279 | } ], 2280 | "onOperation" : false, 2281 | "onFragment" : false, 2282 | "onField" : false 2283 | }, { 2284 | "name" : "aws_oidc", 2285 | "description" : "Tells the service this field/object has access authorized by an OIDC token.", 2286 | "locations" : [ "OBJECT", "FIELD_DEFINITION" ], 2287 | "args" : [ ], 2288 | "onOperation" : false, 2289 | "onFragment" : false, 2290 | "onField" : false 2291 | } ] 2292 | } 2293 | } 2294 | } -------------------------------------------------------------------------------- /src/graphql/subscriptions.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | // this is an auto generated file. This will be overwritten 3 | 4 | export const onCreateDevice = /* GraphQL */ ` 5 | subscription OnCreateDevice { 6 | onCreateDevice { 7 | thingName 8 | username 9 | description 10 | createdAt 11 | updatedAt 12 | } 13 | } 14 | `; 15 | export const onUpdateDevice = /* GraphQL */ ` 16 | subscription OnUpdateDevice { 17 | onUpdateDevice { 18 | thingName 19 | username 20 | description 21 | createdAt 22 | updatedAt 23 | } 24 | } 25 | `; 26 | export const onDeleteDevice = /* GraphQL */ ` 27 | subscription OnDeleteDevice { 28 | onDeleteDevice { 29 | thingName 30 | username 31 | description 32 | createdAt 33 | updatedAt 34 | } 35 | } 36 | `; 37 | -------------------------------------------------------------------------------- /src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", 4 | "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", 12 | monospace; 13 | } 14 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import './index.css'; 4 | import App from './App'; 5 | import * as serviceWorker from './serviceWorker'; 6 | 7 | ReactDOM.render(, document.getElementById('root')); 8 | 9 | // If you want your app to work offline and load faster, you can change 10 | // unregister() to register() below. Note this comes with some pitfalls. 11 | // Learn more about service workers: https://bit.ly/CRA-PWA 12 | serviceWorker.unregister(); 13 | -------------------------------------------------------------------------------- /src/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/serviceWorker.js: -------------------------------------------------------------------------------- 1 | // This optional code is used to register a service worker. 2 | // register() is not called by default. 3 | 4 | // This lets the app load faster on subsequent visits in production, and gives 5 | // it offline capabilities. However, it also means that developers (and users) 6 | // will only see deployed updates on subsequent visits to a page, after all the 7 | // existing tabs open on the page have been closed, since previously cached 8 | // resources are updated in the background. 9 | 10 | // To learn more about the benefits of this model and instructions on how to 11 | // opt-in, read https://bit.ly/CRA-PWA 12 | 13 | const isLocalhost = Boolean( 14 | window.location.hostname === 'localhost' || 15 | // [::1] is the IPv6 localhost address. 16 | window.location.hostname === '[::1]' || 17 | // 127.0.0.1/8 is considered localhost for IPv4. 18 | window.location.hostname.match( 19 | /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/ 20 | ) 21 | ); 22 | 23 | export function register(config) { 24 | if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) { 25 | // The URL constructor is available in all browsers that support SW. 26 | const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href); 27 | if (publicUrl.origin !== window.location.origin) { 28 | // Our service worker won't work if PUBLIC_URL is on a different origin 29 | // from what our page is served on. This might happen if a CDN is used to 30 | // serve assets; see https://github.com/facebook/create-react-app/issues/2374 31 | return; 32 | } 33 | 34 | window.addEventListener('load', () => { 35 | const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`; 36 | 37 | if (isLocalhost) { 38 | // This is running on localhost. Let's check if a service worker still exists or not. 39 | checkValidServiceWorker(swUrl, config); 40 | 41 | // Add some additional logging to localhost, pointing developers to the 42 | // service worker/PWA documentation. 43 | navigator.serviceWorker.ready.then(() => { 44 | console.log( 45 | 'This web app is being served cache-first by a service ' + 46 | 'worker. To learn more, visit https://bit.ly/CRA-PWA' 47 | ); 48 | }); 49 | } else { 50 | // Is not localhost. Just register service worker 51 | registerValidSW(swUrl, config); 52 | } 53 | }); 54 | } 55 | } 56 | 57 | function registerValidSW(swUrl, config) { 58 | navigator.serviceWorker 59 | .register(swUrl) 60 | .then(registration => { 61 | registration.onupdatefound = () => { 62 | const installingWorker = registration.installing; 63 | if (installingWorker == null) { 64 | return; 65 | } 66 | installingWorker.onstatechange = () => { 67 | if (installingWorker.state === 'installed') { 68 | if (navigator.serviceWorker.controller) { 69 | // At this point, the updated precached content has been fetched, 70 | // but the previous service worker will still serve the older 71 | // content until all client tabs are closed. 72 | console.log( 73 | 'New content is available and will be used when all ' + 74 | 'tabs for this page are closed. See https://bit.ly/CRA-PWA.' 75 | ); 76 | 77 | // Execute callback 78 | if (config && config.onUpdate) { 79 | config.onUpdate(registration); 80 | } 81 | } else { 82 | // At this point, everything has been precached. 83 | // It's the perfect time to display a 84 | // "Content is cached for offline use." message. 85 | console.log('Content is cached for offline use.'); 86 | 87 | // Execute callback 88 | if (config && config.onSuccess) { 89 | config.onSuccess(registration); 90 | } 91 | } 92 | } 93 | }; 94 | }; 95 | }) 96 | .catch(error => { 97 | console.error('Error during service worker registration:', error); 98 | }); 99 | } 100 | 101 | function checkValidServiceWorker(swUrl, config) { 102 | // Check if the service worker can be found. If it can't reload the page. 103 | fetch(swUrl) 104 | .then(response => { 105 | // Ensure service worker exists, and that we really are getting a JS file. 106 | const contentType = response.headers.get('content-type'); 107 | if ( 108 | response.status === 404 || 109 | (contentType != null && contentType.indexOf('javascript') === -1) 110 | ) { 111 | // No service worker found. Probably a different app. Reload the page. 112 | navigator.serviceWorker.ready.then(registration => { 113 | registration.unregister().then(() => { 114 | window.location.reload(); 115 | }); 116 | }); 117 | } else { 118 | // Service worker found. Proceed as normal. 119 | registerValidSW(swUrl, config); 120 | } 121 | }) 122 | .catch(() => { 123 | console.log( 124 | 'No internet connection found. App is running in offline mode.' 125 | ); 126 | }); 127 | } 128 | 129 | export function unregister() { 130 | if ('serviceWorker' in navigator) { 131 | navigator.serviceWorker.ready.then(registration => { 132 | registration.unregister(); 133 | }); 134 | } 135 | } 136 | --------------------------------------------------------------------------------