/
index.ts
73 lines (61 loc) · 3.14 KB
/
index.ts
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
import { printSchemaWithDirectives } from '@graphql-toolkit/common';
import { parse, GraphQLSchema, DefinitionNode } from 'graphql';
import { Types, PluginFunction } from '@graphql-codegen/plugin-helpers';
import { transformASTSchema, Parser as RelayParser } from 'relay-compiler';
import * as SkipRedundantNodesTransform from 'relay-compiler/lib/transforms/SkipRedundantNodesTransform';
import * as InlineFragmentsTransform from 'relay-compiler/lib/transforms/InlineFragmentsTransform';
import * as ApplyFragmentArgumentTransform from 'relay-compiler/lib/transforms/ApplyFragmentArgumentTransform';
import * as FlattenTransform from 'relay-compiler/lib/transforms/FlattenTransform';
const RelayCreate = require('relay-compiler/lib/core/Schema');
const GraphQLCompilerContext = require('relay-compiler/lib/core/GraphQLCompilerContext');
const { print } = require('relay-compiler/lib/core/GraphQLIRPrinter');
// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface RelayOptimizerPluginConfig {}
export const plugin: PluginFunction<RelayOptimizerPluginConfig> = (
schema: GraphQLSchema,
documents: Types.DocumentFile[],
// eslint-disable-next-line @typescript-eslint/no-unused-vars
config: RelayOptimizerPluginConfig
) => {
// @TODO way for users to define directives they use, otherwise relay will throw an unknown directive error
// Maybe we can scan the queries and add them dynamically without users having to do some extra stuff
// transformASTSchema creates a new schema instance instead of mutating the old one
const adjustedSchema = RelayCreate.create(
printSchemaWithDirectives(
transformASTSchema(schema, [
/* GraphQL */ `
directive @connection(key: String!) on FIELD
directive @client on FIELD
`,
])
)
);
const documentAsts = documents.reduce((prev, v) => {
return [...prev, ...v.content.definitions];
}, [] as DefinitionNode[]);
const relayDocuments = RelayParser.transform(adjustedSchema, documentAsts);
const fragmentCompilerContext = new GraphQLCompilerContext(adjustedSchema).addAll(relayDocuments);
const fragmentDocuments = fragmentCompilerContext
.applyTransforms([ApplyFragmentArgumentTransform.transform, FlattenTransform.transformWithOptions({ flattenAbstractTypes: false }), SkipRedundantNodesTransform.transform])
.documents()
.filter(doc => doc.kind === 'Fragment');
const queryCompilerContext = new GraphQLCompilerContext(adjustedSchema)
.addAll(relayDocuments)
.applyTransforms([ApplyFragmentArgumentTransform.transform, InlineFragmentsTransform.transform, FlattenTransform.transformWithOptions({ flattenAbstractTypes: false }), SkipRedundantNodesTransform.transform]);
const newQueryDocuments = queryCompilerContext.documents().map(doc => ({
filePath: 'optimized by relay',
content: parse(print(adjustedSchema, doc)),
}));
const newDocuments = [
...fragmentDocuments.map(doc => ({
filePath: 'optimized by relay',
content: parse(print(adjustedSchema, doc)),
})),
...newQueryDocuments,
];
documents.splice(0, documents.length);
documents.push(...newDocuments);
return {
content: '',
};
};