@salesforce/lds-graphql-parser 1.128.0 → 1.128.1
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/ldsGraphqlParser.js +737 -737
- package/package.json +2 -2
package/dist/ldsGraphqlParser.js
CHANGED
@@ -10740,745 +10740,745 @@ function dedentBlockString(blockStr) {
|
|
10740
10740
|
return '"""' + body + '"""';
|
10741
10741
|
}
|
10742
10742
|
|
10743
|
-
/* Util Functions */
|
10744
|
-
function isOperationDefinitionNode(input) {
|
10745
|
-
return input.kind === 'OperationDefinition';
|
10746
|
-
}
|
10747
|
-
function isFragmentDefinitionNode(input) {
|
10748
|
-
return input.kind === 'FragmentDefinition';
|
10749
|
-
}
|
10750
|
-
function isNamedTypeNode(input) {
|
10751
|
-
return input.kind === 'NamedType';
|
10752
|
-
}
|
10753
|
-
function isListTypeNode(input) {
|
10754
|
-
return input.kind === 'ListType';
|
10755
|
-
}
|
10756
|
-
function isNonNullTypeNode(input) {
|
10757
|
-
return input.kind === 'NonNullType';
|
10758
|
-
}
|
10759
|
-
|
10760
|
-
const CUSTOM_DIRECTIVE_CONNECTION = 'connection';
|
10761
|
-
const CUSTOM_DIRECTIVE_RESOURCE = 'resource';
|
10762
|
-
const NODE_KIND_CUSTOM_FIELD_SELECTION = 'CustomFieldSelection';
|
10763
|
-
const NODE_KIND_FIELD = 'Field';
|
10764
|
-
const NODE_KIND_FRAGMENT_SPREAD = 'FragmentSpread';
|
10765
|
-
const NODE_KIND_INLINE_FRAGMENT = 'InlineFragment';
|
10766
|
-
const NODE_KIND_LIST_TYPE = 'ListType';
|
10767
|
-
const NODE_KIND_NAMED_TYPE = 'NamedType';
|
10768
|
-
const NODE_KIND_NON_NULL_TYPE = 'NonNullType';
|
10769
|
-
const NODE_KIND_OBJECT_FIELD_SELECTION = 'ObjectFieldSelection';
|
10770
|
-
const NODE_KIND_SCALAR_FIELD_SELECTION = 'ScalarFieldSelection';
|
10743
|
+
/* Util Functions */
|
10744
|
+
function isOperationDefinitionNode(input) {
|
10745
|
+
return input.kind === 'OperationDefinition';
|
10746
|
+
}
|
10747
|
+
function isFragmentDefinitionNode(input) {
|
10748
|
+
return input.kind === 'FragmentDefinition';
|
10749
|
+
}
|
10750
|
+
function isNamedTypeNode(input) {
|
10751
|
+
return input.kind === 'NamedType';
|
10752
|
+
}
|
10753
|
+
function isListTypeNode(input) {
|
10754
|
+
return input.kind === 'ListType';
|
10755
|
+
}
|
10756
|
+
function isNonNullTypeNode(input) {
|
10757
|
+
return input.kind === 'NonNullType';
|
10758
|
+
}
|
10759
|
+
|
10760
|
+
const CUSTOM_DIRECTIVE_CONNECTION = 'connection';
|
10761
|
+
const CUSTOM_DIRECTIVE_RESOURCE = 'resource';
|
10762
|
+
const NODE_KIND_CUSTOM_FIELD_SELECTION = 'CustomFieldSelection';
|
10763
|
+
const NODE_KIND_FIELD = 'Field';
|
10764
|
+
const NODE_KIND_FRAGMENT_SPREAD = 'FragmentSpread';
|
10765
|
+
const NODE_KIND_INLINE_FRAGMENT = 'InlineFragment';
|
10766
|
+
const NODE_KIND_LIST_TYPE = 'ListType';
|
10767
|
+
const NODE_KIND_NAMED_TYPE = 'NamedType';
|
10768
|
+
const NODE_KIND_NON_NULL_TYPE = 'NonNullType';
|
10769
|
+
const NODE_KIND_OBJECT_FIELD_SELECTION = 'ObjectFieldSelection';
|
10770
|
+
const NODE_KIND_SCALAR_FIELD_SELECTION = 'ScalarFieldSelection';
|
10771
10771
|
const NODE_TYPE_CONNECTION = 'Connection';
|
10772
10772
|
|
10773
|
-
function transform$b(node, transformState) {
|
10774
|
-
switch (node.kind) {
|
10775
|
-
case 'Variable':
|
10776
|
-
transformState.variablesUsed[node.name.value] = true;
|
10777
|
-
return {
|
10778
|
-
kind: 'Variable',
|
10779
|
-
name: node.name.value,
|
10780
|
-
};
|
10781
|
-
case 'IntValue':
|
10782
|
-
return {
|
10783
|
-
kind: 'IntValue',
|
10784
|
-
value: node.value,
|
10785
|
-
};
|
10786
|
-
case 'FloatValue':
|
10787
|
-
return {
|
10788
|
-
kind: 'FloatValue',
|
10789
|
-
value: node.value,
|
10790
|
-
};
|
10791
|
-
case 'StringValue':
|
10792
|
-
return {
|
10793
|
-
kind: 'StringValue',
|
10794
|
-
value: node.value,
|
10795
|
-
};
|
10796
|
-
case 'BooleanValue':
|
10797
|
-
return {
|
10798
|
-
kind: 'BooleanValue',
|
10799
|
-
value: node.value,
|
10800
|
-
};
|
10801
|
-
case 'EnumValue':
|
10802
|
-
return {
|
10803
|
-
kind: 'EnumValue',
|
10804
|
-
value: node.value,
|
10805
|
-
};
|
10806
|
-
case 'NullValue':
|
10807
|
-
return {
|
10808
|
-
kind: 'NullValue',
|
10809
|
-
};
|
10810
|
-
case 'ListValue': {
|
10811
|
-
const values = [];
|
10812
|
-
for (var index = 0; index < node.values.length; index++) {
|
10813
|
-
const value = transform$b(node.values[index], transformState);
|
10814
|
-
values.push(value);
|
10815
|
-
}
|
10816
|
-
return {
|
10817
|
-
kind: 'ListValue',
|
10818
|
-
values: values,
|
10819
|
-
};
|
10820
|
-
}
|
10821
|
-
case 'ObjectValue': {
|
10822
|
-
const { fields } = node;
|
10823
|
-
const result = {};
|
10824
|
-
fields.forEach((field) => {
|
10825
|
-
const name = field.name.value;
|
10826
|
-
const value = transform$b(field.value, transformState);
|
10827
|
-
result[name] = value;
|
10828
|
-
});
|
10829
|
-
return {
|
10830
|
-
kind: 'ObjectValue',
|
10831
|
-
fields: result,
|
10832
|
-
};
|
10833
|
-
}
|
10834
|
-
default:
|
10835
|
-
throw new Error('Unsupported ValueNode kind');
|
10836
|
-
}
|
10837
|
-
}
|
10838
|
-
|
10839
|
-
function transform$a(node, transformState) {
|
10840
|
-
const { kind, name: { value: nodeName }, value: nodeValue, } = node;
|
10841
|
-
const valueNode = transform$b(nodeValue, transformState);
|
10842
|
-
return {
|
10843
|
-
kind,
|
10844
|
-
name: nodeName,
|
10845
|
-
value: valueNode,
|
10846
|
-
};
|
10847
|
-
}
|
10848
|
-
|
10849
|
-
function transform$9(node, transformState) {
|
10850
|
-
const { kind, name: { value: nodeName }, arguments: nodeArguments, } = node;
|
10851
|
-
const ret = {
|
10852
|
-
kind,
|
10853
|
-
name: nodeName,
|
10854
|
-
};
|
10855
|
-
if (nodeArguments !== undefined && nodeArguments.length > 0) {
|
10856
|
-
let returnArguments = [];
|
10857
|
-
for (var index = 0; index < nodeArguments.length; index++) {
|
10858
|
-
const argumentNode = nodeArguments[index];
|
10859
|
-
const value = transform$a(argumentNode, transformState);
|
10860
|
-
returnArguments.push(value);
|
10861
|
-
}
|
10862
|
-
ret.arguments = returnArguments;
|
10863
|
-
}
|
10864
|
-
return ret;
|
10865
|
-
}
|
10866
|
-
function isCustomDirective$1(node) {
|
10867
|
-
return (node.name.value === CUSTOM_DIRECTIVE_CONNECTION ||
|
10868
|
-
node.name.value === CUSTOM_DIRECTIVE_RESOURCE);
|
10869
|
-
}
|
10870
|
-
|
10871
|
-
function transform$8(node, transformState) {
|
10872
|
-
const { name, alias, arguments: fieldArgs, selectionSet, directives } = node;
|
10873
|
-
let luvioNode = {
|
10874
|
-
kind: NODE_KIND_OBJECT_FIELD_SELECTION,
|
10875
|
-
name: name.value,
|
10876
|
-
luvioSelections: [],
|
10877
|
-
};
|
10878
|
-
if (selectionSet === undefined || selectionSet.selections.length === 0) {
|
10879
|
-
luvioNode = {
|
10880
|
-
kind: NODE_KIND_SCALAR_FIELD_SELECTION,
|
10881
|
-
name: name.value,
|
10882
|
-
};
|
10883
|
-
}
|
10884
|
-
else {
|
10885
|
-
// object or custom field node
|
10886
|
-
if (directives !== undefined && directives.length > 0) {
|
10887
|
-
const customDirectiveNode = directives.find(isCustomDirective$1);
|
10888
|
-
if (customDirectiveNode === undefined) {
|
10889
|
-
// transform non client-side directives
|
10890
|
-
luvioNode.directives = directives.map((directive) => transform$9(directive, transformState));
|
10891
|
-
}
|
10892
|
-
else {
|
10893
|
-
if (customDirectiveNode.name.value === CUSTOM_DIRECTIVE_CONNECTION) {
|
10894
|
-
luvioNode = {
|
10895
|
-
kind: NODE_KIND_CUSTOM_FIELD_SELECTION,
|
10896
|
-
name: name.value,
|
10897
|
-
type: NODE_TYPE_CONNECTION,
|
10898
|
-
luvioSelections: [],
|
10899
|
-
};
|
10900
|
-
}
|
10901
|
-
else if (customDirectiveNode.name.value === CUSTOM_DIRECTIVE_RESOURCE) {
|
10902
|
-
luvioNode = {
|
10903
|
-
kind: NODE_KIND_CUSTOM_FIELD_SELECTION,
|
10904
|
-
name: name.value,
|
10905
|
-
type: customDirectiveNode.arguments[0].value.value,
|
10906
|
-
luvioSelections: [],
|
10907
|
-
};
|
10908
|
-
}
|
10909
|
-
}
|
10910
|
-
}
|
10911
|
-
if (fieldArgs !== undefined && fieldArgs.length > 0) {
|
10912
|
-
const returnArguments = [];
|
10913
|
-
for (var index = 0; index < fieldArgs.length; index++) {
|
10914
|
-
const value = transform$a(fieldArgs[index], transformState);
|
10915
|
-
returnArguments.push(value);
|
10916
|
-
}
|
10917
|
-
luvioNode.arguments = returnArguments;
|
10918
|
-
}
|
10919
|
-
}
|
10920
|
-
if (alias !== undefined) {
|
10921
|
-
luvioNode.alias = alias.value;
|
10922
|
-
}
|
10923
|
-
return luvioNode;
|
10924
|
-
}
|
10925
|
-
|
10926
|
-
function transform$7(node, transformState) {
|
10927
|
-
const { kind, name: { value }, directives, } = node;
|
10928
|
-
const luvioNode = {
|
10929
|
-
kind,
|
10930
|
-
name: value,
|
10931
|
-
};
|
10932
|
-
if (directives !== undefined && directives.length > 0) {
|
10933
|
-
luvioNode.directives = directives.map((directive) => transform$9(directive, transformState));
|
10934
|
-
}
|
10935
|
-
return luvioNode;
|
10936
|
-
}
|
10937
|
-
|
10938
|
-
function transform$6(node, transformState) {
|
10939
|
-
const { kind: nodeKind, typeCondition, directives } = node;
|
10940
|
-
const luvioNode = {
|
10941
|
-
kind: nodeKind,
|
10942
|
-
luvioSelections: [],
|
10943
|
-
};
|
10944
|
-
if (typeCondition !== undefined) {
|
10945
|
-
luvioNode.typeCondition = {
|
10946
|
-
kind: typeCondition.kind,
|
10947
|
-
name: typeCondition.name.value,
|
10948
|
-
};
|
10949
|
-
}
|
10950
|
-
if (directives !== undefined && directives.length > 0) {
|
10951
|
-
luvioNode.directives = directives.map((directive) => transform$9(directive, transformState));
|
10952
|
-
}
|
10953
|
-
return luvioNode;
|
10954
|
-
}
|
10955
|
-
|
10956
|
-
function selectionSetVisitor(ast, luvioSelectionPath, transformState) {
|
10957
|
-
const visitor = {
|
10958
|
-
enter(node) {
|
10959
|
-
let selectionNode;
|
10960
|
-
switch (node.kind) {
|
10961
|
-
case NODE_KIND_FIELD: {
|
10962
|
-
const fieldNode = transform$8(node, transformState);
|
10963
|
-
selectionNode = fieldNode;
|
10964
|
-
break;
|
10965
|
-
}
|
10966
|
-
case NODE_KIND_FRAGMENT_SPREAD:
|
10967
|
-
selectionNode = transform$7(node, transformState);
|
10968
|
-
break;
|
10969
|
-
case NODE_KIND_INLINE_FRAGMENT:
|
10970
|
-
selectionNode = transform$6(node, transformState);
|
10971
|
-
break;
|
10972
|
-
}
|
10973
|
-
if (selectionNode !== undefined) {
|
10974
|
-
const parentNode = luvioSelectionPath[luvioSelectionPath.length - 1];
|
10975
|
-
if (parentNode.kind === NODE_KIND_OBJECT_FIELD_SELECTION ||
|
10976
|
-
parentNode.kind === NODE_KIND_CUSTOM_FIELD_SELECTION ||
|
10977
|
-
parentNode.kind === NODE_KIND_INLINE_FRAGMENT) {
|
10978
|
-
parentNode.luvioSelections.push(selectionNode);
|
10979
|
-
}
|
10980
|
-
luvioSelectionPath.push(selectionNode);
|
10981
|
-
}
|
10982
|
-
},
|
10983
|
-
leave(node) {
|
10984
|
-
switch (node.kind) {
|
10985
|
-
case NODE_KIND_FIELD:
|
10986
|
-
case NODE_KIND_FRAGMENT_SPREAD:
|
10987
|
-
case NODE_KIND_INLINE_FRAGMENT:
|
10988
|
-
luvioSelectionPath.pop();
|
10989
|
-
break;
|
10990
|
-
}
|
10991
|
-
},
|
10992
|
-
};
|
10993
|
-
visit(ast, visitor);
|
10994
|
-
}
|
10995
|
-
|
10996
|
-
function transform$5(node) {
|
10997
|
-
if (isNamedTypeNode(node)) {
|
10998
|
-
return {
|
10999
|
-
kind: NODE_KIND_NAMED_TYPE,
|
11000
|
-
name: node.name.value,
|
11001
|
-
};
|
11002
|
-
}
|
11003
|
-
else if (isListTypeNode(node)) {
|
11004
|
-
return {
|
11005
|
-
kind: NODE_KIND_LIST_TYPE,
|
11006
|
-
type: transform$5(node.type),
|
11007
|
-
};
|
11008
|
-
}
|
11009
|
-
else if (isNonNullTypeNode(node)) {
|
11010
|
-
if (isNamedTypeNode(node.type)) {
|
11011
|
-
return {
|
11012
|
-
kind: NODE_KIND_NON_NULL_TYPE,
|
11013
|
-
type: {
|
11014
|
-
kind: NODE_KIND_NAMED_TYPE,
|
11015
|
-
name: node.type.name.value,
|
11016
|
-
},
|
11017
|
-
};
|
11018
|
-
}
|
11019
|
-
else if (isListTypeNode(node.type)) {
|
11020
|
-
return {
|
11021
|
-
kind: NODE_KIND_NON_NULL_TYPE,
|
11022
|
-
type: {
|
11023
|
-
kind: NODE_KIND_LIST_TYPE,
|
11024
|
-
type: transform$5(node.type.type),
|
11025
|
-
},
|
11026
|
-
};
|
11027
|
-
}
|
11028
|
-
else {
|
11029
|
-
throw new Error('Unsupported NonNullTypeNode');
|
11030
|
-
}
|
11031
|
-
}
|
11032
|
-
else {
|
11033
|
-
throw new Error('Unsupported TypeNode');
|
11034
|
-
}
|
11035
|
-
}
|
11036
|
-
|
11037
|
-
function transform$4(variableDefinitions, transformState) {
|
11038
|
-
const { kind, variable: { kind: variableKind, name: { value: variableName }, }, type, defaultValue, } = variableDefinitions;
|
11039
|
-
const ret = {
|
11040
|
-
kind,
|
11041
|
-
variable: {
|
11042
|
-
kind: variableKind,
|
11043
|
-
name: variableName,
|
11044
|
-
},
|
11045
|
-
type: transform$5(type),
|
11046
|
-
};
|
11047
|
-
if (defaultValue !== undefined) {
|
11048
|
-
const value = transform$b(defaultValue, transformState);
|
11049
|
-
ret.defaultValue = value;
|
11050
|
-
}
|
11051
|
-
// TODO: transform directives
|
11052
|
-
return ret;
|
11053
|
-
}
|
11054
|
-
|
11055
|
-
function validateVariables(variableDefinitions, transformState) {
|
11056
|
-
if (process.env.NODE_ENV === 'production') {
|
11057
|
-
throw new ReferenceError("Do not call this function in production becuase we don't want to break existing uses. Other environments are okay because we want to catch errors early.");
|
11058
|
-
}
|
11059
|
-
const variablesDefined = {};
|
11060
|
-
if (variableDefinitions !== undefined) {
|
11061
|
-
for (let i = 0, len = variableDefinitions.length; i < len; i++) {
|
11062
|
-
const definedVariableName = variableDefinitions[i].variable.name.value;
|
11063
|
-
variablesDefined[definedVariableName] = true;
|
11064
|
-
if (transformState.variablesUsed[definedVariableName] === undefined) {
|
11065
|
-
throw new Error(`Variable $${definedVariableName} was defined but never used.`);
|
11066
|
-
}
|
11067
|
-
}
|
11068
|
-
}
|
11069
|
-
const usedVariableKeys = Object.keys(transformState.variablesUsed);
|
11070
|
-
for (let i = 0, len = usedVariableKeys.length; i < len; i++) {
|
11071
|
-
if (variablesDefined[usedVariableKeys[i]] !== true) {
|
11072
|
-
throw new Error(`Variable $${usedVariableKeys[i]} was used but never defined.`);
|
11073
|
-
}
|
11074
|
-
}
|
11075
|
-
}
|
11076
|
-
function transform$3(node) {
|
11077
|
-
const queryRoot = {
|
11078
|
-
kind: 'ObjectFieldSelection',
|
11079
|
-
name: 'query',
|
11080
|
-
luvioSelections: [],
|
11081
|
-
};
|
11082
|
-
const currentNodePath = [queryRoot];
|
11083
|
-
const transformState = {
|
11084
|
-
variablesUsed: {},
|
11085
|
-
};
|
11086
|
-
selectionSetVisitor(node, currentNodePath, transformState);
|
11087
|
-
const operationDefinition = {
|
11088
|
-
kind: 'OperationDefinition',
|
11089
|
-
operation: 'query',
|
11090
|
-
luvioSelections: queryRoot.luvioSelections,
|
11091
|
-
};
|
11092
|
-
if (node.name !== undefined) {
|
11093
|
-
operationDefinition.name = node.name.value;
|
11094
|
-
}
|
11095
|
-
const { variableDefinitions, directives } = node;
|
11096
|
-
if (variableDefinitions !== undefined && variableDefinitions.length > 0) {
|
11097
|
-
operationDefinition.variableDefinitions = variableDefinitions.map((variableDefinition) => transform$4(variableDefinition, transformState));
|
11098
|
-
}
|
11099
|
-
if (directives !== undefined && directives.length > 0) {
|
11100
|
-
operationDefinition.directives = directives.map((node) => transform$9(node, transformState));
|
11101
|
-
}
|
11102
|
-
if (process.env.NODE_ENV !== 'production') {
|
11103
|
-
validateVariables(variableDefinitions, transformState);
|
11104
|
-
}
|
11105
|
-
return operationDefinition;
|
11106
|
-
}
|
11107
|
-
|
11108
|
-
function transform$2(node) {
|
11109
|
-
const { operation } = node;
|
11110
|
-
if (operation === 'query') {
|
11111
|
-
return transform$3(node);
|
11112
|
-
}
|
11113
|
-
throw new Error(`Unsupported ${operation} operation. Only query operation is supported`);
|
11114
|
-
}
|
11115
|
-
|
11116
|
-
function transform$1(node) {
|
11117
|
-
const { kind: nodeKind, name: { value: nodeName }, typeCondition: { kind: typeKind, name: { value: typeName }, }, directives, } = node;
|
11118
|
-
// dummy root node
|
11119
|
-
const fragmentRoot = {
|
11120
|
-
kind: NODE_KIND_OBJECT_FIELD_SELECTION,
|
11121
|
-
name: 'fragment',
|
11122
|
-
luvioSelections: [],
|
11123
|
-
};
|
11124
|
-
const currentNodePath = [fragmentRoot];
|
11125
|
-
const transformState = { variablesUsed: {} };
|
11126
|
-
selectionSetVisitor(node, currentNodePath, transformState);
|
11127
|
-
const luvioNode = {
|
11128
|
-
kind: nodeKind,
|
11129
|
-
name: nodeName,
|
11130
|
-
typeCondition: {
|
11131
|
-
kind: typeKind,
|
11132
|
-
name: typeName,
|
11133
|
-
},
|
11134
|
-
luvioSelections: fragmentRoot.luvioSelections,
|
11135
|
-
};
|
11136
|
-
if (directives !== undefined && directives.length > 0) {
|
11137
|
-
luvioNode.directives = directives.map((node) => transform$9(node, transformState));
|
11138
|
-
}
|
11139
|
-
return luvioNode;
|
11140
|
-
}
|
11141
|
-
|
11142
|
-
function transform(root) {
|
11143
|
-
const { kind, definitions } = root;
|
11144
|
-
const luvioDefinitions = [];
|
11145
|
-
for (let i = 0; i < definitions.length; i++) {
|
11146
|
-
const definition = definitions[i];
|
11147
|
-
if (isOperationDefinitionNode(definition)) {
|
11148
|
-
luvioDefinitions.push(transform$2(definition));
|
11149
|
-
}
|
11150
|
-
else if (isFragmentDefinitionNode(definition)) {
|
11151
|
-
luvioDefinitions.push(transform$1(definition));
|
11152
|
-
}
|
11153
|
-
else {
|
11154
|
-
if (process.env.NODE_ENV !== 'production') {
|
11155
|
-
throw new Error(`Unsupported ${definition.kind} definition. Only OperationDefinition and FragmentDefinition are supported in a GraphQL Document`);
|
11156
|
-
}
|
11157
|
-
}
|
11158
|
-
}
|
11159
|
-
return {
|
11160
|
-
kind,
|
11161
|
-
definitions: luvioDefinitions,
|
11162
|
-
};
|
11163
|
-
}
|
11164
|
-
|
11165
|
-
/**
|
11166
|
-
* we should look into optimizing this before it turns into a memory hog
|
11167
|
-
* weakmaps, or limiting the size of the cache, or something
|
11168
|
-
*/
|
11169
|
-
const docMap = new Map();
|
11170
|
-
/**
|
11171
|
-
* Opaque reference map to return keys to userland
|
11172
|
-
* As a user shouldn't have access to the Document
|
11173
|
-
*/
|
11174
|
-
const referenceMap = new WeakMap();
|
11175
|
-
/**
|
11176
|
-
* Strips characters that are not significant to the validity or execution
|
11177
|
-
* of a GraphQL document:
|
11178
|
-
* - UnicodeBOM
|
11179
|
-
* - WhiteSpace
|
11180
|
-
* - LineTerminator
|
11181
|
-
* - Comment
|
11182
|
-
* - Comma
|
11183
|
-
* - BlockString indentation
|
11184
|
-
*/
|
11185
|
-
function operationKeyBuilder(inputString) {
|
11186
|
-
return stripIgnoredCharacters(inputString);
|
11187
|
-
}
|
11188
|
-
/**
|
11189
|
-
* Returns document node if cached or else update the cache and return the document node
|
11190
|
-
* @param inputString - operation string
|
11191
|
-
* @returns DocumentNode
|
11192
|
-
*/
|
11193
|
-
function parseDocument(inputString) {
|
11194
|
-
const operationKey = operationKeyBuilder(inputString);
|
11195
|
-
const cachedDoc = docMap.get(operationKey);
|
11196
|
-
if (cachedDoc !== undefined) {
|
11197
|
-
return cachedDoc;
|
11198
|
-
}
|
11199
|
-
// parse throws an GraphQLError in case of invalid query, should this be in try/catch?
|
11200
|
-
const parsedDoc = parse(inputString, { noLocation: true });
|
11201
|
-
if (!parsedDoc || parsedDoc.kind !== 'Document') {
|
11202
|
-
if (process.env.NODE_ENV !== 'production') {
|
11203
|
-
throw new Error('Invalid graphql doc');
|
11204
|
-
}
|
11205
|
-
return null;
|
11206
|
-
}
|
11207
|
-
docMap.set(operationKey, parsedDoc);
|
11208
|
-
return parsedDoc;
|
11209
|
-
}
|
11210
|
-
/**
|
11211
|
-
* If the input string has fragment substitution
|
11212
|
-
* Insert the fragments AST to the query document node
|
11213
|
-
*/
|
11214
|
-
function insertFragments(doc, fragments) {
|
11215
|
-
fragments.forEach((fragment) => {
|
11216
|
-
// @ts-ignore
|
11217
|
-
// graphql describes definitions as "readonly"
|
11218
|
-
// so we aren't supposed to mutate the document node
|
11219
|
-
// but instead of parsing the fragment again, we substitute it's definition in the document node
|
11220
|
-
doc.definitions.push(fragment);
|
11221
|
-
});
|
11222
|
-
return doc;
|
11223
|
-
}
|
11224
|
-
function updateReferenceMapWithKnownKey(doc, key) {
|
11225
|
-
referenceMap.set(key, doc);
|
11226
|
-
}
|
11227
|
-
function updateReferenceMapAndGetKey(doc) {
|
11228
|
-
// the key is a String object so that legacy locker does not replace its identity.
|
11229
|
-
const key = new String();
|
11230
|
-
updateReferenceMapWithKnownKey(doc, key);
|
11231
|
-
return key;
|
11232
|
-
}
|
11233
|
-
/**
|
11234
|
-
* Insert string and fragment substitutions with the actual nodes
|
11235
|
-
* @param inputString
|
11236
|
-
* @param substitutions - string | fragment DocumentNode
|
11237
|
-
* @returns { operation string, fragment docs [] }
|
11238
|
-
*/
|
11239
|
-
function processSubstitutions(inputString, substitutions) {
|
11240
|
-
let outputString = '';
|
11241
|
-
const fragments = [];
|
11242
|
-
const subLength = substitutions.length;
|
11243
|
-
for (let i = 0; i < subLength; i++) {
|
11244
|
-
const substitution = substitutions[i];
|
11245
|
-
outputString += inputString[i];
|
11246
|
-
if (typeof substitution === 'string' || typeof substitution === 'number') {
|
11247
|
-
outputString += substitution;
|
11248
|
-
}
|
11249
|
-
else if (typeof substitution === 'object') {
|
11250
|
-
const doc = referenceMap.get(substitution);
|
11251
|
-
if (doc === undefined) {
|
11252
|
-
if (process.env.NODE_ENV !== 'production') {
|
11253
|
-
throw new Error('Invalid substitution fragment');
|
11254
|
-
}
|
11255
|
-
return null;
|
11256
|
-
}
|
11257
|
-
for (const def of doc.definitions) {
|
11258
|
-
fragments.push(def);
|
11259
|
-
}
|
11260
|
-
}
|
11261
|
-
else {
|
11262
|
-
if (process.env.NODE_ENV !== 'production') {
|
11263
|
-
throw new Error('Unsupported substitution type');
|
11264
|
-
}
|
11265
|
-
return null;
|
11266
|
-
}
|
11267
|
-
}
|
11268
|
-
return {
|
11269
|
-
operationString: outputString + inputString[subLength],
|
11270
|
-
fragments,
|
11271
|
-
};
|
11272
|
-
}
|
11273
|
-
/**
|
11274
|
-
*
|
11275
|
-
* @param astReference - ast reference passed from user land
|
11276
|
-
*/
|
11277
|
-
const astResolver = function (astReference) {
|
11278
|
-
return referenceMap.get(astReference);
|
11279
|
-
};
|
11280
|
-
/**
|
11281
|
-
*
|
11282
|
-
* @param literals - operation query string
|
11283
|
-
* @param subs - all other substitutions
|
11284
|
-
* @returns an opaque reference to the parsed document
|
11285
|
-
*/
|
11286
|
-
function gql(literals, ...subs) {
|
11287
|
-
let inputString;
|
11288
|
-
let inputSubstitutionFragments;
|
11289
|
-
if (!literals) {
|
11290
|
-
if (process.env.NODE_ENV !== 'production') {
|
11291
|
-
throw new Error('Invalid query');
|
11292
|
-
}
|
11293
|
-
return null;
|
11294
|
-
}
|
11295
|
-
else if (typeof literals === 'string') {
|
11296
|
-
inputString = literals.trim();
|
11297
|
-
inputSubstitutionFragments = [];
|
11298
|
-
}
|
11299
|
-
else {
|
11300
|
-
// called as template literal
|
11301
|
-
const sub = processSubstitutions(literals, subs);
|
11302
|
-
// if invalid fragment references found
|
11303
|
-
if (sub === null) {
|
11304
|
-
return null;
|
11305
|
-
}
|
11306
|
-
const { operationString, fragments } = sub;
|
11307
|
-
inputString = operationString.trim();
|
11308
|
-
inputSubstitutionFragments = fragments;
|
11309
|
-
}
|
11310
|
-
if (inputString.length === 0) {
|
11311
|
-
if (process.env.NODE_ENV !== 'production') {
|
11312
|
-
throw new Error('Invalid query');
|
11313
|
-
}
|
11314
|
-
return null;
|
11315
|
-
}
|
11316
|
-
const document = parseDocument(inputString);
|
11317
|
-
if (document === null) {
|
11318
|
-
return null;
|
11319
|
-
}
|
11320
|
-
if (inputSubstitutionFragments.length === 0) {
|
11321
|
-
return updateReferenceMapAndGetKey(document);
|
11322
|
-
}
|
11323
|
-
return updateReferenceMapAndGetKey(insertFragments(document, inputSubstitutionFragments));
|
11324
|
-
}
|
11325
|
-
|
11326
|
-
const DIRECTIVE_RECORD_QUERY_CATEGORY = {
|
11327
|
-
kind: 'Directive',
|
11328
|
-
name: {
|
11329
|
-
kind: 'Name',
|
11330
|
-
value: 'category',
|
11331
|
-
},
|
11332
|
-
arguments: [
|
11333
|
-
{
|
11334
|
-
kind: 'Argument',
|
11335
|
-
name: {
|
11336
|
-
kind: 'Name',
|
11337
|
-
value: 'name',
|
11338
|
-
},
|
11339
|
-
value: {
|
11340
|
-
kind: 'StringValue',
|
11341
|
-
value: 'recordQuery',
|
11342
|
-
block: false,
|
11343
|
-
},
|
11344
|
-
},
|
11345
|
-
],
|
11346
|
-
};
|
11347
|
-
const DIRECTIVE_CHILD_RELATIONSHIP_CATEGORY = {
|
11348
|
-
kind: 'Directive',
|
11349
|
-
name: {
|
11350
|
-
kind: 'Name',
|
11351
|
-
value: 'category',
|
11352
|
-
},
|
11353
|
-
arguments: [
|
11354
|
-
{
|
11355
|
-
kind: 'Argument',
|
11356
|
-
name: {
|
11357
|
-
kind: 'Name',
|
11358
|
-
value: 'name',
|
11359
|
-
},
|
11360
|
-
value: {
|
11361
|
-
kind: 'StringValue',
|
11362
|
-
value: 'childRelationship',
|
11363
|
-
block: false,
|
11364
|
-
},
|
11365
|
-
},
|
11366
|
-
],
|
11367
|
-
};
|
11368
|
-
const DIRECTIVE_PARENT_CATEGORY = {
|
11369
|
-
kind: 'Directive',
|
11370
|
-
name: {
|
11371
|
-
kind: 'Name',
|
11372
|
-
value: 'category',
|
11373
|
-
},
|
11374
|
-
arguments: [
|
11375
|
-
{
|
11376
|
-
kind: 'Argument',
|
11377
|
-
name: {
|
11378
|
-
kind: 'Name',
|
11379
|
-
value: 'name',
|
11380
|
-
},
|
11381
|
-
value: {
|
11382
|
-
kind: 'StringValue',
|
11383
|
-
value: 'parentRelationship',
|
11384
|
-
block: false,
|
11385
|
-
},
|
11386
|
-
},
|
11387
|
-
],
|
11388
|
-
};
|
11389
|
-
function substituteDirectives(directives, index, selection, parentNode) {
|
11390
|
-
if (directives[index].name.value === CUSTOM_DIRECTIVE_CONNECTION) {
|
11391
|
-
if (parentNode !== undefined &&
|
11392
|
-
parentNode.kind === 'Field' &&
|
11393
|
-
parentNode.name.value === 'uiapi') {
|
11394
|
-
// @ts-ignore - Document is read only
|
11395
|
-
directives[index] = DIRECTIVE_RECORD_QUERY_CATEGORY;
|
11396
|
-
}
|
11397
|
-
else {
|
11398
|
-
// @ts-ignore - Document is read only
|
11399
|
-
directives[index] = DIRECTIVE_CHILD_RELATIONSHIP_CATEGORY;
|
11400
|
-
}
|
11401
|
-
}
|
11402
|
-
else if (directives[index].name.value === CUSTOM_DIRECTIVE_RESOURCE) {
|
11403
|
-
// node gets its type from @category recordQuery or @category childRelationship
|
11404
|
-
if (selection.kind === 'Field' && selection.name.value === 'node') {
|
11405
|
-
// @ts-ignore - Document is read only
|
11406
|
-
directives.splice(index, 1);
|
11407
|
-
}
|
11408
|
-
else {
|
11409
|
-
// @ts-ignore - Document is read only
|
11410
|
-
directives[index] = DIRECTIVE_PARENT_CATEGORY;
|
11411
|
-
}
|
11412
|
-
}
|
11413
|
-
}
|
11414
|
-
/**
|
11415
|
-
* Returns true if the directive node is of legacy type
|
11416
|
-
* @param node : Directive node
|
11417
|
-
* @returns
|
11418
|
-
*/
|
11419
|
-
function isCustomDirective(node) {
|
11420
|
-
return (node.name.value === CUSTOM_DIRECTIVE_CONNECTION ||
|
11421
|
-
node.name.value === CUSTOM_DIRECTIVE_RESOURCE);
|
11422
|
-
}
|
11423
|
-
/**
|
11424
|
-
* Traverses a selection and it's nested selections,
|
11425
|
-
* to find any legacy custom directives and substitute them with metaschema directives
|
11426
|
-
* @param node - SelectionNode
|
11427
|
-
* @returns void
|
11428
|
-
*/
|
11429
|
-
function traverseSelection(node, parentNode) {
|
11430
|
-
if (node === undefined || node.kind === 'FragmentSpread' || node.selectionSet === undefined) {
|
11431
|
-
return;
|
11432
|
-
}
|
11433
|
-
const { selectionSet } = node;
|
11434
|
-
for (const selection of selectionSet.selections) {
|
11435
|
-
replaceCustomDirectives(selection, parentNode);
|
11436
|
-
traverseSelection(selection, node);
|
11437
|
-
}
|
11438
|
-
}
|
11439
|
-
function replaceCustomDirectives(selection, parentNode) {
|
11440
|
-
const { directives } = selection;
|
11441
|
-
if (directives !== undefined && directives.length > 0) {
|
11442
|
-
// we follow this pattern instead of map to preserve the order of directives
|
11443
|
-
// order of directives may be significant as per graphql spec
|
11444
|
-
const index = directives.findIndex(isCustomDirective);
|
11445
|
-
if (index !== -1) {
|
11446
|
-
substituteDirectives(directives, index, selection, parentNode);
|
11447
|
-
}
|
11448
|
-
}
|
11449
|
-
}
|
11450
|
-
/**
|
11451
|
-
* Accepts a document node and replaces the legacy custom directives with metaschema directives "in-place"
|
11452
|
-
* @param doc
|
11453
|
-
*/
|
11454
|
-
function metaschemaMapper(doc) {
|
11455
|
-
// this method is only callable for Executable definitions
|
11456
|
-
// such as Operations and Fragments
|
11457
|
-
// so we have to explicitly cast the definitions for ts
|
11458
|
-
const { definitions } = doc;
|
11459
|
-
for (const def of definitions) {
|
11460
|
-
const { selectionSet } = def;
|
11461
|
-
// This is just iterating through the top level 'Query' operations. There should never be any custom
|
11462
|
-
// directives at this level, as RecordQuery is actually a field lower in the schema. So we can skip looking for them.
|
11463
|
-
selectionSet.selections.forEach((selection) => {
|
11464
|
-
traverseSelection(selection);
|
11465
|
-
});
|
11466
|
-
}
|
11467
|
-
}
|
11468
|
-
|
11469
|
-
/**
|
11470
|
-
* @deprecated In favor of gql tagged template literal
|
11471
|
-
*/
|
11472
|
-
function parseAndVisit(source) {
|
11473
|
-
const ast = parse(source, { noLocation: true });
|
11474
|
-
const luvioDocumentNode = transform(ast);
|
11475
|
-
// In-place substitution of metaschema annotations
|
11476
|
-
metaschemaMapper(ast);
|
11477
|
-
// Set the AST reference map with LuvioDocumentNode as the key
|
11478
|
-
// ASTResolver will resolve it to metaschema mapped AST
|
11479
|
-
updateReferenceMapWithKnownKey(ast, luvioDocumentNode);
|
11480
|
-
return luvioDocumentNode;
|
10773
|
+
function transform$b(node, transformState) {
|
10774
|
+
switch (node.kind) {
|
10775
|
+
case 'Variable':
|
10776
|
+
transformState.variablesUsed[node.name.value] = true;
|
10777
|
+
return {
|
10778
|
+
kind: 'Variable',
|
10779
|
+
name: node.name.value,
|
10780
|
+
};
|
10781
|
+
case 'IntValue':
|
10782
|
+
return {
|
10783
|
+
kind: 'IntValue',
|
10784
|
+
value: node.value,
|
10785
|
+
};
|
10786
|
+
case 'FloatValue':
|
10787
|
+
return {
|
10788
|
+
kind: 'FloatValue',
|
10789
|
+
value: node.value,
|
10790
|
+
};
|
10791
|
+
case 'StringValue':
|
10792
|
+
return {
|
10793
|
+
kind: 'StringValue',
|
10794
|
+
value: node.value,
|
10795
|
+
};
|
10796
|
+
case 'BooleanValue':
|
10797
|
+
return {
|
10798
|
+
kind: 'BooleanValue',
|
10799
|
+
value: node.value,
|
10800
|
+
};
|
10801
|
+
case 'EnumValue':
|
10802
|
+
return {
|
10803
|
+
kind: 'EnumValue',
|
10804
|
+
value: node.value,
|
10805
|
+
};
|
10806
|
+
case 'NullValue':
|
10807
|
+
return {
|
10808
|
+
kind: 'NullValue',
|
10809
|
+
};
|
10810
|
+
case 'ListValue': {
|
10811
|
+
const values = [];
|
10812
|
+
for (var index = 0; index < node.values.length; index++) {
|
10813
|
+
const value = transform$b(node.values[index], transformState);
|
10814
|
+
values.push(value);
|
10815
|
+
}
|
10816
|
+
return {
|
10817
|
+
kind: 'ListValue',
|
10818
|
+
values: values,
|
10819
|
+
};
|
10820
|
+
}
|
10821
|
+
case 'ObjectValue': {
|
10822
|
+
const { fields } = node;
|
10823
|
+
const result = {};
|
10824
|
+
fields.forEach((field) => {
|
10825
|
+
const name = field.name.value;
|
10826
|
+
const value = transform$b(field.value, transformState);
|
10827
|
+
result[name] = value;
|
10828
|
+
});
|
10829
|
+
return {
|
10830
|
+
kind: 'ObjectValue',
|
10831
|
+
fields: result,
|
10832
|
+
};
|
10833
|
+
}
|
10834
|
+
default:
|
10835
|
+
throw new Error('Unsupported ValueNode kind');
|
10836
|
+
}
|
10837
|
+
}
|
10838
|
+
|
10839
|
+
function transform$a(node, transformState) {
|
10840
|
+
const { kind, name: { value: nodeName }, value: nodeValue, } = node;
|
10841
|
+
const valueNode = transform$b(nodeValue, transformState);
|
10842
|
+
return {
|
10843
|
+
kind,
|
10844
|
+
name: nodeName,
|
10845
|
+
value: valueNode,
|
10846
|
+
};
|
10847
|
+
}
|
10848
|
+
|
10849
|
+
function transform$9(node, transformState) {
|
10850
|
+
const { kind, name: { value: nodeName }, arguments: nodeArguments, } = node;
|
10851
|
+
const ret = {
|
10852
|
+
kind,
|
10853
|
+
name: nodeName,
|
10854
|
+
};
|
10855
|
+
if (nodeArguments !== undefined && nodeArguments.length > 0) {
|
10856
|
+
let returnArguments = [];
|
10857
|
+
for (var index = 0; index < nodeArguments.length; index++) {
|
10858
|
+
const argumentNode = nodeArguments[index];
|
10859
|
+
const value = transform$a(argumentNode, transformState);
|
10860
|
+
returnArguments.push(value);
|
10861
|
+
}
|
10862
|
+
ret.arguments = returnArguments;
|
10863
|
+
}
|
10864
|
+
return ret;
|
10865
|
+
}
|
10866
|
+
function isCustomDirective$1(node) {
|
10867
|
+
return (node.name.value === CUSTOM_DIRECTIVE_CONNECTION ||
|
10868
|
+
node.name.value === CUSTOM_DIRECTIVE_RESOURCE);
|
10869
|
+
}
|
10870
|
+
|
10871
|
+
function transform$8(node, transformState) {
|
10872
|
+
const { name, alias, arguments: fieldArgs, selectionSet, directives } = node;
|
10873
|
+
let luvioNode = {
|
10874
|
+
kind: NODE_KIND_OBJECT_FIELD_SELECTION,
|
10875
|
+
name: name.value,
|
10876
|
+
luvioSelections: [],
|
10877
|
+
};
|
10878
|
+
if (selectionSet === undefined || selectionSet.selections.length === 0) {
|
10879
|
+
luvioNode = {
|
10880
|
+
kind: NODE_KIND_SCALAR_FIELD_SELECTION,
|
10881
|
+
name: name.value,
|
10882
|
+
};
|
10883
|
+
}
|
10884
|
+
else {
|
10885
|
+
// object or custom field node
|
10886
|
+
if (directives !== undefined && directives.length > 0) {
|
10887
|
+
const customDirectiveNode = directives.find(isCustomDirective$1);
|
10888
|
+
if (customDirectiveNode === undefined) {
|
10889
|
+
// transform non client-side directives
|
10890
|
+
luvioNode.directives = directives.map((directive) => transform$9(directive, transformState));
|
10891
|
+
}
|
10892
|
+
else {
|
10893
|
+
if (customDirectiveNode.name.value === CUSTOM_DIRECTIVE_CONNECTION) {
|
10894
|
+
luvioNode = {
|
10895
|
+
kind: NODE_KIND_CUSTOM_FIELD_SELECTION,
|
10896
|
+
name: name.value,
|
10897
|
+
type: NODE_TYPE_CONNECTION,
|
10898
|
+
luvioSelections: [],
|
10899
|
+
};
|
10900
|
+
}
|
10901
|
+
else if (customDirectiveNode.name.value === CUSTOM_DIRECTIVE_RESOURCE) {
|
10902
|
+
luvioNode = {
|
10903
|
+
kind: NODE_KIND_CUSTOM_FIELD_SELECTION,
|
10904
|
+
name: name.value,
|
10905
|
+
type: customDirectiveNode.arguments[0].value.value,
|
10906
|
+
luvioSelections: [],
|
10907
|
+
};
|
10908
|
+
}
|
10909
|
+
}
|
10910
|
+
}
|
10911
|
+
if (fieldArgs !== undefined && fieldArgs.length > 0) {
|
10912
|
+
const returnArguments = [];
|
10913
|
+
for (var index = 0; index < fieldArgs.length; index++) {
|
10914
|
+
const value = transform$a(fieldArgs[index], transformState);
|
10915
|
+
returnArguments.push(value);
|
10916
|
+
}
|
10917
|
+
luvioNode.arguments = returnArguments;
|
10918
|
+
}
|
10919
|
+
}
|
10920
|
+
if (alias !== undefined) {
|
10921
|
+
luvioNode.alias = alias.value;
|
10922
|
+
}
|
10923
|
+
return luvioNode;
|
10924
|
+
}
|
10925
|
+
|
10926
|
+
function transform$7(node, transformState) {
|
10927
|
+
const { kind, name: { value }, directives, } = node;
|
10928
|
+
const luvioNode = {
|
10929
|
+
kind,
|
10930
|
+
name: value,
|
10931
|
+
};
|
10932
|
+
if (directives !== undefined && directives.length > 0) {
|
10933
|
+
luvioNode.directives = directives.map((directive) => transform$9(directive, transformState));
|
10934
|
+
}
|
10935
|
+
return luvioNode;
|
10936
|
+
}
|
10937
|
+
|
10938
|
+
function transform$6(node, transformState) {
|
10939
|
+
const { kind: nodeKind, typeCondition, directives } = node;
|
10940
|
+
const luvioNode = {
|
10941
|
+
kind: nodeKind,
|
10942
|
+
luvioSelections: [],
|
10943
|
+
};
|
10944
|
+
if (typeCondition !== undefined) {
|
10945
|
+
luvioNode.typeCondition = {
|
10946
|
+
kind: typeCondition.kind,
|
10947
|
+
name: typeCondition.name.value,
|
10948
|
+
};
|
10949
|
+
}
|
10950
|
+
if (directives !== undefined && directives.length > 0) {
|
10951
|
+
luvioNode.directives = directives.map((directive) => transform$9(directive, transformState));
|
10952
|
+
}
|
10953
|
+
return luvioNode;
|
10954
|
+
}
|
10955
|
+
|
10956
|
+
function selectionSetVisitor(ast, luvioSelectionPath, transformState) {
|
10957
|
+
const visitor = {
|
10958
|
+
enter(node) {
|
10959
|
+
let selectionNode;
|
10960
|
+
switch (node.kind) {
|
10961
|
+
case NODE_KIND_FIELD: {
|
10962
|
+
const fieldNode = transform$8(node, transformState);
|
10963
|
+
selectionNode = fieldNode;
|
10964
|
+
break;
|
10965
|
+
}
|
10966
|
+
case NODE_KIND_FRAGMENT_SPREAD:
|
10967
|
+
selectionNode = transform$7(node, transformState);
|
10968
|
+
break;
|
10969
|
+
case NODE_KIND_INLINE_FRAGMENT:
|
10970
|
+
selectionNode = transform$6(node, transformState);
|
10971
|
+
break;
|
10972
|
+
}
|
10973
|
+
if (selectionNode !== undefined) {
|
10974
|
+
const parentNode = luvioSelectionPath[luvioSelectionPath.length - 1];
|
10975
|
+
if (parentNode.kind === NODE_KIND_OBJECT_FIELD_SELECTION ||
|
10976
|
+
parentNode.kind === NODE_KIND_CUSTOM_FIELD_SELECTION ||
|
10977
|
+
parentNode.kind === NODE_KIND_INLINE_FRAGMENT) {
|
10978
|
+
parentNode.luvioSelections.push(selectionNode);
|
10979
|
+
}
|
10980
|
+
luvioSelectionPath.push(selectionNode);
|
10981
|
+
}
|
10982
|
+
},
|
10983
|
+
leave(node) {
|
10984
|
+
switch (node.kind) {
|
10985
|
+
case NODE_KIND_FIELD:
|
10986
|
+
case NODE_KIND_FRAGMENT_SPREAD:
|
10987
|
+
case NODE_KIND_INLINE_FRAGMENT:
|
10988
|
+
luvioSelectionPath.pop();
|
10989
|
+
break;
|
10990
|
+
}
|
10991
|
+
},
|
10992
|
+
};
|
10993
|
+
visit(ast, visitor);
|
10994
|
+
}
|
10995
|
+
|
10996
|
+
function transform$5(node) {
|
10997
|
+
if (isNamedTypeNode(node)) {
|
10998
|
+
return {
|
10999
|
+
kind: NODE_KIND_NAMED_TYPE,
|
11000
|
+
name: node.name.value,
|
11001
|
+
};
|
11002
|
+
}
|
11003
|
+
else if (isListTypeNode(node)) {
|
11004
|
+
return {
|
11005
|
+
kind: NODE_KIND_LIST_TYPE,
|
11006
|
+
type: transform$5(node.type),
|
11007
|
+
};
|
11008
|
+
}
|
11009
|
+
else if (isNonNullTypeNode(node)) {
|
11010
|
+
if (isNamedTypeNode(node.type)) {
|
11011
|
+
return {
|
11012
|
+
kind: NODE_KIND_NON_NULL_TYPE,
|
11013
|
+
type: {
|
11014
|
+
kind: NODE_KIND_NAMED_TYPE,
|
11015
|
+
name: node.type.name.value,
|
11016
|
+
},
|
11017
|
+
};
|
11018
|
+
}
|
11019
|
+
else if (isListTypeNode(node.type)) {
|
11020
|
+
return {
|
11021
|
+
kind: NODE_KIND_NON_NULL_TYPE,
|
11022
|
+
type: {
|
11023
|
+
kind: NODE_KIND_LIST_TYPE,
|
11024
|
+
type: transform$5(node.type.type),
|
11025
|
+
},
|
11026
|
+
};
|
11027
|
+
}
|
11028
|
+
else {
|
11029
|
+
throw new Error('Unsupported NonNullTypeNode');
|
11030
|
+
}
|
11031
|
+
}
|
11032
|
+
else {
|
11033
|
+
throw new Error('Unsupported TypeNode');
|
11034
|
+
}
|
11035
|
+
}
|
11036
|
+
|
11037
|
+
function transform$4(variableDefinitions, transformState) {
|
11038
|
+
const { kind, variable: { kind: variableKind, name: { value: variableName }, }, type, defaultValue, } = variableDefinitions;
|
11039
|
+
const ret = {
|
11040
|
+
kind,
|
11041
|
+
variable: {
|
11042
|
+
kind: variableKind,
|
11043
|
+
name: variableName,
|
11044
|
+
},
|
11045
|
+
type: transform$5(type),
|
11046
|
+
};
|
11047
|
+
if (defaultValue !== undefined) {
|
11048
|
+
const value = transform$b(defaultValue, transformState);
|
11049
|
+
ret.defaultValue = value;
|
11050
|
+
}
|
11051
|
+
// TODO: transform directives
|
11052
|
+
return ret;
|
11053
|
+
}
|
11054
|
+
|
11055
|
+
function validateVariables(variableDefinitions, transformState) {
|
11056
|
+
if (process.env.NODE_ENV === 'production') {
|
11057
|
+
throw new ReferenceError("Do not call this function in production becuase we don't want to break existing uses. Other environments are okay because we want to catch errors early.");
|
11058
|
+
}
|
11059
|
+
const variablesDefined = {};
|
11060
|
+
if (variableDefinitions !== undefined) {
|
11061
|
+
for (let i = 0, len = variableDefinitions.length; i < len; i++) {
|
11062
|
+
const definedVariableName = variableDefinitions[i].variable.name.value;
|
11063
|
+
variablesDefined[definedVariableName] = true;
|
11064
|
+
if (transformState.variablesUsed[definedVariableName] === undefined) {
|
11065
|
+
throw new Error(`Variable $${definedVariableName} was defined but never used.`);
|
11066
|
+
}
|
11067
|
+
}
|
11068
|
+
}
|
11069
|
+
const usedVariableKeys = Object.keys(transformState.variablesUsed);
|
11070
|
+
for (let i = 0, len = usedVariableKeys.length; i < len; i++) {
|
11071
|
+
if (variablesDefined[usedVariableKeys[i]] !== true) {
|
11072
|
+
throw new Error(`Variable $${usedVariableKeys[i]} was used but never defined.`);
|
11073
|
+
}
|
11074
|
+
}
|
11075
|
+
}
|
11076
|
+
function transform$3(node) {
|
11077
|
+
const queryRoot = {
|
11078
|
+
kind: 'ObjectFieldSelection',
|
11079
|
+
name: 'query',
|
11080
|
+
luvioSelections: [],
|
11081
|
+
};
|
11082
|
+
const currentNodePath = [queryRoot];
|
11083
|
+
const transformState = {
|
11084
|
+
variablesUsed: {},
|
11085
|
+
};
|
11086
|
+
selectionSetVisitor(node, currentNodePath, transformState);
|
11087
|
+
const operationDefinition = {
|
11088
|
+
kind: 'OperationDefinition',
|
11089
|
+
operation: 'query',
|
11090
|
+
luvioSelections: queryRoot.luvioSelections,
|
11091
|
+
};
|
11092
|
+
if (node.name !== undefined) {
|
11093
|
+
operationDefinition.name = node.name.value;
|
11094
|
+
}
|
11095
|
+
const { variableDefinitions, directives } = node;
|
11096
|
+
if (variableDefinitions !== undefined && variableDefinitions.length > 0) {
|
11097
|
+
operationDefinition.variableDefinitions = variableDefinitions.map((variableDefinition) => transform$4(variableDefinition, transformState));
|
11098
|
+
}
|
11099
|
+
if (directives !== undefined && directives.length > 0) {
|
11100
|
+
operationDefinition.directives = directives.map((node) => transform$9(node, transformState));
|
11101
|
+
}
|
11102
|
+
if (process.env.NODE_ENV !== 'production') {
|
11103
|
+
validateVariables(variableDefinitions, transformState);
|
11104
|
+
}
|
11105
|
+
return operationDefinition;
|
11106
|
+
}
|
11107
|
+
|
11108
|
+
function transform$2(node) {
|
11109
|
+
const { operation } = node;
|
11110
|
+
if (operation === 'query') {
|
11111
|
+
return transform$3(node);
|
11112
|
+
}
|
11113
|
+
throw new Error(`Unsupported ${operation} operation. Only query operation is supported`);
|
11114
|
+
}
|
11115
|
+
|
11116
|
+
function transform$1(node) {
|
11117
|
+
const { kind: nodeKind, name: { value: nodeName }, typeCondition: { kind: typeKind, name: { value: typeName }, }, directives, } = node;
|
11118
|
+
// dummy root node
|
11119
|
+
const fragmentRoot = {
|
11120
|
+
kind: NODE_KIND_OBJECT_FIELD_SELECTION,
|
11121
|
+
name: 'fragment',
|
11122
|
+
luvioSelections: [],
|
11123
|
+
};
|
11124
|
+
const currentNodePath = [fragmentRoot];
|
11125
|
+
const transformState = { variablesUsed: {} };
|
11126
|
+
selectionSetVisitor(node, currentNodePath, transformState);
|
11127
|
+
const luvioNode = {
|
11128
|
+
kind: nodeKind,
|
11129
|
+
name: nodeName,
|
11130
|
+
typeCondition: {
|
11131
|
+
kind: typeKind,
|
11132
|
+
name: typeName,
|
11133
|
+
},
|
11134
|
+
luvioSelections: fragmentRoot.luvioSelections,
|
11135
|
+
};
|
11136
|
+
if (directives !== undefined && directives.length > 0) {
|
11137
|
+
luvioNode.directives = directives.map((node) => transform$9(node, transformState));
|
11138
|
+
}
|
11139
|
+
return luvioNode;
|
11140
|
+
}
|
11141
|
+
|
11142
|
+
function transform(root) {
|
11143
|
+
const { kind, definitions } = root;
|
11144
|
+
const luvioDefinitions = [];
|
11145
|
+
for (let i = 0; i < definitions.length; i++) {
|
11146
|
+
const definition = definitions[i];
|
11147
|
+
if (isOperationDefinitionNode(definition)) {
|
11148
|
+
luvioDefinitions.push(transform$2(definition));
|
11149
|
+
}
|
11150
|
+
else if (isFragmentDefinitionNode(definition)) {
|
11151
|
+
luvioDefinitions.push(transform$1(definition));
|
11152
|
+
}
|
11153
|
+
else {
|
11154
|
+
if (process.env.NODE_ENV !== 'production') {
|
11155
|
+
throw new Error(`Unsupported ${definition.kind} definition. Only OperationDefinition and FragmentDefinition are supported in a GraphQL Document`);
|
11156
|
+
}
|
11157
|
+
}
|
11158
|
+
}
|
11159
|
+
return {
|
11160
|
+
kind,
|
11161
|
+
definitions: luvioDefinitions,
|
11162
|
+
};
|
11163
|
+
}
|
11164
|
+
|
11165
|
+
/**
|
11166
|
+
* we should look into optimizing this before it turns into a memory hog
|
11167
|
+
* weakmaps, or limiting the size of the cache, or something
|
11168
|
+
*/
|
11169
|
+
const docMap = new Map();
|
11170
|
+
/**
|
11171
|
+
* Opaque reference map to return keys to userland
|
11172
|
+
* As a user shouldn't have access to the Document
|
11173
|
+
*/
|
11174
|
+
const referenceMap = new WeakMap();
|
11175
|
+
/**
|
11176
|
+
* Strips characters that are not significant to the validity or execution
|
11177
|
+
* of a GraphQL document:
|
11178
|
+
* - UnicodeBOM
|
11179
|
+
* - WhiteSpace
|
11180
|
+
* - LineTerminator
|
11181
|
+
* - Comment
|
11182
|
+
* - Comma
|
11183
|
+
* - BlockString indentation
|
11184
|
+
*/
|
11185
|
+
function operationKeyBuilder(inputString) {
|
11186
|
+
return stripIgnoredCharacters(inputString);
|
11187
|
+
}
|
11188
|
+
/**
|
11189
|
+
* Returns document node if cached or else update the cache and return the document node
|
11190
|
+
* @param inputString - operation string
|
11191
|
+
* @returns DocumentNode
|
11192
|
+
*/
|
11193
|
+
function parseDocument(inputString) {
|
11194
|
+
const operationKey = operationKeyBuilder(inputString);
|
11195
|
+
const cachedDoc = docMap.get(operationKey);
|
11196
|
+
if (cachedDoc !== undefined) {
|
11197
|
+
return cachedDoc;
|
11198
|
+
}
|
11199
|
+
// parse throws an GraphQLError in case of invalid query, should this be in try/catch?
|
11200
|
+
const parsedDoc = parse(inputString, { noLocation: true });
|
11201
|
+
if (!parsedDoc || parsedDoc.kind !== 'Document') {
|
11202
|
+
if (process.env.NODE_ENV !== 'production') {
|
11203
|
+
throw new Error('Invalid graphql doc');
|
11204
|
+
}
|
11205
|
+
return null;
|
11206
|
+
}
|
11207
|
+
docMap.set(operationKey, parsedDoc);
|
11208
|
+
return parsedDoc;
|
11209
|
+
}
|
11210
|
+
/**
|
11211
|
+
* If the input string has fragment substitution
|
11212
|
+
* Insert the fragments AST to the query document node
|
11213
|
+
*/
|
11214
|
+
function insertFragments(doc, fragments) {
|
11215
|
+
fragments.forEach((fragment) => {
|
11216
|
+
// @ts-ignore
|
11217
|
+
// graphql describes definitions as "readonly"
|
11218
|
+
// so we aren't supposed to mutate the document node
|
11219
|
+
// but instead of parsing the fragment again, we substitute it's definition in the document node
|
11220
|
+
doc.definitions.push(fragment);
|
11221
|
+
});
|
11222
|
+
return doc;
|
11223
|
+
}
|
11224
|
+
function updateReferenceMapWithKnownKey(doc, key) {
|
11225
|
+
referenceMap.set(key, doc);
|
11226
|
+
}
|
11227
|
+
function updateReferenceMapAndGetKey(doc) {
|
11228
|
+
// the key is a String object so that legacy locker does not replace its identity.
|
11229
|
+
const key = new String();
|
11230
|
+
updateReferenceMapWithKnownKey(doc, key);
|
11231
|
+
return key;
|
11232
|
+
}
|
11233
|
+
/**
|
11234
|
+
* Insert string and fragment substitutions with the actual nodes
|
11235
|
+
* @param inputString
|
11236
|
+
* @param substitutions - string | fragment DocumentNode
|
11237
|
+
* @returns { operation string, fragment docs [] }
|
11238
|
+
*/
|
11239
|
+
function processSubstitutions(inputString, substitutions) {
|
11240
|
+
let outputString = '';
|
11241
|
+
const fragments = [];
|
11242
|
+
const subLength = substitutions.length;
|
11243
|
+
for (let i = 0; i < subLength; i++) {
|
11244
|
+
const substitution = substitutions[i];
|
11245
|
+
outputString += inputString[i];
|
11246
|
+
if (typeof substitution === 'string' || typeof substitution === 'number') {
|
11247
|
+
outputString += substitution;
|
11248
|
+
}
|
11249
|
+
else if (typeof substitution === 'object') {
|
11250
|
+
const doc = referenceMap.get(substitution);
|
11251
|
+
if (doc === undefined) {
|
11252
|
+
if (process.env.NODE_ENV !== 'production') {
|
11253
|
+
throw new Error('Invalid substitution fragment');
|
11254
|
+
}
|
11255
|
+
return null;
|
11256
|
+
}
|
11257
|
+
for (const def of doc.definitions) {
|
11258
|
+
fragments.push(def);
|
11259
|
+
}
|
11260
|
+
}
|
11261
|
+
else {
|
11262
|
+
if (process.env.NODE_ENV !== 'production') {
|
11263
|
+
throw new Error('Unsupported substitution type');
|
11264
|
+
}
|
11265
|
+
return null;
|
11266
|
+
}
|
11267
|
+
}
|
11268
|
+
return {
|
11269
|
+
operationString: outputString + inputString[subLength],
|
11270
|
+
fragments,
|
11271
|
+
};
|
11272
|
+
}
|
11273
|
+
/**
|
11274
|
+
*
|
11275
|
+
* @param astReference - ast reference passed from user land
|
11276
|
+
*/
|
11277
|
+
const astResolver = function (astReference) {
|
11278
|
+
return referenceMap.get(astReference);
|
11279
|
+
};
|
11280
|
+
/**
|
11281
|
+
*
|
11282
|
+
* @param literals - operation query string
|
11283
|
+
* @param subs - all other substitutions
|
11284
|
+
* @returns an opaque reference to the parsed document
|
11285
|
+
*/
|
11286
|
+
function gql(literals, ...subs) {
|
11287
|
+
let inputString;
|
11288
|
+
let inputSubstitutionFragments;
|
11289
|
+
if (!literals) {
|
11290
|
+
if (process.env.NODE_ENV !== 'production') {
|
11291
|
+
throw new Error('Invalid query');
|
11292
|
+
}
|
11293
|
+
return null;
|
11294
|
+
}
|
11295
|
+
else if (typeof literals === 'string') {
|
11296
|
+
inputString = literals.trim();
|
11297
|
+
inputSubstitutionFragments = [];
|
11298
|
+
}
|
11299
|
+
else {
|
11300
|
+
// called as template literal
|
11301
|
+
const sub = processSubstitutions(literals, subs);
|
11302
|
+
// if invalid fragment references found
|
11303
|
+
if (sub === null) {
|
11304
|
+
return null;
|
11305
|
+
}
|
11306
|
+
const { operationString, fragments } = sub;
|
11307
|
+
inputString = operationString.trim();
|
11308
|
+
inputSubstitutionFragments = fragments;
|
11309
|
+
}
|
11310
|
+
if (inputString.length === 0) {
|
11311
|
+
if (process.env.NODE_ENV !== 'production') {
|
11312
|
+
throw new Error('Invalid query');
|
11313
|
+
}
|
11314
|
+
return null;
|
11315
|
+
}
|
11316
|
+
const document = parseDocument(inputString);
|
11317
|
+
if (document === null) {
|
11318
|
+
return null;
|
11319
|
+
}
|
11320
|
+
if (inputSubstitutionFragments.length === 0) {
|
11321
|
+
return updateReferenceMapAndGetKey(document);
|
11322
|
+
}
|
11323
|
+
return updateReferenceMapAndGetKey(insertFragments(document, inputSubstitutionFragments));
|
11324
|
+
}
|
11325
|
+
|
11326
|
+
const DIRECTIVE_RECORD_QUERY_CATEGORY = {
|
11327
|
+
kind: 'Directive',
|
11328
|
+
name: {
|
11329
|
+
kind: 'Name',
|
11330
|
+
value: 'category',
|
11331
|
+
},
|
11332
|
+
arguments: [
|
11333
|
+
{
|
11334
|
+
kind: 'Argument',
|
11335
|
+
name: {
|
11336
|
+
kind: 'Name',
|
11337
|
+
value: 'name',
|
11338
|
+
},
|
11339
|
+
value: {
|
11340
|
+
kind: 'StringValue',
|
11341
|
+
value: 'recordQuery',
|
11342
|
+
block: false,
|
11343
|
+
},
|
11344
|
+
},
|
11345
|
+
],
|
11346
|
+
};
|
11347
|
+
const DIRECTIVE_CHILD_RELATIONSHIP_CATEGORY = {
|
11348
|
+
kind: 'Directive',
|
11349
|
+
name: {
|
11350
|
+
kind: 'Name',
|
11351
|
+
value: 'category',
|
11352
|
+
},
|
11353
|
+
arguments: [
|
11354
|
+
{
|
11355
|
+
kind: 'Argument',
|
11356
|
+
name: {
|
11357
|
+
kind: 'Name',
|
11358
|
+
value: 'name',
|
11359
|
+
},
|
11360
|
+
value: {
|
11361
|
+
kind: 'StringValue',
|
11362
|
+
value: 'childRelationship',
|
11363
|
+
block: false,
|
11364
|
+
},
|
11365
|
+
},
|
11366
|
+
],
|
11367
|
+
};
|
11368
|
+
const DIRECTIVE_PARENT_CATEGORY = {
|
11369
|
+
kind: 'Directive',
|
11370
|
+
name: {
|
11371
|
+
kind: 'Name',
|
11372
|
+
value: 'category',
|
11373
|
+
},
|
11374
|
+
arguments: [
|
11375
|
+
{
|
11376
|
+
kind: 'Argument',
|
11377
|
+
name: {
|
11378
|
+
kind: 'Name',
|
11379
|
+
value: 'name',
|
11380
|
+
},
|
11381
|
+
value: {
|
11382
|
+
kind: 'StringValue',
|
11383
|
+
value: 'parentRelationship',
|
11384
|
+
block: false,
|
11385
|
+
},
|
11386
|
+
},
|
11387
|
+
],
|
11388
|
+
};
|
11389
|
+
function substituteDirectives(directives, index, selection, parentNode) {
|
11390
|
+
if (directives[index].name.value === CUSTOM_DIRECTIVE_CONNECTION) {
|
11391
|
+
if (parentNode !== undefined &&
|
11392
|
+
parentNode.kind === 'Field' &&
|
11393
|
+
parentNode.name.value === 'uiapi') {
|
11394
|
+
// @ts-ignore - Document is read only
|
11395
|
+
directives[index] = DIRECTIVE_RECORD_QUERY_CATEGORY;
|
11396
|
+
}
|
11397
|
+
else {
|
11398
|
+
// @ts-ignore - Document is read only
|
11399
|
+
directives[index] = DIRECTIVE_CHILD_RELATIONSHIP_CATEGORY;
|
11400
|
+
}
|
11401
|
+
}
|
11402
|
+
else if (directives[index].name.value === CUSTOM_DIRECTIVE_RESOURCE) {
|
11403
|
+
// node gets its type from @category recordQuery or @category childRelationship
|
11404
|
+
if (selection.kind === 'Field' && selection.name.value === 'node') {
|
11405
|
+
// @ts-ignore - Document is read only
|
11406
|
+
directives.splice(index, 1);
|
11407
|
+
}
|
11408
|
+
else {
|
11409
|
+
// @ts-ignore - Document is read only
|
11410
|
+
directives[index] = DIRECTIVE_PARENT_CATEGORY;
|
11411
|
+
}
|
11412
|
+
}
|
11413
|
+
}
|
11414
|
+
/**
|
11415
|
+
* Returns true if the directive node is of legacy type
|
11416
|
+
* @param node : Directive node
|
11417
|
+
* @returns
|
11418
|
+
*/
|
11419
|
+
function isCustomDirective(node) {
|
11420
|
+
return (node.name.value === CUSTOM_DIRECTIVE_CONNECTION ||
|
11421
|
+
node.name.value === CUSTOM_DIRECTIVE_RESOURCE);
|
11422
|
+
}
|
11423
|
+
/**
|
11424
|
+
* Traverses a selection and it's nested selections,
|
11425
|
+
* to find any legacy custom directives and substitute them with metaschema directives
|
11426
|
+
* @param node - SelectionNode
|
11427
|
+
* @returns void
|
11428
|
+
*/
|
11429
|
+
function traverseSelection(node, parentNode) {
|
11430
|
+
if (node === undefined || node.kind === 'FragmentSpread' || node.selectionSet === undefined) {
|
11431
|
+
return;
|
11432
|
+
}
|
11433
|
+
const { selectionSet } = node;
|
11434
|
+
for (const selection of selectionSet.selections) {
|
11435
|
+
replaceCustomDirectives(selection, parentNode);
|
11436
|
+
traverseSelection(selection, node);
|
11437
|
+
}
|
11438
|
+
}
|
11439
|
+
function replaceCustomDirectives(selection, parentNode) {
|
11440
|
+
const { directives } = selection;
|
11441
|
+
if (directives !== undefined && directives.length > 0) {
|
11442
|
+
// we follow this pattern instead of map to preserve the order of directives
|
11443
|
+
// order of directives may be significant as per graphql spec
|
11444
|
+
const index = directives.findIndex(isCustomDirective);
|
11445
|
+
if (index !== -1) {
|
11446
|
+
substituteDirectives(directives, index, selection, parentNode);
|
11447
|
+
}
|
11448
|
+
}
|
11449
|
+
}
|
11450
|
+
/**
|
11451
|
+
* Accepts a document node and replaces the legacy custom directives with metaschema directives "in-place"
|
11452
|
+
* @param doc
|
11453
|
+
*/
|
11454
|
+
function metaschemaMapper(doc) {
|
11455
|
+
// this method is only callable for Executable definitions
|
11456
|
+
// such as Operations and Fragments
|
11457
|
+
// so we have to explicitly cast the definitions for ts
|
11458
|
+
const { definitions } = doc;
|
11459
|
+
for (const def of definitions) {
|
11460
|
+
const { selectionSet } = def;
|
11461
|
+
// This is just iterating through the top level 'Query' operations. There should never be any custom
|
11462
|
+
// directives at this level, as RecordQuery is actually a field lower in the schema. So we can skip looking for them.
|
11463
|
+
selectionSet.selections.forEach((selection) => {
|
11464
|
+
traverseSelection(selection);
|
11465
|
+
});
|
11466
|
+
}
|
11467
|
+
}
|
11468
|
+
|
11469
|
+
/**
|
11470
|
+
* @deprecated In favor of gql tagged template literal
|
11471
|
+
*/
|
11472
|
+
function parseAndVisit(source) {
|
11473
|
+
const ast = parse(source, { noLocation: true });
|
11474
|
+
const luvioDocumentNode = transform(ast);
|
11475
|
+
// In-place substitution of metaschema annotations
|
11476
|
+
metaschemaMapper(ast);
|
11477
|
+
// Set the AST reference map with LuvioDocumentNode as the key
|
11478
|
+
// ASTResolver will resolve it to metaschema mapped AST
|
11479
|
+
updateReferenceMapWithKnownKey(ast, luvioDocumentNode);
|
11480
|
+
return luvioDocumentNode;
|
11481
11481
|
}
|
11482
11482
|
|
11483
11483
|
export { Kind, astResolver, buildSchema, defaultFieldResolver, execute, gql, isObjectType, parse, parseAndVisit, print, visit };
|
11484
|
-
// version: 1.128.
|
11484
|
+
// version: 1.128.1-55cd38df6
|