Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge #21

Merged
merged 30 commits into from
Aug 31, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
ea1072d
feat(rds): custom security groups for OptionGroups
njlynch Aug 27, 2020
07acac2
Revert "feat(rds): custom security groups for OptionGroups"
njlynch Aug 27, 2020
3bb6c81
docs(cognito): fix up grammar in README (#10003)
Albert-Gao Aug 27, 2020
77f9703
fix(lamba): Add Java 8 Corretto Runtime support
flemjame-at-amazon Aug 27, 2020
064b884
Add custom AL2 runtime
flemjame-at-amazon Aug 27, 2020
ad7465d
refactor(appsync): abstract schema stringify to utility functions (#1…
BryanPan342 Aug 27, 2020
c5bb55c
fix(cli): unable to upgrade new style bootstrap to version (#10030)
shivlaks Aug 28, 2020
8d3e422
fix(cli): unable to upgrade new style bootstrap to version (#10030)
shivlaks Aug 28, 2020
0748889
chore(release): 1.61.1
RomainMuller Aug 28, 2020
7f351ff
fix(custom-resources): buffers returned by AwsCustomResource are unus…
jogold Aug 28, 2020
347918f
chore(release): 1.61.1 (#10034)
mergify[bot] Aug 28, 2020
5738dc1
feat(rds): custom security groups for OptionGroups (#10011)
njlynch Aug 28, 2020
ff33b54
feat(cloudfront): import existing CloudFrontWebDistributions (#10007)
njlynch Aug 28, 2020
9098e29
fix(cloudfront): Distribution does not add edgelambda trust policy (#…
njlynch Aug 28, 2020
95c0332
fix(cli): AssumeRole profiles require a [default] profile (#10032)
rix0rrr Aug 28, 2020
d748f44
fix(lambda): grantInvoke fails for imported IAM identities (#9957)
rix0rrr Aug 28, 2020
d10b829
chore(monocdk-experiment): `constructs` should NOT be a dependency (#…
rix0rrr Aug 28, 2020
86e8287
Merge branch 'master' into merge-back/1.61.1
RomainMuller Aug 28, 2020
9ffb268
feat(cloudfront): support includeBody for Lambda@Edge (#10008)
njlynch Aug 28, 2020
59b0c12
Merge branch 'master' into merge-back/1.61.1
mergify[bot] Aug 28, 2020
af41534
chore(merge-back): 1.61.1 (#10038)
mergify[bot] Aug 28, 2020
1ce3db3
Merge branch 'master' into lambda-corretto-8
NetaNir Aug 28, 2020
d5e1cc6
Merge pull request #10015 from flemjame-at-amazon/lambda-corretto-8
NetaNir Aug 28, 2020
6114045
fix(appsync): `GraphQLApi.UserPoolConfig` requires `DefaultAction` (#…
civilizeddev Aug 28, 2020
ba51ea3
fix(aws-stepfunctions-tasks): SageMaker create training job has incor…
mirgj Aug 28, 2020
1ed119e
feat(appsync): support query & mutation generation for code-first app…
BryanPan342 Aug 29, 2020
2596ef7
feat(bootstrap): customizable bootstrap template (#9886)
rix0rrr Aug 31, 2020
454cdc6
fix(eks): README.md grammar (#10072)
0xVesion Aug 31, 2020
f5dbed6
chore(cli): fix missing single quote (#10047)
rayou Aug 31, 2020
34f40b9
docs: fixes typo in tryGetContext docstring (#10061)
dehli Aug 31, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@

All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.

## [1.61.1](https://github.com/aws/aws-cdk/compare/v1.61.0...v1.61.1) (2020-08-28)


### Bug Fixes

* **cli:** unable to upgrade new style bootstrap to version ([#10030](https://github.com/aws/aws-cdk/issues/10030)) ([8d3e422](https://github.com/aws/aws-cdk/commit/8d3e422809c29da926bae878276619a59ae82ecb)), closes [#10016](https://github.com/aws/aws-cdk/issues/10016)

## [1.61.0](https://github.com/aws/aws-cdk/compare/v1.60.0...v1.61.0) (2020-08-27)


Expand Down Expand Up @@ -39,7 +46,7 @@ All notable changes to this project will be documented in this file. See [standa
### ⚠ BREAKING CHANGES TO EXPERIMENTAL FEATURES

* **cloudfront:** Distribution: `.domains` must be specified if `certificate` is provided.
* **appsync:** **appsync.addXxxDataSource** `name` and `description` props are now optional and in an `DataSourceOptions` interface.
* **appsync:** **appsync.addXxxDataSource** `name` and `description` props are now optional and in an `DataSourceOptions` interface.
- **appsync**: the props `name` and `description` in `addXxxDataSource` have been moved into new props `options` of type `DataSourceOptions`
- **appsync**: `DataSourceOptions.name` defaults to id
- **appsync**: `DataSourceOptions.description` defaults to undefined
Expand Down
2 changes: 1 addition & 1 deletion lerna.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,5 @@
"tools/*"
],
"rejectCycles": "true",
"version": "1.61.0"
"version": "1.61.1"
}
79 changes: 61 additions & 18 deletions packages/@aws-cdk/aws-appsync/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ api.grantMutation(role, 'updateExample');
api.grant(role, appsync.IamResource.ofType('Mutation', 'updateExample'), 'appsync:GraphQL');
```

## Code-First Schema
### 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:
Expand All @@ -235,7 +235,7 @@ A code-first approach offers a developer workflow with:

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
#### Code-First Example

To showcase the code-first approach. Let's try to model the following schema segment.

Expand Down Expand Up @@ -331,15 +331,13 @@ this.objectTypes = [ schema.Node, schema.Film ];

const filmConnections = schema.generateEdgeAndConnection(schema.Film);

api.addType('Query', {
definition: {
allFilms: new appsync.ResolvableField(dummyDataSource, {
returnType: filmConnections.connection.attribute(),
args: schema.args,
requestMappingTemplate: dummyRequest,
responseMappingTemplate: dummyResponse,
}),
}
api.addQuery('allFilms', new appsync.ResolvableField({
returnType: filmConnections.connection.attribute(),
args: schema.args,
dataSource: dummyDataSource,
requestMappingTemplate: dummyRequest,
responseMappingTemplate: dummyResponse,
}),
});

this.objectTypes.map((t) => api.addType(t));
Expand All @@ -353,7 +351,7 @@ create the base Object Type (i.e. Film) and from there we can generate its respe

Check out a more in-depth example [here](https://github.com/BryanPan342/starwars-code-first).

### GraphQL Types
#### 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**.
Expand All @@ -369,12 +367,12 @@ 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`.

### Field and Resolvable Fields
#### 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

`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.
Expand All @@ -401,7 +399,7 @@ const type = new appsync.InterfaceType('Node', {
});
```

#### Resolvable Fields
##### 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
Expand Down Expand Up @@ -463,7 +461,7 @@ const query = new appsync.ObjectType('Query', {

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

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
Expand All @@ -473,7 +471,7 @@ Intermediate Types include:
- [**Interface Types**](#Interface-Types)
- [**Object Types**](#Object-Types)

### Interface 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
Expand All @@ -488,7 +486,7 @@ const node = new appsync.InterfaceType('Node', {
});
```

### Object Types
##### 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
Expand Down Expand Up @@ -565,3 +563,48 @@ You can create Object Types in three ways:
```
> This method provides easy use and is ideal for smaller projects.

#### 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
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 `Object Type` 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
const string = appsync.GraphqlType.string();
const int = appsync.GraphqlType.int();
api.addMutation('addFilm', new appsync.ResolvableField({
returnType: film.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).
34 changes: 33 additions & 1 deletion packages/@aws-cdk/aws-appsync/lib/graphqlapi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import { CfnApiKey, CfnGraphQLApi, CfnGraphQLSchema } 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';

/**
* enum with all possible values for AppSync authorization type
Expand Down Expand Up @@ -531,7 +533,7 @@ export class GraphQLApi extends GraphqlApiBase {
userPoolId: config.userPool.userPoolId,
awsRegion: config.userPool.stack.region,
appIdClientRegex: config.appIdClientRegex,
defaultAction: config.defaultAction,
defaultAction: config.defaultAction || UserPoolDefaultAction.ALLOW,
};
}

Expand Down Expand Up @@ -588,4 +590,34 @@ export class GraphQLApi extends GraphqlApiBase {
public addType(type: IIntermediateType): IIntermediateType {
return this.schema.addType(type);
}

/**
* Add a query field to the schema's Query. If one isn't set by
* the user, 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. If one isn't set by
* the user, 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);
}
}
99 changes: 94 additions & 5 deletions packages/@aws-cdk/aws-appsync/lib/private.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
function concatAndDedup<T>(left: T[], right: T[]): T[] {
return left.concat(right).filter((elem, index, self) => {
return index === self.indexOf(elem);
});
}
import { Directive } from './schema-base';
import { InterfaceType } from './schema-intermediate';

/**
* Utility enum for Schema class
Expand All @@ -12,6 +9,69 @@ export enum SchemaMode {
CODE = 'CODE',
};

/**
* 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[];
}

/**
* 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(options.directives);
return options.fields.reduce((acc, field) =>
`${acc} ${field}\n`, `${options.prefix}${typeName()}${interfaces}${directives} {\n`) + '}';
}

/**
* Utility class to represent DynamoDB key conditions.
*/
Expand Down Expand Up @@ -118,4 +178,33 @@ export class Between extends BaseKeyCondition {
public args(): string[] {
return [this.arg1, this.arg2];
}
}

function concatAndDedup<T>(left: T[], right: T[]): T[] {
return left.concat(right).filter((elem, index, self) => {
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, -1);
}

/**
* Utility function to generate directives
*
* @param directives the directives of a given type
* @param delimiter the separator betweeen directives (by default we will add a space)
*/
function generateDirectives(directives?: Directive[], delimiter?: string): string {
if (!directives || directives.length === 0) return '';
return directives.reduce((acc, directive) =>
`${acc}${directive.statement}${delimiter ?? ' '}`, ' ').slice(0, -1);
}
Loading