├── .gitignore ├── .npmignore ├── LICENSE ├── README.md ├── bin └── app.ts ├── blogpost └── README.md ├── cdk.json ├── frontend-example ├── .gitignore ├── README.md ├── package-lock.json ├── package.json ├── public │ ├── favicon.ico │ ├── index.html │ ├── logo192.png │ ├── logo512.png │ ├── manifest.json │ └── robots.txt └── src │ ├── App.css │ ├── App.js │ ├── App.test.js │ ├── graphql │ ├── mutations.js │ ├── queries.js │ ├── schema.json │ └── subscriptions.js │ ├── index.css │ ├── index.js │ ├── models │ ├── index.js │ └── schema.js │ ├── serviceWorker.js │ └── setupTests.js ├── lib └── app-stack.ts ├── package-lock.json ├── package.json ├── schema.graphql ├── scripts └── deploy.sh ├── transform ├── schema-transformer.ts ├── transform.conf.json └── transformer.ts └── tsconfig.json /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | 9 | # Diagnostic reports (https://nodejs.org/api/report.html) 10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 11 | 12 | # Runtime data 13 | pids 14 | *.pid 15 | *.seed 16 | *.pid.lock 17 | 18 | # Directory for instrumented libs generated by jscoverage/JSCover 19 | lib-cov 20 | 21 | # Coverage directory used by tools like istanbul 22 | coverage 23 | *.lcov 24 | 25 | # nyc test coverage 26 | .nyc_output 27 | 28 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 29 | .grunt 30 | 31 | # Bower dependency directory (https://bower.io/) 32 | bower_components 33 | 34 | # node-waf configuration 35 | .lock-wscript 36 | 37 | # Compiled binary addons (https://nodejs.org/api/addons.html) 38 | build/Release 39 | 40 | # Dependency directories 41 | node_modules/ 42 | jspm_packages/ 43 | 44 | # TypeScript v1 declaration files 45 | typings/ 46 | 47 | # TypeScript cache 48 | *.tsbuildinfo 49 | 50 | # Optional npm cache directory 51 | .npm 52 | 53 | # Optional eslint cache 54 | .eslintcache 55 | 56 | # Microbundle cache 57 | .rpt2_cache/ 58 | .rts2_cache_cjs/ 59 | .rts2_cache_es/ 60 | .rts2_cache_umd/ 61 | 62 | # Optional REPL history 63 | .node_repl_history 64 | 65 | # Output of 'npm pack' 66 | *.tgz 67 | 68 | # Yarn Integrity file 69 | .yarn-integrity 70 | 71 | # dotenv environment variables file 72 | .env 73 | .env.test 74 | 75 | # parcel-bundler cache (https://parceljs.org/) 76 | .cache 77 | 78 | # Next.js build output 79 | .next 80 | 81 | # Nuxt.js build / generate output 82 | .nuxt 83 | dist 84 | 85 | # Gatsby files 86 | .cache/ 87 | # Comment in the public line in if your project uses Gatsby and *not* Next.js 88 | # https://nextjs.org/blog/next-9-1#public-directory-support 89 | # public 90 | 91 | # vuepress build output 92 | .vuepress/dist 93 | 94 | # Serverless directories 95 | .serverless/ 96 | 97 | # FuseBox cache 98 | .fusebox/ 99 | 100 | # DynamoDB Local files 101 | .dynamodb/ 102 | 103 | # TernJS port file 104 | .tern-port 105 | 106 | # CDK Generated 107 | !jest.config.js 108 | *.d.ts 109 | node_modules 110 | 111 | # CDK asset staging directory 112 | .cdk.staging 113 | cdk.out 114 | 115 | # Generated AppSync Files 116 | appsync/* 117 | 118 | #amplify 119 | amplify/\#current-cloud-backend 120 | amplify/.config/local-* 121 | amplify/mock-data 122 | amplify/backend/amplify-meta.json 123 | amplify/backend/awscloudformation 124 | build/ 125 | dist/ 126 | node_modules/ 127 | aws-exports.js 128 | awsconfiguration.json 129 | amplifyconfiguration.json 130 | amplify-gradle-config.json 131 | amplifyxc.config -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | *.ts 2 | !*.d.ts 3 | 4 | # CDK asset staging directory 5 | .cdk.staging 6 | cdk.out 7 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Kenneth Winner 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CDK AppSync Transformer Demo 2 | 3 | Accompanying repo for blog post regarding CDK AppSync Transformations. Find the post [here](). If you have any questions feel free to reach out here or [@KenWin0x539](https://twitter.com/KenWin0x539). 4 | 5 | ## Pre-reqs 6 | 7 | * Node JS 8 | * [AWS CDK](https://docs.aws.amazon.com/cdk/latest/guide/getting_started.html) 9 | * `npm install -g aws-cdk` 10 | 11 | ## Dependencies 12 | 13 | ### Transformation 14 | 15 | * `graphql-transformer-core` 16 | * `graphql-dynamodb-transformer` 17 | * `graphql-connection-transformer` 18 | * `graphql-key-transformer` 19 | * `graphql-function-transformer` 20 | * `graphql-versioned-transformer` 21 | * `graphql-auth-transformer` 22 | * `graphql-appsync-transformer` 23 | 24 | You can find other available transformers [here](https://github.com/aws-amplify/amplify-cli/tree/master/packages) 25 | 26 | ### Custom Transformer 27 | 28 | * `graphql-transformer-core` 29 | * `graphql` 30 | * `graphql-transformer-common` 31 | * `graphql-mapping-template` 32 | * `cloudform-types` 33 | 34 | ## Execution 35 | 36 | ### `cdk synth` 37 | 38 | Emits the synthesized CloudFormation template. Additionally, this will run our transformer. Resolvers and generated schema go to `./appsync` directory locally. Refrain from editing the generated schema - make necessary changes in the root `./schema.graphql`. The generated file will be overwritten. 39 | 40 | ### `cdk deploy` 41 | 42 | Deploys the stack with out generated schema, tables and resolvers. 43 | 44 | ## Getting Amplify DataStore To Work 45 | 46 | It's a little bit hacky, but this is what I have so far. Awaiting further suggestions or ideas for optimizing. There is no native integration for the model generation at the moment. 47 | 48 | * `amplify add api --apiId xxx` 49 | * Copy schema to frontend amplify direction 50 | * From frontend - `cp ../api/appsync/schema.graphql ./amplify/#current-cloud-backend/api/api-dev/` 51 | * From frontend - `cp ../api/schema.graphql ./amplify/backend/api/api-dev/` 52 | * Modify `${FRONTEND_DIR}/amplify/backend/amplify-meta.json` 53 | 54 | ```json 55 | "api": { 56 | "my-cool-api-dev": { 57 | "service": "AppSync", 58 | "providerPlugin": "awscloudformation", 59 | ... 60 | ... 61 | } 62 | } 63 | ``` 64 | 65 | * `amplify codegen models` - This should now work... I know, it's not lovely. 66 | 67 | ## Where Do We Go From Here? 68 | 69 | We believe this would work much better as a CDK plugin or an npm package. Unfortunately, the CDK plugin system currently only supports credential providers at the moment. I played around with writing it in as a plugin (it sort of works), but you would have to write the cfdoc to a file and read it from your app to bring in the resources. Perhaps an opinionated AppSync API Construct would be best here. 70 | 71 | I'm not sold on the `transform.conf.json` method for triggering the sync enablement. I went this route because this is what the Amplify libraries do. Originally I was going to have props passed in to the `SchemaTransformer` (there are still some remnants of this code as I decide what to do...). 72 | 73 | ## Resources / References 74 | 75 | * [Amplify GraphQL Transform](https://aws-amplify.github.io/docs/cli-toolchain/graphql) 76 | * [GraphQL Auto Transformer](https://github.com/hirochachacha/graphql-auto-transformer) -------------------------------------------------------------------------------- /bin/app.ts: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | import * as cdk from '@aws-cdk/core'; 3 | import { AppStack } from '../lib/app-stack'; 4 | 5 | import { SchemaTransformer } from '../transform/schema-transformer'; 6 | 7 | const transformer = new SchemaTransformer(); 8 | const outputs = transformer.transform(); 9 | const resolvers = transformer.getResolvers(); 10 | 11 | // AWS Guidance below. However, I prefer to use the cdk context for environment values instead of multiple stacks 12 | // https://docs.aws.amazon.com/cdk/latest/guide/environments.html 13 | // https://github.com/aws/aws-cdk/issues/4846#issuecomment-552797597 14 | const STAGE = process.env.STAGE || 'demo' 15 | 16 | const app = new cdk.App( 17 | { 18 | context: { 19 | STAGE: STAGE 20 | } 21 | }) 22 | 23 | new AppStack(app, 'AppStack', outputs, resolvers); -------------------------------------------------------------------------------- /blogpost/README.md: -------------------------------------------------------------------------------- 1 | # AppSync With The AWS Cloud Development Kit 2 | 3 | ## Deploying with automated schema definition language (SDL) transforms 4 | 5 | All code and information can be found [on GitHub](https://github.com/kcwinner/cdk-appsync-transformer-demo/). 6 | 7 | ### The Challenge With AppSync 8 | 9 | If you are familiar with AppSync, you know how frustrating it can be to build out a full API, writing each individual piece of the schema for your models, your connections, filters, queries, and mutations. Not only must you write the schema, you have to also write each resolver using velocity template language (VTL). A simple application can quickly become a few hundred lines of SDL, VTL, and Cloudformation. 10 | 11 | ### [GraphQL Transform](https://docs.amplify.aws/cli/graphql-transformer/storage) Saves The Day 12 | 13 | The Amplify CLI introduced some fantastic packages to help transform your AppSync schema into types, queries, mutations, subscriptions, tables, and resolvers using something called the GraphQL Schema Definition Language (SDL). Using [supported directives](https://aws-amplify.github.io/docs/cli-toolchain/graphql?sdk=js#directives) the CLI transformation plugin will transform your SDL into deployable templates, streamlining the process of creating AppSync APIs. 14 | 15 | An example directive for the @model directive looks like this: 16 | 17 | ```graphql 18 | type Product 19 | @model { 20 | id: ID! 21 | name: String! 22 | description: String! 23 | price: String! 24 | active: Boolean! 25 | added: AWSDateTime! 26 | } 27 | ``` 28 | 29 | After transformation, we get the following schema, as well as resolvers and CloudFormation for a DynamoDB table. 30 | 31 | ```graphql 32 | type Product { 33 | id: ID! 34 | name: String! 35 | description: String! 36 | price: String! 37 | active: Boolean! 38 | added: AWSDateTime! 39 | } 40 | 41 | type ModelProductConnection { 42 | items: [Product] 43 | nextToken: String 44 | } 45 | 46 | input CreateProductInput { 47 | id: ID 48 | name: String! 49 | description: String! 50 | price: String! 51 | active: Boolean! 52 | added: AWSDateTime! 53 | } 54 | 55 | input UpdateProductInput { 56 | id: ID! 57 | name: String 58 | description: String 59 | price: String 60 | active: Boolean 61 | added: AWSDateTime 62 | } 63 | 64 | input DeleteProductInput { 65 | id: ID 66 | } 67 | 68 | input ModelProductFilterInput { 69 | id: ModelIDFilterInput 70 | name: ModelStringFilterInput 71 | description: ModelStringFilterInput 72 | price: ModelStringFilterInput 73 | active: ModelBooleanFilterInput 74 | added: ModelStringFilterInput 75 | and: [ModelProductFilterInput] 76 | or: [ModelProductFilterInput] 77 | not: ModelProductFilterInput 78 | } 79 | 80 | type Query { 81 | getProduct(id: ID!): Product 82 | listProducts(filter: ModelProductFilterInput, limit: Int, nextToken: String): ModelProductConnection 83 | } 84 | 85 | type Mutation { 86 | createProduct(input: CreateProductInput!): Product 87 | updateProduct(input: UpdateProductInput!): Product 88 | deleteProduct(input: DeleteProductInput!): Product 89 | } 90 | 91 | type Subscription { 92 | onCreateProduct: Product @aws_subscribe(mutations: ["createProduct"]) 93 | onUpdateProduct: Product @aws_subscribe(mutations: ["updateProduct"]) 94 | onDeleteProduct: Product @aws_subscribe(mutations: ["deleteProduct"]) 95 | } 96 | ``` 97 | 98 | Using the GraphQL Transform plugin, we turned 9 lines of SDL with a declaration into 62 lines. Extrapolate this to multiple types, and we begin to see how automated transformations not only save us time but also give us a concise way of declaring some of the boilerplate around AppSync APIs. 99 | 100 | ### Challenges of using AWS Amplify CLI 101 | 102 | As outstanding as many of the features of the Amplify CLI are, I've found I personally prefer to define my resources using the AWS Cloud Development Kit (CDK) since it's easier to integrate with other existing systems and processes. Unfortunately for me, the transformation plugin only exists in the Amplify CLI. I decided that to emulate this functionality, I would take the same transformation packages used in the Amplify CLI and integrate them into my CDK project! 103 | 104 | #### Recreating The Schema Transformer 105 | 106 | To emulate the Amplify CLI transformer, we have to have a schema transformer and import the existing transformers. Luckily the Amplify docs show us an implementation [here](https://aws-amplify.github.io/docs/cli-toolchain/plugins?sdk=js). Since we want to have all the same directives available to us, we must implement the same packages and structure outlined above. This gives us our directive resolution, resolver creation, and template generation! 107 | 108 | We end up with something like this: 109 | 110 | ```typescript 111 | import { GraphQLTransform } from 'graphql-transformer-core'; 112 | import { DynamoDBModelTransformer } from 'graphql-dynamodb-transformer'; 113 | import { ModelConnectionTransformer } from 'graphql-connection-transformer'; 114 | import { KeyTransformer } from 'graphql-key-transformer'; 115 | import { FunctionTransformer } from 'graphql-function-transformer'; 116 | import { VersionedModelTransformer } from 'graphql-versioned-transformer'; 117 | import { ModelAuthTransformer, ModelAuthTransformerConfig } from 'graphql-auth-transformer' 118 | const { AppSyncTransformer } = require('graphql-appsync-transformer') 119 | import { normalize } from 'path'; 120 | import * as fs from "fs"; 121 | 122 | const outputPath = './appsync' 123 | 124 | export class SchemaTransformer { 125 | transform() { 126 | // These config values do not even matter... So set it up for both 127 | const authTransformerConfig: ModelAuthTransformerConfig = { 128 | authConfig: { 129 | defaultAuthentication: { 130 | authenticationType: 'API_KEY', 131 | apiKeyConfig: { 132 | description: 'Testing', 133 | apiKeyExpirationDays: 100 134 | } 135 | }, 136 | additionalAuthenticationProviders: [ 137 | { 138 | authenticationType: 'AMAZON_COGNITO_USER_POOLS', 139 | userPoolConfig: { 140 | userPoolId: '12345xyz' 141 | } 142 | } 143 | ] 144 | } 145 | } 146 | 147 | // Note: This is not exact as we are omitting the @searchable transformer. 148 | const transformer = new GraphQLTransform({ 149 | transformers: [ 150 | new AppSyncTransformer(outputPath), 151 | new DynamoDBModelTransformer(), 152 | new VersionedModelTransformer(), 153 | new FunctionTransformer(), 154 | new KeyTransformer(), 155 | new ModelAuthTransformer(authTransformerConfig), 156 | new ModelConnectionTransformer(), 157 | ] 158 | }) 159 | 160 | const schema_path = './schema.graphql' 161 | const schema = fs.readFileSync(schema_path) 162 | 163 | return transformer.transform(schema.toString()); 164 | } 165 | } 166 | ``` 167 | 168 | #### Writing Our Own Transformer 169 | 170 | After implementing the schema transformer exactly the same, I realized it doesn't fit our CDK implementation perfectly. For example, instead of the JSON CloudFormation output of our DynamoDB tables, we want iterable resources that can be created via the CDK. In comes our own [transformer](https://github.com/kcwinner/cdk-appsync-transformer-demo/blob/master/lib/transformer.ts)! 171 | 172 | In this custom transformer, we do two things - look for the @nullable directive and grab the transformer context after completion. 173 | 174 | ##### @nullable Directive 175 | 176 | When creating a custom key using the `@key` direction on a model, the associated resolver does not allow for using `$util.autoId()` to generate a unique identifier and creation time. I've implemented this new directive using [graphql-auto-transformer](https://github.com/hirochachacha/graphql-auto-transformer) as a guide. This outputs a modified resolver for the field with our custom directive. 177 | 178 | ##### Post Transformation 179 | 180 | After schema transformation is complete, our custom transformer grabs the context, searches for `AWS::DynamoDB::Table` resources, and builds a table object for us to create a table from later. Later, we can loop over this output and create our tables and resolvers like so: 181 | 182 | ```typescript 183 | createTablesAndResolvers(api: GraphQLApi, tableData: any, resolvers: any) { 184 | Object.keys(tableData).forEach((tableKey: any) => { 185 | let table = this.createTable(tableData[tableKey]); 186 | 187 | const dataSource = api.addDynamoDbDataSource(tableKey, `Data source for ${tableKey}`, table); 188 | 189 | Object.keys(resolvers).forEach((resolverKey: any) => { 190 | let resolverTableName = this.getTableNameFromFieldName(resolverKey) 191 | if (tableKey === resolverTableName) { 192 | let resolver = resolvers[resolverKey] 193 | 194 | dataSource.createResolver({ 195 | typeName: resolver.typeName, 196 | fieldName: resolver.fieldName, 197 | requestMappingTemplate: MappingTemplate.fromFile(resolver.requestMappingTemplate), 198 | responseMappingTemplate: MappingTemplate.fromFile(resolver.responseMappingTemplate), 199 | }) 200 | } 201 | }) 202 | }); 203 | } 204 | ``` 205 | 206 | #### Using The Schema Transformer 207 | 208 | To run our transformer before the CDK's template generation, we must import our transformer, run the transformer, and pass the data to our stack! 209 | 210 | ```typescript 211 | #!/usr/bin/env node 212 | import * as cdk from '@aws-cdk/core'; 213 | import { AppStack } from '../lib/app-stack'; 214 | import { SchemaTransformer } from '../lib/schema-transformer'; 215 | 216 | const transformer = new SchemaTransformer(); 217 | const outputs = transformer.transform(); 218 | const resolvers = transformer.getResolvers(); 219 | 220 | const STAGE = process.env.STAGE || 'demo' 221 | 222 | const app = new cdk.App({ 223 | context: { STAGE: STAGE } 224 | }) 225 | 226 | new AppStack(app, 'AppStack', outputs, resolvers); 227 | ``` 228 | 229 | All code can be found [here](https://github.com/kcwinner/cdk-appsync-transformer-demo/) 230 | 231 | ### Where Do We Go From Here? 232 | 233 | We believe this would work much better as a CDK plugin or an npm package. Unfortunately, the CDK plugin system currently only supports credential providers at the moment. I played around with writing it in as a plugin (it sort of works), but you would have to write the cfdoc to a file and read it from your app to bring in the resources. 234 | 235 | ## References 236 | 237 | * [Amplify Docs](https://aws-amplify.github.io/docs/) 238 | * [GraphQL Auto Transformer](https://github.com/hirochachacha/graphql-auto-transformer) 239 | -------------------------------------------------------------------------------- /cdk.json: -------------------------------------------------------------------------------- 1 | { 2 | "app": "npx ts-node bin/app.ts" 3 | } 4 | -------------------------------------------------------------------------------- /frontend-example/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | 25 | #amplify 26 | amplify/\#current-cloud-backend 27 | amplify/.config/local-* 28 | amplify/mock-data 29 | amplify/backend/amplify-meta.json 30 | amplify/backend/awscloudformation 31 | build/ 32 | dist/ 33 | node_modules/ 34 | aws-exports.js 35 | awsconfiguration.json 36 | amplifyconfiguration.json 37 | amplify-gradle-config.json 38 | amplifyxc.config -------------------------------------------------------------------------------- /frontend-example/README.md: -------------------------------------------------------------------------------- 1 | # Frontend Example 2 | 3 | This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app). 4 | 5 | ## Amplify Setup 6 | 7 | * `amplify init` 8 | * `npm install` 9 | 10 | ### Add Api And Codegen 11 | 12 | * `amplify codegen add --apiId xxx` - This will download the introspection schema 13 | * Follow prompts 14 | * `javascript` 15 | * `enter` 16 | * `Y` 17 | * `Y` 18 | 19 | * `mkdir -p ./amplify/#current-cloud-backend/api/demo-api-demo/ && cp ../appsync/schema.graphql "$_"` 20 | * `mkdir -p ./amplify/backend/api/demo-api-demo/ && cp ../schema.graphql "$_"` 21 | * This is where you have to modify your `amplify/backend/amplify-meta.json` file 22 | * Add the line `"providerPlugin": "awscloudformation",` underneath `"service": "AppSync",` 23 | * Since we are also using a custom field directive that I built, @nullable, in the example, we have to remove that from `amplify/backend/api/demo-api-demo/schema.graphql`. Don't worry, I'll figure something better out for this... 24 | * `amplify codegen models` -------------------------------------------------------------------------------- /frontend-example/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "frontend-example", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@aws-amplify/datastore": "^2.0.5", 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.5", 11 | "react": "^16.13.1", 12 | "react-dom": "^16.13.1", 13 | "react-scripts": "3.4.1" 14 | }, 15 | "scripts": { 16 | "start": "react-scripts start", 17 | "build": "react-scripts build", 18 | "test": "react-scripts test", 19 | "eject": "react-scripts eject" 20 | }, 21 | "eslintConfig": { 22 | "extends": "react-app" 23 | }, 24 | "browserslist": { 25 | "production": [ 26 | ">0.2%", 27 | "not dead", 28 | "not op_mini all" 29 | ], 30 | "development": [ 31 | "last 1 chrome version", 32 | "last 1 firefox version", 33 | "last 1 safari version" 34 | ] 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /frontend-example/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kcwinner/cdk-appsync-transformer-demo/0452ce09569585852dbd1e2fd3ede2b7e74eebbd/frontend-example/public/favicon.ico -------------------------------------------------------------------------------- /frontend-example/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 17 | 18 | 27 | React App 28 | 29 | 30 | 31 |
32 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /frontend-example/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kcwinner/cdk-appsync-transformer-demo/0452ce09569585852dbd1e2fd3ede2b7e74eebbd/frontend-example/public/logo192.png -------------------------------------------------------------------------------- /frontend-example/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kcwinner/cdk-appsync-transformer-demo/0452ce09569585852dbd1e2fd3ede2b7e74eebbd/frontend-example/public/logo512.png -------------------------------------------------------------------------------- /frontend-example/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 | -------------------------------------------------------------------------------- /frontend-example/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /frontend-example/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 | -------------------------------------------------------------------------------- /frontend-example/src/App.js: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect } from 'react'; 2 | import './App.css'; 3 | 4 | import Amplify from 'aws-amplify'; 5 | 6 | import { DataStore, Predicates } from '@aws-amplify/datastore' 7 | import { Customer, Product } from './models'; 8 | 9 | import awsconfig from './aws-exports'; 10 | Amplify.configure(awsconfig); 11 | 12 | function App() { 13 | const [customers, setCustomers] = useState([]); 14 | const [products, setProducts] = useState([]); 15 | 16 | const updateCustomers = async (setCustomers) => { 17 | const updatedCustomers = await DataStore.query(Customer, Predicates.All); 18 | setCustomers(updatedCustomers); 19 | } 20 | 21 | const updateProducts = async (setProducts) => { 22 | const updatedProducts = await DataStore.query(Product, Predicates.All); 23 | setProducts(updatedProducts); 24 | } 25 | 26 | useEffect(() => { 27 | const fetchCustomers = async () => { 28 | const customers = await DataStore.query(Customer, Predicates.All); 29 | setCustomers(customers); 30 | } 31 | 32 | fetchCustomers(); 33 | 34 | const customerSubscription = DataStore.observe(Customer).subscribe(() => { 35 | updateCustomers(setCustomers); 36 | }) 37 | 38 | const productSubscription = DataStore.observe(Product).subscribe(() => { 39 | updateProducts(setProducts); 40 | }) 41 | 42 | 43 | return () => { 44 | customerSubscription.unsubscribe(); 45 | productSubscription.unsubscribe(); 46 | } 47 | }, []) 48 | 49 | return ( 50 |
51 |
52 |

React Example

53 |
54 | 55 | 56 | 57 |
58 | 59 | 60 |
61 | ); 62 | } 63 | 64 | export default App; 65 | 66 | function CustomersTable({ customers }) { 67 | 68 | const addCustomer = async () => { 69 | let customer = await DataStore.save( 70 | new Customer({ 71 | firstName: 'Greatest', 72 | lastName: 'Example', 73 | active: true, 74 | address: '1600 Joshua Lane' 75 | }) 76 | ); 77 | 78 | console.log(customer); 79 | } 80 | 81 | return ( 82 | <> 83 |

Customers

84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | { 96 | customers.map(customer => { 97 | return ( 98 | 99 | 100 | 101 | 102 | 103 | 104 | ) 105 | }) 106 | } 107 | 108 |
First NameLast NameActiveAddress
{customer.firstName}{customer.lastName}{customer.active.toString()}{customer.address}
109 | 110 | ) 111 | } 112 | 113 | function ProductsTable({ products }) { 114 | 115 | const addProduct = async () => { 116 | let product = await DataStore.save( 117 | new Product({ 118 | name: 'Water Bottle', 119 | description: 'Example product', 120 | price: '$2.00', 121 | active: true, 122 | added: new Date().toISOString() 123 | }) 124 | ); 125 | 126 | console.log(product); 127 | } 128 | 129 | return ( 130 | <> 131 |

Products

132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | { 145 | products.map(product => { 146 | return ( 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | ) 155 | }) 156 | } 157 | 158 |
NameDescriptionPriceActiveAdded
{product.name}{product.description}{product.price}{product.active.toString()}{product.added}
159 | 160 | ) 161 | } -------------------------------------------------------------------------------- /frontend-example/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 | -------------------------------------------------------------------------------- /frontend-example/src/graphql/mutations.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | // this is an auto generated file. This will be overwritten 3 | 4 | export const createProduct = /* GraphQL */ ` 5 | mutation CreateProduct( 6 | $input: CreateProductInput! 7 | $condition: ModelProductConditionInput 8 | ) { 9 | createProduct(input: $input, condition: $condition) { 10 | id 11 | name 12 | description 13 | price 14 | active 15 | added 16 | _version 17 | _deleted 18 | _lastChangedAt 19 | } 20 | } 21 | `; 22 | export const updateProduct = /* GraphQL */ ` 23 | mutation UpdateProduct( 24 | $input: UpdateProductInput! 25 | $condition: ModelProductConditionInput 26 | ) { 27 | updateProduct(input: $input, condition: $condition) { 28 | id 29 | name 30 | description 31 | price 32 | active 33 | added 34 | _version 35 | _deleted 36 | _lastChangedAt 37 | } 38 | } 39 | `; 40 | export const deleteProduct = /* GraphQL */ ` 41 | mutation DeleteProduct( 42 | $input: DeleteProductInput! 43 | $condition: ModelProductConditionInput 44 | ) { 45 | deleteProduct(input: $input, condition: $condition) { 46 | id 47 | name 48 | description 49 | price 50 | active 51 | added 52 | _version 53 | _deleted 54 | _lastChangedAt 55 | } 56 | } 57 | `; 58 | export const createOrder = /* GraphQL */ ` 59 | mutation CreateOrder( 60 | $input: CreateOrderInput! 61 | $condition: ModelOrderConditionInput 62 | ) { 63 | createOrder(input: $input, condition: $condition) { 64 | id 65 | productID 66 | total 67 | ordered 68 | _version 69 | _deleted 70 | _lastChangedAt 71 | } 72 | } 73 | `; 74 | export const updateOrder = /* GraphQL */ ` 75 | mutation UpdateOrder( 76 | $input: UpdateOrderInput! 77 | $condition: ModelOrderConditionInput 78 | ) { 79 | updateOrder(input: $input, condition: $condition) { 80 | id 81 | productID 82 | total 83 | ordered 84 | _version 85 | _deleted 86 | _lastChangedAt 87 | } 88 | } 89 | `; 90 | export const deleteOrder = /* GraphQL */ ` 91 | mutation DeleteOrder( 92 | $input: DeleteOrderInput! 93 | $condition: ModelOrderConditionInput 94 | ) { 95 | deleteOrder(input: $input, condition: $condition) { 96 | id 97 | productID 98 | total 99 | ordered 100 | _version 101 | _deleted 102 | _lastChangedAt 103 | } 104 | } 105 | `; 106 | export const createCustomer = /* GraphQL */ ` 107 | mutation CreateCustomer( 108 | $input: CreateCustomerInput! 109 | $condition: ModelCustomerConditionInput 110 | ) { 111 | createCustomer(input: $input, condition: $condition) { 112 | id 113 | firstName 114 | lastName 115 | active 116 | address 117 | _version 118 | _deleted 119 | _lastChangedAt 120 | version 121 | owner 122 | } 123 | } 124 | `; 125 | export const updateCustomer = /* GraphQL */ ` 126 | mutation UpdateCustomer( 127 | $input: UpdateCustomerInput! 128 | $condition: ModelCustomerConditionInput 129 | ) { 130 | updateCustomer(input: $input, condition: $condition) { 131 | id 132 | firstName 133 | lastName 134 | active 135 | address 136 | _version 137 | _deleted 138 | _lastChangedAt 139 | version 140 | owner 141 | } 142 | } 143 | `; 144 | export const deleteCustomer = /* GraphQL */ ` 145 | mutation DeleteCustomer( 146 | $input: DeleteCustomerInput! 147 | $condition: ModelCustomerConditionInput 148 | ) { 149 | deleteCustomer(input: $input, condition: $condition) { 150 | id 151 | firstName 152 | lastName 153 | active 154 | address 155 | _version 156 | _deleted 157 | _lastChangedAt 158 | version 159 | owner 160 | } 161 | } 162 | `; 163 | -------------------------------------------------------------------------------- /frontend-example/src/graphql/queries.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | // this is an auto generated file. This will be overwritten 3 | 4 | export const syncProducts = /* GraphQL */ ` 5 | query SyncProducts( 6 | $filter: ModelProductFilterInput 7 | $limit: Int 8 | $nextToken: String 9 | $lastSync: AWSTimestamp 10 | ) { 11 | syncProducts( 12 | filter: $filter 13 | limit: $limit 14 | nextToken: $nextToken 15 | lastSync: $lastSync 16 | ) { 17 | items { 18 | id 19 | name 20 | description 21 | price 22 | active 23 | added 24 | _version 25 | _deleted 26 | _lastChangedAt 27 | } 28 | nextToken 29 | startedAt 30 | } 31 | } 32 | `; 33 | export const getProduct = /* GraphQL */ ` 34 | query GetProduct($id: ID!) { 35 | getProduct(id: $id) { 36 | id 37 | name 38 | description 39 | price 40 | active 41 | added 42 | _version 43 | _deleted 44 | _lastChangedAt 45 | } 46 | } 47 | `; 48 | export const listProducts = /* GraphQL */ ` 49 | query ListProducts( 50 | $filter: ModelProductFilterInput 51 | $limit: Int 52 | $nextToken: String 53 | ) { 54 | listProducts(filter: $filter, limit: $limit, nextToken: $nextToken) { 55 | items { 56 | id 57 | name 58 | description 59 | price 60 | active 61 | added 62 | _version 63 | _deleted 64 | _lastChangedAt 65 | } 66 | nextToken 67 | startedAt 68 | } 69 | } 70 | `; 71 | export const syncOrders = /* GraphQL */ ` 72 | query SyncOrders( 73 | $filter: ModelOrderFilterInput 74 | $limit: Int 75 | $nextToken: String 76 | $lastSync: AWSTimestamp 77 | ) { 78 | syncOrders( 79 | filter: $filter 80 | limit: $limit 81 | nextToken: $nextToken 82 | lastSync: $lastSync 83 | ) { 84 | items { 85 | id 86 | productID 87 | total 88 | ordered 89 | _version 90 | _deleted 91 | _lastChangedAt 92 | } 93 | nextToken 94 | startedAt 95 | } 96 | } 97 | `; 98 | export const getOrder = /* GraphQL */ ` 99 | query GetOrder($id: ID!, $productID: ID!) { 100 | getOrder(id: $id, productID: $productID) { 101 | id 102 | productID 103 | total 104 | ordered 105 | _version 106 | _deleted 107 | _lastChangedAt 108 | } 109 | } 110 | `; 111 | export const listOrders = /* GraphQL */ ` 112 | query ListOrders( 113 | $id: ID 114 | $productID: ModelIDKeyConditionInput 115 | $filter: ModelOrderFilterInput 116 | $limit: Int 117 | $nextToken: String 118 | $sortDirection: ModelSortDirection 119 | ) { 120 | listOrders( 121 | id: $id 122 | productID: $productID 123 | filter: $filter 124 | limit: $limit 125 | nextToken: $nextToken 126 | sortDirection: $sortDirection 127 | ) { 128 | items { 129 | id 130 | productID 131 | total 132 | ordered 133 | _version 134 | _deleted 135 | _lastChangedAt 136 | } 137 | nextToken 138 | startedAt 139 | } 140 | } 141 | `; 142 | export const getCustomer = /* GraphQL */ ` 143 | query GetCustomer($id: ID!) { 144 | getCustomer(id: $id) { 145 | id 146 | firstName 147 | lastName 148 | active 149 | address 150 | _version 151 | _deleted 152 | _lastChangedAt 153 | version 154 | owner 155 | } 156 | } 157 | `; 158 | export const listCustomers = /* GraphQL */ ` 159 | query ListCustomers( 160 | $filter: ModelCustomerFilterInput 161 | $limit: Int 162 | $nextToken: String 163 | ) { 164 | listCustomers(filter: $filter, limit: $limit, nextToken: $nextToken) { 165 | items { 166 | id 167 | firstName 168 | lastName 169 | active 170 | address 171 | _version 172 | _deleted 173 | _lastChangedAt 174 | version 175 | owner 176 | } 177 | nextToken 178 | startedAt 179 | } 180 | } 181 | `; 182 | export const syncCustomers = /* GraphQL */ ` 183 | query SyncCustomers( 184 | $filter: ModelCustomerFilterInput 185 | $limit: Int 186 | $nextToken: String 187 | $lastSync: AWSTimestamp 188 | ) { 189 | syncCustomers( 190 | filter: $filter 191 | limit: $limit 192 | nextToken: $nextToken 193 | lastSync: $lastSync 194 | ) { 195 | items { 196 | id 197 | firstName 198 | lastName 199 | active 200 | address 201 | _version 202 | _deleted 203 | _lastChangedAt 204 | version 205 | owner 206 | } 207 | nextToken 208 | startedAt 209 | } 210 | } 211 | `; 212 | -------------------------------------------------------------------------------- /frontend-example/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" : "syncProducts", 19 | "description" : null, 20 | "args" : [ { 21 | "name" : "filter", 22 | "description" : null, 23 | "type" : { 24 | "kind" : "INPUT_OBJECT", 25 | "name" : "ModelProductFilterInput", 26 | "ofType" : null 27 | }, 28 | "defaultValue" : null 29 | }, { 30 | "name" : "limit", 31 | "description" : null, 32 | "type" : { 33 | "kind" : "SCALAR", 34 | "name" : "Int", 35 | "ofType" : null 36 | }, 37 | "defaultValue" : null 38 | }, { 39 | "name" : "nextToken", 40 | "description" : null, 41 | "type" : { 42 | "kind" : "SCALAR", 43 | "name" : "String", 44 | "ofType" : null 45 | }, 46 | "defaultValue" : null 47 | }, { 48 | "name" : "lastSync", 49 | "description" : null, 50 | "type" : { 51 | "kind" : "SCALAR", 52 | "name" : "AWSTimestamp", 53 | "ofType" : null 54 | }, 55 | "defaultValue" : null 56 | } ], 57 | "type" : { 58 | "kind" : "OBJECT", 59 | "name" : "ModelProductConnection", 60 | "ofType" : null 61 | }, 62 | "isDeprecated" : false, 63 | "deprecationReason" : null 64 | }, { 65 | "name" : "getProduct", 66 | "description" : null, 67 | "args" : [ { 68 | "name" : "id", 69 | "description" : null, 70 | "type" : { 71 | "kind" : "NON_NULL", 72 | "name" : null, 73 | "ofType" : { 74 | "kind" : "SCALAR", 75 | "name" : "ID", 76 | "ofType" : null 77 | } 78 | }, 79 | "defaultValue" : null 80 | } ], 81 | "type" : { 82 | "kind" : "OBJECT", 83 | "name" : "Product", 84 | "ofType" : null 85 | }, 86 | "isDeprecated" : false, 87 | "deprecationReason" : null 88 | }, { 89 | "name" : "listProducts", 90 | "description" : null, 91 | "args" : [ { 92 | "name" : "filter", 93 | "description" : null, 94 | "type" : { 95 | "kind" : "INPUT_OBJECT", 96 | "name" : "ModelProductFilterInput", 97 | "ofType" : null 98 | }, 99 | "defaultValue" : null 100 | }, { 101 | "name" : "limit", 102 | "description" : null, 103 | "type" : { 104 | "kind" : "SCALAR", 105 | "name" : "Int", 106 | "ofType" : null 107 | }, 108 | "defaultValue" : null 109 | }, { 110 | "name" : "nextToken", 111 | "description" : null, 112 | "type" : { 113 | "kind" : "SCALAR", 114 | "name" : "String", 115 | "ofType" : null 116 | }, 117 | "defaultValue" : null 118 | } ], 119 | "type" : { 120 | "kind" : "OBJECT", 121 | "name" : "ModelProductConnection", 122 | "ofType" : null 123 | }, 124 | "isDeprecated" : false, 125 | "deprecationReason" : null 126 | }, { 127 | "name" : "syncOrders", 128 | "description" : null, 129 | "args" : [ { 130 | "name" : "filter", 131 | "description" : null, 132 | "type" : { 133 | "kind" : "INPUT_OBJECT", 134 | "name" : "ModelOrderFilterInput", 135 | "ofType" : null 136 | }, 137 | "defaultValue" : null 138 | }, { 139 | "name" : "limit", 140 | "description" : null, 141 | "type" : { 142 | "kind" : "SCALAR", 143 | "name" : "Int", 144 | "ofType" : null 145 | }, 146 | "defaultValue" : null 147 | }, { 148 | "name" : "nextToken", 149 | "description" : null, 150 | "type" : { 151 | "kind" : "SCALAR", 152 | "name" : "String", 153 | "ofType" : null 154 | }, 155 | "defaultValue" : null 156 | }, { 157 | "name" : "lastSync", 158 | "description" : null, 159 | "type" : { 160 | "kind" : "SCALAR", 161 | "name" : "AWSTimestamp", 162 | "ofType" : null 163 | }, 164 | "defaultValue" : null 165 | } ], 166 | "type" : { 167 | "kind" : "OBJECT", 168 | "name" : "ModelOrderConnection", 169 | "ofType" : null 170 | }, 171 | "isDeprecated" : false, 172 | "deprecationReason" : null 173 | }, { 174 | "name" : "getOrder", 175 | "description" : null, 176 | "args" : [ { 177 | "name" : "id", 178 | "description" : null, 179 | "type" : { 180 | "kind" : "NON_NULL", 181 | "name" : null, 182 | "ofType" : { 183 | "kind" : "SCALAR", 184 | "name" : "ID", 185 | "ofType" : null 186 | } 187 | }, 188 | "defaultValue" : null 189 | }, { 190 | "name" : "productID", 191 | "description" : null, 192 | "type" : { 193 | "kind" : "NON_NULL", 194 | "name" : null, 195 | "ofType" : { 196 | "kind" : "SCALAR", 197 | "name" : "ID", 198 | "ofType" : null 199 | } 200 | }, 201 | "defaultValue" : null 202 | } ], 203 | "type" : { 204 | "kind" : "OBJECT", 205 | "name" : "Order", 206 | "ofType" : null 207 | }, 208 | "isDeprecated" : false, 209 | "deprecationReason" : null 210 | }, { 211 | "name" : "listOrders", 212 | "description" : null, 213 | "args" : [ { 214 | "name" : "id", 215 | "description" : null, 216 | "type" : { 217 | "kind" : "SCALAR", 218 | "name" : "ID", 219 | "ofType" : null 220 | }, 221 | "defaultValue" : null 222 | }, { 223 | "name" : "productID", 224 | "description" : null, 225 | "type" : { 226 | "kind" : "INPUT_OBJECT", 227 | "name" : "ModelIDKeyConditionInput", 228 | "ofType" : null 229 | }, 230 | "defaultValue" : null 231 | }, { 232 | "name" : "filter", 233 | "description" : null, 234 | "type" : { 235 | "kind" : "INPUT_OBJECT", 236 | "name" : "ModelOrderFilterInput", 237 | "ofType" : null 238 | }, 239 | "defaultValue" : null 240 | }, { 241 | "name" : "limit", 242 | "description" : null, 243 | "type" : { 244 | "kind" : "SCALAR", 245 | "name" : "Int", 246 | "ofType" : null 247 | }, 248 | "defaultValue" : null 249 | }, { 250 | "name" : "nextToken", 251 | "description" : null, 252 | "type" : { 253 | "kind" : "SCALAR", 254 | "name" : "String", 255 | "ofType" : null 256 | }, 257 | "defaultValue" : null 258 | }, { 259 | "name" : "sortDirection", 260 | "description" : null, 261 | "type" : { 262 | "kind" : "ENUM", 263 | "name" : "ModelSortDirection", 264 | "ofType" : null 265 | }, 266 | "defaultValue" : null 267 | } ], 268 | "type" : { 269 | "kind" : "OBJECT", 270 | "name" : "ModelOrderConnection", 271 | "ofType" : null 272 | }, 273 | "isDeprecated" : false, 274 | "deprecationReason" : null 275 | }, { 276 | "name" : "getCustomer", 277 | "description" : null, 278 | "args" : [ { 279 | "name" : "id", 280 | "description" : null, 281 | "type" : { 282 | "kind" : "NON_NULL", 283 | "name" : null, 284 | "ofType" : { 285 | "kind" : "SCALAR", 286 | "name" : "ID", 287 | "ofType" : null 288 | } 289 | }, 290 | "defaultValue" : null 291 | } ], 292 | "type" : { 293 | "kind" : "OBJECT", 294 | "name" : "Customer", 295 | "ofType" : null 296 | }, 297 | "isDeprecated" : false, 298 | "deprecationReason" : null 299 | }, { 300 | "name" : "listCustomers", 301 | "description" : null, 302 | "args" : [ { 303 | "name" : "filter", 304 | "description" : null, 305 | "type" : { 306 | "kind" : "INPUT_OBJECT", 307 | "name" : "ModelCustomerFilterInput", 308 | "ofType" : null 309 | }, 310 | "defaultValue" : null 311 | }, { 312 | "name" : "limit", 313 | "description" : null, 314 | "type" : { 315 | "kind" : "SCALAR", 316 | "name" : "Int", 317 | "ofType" : null 318 | }, 319 | "defaultValue" : null 320 | }, { 321 | "name" : "nextToken", 322 | "description" : null, 323 | "type" : { 324 | "kind" : "SCALAR", 325 | "name" : "String", 326 | "ofType" : null 327 | }, 328 | "defaultValue" : null 329 | } ], 330 | "type" : { 331 | "kind" : "OBJECT", 332 | "name" : "ModelCustomerConnection", 333 | "ofType" : null 334 | }, 335 | "isDeprecated" : false, 336 | "deprecationReason" : null 337 | }, { 338 | "name" : "syncCustomers", 339 | "description" : null, 340 | "args" : [ { 341 | "name" : "filter", 342 | "description" : null, 343 | "type" : { 344 | "kind" : "INPUT_OBJECT", 345 | "name" : "ModelCustomerFilterInput", 346 | "ofType" : null 347 | }, 348 | "defaultValue" : null 349 | }, { 350 | "name" : "limit", 351 | "description" : null, 352 | "type" : { 353 | "kind" : "SCALAR", 354 | "name" : "Int", 355 | "ofType" : null 356 | }, 357 | "defaultValue" : null 358 | }, { 359 | "name" : "nextToken", 360 | "description" : null, 361 | "type" : { 362 | "kind" : "SCALAR", 363 | "name" : "String", 364 | "ofType" : null 365 | }, 366 | "defaultValue" : null 367 | }, { 368 | "name" : "lastSync", 369 | "description" : null, 370 | "type" : { 371 | "kind" : "SCALAR", 372 | "name" : "AWSTimestamp", 373 | "ofType" : null 374 | }, 375 | "defaultValue" : null 376 | } ], 377 | "type" : { 378 | "kind" : "OBJECT", 379 | "name" : "ModelCustomerConnection", 380 | "ofType" : null 381 | }, 382 | "isDeprecated" : false, 383 | "deprecationReason" : null 384 | } ], 385 | "inputFields" : null, 386 | "interfaces" : [ ], 387 | "enumValues" : null, 388 | "possibleTypes" : null 389 | }, { 390 | "kind" : "OBJECT", 391 | "name" : "ModelProductConnection", 392 | "description" : null, 393 | "fields" : [ { 394 | "name" : "items", 395 | "description" : null, 396 | "args" : [ ], 397 | "type" : { 398 | "kind" : "LIST", 399 | "name" : null, 400 | "ofType" : { 401 | "kind" : "OBJECT", 402 | "name" : "Product", 403 | "ofType" : null 404 | } 405 | }, 406 | "isDeprecated" : false, 407 | "deprecationReason" : null 408 | }, { 409 | "name" : "nextToken", 410 | "description" : null, 411 | "args" : [ ], 412 | "type" : { 413 | "kind" : "SCALAR", 414 | "name" : "String", 415 | "ofType" : null 416 | }, 417 | "isDeprecated" : false, 418 | "deprecationReason" : null 419 | }, { 420 | "name" : "startedAt", 421 | "description" : null, 422 | "args" : [ ], 423 | "type" : { 424 | "kind" : "SCALAR", 425 | "name" : "AWSTimestamp", 426 | "ofType" : null 427 | }, 428 | "isDeprecated" : false, 429 | "deprecationReason" : null 430 | } ], 431 | "inputFields" : null, 432 | "interfaces" : [ ], 433 | "enumValues" : null, 434 | "possibleTypes" : null 435 | }, { 436 | "kind" : "OBJECT", 437 | "name" : "Product", 438 | "description" : null, 439 | "fields" : [ { 440 | "name" : "id", 441 | "description" : null, 442 | "args" : [ ], 443 | "type" : { 444 | "kind" : "NON_NULL", 445 | "name" : null, 446 | "ofType" : { 447 | "kind" : "SCALAR", 448 | "name" : "ID", 449 | "ofType" : null 450 | } 451 | }, 452 | "isDeprecated" : false, 453 | "deprecationReason" : null 454 | }, { 455 | "name" : "name", 456 | "description" : null, 457 | "args" : [ ], 458 | "type" : { 459 | "kind" : "NON_NULL", 460 | "name" : null, 461 | "ofType" : { 462 | "kind" : "SCALAR", 463 | "name" : "String", 464 | "ofType" : null 465 | } 466 | }, 467 | "isDeprecated" : false, 468 | "deprecationReason" : null 469 | }, { 470 | "name" : "description", 471 | "description" : null, 472 | "args" : [ ], 473 | "type" : { 474 | "kind" : "NON_NULL", 475 | "name" : null, 476 | "ofType" : { 477 | "kind" : "SCALAR", 478 | "name" : "String", 479 | "ofType" : null 480 | } 481 | }, 482 | "isDeprecated" : false, 483 | "deprecationReason" : null 484 | }, { 485 | "name" : "price", 486 | "description" : null, 487 | "args" : [ ], 488 | "type" : { 489 | "kind" : "NON_NULL", 490 | "name" : null, 491 | "ofType" : { 492 | "kind" : "SCALAR", 493 | "name" : "String", 494 | "ofType" : null 495 | } 496 | }, 497 | "isDeprecated" : false, 498 | "deprecationReason" : null 499 | }, { 500 | "name" : "active", 501 | "description" : null, 502 | "args" : [ ], 503 | "type" : { 504 | "kind" : "NON_NULL", 505 | "name" : null, 506 | "ofType" : { 507 | "kind" : "SCALAR", 508 | "name" : "Boolean", 509 | "ofType" : null 510 | } 511 | }, 512 | "isDeprecated" : false, 513 | "deprecationReason" : null 514 | }, { 515 | "name" : "added", 516 | "description" : null, 517 | "args" : [ ], 518 | "type" : { 519 | "kind" : "NON_NULL", 520 | "name" : null, 521 | "ofType" : { 522 | "kind" : "SCALAR", 523 | "name" : "AWSDateTime", 524 | "ofType" : null 525 | } 526 | }, 527 | "isDeprecated" : false, 528 | "deprecationReason" : null 529 | }, { 530 | "name" : "_version", 531 | "description" : null, 532 | "args" : [ ], 533 | "type" : { 534 | "kind" : "NON_NULL", 535 | "name" : null, 536 | "ofType" : { 537 | "kind" : "SCALAR", 538 | "name" : "Int", 539 | "ofType" : null 540 | } 541 | }, 542 | "isDeprecated" : false, 543 | "deprecationReason" : null 544 | }, { 545 | "name" : "_deleted", 546 | "description" : null, 547 | "args" : [ ], 548 | "type" : { 549 | "kind" : "SCALAR", 550 | "name" : "Boolean", 551 | "ofType" : null 552 | }, 553 | "isDeprecated" : false, 554 | "deprecationReason" : null 555 | }, { 556 | "name" : "_lastChangedAt", 557 | "description" : null, 558 | "args" : [ ], 559 | "type" : { 560 | "kind" : "NON_NULL", 561 | "name" : null, 562 | "ofType" : { 563 | "kind" : "SCALAR", 564 | "name" : "AWSTimestamp", 565 | "ofType" : null 566 | } 567 | }, 568 | "isDeprecated" : false, 569 | "deprecationReason" : null 570 | } ], 571 | "inputFields" : null, 572 | "interfaces" : [ ], 573 | "enumValues" : null, 574 | "possibleTypes" : null 575 | }, { 576 | "kind" : "SCALAR", 577 | "name" : "ID", 578 | "description" : "Built-in ID", 579 | "fields" : null, 580 | "inputFields" : null, 581 | "interfaces" : null, 582 | "enumValues" : null, 583 | "possibleTypes" : null 584 | }, { 585 | "kind" : "SCALAR", 586 | "name" : "String", 587 | "description" : "Built-in String", 588 | "fields" : null, 589 | "inputFields" : null, 590 | "interfaces" : null, 591 | "enumValues" : null, 592 | "possibleTypes" : null 593 | }, { 594 | "kind" : "SCALAR", 595 | "name" : "Boolean", 596 | "description" : "Built-in Boolean", 597 | "fields" : null, 598 | "inputFields" : null, 599 | "interfaces" : null, 600 | "enumValues" : null, 601 | "possibleTypes" : null 602 | }, { 603 | "kind" : "SCALAR", 604 | "name" : "AWSDateTime", 605 | "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.", 606 | "fields" : null, 607 | "inputFields" : null, 608 | "interfaces" : null, 609 | "enumValues" : null, 610 | "possibleTypes" : null 611 | }, { 612 | "kind" : "SCALAR", 613 | "name" : "Int", 614 | "description" : "Built-in Int", 615 | "fields" : null, 616 | "inputFields" : null, 617 | "interfaces" : null, 618 | "enumValues" : null, 619 | "possibleTypes" : null 620 | }, { 621 | "kind" : "SCALAR", 622 | "name" : "AWSTimestamp", 623 | "description" : "The `AWSTimestamp` scalar type provided by AWS AppSync, represents the number of seconds that have elapsed since `1970-01-01T00:00Z`. Negative values are also accepted and these represent the number of seconds till `1970-01-01T00:00Z`. Timestamps are serialized and deserialized as integers. The minimum supported timestamp value is **`-31557014167219200`** which corresponds to `-1000000000-01-01T00:00Z`. The maximum supported timestamp value is **`31556889864403199`** which corresponds to `1000000000-12-31T23:59:59.999999999Z`.", 624 | "fields" : null, 625 | "inputFields" : null, 626 | "interfaces" : null, 627 | "enumValues" : null, 628 | "possibleTypes" : null 629 | }, { 630 | "kind" : "INPUT_OBJECT", 631 | "name" : "ModelProductFilterInput", 632 | "description" : null, 633 | "fields" : null, 634 | "inputFields" : [ { 635 | "name" : "id", 636 | "description" : null, 637 | "type" : { 638 | "kind" : "INPUT_OBJECT", 639 | "name" : "ModelIDInput", 640 | "ofType" : null 641 | }, 642 | "defaultValue" : null 643 | }, { 644 | "name" : "name", 645 | "description" : null, 646 | "type" : { 647 | "kind" : "INPUT_OBJECT", 648 | "name" : "ModelStringInput", 649 | "ofType" : null 650 | }, 651 | "defaultValue" : null 652 | }, { 653 | "name" : "description", 654 | "description" : null, 655 | "type" : { 656 | "kind" : "INPUT_OBJECT", 657 | "name" : "ModelStringInput", 658 | "ofType" : null 659 | }, 660 | "defaultValue" : null 661 | }, { 662 | "name" : "price", 663 | "description" : null, 664 | "type" : { 665 | "kind" : "INPUT_OBJECT", 666 | "name" : "ModelStringInput", 667 | "ofType" : null 668 | }, 669 | "defaultValue" : null 670 | }, { 671 | "name" : "active", 672 | "description" : null, 673 | "type" : { 674 | "kind" : "INPUT_OBJECT", 675 | "name" : "ModelBooleanInput", 676 | "ofType" : null 677 | }, 678 | "defaultValue" : null 679 | }, { 680 | "name" : "added", 681 | "description" : null, 682 | "type" : { 683 | "kind" : "INPUT_OBJECT", 684 | "name" : "ModelStringInput", 685 | "ofType" : null 686 | }, 687 | "defaultValue" : null 688 | }, { 689 | "name" : "and", 690 | "description" : null, 691 | "type" : { 692 | "kind" : "LIST", 693 | "name" : null, 694 | "ofType" : { 695 | "kind" : "INPUT_OBJECT", 696 | "name" : "ModelProductFilterInput", 697 | "ofType" : null 698 | } 699 | }, 700 | "defaultValue" : null 701 | }, { 702 | "name" : "or", 703 | "description" : null, 704 | "type" : { 705 | "kind" : "LIST", 706 | "name" : null, 707 | "ofType" : { 708 | "kind" : "INPUT_OBJECT", 709 | "name" : "ModelProductFilterInput", 710 | "ofType" : null 711 | } 712 | }, 713 | "defaultValue" : null 714 | }, { 715 | "name" : "not", 716 | "description" : null, 717 | "type" : { 718 | "kind" : "INPUT_OBJECT", 719 | "name" : "ModelProductFilterInput", 720 | "ofType" : null 721 | }, 722 | "defaultValue" : null 723 | } ], 724 | "interfaces" : null, 725 | "enumValues" : null, 726 | "possibleTypes" : null 727 | }, { 728 | "kind" : "INPUT_OBJECT", 729 | "name" : "ModelIDInput", 730 | "description" : null, 731 | "fields" : null, 732 | "inputFields" : [ { 733 | "name" : "ne", 734 | "description" : null, 735 | "type" : { 736 | "kind" : "SCALAR", 737 | "name" : "ID", 738 | "ofType" : null 739 | }, 740 | "defaultValue" : null 741 | }, { 742 | "name" : "eq", 743 | "description" : null, 744 | "type" : { 745 | "kind" : "SCALAR", 746 | "name" : "ID", 747 | "ofType" : null 748 | }, 749 | "defaultValue" : null 750 | }, { 751 | "name" : "le", 752 | "description" : null, 753 | "type" : { 754 | "kind" : "SCALAR", 755 | "name" : "ID", 756 | "ofType" : null 757 | }, 758 | "defaultValue" : null 759 | }, { 760 | "name" : "lt", 761 | "description" : null, 762 | "type" : { 763 | "kind" : "SCALAR", 764 | "name" : "ID", 765 | "ofType" : null 766 | }, 767 | "defaultValue" : null 768 | }, { 769 | "name" : "ge", 770 | "description" : null, 771 | "type" : { 772 | "kind" : "SCALAR", 773 | "name" : "ID", 774 | "ofType" : null 775 | }, 776 | "defaultValue" : null 777 | }, { 778 | "name" : "gt", 779 | "description" : null, 780 | "type" : { 781 | "kind" : "SCALAR", 782 | "name" : "ID", 783 | "ofType" : null 784 | }, 785 | "defaultValue" : null 786 | }, { 787 | "name" : "contains", 788 | "description" : null, 789 | "type" : { 790 | "kind" : "SCALAR", 791 | "name" : "ID", 792 | "ofType" : null 793 | }, 794 | "defaultValue" : null 795 | }, { 796 | "name" : "notContains", 797 | "description" : null, 798 | "type" : { 799 | "kind" : "SCALAR", 800 | "name" : "ID", 801 | "ofType" : null 802 | }, 803 | "defaultValue" : null 804 | }, { 805 | "name" : "between", 806 | "description" : null, 807 | "type" : { 808 | "kind" : "LIST", 809 | "name" : null, 810 | "ofType" : { 811 | "kind" : "SCALAR", 812 | "name" : "ID", 813 | "ofType" : null 814 | } 815 | }, 816 | "defaultValue" : null 817 | }, { 818 | "name" : "beginsWith", 819 | "description" : null, 820 | "type" : { 821 | "kind" : "SCALAR", 822 | "name" : "ID", 823 | "ofType" : null 824 | }, 825 | "defaultValue" : null 826 | }, { 827 | "name" : "attributeExists", 828 | "description" : null, 829 | "type" : { 830 | "kind" : "SCALAR", 831 | "name" : "Boolean", 832 | "ofType" : null 833 | }, 834 | "defaultValue" : null 835 | }, { 836 | "name" : "attributeType", 837 | "description" : null, 838 | "type" : { 839 | "kind" : "ENUM", 840 | "name" : "ModelAttributeTypes", 841 | "ofType" : null 842 | }, 843 | "defaultValue" : null 844 | }, { 845 | "name" : "size", 846 | "description" : null, 847 | "type" : { 848 | "kind" : "INPUT_OBJECT", 849 | "name" : "ModelSizeInput", 850 | "ofType" : null 851 | }, 852 | "defaultValue" : null 853 | } ], 854 | "interfaces" : null, 855 | "enumValues" : null, 856 | "possibleTypes" : null 857 | }, { 858 | "kind" : "ENUM", 859 | "name" : "ModelAttributeTypes", 860 | "description" : null, 861 | "fields" : null, 862 | "inputFields" : null, 863 | "interfaces" : null, 864 | "enumValues" : [ { 865 | "name" : "binary", 866 | "description" : null, 867 | "isDeprecated" : false, 868 | "deprecationReason" : null 869 | }, { 870 | "name" : "binarySet", 871 | "description" : null, 872 | "isDeprecated" : false, 873 | "deprecationReason" : null 874 | }, { 875 | "name" : "bool", 876 | "description" : null, 877 | "isDeprecated" : false, 878 | "deprecationReason" : null 879 | }, { 880 | "name" : "list", 881 | "description" : null, 882 | "isDeprecated" : false, 883 | "deprecationReason" : null 884 | }, { 885 | "name" : "map", 886 | "description" : null, 887 | "isDeprecated" : false, 888 | "deprecationReason" : null 889 | }, { 890 | "name" : "number", 891 | "description" : null, 892 | "isDeprecated" : false, 893 | "deprecationReason" : null 894 | }, { 895 | "name" : "numberSet", 896 | "description" : null, 897 | "isDeprecated" : false, 898 | "deprecationReason" : null 899 | }, { 900 | "name" : "string", 901 | "description" : null, 902 | "isDeprecated" : false, 903 | "deprecationReason" : null 904 | }, { 905 | "name" : "stringSet", 906 | "description" : null, 907 | "isDeprecated" : false, 908 | "deprecationReason" : null 909 | }, { 910 | "name" : "_null", 911 | "description" : null, 912 | "isDeprecated" : false, 913 | "deprecationReason" : null 914 | } ], 915 | "possibleTypes" : null 916 | }, { 917 | "kind" : "INPUT_OBJECT", 918 | "name" : "ModelSizeInput", 919 | "description" : null, 920 | "fields" : null, 921 | "inputFields" : [ { 922 | "name" : "ne", 923 | "description" : null, 924 | "type" : { 925 | "kind" : "SCALAR", 926 | "name" : "Int", 927 | "ofType" : null 928 | }, 929 | "defaultValue" : null 930 | }, { 931 | "name" : "eq", 932 | "description" : null, 933 | "type" : { 934 | "kind" : "SCALAR", 935 | "name" : "Int", 936 | "ofType" : null 937 | }, 938 | "defaultValue" : null 939 | }, { 940 | "name" : "le", 941 | "description" : null, 942 | "type" : { 943 | "kind" : "SCALAR", 944 | "name" : "Int", 945 | "ofType" : null 946 | }, 947 | "defaultValue" : null 948 | }, { 949 | "name" : "lt", 950 | "description" : null, 951 | "type" : { 952 | "kind" : "SCALAR", 953 | "name" : "Int", 954 | "ofType" : null 955 | }, 956 | "defaultValue" : null 957 | }, { 958 | "name" : "ge", 959 | "description" : null, 960 | "type" : { 961 | "kind" : "SCALAR", 962 | "name" : "Int", 963 | "ofType" : null 964 | }, 965 | "defaultValue" : null 966 | }, { 967 | "name" : "gt", 968 | "description" : null, 969 | "type" : { 970 | "kind" : "SCALAR", 971 | "name" : "Int", 972 | "ofType" : null 973 | }, 974 | "defaultValue" : null 975 | }, { 976 | "name" : "between", 977 | "description" : null, 978 | "type" : { 979 | "kind" : "LIST", 980 | "name" : null, 981 | "ofType" : { 982 | "kind" : "SCALAR", 983 | "name" : "Int", 984 | "ofType" : null 985 | } 986 | }, 987 | "defaultValue" : null 988 | } ], 989 | "interfaces" : null, 990 | "enumValues" : null, 991 | "possibleTypes" : null 992 | }, { 993 | "kind" : "INPUT_OBJECT", 994 | "name" : "ModelStringInput", 995 | "description" : null, 996 | "fields" : null, 997 | "inputFields" : [ { 998 | "name" : "ne", 999 | "description" : null, 1000 | "type" : { 1001 | "kind" : "SCALAR", 1002 | "name" : "String", 1003 | "ofType" : null 1004 | }, 1005 | "defaultValue" : null 1006 | }, { 1007 | "name" : "eq", 1008 | "description" : null, 1009 | "type" : { 1010 | "kind" : "SCALAR", 1011 | "name" : "String", 1012 | "ofType" : null 1013 | }, 1014 | "defaultValue" : null 1015 | }, { 1016 | "name" : "le", 1017 | "description" : null, 1018 | "type" : { 1019 | "kind" : "SCALAR", 1020 | "name" : "String", 1021 | "ofType" : null 1022 | }, 1023 | "defaultValue" : null 1024 | }, { 1025 | "name" : "lt", 1026 | "description" : null, 1027 | "type" : { 1028 | "kind" : "SCALAR", 1029 | "name" : "String", 1030 | "ofType" : null 1031 | }, 1032 | "defaultValue" : null 1033 | }, { 1034 | "name" : "ge", 1035 | "description" : null, 1036 | "type" : { 1037 | "kind" : "SCALAR", 1038 | "name" : "String", 1039 | "ofType" : null 1040 | }, 1041 | "defaultValue" : null 1042 | }, { 1043 | "name" : "gt", 1044 | "description" : null, 1045 | "type" : { 1046 | "kind" : "SCALAR", 1047 | "name" : "String", 1048 | "ofType" : null 1049 | }, 1050 | "defaultValue" : null 1051 | }, { 1052 | "name" : "contains", 1053 | "description" : null, 1054 | "type" : { 1055 | "kind" : "SCALAR", 1056 | "name" : "String", 1057 | "ofType" : null 1058 | }, 1059 | "defaultValue" : null 1060 | }, { 1061 | "name" : "notContains", 1062 | "description" : null, 1063 | "type" : { 1064 | "kind" : "SCALAR", 1065 | "name" : "String", 1066 | "ofType" : null 1067 | }, 1068 | "defaultValue" : null 1069 | }, { 1070 | "name" : "between", 1071 | "description" : null, 1072 | "type" : { 1073 | "kind" : "LIST", 1074 | "name" : null, 1075 | "ofType" : { 1076 | "kind" : "SCALAR", 1077 | "name" : "String", 1078 | "ofType" : null 1079 | } 1080 | }, 1081 | "defaultValue" : null 1082 | }, { 1083 | "name" : "beginsWith", 1084 | "description" : null, 1085 | "type" : { 1086 | "kind" : "SCALAR", 1087 | "name" : "String", 1088 | "ofType" : null 1089 | }, 1090 | "defaultValue" : null 1091 | }, { 1092 | "name" : "attributeExists", 1093 | "description" : null, 1094 | "type" : { 1095 | "kind" : "SCALAR", 1096 | "name" : "Boolean", 1097 | "ofType" : null 1098 | }, 1099 | "defaultValue" : null 1100 | }, { 1101 | "name" : "attributeType", 1102 | "description" : null, 1103 | "type" : { 1104 | "kind" : "ENUM", 1105 | "name" : "ModelAttributeTypes", 1106 | "ofType" : null 1107 | }, 1108 | "defaultValue" : null 1109 | }, { 1110 | "name" : "size", 1111 | "description" : null, 1112 | "type" : { 1113 | "kind" : "INPUT_OBJECT", 1114 | "name" : "ModelSizeInput", 1115 | "ofType" : null 1116 | }, 1117 | "defaultValue" : null 1118 | } ], 1119 | "interfaces" : null, 1120 | "enumValues" : null, 1121 | "possibleTypes" : null 1122 | }, { 1123 | "kind" : "INPUT_OBJECT", 1124 | "name" : "ModelBooleanInput", 1125 | "description" : null, 1126 | "fields" : null, 1127 | "inputFields" : [ { 1128 | "name" : "ne", 1129 | "description" : null, 1130 | "type" : { 1131 | "kind" : "SCALAR", 1132 | "name" : "Boolean", 1133 | "ofType" : null 1134 | }, 1135 | "defaultValue" : null 1136 | }, { 1137 | "name" : "eq", 1138 | "description" : null, 1139 | "type" : { 1140 | "kind" : "SCALAR", 1141 | "name" : "Boolean", 1142 | "ofType" : null 1143 | }, 1144 | "defaultValue" : null 1145 | }, { 1146 | "name" : "attributeExists", 1147 | "description" : null, 1148 | "type" : { 1149 | "kind" : "SCALAR", 1150 | "name" : "Boolean", 1151 | "ofType" : null 1152 | }, 1153 | "defaultValue" : null 1154 | }, { 1155 | "name" : "attributeType", 1156 | "description" : null, 1157 | "type" : { 1158 | "kind" : "ENUM", 1159 | "name" : "ModelAttributeTypes", 1160 | "ofType" : null 1161 | }, 1162 | "defaultValue" : null 1163 | } ], 1164 | "interfaces" : null, 1165 | "enumValues" : null, 1166 | "possibleTypes" : null 1167 | }, { 1168 | "kind" : "OBJECT", 1169 | "name" : "ModelOrderConnection", 1170 | "description" : null, 1171 | "fields" : [ { 1172 | "name" : "items", 1173 | "description" : null, 1174 | "args" : [ ], 1175 | "type" : { 1176 | "kind" : "LIST", 1177 | "name" : null, 1178 | "ofType" : { 1179 | "kind" : "OBJECT", 1180 | "name" : "Order", 1181 | "ofType" : null 1182 | } 1183 | }, 1184 | "isDeprecated" : false, 1185 | "deprecationReason" : null 1186 | }, { 1187 | "name" : "nextToken", 1188 | "description" : null, 1189 | "args" : [ ], 1190 | "type" : { 1191 | "kind" : "SCALAR", 1192 | "name" : "String", 1193 | "ofType" : null 1194 | }, 1195 | "isDeprecated" : false, 1196 | "deprecationReason" : null 1197 | }, { 1198 | "name" : "startedAt", 1199 | "description" : null, 1200 | "args" : [ ], 1201 | "type" : { 1202 | "kind" : "SCALAR", 1203 | "name" : "AWSTimestamp", 1204 | "ofType" : null 1205 | }, 1206 | "isDeprecated" : false, 1207 | "deprecationReason" : null 1208 | } ], 1209 | "inputFields" : null, 1210 | "interfaces" : [ ], 1211 | "enumValues" : null, 1212 | "possibleTypes" : null 1213 | }, { 1214 | "kind" : "OBJECT", 1215 | "name" : "Order", 1216 | "description" : null, 1217 | "fields" : [ { 1218 | "name" : "id", 1219 | "description" : null, 1220 | "args" : [ ], 1221 | "type" : { 1222 | "kind" : "NON_NULL", 1223 | "name" : null, 1224 | "ofType" : { 1225 | "kind" : "SCALAR", 1226 | "name" : "ID", 1227 | "ofType" : null 1228 | } 1229 | }, 1230 | "isDeprecated" : false, 1231 | "deprecationReason" : null 1232 | }, { 1233 | "name" : "productID", 1234 | "description" : null, 1235 | "args" : [ ], 1236 | "type" : { 1237 | "kind" : "NON_NULL", 1238 | "name" : null, 1239 | "ofType" : { 1240 | "kind" : "SCALAR", 1241 | "name" : "ID", 1242 | "ofType" : null 1243 | } 1244 | }, 1245 | "isDeprecated" : false, 1246 | "deprecationReason" : null 1247 | }, { 1248 | "name" : "total", 1249 | "description" : null, 1250 | "args" : [ ], 1251 | "type" : { 1252 | "kind" : "NON_NULL", 1253 | "name" : null, 1254 | "ofType" : { 1255 | "kind" : "SCALAR", 1256 | "name" : "String", 1257 | "ofType" : null 1258 | } 1259 | }, 1260 | "isDeprecated" : false, 1261 | "deprecationReason" : null 1262 | }, { 1263 | "name" : "ordered", 1264 | "description" : null, 1265 | "args" : [ ], 1266 | "type" : { 1267 | "kind" : "NON_NULL", 1268 | "name" : null, 1269 | "ofType" : { 1270 | "kind" : "SCALAR", 1271 | "name" : "AWSDateTime", 1272 | "ofType" : null 1273 | } 1274 | }, 1275 | "isDeprecated" : false, 1276 | "deprecationReason" : null 1277 | }, { 1278 | "name" : "_version", 1279 | "description" : null, 1280 | "args" : [ ], 1281 | "type" : { 1282 | "kind" : "NON_NULL", 1283 | "name" : null, 1284 | "ofType" : { 1285 | "kind" : "SCALAR", 1286 | "name" : "Int", 1287 | "ofType" : null 1288 | } 1289 | }, 1290 | "isDeprecated" : false, 1291 | "deprecationReason" : null 1292 | }, { 1293 | "name" : "_deleted", 1294 | "description" : null, 1295 | "args" : [ ], 1296 | "type" : { 1297 | "kind" : "SCALAR", 1298 | "name" : "Boolean", 1299 | "ofType" : null 1300 | }, 1301 | "isDeprecated" : false, 1302 | "deprecationReason" : null 1303 | }, { 1304 | "name" : "_lastChangedAt", 1305 | "description" : null, 1306 | "args" : [ ], 1307 | "type" : { 1308 | "kind" : "NON_NULL", 1309 | "name" : null, 1310 | "ofType" : { 1311 | "kind" : "SCALAR", 1312 | "name" : "AWSTimestamp", 1313 | "ofType" : null 1314 | } 1315 | }, 1316 | "isDeprecated" : false, 1317 | "deprecationReason" : null 1318 | } ], 1319 | "inputFields" : null, 1320 | "interfaces" : [ ], 1321 | "enumValues" : null, 1322 | "possibleTypes" : null 1323 | }, { 1324 | "kind" : "INPUT_OBJECT", 1325 | "name" : "ModelOrderFilterInput", 1326 | "description" : null, 1327 | "fields" : null, 1328 | "inputFields" : [ { 1329 | "name" : "id", 1330 | "description" : null, 1331 | "type" : { 1332 | "kind" : "INPUT_OBJECT", 1333 | "name" : "ModelIDInput", 1334 | "ofType" : null 1335 | }, 1336 | "defaultValue" : null 1337 | }, { 1338 | "name" : "productID", 1339 | "description" : null, 1340 | "type" : { 1341 | "kind" : "INPUT_OBJECT", 1342 | "name" : "ModelIDInput", 1343 | "ofType" : null 1344 | }, 1345 | "defaultValue" : null 1346 | }, { 1347 | "name" : "total", 1348 | "description" : null, 1349 | "type" : { 1350 | "kind" : "INPUT_OBJECT", 1351 | "name" : "ModelStringInput", 1352 | "ofType" : null 1353 | }, 1354 | "defaultValue" : null 1355 | }, { 1356 | "name" : "ordered", 1357 | "description" : null, 1358 | "type" : { 1359 | "kind" : "INPUT_OBJECT", 1360 | "name" : "ModelStringInput", 1361 | "ofType" : null 1362 | }, 1363 | "defaultValue" : null 1364 | }, { 1365 | "name" : "and", 1366 | "description" : null, 1367 | "type" : { 1368 | "kind" : "LIST", 1369 | "name" : null, 1370 | "ofType" : { 1371 | "kind" : "INPUT_OBJECT", 1372 | "name" : "ModelOrderFilterInput", 1373 | "ofType" : null 1374 | } 1375 | }, 1376 | "defaultValue" : null 1377 | }, { 1378 | "name" : "or", 1379 | "description" : null, 1380 | "type" : { 1381 | "kind" : "LIST", 1382 | "name" : null, 1383 | "ofType" : { 1384 | "kind" : "INPUT_OBJECT", 1385 | "name" : "ModelOrderFilterInput", 1386 | "ofType" : null 1387 | } 1388 | }, 1389 | "defaultValue" : null 1390 | }, { 1391 | "name" : "not", 1392 | "description" : null, 1393 | "type" : { 1394 | "kind" : "INPUT_OBJECT", 1395 | "name" : "ModelOrderFilterInput", 1396 | "ofType" : null 1397 | }, 1398 | "defaultValue" : null 1399 | } ], 1400 | "interfaces" : null, 1401 | "enumValues" : null, 1402 | "possibleTypes" : null 1403 | }, { 1404 | "kind" : "INPUT_OBJECT", 1405 | "name" : "ModelIDKeyConditionInput", 1406 | "description" : null, 1407 | "fields" : null, 1408 | "inputFields" : [ { 1409 | "name" : "eq", 1410 | "description" : null, 1411 | "type" : { 1412 | "kind" : "SCALAR", 1413 | "name" : "ID", 1414 | "ofType" : null 1415 | }, 1416 | "defaultValue" : null 1417 | }, { 1418 | "name" : "le", 1419 | "description" : null, 1420 | "type" : { 1421 | "kind" : "SCALAR", 1422 | "name" : "ID", 1423 | "ofType" : null 1424 | }, 1425 | "defaultValue" : null 1426 | }, { 1427 | "name" : "lt", 1428 | "description" : null, 1429 | "type" : { 1430 | "kind" : "SCALAR", 1431 | "name" : "ID", 1432 | "ofType" : null 1433 | }, 1434 | "defaultValue" : null 1435 | }, { 1436 | "name" : "ge", 1437 | "description" : null, 1438 | "type" : { 1439 | "kind" : "SCALAR", 1440 | "name" : "ID", 1441 | "ofType" : null 1442 | }, 1443 | "defaultValue" : null 1444 | }, { 1445 | "name" : "gt", 1446 | "description" : null, 1447 | "type" : { 1448 | "kind" : "SCALAR", 1449 | "name" : "ID", 1450 | "ofType" : null 1451 | }, 1452 | "defaultValue" : null 1453 | }, { 1454 | "name" : "between", 1455 | "description" : null, 1456 | "type" : { 1457 | "kind" : "LIST", 1458 | "name" : null, 1459 | "ofType" : { 1460 | "kind" : "SCALAR", 1461 | "name" : "ID", 1462 | "ofType" : null 1463 | } 1464 | }, 1465 | "defaultValue" : null 1466 | }, { 1467 | "name" : "beginsWith", 1468 | "description" : null, 1469 | "type" : { 1470 | "kind" : "SCALAR", 1471 | "name" : "ID", 1472 | "ofType" : null 1473 | }, 1474 | "defaultValue" : null 1475 | } ], 1476 | "interfaces" : null, 1477 | "enumValues" : null, 1478 | "possibleTypes" : null 1479 | }, { 1480 | "kind" : "ENUM", 1481 | "name" : "ModelSortDirection", 1482 | "description" : null, 1483 | "fields" : null, 1484 | "inputFields" : null, 1485 | "interfaces" : null, 1486 | "enumValues" : [ { 1487 | "name" : "ASC", 1488 | "description" : null, 1489 | "isDeprecated" : false, 1490 | "deprecationReason" : null 1491 | }, { 1492 | "name" : "DESC", 1493 | "description" : null, 1494 | "isDeprecated" : false, 1495 | "deprecationReason" : null 1496 | } ], 1497 | "possibleTypes" : null 1498 | }, { 1499 | "kind" : "OBJECT", 1500 | "name" : "Customer", 1501 | "description" : null, 1502 | "fields" : [ { 1503 | "name" : "id", 1504 | "description" : null, 1505 | "args" : [ ], 1506 | "type" : { 1507 | "kind" : "NON_NULL", 1508 | "name" : null, 1509 | "ofType" : { 1510 | "kind" : "SCALAR", 1511 | "name" : "ID", 1512 | "ofType" : null 1513 | } 1514 | }, 1515 | "isDeprecated" : false, 1516 | "deprecationReason" : null 1517 | }, { 1518 | "name" : "firstName", 1519 | "description" : null, 1520 | "args" : [ ], 1521 | "type" : { 1522 | "kind" : "NON_NULL", 1523 | "name" : null, 1524 | "ofType" : { 1525 | "kind" : "SCALAR", 1526 | "name" : "String", 1527 | "ofType" : null 1528 | } 1529 | }, 1530 | "isDeprecated" : false, 1531 | "deprecationReason" : null 1532 | }, { 1533 | "name" : "lastName", 1534 | "description" : null, 1535 | "args" : [ ], 1536 | "type" : { 1537 | "kind" : "NON_NULL", 1538 | "name" : null, 1539 | "ofType" : { 1540 | "kind" : "SCALAR", 1541 | "name" : "String", 1542 | "ofType" : null 1543 | } 1544 | }, 1545 | "isDeprecated" : false, 1546 | "deprecationReason" : null 1547 | }, { 1548 | "name" : "active", 1549 | "description" : null, 1550 | "args" : [ ], 1551 | "type" : { 1552 | "kind" : "NON_NULL", 1553 | "name" : null, 1554 | "ofType" : { 1555 | "kind" : "SCALAR", 1556 | "name" : "Boolean", 1557 | "ofType" : null 1558 | } 1559 | }, 1560 | "isDeprecated" : false, 1561 | "deprecationReason" : null 1562 | }, { 1563 | "name" : "address", 1564 | "description" : null, 1565 | "args" : [ ], 1566 | "type" : { 1567 | "kind" : "NON_NULL", 1568 | "name" : null, 1569 | "ofType" : { 1570 | "kind" : "SCALAR", 1571 | "name" : "String", 1572 | "ofType" : null 1573 | } 1574 | }, 1575 | "isDeprecated" : false, 1576 | "deprecationReason" : null 1577 | }, { 1578 | "name" : "_version", 1579 | "description" : null, 1580 | "args" : [ ], 1581 | "type" : { 1582 | "kind" : "NON_NULL", 1583 | "name" : null, 1584 | "ofType" : { 1585 | "kind" : "SCALAR", 1586 | "name" : "Int", 1587 | "ofType" : null 1588 | } 1589 | }, 1590 | "isDeprecated" : false, 1591 | "deprecationReason" : null 1592 | }, { 1593 | "name" : "_deleted", 1594 | "description" : null, 1595 | "args" : [ ], 1596 | "type" : { 1597 | "kind" : "SCALAR", 1598 | "name" : "Boolean", 1599 | "ofType" : null 1600 | }, 1601 | "isDeprecated" : false, 1602 | "deprecationReason" : null 1603 | }, { 1604 | "name" : "_lastChangedAt", 1605 | "description" : null, 1606 | "args" : [ ], 1607 | "type" : { 1608 | "kind" : "NON_NULL", 1609 | "name" : null, 1610 | "ofType" : { 1611 | "kind" : "SCALAR", 1612 | "name" : "AWSTimestamp", 1613 | "ofType" : null 1614 | } 1615 | }, 1616 | "isDeprecated" : false, 1617 | "deprecationReason" : null 1618 | }, { 1619 | "name" : "version", 1620 | "description" : null, 1621 | "args" : [ ], 1622 | "type" : { 1623 | "kind" : "NON_NULL", 1624 | "name" : null, 1625 | "ofType" : { 1626 | "kind" : "SCALAR", 1627 | "name" : "Int", 1628 | "ofType" : null 1629 | } 1630 | }, 1631 | "isDeprecated" : false, 1632 | "deprecationReason" : null 1633 | }, { 1634 | "name" : "owner", 1635 | "description" : null, 1636 | "args" : [ ], 1637 | "type" : { 1638 | "kind" : "SCALAR", 1639 | "name" : "String", 1640 | "ofType" : null 1641 | }, 1642 | "isDeprecated" : false, 1643 | "deprecationReason" : null 1644 | } ], 1645 | "inputFields" : null, 1646 | "interfaces" : [ ], 1647 | "enumValues" : null, 1648 | "possibleTypes" : null 1649 | }, { 1650 | "kind" : "OBJECT", 1651 | "name" : "ModelCustomerConnection", 1652 | "description" : null, 1653 | "fields" : [ { 1654 | "name" : "items", 1655 | "description" : null, 1656 | "args" : [ ], 1657 | "type" : { 1658 | "kind" : "LIST", 1659 | "name" : null, 1660 | "ofType" : { 1661 | "kind" : "OBJECT", 1662 | "name" : "Customer", 1663 | "ofType" : null 1664 | } 1665 | }, 1666 | "isDeprecated" : false, 1667 | "deprecationReason" : null 1668 | }, { 1669 | "name" : "nextToken", 1670 | "description" : null, 1671 | "args" : [ ], 1672 | "type" : { 1673 | "kind" : "SCALAR", 1674 | "name" : "String", 1675 | "ofType" : null 1676 | }, 1677 | "isDeprecated" : false, 1678 | "deprecationReason" : null 1679 | }, { 1680 | "name" : "startedAt", 1681 | "description" : null, 1682 | "args" : [ ], 1683 | "type" : { 1684 | "kind" : "SCALAR", 1685 | "name" : "AWSTimestamp", 1686 | "ofType" : null 1687 | }, 1688 | "isDeprecated" : false, 1689 | "deprecationReason" : null 1690 | } ], 1691 | "inputFields" : null, 1692 | "interfaces" : [ ], 1693 | "enumValues" : null, 1694 | "possibleTypes" : null 1695 | }, { 1696 | "kind" : "INPUT_OBJECT", 1697 | "name" : "ModelCustomerFilterInput", 1698 | "description" : null, 1699 | "fields" : null, 1700 | "inputFields" : [ { 1701 | "name" : "id", 1702 | "description" : null, 1703 | "type" : { 1704 | "kind" : "INPUT_OBJECT", 1705 | "name" : "ModelIDInput", 1706 | "ofType" : null 1707 | }, 1708 | "defaultValue" : null 1709 | }, { 1710 | "name" : "firstName", 1711 | "description" : null, 1712 | "type" : { 1713 | "kind" : "INPUT_OBJECT", 1714 | "name" : "ModelStringInput", 1715 | "ofType" : null 1716 | }, 1717 | "defaultValue" : null 1718 | }, { 1719 | "name" : "lastName", 1720 | "description" : null, 1721 | "type" : { 1722 | "kind" : "INPUT_OBJECT", 1723 | "name" : "ModelStringInput", 1724 | "ofType" : null 1725 | }, 1726 | "defaultValue" : null 1727 | }, { 1728 | "name" : "active", 1729 | "description" : null, 1730 | "type" : { 1731 | "kind" : "INPUT_OBJECT", 1732 | "name" : "ModelBooleanInput", 1733 | "ofType" : null 1734 | }, 1735 | "defaultValue" : null 1736 | }, { 1737 | "name" : "address", 1738 | "description" : null, 1739 | "type" : { 1740 | "kind" : "INPUT_OBJECT", 1741 | "name" : "ModelStringInput", 1742 | "ofType" : null 1743 | }, 1744 | "defaultValue" : null 1745 | }, { 1746 | "name" : "and", 1747 | "description" : null, 1748 | "type" : { 1749 | "kind" : "LIST", 1750 | "name" : null, 1751 | "ofType" : { 1752 | "kind" : "INPUT_OBJECT", 1753 | "name" : "ModelCustomerFilterInput", 1754 | "ofType" : null 1755 | } 1756 | }, 1757 | "defaultValue" : null 1758 | }, { 1759 | "name" : "or", 1760 | "description" : null, 1761 | "type" : { 1762 | "kind" : "LIST", 1763 | "name" : null, 1764 | "ofType" : { 1765 | "kind" : "INPUT_OBJECT", 1766 | "name" : "ModelCustomerFilterInput", 1767 | "ofType" : null 1768 | } 1769 | }, 1770 | "defaultValue" : null 1771 | }, { 1772 | "name" : "not", 1773 | "description" : null, 1774 | "type" : { 1775 | "kind" : "INPUT_OBJECT", 1776 | "name" : "ModelCustomerFilterInput", 1777 | "ofType" : null 1778 | }, 1779 | "defaultValue" : null 1780 | } ], 1781 | "interfaces" : null, 1782 | "enumValues" : null, 1783 | "possibleTypes" : null 1784 | }, { 1785 | "kind" : "OBJECT", 1786 | "name" : "Mutation", 1787 | "description" : null, 1788 | "fields" : [ { 1789 | "name" : "createProduct", 1790 | "description" : null, 1791 | "args" : [ { 1792 | "name" : "input", 1793 | "description" : null, 1794 | "type" : { 1795 | "kind" : "NON_NULL", 1796 | "name" : null, 1797 | "ofType" : { 1798 | "kind" : "INPUT_OBJECT", 1799 | "name" : "CreateProductInput", 1800 | "ofType" : null 1801 | } 1802 | }, 1803 | "defaultValue" : null 1804 | }, { 1805 | "name" : "condition", 1806 | "description" : null, 1807 | "type" : { 1808 | "kind" : "INPUT_OBJECT", 1809 | "name" : "ModelProductConditionInput", 1810 | "ofType" : null 1811 | }, 1812 | "defaultValue" : null 1813 | } ], 1814 | "type" : { 1815 | "kind" : "OBJECT", 1816 | "name" : "Product", 1817 | "ofType" : null 1818 | }, 1819 | "isDeprecated" : false, 1820 | "deprecationReason" : null 1821 | }, { 1822 | "name" : "updateProduct", 1823 | "description" : null, 1824 | "args" : [ { 1825 | "name" : "input", 1826 | "description" : null, 1827 | "type" : { 1828 | "kind" : "NON_NULL", 1829 | "name" : null, 1830 | "ofType" : { 1831 | "kind" : "INPUT_OBJECT", 1832 | "name" : "UpdateProductInput", 1833 | "ofType" : null 1834 | } 1835 | }, 1836 | "defaultValue" : null 1837 | }, { 1838 | "name" : "condition", 1839 | "description" : null, 1840 | "type" : { 1841 | "kind" : "INPUT_OBJECT", 1842 | "name" : "ModelProductConditionInput", 1843 | "ofType" : null 1844 | }, 1845 | "defaultValue" : null 1846 | } ], 1847 | "type" : { 1848 | "kind" : "OBJECT", 1849 | "name" : "Product", 1850 | "ofType" : null 1851 | }, 1852 | "isDeprecated" : false, 1853 | "deprecationReason" : null 1854 | }, { 1855 | "name" : "deleteProduct", 1856 | "description" : null, 1857 | "args" : [ { 1858 | "name" : "input", 1859 | "description" : null, 1860 | "type" : { 1861 | "kind" : "NON_NULL", 1862 | "name" : null, 1863 | "ofType" : { 1864 | "kind" : "INPUT_OBJECT", 1865 | "name" : "DeleteProductInput", 1866 | "ofType" : null 1867 | } 1868 | }, 1869 | "defaultValue" : null 1870 | }, { 1871 | "name" : "condition", 1872 | "description" : null, 1873 | "type" : { 1874 | "kind" : "INPUT_OBJECT", 1875 | "name" : "ModelProductConditionInput", 1876 | "ofType" : null 1877 | }, 1878 | "defaultValue" : null 1879 | } ], 1880 | "type" : { 1881 | "kind" : "OBJECT", 1882 | "name" : "Product", 1883 | "ofType" : null 1884 | }, 1885 | "isDeprecated" : false, 1886 | "deprecationReason" : null 1887 | }, { 1888 | "name" : "createOrder", 1889 | "description" : null, 1890 | "args" : [ { 1891 | "name" : "input", 1892 | "description" : null, 1893 | "type" : { 1894 | "kind" : "NON_NULL", 1895 | "name" : null, 1896 | "ofType" : { 1897 | "kind" : "INPUT_OBJECT", 1898 | "name" : "CreateOrderInput", 1899 | "ofType" : null 1900 | } 1901 | }, 1902 | "defaultValue" : null 1903 | }, { 1904 | "name" : "condition", 1905 | "description" : null, 1906 | "type" : { 1907 | "kind" : "INPUT_OBJECT", 1908 | "name" : "ModelOrderConditionInput", 1909 | "ofType" : null 1910 | }, 1911 | "defaultValue" : null 1912 | } ], 1913 | "type" : { 1914 | "kind" : "OBJECT", 1915 | "name" : "Order", 1916 | "ofType" : null 1917 | }, 1918 | "isDeprecated" : false, 1919 | "deprecationReason" : null 1920 | }, { 1921 | "name" : "updateOrder", 1922 | "description" : null, 1923 | "args" : [ { 1924 | "name" : "input", 1925 | "description" : null, 1926 | "type" : { 1927 | "kind" : "NON_NULL", 1928 | "name" : null, 1929 | "ofType" : { 1930 | "kind" : "INPUT_OBJECT", 1931 | "name" : "UpdateOrderInput", 1932 | "ofType" : null 1933 | } 1934 | }, 1935 | "defaultValue" : null 1936 | }, { 1937 | "name" : "condition", 1938 | "description" : null, 1939 | "type" : { 1940 | "kind" : "INPUT_OBJECT", 1941 | "name" : "ModelOrderConditionInput", 1942 | "ofType" : null 1943 | }, 1944 | "defaultValue" : null 1945 | } ], 1946 | "type" : { 1947 | "kind" : "OBJECT", 1948 | "name" : "Order", 1949 | "ofType" : null 1950 | }, 1951 | "isDeprecated" : false, 1952 | "deprecationReason" : null 1953 | }, { 1954 | "name" : "deleteOrder", 1955 | "description" : null, 1956 | "args" : [ { 1957 | "name" : "input", 1958 | "description" : null, 1959 | "type" : { 1960 | "kind" : "NON_NULL", 1961 | "name" : null, 1962 | "ofType" : { 1963 | "kind" : "INPUT_OBJECT", 1964 | "name" : "DeleteOrderInput", 1965 | "ofType" : null 1966 | } 1967 | }, 1968 | "defaultValue" : null 1969 | }, { 1970 | "name" : "condition", 1971 | "description" : null, 1972 | "type" : { 1973 | "kind" : "INPUT_OBJECT", 1974 | "name" : "ModelOrderConditionInput", 1975 | "ofType" : null 1976 | }, 1977 | "defaultValue" : null 1978 | } ], 1979 | "type" : { 1980 | "kind" : "OBJECT", 1981 | "name" : "Order", 1982 | "ofType" : null 1983 | }, 1984 | "isDeprecated" : false, 1985 | "deprecationReason" : null 1986 | }, { 1987 | "name" : "createCustomer", 1988 | "description" : null, 1989 | "args" : [ { 1990 | "name" : "input", 1991 | "description" : null, 1992 | "type" : { 1993 | "kind" : "NON_NULL", 1994 | "name" : null, 1995 | "ofType" : { 1996 | "kind" : "INPUT_OBJECT", 1997 | "name" : "CreateCustomerInput", 1998 | "ofType" : null 1999 | } 2000 | }, 2001 | "defaultValue" : null 2002 | }, { 2003 | "name" : "condition", 2004 | "description" : null, 2005 | "type" : { 2006 | "kind" : "INPUT_OBJECT", 2007 | "name" : "ModelCustomerConditionInput", 2008 | "ofType" : null 2009 | }, 2010 | "defaultValue" : null 2011 | } ], 2012 | "type" : { 2013 | "kind" : "OBJECT", 2014 | "name" : "Customer", 2015 | "ofType" : null 2016 | }, 2017 | "isDeprecated" : false, 2018 | "deprecationReason" : null 2019 | }, { 2020 | "name" : "updateCustomer", 2021 | "description" : null, 2022 | "args" : [ { 2023 | "name" : "input", 2024 | "description" : null, 2025 | "type" : { 2026 | "kind" : "NON_NULL", 2027 | "name" : null, 2028 | "ofType" : { 2029 | "kind" : "INPUT_OBJECT", 2030 | "name" : "UpdateCustomerInput", 2031 | "ofType" : null 2032 | } 2033 | }, 2034 | "defaultValue" : null 2035 | }, { 2036 | "name" : "condition", 2037 | "description" : null, 2038 | "type" : { 2039 | "kind" : "INPUT_OBJECT", 2040 | "name" : "ModelCustomerConditionInput", 2041 | "ofType" : null 2042 | }, 2043 | "defaultValue" : null 2044 | } ], 2045 | "type" : { 2046 | "kind" : "OBJECT", 2047 | "name" : "Customer", 2048 | "ofType" : null 2049 | }, 2050 | "isDeprecated" : false, 2051 | "deprecationReason" : null 2052 | }, { 2053 | "name" : "deleteCustomer", 2054 | "description" : null, 2055 | "args" : [ { 2056 | "name" : "input", 2057 | "description" : null, 2058 | "type" : { 2059 | "kind" : "NON_NULL", 2060 | "name" : null, 2061 | "ofType" : { 2062 | "kind" : "INPUT_OBJECT", 2063 | "name" : "DeleteCustomerInput", 2064 | "ofType" : null 2065 | } 2066 | }, 2067 | "defaultValue" : null 2068 | }, { 2069 | "name" : "condition", 2070 | "description" : null, 2071 | "type" : { 2072 | "kind" : "INPUT_OBJECT", 2073 | "name" : "ModelCustomerConditionInput", 2074 | "ofType" : null 2075 | }, 2076 | "defaultValue" : null 2077 | } ], 2078 | "type" : { 2079 | "kind" : "OBJECT", 2080 | "name" : "Customer", 2081 | "ofType" : null 2082 | }, 2083 | "isDeprecated" : false, 2084 | "deprecationReason" : null 2085 | } ], 2086 | "inputFields" : null, 2087 | "interfaces" : [ ], 2088 | "enumValues" : null, 2089 | "possibleTypes" : null 2090 | }, { 2091 | "kind" : "INPUT_OBJECT", 2092 | "name" : "CreateProductInput", 2093 | "description" : null, 2094 | "fields" : null, 2095 | "inputFields" : [ { 2096 | "name" : "id", 2097 | "description" : null, 2098 | "type" : { 2099 | "kind" : "SCALAR", 2100 | "name" : "ID", 2101 | "ofType" : null 2102 | }, 2103 | "defaultValue" : null 2104 | }, { 2105 | "name" : "name", 2106 | "description" : null, 2107 | "type" : { 2108 | "kind" : "NON_NULL", 2109 | "name" : null, 2110 | "ofType" : { 2111 | "kind" : "SCALAR", 2112 | "name" : "String", 2113 | "ofType" : null 2114 | } 2115 | }, 2116 | "defaultValue" : null 2117 | }, { 2118 | "name" : "description", 2119 | "description" : null, 2120 | "type" : { 2121 | "kind" : "NON_NULL", 2122 | "name" : null, 2123 | "ofType" : { 2124 | "kind" : "SCALAR", 2125 | "name" : "String", 2126 | "ofType" : null 2127 | } 2128 | }, 2129 | "defaultValue" : null 2130 | }, { 2131 | "name" : "price", 2132 | "description" : null, 2133 | "type" : { 2134 | "kind" : "NON_NULL", 2135 | "name" : null, 2136 | "ofType" : { 2137 | "kind" : "SCALAR", 2138 | "name" : "String", 2139 | "ofType" : null 2140 | } 2141 | }, 2142 | "defaultValue" : null 2143 | }, { 2144 | "name" : "active", 2145 | "description" : null, 2146 | "type" : { 2147 | "kind" : "NON_NULL", 2148 | "name" : null, 2149 | "ofType" : { 2150 | "kind" : "SCALAR", 2151 | "name" : "Boolean", 2152 | "ofType" : null 2153 | } 2154 | }, 2155 | "defaultValue" : null 2156 | }, { 2157 | "name" : "added", 2158 | "description" : null, 2159 | "type" : { 2160 | "kind" : "NON_NULL", 2161 | "name" : null, 2162 | "ofType" : { 2163 | "kind" : "SCALAR", 2164 | "name" : "AWSDateTime", 2165 | "ofType" : null 2166 | } 2167 | }, 2168 | "defaultValue" : null 2169 | }, { 2170 | "name" : "_version", 2171 | "description" : null, 2172 | "type" : { 2173 | "kind" : "SCALAR", 2174 | "name" : "Int", 2175 | "ofType" : null 2176 | }, 2177 | "defaultValue" : null 2178 | } ], 2179 | "interfaces" : null, 2180 | "enumValues" : null, 2181 | "possibleTypes" : null 2182 | }, { 2183 | "kind" : "INPUT_OBJECT", 2184 | "name" : "ModelProductConditionInput", 2185 | "description" : null, 2186 | "fields" : null, 2187 | "inputFields" : [ { 2188 | "name" : "name", 2189 | "description" : null, 2190 | "type" : { 2191 | "kind" : "INPUT_OBJECT", 2192 | "name" : "ModelStringInput", 2193 | "ofType" : null 2194 | }, 2195 | "defaultValue" : null 2196 | }, { 2197 | "name" : "description", 2198 | "description" : null, 2199 | "type" : { 2200 | "kind" : "INPUT_OBJECT", 2201 | "name" : "ModelStringInput", 2202 | "ofType" : null 2203 | }, 2204 | "defaultValue" : null 2205 | }, { 2206 | "name" : "price", 2207 | "description" : null, 2208 | "type" : { 2209 | "kind" : "INPUT_OBJECT", 2210 | "name" : "ModelStringInput", 2211 | "ofType" : null 2212 | }, 2213 | "defaultValue" : null 2214 | }, { 2215 | "name" : "active", 2216 | "description" : null, 2217 | "type" : { 2218 | "kind" : "INPUT_OBJECT", 2219 | "name" : "ModelBooleanInput", 2220 | "ofType" : null 2221 | }, 2222 | "defaultValue" : null 2223 | }, { 2224 | "name" : "added", 2225 | "description" : null, 2226 | "type" : { 2227 | "kind" : "INPUT_OBJECT", 2228 | "name" : "ModelStringInput", 2229 | "ofType" : null 2230 | }, 2231 | "defaultValue" : null 2232 | }, { 2233 | "name" : "and", 2234 | "description" : null, 2235 | "type" : { 2236 | "kind" : "LIST", 2237 | "name" : null, 2238 | "ofType" : { 2239 | "kind" : "INPUT_OBJECT", 2240 | "name" : "ModelProductConditionInput", 2241 | "ofType" : null 2242 | } 2243 | }, 2244 | "defaultValue" : null 2245 | }, { 2246 | "name" : "or", 2247 | "description" : null, 2248 | "type" : { 2249 | "kind" : "LIST", 2250 | "name" : null, 2251 | "ofType" : { 2252 | "kind" : "INPUT_OBJECT", 2253 | "name" : "ModelProductConditionInput", 2254 | "ofType" : null 2255 | } 2256 | }, 2257 | "defaultValue" : null 2258 | }, { 2259 | "name" : "not", 2260 | "description" : null, 2261 | "type" : { 2262 | "kind" : "INPUT_OBJECT", 2263 | "name" : "ModelProductConditionInput", 2264 | "ofType" : null 2265 | }, 2266 | "defaultValue" : null 2267 | } ], 2268 | "interfaces" : null, 2269 | "enumValues" : null, 2270 | "possibleTypes" : null 2271 | }, { 2272 | "kind" : "INPUT_OBJECT", 2273 | "name" : "UpdateProductInput", 2274 | "description" : null, 2275 | "fields" : null, 2276 | "inputFields" : [ { 2277 | "name" : "id", 2278 | "description" : null, 2279 | "type" : { 2280 | "kind" : "NON_NULL", 2281 | "name" : null, 2282 | "ofType" : { 2283 | "kind" : "SCALAR", 2284 | "name" : "ID", 2285 | "ofType" : null 2286 | } 2287 | }, 2288 | "defaultValue" : null 2289 | }, { 2290 | "name" : "name", 2291 | "description" : null, 2292 | "type" : { 2293 | "kind" : "SCALAR", 2294 | "name" : "String", 2295 | "ofType" : null 2296 | }, 2297 | "defaultValue" : null 2298 | }, { 2299 | "name" : "description", 2300 | "description" : null, 2301 | "type" : { 2302 | "kind" : "SCALAR", 2303 | "name" : "String", 2304 | "ofType" : null 2305 | }, 2306 | "defaultValue" : null 2307 | }, { 2308 | "name" : "price", 2309 | "description" : null, 2310 | "type" : { 2311 | "kind" : "SCALAR", 2312 | "name" : "String", 2313 | "ofType" : null 2314 | }, 2315 | "defaultValue" : null 2316 | }, { 2317 | "name" : "active", 2318 | "description" : null, 2319 | "type" : { 2320 | "kind" : "SCALAR", 2321 | "name" : "Boolean", 2322 | "ofType" : null 2323 | }, 2324 | "defaultValue" : null 2325 | }, { 2326 | "name" : "added", 2327 | "description" : null, 2328 | "type" : { 2329 | "kind" : "SCALAR", 2330 | "name" : "AWSDateTime", 2331 | "ofType" : null 2332 | }, 2333 | "defaultValue" : null 2334 | }, { 2335 | "name" : "_version", 2336 | "description" : null, 2337 | "type" : { 2338 | "kind" : "SCALAR", 2339 | "name" : "Int", 2340 | "ofType" : null 2341 | }, 2342 | "defaultValue" : null 2343 | } ], 2344 | "interfaces" : null, 2345 | "enumValues" : null, 2346 | "possibleTypes" : null 2347 | }, { 2348 | "kind" : "INPUT_OBJECT", 2349 | "name" : "DeleteProductInput", 2350 | "description" : null, 2351 | "fields" : null, 2352 | "inputFields" : [ { 2353 | "name" : "id", 2354 | "description" : null, 2355 | "type" : { 2356 | "kind" : "SCALAR", 2357 | "name" : "ID", 2358 | "ofType" : null 2359 | }, 2360 | "defaultValue" : null 2361 | }, { 2362 | "name" : "_version", 2363 | "description" : null, 2364 | "type" : { 2365 | "kind" : "SCALAR", 2366 | "name" : "Int", 2367 | "ofType" : null 2368 | }, 2369 | "defaultValue" : null 2370 | } ], 2371 | "interfaces" : null, 2372 | "enumValues" : null, 2373 | "possibleTypes" : null 2374 | }, { 2375 | "kind" : "INPUT_OBJECT", 2376 | "name" : "CreateOrderInput", 2377 | "description" : null, 2378 | "fields" : null, 2379 | "inputFields" : [ { 2380 | "name" : "id", 2381 | "description" : null, 2382 | "type" : { 2383 | "kind" : "SCALAR", 2384 | "name" : "ID", 2385 | "ofType" : null 2386 | }, 2387 | "defaultValue" : null 2388 | }, { 2389 | "name" : "productID", 2390 | "description" : null, 2391 | "type" : { 2392 | "kind" : "NON_NULL", 2393 | "name" : null, 2394 | "ofType" : { 2395 | "kind" : "SCALAR", 2396 | "name" : "ID", 2397 | "ofType" : null 2398 | } 2399 | }, 2400 | "defaultValue" : null 2401 | }, { 2402 | "name" : "total", 2403 | "description" : null, 2404 | "type" : { 2405 | "kind" : "NON_NULL", 2406 | "name" : null, 2407 | "ofType" : { 2408 | "kind" : "SCALAR", 2409 | "name" : "String", 2410 | "ofType" : null 2411 | } 2412 | }, 2413 | "defaultValue" : null 2414 | }, { 2415 | "name" : "ordered", 2416 | "description" : null, 2417 | "type" : { 2418 | "kind" : "NON_NULL", 2419 | "name" : null, 2420 | "ofType" : { 2421 | "kind" : "SCALAR", 2422 | "name" : "AWSDateTime", 2423 | "ofType" : null 2424 | } 2425 | }, 2426 | "defaultValue" : null 2427 | }, { 2428 | "name" : "_version", 2429 | "description" : null, 2430 | "type" : { 2431 | "kind" : "SCALAR", 2432 | "name" : "Int", 2433 | "ofType" : null 2434 | }, 2435 | "defaultValue" : null 2436 | } ], 2437 | "interfaces" : null, 2438 | "enumValues" : null, 2439 | "possibleTypes" : null 2440 | }, { 2441 | "kind" : "INPUT_OBJECT", 2442 | "name" : "ModelOrderConditionInput", 2443 | "description" : null, 2444 | "fields" : null, 2445 | "inputFields" : [ { 2446 | "name" : "total", 2447 | "description" : null, 2448 | "type" : { 2449 | "kind" : "INPUT_OBJECT", 2450 | "name" : "ModelStringInput", 2451 | "ofType" : null 2452 | }, 2453 | "defaultValue" : null 2454 | }, { 2455 | "name" : "ordered", 2456 | "description" : null, 2457 | "type" : { 2458 | "kind" : "INPUT_OBJECT", 2459 | "name" : "ModelStringInput", 2460 | "ofType" : null 2461 | }, 2462 | "defaultValue" : null 2463 | }, { 2464 | "name" : "and", 2465 | "description" : null, 2466 | "type" : { 2467 | "kind" : "LIST", 2468 | "name" : null, 2469 | "ofType" : { 2470 | "kind" : "INPUT_OBJECT", 2471 | "name" : "ModelOrderConditionInput", 2472 | "ofType" : null 2473 | } 2474 | }, 2475 | "defaultValue" : null 2476 | }, { 2477 | "name" : "or", 2478 | "description" : null, 2479 | "type" : { 2480 | "kind" : "LIST", 2481 | "name" : null, 2482 | "ofType" : { 2483 | "kind" : "INPUT_OBJECT", 2484 | "name" : "ModelOrderConditionInput", 2485 | "ofType" : null 2486 | } 2487 | }, 2488 | "defaultValue" : null 2489 | }, { 2490 | "name" : "not", 2491 | "description" : null, 2492 | "type" : { 2493 | "kind" : "INPUT_OBJECT", 2494 | "name" : "ModelOrderConditionInput", 2495 | "ofType" : null 2496 | }, 2497 | "defaultValue" : null 2498 | } ], 2499 | "interfaces" : null, 2500 | "enumValues" : null, 2501 | "possibleTypes" : null 2502 | }, { 2503 | "kind" : "INPUT_OBJECT", 2504 | "name" : "UpdateOrderInput", 2505 | "description" : null, 2506 | "fields" : null, 2507 | "inputFields" : [ { 2508 | "name" : "id", 2509 | "description" : null, 2510 | "type" : { 2511 | "kind" : "NON_NULL", 2512 | "name" : null, 2513 | "ofType" : { 2514 | "kind" : "SCALAR", 2515 | "name" : "ID", 2516 | "ofType" : null 2517 | } 2518 | }, 2519 | "defaultValue" : null 2520 | }, { 2521 | "name" : "productID", 2522 | "description" : null, 2523 | "type" : { 2524 | "kind" : "NON_NULL", 2525 | "name" : null, 2526 | "ofType" : { 2527 | "kind" : "SCALAR", 2528 | "name" : "ID", 2529 | "ofType" : null 2530 | } 2531 | }, 2532 | "defaultValue" : null 2533 | }, { 2534 | "name" : "total", 2535 | "description" : null, 2536 | "type" : { 2537 | "kind" : "SCALAR", 2538 | "name" : "String", 2539 | "ofType" : null 2540 | }, 2541 | "defaultValue" : null 2542 | }, { 2543 | "name" : "ordered", 2544 | "description" : null, 2545 | "type" : { 2546 | "kind" : "SCALAR", 2547 | "name" : "AWSDateTime", 2548 | "ofType" : null 2549 | }, 2550 | "defaultValue" : null 2551 | }, { 2552 | "name" : "_version", 2553 | "description" : null, 2554 | "type" : { 2555 | "kind" : "SCALAR", 2556 | "name" : "Int", 2557 | "ofType" : null 2558 | }, 2559 | "defaultValue" : null 2560 | } ], 2561 | "interfaces" : null, 2562 | "enumValues" : null, 2563 | "possibleTypes" : null 2564 | }, { 2565 | "kind" : "INPUT_OBJECT", 2566 | "name" : "DeleteOrderInput", 2567 | "description" : null, 2568 | "fields" : null, 2569 | "inputFields" : [ { 2570 | "name" : "id", 2571 | "description" : null, 2572 | "type" : { 2573 | "kind" : "NON_NULL", 2574 | "name" : null, 2575 | "ofType" : { 2576 | "kind" : "SCALAR", 2577 | "name" : "ID", 2578 | "ofType" : null 2579 | } 2580 | }, 2581 | "defaultValue" : null 2582 | }, { 2583 | "name" : "productID", 2584 | "description" : null, 2585 | "type" : { 2586 | "kind" : "NON_NULL", 2587 | "name" : null, 2588 | "ofType" : { 2589 | "kind" : "SCALAR", 2590 | "name" : "ID", 2591 | "ofType" : null 2592 | } 2593 | }, 2594 | "defaultValue" : null 2595 | }, { 2596 | "name" : "_version", 2597 | "description" : null, 2598 | "type" : { 2599 | "kind" : "SCALAR", 2600 | "name" : "Int", 2601 | "ofType" : null 2602 | }, 2603 | "defaultValue" : null 2604 | } ], 2605 | "interfaces" : null, 2606 | "enumValues" : null, 2607 | "possibleTypes" : null 2608 | }, { 2609 | "kind" : "INPUT_OBJECT", 2610 | "name" : "CreateCustomerInput", 2611 | "description" : null, 2612 | "fields" : null, 2613 | "inputFields" : [ { 2614 | "name" : "id", 2615 | "description" : null, 2616 | "type" : { 2617 | "kind" : "SCALAR", 2618 | "name" : "ID", 2619 | "ofType" : null 2620 | }, 2621 | "defaultValue" : null 2622 | }, { 2623 | "name" : "firstName", 2624 | "description" : null, 2625 | "type" : { 2626 | "kind" : "NON_NULL", 2627 | "name" : null, 2628 | "ofType" : { 2629 | "kind" : "SCALAR", 2630 | "name" : "String", 2631 | "ofType" : null 2632 | } 2633 | }, 2634 | "defaultValue" : null 2635 | }, { 2636 | "name" : "lastName", 2637 | "description" : null, 2638 | "type" : { 2639 | "kind" : "NON_NULL", 2640 | "name" : null, 2641 | "ofType" : { 2642 | "kind" : "SCALAR", 2643 | "name" : "String", 2644 | "ofType" : null 2645 | } 2646 | }, 2647 | "defaultValue" : null 2648 | }, { 2649 | "name" : "active", 2650 | "description" : null, 2651 | "type" : { 2652 | "kind" : "NON_NULL", 2653 | "name" : null, 2654 | "ofType" : { 2655 | "kind" : "SCALAR", 2656 | "name" : "Boolean", 2657 | "ofType" : null 2658 | } 2659 | }, 2660 | "defaultValue" : null 2661 | }, { 2662 | "name" : "address", 2663 | "description" : null, 2664 | "type" : { 2665 | "kind" : "NON_NULL", 2666 | "name" : null, 2667 | "ofType" : { 2668 | "kind" : "SCALAR", 2669 | "name" : "String", 2670 | "ofType" : null 2671 | } 2672 | }, 2673 | "defaultValue" : null 2674 | }, { 2675 | "name" : "_version", 2676 | "description" : null, 2677 | "type" : { 2678 | "kind" : "SCALAR", 2679 | "name" : "Int", 2680 | "ofType" : null 2681 | }, 2682 | "defaultValue" : null 2683 | } ], 2684 | "interfaces" : null, 2685 | "enumValues" : null, 2686 | "possibleTypes" : null 2687 | }, { 2688 | "kind" : "INPUT_OBJECT", 2689 | "name" : "ModelCustomerConditionInput", 2690 | "description" : null, 2691 | "fields" : null, 2692 | "inputFields" : [ { 2693 | "name" : "firstName", 2694 | "description" : null, 2695 | "type" : { 2696 | "kind" : "INPUT_OBJECT", 2697 | "name" : "ModelStringInput", 2698 | "ofType" : null 2699 | }, 2700 | "defaultValue" : null 2701 | }, { 2702 | "name" : "lastName", 2703 | "description" : null, 2704 | "type" : { 2705 | "kind" : "INPUT_OBJECT", 2706 | "name" : "ModelStringInput", 2707 | "ofType" : null 2708 | }, 2709 | "defaultValue" : null 2710 | }, { 2711 | "name" : "active", 2712 | "description" : null, 2713 | "type" : { 2714 | "kind" : "INPUT_OBJECT", 2715 | "name" : "ModelBooleanInput", 2716 | "ofType" : null 2717 | }, 2718 | "defaultValue" : null 2719 | }, { 2720 | "name" : "address", 2721 | "description" : null, 2722 | "type" : { 2723 | "kind" : "INPUT_OBJECT", 2724 | "name" : "ModelStringInput", 2725 | "ofType" : null 2726 | }, 2727 | "defaultValue" : null 2728 | }, { 2729 | "name" : "and", 2730 | "description" : null, 2731 | "type" : { 2732 | "kind" : "LIST", 2733 | "name" : null, 2734 | "ofType" : { 2735 | "kind" : "INPUT_OBJECT", 2736 | "name" : "ModelCustomerConditionInput", 2737 | "ofType" : null 2738 | } 2739 | }, 2740 | "defaultValue" : null 2741 | }, { 2742 | "name" : "or", 2743 | "description" : null, 2744 | "type" : { 2745 | "kind" : "LIST", 2746 | "name" : null, 2747 | "ofType" : { 2748 | "kind" : "INPUT_OBJECT", 2749 | "name" : "ModelCustomerConditionInput", 2750 | "ofType" : null 2751 | } 2752 | }, 2753 | "defaultValue" : null 2754 | }, { 2755 | "name" : "not", 2756 | "description" : null, 2757 | "type" : { 2758 | "kind" : "INPUT_OBJECT", 2759 | "name" : "ModelCustomerConditionInput", 2760 | "ofType" : null 2761 | }, 2762 | "defaultValue" : null 2763 | } ], 2764 | "interfaces" : null, 2765 | "enumValues" : null, 2766 | "possibleTypes" : null 2767 | }, { 2768 | "kind" : "INPUT_OBJECT", 2769 | "name" : "UpdateCustomerInput", 2770 | "description" : null, 2771 | "fields" : null, 2772 | "inputFields" : [ { 2773 | "name" : "id", 2774 | "description" : null, 2775 | "type" : { 2776 | "kind" : "NON_NULL", 2777 | "name" : null, 2778 | "ofType" : { 2779 | "kind" : "SCALAR", 2780 | "name" : "ID", 2781 | "ofType" : null 2782 | } 2783 | }, 2784 | "defaultValue" : null 2785 | }, { 2786 | "name" : "firstName", 2787 | "description" : null, 2788 | "type" : { 2789 | "kind" : "SCALAR", 2790 | "name" : "String", 2791 | "ofType" : null 2792 | }, 2793 | "defaultValue" : null 2794 | }, { 2795 | "name" : "lastName", 2796 | "description" : null, 2797 | "type" : { 2798 | "kind" : "SCALAR", 2799 | "name" : "String", 2800 | "ofType" : null 2801 | }, 2802 | "defaultValue" : null 2803 | }, { 2804 | "name" : "active", 2805 | "description" : null, 2806 | "type" : { 2807 | "kind" : "SCALAR", 2808 | "name" : "Boolean", 2809 | "ofType" : null 2810 | }, 2811 | "defaultValue" : null 2812 | }, { 2813 | "name" : "address", 2814 | "description" : null, 2815 | "type" : { 2816 | "kind" : "SCALAR", 2817 | "name" : "String", 2818 | "ofType" : null 2819 | }, 2820 | "defaultValue" : null 2821 | }, { 2822 | "name" : "_version", 2823 | "description" : null, 2824 | "type" : { 2825 | "kind" : "SCALAR", 2826 | "name" : "Int", 2827 | "ofType" : null 2828 | }, 2829 | "defaultValue" : null 2830 | }, { 2831 | "name" : "expectedVersion", 2832 | "description" : null, 2833 | "type" : { 2834 | "kind" : "NON_NULL", 2835 | "name" : null, 2836 | "ofType" : { 2837 | "kind" : "SCALAR", 2838 | "name" : "Int", 2839 | "ofType" : null 2840 | } 2841 | }, 2842 | "defaultValue" : null 2843 | } ], 2844 | "interfaces" : null, 2845 | "enumValues" : null, 2846 | "possibleTypes" : null 2847 | }, { 2848 | "kind" : "INPUT_OBJECT", 2849 | "name" : "DeleteCustomerInput", 2850 | "description" : null, 2851 | "fields" : null, 2852 | "inputFields" : [ { 2853 | "name" : "id", 2854 | "description" : null, 2855 | "type" : { 2856 | "kind" : "SCALAR", 2857 | "name" : "ID", 2858 | "ofType" : null 2859 | }, 2860 | "defaultValue" : null 2861 | }, { 2862 | "name" : "_version", 2863 | "description" : null, 2864 | "type" : { 2865 | "kind" : "SCALAR", 2866 | "name" : "Int", 2867 | "ofType" : null 2868 | }, 2869 | "defaultValue" : null 2870 | }, { 2871 | "name" : "expectedVersion", 2872 | "description" : null, 2873 | "type" : { 2874 | "kind" : "NON_NULL", 2875 | "name" : null, 2876 | "ofType" : { 2877 | "kind" : "SCALAR", 2878 | "name" : "Int", 2879 | "ofType" : null 2880 | } 2881 | }, 2882 | "defaultValue" : null 2883 | } ], 2884 | "interfaces" : null, 2885 | "enumValues" : null, 2886 | "possibleTypes" : null 2887 | }, { 2888 | "kind" : "OBJECT", 2889 | "name" : "Subscription", 2890 | "description" : null, 2891 | "fields" : [ { 2892 | "name" : "onCreateProduct", 2893 | "description" : null, 2894 | "args" : [ ], 2895 | "type" : { 2896 | "kind" : "OBJECT", 2897 | "name" : "Product", 2898 | "ofType" : null 2899 | }, 2900 | "isDeprecated" : false, 2901 | "deprecationReason" : null 2902 | }, { 2903 | "name" : "onUpdateProduct", 2904 | "description" : null, 2905 | "args" : [ ], 2906 | "type" : { 2907 | "kind" : "OBJECT", 2908 | "name" : "Product", 2909 | "ofType" : null 2910 | }, 2911 | "isDeprecated" : false, 2912 | "deprecationReason" : null 2913 | }, { 2914 | "name" : "onDeleteProduct", 2915 | "description" : null, 2916 | "args" : [ ], 2917 | "type" : { 2918 | "kind" : "OBJECT", 2919 | "name" : "Product", 2920 | "ofType" : null 2921 | }, 2922 | "isDeprecated" : false, 2923 | "deprecationReason" : null 2924 | }, { 2925 | "name" : "onCreateOrder", 2926 | "description" : null, 2927 | "args" : [ ], 2928 | "type" : { 2929 | "kind" : "OBJECT", 2930 | "name" : "Order", 2931 | "ofType" : null 2932 | }, 2933 | "isDeprecated" : false, 2934 | "deprecationReason" : null 2935 | }, { 2936 | "name" : "onUpdateOrder", 2937 | "description" : null, 2938 | "args" : [ ], 2939 | "type" : { 2940 | "kind" : "OBJECT", 2941 | "name" : "Order", 2942 | "ofType" : null 2943 | }, 2944 | "isDeprecated" : false, 2945 | "deprecationReason" : null 2946 | }, { 2947 | "name" : "onDeleteOrder", 2948 | "description" : null, 2949 | "args" : [ ], 2950 | "type" : { 2951 | "kind" : "OBJECT", 2952 | "name" : "Order", 2953 | "ofType" : null 2954 | }, 2955 | "isDeprecated" : false, 2956 | "deprecationReason" : null 2957 | }, { 2958 | "name" : "onCreateCustomer", 2959 | "description" : null, 2960 | "args" : [ { 2961 | "name" : "owner", 2962 | "description" : null, 2963 | "type" : { 2964 | "kind" : "SCALAR", 2965 | "name" : "String", 2966 | "ofType" : null 2967 | }, 2968 | "defaultValue" : null 2969 | } ], 2970 | "type" : { 2971 | "kind" : "OBJECT", 2972 | "name" : "Customer", 2973 | "ofType" : null 2974 | }, 2975 | "isDeprecated" : false, 2976 | "deprecationReason" : null 2977 | }, { 2978 | "name" : "onUpdateCustomer", 2979 | "description" : null, 2980 | "args" : [ { 2981 | "name" : "owner", 2982 | "description" : null, 2983 | "type" : { 2984 | "kind" : "SCALAR", 2985 | "name" : "String", 2986 | "ofType" : null 2987 | }, 2988 | "defaultValue" : null 2989 | } ], 2990 | "type" : { 2991 | "kind" : "OBJECT", 2992 | "name" : "Customer", 2993 | "ofType" : null 2994 | }, 2995 | "isDeprecated" : false, 2996 | "deprecationReason" : null 2997 | }, { 2998 | "name" : "onDeleteCustomer", 2999 | "description" : null, 3000 | "args" : [ { 3001 | "name" : "owner", 3002 | "description" : null, 3003 | "type" : { 3004 | "kind" : "SCALAR", 3005 | "name" : "String", 3006 | "ofType" : null 3007 | }, 3008 | "defaultValue" : null 3009 | } ], 3010 | "type" : { 3011 | "kind" : "OBJECT", 3012 | "name" : "Customer", 3013 | "ofType" : null 3014 | }, 3015 | "isDeprecated" : false, 3016 | "deprecationReason" : null 3017 | } ], 3018 | "inputFields" : null, 3019 | "interfaces" : [ ], 3020 | "enumValues" : null, 3021 | "possibleTypes" : null 3022 | }, { 3023 | "kind" : "INPUT_OBJECT", 3024 | "name" : "ModelFloatInput", 3025 | "description" : null, 3026 | "fields" : null, 3027 | "inputFields" : [ { 3028 | "name" : "ne", 3029 | "description" : null, 3030 | "type" : { 3031 | "kind" : "SCALAR", 3032 | "name" : "Float", 3033 | "ofType" : null 3034 | }, 3035 | "defaultValue" : null 3036 | }, { 3037 | "name" : "eq", 3038 | "description" : null, 3039 | "type" : { 3040 | "kind" : "SCALAR", 3041 | "name" : "Float", 3042 | "ofType" : null 3043 | }, 3044 | "defaultValue" : null 3045 | }, { 3046 | "name" : "le", 3047 | "description" : null, 3048 | "type" : { 3049 | "kind" : "SCALAR", 3050 | "name" : "Float", 3051 | "ofType" : null 3052 | }, 3053 | "defaultValue" : null 3054 | }, { 3055 | "name" : "lt", 3056 | "description" : null, 3057 | "type" : { 3058 | "kind" : "SCALAR", 3059 | "name" : "Float", 3060 | "ofType" : null 3061 | }, 3062 | "defaultValue" : null 3063 | }, { 3064 | "name" : "ge", 3065 | "description" : null, 3066 | "type" : { 3067 | "kind" : "SCALAR", 3068 | "name" : "Float", 3069 | "ofType" : null 3070 | }, 3071 | "defaultValue" : null 3072 | }, { 3073 | "name" : "gt", 3074 | "description" : null, 3075 | "type" : { 3076 | "kind" : "SCALAR", 3077 | "name" : "Float", 3078 | "ofType" : null 3079 | }, 3080 | "defaultValue" : null 3081 | }, { 3082 | "name" : "between", 3083 | "description" : null, 3084 | "type" : { 3085 | "kind" : "LIST", 3086 | "name" : null, 3087 | "ofType" : { 3088 | "kind" : "SCALAR", 3089 | "name" : "Float", 3090 | "ofType" : null 3091 | } 3092 | }, 3093 | "defaultValue" : null 3094 | }, { 3095 | "name" : "attributeExists", 3096 | "description" : null, 3097 | "type" : { 3098 | "kind" : "SCALAR", 3099 | "name" : "Boolean", 3100 | "ofType" : null 3101 | }, 3102 | "defaultValue" : null 3103 | }, { 3104 | "name" : "attributeType", 3105 | "description" : null, 3106 | "type" : { 3107 | "kind" : "ENUM", 3108 | "name" : "ModelAttributeTypes", 3109 | "ofType" : null 3110 | }, 3111 | "defaultValue" : null 3112 | } ], 3113 | "interfaces" : null, 3114 | "enumValues" : null, 3115 | "possibleTypes" : null 3116 | }, { 3117 | "kind" : "SCALAR", 3118 | "name" : "Float", 3119 | "description" : "Built-in Float", 3120 | "fields" : null, 3121 | "inputFields" : null, 3122 | "interfaces" : null, 3123 | "enumValues" : null, 3124 | "possibleTypes" : null 3125 | }, { 3126 | "kind" : "INPUT_OBJECT", 3127 | "name" : "ModelIntInput", 3128 | "description" : null, 3129 | "fields" : null, 3130 | "inputFields" : [ { 3131 | "name" : "ne", 3132 | "description" : null, 3133 | "type" : { 3134 | "kind" : "SCALAR", 3135 | "name" : "Int", 3136 | "ofType" : null 3137 | }, 3138 | "defaultValue" : null 3139 | }, { 3140 | "name" : "eq", 3141 | "description" : null, 3142 | "type" : { 3143 | "kind" : "SCALAR", 3144 | "name" : "Int", 3145 | "ofType" : null 3146 | }, 3147 | "defaultValue" : null 3148 | }, { 3149 | "name" : "le", 3150 | "description" : null, 3151 | "type" : { 3152 | "kind" : "SCALAR", 3153 | "name" : "Int", 3154 | "ofType" : null 3155 | }, 3156 | "defaultValue" : null 3157 | }, { 3158 | "name" : "lt", 3159 | "description" : null, 3160 | "type" : { 3161 | "kind" : "SCALAR", 3162 | "name" : "Int", 3163 | "ofType" : null 3164 | }, 3165 | "defaultValue" : null 3166 | }, { 3167 | "name" : "ge", 3168 | "description" : null, 3169 | "type" : { 3170 | "kind" : "SCALAR", 3171 | "name" : "Int", 3172 | "ofType" : null 3173 | }, 3174 | "defaultValue" : null 3175 | }, { 3176 | "name" : "gt", 3177 | "description" : null, 3178 | "type" : { 3179 | "kind" : "SCALAR", 3180 | "name" : "Int", 3181 | "ofType" : null 3182 | }, 3183 | "defaultValue" : null 3184 | }, { 3185 | "name" : "between", 3186 | "description" : null, 3187 | "type" : { 3188 | "kind" : "LIST", 3189 | "name" : null, 3190 | "ofType" : { 3191 | "kind" : "SCALAR", 3192 | "name" : "Int", 3193 | "ofType" : null 3194 | } 3195 | }, 3196 | "defaultValue" : null 3197 | }, { 3198 | "name" : "attributeExists", 3199 | "description" : null, 3200 | "type" : { 3201 | "kind" : "SCALAR", 3202 | "name" : "Boolean", 3203 | "ofType" : null 3204 | }, 3205 | "defaultValue" : null 3206 | }, { 3207 | "name" : "attributeType", 3208 | "description" : null, 3209 | "type" : { 3210 | "kind" : "ENUM", 3211 | "name" : "ModelAttributeTypes", 3212 | "ofType" : null 3213 | }, 3214 | "defaultValue" : null 3215 | } ], 3216 | "interfaces" : null, 3217 | "enumValues" : null, 3218 | "possibleTypes" : null 3219 | }, { 3220 | "kind" : "OBJECT", 3221 | "name" : "__Schema", 3222 | "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.", 3223 | "fields" : [ { 3224 | "name" : "types", 3225 | "description" : "A list of all types supported by this server.", 3226 | "args" : [ ], 3227 | "type" : { 3228 | "kind" : "NON_NULL", 3229 | "name" : null, 3230 | "ofType" : { 3231 | "kind" : "LIST", 3232 | "name" : null, 3233 | "ofType" : { 3234 | "kind" : "NON_NULL", 3235 | "name" : null, 3236 | "ofType" : { 3237 | "kind" : "OBJECT", 3238 | "name" : "__Type", 3239 | "ofType" : null 3240 | } 3241 | } 3242 | } 3243 | }, 3244 | "isDeprecated" : false, 3245 | "deprecationReason" : null 3246 | }, { 3247 | "name" : "queryType", 3248 | "description" : "The type that query operations will be rooted at.", 3249 | "args" : [ ], 3250 | "type" : { 3251 | "kind" : "NON_NULL", 3252 | "name" : null, 3253 | "ofType" : { 3254 | "kind" : "OBJECT", 3255 | "name" : "__Type", 3256 | "ofType" : null 3257 | } 3258 | }, 3259 | "isDeprecated" : false, 3260 | "deprecationReason" : null 3261 | }, { 3262 | "name" : "mutationType", 3263 | "description" : "If this server supports mutation, the type that mutation operations will be rooted at.", 3264 | "args" : [ ], 3265 | "type" : { 3266 | "kind" : "OBJECT", 3267 | "name" : "__Type", 3268 | "ofType" : null 3269 | }, 3270 | "isDeprecated" : false, 3271 | "deprecationReason" : null 3272 | }, { 3273 | "name" : "directives", 3274 | "description" : "'A list of all directives supported by this server.", 3275 | "args" : [ ], 3276 | "type" : { 3277 | "kind" : "NON_NULL", 3278 | "name" : null, 3279 | "ofType" : { 3280 | "kind" : "LIST", 3281 | "name" : null, 3282 | "ofType" : { 3283 | "kind" : "NON_NULL", 3284 | "name" : null, 3285 | "ofType" : { 3286 | "kind" : "OBJECT", 3287 | "name" : "__Directive", 3288 | "ofType" : null 3289 | } 3290 | } 3291 | } 3292 | }, 3293 | "isDeprecated" : false, 3294 | "deprecationReason" : null 3295 | }, { 3296 | "name" : "subscriptionType", 3297 | "description" : "'If this server support subscription, the type that subscription operations will be rooted at.", 3298 | "args" : [ ], 3299 | "type" : { 3300 | "kind" : "OBJECT", 3301 | "name" : "__Type", 3302 | "ofType" : null 3303 | }, 3304 | "isDeprecated" : false, 3305 | "deprecationReason" : null 3306 | } ], 3307 | "inputFields" : null, 3308 | "interfaces" : [ ], 3309 | "enumValues" : null, 3310 | "possibleTypes" : null 3311 | }, { 3312 | "kind" : "OBJECT", 3313 | "name" : "__Type", 3314 | "description" : null, 3315 | "fields" : [ { 3316 | "name" : "kind", 3317 | "description" : null, 3318 | "args" : [ ], 3319 | "type" : { 3320 | "kind" : "NON_NULL", 3321 | "name" : null, 3322 | "ofType" : { 3323 | "kind" : "ENUM", 3324 | "name" : "__TypeKind", 3325 | "ofType" : null 3326 | } 3327 | }, 3328 | "isDeprecated" : false, 3329 | "deprecationReason" : null 3330 | }, { 3331 | "name" : "name", 3332 | "description" : null, 3333 | "args" : [ ], 3334 | "type" : { 3335 | "kind" : "SCALAR", 3336 | "name" : "String", 3337 | "ofType" : null 3338 | }, 3339 | "isDeprecated" : false, 3340 | "deprecationReason" : null 3341 | }, { 3342 | "name" : "description", 3343 | "description" : null, 3344 | "args" : [ ], 3345 | "type" : { 3346 | "kind" : "SCALAR", 3347 | "name" : "String", 3348 | "ofType" : null 3349 | }, 3350 | "isDeprecated" : false, 3351 | "deprecationReason" : null 3352 | }, { 3353 | "name" : "fields", 3354 | "description" : null, 3355 | "args" : [ { 3356 | "name" : "includeDeprecated", 3357 | "description" : null, 3358 | "type" : { 3359 | "kind" : "SCALAR", 3360 | "name" : "Boolean", 3361 | "ofType" : null 3362 | }, 3363 | "defaultValue" : "false" 3364 | } ], 3365 | "type" : { 3366 | "kind" : "LIST", 3367 | "name" : null, 3368 | "ofType" : { 3369 | "kind" : "NON_NULL", 3370 | "name" : null, 3371 | "ofType" : { 3372 | "kind" : "OBJECT", 3373 | "name" : "__Field", 3374 | "ofType" : null 3375 | } 3376 | } 3377 | }, 3378 | "isDeprecated" : false, 3379 | "deprecationReason" : null 3380 | }, { 3381 | "name" : "interfaces", 3382 | "description" : null, 3383 | "args" : [ ], 3384 | "type" : { 3385 | "kind" : "LIST", 3386 | "name" : null, 3387 | "ofType" : { 3388 | "kind" : "NON_NULL", 3389 | "name" : null, 3390 | "ofType" : { 3391 | "kind" : "OBJECT", 3392 | "name" : "__Type", 3393 | "ofType" : null 3394 | } 3395 | } 3396 | }, 3397 | "isDeprecated" : false, 3398 | "deprecationReason" : null 3399 | }, { 3400 | "name" : "possibleTypes", 3401 | "description" : null, 3402 | "args" : [ ], 3403 | "type" : { 3404 | "kind" : "LIST", 3405 | "name" : null, 3406 | "ofType" : { 3407 | "kind" : "NON_NULL", 3408 | "name" : null, 3409 | "ofType" : { 3410 | "kind" : "OBJECT", 3411 | "name" : "__Type", 3412 | "ofType" : null 3413 | } 3414 | } 3415 | }, 3416 | "isDeprecated" : false, 3417 | "deprecationReason" : null 3418 | }, { 3419 | "name" : "enumValues", 3420 | "description" : null, 3421 | "args" : [ { 3422 | "name" : "includeDeprecated", 3423 | "description" : null, 3424 | "type" : { 3425 | "kind" : "SCALAR", 3426 | "name" : "Boolean", 3427 | "ofType" : null 3428 | }, 3429 | "defaultValue" : "false" 3430 | } ], 3431 | "type" : { 3432 | "kind" : "LIST", 3433 | "name" : null, 3434 | "ofType" : { 3435 | "kind" : "NON_NULL", 3436 | "name" : null, 3437 | "ofType" : { 3438 | "kind" : "OBJECT", 3439 | "name" : "__EnumValue", 3440 | "ofType" : null 3441 | } 3442 | } 3443 | }, 3444 | "isDeprecated" : false, 3445 | "deprecationReason" : null 3446 | }, { 3447 | "name" : "inputFields", 3448 | "description" : null, 3449 | "args" : [ ], 3450 | "type" : { 3451 | "kind" : "LIST", 3452 | "name" : null, 3453 | "ofType" : { 3454 | "kind" : "NON_NULL", 3455 | "name" : null, 3456 | "ofType" : { 3457 | "kind" : "OBJECT", 3458 | "name" : "__InputValue", 3459 | "ofType" : null 3460 | } 3461 | } 3462 | }, 3463 | "isDeprecated" : false, 3464 | "deprecationReason" : null 3465 | }, { 3466 | "name" : "ofType", 3467 | "description" : null, 3468 | "args" : [ ], 3469 | "type" : { 3470 | "kind" : "OBJECT", 3471 | "name" : "__Type", 3472 | "ofType" : null 3473 | }, 3474 | "isDeprecated" : false, 3475 | "deprecationReason" : null 3476 | } ], 3477 | "inputFields" : null, 3478 | "interfaces" : [ ], 3479 | "enumValues" : null, 3480 | "possibleTypes" : null 3481 | }, { 3482 | "kind" : "ENUM", 3483 | "name" : "__TypeKind", 3484 | "description" : "An enum describing what kind of type a given __Type is", 3485 | "fields" : null, 3486 | "inputFields" : null, 3487 | "interfaces" : null, 3488 | "enumValues" : [ { 3489 | "name" : "SCALAR", 3490 | "description" : "Indicates this type is a scalar.", 3491 | "isDeprecated" : false, 3492 | "deprecationReason" : null 3493 | }, { 3494 | "name" : "OBJECT", 3495 | "description" : "Indicates this type is an object. `fields` and `interfaces` are valid fields.", 3496 | "isDeprecated" : false, 3497 | "deprecationReason" : null 3498 | }, { 3499 | "name" : "INTERFACE", 3500 | "description" : "Indicates this type is an interface. `fields` and `possibleTypes` are valid fields.", 3501 | "isDeprecated" : false, 3502 | "deprecationReason" : null 3503 | }, { 3504 | "name" : "UNION", 3505 | "description" : "Indicates this type is a union. `possibleTypes` is a valid field.", 3506 | "isDeprecated" : false, 3507 | "deprecationReason" : null 3508 | }, { 3509 | "name" : "ENUM", 3510 | "description" : "Indicates this type is an enum. `enumValues` is a valid field.", 3511 | "isDeprecated" : false, 3512 | "deprecationReason" : null 3513 | }, { 3514 | "name" : "INPUT_OBJECT", 3515 | "description" : "Indicates this type is an input object. `inputFields` is a valid field.", 3516 | "isDeprecated" : false, 3517 | "deprecationReason" : null 3518 | }, { 3519 | "name" : "LIST", 3520 | "description" : "Indicates this type is a list. `ofType` is a valid field.", 3521 | "isDeprecated" : false, 3522 | "deprecationReason" : null 3523 | }, { 3524 | "name" : "NON_NULL", 3525 | "description" : "Indicates this type is a non-null. `ofType` is a valid field.", 3526 | "isDeprecated" : false, 3527 | "deprecationReason" : null 3528 | } ], 3529 | "possibleTypes" : null 3530 | }, { 3531 | "kind" : "OBJECT", 3532 | "name" : "__Field", 3533 | "description" : null, 3534 | "fields" : [ { 3535 | "name" : "name", 3536 | "description" : null, 3537 | "args" : [ ], 3538 | "type" : { 3539 | "kind" : "NON_NULL", 3540 | "name" : null, 3541 | "ofType" : { 3542 | "kind" : "SCALAR", 3543 | "name" : "String", 3544 | "ofType" : null 3545 | } 3546 | }, 3547 | "isDeprecated" : false, 3548 | "deprecationReason" : null 3549 | }, { 3550 | "name" : "description", 3551 | "description" : null, 3552 | "args" : [ ], 3553 | "type" : { 3554 | "kind" : "SCALAR", 3555 | "name" : "String", 3556 | "ofType" : null 3557 | }, 3558 | "isDeprecated" : false, 3559 | "deprecationReason" : null 3560 | }, { 3561 | "name" : "args", 3562 | "description" : null, 3563 | "args" : [ ], 3564 | "type" : { 3565 | "kind" : "NON_NULL", 3566 | "name" : null, 3567 | "ofType" : { 3568 | "kind" : "LIST", 3569 | "name" : null, 3570 | "ofType" : { 3571 | "kind" : "NON_NULL", 3572 | "name" : null, 3573 | "ofType" : { 3574 | "kind" : "OBJECT", 3575 | "name" : "__InputValue", 3576 | "ofType" : null 3577 | } 3578 | } 3579 | } 3580 | }, 3581 | "isDeprecated" : false, 3582 | "deprecationReason" : null 3583 | }, { 3584 | "name" : "type", 3585 | "description" : null, 3586 | "args" : [ ], 3587 | "type" : { 3588 | "kind" : "NON_NULL", 3589 | "name" : null, 3590 | "ofType" : { 3591 | "kind" : "OBJECT", 3592 | "name" : "__Type", 3593 | "ofType" : null 3594 | } 3595 | }, 3596 | "isDeprecated" : false, 3597 | "deprecationReason" : null 3598 | }, { 3599 | "name" : "isDeprecated", 3600 | "description" : null, 3601 | "args" : [ ], 3602 | "type" : { 3603 | "kind" : "NON_NULL", 3604 | "name" : null, 3605 | "ofType" : { 3606 | "kind" : "SCALAR", 3607 | "name" : "Boolean", 3608 | "ofType" : null 3609 | } 3610 | }, 3611 | "isDeprecated" : false, 3612 | "deprecationReason" : null 3613 | }, { 3614 | "name" : "deprecationReason", 3615 | "description" : null, 3616 | "args" : [ ], 3617 | "type" : { 3618 | "kind" : "SCALAR", 3619 | "name" : "String", 3620 | "ofType" : null 3621 | }, 3622 | "isDeprecated" : false, 3623 | "deprecationReason" : null 3624 | } ], 3625 | "inputFields" : null, 3626 | "interfaces" : [ ], 3627 | "enumValues" : null, 3628 | "possibleTypes" : null 3629 | }, { 3630 | "kind" : "OBJECT", 3631 | "name" : "__InputValue", 3632 | "description" : null, 3633 | "fields" : [ { 3634 | "name" : "name", 3635 | "description" : null, 3636 | "args" : [ ], 3637 | "type" : { 3638 | "kind" : "NON_NULL", 3639 | "name" : null, 3640 | "ofType" : { 3641 | "kind" : "SCALAR", 3642 | "name" : "String", 3643 | "ofType" : null 3644 | } 3645 | }, 3646 | "isDeprecated" : false, 3647 | "deprecationReason" : null 3648 | }, { 3649 | "name" : "description", 3650 | "description" : null, 3651 | "args" : [ ], 3652 | "type" : { 3653 | "kind" : "SCALAR", 3654 | "name" : "String", 3655 | "ofType" : null 3656 | }, 3657 | "isDeprecated" : false, 3658 | "deprecationReason" : null 3659 | }, { 3660 | "name" : "type", 3661 | "description" : null, 3662 | "args" : [ ], 3663 | "type" : { 3664 | "kind" : "NON_NULL", 3665 | "name" : null, 3666 | "ofType" : { 3667 | "kind" : "OBJECT", 3668 | "name" : "__Type", 3669 | "ofType" : null 3670 | } 3671 | }, 3672 | "isDeprecated" : false, 3673 | "deprecationReason" : null 3674 | }, { 3675 | "name" : "defaultValue", 3676 | "description" : null, 3677 | "args" : [ ], 3678 | "type" : { 3679 | "kind" : "SCALAR", 3680 | "name" : "String", 3681 | "ofType" : null 3682 | }, 3683 | "isDeprecated" : false, 3684 | "deprecationReason" : null 3685 | } ], 3686 | "inputFields" : null, 3687 | "interfaces" : [ ], 3688 | "enumValues" : null, 3689 | "possibleTypes" : null 3690 | }, { 3691 | "kind" : "OBJECT", 3692 | "name" : "__EnumValue", 3693 | "description" : null, 3694 | "fields" : [ { 3695 | "name" : "name", 3696 | "description" : null, 3697 | "args" : [ ], 3698 | "type" : { 3699 | "kind" : "NON_NULL", 3700 | "name" : null, 3701 | "ofType" : { 3702 | "kind" : "SCALAR", 3703 | "name" : "String", 3704 | "ofType" : null 3705 | } 3706 | }, 3707 | "isDeprecated" : false, 3708 | "deprecationReason" : null 3709 | }, { 3710 | "name" : "description", 3711 | "description" : null, 3712 | "args" : [ ], 3713 | "type" : { 3714 | "kind" : "SCALAR", 3715 | "name" : "String", 3716 | "ofType" : null 3717 | }, 3718 | "isDeprecated" : false, 3719 | "deprecationReason" : null 3720 | }, { 3721 | "name" : "isDeprecated", 3722 | "description" : null, 3723 | "args" : [ ], 3724 | "type" : { 3725 | "kind" : "NON_NULL", 3726 | "name" : null, 3727 | "ofType" : { 3728 | "kind" : "SCALAR", 3729 | "name" : "Boolean", 3730 | "ofType" : null 3731 | } 3732 | }, 3733 | "isDeprecated" : false, 3734 | "deprecationReason" : null 3735 | }, { 3736 | "name" : "deprecationReason", 3737 | "description" : null, 3738 | "args" : [ ], 3739 | "type" : { 3740 | "kind" : "SCALAR", 3741 | "name" : "String", 3742 | "ofType" : null 3743 | }, 3744 | "isDeprecated" : false, 3745 | "deprecationReason" : null 3746 | } ], 3747 | "inputFields" : null, 3748 | "interfaces" : [ ], 3749 | "enumValues" : null, 3750 | "possibleTypes" : null 3751 | }, { 3752 | "kind" : "OBJECT", 3753 | "name" : "__Directive", 3754 | "description" : null, 3755 | "fields" : [ { 3756 | "name" : "name", 3757 | "description" : null, 3758 | "args" : [ ], 3759 | "type" : { 3760 | "kind" : "SCALAR", 3761 | "name" : "String", 3762 | "ofType" : null 3763 | }, 3764 | "isDeprecated" : false, 3765 | "deprecationReason" : null 3766 | }, { 3767 | "name" : "description", 3768 | "description" : null, 3769 | "args" : [ ], 3770 | "type" : { 3771 | "kind" : "SCALAR", 3772 | "name" : "String", 3773 | "ofType" : null 3774 | }, 3775 | "isDeprecated" : false, 3776 | "deprecationReason" : null 3777 | }, { 3778 | "name" : "locations", 3779 | "description" : null, 3780 | "args" : [ ], 3781 | "type" : { 3782 | "kind" : "LIST", 3783 | "name" : null, 3784 | "ofType" : { 3785 | "kind" : "NON_NULL", 3786 | "name" : null, 3787 | "ofType" : { 3788 | "kind" : "ENUM", 3789 | "name" : "__DirectiveLocation", 3790 | "ofType" : null 3791 | } 3792 | } 3793 | }, 3794 | "isDeprecated" : false, 3795 | "deprecationReason" : null 3796 | }, { 3797 | "name" : "args", 3798 | "description" : null, 3799 | "args" : [ ], 3800 | "type" : { 3801 | "kind" : "NON_NULL", 3802 | "name" : null, 3803 | "ofType" : { 3804 | "kind" : "LIST", 3805 | "name" : null, 3806 | "ofType" : { 3807 | "kind" : "NON_NULL", 3808 | "name" : null, 3809 | "ofType" : { 3810 | "kind" : "OBJECT", 3811 | "name" : "__InputValue", 3812 | "ofType" : null 3813 | } 3814 | } 3815 | } 3816 | }, 3817 | "isDeprecated" : false, 3818 | "deprecationReason" : null 3819 | }, { 3820 | "name" : "onOperation", 3821 | "description" : null, 3822 | "args" : [ ], 3823 | "type" : { 3824 | "kind" : "SCALAR", 3825 | "name" : "Boolean", 3826 | "ofType" : null 3827 | }, 3828 | "isDeprecated" : true, 3829 | "deprecationReason" : "Use `locations`." 3830 | }, { 3831 | "name" : "onFragment", 3832 | "description" : null, 3833 | "args" : [ ], 3834 | "type" : { 3835 | "kind" : "SCALAR", 3836 | "name" : "Boolean", 3837 | "ofType" : null 3838 | }, 3839 | "isDeprecated" : true, 3840 | "deprecationReason" : "Use `locations`." 3841 | }, { 3842 | "name" : "onField", 3843 | "description" : null, 3844 | "args" : [ ], 3845 | "type" : { 3846 | "kind" : "SCALAR", 3847 | "name" : "Boolean", 3848 | "ofType" : null 3849 | }, 3850 | "isDeprecated" : true, 3851 | "deprecationReason" : "Use `locations`." 3852 | } ], 3853 | "inputFields" : null, 3854 | "interfaces" : [ ], 3855 | "enumValues" : null, 3856 | "possibleTypes" : null 3857 | }, { 3858 | "kind" : "ENUM", 3859 | "name" : "__DirectiveLocation", 3860 | "description" : "An enum describing valid locations where a directive can be placed", 3861 | "fields" : null, 3862 | "inputFields" : null, 3863 | "interfaces" : null, 3864 | "enumValues" : [ { 3865 | "name" : "QUERY", 3866 | "description" : "Indicates the directive is valid on queries.", 3867 | "isDeprecated" : false, 3868 | "deprecationReason" : null 3869 | }, { 3870 | "name" : "MUTATION", 3871 | "description" : "Indicates the directive is valid on mutations.", 3872 | "isDeprecated" : false, 3873 | "deprecationReason" : null 3874 | }, { 3875 | "name" : "FIELD", 3876 | "description" : "Indicates the directive is valid on fields.", 3877 | "isDeprecated" : false, 3878 | "deprecationReason" : null 3879 | }, { 3880 | "name" : "FRAGMENT_DEFINITION", 3881 | "description" : "Indicates the directive is valid on fragment definitions.", 3882 | "isDeprecated" : false, 3883 | "deprecationReason" : null 3884 | }, { 3885 | "name" : "FRAGMENT_SPREAD", 3886 | "description" : "Indicates the directive is valid on fragment spreads.", 3887 | "isDeprecated" : false, 3888 | "deprecationReason" : null 3889 | }, { 3890 | "name" : "INLINE_FRAGMENT", 3891 | "description" : "Indicates the directive is valid on inline fragments.", 3892 | "isDeprecated" : false, 3893 | "deprecationReason" : null 3894 | }, { 3895 | "name" : "SCHEMA", 3896 | "description" : "Indicates the directive is valid on a schema SDL definition.", 3897 | "isDeprecated" : false, 3898 | "deprecationReason" : null 3899 | }, { 3900 | "name" : "SCALAR", 3901 | "description" : "Indicates the directive is valid on a scalar SDL definition.", 3902 | "isDeprecated" : false, 3903 | "deprecationReason" : null 3904 | }, { 3905 | "name" : "OBJECT", 3906 | "description" : "Indicates the directive is valid on an object SDL definition.", 3907 | "isDeprecated" : false, 3908 | "deprecationReason" : null 3909 | }, { 3910 | "name" : "FIELD_DEFINITION", 3911 | "description" : "Indicates the directive is valid on a field SDL definition.", 3912 | "isDeprecated" : false, 3913 | "deprecationReason" : null 3914 | }, { 3915 | "name" : "ARGUMENT_DEFINITION", 3916 | "description" : "Indicates the directive is valid on a field argument SDL definition.", 3917 | "isDeprecated" : false, 3918 | "deprecationReason" : null 3919 | }, { 3920 | "name" : "INTERFACE", 3921 | "description" : "Indicates the directive is valid on an interface SDL definition.", 3922 | "isDeprecated" : false, 3923 | "deprecationReason" : null 3924 | }, { 3925 | "name" : "UNION", 3926 | "description" : "Indicates the directive is valid on an union SDL definition.", 3927 | "isDeprecated" : false, 3928 | "deprecationReason" : null 3929 | }, { 3930 | "name" : "ENUM", 3931 | "description" : "Indicates the directive is valid on an enum SDL definition.", 3932 | "isDeprecated" : false, 3933 | "deprecationReason" : null 3934 | }, { 3935 | "name" : "ENUM_VALUE", 3936 | "description" : "Indicates the directive is valid on an enum value SDL definition.", 3937 | "isDeprecated" : false, 3938 | "deprecationReason" : null 3939 | }, { 3940 | "name" : "INPUT_OBJECT", 3941 | "description" : "Indicates the directive is valid on an input object SDL definition.", 3942 | "isDeprecated" : false, 3943 | "deprecationReason" : null 3944 | }, { 3945 | "name" : "INPUT_FIELD_DEFINITION", 3946 | "description" : "Indicates the directive is valid on an input object field SDL definition.", 3947 | "isDeprecated" : false, 3948 | "deprecationReason" : null 3949 | } ], 3950 | "possibleTypes" : null 3951 | } ], 3952 | "directives" : [ { 3953 | "name" : "include", 3954 | "description" : "Directs the executor to include this field or fragment only when the `if` argument is true", 3955 | "locations" : [ "FIELD", "FRAGMENT_SPREAD", "INLINE_FRAGMENT" ], 3956 | "args" : [ { 3957 | "name" : "if", 3958 | "description" : "Included when true.", 3959 | "type" : { 3960 | "kind" : "NON_NULL", 3961 | "name" : null, 3962 | "ofType" : { 3963 | "kind" : "SCALAR", 3964 | "name" : "Boolean", 3965 | "ofType" : null 3966 | } 3967 | }, 3968 | "defaultValue" : null 3969 | } ], 3970 | "onOperation" : false, 3971 | "onFragment" : true, 3972 | "onField" : true 3973 | }, { 3974 | "name" : "skip", 3975 | "description" : "Directs the executor to skip this field or fragment when the `if`'argument is true.", 3976 | "locations" : [ "FIELD", "FRAGMENT_SPREAD", "INLINE_FRAGMENT" ], 3977 | "args" : [ { 3978 | "name" : "if", 3979 | "description" : "Skipped when true.", 3980 | "type" : { 3981 | "kind" : "NON_NULL", 3982 | "name" : null, 3983 | "ofType" : { 3984 | "kind" : "SCALAR", 3985 | "name" : "Boolean", 3986 | "ofType" : null 3987 | } 3988 | }, 3989 | "defaultValue" : null 3990 | } ], 3991 | "onOperation" : false, 3992 | "onFragment" : true, 3993 | "onField" : true 3994 | }, { 3995 | "name" : "defer", 3996 | "description" : "This directive allows results to be deferred during execution", 3997 | "locations" : [ "FIELD" ], 3998 | "args" : [ ], 3999 | "onOperation" : false, 4000 | "onFragment" : false, 4001 | "onField" : true 4002 | }, { 4003 | "name" : "aws_oidc", 4004 | "description" : "Tells the service this field/object has access authorized by an OIDC token.", 4005 | "locations" : [ "OBJECT", "FIELD_DEFINITION" ], 4006 | "args" : [ ], 4007 | "onOperation" : false, 4008 | "onFragment" : false, 4009 | "onField" : false 4010 | }, { 4011 | "name" : "aws_auth", 4012 | "description" : "Directs the schema to enforce authorization on a field", 4013 | "locations" : [ "FIELD_DEFINITION" ], 4014 | "args" : [ { 4015 | "name" : "cognito_groups", 4016 | "description" : "List of cognito user pool groups which have access on this field", 4017 | "type" : { 4018 | "kind" : "LIST", 4019 | "name" : null, 4020 | "ofType" : { 4021 | "kind" : "SCALAR", 4022 | "name" : "String", 4023 | "ofType" : null 4024 | } 4025 | }, 4026 | "defaultValue" : null 4027 | } ], 4028 | "onOperation" : false, 4029 | "onFragment" : false, 4030 | "onField" : false 4031 | }, { 4032 | "name" : "aws_publish", 4033 | "description" : "Tells the service which subscriptions will be published to when this mutation is called. This directive is deprecated use @aws_susbscribe directive instead.", 4034 | "locations" : [ "FIELD_DEFINITION" ], 4035 | "args" : [ { 4036 | "name" : "subscriptions", 4037 | "description" : "List of subscriptions which will be published to when this mutation is called.", 4038 | "type" : { 4039 | "kind" : "LIST", 4040 | "name" : null, 4041 | "ofType" : { 4042 | "kind" : "SCALAR", 4043 | "name" : "String", 4044 | "ofType" : null 4045 | } 4046 | }, 4047 | "defaultValue" : null 4048 | } ], 4049 | "onOperation" : false, 4050 | "onFragment" : false, 4051 | "onField" : false 4052 | }, { 4053 | "name" : "deprecated", 4054 | "description" : null, 4055 | "locations" : [ "FIELD_DEFINITION", "ENUM_VALUE" ], 4056 | "args" : [ { 4057 | "name" : "reason", 4058 | "description" : null, 4059 | "type" : { 4060 | "kind" : "SCALAR", 4061 | "name" : "String", 4062 | "ofType" : null 4063 | }, 4064 | "defaultValue" : "\"No longer supported\"" 4065 | } ], 4066 | "onOperation" : false, 4067 | "onFragment" : false, 4068 | "onField" : false 4069 | }, { 4070 | "name" : "aws_cognito_user_pools", 4071 | "description" : "Tells the service this field/object has access authorized by a Cognito User Pools token.", 4072 | "locations" : [ "OBJECT", "FIELD_DEFINITION" ], 4073 | "args" : [ { 4074 | "name" : "cognito_groups", 4075 | "description" : "List of cognito user pool groups which have access on this field", 4076 | "type" : { 4077 | "kind" : "LIST", 4078 | "name" : null, 4079 | "ofType" : { 4080 | "kind" : "SCALAR", 4081 | "name" : "String", 4082 | "ofType" : null 4083 | } 4084 | }, 4085 | "defaultValue" : null 4086 | } ], 4087 | "onOperation" : false, 4088 | "onFragment" : false, 4089 | "onField" : false 4090 | }, { 4091 | "name" : "aws_subscribe", 4092 | "description" : "Tells the service which mutation triggers this subscription.", 4093 | "locations" : [ "FIELD_DEFINITION" ], 4094 | "args" : [ { 4095 | "name" : "mutations", 4096 | "description" : "List of mutations which will trigger this subscription when they are called.", 4097 | "type" : { 4098 | "kind" : "LIST", 4099 | "name" : null, 4100 | "ofType" : { 4101 | "kind" : "SCALAR", 4102 | "name" : "String", 4103 | "ofType" : null 4104 | } 4105 | }, 4106 | "defaultValue" : null 4107 | } ], 4108 | "onOperation" : false, 4109 | "onFragment" : false, 4110 | "onField" : false 4111 | }, { 4112 | "name" : "aws_iam", 4113 | "description" : "Tells the service this field/object has access authorized by sigv4 signing.", 4114 | "locations" : [ "OBJECT", "FIELD_DEFINITION" ], 4115 | "args" : [ ], 4116 | "onOperation" : false, 4117 | "onFragment" : false, 4118 | "onField" : false 4119 | }, { 4120 | "name" : "aws_api_key", 4121 | "description" : "Tells the service this field/object has access authorized by an API key.", 4122 | "locations" : [ "OBJECT", "FIELD_DEFINITION" ], 4123 | "args" : [ ], 4124 | "onOperation" : false, 4125 | "onFragment" : false, 4126 | "onField" : false 4127 | } ] 4128 | } 4129 | } 4130 | } -------------------------------------------------------------------------------- /frontend-example/src/graphql/subscriptions.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | // this is an auto generated file. This will be overwritten 3 | 4 | export const onCreateProduct = /* GraphQL */ ` 5 | subscription OnCreateProduct { 6 | onCreateProduct { 7 | id 8 | name 9 | description 10 | price 11 | active 12 | added 13 | _version 14 | _deleted 15 | _lastChangedAt 16 | } 17 | } 18 | `; 19 | export const onUpdateProduct = /* GraphQL */ ` 20 | subscription OnUpdateProduct { 21 | onUpdateProduct { 22 | id 23 | name 24 | description 25 | price 26 | active 27 | added 28 | _version 29 | _deleted 30 | _lastChangedAt 31 | } 32 | } 33 | `; 34 | export const onDeleteProduct = /* GraphQL */ ` 35 | subscription OnDeleteProduct { 36 | onDeleteProduct { 37 | id 38 | name 39 | description 40 | price 41 | active 42 | added 43 | _version 44 | _deleted 45 | _lastChangedAt 46 | } 47 | } 48 | `; 49 | export const onCreateOrder = /* GraphQL */ ` 50 | subscription OnCreateOrder { 51 | onCreateOrder { 52 | id 53 | productID 54 | total 55 | ordered 56 | _version 57 | _deleted 58 | _lastChangedAt 59 | } 60 | } 61 | `; 62 | export const onUpdateOrder = /* GraphQL */ ` 63 | subscription OnUpdateOrder { 64 | onUpdateOrder { 65 | id 66 | productID 67 | total 68 | ordered 69 | _version 70 | _deleted 71 | _lastChangedAt 72 | } 73 | } 74 | `; 75 | export const onDeleteOrder = /* GraphQL */ ` 76 | subscription OnDeleteOrder { 77 | onDeleteOrder { 78 | id 79 | productID 80 | total 81 | ordered 82 | _version 83 | _deleted 84 | _lastChangedAt 85 | } 86 | } 87 | `; 88 | export const onCreateCustomer = /* GraphQL */ ` 89 | subscription OnCreateCustomer($owner: String) { 90 | onCreateCustomer(owner: $owner) { 91 | id 92 | firstName 93 | lastName 94 | active 95 | address 96 | _version 97 | _deleted 98 | _lastChangedAt 99 | version 100 | owner 101 | } 102 | } 103 | `; 104 | export const onUpdateCustomer = /* GraphQL */ ` 105 | subscription OnUpdateCustomer($owner: String) { 106 | onUpdateCustomer(owner: $owner) { 107 | id 108 | firstName 109 | lastName 110 | active 111 | address 112 | _version 113 | _deleted 114 | _lastChangedAt 115 | version 116 | owner 117 | } 118 | } 119 | `; 120 | export const onDeleteCustomer = /* GraphQL */ ` 121 | subscription OnDeleteCustomer($owner: String) { 122 | onDeleteCustomer(owner: $owner) { 123 | id 124 | firstName 125 | lastName 126 | active 127 | address 128 | _version 129 | _deleted 130 | _lastChangedAt 131 | version 132 | owner 133 | } 134 | } 135 | `; 136 | -------------------------------------------------------------------------------- /frontend-example/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 | table { 16 | font-family: arial, sans-serif; 17 | border-collapse: collapse; 18 | width: 100%; 19 | } 20 | 21 | td, th { 22 | border: 1px solid #dddddd; 23 | text-align: left; 24 | padding: 8px; 25 | } -------------------------------------------------------------------------------- /frontend-example/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import './index.css'; 4 | import App from './App'; 5 | import * as serviceWorker from './serviceWorker'; 6 | 7 | ReactDOM.render( 8 | 9 | 10 | , 11 | document.getElementById('root') 12 | ); 13 | 14 | // If you want your app to work offline and load faster, you can change 15 | // unregister() to register() below. Note this comes with some pitfalls. 16 | // Learn more about service workers: https://bit.ly/CRA-PWA 17 | serviceWorker.unregister(); 18 | -------------------------------------------------------------------------------- /frontend-example/src/models/index.js: -------------------------------------------------------------------------------- 1 | // @ts-check 2 | import { initSchema } from '@aws-amplify/datastore'; 3 | import { schema } from './schema'; 4 | 5 | 6 | 7 | const { Customer, Product, Order } = initSchema(schema); 8 | 9 | export { 10 | Customer, 11 | Product, 12 | Order 13 | }; -------------------------------------------------------------------------------- /frontend-example/src/models/schema.js: -------------------------------------------------------------------------------- 1 | export const schema = { 2 | "models": { 3 | "Customer": { 4 | "syncable": true, 5 | "name": "Customer", 6 | "pluralName": "Customers", 7 | "attributes": [ 8 | { 9 | "type": "model", 10 | "properties": {} 11 | } 12 | ], 13 | "fields": { 14 | "id": { 15 | "name": "id", 16 | "isArray": false, 17 | "type": "ID", 18 | "isRequired": true, 19 | "attributes": [] 20 | }, 21 | "firstName": { 22 | "name": "firstName", 23 | "isArray": false, 24 | "type": "String", 25 | "isRequired": true, 26 | "attributes": [] 27 | }, 28 | "lastName": { 29 | "name": "lastName", 30 | "isArray": false, 31 | "type": "String", 32 | "isRequired": true, 33 | "attributes": [] 34 | }, 35 | "active": { 36 | "name": "active", 37 | "isArray": false, 38 | "type": "Boolean", 39 | "isRequired": true, 40 | "attributes": [] 41 | }, 42 | "address": { 43 | "name": "address", 44 | "isArray": false, 45 | "type": "String", 46 | "isRequired": true, 47 | "attributes": [] 48 | } 49 | } 50 | }, 51 | "Product": { 52 | "syncable": true, 53 | "name": "Product", 54 | "pluralName": "Products", 55 | "attributes": [ 56 | { 57 | "type": "model", 58 | "properties": {} 59 | } 60 | ], 61 | "fields": { 62 | "id": { 63 | "name": "id", 64 | "isArray": false, 65 | "type": "ID", 66 | "isRequired": true, 67 | "attributes": [] 68 | }, 69 | "name": { 70 | "name": "name", 71 | "isArray": false, 72 | "type": "String", 73 | "isRequired": true, 74 | "attributes": [] 75 | }, 76 | "description": { 77 | "name": "description", 78 | "isArray": false, 79 | "type": "String", 80 | "isRequired": true, 81 | "attributes": [] 82 | }, 83 | "price": { 84 | "name": "price", 85 | "isArray": false, 86 | "type": "String", 87 | "isRequired": true, 88 | "attributes": [] 89 | }, 90 | "active": { 91 | "name": "active", 92 | "isArray": false, 93 | "type": "Boolean", 94 | "isRequired": true, 95 | "attributes": [] 96 | }, 97 | "added": { 98 | "name": "added", 99 | "isArray": false, 100 | "type": "AWSDateTime", 101 | "isRequired": true, 102 | "attributes": [] 103 | } 104 | } 105 | }, 106 | "Order": { 107 | "syncable": true, 108 | "name": "Order", 109 | "pluralName": "Orders", 110 | "attributes": [ 111 | { 112 | "type": "model", 113 | "properties": {} 114 | }, 115 | { 116 | "type": "key", 117 | "properties": { 118 | "fields": [ 119 | "id", 120 | "productID" 121 | ] 122 | } 123 | } 124 | ], 125 | "fields": { 126 | "id": { 127 | "name": "id", 128 | "isArray": false, 129 | "type": "ID", 130 | "isRequired": true, 131 | "attributes": [] 132 | }, 133 | "productID": { 134 | "name": "productID", 135 | "isArray": false, 136 | "type": "ID", 137 | "isRequired": true, 138 | "attributes": [] 139 | }, 140 | "total": { 141 | "name": "total", 142 | "isArray": false, 143 | "type": "String", 144 | "isRequired": true, 145 | "attributes": [] 146 | }, 147 | "ordered": { 148 | "name": "ordered", 149 | "isArray": false, 150 | "type": "AWSDateTime", 151 | "isRequired": true, 152 | "attributes": [] 153 | } 154 | } 155 | } 156 | }, 157 | "enums": {}, 158 | "version": "f2efde37854af9fbf68d0db2b7f71b3c" 159 | }; -------------------------------------------------------------------------------- /frontend-example/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 | -------------------------------------------------------------------------------- /frontend-example/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 | -------------------------------------------------------------------------------- /lib/app-stack.ts: -------------------------------------------------------------------------------- 1 | import * as cdk from '@aws-cdk/core'; 2 | import { PolicyStatement, Effect } from '@aws-cdk/aws-iam' 3 | import { GraphQLApi, FieldLogLevel, MappingTemplate } from '@aws-cdk/aws-appsync'; 4 | import { Table, AttributeType, BillingMode, ProjectionType } from '@aws-cdk/aws-dynamodb'; 5 | 6 | export class AppStack extends cdk.Stack { 7 | private isSyncEnabled: boolean 8 | private syncTable: Table 9 | 10 | constructor(scope: cdk.Construct, id: string, outputs: any, resolvers: any, props?: cdk.StackProps) { 11 | super(scope, id, props); 12 | 13 | const STAGE = this.node.tryGetContext('STAGE') 14 | 15 | const api = new GraphQLApi( 16 | this, 17 | 'demo-gql-api', { 18 | name: `demo-api-${STAGE}`, 19 | authorizationConfig: { 20 | defaultAuthorization: { 21 | apiKeyDesc: 'Dev Testing Only', 22 | expire: 100 23 | }, 24 | }, 25 | logConfig: { 26 | fieldLogLevel: FieldLogLevel.ERROR, 27 | }, 28 | schemaDefinitionFile: './appsync/schema.graphql' 29 | }) 30 | 31 | let tableData = outputs.CDK_TABLES 32 | 33 | // Check to see if sync is enabled 34 | if (tableData['DataStore']) { 35 | this.isSyncEnabled = true 36 | this.syncTable = this.createSyncTable(tableData['DataStore']); 37 | delete tableData['DataStore'] // We don't want to create this again below so remove it from the tableData map 38 | } 39 | 40 | this.createTablesAndResolvers(api, tableData, resolvers) 41 | } 42 | 43 | createTablesAndResolvers(api: GraphQLApi, tableData: any, resolvers: any) { 44 | Object.keys(tableData).forEach((tableKey: any) => { 45 | const table = this.createTable(tableData[tableKey]); 46 | const dataSource = api.addDynamoDbDataSource(tableKey, `Data source for ${tableKey}`, table); 47 | 48 | // https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-appsync-datasource-deltasyncconfig.html 49 | 50 | if (this.isSyncEnabled) { 51 | //@ts-ignore - ds is the base CfnDataSource and the db config needs to be versioned - see CfnDataSource 52 | dataSource.ds.dynamoDbConfig.versioned = true 53 | 54 | //@ts-ignore - ds is the base CfnDataSource - see CfnDataSource 55 | dataSource.ds.dynamoDbConfig.deltaSyncConfig = { 56 | baseTableTtl: '43200', // Got this value from amplify - 30 days in minutes 57 | deltaSyncTableName: this.syncTable.tableName, 58 | deltaSyncTableTtl: '30' // Got this value from amplify - 30 minutes 59 | } 60 | 61 | // Need to add permission for our datasource service role to access the sync table 62 | dataSource.grantPrincipal.addToPolicy(new PolicyStatement({ 63 | effect: Effect.ALLOW, 64 | actions: [ 65 | 'dynamodb:*' 66 | ], 67 | resources: [ 68 | this.syncTable.tableArn 69 | ] 70 | })) 71 | } 72 | 73 | Object.keys(resolvers).forEach((resolverKey: any) => { 74 | let resolverTableName = this.getTableNameFromFieldName(resolverKey) 75 | if (tableKey === resolverTableName) { 76 | let resolver = resolvers[resolverKey] 77 | 78 | dataSource.createResolver({ 79 | typeName: resolver.typeName, 80 | fieldName: resolver.fieldName, 81 | requestMappingTemplate: MappingTemplate.fromFile(resolver.requestMappingTemplate), 82 | responseMappingTemplate: MappingTemplate.fromFile(resolver.responseMappingTemplate), 83 | }) 84 | } 85 | }) 86 | }); 87 | } 88 | 89 | createTable(tableData: any) { 90 | let tableProps: any = { 91 | billingMode: BillingMode.PAY_PER_REQUEST, 92 | partitionKey: { 93 | name: tableData.PartitionKey.name, 94 | type: this.convertAttributeType(tableData.PartitionKey.type) 95 | } 96 | }; 97 | 98 | if (tableData.SortKey && tableData.SortKey.name) { 99 | tableProps.sortKey = { 100 | name: tableData.SortKey.name, 101 | type: this.convertAttributeType(tableData.SortKey.type) 102 | }; 103 | }; 104 | 105 | if (tableData.TTL && tableData.TTL.Enabled) { 106 | tableProps.timeToLiveAttribute = tableData.TTL.AttributeName; 107 | } 108 | 109 | let table = new Table(this, tableData.TableName, tableProps); 110 | 111 | if (tableData.GlobalSecondaryIndexes && tableData.GlobalSecondaryIndexes.length > 0) { 112 | tableData.GlobalSecondaryIndexes.forEach((gsi: any) => { 113 | table.addGlobalSecondaryIndex({ 114 | indexName: gsi.IndexName, 115 | partitionKey: { 116 | name: gsi.PartitionKey.name, 117 | type: this.convertAttributeType(gsi.PartitionKey.type) 118 | }, 119 | projectionType: this.convertProjectionType(gsi.Projection.ProjectionType) 120 | }) 121 | }) 122 | } 123 | 124 | return table; 125 | } 126 | 127 | // https://docs.aws.amazon.com/appsync/latest/devguide/conflict-detection-and-sync.html 128 | createSyncTable(tableData: any) { 129 | return new Table(this, 'sync-table', { 130 | billingMode: BillingMode.PAY_PER_REQUEST, 131 | partitionKey: { 132 | name: tableData.PartitionKey.name, 133 | type: this.convertAttributeType(tableData.PartitionKey.type) 134 | }, 135 | sortKey: { 136 | name: tableData.SortKey.name, 137 | type: this.convertAttributeType(tableData.SortKey.type) 138 | }, 139 | timeToLiveAttribute: tableData.TTL?.AttributeName || '_ttl' 140 | }) 141 | } 142 | 143 | convertAttributeType(type: string) { 144 | switch (type) { 145 | case 'S': 146 | return AttributeType.STRING 147 | case 'N': 148 | return AttributeType.NUMBER 149 | case 'B': 150 | return AttributeType.BINARY 151 | default: 152 | return AttributeType.STRING 153 | } 154 | } 155 | 156 | convertProjectionType(type: string) { 157 | switch (type) { 158 | case 'ALL': 159 | return ProjectionType.ALL 160 | case 'INCLUDE': 161 | return ProjectionType.INCLUDE 162 | case 'KEYS_ONLY': 163 | return ProjectionType.KEYS_ONLY 164 | default: 165 | return ProjectionType.ALL 166 | } 167 | } 168 | 169 | getTableNameFromFieldName(fieldName: string) { 170 | let tableName = '' 171 | let plural = false 172 | let replace = '' 173 | 174 | if (fieldName.indexOf('list') > -1) { 175 | replace = 'list' 176 | plural = true 177 | } else if (fieldName.indexOf('sync') > -1) { 178 | replace = 'sync' 179 | plural = true 180 | } else if (fieldName.indexOf('get') > -1) { 181 | replace = 'get' 182 | } else if (fieldName.indexOf('delete') > -1) { 183 | replace = 'delete' 184 | } else if (fieldName.indexOf('create') > -1) { 185 | replace = 'create' 186 | } else if (fieldName.indexOf('update') > -1) { 187 | replace = 'update' 188 | } 189 | 190 | tableName = fieldName.replace(replace, '') 191 | 192 | if (plural) { 193 | tableName = tableName.slice(0, -1) 194 | } 195 | 196 | return tableName + 'Table' 197 | } 198 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "app", 3 | "version": "0.1.0", 4 | "bin": { 5 | "app": "bin/app.js" 6 | }, 7 | "scripts": { 8 | "build": "tsc", 9 | "watch": "tsc -w", 10 | "test": "jest", 11 | "cdk": "cdk" 12 | }, 13 | "devDependencies": { 14 | "@aws-cdk/assert": "1.31.0", 15 | "@types/jest": "^24.0.22", 16 | "@types/node": "10.17.5", 17 | "aws-cdk": "1.31.0", 18 | "cloudform-types": "^4.1.0", 19 | "graphql": "^15.0.0", 20 | "graphql-appsync-transformer": "^1.0.35", 21 | "graphql-auth-transformer": "^6.15.2", 22 | "graphql-connection-transformer": "^4.15.2", 23 | "graphql-dynamodb-transformer": "^6.16.0", 24 | "graphql-function-transformer": "^2.3.2", 25 | "graphql-key-transformer": "^2.15.2", 26 | "graphql-mapping-template": "^4.13.3", 27 | "graphql-transformer-common": "^4.14.0", 28 | "graphql-transformer-core": "^6.16.1", 29 | "graphql-versioned-transformer": "^4.15.2", 30 | "jest": "^24.9.0", 31 | "ts-jest": "^24.1.0", 32 | "ts-node": "^8.1.0", 33 | "typescript": "~3.7.2" 34 | }, 35 | "dependencies": { 36 | "@aws-cdk/aws-appsync": "^1.31.0", 37 | "@aws-cdk/aws-dynamodb": "^1.31.0", 38 | "@aws-cdk/aws-iam": "^1.31.0", 39 | "@aws-cdk/core": "^1.31.0" 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /schema.graphql: -------------------------------------------------------------------------------- 1 | type Customer 2 | @model { 3 | id: ID! 4 | firstName: String! 5 | lastName: String! 6 | active: Boolean! 7 | address: String! 8 | } 9 | 10 | type Product 11 | @model { 12 | id: ID! 13 | name: String! 14 | description: String! 15 | price: String! 16 | active: Boolean! 17 | added: AWSDateTime! 18 | } 19 | 20 | # We use my nullable tag so that the create can have an autoid on the ID field 21 | type Order 22 | @model 23 | @key(fields: ["id", "productID"]) { 24 | id: ID! @nullable 25 | productID: ID! 26 | total: String! 27 | ordered: AWSDateTime! 28 | } -------------------------------------------------------------------------------- /scripts/deploy.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | echo "Running cdk synth > template.yaml" 4 | cdk synth > template.yaml 5 | 6 | STAGE=${STAGE:-"dev"} 7 | REGION=${REGION:-"us-east-2"} 8 | ACCOUNT=`aws sts get-caller-identity --query 'Account' --output text` 9 | 10 | S3_BUCKET="sam-deployments-${REGION}-${ACCOUNT}" 11 | OUTPUT_FILE="sam-output.yaml" 12 | STACK_NAME="demo-api-${STAGE}" 13 | TEMPLATE_FILE=".aws-sam/build/template.yaml" 14 | 15 | rm ${OUTPUT_FILE} 16 | rm -rf .aws-sam 17 | 18 | sam build 19 | 20 | sam package \ 21 | --template-file ${TEMPLATE_FILE} \ 22 | --s3-bucket ${S3_BUCKET} \ 23 | --output-template-file ${OUTPUT_FILE} 24 | 25 | sam deploy \ 26 | --template-file ${OUTPUT_FILE} \ 27 | --stack-name ${STACK_NAME} \ 28 | --capabilities CAPABILITY_IAM \ 29 | --s3-bucket ${S3_BUCKET} \ 30 | --region ${REGION} \ 31 | --parameter-overrides \ 32 | Stage=${STAGE} -------------------------------------------------------------------------------- /transform/schema-transformer.ts: -------------------------------------------------------------------------------- 1 | import { GraphQLTransform } from 'graphql-transformer-core'; 2 | import { DynamoDBModelTransformer } from 'graphql-dynamodb-transformer'; 3 | import { ModelConnectionTransformer } from 'graphql-connection-transformer'; 4 | import { KeyTransformer } from 'graphql-key-transformer'; 5 | import { FunctionTransformer } from 'graphql-function-transformer'; 6 | import { VersionedModelTransformer } from 'graphql-versioned-transformer'; 7 | import { ModelAuthTransformer, ModelAuthTransformerConfig, } from 'graphql-auth-transformer'; 8 | 9 | import { 10 | TransformConfig, 11 | TRANSFORM_CURRENT_VERSION, 12 | TRANSFORM_CONFIG_FILE_NAME 13 | } from 'graphql-transformer-core/lib/util/transformConfig'; 14 | 15 | const { AppSyncTransformer } = require('graphql-appsync-transformer') 16 | const { MyTransformer } = require('./transformer'); 17 | 18 | import { normalize, join } from 'path'; 19 | import * as fs from "fs"; 20 | 21 | export interface SchemaTransformerProps { 22 | outputPath?: string 23 | enableDeletionProtection?: boolean 24 | enableSync?: boolean 25 | } 26 | 27 | export class SchemaTransformer { 28 | outputs: any 29 | resolvers: any 30 | outputPath: string 31 | enableDeletionProtection: boolean 32 | enableSync: boolean 33 | 34 | constructor(props?: SchemaTransformerProps) { 35 | this.resolvers = {} 36 | 37 | this.outputPath = props?.outputPath || './appsync'; 38 | this.enableDeletionProtection = props?.enableDeletionProtection || false; 39 | this.enableSync = props?.enableSync || true 40 | } 41 | 42 | transform() { 43 | // These config values do not even matter... So set it up for both 44 | // Typically this is loaded from amplify in `backend-config.json` 45 | const authTransformerConfig: ModelAuthTransformerConfig = { 46 | authConfig: { 47 | defaultAuthentication: { 48 | authenticationType: 'API_KEY', 49 | apiKeyConfig: { 50 | description: 'Testing', 51 | apiKeyExpirationDays: 100 52 | } 53 | }, 54 | additionalAuthenticationProviders: [ 55 | { 56 | authenticationType: 'AMAZON_COGNITO_USER_POOLS', 57 | userPoolConfig: { 58 | userPoolId: '12345xyz' 59 | } 60 | } 61 | ] 62 | } 63 | } 64 | 65 | let transformConfig = this.loadConfigSync('transform/'); 66 | 67 | // Note: This is not exact as we are omitting the @searchable transformer. 68 | const transformer = new GraphQLTransform({ 69 | transformConfig: transformConfig, 70 | transformers: [ 71 | new AppSyncTransformer(this.outputPath), 72 | new DynamoDBModelTransformer(), 73 | new VersionedModelTransformer(), 74 | new FunctionTransformer(), 75 | new KeyTransformer(), 76 | new ModelAuthTransformer(authTransformerConfig), 77 | new ModelConnectionTransformer(), 78 | new MyTransformer() 79 | ] 80 | }) 81 | 82 | const schema_path = './schema.graphql' 83 | const schema = fs.readFileSync(schema_path) 84 | 85 | const cfdoc = transformer.transform(schema.toString()); 86 | this.outputs = cfdoc.rootStack.Outputs; 87 | 88 | return this.outputs; 89 | } 90 | 91 | getResolvers() { 92 | const resolversDirPath = normalize('./appsync/resolvers') 93 | if (fs.existsSync(resolversDirPath)) { 94 | const files = fs.readdirSync(resolversDirPath) 95 | files.forEach(file => { 96 | // Example: Mutation.createChannel.response 97 | let args = file.split('.') 98 | let name: string = args[1] 99 | let templateType = args[2] // request or response 100 | let filepath = normalize(`${resolversDirPath}/${file}`) 101 | 102 | if (!this.resolvers[name]) { 103 | this.resolvers[name] = { 104 | typeName: args[0], 105 | fieldName: name, 106 | } 107 | } 108 | 109 | if (templateType === 'request') { 110 | this.resolvers[name]['requestMappingTemplate'] = filepath 111 | } else if (templateType === 'response') { 112 | this.resolvers[name]['responseMappingTemplate'] = filepath 113 | } 114 | }) 115 | } 116 | 117 | return this.resolvers; 118 | } 119 | 120 | private loadConfigSync(projectDir: string): TransformConfig { 121 | // Initialize the config always with the latest version, other members are optional for now. 122 | let config = { 123 | Version: TRANSFORM_CURRENT_VERSION 124 | }; 125 | 126 | try { 127 | const configPath = join(projectDir, TRANSFORM_CONFIG_FILE_NAME); 128 | const configExists = fs.existsSync(configPath); 129 | if (configExists) { 130 | const configStr = fs.readFileSync(configPath); 131 | config = JSON.parse(configStr.toString()); 132 | } 133 | return config as TransformConfig; 134 | } catch (err) { 135 | return config; 136 | } 137 | } 138 | } -------------------------------------------------------------------------------- /transform/transform.conf.json: -------------------------------------------------------------------------------- 1 | { 2 | "Version": 5, 3 | "ResolverConfig": { 4 | "project": { 5 | "ConflictHandler": "OPTIMISTIC_CONCURRENCY", 6 | "ConflictDetection": "VERSION" 7 | } 8 | } 9 | } -------------------------------------------------------------------------------- /transform/transformer.ts: -------------------------------------------------------------------------------- 1 | import { 2 | Transformer, 3 | TransformerContext, 4 | InvalidDirectiveError, 5 | TransformerContractError, 6 | getDirectiveArguments 7 | } from "graphql-transformer-core"; 8 | 9 | import { 10 | ObjectTypeDefinitionNode, 11 | DirectiveNode, 12 | InterfaceTypeDefinitionNode, 13 | FieldDefinitionNode, 14 | Kind 15 | } from 'graphql'; 16 | 17 | import { 18 | ResourceConstants, 19 | ModelResourceIDs, 20 | ResolverResourceIDs, 21 | isNonNullType, 22 | makeInputValueDefinition, 23 | unwrapNonNull, 24 | toCamelCase, 25 | graphqlName, 26 | toUpper 27 | } from 'graphql-transformer-common'; 28 | 29 | import { 30 | set, 31 | compoundExpression, 32 | printBlock, 33 | print, 34 | ifElse, 35 | qref, 36 | raw, 37 | ref, 38 | obj, 39 | str, 40 | iff, 41 | and, 42 | DynamoDBMappingTemplate 43 | } from 'graphql-mapping-template'; 44 | 45 | // TODO: Needs cleaned up 46 | const cloudform_types_1 = require('cloudform-types') 47 | 48 | import Resource from "cloudform-types/types/resource"; 49 | import { normalize } from "path"; 50 | import fs = require('fs'); 51 | 52 | export interface TransformerConfig { 53 | enableSync?: boolean 54 | outputPath?: string 55 | } 56 | 57 | export class MyTransformer extends Transformer { 58 | outputPath: string 59 | tables: any 60 | enableSync: boolean 61 | 62 | constructor(config?: TransformerConfig) { 63 | super( 64 | 'MyTransformer', 65 | 'directive @nullable on FIELD_DEFINITION' 66 | ) 67 | 68 | this.tables = {} 69 | 70 | if (config?.outputPath) { 71 | this.outputPath = normalize(config.outputPath); 72 | } 73 | } 74 | 75 | public before = (ctx: TransformerContext): void => {} 76 | 77 | public after = (ctx: TransformerContext): void => { 78 | this.printWithoutFilePath(ctx); 79 | 80 | if (this.outputPath) { 81 | this.printWithFilePath(ctx); 82 | this.tables.forEach((table: any) => { 83 | this.writeTableToFile(table) 84 | }) 85 | } 86 | 87 | ctx.setOutput('CDK_TABLES', this.tables) 88 | } 89 | 90 | private printWithoutFilePath(ctx: TransformerContext): void { 91 | // @ts-ignore 92 | const templateResources: { [key: string]: Resource } = ctx.template.Resources 93 | 94 | for (const resourceName of Object.keys(templateResources)) { 95 | const resource: Resource = templateResources[resourceName] 96 | if (resource.Type === 'AWS::DynamoDB::Table') { 97 | this.buildTablesFromResource(resourceName, ctx) 98 | } 99 | } 100 | } 101 | 102 | private printWithFilePath(ctx: TransformerContext): void { 103 | if (!fs.existsSync(this.outputPath)) { 104 | fs.mkdirSync(this.outputPath); 105 | } 106 | 107 | const tableFilePath = normalize(this.outputPath + '/tables') 108 | if (fs.existsSync(tableFilePath)) { 109 | const files = fs.readdirSync(tableFilePath) 110 | files.forEach(file => fs.unlinkSync(tableFilePath + '/' + file)) 111 | fs.rmdirSync(tableFilePath) 112 | } 113 | } 114 | 115 | private buildTablesFromResource(resourceName: string, ctx: TransformerContext): void { 116 | // @ts-ignore 117 | const tableResource = ctx.template.Resources[resourceName] 118 | 119 | const attributeDefinitions = tableResource.Properties?.AttributeDefinitions 120 | const keySchema = tableResource.Properties?.KeySchema 121 | 122 | let keys = this.parseKeySchema(keySchema, attributeDefinitions); 123 | 124 | let table = { 125 | TableName: resourceName, 126 | PartitionKey: keys.partitionKey, 127 | SortKey: keys.sortKey, 128 | TTL: tableResource.Properties?.TimeToLiveSpecification, 129 | GlobalSecondaryIndexes: [] as any[] 130 | } 131 | 132 | const gsis = tableResource.Properties?.GlobalSecondaryIndexes; 133 | if (gsis) { 134 | gsis.forEach((gsi: any) => { 135 | let gsiKeys = this.parseKeySchema(gsi.KeySchema, attributeDefinitions); 136 | let gsiDefinition = { 137 | IndexName: gsi.IndexName, 138 | Projection: gsi.Projection, 139 | PartitionKey: gsiKeys.partitionKey, 140 | SortKey: gsiKeys.sortKey, 141 | } 142 | 143 | table.GlobalSecondaryIndexes.push(gsiDefinition); 144 | }) 145 | } 146 | 147 | this.tables[resourceName] = table 148 | } 149 | 150 | private parseKeySchema(keySchema: any, attributeDefinitions: any, ) { 151 | let partitionKey: any = {} 152 | let sortKey: any = {} 153 | 154 | keySchema.forEach((key: any) => { 155 | let keyType = key.KeyType 156 | let attributeName = key.AttributeName 157 | 158 | let attribute = attributeDefinitions.find((attribute: any) => { 159 | return attribute.AttributeName === attributeName 160 | }) 161 | 162 | if (keyType === 'HASH') { 163 | partitionKey = { 164 | name: attribute.AttributeName, 165 | type: attribute.AttributeType 166 | } 167 | } else if (keyType === 'RANGE') { 168 | sortKey = { 169 | name: attribute.AttributeName, 170 | type: attribute.AttributeType 171 | } 172 | } 173 | }) 174 | 175 | return { 176 | partitionKey, 177 | sortKey 178 | } 179 | } 180 | 181 | private writeTableToFile(table: any): void { 182 | const tableFilePath = normalize(this.outputPath + '/tables') 183 | if (!fs.existsSync(tableFilePath)) { 184 | fs.mkdirSync(tableFilePath); 185 | } 186 | 187 | fs.writeFileSync(`${tableFilePath}/${table.TableName}.json`, JSON.stringify(table)) 188 | } 189 | 190 | public field = ( 191 | parent: ObjectTypeDefinitionNode | InterfaceTypeDefinitionNode, 192 | definition: FieldDefinitionNode, 193 | directive: DirectiveNode, 194 | ctx: TransformerContext 195 | ) => { 196 | if (parent.kind === Kind.INTERFACE_TYPE_DEFINITION) { 197 | throw new InvalidDirectiveError( 198 | `The @nullable directive cannot be placed on an interface's field. See ${parent.name.value}${definition.name.value}` 199 | ) 200 | } 201 | 202 | //@ts-ignore 203 | const modelDirective = parent.directives?.find((dir) => dir.name.value === 'key') 204 | if (!modelDirective) { 205 | throw new InvalidDirectiveError('Types annotated with @nullable must also be annotated with @key.') 206 | } 207 | 208 | if (!isNonNullType(definition.type)) { 209 | throw new TransformerContractError(`@nullable directive can only be used on non-nullable type fields`) 210 | } 211 | 212 | this.updateCreateInput(ctx, parent.name.value, definition) 213 | 214 | const createResolver = ctx.getResource(ResolverResourceIDs.DynamoDBCreateResolverResourceID(parent.name.value)); 215 | if (createResolver !== undefined) { 216 | let directive = this.getParentKeyDirective(parent) 217 | 218 | //@ts-ignore 219 | // console.log(DynamoDBMappingTemplate.putItem(directive)) 220 | 221 | let newResolver = this.makeCreateResolver({ 222 | type: parent.name.value 223 | }); 224 | 225 | //@ts-ignore 226 | createResolver.Properties.RequestMappingTemplate = this.joinSnippets([ 227 | this.setKeySnippet(directive, true), 228 | this.ensureCompositeKeySnippet(directive), 229 | //@ts-ignore 230 | // createResolver.Properties.RequestMappingTemplate, 231 | newResolver.Properties.RequestMappingTemplate 232 | ]); 233 | } 234 | } 235 | 236 | private updateCreateInput( 237 | ctx: TransformerContext, 238 | typeName: string, 239 | autoField: FieldDefinitionNode 240 | ) { 241 | this.updateInput(ctx, ModelResourceIDs.ModelCreateInputObjectName(typeName), autoField) 242 | } 243 | 244 | private updateInput( 245 | ctx: TransformerContext, 246 | inputName: string, 247 | autoField: FieldDefinitionNode 248 | ) { 249 | const input = ctx.getType(inputName) 250 | if (input && input.kind === Kind.INPUT_OBJECT_TYPE_DEFINITION) { 251 | //@ts-ignore 252 | if (input.fields) { 253 | // make autoField nullable 254 | //@ts-ignore 255 | ctx.putType({ 256 | ...input, 257 | //@ts-ignore 258 | fields: input.fields.map((f) => { 259 | if (f.name.value === autoField.name.value) { 260 | return makeInputValueDefinition(autoField.name.value, unwrapNonNull(autoField.type)) 261 | } 262 | return f 263 | }), 264 | }) 265 | } 266 | } 267 | } 268 | 269 | private setKeySnippet(directive: DirectiveNode, isMutation: boolean = false) { 270 | const directiveArgs = getDirectiveArguments(directive); 271 | 272 | //@ts-ignore 273 | const cmds = [set(ref(ResourceConstants.SNIPPETS.ModelObjectKey), this.modelObjectKey(directiveArgs, isMutation))]; 274 | return printBlock(`Set the primary @key`)(compoundExpression(cmds)); 275 | }; 276 | 277 | private ensureCompositeKeySnippet(directive: DirectiveNode) { 278 | const args = getDirectiveArguments(directive); 279 | const argsPrefix = 'ctx.args.input'; 280 | if (args.fields.length > 2) { 281 | const rangeKeyFields = args.fields.slice(1); 282 | const condensedSortKey = this.condenseRangeKey(rangeKeyFields); 283 | const dynamoDBFriendlySortKeyName = toCamelCase(rangeKeyFields.map((f: any) => graphqlName(f))); 284 | const condensedSortKeyValue = this.condenseRangeKey(rangeKeyFields.map((keyField: any) => `\${${argsPrefix}.${keyField}}`)); 285 | return print(compoundExpression([ 286 | //@ts-ignore 287 | ifElse(raw(`$util.isNull($${ResourceConstants.SNIPPETS.DynamoDBNameOverrideMap})`), set(ref(ResourceConstants.SNIPPETS.DynamoDBNameOverrideMap), obj({ 288 | [condensedSortKey]: str(dynamoDBFriendlySortKeyName), 289 | })), 290 | //@ts-ignore 291 | qref(`$${ResourceConstants.SNIPPETS.DynamoDBNameOverrideMap}.put("${condensedSortKey}", "${dynamoDBFriendlySortKeyName}")`)), 292 | qref(`$ctx.args.input.put("${condensedSortKey}","${condensedSortKeyValue}")`), 293 | ])); 294 | } 295 | return ''; 296 | } 297 | 298 | private condenseRangeKey(fields: any) { 299 | //@ts-ignore 300 | return fields.join(ModelResourceIDs.ModelCompositeKeySeparator()); 301 | } 302 | 303 | private modelObjectKey(args: any, isMutation: boolean) { 304 | const argsPrefix = isMutation ? 'ctx.args.input' : 'ctx.args'; 305 | if (args.fields.length > 2) { 306 | const rangeKeyFields = args.fields.slice(1); 307 | const condensedSortKey = this.condenseRangeKey(rangeKeyFields); 308 | //@ts-ignore 309 | const condensedSortKeyValue = this.condenseRangeKey(rangeKeyFields.map(keyField => `\${${argsPrefix}.${keyField}}`)); 310 | return obj({ 311 | [args.fields[0]]: ref(`util.dynamodb.toDynamoDB($${argsPrefix}.${args.fields[0]})`), 312 | [condensedSortKey]: ref(`util.dynamodb.toDynamoDB("${condensedSortKeyValue}")`), 313 | }); 314 | } 315 | else if (args.fields.length === 2) { 316 | return obj({ 317 | [args.fields[0]]: ref(`util.dynamodb.toDynamoDB($util.defaultIfNullOrBlank($${argsPrefix}.${args.fields[0]}, $util.autoId()))`), 318 | [args.fields[1]]: ref(`util.dynamodb.toDynamoDB($${argsPrefix}.${args.fields[1]})`), 319 | }); 320 | } 321 | else if (args.fields.length === 1) { 322 | return obj({ 323 | [args.fields[0]]: ref(`util.dynamodb.toDynamoDB($${argsPrefix}.${args.fields[0]})`), 324 | }); 325 | } 326 | throw new InvalidDirectiveError('@key directives must include at least one field.'); 327 | } 328 | 329 | private joinSnippets(lines: any) { 330 | return lines.join('\n'); 331 | } 332 | 333 | private getParentKeyDirective(parent: any) { 334 | let directive = parent.directives.find((directive: any) => { 335 | return directive.name.value === 'key' 336 | }) 337 | return directive 338 | } 339 | 340 | //@ts-ignore 341 | private makeCreateResolver({ type, mutationTypeName = 'Mutation' }) { 342 | const fieldName = graphqlName('create' + toUpper(type)); 343 | return new cloudform_types_1.AppSync.Resolver({ 344 | ApiId: cloudform_types_1.Fn.GetAtt(ResourceConstants.RESOURCES.GraphQLAPILogicalID, 'ApiId'), 345 | DataSourceName: cloudform_types_1.Fn.GetAtt(ModelResourceIDs.ModelTableDataSourceID(type), 'Name'), 346 | FieldName: fieldName, 347 | TypeName: mutationTypeName, 348 | RequestMappingTemplate: printBlock('Prepare DynamoDB PutItem Request')(compoundExpression([ 349 | qref('$context.args.input.put("createdAt", $util.defaultIfNull($ctx.args.input.createdAt, $util.time.nowISO8601()))'), 350 | qref('$context.args.input.put("updatedAt", $util.defaultIfNull($ctx.args.input.updatedAt, $util.time.nowISO8601()))'), 351 | qref(`$context.args.input.put("__typename", "${type}")`), 352 | set(ref('condition'), obj({ 353 | expression: str('attribute_not_exists(#id)'), 354 | expressionNames: obj({ 355 | '#id': str('id'), 356 | }), 357 | })), 358 | iff(ref('context.args.condition'), compoundExpression([ 359 | set(ref('condition.expressionValues'), obj({})), 360 | set(ref('conditionFilterExpressions'), raw('$util.parseJson($util.transform.toDynamoDBConditionExpression($context.args.condition))')), 361 | qref(`$condition.put("expression", "($condition.expression) AND $conditionFilterExpressions.expression")`), 362 | qref(`$condition.expressionNames.putAll($conditionFilterExpressions.expressionNames)`), 363 | qref(`$condition.expressionValues.putAll($conditionFilterExpressions.expressionValues)`), 364 | ])), 365 | iff(and([ref('condition.expressionValues'), raw('$condition.expressionValues.size() == 0')]), set(ref('condition'), obj({ 366 | expression: ref('condition.expression'), 367 | expressionNames: ref('condition.expressionNames'), 368 | }))), 369 | DynamoDBMappingTemplate.putItem({ 370 | //@ts-ignore 371 | key: ifElse(ref(ResourceConstants.SNIPPETS.ModelObjectKey), raw(`$util.toJson(\$${ResourceConstants.SNIPPETS.ModelObjectKey})`), obj({ 372 | id: raw(`$util.dynamodb.toDynamoDBJson($util.defaultIfNullOrBlank($ctx.args.input.id, $util.autoId()))`), 373 | }), true), 374 | attributeValues: ref('util.dynamodb.toMapValuesJson($context.args.input)'), 375 | condition: ref('util.toJson($condition)'), 376 | //@ts-ignore 377 | }, '2017-02-28'), 378 | ])) 379 | }); 380 | } 381 | } 382 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target":"ES2018", 4 | "module": "commonjs", 5 | "lib": ["es2018"], 6 | "declaration": true, 7 | "strict": true, 8 | "noImplicitAny": true, 9 | "strictNullChecks": true, 10 | "noImplicitThis": true, 11 | "alwaysStrict": true, 12 | "noUnusedLocals": false, 13 | "noUnusedParameters": false, 14 | "noImplicitReturns": true, 15 | "noFallthroughCasesInSwitch": false, 16 | "inlineSourceMap": true, 17 | "inlineSources": true, 18 | "experimentalDecorators": true, 19 | "strictPropertyInitialization":false, 20 | "typeRoots": ["./node_modules/@types"] 21 | }, 22 | "exclude": ["cdk.out"] 23 | } 24 | --------------------------------------------------------------------------------