graphql-jerky 1.0.8 → 1.0.9
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/README.md +21 -0
- package/build/lib.cjs +93 -63
- package/build/lib.mjs +94 -64
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -34,6 +34,27 @@ in the same directory.
|
|
|
34
34
|
A path to a directory or file can be passed as the first parameter to limit to
|
|
35
35
|
scope of the search.
|
|
36
36
|
|
|
37
|
+
### Type extensions
|
|
38
|
+
|
|
39
|
+
Type extensions (`extend type`, `extend interface`, `extend union`,
|
|
40
|
+
`extend enum`, `extend input` and `extend scalar`) are merged into the type
|
|
41
|
+
that they extend. The extension and the definition can be in different files,
|
|
42
|
+
in any order.
|
|
43
|
+
|
|
44
|
+
```gql
|
|
45
|
+
# user.graphql
|
|
46
|
+
type Query {
|
|
47
|
+
me: User
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
# post.graphql
|
|
51
|
+
extend type Query {
|
|
52
|
+
posts: [Post!]!
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
An extension of a type that is not defined causes an error.
|
|
57
|
+
|
|
37
58
|
### Options
|
|
38
59
|
|
|
39
60
|
#### --graphql
|
package/build/lib.cjs
CHANGED
|
@@ -340,14 +340,8 @@ function renderAstNode(astNode) {
|
|
|
340
340
|
}
|
|
341
341
|
function isBuiltInDirective(name) {
|
|
342
342
|
// https://spec.graphql.org/draft/#sec-Type-System.Directives.Built-in-Directives
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
case "skip":
|
|
346
|
-
case "include":
|
|
347
|
-
case "specifiedBy":
|
|
348
|
-
return true;
|
|
349
|
-
}
|
|
350
|
-
return false;
|
|
343
|
+
// Use the list from graphql, because new versions add directives (for example, @oneOf).
|
|
344
|
+
return graphql.specifiedDirectives.some((d) => d.name === name);
|
|
351
345
|
}
|
|
352
346
|
function truthify(arr) {
|
|
353
347
|
return arr.filter(Boolean);
|
|
@@ -1613,6 +1607,9 @@ function setTraceToSchema(err, name, loc) {
|
|
|
1613
1607
|
}
|
|
1614
1608
|
return err;
|
|
1615
1609
|
}
|
|
1610
|
+
function isMergableDefinitionNode(node) {
|
|
1611
|
+
return graphql.isTypeDefinitionNode(node) || node.kind === graphql.Kind.DIRECTIVE_DEFINITION;
|
|
1612
|
+
}
|
|
1616
1613
|
function namedNodesDict(nodes = []) {
|
|
1617
1614
|
return Object.fromEntries(nodes.map((node) => [node.name.value, node]));
|
|
1618
1615
|
}
|
|
@@ -1726,7 +1723,7 @@ function mergeFieldDefinitionNodes(name, a, b) {
|
|
|
1726
1723
|
console.warn(`WARNING: there is more than one declaration for ${name}.${f.name.value}${traceLine(f.loc)}${traceLine(prev.loc, "previously ")}\n`);
|
|
1727
1724
|
fields[f.name.value] = {
|
|
1728
1725
|
...prev,
|
|
1729
|
-
directives: mergeDirectiveNodes(
|
|
1726
|
+
directives: mergeDirectiveNodes(prev.directives, f.directives),
|
|
1730
1727
|
};
|
|
1731
1728
|
}
|
|
1732
1729
|
else {
|
|
@@ -1751,7 +1748,7 @@ function mergeInputValueDefinitionNodes(name, a, b) {
|
|
|
1751
1748
|
console.warn(`WARNING: there is more than one declaration for ${name}.${f.name.value}${traceLine(f.loc)}${traceLine(prev.loc, "previously ")}\n`);
|
|
1752
1749
|
fields[f.name.value] = {
|
|
1753
1750
|
...prev,
|
|
1754
|
-
directives: mergeDirectiveNodes(
|
|
1751
|
+
directives: mergeDirectiveNodes(prev.directives, f.directives),
|
|
1755
1752
|
};
|
|
1756
1753
|
}
|
|
1757
1754
|
else {
|
|
@@ -1770,18 +1767,19 @@ function mergeNamedNodes(a, b) {
|
|
|
1770
1767
|
}
|
|
1771
1768
|
return Object.values(nodes);
|
|
1772
1769
|
}
|
|
1773
|
-
function mergeDirectiveNodes(
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1770
|
+
function mergeDirectiveNodes(a, b) {
|
|
1771
|
+
// Keep each occurrence, because a repeatable directive can occur more than
|
|
1772
|
+
// once. Skip only an occurrence that is identical to one that is already
|
|
1773
|
+
// applied. buildASTSchema rejects a non-repeatable directive that occurs
|
|
1774
|
+
// more than once.
|
|
1775
|
+
const directives = Array.from(a ?? []);
|
|
1776
|
+
for (const d of b ?? []) {
|
|
1777
|
+
if (!directives.some((prev) => prev.name.value === d.name.value &&
|
|
1778
|
+
isArgumentNodesEqual(prev.arguments, d.arguments))) {
|
|
1779
|
+
directives.push(d);
|
|
1780
|
+
}
|
|
1781
|
+
}
|
|
1782
|
+
return directives;
|
|
1785
1783
|
}
|
|
1786
1784
|
function mergeScalarTypeDefinitionNodes(a, b) {
|
|
1787
1785
|
if (a.name.value !== b.name.value) {
|
|
@@ -1789,8 +1787,10 @@ function mergeScalarTypeDefinitionNodes(a, b) {
|
|
|
1789
1787
|
}
|
|
1790
1788
|
return {
|
|
1791
1789
|
kind: graphql.Kind.SCALAR_TYPE_DEFINITION,
|
|
1790
|
+
loc: a.loc,
|
|
1792
1791
|
name: a.name,
|
|
1793
|
-
|
|
1792
|
+
description: a.description || b.description,
|
|
1793
|
+
directives: mergeDirectiveNodes(a.directives, b.directives),
|
|
1794
1794
|
};
|
|
1795
1795
|
}
|
|
1796
1796
|
function mergeObjectTypeDefinitionNodes(a, b) {
|
|
@@ -1800,7 +1800,7 @@ function mergeObjectTypeDefinitionNodes(a, b) {
|
|
|
1800
1800
|
name: a.name,
|
|
1801
1801
|
description: a.description || b.description,
|
|
1802
1802
|
interfaces: mergeNamedNodes(a.interfaces, b.interfaces),
|
|
1803
|
-
directives: mergeDirectiveNodes(a.
|
|
1803
|
+
directives: mergeDirectiveNodes(a.directives, b.directives),
|
|
1804
1804
|
fields: mergeFieldDefinitionNodes(a.name.value, a.fields, b.fields),
|
|
1805
1805
|
};
|
|
1806
1806
|
}
|
|
@@ -1811,7 +1811,7 @@ function mergeInterfaceTypeDefinitionNodes(a, b) {
|
|
|
1811
1811
|
name: a.name,
|
|
1812
1812
|
description: a.description || b.description,
|
|
1813
1813
|
interfaces: mergeNamedNodes(a.interfaces, b.interfaces),
|
|
1814
|
-
directives: mergeDirectiveNodes(a.
|
|
1814
|
+
directives: mergeDirectiveNodes(a.directives, b.directives),
|
|
1815
1815
|
fields: mergeFieldDefinitionNodes(a.name.value, a.fields, b.fields),
|
|
1816
1816
|
};
|
|
1817
1817
|
}
|
|
@@ -1821,7 +1821,7 @@ function mergeUnionTypeDefinitionNodes(a, b) {
|
|
|
1821
1821
|
loc: a.loc,
|
|
1822
1822
|
name: a.name,
|
|
1823
1823
|
description: a.description || b.description,
|
|
1824
|
-
directives: mergeDirectiveNodes(a.
|
|
1824
|
+
directives: mergeDirectiveNodes(a.directives, b.directives),
|
|
1825
1825
|
types: mergeNamedNodes(a.types, b.types),
|
|
1826
1826
|
};
|
|
1827
1827
|
}
|
|
@@ -1830,7 +1830,7 @@ function mergeEnumTypeDefinitionNodes(a, b) {
|
|
|
1830
1830
|
if (b) {
|
|
1831
1831
|
for (const v of b.values || []) {
|
|
1832
1832
|
if (v.name.value in values) {
|
|
1833
|
-
throw setTraceToSchema(new graphql.GraphQLError(`Cannot merge duplicate enum value: ${
|
|
1833
|
+
throw setTraceToSchema(new graphql.GraphQLError(`Cannot merge duplicate enum value: ${a.name.value}.${v.name.value}`), `${a.name.value}.${v.name.value}`, v.loc);
|
|
1834
1834
|
}
|
|
1835
1835
|
values[v.name.value] = v;
|
|
1836
1836
|
}
|
|
@@ -1840,7 +1840,7 @@ function mergeEnumTypeDefinitionNodes(a, b) {
|
|
|
1840
1840
|
loc: a.loc,
|
|
1841
1841
|
name: a.name,
|
|
1842
1842
|
description: a.description || b.description,
|
|
1843
|
-
directives: mergeDirectiveNodes(a.
|
|
1843
|
+
directives: mergeDirectiveNodes(a.directives, b.directives),
|
|
1844
1844
|
values: Object.values(values),
|
|
1845
1845
|
};
|
|
1846
1846
|
}
|
|
@@ -1850,26 +1850,74 @@ function mergeInputObjectTypeDefinitionNodes(a, b) {
|
|
|
1850
1850
|
loc: a.loc,
|
|
1851
1851
|
name: a.name,
|
|
1852
1852
|
description: a.description || b.description,
|
|
1853
|
-
directives: mergeDirectiveNodes(a.
|
|
1853
|
+
directives: mergeDirectiveNodes(a.directives, b.directives),
|
|
1854
1854
|
fields: mergeInputValueDefinitionNodes(a.name.value, a.fields, b.fields),
|
|
1855
1855
|
};
|
|
1856
1856
|
}
|
|
1857
|
+
const EXTENSION_DEFINITION_KINDS = {
|
|
1858
|
+
[graphql.Kind.SCALAR_TYPE_EXTENSION]: graphql.Kind.SCALAR_TYPE_DEFINITION,
|
|
1859
|
+
[graphql.Kind.OBJECT_TYPE_EXTENSION]: graphql.Kind.OBJECT_TYPE_DEFINITION,
|
|
1860
|
+
[graphql.Kind.INTERFACE_TYPE_EXTENSION]: graphql.Kind.INTERFACE_TYPE_DEFINITION,
|
|
1861
|
+
[graphql.Kind.UNION_TYPE_EXTENSION]: graphql.Kind.UNION_TYPE_DEFINITION,
|
|
1862
|
+
[graphql.Kind.ENUM_TYPE_EXTENSION]: graphql.Kind.ENUM_TYPE_DEFINITION,
|
|
1863
|
+
[graphql.Kind.INPUT_OBJECT_TYPE_EXTENSION]: graphql.Kind.INPUT_OBJECT_TYPE_DEFINITION,
|
|
1864
|
+
};
|
|
1865
|
+
function mergeTypeDefinitionNodes(a, b) {
|
|
1866
|
+
switch (b.kind) {
|
|
1867
|
+
case graphql.Kind.SCALAR_TYPE_DEFINITION:
|
|
1868
|
+
return mergeScalarTypeDefinitionNodes(a, b);
|
|
1869
|
+
case graphql.Kind.OBJECT_TYPE_DEFINITION:
|
|
1870
|
+
return mergeObjectTypeDefinitionNodes(a, b);
|
|
1871
|
+
case graphql.Kind.INTERFACE_TYPE_DEFINITION:
|
|
1872
|
+
return mergeInterfaceTypeDefinitionNodes(a, b);
|
|
1873
|
+
case graphql.Kind.UNION_TYPE_DEFINITION:
|
|
1874
|
+
return mergeUnionTypeDefinitionNodes(a, b);
|
|
1875
|
+
case graphql.Kind.ENUM_TYPE_DEFINITION:
|
|
1876
|
+
return mergeEnumTypeDefinitionNodes(a, b);
|
|
1877
|
+
case graphql.Kind.INPUT_OBJECT_TYPE_DEFINITION:
|
|
1878
|
+
return mergeInputObjectTypeDefinitionNodes(a, b);
|
|
1879
|
+
}
|
|
1880
|
+
}
|
|
1881
|
+
function applyTypeExtensionNode(definitions, extension) {
|
|
1882
|
+
const name = extension.name.value;
|
|
1883
|
+
const definition = definitions[name];
|
|
1884
|
+
if (!definition) {
|
|
1885
|
+
throw setTraceToSchema(new graphql.GraphQLError(`Cannot extend type that is not defined: ${name}`), name, extension.loc);
|
|
1886
|
+
}
|
|
1887
|
+
const kind = EXTENSION_DEFINITION_KINDS[extension.kind];
|
|
1888
|
+
if (definition.kind !== kind) {
|
|
1889
|
+
throw setTraceToSchema(new graphql.GraphQLError(`Cannot extend ${definition.kind} with ${extension.kind}: ${name}`), name, extension.loc);
|
|
1890
|
+
}
|
|
1891
|
+
// An extension has the same shape as its definition, without a description.
|
|
1892
|
+
const merged = mergeTypeDefinitionNodes(definition, {
|
|
1893
|
+
...extension,
|
|
1894
|
+
kind,
|
|
1895
|
+
directives: undefined,
|
|
1896
|
+
});
|
|
1897
|
+
// The directives of an extension are added to the directives of the type.
|
|
1898
|
+
// buildASTSchema rejects a non-repeatable directive that occurs more than
|
|
1899
|
+
// once.
|
|
1900
|
+
definitions[name] = {
|
|
1901
|
+
...merged,
|
|
1902
|
+
directives: [
|
|
1903
|
+
...(definition.directives ?? []),
|
|
1904
|
+
...(extension.directives ?? []),
|
|
1905
|
+
],
|
|
1906
|
+
};
|
|
1907
|
+
}
|
|
1857
1908
|
function mergeDocumentNodes(documentNodes) {
|
|
1858
1909
|
const definitions = {};
|
|
1910
|
+
const extensions = [];
|
|
1859
1911
|
for (const documentNode of documentNodes) {
|
|
1860
1912
|
for (const definition of documentNode.definitions) {
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
case graphql.Kind.UNION_TYPE_EXTENSION:
|
|
1870
|
-
case graphql.Kind.ENUM_TYPE_EXTENSION:
|
|
1871
|
-
case graphql.Kind.INPUT_OBJECT_TYPE_EXTENSION:
|
|
1872
|
-
throw new Error(`unexpected definition kind: ${definition.kind}`);
|
|
1913
|
+
if (graphql.isTypeExtensionNode(definition)) {
|
|
1914
|
+
// Apply extensions after all definitions are known, because an
|
|
1915
|
+
// extension can occur before the definition that it extends.
|
|
1916
|
+
extensions.push(definition);
|
|
1917
|
+
continue;
|
|
1918
|
+
}
|
|
1919
|
+
if (!isMergableDefinitionNode(definition)) {
|
|
1920
|
+
throw new Error(`unexpected definition kind: ${definition.kind}`);
|
|
1873
1921
|
}
|
|
1874
1922
|
const prevDefinition = definitions[definition.name.value];
|
|
1875
1923
|
if (!prevDefinition) {
|
|
@@ -1887,30 +1935,12 @@ function mergeDocumentNodes(documentNodes) {
|
|
|
1887
1935
|
prevDefinition.description.value !== definition.description.value) {
|
|
1888
1936
|
console.warn(`WARNING: different descriptions for type ${prevDefinition.name.value}: ${JSON.stringify(prevDefinition.description.value)} and ${JSON.stringify(definition.description.value)}${traceLine(definition.description.loc)}${traceLine(prevDefinition.description.loc, "previously ")}\n`);
|
|
1889
1937
|
}
|
|
1890
|
-
|
|
1891
|
-
case graphql.Kind.SCALAR_TYPE_DEFINITION:
|
|
1892
|
-
definitions[definition.name.value] = mergeScalarTypeDefinitionNodes(prevDefinition, definition);
|
|
1893
|
-
break;
|
|
1894
|
-
case graphql.Kind.OBJECT_TYPE_DEFINITION:
|
|
1895
|
-
definitions[definition.name.value] = mergeObjectTypeDefinitionNodes(prevDefinition, definition);
|
|
1896
|
-
break;
|
|
1897
|
-
case graphql.Kind.INTERFACE_TYPE_DEFINITION:
|
|
1898
|
-
definitions[definition.name.value] =
|
|
1899
|
-
mergeInterfaceTypeDefinitionNodes(prevDefinition, definition);
|
|
1900
|
-
break;
|
|
1901
|
-
case graphql.Kind.UNION_TYPE_DEFINITION:
|
|
1902
|
-
definitions[definition.name.value] = mergeUnionTypeDefinitionNodes(prevDefinition, definition);
|
|
1903
|
-
break;
|
|
1904
|
-
case graphql.Kind.ENUM_TYPE_DEFINITION:
|
|
1905
|
-
definitions[definition.name.value] = mergeEnumTypeDefinitionNodes(prevDefinition, definition);
|
|
1906
|
-
break;
|
|
1907
|
-
case graphql.Kind.INPUT_OBJECT_TYPE_DEFINITION:
|
|
1908
|
-
definitions[definition.name.value] =
|
|
1909
|
-
mergeInputObjectTypeDefinitionNodes(prevDefinition, definition);
|
|
1910
|
-
break;
|
|
1911
|
-
}
|
|
1938
|
+
definitions[definition.name.value] = mergeTypeDefinitionNodes(prevDefinition, definition);
|
|
1912
1939
|
}
|
|
1913
1940
|
}
|
|
1941
|
+
for (const extension of extensions) {
|
|
1942
|
+
applyTypeExtensionNode(definitions, extension);
|
|
1943
|
+
}
|
|
1914
1944
|
return {
|
|
1915
1945
|
kind: graphql.Kind.DOCUMENT,
|
|
1916
1946
|
loc: documentNodes[0].loc,
|
package/build/lib.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import path, { resolve, basename, extname, join } from 'node:path';
|
|
2
2
|
import { pathToFileURL, fileURLToPath } from 'node:url';
|
|
3
|
-
import { GraphQLNonNull, GraphQLList, GraphQLScalarType, GraphQLEnumType, GraphQLDirective, Kind, GraphQLObjectType, getNamedType, getNullableType, GraphQLInterfaceType, GraphQLUnionType, GraphQLInputObjectType, DirectiveLocation, GraphQLError, parse as parse$3, Source, buildASTSchema, validateSchema } from 'graphql';
|
|
3
|
+
import { GraphQLNonNull, GraphQLList, GraphQLScalarType, GraphQLEnumType, GraphQLDirective, Kind, GraphQLObjectType, getNamedType, getNullableType, GraphQLInterfaceType, GraphQLUnionType, GraphQLInputObjectType, DirectiveLocation, specifiedDirectives, isTypeExtensionNode, GraphQLError, isTypeDefinitionNode, parse as parse$3, Source, buildASTSchema, validateSchema } from 'graphql';
|
|
4
4
|
import jen$1, { jen } from 'jennifer-js';
|
|
5
5
|
import format from 'jennifer-js/format';
|
|
6
6
|
import partition from 'just-partition';
|
|
@@ -338,14 +338,8 @@ function renderAstNode(astNode) {
|
|
|
338
338
|
}
|
|
339
339
|
function isBuiltInDirective(name) {
|
|
340
340
|
// https://spec.graphql.org/draft/#sec-Type-System.Directives.Built-in-Directives
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
case "skip":
|
|
344
|
-
case "include":
|
|
345
|
-
case "specifiedBy":
|
|
346
|
-
return true;
|
|
347
|
-
}
|
|
348
|
-
return false;
|
|
341
|
+
// Use the list from graphql, because new versions add directives (for example, @oneOf).
|
|
342
|
+
return specifiedDirectives.some((d) => d.name === name);
|
|
349
343
|
}
|
|
350
344
|
function truthify(arr) {
|
|
351
345
|
return arr.filter(Boolean);
|
|
@@ -1611,6 +1605,9 @@ function setTraceToSchema(err, name, loc) {
|
|
|
1611
1605
|
}
|
|
1612
1606
|
return err;
|
|
1613
1607
|
}
|
|
1608
|
+
function isMergableDefinitionNode(node) {
|
|
1609
|
+
return isTypeDefinitionNode(node) || node.kind === Kind.DIRECTIVE_DEFINITION;
|
|
1610
|
+
}
|
|
1614
1611
|
function namedNodesDict(nodes = []) {
|
|
1615
1612
|
return Object.fromEntries(nodes.map((node) => [node.name.value, node]));
|
|
1616
1613
|
}
|
|
@@ -1724,7 +1721,7 @@ function mergeFieldDefinitionNodes(name, a, b) {
|
|
|
1724
1721
|
console.warn(`WARNING: there is more than one declaration for ${name}.${f.name.value}${traceLine(f.loc)}${traceLine(prev.loc, "previously ")}\n`);
|
|
1725
1722
|
fields[f.name.value] = {
|
|
1726
1723
|
...prev,
|
|
1727
|
-
directives: mergeDirectiveNodes(
|
|
1724
|
+
directives: mergeDirectiveNodes(prev.directives, f.directives),
|
|
1728
1725
|
};
|
|
1729
1726
|
}
|
|
1730
1727
|
else {
|
|
@@ -1749,7 +1746,7 @@ function mergeInputValueDefinitionNodes(name, a, b) {
|
|
|
1749
1746
|
console.warn(`WARNING: there is more than one declaration for ${name}.${f.name.value}${traceLine(f.loc)}${traceLine(prev.loc, "previously ")}\n`);
|
|
1750
1747
|
fields[f.name.value] = {
|
|
1751
1748
|
...prev,
|
|
1752
|
-
directives: mergeDirectiveNodes(
|
|
1749
|
+
directives: mergeDirectiveNodes(prev.directives, f.directives),
|
|
1753
1750
|
};
|
|
1754
1751
|
}
|
|
1755
1752
|
else {
|
|
@@ -1768,18 +1765,19 @@ function mergeNamedNodes(a, b) {
|
|
|
1768
1765
|
}
|
|
1769
1766
|
return Object.values(nodes);
|
|
1770
1767
|
}
|
|
1771
|
-
function mergeDirectiveNodes(
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1768
|
+
function mergeDirectiveNodes(a, b) {
|
|
1769
|
+
// Keep each occurrence, because a repeatable directive can occur more than
|
|
1770
|
+
// once. Skip only an occurrence that is identical to one that is already
|
|
1771
|
+
// applied. buildASTSchema rejects a non-repeatable directive that occurs
|
|
1772
|
+
// more than once.
|
|
1773
|
+
const directives = Array.from(a ?? []);
|
|
1774
|
+
for (const d of b ?? []) {
|
|
1775
|
+
if (!directives.some((prev) => prev.name.value === d.name.value &&
|
|
1776
|
+
isArgumentNodesEqual(prev.arguments, d.arguments))) {
|
|
1777
|
+
directives.push(d);
|
|
1778
|
+
}
|
|
1779
|
+
}
|
|
1780
|
+
return directives;
|
|
1783
1781
|
}
|
|
1784
1782
|
function mergeScalarTypeDefinitionNodes(a, b) {
|
|
1785
1783
|
if (a.name.value !== b.name.value) {
|
|
@@ -1787,8 +1785,10 @@ function mergeScalarTypeDefinitionNodes(a, b) {
|
|
|
1787
1785
|
}
|
|
1788
1786
|
return {
|
|
1789
1787
|
kind: Kind.SCALAR_TYPE_DEFINITION,
|
|
1788
|
+
loc: a.loc,
|
|
1790
1789
|
name: a.name,
|
|
1791
|
-
|
|
1790
|
+
description: a.description || b.description,
|
|
1791
|
+
directives: mergeDirectiveNodes(a.directives, b.directives),
|
|
1792
1792
|
};
|
|
1793
1793
|
}
|
|
1794
1794
|
function mergeObjectTypeDefinitionNodes(a, b) {
|
|
@@ -1798,7 +1798,7 @@ function mergeObjectTypeDefinitionNodes(a, b) {
|
|
|
1798
1798
|
name: a.name,
|
|
1799
1799
|
description: a.description || b.description,
|
|
1800
1800
|
interfaces: mergeNamedNodes(a.interfaces, b.interfaces),
|
|
1801
|
-
directives: mergeDirectiveNodes(a.
|
|
1801
|
+
directives: mergeDirectiveNodes(a.directives, b.directives),
|
|
1802
1802
|
fields: mergeFieldDefinitionNodes(a.name.value, a.fields, b.fields),
|
|
1803
1803
|
};
|
|
1804
1804
|
}
|
|
@@ -1809,7 +1809,7 @@ function mergeInterfaceTypeDefinitionNodes(a, b) {
|
|
|
1809
1809
|
name: a.name,
|
|
1810
1810
|
description: a.description || b.description,
|
|
1811
1811
|
interfaces: mergeNamedNodes(a.interfaces, b.interfaces),
|
|
1812
|
-
directives: mergeDirectiveNodes(a.
|
|
1812
|
+
directives: mergeDirectiveNodes(a.directives, b.directives),
|
|
1813
1813
|
fields: mergeFieldDefinitionNodes(a.name.value, a.fields, b.fields),
|
|
1814
1814
|
};
|
|
1815
1815
|
}
|
|
@@ -1819,7 +1819,7 @@ function mergeUnionTypeDefinitionNodes(a, b) {
|
|
|
1819
1819
|
loc: a.loc,
|
|
1820
1820
|
name: a.name,
|
|
1821
1821
|
description: a.description || b.description,
|
|
1822
|
-
directives: mergeDirectiveNodes(a.
|
|
1822
|
+
directives: mergeDirectiveNodes(a.directives, b.directives),
|
|
1823
1823
|
types: mergeNamedNodes(a.types, b.types),
|
|
1824
1824
|
};
|
|
1825
1825
|
}
|
|
@@ -1828,7 +1828,7 @@ function mergeEnumTypeDefinitionNodes(a, b) {
|
|
|
1828
1828
|
if (b) {
|
|
1829
1829
|
for (const v of b.values || []) {
|
|
1830
1830
|
if (v.name.value in values) {
|
|
1831
|
-
throw setTraceToSchema(new GraphQLError(`Cannot merge duplicate enum value: ${
|
|
1831
|
+
throw setTraceToSchema(new GraphQLError(`Cannot merge duplicate enum value: ${a.name.value}.${v.name.value}`), `${a.name.value}.${v.name.value}`, v.loc);
|
|
1832
1832
|
}
|
|
1833
1833
|
values[v.name.value] = v;
|
|
1834
1834
|
}
|
|
@@ -1838,7 +1838,7 @@ function mergeEnumTypeDefinitionNodes(a, b) {
|
|
|
1838
1838
|
loc: a.loc,
|
|
1839
1839
|
name: a.name,
|
|
1840
1840
|
description: a.description || b.description,
|
|
1841
|
-
directives: mergeDirectiveNodes(a.
|
|
1841
|
+
directives: mergeDirectiveNodes(a.directives, b.directives),
|
|
1842
1842
|
values: Object.values(values),
|
|
1843
1843
|
};
|
|
1844
1844
|
}
|
|
@@ -1848,26 +1848,74 @@ function mergeInputObjectTypeDefinitionNodes(a, b) {
|
|
|
1848
1848
|
loc: a.loc,
|
|
1849
1849
|
name: a.name,
|
|
1850
1850
|
description: a.description || b.description,
|
|
1851
|
-
directives: mergeDirectiveNodes(a.
|
|
1851
|
+
directives: mergeDirectiveNodes(a.directives, b.directives),
|
|
1852
1852
|
fields: mergeInputValueDefinitionNodes(a.name.value, a.fields, b.fields),
|
|
1853
1853
|
};
|
|
1854
1854
|
}
|
|
1855
|
+
const EXTENSION_DEFINITION_KINDS = {
|
|
1856
|
+
[Kind.SCALAR_TYPE_EXTENSION]: Kind.SCALAR_TYPE_DEFINITION,
|
|
1857
|
+
[Kind.OBJECT_TYPE_EXTENSION]: Kind.OBJECT_TYPE_DEFINITION,
|
|
1858
|
+
[Kind.INTERFACE_TYPE_EXTENSION]: Kind.INTERFACE_TYPE_DEFINITION,
|
|
1859
|
+
[Kind.UNION_TYPE_EXTENSION]: Kind.UNION_TYPE_DEFINITION,
|
|
1860
|
+
[Kind.ENUM_TYPE_EXTENSION]: Kind.ENUM_TYPE_DEFINITION,
|
|
1861
|
+
[Kind.INPUT_OBJECT_TYPE_EXTENSION]: Kind.INPUT_OBJECT_TYPE_DEFINITION,
|
|
1862
|
+
};
|
|
1863
|
+
function mergeTypeDefinitionNodes(a, b) {
|
|
1864
|
+
switch (b.kind) {
|
|
1865
|
+
case Kind.SCALAR_TYPE_DEFINITION:
|
|
1866
|
+
return mergeScalarTypeDefinitionNodes(a, b);
|
|
1867
|
+
case Kind.OBJECT_TYPE_DEFINITION:
|
|
1868
|
+
return mergeObjectTypeDefinitionNodes(a, b);
|
|
1869
|
+
case Kind.INTERFACE_TYPE_DEFINITION:
|
|
1870
|
+
return mergeInterfaceTypeDefinitionNodes(a, b);
|
|
1871
|
+
case Kind.UNION_TYPE_DEFINITION:
|
|
1872
|
+
return mergeUnionTypeDefinitionNodes(a, b);
|
|
1873
|
+
case Kind.ENUM_TYPE_DEFINITION:
|
|
1874
|
+
return mergeEnumTypeDefinitionNodes(a, b);
|
|
1875
|
+
case Kind.INPUT_OBJECT_TYPE_DEFINITION:
|
|
1876
|
+
return mergeInputObjectTypeDefinitionNodes(a, b);
|
|
1877
|
+
}
|
|
1878
|
+
}
|
|
1879
|
+
function applyTypeExtensionNode(definitions, extension) {
|
|
1880
|
+
const name = extension.name.value;
|
|
1881
|
+
const definition = definitions[name];
|
|
1882
|
+
if (!definition) {
|
|
1883
|
+
throw setTraceToSchema(new GraphQLError(`Cannot extend type that is not defined: ${name}`), name, extension.loc);
|
|
1884
|
+
}
|
|
1885
|
+
const kind = EXTENSION_DEFINITION_KINDS[extension.kind];
|
|
1886
|
+
if (definition.kind !== kind) {
|
|
1887
|
+
throw setTraceToSchema(new GraphQLError(`Cannot extend ${definition.kind} with ${extension.kind}: ${name}`), name, extension.loc);
|
|
1888
|
+
}
|
|
1889
|
+
// An extension has the same shape as its definition, without a description.
|
|
1890
|
+
const merged = mergeTypeDefinitionNodes(definition, {
|
|
1891
|
+
...extension,
|
|
1892
|
+
kind,
|
|
1893
|
+
directives: undefined,
|
|
1894
|
+
});
|
|
1895
|
+
// The directives of an extension are added to the directives of the type.
|
|
1896
|
+
// buildASTSchema rejects a non-repeatable directive that occurs more than
|
|
1897
|
+
// once.
|
|
1898
|
+
definitions[name] = {
|
|
1899
|
+
...merged,
|
|
1900
|
+
directives: [
|
|
1901
|
+
...(definition.directives ?? []),
|
|
1902
|
+
...(extension.directives ?? []),
|
|
1903
|
+
],
|
|
1904
|
+
};
|
|
1905
|
+
}
|
|
1855
1906
|
function mergeDocumentNodes(documentNodes) {
|
|
1856
1907
|
const definitions = {};
|
|
1908
|
+
const extensions = [];
|
|
1857
1909
|
for (const documentNode of documentNodes) {
|
|
1858
1910
|
for (const definition of documentNode.definitions) {
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
case Kind.UNION_TYPE_EXTENSION:
|
|
1868
|
-
case Kind.ENUM_TYPE_EXTENSION:
|
|
1869
|
-
case Kind.INPUT_OBJECT_TYPE_EXTENSION:
|
|
1870
|
-
throw new Error(`unexpected definition kind: ${definition.kind}`);
|
|
1911
|
+
if (isTypeExtensionNode(definition)) {
|
|
1912
|
+
// Apply extensions after all definitions are known, because an
|
|
1913
|
+
// extension can occur before the definition that it extends.
|
|
1914
|
+
extensions.push(definition);
|
|
1915
|
+
continue;
|
|
1916
|
+
}
|
|
1917
|
+
if (!isMergableDefinitionNode(definition)) {
|
|
1918
|
+
throw new Error(`unexpected definition kind: ${definition.kind}`);
|
|
1871
1919
|
}
|
|
1872
1920
|
const prevDefinition = definitions[definition.name.value];
|
|
1873
1921
|
if (!prevDefinition) {
|
|
@@ -1885,30 +1933,12 @@ function mergeDocumentNodes(documentNodes) {
|
|
|
1885
1933
|
prevDefinition.description.value !== definition.description.value) {
|
|
1886
1934
|
console.warn(`WARNING: different descriptions for type ${prevDefinition.name.value}: ${JSON.stringify(prevDefinition.description.value)} and ${JSON.stringify(definition.description.value)}${traceLine(definition.description.loc)}${traceLine(prevDefinition.description.loc, "previously ")}\n`);
|
|
1887
1935
|
}
|
|
1888
|
-
|
|
1889
|
-
case Kind.SCALAR_TYPE_DEFINITION:
|
|
1890
|
-
definitions[definition.name.value] = mergeScalarTypeDefinitionNodes(prevDefinition, definition);
|
|
1891
|
-
break;
|
|
1892
|
-
case Kind.OBJECT_TYPE_DEFINITION:
|
|
1893
|
-
definitions[definition.name.value] = mergeObjectTypeDefinitionNodes(prevDefinition, definition);
|
|
1894
|
-
break;
|
|
1895
|
-
case Kind.INTERFACE_TYPE_DEFINITION:
|
|
1896
|
-
definitions[definition.name.value] =
|
|
1897
|
-
mergeInterfaceTypeDefinitionNodes(prevDefinition, definition);
|
|
1898
|
-
break;
|
|
1899
|
-
case Kind.UNION_TYPE_DEFINITION:
|
|
1900
|
-
definitions[definition.name.value] = mergeUnionTypeDefinitionNodes(prevDefinition, definition);
|
|
1901
|
-
break;
|
|
1902
|
-
case Kind.ENUM_TYPE_DEFINITION:
|
|
1903
|
-
definitions[definition.name.value] = mergeEnumTypeDefinitionNodes(prevDefinition, definition);
|
|
1904
|
-
break;
|
|
1905
|
-
case Kind.INPUT_OBJECT_TYPE_DEFINITION:
|
|
1906
|
-
definitions[definition.name.value] =
|
|
1907
|
-
mergeInputObjectTypeDefinitionNodes(prevDefinition, definition);
|
|
1908
|
-
break;
|
|
1909
|
-
}
|
|
1936
|
+
definitions[definition.name.value] = mergeTypeDefinitionNodes(prevDefinition, definition);
|
|
1910
1937
|
}
|
|
1911
1938
|
}
|
|
1939
|
+
for (const extension of extensions) {
|
|
1940
|
+
applyTypeExtensionNode(definitions, extension);
|
|
1941
|
+
}
|
|
1912
1942
|
return {
|
|
1913
1943
|
kind: Kind.DOCUMENT,
|
|
1914
1944
|
loc: documentNodes[0].loc,
|