From 16c4a0482dafc2a581aa88b3152ea2d14664dfd3 Mon Sep 17 00:00:00 2001 From: Mitchell Valine Date: Wed, 26 Oct 2022 12:34:28 -0700 Subject: [PATCH 1/6] chore(appsync): removes codefirst schema generation Removes all of the code first schema generation code in favor of this living in a separate module. This will make stabilizing the other constructs easier while allowing for continuing development of high level utilities within the `aws-cdk-appsync-utilities` library. BREAKING CHANGE: Renames `Schema` to `SchemaFile` that implements `ISchema`. Removes all 'addXxx' type methods from `GraphQlApi`. --- packages/@aws-cdk/aws-appsync/README.md | 566 +----------------- .../@aws-cdk/aws-appsync/lib/graphqlapi.ts | 82 +-- packages/@aws-cdk/aws-appsync/lib/index.ts | 3 - packages/@aws-cdk/aws-appsync/lib/private.ts | 10 +- .../@aws-cdk/aws-appsync/lib/schema-base.ts | 396 ------------ .../@aws-cdk/aws-appsync/lib/schema-field.ts | 460 -------------- .../aws-appsync/lib/schema-intermediate.ts | 488 --------------- packages/@aws-cdk/aws-appsync/lib/schema.ts | 225 ++----- .../rosetta/with-objects.ts-fixture | 50 -- .../aws-appsync/test/appsync-auth.test.ts | 66 +- .../test/appsync-caching-config.test.ts | 2 +- .../test/appsync-code-first.test.ts | 329 ---------- .../test/appsync-directives.test.ts | 140 ----- .../aws-appsync/test/appsync-domain.test.ts | 6 +- .../aws-appsync/test/appsync-dynamodb.test.ts | 2 +- .../test/appsync-elasticsearch.test.ts | 2 +- .../test/appsync-enum-type.test.ts | 106 ---- .../aws-appsync/test/appsync-grant.test.ts | 2 +- .../aws-appsync/test/appsync-http.test.ts | 2 +- .../test/appsync-input-types.test.ts | 95 --- .../test/appsync-interface-type.test.ts | 174 ------ .../aws-appsync/test/appsync-lambda.test.ts | 4 +- .../test/appsync-mapping-template.test.ts | 2 +- .../aws-appsync/test/appsync-none.test.ts | 2 +- .../test/appsync-object-type.test.ts | 295 --------- .../test/appsync-opensearch.test.ts | 2 +- .../aws-appsync/test/appsync-rds.test.ts | 2 +- .../test/appsync-scalar-type.test.ts | 227 ------- .../aws-appsync/test/appsync-schema.test.ts | 275 --------- .../test/appsync-union-types.test.ts | 152 ----- .../@aws-cdk/aws-appsync/test/appsync.test.ts | 12 +- .../aws-appsync/test/integ.api-import.ts | 2 +- .../aws-appsync/test/integ.appsync-lambda.ts | 2 +- .../aws-appsync/test/integ.appsync-none.ts | 2 +- .../aws-appsync/test/integ.auth-apikey.ts | 6 +- .../test/integ.graphql-elasticsearch.ts | 2 +- .../aws-appsync/test/integ.graphql-iam.ts | 4 +- .../test/integ.graphql-opensearch.ts | 2 +- .../aws-appsync/test/integ.graphql-schema.ts | 133 ---- .../aws-appsync/test/integ.graphql.ts | 4 +- .../aws-appsync/test/integ.log-retention.ts | 6 +- .../test/object-type-definitions.ts | 19 - .../test/scalar-type-defintions.ts | 63 -- 43 files changed, 130 insertions(+), 4294 deletions(-) delete mode 100644 packages/@aws-cdk/aws-appsync/lib/schema-base.ts delete mode 100644 packages/@aws-cdk/aws-appsync/lib/schema-field.ts delete mode 100644 packages/@aws-cdk/aws-appsync/lib/schema-intermediate.ts delete mode 100644 packages/@aws-cdk/aws-appsync/rosetta/with-objects.ts-fixture delete mode 100644 packages/@aws-cdk/aws-appsync/test/appsync-code-first.test.ts delete mode 100644 packages/@aws-cdk/aws-appsync/test/appsync-directives.test.ts delete mode 100644 packages/@aws-cdk/aws-appsync/test/appsync-enum-type.test.ts delete mode 100644 packages/@aws-cdk/aws-appsync/test/appsync-input-types.test.ts delete mode 100644 packages/@aws-cdk/aws-appsync/test/appsync-interface-type.test.ts delete mode 100644 packages/@aws-cdk/aws-appsync/test/appsync-object-type.test.ts delete mode 100644 packages/@aws-cdk/aws-appsync/test/appsync-scalar-type.test.ts delete mode 100644 packages/@aws-cdk/aws-appsync/test/appsync-schema.test.ts delete mode 100644 packages/@aws-cdk/aws-appsync/test/appsync-union-types.test.ts delete mode 100644 packages/@aws-cdk/aws-appsync/test/integ.graphql-schema.ts delete mode 100644 packages/@aws-cdk/aws-appsync/test/object-type-definitions.ts delete mode 100644 packages/@aws-cdk/aws-appsync/test/scalar-type-defintions.ts diff --git a/packages/@aws-cdk/aws-appsync/README.md b/packages/@aws-cdk/aws-appsync/README.md index 1b2717610eb4f..3fc833f5b3c5d 100644 --- a/packages/@aws-cdk/aws-appsync/README.md +++ b/packages/@aws-cdk/aws-appsync/README.md @@ -58,7 +58,7 @@ CDK stack file `app-stack.ts`: ```ts const api = new appsync.GraphqlApi(this, 'Api', { name: 'demo', - schema: appsync.Schema.fromAsset(path.join(__dirname, 'schema.graphql')), + schema: appsync.SchemaFile.fromAsset(path.join(__dirname, 'schema.graphql')), authorizationConfig: { defaultAuthorization: { authorizationType: appsync.AuthorizationType.IAM, @@ -228,7 +228,7 @@ CDK stack file `app-stack.ts`: ```ts const api = new appsync.GraphqlApi(this, 'api', { name: 'api', - schema: appsync.Schema.fromAsset(path.join(__dirname, 'schema.graphql')), + schema: appsync.SchemaFile.fromAsset(path.join(__dirname, 'schema.graphql')), }); const httpDs = api.addHttpDataSource( @@ -352,56 +352,27 @@ const logConfig: appsync.LogConfig = { new appsync.GraphqlApi(this, 'api', { authorizationConfig: {}, name: 'myApi', - schema: appsync.Schema.fromAsset(path.join(__dirname, 'myApi.graphql')), + schema: appsync.SchemaFile.fromAsset(path.join(__dirname, 'myApi.graphql')), logConfig, }); ``` ## Schema -Every GraphQL Api needs a schema to define the Api. CDK offers `appsync.Schema` -for static convenience methods for various types of schema declaration: code-first -or schema-first. - -### Code-First - -When declaring your GraphQL Api, CDK defaults to a code-first approach if the -`schema` property is not configured. - -```ts -const api = new appsync.GraphqlApi(this, 'api', { name: 'myApi' }); -``` - -CDK will declare a `Schema` class that will give your Api access functions to -define your schema code-first: `addType`, `addToSchema`, etc. - -You can also declare your `Schema` class outside of your CDK stack, to define -your schema externally. +You can define a schema using from a local file using `SchemaFile.fromAsset` ```ts -const schema = new appsync.Schema(); -schema.addType(new appsync.ObjectType('demo', { - definition: { id: appsync.GraphqlType.id() }, -})); const api = new appsync.GraphqlApi(this, 'api', { name: 'myApi', - schema, + schema: appsync.SchemaFile.fromAsset(path.join(__dirname, 'schema.graphl')), }); ``` -See the [code-first schema](#Code-First-Schema) section for more details. +### ISchema -### Schema-First - -You can define your GraphQL Schema from a file on disk. For convenience, use -the `appsync.Schema.fromAsset` to specify the file representing your schema. - -```ts -const api = new appsync.GraphqlApi(this, 'api', { - name: 'myApi', - schema: appsync.Schema.fromAsset(path.join(__dirname, 'schema.graphl')), -}); -``` +Alternative schema sources can be defined by implementing the `ISchema` +interface. An example of this is the `CodeFirstSchema` class provided in +[awscdk-appsync-utils](https://github.com/cdklabs/awscdk-appsync-utils) ## Imports @@ -445,7 +416,7 @@ declare const authFunction: lambda.Function; new appsync.GraphqlApi(this, 'api', { name: 'api', - schema: appsync.Schema.fromAsset(path.join(__dirname, 'appsync.test.graphql')), + schema: appsync.SchemaFile.fromAsset(path.join(__dirname, 'appsync.test.graphql')), authorizationConfig: { defaultAuthorization: { authorizationType: appsync.AuthorizationType.LAMBDA, @@ -578,520 +549,3 @@ const pipelineResolver = new appsync.Resolver(this, 'pipeline', { ``` Learn more about Pipeline Resolvers and AppSync Functions [here](https://docs.aws.amazon.com/appsync/latest/devguide/pipeline-resolvers.html). - -## Code-First Schema - -CDK offers the ability to generate your schema in a code-first approach. -A code-first approach offers a developer workflow with: - -- **modularity**: organizing schema type definitions into different files -- **reusability**: simplifying down boilerplate/repetitive code -- **consistency**: resolvers and schema definition will always be synced - -The code-first approach allows for **dynamic** schema generation. You can generate your schema based on variables and templates to reduce code duplication. - -### Code-First Example - -To showcase the code-first approach. Let's try to model the following schema segment. - -```gql -interface Node { - id: String -} - -type Query { - allFilms(after: String, first: Int, before: String, last: Int): FilmConnection -} - -type FilmNode implements Node { - filmName: String -} - -type FilmConnection { - edges: [FilmEdge] - films: [Film] - totalCount: Int -} - -type FilmEdge { - node: Film - cursor: String -} -``` - -Above we see a schema that allows for generating paginated responses. For example, -we can query `allFilms(first: 100)` since `FilmConnection` acts as an intermediary -for holding `FilmEdges` we can write a resolver to return the first 100 films. - -In a separate file, we can declare our object types and related functions. -We will call this file `object-types.ts` and we will have created it in a way that -allows us to generate other `XxxConnection` and `XxxEdges` in the future. - -```ts nofixture -import * as appsync from '@aws-cdk/aws-appsync'; -const pluralize = require('pluralize'); - -export const args = { - after: appsync.GraphqlType.string(), - first: appsync.GraphqlType.int(), - before: appsync.GraphqlType.string(), - last: appsync.GraphqlType.int(), -}; - -export const Node = new appsync.InterfaceType('Node', { - definition: { id: appsync.GraphqlType.string() } -}); -export const FilmNode = new appsync.ObjectType('FilmNode', { - interfaceTypes: [Node], - definition: { filmName: appsync.GraphqlType.string() } -}); - -export function generateEdgeAndConnection(base: appsync.ObjectType) { - const edge = new appsync.ObjectType(`${base.name}Edge`, { - definition: { node: base.attribute(), cursor: appsync.GraphqlType.string() } - }); - const connection = new appsync.ObjectType(`${base.name}Connection`, { - definition: { - edges: edge.attribute({ isList: true }), - [pluralize(base.name)]: base.attribute({ isList: true }), - totalCount: appsync.GraphqlType.int(), - } - }); - return { edge: edge, connection: connection }; -} -``` - -Finally, we will go to our `cdk-stack` and combine everything together -to generate our schema. - -```ts fixture=with-objects -declare const dummyRequest: appsync.MappingTemplate; -declare const dummyResponse: appsync.MappingTemplate; - -const api = new appsync.GraphqlApi(this, 'Api', { - name: 'demo', -}); - -const objectTypes = [ Node, FilmNode ]; - -const filmConnections = generateEdgeAndConnection(FilmNode); - -api.addQuery('allFilms', new appsync.ResolvableField({ - returnType: filmConnections.connection.attribute(), - args: args, - dataSource: api.addNoneDataSource('none'), - requestMappingTemplate: dummyRequest, - responseMappingTemplate: dummyResponse, -})); - -api.addType(Node); -api.addType(FilmNode); -api.addType(filmConnections.edge); -api.addType(filmConnections.connection); -``` - -Notice how we can utilize the `generateEdgeAndConnection` function to generate -Object Types. In the future, if we wanted to create more Object Types, we can simply -create the base Object Type (i.e. Film) and from there we can generate its respective -`Connections` and `Edges`. - -Check out a more in-depth example [here](https://github.com/BryanPan342/starwars-code-first). - -## GraphQL Types - -One of the benefits of GraphQL is its strongly typed nature. We define the -types within an object, query, mutation, interface, etc. as **GraphQL Types**. - -GraphQL Types are the building blocks of types, whether they are scalar, objects, -interfaces, etc. GraphQL Types can be: - -- [**Scalar Types**](https://docs.aws.amazon.com/appsync/latest/devguide/scalars.html): Id, Int, String, AWSDate, etc. -- [**Object Types**](#Object-Types): types that you generate (i.e. `demo` from the example above) -- [**Interface Types**](#Interface-Types): abstract types that define the base implementation of other -Intermediate Types - -More concretely, GraphQL Types are simply the types appended to variables. -Referencing the object type `Demo` in the previous example, the GraphQL Types -is `String!` and is applied to both the names `id` and `version`. - -### Directives - -`Directives` are attached to a field or type and affect the execution of queries, -mutations, and types. With AppSync, we use `Directives` to configure authorization. -CDK provides static functions to add directives to your Schema. - -- `Directive.iam()` sets a type or field's authorization to be validated through `Iam` -- `Directive.apiKey()` sets a type or field's authorization to be validated through a `Api Key` -- `Directive.oidc()` sets a type or field's authorization to be validated through `OpenID Connect` -- `Directive.cognito(...groups: string[])` sets a type or field's authorization to be validated -through `Cognito User Pools` - - `groups` the name of the cognito groups to give access - -To learn more about authorization and directives, read these docs [here](https://docs.aws.amazon.com/appsync/latest/devguide/security.html). - -### Field and Resolvable Fields - -While `GraphqlType` is a base implementation for GraphQL fields, we have abstractions -on top of `GraphqlType` that provide finer grain support. - -### Field - -`Field` extends `GraphqlType` and will allow you to define arguments. [**Interface Types**](#Interface-Types) are not resolvable and this class will allow you to define arguments, -but not its resolvers. - -For example, if we want to create the following type: - -```gql -type Node { - test(argument: string): String -} -``` - -The CDK code required would be: - -```ts -const field = new appsync.Field({ - returnType: appsync.GraphqlType.string(), - args: { - argument: appsync.GraphqlType.string(), - }, -}); -const type = new appsync.InterfaceType('Node', { - definition: { test: field }, -}); -``` - -### Resolvable Fields - -`ResolvableField` extends `Field` and will allow you to define arguments and its resolvers. -[**Object Types**](#Object-Types) can have fields that resolve and perform operations on -your backend. - -You can also create resolvable fields for object types. - -```gql -type Info { - node(id: String): String -} -``` - -The CDK code required would be: - -```ts -declare const api: appsync.GraphqlApi; -declare const dummyRequest: appsync.MappingTemplate; -declare const dummyResponse: appsync.MappingTemplate; -const info = new appsync.ObjectType('Info', { - definition: { - node: new appsync.ResolvableField({ - returnType: appsync.GraphqlType.string(), - args: { - id: appsync.GraphqlType.string(), - }, - dataSource: api.addNoneDataSource('none'), - requestMappingTemplate: dummyRequest, - responseMappingTemplate: dummyResponse, - }), - }, -}); -``` - -To nest resolvers, we can also create top level query types that call upon -other types. Building off the previous example, if we want the following graphql -type definition: - -```gql -type Query { - get(argument: string): Info -} -``` - -The CDK code required would be: - -```ts -declare const api: appsync.GraphqlApi; -declare const dummyRequest: appsync.MappingTemplate; -declare const dummyResponse: appsync.MappingTemplate; -const query = new appsync.ObjectType('Query', { - definition: { - get: new appsync.ResolvableField({ - returnType: appsync.GraphqlType.string(), - args: { - argument: appsync.GraphqlType.string(), - }, - dataSource: api.addNoneDataSource('none'), - requestMappingTemplate: dummyRequest, - responseMappingTemplate: dummyResponse, - }), - }, -}); -``` - -Learn more about fields and resolvers [here](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-mapping-template-reference-overview.html). - -### Intermediate Types - -Intermediate Types are defined by Graphql Types and Fields. They have a set of defined -fields, where each field corresponds to another type in the system. Intermediate -Types will be the meat of your GraphQL Schema as they are the types defined by you. - -Intermediate Types include: - -- [**Interface Types**](#Interface-Types) -- [**Object Types**](#Object-Types) -- [**Enum Types**](#Enum-Types) -- [**Input Types**](#Input-Types) -- [**Union Types**](#Union-Types) - -#### Interface Types - -**Interface Types** are abstract types that define the implementation of other -intermediate types. They are useful for eliminating duplication and can be used -to generate Object Types with less work. - -You can create Interface Types ***externally***. - -```ts -const node = new appsync.InterfaceType('Node', { - definition: { - id: appsync.GraphqlType.string({ isRequired: true }), - }, -}); -``` - -To learn more about **Interface Types**, read the docs [here](https://graphql.org/learn/schema/#interfaces). - -#### Object Types - -**Object Types** are types that you declare. For example, in the [code-first example](#code-first-example) -the `demo` variable is an **Object Type**. **Object Types** are defined by -GraphQL Types and are only usable when linked to a GraphQL Api. - -You can create Object Types in two ways: - -1. Object Types can be created ***externally***. - - ```ts - const api = new appsync.GraphqlApi(this, 'Api', { - name: 'demo', - }); - const demo = new appsync.ObjectType('Demo', { - definition: { - id: appsync.GraphqlType.string({ isRequired: true }), - version: appsync.GraphqlType.string({ isRequired: true }), - }, - }); - - api.addType(demo); - ``` - - > This method allows for reusability and modularity, ideal for larger projects. - For example, imagine moving all Object Type definition outside the stack. - - `object-types.ts` - a file for object type definitions - - ```ts nofixture - import * as appsync from '@aws-cdk/aws-appsync'; - export const demo = new appsync.ObjectType('Demo', { - definition: { - id: appsync.GraphqlType.string({ isRequired: true }), - version: appsync.GraphqlType.string({ isRequired: true }), - }, - }); - ``` - - `cdk-stack.ts` - a file containing our cdk stack - - ```ts fixture=with-objects - declare const api: appsync.GraphqlApi; - api.addType(demo); - ``` - -2. Object Types can be created ***externally*** from an Interface Type. - - ```ts - const node = new appsync.InterfaceType('Node', { - definition: { - id: appsync.GraphqlType.string({ isRequired: true }), - }, - }); - const demo = new appsync.ObjectType('Demo', { - interfaceTypes: [ node ], - definition: { - version: appsync.GraphqlType.string({ isRequired: true }), - }, - }); - ``` - - > This method allows for reusability and modularity, ideal for reducing code duplication. - -To learn more about **Object Types**, read the docs [here](https://graphql.org/learn/schema/#object-types-and-fields). - -#### Enum Types - -**Enum Types** are a special type of Intermediate Type. They restrict a particular -set of allowed values for other Intermediate Types. - -```gql -enum Episode { - NEWHOPE - EMPIRE - JEDI -} -``` - -> This means that wherever we use the type Episode in our schema, we expect it to -> be exactly one of NEWHOPE, EMPIRE, or JEDI. - -The above GraphQL Enumeration Type can be expressed in CDK as the following: - -```ts -declare const api: appsync.GraphqlApi; -const episode = new appsync.EnumType('Episode', { - definition: [ - 'NEWHOPE', - 'EMPIRE', - 'JEDI', - ], -}); -api.addType(episode); -``` - -To learn more about **Enum Types**, read the docs [here](https://graphql.org/learn/schema/#enumeration-types). - -#### Input Types - -**Input Types** are special types of Intermediate Types. They give users an -easy way to pass complex objects for top level Mutation and Queries. - -```gql -input Review { - stars: Int! - commentary: String -} -``` - -The above GraphQL Input Type can be expressed in CDK as the following: - -```ts -declare const api: appsync.GraphqlApi; -const review = new appsync.InputType('Review', { - definition: { - stars: appsync.GraphqlType.int({ isRequired: true }), - commentary: appsync.GraphqlType.string(), - }, -}); -api.addType(review); -``` - -To learn more about **Input Types**, read the docs [here](https://graphql.org/learn/schema/#input-types). - -#### Union Types - -**Union Types** are a special type of Intermediate Type. They are similar to -Interface Types, but they cannot specify any common fields between types. - -**Note:** the fields of a union type need to be `Object Types`. In other words, you -can't create a union type out of interfaces, other unions, or inputs. - -```gql -union Search = Human | Droid | Starship -``` - -The above GraphQL Union Type encompasses the Object Types of Human, Droid and Starship. It -can be expressed in CDK as the following: - -```ts -declare const api: appsync.GraphqlApi; -const string = appsync.GraphqlType.string(); -const human = new appsync.ObjectType('Human', { definition: { name: string } }); -const droid = new appsync.ObjectType('Droid', { definition: { name: string } }); -const starship = new appsync.ObjectType('Starship', { definition: { name: string } });); -const search = new appsync.UnionType('Search', { - definition: [ human, droid, starship ], -}); -api.addType(search); -``` - -To learn more about **Union Types**, read the docs [here](https://graphql.org/learn/schema/#union-types). - -### Query - -Every schema requires a top level Query type. By default, the schema will look -for the `Object Type` named `Query`. The top level `Query` is the **only** exposed -type that users can access to perform `GET` operations on your Api. - -To add fields for these queries, we can simply run the `addQuery` function to add -to the schema's `Query` type. - -```ts -declare const api: appsync.GraphqlApi; -declare const filmConnection: appsync.InterfaceType; -declare const dummyRequest: appsync.MappingTemplate; -declare const dummyResponse: appsync.MappingTemplate; - -const string = appsync.GraphqlType.string(); -const int = appsync.GraphqlType.int(); -api.addQuery('allFilms', new appsync.ResolvableField({ - returnType: filmConnection.attribute(), - args: { after: string, first: int, before: string, last: int}, - dataSource: api.addNoneDataSource('none'), - requestMappingTemplate: dummyRequest, - responseMappingTemplate: dummyResponse, -})); -``` - -To learn more about top level operations, check out the docs [here](https://docs.aws.amazon.com/appsync/latest/devguide/graphql-overview.html). - -### Mutation - -Every schema **can** have a top level Mutation type. By default, the schema will look -for the `ObjectType` named `Mutation`. The top level `Mutation` Type is the only exposed -type that users can access to perform `mutable` operations on your Api. - -To add fields for these mutations, we can simply run the `addMutation` function to add -to the schema's `Mutation` type. - -```ts -declare const api: appsync.GraphqlApi; -declare const filmNode: appsync.ObjectType; -declare const dummyRequest: appsync.MappingTemplate; -declare const dummyResponse: appsync.MappingTemplate; - -const string = appsync.GraphqlType.string(); -const int = appsync.GraphqlType.int(); -api.addMutation('addFilm', new appsync.ResolvableField({ - returnType: filmNode.attribute(), - args: { name: string, film_number: int }, - dataSource: api.addNoneDataSource('none'), - requestMappingTemplate: dummyRequest, - responseMappingTemplate: dummyResponse, -})); -``` - -To learn more about top level operations, check out the docs [here](https://docs.aws.amazon.com/appsync/latest/devguide/graphql-overview.html). - -### Subscription - -Every schema **can** have a top level Subscription type. The top level `Subscription` Type -is the only exposed type that users can access to invoke a response to a mutation. `Subscriptions` -notify users when a mutation specific mutation is called. This means you can make any data source -real time by specify a GraphQL Schema directive on a mutation. - -**Note**: The AWS AppSync client SDK automatically handles subscription connection management. - -To add fields for these subscriptions, we can simply run the `addSubscription` function to add -to the schema's `Subscription` type. - -```ts -declare const api: appsync.GraphqlApi; -declare const film: appsync.InterfaceType; - -api.addSubscription('addedFilm', new appsync.Field({ - returnType: film.attribute(), - args: { id: appsync.GraphqlType.id({ isRequired: true }) }, - directives: [appsync.Directive.subscribe('addFilm')], -})); -``` - -To learn more about top level operations, check out the docs [here](https://docs.aws.amazon.com/appsync/latest/devguide/real-time-data.html). diff --git a/packages/@aws-cdk/aws-appsync/lib/graphqlapi.ts b/packages/@aws-cdk/aws-appsync/lib/graphqlapi.ts index 5736f888fbf73..83027eafd5603 100644 --- a/packages/@aws-cdk/aws-appsync/lib/graphqlapi.ts +++ b/packages/@aws-cdk/aws-appsync/lib/graphqlapi.ts @@ -7,10 +7,7 @@ import { ArnFormat, CfnResource, Duration, Expiration, IResolvable, Stack } from import { Construct } from 'constructs'; import { CfnApiKey, CfnGraphQLApi, CfnGraphQLSchema, CfnDomainName, CfnDomainNameApiAssociation } from './appsync.generated'; import { IGraphqlApi, GraphqlApiBase } from './graphqlapi-base'; -import { Schema } from './schema'; -import { IIntermediateType } from './schema-base'; -import { ResolvableField } from './schema-field'; -import { ObjectType } from './schema-intermediate'; +import { ISchema } from './schema'; /** * enum with all possible values for AppSync authorization type @@ -307,7 +304,7 @@ export interface GraphqlApiProps { * @default - schema will be generated code-first (i.e. addType, addObjectType, etc.) * */ - readonly schema?: Schema; + readonly schema: ISchema; /** * A flag indicating whether or not X-Ray tracing is enabled for the GraphQL API. * @@ -456,7 +453,7 @@ export class GraphqlApi extends GraphqlApiBase { /** * the schema attached to this api */ - public readonly schema: Schema; + public readonly schema: ISchema; /** * The Authorization Types for this GraphQL Api @@ -507,8 +504,8 @@ export class GraphqlApi extends GraphqlApiBase { this.arn = this.api.attrArn; this.graphqlUrl = this.api.attrGraphQlUrl; this.name = this.api.name; - this.schema = props.schema ?? new Schema(); - this.schemaResource = this.schema.bind(this); + this.schema = props.schema; + this.schemaResource = new CfnGraphQLSchema(this, 'Schema', this.schema.bind(this)); if (props.domainName) { this.domainNameResource = new CfnDomainName(this, 'DomainName', { @@ -707,75 +704,6 @@ export class GraphqlApi extends GraphqlApiBase { }); } - /** - * Escape hatch to append to Schema as desired. Will always result - * in a newline. - * - * @param addition the addition to add to schema - * @param delimiter the delimiter between schema and addition - * @default - '' - * - */ - public addToSchema(addition: string, delimiter?: string): void { - this.schema.addToSchema(addition, delimiter); - } - - /** - * Add type to the schema - * - * @param type the intermediate type to add to the schema - * - */ - public addType(type: IIntermediateType): IIntermediateType { - return this.schema.addType(type); - } - - /** - * Add a query field to the schema's Query. CDK will create an - * Object Type called 'Query'. For example, - * - * type Query { - * fieldName: Field.returnType - * } - * - * @param fieldName the name of the query - * @param field the resolvable field to for this query - */ - public addQuery(fieldName: string, field: ResolvableField): ObjectType { - return this.schema.addQuery(fieldName, field); - } - - /** - * Add a mutation field to the schema's Mutation. CDK will create an - * Object Type called 'Mutation'. For example, - * - * type Mutation { - * fieldName: Field.returnType - * } - * - * @param fieldName the name of the Mutation - * @param field the resolvable field to for this Mutation - */ - public addMutation(fieldName: string, field: ResolvableField): ObjectType { - return this.schema.addMutation(fieldName, field); - } - - /** - * Add a subscription field to the schema's Subscription. CDK will create an - * Object Type called 'Subscription'. For example, - * - * type Subscription { - * fieldName: Field.returnType - * } - * - * @param fieldName the name of the Subscription - * @param field the resolvable field to for this Subscription - */ - public addSubscription(fieldName: string, field: ResolvableField): ObjectType { - return this.schema.addSubscription(fieldName, field); - } - - /** * The AppSyncDomainName of the associated custom domain */ diff --git a/packages/@aws-cdk/aws-appsync/lib/index.ts b/packages/@aws-cdk/aws-appsync/lib/index.ts index a102b16ac37a1..70286a0e72748 100644 --- a/packages/@aws-cdk/aws-appsync/lib/index.ts +++ b/packages/@aws-cdk/aws-appsync/lib/index.ts @@ -8,8 +8,5 @@ export * from './data-source'; export * from './mapping-template'; export * from './resolver'; export * from './schema'; -export * from './schema-intermediate'; -export * from './schema-field'; -export * from './schema-base'; export * from './graphqlapi'; export * from './graphqlapi-base'; diff --git a/packages/@aws-cdk/aws-appsync/lib/private.ts b/packages/@aws-cdk/aws-appsync/lib/private.ts index 9e2bd335bed1e..448702da43662 100644 --- a/packages/@aws-cdk/aws-appsync/lib/private.ts +++ b/packages/@aws-cdk/aws-appsync/lib/private.ts @@ -2,14 +2,6 @@ import { AuthorizationType } from './graphqlapi'; import { Directive } from './schema-base'; import { InterfaceType } from './schema-intermediate'; -/** - * Utility enum for Schema class - */ -export enum SchemaMode { - FILE = 'FILE', - CODE = 'CODE', -}; - /** * Generates an addition to the schema * @@ -234,4 +226,4 @@ function generateDirectives(options: generateDirectivesOptions): string { // pass in the auth modes for checks to happen on compile time return options.directives.reduce((acc, directive) => `${acc}${directive._bindToAuthModes(options.modes).toString()}${options.delimiter ?? ' '}`, ' ').slice(0, -1); -} \ No newline at end of file +} diff --git a/packages/@aws-cdk/aws-appsync/lib/schema-base.ts b/packages/@aws-cdk/aws-appsync/lib/schema-base.ts deleted file mode 100644 index fa876c395bc25..0000000000000 --- a/packages/@aws-cdk/aws-appsync/lib/schema-base.ts +++ /dev/null @@ -1,396 +0,0 @@ -import { AuthorizationType, GraphqlApi } from './graphqlapi'; -import { Resolver } from './resolver'; -import { ResolvableFieldOptions, BaseTypeOptions, GraphqlType } from './schema-field'; -import { InterfaceType } from './schema-intermediate'; - -/** - * A Graphql Field - */ -export interface IField { - /** - * the type of attribute - */ - readonly type: Type; - - /** - * property determining if this attribute is a list - * i.e. if true, attribute would be `[Type]` - * - * @default false - */ - readonly isList: boolean; - - /** - * property determining if this attribute is non-nullable - * i.e. if true, attribute would be `Type!` and this attribute - * must always have a value - * - * @default false - */ - readonly isRequired: boolean; - - /** - * property determining if this attribute is a non-nullable list - * i.e. if true, attribute would be `[ Type ]!` and this attribute's - * list must always have a value - * - * @default false - */ - readonly isRequiredList: boolean; - - /** - * The options to make this field resolvable - * - * @default - not a resolvable field - */ - readonly fieldOptions?: ResolvableFieldOptions; - - /** - * the intermediate type linked to this attribute - * (i.e. an interface or an object) - * - * @default - no intermediate type - */ - readonly intermediateType?: IIntermediateType; - - /** - * Generate the string for this attribute - */ - toString(): string; - - /** - * Generate the arguments for this field - */ - argsToString(): string; - - /** - * Generate the directives for this field - * - * @param modes the authorization modes of the graphql api - * - * @default - no authorization modes - */ - directivesToString(modes?: AuthorizationType[]): string -} - -/** - * The options to add a field to an Intermediate Type - */ -export interface AddFieldOptions { - /** - * The name of the field - * - * This option must be configured for Object, Interface, - * Input and Enum Types. - * - * @default - no fieldName - */ - readonly fieldName?: string; - /** - * The resolvable field to add - * - * This option must be configured for Object, Interface, - * Input and Union Types. - * - * @default - no IField - */ - readonly field?: IField; -} - -/** - * Intermediate Types are types that includes a certain set of fields - * that define the entirety of your schema - */ -export interface IIntermediateType { - /** - * the name of this type - */ - readonly name: string; - - /** - * the attributes of this type - */ - readonly definition: { [key: string]: IField }; - - /** - * The Interface Types this Intermediate Type implements - * - * @default - no interface types - */ - readonly interfaceTypes?: InterfaceType[]; - - /** - * the directives for this object type - * - * @default - no directives - */ - readonly directives?: Directive[]; - - /** - * The resolvers linked to this data source - */ - resolvers?: Resolver[]; - - /** - * the intermediate type linked to this attribute - * (i.e. an interface or an object) - * - * @default - no intermediate type - */ - readonly intermediateType?: IIntermediateType; - - /** - * Method called when the stringifying Intermediate Types for schema generation - * - * @param api The binding GraphQL Api - * - * @internal - */ - _bindToGraphqlApi(api: GraphqlApi): IIntermediateType; - - /** - * Create an GraphQL Type representing this Intermediate Type - * - * @param options the options to configure this attribute - * - isList - * - isRequired - * - isRequiredList - */ - attribute(options?: BaseTypeOptions): GraphqlType; - - /** - * Generate the string of this object type - */ - toString(): string; - - /** - * Add a field to this Intermediate Type - */ - addField(options: AddFieldOptions): void; -} - -interface DirectiveOptions { - /** - * The authorization type of this directive - */ - readonly mode?: AuthorizationType; - - /** - * Mutation fields for a subscription directive - */ - readonly mutationFields?: string[]; -} - -/** - * Directives for types - * - * i.e. @aws_iam or @aws_subscribe - * - */ -export class Directive { - /** - * Add the @aws_iam directive - */ - public static iam(): Directive { - return new Directive('@aws_iam', { mode: AuthorizationType.IAM }); - } - - /** - * Add the @aws_oidc directive - */ - public static oidc(): Directive { - return new Directive('@aws_oidc', { mode: AuthorizationType.OIDC }); - } - - /** - * Add the @aws_api_key directive - */ - public static apiKey(): Directive { - return new Directive('@aws_api_key', { mode: AuthorizationType.API_KEY }); - } - - /** - * Add the @aws_auth or @aws_cognito_user_pools directive - * - * @param groups the groups to allow access to - */ - public static cognito(...groups: string[]): Directive { - if (groups.length === 0) { - throw new Error(`Cognito authorization requires at least one Cognito group to be supplied. Received: ${groups.length}`); - } - // this function creates the cognito groups as a string (i.e. ["group1", "group2", "group3"]) - const stringify = (array: string[]): string => { - return array.reduce((acc, element) => `${acc}"${element}", `, '').slice(0, -2); - }; - return new Directive(`@aws_auth(cognito_groups: [${stringify(groups)}])`, { mode: AuthorizationType.USER_POOL }); - } - - /** - * Add the @aws_subscribe directive. Only use for top level Subscription type. - * - * @param mutations the mutation fields to link to - */ - public static subscribe(...mutations: string[]): Directive { - if (mutations.length === 0) { - throw new Error(`Subscribe directive requires at least one mutation field to be supplied. Received: ${mutations.length}`); - } - // this function creates the subscribe directive as a string (i.e. ["mutation_field_1", "mutation_field_2"]) - const stringify = (array: string[]): string => { - return array.reduce((acc, mutation) => `${acc}"${mutation}", `, '').slice(0, -2); - }; - return new Directive(`@aws_subscribe(mutations: [${stringify(mutations)}])`, { mutationFields: mutations }); - } - - /** - * Add a custom directive - * - * @param statement - the directive statement to append - */ - public static custom(statement: string): Directive { - return new Directive(statement); - } - - /** - * The authorization type of this directive - * - * @default - not an authorization directive - */ - public readonly mode?: AuthorizationType; - - /** - * Mutation fields for a subscription directive - * - * @default - not a subscription directive - */ - public readonly mutationFields?: string[]; - - /** - * the directive statement - */ - private statement: string; - - /** - * the authorization modes for this intermediate type - */ - protected modes?: AuthorizationType[]; - - private constructor(statement: string, options?: DirectiveOptions) { - this.statement = statement; - this.mode = options?.mode; - this.mutationFields = options?.mutationFields; - } - - /** - * Method called when the stringifying Directive for schema generation - * - * @param modes the authorization modes - * - * @internal - */ - public _bindToAuthModes(modes?: AuthorizationType[]): Directive { - this.modes = modes; - return this; - } - - /** - * Generate the directive statement - */ - public toString(): string { - if (this.modes && this.mode && !this.modes.some((mode) => mode === this.mode)) { - throw new Error(`No Authorization Type ${this.mode} declared in GraphQL Api.`); - } - if (this.mode === AuthorizationType.USER_POOL && this.modes && this.modes.length > 1) { - this.statement = this.statement.replace('@aws_auth', '@aws_cognito_user_pools'); - } - return this.statement; - } -} - -/** - * Enum containing the Types that can be used to define ObjectTypes - */ -export enum Type { - /** - * `ID` scalar type is a unique identifier. `ID` type is serialized similar to `String`. - * - * Often used as a key for a cache and not intended to be human-readable. - */ - ID = 'ID', - /** - * `String` scalar type is a free-form human-readable text. - */ - STRING = 'String', - /** - * `Int` scalar type is a signed non-fractional numerical value. - */ - INT = 'Int', - /** - * `Float` scalar type is a signed double-precision fractional value. - */ - FLOAT = 'Float', - /** - * `Boolean` scalar type is a boolean value: true or false. - */ - BOOLEAN = 'Boolean', - - /** - * `AWSDate` scalar type represents a valid extended `ISO 8601 Date` string. - * - * In other words, accepts date strings in the form of `YYYY-MM-DD`. It accepts time zone offsets. - * - * @see https://en.wikipedia.org/wiki/ISO_8601#Calendar_dates - */ - AWS_DATE = 'AWSDate', - /** - * `AWSTime` scalar type represents a valid extended `ISO 8601 Time` string. - * - * In other words, accepts date strings in the form of `hh:mm:ss.sss`. It accepts time zone offsets. - * - * @see https://en.wikipedia.org/wiki/ISO_8601#Times - */ - AWS_TIME = 'AWSTime', - /** - * `AWSDateTime` scalar type represents a valid extended `ISO 8601 DateTime` string. - * - * In other words, accepts date strings in the form of `YYYY-MM-DDThh:mm:ss.sssZ`. It accepts time zone offsets. - * - * @see https://en.wikipedia.org/wiki/ISO_8601#Combined_date_and_time_representations - */ - AWS_DATE_TIME = 'AWSDateTime', - /** - * `AWSTimestamp` scalar type represents the number of seconds since `1970-01-01T00:00Z`. - * - * Timestamps are serialized and deserialized as numbers. - */ - AWS_TIMESTAMP = 'AWSTimestamp', - /** - * `AWSEmail` scalar type represents an email address string (i.e.`username@example.com`) - */ - AWS_EMAIL = 'AWSEmail', - /** - * `AWSJson` scalar type represents a JSON string. - */ - AWS_JSON = 'AWSJSON', - /** - * `AWSURL` scalar type represetns a valid URL string. - * - * URLs wihtout schemes or contain double slashes are considered invalid. - */ - AWS_URL = 'AWSURL', - /** - * `AWSPhone` scalar type represents a valid phone number. Phone numbers maybe be whitespace delimited or hyphenated. - * - * The number can specify a country code at the beginning, but is not required for US phone numbers. - */ - AWS_PHONE = 'AWSPhone', - /** - * `AWSIPAddress` scalar type respresents a valid `IPv4` of `IPv6` address string. - */ - AWS_IP_ADDRESS = 'AWSIPAddress', - - /** - * Type used for Intermediate Types - * (i.e. an interface or an object type) - */ - INTERMEDIATE = 'INTERMEDIATE', -} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-appsync/lib/schema-field.ts b/packages/@aws-cdk/aws-appsync/lib/schema-field.ts deleted file mode 100644 index f8cf13a698878..0000000000000 --- a/packages/@aws-cdk/aws-appsync/lib/schema-field.ts +++ /dev/null @@ -1,460 +0,0 @@ -import { IAppsyncFunction } from './appsync-function'; -import { BaseDataSource } from './data-source'; -import { AuthorizationType } from './graphqlapi'; -import { MappingTemplate } from './mapping-template'; -import { Type, IField, IIntermediateType, Directive } from './schema-base'; - -/** - * Base options for GraphQL Types - * - * @option isList - is this attribute a list - * @option isRequired - is this attribute non-nullable - * @option isRequiredList - is this attribute a non-nullable list - * - */ -export interface BaseTypeOptions { - /** - * property determining if this attribute is a list - * i.e. if true, attribute would be [Type] - * - * @default - false - */ - readonly isList?: boolean; - - /** - * property determining if this attribute is non-nullable - * i.e. if true, attribute would be Type! - * - * @default - false - */ - readonly isRequired?: boolean; - - /** - * property determining if this attribute is a non-nullable list - * i.e. if true, attribute would be [ Type ]! - * or if isRequired true, attribe would be [ Type! ]! - * - * @default - false - */ - readonly isRequiredList?: boolean; -} - -/** - * Options for GraphQL Types - * - * @option isList - is this attribute a list - * @option isRequired - is this attribute non-nullable - * @option isRequiredList - is this attribute a non-nullable list - * @option objectType - the object type linked to this attribute - * - */ -export interface GraphqlTypeOptions extends BaseTypeOptions { - /** - * the intermediate type linked to this attribute - * @default - no intermediate type - */ - readonly intermediateType?: IIntermediateType; -} - -/** - * The GraphQL Types in AppSync's GraphQL. GraphQL Types are the - * building blocks for object types, queries, mutations, etc. They are - * types like String, Int, Id or even Object Types you create. - * - * i.e. `String`, `String!`, `[String]`, `[String!]`, `[String]!` - * - * GraphQL Types are used to define the entirety of schema. - */ -export class GraphqlType implements IField { - /** - * `ID` scalar type is a unique identifier. `ID` type is serialized similar to `String`. - * - * Often used as a key for a cache and not intended to be human-readable. - * - * @param options the options to configure this attribute - * - isList - * - isRequired - * - isRequiredList - */ - public static id(options?: BaseTypeOptions): GraphqlType { - return new GraphqlType(Type.ID, options); - } - /** - * `String` scalar type is a free-form human-readable text. - * - * @param options the options to configure this attribute - * - isList - * - isRequired - * - isRequiredList - */ - public static string(options?: BaseTypeOptions): GraphqlType { - return new GraphqlType(Type.STRING, options); - } - /** - * `Int` scalar type is a signed non-fractional numerical value. - * - * @param options the options to configure this attribute - * - isList - * - isRequired - * - isRequiredList - */ - public static int(options?: BaseTypeOptions): GraphqlType { - return new GraphqlType(Type.INT, options); - } - /** - * `Float` scalar type is a signed double-precision fractional value. - * - * @param options the options to configure this attribute - * - isList - * - isRequired - * - isRequiredList - */ - public static float(options?: BaseTypeOptions): GraphqlType { - return new GraphqlType(Type.FLOAT, options); - } - /** - * `Boolean` scalar type is a boolean value: true or false. - * - * @param options the options to configure this attribute - * - isList - * - isRequired - * - isRequiredList - */ - public static boolean(options?: BaseTypeOptions): GraphqlType { - return new GraphqlType(Type.BOOLEAN, options); - } - - /** - * `AWSDate` scalar type represents a valid extended `ISO 8601 Date` string. - * - * In other words, accepts date strings in the form of `YYYY-MM-DD`. It accepts time zone offsets. - * - * @param options the options to configure this attribute - * - isList - * - isRequired - * - isRequiredList - */ - public static awsDate(options?: BaseTypeOptions): GraphqlType { - return new GraphqlType(Type.AWS_DATE, options); - } - /** - * `AWSTime` scalar type represents a valid extended `ISO 8601 Time` string. - * - * In other words, accepts date strings in the form of `hh:mm:ss.sss`. It accepts time zone offsets. - * - * @param options the options to configure this attribute - * - isList - * - isRequired - * - isRequiredList - */ - public static awsTime(options?: BaseTypeOptions): GraphqlType { - return new GraphqlType(Type.AWS_TIME, options); - } - /** - * `AWSDateTime` scalar type represents a valid extended `ISO 8601 DateTime` string. - * - * In other words, accepts date strings in the form of `YYYY-MM-DDThh:mm:ss.sssZ`. It accepts time zone offsets. - * - * @param options the options to configure this attribute - * - isList - * - isRequired - * - isRequiredList - */ - public static awsDateTime(options?: BaseTypeOptions): GraphqlType { - return new GraphqlType(Type.AWS_DATE_TIME, options); - } - /** - * `AWSTimestamp` scalar type represents the number of seconds since `1970-01-01T00:00Z`. - * - * Timestamps are serialized and deserialized as numbers. - * - * @param options the options to configure this attribute - * - isList - * - isRequired - * - isRequiredList - */ - public static awsTimestamp(options?: BaseTypeOptions): GraphqlType { - return new GraphqlType(Type.AWS_TIMESTAMP, options); - } - /** - * `AWSEmail` scalar type represents an email address string (i.e.`username@example.com`) - * - * @param options the options to configure this attribute - * - isList - * - isRequired - * - isRequiredList - */ - public static awsEmail(options?: BaseTypeOptions): GraphqlType { - return new GraphqlType(Type.AWS_EMAIL, options); - } - /** - * `AWSJson` scalar type represents a JSON string. - * - * @param options the options to configure this attribute - * - isList - * - isRequired - * - isRequiredList - */ - public static awsJson(options?: BaseTypeOptions): GraphqlType { - return new GraphqlType(Type.AWS_JSON, options); - } - /** - * `AWSURL` scalar type represetns a valid URL string. - * - * URLs wihtout schemes or contain double slashes are considered invalid. - * - * @param options the options to configure this attribute - * - isList - * - isRequired - * - isRequiredList - */ - public static awsUrl(options?: BaseTypeOptions): GraphqlType { - return new GraphqlType(Type.AWS_URL, options); - } - /** - * `AWSPhone` scalar type represents a valid phone number. Phone numbers maybe be whitespace delimited or hyphenated. - * - * The number can specify a country code at the beginning, but is not required for US phone numbers. - * - * @param options the options to configure this attribute - * - isList - * - isRequired - * - isRequiredList - */ - public static awsPhone(options?: BaseTypeOptions): GraphqlType { - return new GraphqlType(Type.AWS_PHONE, options); - } - /** - * `AWSIPAddress` scalar type respresents a valid `IPv4` of `IPv6` address string. - * - * @param options the options to configure this attribute - * - isList - * - isRequired - * - isRequiredList - */ - public static awsIpAddress(options?: BaseTypeOptions): GraphqlType { - return new GraphqlType(Type.AWS_IP_ADDRESS, options); - } - - /** - * an intermediate type to be added as an attribute - * (i.e. an interface or an object type) - * - * @param options the options to configure this attribute - * - isList - * - isRequired - * - isRequiredList - * - intermediateType - */ - public static intermediate(options?: GraphqlTypeOptions): GraphqlType { - if (!options?.intermediateType) { - throw new Error('GraphQL Type of interface must be configured with corresponding Intermediate Type'); - } - return new GraphqlType(Type.INTERMEDIATE, options); - } - - /** - * the type of attribute - */ - public readonly type: Type; - - /** - * property determining if this attribute is a list - * i.e. if true, attribute would be `[Type]` - * - * @default - false - */ - public readonly isList: boolean; - - /** - * property determining if this attribute is non-nullable - * i.e. if true, attribute would be `Type!` and this attribute - * must always have a value - * - * @default - false - */ - public readonly isRequired: boolean; - - /** - * property determining if this attribute is a non-nullable list - * i.e. if true, attribute would be `[ Type ]!` and this attribute's - * list must always have a value - * - * @default - false - */ - public readonly isRequiredList: boolean; - - /** - * the intermediate type linked to this attribute - * (i.e. an interface or an object) - * - * @default - no intermediate type - */ - public readonly intermediateType?: IIntermediateType; - - protected constructor(type: Type, options?: GraphqlTypeOptions) { - this.type = type; - this.isList = options?.isList ?? false; - this.isRequired = options?.isRequired ?? false; - this.isRequiredList = options?.isRequiredList ?? false; - this.intermediateType = options?.intermediateType; - } - - /** - * Generate the string for this attribute - */ - public toString(): string { - // If an Object Type, we use the name of the Object Type - let type = this.intermediateType ? this.intermediateType?.name : this.type; - // If configured as required, the GraphQL Type becomes required - type = this.isRequired ? `${type}!` : type; - // If configured with isXxxList, the GraphQL Type becomes a list - type = this.isList || this.isRequiredList ? `[${type}]` : type; - // If configured with isRequiredList, the list becomes required - type = this.isRequiredList ? `${type}!` : type; - return type; - } - - /** - * Generate the arguments for this field - */ - public argsToString(): string { - return ''; - } - - /** - * Generate the directives for this field - */ - public directivesToString(_modes?: AuthorizationType[]): string { - return ''; - } -} - -/** - * Properties for configuring a field - * - * @options args - the variables and types that define the arguments - * - * i.e. { string: GraphqlType, string: GraphqlType } - */ -export interface FieldOptions { - /** - * The return type for this field - */ - readonly returnType: GraphqlType; - /** - * The arguments for this field. - * - * i.e. type Example (first: String second: String) {} - * - where 'first' and 'second' are key values for args - * and 'String' is the GraphqlType - * - * @default - no arguments - */ - readonly args?: { [key: string]: GraphqlType }; - /** - * the directives for this field - * - * @default - no directives - */ - readonly directives?: Directive[]; -} - -/** - * Fields build upon Graphql Types and provide typing - * and arguments. - */ -export class Field extends GraphqlType implements IField { - /** - * The options for this field - * - * @default - no arguments - */ - public readonly fieldOptions?: ResolvableFieldOptions; - - public constructor(options: FieldOptions) { - const props = { - isList: options.returnType.isList, - isRequired: options.returnType.isRequired, - isRequiredList: options.returnType.isRequiredList, - intermediateType: options.returnType.intermediateType, - }; - super(options.returnType.type, props); - this.fieldOptions = options; - } - - /** - * Generate the args string of this resolvable field - */ - public argsToString(): string { - if (!this.fieldOptions || !this.fieldOptions.args) { return ''; } - return Object.keys(this.fieldOptions.args).reduce((acc, key) => - `${acc}${key}: ${this.fieldOptions?.args?.[key].toString()} `, '(').slice(0, -1) + ')'; - } - - /** - * Generate the directives for this field - */ - public directivesToString(modes?: AuthorizationType[]): string { - if (!this.fieldOptions || !this.fieldOptions.directives) { return ''; } - return this.fieldOptions.directives.reduce((acc, directive) => - `${acc}${directive._bindToAuthModes(modes).toString()} `, '\n ').slice(0, -1); - } -} - -/** - * Properties for configuring a resolvable field - * - * @options dataSource - the data source linked to this resolvable field - * @options requestMappingTemplate - the mapping template for requests to this resolver - * @options responseMappingTemplate - the mapping template for responses from this resolver - */ -export interface ResolvableFieldOptions extends FieldOptions { - /** - * The data source creating linked to this resolvable field - * - * @default - no data source - */ - readonly dataSource?: BaseDataSource; - /** - * configuration of the pipeline resolver - * - * @default - no pipeline resolver configuration - * An empty array or undefined prop will set resolver to be of type unit - */ - readonly pipelineConfig?: IAppsyncFunction[]; - /** - * The request mapping template for this resolver - * - * @default - No mapping template - */ - readonly requestMappingTemplate?: MappingTemplate; - /** - * The response mapping template for this resolver - * - * @default - No mapping template - */ - readonly responseMappingTemplate?: MappingTemplate; -} - -/** - * Resolvable Fields build upon Graphql Types and provide fields - * that can resolve into operations on a data source. - */ -export class ResolvableField extends Field implements IField { - /** - * The options to make this field resolvable - * - * @default - not a resolvable field - */ - public readonly fieldOptions?: ResolvableFieldOptions; - - public constructor(options: ResolvableFieldOptions) { - const props = { - returnType: options.returnType, - args: options.args, - }; - super(props); - this.fieldOptions = options; - } -} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-appsync/lib/schema-intermediate.ts b/packages/@aws-cdk/aws-appsync/lib/schema-intermediate.ts deleted file mode 100644 index a661d4e4baf61..0000000000000 --- a/packages/@aws-cdk/aws-appsync/lib/schema-intermediate.ts +++ /dev/null @@ -1,488 +0,0 @@ -import { AuthorizationType, GraphqlApi } from './graphqlapi'; -import { IGraphqlApi } from './graphqlapi-base'; -import { shapeAddition } from './private'; -import { Resolver } from './resolver'; -import { Directive, IField, IIntermediateType, AddFieldOptions } from './schema-base'; -import { BaseTypeOptions, GraphqlType, ResolvableFieldOptions, ResolvableField } from './schema-field'; - -/** - * Properties for configuring an Intermediate Type - * - * @param definition - the variables and types that define this type - * i.e. { string: GraphqlType, string: GraphqlType } - * @param directives - the directives for this object type - * - */ -export interface IntermediateTypeOptions { - /** - * the attributes of this type - */ - readonly definition: { [key: string]: IField }; - /** - * the directives for this object type - * - * @default - no directives - */ - readonly directives?: Directive[]; -} - -/** - * Interface Types are abstract types that includes a certain set of fields - * that other types must include if they implement the interface. - * - */ -export class InterfaceType implements IIntermediateType { - /** - * the name of this type - */ - public readonly name: string; - /** - * the attributes of this type - */ - public readonly definition: { [key: string]: IField }; - /** - * the directives for this object type - * - * @default - no directives - */ - public readonly directives?: Directive[]; - /** - * the authorization modes for this intermediate type - */ - protected modes?: AuthorizationType[]; - - public constructor(name: string, props: IntermediateTypeOptions) { - this.name = name; - this.definition = props.definition; - this.directives = props.directives; - } - - /** - * Create a GraphQL Type representing this Intermediate Type - * - * @param options the options to configure this attribute - */ - public attribute(options?: BaseTypeOptions): GraphqlType { - return GraphqlType.intermediate({ - isList: options?.isList, - isRequired: options?.isRequired, - isRequiredList: options?.isRequiredList, - intermediateType: this, - }); - } - - /** - * Generate the string of this object type - */ - public toString(): string { - return shapeAddition({ - prefix: 'interface', - name: this.name, - directives: this.directives, - fields: Object.keys(this.definition).map((key) => { - const field = this.definition[key]; - return `${key}${field.argsToString()}: ${field.toString()}${field.directivesToString(this.modes)}`; - }), - modes: this.modes, - }); - } - - /** - * Add a field to this Interface Type. - * - * Interface Types must have both fieldName and field options. - * - * @param options the options to add a field - */ - public addField(options: AddFieldOptions): void { - if (!options.fieldName || !options.field) { - throw new Error('Interface Types must have both fieldName and field options.'); - } - this.definition[options.fieldName] = options.field; - } - - /** - * Method called when the stringifying Intermediate Types for schema generation - * - * @internal - */ - public _bindToGraphqlApi(api: GraphqlApi): IIntermediateType { - this.modes = api.modes; - return this; - } -} - -/** - * Properties for configuring an Object Type - * - * @param definition - the variables and types that define this type - * i.e. { string: GraphqlType, string: GraphqlType } - * @param interfaceTypes - the interfaces that this object type implements - * @param directives - the directives for this object type - * - */ -export interface ObjectTypeOptions extends IntermediateTypeOptions { - /** - * The Interface Types this Object Type implements - * - * @default - no interface types - */ - readonly interfaceTypes?: InterfaceType[]; -} - -/** - * Object Types are types declared by you. - * - */ -export class ObjectType extends InterfaceType implements IIntermediateType { - /** - * The Interface Types this Object Type implements - * - * @default - no interface types - */ - public readonly interfaceTypes?: InterfaceType[]; - /** - * The resolvers linked to this data source - */ - public resolvers?: Resolver[]; - - public constructor(name: string, props: ObjectTypeOptions) { - const options = { - definition: props.interfaceTypes?.reduce((def, interfaceType) => { - return Object.assign({}, def, interfaceType.definition); - }, props.definition) ?? props.definition, - directives: props.directives, - }; - super(name, options); - this.interfaceTypes = props.interfaceTypes; - this.resolvers = []; - } - - /** - * Method called when the stringifying Intermediate Types for schema generation - * - * @internal - */ - public _bindToGraphqlApi(api: GraphqlApi): IIntermediateType { - this.modes = api.modes; - // If the resolvers have been generated, skip the bind - if (this.resolvers && this.resolvers.length > 0) { - return this; - } - Object.keys(this.definition).forEach((fieldName) => { - const field = this.definition[fieldName]; - if (field instanceof ResolvableField) { - if (!this.resolvers) this.resolvers = []; - this.resolvers.push(this.generateResolver(api, fieldName, field.fieldOptions)); - } - }); - return this; - } - - /** - * Add a field to this Object Type. - * - * Object Types must have both fieldName and field options. - * - * @param options the options to add a field - */ - public addField(options: AddFieldOptions): void { - if (!options.fieldName || !options.field) { - throw new Error('Object Types must have both fieldName and field options.'); - } - this.definition[options.fieldName] = options.field; - } - - /** - * Generate the string of this object type - */ - public toString(): string { - return shapeAddition({ - prefix: 'type', - name: this.name, - interfaceTypes: this.interfaceTypes, - directives: this.directives, - fields: Object.keys(this.definition).map((key) => { - const field = this.definition[key]; - return `${key}${field.argsToString()}: ${field.toString()}${field.directivesToString(this.modes)}`; - }), - modes: this.modes, - }); - } - - /** - * Generate the resolvers linked to this Object Type - */ - protected generateResolver(api: IGraphqlApi, fieldName: string, options?: ResolvableFieldOptions): Resolver { - return api.createResolver({ - typeName: this.name, - fieldName: fieldName, - dataSource: options?.dataSource, - pipelineConfig: options?.pipelineConfig, - requestMappingTemplate: options?.requestMappingTemplate, - responseMappingTemplate: options?.responseMappingTemplate, - }); - } -} - -/** - * Input Types are abstract types that define complex objects. - * They are used in arguments to represent - * - */ -export class InputType implements IIntermediateType { - /** - * the name of this type - */ - public readonly name: string; - /** - * the attributes of this type - */ - public readonly definition: { [key: string]: IField }; - /** - * the authorization modes for this intermediate type - */ - protected modes?: AuthorizationType[]; - - public constructor(name: string, props: IntermediateTypeOptions) { - this.name = name; - this.definition = props.definition; - } - - /** - * Create a GraphQL Type representing this Input Type - * - * @param options the options to configure this attribute - */ - public attribute(options?: BaseTypeOptions): GraphqlType { - return GraphqlType.intermediate({ - isList: options?.isList, - isRequired: options?.isRequired, - isRequiredList: options?.isRequiredList, - intermediateType: this, - }); - } - - /** - * Generate the string of this input type - */ - public toString(): string { - return shapeAddition({ - prefix: 'input', - name: this.name, - fields: Object.keys(this.definition).map((key) => - `${key}${this.definition[key].argsToString()}: ${this.definition[key].toString()}`), - modes: this.modes, - }); - } - - /** - * Add a field to this Input Type. - * - * Input Types must have both fieldName and field options. - * - * @param options the options to add a field - */ - public addField(options: AddFieldOptions): void { - if (!options.fieldName || !options.field) { - throw new Error('Input Types must have both fieldName and field options.'); - } - this.definition[options.fieldName] = options.field; - } - - /** - * Method called when the stringifying Intermediate Types for schema generation - * - * @internal - */ - public _bindToGraphqlApi(api: GraphqlApi): IIntermediateType { - this.modes = api.modes; - return this; - } -} - -/** - * Properties for configuring an Union Type - * - */ -export interface UnionTypeOptions { - /** - * the object types for this union type - */ - readonly definition: IIntermediateType[]; -} - -/** - * Union Types are abstract types that are similar to Interface Types, - * but they cannot to specify any common fields between types. - * - * Note that fields of a union type need to be object types. In other words, - * you can't create a union type out of interfaces, other unions, or inputs. - * - */ -export class UnionType implements IIntermediateType { - /** - * the name of this type - */ - public readonly name: string; - /** - * the attributes of this type - */ - public readonly definition: { [key: string]: IField }; - /** - * the authorization modes supported by this intermediate type - */ - protected modes?: AuthorizationType[]; - - public constructor(name: string, options: UnionTypeOptions) { - this.name = name; - this.definition = {}; - options.definition.map((def) => this.addField({ field: def.attribute() })); - } - - /** - * Create a GraphQL Type representing this Union Type - * - * @param options the options to configure this attribute - */ - public attribute(options?: BaseTypeOptions): GraphqlType { - return GraphqlType.intermediate({ - isList: options?.isList, - isRequired: options?.isRequired, - isRequiredList: options?.isRequiredList, - intermediateType: this, - }); - } - - /** - * Generate the string of this Union type - */ - public toString(): string { - // Return a string that appends all Object Types for this Union Type - // i.e. 'union Example = example1 | example2' - return Object.values(this.definition).reduce((acc, field) => - `${acc} ${field.toString()} |`, `union ${this.name} =`).slice(0, -2); - } - - /** - * Add a field to this Union Type - * - * Input Types must have field options and the IField must be an Object Type. - * - * @param options the options to add a field - */ - public addField(options: AddFieldOptions): void { - if (options.fieldName) { - throw new Error('Union Types cannot be configured with the fieldName option. Use the field option instead.'); - } - if (!options.field) { - throw new Error('Union Types must be configured with the field option.'); - } - if (options.field && !(options.field.intermediateType instanceof ObjectType)) { - throw new Error('Fields for Union Types must be Object Types.'); - } - this.definition[options.field.toString()] = options.field; - } - - /** - * Method called when the stringifying Intermediate Types for schema generation - * - * @internal - */ - public _bindToGraphqlApi(api: GraphqlApi): IIntermediateType { - this.modes = api.modes; - return this; - } -} - -/** - * Properties for configuring an Enum Type - * - */ -export interface EnumTypeOptions { - /** - * the attributes of this type - */ - readonly definition: string[]; -} - -/** - * Enum Types are abstract types that includes a set of fields - * that represent the strings this type can create. - * - */ -export class EnumType implements IIntermediateType { - /** - * the name of this type - */ - public readonly name: string; - /** - * the attributes of this type - */ - public readonly definition: { [key: string]: IField }; - /** - * the authorization modes for this intermediate type - */ - protected modes?: AuthorizationType[]; - - public constructor(name: string, options: EnumTypeOptions) { - this.name = name; - this.definition = {}; - options.definition.map((fieldName: string) => this.addField({ fieldName })); - } - - /** - * Create an GraphQL Type representing this Enum Type - */ - public attribute(options?: BaseTypeOptions): GraphqlType { - return GraphqlType.intermediate({ - isList: options?.isList, - isRequired: options?.isRequired, - isRequiredList: options?.isRequiredList, - intermediateType: this, - }); - } - - /** - * Generate the string of this enum type - */ - public toString(): string { - return shapeAddition({ - prefix: 'enum', - name: this.name, - fields: Object.keys(this.definition), - modes: this.modes, - }); - } - - /** - * Add a field to this Enum Type - * - * To add a field to this Enum Type, you must only configure - * addField with the fieldName options. - * - * @param options the options to add a field - */ - public addField(options: AddFieldOptions): void { - if (options.field) { - throw new Error('Enum Type fields consist of strings. Use the fieldName option instead of the field option.'); - } - if (!options.fieldName) { - throw new Error('When adding a field to an Enum Type, you must configure the fieldName option.'); - } - if (options.fieldName.indexOf(' ') > -1) { - throw new Error(`Enum Type values cannot have whitespace. Received: ${options.fieldName}`); - } - this.definition[options.fieldName] = GraphqlType.string(); - } - - /** - * Method called when the stringifying Intermediate Types for schema generation - * - * @internal - */ - public _bindToGraphqlApi(api: GraphqlApi): IIntermediateType { - this.modes = api.modes; - return this; - } -} diff --git a/packages/@aws-cdk/aws-appsync/lib/schema.ts b/packages/@aws-cdk/aws-appsync/lib/schema.ts index ad94da1610532..cd34dbb385310 100644 --- a/packages/@aws-cdk/aws-appsync/lib/schema.ts +++ b/packages/@aws-cdk/aws-appsync/lib/schema.ts @@ -1,27 +1,48 @@ import { readFileSync } from 'fs'; -import { Lazy } from '@aws-cdk/core'; -import { CfnGraphQLSchema } from './appsync.generated'; -import { GraphqlApi } from './graphqlapi'; -import { SchemaMode, shapeAddition } from './private'; -import { IIntermediateType } from './schema-base'; -import { Field, ResolvableField } from './schema-field'; -import { ObjectType } from './schema-intermediate'; +import { IGraphqlApi } from './graphqlapi-base'; /** - * The options for configuring a schema - * - * If no options are specified, then the schema will - * be generated code-first. + * Configuration for bound graphql schema + * + * Returned from ISchema.bind allowing late binding of schemas to graphqlapi-base + */ +export interface ISchemaConfig { + /** + * The ID of the api the schema is bound to + */ + apiId: string; + + /** + * The schema definition string + */ + definition: string; +} + +/** + * Interface for implementing your own schema + * + * Useful for providing schema's from sources other than assets + */ +export interface ISchema { + /** + * Binds a schema string to a GraphQlApi + * + * @returns ISchemaConfig with apiId and schema definition string + * @param api the api to bind the schema to + */ + bind(api: IGraphqlApi): ISchemaConfig; +} + +/** + * The options for configuring a schema from an existing file */ -export interface SchemaOptions { +export interface SchemaProps { /** * The file path for the schema. When this option is * configured, then the schema will be generated from an * existing file from disk. - * - * @default - schema not configured through disk asset */ - readonly filePath?: string, + readonly filePath: string, }; /** @@ -30,15 +51,15 @@ export interface SchemaOptions { * If no options are configured, schema will be generated * code-first. */ -export class Schema { +export class SchemaFile implements ISchema { /** * Generate a Schema from file * * @returns `SchemaAsset` with immutable schema defintion * @param filePath the file path of the schema file */ - public static fromAsset(filePath: string): Schema { - return new Schema({ filePath }); + public static fromAsset(filePath: string): SchemaFile { + return new SchemaFile({ filePath }); } /** @@ -46,27 +67,8 @@ export class Schema { */ public definition: string; - private query?: ObjectType; - - private mutation?: ObjectType; - - private subscription?: ObjectType; - - private schema?: CfnGraphQLSchema; - - private mode: SchemaMode; - - private types: IIntermediateType[]; - - public constructor(options?: SchemaOptions) { - if (options?.filePath) { - this.mode = SchemaMode.FILE; - this.definition = readFileSync(options.filePath).toString('utf-8'); - } else { - this.mode = SchemaMode.CODE; - this.definition = ''; - } - this.types = []; + public constructor(options: SchemaProps) { + this.definition = readFileSync(options.filePath).toString('utf-8'); } /** @@ -75,145 +77,10 @@ export class Schema { * * @param api The binding GraphQL Api */ - public bind(api: GraphqlApi): CfnGraphQLSchema { - if (!this.schema) { - this.schema = new CfnGraphQLSchema(api, 'Schema', { - apiId: api.apiId, - definition: this.mode === SchemaMode.CODE ? - Lazy.string({ - produce: () => this.types.reduce((acc, type) => `${acc}${type._bindToGraphqlApi(api).toString()}\n`, - `${this.declareSchema()}${this.definition}`), - }) - : this.definition, - }); - } - return this.schema; - } - - /** - * Escape hatch to add to Schema as desired. Will always result - * in a newline. - * - * @param addition the addition to add to schema - * @param delimiter the delimiter between schema and addition - * @default - '' - * - */ - public addToSchema(addition: string, delimiter?: string): void { - if (this.mode !== SchemaMode.CODE) { - throw new Error('API cannot append to schema because schema definition mode is not configured as CODE.'); - } - const sep = delimiter ?? ''; - this.definition = `${this.definition}${sep}${addition}\n`; - } - - /** - * Add a query field to the schema's Query. CDK will create an - * Object Type called 'Query'. For example, - * - * type Query { - * fieldName: Field.returnType - * } - * - * @param fieldName the name of the query - * @param field the resolvable field to for this query - */ - public addQuery(fieldName: string, field: ResolvableField): ObjectType { - if (this.mode !== SchemaMode.CODE) { - throw new Error(`Unable to add query. Schema definition mode must be ${SchemaMode.CODE}. Received: ${this.mode}`); - } - if (!this.query) { - this.query = new ObjectType('Query', { definition: {} }); - this.addType(this.query); + public bind(api: IGraphqlApi): ISchemaConfig { + return { + apiId: api.apiId, + definition: this.definition, }; - this.query.addField({ fieldName, field }); - return this.query; - } - - /** - * Add a mutation field to the schema's Mutation. CDK will create an - * Object Type called 'Mutation'. For example, - * - * type Mutation { - * fieldName: Field.returnType - * } - * - * @param fieldName the name of the Mutation - * @param field the resolvable field to for this Mutation - */ - public addMutation(fieldName: string, field: ResolvableField): ObjectType { - if (this.mode !== SchemaMode.CODE) { - throw new Error(`Unable to add mutation. Schema definition mode must be ${SchemaMode.CODE}. Received: ${this.mode}`); - } - if (!this.mutation) { - this.mutation = new ObjectType('Mutation', { definition: {} }); - this.addType(this.mutation); - }; - this.mutation.addField({ fieldName, field }); - return this.mutation; - } - - /** - * Add a subscription field to the schema's Subscription. CDK will create an - * Object Type called 'Subscription'. For example, - * - * type Subscription { - * fieldName: Field.returnType - * } - * - * @param fieldName the name of the Subscription - * @param field the resolvable field to for this Subscription - */ - public addSubscription(fieldName: string, field: Field): ObjectType { - if (this.mode !== SchemaMode.CODE) { - throw new Error(`Unable to add subscription. Schema definition mode must be ${SchemaMode.CODE}. Received: ${this.mode}`); - } - if (!this.subscription) { - this.subscription = new ObjectType('Subscription', { definition: {} }); - this.addType(this.subscription); - } - const directives = field.fieldOptions?.directives?.filter((directive) => directive.mutationFields); - if (directives && directives.length > 1) { - throw new Error(`Subscription fields must not have more than one @aws_subscribe directives. Received: ${directives.length}`); - } - this.subscription.addField({ fieldName, field }); - return this.subscription; - } - - /** - * Add type to the schema - * - * @param type the intermediate type to add to the schema - * - */ - public addType(type: IIntermediateType): IIntermediateType { - if (this.mode !== SchemaMode.CODE) { - throw new Error('API cannot add type because schema definition mode is not configured as CODE.'); - } - this.types.push(type); - return type; - } - - /** - * Set the root types of this schema if they are defined. - * - * For example: - * schema { - * query: Query - * mutation: Mutation - * subscription: Subscription - * } - */ - private declareSchema(): string { - if (!this.query && !this.mutation && !this.subscription) { - return ''; - } - type root = 'mutation' | 'query' | 'subscription'; - const list: root[] = ['query', 'mutation', 'subscription']; - return shapeAddition({ - prefix: 'schema', - fields: list.map((key: root) => this[key] ? `${key}: ${this[key]?.name}` : '') - .filter((field) => field != ''), - }) + '\n'; } -} \ No newline at end of file +} diff --git a/packages/@aws-cdk/aws-appsync/rosetta/with-objects.ts-fixture b/packages/@aws-cdk/aws-appsync/rosetta/with-objects.ts-fixture deleted file mode 100644 index 1058e0c2d6fbf..0000000000000 --- a/packages/@aws-cdk/aws-appsync/rosetta/with-objects.ts-fixture +++ /dev/null @@ -1,50 +0,0 @@ -// Fixture with packages imported, but nothing else -import { Stack } from '@aws-cdk/core'; -import { Construct } from 'constructs'; -import appsync = require('@aws-cdk/aws-appsync'); -const pluralize = require('pluralize'); - -const args = { - after: appsync.GraphqlType.string(), - first: appsync.GraphqlType.int(), - before: appsync.GraphqlType.string(), - last: appsync.GraphqlType.int(), -}; - -const Node = new appsync.InterfaceType('Node', { - definition: { id: appsync.GraphqlType.string() } -}); - -const FilmNode = new appsync.ObjectType('FilmNode', { - interfaceTypes: [Node], - definition: { filmName: appsync.GraphqlType.string() } -}); - -function generateEdgeAndConnection(base: appsync.ObjectType) { - const edge = new appsync.ObjectType(`${base.name}Edge`, { - definition: { node: base.attribute(), cursor: appsync.GraphqlType.string() } - }); - const connection = new appsync.ObjectType(`${base.name}Connection`, { - definition: { - edges: edge.attribute({ isList: true }), - [pluralize(base.name)]: base.attribute({ isList: true }), - totalCount: appsync.GraphqlType.int(), - } - }); - return { edge: edge, connection: connection }; -} - -const demo = new appsync.ObjectType('Demo', { - definition: { - id: appsync.GraphqlType.string({ isRequired: true }), - version: appsync.GraphqlType.string({ isRequired: true }), - }, -}); - -class Fixture extends Stack { - constructor(scope: Construct, id: string) { - super(scope, id); - - /// here - } -} diff --git a/packages/@aws-cdk/aws-appsync/test/appsync-auth.test.ts b/packages/@aws-cdk/aws-appsync/test/appsync-auth.test.ts index b220e9d6f2d3b..7331fdfd907e7 100644 --- a/packages/@aws-cdk/aws-appsync/test/appsync-auth.test.ts +++ b/packages/@aws-cdk/aws-appsync/test/appsync-auth.test.ts @@ -16,7 +16,7 @@ describe('AppSync API Key Authorization', () => { // WHEN new appsync.GraphqlApi(stack, 'api', { name: 'api', - schema: appsync.Schema.fromAsset(path.join(__dirname, 'appsync.test.graphql')), + schema: appsync.SchemaFile.fromAsset(path.join(__dirname, 'appsync.test.graphql')), }); // THEN @@ -27,7 +27,7 @@ describe('AppSync API Key Authorization', () => { // WHEN new appsync.GraphqlApi(stack, 'api', { name: 'api', - schema: appsync.Schema.fromAsset(path.join(__dirname, 'appsync.test.graphql')), + schema: appsync.SchemaFile.fromAsset(path.join(__dirname, 'appsync.test.graphql')), authorizationConfig: { defaultAuthorization: { authorizationType: appsync.AuthorizationType.IAM }, additionalAuthorizationModes: [ @@ -44,7 +44,7 @@ describe('AppSync API Key Authorization', () => { // WHEN new appsync.GraphqlApi(stack, 'api', { name: 'api', - schema: appsync.Schema.fromAsset(path.join(__dirname, 'appsync.test.graphql')), + schema: appsync.SchemaFile.fromAsset(path.join(__dirname, 'appsync.test.graphql')), authorizationConfig: { defaultAuthorization: { authorizationType: appsync.AuthorizationType.IAM }, }, @@ -58,7 +58,7 @@ describe('AppSync API Key Authorization', () => { // WHEN new appsync.GraphqlApi(stack, 'api', { name: 'api', - schema: appsync.Schema.fromAsset(path.join(__dirname, 'appsync.test.graphql')), + schema: appsync.SchemaFile.fromAsset(path.join(__dirname, 'appsync.test.graphql')), authorizationConfig: { defaultAuthorization: { authorizationType: appsync.AuthorizationType.IAM }, additionalAuthorizationModes: [], @@ -73,7 +73,7 @@ describe('AppSync API Key Authorization', () => { // WHEN new appsync.GraphqlApi(stack, 'api', { name: 'api', - schema: appsync.Schema.fromAsset(path.join(__dirname, 'appsync.test.graphql')), + schema: appsync.SchemaFile.fromAsset(path.join(__dirname, 'appsync.test.graphql')), authorizationConfig: { defaultAuthorization: { authorizationType: appsync.AuthorizationType.IAM }, additionalAuthorizationModes: [{ @@ -96,7 +96,7 @@ describe('AppSync API Key Authorization', () => { // WHEN new appsync.GraphqlApi(stack, 'API', { name: 'apiKeyUnitTest', - schema: appsync.Schema.fromAsset(path.join(__dirname, 'appsync.auth.graphql')), + schema: appsync.SchemaFile.fromAsset(path.join(__dirname, 'appsync.auth.graphql')), authorizationConfig: { defaultAuthorization: { authorizationType: appsync.AuthorizationType.API_KEY, @@ -118,7 +118,7 @@ describe('AppSync API Key Authorization', () => { const when = () => { new appsync.GraphqlApi(stack, 'API', { name: 'apiKeyUnitTest', - schema: appsync.Schema.fromAsset(path.join(__dirname, 'appsync.auth.graphql')), + schema: appsync.SchemaFile.fromAsset(path.join(__dirname, 'appsync.auth.graphql')), authorizationConfig: { defaultAuthorization: { authorizationType: appsync.AuthorizationType.API_KEY, @@ -139,7 +139,7 @@ describe('AppSync API Key Authorization', () => { const when = () => { new appsync.GraphqlApi(stack, 'API', { name: 'apiKeyUnitTest', - schema: appsync.Schema.fromAsset(path.join(__dirname, 'appsync.auth.graphql')), + schema: appsync.SchemaFile.fromAsset(path.join(__dirname, 'appsync.auth.graphql')), authorizationConfig: { defaultAuthorization: { authorizationType: appsync.AuthorizationType.API_KEY, @@ -159,7 +159,7 @@ describe('AppSync API Key Authorization', () => { // WHEN new appsync.GraphqlApi(stack, 'api', { name: 'api', - schema: appsync.Schema.fromAsset(path.join(__dirname, 'appsync.test.graphql')), + schema: appsync.SchemaFile.fromAsset(path.join(__dirname, 'appsync.test.graphql')), authorizationConfig: { defaultAuthorization: { authorizationType: appsync.AuthorizationType.IAM }, additionalAuthorizationModes: [ @@ -186,7 +186,7 @@ describe('AppSync API Key Authorization', () => { expect(() => { new appsync.GraphqlApi(stack, 'api', { name: 'api', - schema: appsync.Schema.fromAsset(path.join(__dirname, 'appsync.test.graphql')), + schema: appsync.SchemaFile.fromAsset(path.join(__dirname, 'appsync.test.graphql')), authorizationConfig: { additionalAuthorizationModes: [{ authorizationType: appsync.AuthorizationType.API_KEY, @@ -201,7 +201,7 @@ describe('AppSync API Key Authorization', () => { expect(() => { new appsync.GraphqlApi(stack, 'api', { name: 'api', - schema: appsync.Schema.fromAsset(path.join(__dirname, 'appsync.test.graphql')), + schema: appsync.SchemaFile.fromAsset(path.join(__dirname, 'appsync.test.graphql')), authorizationConfig: { defaultAuthorization: { authorizationType: appsync.AuthorizationType.API_KEY }, additionalAuthorizationModes: [{ @@ -217,7 +217,7 @@ describe('AppSync API Key Authorization', () => { expect(() => { new appsync.GraphqlApi(stack, 'api', { name: 'api', - schema: appsync.Schema.fromAsset(path.join(__dirname, 'appsync.test.graphql')), + schema: appsync.SchemaFile.fromAsset(path.join(__dirname, 'appsync.test.graphql')), authorizationConfig: { defaultAuthorization: { authorizationType: appsync.AuthorizationType.IAM }, additionalAuthorizationModes: [ @@ -235,7 +235,7 @@ describe('AppSync IAM Authorization', () => { // WHEN new appsync.GraphqlApi(stack, 'api', { name: 'api', - schema: appsync.Schema.fromAsset(path.join(__dirname, 'appsync.test.graphql')), + schema: appsync.SchemaFile.fromAsset(path.join(__dirname, 'appsync.test.graphql')), authorizationConfig: { defaultAuthorization: { authorizationType: appsync.AuthorizationType.IAM }, }, @@ -251,7 +251,7 @@ describe('AppSync IAM Authorization', () => { // WHEN new appsync.GraphqlApi(stack, 'api', { name: 'api', - schema: appsync.Schema.fromAsset(path.join(__dirname, 'appsync.test.graphql')), + schema: appsync.SchemaFile.fromAsset(path.join(__dirname, 'appsync.test.graphql')), authorizationConfig: { additionalAuthorizationModes: [{ authorizationType: appsync.AuthorizationType.IAM }], }, @@ -268,7 +268,7 @@ describe('AppSync IAM Authorization', () => { expect(() => { new appsync.GraphqlApi(stack, 'api', { name: 'api', - schema: appsync.Schema.fromAsset(path.join(__dirname, 'appsync.test.graphql')), + schema: appsync.SchemaFile.fromAsset(path.join(__dirname, 'appsync.test.graphql')), authorizationConfig: { defaultAuthorization: { authorizationType: appsync.AuthorizationType.IAM }, additionalAuthorizationModes: [{ authorizationType: appsync.AuthorizationType.IAM }], @@ -282,7 +282,7 @@ describe('AppSync IAM Authorization', () => { expect(() => { new appsync.GraphqlApi(stack, 'api', { name: 'api', - schema: appsync.Schema.fromAsset(path.join(__dirname, 'appsync.test.graphql')), + schema: appsync.SchemaFile.fromAsset(path.join(__dirname, 'appsync.test.graphql')), authorizationConfig: { additionalAuthorizationModes: [ { authorizationType: appsync.AuthorizationType.IAM }, @@ -303,7 +303,7 @@ describe('AppSync User Pool Authorization', () => { // WHEN new appsync.GraphqlApi(stack, 'api', { name: 'api', - schema: appsync.Schema.fromAsset(path.join(__dirname, 'appsync.test.graphql')), + schema: appsync.SchemaFile.fromAsset(path.join(__dirname, 'appsync.test.graphql')), authorizationConfig: { defaultAuthorization: { authorizationType: appsync.AuthorizationType.USER_POOL, @@ -327,7 +327,7 @@ describe('AppSync User Pool Authorization', () => { // WHEN new appsync.GraphqlApi(stack, 'api', { name: 'api', - schema: appsync.Schema.fromAsset(path.join(__dirname, 'appsync.test.graphql')), + schema: appsync.SchemaFile.fromAsset(path.join(__dirname, 'appsync.test.graphql')), authorizationConfig: { defaultAuthorization: { authorizationType: appsync.AuthorizationType.USER_POOL, @@ -356,7 +356,7 @@ describe('AppSync User Pool Authorization', () => { // WHEN new appsync.GraphqlApi(stack, 'api', { name: 'api', - schema: appsync.Schema.fromAsset(path.join(__dirname, 'appsync.test.graphql')), + schema: appsync.SchemaFile.fromAsset(path.join(__dirname, 'appsync.test.graphql')), authorizationConfig: { additionalAuthorizationModes: [{ authorizationType: appsync.AuthorizationType.USER_POOL, @@ -381,7 +381,7 @@ describe('AppSync User Pool Authorization', () => { // WHEN new appsync.GraphqlApi(stack, 'api', { name: 'api', - schema: appsync.Schema.fromAsset(path.join(__dirname, 'appsync.test.graphql')), + schema: appsync.SchemaFile.fromAsset(path.join(__dirname, 'appsync.test.graphql')), authorizationConfig: { additionalAuthorizationModes: [{ authorizationType: appsync.AuthorizationType.USER_POOL, @@ -411,7 +411,7 @@ describe('AppSync User Pool Authorization', () => { // WHEN new appsync.GraphqlApi(stack, 'api', { name: 'api', - schema: appsync.Schema.fromAsset(path.join(__dirname, 'appsync.test.graphql')), + schema: appsync.SchemaFile.fromAsset(path.join(__dirname, 'appsync.test.graphql')), authorizationConfig: { defaultAuthorization: { authorizationType: appsync.AuthorizationType.USER_POOL, @@ -468,7 +468,7 @@ describe('AppSync OIDC Authorization', () => { // WHEN new appsync.GraphqlApi(stack, 'api', { name: 'api', - schema: appsync.Schema.fromAsset(path.join(__dirname, 'appsync.test.graphql')), + schema: appsync.SchemaFile.fromAsset(path.join(__dirname, 'appsync.test.graphql')), authorizationConfig: { defaultAuthorization: { authorizationType: appsync.AuthorizationType.OIDC, @@ -490,7 +490,7 @@ describe('AppSync OIDC Authorization', () => { // WHEN new appsync.GraphqlApi(stack, 'api', { name: 'api', - schema: appsync.Schema.fromAsset(path.join(__dirname, 'appsync.test.graphql')), + schema: appsync.SchemaFile.fromAsset(path.join(__dirname, 'appsync.test.graphql')), authorizationConfig: { defaultAuthorization: { authorizationType: appsync.AuthorizationType.OIDC, @@ -520,7 +520,7 @@ describe('AppSync OIDC Authorization', () => { // WHEN new appsync.GraphqlApi(stack, 'api', { name: 'api', - schema: appsync.Schema.fromAsset(path.join(__dirname, 'appsync.test.graphql')), + schema: appsync.SchemaFile.fromAsset(path.join(__dirname, 'appsync.test.graphql')), authorizationConfig: { additionalAuthorizationModes: [{ authorizationType: appsync.AuthorizationType.OIDC, @@ -544,7 +544,7 @@ describe('AppSync OIDC Authorization', () => { // WHEN new appsync.GraphqlApi(stack, 'api', { name: 'api', - schema: appsync.Schema.fromAsset(path.join(__dirname, 'appsync.test.graphql')), + schema: appsync.SchemaFile.fromAsset(path.join(__dirname, 'appsync.test.graphql')), authorizationConfig: { additionalAuthorizationModes: [{ authorizationType: appsync.AuthorizationType.OIDC, @@ -576,7 +576,7 @@ describe('AppSync OIDC Authorization', () => { // WHEN new appsync.GraphqlApi(stack, 'api', { name: 'api', - schema: appsync.Schema.fromAsset(path.join(__dirname, 'appsync.test.graphql')), + schema: appsync.SchemaFile.fromAsset(path.join(__dirname, 'appsync.test.graphql')), authorizationConfig: { defaultAuthorization: { authorizationType: appsync.AuthorizationType.OIDC, @@ -647,7 +647,7 @@ describe('AppSync Lambda Authorization', () => { // WHEN new appsync.GraphqlApi(stack, 'api', { name: 'api', - schema: appsync.Schema.fromAsset(path.join(__dirname, 'appsync.test.graphql')), + schema: appsync.SchemaFile.fromAsset(path.join(__dirname, 'appsync.test.graphql')), authorizationConfig: { defaultAuthorization: { authorizationType: appsync.AuthorizationType.LAMBDA, @@ -688,7 +688,7 @@ describe('AppSync Lambda Authorization', () => { // WHEN new appsync.GraphqlApi(stack, 'api', { name: 'api', - schema: appsync.Schema.fromAsset(path.join(__dirname, 'appsync.test.graphql')), + schema: appsync.SchemaFile.fromAsset(path.join(__dirname, 'appsync.test.graphql')), authorizationConfig: { defaultAuthorization: { authorizationType: appsync.AuthorizationType.LAMBDA, @@ -730,7 +730,7 @@ describe('AppSync Lambda Authorization', () => { // WHEN new appsync.GraphqlApi(stack, 'api', { name: 'api', - schema: appsync.Schema.fromAsset(path.join(__dirname, 'appsync.test.graphql')), + schema: appsync.SchemaFile.fromAsset(path.join(__dirname, 'appsync.test.graphql')), authorizationConfig: { additionalAuthorizationModes: [{ authorizationType: appsync.AuthorizationType.LAMBDA, @@ -770,7 +770,7 @@ describe('AppSync Lambda Authorization', () => { // WHEN new appsync.GraphqlApi(stack, 'api', { name: 'api', - schema: appsync.Schema.fromAsset(path.join(__dirname, 'appsync.test.graphql')), + schema: appsync.SchemaFile.fromAsset(path.join(__dirname, 'appsync.test.graphql')), authorizationConfig: { additionalAuthorizationModes: [{ authorizationType: appsync.AuthorizationType.LAMBDA, @@ -813,7 +813,7 @@ describe('AppSync Lambda Authorization', () => { test('Lambda authorization throws with multiple lambda authorization', () => { expect(() => new appsync.GraphqlApi(stack, 'api', { name: 'api', - schema: appsync.Schema.fromAsset(path.join(__dirname, 'appsync.test.graphql')), + schema: appsync.SchemaFile.fromAsset(path.join(__dirname, 'appsync.test.graphql')), authorizationConfig: { defaultAuthorization: { authorizationType: appsync.AuthorizationType.LAMBDA, @@ -836,7 +836,7 @@ describe('AppSync Lambda Authorization', () => { expect(() => new appsync.GraphqlApi(stack, 'api2', { name: 'api', - schema: appsync.Schema.fromAsset(path.join(__dirname, 'appsync.test.graphql')), + schema: appsync.SchemaFile.fromAsset(path.join(__dirname, 'appsync.test.graphql')), authorizationConfig: { defaultAuthorization: { authorizationType: appsync.AuthorizationType.IAM }, additionalAuthorizationModes: [ @@ -864,7 +864,7 @@ describe('AppSync Lambda Authorization', () => { test('throws if authorization type and mode do not match', () => { expect(() => new appsync.GraphqlApi(stack, 'api', { name: 'api', - schema: appsync.Schema.fromAsset(path.join(__dirname, 'appsync.test.graphql')), + schema: appsync.SchemaFile.fromAsset(path.join(__dirname, 'appsync.test.graphql')), authorizationConfig: { defaultAuthorization: { authorizationType: appsync.AuthorizationType.LAMBDA, diff --git a/packages/@aws-cdk/aws-appsync/test/appsync-caching-config.test.ts b/packages/@aws-cdk/aws-appsync/test/appsync-caching-config.test.ts index c012ee8f1f04c..3537c9c91a3ce 100644 --- a/packages/@aws-cdk/aws-appsync/test/appsync-caching-config.test.ts +++ b/packages/@aws-cdk/aws-appsync/test/appsync-caching-config.test.ts @@ -13,7 +13,7 @@ beforeEach(() => { stack = new cdk.Stack(); api = new appsync.GraphqlApi(stack, 'api', { name: 'api', - schema: appsync.Schema.fromAsset(path.join(__dirname, 'appsync.lambda.graphql')), + schema: appsync.SchemaFile.fromAsset(path.join(__dirname, 'appsync.lambda.graphql')), }); }); diff --git a/packages/@aws-cdk/aws-appsync/test/appsync-code-first.test.ts b/packages/@aws-cdk/aws-appsync/test/appsync-code-first.test.ts deleted file mode 100644 index f79e92ab67d35..0000000000000 --- a/packages/@aws-cdk/aws-appsync/test/appsync-code-first.test.ts +++ /dev/null @@ -1,329 +0,0 @@ -import { Template } from '@aws-cdk/assertions'; -import * as cdk from '@aws-cdk/core'; -import * as appsync from '../lib'; -import * as t from './scalar-type-defintions'; - -let stack: cdk.Stack; -beforeEach(() => { - // GIVEN - stack = new cdk.Stack(); -}); - -describe('code-first implementation through GraphQL Api functions`', () => { - let api: appsync.GraphqlApi; - beforeEach(() => { - // GIVEN - api = new appsync.GraphqlApi(stack, 'api', { - name: 'api', - }); - }); - - test('testing addType w/ Interface Type for schema definition mode `code`', () => { - // WHEN - const test = new appsync.InterfaceType('Test', { - definition: { - id: t.id, - lid: t.list_id, - rid: t.required_id, - rlid: t.required_list_id, - rlrid: t.required_list_required_id, - }, - }); - api.addType(test); - test.addField({ fieldName: 'dupid', field: t.dup_id }); - const out = 'interface Test {\n id: ID\n lid: [ID]\n rid: ID!\n rlid: [ID]!\n rlrid: [ID!]!\n dupid: [ID!]!\n}\n'; - - // THEN - Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { - Definition: `${out}`, - }); - }); - - test('testing addType w/ Object Type for schema definition mode `code`', () => { - // WHEN - const test = new appsync.ObjectType('Test', { - definition: { - id: t.id, - lid: t.list_id, - rid: t.required_id, - rlid: t.required_list_id, - rlrid: t.required_list_required_id, - }, - }); - api.addType(test); - test.addField({ fieldName: 'dupid', field: t.dup_id }); - const out = 'type Test {\n id: ID\n lid: [ID]\n rid: ID!\n rlid: [ID]!\n rlrid: [ID!]!\n dupid: [ID!]!\n}\n'; - - // THEN - Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { - Definition: `${out}`, - }); - }); - - test('testing addObjectType for schema definition mode `code`', () => { - // WHEN - api.addType(new appsync.ObjectType('Test', { - definition: { - id: t.id, - lid: t.list_id, - rid: t.required_id, - rlid: t.required_list_id, - rlrid: t.required_list_required_id, - dupid: t.dup_id, - }, - })); - const out = 'type Test {\n id: ID\n lid: [ID]\n rid: ID!\n rlid: [ID]!\n rlrid: [ID!]!\n dupid: [ID!]!\n}\n'; - - // THEN - Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { - Definition: `${out}`, - }); - }); - - test('addField dynamically adds field to schema for ObjectType', () => { - // WHEN - const test = api.addType(new appsync.ObjectType('Test', { - definition: { - id: t.id, - lid: t.list_id, - rid: t.required_id, - rlid: t.required_list_id, - rlrid: t.required_list_required_id, - }, - })); - - test.addField({ fieldName: 'dupid', field: t.dup_id }); - const out = 'type Test {\n id: ID\n lid: [ID]\n rid: ID!\n rlid: [ID]!\n rlrid: [ID!]!\n dupid: [ID!]!\n}\n'; - - // THEN - Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { - Definition: `${out}`, - }); - }); - - test('testing addInterfaceType for schema definition mode `code`', () => { - // WHEN - api.addType(new appsync.InterfaceType('Test', { - definition: { - id: t.id, - lid: t.list_id, - rid: t.required_id, - rlid: t.required_list_id, - rlrid: t.required_list_required_id, - dupid: t.dup_id, - }, - })); - const out = 'interface Test {\n id: ID\n lid: [ID]\n rid: ID!\n rlid: [ID]!\n rlrid: [ID!]!\n dupid: [ID!]!\n}\n'; - - // THEN - Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { - Definition: `${out}`, - }); - }); - - test('addField dynamically adds field to schema for InterfaceType', () => { - // WHEN - const test = api.addType(new appsync.InterfaceType('Test', { - definition: { - id: t.id, - lid: t.list_id, - rid: t.required_id, - rlid: t.required_list_id, - rlrid: t.required_list_required_id, - }, - })); - - test.addField({ fieldName: 'dupid', field: t.dup_id }); - const out = 'interface Test {\n id: ID\n lid: [ID]\n rid: ID!\n rlid: [ID]!\n rlrid: [ID!]!\n dupid: [ID!]!\n}\n'; - - // THEN - Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { - Definition: `${out}`, - }); - }); - - test('addSubscription allows for adding fields but not resolvable fields', () => { - const ds = api.addNoneDataSource('DS'); - - // WHEN - api.addMutation('addId', new appsync.ResolvableField({ - returnType: t.required_id, - args: { id: t.required_id }, - dataSource: ds, - })); - api.addSubscription('addedId', new appsync.Field({ - returnType: t.required_id, - args: { id: t.required_id }, - directives: [appsync.Directive.subscribe('addId')], - })); - - const schemaDef = 'schema {\n mutation: Mutation\n subscription: Subscription\n}\n'; - const mutationDef = 'type Mutation {\n addId(id: ID!): ID!\n}\n'; - const subscriptionDef = 'type Subscription {\n addedId(id: ID!): ID!\n @aws_subscribe(mutations: ["addId"])\n}\n'; - - // THEN - Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { - Definition: `${schemaDef}${mutationDef}${subscriptionDef}`, - }); - }); -}); - -describe('code-first implementation through Schema functions`', () => { - let schema: appsync.Schema; - beforeEach(() => { - // GIVEN - schema = new appsync.Schema(); - }); - - test('testing addType w/ Interface Type for schema definition mode `code`', () => { - // WHEN - const test = new appsync.InterfaceType('Test', { - definition: { - id: t.id, - lid: t.list_id, - rid: t.required_id, - rlid: t.required_list_id, - rlrid: t.required_list_required_id, - }, - }); - schema.addType(test); - test.addField({ fieldName: 'dupid', field: t.dup_id }); - - new appsync.GraphqlApi(stack, 'api', { - name: 'api', - schema, - }); - const out = 'interface Test {\n id: ID\n lid: [ID]\n rid: ID!\n rlid: [ID]!\n rlrid: [ID!]!\n dupid: [ID!]!\n}\n'; - - // THEN - Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { - Definition: `${out}`, - }); - }); - - test('testing addType w/ Object Type for schema definition mode `code`', () => { - // WHEN - const test = new appsync.ObjectType('Test', { - definition: { - id: t.id, - lid: t.list_id, - rid: t.required_id, - rlid: t.required_list_id, - rlrid: t.required_list_required_id, - }, - }); - schema.addType(test); - test.addField({ fieldName: 'dupid', field: t.dup_id }); - - new appsync.GraphqlApi(stack, 'api', { - name: 'api', - schema, - }); - const out = 'type Test {\n id: ID\n lid: [ID]\n rid: ID!\n rlid: [ID]!\n rlrid: [ID!]!\n dupid: [ID!]!\n}\n'; - - // THEN - Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { - Definition: `${out}`, - }); - }); - - test('testing addObjectType for schema definition mode `code`', () => { - // WHEN - schema.addType(new appsync.ObjectType('Test', { - definition: { - id: t.id, - lid: t.list_id, - rid: t.required_id, - rlid: t.required_list_id, - rlrid: t.required_list_required_id, - dupid: t.dup_id, - }, - })); - - new appsync.GraphqlApi(stack, 'api', { - name: 'api', - schema, - }); - - const out = 'type Test {\n id: ID\n lid: [ID]\n rid: ID!\n rlid: [ID]!\n rlrid: [ID!]!\n dupid: [ID!]!\n}\n'; - - // THEN - Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { - Definition: `${out}`, - }); - }); - - test('schema.addField dynamically adds field to schema for ObjectType', () => { - // WHEN - const test = schema.addType(new appsync.ObjectType('Test', { - definition: { - id: t.id, - lid: t.list_id, - rid: t.required_id, - rlid: t.required_list_id, - rlrid: t.required_list_required_id, - }, - })); - - test.addField({ fieldName: 'dupid', field: t.dup_id }); - new appsync.GraphqlApi(stack, 'api', { - name: 'api', - schema, - }); - const out = 'type Test {\n id: ID\n lid: [ID]\n rid: ID!\n rlid: [ID]!\n rlrid: [ID!]!\n dupid: [ID!]!\n}\n'; - - // THEN - Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { - Definition: `${out}`, - }); - }); - - test('testing addInterfaceType for schema definition mode `code`', () => { - // WHEN - schema.addType(new appsync.InterfaceType('Test', { - definition: { - id: t.id, - lid: t.list_id, - rid: t.required_id, - rlid: t.required_list_id, - rlrid: t.required_list_required_id, - dupid: t.dup_id, - }, - })); - new appsync.GraphqlApi(stack, 'api', { - name: 'api', - schema, - }); - const out = 'interface Test {\n id: ID\n lid: [ID]\n rid: ID!\n rlid: [ID]!\n rlrid: [ID!]!\n dupid: [ID!]!\n}\n'; - - // THEN - Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { - Definition: `${out}`, - }); - }); - - test('schema addField dynamically adds field to schema for InterfaceType', () => { - // WHEN - const test = schema.addType(new appsync.InterfaceType('Test', { - definition: { - id: t.id, - lid: t.list_id, - rid: t.required_id, - rlid: t.required_list_id, - rlrid: t.required_list_required_id, - }, - })); - - test.addField({ fieldName: 'dupid', field: t.dup_id }); - new appsync.GraphqlApi(stack, 'api', { - name: 'api', - schema, - }); - const out = 'interface Test {\n id: ID\n lid: [ID]\n rid: ID!\n rlid: [ID]!\n rlrid: [ID!]!\n dupid: [ID!]!\n}\n'; - - // THEN - Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { - Definition: `${out}`, - }); - }); -}); diff --git a/packages/@aws-cdk/aws-appsync/test/appsync-directives.test.ts b/packages/@aws-cdk/aws-appsync/test/appsync-directives.test.ts deleted file mode 100644 index de2ce5d864813..0000000000000 --- a/packages/@aws-cdk/aws-appsync/test/appsync-directives.test.ts +++ /dev/null @@ -1,140 +0,0 @@ -import { Template } from '@aws-cdk/assertions'; -import * as cognito from '@aws-cdk/aws-cognito'; -import * as cdk from '@aws-cdk/core'; -import * as appsync from '../lib'; -import * as t from './scalar-type-defintions'; - -const iam = [appsync.Directive.iam()]; -const apiKey = [appsync.Directive.apiKey()]; -const oidc = [appsync.Directive.oidc()]; -const cognito_default = [appsync.Directive.cognito('test', 'test2')]; -const cognito_additional = [appsync.Directive.cognito('test', 'test2')]; -const custom = [appsync.Directive.custom('custom')]; - -const generateField = (directives: appsync.Directive[]): appsync.Field => { - return new appsync.Field({ - returnType: t.string, - directives, - }); -}; - -const generateRField = (directives: appsync.Directive[]): appsync.ResolvableField => { - return new appsync.ResolvableField({ - returnType: t.string, - directives, - }); -}; - -let stack: cdk.Stack; - -let api_apiKey: appsync.GraphqlApi, api_iam: appsync.GraphqlApi, api_oidc: appsync.GraphqlApi, - api_auth: appsync.GraphqlApi, api_cognito: appsync.GraphqlApi; -beforeEach(() => { - // GIVEN - stack = new cdk.Stack(); - const userPool = new cognito.UserPool(stack, 'userpool'); - api_apiKey = new appsync.GraphqlApi(stack, 'api_apiKey', { - name: 'api', - }); - api_iam = new appsync.GraphqlApi(stack, 'api_iam', { - name: 'api', - authorizationConfig: { - defaultAuthorization: { - authorizationType: appsync.AuthorizationType.IAM, - }, - }, - }); - api_oidc = new appsync.GraphqlApi(stack, 'api_oidc', { - name: 'api', - authorizationConfig: { - defaultAuthorization: { - authorizationType: appsync.AuthorizationType.OIDC, - openIdConnectConfig: { oidcProvider: 'test' }, - }, - }, - }); - api_auth = new appsync.GraphqlApi(stack, 'api_cognito_default', { - name: 'api', - authorizationConfig: { - defaultAuthorization: { - authorizationType: appsync.AuthorizationType.USER_POOL, - userPoolConfig: { userPool }, - }, - }, - }); - api_cognito = new appsync.GraphqlApi(stack, 'api_cognito_additional', { - name: 'api', - authorizationConfig: { - additionalAuthorizationModes: [ - { - authorizationType: appsync.AuthorizationType.USER_POOL, - userPoolConfig: { userPool }, - }, - ], - }, - }); -}); - -const testObjectType = (IApi: appsync.GraphqlApi, directives: appsync.Directive[], tag: string): any => { - // WHEN - IApi.addType(new appsync.ObjectType('Test', { - definition: { - field: generateField(directives), - rfield: generateRField(directives), - }, - directives: directives, - })); - // THEN - Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { - Definition: `type Test ${tag} {\n field: String\n ${tag}\n rfield: String\n ${tag}\n}\n`, - }); -}; - -const testInterfaceType = (IApi: appsync.GraphqlApi, directives: appsync.Directive[], tag: string): any => { - // WHEN - IApi.addType(new appsync.InterfaceType('Test', { - definition: { - field: generateField(directives), - rfield: generateRField(directives), - }, - directives: directives, - })); - // THEN - Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { - Definition: `interface Test ${tag} {\n field: String\n ${tag}\n rfield: String\n ${tag}\n}\n`, - }); -}; - -describe('Basic Testing of Directives for Code-First', () => { - test('Iam directive configures in Object Type', () => { testObjectType(api_iam, iam, '@aws_iam'); }); - - test('Iam directive configures in Interface Type', () => { testInterfaceType(api_iam, iam, '@aws_iam'); }); - - test('Api Key directive configures in Object Type', () => { testObjectType(api_apiKey, apiKey, '@aws_api_key'); }); - - test('Api Key directive configures in Interface Type', () => { testInterfaceType(api_apiKey, apiKey, '@aws_api_key'); }); - - test('OIDC directive configures in Object Type', () => { testObjectType(api_oidc, oidc, '@aws_oidc'); }); - - test('OIDC directive configures in Interface Type', () => { testInterfaceType(api_oidc, oidc, '@aws_oidc'); }); - - test('Cognito as default directive configures in Object Type', () => { - testObjectType(api_auth, cognito_default, '@aws_auth(cognito_groups: ["test", "test2"])'); - }); - - test('Cognito as default directive configures in Interface Type', () => { - testInterfaceType(api_auth, cognito_default, '@aws_auth(cognito_groups: ["test", "test2"])'); - }); - - test('Cognito as additional directive configures in Object Type', () => { - testObjectType(api_cognito, cognito_additional, '@aws_cognito_user_pools(cognito_groups: ["test", "test2"])'); - }); - - test('Custom directive configures in Object Type', () => { - testObjectType(api_cognito, custom, 'custom'); - }); - - test('Custom directive configures in Interface Type', () => { - testInterfaceType(api_cognito, custom, 'custom'); - }); -}); \ No newline at end of file diff --git a/packages/@aws-cdk/aws-appsync/test/appsync-domain.test.ts b/packages/@aws-cdk/aws-appsync/test/appsync-domain.test.ts index ddc3041670fa0..aac7539679b4a 100644 --- a/packages/@aws-cdk/aws-appsync/test/appsync-domain.test.ts +++ b/packages/@aws-cdk/aws-appsync/test/appsync-domain.test.ts @@ -20,7 +20,7 @@ describe('Tests of AppSync Domain Name', () => { test('DomainNameAssociation depends on DomainName construct', () => { new appsync.GraphqlApi(stack, 'baseApi', { name: 'api', - schema: appsync.Schema.fromAsset( + schema: appsync.SchemaFile.fromAsset( path.join(__dirname, 'appsync.test.graphql'), ), domainName: { @@ -44,7 +44,7 @@ describe('Tests of AppSync Domain Name', () => { test('appSyncDomainName exposes the domain of the associated AWS::AppSync::DomainName', () => { const api = new appsync.GraphqlApi(stack, 'baseApi', { name: 'api', - schema: appsync.Schema.fromAsset( + schema: appsync.SchemaFile.fromAsset( path.join(__dirname, 'appsync.test.graphql'), ), domainName: { @@ -59,7 +59,7 @@ describe('Tests of AppSync Domain Name', () => { test('appSyncDomainName should throw an error when no custom domain has been configured', () => { const api = new appsync.GraphqlApi(stack, 'baseApi', { name: 'api', - schema: appsync.Schema.fromAsset( + schema: appsync.SchemaFile.fromAsset( path.join(__dirname, 'appsync.test.graphql'), ), }); diff --git a/packages/@aws-cdk/aws-appsync/test/appsync-dynamodb.test.ts b/packages/@aws-cdk/aws-appsync/test/appsync-dynamodb.test.ts index 35ddd4e3cbb24..d49dfffa61ffa 100644 --- a/packages/@aws-cdk/aws-appsync/test/appsync-dynamodb.test.ts +++ b/packages/@aws-cdk/aws-appsync/test/appsync-dynamodb.test.ts @@ -16,7 +16,7 @@ beforeEach(() => { stack = new cdk.Stack(); api = new appsync.GraphqlApi(stack, 'baseApi', { name: 'api', - schema: appsync.Schema.fromAsset(path.join(__dirname, 'appsync.test.graphql')), + schema: appsync.SchemaFile.fromAsset(path.join(__dirname, 'appsync.test.graphql')), }); }); diff --git a/packages/@aws-cdk/aws-appsync/test/appsync-elasticsearch.test.ts b/packages/@aws-cdk/aws-appsync/test/appsync-elasticsearch.test.ts index c6049ba4b3baa..86dbf19885546 100644 --- a/packages/@aws-cdk/aws-appsync/test/appsync-elasticsearch.test.ts +++ b/packages/@aws-cdk/aws-appsync/test/appsync-elasticsearch.test.ts @@ -15,7 +15,7 @@ describeDeprecated('Appsync Elasticsearch integration', () => { stack = new cdk.Stack(); api = new appsync.GraphqlApi(stack, 'baseApi', { name: 'api', - schema: appsync.Schema.fromAsset(path.join(__dirname, 'appsync.test.graphql')), + schema: appsync.SchemaFile.fromAsset(path.join(__dirname, 'appsync.test.graphql')), }); domain = new es.Domain(stack, 'EsDomain', { version: es.ElasticsearchVersion.V7_10, diff --git a/packages/@aws-cdk/aws-appsync/test/appsync-enum-type.test.ts b/packages/@aws-cdk/aws-appsync/test/appsync-enum-type.test.ts deleted file mode 100644 index a04e9a5c89d82..0000000000000 --- a/packages/@aws-cdk/aws-appsync/test/appsync-enum-type.test.ts +++ /dev/null @@ -1,106 +0,0 @@ -import { Template } from '@aws-cdk/assertions'; -import * as cdk from '@aws-cdk/core'; -import * as appsync from '../lib'; -import * as t from './scalar-type-defintions'; - -const out = 'enum Test {\n test1\n test2\n test3\n}\n'; -let stack: cdk.Stack; -let api: appsync.GraphqlApi; -beforeEach(() => { - // GIVEN - stack = new cdk.Stack(); - api = new appsync.GraphqlApi(stack, 'api', { - name: 'api', - }); -}); - -describe('testing Enum Type properties', () => { - test('EnumType configures properly', () => { - // WHEN - const test = new appsync.EnumType('Test', { - definition: ['test1', 'test2', 'test3'], - }); - api.addType(test); - - // THEN - Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { - Definition: `${out}`, - }); - Template.fromStack(stack).resourceCountIs('AWS::AppSync::Resolver', 0); - }); - - test('EnumType can addField', () => { - // WHEN - const test = new appsync.EnumType('Test', { - definition: ['test1', 'test2'], - }); - api.addType(test); - test.addField({ fieldName: 'test3' }); - - // THEN - Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { - Definition: `${out}`, - }); - }); - - test('EnumType can be a GraphqlType', () => { - // WHEN - const test = new appsync.EnumType('Test', { - definition: ['test1', 'test2', 'test3'], - }); - api.addType(test); - - api.addType(new appsync.ObjectType('Test2', { - definition: { enum: test.attribute() }, - })); - - const obj = 'type Test2 {\n enum: Test\n}\n'; - - // THEN - Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { - Definition: `${out}${obj}`, - }); - }); - - test('errors when enum type is configured with white space', () => { - // THEN - expect(() => { - new appsync.EnumType('Test', { - definition: ['test 1', 'test2', 'test3'], - }); - }).toThrowError('Enum Type values cannot have whitespace. Received: test 1'); - }); - - test('errors when the fieldName in addField has white space', () => { - // WHEN - const test = new appsync.EnumType('Test', { - definition: [], - }); - // THEN - expect(() => { - test.addField({ fieldName: ' ' }); - }).toThrowError('Enum Type values cannot have whitespace. Received: '); - }); - - test('errors when enum type is configured with field options', () => { - // WHEN - const test = new appsync.EnumType('Test', { - definition: [], - }); - // THEN - expect(() => { - test.addField({ fieldName: 'test', field: t.string }); - }).toThrowError('Enum Type fields consist of strings. Use the fieldName option instead of the field option.'); - }); - - test('errors when enum type is missing fieldName option', () => { - // WHEN - const test = new appsync.EnumType('Test', { - definition: [], - }); - // THEN - expect(() => { - test.addField({}); - }).toThrowError('When adding a field to an Enum Type, you must configure the fieldName option.'); - }); -}); \ No newline at end of file diff --git a/packages/@aws-cdk/aws-appsync/test/appsync-grant.test.ts b/packages/@aws-cdk/aws-appsync/test/appsync-grant.test.ts index fb23df6e8ec74..0b95a93bc9947 100644 --- a/packages/@aws-cdk/aws-appsync/test/appsync-grant.test.ts +++ b/packages/@aws-cdk/aws-appsync/test/appsync-grant.test.ts @@ -15,7 +15,7 @@ beforeEach(() => { }); api = new appsync.GraphqlApi(stack, 'API', { name: 'demo', - schema: appsync.Schema.fromAsset(join(__dirname, 'appsync.test.graphql')), + schema: appsync.SchemaFile.fromAsset(join(__dirname, 'appsync.test.graphql')), authorizationConfig: { defaultAuthorization: { authorizationType: appsync.AuthorizationType.IAM, diff --git a/packages/@aws-cdk/aws-appsync/test/appsync-http.test.ts b/packages/@aws-cdk/aws-appsync/test/appsync-http.test.ts index 2f380b028c592..655527a414a82 100644 --- a/packages/@aws-cdk/aws-appsync/test/appsync-http.test.ts +++ b/packages/@aws-cdk/aws-appsync/test/appsync-http.test.ts @@ -12,7 +12,7 @@ beforeEach(() => { stack = new cdk.Stack(); api = new appsync.GraphqlApi(stack, 'baseApi', { name: 'api', - schema: appsync.Schema.fromAsset(path.join(__dirname, 'appsync.test.graphql')), + schema: appsync.SchemaFile.fromAsset(path.join(__dirname, 'appsync.test.graphql')), }); endpoint = 'aws.amazon.com'; }); diff --git a/packages/@aws-cdk/aws-appsync/test/appsync-input-types.test.ts b/packages/@aws-cdk/aws-appsync/test/appsync-input-types.test.ts deleted file mode 100644 index f58196e43cd31..0000000000000 --- a/packages/@aws-cdk/aws-appsync/test/appsync-input-types.test.ts +++ /dev/null @@ -1,95 +0,0 @@ -import { Template } from '@aws-cdk/assertions'; -import * as cdk from '@aws-cdk/core'; -import * as appsync from '../lib'; -import * as t from './scalar-type-defintions'; - -const out = 'input Test {\n test: String\n}\n'; -let stack: cdk.Stack; -let api: appsync.GraphqlApi; -beforeEach(() => { - // GIVEN - stack = new cdk.Stack(); - api = new appsync.GraphqlApi(stack, 'api', { - name: 'api', - }); -}); - -describe('testing Input Type properties', () => { - test('InputType configures properly', () => { - // WHEN - const test = new appsync.InputType('Test', { - definition: { test: t.string }, - }); - api.addType(test); - - // THEN - Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { - Definition: `${out}`, - }); - Template.fromStack(stack).resourceCountIs('AWS::AppSync::Resolver', 0); - }); - - test('InputType can addField', () => { - // WHEN - const test = new appsync.InputType('Test', { definition: {} }); - api.addType(test); - test.addField({ fieldName: 'test', field: t.string }); - - // THEN - Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { - Definition: `${out}`, - }); - }); - - test('appsync fails addField with InputType missing fieldName', () => { - // WHEN - const test = new appsync.InputType('Test', { definition: {} }); - api.addType(test); - - // THEN - expect(() => { - test.addField({ fieldName: 'test' }); - }).toThrowError('Input Types must have both fieldName and field options.'); - }); - - test('appsync fails addField with InputType missing field', () => { - // WHEN - const test = new appsync.InputType('Test', { definition: {} }); - api.addType(test); - - // THEN - expect(() => { - test.addField({ field: t.string }); - }).toThrowError('Input Types must have both fieldName and field options.'); - }); - - test('appsync fails addField with InputType missing both fieldName and field options', () => { - // WHEN - const test = new appsync.InputType('Test', { definition: {} }); - api.addType(test); - - // THEN - expect(() => { - test.addField({}); - }).toThrowError('Input Types must have both fieldName and field options.'); - }); - - test('InputType can be a GraphqlType', () => { - // WHEN - const test = new appsync.InputType('Test', { - definition: { test: t.string }, - }); - api.addType(test); - - api.addType(new appsync.ObjectType('Test2', { - definition: { input: test.attribute() }, - })); - - const obj = 'type Test2 {\n input: Test\n}\n'; - - // THEN - Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { - Definition: `${out}${obj}`, - }); - }); -}); \ No newline at end of file diff --git a/packages/@aws-cdk/aws-appsync/test/appsync-interface-type.test.ts b/packages/@aws-cdk/aws-appsync/test/appsync-interface-type.test.ts deleted file mode 100644 index f94400fab6ea3..0000000000000 --- a/packages/@aws-cdk/aws-appsync/test/appsync-interface-type.test.ts +++ /dev/null @@ -1,174 +0,0 @@ -import { Template } from '@aws-cdk/assertions'; -import * as cdk from '@aws-cdk/core'; -import * as appsync from '../lib'; -import * as t from './scalar-type-defintions'; - -let stack: cdk.Stack; -let api: appsync.GraphqlApi; -beforeEach(() => { - // GIVEN - stack = new cdk.Stack(); - api = new appsync.GraphqlApi(stack, 'api', { - name: 'api', - }); -}); - -describe('testing InterfaceType properties', () => { - let baseTest: appsync.InterfaceType; - beforeEach(()=>{ - baseTest = new appsync.InterfaceType('baseTest', { - definition: { - id: t.id, - }, - }); - }); - test('basic InterfaceType produces correct schema', () => { - // WHEN - api.addToSchema(baseTest.toString()); - const out = 'interface baseTest {\n id: ID\n}\n'; - - // THEN - Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { - Definition: `${out}`, - }); - }); - - test('InterfaceType fields can have arguments', () => { - // WHEN - baseTest.addField({ - fieldName: 'test', - field: new appsync.Field({ - returnType: t.string, - args: { success: t.int }, - }), - }); - api.addToSchema(baseTest.toString()); - const out = 'interface baseTest {\n id: ID\n test(success: Int): String\n}\n'; - - // THEN - Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { - Definition: `${out}`, - }); - }); - - test('InterfaceType fields will not produce resolvers', () => { - // WHEN - baseTest.addField({ - fieldName: 'test', - field: new appsync.ResolvableField({ - returnType: t.string, - args: { success: t.int }, - dataSource: api.addNoneDataSource('none'), - }), - }); - api.addToSchema(baseTest.toString()); - const out = 'interface baseTest {\n id: ID\n test(success: Int): String\n}\n'; - - // THEN - Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { - Definition: `${out}`, - }); - Template.fromStack(stack).resourceCountIs('AWS::AppSync::Resolver', 0); - }); - - test('Interface Type can be a Graphql Type', () => { - // WHEN - const graphqlType = baseTest.attribute(); - - const test = new appsync.ObjectType('Test', { - definition: { - test: graphqlType, - }, - }); - api.addToSchema(test.toString()); - const out = 'type Test {\n test: baseTest\n}\n'; - - // THEN - Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { - Definition: `${out}`, - }); - }); - - test('Interface Type can generate Fields with Directives', () => { - // WHEN - const test = new appsync.InterfaceType('Test', { - definition: { - test: t.string, - }, - }); - test.addField({ - fieldName: 'resolve', - field: new appsync.Field({ - returnType: t.string, - directives: [appsync.Directive.apiKey()], - }), - }); - - api.addType(test); - const out = 'interface Test {\n test: String\n resolve: String\n @aws_api_key\n}\n'; - - // THEN - Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { - Definition: `${out}`, - }); - }); - - test('Interface Type can generate ResolvableFields with Directives, but not the resolver', () => { - // WHEN - const test = new appsync.InterfaceType('Test', { - definition: { - test: t.string, - }, - }); - test.addField({ - fieldName: 'resolve', - field: new appsync.ResolvableField({ - returnType: t.string, - directives: [appsync.Directive.apiKey()], - dataSource: api.addNoneDataSource('none'), - }), - }); - - api.addType(test); - const out = 'interface Test {\n test: String\n resolve: String\n @aws_api_key\n}\n'; - - // THEN - Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { - Definition: `${out}`, - }); - Template.fromStack(stack).resourceCountIs('AWS::AppSync::Resolver', 0); - }); - - test('appsync fails addField with InterfaceType missing fieldName', () => { - // WHEN - const test = new appsync.InterfaceType('Test', { definition: {} }); - api.addType(test); - - // THEN - expect(() => { - test.addField({ fieldName: 'test' }); - }).toThrowError('Interface Types must have both fieldName and field options.'); - }); - - test('appsync fails addField with InterfaceType missing field', () => { - // WHEN - const test = new appsync.InterfaceType('Test', { definition: {} }); - api.addType(test); - - // THEN - expect(() => { - test.addField({ field: t.string }); - }).toThrowError('Interface Types must have both fieldName and field options.'); - }); - - test('appsync fails addField with InterfaceType missing both fieldName and field options', () => { - // WHEN - const test = new appsync.InterfaceType('Test', { definition: {} }); - api.addType(test); - - // THEN - expect(() => { - test.addField({}); - }).toThrowError('Interface Types must have both fieldName and field options.'); - }); -}); \ No newline at end of file diff --git a/packages/@aws-cdk/aws-appsync/test/appsync-lambda.test.ts b/packages/@aws-cdk/aws-appsync/test/appsync-lambda.test.ts index 3db68304b8c9f..702c85ab928a4 100644 --- a/packages/@aws-cdk/aws-appsync/test/appsync-lambda.test.ts +++ b/packages/@aws-cdk/aws-appsync/test/appsync-lambda.test.ts @@ -11,7 +11,7 @@ beforeEach(() => { stack = new cdk.Stack(); api = new appsync.GraphqlApi(stack, 'baseApi', { name: 'api', - schema: appsync.Schema.fromAsset(path.join(__dirname, 'appsync.test.graphql')), + schema: appsync.SchemaFile.fromAsset(path.join(__dirname, 'appsync.test.graphql')), }); }); @@ -73,7 +73,7 @@ describe('Lambda Data Source configuration', () => { const newStack = new cdk.Stack(); const graphqlapi = new appsync.GraphqlApi(newStack, 'baseApi', { name: 'api', - schema: appsync.Schema.fromAsset(path.join(__dirname, 'appsync.test.graphql')), + schema: appsync.SchemaFile.fromAsset(path.join(__dirname, 'appsync.test.graphql')), }); const dummyFunction = new lambda.Function(newStack, 'func', { code: lambda.Code.fromAsset(path.join(__dirname, 'verify/iam-query')), diff --git a/packages/@aws-cdk/aws-appsync/test/appsync-mapping-template.test.ts b/packages/@aws-cdk/aws-appsync/test/appsync-mapping-template.test.ts index b01403a7ba9fc..67ab1b05fd54c 100644 --- a/packages/@aws-cdk/aws-appsync/test/appsync-mapping-template.test.ts +++ b/packages/@aws-cdk/aws-appsync/test/appsync-mapping-template.test.ts @@ -12,7 +12,7 @@ beforeEach(() => { stack = new cdk.Stack(); api = new appsync.GraphqlApi(stack, 'api', { name: 'api', - schema: appsync.Schema.fromAsset(path.join(__dirname, 'appsync.lambda.graphql')), + schema: appsync.SchemaFile.fromAsset(path.join(__dirname, 'appsync.lambda.graphql')), }); }); diff --git a/packages/@aws-cdk/aws-appsync/test/appsync-none.test.ts b/packages/@aws-cdk/aws-appsync/test/appsync-none.test.ts index cbe768f095f26..caf9aaa090561 100644 --- a/packages/@aws-cdk/aws-appsync/test/appsync-none.test.ts +++ b/packages/@aws-cdk/aws-appsync/test/appsync-none.test.ts @@ -10,7 +10,7 @@ beforeEach(() => { stack = new cdk.Stack(); api = new appsync.GraphqlApi(stack, 'baseApi', { name: 'api', - schema: appsync.Schema.fromAsset(path.join(__dirname, 'appsync.test.graphql')), + schema: appsync.SchemaFile.fromAsset(path.join(__dirname, 'appsync.test.graphql')), }); }); diff --git a/packages/@aws-cdk/aws-appsync/test/appsync-object-type.test.ts b/packages/@aws-cdk/aws-appsync/test/appsync-object-type.test.ts deleted file mode 100644 index 4180ec9d30dad..0000000000000 --- a/packages/@aws-cdk/aws-appsync/test/appsync-object-type.test.ts +++ /dev/null @@ -1,295 +0,0 @@ -import { Template } from '@aws-cdk/assertions'; -import * as cdk from '@aws-cdk/core'; -import * as appsync from '../lib'; -import * as t from './scalar-type-defintions'; - -let stack: cdk.Stack; -let api: appsync.GraphqlApi; -beforeEach(() => { - // GIVEN - stack = new cdk.Stack(); - api = new appsync.GraphqlApi(stack, 'api', { - name: 'api', - }); -}); - -describe('testing Object Type properties', () => { - test('ObjectType can implement from interface types', () => { - // WHEN - const baseTest = new appsync.InterfaceType('baseTest', { - definition: { - id: t.id, - }, - }); - const objectTest = new appsync.ObjectType('objectTest', { - interfaceTypes: [baseTest], - definition: { - id2: t.id, - }, - directives: [appsync.Directive.custom('@test')], - }); - - api.addType(baseTest); - api.addType(objectTest); - const gql_interface = 'interface baseTest {\n id: ID\n}\n'; - const gql_object = 'type objectTest implements baseTest @test {\n id2: ID\n id: ID\n}\n'; - const out = `${gql_interface}${gql_object}`; - - // THEN - Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { - Definition: `${out}`, - }); - }); - - test('ObjectType can implement from multiple interface types', () => { - // WHEN - const baseTest = new appsync.InterfaceType('baseTest', { - definition: { id: t.id }, - }); - const anotherTest = new appsync.InterfaceType('anotherTest', { - definition: { id2: t.id }, - }); - const objectTest = new appsync.ObjectType('objectTest', { - interfaceTypes: [anotherTest, baseTest], - definition: { - id3: t.id, - }, - }); - - api.addType(baseTest); - api.addType(anotherTest); - api.addType(objectTest); - - const gql_interface = 'interface baseTest {\n id: ID\n}\ninterface anotherTest {\n id2: ID\n}\n'; - const gql_object = 'type objectTest implements anotherTest & baseTest {\n id3: ID\n id2: ID\n id: ID\n}\n'; - const out = `${gql_interface}${gql_object}`; - - // THEN - Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { - Definition: `${out}`, - }); - }); - - test('Object Type can be a Graphql Type', () => { - // WHEN - const baseTest = new appsync.ObjectType('baseTest', { - definition: { - id: t.id, - }, - }); - const graphqlType = baseTest.attribute(); - const test = new appsync.ObjectType('Test', { - definition: { - test: graphqlType, - }, - }); - api.addType(test); - const out = 'type Test {\n test: baseTest\n}\n'; - - // THEN - Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { - Definition: `${out}`, - }); - }); - - test('Object Type can implement Resolvable Field in definition', () => { - // WHEN - const field = new appsync.ResolvableField({ - returnType: t.string, - dataSource: api.addNoneDataSource('none'), - args: { - arg: t.int, - }, - - }); - const test = new appsync.ObjectType('Test', { - definition: { - test: t.string, - resolve: field, - }, - }); - api.addType(test); - const out = 'type Test {\n test: String\n resolve(arg: Int): String\n}\n'; - - // THEN - Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { - Definition: `${out}`, - }); - }); - - test('Object Type can implement Resolvable Field from GraphqlType', () => { - // WHEN - const field = new appsync.ResolvableField({ - returnType: t.string, - dataSource: api.addNoneDataSource('none'), - args: { - arg: t.int, - }, - - }); - const test = new appsync.ObjectType('Test', { - definition: { - test: t.string, - resolve: field, - }, - }); - api.addType(test); - const out = 'type Test {\n test: String\n resolve(arg: Int): String\n}\n'; - - // THEN - Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { - Definition: `${out}`, - }); - }); - - test('Object Type can implement Resolvable Field for pipelineResolvers', () => { - // WHEN - const ds = api.addNoneDataSource('none'); - const test1 = ds.createFunction({ - name: 'test1', - }); - const test2 = ds.createFunction({ - name: 'test2', - }); - const test = new appsync.ObjectType('Test', { - definition: { - resolve: new appsync.ResolvableField({ - returnType: t.string, - args: { - arg: t.int, - }, - pipelineConfig: [test1, test2], - requestMappingTemplate: appsync.MappingTemplate.fromString(JSON.stringify({ - version: '2017-02-28', - })), - responseMappingTemplate: appsync.MappingTemplate.fromString(JSON.stringify({ - version: 'v1', - })), - }), - }, - }); - api.addType(test); - - // THEN - Template.fromStack(stack).hasResourceProperties('AWS::AppSync::Resolver', { - Kind: 'PIPELINE', - PipelineConfig: { - Functions: [ - { 'Fn::GetAtt': ['apinonetest1FunctionEF63046F', 'FunctionId'] }, - { 'Fn::GetAtt': ['apinonetest2Function615111D0', 'FunctionId'] }, - ], - }, - }); - }); - - test('Object Type can dynamically add Fields', () => { - // WHEN - const field = new appsync.ResolvableField({ - returnType: t.string, - dataSource: api.addNoneDataSource('none'), - args: { arg: t.int }, - - }); - const test = new appsync.ObjectType('Test', { - definition: { - test: t.string, - }, - }); - test.addField({ fieldName: 'resolve', field }); - test.addField({ fieldName: 'dynamic', field: t.string }); - - api.addType(test); - const out = 'type Test {\n test: String\n resolve(arg: Int): String\n dynamic: String\n}\n'; - - // THEN - Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { - Definition: `${out}`, - }); - Template.fromStack(stack).resourceCountIs('AWS::AppSync::Resolver', 1); - }); - - test('Object Type can generate Fields with Directives', () => { - // WHEN - const test = new appsync.ObjectType('Test', { - definition: { - test: t.string, - }, - }); - test.addField({ - fieldName: 'resolve', - field: new appsync.Field({ - returnType: t.string, - directives: [appsync.Directive.apiKey()], - }), - }); - - api.addType(test); - const out = 'type Test {\n test: String\n resolve: String\n @aws_api_key\n}\n'; - - // THEN - Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { - Definition: `${out}`, - }); - }); - - test('Object Type can generate ResolvableFields with Directives', () => { - // WHEN - const test = new appsync.ObjectType('Test', { - definition: { - test: t.string, - }, - }); - const field = new appsync.ResolvableField({ - returnType: t.string, - directives: [appsync.Directive.apiKey()], - dataSource: api.addNoneDataSource('none'), - args: { - arg: t.string, - }, - - }); - test.addField({ fieldName: 'resolve', field }); - - api.addType(test); - const out = 'type Test {\n test: String\n resolve(arg: String): String\n @aws_api_key\n}\n'; - - // THEN - Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { - Definition: `${out}`, - }); - Template.fromStack(stack).resourceCountIs('AWS::AppSync::Resolver', 1); - }); - - test('appsync fails addField with ObjectType missing fieldName', () => { - // WHEN - const test = new appsync.ObjectType('Test', { definition: {} }); - api.addType(test); - - // THEN - expect(() => { - test.addField({ fieldName: 'test' }); - }).toThrowError('Object Types must have both fieldName and field options.'); - }); - - test('appsync fails addField with ObjectType missing field', () => { - // WHEN - const test = new appsync.ObjectType('Test', { definition: {} }); - api.addType(test); - - // THEN - expect(() => { - test.addField({ field: t.string }); - }).toThrowError('Object Types must have both fieldName and field options.'); - }); - - test('appsync fails addField with ObjectType missing both fieldName and field options', () => { - // WHEN - const test = new appsync.ObjectType('Test', { definition: {} }); - api.addType(test); - - // THEN - expect(() => { - test.addField({}); - }).toThrowError('Object Types must have both fieldName and field options.'); - }); -}); diff --git a/packages/@aws-cdk/aws-appsync/test/appsync-opensearch.test.ts b/packages/@aws-cdk/aws-appsync/test/appsync-opensearch.test.ts index 92cf5d26c0abf..fe88042030fb4 100644 --- a/packages/@aws-cdk/aws-appsync/test/appsync-opensearch.test.ts +++ b/packages/@aws-cdk/aws-appsync/test/appsync-opensearch.test.ts @@ -12,7 +12,7 @@ beforeEach(() => { stack = new cdk.Stack(); api = new appsync.GraphqlApi(stack, 'baseApi', { name: 'api', - schema: appsync.Schema.fromAsset(path.join(__dirname, 'appsync.test.graphql')), + schema: appsync.SchemaFile.fromAsset(path.join(__dirname, 'appsync.test.graphql')), }); domain = new opensearch.Domain(stack, 'OsDomain', { version: opensearch.EngineVersion.OPENSEARCH_1_1, diff --git a/packages/@aws-cdk/aws-appsync/test/appsync-rds.test.ts b/packages/@aws-cdk/aws-appsync/test/appsync-rds.test.ts index 2030c900d5977..a281737d1ab3c 100644 --- a/packages/@aws-cdk/aws-appsync/test/appsync-rds.test.ts +++ b/packages/@aws-cdk/aws-appsync/test/appsync-rds.test.ts @@ -12,7 +12,7 @@ beforeEach(() => { stack = new cdk.Stack(); api = new appsync.GraphqlApi(stack, 'baseApi', { name: 'api', - schema: new appsync.Schema({ + schema: new appsync.SchemaFile({ filePath: path.join(__dirname, 'appsync.test.graphql'), }), }); diff --git a/packages/@aws-cdk/aws-appsync/test/appsync-scalar-type.test.ts b/packages/@aws-cdk/aws-appsync/test/appsync-scalar-type.test.ts deleted file mode 100644 index 01cf50bd8904b..0000000000000 --- a/packages/@aws-cdk/aws-appsync/test/appsync-scalar-type.test.ts +++ /dev/null @@ -1,227 +0,0 @@ -import { Template } from '@aws-cdk/assertions'; -import * as cdk from '@aws-cdk/core'; -import * as appsync from '../lib'; -import * as t from './scalar-type-defintions'; - -let stack: cdk.Stack; -let api: appsync.GraphqlApi; -beforeEach(() => { - // GIVEN - stack = new cdk.Stack(); - api = new appsync.GraphqlApi(stack, 'api', { - name: 'api', - }); -}); - -describe('testing all GraphQL Types', () => { - test('scalar type id', () => { - // WHEN - api.addType(new appsync.ObjectType('Test', { - definition: { - id: t.id, - }, - })); - const out = 'type Test {\n id: ID\n}\n'; - - // THEN - Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { - Definition: `${out}`, - }); - }); - - test('scalar type string', () => { - // WHEN - api.addType(new appsync.ObjectType('Test', { - definition: { - id: t.string, - }, - })); - const out = 'type Test {\n id: String\n}\n'; - - // THEN - Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { - Definition: `${out}`, - }); - }); - - test('scalar type int', () => { - // WHEN - api.addType(new appsync.ObjectType('Test', { - definition: { - id: t.int, - }, - })); - const out = 'type Test {\n id: Int\n}\n'; - - // THEN - Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { - Definition: `${out}`, - }); - }); - - test('scalar type float', () => { - // WHEN - api.addType(new appsync.ObjectType('Test', { - definition: { - id: t.float, - }, - })); - const out = 'type Test {\n id: Float\n}\n'; - - // THEN - Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { - Definition: `${out}`, - }); - }); - - test('scalar type boolean', () => { - // WHEN - api.addType(new appsync.ObjectType('Test', { - definition: { - id: t.boolean, - }, - })); - const out = 'type Test {\n id: Boolean\n}\n'; - - // THEN - Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { - Definition: `${out}`, - }); - }); - - test('scalar type AWSDate', () => { - // WHEN - api.addType(new appsync.ObjectType('Test', { - definition: { - id: t.awsDate, - }, - })); - const out = 'type Test {\n id: AWSDate\n}\n'; - - // THEN - Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { - Definition: `${out}`, - }); - }); - - test('scalar type AWSTime', () => { - // WHEN - api.addType(new appsync.ObjectType('Test', { - definition: { - id: t.awsTime, - }, - })); - const out = 'type Test {\n id: AWSTime\n}\n'; - - // THEN - Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { - Definition: `${out}`, - }); - }); - - test('scalar type AWSDateTime', () => { - // WHEN - api.addType(new appsync.ObjectType('Test', { - definition: { - id: t.awsDateTime, - }, - })); - const out = 'type Test {\n id: AWSDateTime\n}\n'; - - // THEN - Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { - Definition: `${out}`, - }); - }); - - test('scalar type AWSTimestamp', () => { - // WHEN - api.addType(new appsync.ObjectType('Test', { - definition: { - id: t.awsTimestamp, - }, - })); - const out = 'type Test {\n id: AWSTimestamp\n}\n'; - - // THEN - Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { - Definition: `${out}`, - }); - }); - - test('scalar type AWSEmail', () => { - // WHEN - api.addType(new appsync.ObjectType('Test', { - definition: { - id: t.awsEmail, - }, - })); - const out = 'type Test {\n id: AWSEmail\n}\n'; - - // THEN - Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { - Definition: `${out}`, - }); - }); - - test('scalar type AWSJSON', () => { - // WHEN - api.addType(new appsync.ObjectType('Test', { - definition: { - id: t.awsJson, - }, - })); - const out = 'type Test {\n id: AWSJSON\n}\n'; - - // THEN - Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { - Definition: `${out}`, - }); - }); - - - test('scalar type AWSUrl', () => { - // WHEN - api.addType(new appsync.ObjectType('Test', { - definition: { - id: t.awsUrl, - }, - })); - const out = 'type Test {\n id: AWSURL\n}\n'; - - // THEN - Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { - Definition: `${out}`, - }); - }); - - test('scalar type AWSPhone', () => { - // WHEN - api.addType(new appsync.ObjectType('Test', { - definition: { - id: t.awsPhone, - }, - })); - const out = 'type Test {\n id: AWSPhone\n}\n'; - - // THEN - Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { - Definition: `${out}`, - }); - }); - - test('scalar type AWSIPAddress', () => { - // WHEN - api.addType( new appsync.ObjectType('Test', { - definition: { - id: t.awsIpAddress, - }, - })); - const out = 'type Test {\n id: AWSIPAddress\n}\n'; - - // THEN - Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { - Definition: `${out}`, - }); - }); -}); \ No newline at end of file diff --git a/packages/@aws-cdk/aws-appsync/test/appsync-schema.test.ts b/packages/@aws-cdk/aws-appsync/test/appsync-schema.test.ts deleted file mode 100644 index 9e3c5d951d807..0000000000000 --- a/packages/@aws-cdk/aws-appsync/test/appsync-schema.test.ts +++ /dev/null @@ -1,275 +0,0 @@ -import { join } from 'path'; -import { Template } from '@aws-cdk/assertions'; -import * as cdk from '@aws-cdk/core'; -import * as appsync from '../lib'; -import * as t from './scalar-type-defintions'; - -// Schema Definitions -const type = new appsync.ObjectType('test', { - definition: { - version: t.required_string, - }, -}); -const query = new appsync.ObjectType('Query', { - definition: { - getTests: new appsync.ResolvableField({ - returnType: type.attribute({ isRequiredList: true, isList: true }), - }), - }, -}); -const mutation = new appsync.ObjectType('Mutation', { - definition: { - addTest: new appsync.ResolvableField({ - returnType: type.attribute(), - args: { version: t.required_string }, - }), - }, -}); - -let stack: cdk.Stack; -beforeEach(() => { - // GIVEN - stack = new cdk.Stack(); -}); - -describe('basic testing schema definition mode `code`', () => { - - test('definition mode `code` produces empty schema definition', () => { - // WHEN - new appsync.GraphqlApi(stack, 'API', { - name: 'demo', - }); - - // THEN - Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { - Definition: '', - }); - }); - - test('definition mode `code` generates correct schema with addToSchema', () => { - // WHEN - const api = new appsync.GraphqlApi(stack, 'API', { - name: 'demo', - }); - api.addType(type); - api.addType(query); - api.addType(mutation); - - // THEN - Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { - Definition: `${type.toString()}\n${query.toString()}\n${mutation.toString()}\n`, - }); - }); - - test('definition mode `code` allows for api to addQuery', () => { - // WHEN - const api = new appsync.GraphqlApi(stack, 'API', { - name: 'demo', - }); - api.addQuery('test', new appsync.ResolvableField({ - returnType: t.string, - })); - - // THEN - Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { - Definition: 'schema {\n query: Query\n}\ntype Query {\n test: String\n}\n', - }); - }); - - test('definition mode `code` allows for schema to addQuery', () => { - // WHEN - const schema = new appsync.Schema(); - new appsync.GraphqlApi(stack, 'API', { - name: 'demo', - schema, - }); - schema.addQuery('test', new appsync.ResolvableField({ - returnType: t.string, - })); - - // THEN - Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { - Definition: 'schema {\n query: Query\n}\ntype Query {\n test: String\n}\n', - }); - }); - - test('definition mode `code` allows for api to addMutation', () => { - // WHEN - const api = new appsync.GraphqlApi(stack, 'API', { - name: 'demo', - }); - api.addMutation('test', new appsync.ResolvableField({ - returnType: t.string, - })); - - // THEN - Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { - Definition: 'schema {\n mutation: Mutation\n}\ntype Mutation {\n test: String\n}\n', - }); - }); - - test('definition mode `code` allows for schema to addMutation', () => { - // WHEN - const schema = new appsync.Schema(); - new appsync.GraphqlApi(stack, 'API', { - name: 'demo', - schema, - }); - schema.addMutation('test', new appsync.ResolvableField({ - returnType: t.string, - })); - - // THEN - Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { - Definition: 'schema {\n mutation: Mutation\n}\ntype Mutation {\n test: String\n}\n', - }); - }); - - test('definition mode `code` allows for api to addSubscription', () => { - // WHEN - const api = new appsync.GraphqlApi(stack, 'API', { - name: 'demo', - }); - api.addSubscription('test', new appsync.ResolvableField({ - returnType: t.string, - })); - - // THEN - Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { - Definition: 'schema {\n subscription: Subscription\n}\ntype Subscription {\n test: String\n}\n', - }); - }); - - test('definition mode `code` allows for schema to addSubscription', () => { - // WHEN - const schema = new appsync.Schema(); - new appsync.GraphqlApi(stack, 'API', { - name: 'demo', - schema, - }); - schema.addSubscription('test', new appsync.ResolvableField({ - returnType: t.string, - })); - - // THEN - Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { - Definition: 'schema {\n subscription: Subscription\n}\ntype Subscription {\n test: String\n}\n', - }); - }); - - test('definition mode `code` addSubscription w/ @aws_subscribe', () => { - // WHE - const api = new appsync.GraphqlApi(stack, 'API', { - name: 'demo', - }); - api.addSubscription('test', new appsync.ResolvableField({ - returnType: t.string, - directives: [appsync.Directive.subscribe('test1')], - })); - - const out = 'schema {\n subscription: Subscription\n}\ntype Subscription {\n test: String\n @aws_subscribe(mutations: ["test1"])\n}\n'; - - // THEN - Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { - Definition: out, - }); - }); -}); - -describe('testing schema definition mode `file`', () => { - - test('definition mode `file` produces correct output', () => { - // WHEN - new appsync.GraphqlApi(stack, 'API', { - name: 'demo', - schema: appsync.Schema.fromAsset(join(__dirname, 'appsync.test.graphql')), - }); - - // THEN - Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { - Definition: `${type.toString()}\n${query.toString()}\n${mutation.toString()}\n`, - }); - }); - - test('definition mode `file` errors when addType for object is called', () => { - // WHEN - const api = new appsync.GraphqlApi(stack, 'API', { - name: 'demo', - schema: appsync.Schema.fromAsset(join(__dirname, 'appsync.test.graphql')), - }); - - // THEN - expect(() => { - api.addType(new appsync.ObjectType('blah', { - definition: { fail: t.id }, - })); - }).toThrowError('API cannot add type because schema definition mode is not configured as CODE.'); - }); - - test('definition mode `file` errors when addType for interface is called', () => { - // WHEN - const api = new appsync.GraphqlApi(stack, 'API', { - name: 'demo', - schema: appsync.Schema.fromAsset(join(__dirname, 'appsync.test.graphql')), - }); - - // THEN - expect(() => { - api.addType(new appsync.InterfaceType('blah', { - definition: { fail: t.id }, - })); - }).toThrowError('API cannot add type because schema definition mode is not configured as CODE.'); - }); - - test('definition mode `file` errors when addToSchema is called', () => { - // WHEN - const api = new appsync.GraphqlApi(stack, 'API', { - name: 'demo', - schema: appsync.Schema.fromAsset(join(__dirname, 'appsync.test.graphql')), - }); - - // THEN - expect(() => { - api.addToSchema('blah'); - }).toThrowError('API cannot append to schema because schema definition mode is not configured as CODE.'); - }); - - test('definition mode `file` errors when addQuery is called', () => { - // WHEN - const api = new appsync.GraphqlApi(stack, 'API', { - name: 'demo', - schema: appsync.Schema.fromAsset(join(__dirname, 'appsync.test.graphql')), - }); - - // THEN - expect(() => { - api.addQuery('blah', new appsync.ResolvableField({ returnType: t.string })); - }).toThrowError('Unable to add query. Schema definition mode must be CODE. Received: FILE'); - }); - - test('definition mode `file` errors when addMutation is called', () => { - // WHEN - const api = new appsync.GraphqlApi(stack, 'API', { - name: 'demo', - schema: appsync.Schema.fromAsset(join(__dirname, 'appsync.test.graphql')), - }); - - // THEN - expect(() => { - api.addMutation('blah', new appsync.ResolvableField({ returnType: t.string })); - }).toThrowError('Unable to add mutation. Schema definition mode must be CODE. Received: FILE'); - }); - - test('definition mode `file` errors when addSubscription is called', () => { - // WHEN - const api = new appsync.GraphqlApi(stack, 'API', { - name: 'demo', - schema: appsync.Schema.fromAsset(join(__dirname, 'appsync.test.graphql')), - }); - - // THEN - expect(() => { - api.addSubscription('blah', new appsync.ResolvableField({ returnType: t.string })); - }).toThrowError('Unable to add subscription. Schema definition mode must be CODE. Received: FILE'); - }); -}); \ No newline at end of file diff --git a/packages/@aws-cdk/aws-appsync/test/appsync-union-types.test.ts b/packages/@aws-cdk/aws-appsync/test/appsync-union-types.test.ts deleted file mode 100644 index b84099b93e68f..0000000000000 --- a/packages/@aws-cdk/aws-appsync/test/appsync-union-types.test.ts +++ /dev/null @@ -1,152 +0,0 @@ -import { Template } from '@aws-cdk/assertions'; -import * as cdk from '@aws-cdk/core'; -import * as appsync from '../lib'; -import * as t from './scalar-type-defintions'; - -const out = 'type Test1 {\n test1: String\n}\ntype Test2 {\n test2: String\n}\nunion UnionTest = Test1 | Test2\n'; -const test1 = new appsync.ObjectType('Test1', { - definition: { test1: t.string }, -}); -const test2 = new appsync.ObjectType('Test2', { - definition: { test2: t.string }, -}); -let stack: cdk.Stack; -let api: appsync.GraphqlApi; -beforeEach(() => { - // GIVEN - stack = new cdk.Stack(); - api = new appsync.GraphqlApi(stack, 'api', { - name: 'api', - }); - api.addType(test1); - api.addType(test2); -}); - -describe('testing Union Type properties', () => { - test('UnionType configures properly', () => { - // WHEN - const union = new appsync.UnionType('UnionTest', { - definition: [test1, test2], - }); - api.addType(union); - // THEN - Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { - Definition: `${out}`, - }); - Template.fromStack(stack).resourceCountIs('AWS::AppSync::Resolver', 0); - }); - - test('UnionType can addField', () => { - // WHEN - const union = new appsync.UnionType('UnionTest', { - definition: [test1], - }); - api.addType(union); - union.addField({ field: test2.attribute() }); - - // THEN - Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { - Definition: `${out}`, - }); - }); - - test('UnionType errors when addField is configured with fieldName option', () => { - // WHEN - const union = new appsync.UnionType('UnionTest', { - definition: [test1], - }); - api.addType(union); - - // THEN - expect(() => { - union.addField({ fieldName: 'fail', field: test2.attribute() }); - }).toThrowError('Union Types cannot be configured with the fieldName option. Use the field option instead.'); - }); - - test('UnionType errors when addField is not configured with field option', () => { - // WHEN - const union = new appsync.UnionType('UnionTest', { - definition: [test1], - }); - api.addType(union); - - // THEN - expect(() => { - union.addField({}); - }).toThrowError('Union Types must be configured with the field option.'); - }); - - test('UnionType can be a GraphqlType', () => { - // WHEN - const union = new appsync.UnionType('UnionTest', { - definition: [test1, test2], - }); - api.addType(union); - - api.addType(new appsync.ObjectType('Test2', { - definition: { union: union.attribute() }, - })); - - const obj = 'type Test2 {\n union: UnionTest\n}\n'; - - // THEN - Template.fromStack(stack).hasResourceProperties('AWS::AppSync::GraphQLSchema', { - Definition: `${out}${obj}`, - }); - }); - - test('appsync errors when addField with Graphql Types', () => { - // WHEN - const test = new appsync.UnionType('Test', { - definition: [], - }); - // THEN - expect(() => { - test.addField({ field: t.string }); - }).toThrowError('Fields for Union Types must be Object Types.'); - }); - - test('appsync errors when addField with Field', () => { - // WHEN - const test = new appsync.UnionType('Test', { - definition: [], - }); - // THEN - expect(() => { - test.addField({ field: new appsync.Field({ returnType: t.string }) }); - }).toThrowError('Fields for Union Types must be Object Types.'); - }); - - test('appsync errors when addField with ResolvableField', () => { - // WHEN - const test = new appsync.UnionType('Test', { - definition: [], - }); - // THEN - expect(() => { - test.addField({ field: new appsync.ResolvableField({ returnType: t.string }) }); - }).toThrowError('Fields for Union Types must be Object Types.'); - }); - - test('appsync errors when addField with Interface Types', () => { - // WHEN - const test = new appsync.UnionType('Test', { - definition: [], - }); - // THEN - expect(() => { - test.addField({ field: new appsync.InterfaceType('break', { definition: {} }).attribute() }); - }).toThrowError('Fields for Union Types must be Object Types.'); - }); - - test('appsync errors when addField with Union Types', () => { - // WHEN - const test = new appsync.UnionType('Test', { - definition: [], - }); - // THEN - expect(() => { - test.addField({ field: test.attribute() }); - }).toThrowError('Fields for Union Types must be Object Types.'); - }); -}); \ No newline at end of file diff --git a/packages/@aws-cdk/aws-appsync/test/appsync.test.ts b/packages/@aws-cdk/aws-appsync/test/appsync.test.ts index 1ed2a95b6aeae..bb64702c47b94 100644 --- a/packages/@aws-cdk/aws-appsync/test/appsync.test.ts +++ b/packages/@aws-cdk/aws-appsync/test/appsync.test.ts @@ -13,7 +13,7 @@ beforeEach(() => { api = new appsync.GraphqlApi(stack, 'api', { authorizationConfig: {}, name: 'api', - schema: appsync.Schema.fromAsset(path.join(__dirname, 'appsync.test.graphql')), + schema: appsync.SchemaFile.fromAsset(path.join(__dirname, 'appsync.test.graphql')), logConfig: {}, }); }); @@ -100,7 +100,7 @@ test('when xray is enabled should not throw an Error', () => { new appsync.GraphqlApi(stack, 'api-x-ray', { authorizationConfig: {}, name: 'api', - schema: appsync.Schema.fromAsset(path.join(__dirname, 'appsync.test.graphql')), + schema: appsync.SchemaFile.fromAsset(path.join(__dirname, 'appsync.test.graphql')), xrayEnabled: true, }); @@ -123,7 +123,7 @@ test('appsync GraphqlApi should be configured with custom CloudWatch Logs role w new appsync.GraphqlApi(stack, 'api-custom-cw-logs-role', { authorizationConfig: {}, name: 'apiWithCustomRole', - schema: appsync.Schema.fromAsset(path.join(__dirname, 'appsync.test.graphql')), + schema: appsync.SchemaFile.fromAsset(path.join(__dirname, 'appsync.test.graphql')), logConfig: { role: cloudWatchLogRole, }, @@ -169,7 +169,7 @@ test('appsync GraphqlApi should be configured with custom domain when specified' new appsync.GraphqlApi(stack, 'api-custom-cw-logs-role', { authorizationConfig: {}, name: 'apiWithCustomRole', - schema: appsync.Schema.fromAsset(path.join(__dirname, 'appsync.test.graphql')), + schema: appsync.SchemaFile.fromAsset(path.join(__dirname, 'appsync.test.graphql')), domainName: { domainName, certificate, @@ -201,7 +201,7 @@ test('log retention should be configured with given retention time when specifie new appsync.GraphqlApi(stack, 'log-retention', { authorizationConfig: {}, name: 'log-retention', - schema: appsync.Schema.fromAsset(path.join(__dirname, 'appsync.test.graphql')), + schema: appsync.SchemaFile.fromAsset(path.join(__dirname, 'appsync.test.graphql')), logConfig: { retention: retentionTime, }, @@ -232,7 +232,7 @@ test('log retention should not appear when no retention time is specified', () = new appsync.GraphqlApi(stack, 'no-log-retention', { authorizationConfig: {}, name: 'no-log-retention', - schema: appsync.Schema.fromAsset(path.join(__dirname, 'appsync.test.graphql')), + schema: appsync.SchemaFile.fromAsset(path.join(__dirname, 'appsync.test.graphql')), }); // THEN diff --git a/packages/@aws-cdk/aws-appsync/test/integ.api-import.ts b/packages/@aws-cdk/aws-appsync/test/integ.api-import.ts index a4ebc3105209e..1ccf3228a5dbd 100644 --- a/packages/@aws-cdk/aws-appsync/test/integ.api-import.ts +++ b/packages/@aws-cdk/aws-appsync/test/integ.api-import.ts @@ -24,7 +24,7 @@ const baseStack = new cdk.Stack(app, 'baseStack'); const baseApi = new appsync.GraphqlApi(baseStack, 'baseApi', { name: 'baseApi', - schema: appsync.Schema.fromAsset(path.join(__dirname, 'appsync.test.graphql')), + schema: appsync.SchemaFile.fromAsset(path.join(__dirname, 'appsync.test.graphql')), }); const stack = new cdk.Stack(app, 'stack'); diff --git a/packages/@aws-cdk/aws-appsync/test/integ.appsync-lambda.ts b/packages/@aws-cdk/aws-appsync/test/integ.appsync-lambda.ts index b60dd5e23223d..3a4ec57b07898 100644 --- a/packages/@aws-cdk/aws-appsync/test/integ.appsync-lambda.ts +++ b/packages/@aws-cdk/aws-appsync/test/integ.appsync-lambda.ts @@ -23,7 +23,7 @@ const stack = new cdk.Stack(app, 'stack'); const api = new appsync.GraphqlApi(stack, 'LambdaAPI', { name: 'LambdaAPI', - schema: appsync.Schema.fromAsset(path.join(__dirname, 'appsync.lambda.graphql')), + schema: appsync.SchemaFile.fromAsset(path.join(__dirname, 'appsync.lambda.graphql')), }); const func = new lambda.Function(stack, 'func', { diff --git a/packages/@aws-cdk/aws-appsync/test/integ.appsync-none.ts b/packages/@aws-cdk/aws-appsync/test/integ.appsync-none.ts index 34ce22aefba68..20d8922210d1a 100644 --- a/packages/@aws-cdk/aws-appsync/test/integ.appsync-none.ts +++ b/packages/@aws-cdk/aws-appsync/test/integ.appsync-none.ts @@ -8,7 +8,7 @@ const stack = new cdk.Stack(app, 'stack'); const api = new appsync.GraphqlApi(stack, 'NoneAPI', { name: 'NoneAPI', - schema: appsync.Schema.fromAsset(path.join(__dirname, 'appsync.none.graphql')), + schema: appsync.SchemaFile.fromAsset(path.join(__dirname, 'appsync.none.graphql')), }); api.addNoneDataSource('NoneDS', { diff --git a/packages/@aws-cdk/aws-appsync/test/integ.auth-apikey.ts b/packages/@aws-cdk/aws-appsync/test/integ.auth-apikey.ts index 4adb6e5bdafbe..39462d91e327f 100644 --- a/packages/@aws-cdk/aws-appsync/test/integ.auth-apikey.ts +++ b/packages/@aws-cdk/aws-appsync/test/integ.auth-apikey.ts @@ -1,7 +1,7 @@ import { join } from 'path'; import { AttributeType, BillingMode, Table } from '@aws-cdk/aws-dynamodb'; import { App, RemovalPolicy, Stack } from '@aws-cdk/core'; -import { AuthorizationType, GraphqlApi, MappingTemplate, PrimaryKey, Schema, Values } from '../lib'; +import { AuthorizationType, GraphqlApi, MappingTemplate, PrimaryKey, SchemaFile, Values } from '../lib'; /* * Creates an Appsync GraphQL API with API_KEY authorization. @@ -23,7 +23,7 @@ const stack = new Stack(app, 'aws-appsync-integ'); const api = new GraphqlApi(stack, 'Api', { name: 'Integ_Test_APIKey', - schema: Schema.fromAsset(join(__dirname, 'appsync.auth.graphql')), + schema: SchemaFile.fromAsset(join(__dirname, 'appsync.auth.graphql')), authorizationConfig: { defaultAuthorization: { authorizationType: AuthorizationType.API_KEY, @@ -60,4 +60,4 @@ testDS.createResolver({ responseMappingTemplate: MappingTemplate.dynamoDbResultItem(), }); -app.synth(); \ No newline at end of file +app.synth(); diff --git a/packages/@aws-cdk/aws-appsync/test/integ.graphql-elasticsearch.ts b/packages/@aws-cdk/aws-appsync/test/integ.graphql-elasticsearch.ts index 933572da29eca..199dcb6454aeb 100644 --- a/packages/@aws-cdk/aws-appsync/test/integ.graphql-elasticsearch.ts +++ b/packages/@aws-cdk/aws-appsync/test/integ.graphql-elasticsearch.ts @@ -22,7 +22,7 @@ const domain = new es.Domain(stack, 'Domain', { const api = new appsync.GraphqlApi(stack, 'api', { name: 'api', - schema: appsync.Schema.fromAsset(path.join(__dirname, 'appsync.test.graphql')), + schema: appsync.SchemaFile.fromAsset(path.join(__dirname, 'appsync.test.graphql')), }); const ds = api.addElasticsearchDataSource('ds', domain); diff --git a/packages/@aws-cdk/aws-appsync/test/integ.graphql-iam.ts b/packages/@aws-cdk/aws-appsync/test/integ.graphql-iam.ts index 86496338f585b..9d2105e923c18 100644 --- a/packages/@aws-cdk/aws-appsync/test/integ.graphql-iam.ts +++ b/packages/@aws-cdk/aws-appsync/test/integ.graphql-iam.ts @@ -12,7 +12,7 @@ import { UserPoolDefaultAction, Values, IamResource, - Schema, + SchemaFile, } from '../lib'; /* @@ -38,7 +38,7 @@ const userPool = new UserPool(stack, 'Pool', { const api = new GraphqlApi(stack, 'Api', { name: 'Integ_Test_IAM', - schema: Schema.fromAsset(join(__dirname, 'integ.graphql-iam.graphql')), + schema: SchemaFile.fromAsset(join(__dirname, 'integ.graphql-iam.graphql')), authorizationConfig: { defaultAuthorization: { authorizationType: AuthorizationType.USER_POOL, diff --git a/packages/@aws-cdk/aws-appsync/test/integ.graphql-opensearch.ts b/packages/@aws-cdk/aws-appsync/test/integ.graphql-opensearch.ts index a8c8984c04e14..db7903a6deb5b 100644 --- a/packages/@aws-cdk/aws-appsync/test/integ.graphql-opensearch.ts +++ b/packages/@aws-cdk/aws-appsync/test/integ.graphql-opensearch.ts @@ -22,7 +22,7 @@ const domain = new opensearch.Domain(stack, 'Domain', { const api = new appsync.GraphqlApi(stack, 'api', { name: 'api', - schema: appsync.Schema.fromAsset(path.join(__dirname, 'appsync.test.graphql')), + schema: appsync.SchemaFile.fromAsset(path.join(__dirname, 'appsync.test.graphql')), }); const ds = api.addOpenSearchDataSource('ds', domain); diff --git a/packages/@aws-cdk/aws-appsync/test/integ.graphql-schema.ts b/packages/@aws-cdk/aws-appsync/test/integ.graphql-schema.ts deleted file mode 100644 index 6475b0bfae971..0000000000000 --- a/packages/@aws-cdk/aws-appsync/test/integ.graphql-schema.ts +++ /dev/null @@ -1,133 +0,0 @@ -import * as db from '@aws-cdk/aws-dynamodb'; -import * as cdk from '@aws-cdk/core'; -import * as appsync from '../lib'; -import * as ObjectType from './object-type-definitions'; -import * as ScalarType from './scalar-type-defintions'; - -/* - * Creates an Appsync GraphQL API and schema in a code-first approach. - * - * Stack verification steps: - * Deploy stack, get api key and endpoinScalarType. Check if schema connects to data source. - * - * -- bash verify.integ.graphql-schema.sh --start -- start -- - * -- aws appsync list-graphql-apis -- obtain apiId & endpoint -- - * -- aws appsync list-api-keys --api-id [apiId] -- obtain api key -- - * -- bash verify.integ.graphql-schema.sh --check [apiKey] [url] -- check if success -- - * -- bash verify.integ.graphql-schema.sh --clean -- clean -- - */ -const app = new cdk.App(); -const stack = new cdk.Stack(app, 'code-first-schema'); - -const schema = new appsync.Schema(); - -const node = new appsync.InterfaceType('Node', { - definition: { - created: ScalarType.string, - edited: ScalarType.string, - id: ScalarType.required_id, - }, -}); - -schema.addType(node); - -const api = new appsync.GraphqlApi(stack, 'code-first-api', { - name: 'api', - schema: schema, -}); - -const table = new db.Table(stack, 'table', { - partitionKey: { - name: 'id', - type: db.AttributeType.STRING, - }, -}); - -const tableDS = api.addDynamoDbDataSource('planets', table); - -const planet = ObjectType.planet; -schema.addType(planet); - -const species = api.addType(new appsync.ObjectType('Species', { - interfaceTypes: [node], - definition: { - name: ScalarType.string, - classification: ScalarType.string, - designation: ScalarType.string, - averageHeight: ScalarType.float, - averageLifespan: ScalarType.int, - eyeColors: ScalarType.list_string, - hairColors: ScalarType.list_string, - skinColors: ScalarType.list_string, - language: ScalarType.string, - homeworld: planet.attribute(), - }, -})); - -api.addQuery('getPlanets', new appsync.ResolvableField({ - returnType: planet.attribute({ isList: true }), - dataSource: tableDS, - requestMappingTemplate: appsync.MappingTemplate.dynamoDbScanTable(), - responseMappingTemplate: appsync.MappingTemplate.dynamoDbResultList(), -})); - -/* ATTRIBUTES */ -const name = new appsync.Assign('name', '$context.arguments.name'); -const diameter = new appsync.Assign('diameter', '$context.arguments.diameter'); -const rotationPeriod = new appsync.Assign('rotationPeriod', '$context.arguments.rotationPeriod'); -const orbitalPeriod = new appsync.Assign('orbitalPeriod', '$context.arguments.orbitalPeriod'); -const gravity = new appsync.Assign('gravityPeriod', '$context.arguments.gravity'); -const population = new appsync.Assign('population', '$context.arguments.population'); -const climates = new appsync.Assign('climates', '$context.arguments.climates'); -const terrains = new appsync.Assign('terrains', '$context.arguments.terrains'); -const surfaceWater = new appsync.Assign('surfaceWater', '$context.arguments.surfaceWater'); -api.addMutation('addPlanet', new appsync.ResolvableField({ - returnType: planet.attribute(), - args: { - name: ScalarType.string, - diameter: ScalarType.int, - rotationPeriod: ScalarType.int, - orbitalPeriod: ScalarType.int, - gravity: ScalarType.string, - population: ScalarType.list_string, - climates: ScalarType.list_string, - terrains: ScalarType.list_string, - surfaceWater: ScalarType.float, - }, - dataSource: tableDS, - requestMappingTemplate: appsync.MappingTemplate.dynamoDbPutItem( - appsync.PrimaryKey.partition('id').auto(), new appsync.AttributeValues('$context.arguments', - [name, diameter, rotationPeriod, orbitalPeriod, gravity, population, climates, terrains, surfaceWater], - ), - ), - responseMappingTemplate: appsync.MappingTemplate.dynamoDbResultItem(), -})); - -api.addSubscription('addedPlanets', new appsync.Field({ - returnType: planet.attribute(), - args: { id: ScalarType.required_id }, - directives: [appsync.Directive.subscribe('addPlanet')], -})); -api.addType(new appsync.InputType('AwesomeInput', { - definition: { awesomeInput: ScalarType.string }, -})); - -api.addType(new appsync.EnumType('Episodes', { - definition: [ - 'The_Phantom_Menace', - 'Attack_of_the_Clones', - 'Revenge_of_the_Sith', - 'A_New_Hope', - 'The_Empire_Strikes_Back', - 'Return_of_the_Jedi', - 'The_Force_Awakens', - 'The_Last_Jedi', - 'The_Rise_of_Skywalker', - ], -})); - -api.addType(new appsync.UnionType('Union', { - definition: [species, planet], -})); - -app.synth(); \ No newline at end of file diff --git a/packages/@aws-cdk/aws-appsync/test/integ.graphql.ts b/packages/@aws-cdk/aws-appsync/test/integ.graphql.ts index fa0feb5ae2921..66e4145d51421 100644 --- a/packages/@aws-cdk/aws-appsync/test/integ.graphql.ts +++ b/packages/@aws-cdk/aws-appsync/test/integ.graphql.ts @@ -8,7 +8,7 @@ import { KeyCondition, MappingTemplate, PrimaryKey, - Schema, + SchemaFile, Values, } from '../lib'; @@ -35,7 +35,7 @@ const userPool = new UserPool(stack, 'Pool', { const api = new GraphqlApi(stack, 'Api', { name: 'demoapi', - schema: Schema.fromAsset(join(__dirname, 'integ.graphql.graphql')), + schema: SchemaFile.fromAsset(join(__dirname, 'integ.graphql.graphql')), authorizationConfig: { defaultAuthorization: { authorizationType: AuthorizationType.USER_POOL, diff --git a/packages/@aws-cdk/aws-appsync/test/integ.log-retention.ts b/packages/@aws-cdk/aws-appsync/test/integ.log-retention.ts index 664c28ceee237..96f981ce6c197 100644 --- a/packages/@aws-cdk/aws-appsync/test/integ.log-retention.ts +++ b/packages/@aws-cdk/aws-appsync/test/integ.log-retention.ts @@ -2,7 +2,7 @@ import { join } from 'path'; import { RetentionDays } from '@aws-cdk/aws-logs'; import { App, Stack } from '@aws-cdk/core'; import { ExpectedResult, IntegTest } from '@aws-cdk/integ-tests'; -import { GraphqlApi, LogConfig, Schema } from '../lib'; +import { GraphqlApi, LogConfig, SchemaFile } from '../lib'; const app = new App(); const stack = new Stack(app, 'AppSyncIntegLogRetention'); @@ -16,7 +16,7 @@ const logConfig: LogConfig = { const api = new GraphqlApi(stack, 'GraphqlApi', { authorizationConfig: {}, name: 'IntegLogRetention', - schema: Schema.fromAsset(join(__dirname, 'appsync.test.graphql')), + schema: SchemaFile.fromAsset(join(__dirname, 'appsync.test.graphql')), logConfig, }); @@ -37,4 +37,4 @@ describe.expect(ExpectedResult.objectLike({ ], })); -app.synth(); \ No newline at end of file +app.synth(); diff --git a/packages/@aws-cdk/aws-appsync/test/object-type-definitions.ts b/packages/@aws-cdk/aws-appsync/test/object-type-definitions.ts deleted file mode 100644 index 138f2d7e1faa1..0000000000000 --- a/packages/@aws-cdk/aws-appsync/test/object-type-definitions.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { ObjectType } from '../lib'; -import * as ScalarType from './scalar-type-defintions'; - -export const planet = new ObjectType('Planet', { - definition: { - name: ScalarType.string, - diameter: ScalarType.int, - rotationPeriod: ScalarType.int, - orbitalPeriod: ScalarType.int, - gravity: ScalarType.string, - population: ScalarType.list_string, - climates: ScalarType.list_string, - terrains: ScalarType.list_string, - surfaceWater: ScalarType.float, - created: ScalarType.string, - edited: ScalarType.string, - id: ScalarType.required_id, - }, -}); \ No newline at end of file diff --git a/packages/@aws-cdk/aws-appsync/test/scalar-type-defintions.ts b/packages/@aws-cdk/aws-appsync/test/scalar-type-defintions.ts deleted file mode 100644 index 80d03d28d1230..0000000000000 --- a/packages/@aws-cdk/aws-appsync/test/scalar-type-defintions.ts +++ /dev/null @@ -1,63 +0,0 @@ -import { GraphqlType } from '../lib'; - -// ID -export const id = GraphqlType.id(); -export const list_id = GraphqlType.id({ - isList: true, -}); -export const required_id = GraphqlType.id({ - isRequired: true, -}); -export const required_list_id = GraphqlType.id({ - isRequiredList: true, -}); -export const required_list_required_id = GraphqlType.id({ - isRequired: true, - isRequiredList: true, -}); -export const dup_id = GraphqlType.id({ - isList: true, - isRequired: true, - isRequiredList: true, -}); - -// STRING -export const string = GraphqlType.string(); -export const required_string = GraphqlType.string({ isRequired: true }); -export const list_string = GraphqlType.string({ isList: true }); - -// INT -export const int = GraphqlType.int(); - -// FLOAT -export const float = GraphqlType.float(); - -// BOOLEAN -export const boolean = GraphqlType.boolean(); - -// AWSDate -export const awsDate = GraphqlType.awsDate(); - -// AWSTime -export const awsTime = GraphqlType.awsTime(); - -// AWSDateTime -export const awsDateTime = GraphqlType.awsDateTime(); - -// AWSTimestamp -export const awsTimestamp = GraphqlType.awsTimestamp(); - -// AWSEmail -export const awsEmail = GraphqlType.awsEmail(); - -// AWSJSON -export const awsJson = GraphqlType.awsJson(); - -// AWSUrl -export const awsUrl = GraphqlType.awsUrl(); - -// AWSPhone -export const awsPhone = GraphqlType.awsPhone(); - -// AWSIPAddress -export const awsIpAddress = GraphqlType.awsIpAddress(); From 8804b27b4f4f2934a2b56567235060f048ada8c9 Mon Sep 17 00:00:00 2001 From: Mitchell Valine Date: Tue, 6 Dec 2022 15:14:25 -0800 Subject: [PATCH 2/6] chore: remove additional unused functions in private.ts --- packages/@aws-cdk/aws-appsync/lib/private.ts | 116 ------------------- 1 file changed, 116 deletions(-) diff --git a/packages/@aws-cdk/aws-appsync/lib/private.ts b/packages/@aws-cdk/aws-appsync/lib/private.ts index 448702da43662..23d04967b7297 100644 --- a/packages/@aws-cdk/aws-appsync/lib/private.ts +++ b/packages/@aws-cdk/aws-appsync/lib/private.ts @@ -1,77 +1,3 @@ -import { AuthorizationType } from './graphqlapi'; -import { Directive } from './schema-base'; -import { InterfaceType } from './schema-intermediate'; - -/** - * Generates an addition to the schema - * - * ``` - * prefix name interfaces directives { - * field - * field - * ... - * } - * ``` - */ -export interface SchemaAdditionOptions { - /** - * the prefix for this additon (type, interface, enum, input, schema) - */ - readonly prefix: string; - /** - * the name for this addition (some additions dont need this [i.e. schema]) - * - * @default - no name - */ - readonly name?: string; - /** - * the interface types if this is creating an object type - * - * @default - no interfaces - */ - readonly interfaceTypes?: InterfaceType[]; - /** - * the directives for this type - * - * @default - no directives - */ - readonly directives?: Directive[]; - /** - * the fields to reduce onto the addition - */ - readonly fields: string[]; - /** - * the authorization modes for this graphql type - */ - readonly modes?: AuthorizationType[]; -} - -/** - * Generates an addition to the schema - * - * @param options the options to produced a stringfied addition - * - * @returns the following shape: - * - * ``` - * prefix name interfaces directives { - * field - * field - * ... - * } - * ``` - */ -export function shapeAddition(options: SchemaAdditionOptions): string { - const typeName = (): string => { return options.name ? ` ${options.name}` : ''; }; - const interfaces = generateInterfaces(options.interfaceTypes); - const directives = generateDirectives({ - directives: options.directives, - modes: options.modes, - }); - return options.fields.reduce((acc, field) => - `${acc} ${field}\n`, `${options.prefix}${typeName()}${interfaces}${directives} {\n`) + '}'; -} - /** * Utility class to represent DynamoDB key conditions. */ @@ -185,45 +111,3 @@ function concatAndDedup(left: T[], right: T[]): T[] { return index === self.indexOf(elem); }); } - -/** - * Utility function to generate interfaces for object types - * - * @param interfaceTypes the interfaces this object type implements - */ -function generateInterfaces(interfaceTypes?: InterfaceType[]): string { - if (!interfaceTypes || interfaceTypes.length === 0) return ''; - return interfaceTypes.reduce((acc, interfaceType) => - `${acc} ${interfaceType.name} &`, ' implements').slice(0, -2); -} - -/** - * options to generate directives - */ -interface generateDirectivesOptions { - /** - * the directives of a given type - */ - readonly directives?: Directive[]; - /** - * thee separator betweeen directives - * - * @default - a space - */ - readonly delimiter?: string; - /** - * the authorization modes - */ - readonly modes?: AuthorizationType[]; -} - -/** - * Utility function to generate directives - */ -function generateDirectives(options: generateDirectivesOptions): string { - if (!options.directives || options.directives.length === 0) return ''; - // reduce over all directives and get string version of the directive - // pass in the auth modes for checks to happen on compile time - return options.directives.reduce((acc, directive) => - `${acc}${directive._bindToAuthModes(options.modes).toString()}${options.delimiter ?? ' '}`, ' ').slice(0, -1); -} From 063a179824b884050a9881c60e8a4589df9d8c21 Mon Sep 17 00:00:00 2001 From: Mitchell Valine Date: Wed, 7 Dec 2022 08:21:29 -0800 Subject: [PATCH 3/6] fix bad example --- packages/@aws-cdk/aws-appsync/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/@aws-cdk/aws-appsync/README.md b/packages/@aws-cdk/aws-appsync/README.md index 3fc833f5b3c5d..88f9d1b5546bc 100644 --- a/packages/@aws-cdk/aws-appsync/README.md +++ b/packages/@aws-cdk/aws-appsync/README.md @@ -308,8 +308,10 @@ import * as route53 from '@aws-cdk/aws-route53'; const myDomainName = 'api.example.com'; const certificate = new acm.Certificate(this, 'cert', { domainName: myDomainName }); +const schema = new appsync.SchemaFile({ filePath: 'mySchemaFile' }) const api = new appsync.GraphqlApi(this, 'api', { name: 'myApi', + schema, domainName: { certificate, domainName: myDomainName, From 6f8a8bfe23f0e3768aaeed03b02075eff3fd1b5c Mon Sep 17 00:00:00 2001 From: Mitchell Valine Date: Wed, 7 Dec 2022 08:51:36 -0800 Subject: [PATCH 4/6] add options to bind in ISchema --- packages/@aws-cdk/aws-appsync/lib/schema.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/packages/@aws-cdk/aws-appsync/lib/schema.ts b/packages/@aws-cdk/aws-appsync/lib/schema.ts index cd34dbb385310..b96cb2c4fd5f8 100644 --- a/packages/@aws-cdk/aws-appsync/lib/schema.ts +++ b/packages/@aws-cdk/aws-appsync/lib/schema.ts @@ -18,6 +18,14 @@ export interface ISchemaConfig { definition: string; } +/** + * Used for configuring schema bind behavior. + * + * This is intended to prevent breaking changes to implementors of ISchema + * if needing to add new behavior. + */ +export interface SchemaBindOptions {} + /** * Interface for implementing your own schema * @@ -30,7 +38,7 @@ export interface ISchema { * @returns ISchemaConfig with apiId and schema definition string * @param api the api to bind the schema to */ - bind(api: IGraphqlApi): ISchemaConfig; + bind(api: IGraphqlApi, options?: SchemaBindOptions): ISchemaConfig; } /** From 3b54e78871ff17a2969464e6db979cf9eeb8a3b4 Mon Sep 17 00:00:00 2001 From: Mitchell Valine Date: Wed, 7 Dec 2022 08:52:43 -0800 Subject: [PATCH 5/6] fix jsdoc --- packages/@aws-cdk/aws-appsync/lib/schema.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/@aws-cdk/aws-appsync/lib/schema.ts b/packages/@aws-cdk/aws-appsync/lib/schema.ts index b96cb2c4fd5f8..a82693268c646 100644 --- a/packages/@aws-cdk/aws-appsync/lib/schema.ts +++ b/packages/@aws-cdk/aws-appsync/lib/schema.ts @@ -37,6 +37,7 @@ export interface ISchema { * * @returns ISchemaConfig with apiId and schema definition string * @param api the api to bind the schema to + * @param options configuration for bind behavior */ bind(api: IGraphqlApi, options?: SchemaBindOptions): ISchemaConfig; } From 45e8f02d3db4eee63f371b57338b9fcad3e19088 Mon Sep 17 00:00:00 2001 From: Mitchell Valine Date: Wed, 7 Dec 2022 14:42:49 -0800 Subject: [PATCH 6/6] missing impl arg --- packages/@aws-cdk/aws-appsync/lib/schema.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/@aws-cdk/aws-appsync/lib/schema.ts b/packages/@aws-cdk/aws-appsync/lib/schema.ts index a82693268c646..2cfd0a927dc74 100644 --- a/packages/@aws-cdk/aws-appsync/lib/schema.ts +++ b/packages/@aws-cdk/aws-appsync/lib/schema.ts @@ -86,7 +86,7 @@ export class SchemaFile implements ISchema { * * @param api The binding GraphQL Api */ - public bind(api: IGraphqlApi): ISchemaConfig { + public bind(api: IGraphqlApi, _options?: SchemaBindOptions): ISchemaConfig { return { apiId: api.apiId, definition: this.definition,