@luvio/graphql-parser 0.62.2

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 (42) hide show
  1. package/babel.config.js +1 -0
  2. package/dist/argument-node.d.ts +4 -0
  3. package/dist/ast.d.ts +95 -0
  4. package/dist/constants.d.ts +12 -0
  5. package/dist/directive-node.d.ts +5 -0
  6. package/dist/document.d.ts +3 -0
  7. package/dist/field-node.d.ts +4 -0
  8. package/dist/fragment-spread-node.d.ts +4 -0
  9. package/dist/fragment.d.ts +3 -0
  10. package/dist/inline-fragment-node.d.ts +4 -0
  11. package/dist/luvioGraphqlParser.js +3887 -0
  12. package/dist/main.d.ts +4 -0
  13. package/dist/operation/index.d.ts +3 -0
  14. package/dist/operation/query/index.d.ts +6 -0
  15. package/dist/type-node.d.ts +3 -0
  16. package/dist/value-node.d.ts +4 -0
  17. package/dist/variable-definition.d.ts +4 -0
  18. package/dist/visitor.d.ts +4 -0
  19. package/jest.config.js +8 -0
  20. package/package.json +19 -0
  21. package/rollup.config.js +19 -0
  22. package/scripts/cli.mjs +18 -0
  23. package/src/__tests__/ast.spec.ts +109 -0
  24. package/src/__tests__/main.spec.ts +600 -0
  25. package/src/__tests__/type-node.spec.ts +82 -0
  26. package/src/argument-node.ts +18 -0
  27. package/src/ast.ts +200 -0
  28. package/src/constants.ts +14 -0
  29. package/src/directive-node.ts +36 -0
  30. package/src/document.ts +33 -0
  31. package/src/field-node.ts +72 -0
  32. package/src/fragment-spread-node.ts +28 -0
  33. package/src/fragment.ts +46 -0
  34. package/src/inline-fragment-node.ts +31 -0
  35. package/src/main.ts +58 -0
  36. package/src/operation/index.ts +12 -0
  37. package/src/operation/query/index.ts +78 -0
  38. package/src/type-node.ts +39 -0
  39. package/src/value-node.ts +71 -0
  40. package/src/variable-definition.ts +37 -0
  41. package/src/visitor.ts +62 -0
  42. package/tsconfig.json +9 -0
@@ -0,0 +1,18 @@
1
+ import { ArgumentNode } from 'graphql/language';
2
+ import { LuvioArgumentNode } from './ast';
3
+ import { TransformState } from './operation/query';
4
+ import { transform as transformValueNode } from './value-node';
5
+
6
+ export function transform(node: ArgumentNode, transformState: TransformState): LuvioArgumentNode {
7
+ const {
8
+ kind,
9
+ name: { value: nodeName },
10
+ value: nodeValue,
11
+ } = node;
12
+ const valueNode = transformValueNode(nodeValue, transformState);
13
+ return {
14
+ kind,
15
+ name: nodeName,
16
+ value: valueNode,
17
+ };
18
+ }
package/src/ast.ts ADDED
@@ -0,0 +1,200 @@
1
+ import {
2
+ DocumentNode,
3
+ OperationDefinitionNode,
4
+ FieldNode,
5
+ ArgumentNode,
6
+ IntValueNode,
7
+ ListValueNode,
8
+ ObjectValueNode,
9
+ FloatValueNode,
10
+ StringValueNode,
11
+ BooleanValueNode,
12
+ NullValueNode,
13
+ EnumValueNode,
14
+ VariableNode,
15
+ DirectiveNode,
16
+ VariableDefinitionNode,
17
+ NonNullTypeNode,
18
+ ListTypeNode,
19
+ NamedTypeNode,
20
+ FragmentSpreadNode,
21
+ InlineFragmentNode,
22
+ FragmentDefinitionNode,
23
+ DefinitionNode,
24
+ TypeNode,
25
+ } from 'graphql/language';
26
+
27
+ /**
28
+ * Luvio specific custom GraphQL AST
29
+ *
30
+ * - Omit Location
31
+ * - flatten NameNode for easier value access
32
+ * - Add luvioSelections for custom selections
33
+ * - LuvioSelectionCustomFieldNode for fields with custom client side directives
34
+ */
35
+
36
+ /* Document */
37
+ export interface LuvioDocumentNode extends Omit<DocumentNode, 'loc' | 'definitions'> {
38
+ definitions: LuvioDefinitionNode[];
39
+ }
40
+
41
+ export type LuvioDefinitionNode = LuvioOperationDefinitionNode | LuvioFragmentDefinitionNode;
42
+
43
+ export interface LuvioOperationDefinitionNode
44
+ extends Omit<
45
+ OperationDefinitionNode,
46
+ 'loc' | 'name' | 'variableDefinitions' | 'directives' | 'selectionSet'
47
+ > {
48
+ name?: string;
49
+ variableDefinitions?: LuvioVariableDefinitionNode[];
50
+ directives?: LuvioDirectiveNode[];
51
+ luvioSelections: LuvioSelectionNode[];
52
+ }
53
+
54
+ export interface LuvioVariableDefinitionNode
55
+ extends Omit<
56
+ VariableDefinitionNode,
57
+ 'loc' | 'variable' | 'type' | 'defaultValue' | 'directives'
58
+ > {
59
+ variable: LuvioVariableNode;
60
+ type: LuvioTypeNode;
61
+ defaultValue?: LuvioValueNode;
62
+ directives?: LuvioDirectiveNode[];
63
+ }
64
+
65
+ export interface LuvioVariableNode extends Omit<VariableNode, 'loc' | 'name'> {
66
+ name: string;
67
+ }
68
+
69
+ export type LuvioSelectionNode = LuvioFieldNode | LuvioFragmentSpreadNode | LuvioInlineFragmentNode;
70
+
71
+ export type LuvioFieldNode =
72
+ | LuvioSelectionScalarFieldNode
73
+ | LuvioSelectionObjectFieldNode
74
+ | LuvioSelectionCustomFieldNode;
75
+
76
+ export interface LuvioArgumentNode extends Omit<ArgumentNode, 'loc' | 'name' | 'value'> {
77
+ name: string;
78
+ value: LuvioValueNode;
79
+ }
80
+
81
+ /* Fragments */
82
+ export interface LuvioFragmentSpreadNode
83
+ extends Omit<FragmentSpreadNode, 'loc' | 'name' | 'directives'> {
84
+ name: string;
85
+ directives?: LuvioDirectiveNode[];
86
+ }
87
+
88
+ export interface LuvioInlineFragmentNode
89
+ extends Omit<InlineFragmentNode, 'loc' | 'typeCondition' | 'directives' | 'selectionSet'> {
90
+ typeCondition?: LuvioNamedTypeNode;
91
+ directives?: LuvioDirectiveNode[];
92
+ luvioSelections: LuvioSelectionNode[];
93
+ }
94
+
95
+ export interface LuvioFragmentDefinitionNode
96
+ extends Omit<
97
+ FragmentDefinitionNode,
98
+ 'loc' | 'name' | 'variableDefinitions' | 'typeCondition' | 'directives' | 'selectionSet'
99
+ > {
100
+ name: string;
101
+ // Note: fragment variable definitions are experimental and may be changed
102
+ // or removed in the future.
103
+ variableDefinitions?: LuvioVariableDefinitionNode[];
104
+ typeCondition: LuvioNamedTypeNode;
105
+ directives?: LuvioDirectiveNode[];
106
+ luvioSelections: LuvioSelectionNode[];
107
+ }
108
+
109
+ /* Values */
110
+ export type LuvioValueNode =
111
+ | LuvioVariableNode
112
+ | IntValueNode
113
+ | FloatValueNode
114
+ | StringValueNode
115
+ | BooleanValueNode
116
+ | NullValueNode
117
+ | EnumValueNode
118
+ | LuvioListValueNode
119
+ | LuvioObjectValueNode;
120
+
121
+ export interface LuvioListValueNode extends Omit<ListValueNode, 'loc' | 'values'> {
122
+ values: LuvioValueNode[];
123
+ }
124
+
125
+ export interface LuvioObjectValueNode extends Omit<ObjectValueNode, 'loc' | 'fields'> {
126
+ fields: {
127
+ [name: string]: LuvioValueNode;
128
+ };
129
+ }
130
+
131
+ /* Directives */
132
+ export interface LuvioDirectiveNode extends Omit<DirectiveNode, 'loc' | 'name' | 'arguments'> {
133
+ name: string;
134
+ arguments?: LuvioArgumentNode[];
135
+ }
136
+
137
+ /* Type Reference */
138
+ export type LuvioTypeNode = LuvioNamedTypeNode | LuvioListTypeNode | LuvioNonNullTypeNode;
139
+
140
+ export interface LuvioNamedTypeNode extends Omit<NamedTypeNode, 'loc' | 'name'> {
141
+ name: string;
142
+ }
143
+
144
+ export interface LuvioListTypeNode extends Omit<ListTypeNode, 'loc' | 'type'> {
145
+ type: LuvioTypeNode;
146
+ }
147
+
148
+ export interface LuvioNonNullTypeNode extends Omit<NonNullTypeNode, 'loc' | 'type'> {
149
+ type: LuvioNamedTypeNode | LuvioListTypeNode;
150
+ }
151
+
152
+ /* Custom Selection Fields */
153
+ export interface LuvioSelectionScalarFieldNode
154
+ extends Omit<
155
+ FieldNode,
156
+ 'kind' | 'loc' | 'alias' | 'name' | 'arguments' | 'directives' | 'selectionSet'
157
+ > {
158
+ kind: 'ScalarFieldSelection';
159
+ alias?: string;
160
+ name: string;
161
+ }
162
+
163
+ export interface LuvioSelectionObjectFieldNode
164
+ extends Omit<
165
+ FieldNode,
166
+ 'kind' | 'loc' | 'alias' | 'name' | 'arguments' | 'directives' | 'selectionSet'
167
+ > {
168
+ kind: 'ObjectFieldSelection';
169
+ alias?: string;
170
+ name: string;
171
+ arguments?: LuvioArgumentNode[];
172
+ directives?: LuvioDirectiveNode[];
173
+ luvioSelections?: LuvioSelectionNode[];
174
+ }
175
+
176
+ export interface LuvioSelectionCustomFieldNode extends Omit<LuvioSelectionObjectFieldNode, 'kind'> {
177
+ kind: 'CustomFieldSelection';
178
+ type: string;
179
+ }
180
+
181
+ /* Util Functions */
182
+ export function isOperationDefinitionNode(input: DefinitionNode): input is OperationDefinitionNode {
183
+ return input.kind === 'OperationDefinition';
184
+ }
185
+
186
+ export function isFragmentDefinitionNode(input: DefinitionNode): input is FragmentDefinitionNode {
187
+ return input.kind === 'FragmentDefinition';
188
+ }
189
+
190
+ export function isNamedTypeNode(input: TypeNode): input is NamedTypeNode {
191
+ return input.kind === 'NamedType';
192
+ }
193
+
194
+ export function isListTypeNode(input: TypeNode): input is ListTypeNode {
195
+ return input.kind === 'ListType';
196
+ }
197
+
198
+ export function isNonNullTypeNode(input: TypeNode): input is NonNullTypeNode {
199
+ return input.kind === 'NonNullType';
200
+ }
@@ -0,0 +1,14 @@
1
+ export const CUSTOM_DIRECTIVE_CONNECTION = 'connection';
2
+ export const CUSTOM_DIRECTIVE_RESOURCE = 'resource';
3
+
4
+ export const NODE_KIND_CUSTOM_FIELD_SELECTION = 'CustomFieldSelection';
5
+ export const NODE_KIND_FIELD = 'Field';
6
+ export const NODE_KIND_FRAGMENT_SPREAD = 'FragmentSpread';
7
+ export const NODE_KIND_INLINE_FRAGMENT = 'InlineFragment';
8
+ export const NODE_KIND_LIST_TYPE = 'ListType';
9
+ export const NODE_KIND_NAMED_TYPE = 'NamedType';
10
+ export const NODE_KIND_NON_NULL_TYPE = 'NonNullType';
11
+ export const NODE_KIND_OBJECT_FIELD_SELECTION = 'ObjectFieldSelection';
12
+ export const NODE_KIND_SCALAR_FIELD_SELECTION = 'ScalarFieldSelection';
13
+
14
+ export const NODE_TYPE_CONNECTION = 'Connection';
@@ -0,0 +1,36 @@
1
+ import { DirectiveNode } from 'graphql/language';
2
+ import { LuvioArgumentNode, LuvioDirectiveNode } from './ast';
3
+ import { transform as transformArgumentNode } from './argument-node';
4
+ import { CUSTOM_DIRECTIVE_CONNECTION, CUSTOM_DIRECTIVE_RESOURCE } from './constants';
5
+ import { TransformState } from './operation/query';
6
+
7
+ export function transform(node: DirectiveNode, transformState: TransformState): LuvioDirectiveNode {
8
+ const {
9
+ kind,
10
+ name: { value: nodeName },
11
+ arguments: nodeArguments,
12
+ } = node;
13
+ const ret: LuvioDirectiveNode = {
14
+ kind,
15
+ name: nodeName,
16
+ };
17
+
18
+ if (nodeArguments !== undefined && nodeArguments.length > 0) {
19
+ let returnArguments: LuvioArgumentNode[] = [];
20
+ for (var index = 0; index < nodeArguments.length; index++) {
21
+ const argumentNode = nodeArguments[index];
22
+ const value = transformArgumentNode(argumentNode, transformState);
23
+ returnArguments.push(value);
24
+ }
25
+ ret.arguments = returnArguments;
26
+ }
27
+
28
+ return ret;
29
+ }
30
+
31
+ export function isCustomDirective(node: DirectiveNode): boolean {
32
+ return (
33
+ node.name.value === CUSTOM_DIRECTIVE_CONNECTION ||
34
+ node.name.value === CUSTOM_DIRECTIVE_RESOURCE
35
+ );
36
+ }
@@ -0,0 +1,33 @@
1
+ import { DocumentNode } from 'graphql/language';
2
+ import {
3
+ LuvioDocumentNode,
4
+ LuvioDefinitionNode,
5
+ isOperationDefinitionNode,
6
+ isFragmentDefinitionNode,
7
+ } from './ast';
8
+ import { transform as operationDefinitionTransform } from './operation';
9
+ import { transform as fragmentDefinitionTransform } from './fragment';
10
+
11
+ export function transform(root: DocumentNode): LuvioDocumentNode {
12
+ const { kind, definitions } = root;
13
+ const luvioDefinitions: LuvioDefinitionNode[] = [];
14
+ for (let i = 0; i < definitions.length; i++) {
15
+ const definition = definitions[i];
16
+ if (isOperationDefinitionNode(definition)) {
17
+ luvioDefinitions.push(operationDefinitionTransform(definition));
18
+ } else if (isFragmentDefinitionNode(definition)) {
19
+ luvioDefinitions.push(fragmentDefinitionTransform(definition));
20
+ } else {
21
+ if (process.env.NODE_ENV !== 'production') {
22
+ throw new Error(
23
+ `Unsupported ${definition.kind} definition. Only OperationDefinition and FragmentDefinition are supported in a GraphQL Document`
24
+ );
25
+ }
26
+ }
27
+ }
28
+
29
+ return {
30
+ kind,
31
+ definitions: luvioDefinitions,
32
+ };
33
+ }
@@ -0,0 +1,72 @@
1
+ import { FieldNode, StringValueNode } from 'graphql/language';
2
+ import { transform as transformArgumentNode } from './argument-node';
3
+ import { LuvioArgumentNode, LuvioFieldNode } from './ast';
4
+ import {
5
+ CUSTOM_DIRECTIVE_CONNECTION,
6
+ CUSTOM_DIRECTIVE_RESOURCE,
7
+ NODE_KIND_CUSTOM_FIELD_SELECTION,
8
+ NODE_KIND_OBJECT_FIELD_SELECTION,
9
+ NODE_KIND_SCALAR_FIELD_SELECTION,
10
+ NODE_TYPE_CONNECTION,
11
+ } from './constants';
12
+ import { isCustomDirective, transform as transformDirectiveNode } from './directive-node';
13
+ import { TransformState } from './operation/query';
14
+
15
+ export function transform(node: FieldNode, transformState: TransformState): LuvioFieldNode {
16
+ const { name, alias, arguments: fieldArgs, selectionSet, directives } = node;
17
+
18
+ let luvioNode: LuvioFieldNode = {
19
+ kind: NODE_KIND_OBJECT_FIELD_SELECTION,
20
+ name: name.value,
21
+ luvioSelections: [],
22
+ };
23
+
24
+ if (selectionSet === undefined || selectionSet.selections.length === 0) {
25
+ luvioNode = {
26
+ kind: NODE_KIND_SCALAR_FIELD_SELECTION,
27
+ name: name.value,
28
+ };
29
+ } else {
30
+ // object or custom field node
31
+ if (directives !== undefined && directives.length > 0) {
32
+ const customDirectiveNode = directives.find(isCustomDirective);
33
+ if (customDirectiveNode === undefined) {
34
+ // transform non client-side directives
35
+ luvioNode.directives = directives.map((directive) =>
36
+ transformDirectiveNode(directive, transformState)
37
+ );
38
+ } else {
39
+ if (customDirectiveNode.name.value === CUSTOM_DIRECTIVE_CONNECTION) {
40
+ luvioNode = {
41
+ kind: NODE_KIND_CUSTOM_FIELD_SELECTION,
42
+ name: name.value,
43
+ type: NODE_TYPE_CONNECTION,
44
+ luvioSelections: [],
45
+ };
46
+ } else if (customDirectiveNode.name.value === CUSTOM_DIRECTIVE_RESOURCE) {
47
+ luvioNode = {
48
+ kind: NODE_KIND_CUSTOM_FIELD_SELECTION,
49
+ name: name.value,
50
+ type: (customDirectiveNode!.arguments![0].value as StringValueNode).value,
51
+ luvioSelections: [],
52
+ };
53
+ }
54
+ }
55
+ }
56
+
57
+ if (fieldArgs !== undefined && fieldArgs.length > 0) {
58
+ const returnArguments: LuvioArgumentNode[] = [];
59
+ for (var index = 0; index < fieldArgs.length; index++) {
60
+ const value = transformArgumentNode(fieldArgs[index], transformState);
61
+ returnArguments.push(value);
62
+ }
63
+ luvioNode.arguments = returnArguments;
64
+ }
65
+ }
66
+
67
+ if (alias !== undefined) {
68
+ luvioNode.alias = alias.value;
69
+ }
70
+
71
+ return luvioNode;
72
+ }
@@ -0,0 +1,28 @@
1
+ import { FragmentSpreadNode } from 'graphql/language';
2
+ import { LuvioFragmentSpreadNode } from './ast';
3
+ import { transform as transformDirectiveNode } from './directive-node';
4
+ import { TransformState } from './operation/query';
5
+
6
+ export function transform(
7
+ node: FragmentSpreadNode,
8
+ transformState: TransformState
9
+ ): LuvioFragmentSpreadNode {
10
+ const {
11
+ kind,
12
+ name: { value },
13
+ directives,
14
+ } = node;
15
+
16
+ const luvioNode: LuvioFragmentSpreadNode = {
17
+ kind,
18
+ name: value,
19
+ };
20
+
21
+ if (directives !== undefined && directives.length > 0) {
22
+ luvioNode.directives = directives.map((directive) =>
23
+ transformDirectiveNode(directive, transformState)
24
+ );
25
+ }
26
+
27
+ return luvioNode;
28
+ }
@@ -0,0 +1,46 @@
1
+ import { FragmentDefinitionNode } from 'graphql/language';
2
+ import { LuvioFieldNode, LuvioFragmentDefinitionNode, LuvioSelectionNode } from './ast';
3
+ import { selectionSetVisitor } from './visitor';
4
+ import { transform as transformDirectiveNode } from './directive-node';
5
+ import { NODE_KIND_OBJECT_FIELD_SELECTION } from './constants';
6
+
7
+ export function transform(node: FragmentDefinitionNode): LuvioFragmentDefinitionNode {
8
+ const {
9
+ kind: nodeKind,
10
+ name: { value: nodeName },
11
+ typeCondition: {
12
+ kind: typeKind,
13
+ name: { value: typeName },
14
+ },
15
+ directives,
16
+ } = node;
17
+
18
+ // dummy root node
19
+ const fragmentRoot: LuvioFieldNode = {
20
+ kind: NODE_KIND_OBJECT_FIELD_SELECTION,
21
+ name: 'fragment',
22
+ luvioSelections: [],
23
+ };
24
+ const currentNodePath: LuvioSelectionNode[] = [fragmentRoot];
25
+
26
+ const transformState = { variablesUsed: {} };
27
+ selectionSetVisitor(node, currentNodePath, transformState);
28
+
29
+ const luvioNode: LuvioFragmentDefinitionNode = {
30
+ kind: nodeKind,
31
+ name: nodeName,
32
+ typeCondition: {
33
+ kind: typeKind,
34
+ name: typeName,
35
+ },
36
+ luvioSelections: fragmentRoot.luvioSelections!,
37
+ };
38
+
39
+ if (directives !== undefined && directives.length > 0) {
40
+ luvioNode.directives = directives.map((node) =>
41
+ transformDirectiveNode(node, transformState)
42
+ );
43
+ }
44
+
45
+ return luvioNode;
46
+ }
@@ -0,0 +1,31 @@
1
+ import { InlineFragmentNode } from 'graphql/language';
2
+ import { LuvioInlineFragmentNode } from './ast';
3
+ import { transform as transformDirectiveNode } from './directive-node';
4
+ import { TransformState } from './operation/query';
5
+
6
+ export function transform(
7
+ node: InlineFragmentNode,
8
+ transformState: TransformState
9
+ ): LuvioInlineFragmentNode {
10
+ const { kind: nodeKind, typeCondition, directives } = node;
11
+
12
+ const luvioNode: LuvioInlineFragmentNode = {
13
+ kind: nodeKind,
14
+ luvioSelections: [],
15
+ };
16
+
17
+ if (typeCondition !== undefined) {
18
+ luvioNode.typeCondition = {
19
+ kind: typeCondition.kind,
20
+ name: typeCondition.name.value,
21
+ };
22
+ }
23
+
24
+ if (directives !== undefined && directives.length > 0) {
25
+ luvioNode.directives = directives.map((directive) =>
26
+ transformDirectiveNode(directive, transformState)
27
+ );
28
+ }
29
+
30
+ return luvioNode;
31
+ }
package/src/main.ts ADDED
@@ -0,0 +1,58 @@
1
+ import {
2
+ parse,
3
+ BooleanValueNode,
4
+ FloatValueNode,
5
+ IntValueNode,
6
+ StringValueNode,
7
+ } from 'graphql/language';
8
+ import {
9
+ LuvioDocumentNode,
10
+ LuvioArgumentNode,
11
+ LuvioDefinitionNode,
12
+ LuvioObjectValueNode,
13
+ LuvioOperationDefinitionNode,
14
+ LuvioSelectionCustomFieldNode,
15
+ LuvioSelectionNode,
16
+ LuvioSelectionObjectFieldNode,
17
+ LuvioSelectionScalarFieldNode,
18
+ LuvioValueNode,
19
+ LuvioFieldNode,
20
+ LuvioVariableDefinitionNode,
21
+ LuvioVariableNode,
22
+ LuvioNamedTypeNode,
23
+ LuvioListTypeNode,
24
+ LuvioListValueNode,
25
+ LuvioTypeNode,
26
+ } from './ast';
27
+ import { transform } from './document';
28
+
29
+ export function parseAndVisit(source: string): LuvioDocumentNode {
30
+ // TODO: handle generic <Type>
31
+ const ast = parse(source);
32
+ return transform(ast);
33
+ }
34
+
35
+ // type exports
36
+ export {
37
+ BooleanValueNode,
38
+ FloatValueNode,
39
+ IntValueNode,
40
+ StringValueNode,
41
+ LuvioDocumentNode,
42
+ LuvioArgumentNode,
43
+ LuvioDefinitionNode,
44
+ LuvioObjectValueNode,
45
+ LuvioOperationDefinitionNode,
46
+ LuvioSelectionCustomFieldNode,
47
+ LuvioSelectionNode,
48
+ LuvioSelectionObjectFieldNode,
49
+ LuvioSelectionScalarFieldNode,
50
+ LuvioValueNode,
51
+ LuvioFieldNode,
52
+ LuvioVariableDefinitionNode,
53
+ LuvioVariableNode,
54
+ LuvioNamedTypeNode,
55
+ LuvioListTypeNode,
56
+ LuvioListValueNode,
57
+ LuvioTypeNode,
58
+ };
@@ -0,0 +1,12 @@
1
+ import { OperationDefinitionNode } from 'graphql/language';
2
+ import { LuvioOperationDefinitionNode } from '../ast';
3
+ import { transform as QueryTransform } from './query';
4
+
5
+ export function transform(node: OperationDefinitionNode): LuvioOperationDefinitionNode {
6
+ const { operation } = node;
7
+ if (operation === 'query') {
8
+ return QueryTransform(node);
9
+ }
10
+
11
+ throw new Error(`Unsupported ${operation} operation. Only query operation is supported`);
12
+ }
@@ -0,0 +1,78 @@
1
+ import { OperationDefinitionNode, VariableDefinitionNode } from 'graphql/language';
2
+ import { LuvioFieldNode, LuvioOperationDefinitionNode, LuvioSelectionNode } from '../../ast';
3
+ import { selectionSetVisitor } from '../../visitor';
4
+ import { transform as transformVariableDefinition } from '../../variable-definition';
5
+ import { transform as transformDirectiveNode } from '../../directive-node';
6
+
7
+ export interface TransformState {
8
+ variablesUsed: Record<string, true>;
9
+ }
10
+
11
+ export function transform(node: OperationDefinitionNode): LuvioOperationDefinitionNode {
12
+ const queryRoot: LuvioFieldNode = {
13
+ kind: 'ObjectFieldSelection',
14
+ name: 'query',
15
+ luvioSelections: [],
16
+ };
17
+ const currentNodePath: LuvioSelectionNode[] = [queryRoot];
18
+
19
+ const transformState = {
20
+ variablesUsed: {},
21
+ };
22
+ selectionSetVisitor(node, currentNodePath, transformState);
23
+
24
+ const operationDefinition: LuvioOperationDefinitionNode = {
25
+ kind: 'OperationDefinition',
26
+ operation: 'query',
27
+ luvioSelections: queryRoot.luvioSelections!,
28
+ };
29
+
30
+ if (node.name !== undefined) {
31
+ operationDefinition.name = node.name.value;
32
+ }
33
+
34
+ const { variableDefinitions, directives } = node;
35
+ if (variableDefinitions !== undefined && variableDefinitions.length > 0) {
36
+ operationDefinition.variableDefinitions = variableDefinitions.map((variableDefinition) =>
37
+ transformVariableDefinition(variableDefinition, transformState)
38
+ );
39
+ }
40
+
41
+ if (directives !== undefined && directives.length > 0) {
42
+ operationDefinition.directives = directives.map((node) =>
43
+ transformDirectiveNode(node, transformState)
44
+ );
45
+ }
46
+
47
+ validateVariables(variableDefinitions, transformState);
48
+
49
+ return operationDefinition;
50
+ }
51
+
52
+ function validateVariables(
53
+ variableDefinitions: readonly VariableDefinitionNode[] | undefined,
54
+ transformState: TransformState
55
+ ) {
56
+ const variablesDefined: Record<string, true> = {};
57
+
58
+ if (variableDefinitions !== undefined) {
59
+ for (let i = 0, len = variableDefinitions.length; i < len; i++) {
60
+ const definedVariableName = variableDefinitions[i].variable.name.value;
61
+ variablesDefined[definedVariableName] = true;
62
+ if (transformState.variablesUsed[definedVariableName] === undefined) {
63
+ if (process.env.NODE_ENV !== 'production') {
64
+ throw new Error(`Variable $${definedVariableName} was defined but never used.`);
65
+ }
66
+ }
67
+ }
68
+ }
69
+
70
+ const usedVariableKeys = Object.keys(transformState.variablesUsed);
71
+ for (let i = 0, len = usedVariableKeys.length; i < len; i++) {
72
+ if (variablesDefined[usedVariableKeys[i]] !== true) {
73
+ if (process.env.NODE_ENV !== 'production') {
74
+ throw new Error(`Variable $${usedVariableKeys[i]} was used but never defined.`);
75
+ }
76
+ }
77
+ }
78
+ }
@@ -0,0 +1,39 @@
1
+ import { TypeNode } from 'graphql/language';
2
+ import { isListTypeNode, isNamedTypeNode, isNonNullTypeNode, LuvioTypeNode } from './ast';
3
+ import { NODE_KIND_NAMED_TYPE, NODE_KIND_LIST_TYPE, NODE_KIND_NON_NULL_TYPE } from './constants';
4
+
5
+ export function transform(node: TypeNode): LuvioTypeNode {
6
+ if (isNamedTypeNode(node)) {
7
+ return {
8
+ kind: NODE_KIND_NAMED_TYPE,
9
+ name: node.name.value,
10
+ };
11
+ } else if (isListTypeNode(node)) {
12
+ return {
13
+ kind: NODE_KIND_LIST_TYPE,
14
+ type: transform(node.type),
15
+ };
16
+ } else if (isNonNullTypeNode(node)) {
17
+ if (isNamedTypeNode(node.type)) {
18
+ return {
19
+ kind: NODE_KIND_NON_NULL_TYPE,
20
+ type: {
21
+ kind: NODE_KIND_NAMED_TYPE,
22
+ name: node.type.name.value,
23
+ },
24
+ };
25
+ } else if (isListTypeNode(node.type)) {
26
+ return {
27
+ kind: NODE_KIND_NON_NULL_TYPE,
28
+ type: {
29
+ kind: NODE_KIND_LIST_TYPE,
30
+ type: transform(node.type.type),
31
+ },
32
+ };
33
+ } else {
34
+ throw new Error('Unsupported NonNullTypeNode');
35
+ }
36
+ } else {
37
+ throw new Error('Unsupported TypeNode');
38
+ }
39
+ }