-
Notifications
You must be signed in to change notification settings - Fork 190
Expand file tree
/
Copy pathSchema.ts
More file actions
96 lines (86 loc) · 2.53 KB
/
Schema.ts
File metadata and controls
96 lines (86 loc) · 2.53 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
import globby from 'globby';
import fs from 'fs';
import path from 'path';
import { CfnResources } from '../types/cloudFormation';
import { Api } from './Api';
import { flatten } from 'lodash';
import { parse, print } from 'graphql';
import { validateSDL } from 'graphql/validation/validate';
import { mergeTypeDefs } from '@graphql-tools/merge';
const AWS_TYPES = `
directive @aws_iam on FIELD_DEFINITION | OBJECT
directive @aws_oidc on FIELD_DEFINITION | OBJECT
directive @aws_api_key on FIELD_DEFINITION | OBJECT
directive @aws_lambda on FIELD_DEFINITION | OBJECT
directive @aws_auth(cognito_groups: [String]) on FIELD_DEFINITION | OBJECT
directive @aws_cognito_user_pools(
cognito_groups: [String]
) on FIELD_DEFINITION | OBJECT
directive @aws_subscribe(mutations: [String]) on FIELD_DEFINITION
directive @canonical on OBJECT
directive @hidden on OBJECT
directive @renamed on OBJECT
scalar AWSDate
scalar AWSTime
scalar AWSDateTime
scalar AWSTimestamp
scalar AWSEmail
scalar AWSJSON
scalar AWSURL
scalar AWSPhone
scalar AWSIPAddress
`;
export class Schema {
constructor(private api: Api, private schemas: string[]) {}
compile(): CfnResources {
const logicalId = this.api.naming.getSchemaLogicalId();
return {
[logicalId]: {
Type: 'AWS::AppSync::GraphQLSchema',
Properties: {
Definition: this.generateSchema(),
ApiId: this.api.getApiId(),
},
},
};
}
valdiateSchema(schema: string) {
const errors = validateSDL(parse(schema));
if (errors.length > 0) {
throw new this.api.plugin.serverless.classes.Error(
'Invalid GraphQL schema:\n' +
errors.map((error) => ` ${error.message}`).join('\n'),
);
}
}
generateSchema() {
const schemaFiles = flatten(
globby.sync(
this.schemas.map((schema) =>
path
.join(this.api.plugin.serverless.config.servicePath, schema)
.replace(/\\/g, '/'),
),
),
);
const schemas = schemaFiles.map((file) => {
return fs.readFileSync(file, 'utf8');
});
this.valdiateSchema(AWS_TYPES + '\n' + schemas.join('\n'));
// Return single files as-is.
if (schemas.length === 1) {
return schemas[0];
}
// AppSync does not support Object extensions
// https://spec.graphql.org/October2021/#sec-Object-Extensions
// Merge the schemas
return print(
mergeTypeDefs(schemas, {
forceSchemaDefinition: false,
useSchemaDefinition: false,
sort: true,
throwOnConflict: true,
}),
);
}
}