├── .env ├── .gitignore ├── .graphqlconfig.yml ├── README.md ├── amplify.json ├── amplify ├── .config │ └── project-config.json └── backend │ ├── api │ └── AmplifyChat │ │ ├── parameters.json │ │ ├── schema.graphql │ │ ├── stacks │ │ └── CustomResources.json │ │ └── transform.conf.json │ ├── auth │ └── chatclienta73d146f │ │ ├── chatclienta73d146f-cloudformation-template.yml │ │ └── parameters.json │ └── backend-config.json ├── header.jpg ├── package.json ├── public ├── favicon.ico ├── index.html ├── logo192.png ├── logo512.png ├── manifest.json └── robots.txt ├── src ├── App.css ├── App.js ├── App.test.js ├── Chat.js ├── Profile.js ├── Rooms.js ├── aws-exports-example.js ├── graphql │ ├── mutations.js │ ├── queries.js │ ├── schema.json │ └── subscriptions.js ├── index.css ├── index.js ├── logo.svg ├── serviceWorker.js ├── setupTests.js └── theme.js └── yarn.lock /.env: -------------------------------------------------------------------------------- 1 | SKIP_PREFLIGHT_CHECK=true -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | src/aws-exports.js 4 | 5 | # dependencies 6 | /node_modules 7 | /.pnp 8 | .pnp.js 9 | 10 | # testing 11 | /coverage 12 | 13 | # production 14 | /build 15 | 16 | # misc 17 | .DS_Store 18 | .env.local 19 | .env.development.local 20 | .env.test.local 21 | .env.production.local 22 | 23 | npm-debug.log* 24 | yarn-debug.log* 25 | yarn-error.log* 26 | 27 | amplify/team-provider-info.json 28 | 29 | #amplify 30 | amplify/\#current-cloud-backend 31 | amplify/.config/local-* 32 | amplify/mock-data 33 | amplify/backend/amplify-meta.json 34 | amplify/backend/awscloudformation 35 | build/ 36 | dist/ 37 | node_modules/ 38 | aws-exports.js 39 | awsconfiguration.json 40 | amplifyconfiguration.json 41 | amplify-build-config.json 42 | amplify-gradle-config.json 43 | amplifytools.xcconfig -------------------------------------------------------------------------------- /.graphqlconfig.yml: -------------------------------------------------------------------------------- 1 | projects: 2 | AmplifyChat: 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![Chat App with React & AWS](header.jpg) 2 | 3 | ## Real Time Chat with React, GraphQL, and AWS AppSync 4 | 5 | This application can be deployed with either AWS Amplify or CDK. 6 | 7 | ### Deploying with AWS Amplify 8 | 9 | 1. Clone the repo and change into the directory: 10 | 11 | ```sh 12 | git clone https://github.com/full-stack-serverless/react-chat-app-aws.git 13 | 14 | cd react-chat-app-aws 15 | ``` 16 | 17 | 2. Install the dependencies: 18 | 19 | ```sh 20 | npm install 21 | 22 | # or 23 | 24 | yarn 25 | ``` 26 | 27 | 3. Deploy the back end 28 | 29 | ```sh 30 | amplify init 31 | 32 | # walk through steps 33 | 34 | amplify push 35 | ``` 36 | 37 | 4. Start the app 38 | 39 | ```sh 40 | npm start 41 | ``` 42 | 43 | ### Deploying with CDK 44 | 45 | To deploy with CDK, follow the steps [here](https://github.com/full-stack-serverless/cdk-appsync-chat) -------------------------------------------------------------------------------- /amplify.json: -------------------------------------------------------------------------------- 1 | { 2 | "features": 3 | { 4 | "graphqltransformer": 5 | { 6 | "transformerversion": 5 7 | }, 8 | "keytransformer": 9 | { 10 | "defaultquery": true 11 | } 12 | } 13 | } -------------------------------------------------------------------------------- /amplify/.config/project-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "projectName": "chatclient", 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/backend/api/AmplifyChat/parameters.json: -------------------------------------------------------------------------------- 1 | { 2 | "AppSyncApiName": "AmplifyChat", 3 | "DynamoDBBillingMode": "PAY_PER_REQUEST", 4 | "DynamoDBEnableServerSideEncryption": false, 5 | "AuthCognitoUserPoolId": { 6 | "Fn::GetAtt": [ 7 | "authchatclienta73d146f", 8 | "Outputs.UserPoolId" 9 | ] 10 | } 11 | } -------------------------------------------------------------------------------- /amplify/backend/api/AmplifyChat/schema.graphql: -------------------------------------------------------------------------------- 1 | type Room @model { 2 | id: ID! 3 | name: String 4 | messages: [Message] @connection(keyName: "messagesbyRoomId", fields: ["id"]) 5 | createdAt: AWSDateTime 6 | updatedAt: AWSDateTime 7 | } 8 | 9 | type Message @model 10 | @auth(rules: [ 11 | { allow: owner }, 12 | { allow: private, operations: [read] } 13 | ]) 14 | @key(name: "messagesbyRoomId", fields: ["roomId", "createdAt"], queryField: "listMessagesForRoom") { 15 | id: ID! 16 | content: String! 17 | owner: String 18 | createdAt: String 19 | roomId: ID 20 | } 21 | 22 | type Subscription { 23 | onCreateMessageByRoomId(roomId: ID): Message 24 | @aws_subscribe(mutations: ["createMessage"]) 25 | } -------------------------------------------------------------------------------- /amplify/backend/api/AmplifyChat/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": ["true", "false"] 50 | } 51 | }, 52 | "Outputs": { 53 | "EmptyOutput": { 54 | "Description": "An empty output. You may delete this if you have at least one resource above.", 55 | "Value": "" 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /amplify/backend/api/AmplifyChat/transform.conf.json: -------------------------------------------------------------------------------- 1 | { 2 | "Version": 5, 3 | "ElasticsearchWarning": true, 4 | "ResolverConfig": {} 5 | } -------------------------------------------------------------------------------- /amplify/backend/auth/chatclienta73d146f/chatclienta73d146f-cloudformation-template.yml: -------------------------------------------------------------------------------- 1 | AWSTemplateFormatVersion: 2010-09-09 2 | 3 | Parameters: 4 | env: 5 | Type: String 6 | authRoleArn: 7 | Type: String 8 | unauthRoleArn: 9 | Type: String 10 | 11 | 12 | 13 | 14 | identityPoolName: 15 | Type: String 16 | 17 | allowUnauthenticatedIdentities: 18 | Type: String 19 | 20 | resourceNameTruncated: 21 | Type: String 22 | 23 | userPoolName: 24 | Type: String 25 | 26 | autoVerifiedAttributes: 27 | Type: CommaDelimitedList 28 | 29 | mfaConfiguration: 30 | Type: String 31 | 32 | mfaTypes: 33 | Type: CommaDelimitedList 34 | 35 | smsAuthenticationMessage: 36 | Type: String 37 | 38 | smsVerificationMessage: 39 | Type: String 40 | 41 | emailVerificationSubject: 42 | Type: String 43 | 44 | emailVerificationMessage: 45 | Type: String 46 | 47 | defaultPasswordPolicy: 48 | Type: String 49 | 50 | passwordPolicyMinLength: 51 | Type: Number 52 | 53 | passwordPolicyCharacters: 54 | Type: CommaDelimitedList 55 | 56 | requiredAttributes: 57 | Type: CommaDelimitedList 58 | 59 | userpoolClientGenerateSecret: 60 | Type: String 61 | 62 | userpoolClientRefreshTokenValidity: 63 | Type: Number 64 | 65 | userpoolClientWriteAttributes: 66 | Type: CommaDelimitedList 67 | 68 | userpoolClientReadAttributes: 69 | Type: CommaDelimitedList 70 | 71 | userpoolClientLambdaRole: 72 | Type: String 73 | 74 | userpoolClientSetAttributes: 75 | Type: String 76 | 77 | sharedId: 78 | Type: String 79 | 80 | resourceName: 81 | Type: String 82 | 83 | authSelections: 84 | Type: String 85 | 86 | useDefault: 87 | Type: String 88 | 89 | userPoolGroupList: 90 | Type: CommaDelimitedList 91 | 92 | dependsOn: 93 | Type: CommaDelimitedList 94 | 95 | Conditions: 96 | ShouldNotCreateEnvResources: !Equals [ !Ref env, NONE ] 97 | 98 | Resources: 99 | 100 | 101 | # BEGIN SNS ROLE RESOURCE 102 | SNSRole: 103 | # Created to allow the UserPool SMS Config to publish via the Simple Notification Service during MFA Process 104 | Type: AWS::IAM::Role 105 | Properties: 106 | RoleName: !If [ShouldNotCreateEnvResources, 'chatcla73d146f_sns-role', !Join ['',[ 'sns', 'a73d146f', !Select [3, !Split ['-', !Ref 'AWS::StackName']], '-', !Ref env]]] 107 | AssumeRolePolicyDocument: 108 | Version: "2012-10-17" 109 | Statement: 110 | - Sid: "" 111 | Effect: "Allow" 112 | Principal: 113 | Service: "cognito-idp.amazonaws.com" 114 | Action: 115 | - "sts:AssumeRole" 116 | Condition: 117 | StringEquals: 118 | sts:ExternalId: chatcla73d146f_role_external_id 119 | Policies: 120 | - 121 | PolicyName: chatcla73d146f-sns-policy 122 | PolicyDocument: 123 | Version: "2012-10-17" 124 | Statement: 125 | - 126 | Effect: "Allow" 127 | Action: 128 | - "sns:Publish" 129 | Resource: "*" 130 | # BEGIN USER POOL RESOURCES 131 | UserPool: 132 | # Created upon user selection 133 | # Depends on SNS Role for Arn if MFA is enabled 134 | Type: AWS::Cognito::UserPool 135 | UpdateReplacePolicy: Retain 136 | Properties: 137 | UserPoolName: !If [ShouldNotCreateEnvResources, !Ref userPoolName, !Join ['',[!Ref userPoolName, '-', !Ref env]]] 138 | 139 | Schema: 140 | 141 | - 142 | Name: email 143 | Required: true 144 | Mutable: true 145 | 146 | 147 | 148 | 149 | AutoVerifiedAttributes: !Ref autoVerifiedAttributes 150 | 151 | 152 | EmailVerificationMessage: !Ref emailVerificationMessage 153 | EmailVerificationSubject: !Ref emailVerificationSubject 154 | 155 | Policies: 156 | PasswordPolicy: 157 | MinimumLength: !Ref passwordPolicyMinLength 158 | RequireLowercase: false 159 | RequireNumbers: false 160 | RequireSymbols: false 161 | RequireUppercase: false 162 | 163 | MfaConfiguration: !Ref mfaConfiguration 164 | SmsVerificationMessage: !Ref smsVerificationMessage 165 | SmsConfiguration: 166 | SnsCallerArn: !GetAtt SNSRole.Arn 167 | ExternalId: chatcla73d146f_role_external_id 168 | 169 | 170 | UserPoolClientWeb: 171 | # Created provide application access to user pool 172 | # Depends on UserPool for ID reference 173 | Type: "AWS::Cognito::UserPoolClient" 174 | Properties: 175 | ClientName: chatcla73d146f_app_clientWeb 176 | 177 | RefreshTokenValidity: !Ref userpoolClientRefreshTokenValidity 178 | UserPoolId: !Ref UserPool 179 | DependsOn: UserPool 180 | UserPoolClient: 181 | # Created provide application access to user pool 182 | # Depends on UserPool for ID reference 183 | Type: "AWS::Cognito::UserPoolClient" 184 | Properties: 185 | ClientName: chatcla73d146f_app_client 186 | 187 | GenerateSecret: !Ref userpoolClientGenerateSecret 188 | RefreshTokenValidity: !Ref userpoolClientRefreshTokenValidity 189 | UserPoolId: !Ref UserPool 190 | DependsOn: UserPool 191 | # BEGIN USER POOL LAMBDA RESOURCES 192 | UserPoolClientRole: 193 | # Created to execute Lambda which gets userpool app client config values 194 | Type: 'AWS::IAM::Role' 195 | Properties: 196 | RoleName: !If [ShouldNotCreateEnvResources, !Ref userpoolClientLambdaRole, !Join ['',['upClientLambdaRole', 'a73d146f', !Select [3, !Split ['-', !Ref 'AWS::StackName']], '-', !Ref env]]] 197 | AssumeRolePolicyDocument: 198 | Version: '2012-10-17' 199 | Statement: 200 | - Effect: Allow 201 | Principal: 202 | Service: 203 | - lambda.amazonaws.com 204 | Action: 205 | - 'sts:AssumeRole' 206 | DependsOn: UserPoolClient 207 | UserPoolClientLambda: 208 | # Lambda which gets userpool app client config values 209 | # Depends on UserPool for id 210 | # Depends on UserPoolClientRole for role ARN 211 | Type: 'AWS::Lambda::Function' 212 | Properties: 213 | Code: 214 | ZipFile: !Join 215 | - |+ 216 | - - 'const response = require(''cfn-response'');' 217 | - 'const aws = require(''aws-sdk'');' 218 | - 'const identity = new aws.CognitoIdentityServiceProvider();' 219 | - 'exports.handler = (event, context, callback) => {' 220 | - ' if (event.RequestType == ''Delete'') { ' 221 | - ' response.send(event, context, response.SUCCESS, {})' 222 | - ' }' 223 | - ' if (event.RequestType == ''Update'' || event.RequestType == ''Create'') {' 224 | - ' const params = {' 225 | - ' ClientId: event.ResourceProperties.clientId,' 226 | - ' UserPoolId: event.ResourceProperties.userpoolId' 227 | - ' };' 228 | - ' identity.describeUserPoolClient(params).promise()' 229 | - ' .then((res) => {' 230 | - ' response.send(event, context, response.SUCCESS, {''appSecret'': res.UserPoolClient.ClientSecret});' 231 | - ' })' 232 | - ' .catch((err) => {' 233 | - ' response.send(event, context, response.FAILED, {err});' 234 | - ' });' 235 | - ' }' 236 | - '};' 237 | Handler: index.handler 238 | Runtime: nodejs10.x 239 | Timeout: '300' 240 | Role: !GetAtt 241 | - UserPoolClientRole 242 | - Arn 243 | DependsOn: UserPoolClientRole 244 | UserPoolClientLambdaPolicy: 245 | # Sets userpool policy for the role that executes the Userpool Client Lambda 246 | # Depends on UserPool for Arn 247 | # Marked as depending on UserPoolClientRole for easier to understand CFN sequencing 248 | Type: 'AWS::IAM::Policy' 249 | Properties: 250 | PolicyName: chatcla73d146f_userpoolclient_lambda_iam_policy 251 | Roles: 252 | - !Ref UserPoolClientRole 253 | PolicyDocument: 254 | Version: '2012-10-17' 255 | Statement: 256 | - Effect: Allow 257 | Action: 258 | - 'cognito-idp:DescribeUserPoolClient' 259 | Resource: !GetAtt UserPool.Arn 260 | DependsOn: UserPoolClientLambda 261 | UserPoolClientLogPolicy: 262 | # Sets log policy for the role that executes the Userpool Client Lambda 263 | # Depends on UserPool for Arn 264 | # Marked as depending on UserPoolClientLambdaPolicy for easier to understand CFN sequencing 265 | Type: 'AWS::IAM::Policy' 266 | Properties: 267 | PolicyName: chatcla73d146f_userpoolclient_lambda_log_policy 268 | Roles: 269 | - !Ref UserPoolClientRole 270 | PolicyDocument: 271 | Version: 2012-10-17 272 | Statement: 273 | - Effect: Allow 274 | Action: 275 | - 'logs:CreateLogGroup' 276 | - 'logs:CreateLogStream' 277 | - 'logs:PutLogEvents' 278 | Resource: !Sub 279 | - arn:aws:logs:${region}:${account}:log-group:/aws/lambda/${lambda}:log-stream:* 280 | - { region: !Ref "AWS::Region", account: !Ref "AWS::AccountId", lambda: !Ref UserPoolClientLambda} 281 | DependsOn: UserPoolClientLambdaPolicy 282 | UserPoolClientInputs: 283 | # Values passed to Userpool client Lambda 284 | # Depends on UserPool for Id 285 | # Depends on UserPoolClient for Id 286 | # Marked as depending on UserPoolClientLambdaPolicy for easier to understand CFN sequencing 287 | Type: 'Custom::LambdaCallout' 288 | Properties: 289 | ServiceToken: !GetAtt UserPoolClientLambda.Arn 290 | clientId: !Ref UserPoolClient 291 | userpoolId: !Ref UserPool 292 | DependsOn: UserPoolClientLogPolicy 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | # BEGIN IDENTITY POOL RESOURCES 301 | 302 | 303 | IdentityPool: 304 | # Always created 305 | Type: AWS::Cognito::IdentityPool 306 | Properties: 307 | IdentityPoolName: !If [ShouldNotCreateEnvResources, 'chatclienta73d146f_identitypool_a73d146f', !Join ['',['chatclienta73d146f_identitypool_a73d146f', '__', !Ref env]]] 308 | 309 | CognitoIdentityProviders: 310 | - ClientId: !Ref UserPoolClient 311 | ProviderName: !Sub 312 | - cognito-idp.${region}.amazonaws.com/${client} 313 | - { region: !Ref "AWS::Region", client: !Ref UserPool} 314 | - ClientId: !Ref UserPoolClientWeb 315 | ProviderName: !Sub 316 | - cognito-idp.${region}.amazonaws.com/${client} 317 | - { region: !Ref "AWS::Region", client: !Ref UserPool} 318 | 319 | AllowUnauthenticatedIdentities: !Ref allowUnauthenticatedIdentities 320 | 321 | 322 | DependsOn: UserPoolClientInputs 323 | 324 | 325 | IdentityPoolRoleMap: 326 | # Created to map Auth and Unauth roles to the identity pool 327 | # Depends on Identity Pool for ID ref 328 | Type: AWS::Cognito::IdentityPoolRoleAttachment 329 | Properties: 330 | IdentityPoolId: !Ref IdentityPool 331 | Roles: 332 | unauthenticated: !Ref unauthRoleArn 333 | authenticated: !Ref authRoleArn 334 | DependsOn: IdentityPool 335 | 336 | 337 | Outputs : 338 | 339 | IdentityPoolId: 340 | Value: !Ref 'IdentityPool' 341 | Description: Id for the identity pool 342 | IdentityPoolName: 343 | Value: !GetAtt IdentityPool.Name 344 | 345 | 346 | 347 | 348 | UserPoolId: 349 | Value: !Ref 'UserPool' 350 | Description: Id for the user pool 351 | UserPoolName: 352 | Value: !Ref userPoolName 353 | AppClientIDWeb: 354 | Value: !Ref 'UserPoolClientWeb' 355 | Description: The user pool app client id for web 356 | AppClientID: 357 | Value: !Ref 'UserPoolClient' 358 | Description: The user pool app client id 359 | AppClientSecret: 360 | Value: !GetAtt UserPoolClientInputs.appSecret 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | -------------------------------------------------------------------------------- /amplify/backend/auth/chatclienta73d146f/parameters.json: -------------------------------------------------------------------------------- 1 | { 2 | "identityPoolName": "chatclienta73d146f_identitypool_a73d146f", 3 | "allowUnauthenticatedIdentities": false, 4 | "resourceNameTruncated": "chatcla73d146f", 5 | "userPoolName": "chatclienta73d146f_userpool_a73d146f", 6 | "autoVerifiedAttributes": [ 7 | "email" 8 | ], 9 | "mfaConfiguration": "OFF", 10 | "mfaTypes": [ 11 | "SMS Text Message" 12 | ], 13 | "smsAuthenticationMessage": "Your authentication code is {####}", 14 | "smsVerificationMessage": "Your verification code is {####}", 15 | "emailVerificationSubject": "Your verification code", 16 | "emailVerificationMessage": "Your verification code is {####}", 17 | "defaultPasswordPolicy": false, 18 | "passwordPolicyMinLength": 8, 19 | "passwordPolicyCharacters": [], 20 | "requiredAttributes": [ 21 | "email" 22 | ], 23 | "userpoolClientGenerateSecret": true, 24 | "userpoolClientRefreshTokenValidity": 30, 25 | "userpoolClientWriteAttributes": [ 26 | "email" 27 | ], 28 | "userpoolClientReadAttributes": [ 29 | "email" 30 | ], 31 | "userpoolClientLambdaRole": "chatcla73d146f_userpoolclient_lambda_role", 32 | "userpoolClientSetAttributes": false, 33 | "sharedId": "a73d146f", 34 | "resourceName": "chatclienta73d146f", 35 | "authSelections": "identityPoolAndUserPool", 36 | "authRoleArn": { 37 | "Fn::GetAtt": [ 38 | "AuthRole", 39 | "Arn" 40 | ] 41 | }, 42 | "unauthRoleArn": { 43 | "Fn::GetAtt": [ 44 | "UnauthRole", 45 | "Arn" 46 | ] 47 | }, 48 | "useDefault": "default", 49 | "userPoolGroupList": [], 50 | "dependsOn": [] 51 | } -------------------------------------------------------------------------------- /amplify/backend/backend-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "auth": { 3 | "chatclienta73d146f": { 4 | "service": "Cognito", 5 | "providerPlugin": "awscloudformation", 6 | "dependsOn": [], 7 | "customAuth": false 8 | } 9 | }, 10 | "api": { 11 | "AmplifyChat": { 12 | "service": "AppSync", 13 | "providerPlugin": "awscloudformation", 14 | "output": { 15 | "authConfig": { 16 | "defaultAuthentication": { 17 | "authenticationType": "AMAZON_COGNITO_USER_POOLS", 18 | "userPoolConfig": { 19 | "userPoolId": "authchatclienta73d146f" 20 | } 21 | }, 22 | "additionalAuthenticationProviders": [] 23 | } 24 | } 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /header.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/full-stack-serverless/react-chat-app-aws/0a1a57a34ee5dd5b277ff887c55e7b61e139cdbd/header.jpg -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "chat-client", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@aws-amplify/ui-react": "^0.2.13", 7 | "@testing-library/jest-dom": "^4.2.4", 8 | "@testing-library/react": "^9.3.2", 9 | "@testing-library/user-event": "^7.1.2", 10 | "aws-amplify": "^3.0.22", 11 | "react": "^16.13.1", 12 | "react-dom": "^16.13.1", 13 | "react-router-dom": "^5.2.0", 14 | "react-scripts": "3.4.1" 15 | }, 16 | "scripts": { 17 | "start": "react-scripts start", 18 | "build": "react-scripts build", 19 | "test": "react-scripts test", 20 | "eject": "react-scripts eject" 21 | }, 22 | "eslintConfig": { 23 | "extends": "react-app" 24 | }, 25 | "browserslist": { 26 | "production": [ 27 | ">0.2%", 28 | "not dead", 29 | "not op_mini all" 30 | ], 31 | "development": [ 32 | "last 1 chrome version", 33 | "last 1 firefox version", 34 | "last 1 safari version" 35 | ] 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/full-stack-serverless/react-chat-app-aws/0a1a57a34ee5dd5b277ff887c55e7b61e139cdbd/public/favicon.ico -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 14 | 15 | 19 | 20 | 29 | React App 30 | 31 | 32 | 33 |
34 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/full-stack-serverless/react-chat-app-aws/0a1a57a34ee5dd5b277ff887c55e7b61e139cdbd/public/logo192.png -------------------------------------------------------------------------------- /public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/full-stack-serverless/react-chat-app-aws/0a1a57a34ee5dd5b277ff887c55e7b61e139cdbd/public/logo512.png -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /src/App.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { AmplifyAuthenticator, AmplifySignUp } from '@aws-amplify/ui-react'; 3 | import { Auth, Hub } from 'aws-amplify'; 4 | import { HashRouter, Route, Link, Switch } from 'react-router-dom'; 5 | 6 | import Chat from './Chat'; 7 | import Rooms from './Rooms'; 8 | import Profile from './Profile'; 9 | import theme from './theme'; 10 | 11 | const { primaryColor } = theme; 12 | 13 | function Router() { 14 | return ( 15 |
16 | 17 |
18 |
19 | 20 |

CDK AppSync Chat

21 |
22 |
23 | 31 |
32 |
33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 |
45 |
46 |
47 | ) 48 | } 49 | 50 | function App() { 51 | const [user, updateUser] = React.useState(null); 52 | React.useEffect(() => { 53 | Auth.currentAuthenticatedUser() 54 | .then(user => updateUser(user)) 55 | .catch(() => console.log('No signed in user.')); 56 | Hub.listen('auth', data => { 57 | switch (data.payload.event) { 58 | case 'signIn': 59 | return updateUser(data.payload.data); 60 | case 'signOut': 61 | return updateUser(null); 62 | } 63 | }); 64 | }, []); 65 | if (user) { 66 | return 67 | } 68 | return ( 69 | 70 | 77 | 78 | ) 79 | } 80 | 81 | const topLevelContainerStyle = { 82 | height: 170, 83 | position: 'fixed', 84 | top: 0, 85 | left: 0, 86 | width: '100%' 87 | } 88 | 89 | const mainViewContainerStyle = { 90 | padding: '180px 30px 80px', 91 | } 92 | 93 | const headerStyle = { 94 | backgroundColor: primaryColor, 95 | padding: 30, 96 | color: 'white' 97 | } 98 | 99 | const titleStyle = { 100 | fontSize: 34, 101 | margin: 0, 102 | fontWeight: 600 103 | } 104 | 105 | const navStyle = { 106 | padding: '20px 30px', 107 | backgroundColor: '#ddd' 108 | } 109 | 110 | const homeLinkStyle = { 111 | textDecoration: 'none', 112 | color: 'white', 113 | } 114 | 115 | const linkStyle = { 116 | margin: 0, 117 | color: primaryColor, 118 | textDecoration: 'none', 119 | fontSize: 20, 120 | marginRight: 20 121 | } 122 | 123 | export default App -------------------------------------------------------------------------------- /src/App.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { render } from '@testing-library/react'; 3 | import App from './App'; 4 | 5 | test('renders learn react link', () => { 6 | const { getByText } = render(); 7 | const linkElement = getByText(/learn react/i); 8 | expect(linkElement).toBeInTheDocument(); 9 | }); 10 | -------------------------------------------------------------------------------- /src/Chat.js: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect, useReducer, useRef } from 'react'; 2 | import { useParams } from 'react-router-dom'; 3 | import { API, Auth } from 'aws-amplify'; 4 | import theme from './theme'; 5 | 6 | import { listMessagesForRoom as ListMessages } from './graphql/queries'; 7 | import { createMessage as CreateMessage } from './graphql/mutations'; 8 | import { onCreateMessageByRoomId as OnCreateMessage } from './graphql/subscriptions'; 9 | 10 | const { primaryColor } = theme; 11 | 12 | const CREATE_MESSAGE = "CREATE_MESSAGE"; 13 | const SET_MESSAGES = "SET_MESSAGES"; 14 | const SET_LOADING = "SET_LOADING"; 15 | 16 | const initialState = { 17 | messages: [], 18 | loading: true 19 | } 20 | 21 | function reducer(state, action) { 22 | switch(action.type) { 23 | case CREATE_MESSAGE: 24 | return { 25 | ...state, messages: [...state.messages, action.message] 26 | } 27 | case SET_MESSAGES: 28 | return { 29 | ...state, messages: action.messages, loading: false 30 | } 31 | case SET_LOADING: 32 | return { 33 | ...state, loading: action.loading 34 | } 35 | default: 36 | return state; 37 | } 38 | } 39 | 40 | const scrollToRef = (ref) => { 41 | if (!ref.current) return; 42 | window.scrollTo(0, ref.current.offsetTop); 43 | } 44 | 45 | const scrollToRefWithAnimation = ref => { 46 | if (!ref.current) return; 47 | window.scrollTo({ 48 | top: ref.current.offsetTop, 49 | behavior: 'smooth' 50 | }); 51 | } 52 | 53 | export default function Chat() { 54 | const [state, dispatch] = useReducer(reducer, initialState); 55 | const [user, setUser] = useState(null); 56 | const [inputValue, setInputValue] = useState(''); 57 | const params = useParams(); 58 | const scrollRef = useRef(null); 59 | const executeScroll = () => scrollToRef(scrollRef); 60 | const executeScrollWithAnimation = () => scrollToRefWithAnimation(scrollRef); 61 | const { name, id } = params; 62 | let subscription; 63 | let isMounted = true; 64 | useEffect(() => { 65 | listMessages(); 66 | setUserState(); 67 | subscribe(); 68 | return () => { 69 | subscription.unsubscribe(); 70 | isMounted = false; 71 | } 72 | }, []); 73 | function subscribe() { 74 | subscription = API.graphql({ 75 | query: OnCreateMessage, 76 | variables: { 77 | roomId: id 78 | } 79 | }) 80 | .subscribe({ 81 | next: async subscriptionData => { 82 | const { value: { data: { onCreateMessageByRoomId }}} = subscriptionData; 83 | const currentUser = await Auth.currentAuthenticatedUser(); 84 | if (onCreateMessageByRoomId.owner === currentUser.username) return; 85 | dispatch({ type: CREATE_MESSAGE, message: onCreateMessageByRoomId }); 86 | executeScrollWithAnimation(); 87 | } 88 | }) 89 | } 90 | async function setUserState() { 91 | const user = await Auth.currentAuthenticatedUser(); 92 | if (!isMounted) return; 93 | setUser(user); 94 | } 95 | async function listMessages() { 96 | try { 97 | const messageData = await API.graphql({ 98 | query: ListMessages, 99 | variables: { 100 | roomId: id, 101 | sortDirection: 'ASC' 102 | } 103 | }) 104 | dispatch({ type: SET_MESSAGES, messages: messageData.data.listMessagesForRoom.items }); 105 | executeScroll(); 106 | } catch (err) { 107 | console.log('error fetching messages: ', err) 108 | } 109 | } 110 | async function createMessage() { 111 | if (!inputValue) return; 112 | const message = { owner: user.username, content: inputValue, roomId: id }; 113 | dispatch({ type: CREATE_MESSAGE, message }); 114 | setInputValue(''); 115 | setTimeout(() => { 116 | executeScrollWithAnimation(); 117 | }) 118 | try { 119 | await API.graphql({ 120 | query: CreateMessage, 121 | variables: { 122 | input: message 123 | } 124 | }) 125 | console.log('message created!') 126 | } catch (err) { 127 | console.log('error creating message: ', err); 128 | } 129 | } 130 | function onChange (e) { 131 | e.persist(); 132 | setInputValue(e.target.value); 133 | } 134 | return ( 135 |
136 |

Room: {name}

137 | { 138 | state.messages.length === Number(0) && !state.loading && ( 139 |
140 |

No messages yet!

141 |
142 | ) 143 | } 144 |
145 | { 146 | state.messages.map((message, index) => ( 147 |
151 |

{message.content}

152 |

{message.owner}

153 |
154 | )) 155 | } 156 |
157 |
158 |
159 | 165 |
166 |
167 | 168 |
169 |
170 |
171 | ) 172 | } 173 | 174 | const messageContainerStyle = (user, message) => { 175 | const isOwner = user && user.username === message.owner; 176 | return { 177 | backgroundColor: isOwner ? primaryColor : '#ddd', 178 | padding: '15px 18px', 179 | borderRadius: 20, 180 | marginBottom: 10, 181 | boxShadow: `0 1px 1px rgba(0,0,0,0.11), 182 | 0 2px 2px rgba(0,0,0,0.11)` 183 | } 184 | } 185 | 186 | const messageStyle = (user, message) => { 187 | const isOwner = user && user.username === message.owner; 188 | return { 189 | color: isOwner ? 'white' : 'black', 190 | fontSize: 22, 191 | margin: 0 192 | } 193 | } 194 | 195 | const ownerStyle = (user, message) => { 196 | const isOwner = user && user.username === message.owner; 197 | return { 198 | color: isOwner ? '#ddd' : '#666', 199 | fontWeight: 400, 200 | fontSize: 18, 201 | marginTop: 8, 202 | marginBottom: 0 203 | } 204 | } 205 | 206 | const inputWrapperStyle = { 207 | display: 'flex' 208 | } 209 | 210 | const buttonWrapperStyle = { 211 | display: 'flex', 212 | alignItems: 'center' 213 | } 214 | 215 | const buttonStyle = { 216 | height: 40, 217 | outline: 'none', 218 | border: 'none', 219 | padding: '0px 20px', 220 | cursor: 'pointer', 221 | backgroundColor: 'transparent', 222 | border: '1px solid', 223 | fontSize: 18 224 | } 225 | 226 | const inputContainerStyle = { 227 | display: 'flex', 228 | position: 'fixed', 229 | bottom: 0, 230 | height: 80, 231 | backgroundColor: '#ddd', 232 | width: '100%', 233 | left: 0 234 | } 235 | 236 | const inputStyle = { 237 | border: 'none', 238 | outline: 'none', 239 | width: 300, 240 | padding: 9, 241 | backgroundColor: 'transparent', 242 | fontSize: 20, 243 | marginLeft: 30 244 | } 245 | 246 | const noMessageContainer = { 247 | marginTop: 200, 248 | display: 'flex', 249 | justifyContent: 'center', 250 | color: primaryColor 251 | } -------------------------------------------------------------------------------- /src/Profile.js: -------------------------------------------------------------------------------- 1 | import React, { useEffect, useState } from 'react'; 2 | import { Auth } from 'aws-amplify'; 3 | import { AmplifySignOut } from '@aws-amplify/ui-react'; 4 | 5 | export default function Profile() { 6 | const [user, setUser] = useState(null); 7 | let isMounted = true; 8 | useEffect(() => { 9 | checkUser(); 10 | return () => { 11 | isMounted = false; 12 | } 13 | }); 14 | async function checkUser() { 15 | const user = await Auth.currentAuthenticatedUser(); 16 | if (!isMounted) return; 17 | setUser(user); 18 | } 19 | return ( 20 |
21 |

Welcome, { user && user.username }

22 | 23 |
24 | ) 25 | } -------------------------------------------------------------------------------- /src/Rooms.js: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect, useReducer } from 'react' 2 | import { Link, useHistory } from 'react-router-dom'; 3 | import { API } from 'aws-amplify'; 4 | 5 | import theme from './theme' 6 | import { listRooms } from './graphql/queries'; 7 | import { createRoom as CreateRoom } from './graphql/mutations'; 8 | import { onCreateRoom as OnCreateRoom } from './graphql/subscriptions'; 9 | 10 | const { primaryColor } = theme; 11 | 12 | const CREATE_ROOM = "CREATE_ROOM"; 13 | const SET_ROOMS = "SET_ROOMS"; 14 | const SET_LOADING = "SET_LOADING"; 15 | 16 | const initialState = { 17 | loading: false, 18 | rooms: [], 19 | loading: true 20 | } 21 | 22 | function reducer(state, action) { 23 | switch (action.type) { 24 | case CREATE_ROOM: 25 | return { ...state, rooms: [...state.rooms, action.room] }; 26 | case SET_ROOMS: 27 | return { ...state, rooms: action.rooms }; 28 | case SET_LOADING: 29 | return { ...state, loading: action.loading }; 30 | default: 31 | return state; 32 | } 33 | } 34 | 35 | export default function Rooms() { 36 | const [state, dispatch] = useReducer(reducer, initialState); 37 | const [inputValue, setInputValue] = useState(''); 38 | const history = useHistory(); 39 | let subscription; 40 | 41 | useEffect(() => { 42 | fetchRooms(); 43 | subscribe(); 44 | return () => subscription.unsubscribe(); 45 | }, []); 46 | function subscribe() { 47 | subscription = API.graphql({ 48 | query: OnCreateRoom 49 | }) 50 | .subscribe({ 51 | next: roomData => { 52 | console.log({ roomData }); 53 | dispatch({ type: CREATE_ROOM, room: roomData.value.data.onCreateRoom }); 54 | } 55 | }) 56 | } 57 | async function fetchRooms() { 58 | try { 59 | const roomData = await API.graphql({ 60 | query: listRooms, 61 | variables: { limit: 1000 } 62 | }); 63 | dispatch({ type: SET_ROOMS, rooms: roomData.data.listRooms.items }); 64 | console.log('roomData: ', roomData); 65 | } catch (err) { 66 | console.log('error: ', err) 67 | } 68 | } 69 | async function createRoom() { 70 | if (!inputValue) return; 71 | try { 72 | const room = await API.graphql({ 73 | query: CreateRoom, 74 | variables: { 75 | input: { 76 | name: inputValue 77 | } 78 | } 79 | }) 80 | history.push(`/chat/${room.data.createRoom.name}/${room.data.createRoom.id}`) 81 | } catch (err) { 82 | console.log('error creating room: ', err); 83 | } 84 | } 85 | async function onChange(e) { 86 | e.persist(); 87 | setInputValue(e.target.value); 88 | } 89 | return ( 90 |
91 |
92 |

Available chat rooms

93 | { 94 | state.rooms.map((room) => ( 95 | 96 |

{room.name}

97 | 98 | )) 99 | } 100 |
101 |
102 |
103 | 108 |
109 |
110 | 111 |
112 |
113 |
114 | ) 115 | } 116 | 117 | const inputWrapperStyle = { 118 | display: 'flex' 119 | } 120 | 121 | const buttonWrapperStyle = { 122 | display: 'flex', 123 | alignItems: 'center' 124 | } 125 | 126 | const buttonStyle = { 127 | height: 40, 128 | outline: 'none', 129 | border: 'none', 130 | padding: '0px 20px', 131 | cursor: 'pointer', 132 | backgroundColor: 'transparent', 133 | border: '1px solid', 134 | fontSize: 18 135 | } 136 | 137 | const inputContainerStyle = { 138 | display: 'flex', 139 | position: 'fixed', 140 | bottom: 0, 141 | height: 80, 142 | backgroundColor: '#ddd', 143 | width: '100%', 144 | left: 0 145 | } 146 | 147 | const inputStyle = { 148 | border: 'none', 149 | outline: 'none', 150 | width: 300, 151 | padding: 9, 152 | backgroundColor: 'transparent', 153 | fontSize: 20, 154 | marginLeft: 30 155 | } 156 | 157 | const roomLinkStyle = { 158 | textDecoration: 'none' 159 | } 160 | 161 | const roomNameStyle = { 162 | padding: '20px 0px', 163 | margin: 0, 164 | borderBottom: '1px solid #ddd', 165 | fontSize: 18, 166 | color: 'black', 167 | fontWeight: 300 168 | } 169 | 170 | const titleStyle = { 171 | color: primaryColor 172 | } -------------------------------------------------------------------------------- /src/aws-exports-example.js: -------------------------------------------------------------------------------- 1 | const config = { 2 | Auth: { 3 | region: "", 4 | userPoolId: "", 5 | userPoolWebClientId: "" 6 | }, 7 | aws_appsync_graphqlEndpoint: "", 8 | aws_appsync_region: "", 9 | aws_appsync_authenticationType: "AMAZON_COGNITO_USER_POOLS" 10 | } 11 | 12 | export default config; -------------------------------------------------------------------------------- /src/graphql/mutations.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | // this is an auto generated file. This will be overwritten 3 | 4 | export const createRoom = /* GraphQL */ ` 5 | mutation CreateRoom( 6 | $input: RoomInput! 7 | ) { 8 | createRoom(input: $input) { 9 | id 10 | name 11 | createdAt 12 | } 13 | } 14 | `; 15 | 16 | 17 | export const createMessage = /* GraphQL */ ` 18 | mutation CreateMessage( 19 | $input: MessageInput! 20 | ) { 21 | createMessage(input: $input) { 22 | id 23 | content 24 | owner 25 | createdAt 26 | roomId 27 | } 28 | } 29 | `; 30 | -------------------------------------------------------------------------------- /src/graphql/queries.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | // this is an auto generated file. This will be overwritten 3 | 4 | export const listRooms = /* GraphQL */ ` 5 | query ListRooms( 6 | $limit: Int 7 | ) { 8 | listRooms(limit: $limit) { 9 | items { 10 | id 11 | name 12 | createdAt 13 | updatedAt 14 | } 15 | } 16 | } 17 | `; 18 | 19 | export const listMessagesForRoom = /* GraphQL */ ` 20 | query ListMessagesForRoom( 21 | $roomId: ID 22 | $sortDirection: ModelSortDirection 23 | ) { 24 | listMessagesForRoom( 25 | roomId: $roomId 26 | sortDirection: $sortDirection 27 | ) { 28 | items { 29 | id 30 | content 31 | owner 32 | createdAt 33 | roomId 34 | } 35 | } 36 | } 37 | `; 38 | -------------------------------------------------------------------------------- /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" : "getRoom", 19 | "description" : null, 20 | "args" : [ { 21 | "name" : "id", 22 | "description" : null, 23 | "type" : { 24 | "kind" : "NON_NULL", 25 | "name" : null, 26 | "ofType" : { 27 | "kind" : "SCALAR", 28 | "name" : "ID", 29 | "ofType" : null 30 | } 31 | }, 32 | "defaultValue" : null 33 | } ], 34 | "type" : { 35 | "kind" : "OBJECT", 36 | "name" : "Room", 37 | "ofType" : null 38 | }, 39 | "isDeprecated" : false, 40 | "deprecationReason" : null 41 | }, { 42 | "name" : "listRooms", 43 | "description" : null, 44 | "args" : [ { 45 | "name" : "filter", 46 | "description" : null, 47 | "type" : { 48 | "kind" : "INPUT_OBJECT", 49 | "name" : "ModelRoomFilterInput", 50 | "ofType" : null 51 | }, 52 | "defaultValue" : null 53 | }, { 54 | "name" : "limit", 55 | "description" : null, 56 | "type" : { 57 | "kind" : "SCALAR", 58 | "name" : "Int", 59 | "ofType" : null 60 | }, 61 | "defaultValue" : null 62 | }, { 63 | "name" : "nextToken", 64 | "description" : null, 65 | "type" : { 66 | "kind" : "SCALAR", 67 | "name" : "String", 68 | "ofType" : null 69 | }, 70 | "defaultValue" : null 71 | } ], 72 | "type" : { 73 | "kind" : "OBJECT", 74 | "name" : "ModelRoomConnection", 75 | "ofType" : null 76 | }, 77 | "isDeprecated" : false, 78 | "deprecationReason" : null 79 | }, { 80 | "name" : "getMessage", 81 | "description" : null, 82 | "args" : [ { 83 | "name" : "id", 84 | "description" : null, 85 | "type" : { 86 | "kind" : "NON_NULL", 87 | "name" : null, 88 | "ofType" : { 89 | "kind" : "SCALAR", 90 | "name" : "ID", 91 | "ofType" : null 92 | } 93 | }, 94 | "defaultValue" : null 95 | } ], 96 | "type" : { 97 | "kind" : "OBJECT", 98 | "name" : "Message", 99 | "ofType" : null 100 | }, 101 | "isDeprecated" : false, 102 | "deprecationReason" : null 103 | }, { 104 | "name" : "listMessages", 105 | "description" : null, 106 | "args" : [ { 107 | "name" : "filter", 108 | "description" : null, 109 | "type" : { 110 | "kind" : "INPUT_OBJECT", 111 | "name" : "ModelMessageFilterInput", 112 | "ofType" : null 113 | }, 114 | "defaultValue" : null 115 | }, { 116 | "name" : "limit", 117 | "description" : null, 118 | "type" : { 119 | "kind" : "SCALAR", 120 | "name" : "Int", 121 | "ofType" : null 122 | }, 123 | "defaultValue" : null 124 | }, { 125 | "name" : "nextToken", 126 | "description" : null, 127 | "type" : { 128 | "kind" : "SCALAR", 129 | "name" : "String", 130 | "ofType" : null 131 | }, 132 | "defaultValue" : null 133 | } ], 134 | "type" : { 135 | "kind" : "OBJECT", 136 | "name" : "ModelMessageConnection", 137 | "ofType" : null 138 | }, 139 | "isDeprecated" : false, 140 | "deprecationReason" : null 141 | }, { 142 | "name" : "listMessagesForRoom", 143 | "description" : null, 144 | "args" : [ { 145 | "name" : "roomId", 146 | "description" : null, 147 | "type" : { 148 | "kind" : "SCALAR", 149 | "name" : "ID", 150 | "ofType" : null 151 | }, 152 | "defaultValue" : null 153 | }, { 154 | "name" : "createdAt", 155 | "description" : null, 156 | "type" : { 157 | "kind" : "INPUT_OBJECT", 158 | "name" : "ModelStringKeyConditionInput", 159 | "ofType" : null 160 | }, 161 | "defaultValue" : null 162 | }, { 163 | "name" : "sortDirection", 164 | "description" : null, 165 | "type" : { 166 | "kind" : "ENUM", 167 | "name" : "ModelSortDirection", 168 | "ofType" : null 169 | }, 170 | "defaultValue" : null 171 | }, { 172 | "name" : "filter", 173 | "description" : null, 174 | "type" : { 175 | "kind" : "INPUT_OBJECT", 176 | "name" : "ModelMessageFilterInput", 177 | "ofType" : null 178 | }, 179 | "defaultValue" : null 180 | }, { 181 | "name" : "limit", 182 | "description" : null, 183 | "type" : { 184 | "kind" : "SCALAR", 185 | "name" : "Int", 186 | "ofType" : null 187 | }, 188 | "defaultValue" : null 189 | }, { 190 | "name" : "nextToken", 191 | "description" : null, 192 | "type" : { 193 | "kind" : "SCALAR", 194 | "name" : "String", 195 | "ofType" : null 196 | }, 197 | "defaultValue" : null 198 | } ], 199 | "type" : { 200 | "kind" : "OBJECT", 201 | "name" : "ModelMessageConnection", 202 | "ofType" : null 203 | }, 204 | "isDeprecated" : false, 205 | "deprecationReason" : null 206 | } ], 207 | "inputFields" : null, 208 | "interfaces" : [ ], 209 | "enumValues" : null, 210 | "possibleTypes" : null 211 | }, { 212 | "kind" : "OBJECT", 213 | "name" : "Room", 214 | "description" : null, 215 | "fields" : [ { 216 | "name" : "id", 217 | "description" : null, 218 | "args" : [ ], 219 | "type" : { 220 | "kind" : "NON_NULL", 221 | "name" : null, 222 | "ofType" : { 223 | "kind" : "SCALAR", 224 | "name" : "ID", 225 | "ofType" : null 226 | } 227 | }, 228 | "isDeprecated" : false, 229 | "deprecationReason" : null 230 | }, { 231 | "name" : "name", 232 | "description" : null, 233 | "args" : [ ], 234 | "type" : { 235 | "kind" : "SCALAR", 236 | "name" : "String", 237 | "ofType" : null 238 | }, 239 | "isDeprecated" : false, 240 | "deprecationReason" : null 241 | }, { 242 | "name" : "messages", 243 | "description" : null, 244 | "args" : [ { 245 | "name" : "createdAt", 246 | "description" : null, 247 | "type" : { 248 | "kind" : "INPUT_OBJECT", 249 | "name" : "ModelStringKeyConditionInput", 250 | "ofType" : null 251 | }, 252 | "defaultValue" : null 253 | }, { 254 | "name" : "filter", 255 | "description" : null, 256 | "type" : { 257 | "kind" : "INPUT_OBJECT", 258 | "name" : "ModelMessageFilterInput", 259 | "ofType" : null 260 | }, 261 | "defaultValue" : null 262 | }, { 263 | "name" : "sortDirection", 264 | "description" : null, 265 | "type" : { 266 | "kind" : "ENUM", 267 | "name" : "ModelSortDirection", 268 | "ofType" : null 269 | }, 270 | "defaultValue" : null 271 | }, { 272 | "name" : "limit", 273 | "description" : null, 274 | "type" : { 275 | "kind" : "SCALAR", 276 | "name" : "Int", 277 | "ofType" : null 278 | }, 279 | "defaultValue" : null 280 | }, { 281 | "name" : "nextToken", 282 | "description" : null, 283 | "type" : { 284 | "kind" : "SCALAR", 285 | "name" : "String", 286 | "ofType" : null 287 | }, 288 | "defaultValue" : null 289 | } ], 290 | "type" : { 291 | "kind" : "OBJECT", 292 | "name" : "ModelMessageConnection", 293 | "ofType" : null 294 | }, 295 | "isDeprecated" : false, 296 | "deprecationReason" : null 297 | }, { 298 | "name" : "createdAt", 299 | "description" : null, 300 | "args" : [ ], 301 | "type" : { 302 | "kind" : "SCALAR", 303 | "name" : "AWSDateTime", 304 | "ofType" : null 305 | }, 306 | "isDeprecated" : false, 307 | "deprecationReason" : null 308 | }, { 309 | "name" : "updatedAt", 310 | "description" : null, 311 | "args" : [ ], 312 | "type" : { 313 | "kind" : "SCALAR", 314 | "name" : "AWSDateTime", 315 | "ofType" : null 316 | }, 317 | "isDeprecated" : false, 318 | "deprecationReason" : null 319 | } ], 320 | "inputFields" : null, 321 | "interfaces" : [ ], 322 | "enumValues" : null, 323 | "possibleTypes" : null 324 | }, { 325 | "kind" : "SCALAR", 326 | "name" : "ID", 327 | "description" : "Built-in ID", 328 | "fields" : null, 329 | "inputFields" : null, 330 | "interfaces" : null, 331 | "enumValues" : null, 332 | "possibleTypes" : null 333 | }, { 334 | "kind" : "SCALAR", 335 | "name" : "String", 336 | "description" : "Built-in String", 337 | "fields" : null, 338 | "inputFields" : null, 339 | "interfaces" : null, 340 | "enumValues" : null, 341 | "possibleTypes" : null 342 | }, { 343 | "kind" : "OBJECT", 344 | "name" : "ModelMessageConnection", 345 | "description" : null, 346 | "fields" : [ { 347 | "name" : "items", 348 | "description" : null, 349 | "args" : [ ], 350 | "type" : { 351 | "kind" : "LIST", 352 | "name" : null, 353 | "ofType" : { 354 | "kind" : "OBJECT", 355 | "name" : "Message", 356 | "ofType" : null 357 | } 358 | }, 359 | "isDeprecated" : false, 360 | "deprecationReason" : null 361 | }, { 362 | "name" : "nextToken", 363 | "description" : null, 364 | "args" : [ ], 365 | "type" : { 366 | "kind" : "SCALAR", 367 | "name" : "String", 368 | "ofType" : null 369 | }, 370 | "isDeprecated" : false, 371 | "deprecationReason" : null 372 | } ], 373 | "inputFields" : null, 374 | "interfaces" : [ ], 375 | "enumValues" : null, 376 | "possibleTypes" : null 377 | }, { 378 | "kind" : "OBJECT", 379 | "name" : "Message", 380 | "description" : null, 381 | "fields" : [ { 382 | "name" : "id", 383 | "description" : null, 384 | "args" : [ ], 385 | "type" : { 386 | "kind" : "NON_NULL", 387 | "name" : null, 388 | "ofType" : { 389 | "kind" : "SCALAR", 390 | "name" : "ID", 391 | "ofType" : null 392 | } 393 | }, 394 | "isDeprecated" : false, 395 | "deprecationReason" : null 396 | }, { 397 | "name" : "content", 398 | "description" : null, 399 | "args" : [ ], 400 | "type" : { 401 | "kind" : "NON_NULL", 402 | "name" : null, 403 | "ofType" : { 404 | "kind" : "SCALAR", 405 | "name" : "String", 406 | "ofType" : null 407 | } 408 | }, 409 | "isDeprecated" : false, 410 | "deprecationReason" : null 411 | }, { 412 | "name" : "owner", 413 | "description" : null, 414 | "args" : [ ], 415 | "type" : { 416 | "kind" : "SCALAR", 417 | "name" : "String", 418 | "ofType" : null 419 | }, 420 | "isDeprecated" : false, 421 | "deprecationReason" : null 422 | }, { 423 | "name" : "createdAt", 424 | "description" : null, 425 | "args" : [ ], 426 | "type" : { 427 | "kind" : "SCALAR", 428 | "name" : "String", 429 | "ofType" : null 430 | }, 431 | "isDeprecated" : false, 432 | "deprecationReason" : null 433 | }, { 434 | "name" : "roomId", 435 | "description" : null, 436 | "args" : [ ], 437 | "type" : { 438 | "kind" : "SCALAR", 439 | "name" : "ID", 440 | "ofType" : null 441 | }, 442 | "isDeprecated" : false, 443 | "deprecationReason" : null 444 | }, { 445 | "name" : "updatedAt", 446 | "description" : null, 447 | "args" : [ ], 448 | "type" : { 449 | "kind" : "NON_NULL", 450 | "name" : null, 451 | "ofType" : { 452 | "kind" : "SCALAR", 453 | "name" : "AWSDateTime", 454 | "ofType" : null 455 | } 456 | }, 457 | "isDeprecated" : false, 458 | "deprecationReason" : null 459 | } ], 460 | "inputFields" : null, 461 | "interfaces" : [ ], 462 | "enumValues" : null, 463 | "possibleTypes" : null 464 | }, { 465 | "kind" : "SCALAR", 466 | "name" : "AWSDateTime", 467 | "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.", 468 | "fields" : null, 469 | "inputFields" : null, 470 | "interfaces" : null, 471 | "enumValues" : null, 472 | "possibleTypes" : null 473 | }, { 474 | "kind" : "INPUT_OBJECT", 475 | "name" : "ModelStringKeyConditionInput", 476 | "description" : null, 477 | "fields" : null, 478 | "inputFields" : [ { 479 | "name" : "eq", 480 | "description" : null, 481 | "type" : { 482 | "kind" : "SCALAR", 483 | "name" : "String", 484 | "ofType" : null 485 | }, 486 | "defaultValue" : null 487 | }, { 488 | "name" : "le", 489 | "description" : null, 490 | "type" : { 491 | "kind" : "SCALAR", 492 | "name" : "String", 493 | "ofType" : null 494 | }, 495 | "defaultValue" : null 496 | }, { 497 | "name" : "lt", 498 | "description" : null, 499 | "type" : { 500 | "kind" : "SCALAR", 501 | "name" : "String", 502 | "ofType" : null 503 | }, 504 | "defaultValue" : null 505 | }, { 506 | "name" : "ge", 507 | "description" : null, 508 | "type" : { 509 | "kind" : "SCALAR", 510 | "name" : "String", 511 | "ofType" : null 512 | }, 513 | "defaultValue" : null 514 | }, { 515 | "name" : "gt", 516 | "description" : null, 517 | "type" : { 518 | "kind" : "SCALAR", 519 | "name" : "String", 520 | "ofType" : null 521 | }, 522 | "defaultValue" : null 523 | }, { 524 | "name" : "between", 525 | "description" : null, 526 | "type" : { 527 | "kind" : "LIST", 528 | "name" : null, 529 | "ofType" : { 530 | "kind" : "SCALAR", 531 | "name" : "String", 532 | "ofType" : null 533 | } 534 | }, 535 | "defaultValue" : null 536 | }, { 537 | "name" : "beginsWith", 538 | "description" : null, 539 | "type" : { 540 | "kind" : "SCALAR", 541 | "name" : "String", 542 | "ofType" : null 543 | }, 544 | "defaultValue" : null 545 | } ], 546 | "interfaces" : null, 547 | "enumValues" : null, 548 | "possibleTypes" : null 549 | }, { 550 | "kind" : "INPUT_OBJECT", 551 | "name" : "ModelMessageFilterInput", 552 | "description" : null, 553 | "fields" : null, 554 | "inputFields" : [ { 555 | "name" : "id", 556 | "description" : null, 557 | "type" : { 558 | "kind" : "INPUT_OBJECT", 559 | "name" : "ModelIDInput", 560 | "ofType" : null 561 | }, 562 | "defaultValue" : null 563 | }, { 564 | "name" : "content", 565 | "description" : null, 566 | "type" : { 567 | "kind" : "INPUT_OBJECT", 568 | "name" : "ModelStringInput", 569 | "ofType" : null 570 | }, 571 | "defaultValue" : null 572 | }, { 573 | "name" : "owner", 574 | "description" : null, 575 | "type" : { 576 | "kind" : "INPUT_OBJECT", 577 | "name" : "ModelStringInput", 578 | "ofType" : null 579 | }, 580 | "defaultValue" : null 581 | }, { 582 | "name" : "createdAt", 583 | "description" : null, 584 | "type" : { 585 | "kind" : "INPUT_OBJECT", 586 | "name" : "ModelStringInput", 587 | "ofType" : null 588 | }, 589 | "defaultValue" : null 590 | }, { 591 | "name" : "roomId", 592 | "description" : null, 593 | "type" : { 594 | "kind" : "INPUT_OBJECT", 595 | "name" : "ModelIDInput", 596 | "ofType" : null 597 | }, 598 | "defaultValue" : null 599 | }, { 600 | "name" : "and", 601 | "description" : null, 602 | "type" : { 603 | "kind" : "LIST", 604 | "name" : null, 605 | "ofType" : { 606 | "kind" : "INPUT_OBJECT", 607 | "name" : "ModelMessageFilterInput", 608 | "ofType" : null 609 | } 610 | }, 611 | "defaultValue" : null 612 | }, { 613 | "name" : "or", 614 | "description" : null, 615 | "type" : { 616 | "kind" : "LIST", 617 | "name" : null, 618 | "ofType" : { 619 | "kind" : "INPUT_OBJECT", 620 | "name" : "ModelMessageFilterInput", 621 | "ofType" : null 622 | } 623 | }, 624 | "defaultValue" : null 625 | }, { 626 | "name" : "not", 627 | "description" : null, 628 | "type" : { 629 | "kind" : "INPUT_OBJECT", 630 | "name" : "ModelMessageFilterInput", 631 | "ofType" : null 632 | }, 633 | "defaultValue" : null 634 | } ], 635 | "interfaces" : null, 636 | "enumValues" : null, 637 | "possibleTypes" : null 638 | }, { 639 | "kind" : "INPUT_OBJECT", 640 | "name" : "ModelIDInput", 641 | "description" : null, 642 | "fields" : null, 643 | "inputFields" : [ { 644 | "name" : "ne", 645 | "description" : null, 646 | "type" : { 647 | "kind" : "SCALAR", 648 | "name" : "ID", 649 | "ofType" : null 650 | }, 651 | "defaultValue" : null 652 | }, { 653 | "name" : "eq", 654 | "description" : null, 655 | "type" : { 656 | "kind" : "SCALAR", 657 | "name" : "ID", 658 | "ofType" : null 659 | }, 660 | "defaultValue" : null 661 | }, { 662 | "name" : "le", 663 | "description" : null, 664 | "type" : { 665 | "kind" : "SCALAR", 666 | "name" : "ID", 667 | "ofType" : null 668 | }, 669 | "defaultValue" : null 670 | }, { 671 | "name" : "lt", 672 | "description" : null, 673 | "type" : { 674 | "kind" : "SCALAR", 675 | "name" : "ID", 676 | "ofType" : null 677 | }, 678 | "defaultValue" : null 679 | }, { 680 | "name" : "ge", 681 | "description" : null, 682 | "type" : { 683 | "kind" : "SCALAR", 684 | "name" : "ID", 685 | "ofType" : null 686 | }, 687 | "defaultValue" : null 688 | }, { 689 | "name" : "gt", 690 | "description" : null, 691 | "type" : { 692 | "kind" : "SCALAR", 693 | "name" : "ID", 694 | "ofType" : null 695 | }, 696 | "defaultValue" : null 697 | }, { 698 | "name" : "contains", 699 | "description" : null, 700 | "type" : { 701 | "kind" : "SCALAR", 702 | "name" : "ID", 703 | "ofType" : null 704 | }, 705 | "defaultValue" : null 706 | }, { 707 | "name" : "notContains", 708 | "description" : null, 709 | "type" : { 710 | "kind" : "SCALAR", 711 | "name" : "ID", 712 | "ofType" : null 713 | }, 714 | "defaultValue" : null 715 | }, { 716 | "name" : "between", 717 | "description" : null, 718 | "type" : { 719 | "kind" : "LIST", 720 | "name" : null, 721 | "ofType" : { 722 | "kind" : "SCALAR", 723 | "name" : "ID", 724 | "ofType" : null 725 | } 726 | }, 727 | "defaultValue" : null 728 | }, { 729 | "name" : "beginsWith", 730 | "description" : null, 731 | "type" : { 732 | "kind" : "SCALAR", 733 | "name" : "ID", 734 | "ofType" : null 735 | }, 736 | "defaultValue" : null 737 | }, { 738 | "name" : "attributeExists", 739 | "description" : null, 740 | "type" : { 741 | "kind" : "SCALAR", 742 | "name" : "Boolean", 743 | "ofType" : null 744 | }, 745 | "defaultValue" : null 746 | }, { 747 | "name" : "attributeType", 748 | "description" : null, 749 | "type" : { 750 | "kind" : "ENUM", 751 | "name" : "ModelAttributeTypes", 752 | "ofType" : null 753 | }, 754 | "defaultValue" : null 755 | }, { 756 | "name" : "size", 757 | "description" : null, 758 | "type" : { 759 | "kind" : "INPUT_OBJECT", 760 | "name" : "ModelSizeInput", 761 | "ofType" : null 762 | }, 763 | "defaultValue" : null 764 | } ], 765 | "interfaces" : null, 766 | "enumValues" : null, 767 | "possibleTypes" : null 768 | }, { 769 | "kind" : "SCALAR", 770 | "name" : "Boolean", 771 | "description" : "Built-in Boolean", 772 | "fields" : null, 773 | "inputFields" : null, 774 | "interfaces" : null, 775 | "enumValues" : null, 776 | "possibleTypes" : null 777 | }, { 778 | "kind" : "ENUM", 779 | "name" : "ModelAttributeTypes", 780 | "description" : null, 781 | "fields" : null, 782 | "inputFields" : null, 783 | "interfaces" : null, 784 | "enumValues" : [ { 785 | "name" : "binary", 786 | "description" : null, 787 | "isDeprecated" : false, 788 | "deprecationReason" : null 789 | }, { 790 | "name" : "binarySet", 791 | "description" : null, 792 | "isDeprecated" : false, 793 | "deprecationReason" : null 794 | }, { 795 | "name" : "bool", 796 | "description" : null, 797 | "isDeprecated" : false, 798 | "deprecationReason" : null 799 | }, { 800 | "name" : "list", 801 | "description" : null, 802 | "isDeprecated" : false, 803 | "deprecationReason" : null 804 | }, { 805 | "name" : "map", 806 | "description" : null, 807 | "isDeprecated" : false, 808 | "deprecationReason" : null 809 | }, { 810 | "name" : "number", 811 | "description" : null, 812 | "isDeprecated" : false, 813 | "deprecationReason" : null 814 | }, { 815 | "name" : "numberSet", 816 | "description" : null, 817 | "isDeprecated" : false, 818 | "deprecationReason" : null 819 | }, { 820 | "name" : "string", 821 | "description" : null, 822 | "isDeprecated" : false, 823 | "deprecationReason" : null 824 | }, { 825 | "name" : "stringSet", 826 | "description" : null, 827 | "isDeprecated" : false, 828 | "deprecationReason" : null 829 | }, { 830 | "name" : "_null", 831 | "description" : null, 832 | "isDeprecated" : false, 833 | "deprecationReason" : null 834 | } ], 835 | "possibleTypes" : null 836 | }, { 837 | "kind" : "INPUT_OBJECT", 838 | "name" : "ModelSizeInput", 839 | "description" : null, 840 | "fields" : null, 841 | "inputFields" : [ { 842 | "name" : "ne", 843 | "description" : null, 844 | "type" : { 845 | "kind" : "SCALAR", 846 | "name" : "Int", 847 | "ofType" : null 848 | }, 849 | "defaultValue" : null 850 | }, { 851 | "name" : "eq", 852 | "description" : null, 853 | "type" : { 854 | "kind" : "SCALAR", 855 | "name" : "Int", 856 | "ofType" : null 857 | }, 858 | "defaultValue" : null 859 | }, { 860 | "name" : "le", 861 | "description" : null, 862 | "type" : { 863 | "kind" : "SCALAR", 864 | "name" : "Int", 865 | "ofType" : null 866 | }, 867 | "defaultValue" : null 868 | }, { 869 | "name" : "lt", 870 | "description" : null, 871 | "type" : { 872 | "kind" : "SCALAR", 873 | "name" : "Int", 874 | "ofType" : null 875 | }, 876 | "defaultValue" : null 877 | }, { 878 | "name" : "ge", 879 | "description" : null, 880 | "type" : { 881 | "kind" : "SCALAR", 882 | "name" : "Int", 883 | "ofType" : null 884 | }, 885 | "defaultValue" : null 886 | }, { 887 | "name" : "gt", 888 | "description" : null, 889 | "type" : { 890 | "kind" : "SCALAR", 891 | "name" : "Int", 892 | "ofType" : null 893 | }, 894 | "defaultValue" : null 895 | }, { 896 | "name" : "between", 897 | "description" : null, 898 | "type" : { 899 | "kind" : "LIST", 900 | "name" : null, 901 | "ofType" : { 902 | "kind" : "SCALAR", 903 | "name" : "Int", 904 | "ofType" : null 905 | } 906 | }, 907 | "defaultValue" : null 908 | } ], 909 | "interfaces" : null, 910 | "enumValues" : null, 911 | "possibleTypes" : null 912 | }, { 913 | "kind" : "SCALAR", 914 | "name" : "Int", 915 | "description" : "Built-in Int", 916 | "fields" : null, 917 | "inputFields" : null, 918 | "interfaces" : null, 919 | "enumValues" : null, 920 | "possibleTypes" : null 921 | }, { 922 | "kind" : "INPUT_OBJECT", 923 | "name" : "ModelStringInput", 924 | "description" : null, 925 | "fields" : null, 926 | "inputFields" : [ { 927 | "name" : "ne", 928 | "description" : null, 929 | "type" : { 930 | "kind" : "SCALAR", 931 | "name" : "String", 932 | "ofType" : null 933 | }, 934 | "defaultValue" : null 935 | }, { 936 | "name" : "eq", 937 | "description" : null, 938 | "type" : { 939 | "kind" : "SCALAR", 940 | "name" : "String", 941 | "ofType" : null 942 | }, 943 | "defaultValue" : null 944 | }, { 945 | "name" : "le", 946 | "description" : null, 947 | "type" : { 948 | "kind" : "SCALAR", 949 | "name" : "String", 950 | "ofType" : null 951 | }, 952 | "defaultValue" : null 953 | }, { 954 | "name" : "lt", 955 | "description" : null, 956 | "type" : { 957 | "kind" : "SCALAR", 958 | "name" : "String", 959 | "ofType" : null 960 | }, 961 | "defaultValue" : null 962 | }, { 963 | "name" : "ge", 964 | "description" : null, 965 | "type" : { 966 | "kind" : "SCALAR", 967 | "name" : "String", 968 | "ofType" : null 969 | }, 970 | "defaultValue" : null 971 | }, { 972 | "name" : "gt", 973 | "description" : null, 974 | "type" : { 975 | "kind" : "SCALAR", 976 | "name" : "String", 977 | "ofType" : null 978 | }, 979 | "defaultValue" : null 980 | }, { 981 | "name" : "contains", 982 | "description" : null, 983 | "type" : { 984 | "kind" : "SCALAR", 985 | "name" : "String", 986 | "ofType" : null 987 | }, 988 | "defaultValue" : null 989 | }, { 990 | "name" : "notContains", 991 | "description" : null, 992 | "type" : { 993 | "kind" : "SCALAR", 994 | "name" : "String", 995 | "ofType" : null 996 | }, 997 | "defaultValue" : null 998 | }, { 999 | "name" : "between", 1000 | "description" : null, 1001 | "type" : { 1002 | "kind" : "LIST", 1003 | "name" : null, 1004 | "ofType" : { 1005 | "kind" : "SCALAR", 1006 | "name" : "String", 1007 | "ofType" : null 1008 | } 1009 | }, 1010 | "defaultValue" : null 1011 | }, { 1012 | "name" : "beginsWith", 1013 | "description" : null, 1014 | "type" : { 1015 | "kind" : "SCALAR", 1016 | "name" : "String", 1017 | "ofType" : null 1018 | }, 1019 | "defaultValue" : null 1020 | }, { 1021 | "name" : "attributeExists", 1022 | "description" : null, 1023 | "type" : { 1024 | "kind" : "SCALAR", 1025 | "name" : "Boolean", 1026 | "ofType" : null 1027 | }, 1028 | "defaultValue" : null 1029 | }, { 1030 | "name" : "attributeType", 1031 | "description" : null, 1032 | "type" : { 1033 | "kind" : "ENUM", 1034 | "name" : "ModelAttributeTypes", 1035 | "ofType" : null 1036 | }, 1037 | "defaultValue" : null 1038 | }, { 1039 | "name" : "size", 1040 | "description" : null, 1041 | "type" : { 1042 | "kind" : "INPUT_OBJECT", 1043 | "name" : "ModelSizeInput", 1044 | "ofType" : null 1045 | }, 1046 | "defaultValue" : null 1047 | } ], 1048 | "interfaces" : null, 1049 | "enumValues" : null, 1050 | "possibleTypes" : null 1051 | }, { 1052 | "kind" : "ENUM", 1053 | "name" : "ModelSortDirection", 1054 | "description" : null, 1055 | "fields" : null, 1056 | "inputFields" : null, 1057 | "interfaces" : null, 1058 | "enumValues" : [ { 1059 | "name" : "ASC", 1060 | "description" : null, 1061 | "isDeprecated" : false, 1062 | "deprecationReason" : null 1063 | }, { 1064 | "name" : "DESC", 1065 | "description" : null, 1066 | "isDeprecated" : false, 1067 | "deprecationReason" : null 1068 | } ], 1069 | "possibleTypes" : null 1070 | }, { 1071 | "kind" : "OBJECT", 1072 | "name" : "ModelRoomConnection", 1073 | "description" : null, 1074 | "fields" : [ { 1075 | "name" : "items", 1076 | "description" : null, 1077 | "args" : [ ], 1078 | "type" : { 1079 | "kind" : "LIST", 1080 | "name" : null, 1081 | "ofType" : { 1082 | "kind" : "OBJECT", 1083 | "name" : "Room", 1084 | "ofType" : null 1085 | } 1086 | }, 1087 | "isDeprecated" : false, 1088 | "deprecationReason" : null 1089 | }, { 1090 | "name" : "nextToken", 1091 | "description" : null, 1092 | "args" : [ ], 1093 | "type" : { 1094 | "kind" : "SCALAR", 1095 | "name" : "String", 1096 | "ofType" : null 1097 | }, 1098 | "isDeprecated" : false, 1099 | "deprecationReason" : null 1100 | } ], 1101 | "inputFields" : null, 1102 | "interfaces" : [ ], 1103 | "enumValues" : null, 1104 | "possibleTypes" : null 1105 | }, { 1106 | "kind" : "INPUT_OBJECT", 1107 | "name" : "ModelRoomFilterInput", 1108 | "description" : null, 1109 | "fields" : null, 1110 | "inputFields" : [ { 1111 | "name" : "id", 1112 | "description" : null, 1113 | "type" : { 1114 | "kind" : "INPUT_OBJECT", 1115 | "name" : "ModelIDInput", 1116 | "ofType" : null 1117 | }, 1118 | "defaultValue" : null 1119 | }, { 1120 | "name" : "name", 1121 | "description" : null, 1122 | "type" : { 1123 | "kind" : "INPUT_OBJECT", 1124 | "name" : "ModelStringInput", 1125 | "ofType" : null 1126 | }, 1127 | "defaultValue" : null 1128 | }, { 1129 | "name" : "createdAt", 1130 | "description" : null, 1131 | "type" : { 1132 | "kind" : "INPUT_OBJECT", 1133 | "name" : "ModelStringInput", 1134 | "ofType" : null 1135 | }, 1136 | "defaultValue" : null 1137 | }, { 1138 | "name" : "updatedAt", 1139 | "description" : null, 1140 | "type" : { 1141 | "kind" : "INPUT_OBJECT", 1142 | "name" : "ModelStringInput", 1143 | "ofType" : null 1144 | }, 1145 | "defaultValue" : null 1146 | }, { 1147 | "name" : "and", 1148 | "description" : null, 1149 | "type" : { 1150 | "kind" : "LIST", 1151 | "name" : null, 1152 | "ofType" : { 1153 | "kind" : "INPUT_OBJECT", 1154 | "name" : "ModelRoomFilterInput", 1155 | "ofType" : null 1156 | } 1157 | }, 1158 | "defaultValue" : null 1159 | }, { 1160 | "name" : "or", 1161 | "description" : null, 1162 | "type" : { 1163 | "kind" : "LIST", 1164 | "name" : null, 1165 | "ofType" : { 1166 | "kind" : "INPUT_OBJECT", 1167 | "name" : "ModelRoomFilterInput", 1168 | "ofType" : null 1169 | } 1170 | }, 1171 | "defaultValue" : null 1172 | }, { 1173 | "name" : "not", 1174 | "description" : null, 1175 | "type" : { 1176 | "kind" : "INPUT_OBJECT", 1177 | "name" : "ModelRoomFilterInput", 1178 | "ofType" : null 1179 | }, 1180 | "defaultValue" : null 1181 | } ], 1182 | "interfaces" : null, 1183 | "enumValues" : null, 1184 | "possibleTypes" : null 1185 | }, { 1186 | "kind" : "OBJECT", 1187 | "name" : "Mutation", 1188 | "description" : null, 1189 | "fields" : [ { 1190 | "name" : "createRoom", 1191 | "description" : null, 1192 | "args" : [ { 1193 | "name" : "input", 1194 | "description" : null, 1195 | "type" : { 1196 | "kind" : "NON_NULL", 1197 | "name" : null, 1198 | "ofType" : { 1199 | "kind" : "INPUT_OBJECT", 1200 | "name" : "CreateRoomInput", 1201 | "ofType" : null 1202 | } 1203 | }, 1204 | "defaultValue" : null 1205 | }, { 1206 | "name" : "condition", 1207 | "description" : null, 1208 | "type" : { 1209 | "kind" : "INPUT_OBJECT", 1210 | "name" : "ModelRoomConditionInput", 1211 | "ofType" : null 1212 | }, 1213 | "defaultValue" : null 1214 | } ], 1215 | "type" : { 1216 | "kind" : "OBJECT", 1217 | "name" : "Room", 1218 | "ofType" : null 1219 | }, 1220 | "isDeprecated" : false, 1221 | "deprecationReason" : null 1222 | }, { 1223 | "name" : "updateRoom", 1224 | "description" : null, 1225 | "args" : [ { 1226 | "name" : "input", 1227 | "description" : null, 1228 | "type" : { 1229 | "kind" : "NON_NULL", 1230 | "name" : null, 1231 | "ofType" : { 1232 | "kind" : "INPUT_OBJECT", 1233 | "name" : "UpdateRoomInput", 1234 | "ofType" : null 1235 | } 1236 | }, 1237 | "defaultValue" : null 1238 | }, { 1239 | "name" : "condition", 1240 | "description" : null, 1241 | "type" : { 1242 | "kind" : "INPUT_OBJECT", 1243 | "name" : "ModelRoomConditionInput", 1244 | "ofType" : null 1245 | }, 1246 | "defaultValue" : null 1247 | } ], 1248 | "type" : { 1249 | "kind" : "OBJECT", 1250 | "name" : "Room", 1251 | "ofType" : null 1252 | }, 1253 | "isDeprecated" : false, 1254 | "deprecationReason" : null 1255 | }, { 1256 | "name" : "deleteRoom", 1257 | "description" : null, 1258 | "args" : [ { 1259 | "name" : "input", 1260 | "description" : null, 1261 | "type" : { 1262 | "kind" : "NON_NULL", 1263 | "name" : null, 1264 | "ofType" : { 1265 | "kind" : "INPUT_OBJECT", 1266 | "name" : "DeleteRoomInput", 1267 | "ofType" : null 1268 | } 1269 | }, 1270 | "defaultValue" : null 1271 | }, { 1272 | "name" : "condition", 1273 | "description" : null, 1274 | "type" : { 1275 | "kind" : "INPUT_OBJECT", 1276 | "name" : "ModelRoomConditionInput", 1277 | "ofType" : null 1278 | }, 1279 | "defaultValue" : null 1280 | } ], 1281 | "type" : { 1282 | "kind" : "OBJECT", 1283 | "name" : "Room", 1284 | "ofType" : null 1285 | }, 1286 | "isDeprecated" : false, 1287 | "deprecationReason" : null 1288 | }, { 1289 | "name" : "createMessage", 1290 | "description" : null, 1291 | "args" : [ { 1292 | "name" : "input", 1293 | "description" : null, 1294 | "type" : { 1295 | "kind" : "NON_NULL", 1296 | "name" : null, 1297 | "ofType" : { 1298 | "kind" : "INPUT_OBJECT", 1299 | "name" : "CreateMessageInput", 1300 | "ofType" : null 1301 | } 1302 | }, 1303 | "defaultValue" : null 1304 | }, { 1305 | "name" : "condition", 1306 | "description" : null, 1307 | "type" : { 1308 | "kind" : "INPUT_OBJECT", 1309 | "name" : "ModelMessageConditionInput", 1310 | "ofType" : null 1311 | }, 1312 | "defaultValue" : null 1313 | } ], 1314 | "type" : { 1315 | "kind" : "OBJECT", 1316 | "name" : "Message", 1317 | "ofType" : null 1318 | }, 1319 | "isDeprecated" : false, 1320 | "deprecationReason" : null 1321 | }, { 1322 | "name" : "updateMessage", 1323 | "description" : null, 1324 | "args" : [ { 1325 | "name" : "input", 1326 | "description" : null, 1327 | "type" : { 1328 | "kind" : "NON_NULL", 1329 | "name" : null, 1330 | "ofType" : { 1331 | "kind" : "INPUT_OBJECT", 1332 | "name" : "UpdateMessageInput", 1333 | "ofType" : null 1334 | } 1335 | }, 1336 | "defaultValue" : null 1337 | }, { 1338 | "name" : "condition", 1339 | "description" : null, 1340 | "type" : { 1341 | "kind" : "INPUT_OBJECT", 1342 | "name" : "ModelMessageConditionInput", 1343 | "ofType" : null 1344 | }, 1345 | "defaultValue" : null 1346 | } ], 1347 | "type" : { 1348 | "kind" : "OBJECT", 1349 | "name" : "Message", 1350 | "ofType" : null 1351 | }, 1352 | "isDeprecated" : false, 1353 | "deprecationReason" : null 1354 | }, { 1355 | "name" : "deleteMessage", 1356 | "description" : null, 1357 | "args" : [ { 1358 | "name" : "input", 1359 | "description" : null, 1360 | "type" : { 1361 | "kind" : "NON_NULL", 1362 | "name" : null, 1363 | "ofType" : { 1364 | "kind" : "INPUT_OBJECT", 1365 | "name" : "DeleteMessageInput", 1366 | "ofType" : null 1367 | } 1368 | }, 1369 | "defaultValue" : null 1370 | }, { 1371 | "name" : "condition", 1372 | "description" : null, 1373 | "type" : { 1374 | "kind" : "INPUT_OBJECT", 1375 | "name" : "ModelMessageConditionInput", 1376 | "ofType" : null 1377 | }, 1378 | "defaultValue" : null 1379 | } ], 1380 | "type" : { 1381 | "kind" : "OBJECT", 1382 | "name" : "Message", 1383 | "ofType" : null 1384 | }, 1385 | "isDeprecated" : false, 1386 | "deprecationReason" : null 1387 | } ], 1388 | "inputFields" : null, 1389 | "interfaces" : [ ], 1390 | "enumValues" : null, 1391 | "possibleTypes" : null 1392 | }, { 1393 | "kind" : "INPUT_OBJECT", 1394 | "name" : "CreateRoomInput", 1395 | "description" : null, 1396 | "fields" : null, 1397 | "inputFields" : [ { 1398 | "name" : "id", 1399 | "description" : null, 1400 | "type" : { 1401 | "kind" : "SCALAR", 1402 | "name" : "ID", 1403 | "ofType" : null 1404 | }, 1405 | "defaultValue" : null 1406 | }, { 1407 | "name" : "name", 1408 | "description" : null, 1409 | "type" : { 1410 | "kind" : "SCALAR", 1411 | "name" : "String", 1412 | "ofType" : null 1413 | }, 1414 | "defaultValue" : null 1415 | }, { 1416 | "name" : "createdAt", 1417 | "description" : null, 1418 | "type" : { 1419 | "kind" : "SCALAR", 1420 | "name" : "AWSDateTime", 1421 | "ofType" : null 1422 | }, 1423 | "defaultValue" : null 1424 | }, { 1425 | "name" : "updatedAt", 1426 | "description" : null, 1427 | "type" : { 1428 | "kind" : "SCALAR", 1429 | "name" : "AWSDateTime", 1430 | "ofType" : null 1431 | }, 1432 | "defaultValue" : null 1433 | } ], 1434 | "interfaces" : null, 1435 | "enumValues" : null, 1436 | "possibleTypes" : null 1437 | }, { 1438 | "kind" : "INPUT_OBJECT", 1439 | "name" : "ModelRoomConditionInput", 1440 | "description" : null, 1441 | "fields" : null, 1442 | "inputFields" : [ { 1443 | "name" : "name", 1444 | "description" : null, 1445 | "type" : { 1446 | "kind" : "INPUT_OBJECT", 1447 | "name" : "ModelStringInput", 1448 | "ofType" : null 1449 | }, 1450 | "defaultValue" : null 1451 | }, { 1452 | "name" : "createdAt", 1453 | "description" : null, 1454 | "type" : { 1455 | "kind" : "INPUT_OBJECT", 1456 | "name" : "ModelStringInput", 1457 | "ofType" : null 1458 | }, 1459 | "defaultValue" : null 1460 | }, { 1461 | "name" : "updatedAt", 1462 | "description" : null, 1463 | "type" : { 1464 | "kind" : "INPUT_OBJECT", 1465 | "name" : "ModelStringInput", 1466 | "ofType" : null 1467 | }, 1468 | "defaultValue" : null 1469 | }, { 1470 | "name" : "and", 1471 | "description" : null, 1472 | "type" : { 1473 | "kind" : "LIST", 1474 | "name" : null, 1475 | "ofType" : { 1476 | "kind" : "INPUT_OBJECT", 1477 | "name" : "ModelRoomConditionInput", 1478 | "ofType" : null 1479 | } 1480 | }, 1481 | "defaultValue" : null 1482 | }, { 1483 | "name" : "or", 1484 | "description" : null, 1485 | "type" : { 1486 | "kind" : "LIST", 1487 | "name" : null, 1488 | "ofType" : { 1489 | "kind" : "INPUT_OBJECT", 1490 | "name" : "ModelRoomConditionInput", 1491 | "ofType" : null 1492 | } 1493 | }, 1494 | "defaultValue" : null 1495 | }, { 1496 | "name" : "not", 1497 | "description" : null, 1498 | "type" : { 1499 | "kind" : "INPUT_OBJECT", 1500 | "name" : "ModelRoomConditionInput", 1501 | "ofType" : null 1502 | }, 1503 | "defaultValue" : null 1504 | } ], 1505 | "interfaces" : null, 1506 | "enumValues" : null, 1507 | "possibleTypes" : null 1508 | }, { 1509 | "kind" : "INPUT_OBJECT", 1510 | "name" : "UpdateRoomInput", 1511 | "description" : null, 1512 | "fields" : null, 1513 | "inputFields" : [ { 1514 | "name" : "id", 1515 | "description" : null, 1516 | "type" : { 1517 | "kind" : "NON_NULL", 1518 | "name" : null, 1519 | "ofType" : { 1520 | "kind" : "SCALAR", 1521 | "name" : "ID", 1522 | "ofType" : null 1523 | } 1524 | }, 1525 | "defaultValue" : null 1526 | }, { 1527 | "name" : "name", 1528 | "description" : null, 1529 | "type" : { 1530 | "kind" : "SCALAR", 1531 | "name" : "String", 1532 | "ofType" : null 1533 | }, 1534 | "defaultValue" : null 1535 | }, { 1536 | "name" : "createdAt", 1537 | "description" : null, 1538 | "type" : { 1539 | "kind" : "SCALAR", 1540 | "name" : "AWSDateTime", 1541 | "ofType" : null 1542 | }, 1543 | "defaultValue" : null 1544 | }, { 1545 | "name" : "updatedAt", 1546 | "description" : null, 1547 | "type" : { 1548 | "kind" : "SCALAR", 1549 | "name" : "AWSDateTime", 1550 | "ofType" : null 1551 | }, 1552 | "defaultValue" : null 1553 | } ], 1554 | "interfaces" : null, 1555 | "enumValues" : null, 1556 | "possibleTypes" : null 1557 | }, { 1558 | "kind" : "INPUT_OBJECT", 1559 | "name" : "DeleteRoomInput", 1560 | "description" : null, 1561 | "fields" : null, 1562 | "inputFields" : [ { 1563 | "name" : "id", 1564 | "description" : null, 1565 | "type" : { 1566 | "kind" : "SCALAR", 1567 | "name" : "ID", 1568 | "ofType" : null 1569 | }, 1570 | "defaultValue" : null 1571 | } ], 1572 | "interfaces" : null, 1573 | "enumValues" : null, 1574 | "possibleTypes" : null 1575 | }, { 1576 | "kind" : "INPUT_OBJECT", 1577 | "name" : "CreateMessageInput", 1578 | "description" : null, 1579 | "fields" : null, 1580 | "inputFields" : [ { 1581 | "name" : "id", 1582 | "description" : null, 1583 | "type" : { 1584 | "kind" : "SCALAR", 1585 | "name" : "ID", 1586 | "ofType" : null 1587 | }, 1588 | "defaultValue" : null 1589 | }, { 1590 | "name" : "content", 1591 | "description" : null, 1592 | "type" : { 1593 | "kind" : "NON_NULL", 1594 | "name" : null, 1595 | "ofType" : { 1596 | "kind" : "SCALAR", 1597 | "name" : "String", 1598 | "ofType" : null 1599 | } 1600 | }, 1601 | "defaultValue" : null 1602 | }, { 1603 | "name" : "owner", 1604 | "description" : null, 1605 | "type" : { 1606 | "kind" : "SCALAR", 1607 | "name" : "String", 1608 | "ofType" : null 1609 | }, 1610 | "defaultValue" : null 1611 | }, { 1612 | "name" : "createdAt", 1613 | "description" : null, 1614 | "type" : { 1615 | "kind" : "SCALAR", 1616 | "name" : "String", 1617 | "ofType" : null 1618 | }, 1619 | "defaultValue" : null 1620 | }, { 1621 | "name" : "roomId", 1622 | "description" : null, 1623 | "type" : { 1624 | "kind" : "SCALAR", 1625 | "name" : "ID", 1626 | "ofType" : null 1627 | }, 1628 | "defaultValue" : null 1629 | } ], 1630 | "interfaces" : null, 1631 | "enumValues" : null, 1632 | "possibleTypes" : null 1633 | }, { 1634 | "kind" : "INPUT_OBJECT", 1635 | "name" : "ModelMessageConditionInput", 1636 | "description" : null, 1637 | "fields" : null, 1638 | "inputFields" : [ { 1639 | "name" : "content", 1640 | "description" : null, 1641 | "type" : { 1642 | "kind" : "INPUT_OBJECT", 1643 | "name" : "ModelStringInput", 1644 | "ofType" : null 1645 | }, 1646 | "defaultValue" : null 1647 | }, { 1648 | "name" : "createdAt", 1649 | "description" : null, 1650 | "type" : { 1651 | "kind" : "INPUT_OBJECT", 1652 | "name" : "ModelStringInput", 1653 | "ofType" : null 1654 | }, 1655 | "defaultValue" : null 1656 | }, { 1657 | "name" : "roomId", 1658 | "description" : null, 1659 | "type" : { 1660 | "kind" : "INPUT_OBJECT", 1661 | "name" : "ModelIDInput", 1662 | "ofType" : null 1663 | }, 1664 | "defaultValue" : null 1665 | }, { 1666 | "name" : "and", 1667 | "description" : null, 1668 | "type" : { 1669 | "kind" : "LIST", 1670 | "name" : null, 1671 | "ofType" : { 1672 | "kind" : "INPUT_OBJECT", 1673 | "name" : "ModelMessageConditionInput", 1674 | "ofType" : null 1675 | } 1676 | }, 1677 | "defaultValue" : null 1678 | }, { 1679 | "name" : "or", 1680 | "description" : null, 1681 | "type" : { 1682 | "kind" : "LIST", 1683 | "name" : null, 1684 | "ofType" : { 1685 | "kind" : "INPUT_OBJECT", 1686 | "name" : "ModelMessageConditionInput", 1687 | "ofType" : null 1688 | } 1689 | }, 1690 | "defaultValue" : null 1691 | }, { 1692 | "name" : "not", 1693 | "description" : null, 1694 | "type" : { 1695 | "kind" : "INPUT_OBJECT", 1696 | "name" : "ModelMessageConditionInput", 1697 | "ofType" : null 1698 | }, 1699 | "defaultValue" : null 1700 | } ], 1701 | "interfaces" : null, 1702 | "enumValues" : null, 1703 | "possibleTypes" : null 1704 | }, { 1705 | "kind" : "INPUT_OBJECT", 1706 | "name" : "UpdateMessageInput", 1707 | "description" : null, 1708 | "fields" : null, 1709 | "inputFields" : [ { 1710 | "name" : "id", 1711 | "description" : null, 1712 | "type" : { 1713 | "kind" : "NON_NULL", 1714 | "name" : null, 1715 | "ofType" : { 1716 | "kind" : "SCALAR", 1717 | "name" : "ID", 1718 | "ofType" : null 1719 | } 1720 | }, 1721 | "defaultValue" : null 1722 | }, { 1723 | "name" : "content", 1724 | "description" : null, 1725 | "type" : { 1726 | "kind" : "SCALAR", 1727 | "name" : "String", 1728 | "ofType" : null 1729 | }, 1730 | "defaultValue" : null 1731 | }, { 1732 | "name" : "owner", 1733 | "description" : null, 1734 | "type" : { 1735 | "kind" : "SCALAR", 1736 | "name" : "String", 1737 | "ofType" : null 1738 | }, 1739 | "defaultValue" : null 1740 | }, { 1741 | "name" : "createdAt", 1742 | "description" : null, 1743 | "type" : { 1744 | "kind" : "SCALAR", 1745 | "name" : "String", 1746 | "ofType" : null 1747 | }, 1748 | "defaultValue" : null 1749 | }, { 1750 | "name" : "roomId", 1751 | "description" : null, 1752 | "type" : { 1753 | "kind" : "SCALAR", 1754 | "name" : "ID", 1755 | "ofType" : null 1756 | }, 1757 | "defaultValue" : null 1758 | } ], 1759 | "interfaces" : null, 1760 | "enumValues" : null, 1761 | "possibleTypes" : null 1762 | }, { 1763 | "kind" : "INPUT_OBJECT", 1764 | "name" : "DeleteMessageInput", 1765 | "description" : null, 1766 | "fields" : null, 1767 | "inputFields" : [ { 1768 | "name" : "id", 1769 | "description" : null, 1770 | "type" : { 1771 | "kind" : "SCALAR", 1772 | "name" : "ID", 1773 | "ofType" : null 1774 | }, 1775 | "defaultValue" : null 1776 | } ], 1777 | "interfaces" : null, 1778 | "enumValues" : null, 1779 | "possibleTypes" : null 1780 | }, { 1781 | "kind" : "OBJECT", 1782 | "name" : "Subscription", 1783 | "description" : null, 1784 | "fields" : [ { 1785 | "name" : "onCreateMessageByRoomId", 1786 | "description" : null, 1787 | "args" : [ { 1788 | "name" : "roomId", 1789 | "description" : null, 1790 | "type" : { 1791 | "kind" : "SCALAR", 1792 | "name" : "ID", 1793 | "ofType" : null 1794 | }, 1795 | "defaultValue" : null 1796 | } ], 1797 | "type" : { 1798 | "kind" : "OBJECT", 1799 | "name" : "Message", 1800 | "ofType" : null 1801 | }, 1802 | "isDeprecated" : false, 1803 | "deprecationReason" : null 1804 | }, { 1805 | "name" : "onCreateRoom", 1806 | "description" : null, 1807 | "args" : [ ], 1808 | "type" : { 1809 | "kind" : "OBJECT", 1810 | "name" : "Room", 1811 | "ofType" : null 1812 | }, 1813 | "isDeprecated" : false, 1814 | "deprecationReason" : null 1815 | }, { 1816 | "name" : "onUpdateRoom", 1817 | "description" : null, 1818 | "args" : [ ], 1819 | "type" : { 1820 | "kind" : "OBJECT", 1821 | "name" : "Room", 1822 | "ofType" : null 1823 | }, 1824 | "isDeprecated" : false, 1825 | "deprecationReason" : null 1826 | }, { 1827 | "name" : "onDeleteRoom", 1828 | "description" : null, 1829 | "args" : [ ], 1830 | "type" : { 1831 | "kind" : "OBJECT", 1832 | "name" : "Room", 1833 | "ofType" : null 1834 | }, 1835 | "isDeprecated" : false, 1836 | "deprecationReason" : null 1837 | }, { 1838 | "name" : "onCreateMessage", 1839 | "description" : null, 1840 | "args" : [ ], 1841 | "type" : { 1842 | "kind" : "OBJECT", 1843 | "name" : "Message", 1844 | "ofType" : null 1845 | }, 1846 | "isDeprecated" : false, 1847 | "deprecationReason" : null 1848 | }, { 1849 | "name" : "onUpdateMessage", 1850 | "description" : null, 1851 | "args" : [ ], 1852 | "type" : { 1853 | "kind" : "OBJECT", 1854 | "name" : "Message", 1855 | "ofType" : null 1856 | }, 1857 | "isDeprecated" : false, 1858 | "deprecationReason" : null 1859 | }, { 1860 | "name" : "onDeleteMessage", 1861 | "description" : null, 1862 | "args" : [ ], 1863 | "type" : { 1864 | "kind" : "OBJECT", 1865 | "name" : "Message", 1866 | "ofType" : null 1867 | }, 1868 | "isDeprecated" : false, 1869 | "deprecationReason" : null 1870 | } ], 1871 | "inputFields" : null, 1872 | "interfaces" : [ ], 1873 | "enumValues" : null, 1874 | "possibleTypes" : null 1875 | }, { 1876 | "kind" : "INPUT_OBJECT", 1877 | "name" : "ModelIntInput", 1878 | "description" : null, 1879 | "fields" : null, 1880 | "inputFields" : [ { 1881 | "name" : "ne", 1882 | "description" : null, 1883 | "type" : { 1884 | "kind" : "SCALAR", 1885 | "name" : "Int", 1886 | "ofType" : null 1887 | }, 1888 | "defaultValue" : null 1889 | }, { 1890 | "name" : "eq", 1891 | "description" : null, 1892 | "type" : { 1893 | "kind" : "SCALAR", 1894 | "name" : "Int", 1895 | "ofType" : null 1896 | }, 1897 | "defaultValue" : null 1898 | }, { 1899 | "name" : "le", 1900 | "description" : null, 1901 | "type" : { 1902 | "kind" : "SCALAR", 1903 | "name" : "Int", 1904 | "ofType" : null 1905 | }, 1906 | "defaultValue" : null 1907 | }, { 1908 | "name" : "lt", 1909 | "description" : null, 1910 | "type" : { 1911 | "kind" : "SCALAR", 1912 | "name" : "Int", 1913 | "ofType" : null 1914 | }, 1915 | "defaultValue" : null 1916 | }, { 1917 | "name" : "ge", 1918 | "description" : null, 1919 | "type" : { 1920 | "kind" : "SCALAR", 1921 | "name" : "Int", 1922 | "ofType" : null 1923 | }, 1924 | "defaultValue" : null 1925 | }, { 1926 | "name" : "gt", 1927 | "description" : null, 1928 | "type" : { 1929 | "kind" : "SCALAR", 1930 | "name" : "Int", 1931 | "ofType" : null 1932 | }, 1933 | "defaultValue" : null 1934 | }, { 1935 | "name" : "between", 1936 | "description" : null, 1937 | "type" : { 1938 | "kind" : "LIST", 1939 | "name" : null, 1940 | "ofType" : { 1941 | "kind" : "SCALAR", 1942 | "name" : "Int", 1943 | "ofType" : null 1944 | } 1945 | }, 1946 | "defaultValue" : null 1947 | }, { 1948 | "name" : "attributeExists", 1949 | "description" : null, 1950 | "type" : { 1951 | "kind" : "SCALAR", 1952 | "name" : "Boolean", 1953 | "ofType" : null 1954 | }, 1955 | "defaultValue" : null 1956 | }, { 1957 | "name" : "attributeType", 1958 | "description" : null, 1959 | "type" : { 1960 | "kind" : "ENUM", 1961 | "name" : "ModelAttributeTypes", 1962 | "ofType" : null 1963 | }, 1964 | "defaultValue" : null 1965 | } ], 1966 | "interfaces" : null, 1967 | "enumValues" : null, 1968 | "possibleTypes" : null 1969 | }, { 1970 | "kind" : "INPUT_OBJECT", 1971 | "name" : "ModelFloatInput", 1972 | "description" : null, 1973 | "fields" : null, 1974 | "inputFields" : [ { 1975 | "name" : "ne", 1976 | "description" : null, 1977 | "type" : { 1978 | "kind" : "SCALAR", 1979 | "name" : "Float", 1980 | "ofType" : null 1981 | }, 1982 | "defaultValue" : null 1983 | }, { 1984 | "name" : "eq", 1985 | "description" : null, 1986 | "type" : { 1987 | "kind" : "SCALAR", 1988 | "name" : "Float", 1989 | "ofType" : null 1990 | }, 1991 | "defaultValue" : null 1992 | }, { 1993 | "name" : "le", 1994 | "description" : null, 1995 | "type" : { 1996 | "kind" : "SCALAR", 1997 | "name" : "Float", 1998 | "ofType" : null 1999 | }, 2000 | "defaultValue" : null 2001 | }, { 2002 | "name" : "lt", 2003 | "description" : null, 2004 | "type" : { 2005 | "kind" : "SCALAR", 2006 | "name" : "Float", 2007 | "ofType" : null 2008 | }, 2009 | "defaultValue" : null 2010 | }, { 2011 | "name" : "ge", 2012 | "description" : null, 2013 | "type" : { 2014 | "kind" : "SCALAR", 2015 | "name" : "Float", 2016 | "ofType" : null 2017 | }, 2018 | "defaultValue" : null 2019 | }, { 2020 | "name" : "gt", 2021 | "description" : null, 2022 | "type" : { 2023 | "kind" : "SCALAR", 2024 | "name" : "Float", 2025 | "ofType" : null 2026 | }, 2027 | "defaultValue" : null 2028 | }, { 2029 | "name" : "between", 2030 | "description" : null, 2031 | "type" : { 2032 | "kind" : "LIST", 2033 | "name" : null, 2034 | "ofType" : { 2035 | "kind" : "SCALAR", 2036 | "name" : "Float", 2037 | "ofType" : null 2038 | } 2039 | }, 2040 | "defaultValue" : null 2041 | }, { 2042 | "name" : "attributeExists", 2043 | "description" : null, 2044 | "type" : { 2045 | "kind" : "SCALAR", 2046 | "name" : "Boolean", 2047 | "ofType" : null 2048 | }, 2049 | "defaultValue" : null 2050 | }, { 2051 | "name" : "attributeType", 2052 | "description" : null, 2053 | "type" : { 2054 | "kind" : "ENUM", 2055 | "name" : "ModelAttributeTypes", 2056 | "ofType" : null 2057 | }, 2058 | "defaultValue" : null 2059 | } ], 2060 | "interfaces" : null, 2061 | "enumValues" : null, 2062 | "possibleTypes" : null 2063 | }, { 2064 | "kind" : "SCALAR", 2065 | "name" : "Float", 2066 | "description" : "Built-in Float", 2067 | "fields" : null, 2068 | "inputFields" : null, 2069 | "interfaces" : null, 2070 | "enumValues" : null, 2071 | "possibleTypes" : null 2072 | }, { 2073 | "kind" : "INPUT_OBJECT", 2074 | "name" : "ModelBooleanInput", 2075 | "description" : null, 2076 | "fields" : null, 2077 | "inputFields" : [ { 2078 | "name" : "ne", 2079 | "description" : null, 2080 | "type" : { 2081 | "kind" : "SCALAR", 2082 | "name" : "Boolean", 2083 | "ofType" : null 2084 | }, 2085 | "defaultValue" : null 2086 | }, { 2087 | "name" : "eq", 2088 | "description" : null, 2089 | "type" : { 2090 | "kind" : "SCALAR", 2091 | "name" : "Boolean", 2092 | "ofType" : null 2093 | }, 2094 | "defaultValue" : null 2095 | }, { 2096 | "name" : "attributeExists", 2097 | "description" : null, 2098 | "type" : { 2099 | "kind" : "SCALAR", 2100 | "name" : "Boolean", 2101 | "ofType" : null 2102 | }, 2103 | "defaultValue" : null 2104 | }, { 2105 | "name" : "attributeType", 2106 | "description" : null, 2107 | "type" : { 2108 | "kind" : "ENUM", 2109 | "name" : "ModelAttributeTypes", 2110 | "ofType" : null 2111 | }, 2112 | "defaultValue" : null 2113 | } ], 2114 | "interfaces" : null, 2115 | "enumValues" : null, 2116 | "possibleTypes" : null 2117 | }, { 2118 | "kind" : "OBJECT", 2119 | "name" : "__Schema", 2120 | "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.", 2121 | "fields" : [ { 2122 | "name" : "types", 2123 | "description" : "A list of all types supported by this server.", 2124 | "args" : [ ], 2125 | "type" : { 2126 | "kind" : "NON_NULL", 2127 | "name" : null, 2128 | "ofType" : { 2129 | "kind" : "LIST", 2130 | "name" : null, 2131 | "ofType" : { 2132 | "kind" : "NON_NULL", 2133 | "name" : null, 2134 | "ofType" : { 2135 | "kind" : "OBJECT", 2136 | "name" : "__Type", 2137 | "ofType" : null 2138 | } 2139 | } 2140 | } 2141 | }, 2142 | "isDeprecated" : false, 2143 | "deprecationReason" : null 2144 | }, { 2145 | "name" : "queryType", 2146 | "description" : "The type that query operations will be rooted at.", 2147 | "args" : [ ], 2148 | "type" : { 2149 | "kind" : "NON_NULL", 2150 | "name" : null, 2151 | "ofType" : { 2152 | "kind" : "OBJECT", 2153 | "name" : "__Type", 2154 | "ofType" : null 2155 | } 2156 | }, 2157 | "isDeprecated" : false, 2158 | "deprecationReason" : null 2159 | }, { 2160 | "name" : "mutationType", 2161 | "description" : "If this server supports mutation, the type that mutation operations will be rooted at.", 2162 | "args" : [ ], 2163 | "type" : { 2164 | "kind" : "OBJECT", 2165 | "name" : "__Type", 2166 | "ofType" : null 2167 | }, 2168 | "isDeprecated" : false, 2169 | "deprecationReason" : null 2170 | }, { 2171 | "name" : "directives", 2172 | "description" : "'A list of all directives supported by this server.", 2173 | "args" : [ ], 2174 | "type" : { 2175 | "kind" : "NON_NULL", 2176 | "name" : null, 2177 | "ofType" : { 2178 | "kind" : "LIST", 2179 | "name" : null, 2180 | "ofType" : { 2181 | "kind" : "NON_NULL", 2182 | "name" : null, 2183 | "ofType" : { 2184 | "kind" : "OBJECT", 2185 | "name" : "__Directive", 2186 | "ofType" : null 2187 | } 2188 | } 2189 | } 2190 | }, 2191 | "isDeprecated" : false, 2192 | "deprecationReason" : null 2193 | }, { 2194 | "name" : "subscriptionType", 2195 | "description" : "'If this server support subscription, the type that subscription operations will be rooted at.", 2196 | "args" : [ ], 2197 | "type" : { 2198 | "kind" : "OBJECT", 2199 | "name" : "__Type", 2200 | "ofType" : null 2201 | }, 2202 | "isDeprecated" : false, 2203 | "deprecationReason" : null 2204 | } ], 2205 | "inputFields" : null, 2206 | "interfaces" : [ ], 2207 | "enumValues" : null, 2208 | "possibleTypes" : null 2209 | }, { 2210 | "kind" : "OBJECT", 2211 | "name" : "__Type", 2212 | "description" : null, 2213 | "fields" : [ { 2214 | "name" : "kind", 2215 | "description" : null, 2216 | "args" : [ ], 2217 | "type" : { 2218 | "kind" : "NON_NULL", 2219 | "name" : null, 2220 | "ofType" : { 2221 | "kind" : "ENUM", 2222 | "name" : "__TypeKind", 2223 | "ofType" : null 2224 | } 2225 | }, 2226 | "isDeprecated" : false, 2227 | "deprecationReason" : null 2228 | }, { 2229 | "name" : "name", 2230 | "description" : null, 2231 | "args" : [ ], 2232 | "type" : { 2233 | "kind" : "SCALAR", 2234 | "name" : "String", 2235 | "ofType" : null 2236 | }, 2237 | "isDeprecated" : false, 2238 | "deprecationReason" : null 2239 | }, { 2240 | "name" : "description", 2241 | "description" : null, 2242 | "args" : [ ], 2243 | "type" : { 2244 | "kind" : "SCALAR", 2245 | "name" : "String", 2246 | "ofType" : null 2247 | }, 2248 | "isDeprecated" : false, 2249 | "deprecationReason" : null 2250 | }, { 2251 | "name" : "fields", 2252 | "description" : null, 2253 | "args" : [ { 2254 | "name" : "includeDeprecated", 2255 | "description" : null, 2256 | "type" : { 2257 | "kind" : "SCALAR", 2258 | "name" : "Boolean", 2259 | "ofType" : null 2260 | }, 2261 | "defaultValue" : "false" 2262 | } ], 2263 | "type" : { 2264 | "kind" : "LIST", 2265 | "name" : null, 2266 | "ofType" : { 2267 | "kind" : "NON_NULL", 2268 | "name" : null, 2269 | "ofType" : { 2270 | "kind" : "OBJECT", 2271 | "name" : "__Field", 2272 | "ofType" : null 2273 | } 2274 | } 2275 | }, 2276 | "isDeprecated" : false, 2277 | "deprecationReason" : null 2278 | }, { 2279 | "name" : "interfaces", 2280 | "description" : null, 2281 | "args" : [ ], 2282 | "type" : { 2283 | "kind" : "LIST", 2284 | "name" : null, 2285 | "ofType" : { 2286 | "kind" : "NON_NULL", 2287 | "name" : null, 2288 | "ofType" : { 2289 | "kind" : "OBJECT", 2290 | "name" : "__Type", 2291 | "ofType" : null 2292 | } 2293 | } 2294 | }, 2295 | "isDeprecated" : false, 2296 | "deprecationReason" : null 2297 | }, { 2298 | "name" : "possibleTypes", 2299 | "description" : null, 2300 | "args" : [ ], 2301 | "type" : { 2302 | "kind" : "LIST", 2303 | "name" : null, 2304 | "ofType" : { 2305 | "kind" : "NON_NULL", 2306 | "name" : null, 2307 | "ofType" : { 2308 | "kind" : "OBJECT", 2309 | "name" : "__Type", 2310 | "ofType" : null 2311 | } 2312 | } 2313 | }, 2314 | "isDeprecated" : false, 2315 | "deprecationReason" : null 2316 | }, { 2317 | "name" : "enumValues", 2318 | "description" : null, 2319 | "args" : [ { 2320 | "name" : "includeDeprecated", 2321 | "description" : null, 2322 | "type" : { 2323 | "kind" : "SCALAR", 2324 | "name" : "Boolean", 2325 | "ofType" : null 2326 | }, 2327 | "defaultValue" : "false" 2328 | } ], 2329 | "type" : { 2330 | "kind" : "LIST", 2331 | "name" : null, 2332 | "ofType" : { 2333 | "kind" : "NON_NULL", 2334 | "name" : null, 2335 | "ofType" : { 2336 | "kind" : "OBJECT", 2337 | "name" : "__EnumValue", 2338 | "ofType" : null 2339 | } 2340 | } 2341 | }, 2342 | "isDeprecated" : false, 2343 | "deprecationReason" : null 2344 | }, { 2345 | "name" : "inputFields", 2346 | "description" : null, 2347 | "args" : [ ], 2348 | "type" : { 2349 | "kind" : "LIST", 2350 | "name" : null, 2351 | "ofType" : { 2352 | "kind" : "NON_NULL", 2353 | "name" : null, 2354 | "ofType" : { 2355 | "kind" : "OBJECT", 2356 | "name" : "__InputValue", 2357 | "ofType" : null 2358 | } 2359 | } 2360 | }, 2361 | "isDeprecated" : false, 2362 | "deprecationReason" : null 2363 | }, { 2364 | "name" : "ofType", 2365 | "description" : null, 2366 | "args" : [ ], 2367 | "type" : { 2368 | "kind" : "OBJECT", 2369 | "name" : "__Type", 2370 | "ofType" : null 2371 | }, 2372 | "isDeprecated" : false, 2373 | "deprecationReason" : null 2374 | } ], 2375 | "inputFields" : null, 2376 | "interfaces" : [ ], 2377 | "enumValues" : null, 2378 | "possibleTypes" : null 2379 | }, { 2380 | "kind" : "ENUM", 2381 | "name" : "__TypeKind", 2382 | "description" : "An enum describing what kind of type a given __Type is", 2383 | "fields" : null, 2384 | "inputFields" : null, 2385 | "interfaces" : null, 2386 | "enumValues" : [ { 2387 | "name" : "SCALAR", 2388 | "description" : "Indicates this type is a scalar.", 2389 | "isDeprecated" : false, 2390 | "deprecationReason" : null 2391 | }, { 2392 | "name" : "OBJECT", 2393 | "description" : "Indicates this type is an object. `fields` and `interfaces` are valid fields.", 2394 | "isDeprecated" : false, 2395 | "deprecationReason" : null 2396 | }, { 2397 | "name" : "INTERFACE", 2398 | "description" : "Indicates this type is an interface. `fields` and `possibleTypes` are valid fields.", 2399 | "isDeprecated" : false, 2400 | "deprecationReason" : null 2401 | }, { 2402 | "name" : "UNION", 2403 | "description" : "Indicates this type is a union. `possibleTypes` is a valid field.", 2404 | "isDeprecated" : false, 2405 | "deprecationReason" : null 2406 | }, { 2407 | "name" : "ENUM", 2408 | "description" : "Indicates this type is an enum. `enumValues` is a valid field.", 2409 | "isDeprecated" : false, 2410 | "deprecationReason" : null 2411 | }, { 2412 | "name" : "INPUT_OBJECT", 2413 | "description" : "Indicates this type is an input object. `inputFields` is a valid field.", 2414 | "isDeprecated" : false, 2415 | "deprecationReason" : null 2416 | }, { 2417 | "name" : "LIST", 2418 | "description" : "Indicates this type is a list. `ofType` is a valid field.", 2419 | "isDeprecated" : false, 2420 | "deprecationReason" : null 2421 | }, { 2422 | "name" : "NON_NULL", 2423 | "description" : "Indicates this type is a non-null. `ofType` is a valid field.", 2424 | "isDeprecated" : false, 2425 | "deprecationReason" : null 2426 | } ], 2427 | "possibleTypes" : null 2428 | }, { 2429 | "kind" : "OBJECT", 2430 | "name" : "__Field", 2431 | "description" : null, 2432 | "fields" : [ { 2433 | "name" : "name", 2434 | "description" : null, 2435 | "args" : [ ], 2436 | "type" : { 2437 | "kind" : "NON_NULL", 2438 | "name" : null, 2439 | "ofType" : { 2440 | "kind" : "SCALAR", 2441 | "name" : "String", 2442 | "ofType" : null 2443 | } 2444 | }, 2445 | "isDeprecated" : false, 2446 | "deprecationReason" : null 2447 | }, { 2448 | "name" : "description", 2449 | "description" : null, 2450 | "args" : [ ], 2451 | "type" : { 2452 | "kind" : "SCALAR", 2453 | "name" : "String", 2454 | "ofType" : null 2455 | }, 2456 | "isDeprecated" : false, 2457 | "deprecationReason" : null 2458 | }, { 2459 | "name" : "args", 2460 | "description" : null, 2461 | "args" : [ ], 2462 | "type" : { 2463 | "kind" : "NON_NULL", 2464 | "name" : null, 2465 | "ofType" : { 2466 | "kind" : "LIST", 2467 | "name" : null, 2468 | "ofType" : { 2469 | "kind" : "NON_NULL", 2470 | "name" : null, 2471 | "ofType" : { 2472 | "kind" : "OBJECT", 2473 | "name" : "__InputValue", 2474 | "ofType" : null 2475 | } 2476 | } 2477 | } 2478 | }, 2479 | "isDeprecated" : false, 2480 | "deprecationReason" : null 2481 | }, { 2482 | "name" : "type", 2483 | "description" : null, 2484 | "args" : [ ], 2485 | "type" : { 2486 | "kind" : "NON_NULL", 2487 | "name" : null, 2488 | "ofType" : { 2489 | "kind" : "OBJECT", 2490 | "name" : "__Type", 2491 | "ofType" : null 2492 | } 2493 | }, 2494 | "isDeprecated" : false, 2495 | "deprecationReason" : null 2496 | }, { 2497 | "name" : "isDeprecated", 2498 | "description" : null, 2499 | "args" : [ ], 2500 | "type" : { 2501 | "kind" : "NON_NULL", 2502 | "name" : null, 2503 | "ofType" : { 2504 | "kind" : "SCALAR", 2505 | "name" : "Boolean", 2506 | "ofType" : null 2507 | } 2508 | }, 2509 | "isDeprecated" : false, 2510 | "deprecationReason" : null 2511 | }, { 2512 | "name" : "deprecationReason", 2513 | "description" : null, 2514 | "args" : [ ], 2515 | "type" : { 2516 | "kind" : "SCALAR", 2517 | "name" : "String", 2518 | "ofType" : null 2519 | }, 2520 | "isDeprecated" : false, 2521 | "deprecationReason" : null 2522 | } ], 2523 | "inputFields" : null, 2524 | "interfaces" : [ ], 2525 | "enumValues" : null, 2526 | "possibleTypes" : null 2527 | }, { 2528 | "kind" : "OBJECT", 2529 | "name" : "__InputValue", 2530 | "description" : null, 2531 | "fields" : [ { 2532 | "name" : "name", 2533 | "description" : null, 2534 | "args" : [ ], 2535 | "type" : { 2536 | "kind" : "NON_NULL", 2537 | "name" : null, 2538 | "ofType" : { 2539 | "kind" : "SCALAR", 2540 | "name" : "String", 2541 | "ofType" : null 2542 | } 2543 | }, 2544 | "isDeprecated" : false, 2545 | "deprecationReason" : null 2546 | }, { 2547 | "name" : "description", 2548 | "description" : null, 2549 | "args" : [ ], 2550 | "type" : { 2551 | "kind" : "SCALAR", 2552 | "name" : "String", 2553 | "ofType" : null 2554 | }, 2555 | "isDeprecated" : false, 2556 | "deprecationReason" : null 2557 | }, { 2558 | "name" : "type", 2559 | "description" : null, 2560 | "args" : [ ], 2561 | "type" : { 2562 | "kind" : "NON_NULL", 2563 | "name" : null, 2564 | "ofType" : { 2565 | "kind" : "OBJECT", 2566 | "name" : "__Type", 2567 | "ofType" : null 2568 | } 2569 | }, 2570 | "isDeprecated" : false, 2571 | "deprecationReason" : null 2572 | }, { 2573 | "name" : "defaultValue", 2574 | "description" : null, 2575 | "args" : [ ], 2576 | "type" : { 2577 | "kind" : "SCALAR", 2578 | "name" : "String", 2579 | "ofType" : null 2580 | }, 2581 | "isDeprecated" : false, 2582 | "deprecationReason" : null 2583 | } ], 2584 | "inputFields" : null, 2585 | "interfaces" : [ ], 2586 | "enumValues" : null, 2587 | "possibleTypes" : null 2588 | }, { 2589 | "kind" : "OBJECT", 2590 | "name" : "__EnumValue", 2591 | "description" : null, 2592 | "fields" : [ { 2593 | "name" : "name", 2594 | "description" : null, 2595 | "args" : [ ], 2596 | "type" : { 2597 | "kind" : "NON_NULL", 2598 | "name" : null, 2599 | "ofType" : { 2600 | "kind" : "SCALAR", 2601 | "name" : "String", 2602 | "ofType" : null 2603 | } 2604 | }, 2605 | "isDeprecated" : false, 2606 | "deprecationReason" : null 2607 | }, { 2608 | "name" : "description", 2609 | "description" : null, 2610 | "args" : [ ], 2611 | "type" : { 2612 | "kind" : "SCALAR", 2613 | "name" : "String", 2614 | "ofType" : null 2615 | }, 2616 | "isDeprecated" : false, 2617 | "deprecationReason" : null 2618 | }, { 2619 | "name" : "isDeprecated", 2620 | "description" : null, 2621 | "args" : [ ], 2622 | "type" : { 2623 | "kind" : "NON_NULL", 2624 | "name" : null, 2625 | "ofType" : { 2626 | "kind" : "SCALAR", 2627 | "name" : "Boolean", 2628 | "ofType" : null 2629 | } 2630 | }, 2631 | "isDeprecated" : false, 2632 | "deprecationReason" : null 2633 | }, { 2634 | "name" : "deprecationReason", 2635 | "description" : null, 2636 | "args" : [ ], 2637 | "type" : { 2638 | "kind" : "SCALAR", 2639 | "name" : "String", 2640 | "ofType" : null 2641 | }, 2642 | "isDeprecated" : false, 2643 | "deprecationReason" : null 2644 | } ], 2645 | "inputFields" : null, 2646 | "interfaces" : [ ], 2647 | "enumValues" : null, 2648 | "possibleTypes" : null 2649 | }, { 2650 | "kind" : "OBJECT", 2651 | "name" : "__Directive", 2652 | "description" : null, 2653 | "fields" : [ { 2654 | "name" : "name", 2655 | "description" : null, 2656 | "args" : [ ], 2657 | "type" : { 2658 | "kind" : "SCALAR", 2659 | "name" : "String", 2660 | "ofType" : null 2661 | }, 2662 | "isDeprecated" : false, 2663 | "deprecationReason" : null 2664 | }, { 2665 | "name" : "description", 2666 | "description" : null, 2667 | "args" : [ ], 2668 | "type" : { 2669 | "kind" : "SCALAR", 2670 | "name" : "String", 2671 | "ofType" : null 2672 | }, 2673 | "isDeprecated" : false, 2674 | "deprecationReason" : null 2675 | }, { 2676 | "name" : "locations", 2677 | "description" : null, 2678 | "args" : [ ], 2679 | "type" : { 2680 | "kind" : "LIST", 2681 | "name" : null, 2682 | "ofType" : { 2683 | "kind" : "NON_NULL", 2684 | "name" : null, 2685 | "ofType" : { 2686 | "kind" : "ENUM", 2687 | "name" : "__DirectiveLocation", 2688 | "ofType" : null 2689 | } 2690 | } 2691 | }, 2692 | "isDeprecated" : false, 2693 | "deprecationReason" : null 2694 | }, { 2695 | "name" : "args", 2696 | "description" : null, 2697 | "args" : [ ], 2698 | "type" : { 2699 | "kind" : "NON_NULL", 2700 | "name" : null, 2701 | "ofType" : { 2702 | "kind" : "LIST", 2703 | "name" : null, 2704 | "ofType" : { 2705 | "kind" : "NON_NULL", 2706 | "name" : null, 2707 | "ofType" : { 2708 | "kind" : "OBJECT", 2709 | "name" : "__InputValue", 2710 | "ofType" : null 2711 | } 2712 | } 2713 | } 2714 | }, 2715 | "isDeprecated" : false, 2716 | "deprecationReason" : null 2717 | }, { 2718 | "name" : "onOperation", 2719 | "description" : null, 2720 | "args" : [ ], 2721 | "type" : { 2722 | "kind" : "SCALAR", 2723 | "name" : "Boolean", 2724 | "ofType" : null 2725 | }, 2726 | "isDeprecated" : true, 2727 | "deprecationReason" : "Use `locations`." 2728 | }, { 2729 | "name" : "onFragment", 2730 | "description" : null, 2731 | "args" : [ ], 2732 | "type" : { 2733 | "kind" : "SCALAR", 2734 | "name" : "Boolean", 2735 | "ofType" : null 2736 | }, 2737 | "isDeprecated" : true, 2738 | "deprecationReason" : "Use `locations`." 2739 | }, { 2740 | "name" : "onField", 2741 | "description" : null, 2742 | "args" : [ ], 2743 | "type" : { 2744 | "kind" : "SCALAR", 2745 | "name" : "Boolean", 2746 | "ofType" : null 2747 | }, 2748 | "isDeprecated" : true, 2749 | "deprecationReason" : "Use `locations`." 2750 | } ], 2751 | "inputFields" : null, 2752 | "interfaces" : [ ], 2753 | "enumValues" : null, 2754 | "possibleTypes" : null 2755 | }, { 2756 | "kind" : "ENUM", 2757 | "name" : "__DirectiveLocation", 2758 | "description" : "An enum describing valid locations where a directive can be placed", 2759 | "fields" : null, 2760 | "inputFields" : null, 2761 | "interfaces" : null, 2762 | "enumValues" : [ { 2763 | "name" : "QUERY", 2764 | "description" : "Indicates the directive is valid on queries.", 2765 | "isDeprecated" : false, 2766 | "deprecationReason" : null 2767 | }, { 2768 | "name" : "MUTATION", 2769 | "description" : "Indicates the directive is valid on mutations.", 2770 | "isDeprecated" : false, 2771 | "deprecationReason" : null 2772 | }, { 2773 | "name" : "FIELD", 2774 | "description" : "Indicates the directive is valid on fields.", 2775 | "isDeprecated" : false, 2776 | "deprecationReason" : null 2777 | }, { 2778 | "name" : "FRAGMENT_DEFINITION", 2779 | "description" : "Indicates the directive is valid on fragment definitions.", 2780 | "isDeprecated" : false, 2781 | "deprecationReason" : null 2782 | }, { 2783 | "name" : "FRAGMENT_SPREAD", 2784 | "description" : "Indicates the directive is valid on fragment spreads.", 2785 | "isDeprecated" : false, 2786 | "deprecationReason" : null 2787 | }, { 2788 | "name" : "INLINE_FRAGMENT", 2789 | "description" : "Indicates the directive is valid on inline fragments.", 2790 | "isDeprecated" : false, 2791 | "deprecationReason" : null 2792 | }, { 2793 | "name" : "SCHEMA", 2794 | "description" : "Indicates the directive is valid on a schema SDL definition.", 2795 | "isDeprecated" : false, 2796 | "deprecationReason" : null 2797 | }, { 2798 | "name" : "SCALAR", 2799 | "description" : "Indicates the directive is valid on a scalar SDL definition.", 2800 | "isDeprecated" : false, 2801 | "deprecationReason" : null 2802 | }, { 2803 | "name" : "OBJECT", 2804 | "description" : "Indicates the directive is valid on an object SDL definition.", 2805 | "isDeprecated" : false, 2806 | "deprecationReason" : null 2807 | }, { 2808 | "name" : "FIELD_DEFINITION", 2809 | "description" : "Indicates the directive is valid on a field SDL definition.", 2810 | "isDeprecated" : false, 2811 | "deprecationReason" : null 2812 | }, { 2813 | "name" : "ARGUMENT_DEFINITION", 2814 | "description" : "Indicates the directive is valid on a field argument SDL definition.", 2815 | "isDeprecated" : false, 2816 | "deprecationReason" : null 2817 | }, { 2818 | "name" : "INTERFACE", 2819 | "description" : "Indicates the directive is valid on an interface SDL definition.", 2820 | "isDeprecated" : false, 2821 | "deprecationReason" : null 2822 | }, { 2823 | "name" : "UNION", 2824 | "description" : "Indicates the directive is valid on an union SDL definition.", 2825 | "isDeprecated" : false, 2826 | "deprecationReason" : null 2827 | }, { 2828 | "name" : "ENUM", 2829 | "description" : "Indicates the directive is valid on an enum SDL definition.", 2830 | "isDeprecated" : false, 2831 | "deprecationReason" : null 2832 | }, { 2833 | "name" : "ENUM_VALUE", 2834 | "description" : "Indicates the directive is valid on an enum value SDL definition.", 2835 | "isDeprecated" : false, 2836 | "deprecationReason" : null 2837 | }, { 2838 | "name" : "INPUT_OBJECT", 2839 | "description" : "Indicates the directive is valid on an input object SDL definition.", 2840 | "isDeprecated" : false, 2841 | "deprecationReason" : null 2842 | }, { 2843 | "name" : "INPUT_FIELD_DEFINITION", 2844 | "description" : "Indicates the directive is valid on an input object field SDL definition.", 2845 | "isDeprecated" : false, 2846 | "deprecationReason" : null 2847 | } ], 2848 | "possibleTypes" : null 2849 | } ], 2850 | "directives" : [ { 2851 | "name" : "include", 2852 | "description" : "Directs the executor to include this field or fragment only when the `if` argument is true", 2853 | "locations" : [ "FIELD", "FRAGMENT_SPREAD", "INLINE_FRAGMENT" ], 2854 | "args" : [ { 2855 | "name" : "if", 2856 | "description" : "Included when true.", 2857 | "type" : { 2858 | "kind" : "NON_NULL", 2859 | "name" : null, 2860 | "ofType" : { 2861 | "kind" : "SCALAR", 2862 | "name" : "Boolean", 2863 | "ofType" : null 2864 | } 2865 | }, 2866 | "defaultValue" : null 2867 | } ], 2868 | "onOperation" : false, 2869 | "onFragment" : true, 2870 | "onField" : true 2871 | }, { 2872 | "name" : "skip", 2873 | "description" : "Directs the executor to skip this field or fragment when the `if`'argument is true.", 2874 | "locations" : [ "FIELD", "FRAGMENT_SPREAD", "INLINE_FRAGMENT" ], 2875 | "args" : [ { 2876 | "name" : "if", 2877 | "description" : "Skipped when true.", 2878 | "type" : { 2879 | "kind" : "NON_NULL", 2880 | "name" : null, 2881 | "ofType" : { 2882 | "kind" : "SCALAR", 2883 | "name" : "Boolean", 2884 | "ofType" : null 2885 | } 2886 | }, 2887 | "defaultValue" : null 2888 | } ], 2889 | "onOperation" : false, 2890 | "onFragment" : true, 2891 | "onField" : true 2892 | }, { 2893 | "name" : "defer", 2894 | "description" : "This directive allows results to be deferred during execution", 2895 | "locations" : [ "FIELD" ], 2896 | "args" : [ ], 2897 | "onOperation" : false, 2898 | "onFragment" : false, 2899 | "onField" : true 2900 | }, { 2901 | "name" : "aws_publish", 2902 | "description" : "Tells the service which subscriptions will be published to when this mutation is called. This directive is deprecated use @aws_susbscribe directive instead.", 2903 | "locations" : [ "FIELD_DEFINITION" ], 2904 | "args" : [ { 2905 | "name" : "subscriptions", 2906 | "description" : "List of subscriptions which will be published to when this mutation is called.", 2907 | "type" : { 2908 | "kind" : "LIST", 2909 | "name" : null, 2910 | "ofType" : { 2911 | "kind" : "SCALAR", 2912 | "name" : "String", 2913 | "ofType" : null 2914 | } 2915 | }, 2916 | "defaultValue" : null 2917 | } ], 2918 | "onOperation" : false, 2919 | "onFragment" : false, 2920 | "onField" : false 2921 | }, { 2922 | "name" : "deprecated", 2923 | "description" : null, 2924 | "locations" : [ "FIELD_DEFINITION", "ENUM_VALUE" ], 2925 | "args" : [ { 2926 | "name" : "reason", 2927 | "description" : null, 2928 | "type" : { 2929 | "kind" : "SCALAR", 2930 | "name" : "String", 2931 | "ofType" : null 2932 | }, 2933 | "defaultValue" : "\"No longer supported\"" 2934 | } ], 2935 | "onOperation" : false, 2936 | "onFragment" : false, 2937 | "onField" : false 2938 | }, { 2939 | "name" : "aws_cognito_user_pools", 2940 | "description" : "Tells the service this field/object has access authorized by a Cognito User Pools token.", 2941 | "locations" : [ "OBJECT", "FIELD_DEFINITION" ], 2942 | "args" : [ { 2943 | "name" : "cognito_groups", 2944 | "description" : "List of cognito user pool groups which have access on this field", 2945 | "type" : { 2946 | "kind" : "LIST", 2947 | "name" : null, 2948 | "ofType" : { 2949 | "kind" : "SCALAR", 2950 | "name" : "String", 2951 | "ofType" : null 2952 | } 2953 | }, 2954 | "defaultValue" : null 2955 | } ], 2956 | "onOperation" : false, 2957 | "onFragment" : false, 2958 | "onField" : false 2959 | }, { 2960 | "name" : "aws_oidc", 2961 | "description" : "Tells the service this field/object has access authorized by an OIDC token.", 2962 | "locations" : [ "OBJECT", "FIELD_DEFINITION" ], 2963 | "args" : [ ], 2964 | "onOperation" : false, 2965 | "onFragment" : false, 2966 | "onField" : false 2967 | }, { 2968 | "name" : "aws_auth", 2969 | "description" : "Directs the schema to enforce authorization on a field", 2970 | "locations" : [ "FIELD_DEFINITION" ], 2971 | "args" : [ { 2972 | "name" : "cognito_groups", 2973 | "description" : "List of cognito user pool groups which have access on this field", 2974 | "type" : { 2975 | "kind" : "LIST", 2976 | "name" : null, 2977 | "ofType" : { 2978 | "kind" : "SCALAR", 2979 | "name" : "String", 2980 | "ofType" : null 2981 | } 2982 | }, 2983 | "defaultValue" : null 2984 | } ], 2985 | "onOperation" : false, 2986 | "onFragment" : false, 2987 | "onField" : false 2988 | }, { 2989 | "name" : "aws_iam", 2990 | "description" : "Tells the service this field/object has access authorized by sigv4 signing.", 2991 | "locations" : [ "OBJECT", "FIELD_DEFINITION" ], 2992 | "args" : [ ], 2993 | "onOperation" : false, 2994 | "onFragment" : false, 2995 | "onField" : false 2996 | }, { 2997 | "name" : "aws_subscribe", 2998 | "description" : "Tells the service which mutation triggers this subscription.", 2999 | "locations" : [ "FIELD_DEFINITION" ], 3000 | "args" : [ { 3001 | "name" : "mutations", 3002 | "description" : "List of mutations which will trigger this subscription when they are called.", 3003 | "type" : { 3004 | "kind" : "LIST", 3005 | "name" : null, 3006 | "ofType" : { 3007 | "kind" : "SCALAR", 3008 | "name" : "String", 3009 | "ofType" : null 3010 | } 3011 | }, 3012 | "defaultValue" : null 3013 | } ], 3014 | "onOperation" : false, 3015 | "onFragment" : false, 3016 | "onField" : false 3017 | }, { 3018 | "name" : "aws_api_key", 3019 | "description" : "Tells the service this field/object has access authorized by an API key.", 3020 | "locations" : [ "OBJECT", "FIELD_DEFINITION" ], 3021 | "args" : [ ], 3022 | "onOperation" : false, 3023 | "onFragment" : false, 3024 | "onField" : false 3025 | } ] 3026 | } 3027 | } 3028 | } -------------------------------------------------------------------------------- /src/graphql/subscriptions.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | // this is an auto generated file. This will be overwritten 3 | 4 | export const onCreateMessageByRoomId = /* GraphQL */ ` 5 | subscription OnCreateMessageByRoomId($roomId: ID) { 6 | onCreateMessageByRoomId(roomId: $roomId) { 7 | id 8 | content 9 | owner 10 | createdAt 11 | roomId 12 | } 13 | } 14 | `; 15 | export const onCreateRoom = /* GraphQL */ ` 16 | subscription OnCreateRoom { 17 | onCreateRoom { 18 | id 19 | name 20 | createdAt 21 | } 22 | } 23 | `; 24 | -------------------------------------------------------------------------------- /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 | 15 | * { 16 | font-family: 'Mulish', sans-serif; 17 | } 18 | 19 | :root { 20 | --amplify-primary-color: #007bff; 21 | --amplify-primary-tint: #0065d1; 22 | --amplify-primary-shade: #0065d1; 23 | } 24 | 25 | amplify-authenticator { 26 | display: flex; 27 | justify-content: center; 28 | align-items: center; 29 | flex: 1; 30 | height: 100vh; 31 | } -------------------------------------------------------------------------------- /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 | import Amplify from 'aws-amplify' 7 | 8 | import config from './aws-exports'; 9 | 10 | Amplify.configure(config) 11 | 12 | ReactDOM.render( 13 | // 14 | , 15 | // , 16 | document.getElementById('root') 17 | ); 18 | 19 | // If you want your app to work offline and load faster, you can change 20 | // unregister() to register() below. Note this comes with some pitfalls. 21 | // Learn more about service workers: https://bit.ly/CRA-PWA 22 | // serviceWorker.unregister(); 23 | -------------------------------------------------------------------------------- /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.0/8 are 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 | headers: { 'Service-Worker': 'script' }, 105 | }) 106 | .then(response => { 107 | // Ensure service worker exists, and that we really are getting a JS file. 108 | const contentType = response.headers.get('content-type'); 109 | if ( 110 | response.status === 404 || 111 | (contentType != null && contentType.indexOf('javascript') === -1) 112 | ) { 113 | // No service worker found. Probably a different app. Reload the page. 114 | navigator.serviceWorker.ready.then(registration => { 115 | registration.unregister().then(() => { 116 | window.location.reload(); 117 | }); 118 | }); 119 | } else { 120 | // Service worker found. Proceed as normal. 121 | registerValidSW(swUrl, config); 122 | } 123 | }) 124 | .catch(() => { 125 | console.log( 126 | 'No internet connection found. App is running in offline mode.' 127 | ); 128 | }); 129 | } 130 | 131 | export function unregister() { 132 | if ('serviceWorker' in navigator) { 133 | navigator.serviceWorker.ready 134 | .then(registration => { 135 | registration.unregister(); 136 | }) 137 | .catch(error => { 138 | console.error(error.message); 139 | }); 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /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/extend-expect'; 6 | -------------------------------------------------------------------------------- /src/theme.js: -------------------------------------------------------------------------------- 1 | const theme = { 2 | primaryColor: '#007bff' 3 | } 4 | 5 | export default theme --------------------------------------------------------------------------------