UNPKG

3.89 kBJavaScriptView Raw
1import { extname } from 'path';
2import { removeFederation } from '@graphql-codegen/plugin-helpers';
3import { execute, parse } from 'graphql';
4const extensions = {
5 ts: ['.ts', '.tsx'],
6 js: ['.js', '.jsx'],
7 json: ['.json'],
8};
9export const plugin = async (schema, _documents, pluginConfig, info) => {
10 const config = {
11 module: 'es2015',
12 federation: false,
13 apolloClientVersion: 3,
14 useExplicitTyping: false,
15 ...pluginConfig,
16 };
17 const apolloClientVersion = parseInt(config.apolloClientVersion);
18 const cleanSchema = config.federation ? removeFederation(schema) : schema;
19 const { useExplicitTyping } = config;
20 const introspection = (await execute({
21 schema: cleanSchema,
22 document: parse(`
23 {
24 __schema {
25 types {
26 kind
27 name
28 possibleTypes {
29 name
30 }
31 }
32 }
33 }
34 `),
35 }));
36 const ext = extname(info.outputFile).toLowerCase();
37 if (!introspection.data) {
38 throw new Error(`Plugin "fragment-matcher" couldn't introspect the schema`);
39 }
40 const filterUnionAndInterfaceTypes = type => type.kind === 'UNION' || type.kind === 'INTERFACE';
41 const createPossibleTypesCollection = (acc, type) => {
42 return { ...acc, ...{ [type.name]: type.possibleTypes.map(possibleType => possibleType.name) } };
43 };
44 const filteredData = apolloClientVersion === 2
45 ? {
46 __schema: {
47 ...introspection.data.__schema,
48 types: introspection.data.__schema.types.filter(type => type.kind === 'UNION' || type.kind === 'INTERFACE'),
49 },
50 }
51 : {
52 possibleTypes: introspection.data.__schema.types
53 .filter(filterUnionAndInterfaceTypes)
54 .reduce(createPossibleTypesCollection, {}),
55 };
56 const content = JSON.stringify(filteredData, null, 2);
57 if (extensions.json.includes(ext)) {
58 return content;
59 }
60 if (extensions.js.includes(ext)) {
61 const defaultExportStatement = config.module === 'es2015' ? `export default` : 'module.exports =';
62 return `
63 ${defaultExportStatement} ${content}
64 `;
65 }
66 if (extensions.ts.includes(ext)) {
67 let typename;
68 if (apolloClientVersion === 2) {
69 typename = `IntrospectionResultData`;
70 }
71 else if (apolloClientVersion === 3) {
72 typename = `PossibleTypesResultData`;
73 }
74 let type;
75 if (useExplicitTyping) {
76 type = `export type ${typename} = ${content};`;
77 }
78 else if (apolloClientVersion === 2) {
79 type = `export interface ${typename} {
80 __schema: {
81 types: {
82 kind: string;
83 name: string;
84 possibleTypes: {
85 name: string;
86 }[];
87 }[];
88 };
89 }`;
90 }
91 else if (apolloClientVersion === 3) {
92 type = `export interface ${typename} {
93 possibleTypes: {
94 [key: string]: string[]
95 }
96 }`;
97 }
98 return `
99 ${type}
100 const result: ${typename} = ${content};
101 export default result;
102 `;
103 }
104 throw new Error(`Extension ${ext} is not supported`);
105};
106export const validate = async (_schema, _documents, config, outputFile) => {
107 const ext = extname(outputFile).toLowerCase();
108 const all = Object.values(extensions).reduce((acc, exts) => [...acc, ...exts], []);
109 if (!all.includes(ext)) {
110 throw new Error(`Plugin "fragment-matcher" requires extension to be one of ${all.map(val => val.replace('.', '')).join(', ')}!`);
111 }
112 if (config.module === 'commonjs' && extensions.ts.includes(ext)) {
113 throw new Error(`Plugin "fragment-matcher" doesn't support commonjs modules combined with TypeScript!`);
114 }
115};