@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.
Files changed (54) hide show
  1. package/dist/argument-node.d.ts +4 -0
  2. package/dist/ast.d.ts +95 -0
  3. package/dist/constants.d.ts +12 -0
  4. package/dist/directive-node.d.ts +5 -0
  5. package/dist/document.d.ts +3 -0
  6. package/dist/field-node.d.ts +4 -0
  7. package/dist/fragment-spread-node.d.ts +4 -0
  8. package/dist/fragment.d.ts +3 -0
  9. package/dist/gql.d.ts +51 -0
  10. package/dist/inline-fragment-node.d.ts +4 -0
  11. package/dist/luvioGraphqlParser.js +12945 -0
  12. package/dist/luvioGraphqlParser.mjs +12923 -0
  13. package/dist/main.d.ts +18 -0
  14. package/dist/metaschema.d.ts +10 -0
  15. package/dist/operation/index.d.ts +3 -0
  16. package/dist/operation/query/index.d.ts +6 -0
  17. package/dist/type-node.d.ts +3 -0
  18. package/dist/util/language.d.ts +9 -0
  19. package/dist/value-node.d.ts +4 -0
  20. package/dist/variable-definition.d.ts +4 -0
  21. package/dist/visitor.d.ts +4 -0
  22. package/package.json +4 -1
  23. package/babel.config.js +0 -1
  24. package/jest.config.js +0 -8
  25. package/project.json +0 -7
  26. package/rollup.config.js +0 -24
  27. package/scripts/cli.mjs +0 -18
  28. package/src/__tests__/ast.json +0 -403
  29. package/src/__tests__/ast.spec.ts +0 -109
  30. package/src/__tests__/astNoLoc.json +0 -147
  31. package/src/__tests__/gql.spec.ts +0 -665
  32. package/src/__tests__/main.spec.ts +0 -651
  33. package/src/__tests__/metaschema.spec.ts +0 -230
  34. package/src/__tests__/type-node.spec.ts +0 -82
  35. package/src/argument-node.ts +0 -18
  36. package/src/ast.ts +0 -200
  37. package/src/constants.ts +0 -14
  38. package/src/directive-node.ts +0 -36
  39. package/src/document.ts +0 -29
  40. package/src/field-node.ts +0 -72
  41. package/src/fragment-spread-node.ts +0 -28
  42. package/src/fragment.ts +0 -46
  43. package/src/gql.ts +0 -222
  44. package/src/inline-fragment-node.ts +0 -31
  45. package/src/main.ts +0 -134
  46. package/src/metaschema.ts +0 -162
  47. package/src/operation/index.ts +0 -12
  48. package/src/operation/query/index.ts +0 -78
  49. package/src/type-node.ts +0 -40
  50. package/src/util/language.ts +0 -10
  51. package/src/value-node.ts +0 -71
  52. package/src/variable-definition.ts +0 -37
  53. package/src/visitor.ts +0 -63
  54. 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
- }
@@ -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
- }