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