@graphql-tools/batch-execute 9.0.6 → 9.0.7-alpha-63d80f9d08b5d8448f4bfb8b04aeff28b977dec8

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.
@@ -1,260 +0,0 @@
1
- // adapted from https://github.com/gatsbyjs/gatsby/blob/master/packages/gatsby-source-graphql/src/batching/merge-queries.js
2
- import { Kind, visit, } from 'graphql';
3
- import { getOperationASTFromRequest } from '@graphql-tools/utils';
4
- import { createPrefix } from './prefix.js';
5
- /**
6
- * Merge multiple queries into a single query in such a way that query results
7
- * can be split and transformed as if they were obtained by running original queries.
8
- *
9
- * Merging algorithm involves several transformations:
10
- * 1. Replace top-level fragment spreads with inline fragments (... on Query {})
11
- * 2. Add unique aliases to all top-level query fields (including those on inline fragments)
12
- * 3. Prefix all variable definitions and variable usages
13
- * 4. Prefix names (and spreads) of fragments
14
- *
15
- * i.e transform:
16
- * [
17
- * `query Foo($id: ID!) { foo, bar(id: $id), ...FooQuery }
18
- * fragment FooQuery on Query { baz }`,
19
- *
20
- * `query Bar($id: ID!) { foo: baz, bar(id: $id), ... on Query { baz } }`
21
- * ]
22
- * to:
23
- * query (
24
- * $graphqlTools1_id: ID!
25
- * $graphqlTools2_id: ID!
26
- * ) {
27
- * graphqlTools1_foo: foo,
28
- * graphqlTools1_bar: bar(id: $graphqlTools1_id)
29
- * ... on Query {
30
- * graphqlTools1__baz: baz
31
- * }
32
- * graphqlTools1__foo: baz
33
- * graphqlTools1__bar: bar(id: $graphqlTools1__id)
34
- * ... on Query {
35
- * graphqlTools1__baz: baz
36
- * }
37
- * }
38
- */
39
- export function mergeRequests(requests, extensionsReducer) {
40
- const mergedVariables = Object.create(null);
41
- const mergedVariableDefinitions = [];
42
- const mergedSelections = [];
43
- const mergedFragmentDefinitions = [];
44
- let mergedExtensions = Object.create(null);
45
- for (let index = 0; index < requests.length; index++) {
46
- const request = requests[index];
47
- const prefixedRequests = prefixRequest(createPrefix(index), request);
48
- for (const def of prefixedRequests.document.definitions) {
49
- if (isOperationDefinition(def)) {
50
- mergedSelections.push(...def.selectionSet.selections);
51
- if (def.variableDefinitions) {
52
- mergedVariableDefinitions.push(...def.variableDefinitions);
53
- }
54
- }
55
- if (isFragmentDefinition(def)) {
56
- mergedFragmentDefinitions.push(def);
57
- }
58
- }
59
- Object.assign(mergedVariables, prefixedRequests.variables);
60
- mergedExtensions = extensionsReducer(mergedExtensions, request);
61
- }
62
- const firstRequest = requests[0];
63
- const operationType = firstRequest.operationType ?? getOperationASTFromRequest(firstRequest).operation;
64
- const mergedOperationDefinition = {
65
- kind: Kind.OPERATION_DEFINITION,
66
- operation: operationType,
67
- variableDefinitions: mergedVariableDefinitions,
68
- selectionSet: {
69
- kind: Kind.SELECTION_SET,
70
- selections: mergedSelections,
71
- },
72
- };
73
- const operationName = firstRequest.operationName ?? firstRequest.info?.operation?.name?.value;
74
- if (operationName) {
75
- mergedOperationDefinition.name = {
76
- kind: Kind.NAME,
77
- value: operationName,
78
- };
79
- }
80
- return {
81
- document: {
82
- kind: Kind.DOCUMENT,
83
- definitions: [mergedOperationDefinition, ...mergedFragmentDefinitions],
84
- },
85
- variables: mergedVariables,
86
- extensions: mergedExtensions,
87
- context: requests[0].context,
88
- info: requests[0].info,
89
- operationType,
90
- rootValue: requests[0].rootValue,
91
- };
92
- }
93
- function prefixRequest(prefix, request) {
94
- const executionVariables = request.variables ?? {};
95
- function prefixNode(node) {
96
- return prefixNodeName(node, prefix);
97
- }
98
- let prefixedDocument = aliasTopLevelFields(prefix, request.document);
99
- const executionVariableNames = Object.keys(executionVariables);
100
- const hasFragmentDefinitions = request.document.definitions.some(def => isFragmentDefinition(def));
101
- const fragmentSpreadImpl = {};
102
- if (executionVariableNames.length > 0 || hasFragmentDefinitions) {
103
- prefixedDocument = visit(prefixedDocument, {
104
- [Kind.VARIABLE]: prefixNode,
105
- [Kind.FRAGMENT_DEFINITION]: prefixNode,
106
- [Kind.FRAGMENT_SPREAD]: node => {
107
- node = prefixNodeName(node, prefix);
108
- fragmentSpreadImpl[node.name.value] = true;
109
- return node;
110
- },
111
- });
112
- }
113
- const prefixedVariables = {};
114
- for (const variableName of executionVariableNames) {
115
- prefixedVariables[prefix + variableName] = executionVariables[variableName];
116
- }
117
- if (hasFragmentDefinitions) {
118
- prefixedDocument = {
119
- ...prefixedDocument,
120
- definitions: prefixedDocument.definitions.filter(def => {
121
- return !isFragmentDefinition(def) || fragmentSpreadImpl[def.name.value];
122
- }),
123
- };
124
- }
125
- return {
126
- document: prefixedDocument,
127
- variables: prefixedVariables,
128
- };
129
- }
130
- /**
131
- * Adds prefixed aliases to top-level fields of the query.
132
- *
133
- * @see aliasFieldsInSelection for implementation details
134
- */
135
- function aliasTopLevelFields(prefix, document) {
136
- const transformer = {
137
- [Kind.OPERATION_DEFINITION]: (def) => {
138
- const { selections } = def.selectionSet;
139
- return {
140
- ...def,
141
- selectionSet: {
142
- ...def.selectionSet,
143
- selections: aliasFieldsInSelection(prefix, selections, document),
144
- },
145
- };
146
- },
147
- };
148
- return visit(document, transformer, {
149
- [Kind.DOCUMENT]: [`definitions`],
150
- });
151
- }
152
- /**
153
- * Add aliases to fields of the selection, including top-level fields of inline fragments.
154
- * Fragment spreads are converted to inline fragments and their top-level fields are also aliased.
155
- *
156
- * Note that this method is shallow. It adds aliases only to the top-level fields and doesn't
157
- * descend to field sub-selections.
158
- *
159
- * For example, transforms:
160
- * {
161
- * foo
162
- * ... on Query { foo }
163
- * ...FragmentWithBarField
164
- * }
165
- * To:
166
- * {
167
- * graphqlTools1_foo: foo
168
- * ... on Query { graphqlTools1_foo: foo }
169
- * ... on Query { graphqlTools1_bar: bar }
170
- * }
171
- */
172
- function aliasFieldsInSelection(prefix, selections, document) {
173
- return selections.map(selection => {
174
- switch (selection.kind) {
175
- case Kind.INLINE_FRAGMENT:
176
- return aliasFieldsInInlineFragment(prefix, selection, document);
177
- case Kind.FRAGMENT_SPREAD: {
178
- const inlineFragment = inlineFragmentSpread(selection, document);
179
- return aliasFieldsInInlineFragment(prefix, inlineFragment, document);
180
- }
181
- case Kind.FIELD:
182
- default:
183
- return aliasField(selection, prefix);
184
- }
185
- });
186
- }
187
- /**
188
- * Add aliases to top-level fields of the inline fragment.
189
- * Returns new inline fragment node.
190
- *
191
- * For Example, transforms:
192
- * ... on Query { foo, ... on Query { bar: foo } }
193
- * To
194
- * ... on Query { graphqlTools1_foo: foo, ... on Query { graphqlTools1_bar: foo } }
195
- */
196
- function aliasFieldsInInlineFragment(prefix, fragment, document) {
197
- const { selections } = fragment.selectionSet;
198
- return {
199
- ...fragment,
200
- selectionSet: {
201
- ...fragment.selectionSet,
202
- selections: aliasFieldsInSelection(prefix, selections, document),
203
- },
204
- };
205
- }
206
- /**
207
- * Replaces fragment spread with inline fragment
208
- *
209
- * Example:
210
- * query { ...Spread }
211
- * fragment Spread on Query { bar }
212
- *
213
- * Transforms to:
214
- * query { ... on Query { bar } }
215
- */
216
- function inlineFragmentSpread(spread, document) {
217
- const fragment = document.definitions.find(def => isFragmentDefinition(def) && def.name.value === spread.name.value);
218
- if (!fragment) {
219
- throw new Error(`Fragment ${spread.name.value} does not exist`);
220
- }
221
- const { typeCondition, selectionSet } = fragment;
222
- return {
223
- kind: Kind.INLINE_FRAGMENT,
224
- typeCondition,
225
- selectionSet,
226
- directives: spread.directives,
227
- };
228
- }
229
- function prefixNodeName(namedNode, prefix) {
230
- return {
231
- ...namedNode,
232
- name: {
233
- ...namedNode.name,
234
- value: prefix + namedNode.name.value,
235
- },
236
- };
237
- }
238
- /**
239
- * Returns a new FieldNode with prefixed alias
240
- *
241
- * Example. Given prefix === "graphqlTools1_" transforms:
242
- * { foo } -> { graphqlTools1_foo: foo }
243
- * { foo: bar } -> { graphqlTools1_foo: bar }
244
- */
245
- function aliasField(field, aliasPrefix) {
246
- const aliasNode = field.alias ? field.alias : field.name;
247
- return {
248
- ...field,
249
- alias: {
250
- ...aliasNode,
251
- value: aliasPrefix + aliasNode.value,
252
- },
253
- };
254
- }
255
- function isOperationDefinition(def) {
256
- return def.kind === Kind.OPERATION_DEFINITION;
257
- }
258
- function isFragmentDefinition(def) {
259
- return def.kind === Kind.FRAGMENT_DEFINITION;
260
- }
package/esm/prefix.js DELETED
@@ -1,36 +0,0 @@
1
- // adapted from https://github.com/gatsbyjs/gatsby/blob/master/packages/gatsby-source-graphql/src/batching/merge-queries.js
2
- export function createPrefix(index) {
3
- return `_${index}_`;
4
- }
5
- function matchKey(prefixedKey) {
6
- const match = /^_(\d+)_(.*)$/.exec(prefixedKey);
7
- if (match && match.length === 3 && !isNaN(Number(match[1])) && match[2]) {
8
- return { index: Number(match[1]), originalKey: match[2] };
9
- }
10
- return null;
11
- }
12
- export function parseKey(prefixedKey) {
13
- const match = matchKey(prefixedKey);
14
- if (!match) {
15
- throw new Error(`Key ${prefixedKey} is not correctly prefixed`);
16
- }
17
- return match;
18
- }
19
- export function parseKeyFromPath(path) {
20
- let keyOffset = 0;
21
- let match = null;
22
- // Keep looping over path until we've found a match or path has no more items left
23
- for (; !match && keyOffset < path.length; keyOffset++) {
24
- const pathKey = path[keyOffset];
25
- if (typeof pathKey === 'string') {
26
- match = matchKey(pathKey);
27
- }
28
- }
29
- if (!match) {
30
- throw new Error(`Path ${path.join('.')} does not contain correctly prefixed key`);
31
- }
32
- return {
33
- ...match,
34
- keyOffset,
35
- };
36
- }
@@ -1,45 +0,0 @@
1
- // adapted from https://github.com/gatsbyjs/gatsby/blob/master/packages/gatsby-source-graphql/src/batching/merge-queries.js
2
- import { relocatedError } from '@graphql-tools/utils';
3
- import { parseKey, parseKeyFromPath } from './prefix.js';
4
- /**
5
- * Split and transform result of the query produced by the `merge` function
6
- */
7
- export function splitResult({ data, errors }, numResults) {
8
- const splitResults = [];
9
- for (let i = 0; i < numResults; i++) {
10
- splitResults.push({});
11
- }
12
- if (data) {
13
- for (const prefixedKey in data) {
14
- const { index, originalKey } = parseKey(prefixedKey);
15
- const result = splitResults[index];
16
- if (result == null) {
17
- continue;
18
- }
19
- if (result.data == null) {
20
- result.data = { [originalKey]: data[prefixedKey] };
21
- }
22
- else {
23
- result.data[originalKey] = data[prefixedKey];
24
- }
25
- }
26
- }
27
- if (errors) {
28
- for (const error of errors) {
29
- if (error.path) {
30
- const { index, originalKey, keyOffset } = parseKeyFromPath(error.path);
31
- const newError = relocatedError(error, [originalKey, ...error.path.slice(keyOffset)]);
32
- const resultErrors = (splitResults[index].errors = (splitResults[index].errors ||
33
- []));
34
- resultErrors.push(newError);
35
- }
36
- else {
37
- splitResults.forEach(result => {
38
- const resultErrors = (result.errors = (result.errors || []));
39
- resultErrors.push(error);
40
- });
41
- }
42
- }
43
- }
44
- return splitResults;
45
- }
@@ -1,3 +0,0 @@
1
- import DataLoader from 'dataloader';
2
- import { ExecutionRequest, Executor } from '@graphql-tools/utils';
3
- export declare function createBatchingExecutor(executor: Executor, dataLoaderOptions?: DataLoader.Options<any, any, any>, extensionsReducer?: (mergedExtensions: Record<string, any>, request: ExecutionRequest) => Record<string, any>): Executor;
@@ -1,3 +0,0 @@
1
- import DataLoader from 'dataloader';
2
- import { ExecutionRequest, Executor } from '@graphql-tools/utils';
3
- export declare function createBatchingExecutor(executor: Executor, dataLoaderOptions?: DataLoader.Options<any, any, any>, extensionsReducer?: (mergedExtensions: Record<string, any>, request: ExecutionRequest) => Record<string, any>): Executor;
@@ -1,3 +0,0 @@
1
- import DataLoader from 'dataloader';
2
- import { ExecutionRequest, Executor } from '@graphql-tools/utils';
3
- export declare const getBatchingExecutor: (_context: Record<string, any>, executor: Executor, dataLoaderOptions?: DataLoader.Options<any, any, any> | undefined, extensionsReducer?: undefined | ((mergedExtensions: Record<string, any>, request: ExecutionRequest) => Record<string, any>)) => Executor;
@@ -1,3 +0,0 @@
1
- import DataLoader from 'dataloader';
2
- import { ExecutionRequest, Executor } from '@graphql-tools/utils';
3
- export declare const getBatchingExecutor: (_context: Record<string, any>, executor: Executor, dataLoaderOptions?: DataLoader.Options<any, any, any> | undefined, extensionsReducer?: undefined | ((mergedExtensions: Record<string, any>, request: ExecutionRequest) => Record<string, any>)) => Executor;
@@ -1,2 +0,0 @@
1
- export * from './createBatchingExecutor.cjs';
2
- export * from './getBatchingExecutor.cjs';
@@ -1,2 +0,0 @@
1
- export * from './createBatchingExecutor.js';
2
- export * from './getBatchingExecutor.js';
@@ -1,36 +0,0 @@
1
- import { ExecutionRequest } from '@graphql-tools/utils';
2
- /**
3
- * Merge multiple queries into a single query in such a way that query results
4
- * can be split and transformed as if they were obtained by running original queries.
5
- *
6
- * Merging algorithm involves several transformations:
7
- * 1. Replace top-level fragment spreads with inline fragments (... on Query {})
8
- * 2. Add unique aliases to all top-level query fields (including those on inline fragments)
9
- * 3. Prefix all variable definitions and variable usages
10
- * 4. Prefix names (and spreads) of fragments
11
- *
12
- * i.e transform:
13
- * [
14
- * `query Foo($id: ID!) { foo, bar(id: $id), ...FooQuery }
15
- * fragment FooQuery on Query { baz }`,
16
- *
17
- * `query Bar($id: ID!) { foo: baz, bar(id: $id), ... on Query { baz } }`
18
- * ]
19
- * to:
20
- * query (
21
- * $graphqlTools1_id: ID!
22
- * $graphqlTools2_id: ID!
23
- * ) {
24
- * graphqlTools1_foo: foo,
25
- * graphqlTools1_bar: bar(id: $graphqlTools1_id)
26
- * ... on Query {
27
- * graphqlTools1__baz: baz
28
- * }
29
- * graphqlTools1__foo: baz
30
- * graphqlTools1__bar: bar(id: $graphqlTools1__id)
31
- * ... on Query {
32
- * graphqlTools1__baz: baz
33
- * }
34
- * }
35
- */
36
- export declare function mergeRequests(requests: ReadonlyArray<ExecutionRequest>, extensionsReducer: (mergedExtensions: Record<string, any>, request: ExecutionRequest) => Record<string, any>): ExecutionRequest;
@@ -1,36 +0,0 @@
1
- import { ExecutionRequest } from '@graphql-tools/utils';
2
- /**
3
- * Merge multiple queries into a single query in such a way that query results
4
- * can be split and transformed as if they were obtained by running original queries.
5
- *
6
- * Merging algorithm involves several transformations:
7
- * 1. Replace top-level fragment spreads with inline fragments (... on Query {})
8
- * 2. Add unique aliases to all top-level query fields (including those on inline fragments)
9
- * 3. Prefix all variable definitions and variable usages
10
- * 4. Prefix names (and spreads) of fragments
11
- *
12
- * i.e transform:
13
- * [
14
- * `query Foo($id: ID!) { foo, bar(id: $id), ...FooQuery }
15
- * fragment FooQuery on Query { baz }`,
16
- *
17
- * `query Bar($id: ID!) { foo: baz, bar(id: $id), ... on Query { baz } }`
18
- * ]
19
- * to:
20
- * query (
21
- * $graphqlTools1_id: ID!
22
- * $graphqlTools2_id: ID!
23
- * ) {
24
- * graphqlTools1_foo: foo,
25
- * graphqlTools1_bar: bar(id: $graphqlTools1_id)
26
- * ... on Query {
27
- * graphqlTools1__baz: baz
28
- * }
29
- * graphqlTools1__foo: baz
30
- * graphqlTools1__bar: bar(id: $graphqlTools1__id)
31
- * ... on Query {
32
- * graphqlTools1__baz: baz
33
- * }
34
- * }
35
- */
36
- export declare function mergeRequests(requests: ReadonlyArray<ExecutionRequest>, extensionsReducer: (mergedExtensions: Record<string, any>, request: ExecutionRequest) => Record<string, any>): ExecutionRequest;
@@ -1,9 +0,0 @@
1
- export declare function createPrefix(index: number): string;
2
- export type KeyMatch = {
3
- index: number;
4
- originalKey: string;
5
- };
6
- export declare function parseKey(prefixedKey: string): KeyMatch;
7
- export declare function parseKeyFromPath(path: readonly (string | number)[]): KeyMatch & {
8
- keyOffset: number;
9
- };
@@ -1,9 +0,0 @@
1
- export declare function createPrefix(index: number): string;
2
- export type KeyMatch = {
3
- index: number;
4
- originalKey: string;
5
- };
6
- export declare function parseKey(prefixedKey: string): KeyMatch;
7
- export declare function parseKeyFromPath(path: readonly (string | number)[]): KeyMatch & {
8
- keyOffset: number;
9
- };
@@ -1,5 +0,0 @@
1
- import { ExecutionResult } from '@graphql-tools/utils';
2
- /**
3
- * Split and transform result of the query produced by the `merge` function
4
- */
5
- export declare function splitResult({ data, errors }: ExecutionResult, numResults: number): Array<ExecutionResult>;
@@ -1,5 +0,0 @@
1
- import { ExecutionResult } from '@graphql-tools/utils';
2
- /**
3
- * Split and transform result of the query produced by the `merge` function
4
- */
5
- export declare function splitResult({ data, errors }: ExecutionResult, numResults: number): Array<ExecutionResult>;