Skip to content

Commit ad7465d

Browse files
authored
refactor(appsync): abstract schema stringify to utility functions (#10019)
Abstract schema addition to utility functions in `private.ts` ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
1 parent 3bb6c81 commit ad7465d

File tree

2 files changed

+107
-42
lines changed

2 files changed

+107
-42
lines changed

packages/@aws-cdk/aws-appsync/lib/private.ts

+94-5
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
1-
function concatAndDedup<T>(left: T[], right: T[]): T[] {
2-
return left.concat(right).filter((elem, index, self) => {
3-
return index === self.indexOf(elem);
4-
});
5-
}
1+
import { Directive } from './schema-base';
2+
import { InterfaceType } from './schema-intermediate';
63

74
/**
85
* Utility enum for Schema class
@@ -12,6 +9,69 @@ export enum SchemaMode {
129
CODE = 'CODE',
1310
};
1411

12+
/**
13+
* Generates an addition to the schema
14+
*
15+
* ```
16+
* prefix name interfaces directives {
17+
* field
18+
* field
19+
* ...
20+
* }
21+
* ```
22+
*/
23+
export interface SchemaAdditionOptions {
24+
/**
25+
* the prefix for this additon (type, interface, enum, input, schema)
26+
*/
27+
readonly prefix: string;
28+
/**
29+
* the name for this addition (some additions dont need this [i.e. schema])
30+
*
31+
* @default - no name
32+
*/
33+
readonly name?: string;
34+
/**
35+
* the interface types if this is creating an object type
36+
*
37+
* @default - no interfaces
38+
*/
39+
readonly interfaceTypes?: InterfaceType[];
40+
/**
41+
* the directives for this type
42+
*
43+
* @default - no directives
44+
*/
45+
readonly directives?: Directive[];
46+
/**
47+
* the fields to reduce onto the addition
48+
*/
49+
readonly fields: string[];
50+
}
51+
52+
/**
53+
* Generates an addition to the schema
54+
*
55+
* @param options the options to produced a stringfied addition
56+
*
57+
* @returns the following shape:
58+
*
59+
* ```
60+
* prefix name interfaces directives {
61+
* field
62+
* field
63+
* ...
64+
* }
65+
* ```
66+
*/
67+
export function shapeAddition(options: SchemaAdditionOptions): string {
68+
const typeName = (): string => { return options.name ? ` ${options.name}` : ''; };
69+
const interfaces = generateInterfaces(options.interfaceTypes);
70+
const directives = generateDirectives(options.directives);
71+
return options.fields.reduce((acc, field) =>
72+
`${acc} ${field}\n`, `${options.prefix}${typeName()}${interfaces}${directives} {\n`) + '}';
73+
}
74+
1575
/**
1676
* Utility class to represent DynamoDB key conditions.
1777
*/
@@ -118,4 +178,33 @@ export class Between extends BaseKeyCondition {
118178
public args(): string[] {
119179
return [this.arg1, this.arg2];
120180
}
181+
}
182+
183+
function concatAndDedup<T>(left: T[], right: T[]): T[] {
184+
return left.concat(right).filter((elem, index, self) => {
185+
return index === self.indexOf(elem);
186+
});
187+
}
188+
189+
/**
190+
* Utility function to generate interfaces for object types
191+
*
192+
* @param interfaceTypes the interfaces this object type implements
193+
*/
194+
function generateInterfaces(interfaceTypes?: InterfaceType[]): string {
195+
if (!interfaceTypes || interfaceTypes.length === 0) return '';
196+
return interfaceTypes.reduce((acc, interfaceType) =>
197+
`${acc} ${interfaceType.name},`, ' implements').slice(0, -1);
198+
}
199+
200+
/**
201+
* Utility function to generate directives
202+
*
203+
* @param directives the directives of a given type
204+
* @param delimiter the separator betweeen directives (by default we will add a space)
205+
*/
206+
function generateDirectives(directives?: Directive[], delimiter?: string): string {
207+
if (!directives || directives.length === 0) return '';
208+
return directives.reduce((acc, directive) =>
209+
`${acc}${directive.statement}${delimiter ?? ' '}`, ' ').slice(0, -1);
121210
}

packages/@aws-cdk/aws-appsync/lib/schema-intermediate.ts

+13-37
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { shapeAddition } from './private';
12
import { Resolver } from './resolver';
23
import { Directive, IField, IIntermediateType } from './schema-base';
34
import { BaseTypeOptions, GraphqlType, ResolvableFieldOptions } from './schema-field';
@@ -59,13 +60,12 @@ export class InterfaceType implements IIntermediateType {
5960
* Generate the string of this object type
6061
*/
6162
public toString(): string {
62-
let schemaAddition = `interface ${this.name} {\n`;
63-
Object.keys(this.definition).forEach( (key) => {
64-
const attribute = this.definition[key];
65-
const args = attribute.argsToString();
66-
schemaAddition = `${schemaAddition} ${key}${args}: ${attribute.toString()}\n`;
63+
return shapeAddition({
64+
prefix: 'interface',
65+
name: this.name,
66+
fields: Object.keys(this.definition).map((key) =>
67+
`${key}${this.definition[key].argsToString()}: ${this.definition[key].toString()}`),
6768
});
68-
return `${schemaAddition}}`;
6969
}
7070

7171
/**
@@ -159,38 +159,14 @@ export class ObjectType extends InterfaceType implements IIntermediateType {
159159
* Generate the string of this object type
160160
*/
161161
public toString(): string {
162-
let title = this.name;
163-
if (this.interfaceTypes && this.interfaceTypes.length) {
164-
title = `${title} implements`;
165-
this.interfaceTypes.map((interfaceType) => {
166-
title = `${title} ${interfaceType.name},`;
167-
});
168-
title = title.slice(0, -1);
169-
}
170-
const directives = this.generateDirectives(this.directives);
171-
let schemaAddition = `type ${title} ${directives}{\n`;
172-
Object.keys(this.definition).forEach( (key) => {
173-
const attribute = this.definition[key];
174-
const args = attribute.argsToString();
175-
schemaAddition = `${schemaAddition} ${key}${args}: ${attribute.toString()}\n`;
176-
});
177-
return `${schemaAddition}}`;
178-
}
179-
180-
/**
181-
* Utility function to generate directives
182-
*
183-
* @param directives the directives of a given type
184-
* @param delimiter the separator betweeen directives
185-
* @default - ' '
186-
*/
187-
private generateDirectives(directives?: Directive[], delimiter?: string): string {
188-
let schemaAddition = '';
189-
if (!directives) { return schemaAddition; }
190-
directives.map((directive) => {
191-
schemaAddition = `${schemaAddition}${directive.statement}${delimiter ?? ' '}`;
162+
return shapeAddition({
163+
prefix: 'type',
164+
name: this.name,
165+
interfaceTypes: this.interfaceTypes,
166+
directives: this.directives,
167+
fields: Object.keys(this.definition).map((key) =>
168+
`${key}${this.definition[key].argsToString()}: ${this.definition[key].toString()}`),
192169
});
193-
return schemaAddition;
194170
}
195171

196172
/**

0 commit comments

Comments
 (0)