@khanacademy/graphql-flow 0.3.0 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/pr-checks.yml +4 -6
- package/CHANGELOG.md +22 -0
- package/Readme.md +41 -167
- package/dist/__test__/example-schema.graphql +67 -0
- package/dist/__test__/generateTypeFileContents.test.js +157 -0
- package/dist/__test__/graphql-flow.test.js +639 -0
- package/dist/__test__/processPragmas.test.js +76 -0
- package/dist/cli/__test__/config.test.js +120 -0
- package/dist/cli/config.js +45 -106
- package/dist/cli/config.js.flow +37 -159
- package/dist/cli/config.js.map +1 -1
- package/dist/cli/run.js +40 -36
- package/dist/cli/run.js.flow +56 -42
- package/dist/cli/run.js.map +1 -1
- package/dist/cli/schema.json +91 -0
- package/dist/enums.js +9 -9
- package/dist/enums.js.flow +11 -11
- package/dist/enums.js.map +1 -1
- package/dist/generateResponseType.js +47 -47
- package/dist/generateResponseType.js.flow +55 -57
- package/dist/generateResponseType.js.map +1 -1
- package/dist/generateTypeFiles.js +13 -17
- package/dist/generateTypeFiles.js.flow +21 -43
- package/dist/generateTypeFiles.js.map +1 -1
- package/dist/generateVariablesType.js +24 -24
- package/dist/generateVariablesType.js.flow +25 -28
- package/dist/generateVariablesType.js.map +1 -1
- package/dist/index.js +0 -8
- package/dist/index.js.flow +4 -5
- package/dist/index.js.map +1 -1
- package/dist/parser/__test__/parse.test.js +247 -0
- package/dist/types.js.flow +26 -6
- package/package.json +3 -2
- package/src/__test__/generateTypeFileContents.test.js +3 -1
- package/src/__test__/graphql-flow.test.js +7 -7
- package/src/__test__/processPragmas.test.js +28 -15
- package/src/cli/__test__/config.test.js +110 -84
- package/src/cli/config.js +37 -159
- package/src/cli/run.js +56 -42
- package/src/cli/schema.json +91 -0
- package/src/enums.js +11 -11
- package/src/generateResponseType.js +55 -57
- package/src/generateTypeFiles.js +21 -43
- package/src/generateVariablesType.js +25 -28
- package/src/index.js +4 -5
- package/src/types.js +26 -6
- package/dist/cli/utils.js +0 -21
- package/dist/cli/utils.js.flow +0 -14
- package/dist/cli/utils.js.map +0 -1
- package/dist/jest-mock-graphql-tag.js +0 -88
- package/dist/jest-mock-graphql-tag.js.flow +0 -96
- package/dist/jest-mock-graphql-tag.js.map +0 -1
- package/src/cli/__test__/utils.test.js +0 -19
- package/src/cli/utils.js +0 -14
- package/src/jest-mock-graphql-tag.js +0 -96
|
@@ -8,7 +8,7 @@ import * as babelTypes from '@babel/types';
|
|
|
8
8
|
import type {OperationDefinitionNode, TypeNode} from 'graphql/language/ast';
|
|
9
9
|
import type {IntrospectionInputTypeRef} from 'graphql/utilities/introspectionQuery';
|
|
10
10
|
import {builtinScalars, enumTypeToFlow, scalarTypeToFlow} from './enums';
|
|
11
|
-
import type {
|
|
11
|
+
import type {Context, Schema} from './types';
|
|
12
12
|
import {
|
|
13
13
|
liftLeadingPropertyComments,
|
|
14
14
|
maybeAddDescriptionComment,
|
|
@@ -16,12 +16,12 @@ import {
|
|
|
16
16
|
} from './utils';
|
|
17
17
|
|
|
18
18
|
export const inputObjectToFlow = (
|
|
19
|
-
|
|
19
|
+
ctx: Context,
|
|
20
20
|
name: string,
|
|
21
21
|
): BabelNodeFlowType => {
|
|
22
|
-
const inputObject =
|
|
22
|
+
const inputObject = ctx.schema.inputObjectsByName[name];
|
|
23
23
|
if (!inputObject) {
|
|
24
|
-
|
|
24
|
+
ctx.errors.push(`Unknown input object ${name}`);
|
|
25
25
|
return babelTypes.stringLiteralTypeAnnotation(
|
|
26
26
|
`Unknown input object ${name}`,
|
|
27
27
|
);
|
|
@@ -35,7 +35,7 @@ export const inputObjectToFlow = (
|
|
|
35
35
|
vbl.description,
|
|
36
36
|
maybeOptionalObjectTypeProperty(
|
|
37
37
|
vbl.name,
|
|
38
|
-
inputRefToFlow(
|
|
38
|
+
inputRefToFlow(ctx, vbl.type),
|
|
39
39
|
),
|
|
40
40
|
),
|
|
41
41
|
),
|
|
@@ -61,75 +61,72 @@ export const maybeOptionalObjectTypeProperty = (
|
|
|
61
61
|
};
|
|
62
62
|
|
|
63
63
|
export const inputRefToFlow = (
|
|
64
|
-
|
|
64
|
+
ctx: Context,
|
|
65
65
|
inputRef: IntrospectionInputTypeRef,
|
|
66
66
|
): BabelNodeFlowType => {
|
|
67
67
|
if (inputRef.kind === 'NON_NULL') {
|
|
68
|
-
return _inputRefToFlow(
|
|
68
|
+
return _inputRefToFlow(ctx, inputRef.ofType);
|
|
69
69
|
}
|
|
70
|
-
const result = _inputRefToFlow(
|
|
70
|
+
const result = _inputRefToFlow(ctx, inputRef);
|
|
71
71
|
return transferLeadingComments(
|
|
72
72
|
result,
|
|
73
73
|
babelTypes.nullableTypeAnnotation(result),
|
|
74
74
|
);
|
|
75
75
|
};
|
|
76
76
|
|
|
77
|
-
const _inputRefToFlow = (
|
|
78
|
-
config: Config,
|
|
79
|
-
inputRef: IntrospectionInputTypeRef,
|
|
80
|
-
) => {
|
|
77
|
+
const _inputRefToFlow = (ctx: Context, inputRef: IntrospectionInputTypeRef) => {
|
|
81
78
|
if (inputRef.kind === 'SCALAR') {
|
|
82
|
-
return scalarTypeToFlow(
|
|
79
|
+
return scalarTypeToFlow(ctx, inputRef.name);
|
|
83
80
|
}
|
|
84
81
|
if (inputRef.kind === 'ENUM') {
|
|
85
|
-
return enumTypeToFlow(
|
|
82
|
+
return enumTypeToFlow(ctx, inputRef.name);
|
|
86
83
|
}
|
|
87
84
|
if (inputRef.kind === 'INPUT_OBJECT') {
|
|
88
|
-
return inputObjectToFlow(
|
|
85
|
+
return inputObjectToFlow(ctx, inputRef.name);
|
|
89
86
|
}
|
|
90
87
|
if (inputRef.kind === 'LIST') {
|
|
91
88
|
return babelTypes.genericTypeAnnotation(
|
|
92
89
|
babelTypes.identifier('$ReadOnlyArray'),
|
|
93
90
|
babelTypes.typeParameterInstantiation([
|
|
94
|
-
inputRefToFlow(
|
|
91
|
+
inputRefToFlow(ctx, inputRef.ofType),
|
|
95
92
|
]),
|
|
96
93
|
);
|
|
97
94
|
}
|
|
98
95
|
return babelTypes.stringLiteralTypeAnnotation(JSON.stringify(inputRef));
|
|
99
96
|
};
|
|
100
97
|
|
|
101
|
-
const variableToFlow = (
|
|
98
|
+
const variableToFlow = (ctx: Context, type: TypeNode) => {
|
|
102
99
|
if (type.kind === 'NonNullType') {
|
|
103
|
-
return _variableToFlow(
|
|
100
|
+
return _variableToFlow(ctx, type.type);
|
|
104
101
|
}
|
|
105
|
-
const result = _variableToFlow(
|
|
102
|
+
const result = _variableToFlow(ctx, type);
|
|
106
103
|
return transferLeadingComments(
|
|
107
104
|
result,
|
|
108
105
|
babelTypes.nullableTypeAnnotation(result),
|
|
109
106
|
);
|
|
110
107
|
};
|
|
111
108
|
|
|
112
|
-
const _variableToFlow = (
|
|
109
|
+
const _variableToFlow = (ctx: Context, type: TypeNode) => {
|
|
113
110
|
if (type.kind === 'NamedType') {
|
|
114
111
|
if (builtinScalars[type.name.value]) {
|
|
115
|
-
return scalarTypeToFlow(
|
|
112
|
+
return scalarTypeToFlow(ctx, type.name.value);
|
|
116
113
|
}
|
|
117
|
-
if (
|
|
118
|
-
return enumTypeToFlow(
|
|
114
|
+
if (ctx.schema.enumsByName[type.name.value]) {
|
|
115
|
+
return enumTypeToFlow(ctx, type.name.value);
|
|
119
116
|
}
|
|
120
|
-
const customScalarType =
|
|
117
|
+
const customScalarType = ctx.scalars[type.name.value];
|
|
121
118
|
if (customScalarType) {
|
|
122
119
|
return babelTypes.genericTypeAnnotation(
|
|
123
120
|
babelTypes.identifier(customScalarType),
|
|
124
121
|
);
|
|
125
122
|
}
|
|
126
|
-
return inputObjectToFlow(
|
|
123
|
+
return inputObjectToFlow(ctx, type.name.value);
|
|
127
124
|
}
|
|
128
125
|
if (type.kind === 'ListType') {
|
|
129
126
|
return babelTypes.genericTypeAnnotation(
|
|
130
127
|
babelTypes.identifier('$ReadOnlyArray'),
|
|
131
128
|
babelTypes.typeParameterInstantiation([
|
|
132
|
-
variableToFlow(
|
|
129
|
+
variableToFlow(ctx, type.type),
|
|
133
130
|
]),
|
|
134
131
|
);
|
|
135
132
|
}
|
|
@@ -141,13 +138,13 @@ const _variableToFlow = (config: Config, type: TypeNode) => {
|
|
|
141
138
|
export const generateVariablesType = (
|
|
142
139
|
schema: Schema,
|
|
143
140
|
item: OperationDefinitionNode,
|
|
144
|
-
|
|
141
|
+
ctx: Context,
|
|
145
142
|
): string => {
|
|
146
143
|
const variableObject = babelTypes.objectTypeAnnotation(
|
|
147
144
|
(item.variableDefinitions || []).map((vbl) => {
|
|
148
145
|
return maybeOptionalObjectTypeProperty(
|
|
149
146
|
vbl.variable.name.value,
|
|
150
|
-
variableToFlow(
|
|
147
|
+
variableToFlow(ctx, vbl.type),
|
|
151
148
|
);
|
|
152
149
|
}),
|
|
153
150
|
undefined /* indexers */,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/generateVariablesType.js"],"names":["inputObjectToFlow","
|
|
1
|
+
{"version":3,"sources":["../src/generateVariablesType.js"],"names":["inputObjectToFlow","ctx","name","inputObject","schema","inputObjectsByName","errors","push","babelTypes","stringLiteralTypeAnnotation","description","objectTypeAnnotation","inputFields","map","vbl","maybeOptionalObjectTypeProperty","inputRefToFlow","type","undefined","prop","objectTypeProperty","identifier","optional","inputRef","kind","_inputRefToFlow","ofType","result","nullableTypeAnnotation","genericTypeAnnotation","typeParameterInstantiation","JSON","stringify","variableToFlow","_variableToFlow","builtinScalars","value","enumsByName","customScalarType","scalars","generateVariablesType","item","variableObject","variableDefinitions","variable","code"],"mappings":"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","sourcesContent":["// @flow\nimport generate from '@babel/generator'; // eslint-disable-line flowtype-errors/uncovered\nimport type {\n BabelNodeFlowType,\n BabelNodeObjectTypeProperty,\n} from '@babel/types';\nimport * as babelTypes from '@babel/types';\nimport type {OperationDefinitionNode, TypeNode} from 'graphql/language/ast';\nimport type {IntrospectionInputTypeRef} from 'graphql/utilities/introspectionQuery';\nimport {builtinScalars, enumTypeToFlow, scalarTypeToFlow} from './enums';\nimport type {Context, Schema} from './types';\nimport {\n liftLeadingPropertyComments,\n maybeAddDescriptionComment,\n transferLeadingComments,\n} from './utils';\n\nexport const inputObjectToFlow = (\n ctx: Context,\n name: string,\n): BabelNodeFlowType => {\n const inputObject = ctx.schema.inputObjectsByName[name];\n if (!inputObject) {\n ctx.errors.push(`Unknown input object ${name}`);\n return babelTypes.stringLiteralTypeAnnotation(\n `Unknown input object ${name}`,\n );\n }\n\n return maybeAddDescriptionComment(\n inputObject.description,\n babelTypes.objectTypeAnnotation(\n inputObject.inputFields.map((vbl) =>\n maybeAddDescriptionComment(\n vbl.description,\n maybeOptionalObjectTypeProperty(\n vbl.name,\n inputRefToFlow(ctx, vbl.type),\n ),\n ),\n ),\n undefined /* indexers */,\n undefined /* callProperties */,\n undefined /* internalSlots */,\n true /* exact */,\n ),\n );\n};\n\nexport const maybeOptionalObjectTypeProperty = (\n name: string,\n type: babelTypes.BabelNodeFlowType,\n): BabelNodeObjectTypeProperty => {\n const prop = liftLeadingPropertyComments(\n babelTypes.objectTypeProperty(babelTypes.identifier(name), type),\n );\n if (type.type === 'NullableTypeAnnotation') {\n prop.optional = true;\n }\n return prop;\n};\n\nexport const inputRefToFlow = (\n ctx: Context,\n inputRef: IntrospectionInputTypeRef,\n): BabelNodeFlowType => {\n if (inputRef.kind === 'NON_NULL') {\n return _inputRefToFlow(ctx, inputRef.ofType);\n }\n const result = _inputRefToFlow(ctx, inputRef);\n return transferLeadingComments(\n result,\n babelTypes.nullableTypeAnnotation(result),\n );\n};\n\nconst _inputRefToFlow = (ctx: Context, inputRef: IntrospectionInputTypeRef) => {\n if (inputRef.kind === 'SCALAR') {\n return scalarTypeToFlow(ctx, inputRef.name);\n }\n if (inputRef.kind === 'ENUM') {\n return enumTypeToFlow(ctx, inputRef.name);\n }\n if (inputRef.kind === 'INPUT_OBJECT') {\n return inputObjectToFlow(ctx, inputRef.name);\n }\n if (inputRef.kind === 'LIST') {\n return babelTypes.genericTypeAnnotation(\n babelTypes.identifier('$ReadOnlyArray'),\n babelTypes.typeParameterInstantiation([\n inputRefToFlow(ctx, inputRef.ofType),\n ]),\n );\n }\n return babelTypes.stringLiteralTypeAnnotation(JSON.stringify(inputRef));\n};\n\nconst variableToFlow = (ctx: Context, type: TypeNode) => {\n if (type.kind === 'NonNullType') {\n return _variableToFlow(ctx, type.type);\n }\n const result = _variableToFlow(ctx, type);\n return transferLeadingComments(\n result,\n babelTypes.nullableTypeAnnotation(result),\n );\n};\n\nconst _variableToFlow = (ctx: Context, type: TypeNode) => {\n if (type.kind === 'NamedType') {\n if (builtinScalars[type.name.value]) {\n return scalarTypeToFlow(ctx, type.name.value);\n }\n if (ctx.schema.enumsByName[type.name.value]) {\n return enumTypeToFlow(ctx, type.name.value);\n }\n const customScalarType = ctx.scalars[type.name.value];\n if (customScalarType) {\n return babelTypes.genericTypeAnnotation(\n babelTypes.identifier(customScalarType),\n );\n }\n return inputObjectToFlow(ctx, type.name.value);\n }\n if (type.kind === 'ListType') {\n return babelTypes.genericTypeAnnotation(\n babelTypes.identifier('$ReadOnlyArray'),\n babelTypes.typeParameterInstantiation([\n variableToFlow(ctx, type.type),\n ]),\n );\n }\n return babelTypes.stringLiteralTypeAnnotation(\n 'UNKNOWN' + JSON.stringify(type),\n );\n};\n\nexport const generateVariablesType = (\n schema: Schema,\n item: OperationDefinitionNode,\n ctx: Context,\n): string => {\n const variableObject = babelTypes.objectTypeAnnotation(\n (item.variableDefinitions || []).map((vbl) => {\n return maybeOptionalObjectTypeProperty(\n vbl.variable.name.value,\n variableToFlow(ctx, vbl.type),\n );\n }),\n undefined /* indexers */,\n undefined /* callProperties */,\n undefined /* internalSlots */,\n true /* exact */,\n );\n return generate(variableObject).code; // eslint-disable-line flowtype-errors/uncovered\n};\n"],"file":"generateVariablesType.js"}
|
package/dist/index.js
CHANGED
|
@@ -4,12 +4,6 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.documentToFlowTypes = exports.FlowGenerationError = void 0;
|
|
7
|
-
Object.defineProperty(exports, "spyOnGraphqlTagToCollectQueries", {
|
|
8
|
-
enumerable: true,
|
|
9
|
-
get: function () {
|
|
10
|
-
return _jestMockGraphqlTag.spyOnGraphqlTagToCollectQueries;
|
|
11
|
-
}
|
|
12
|
-
});
|
|
13
7
|
|
|
14
8
|
var _generator = _interopRequireDefault(require("@babel/generator"));
|
|
15
9
|
|
|
@@ -17,8 +11,6 @@ var _generateResponseType = require("./generateResponseType");
|
|
|
17
11
|
|
|
18
12
|
var _generateVariablesType = require("./generateVariablesType");
|
|
19
13
|
|
|
20
|
-
var _jestMockGraphqlTag = require("./jest-mock-graphql-tag");
|
|
21
|
-
|
|
22
14
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
23
15
|
|
|
24
16
|
/* eslint-disable no-console */
|
package/dist/index.js.flow
CHANGED
|
@@ -16,16 +16,15 @@ import {
|
|
|
16
16
|
} from './generateResponseType';
|
|
17
17
|
import {generateVariablesType} from './generateVariablesType';
|
|
18
18
|
import type {BabelNode} from '@babel/types';
|
|
19
|
-
export {spyOnGraphqlTagToCollectQueries} from './jest-mock-graphql-tag';
|
|
20
19
|
|
|
21
|
-
import type {
|
|
20
|
+
import type {Context, Schema, GenerateConfig} from './types';
|
|
22
21
|
|
|
23
22
|
const optionsToConfig = (
|
|
24
23
|
schema: Schema,
|
|
25
24
|
definitions: $ReadOnlyArray<DefinitionNode>,
|
|
26
|
-
options?:
|
|
25
|
+
options?: GenerateConfig,
|
|
27
26
|
errors: Array<string> = [],
|
|
28
|
-
):
|
|
27
|
+
): Context => {
|
|
29
28
|
const internalOptions = {
|
|
30
29
|
strictNullability: options?.strictNullability ?? true,
|
|
31
30
|
readOnlyArray: options?.readOnlyArray ?? true,
|
|
@@ -61,7 +60,7 @@ export class FlowGenerationError extends Error {
|
|
|
61
60
|
export const documentToFlowTypes = (
|
|
62
61
|
document: DocumentNode,
|
|
63
62
|
schema: Schema,
|
|
64
|
-
options?:
|
|
63
|
+
options?: GenerateConfig,
|
|
65
64
|
): $ReadOnlyArray<{
|
|
66
65
|
name: string,
|
|
67
66
|
typeName: string,
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.js"],"names":["optionsToConfig","schema","definitions","options","errors","internalOptions","strictNullability","readOnlyArray","scalars","fragments","forEach","def","kind","name","value","config","allObjectTypes","path","experimentalEnumsMap","experimentalEnums","undefined","FlowGenerationError","Error","constructor","join","messages","documentToFlowTypes","document","result","map","item","types","code","exportAllObjectTypes","extraTypes","codegenExtraTypes","typeName","isFragment","operation","response","variables","filter","Boolean","length","Object","keys","k"],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../src/index.js"],"names":["optionsToConfig","schema","definitions","options","errors","internalOptions","strictNullability","readOnlyArray","scalars","fragments","forEach","def","kind","name","value","config","allObjectTypes","path","experimentalEnumsMap","experimentalEnums","undefined","FlowGenerationError","Error","constructor","join","messages","documentToFlowTypes","document","result","map","item","types","code","exportAllObjectTypes","extraTypes","codegenExtraTypes","typeName","isFragment","operation","response","variables","filter","Boolean","length","Object","keys","k"],"mappings":"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","sourcesContent":["/* eslint-disable no-console */\n/* flow-uncovered-file */\n// @flow\n/**\n * This tool generates flowtype definitions from graphql queries.\n *\n * It relies on `introspection-query.json` existing in this directory,\n * which is produced by running `./tools/graphql-flow/sendIntrospection.js`.\n */\nimport type {DefinitionNode, DocumentNode} from 'graphql';\n\nimport generate from '@babel/generator'; // eslint-disable-line flowtype-errors/uncovered\nimport {\n generateFragmentType,\n generateResponseType,\n} from './generateResponseType';\nimport {generateVariablesType} from './generateVariablesType';\nimport type {BabelNode} from '@babel/types';\n\nimport type {Context, Schema, GenerateConfig} from './types';\n\nconst optionsToConfig = (\n schema: Schema,\n definitions: $ReadOnlyArray<DefinitionNode>,\n options?: GenerateConfig,\n errors: Array<string> = [],\n): Context => {\n const internalOptions = {\n strictNullability: options?.strictNullability ?? true,\n readOnlyArray: options?.readOnlyArray ?? true,\n scalars: options?.scalars ?? {},\n };\n const fragments = {};\n definitions.forEach((def) => {\n if (def.kind === 'FragmentDefinition') {\n fragments[def.name.value] = def;\n }\n });\n const config = {\n fragments,\n schema,\n errors,\n allObjectTypes: null,\n path: [],\n experimentalEnumsMap: options?.experimentalEnums ? {} : undefined,\n ...internalOptions,\n };\n\n return config;\n};\n\nexport class FlowGenerationError extends Error {\n messages: Array<string>;\n constructor(errors: Array<string>) {\n super(`Graphql-flow type generation failed! ${errors.join('; ')}`);\n this.messages = errors;\n }\n}\n\nexport const documentToFlowTypes = (\n document: DocumentNode,\n schema: Schema,\n options?: GenerateConfig,\n): $ReadOnlyArray<{\n name: string,\n typeName: string,\n code: string,\n isFragment?: boolean,\n extraTypes: {[key: string]: string},\n experimentalEnums: {[key: string]: string},\n}> => {\n const errors: Array<string> = [];\n const config = optionsToConfig(\n schema,\n document.definitions,\n options,\n errors,\n );\n const result = document.definitions\n .map((item) => {\n if (item.kind === 'FragmentDefinition') {\n const name = item.name.value;\n const types = {};\n const code = `export type ${name} = ${generateFragmentType(\n schema,\n item,\n {\n ...config,\n path: [name],\n allObjectTypes: options?.exportAllObjectTypes\n ? types\n : null,\n },\n )};`;\n\n const extraTypes = codegenExtraTypes(types);\n const experimentalEnums = codegenExtraTypes(\n config.experimentalEnumsMap || {},\n );\n\n return {\n name,\n typeName: name,\n code,\n isFragment: true,\n extraTypes,\n experimentalEnums,\n };\n }\n if (\n item.kind === 'OperationDefinition' &&\n (item.operation === 'query' || item.operation === 'mutation') &&\n item.name\n ) {\n const types = {};\n const name = item.name.value;\n const response = generateResponseType(schema, item, {\n ...config,\n path: [name],\n allObjectTypes: options?.exportAllObjectTypes\n ? types\n : null,\n });\n const variables = generateVariablesType(schema, item, {\n ...config,\n path: [name],\n });\n\n const typeName = `${name}Type`;\n // TODO(jared): Maybe make this template configurable?\n // We'll see what's required to get webapp on board.\n const code = `export type ${typeName} = {|\\n variables: ${variables},\\n response: ${response}\\n|};`;\n\n const extraTypes = codegenExtraTypes(types);\n const experimentalEnums = codegenExtraTypes(\n config.experimentalEnumsMap || {},\n );\n\n return {name, typeName, code, extraTypes, experimentalEnums};\n }\n })\n .filter(Boolean);\n if (errors.length) {\n throw new FlowGenerationError(errors);\n }\n return result;\n};\n\nfunction codegenExtraTypes(types: {[key: string]: BabelNode}): {\n [key: string]: string,\n} {\n const extraTypes: {[key: string]: string} = {};\n Object.keys(types).forEach((k: string) => {\n // eslint-disable-next-line flowtype-errors/uncovered\n extraTypes[k] = generate(types[k]).code;\n });\n return extraTypes;\n}\n"],"file":"index.js"}
|
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
// @flow
|
|
2
|
+
|
|
3
|
+
import {processFiles} from '../parse';
|
|
4
|
+
import {resolveDocuments} from '../resolve';
|
|
5
|
+
|
|
6
|
+
import {print} from 'graphql/language/printer';
|
|
7
|
+
|
|
8
|
+
const fixtureFiles: {[key: string]: string} = {
|
|
9
|
+
'/firstFile.js': `
|
|
10
|
+
// Note that you can import graphql-tag as
|
|
11
|
+
// something other than gql.
|
|
12
|
+
import tagme from 'graphql-tag';
|
|
13
|
+
|
|
14
|
+
// Some complex syntax
|
|
15
|
+
const {x} = {x: 10}
|
|
16
|
+
|
|
17
|
+
const notExported = tagme\`
|
|
18
|
+
fragment Something on Otherthing {
|
|
19
|
+
notExportedAttr
|
|
20
|
+
}
|
|
21
|
+
\`;
|
|
22
|
+
|
|
23
|
+
export const fromFirstFile = tagme\`
|
|
24
|
+
fragment FromFirstFile on Something {
|
|
25
|
+
firstFile
|
|
26
|
+
}
|
|
27
|
+
\`;
|
|
28
|
+
|
|
29
|
+
export const alsoFirst = tagme\`
|
|
30
|
+
fragment AlsoFromFirst on Something {
|
|
31
|
+
name
|
|
32
|
+
}
|
|
33
|
+
\`;`,
|
|
34
|
+
|
|
35
|
+
'/secondFile.js': `
|
|
36
|
+
import gql from 'graphql-tag';
|
|
37
|
+
import {fromFirstFile} from './firstFile.js';
|
|
38
|
+
// This import won't be followed, because it's not exported
|
|
39
|
+
// or used in any graphql documents.
|
|
40
|
+
import hello from './someOtherFile.js';
|
|
41
|
+
// Re-exporting a fragment!
|
|
42
|
+
export {fromFirstFile}
|
|
43
|
+
export {alsoFirst} from './firstFile.js';
|
|
44
|
+
|
|
45
|
+
const secondFragment = gql\`
|
|
46
|
+
fragment SecondFragment on Thing {
|
|
47
|
+
secondAttribute
|
|
48
|
+
}
|
|
49
|
+
\`;
|
|
50
|
+
export {secondFragment};`,
|
|
51
|
+
|
|
52
|
+
'/thirdFile.js': `
|
|
53
|
+
import {fromFirstFile, alsoFirst, secondFragment} from './secondFile.js';
|
|
54
|
+
import gql from 'graphql-tag';
|
|
55
|
+
import type {someType} from './somePlace';
|
|
56
|
+
|
|
57
|
+
export const renamedSecond = secondFragment;
|
|
58
|
+
|
|
59
|
+
const otherTemplate = styled\`lets do this\`;
|
|
60
|
+
|
|
61
|
+
const myQuery = gql\`
|
|
62
|
+
query Some {
|
|
63
|
+
hello
|
|
64
|
+
...FromFirstFile
|
|
65
|
+
...AlsoFromFirst
|
|
66
|
+
}
|
|
67
|
+
\${fromFirstFile}
|
|
68
|
+
\${alsoFirst}
|
|
69
|
+
\`;
|
|
70
|
+
|
|
71
|
+
export const runInlineQuery = () => {
|
|
72
|
+
// Here's a fragment defined inline!
|
|
73
|
+
const anotherFragment = gql\`fragment Hello on Something { id }\`;
|
|
74
|
+
|
|
75
|
+
return gql\`
|
|
76
|
+
query InlineQuery {
|
|
77
|
+
hello
|
|
78
|
+
|
|
79
|
+
ok {
|
|
80
|
+
...Hello
|
|
81
|
+
...FromFirstFile
|
|
82
|
+
}
|
|
83
|
+
...SecondFragment
|
|
84
|
+
}
|
|
85
|
+
\${anotherFragment}
|
|
86
|
+
\${fromFirstFile}
|
|
87
|
+
\${renamedSecond}
|
|
88
|
+
\`;
|
|
89
|
+
}`,
|
|
90
|
+
|
|
91
|
+
'/invalidThings.js': `
|
|
92
|
+
import gql from 'graphql-tag';
|
|
93
|
+
// Importing a fragment from an npm module is invalid.
|
|
94
|
+
import someExternalFragment from 'somewhere';
|
|
95
|
+
|
|
96
|
+
const myQuery = gql\`
|
|
97
|
+
query Hello {
|
|
98
|
+
id
|
|
99
|
+
}
|
|
100
|
+
\${someExternalFragment}
|
|
101
|
+
\${someUndefinedFragment}
|
|
102
|
+
// Fancy fragment expressions not supported
|
|
103
|
+
\${2 + 3}
|
|
104
|
+
\`;
|
|
105
|
+
`,
|
|
106
|
+
|
|
107
|
+
'/circular.js': `
|
|
108
|
+
import gql from 'graphql-tag';
|
|
109
|
+
export {otherThing} from './invalidReferences.js';
|
|
110
|
+
import {one} from './invalidReferences.js';
|
|
111
|
+
export const two = gql\`
|
|
112
|
+
fragment Two {
|
|
113
|
+
id
|
|
114
|
+
}
|
|
115
|
+
\${one}
|
|
116
|
+
\`;
|
|
117
|
+
`,
|
|
118
|
+
|
|
119
|
+
'/invalidReferences.js': `
|
|
120
|
+
import gql from 'graphql-tag';
|
|
121
|
+
import {otherThing, two, doesntExist} from './circular.js';
|
|
122
|
+
// 'otherThing' is imported circularly
|
|
123
|
+
export {otherThing}
|
|
124
|
+
const ok = gql\`
|
|
125
|
+
query Hello {
|
|
126
|
+
...Ok
|
|
127
|
+
}
|
|
128
|
+
\${otherThing}
|
|
129
|
+
\${doesntExist}
|
|
130
|
+
\`;
|
|
131
|
+
|
|
132
|
+
// fragments 'one' & 'two' depend on each other
|
|
133
|
+
export const one = gql\`
|
|
134
|
+
fragment One {
|
|
135
|
+
...Ok
|
|
136
|
+
}
|
|
137
|
+
\${two}
|
|
138
|
+
\`;
|
|
139
|
+
`,
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
const getFileSource = (name: string) => {
|
|
143
|
+
if (!fixtureFiles[name]) {
|
|
144
|
+
throw new Error(`No file ${name}`);
|
|
145
|
+
}
|
|
146
|
+
return fixtureFiles[name];
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
describe('processing fragments in various ways', () => {
|
|
150
|
+
it('should work', () => {
|
|
151
|
+
const files = processFiles(['/thirdFile.js'], getFileSource);
|
|
152
|
+
Object.keys(files).forEach((k) => {
|
|
153
|
+
expect(files[k].errors).toEqual([]);
|
|
154
|
+
});
|
|
155
|
+
const {resolved, errors} = resolveDocuments(files);
|
|
156
|
+
expect(errors).toEqual([]);
|
|
157
|
+
const printed = {};
|
|
158
|
+
Object.keys(resolved).map(
|
|
159
|
+
(k) => (printed[k] = print(resolved[k].document).trim()),
|
|
160
|
+
);
|
|
161
|
+
expect(printed).toMatchInlineSnapshot(`
|
|
162
|
+
Object {
|
|
163
|
+
"/firstFile.js:15": "fragment FromFirstFile on Something {
|
|
164
|
+
firstFile
|
|
165
|
+
}",
|
|
166
|
+
"/firstFile.js:21": "fragment AlsoFromFirst on Something {
|
|
167
|
+
name
|
|
168
|
+
}",
|
|
169
|
+
"/firstFile.js:9": "fragment Something on Otherthing {
|
|
170
|
+
notExportedAttr
|
|
171
|
+
}",
|
|
172
|
+
"/secondFile.js:11": "fragment SecondFragment on Thing {
|
|
173
|
+
secondAttribute
|
|
174
|
+
}",
|
|
175
|
+
"/thirdFile.js:10": "query Some {
|
|
176
|
+
hello
|
|
177
|
+
...FromFirstFile
|
|
178
|
+
...AlsoFromFirst
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
fragment FromFirstFile on Something {
|
|
182
|
+
firstFile
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
fragment AlsoFromFirst on Something {
|
|
186
|
+
name
|
|
187
|
+
}",
|
|
188
|
+
"/thirdFile.js:22": "fragment Hello on Something {
|
|
189
|
+
id
|
|
190
|
+
}",
|
|
191
|
+
"/thirdFile.js:24": "query InlineQuery {
|
|
192
|
+
hello
|
|
193
|
+
ok {
|
|
194
|
+
...Hello
|
|
195
|
+
...FromFirstFile
|
|
196
|
+
}
|
|
197
|
+
...SecondFragment
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
fragment Hello on Something {
|
|
201
|
+
id
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
fragment FromFirstFile on Something {
|
|
205
|
+
firstFile
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
fragment SecondFragment on Thing {
|
|
209
|
+
secondAttribute
|
|
210
|
+
}",
|
|
211
|
+
}
|
|
212
|
+
`);
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
it('should flag things it doesnt support', () => {
|
|
216
|
+
const files = processFiles(['/invalidThings.js'], getFileSource);
|
|
217
|
+
expect(files['/invalidThings.js'].errors.map((m) => m.message))
|
|
218
|
+
.toMatchInlineSnapshot(`
|
|
219
|
+
Array [
|
|
220
|
+
"Unable to resolve someExternalFragment",
|
|
221
|
+
"Unable to resolve someUndefinedFragment",
|
|
222
|
+
"Template literal interpolation must be an identifier",
|
|
223
|
+
]
|
|
224
|
+
`);
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
it('should flag resolution errors', () => {
|
|
228
|
+
const files = processFiles(['/invalidReferences.js'], getFileSource);
|
|
229
|
+
Object.keys(files).forEach((k) => {
|
|
230
|
+
expect(files[k].errors).toEqual([]);
|
|
231
|
+
});
|
|
232
|
+
const {resolved, errors} = resolveDocuments(files);
|
|
233
|
+
expect(errors.map((m) => m.message)).toMatchInlineSnapshot(`
|
|
234
|
+
Array [
|
|
235
|
+
"Circular import /circular.js -> /invalidReferences.js -> /circular.js",
|
|
236
|
+
"/circular.js has no valid gql export doesntExist",
|
|
237
|
+
"Recursive template dependency! /invalidReferences.js:15 ~ 1,2 -> /circular.js:5 ~ 1,2 -> /invalidReferences.js:15",
|
|
238
|
+
"Recursive template dependency! /circular.js:5 ~ 1,2 -> /invalidReferences.js:15 ~ 1,2 -> /circular.js:5",
|
|
239
|
+
]
|
|
240
|
+
`);
|
|
241
|
+
const printed = {};
|
|
242
|
+
Object.keys(resolved).map(
|
|
243
|
+
(k) => (printed[k] = print(resolved[k].document).trim()),
|
|
244
|
+
);
|
|
245
|
+
expect(printed).toMatchInlineSnapshot(`Object {}`);
|
|
246
|
+
});
|
|
247
|
+
});
|
package/dist/types.js.flow
CHANGED
|
@@ -14,18 +14,38 @@ import type {
|
|
|
14
14
|
|
|
15
15
|
export type Selections = $ReadOnlyArray<SelectionNode>;
|
|
16
16
|
|
|
17
|
-
export type
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
17
|
+
export type GenerateConfig = {|
|
|
18
|
+
schemaFilePath: string,
|
|
19
|
+
match?: Array<RegExp | string>,
|
|
20
|
+
exclude?: Array<RegExp | string>,
|
|
21
|
+
|
|
21
22
|
scalars?: Scalars,
|
|
23
|
+
strictNullability?: boolean,
|
|
24
|
+
/**
|
|
25
|
+
* The command that users should run to regenerate the types files.
|
|
26
|
+
*/
|
|
27
|
+
regenerateCommand?: string,
|
|
28
|
+
readOnlyArray?: boolean,
|
|
22
29
|
splitTypes?: boolean,
|
|
23
30
|
generatedDirectory?: string,
|
|
24
31
|
exportAllObjectTypes?: boolean,
|
|
25
32
|
typeFileName?: string,
|
|
26
|
-
experimentalEnums?: boolean,
|
|
33
|
+
experimentalEnums?: boolean,
|
|
27
34
|
|};
|
|
28
35
|
|
|
36
|
+
export type CrawlConfig = {
|
|
37
|
+
root: string,
|
|
38
|
+
pragma?: string,
|
|
39
|
+
loosePragma?: string,
|
|
40
|
+
ignorePragma?: string,
|
|
41
|
+
dumpOperations?: string,
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
export type Config = {
|
|
45
|
+
crawl: CrawlConfig,
|
|
46
|
+
generate: GenerateConfig | Array<GenerateConfig>,
|
|
47
|
+
};
|
|
48
|
+
|
|
29
49
|
export type Schema = {
|
|
30
50
|
interfacesByName: {
|
|
31
51
|
[key: string]: IntrospectionInterfaceType & {
|
|
@@ -49,7 +69,7 @@ export type Schema = {
|
|
|
49
69
|
},
|
|
50
70
|
};
|
|
51
71
|
|
|
52
|
-
export type
|
|
72
|
+
export type Context = {
|
|
53
73
|
path: Array<string>,
|
|
54
74
|
strictNullability: boolean,
|
|
55
75
|
readOnlyArray: boolean,
|
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@khanacademy/graphql-flow",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"bin": {
|
|
5
5
|
"graphql-flow": "./dist/cli/run.js"
|
|
6
6
|
},
|
|
7
7
|
"scripts": {
|
|
8
8
|
"test": "jest",
|
|
9
9
|
"publish:ci": "yarn run build && yarn run copy-flow && changeset publish",
|
|
10
|
-
"build": "babel src --out-dir dist --source-maps --ignore 'src/**/*.spec.js','src/**/*.test.js'",
|
|
10
|
+
"build": "babel src -D --out-dir dist --source-maps --ignore 'src/**/*.spec.js','src/**/*.test.js'",
|
|
11
11
|
"copy-flow": "node ./build-copy-source.js"
|
|
12
12
|
},
|
|
13
13
|
"main": "dist/index.js",
|
|
@@ -39,6 +39,7 @@
|
|
|
39
39
|
"@babel/types": "^7.17.0",
|
|
40
40
|
"apollo-utilities": "^1.3.4",
|
|
41
41
|
"graphql": "14.5.8",
|
|
42
|
+
"jsonschema": "^1.4.1",
|
|
42
43
|
"prettier": "^2.5.1",
|
|
43
44
|
"prettier-eslint": "^13.0.0"
|
|
44
45
|
}
|
|
@@ -19,7 +19,7 @@ describe('generateTypeFileContents', () => {
|
|
|
19
19
|
}
|
|
20
20
|
}
|
|
21
21
|
`,
|
|
22
|
-
{splitTypes: true},
|
|
22
|
+
{splitTypes: true, schemaFilePath: ''},
|
|
23
23
|
'__generated__',
|
|
24
24
|
indexPrelude('yarn queries'),
|
|
25
25
|
);
|
|
@@ -73,6 +73,7 @@ describe('generateTypeFileContents', () => {
|
|
|
73
73
|
{
|
|
74
74
|
splitTypes: true,
|
|
75
75
|
typeFileName: 'prefix-[operationName]-suffix.js',
|
|
76
|
+
schemaFilePath: '',
|
|
76
77
|
},
|
|
77
78
|
'__generated__',
|
|
78
79
|
indexPrelude('yarn queries'),
|
|
@@ -115,6 +116,7 @@ describe('generateTypeFileContents', () => {
|
|
|
115
116
|
`,
|
|
116
117
|
{
|
|
117
118
|
experimentalEnums: true,
|
|
119
|
+
schemaFilePath: '',
|
|
118
120
|
},
|
|
119
121
|
'__generated__',
|
|
120
122
|
indexPrelude('yarn queries'),
|