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

feat(appsync): support enumeration types for code-first approach #10023

Merged
merged 39 commits into from
Sep 11, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
56057ef
refactor(appsync): refactoring schema stringfy to abstract reduce log…
BryanPan342 Aug 27, 2020
688b6eb
assign doc strings to properties of SchemaAdditionOptions
BryanPan342 Aug 27, 2020
ca57189
address comments
BryanPan342 Aug 27, 2020
cc4593b
Merge branch 'master' into refactor-stringify
BryanPan342 Aug 27, 2020
a619592
final changes
BryanPan342 Aug 27, 2020
b7f32fd
Merge branch 'refactor-stringify' of https://github.com/BryanPan342/a…
BryanPan342 Aug 27, 2020
72b83b3
initial implementation of enum type
BryanPan342 Aug 27, 2020
ef97d23
add integ test
BryanPan342 Aug 27, 2020
9729049
write readme
BryanPan342 Aug 27, 2020
0dc0ece
Merge branch 'master' into enum
BryanPan342 Aug 27, 2020
f3c77e3
refactor(appsync): graphQLApi to graphqlApi for better snakecasing
BryanPan342 Aug 31, 2020
51edc01
Revert "refactor(appsync): graphQLApi to graphqlApi for better snakec…
BryanPan342 Aug 31, 2020
884e185
Merge remote-tracking branch 'upstream/master'
BryanPan342 Aug 31, 2020
9ad9d36
Merge remote-tracking branch 'upstream/master'
BryanPan342 Sep 1, 2020
9ead652
Merge branch 'master' into enum
BryanPan342 Sep 1, 2020
e62f912
more changes
BryanPan342 Sep 1, 2020
6e7d47c
edits
BryanPan342 Sep 1, 2020
d9ebafb
Merge remote-tracking branch 'upstream/master'
BryanPan342 Sep 1, 2020
64db87e
Merge remote-tracking branch 'upstream/master'
BryanPan342 Sep 1, 2020
b3622b0
Merge remote-tracking branch 'upstream/master'
BryanPan342 Sep 1, 2020
6ed812a
Merge branch 'master' into enum
BryanPan342 Sep 1, 2020
d54dfdb
address changes
BryanPan342 Sep 2, 2020
9e85558
update enum type
BryanPan342 Sep 2, 2020
4cdd244
Merge remote-tracking branch 'upstream/master'
BryanPan342 Sep 2, 2020
6608704
Merge remote-tracking branch 'upstream/master'
BryanPan342 Sep 3, 2020
f85ce81
Merge remote-tracking branch 'upstream/master'
BryanPan342 Sep 4, 2020
be8e113
Merge branch 'master' into enum
BryanPan342 Sep 4, 2020
484b57b
merge fix
BryanPan342 Sep 4, 2020
e8cfc0c
Merge remote-tracking branch 'upstream/master'
BryanPan342 Sep 8, 2020
1423bc6
Merge remote-tracking branch 'upstream/master'
BryanPan342 Sep 8, 2020
2ea72ed
Merge remote-tracking branch 'upstream/master'
BryanPan342 Sep 8, 2020
322d9a1
Merge remote-tracking branch 'upstream/master'
BryanPan342 Sep 9, 2020
6df5ec7
Merge branch 'master' into enum
BryanPan342 Sep 9, 2020
b14e2b8
small change
BryanPan342 Sep 9, 2020
ca76245
address suggestions
BryanPan342 Sep 10, 2020
ffbfc76
bug fix
BryanPan342 Sep 10, 2020
050f192
update integ test
BryanPan342 Sep 10, 2020
fb4d57e
change error message
BryanPan342 Sep 10, 2020
af44256
Merge branch 'master' into enum
mergify[bot] Sep 11, 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
36 changes: 36 additions & 0 deletions packages/@aws-cdk/aws-appsync/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -563,6 +563,7 @@ Types will be the meat of your GraphQL Schema as they are the types defined by y
Intermediate Types include:
- [**Interface Types**](#Interface-Types)
- [**Object Types**](#Object-Types)
- [**Enum Types**](#Enum-Types)
- [**Input Types**](#Input-Types)
- [**Union Types**](#Union-Types)

Expand All @@ -581,6 +582,8 @@ const node = new appsync.InterfaceType('Node', {
});
```

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)
Expand Down Expand Up @@ -644,6 +647,39 @@ You can create Object Types in three ways:
```
> 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
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
Expand Down
166 changes: 129 additions & 37 deletions packages/@aws-cdk/aws-appsync/lib/schema-intermediate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { BaseTypeOptions, GraphqlType, ResolvableFieldOptions } from './schema-f
*
* @experimental
*/
export interface IntermediateTypeProps {
export interface IntermediateTypeOptions {
/**
* the attributes of this type
*/
Expand Down Expand Up @@ -52,22 +52,12 @@ export class InterfaceType implements IIntermediateType {
*/
protected modes?: AuthorizationType[];

public constructor(name: string, props: IntermediateTypeProps) {
public constructor(name: string, props: IntermediateTypeOptions) {
this.name = name;
this.definition = props.definition;
this.directives = props.directives;
}

/**
* Method called when the stringifying Intermediate Types for schema generation
*
* @internal
*/
public _bindToGraphqlApi(api: GraphqlApi): IIntermediateType {
this.modes = api.modes;
return this;
}

/**
* Create a GraphQL Type representing this Intermediate Type
*
Expand Down Expand Up @@ -111,6 +101,16 @@ export class InterfaceType implements IIntermediateType {
}
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;
}
}

/**
Expand All @@ -123,7 +123,7 @@ export class InterfaceType implements IIntermediateType {
*
* @experimental
*/
export interface ObjectTypeProps extends IntermediateTypeProps {
export interface ObjectTypeOptions extends IntermediateTypeOptions {
/**
* The Interface Types this Object Type implements
*
Expand All @@ -149,7 +149,7 @@ export class ObjectType extends InterfaceType implements IIntermediateType {
*/
public resolvers?: Resolver[];

public constructor(name: string, props: ObjectTypeProps) {
public constructor(name: string, props: ObjectTypeOptions) {
const options = {
definition: props.interfaceTypes?.reduce((def, interfaceType) => {
return Object.assign({}, def, interfaceType.definition);
Expand Down Expand Up @@ -234,7 +234,7 @@ export class InputType implements IIntermediateType {
*/
protected modes?: AuthorizationType[];

public constructor(name: string, props: IntermediateTypeProps) {
public constructor(name: string, props: IntermediateTypeOptions) {
this.name = name;
this.definition = props.definition;
}
Expand All @@ -253,16 +253,6 @@ export class InputType implements IIntermediateType {
});
}

/**
* Method called when the stringifying Intermediate Types for schema generation
*
* @internal
*/
public _bindToGraphqlApi(api: GraphqlApi): IIntermediateType {
this.modes = api.modes;
return this;
}

/**
* Generate the string of this input type
*/
Expand All @@ -289,13 +279,21 @@ export class InputType implements IIntermediateType {
}
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
*
* @param definition - the object types for this union type
*
* @experimental
*/
export interface UnionTypeOptions {
Expand Down Expand Up @@ -348,16 +346,6 @@ export class UnionType implements IIntermediateType {
});
}

/**
* Method called when the stringifying Intermediate Types for schema generation
*
* @internal
*/
public _bindToGraphqlApi(api: GraphqlApi): IIntermediateType {
this.modes = api.modes;
return this;
}

/**
* Generate the string of this Union type
*/
Expand Down Expand Up @@ -387,4 +375,108 @@ export class UnionType implements IIntermediateType {
}
this.definition[options.field?.toString() + 'id'] = 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
*
* @experimental
*/
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.
*
* @experimental
*/
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;
}
}
Loading