├── .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 |
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 | First Name |
89 | Last Name |
90 | Active |
91 | Address |
92 |
93 |
94 |
95 | {
96 | customers.map(customer => {
97 | return (
98 |
99 | {customer.firstName} |
100 | {customer.lastName} |
101 | {customer.active.toString()} |
102 | {customer.address} |
103 |
104 | )
105 | })
106 | }
107 |
108 |
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 | Name |
137 | Description |
138 | Price |
139 | Active |
140 | Added |
141 |
142 |
143 |
144 | {
145 | products.map(product => {
146 | return (
147 |
148 | {product.name} |
149 | {product.description} |
150 | {product.price} |
151 | {product.active.toString()} |
152 | {product.added} |
153 |
154 | )
155 | })
156 | }
157 |
158 |
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 |
--------------------------------------------------------------------------------