apollo-utilities
Advanced tools
Comparing version 0.2.0-alpha.4 to 0.2.0-alpha.5
# Change log | ||
### vNEXT | ||
- Added hasDirectives to recurse the AST and return a boolean for an array of directive names | ||
- Improved performance of common store actions by memoizing addTypename and removeConnectionDirective |
@@ -1,2 +0,2 @@ | ||
import { FieldNode, SelectionNode } from 'graphql'; | ||
import { FieldNode, SelectionNode, DocumentNode } from 'graphql'; | ||
export declare type DirectiveInfo = { | ||
@@ -11,1 +11,4 @@ [fieldName: string]: { | ||
}): boolean; | ||
export declare function flattenSelections(selection: SelectionNode): SelectionNode[]; | ||
export declare function getDirectiveNames(doc: DocumentNode): any; | ||
export declare function hasDirectives(names: string[], doc: DocumentNode): any; |
@@ -60,2 +60,38 @@ "use strict"; | ||
exports.shouldInclude = shouldInclude; | ||
function flattenSelections(selection) { | ||
if (!selection.selectionSet || | ||
!(selection.selectionSet.selections.length > 0)) | ||
return [selection]; | ||
return [selection].concat(selection.selectionSet.selections | ||
.map(function (selectionNode) { | ||
return [selectionNode].concat(flattenSelections(selectionNode)); | ||
}) | ||
.reduce(function (selections, selected) { return selections.concat(selected); }, [])); | ||
} | ||
exports.flattenSelections = flattenSelections; | ||
var added = new Map(); | ||
function getDirectiveNames(doc) { | ||
var cached = added.get(doc); | ||
if (cached) | ||
return cached; | ||
var directives = doc.definitions | ||
.filter(function (definition) { | ||
return definition.selectionSet && definition.selectionSet.selections; | ||
}) | ||
.map(function (x) { return flattenSelections(x); }) | ||
.reduce(function (selections, selected) { return selections.concat(selected); }, []) | ||
.filter(function (selection) { | ||
return selection.directives && selection.directives.length > 0; | ||
}) | ||
.map(function (selection) { return selection.directives; }) | ||
.reduce(function (directives, directive) { return directives.concat(directive); }, []) | ||
.map(function (directive) { return directive.name.value; }); | ||
added.set(doc, directives); | ||
return directives; | ||
} | ||
exports.getDirectiveNames = getDirectiveNames; | ||
function hasDirectives(names, doc) { | ||
return getDirectiveNames(doc).some(function (name) { return names.indexOf(name) > -1; }); | ||
} | ||
exports.hasDirectives = hasDirectives; | ||
//# sourceMappingURL=directives.js.map |
{ | ||
"name": "apollo-utilities", | ||
"version": "0.2.0-alpha.4", | ||
"version": "0.2.0-alpha.5", | ||
"description": "Utilities for working with GraphQL ASTs", | ||
@@ -5,0 +5,0 @@ "author": "James Baxley <james@meteor.com>", |
import gql from 'graphql-tag'; | ||
import { cloneDeep } from 'lodash'; | ||
import { shouldInclude } from '../directives'; | ||
import { shouldInclude, hasDirectives } from '../directives'; | ||
import { getQueryDefinition } from '../getFromAST'; | ||
describe('query directives', () => { | ||
describe('hasDirective', () => { | ||
it('should allow searching the ast for a directive', () => { | ||
const query = gql` | ||
query Simple { | ||
field @live | ||
} | ||
`; | ||
expect(hasDirectives(['live'], query)).toBe(true); | ||
expect(hasDirectives(['defer'], query)).toBe(false); | ||
}); | ||
it('works for all operation types', () => { | ||
const query = gql` | ||
{ | ||
field @live { | ||
subField { | ||
hello @live | ||
} | ||
} | ||
} | ||
`; | ||
const mutation = gql` | ||
mutation Directive { | ||
mutate { | ||
field { | ||
subField { | ||
hello @live | ||
} | ||
} | ||
} | ||
} | ||
`; | ||
const subscription = gql` | ||
subscription LiveDirective { | ||
sub { | ||
field { | ||
subField { | ||
hello @live | ||
} | ||
} | ||
} | ||
} | ||
`; | ||
[query, mutation, subscription].forEach(x => { | ||
expect(hasDirectives(['live'], x)).toBe(true); | ||
expect(hasDirectives(['defer'], x)).toBe(false); | ||
}); | ||
}); | ||
it('works for simple fragments', () => { | ||
const query = gql` | ||
query Simple { | ||
...fieldFragment | ||
} | ||
fragment fieldFragment on Field { | ||
foo @live | ||
} | ||
`; | ||
expect(hasDirectives(['live'], query)).toBe(true); | ||
expect(hasDirectives(['defer'], query)).toBe(false); | ||
}); | ||
it('works for nested fragments', () => { | ||
const query = gql` | ||
query Simple { | ||
...fieldFragment1 | ||
} | ||
fragment fieldFragment1 on Field { | ||
bar { | ||
baz { | ||
...nestedFragment | ||
} | ||
} | ||
} | ||
fragment nestedFragment on Field { | ||
foo @live | ||
} | ||
`; | ||
expect(hasDirectives(['live'], query)).toBe(true); | ||
expect(hasDirectives(['defer'], query)).toBe(false); | ||
}); | ||
}); | ||
describe('shouldInclude', () => { | ||
it('should should not include a skipped field', () => { | ||
@@ -9,0 +95,0 @@ const query = gql` |
@@ -5,2 +5,3 @@ // Provides the methods that allow QueryManager to handle | ||
FieldNode, | ||
OperationDefinitionNode, | ||
SelectionNode, | ||
@@ -10,2 +11,3 @@ VariableNode, | ||
DirectiveNode, | ||
DocumentNode, | ||
} from 'graphql'; | ||
@@ -97,1 +99,54 @@ | ||
} | ||
export function flattenSelections(selection: SelectionNode): SelectionNode[] { | ||
if ( | ||
!(selection as FieldNode).selectionSet || | ||
!((selection as FieldNode).selectionSet.selections.length > 0) | ||
) | ||
return [selection]; | ||
return [selection].concat( | ||
(selection as FieldNode).selectionSet.selections | ||
.map(selectionNode => | ||
[selectionNode].concat(flattenSelections(selectionNode)), | ||
) | ||
.reduce((selections, selected) => selections.concat(selected), []), | ||
); | ||
} | ||
const added = new Map(); | ||
export function getDirectiveNames(doc: DocumentNode) { | ||
const cached = added.get(doc); | ||
if (cached) return cached; | ||
// operation => [names of directives]; | ||
const directives = doc.definitions | ||
.filter( | ||
(definition: OperationDefinitionNode) => | ||
definition.selectionSet && definition.selectionSet.selections, | ||
) | ||
// operation => [[Selection]] | ||
.map(x => flattenSelections(x as any)) | ||
// [[Selection]] => [Selection] | ||
.reduce((selections, selected) => selections.concat(selected), []) | ||
// [Selection] => [Selection with Directives] | ||
.filter( | ||
(selection: SelectionNode) => | ||
selection.directives && selection.directives.length > 0, | ||
) | ||
// [Selection with Directives] => [[Directives]] | ||
.map((selection: SelectionNode) => selection.directives) | ||
// [[Directives]] => [Directives] | ||
.reduce((directives, directive) => directives.concat(directive), []) | ||
// [Directives] => [Name] | ||
.map((directive: DirectiveNode) => directive.name.value); | ||
added.set(doc, directives); | ||
return directives; | ||
} | ||
export function hasDirectives(names: string[], doc: DocumentNode) { | ||
return getDirectiveNames(doc).some( | ||
(name: string) => names.indexOf(name) > -1, | ||
); | ||
} |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
127337
3204