@khanacademy/graphql-flow 1.2.0 → 3.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.
Files changed (78) hide show
  1. package/.babelrc +1 -1
  2. package/.eslintrc.js +0 -1
  3. package/.github/workflows/changeset-release.yml +1 -1
  4. package/CHANGELOG.md +16 -0
  5. package/dist/cli/config.js +8 -7
  6. package/dist/cli/run.js +1 -2
  7. package/dist/enums.js +8 -9
  8. package/dist/generateResponseType.js +33 -41
  9. package/dist/generateTypeFiles.js +9 -23
  10. package/dist/generateVariablesType.js +15 -31
  11. package/dist/index.js +8 -15
  12. package/dist/parser/parse.js +6 -7
  13. package/dist/parser/resolve.js +1 -2
  14. package/dist/parser/utils.js +1 -2
  15. package/dist/schemaFromIntrospectionData.js +1 -2
  16. package/dist/types.js +1 -2
  17. package/dist/utils.js +43 -3
  18. package/package.json +9 -8
  19. package/{dist/__test__/generateTypeFileContents.test.js → src/__test__/generateTypeFileContents.test.ts} +38 -41
  20. package/{dist/__test__/graphql-flow.test.js → src/__test__/graphql-flow.test.ts} +232 -235
  21. package/src/__test__/{processPragmas.test.js → processPragmas.test.ts} +0 -1
  22. package/{dist/cli/__test__/config.test.js → src/cli/__test__/config.test.ts} +5 -6
  23. package/src/cli/{config.js → config.ts} +10 -15
  24. package/src/cli/{run.js → run.ts} +5 -4
  25. package/src/{enums.js → enums.ts} +20 -22
  26. package/src/{generateResponseType.js → generateResponseType.ts} +167 -182
  27. package/src/{generateTypeFiles.js → generateTypeFiles.ts} +20 -30
  28. package/src/{generateVariablesType.js → generateVariablesType.ts} +34 -44
  29. package/{dist/index.js.flow → src/index.ts} +32 -24
  30. package/{dist/parser/__test__/parse.test.js → src/parser/__test__/parse.test.ts} +12 -11
  31. package/src/parser/{parse.js → parse.ts} +65 -47
  32. package/{dist/parser/resolve.js.flow → src/parser/resolve.ts} +15 -11
  33. package/{dist/parser/utils.js.flow → src/parser/utils.ts} +0 -1
  34. package/{dist/schemaFromIntrospectionData.js.flow → src/schemaFromIntrospectionData.ts} +1 -4
  35. package/src/types.ts +97 -0
  36. package/src/utils.ts +73 -0
  37. package/tools/{find-files-with-gql.js → find-files-with-gql.ts} +2 -3
  38. package/tsconfig.json +110 -0
  39. package/types/flow-to-ts.d.ts +1 -0
  40. package/dist/__test__/example-schema.graphql +0 -67
  41. package/dist/__test__/processPragmas.test.js +0 -76
  42. package/dist/cli/config.js.flow +0 -84
  43. package/dist/cli/config.js.map +0 -1
  44. package/dist/cli/run.js.flow +0 -236
  45. package/dist/cli/run.js.map +0 -1
  46. package/dist/enums.js.flow +0 -98
  47. package/dist/enums.js.map +0 -1
  48. package/dist/generateResponseType.js.flow +0 -583
  49. package/dist/generateResponseType.js.map +0 -1
  50. package/dist/generateTypeFiles.js.flow +0 -191
  51. package/dist/generateTypeFiles.js.map +0 -1
  52. package/dist/generateVariablesType.js.flow +0 -156
  53. package/dist/generateVariablesType.js.map +0 -1
  54. package/dist/index.js.map +0 -1
  55. package/dist/parser/parse.js.flow +0 -417
  56. package/dist/parser/parse.js.map +0 -1
  57. package/dist/parser/resolve.js.map +0 -1
  58. package/dist/parser/utils.js.map +0 -1
  59. package/dist/schemaFromIntrospectionData.js.map +0 -1
  60. package/dist/types.js.flow +0 -88
  61. package/dist/types.js.map +0 -1
  62. package/dist/utils.js.flow +0 -50
  63. package/dist/utils.js.map +0 -1
  64. package/flow-typed/npm/@babel/types_vx.x.x.js +0 -5331
  65. package/flow-typed/npm/jest_v23.x.x.js +0 -1155
  66. package/flow-typed/overrides.js +0 -435
  67. package/src/__test__/generateTypeFileContents.test.js +0 -157
  68. package/src/__test__/graphql-flow.test.js +0 -639
  69. package/src/cli/__test__/config.test.js +0 -120
  70. package/src/cli/schema.json +0 -97
  71. package/src/index.js +0 -160
  72. package/src/parser/__test__/parse.test.js +0 -249
  73. package/src/parser/resolve.js +0 -119
  74. package/src/parser/utils.js +0 -25
  75. package/src/schemaFromIntrospectionData.js +0 -68
  76. package/src/types.js +0 -88
  77. package/src/utils.js +0 -50
  78. /package/{dist/cli/schema.json → schema.json} +0 -0
@@ -1,13 +1,9 @@
1
- // @flow
2
1
  import generate from '@babel/generator'; // eslint-disable-line flowtype-errors/uncovered
3
- import type {
4
- BabelNodeFlowType,
5
- BabelNodeObjectTypeProperty,
6
- } from '@babel/types';
7
2
  import * as babelTypes from '@babel/types';
8
3
  import type {OperationDefinitionNode, TypeNode} from 'graphql/language/ast';
9
4
  import type {IntrospectionInputTypeRef} from 'graphql/utilities/introspectionQuery';
10
5
  import {builtinScalars, enumTypeToFlow, scalarTypeToFlow} from './enums';
6
+ import {nullableType, isnNullableType, objectTypeFromProperties} from './utils';
11
7
  import type {Context, Schema} from './types';
12
8
  import {
13
9
  liftLeadingPropertyComments,
@@ -18,18 +14,18 @@ import {
18
14
  export const inputObjectToFlow = (
19
15
  ctx: Context,
20
16
  name: string,
21
- ): BabelNodeFlowType => {
17
+ ): babelTypes.TSType => {
22
18
  const inputObject = ctx.schema.inputObjectsByName[name];
23
19
  if (!inputObject) {
24
20
  ctx.errors.push(`Unknown input object ${name}`);
25
- return babelTypes.stringLiteralTypeAnnotation(
26
- `Unknown input object ${name}`,
21
+ return babelTypes.tsLiteralType(
22
+ babelTypes.stringLiteral(`Unknown input object ${name}`),
27
23
  );
28
24
  }
29
25
 
30
26
  return maybeAddDescriptionComment(
31
27
  inputObject.description,
32
- babelTypes.objectTypeAnnotation(
28
+ objectTypeFromProperties(
33
29
  inputObject.inputFields.map((vbl) =>
34
30
  maybeAddDescriptionComment(
35
31
  vbl.description,
@@ -39,22 +35,21 @@ export const inputObjectToFlow = (
39
35
  ),
40
36
  ),
41
37
  ),
42
- undefined /* indexers */,
43
- undefined /* callProperties */,
44
- undefined /* internalSlots */,
45
- true /* exact */,
46
38
  ),
47
39
  );
48
40
  };
49
41
 
50
42
  export const maybeOptionalObjectTypeProperty = (
51
43
  name: string,
52
- type: babelTypes.BabelNodeFlowType,
53
- ): BabelNodeObjectTypeProperty => {
44
+ type: babelTypes.TSType,
45
+ ): babelTypes.TSPropertySignature => {
54
46
  const prop = liftLeadingPropertyComments(
55
- babelTypes.objectTypeProperty(babelTypes.identifier(name), type),
47
+ babelTypes.tsPropertySignature(
48
+ babelTypes.identifier(name),
49
+ babelTypes.tsTypeAnnotation(type),
50
+ ),
56
51
  );
57
- if (type.type === 'NullableTypeAnnotation') {
52
+ if (isnNullableType(type)) {
58
53
  prop.optional = true;
59
54
  }
60
55
  return prop;
@@ -63,18 +58,18 @@ export const maybeOptionalObjectTypeProperty = (
63
58
  export const inputRefToFlow = (
64
59
  ctx: Context,
65
60
  inputRef: IntrospectionInputTypeRef,
66
- ): BabelNodeFlowType => {
61
+ ): babelTypes.TSType => {
67
62
  if (inputRef.kind === 'NON_NULL') {
68
63
  return _inputRefToFlow(ctx, inputRef.ofType);
69
64
  }
70
65
  const result = _inputRefToFlow(ctx, inputRef);
71
- return transferLeadingComments(
72
- result,
73
- babelTypes.nullableTypeAnnotation(result),
74
- );
66
+ return transferLeadingComments(result, nullableType(result));
75
67
  };
76
68
 
77
- const _inputRefToFlow = (ctx: Context, inputRef: IntrospectionInputTypeRef) => {
69
+ const _inputRefToFlow = (
70
+ ctx: Context,
71
+ inputRef: IntrospectionInputTypeRef,
72
+ ): babelTypes.TSType => {
78
73
  if (inputRef.kind === 'SCALAR') {
79
74
  return scalarTypeToFlow(ctx, inputRef.name);
80
75
  }
@@ -85,28 +80,27 @@ const _inputRefToFlow = (ctx: Context, inputRef: IntrospectionInputTypeRef) => {
85
80
  return inputObjectToFlow(ctx, inputRef.name);
86
81
  }
87
82
  if (inputRef.kind === 'LIST') {
88
- return babelTypes.genericTypeAnnotation(
89
- babelTypes.identifier('$ReadOnlyArray'),
90
- babelTypes.typeParameterInstantiation([
83
+ return babelTypes.tsTypeReference(
84
+ babelTypes.identifier('ReadonlyArray'),
85
+ babelTypes.tsTypeParameterInstantiation([
91
86
  inputRefToFlow(ctx, inputRef.ofType),
92
87
  ]),
93
88
  );
94
89
  }
95
- return babelTypes.stringLiteralTypeAnnotation(JSON.stringify(inputRef));
90
+ return babelTypes.tsLiteralType(
91
+ babelTypes.stringLiteral(JSON.stringify(inputRef)),
92
+ );
96
93
  };
97
94
 
98
- const variableToFlow = (ctx: Context, type: TypeNode) => {
95
+ const variableToFlow = (ctx: Context, type: TypeNode): babelTypes.TSType => {
99
96
  if (type.kind === 'NonNullType') {
100
97
  return _variableToFlow(ctx, type.type);
101
98
  }
102
99
  const result = _variableToFlow(ctx, type);
103
- return transferLeadingComments(
104
- result,
105
- babelTypes.nullableTypeAnnotation(result),
106
- );
100
+ return transferLeadingComments(result, nullableType(result));
107
101
  };
108
102
 
109
- const _variableToFlow = (ctx: Context, type: TypeNode) => {
103
+ const _variableToFlow = (ctx: Context, type: TypeNode): babelTypes.TSType => {
110
104
  if (type.kind === 'NamedType') {
111
105
  if (builtinScalars[type.name.value]) {
112
106
  return scalarTypeToFlow(ctx, type.name.value);
@@ -116,22 +110,22 @@ const _variableToFlow = (ctx: Context, type: TypeNode) => {
116
110
  }
117
111
  const customScalarType = ctx.scalars[type.name.value];
118
112
  if (customScalarType) {
119
- return babelTypes.genericTypeAnnotation(
113
+ return babelTypes.tsTypeReference(
120
114
  babelTypes.identifier(customScalarType),
121
115
  );
122
116
  }
123
117
  return inputObjectToFlow(ctx, type.name.value);
124
118
  }
125
119
  if (type.kind === 'ListType') {
126
- return babelTypes.genericTypeAnnotation(
127
- babelTypes.identifier('$ReadOnlyArray'),
128
- babelTypes.typeParameterInstantiation([
120
+ return babelTypes.tsTypeReference(
121
+ babelTypes.identifier('ReadonlyArray'),
122
+ babelTypes.tsTypeParameterInstantiation([
129
123
  variableToFlow(ctx, type.type),
130
124
  ]),
131
125
  );
132
126
  }
133
- return babelTypes.stringLiteralTypeAnnotation(
134
- 'UNKNOWN' + JSON.stringify(type),
127
+ return babelTypes.tsLiteralType(
128
+ babelTypes.stringLiteral('UNKNOWN' + JSON.stringify(type)),
135
129
  );
136
130
  };
137
131
 
@@ -140,17 +134,13 @@ export const generateVariablesType = (
140
134
  item: OperationDefinitionNode,
141
135
  ctx: Context,
142
136
  ): string => {
143
- const variableObject = babelTypes.objectTypeAnnotation(
137
+ const variableObject = objectTypeFromProperties(
144
138
  (item.variableDefinitions || []).map((vbl) => {
145
139
  return maybeOptionalObjectTypeProperty(
146
140
  vbl.variable.name.value,
147
141
  variableToFlow(ctx, vbl.type),
148
142
  );
149
143
  }),
150
- undefined /* indexers */,
151
- undefined /* callProperties */,
152
- undefined /* internalSlots */,
153
- true /* exact */,
154
144
  );
155
145
  return generate(variableObject).code; // eslint-disable-line flowtype-errors/uncovered
156
146
  };
@@ -1,6 +1,6 @@
1
+ import {isTruthy} from '@khanacademy/wonder-stuff-core';
1
2
  /* eslint-disable no-console */
2
3
  /* flow-uncovered-file */
3
- // @flow
4
4
  /**
5
5
  * This tool generates flowtype definitions from graphql queries.
6
6
  *
@@ -15,13 +15,13 @@ import {
15
15
  generateResponseType,
16
16
  } from './generateResponseType';
17
17
  import {generateVariablesType} from './generateVariablesType';
18
- import type {BabelNode} from '@babel/types';
18
+ import type {Node} from '@babel/types';
19
19
 
20
20
  import type {Context, Schema, GenerateConfig} from './types';
21
21
 
22
22
  const optionsToConfig = (
23
23
  schema: Schema,
24
- definitions: $ReadOnlyArray<DefinitionNode>,
24
+ definitions: ReadonlyArray<DefinitionNode>,
25
25
  options?: GenerateConfig,
26
26
  errors: Array<string> = [],
27
27
  ): Context => {
@@ -31,8 +31,8 @@ const optionsToConfig = (
31
31
  scalars: options?.scalars ?? {},
32
32
  typeScript: options?.typeScript ?? false,
33
33
  omitFileExtensions: options?.omitFileExtensions ?? false,
34
- };
35
- const fragments = {};
34
+ } as const;
35
+ const fragments: Record<string, any> = {};
36
36
  definitions.forEach((def) => {
37
37
  if (def.kind === 'FragmentDefinition') {
38
38
  fragments[def.name.value] = def;
@@ -46,8 +46,10 @@ const optionsToConfig = (
46
46
  path: [],
47
47
  experimentalEnumsMap: options?.experimentalEnums ? {} : undefined,
48
48
  ...internalOptions,
49
- };
49
+ } as const;
50
50
 
51
+ // @ts-expect-error: TS2322 - The type 'readonly []' is 'readonly' and cannot be
52
+ // assigned to the mutable type 'string[]'.
51
53
  return config;
52
54
  };
53
55
 
@@ -59,17 +61,17 @@ export class FlowGenerationError extends Error {
59
61
  }
60
62
  }
61
63
 
62
- export const documentToFlowTypes = (
63
- document: DocumentNode,
64
- schema: Schema,
65
- options?: GenerateConfig,
66
- ): $ReadOnlyArray<{
67
- name: string,
68
- typeName: string,
69
- code: string,
70
- isFragment?: boolean,
71
- extraTypes: {[key: string]: string},
72
- experimentalEnums: {[key: string]: string},
64
+ export const documentToFlowTypes = (document: DocumentNode, schema: Schema, options?: GenerateConfig): ReadonlyArray<{
65
+ name: string
66
+ typeName: string
67
+ code: string
68
+ isFragment?: boolean
69
+ extraTypes: {
70
+ [key: string]: string
71
+ }
72
+ experimentalEnums: {
73
+ [key: string]: string
74
+ }
73
75
  }> => {
74
76
  const errors: Array<string> = [];
75
77
  const config = optionsToConfig(
@@ -82,7 +84,7 @@ export const documentToFlowTypes = (
82
84
  .map((item) => {
83
85
  if (item.kind === 'FragmentDefinition') {
84
86
  const name = item.name.value;
85
- const types = {};
87
+ const types: Record<string, any> = {};
86
88
  const code = `export type ${name} = ${generateFragmentType(
87
89
  schema,
88
90
  item,
@@ -114,7 +116,7 @@ export const documentToFlowTypes = (
114
116
  (item.operation === 'query' || item.operation === 'mutation') &&
115
117
  item.name
116
118
  ) {
117
- const types = {};
119
+ const types: Record<string, any> = {};
118
120
  const name = item.name.value;
119
121
  const response = generateResponseType(schema, item, {
120
122
  ...config,
@@ -131,7 +133,7 @@ export const documentToFlowTypes = (
131
133
  const typeName = `${name}Type`;
132
134
  // TODO(jared): Maybe make this template configurable?
133
135
  // We'll see what's required to get webapp on board.
134
- const code = `export type ${typeName} = {|\n variables: ${variables},\n response: ${response}\n|};`;
136
+ const code = `export type ${typeName} = {\n variables: ${variables},\n response: ${response}\n};`;
135
137
 
136
138
  const extraTypes = codegenExtraTypes(types);
137
139
  const experimentalEnums = codegenExtraTypes(
@@ -141,17 +143,23 @@ export const documentToFlowTypes = (
141
143
  return {name, typeName, code, extraTypes, experimentalEnums};
142
144
  }
143
145
  })
144
- .filter(Boolean);
146
+ .filter(isTruthy);
145
147
  if (errors.length) {
146
148
  throw new FlowGenerationError(errors);
147
149
  }
148
150
  return result;
149
151
  };
150
152
 
151
- function codegenExtraTypes(types: {[key: string]: BabelNode}): {
152
- [key: string]: string,
153
+ function codegenExtraTypes(
154
+ types: {
155
+ [key: string]: Node
156
+ },
157
+ ): {
158
+ [key: string]: string
153
159
  } {
154
- const extraTypes: {[key: string]: string} = {};
160
+ const extraTypes: {
161
+ [key: string]: string
162
+ } = {};
155
163
  Object.keys(types).forEach((k: string) => {
156
164
  // eslint-disable-next-line flowtype-errors/uncovered
157
165
  extraTypes[k] = generate(types[k]).code;
@@ -1,12 +1,13 @@
1
- // @flow
2
-
3
1
  import {processFiles} from '../parse';
4
2
  import {resolveDocuments} from '../resolve';
5
3
 
6
4
  import {print} from 'graphql/language/printer';
7
5
 
8
6
  const fixtureFiles: {
9
- [key: string]: string | {text: string, resolvedPath: string},
7
+ [key: string]: string | {
8
+ text: string
9
+ resolvedPath: string
10
+ }
10
11
  } = {
11
12
  '/firstFile.js': `
12
13
  // Note that you can import graphql-tag as
@@ -151,14 +152,14 @@ const getFileSource = (name: string) => {
151
152
  describe('processing fragments in various ways', () => {
152
153
  it('should work', () => {
153
154
  const files = processFiles(['/thirdFile.js'], getFileSource);
154
- Object.keys(files).forEach((k) => {
155
+ Object.keys(files).forEach((k: any) => {
155
156
  expect(files[k].errors).toEqual([]);
156
157
  });
157
158
  const {resolved, errors} = resolveDocuments(files);
158
159
  expect(errors).toEqual([]);
159
- const printed = {};
160
+ const printed: Record<string, any> = {};
160
161
  Object.keys(resolved).map(
161
- (k) => (printed[k] = print(resolved[k].document).trim()),
162
+ (k: any) => (printed[k] = print(resolved[k].document).trim()),
162
163
  );
163
164
  expect(printed).toMatchInlineSnapshot(`
164
165
  Object {
@@ -216,7 +217,7 @@ describe('processing fragments in various ways', () => {
216
217
 
217
218
  it('should flag things it doesnt support', () => {
218
219
  const files = processFiles(['/invalidThings.js'], getFileSource);
219
- expect(files['/invalidThings.js'].errors.map((m) => m.message))
220
+ expect(files['/invalidThings.js'].errors.map((m: any) => m.message))
220
221
  .toMatchInlineSnapshot(`
221
222
  Array [
222
223
  "Unable to resolve someExternalFragment",
@@ -228,11 +229,11 @@ describe('processing fragments in various ways', () => {
228
229
 
229
230
  it('should flag resolution errors', () => {
230
231
  const files = processFiles(['/invalidReferences.js'], getFileSource);
231
- Object.keys(files).forEach((k) => {
232
+ Object.keys(files).forEach((k: any) => {
232
233
  expect(files[k].errors).toEqual([]);
233
234
  });
234
235
  const {resolved, errors} = resolveDocuments(files);
235
- expect(errors.map((m) => m.message)).toMatchInlineSnapshot(`
236
+ expect(errors.map((m: any) => m.message)).toMatchInlineSnapshot(`
236
237
  Array [
237
238
  "Circular import /circular.js -> /invalidReferences.js -> /circular.js",
238
239
  "/circular.js has no valid gql export doesntExist",
@@ -240,9 +241,9 @@ describe('processing fragments in various ways', () => {
240
241
  "Recursive template dependency! /circular.js:5 ~ 1,2 -> /invalidReferences.js:15 ~ 1,2 -> /circular.js:5",
241
242
  ]
242
243
  `);
243
- const printed = {};
244
+ const printed: Record<string, any> = {};
244
245
  Object.keys(resolved).map(
245
- (k) => (printed[k] = print(resolved[k].document).trim()),
246
+ (k: any) => (printed[k] = print(resolved[k].document).trim()),
246
247
  );
247
248
  expect(printed).toMatchInlineSnapshot(`Object {}`);
248
249
  });
@@ -1,4 +1,4 @@
1
- // @flow
1
+ import {isTruthy} from '@khanacademy/wonder-stuff-core';
2
2
  import type {
3
3
  BabelNodeImportDeclaration,
4
4
  BabelNodeVariableDeclarator,
@@ -42,40 +42,54 @@ import {getPathWithExtension} from './utils';
42
42
  * in `gqlOp<Type>()` or not (to inform an auto-wrapper of the future)
43
43
  */
44
44
 
45
- export type Template = {|
46
- literals: Array<string>,
47
- expressions: Array<Document | Import>,
48
- loc: Loc,
49
- |};
50
- export type Loc = {start: number, end: number, path: string, line: number};
45
+ export type Template = {
46
+ literals: Array<string>
47
+ expressions: Array<Document | Import>
48
+ loc: Loc
49
+ };
50
+ export type Loc = {
51
+ start: number
52
+ end: number
53
+ path: string
54
+ line: number
55
+ };
51
56
 
52
- export type Document = {|
53
- type: 'document',
54
- source: Template,
55
- |};
56
- export type Import = {|
57
- type: 'import',
58
- name: string,
59
- path: string,
60
- loc: Loc,
61
- |};
57
+ export type Document = {
58
+ type: 'document'
59
+ source: Template
60
+ };
61
+ export type Import = {
62
+ type: 'import'
63
+ name: string
64
+ path: string
65
+ loc: Loc
66
+ };
62
67
 
63
- export type Operation = {|
64
- source: Template,
68
+ export type Operation = {
69
+ source: Template
65
70
  // TODO: Determine if an operation is already wrapped
66
71
  // in `gqlOp` so we can automatically wrap if needed.
67
72
  // needsWrapping: boolean,
68
- |};
73
+ };
69
74
 
70
- export type FileResult = {|
71
- path: string,
72
- operations: Array<Operation>,
73
- exports: {[key: string]: Document | Import},
74
- locals: {[key: string]: Document | Import},
75
- errors: Array<{loc: Loc, message: string}>,
76
- |};
75
+ export type FileResult = {
76
+ path: string
77
+ operations: Array<Operation>
78
+ exports: {
79
+ [key: string]: Document | Import
80
+ }
81
+ locals: {
82
+ [key: string]: Document | Import
83
+ }
84
+ errors: Array<{
85
+ loc: Loc
86
+ message: string
87
+ }>
88
+ };
77
89
 
78
- export type Files = {[path: string]: FileResult};
90
+ export type Files = {
91
+ [path: string]: FileResult
92
+ };
79
93
 
80
94
  /**
81
95
  * Finds all referenced imports that might possibly be relevant
@@ -86,7 +100,7 @@ export type Files = {[path: string]: FileResult};
86
100
  * from a graphql template are treated as relevant.
87
101
  */
88
102
  const listExternalReferences = (file: FileResult): Array<string> => {
89
- const paths = {};
103
+ const paths: Record<string, any> = {};
90
104
  const add = (v: Document | Import, followImports: boolean) => {
91
105
  if (v.type === 'import') {
92
106
  if (followImports) {
@@ -126,7 +140,10 @@ const listExternalReferences = (file: FileResult): Array<string> => {
126
140
 
127
141
  export const processFile = (
128
142
  filePath: string,
129
- contents: string | {text: string, resolvedPath: string},
143
+ contents: string | {
144
+ text: string
145
+ resolvedPath: string
146
+ },
130
147
  ): FileResult => {
131
148
  const dir = path.dirname(filePath);
132
149
  const result: FileResult = {
@@ -140,7 +157,7 @@ export const processFile = (
140
157
  typeof contents === 'string' ? filePath : contents.resolvedPath;
141
158
  const text = typeof contents === 'string' ? contents : contents.text;
142
159
  const plugins = resolved.match(/\.tsx?$/)
143
- ? ['typescript', filePath.endsWith('x') ? 'jsx' : null].filter(Boolean)
160
+ ? ['typescript', filePath.endsWith('x') ? 'jsx' : null].filter(isTruthy)
144
161
  : [['flow', {enums: true}], 'jsx'];
145
162
  /* eslint-disable flowtype-errors/uncovered */
146
163
  const ast: BabelNodeFile = parse(text, {
@@ -150,7 +167,9 @@ export const processFile = (
150
167
  });
151
168
  /* eslint-enable flowtype-errors/uncovered */
152
169
  const gqlTagNames = [];
153
- const seenTemplates: {[key: number]: Document | false} = {};
170
+ const seenTemplates: {
171
+ [key: number]: Document | false
172
+ } = {};
154
173
 
155
174
  ast.program.body.forEach((toplevel) => {
156
175
  if (toplevel.type === 'ImportDeclaration') {
@@ -176,7 +195,7 @@ export const processFile = (
176
195
  const importPath = source.value.startsWith('.')
177
196
  ? path.resolve(path.join(dir, source.value))
178
197
  : source.value;
179
- toplevel.specifiers?.forEach((spec) => {
198
+ toplevel.specifiers?.forEach((spec: unknown) => {
180
199
  if (
181
200
  spec.type === 'ExportSpecifier' &&
182
201
  spec.exported.type === 'Identifier'
@@ -195,7 +214,7 @@ export const processFile = (
195
214
  }
196
215
  });
197
216
  } else {
198
- toplevel.specifiers?.forEach((spec) => {
217
+ toplevel.specifiers?.forEach((spec: unknown) => {
199
218
  if (spec.type === 'ExportSpecifier') {
200
219
  const local = result.locals[spec.local.name];
201
220
  if (local && spec.exported.type === 'Identifier') {
@@ -285,7 +304,7 @@ export const processFile = (
285
304
 
286
305
  /* eslint-disable flowtype-errors/uncovered */
287
306
  traverse(ast, {
288
- TaggedTemplateExpression(path) {
307
+ TaggedTemplateExpression(path: unknown) {
289
308
  visitTpl(path.node, (name) => {
290
309
  const binding = path.scope.getBinding(name);
291
310
  const start = binding.path.node.init
@@ -306,10 +325,10 @@ export const processFile = (
306
325
  const processTemplate = (
307
326
  tpl: BabelNodeTaggedTemplateExpression,
308
327
  result: FileResult,
309
- getTemplate?: (name: string) => Document | null,
310
328
  // getBinding?: (name: string) => Binding,
311
329
  // seenTemplates,
312
- ): ?Template => {
330
+ getTemplate?: (name: string) => Document | null,
331
+ ): Template | null | undefined => {
313
332
  // 'cooked' is the string as runtime javascript will see it.
314
333
  const literals = tpl.quasi.quasis.map((q) => q.value.cooked || '');
315
334
  const expressions = tpl.quasi.expressions.map(
@@ -347,7 +366,7 @@ const processTemplate = (
347
366
  }
348
367
  return {
349
368
  literals,
350
- expressions: expressions.filter(Boolean),
369
+ expressions: expressions.filter(isTruthy),
351
370
  loc: {
352
371
  line: tpl.loc?.start.line ?? -1,
353
372
  start: tpl.start ?? -1,
@@ -357,18 +376,16 @@ const processTemplate = (
357
376
  };
358
377
  };
359
378
 
360
- const getLocals = (
361
- dir,
362
- toplevel: BabelNodeImportDeclaration,
363
- myPath: string,
364
- ): ?{[key: string]: Import} => {
379
+ const getLocals = (dir: unknown, toplevel: BabelNodeImportDeclaration, myPath: string): {
380
+ [key: string]: Import
381
+ } | null | undefined => {
365
382
  if (toplevel.importKind === 'type') {
366
383
  return null;
367
384
  }
368
385
  const importPath = toplevel.source.value.startsWith('.')
369
386
  ? path.resolve(path.join(dir, toplevel.source.value))
370
387
  : toplevel.source.value;
371
- const locals = {};
388
+ const locals: Record<string, any> = {};
372
389
  toplevel.specifiers.forEach((spec) => {
373
390
  if (spec.type === 'ImportDefaultSpecifier') {
374
391
  locals[spec.local.name] = {
@@ -394,9 +411,10 @@ const getLocals = (
394
411
 
395
412
  export const processFiles = (
396
413
  filePaths: Array<string>,
397
- getFileSource: (
398
- path: string,
399
- ) => string | {text: string, resolvedPath: string},
414
+ getFileSource: (path: string) => string | {
415
+ text: string
416
+ resolvedPath: string
417
+ },
400
418
  ): Files => {
401
419
  const files: Files = {};
402
420
  const toProcess = filePaths.slice();
@@ -1,4 +1,3 @@
1
- // @flow
2
1
  import gql from 'graphql-tag';
3
2
  import {getPathWithExtension} from './utils';
4
3
  import type {DocumentNode} from 'graphql/language/ast';
@@ -6,14 +5,15 @@ import type {FileResult, Files, Import, Template, Document} from './parse';
6
5
 
7
6
  export type Resolved = {
8
7
  [key: string]: {
9
- document: DocumentNode,
10
- raw: Template,
11
- },
8
+ document: DocumentNode
9
+ raw: Template
10
+ }
12
11
  };
13
12
 
14
- export const resolveDocuments = (
15
- files: Files,
16
- ): {resolved: Resolved, errors: FileResult['errors']} => {
13
+ export const resolveDocuments = (files: Files): {
14
+ resolved: Resolved
15
+ errors: FileResult['errors']
16
+ } => {
17
17
  const resolved: Resolved = {};
18
18
  const errors: FileResult['errors'] = [];
19
19
  Object.keys(files).forEach((path) => {
@@ -35,8 +35,10 @@ const resolveImport = (
35
35
  expr: Import,
36
36
  files: Files,
37
37
  errors: FileResult['errors'],
38
- seen: {[key: string]: true},
39
- ): ?Document => {
38
+ seen: {
39
+ [key: string]: true
40
+ },
41
+ ): Document | null | undefined => {
40
42
  const absPath: string = getPathWithExtension(expr.path);
41
43
  if (seen[absPath]) {
42
44
  errors.push({
@@ -72,8 +74,10 @@ const resolveGqlTemplate = (
72
74
  files: Files,
73
75
  errors: FileResult['errors'],
74
76
  resolved: Resolved,
75
- seen: {[key: string]: Template},
76
- ): ?DocumentNode => {
77
+ seen: {
78
+ [key: string]: Template
79
+ },
80
+ ): DocumentNode | null | undefined => {
77
81
  const key = template.loc.path + ':' + template.loc.line;
78
82
  if (seen[key]) {
79
83
  errors.push({
@@ -1,4 +1,3 @@
1
- // @flow
2
1
  import fs from 'fs';
3
2
 
4
3
  export const getPathWithExtension = (pathWithoutExtension: string): string => {
@@ -1,4 +1,3 @@
1
- // @flow
2
1
  /**
3
2
  * Takes the introspectionQuery response and parses it into the "Schema"
4
3
  * type that we use to look up types, interfaces, etc.
@@ -6,9 +5,7 @@
6
5
  import type {IntrospectionQuery} from 'graphql';
7
6
  import type {Schema} from './types';
8
7
 
9
- export const schemaFromIntrospectionData = (
10
- schema: IntrospectionQuery,
11
- ): Schema => {
8
+ export const schemaFromIntrospectionData = (schema: IntrospectionQuery): Schema => {
12
9
  const result: Schema = {
13
10
  interfacesByName: {},
14
11
  typesByName: {},