@luvio/graphql-parser 0.126.0 → 0.126.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.
- package/dist/argument-node.d.ts +4 -0
- package/dist/ast.d.ts +95 -0
- package/dist/constants.d.ts +12 -0
- package/dist/directive-node.d.ts +5 -0
- package/dist/document.d.ts +3 -0
- package/dist/field-node.d.ts +4 -0
- package/dist/fragment-spread-node.d.ts +4 -0
- package/dist/fragment.d.ts +3 -0
- package/dist/gql.d.ts +51 -0
- package/dist/inline-fragment-node.d.ts +4 -0
- package/dist/luvioGraphqlParser.js +12945 -0
- package/dist/luvioGraphqlParser.mjs +12923 -0
- package/dist/main.d.ts +18 -0
- package/dist/metaschema.d.ts +10 -0
- package/dist/operation/index.d.ts +3 -0
- package/dist/operation/query/index.d.ts +6 -0
- package/dist/type-node.d.ts +3 -0
- package/dist/util/language.d.ts +9 -0
- package/dist/value-node.d.ts +4 -0
- package/dist/variable-definition.d.ts +4 -0
- package/dist/visitor.d.ts +4 -0
- package/package.json +4 -1
- package/babel.config.js +0 -1
- package/jest.config.js +0 -8
- package/project.json +0 -7
- package/rollup.config.js +0 -24
- package/scripts/cli.mjs +0 -18
- package/src/__tests__/ast.json +0 -403
- package/src/__tests__/ast.spec.ts +0 -109
- package/src/__tests__/astNoLoc.json +0 -147
- package/src/__tests__/gql.spec.ts +0 -665
- package/src/__tests__/main.spec.ts +0 -651
- package/src/__tests__/metaschema.spec.ts +0 -230
- package/src/__tests__/type-node.spec.ts +0 -82
- package/src/argument-node.ts +0 -18
- package/src/ast.ts +0 -200
- package/src/constants.ts +0 -14
- package/src/directive-node.ts +0 -36
- package/src/document.ts +0 -29
- package/src/field-node.ts +0 -72
- package/src/fragment-spread-node.ts +0 -28
- package/src/fragment.ts +0 -46
- package/src/gql.ts +0 -222
- package/src/inline-fragment-node.ts +0 -31
- package/src/main.ts +0 -134
- package/src/metaschema.ts +0 -162
- package/src/operation/index.ts +0 -12
- package/src/operation/query/index.ts +0 -78
- package/src/type-node.ts +0 -40
- package/src/util/language.ts +0 -10
- package/src/value-node.ts +0 -71
- package/src/variable-definition.ts +0 -37
- package/src/visitor.ts +0 -63
- package/tsconfig.json +0 -9
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import type { FragmentSpreadNode } from 'graphql/language';
|
|
2
|
-
import type { LuvioFragmentSpreadNode } from './ast';
|
|
3
|
-
import { transform as transformDirectiveNode } from './directive-node';
|
|
4
|
-
import type { 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
|
-
}
|
package/src/fragment.ts
DELETED
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import type { FragmentDefinitionNode } from 'graphql/language';
|
|
2
|
-
import type { 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
|
-
}
|
package/src/gql.ts
DELETED
|
@@ -1,222 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Exposes a tagged template literal to parse graphql operation string
|
|
3
|
-
* "gql" is the only publicly exposed method
|
|
4
|
-
* @module gql
|
|
5
|
-
*/
|
|
6
|
-
import type { DefinitionNode, DocumentNode } from 'graphql/language';
|
|
7
|
-
import { parse } from 'graphql/language';
|
|
8
|
-
import { stripIgnoredCharacters } from 'graphql/utilities';
|
|
9
|
-
import { ObjectCreate, ObjectKeys } from './util/language';
|
|
10
|
-
|
|
11
|
-
export type AstResolver = (astReference: any) => DocumentNode | undefined;
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* we should look into optimizing this before it turns into a memory hog
|
|
15
|
-
* weakmaps, or limiting the size of the cache, or something
|
|
16
|
-
*/
|
|
17
|
-
export const docMap = new Map<string, DocumentNode>();
|
|
18
|
-
/**
|
|
19
|
-
* Opaque reference map to return keys to userland
|
|
20
|
-
* As a user shouldn't have access to the Document
|
|
21
|
-
*/
|
|
22
|
-
export const referenceMap = new WeakMap<Object, DocumentNode>();
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Strips characters that are not significant to the validity or execution
|
|
26
|
-
* of a GraphQL document:
|
|
27
|
-
* - UnicodeBOM
|
|
28
|
-
* - WhiteSpace
|
|
29
|
-
* - LineTerminator
|
|
30
|
-
* - Comment
|
|
31
|
-
* - Comma
|
|
32
|
-
* - BlockString indentation
|
|
33
|
-
*/
|
|
34
|
-
function operationKeyBuilder(inputString: string): string {
|
|
35
|
-
return stripIgnoredCharacters(inputString);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* Returns document node if cached or else update the cache and return the document node
|
|
40
|
-
* @param inputString - operation string
|
|
41
|
-
* @returns DocumentNode
|
|
42
|
-
*/
|
|
43
|
-
export function parseDocument(inputString: string): DocumentNode | null {
|
|
44
|
-
const operationKey = operationKeyBuilder(inputString);
|
|
45
|
-
const cachedDoc = docMap.get(operationKey);
|
|
46
|
-
if (cachedDoc !== undefined) {
|
|
47
|
-
return cachedDoc;
|
|
48
|
-
}
|
|
49
|
-
// parse throws an GraphQLError in case of invalid query, should this be in try/catch?
|
|
50
|
-
const parsedDoc = parse(inputString);
|
|
51
|
-
if (!parsedDoc || parsedDoc.kind !== 'Document') {
|
|
52
|
-
if (process.env.NODE_ENV !== 'production') {
|
|
53
|
-
throw new Error('Invalid graphql doc');
|
|
54
|
-
}
|
|
55
|
-
return null;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
const parsedDocNoLoc = stripLocation(parsedDoc);
|
|
59
|
-
|
|
60
|
-
docMap.set(operationKey, parsedDocNoLoc);
|
|
61
|
-
|
|
62
|
-
return parsedDocNoLoc;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* If the input string has fragment substitution
|
|
67
|
-
* Insert the fragments AST to the query document node
|
|
68
|
-
*/
|
|
69
|
-
function insertFragments(doc: DocumentNode, fragments: DefinitionNode[]): DocumentNode {
|
|
70
|
-
fragments.forEach((fragment) => {
|
|
71
|
-
// @ts-ignore
|
|
72
|
-
// graphql describes definitions as "readonly"
|
|
73
|
-
// so we aren't supposed to mutate the document node
|
|
74
|
-
// but instead of parsing the fragment again, we substitute it's definition in the document node
|
|
75
|
-
doc.definitions.push(fragment);
|
|
76
|
-
});
|
|
77
|
-
return doc;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
export function updateReferenceMapWithKnownKey(doc: DocumentNode, key: object): void {
|
|
81
|
-
referenceMap.set(key, doc);
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
export function updateReferenceMapAndGetKey(doc: DocumentNode): object {
|
|
85
|
-
const key = ObjectCreate(null);
|
|
86
|
-
updateReferenceMapWithKnownKey(doc, key);
|
|
87
|
-
|
|
88
|
-
return key;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
/**
|
|
92
|
-
* Insert string and fragment substitutions with the actual nodes
|
|
93
|
-
* @param inputString
|
|
94
|
-
* @param substitutions - string | fragment DocumentNode
|
|
95
|
-
* @returns { operation string, fragment docs [] }
|
|
96
|
-
*/
|
|
97
|
-
export function processSubstitutions(
|
|
98
|
-
inputString: ReadonlyArray<string>,
|
|
99
|
-
substitutions: (string | object)[]
|
|
100
|
-
): { operationString: string; fragments: DefinitionNode[] } | null {
|
|
101
|
-
let outputString = '';
|
|
102
|
-
const fragments: DefinitionNode[] = [];
|
|
103
|
-
const subLength = substitutions.length;
|
|
104
|
-
|
|
105
|
-
for (let i = 0; i < subLength; i++) {
|
|
106
|
-
const substitution = substitutions[i];
|
|
107
|
-
outputString += inputString[i];
|
|
108
|
-
|
|
109
|
-
if (typeof substitution === 'string' || typeof substitution === 'number') {
|
|
110
|
-
outputString += substitution;
|
|
111
|
-
} else if (typeof substitution === 'object') {
|
|
112
|
-
const doc = referenceMap.get(substitution);
|
|
113
|
-
|
|
114
|
-
if (doc === undefined) {
|
|
115
|
-
if (process.env.NODE_ENV !== 'production') {
|
|
116
|
-
throw new Error('Invalid substitution fragment');
|
|
117
|
-
}
|
|
118
|
-
return null;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
for (const def of doc.definitions) {
|
|
122
|
-
fragments.push(def);
|
|
123
|
-
}
|
|
124
|
-
} else {
|
|
125
|
-
if (process.env.NODE_ENV !== 'production') {
|
|
126
|
-
throw new Error('Unsupported substitution type');
|
|
127
|
-
}
|
|
128
|
-
return null;
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
return {
|
|
133
|
-
operationString: outputString + inputString[subLength],
|
|
134
|
-
fragments,
|
|
135
|
-
};
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
/**
|
|
139
|
-
* strips Document node and nested definitions of location references
|
|
140
|
-
*/
|
|
141
|
-
export function stripLocation(node: any) {
|
|
142
|
-
if (node.loc) {
|
|
143
|
-
delete node.loc;
|
|
144
|
-
}
|
|
145
|
-
const keys = ObjectKeys(node);
|
|
146
|
-
const keysLength = keys.length;
|
|
147
|
-
|
|
148
|
-
if (keysLength === 0) {
|
|
149
|
-
return node;
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
for (const key of keys) {
|
|
153
|
-
const subNode = node[key];
|
|
154
|
-
if (subNode && typeof subNode === 'object') {
|
|
155
|
-
stripLocation(subNode);
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
return node;
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
/**
|
|
163
|
-
*
|
|
164
|
-
* @param astReference - ast reference passed from user land
|
|
165
|
-
*/
|
|
166
|
-
export const astResolver: AstResolver = function (astReference: any) {
|
|
167
|
-
return referenceMap.get(astReference);
|
|
168
|
-
};
|
|
169
|
-
|
|
170
|
-
/**
|
|
171
|
-
*
|
|
172
|
-
* @param literals - operation query string
|
|
173
|
-
* @param subs - all other substitutions
|
|
174
|
-
* @returns an opaque reference to the parsed document
|
|
175
|
-
*/
|
|
176
|
-
export function gql(
|
|
177
|
-
literals: ReadonlyArray<string> | string,
|
|
178
|
-
...subs: (string | object)[]
|
|
179
|
-
): object | null {
|
|
180
|
-
let inputString: string;
|
|
181
|
-
let inputSubstitutionFragments: DefinitionNode[];
|
|
182
|
-
|
|
183
|
-
if (!literals) {
|
|
184
|
-
if (process.env.NODE_ENV !== 'production') {
|
|
185
|
-
throw new Error('Invalid query');
|
|
186
|
-
}
|
|
187
|
-
return null;
|
|
188
|
-
} else if (typeof literals === 'string') {
|
|
189
|
-
inputString = literals.trim();
|
|
190
|
-
inputSubstitutionFragments = [];
|
|
191
|
-
} else {
|
|
192
|
-
// called as template literal
|
|
193
|
-
const sub = processSubstitutions(literals, subs);
|
|
194
|
-
// if invalid fragment references found
|
|
195
|
-
if (sub === null) {
|
|
196
|
-
return null;
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
const { operationString, fragments } = sub;
|
|
200
|
-
inputString = operationString.trim();
|
|
201
|
-
inputSubstitutionFragments = fragments;
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
if (inputString.length === 0) {
|
|
205
|
-
if (process.env.NODE_ENV !== 'production') {
|
|
206
|
-
throw new Error('Invalid query');
|
|
207
|
-
}
|
|
208
|
-
return null;
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
const document = parseDocument(inputString);
|
|
212
|
-
|
|
213
|
-
if (document === null) {
|
|
214
|
-
return null;
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
if (inputSubstitutionFragments.length === 0) {
|
|
218
|
-
return updateReferenceMapAndGetKey(document);
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
return updateReferenceMapAndGetKey(insertFragments(document, inputSubstitutionFragments));
|
|
222
|
-
}
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import type { InlineFragmentNode } from 'graphql/language';
|
|
2
|
-
import type { LuvioInlineFragmentNode } from './ast';
|
|
3
|
-
import { transform as transformDirectiveNode } from './directive-node';
|
|
4
|
-
import type { 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
DELETED
|
@@ -1,134 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
GraphQLSchema,
|
|
3
|
-
GraphQLScalarType,
|
|
4
|
-
execute,
|
|
5
|
-
buildSchema,
|
|
6
|
-
getNamedType,
|
|
7
|
-
isObjectType,
|
|
8
|
-
validateSchema,
|
|
9
|
-
NameNode,
|
|
10
|
-
GraphQLError,
|
|
11
|
-
ObjectValueNode,
|
|
12
|
-
defaultFieldResolver,
|
|
13
|
-
type ASTNode,
|
|
14
|
-
type DefinitionNode,
|
|
15
|
-
} from 'graphql';
|
|
16
|
-
import { buildASTSchema } from 'graphql/utilities';
|
|
17
|
-
|
|
18
|
-
import {
|
|
19
|
-
LuvioDocumentNode,
|
|
20
|
-
LuvioArgumentNode,
|
|
21
|
-
LuvioDefinitionNode,
|
|
22
|
-
LuvioObjectValueNode,
|
|
23
|
-
LuvioOperationDefinitionNode,
|
|
24
|
-
LuvioSelectionCustomFieldNode,
|
|
25
|
-
LuvioSelectionNode,
|
|
26
|
-
LuvioSelectionObjectFieldNode,
|
|
27
|
-
LuvioSelectionScalarFieldNode,
|
|
28
|
-
LuvioValueNode,
|
|
29
|
-
LuvioFieldNode,
|
|
30
|
-
LuvioVariableDefinitionNode,
|
|
31
|
-
LuvioVariableNode,
|
|
32
|
-
LuvioNamedTypeNode,
|
|
33
|
-
LuvioListTypeNode,
|
|
34
|
-
LuvioListValueNode,
|
|
35
|
-
LuvioTypeNode,
|
|
36
|
-
} from './ast';
|
|
37
|
-
import { transform } from './document';
|
|
38
|
-
import { updateReferenceMapWithKnownKey } from './gql';
|
|
39
|
-
import { metaschemaMapper } from './metaschema';
|
|
40
|
-
|
|
41
|
-
export type {
|
|
42
|
-
GraphQLObjectType,
|
|
43
|
-
GraphQLInterfaceType,
|
|
44
|
-
GraphQLDirective,
|
|
45
|
-
GraphQLUnionType,
|
|
46
|
-
GraphQLNamedType,
|
|
47
|
-
} from 'graphql/type';
|
|
48
|
-
export type {
|
|
49
|
-
ListTypeNode,
|
|
50
|
-
BooleanValueNode,
|
|
51
|
-
EnumTypeDefinitionNode,
|
|
52
|
-
FieldDefinitionNode,
|
|
53
|
-
FloatValueNode,
|
|
54
|
-
InterfaceTypeDefinitionNode,
|
|
55
|
-
IntValueNode,
|
|
56
|
-
NamedTypeNode,
|
|
57
|
-
ObjectTypeDefinitionNode,
|
|
58
|
-
StringValueNode,
|
|
59
|
-
TypeNode,
|
|
60
|
-
UnionTypeDefinitionNode,
|
|
61
|
-
DocumentNode,
|
|
62
|
-
OperationDefinitionNode,
|
|
63
|
-
FieldNode,
|
|
64
|
-
ArgumentNode,
|
|
65
|
-
ValueNode,
|
|
66
|
-
SelectionNode,
|
|
67
|
-
SelectionSetNode,
|
|
68
|
-
FragmentDefinitionNode,
|
|
69
|
-
DirectiveNode,
|
|
70
|
-
ObjectFieldNode,
|
|
71
|
-
ScalarTypeDefinitionNode,
|
|
72
|
-
InputObjectTypeDefinitionNode,
|
|
73
|
-
InlineFragmentNode,
|
|
74
|
-
FragmentSpreadNode,
|
|
75
|
-
} from 'graphql/language';
|
|
76
|
-
import { parse } from 'graphql/language';
|
|
77
|
-
export { ASTVisitor, parse, Kind, print, visit } from 'graphql/language';
|
|
78
|
-
export { isScalarType } from 'graphql/type';
|
|
79
|
-
export { stripIgnoredCharacters } from 'graphql/utilities';
|
|
80
|
-
export { gql, astResolver } from './gql';
|
|
81
|
-
export type { AstResolver } from './gql';
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* @deprecated - Schema-backed adapters will use standard graphql types re-exported from @luvio/graphql
|
|
85
|
-
*/
|
|
86
|
-
export {
|
|
87
|
-
LuvioDocumentNode,
|
|
88
|
-
LuvioArgumentNode,
|
|
89
|
-
LuvioDefinitionNode,
|
|
90
|
-
LuvioObjectValueNode,
|
|
91
|
-
LuvioOperationDefinitionNode,
|
|
92
|
-
LuvioSelectionCustomFieldNode,
|
|
93
|
-
LuvioSelectionNode,
|
|
94
|
-
LuvioSelectionObjectFieldNode,
|
|
95
|
-
LuvioSelectionScalarFieldNode,
|
|
96
|
-
LuvioValueNode,
|
|
97
|
-
LuvioFieldNode,
|
|
98
|
-
LuvioVariableDefinitionNode,
|
|
99
|
-
LuvioVariableNode,
|
|
100
|
-
LuvioNamedTypeNode,
|
|
101
|
-
LuvioListTypeNode,
|
|
102
|
-
LuvioListValueNode,
|
|
103
|
-
LuvioTypeNode,
|
|
104
|
-
GraphQLSchema,
|
|
105
|
-
GraphQLScalarType,
|
|
106
|
-
NameNode,
|
|
107
|
-
GraphQLError,
|
|
108
|
-
ASTNode,
|
|
109
|
-
DefinitionNode,
|
|
110
|
-
ObjectValueNode,
|
|
111
|
-
buildASTSchema,
|
|
112
|
-
execute,
|
|
113
|
-
buildSchema,
|
|
114
|
-
getNamedType,
|
|
115
|
-
isObjectType,
|
|
116
|
-
validateSchema,
|
|
117
|
-
defaultFieldResolver,
|
|
118
|
-
};
|
|
119
|
-
|
|
120
|
-
/**
|
|
121
|
-
* @deprecated In favor of gql tagged template literal
|
|
122
|
-
*/
|
|
123
|
-
export function parseAndVisit(source: string): LuvioDocumentNode {
|
|
124
|
-
const ast = parse(source);
|
|
125
|
-
const luvioDocumentNode = transform(ast!);
|
|
126
|
-
|
|
127
|
-
// In-place substitution of metaschema annotations
|
|
128
|
-
metaschemaMapper(ast!);
|
|
129
|
-
|
|
130
|
-
// Set the AST reference map with LuvioDocumentNode as the key
|
|
131
|
-
// ASTResolver will resolve it to metaschema mapped AST
|
|
132
|
-
updateReferenceMapWithKnownKey(ast!, luvioDocumentNode);
|
|
133
|
-
return luvioDocumentNode;
|
|
134
|
-
}
|
package/src/metaschema.ts
DELETED
|
@@ -1,162 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Add metaschema annotations to their corresponding custom notation counterparts
|
|
3
|
-
* @module metaschemaMapper
|
|
4
|
-
*/
|
|
5
|
-
import type {
|
|
6
|
-
DefinitionNode,
|
|
7
|
-
DirectiveNode,
|
|
8
|
-
DocumentNode,
|
|
9
|
-
FragmentSpreadNode,
|
|
10
|
-
SelectionNode,
|
|
11
|
-
SelectionSetNode,
|
|
12
|
-
TypeSystemDefinitionNode,
|
|
13
|
-
TypeSystemExtensionNode,
|
|
14
|
-
} from 'graphql/language';
|
|
15
|
-
import { CUSTOM_DIRECTIVE_CONNECTION, CUSTOM_DIRECTIVE_RESOURCE } from './constants';
|
|
16
|
-
|
|
17
|
-
const DIRECTIVE_RECORD_CATEGORY = {
|
|
18
|
-
kind: 'Directive',
|
|
19
|
-
name: {
|
|
20
|
-
kind: 'Name',
|
|
21
|
-
value: 'category',
|
|
22
|
-
},
|
|
23
|
-
arguments: [
|
|
24
|
-
{
|
|
25
|
-
kind: 'Argument',
|
|
26
|
-
name: {
|
|
27
|
-
kind: 'Name',
|
|
28
|
-
value: 'name',
|
|
29
|
-
},
|
|
30
|
-
value: {
|
|
31
|
-
kind: 'StringValue',
|
|
32
|
-
value: 'recordQuery',
|
|
33
|
-
block: false,
|
|
34
|
-
},
|
|
35
|
-
},
|
|
36
|
-
],
|
|
37
|
-
};
|
|
38
|
-
|
|
39
|
-
const DIRECTIVE_PARENT_CATEGORY = {
|
|
40
|
-
kind: 'Directive',
|
|
41
|
-
name: {
|
|
42
|
-
kind: 'Name',
|
|
43
|
-
value: 'category',
|
|
44
|
-
},
|
|
45
|
-
arguments: [
|
|
46
|
-
{
|
|
47
|
-
kind: 'Argument',
|
|
48
|
-
name: {
|
|
49
|
-
kind: 'Name',
|
|
50
|
-
value: 'name',
|
|
51
|
-
},
|
|
52
|
-
value: {
|
|
53
|
-
kind: 'StringValue',
|
|
54
|
-
value: 'parentRelationship',
|
|
55
|
-
block: false,
|
|
56
|
-
},
|
|
57
|
-
},
|
|
58
|
-
],
|
|
59
|
-
};
|
|
60
|
-
|
|
61
|
-
function substituteDirectives(
|
|
62
|
-
directives: ReadonlyArray<DirectiveNode>,
|
|
63
|
-
index: number,
|
|
64
|
-
nodeName: string | undefined
|
|
65
|
-
): void {
|
|
66
|
-
if (directives[index].name.value === CUSTOM_DIRECTIVE_CONNECTION) {
|
|
67
|
-
// replace the custom directive node with the metaschema directive node
|
|
68
|
-
// @ts-ignore - Document is read only
|
|
69
|
-
directives[index] = DIRECTIVE_RECORD_CATEGORY;
|
|
70
|
-
} else if (directives[index].name.value === CUSTOM_DIRECTIVE_RESOURCE) {
|
|
71
|
-
// node gets its type from @category recordQuery
|
|
72
|
-
if (nodeName === 'node') {
|
|
73
|
-
// @ts-ignore - Document is read only
|
|
74
|
-
directives.splice(index, 1);
|
|
75
|
-
} else {
|
|
76
|
-
// @ts-ignore - Document is read only
|
|
77
|
-
directives[index] = DIRECTIVE_PARENT_CATEGORY;
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
/**
|
|
83
|
-
* Returns true if the directive node is of legacy type
|
|
84
|
-
* @param node : Directive node
|
|
85
|
-
* @returns
|
|
86
|
-
*/
|
|
87
|
-
function isCustomDirective(node: DirectiveNode): boolean {
|
|
88
|
-
return (
|
|
89
|
-
node.name.value === CUSTOM_DIRECTIVE_CONNECTION ||
|
|
90
|
-
node.name.value === CUSTOM_DIRECTIVE_RESOURCE
|
|
91
|
-
);
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
type TraverseSelectionSetNode = SelectionSetNode | undefined;
|
|
95
|
-
|
|
96
|
-
/**
|
|
97
|
-
* Traverses a selection set and it's nested selections,
|
|
98
|
-
* to find any legacy custom directives and substitute them with metaschema directives
|
|
99
|
-
* @param node - SelectionSetNode
|
|
100
|
-
* @returns SelectionSetNode
|
|
101
|
-
*/
|
|
102
|
-
function traverseSelectionSet(node: TraverseSelectionSetNode): TraverseSelectionSetNode {
|
|
103
|
-
if (node === undefined) {
|
|
104
|
-
return;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
for (const selection of node.selections) {
|
|
108
|
-
// FragmentSpreadNode doesn't have a selection set
|
|
109
|
-
// which should be handled at this methods entry point
|
|
110
|
-
const { directives, selectionSet } = selection as Exclude<
|
|
111
|
-
SelectionNode,
|
|
112
|
-
FragmentSpreadNode
|
|
113
|
-
>;
|
|
114
|
-
let selectionName: string | undefined;
|
|
115
|
-
|
|
116
|
-
if (selection.kind !== 'InlineFragment') {
|
|
117
|
-
selectionName = selection.name.value;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
if (directives !== undefined && directives.length > 0) {
|
|
121
|
-
// we follow this pattern instead of map to preserve the order of directives
|
|
122
|
-
// order of directives may be significant as per graphql spec
|
|
123
|
-
const index = directives.findIndex(isCustomDirective);
|
|
124
|
-
|
|
125
|
-
if (index !== -1) {
|
|
126
|
-
substituteDirectives(directives, index, selectionName);
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
traverseSelectionSet(selectionSet);
|
|
131
|
-
}
|
|
132
|
-
return node;
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
/**
|
|
136
|
-
* Accepts a document node and replaces the legacy custom directives with metaschema directives "in-place"
|
|
137
|
-
* @param doc
|
|
138
|
-
*/
|
|
139
|
-
export function metaschemaMapper(doc: DocumentNode): void {
|
|
140
|
-
// this method is only callable for Executable definitions
|
|
141
|
-
// such as Operations and Fragments
|
|
142
|
-
// so we have to explicitly cast the definitions for ts
|
|
143
|
-
const { definitions }: { definitions: unknown } = doc;
|
|
144
|
-
|
|
145
|
-
for (const def of definitions as ReadonlyArray<
|
|
146
|
-
Exclude<DefinitionNode, TypeSystemDefinitionNode | TypeSystemExtensionNode>
|
|
147
|
-
>) {
|
|
148
|
-
const { directives, selectionSet } = def;
|
|
149
|
-
|
|
150
|
-
if (directives !== undefined && directives.length > 0) {
|
|
151
|
-
// we are making an assumption here that only one custom directive can be applied to a node
|
|
152
|
-
// we can revisit if this condition changes
|
|
153
|
-
const index = directives.findIndex(isCustomDirective);
|
|
154
|
-
|
|
155
|
-
if (index !== -1) {
|
|
156
|
-
substituteDirectives(directives, index, undefined);
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
traverseSelectionSet(selectionSet);
|
|
161
|
-
}
|
|
162
|
-
}
|
package/src/operation/index.ts
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import type { OperationDefinitionNode } from 'graphql/language';
|
|
2
|
-
import type { 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
|
-
}
|