@graphql-mesh/runtime 1.0.0-alpha-20220804093904-8e2e41f7f → 1.0.0-alpha-20230420181317-a95037648

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.
@@ -0,0 +1,273 @@
1
+ import { getOperationAST, specifiedRules, validate, } from 'graphql';
2
+ import { envelop, useEngine, useExtendContext } from '@envelop/core';
3
+ import { OneOfInputObjectsRule, useExtendedValidation } from '@envelop/extended-validation';
4
+ import { process } from '@graphql-mesh/cross-helpers';
5
+ import { applySchemaTransforms, DefaultLogger, getHeadersObj, groupTransforms, parseWithCache, PubSub, } from '@graphql-mesh/utils';
6
+ import { Subschema } from '@graphql-tools/delegate';
7
+ import { AggregateError, getRootTypeMap, inspect, isAsyncIterable, mapAsyncIterator, memoize1, } from '@graphql-tools/utils';
8
+ import { fetch as defaultFetchFn } from '@whatwg-node/fetch';
9
+ import { MESH_CONTEXT_SYMBOL } from './constants.js';
10
+ import { getInContextSDK } from './in-context-sdk.js';
11
+ import { useSubschema } from './useSubschema.js';
12
+ const memoizedGetEnvelopedFactory = memoize1(function getEnvelopedFactory(plugins) {
13
+ return envelop({
14
+ plugins,
15
+ });
16
+ });
17
+ const memoizedGetOperationType = memoize1((document) => {
18
+ const operationAST = getOperationAST(document, undefined);
19
+ if (!operationAST) {
20
+ throw new Error('Must provide document with a valid operation');
21
+ }
22
+ return operationAST.operation;
23
+ });
24
+ export function wrapFetchWithPlugins(plugins) {
25
+ return async function wrappedFetchFn(url, options, context, info) {
26
+ if (url != null && typeof url !== 'string') {
27
+ throw new TypeError(`First parameter(url) of 'fetch' must be a string, got ${inspect(url)}`);
28
+ }
29
+ if (options != null && typeof options !== 'object') {
30
+ throw new TypeError(`Second parameter(options) of 'fetch' must be an object, got ${inspect(options)}`);
31
+ }
32
+ if (context != null && typeof context !== 'object') {
33
+ throw new TypeError(`Third parameter(context) of 'fetch' must be an object, got ${inspect(context)}`);
34
+ }
35
+ if (info != null && typeof info !== 'object') {
36
+ throw new TypeError(`Fourth parameter(info) of 'fetch' must be an object, got ${inspect(info)}`);
37
+ }
38
+ let fetchFn;
39
+ const doneHooks = [];
40
+ for (const plugin of plugins) {
41
+ if ((plugin === null || plugin === void 0 ? void 0 : plugin.onFetch) != null) {
42
+ const doneHook = await plugin.onFetch({
43
+ fetchFn,
44
+ setFetchFn(newFetchFn) {
45
+ fetchFn = newFetchFn;
46
+ },
47
+ url,
48
+ options,
49
+ context,
50
+ info,
51
+ });
52
+ if (doneHook) {
53
+ doneHooks.push(doneHook);
54
+ }
55
+ }
56
+ }
57
+ let response = await fetchFn(url, options, context, info);
58
+ for (const doneHook of doneHooks) {
59
+ await doneHook({
60
+ response,
61
+ setResponse(newResponse) {
62
+ response = newResponse;
63
+ },
64
+ });
65
+ }
66
+ return response;
67
+ };
68
+ }
69
+ // Use in-context-sdk for tracing
70
+ function createProxyingResolverFactory(apiName, rootTypeMap) {
71
+ return function createProxyingResolver({ operation }) {
72
+ const rootType = rootTypeMap.get(operation);
73
+ return function proxyingResolver(root, args, context, info) {
74
+ var _a, _b;
75
+ if (!((_b = (_a = context === null || context === void 0 ? void 0 : context[apiName]) === null || _a === void 0 ? void 0 : _a[rootType.name]) === null || _b === void 0 ? void 0 : _b[info.fieldName])) {
76
+ throw new Error(`${info.fieldName} couldn't find in ${rootType.name} of ${apiName} as a ${operation}`);
77
+ }
78
+ return context[apiName][rootType.name][info.fieldName]({ root, args, context, info });
79
+ };
80
+ };
81
+ }
82
+ export async function getMesh(options) {
83
+ const rawSources = [];
84
+ const { pubsub = new PubSub(), cache, logger = new DefaultLogger('🕸️ Mesh'), additionalEnvelopPlugins = [], sources, merger, additionalResolvers = [], additionalTypeDefs = [], transforms = [], fetchFn = defaultFetchFn, } = options;
85
+ const getMeshLogger = logger.child('GetMesh');
86
+ getMeshLogger.debug(`Getting subschemas from source handlers`);
87
+ let failed = false;
88
+ const initialPluginList = [
89
+ // TODO: Not a good practise to expect users to be a Yoga user
90
+ useExtendContext(({ request, req }) => {
91
+ // Maybe Node-like environment
92
+ if (req === null || req === void 0 ? void 0 : req.headers) {
93
+ return {
94
+ headers: getHeadersObj(req.headers),
95
+ };
96
+ }
97
+ // Fetch environment
98
+ if (request === null || request === void 0 ? void 0 : request.headers) {
99
+ return {
100
+ headers: getHeadersObj(request.headers),
101
+ };
102
+ }
103
+ return {};
104
+ }),
105
+ useExtendContext(() => ({
106
+ pubsub,
107
+ cache,
108
+ logger,
109
+ [MESH_CONTEXT_SYMBOL]: true,
110
+ })),
111
+ {
112
+ onFetch({ setFetchFn }) {
113
+ setFetchFn(fetchFn);
114
+ },
115
+ },
116
+ {
117
+ onParse({ setParseFn }) {
118
+ setParseFn(parseWithCache);
119
+ },
120
+ },
121
+ ...additionalEnvelopPlugins,
122
+ ];
123
+ const wrappedFetchFn = wrapFetchWithPlugins(initialPluginList);
124
+ await Promise.allSettled(sources.map(async (apiSource) => {
125
+ const apiName = apiSource.name;
126
+ const sourceLogger = logger.child(apiName);
127
+ sourceLogger.debug(`Generating the schema`);
128
+ try {
129
+ const source = await apiSource.handler.getMeshSource({
130
+ fetchFn: wrappedFetchFn,
131
+ });
132
+ sourceLogger.debug(`The schema has been generated successfully`);
133
+ let apiSchema = source.schema;
134
+ sourceLogger.debug(`Analyzing transforms`);
135
+ let transforms;
136
+ const { wrapTransforms, noWrapTransforms } = groupTransforms(apiSource.transforms);
137
+ if (!(wrapTransforms === null || wrapTransforms === void 0 ? void 0 : wrapTransforms.length) && (noWrapTransforms === null || noWrapTransforms === void 0 ? void 0 : noWrapTransforms.length)) {
138
+ sourceLogger.debug(`${noWrapTransforms.length} bare transforms found and applying`);
139
+ apiSchema = applySchemaTransforms(apiSchema, source, null, noWrapTransforms);
140
+ }
141
+ else {
142
+ transforms = apiSource.transforms;
143
+ }
144
+ const rootTypeMap = getRootTypeMap(apiSchema);
145
+ rawSources.push({
146
+ name: apiName,
147
+ schema: apiSchema,
148
+ executor: source.executor,
149
+ transforms,
150
+ contextVariables: source.contextVariables || {},
151
+ handler: apiSource.handler,
152
+ batch: 'batch' in source ? source.batch : true,
153
+ merge: source.merge,
154
+ createProxyingResolver: createProxyingResolverFactory(apiName, rootTypeMap),
155
+ });
156
+ }
157
+ catch (e) {
158
+ sourceLogger.error(`Failed to generate the schema`, e);
159
+ failed = true;
160
+ }
161
+ }));
162
+ if (failed) {
163
+ throw new Error(`Schemas couldn't be generated successfully. Check for the logs by running Mesh${process.env.DEBUG == null
164
+ ? ' with DEBUG=1 environmental variable to get more verbose output'
165
+ : ''}.`);
166
+ }
167
+ getMeshLogger.debug(`Schemas have been generated by the source handlers`);
168
+ getMeshLogger.debug(`Merging schemas using the defined merging strategy.`);
169
+ const unifiedSubschema = await merger.getUnifiedSchema({
170
+ rawSources,
171
+ typeDefs: additionalTypeDefs,
172
+ resolvers: additionalResolvers,
173
+ });
174
+ unifiedSubschema.transforms = unifiedSubschema.transforms || [];
175
+ for (const rootLevelTransform of transforms) {
176
+ if (rootLevelTransform.noWrap) {
177
+ if (rootLevelTransform.transformSchema) {
178
+ unifiedSubschema.schema = rootLevelTransform.transformSchema(unifiedSubschema.schema, unifiedSubschema);
179
+ }
180
+ }
181
+ else {
182
+ unifiedSubschema.transforms.push(rootLevelTransform);
183
+ }
184
+ }
185
+ let inContextSDK$;
186
+ const subschema = new Subschema(unifiedSubschema);
187
+ const plugins = [
188
+ useEngine({
189
+ validate,
190
+ specifiedRules,
191
+ }),
192
+ useSubschema(subschema),
193
+ useExtendContext(() => {
194
+ if (!inContextSDK$) {
195
+ const onDelegateHooks = [];
196
+ for (const plugin of initialPluginList) {
197
+ if ((plugin === null || plugin === void 0 ? void 0 : plugin.onDelegate) != null) {
198
+ onDelegateHooks.push(plugin.onDelegate);
199
+ }
200
+ }
201
+ inContextSDK$ = getInContextSDK(subschema.transformedSchema, rawSources, logger, onDelegateHooks);
202
+ }
203
+ return inContextSDK$;
204
+ }),
205
+ useExtendedValidation({
206
+ rules: [OneOfInputObjectsRule],
207
+ }),
208
+ ...initialPluginList,
209
+ ];
210
+ const EMPTY_ROOT_VALUE = {};
211
+ const EMPTY_CONTEXT_VALUE = {};
212
+ const EMPTY_VARIABLES_VALUE = {};
213
+ function createExecutor(globalContext = EMPTY_CONTEXT_VALUE) {
214
+ const getEnveloped = memoizedGetEnvelopedFactory(plugins);
215
+ const { schema, parse, execute, subscribe, contextFactory } = getEnveloped(globalContext);
216
+ return async function meshExecutor(documentOrSDL, variableValues = EMPTY_VARIABLES_VALUE, contextValue = EMPTY_CONTEXT_VALUE, rootValue = EMPTY_ROOT_VALUE, operationName) {
217
+ const document = typeof documentOrSDL === 'string' ? parse(documentOrSDL) : documentOrSDL;
218
+ const executeFn = memoizedGetOperationType(document) === 'subscription' ? subscribe : execute;
219
+ return executeFn({
220
+ schema,
221
+ document,
222
+ contextValue: await contextFactory(contextValue),
223
+ rootValue,
224
+ variableValues: variableValues,
225
+ operationName,
226
+ });
227
+ };
228
+ }
229
+ function sdkRequesterFactory(globalContext) {
230
+ const executor = createExecutor(globalContext);
231
+ return async function sdkRequester(...args) {
232
+ const result = await executor(...args);
233
+ if (isAsyncIterable(result)) {
234
+ return mapAsyncIterator(result, extractDataOrThrowErrors);
235
+ }
236
+ return extractDataOrThrowErrors(result);
237
+ };
238
+ }
239
+ function meshDestroy() {
240
+ return pubsub.publish('destroy', undefined);
241
+ }
242
+ return {
243
+ get schema() {
244
+ return subschema.transformedSchema;
245
+ },
246
+ rawSources,
247
+ cache,
248
+ pubsub,
249
+ destroy: meshDestroy,
250
+ logger,
251
+ plugins,
252
+ get getEnveloped() {
253
+ return memoizedGetEnvelopedFactory(plugins);
254
+ },
255
+ createExecutor,
256
+ get execute() {
257
+ return createExecutor();
258
+ },
259
+ get subscribe() {
260
+ return createExecutor();
261
+ },
262
+ sdkRequesterFactory,
263
+ };
264
+ }
265
+ function extractDataOrThrowErrors(result) {
266
+ if (result.errors) {
267
+ if (result.errors.length === 1) {
268
+ throw result.errors[0];
269
+ }
270
+ throw new AggregateError(result.errors);
271
+ }
272
+ return result.data;
273
+ }
@@ -0,0 +1,234 @@
1
+ import { getNamedType, isLeafType, Kind, } from 'graphql';
2
+ import { parseWithCache } from '@graphql-mesh/utils';
3
+ import { batchDelegateToSchema } from '@graphql-tools/batch-delegate';
4
+ import { delegateToSchema, } from '@graphql-tools/delegate';
5
+ import { isDocumentNode, memoize1 } from '@graphql-tools/utils';
6
+ import { WrapQuery } from '@graphql-tools/wrap';
7
+ import { MESH_API_CONTEXT_SYMBOL } from './constants.js';
8
+ export async function getInContextSDK(unifiedSchema, rawSources, logger, onDelegateHooks) {
9
+ const inContextSDK = {};
10
+ const sourceMap = unifiedSchema.extensions.sourceMap;
11
+ for (const rawSource of rawSources) {
12
+ const rawSourceLogger = logger.child(`${rawSource.name}`);
13
+ const rawSourceContext = {
14
+ rawSource,
15
+ [MESH_API_CONTEXT_SYMBOL]: true,
16
+ };
17
+ // TODO: Somehow rawSource reference got lost in somewhere
18
+ let rawSourceSubSchemaConfig;
19
+ const stitchingInfo = unifiedSchema.extensions.stitchingInfo;
20
+ if (stitchingInfo) {
21
+ for (const [subschemaConfig, subschema] of stitchingInfo.subschemaMap) {
22
+ if (subschemaConfig.name === rawSource.name) {
23
+ rawSourceSubSchemaConfig = subschema;
24
+ break;
25
+ }
26
+ }
27
+ }
28
+ else {
29
+ rawSourceSubSchemaConfig = rawSource;
30
+ }
31
+ // If there is a single source, there is no unifiedSchema
32
+ const transformedSchema = sourceMap.get(rawSource);
33
+ const rootTypes = {
34
+ query: transformedSchema.getQueryType(),
35
+ mutation: transformedSchema.getMutationType(),
36
+ subscription: transformedSchema.getSubscriptionType(),
37
+ };
38
+ rawSourceLogger.debug(`Generating In Context SDK`);
39
+ for (const operationType in rootTypes) {
40
+ const rootType = rootTypes[operationType];
41
+ if (rootType) {
42
+ rawSourceContext[rootType.name] = {};
43
+ const rootTypeFieldMap = rootType.getFields();
44
+ for (const fieldName in rootTypeFieldMap) {
45
+ const rootTypeField = rootTypeFieldMap[fieldName];
46
+ const inContextSdkLogger = rawSourceLogger.child(`InContextSDK.${rootType.name}.${fieldName}`);
47
+ const namedReturnType = getNamedType(rootTypeField.type);
48
+ const shouldHaveSelectionSet = !isLeafType(namedReturnType);
49
+ rawSourceContext[rootType.name][fieldName] = async ({ root, args, context, info = {
50
+ fieldName,
51
+ fieldNodes: [],
52
+ returnType: namedReturnType,
53
+ parentType: rootType,
54
+ path: {
55
+ typename: rootType.name,
56
+ key: fieldName,
57
+ prev: undefined,
58
+ },
59
+ schema: transformedSchema,
60
+ fragments: {},
61
+ rootValue: root,
62
+ operation: {
63
+ kind: Kind.OPERATION_DEFINITION,
64
+ operation: operationType,
65
+ selectionSet: {
66
+ kind: Kind.SELECTION_SET,
67
+ selections: [],
68
+ },
69
+ },
70
+ variableValues: {},
71
+ }, selectionSet, key, argsFromKeys, valuesFromResults, }) => {
72
+ inContextSdkLogger.debug(`Called with`, {
73
+ args,
74
+ key,
75
+ });
76
+ const commonDelegateOptions = {
77
+ schema: rawSourceSubSchemaConfig,
78
+ rootValue: root,
79
+ operation: operationType,
80
+ fieldName,
81
+ context,
82
+ transformedSchema,
83
+ info,
84
+ transforms: [],
85
+ };
86
+ // If there isn't an extraction of a value
87
+ if (typeof selectionSet !== 'function') {
88
+ commonDelegateOptions.returnType = rootTypeField.type;
89
+ }
90
+ if (shouldHaveSelectionSet) {
91
+ let selectionCount = 0;
92
+ for (const fieldNode of info.fieldNodes) {
93
+ if (fieldNode.selectionSet != null) {
94
+ selectionCount += fieldNode.selectionSet.selections.length;
95
+ }
96
+ }
97
+ if (selectionCount === 0) {
98
+ if (!selectionSet) {
99
+ throw new Error(`You have to provide 'selectionSet' for context.${rawSource.name}.${rootType.name}.${fieldName}`);
100
+ }
101
+ commonDelegateOptions.info = {
102
+ ...info,
103
+ fieldNodes: [
104
+ {
105
+ ...info.fieldNodes[0],
106
+ selectionSet: {
107
+ kind: Kind.SELECTION_SET,
108
+ selections: [
109
+ {
110
+ kind: Kind.FIELD,
111
+ name: {
112
+ kind: Kind.NAME,
113
+ value: '__typename',
114
+ },
115
+ },
116
+ ],
117
+ },
118
+ },
119
+ ...info.fieldNodes.slice(1),
120
+ ],
121
+ };
122
+ }
123
+ }
124
+ if (key && argsFromKeys) {
125
+ const batchDelegationOptions = {
126
+ ...commonDelegateOptions,
127
+ key,
128
+ argsFromKeys,
129
+ valuesFromResults,
130
+ };
131
+ if (selectionSet) {
132
+ const selectionSetFactory = normalizeSelectionSetParamOrFactory(selectionSet);
133
+ const path = [fieldName];
134
+ const wrapQueryTransform = new WrapQuery(path, selectionSetFactory, identical);
135
+ batchDelegationOptions.transforms = [wrapQueryTransform];
136
+ }
137
+ const onDelegateHookDones = [];
138
+ for (const onDelegateHook of onDelegateHooks) {
139
+ const onDelegateDone = await onDelegateHook({
140
+ ...batchDelegationOptions,
141
+ sourceName: rawSource.name,
142
+ typeName: rootType.name,
143
+ fieldName,
144
+ });
145
+ if (onDelegateDone) {
146
+ onDelegateHookDones.push(onDelegateDone);
147
+ }
148
+ }
149
+ let result = await batchDelegateToSchema(batchDelegationOptions);
150
+ for (const onDelegateHookDone of onDelegateHookDones) {
151
+ await onDelegateHookDone({
152
+ result,
153
+ setResult(newResult) {
154
+ result = newResult;
155
+ },
156
+ });
157
+ }
158
+ return result;
159
+ }
160
+ else {
161
+ const regularDelegateOptions = {
162
+ ...commonDelegateOptions,
163
+ args,
164
+ };
165
+ if (selectionSet) {
166
+ const selectionSetFactory = normalizeSelectionSetParamOrFactory(selectionSet);
167
+ const path = [fieldName];
168
+ const wrapQueryTransform = new WrapQuery(path, selectionSetFactory, valuesFromResults || identical);
169
+ regularDelegateOptions.transforms = [wrapQueryTransform];
170
+ }
171
+ const onDelegateHookDones = [];
172
+ for (const onDelegateHook of onDelegateHooks) {
173
+ const onDelegateDone = await onDelegateHook({
174
+ ...regularDelegateOptions,
175
+ sourceName: rawSource.name,
176
+ typeName: rootType.name,
177
+ fieldName,
178
+ });
179
+ if (onDelegateDone) {
180
+ onDelegateHookDones.push(onDelegateDone);
181
+ }
182
+ }
183
+ let result = await delegateToSchema(regularDelegateOptions);
184
+ for (const onDelegateHookDone of onDelegateHookDones) {
185
+ await onDelegateHookDone({
186
+ result,
187
+ setResult(newResult) {
188
+ result = newResult;
189
+ },
190
+ });
191
+ }
192
+ return result;
193
+ }
194
+ };
195
+ }
196
+ }
197
+ }
198
+ inContextSDK[rawSource.name] = rawSourceContext;
199
+ }
200
+ return inContextSDK;
201
+ }
202
+ function getSelectionSetFromDocumentNode(documentNode) {
203
+ const operationDefinition = documentNode.definitions.find(definition => definition.kind === Kind.OPERATION_DEFINITION);
204
+ if (!operationDefinition) {
205
+ throw new Error('DocumentNode must contain an OperationDefinitionNode');
206
+ }
207
+ return operationDefinition.selectionSet;
208
+ }
209
+ function normalizeSelectionSetParam(selectionSetParam) {
210
+ if (typeof selectionSetParam === 'string') {
211
+ const documentNode = parseWithCache(selectionSetParam);
212
+ return getSelectionSetFromDocumentNode(documentNode);
213
+ }
214
+ if (isDocumentNode(selectionSetParam)) {
215
+ return getSelectionSetFromDocumentNode(selectionSetParam);
216
+ }
217
+ return selectionSetParam;
218
+ }
219
+ const normalizeSelectionSetParamFactory = memoize1(function normalizeSelectionSetParamFactory(selectionSetParamFactory) {
220
+ const memoizedSelectionSetFactory = memoize1(selectionSetParamFactory);
221
+ return function selectionSetFactory(subtree) {
222
+ const selectionSetParam = memoizedSelectionSetFactory(subtree);
223
+ return normalizeSelectionSetParam(selectionSetParam);
224
+ };
225
+ });
226
+ function normalizeSelectionSetParamOrFactory(selectionSetParamOrFactory) {
227
+ if (typeof selectionSetParamOrFactory === 'function') {
228
+ return normalizeSelectionSetParamFactory(selectionSetParamOrFactory);
229
+ }
230
+ return () => normalizeSelectionSetParam(selectionSetParamOrFactory);
231
+ }
232
+ function identical(val) {
233
+ return val;
234
+ }
package/esm/index.js ADDED
@@ -0,0 +1,3 @@
1
+ export * from './get-mesh.js';
2
+ export * from './types.js';
3
+ export * from './useSubschema.js';
package/esm/types.js ADDED
@@ -0,0 +1 @@
1
+ import { MESH_CONTEXT_SYMBOL } from './constants.js';
@@ -0,0 +1,106 @@
1
+ import { BREAK, execute, visit } from 'graphql';
2
+ import { mapAsyncIterator } from '@envelop/core';
3
+ import { applyRequestTransforms, applyResultTransforms } from '@graphql-mesh/utils';
4
+ import { createBatchingExecutor } from '@graphql-tools/batch-execute';
5
+ import { applySchemaTransforms, createDefaultExecutor, } from '@graphql-tools/delegate';
6
+ import { getDefinedRootType, getOperationASTFromRequest, isAsyncIterable, printSchemaWithDirectives, } from '@graphql-tools/utils';
7
+ var IntrospectionQueryType;
8
+ (function (IntrospectionQueryType) {
9
+ IntrospectionQueryType["FEDERATION"] = "FEDERATION";
10
+ IntrospectionQueryType["REGULAR"] = "REGULAR";
11
+ })(IntrospectionQueryType || (IntrospectionQueryType = {}));
12
+ function getIntrospectionOperationType(operationAST) {
13
+ let introspectionQueryType = null;
14
+ visit(operationAST, {
15
+ Field: node => {
16
+ if (node.name.value === '__schema' || node.name.value === '__type') {
17
+ introspectionQueryType = IntrospectionQueryType.REGULAR;
18
+ return BREAK;
19
+ }
20
+ if (node.name.value === '_service') {
21
+ introspectionQueryType = IntrospectionQueryType.FEDERATION;
22
+ return BREAK;
23
+ }
24
+ },
25
+ });
26
+ return introspectionQueryType;
27
+ }
28
+ function getExecuteFn(subschema) {
29
+ return async function subschemaExecute(args) {
30
+ var _a;
31
+ const originalRequest = {
32
+ document: args.document,
33
+ variables: args.variableValues,
34
+ operationName: (_a = args.operationName) !== null && _a !== void 0 ? _a : undefined,
35
+ rootValue: args.rootValue,
36
+ context: args.contextValue,
37
+ };
38
+ const operationAST = getOperationASTFromRequest(originalRequest);
39
+ // TODO: We need more elegant solution
40
+ const introspectionQueryType = getIntrospectionOperationType(operationAST);
41
+ if (introspectionQueryType === IntrospectionQueryType.FEDERATION) {
42
+ const executionResult = {
43
+ data: {
44
+ _service: {
45
+ sdl: printSchemaWithDirectives(args.schema),
46
+ },
47
+ },
48
+ };
49
+ return executionResult;
50
+ }
51
+ else if (introspectionQueryType === IntrospectionQueryType.REGULAR) {
52
+ return execute(args);
53
+ }
54
+ const delegationContext = {
55
+ subschema,
56
+ subschemaConfig: subschema,
57
+ targetSchema: args.schema,
58
+ operation: operationAST.operation,
59
+ fieldName: '',
60
+ context: args.contextValue,
61
+ rootValue: args.rootValue,
62
+ transforms: subschema.transforms,
63
+ transformedSchema: subschema.transformedSchema,
64
+ skipTypeMerging: true,
65
+ returnType: getDefinedRootType(args.schema, operationAST.operation),
66
+ };
67
+ let executor = subschema.executor;
68
+ if (executor == null) {
69
+ executor = createDefaultExecutor(subschema.schema);
70
+ }
71
+ if (subschema.batch) {
72
+ executor = createBatchingExecutor(executor);
73
+ }
74
+ const transformationContext = {};
75
+ const transformedRequest = applyRequestTransforms(originalRequest, delegationContext, transformationContext, subschema.transforms);
76
+ const originalResult = await executor(transformedRequest);
77
+ if (isAsyncIterable(originalResult)) {
78
+ return mapAsyncIterator(originalResult, singleResult => applyResultTransforms(singleResult, delegationContext, transformationContext, subschema.transforms));
79
+ }
80
+ const transformedResult = applyResultTransforms(originalResult, delegationContext, transformationContext, subschema.transforms);
81
+ return transformedResult;
82
+ };
83
+ }
84
+ // Creates an envelop plugin to execute a subschema inside Envelop
85
+ export function useSubschema(subschema) {
86
+ const executeFn = getExecuteFn(subschema);
87
+ const plugin = {
88
+ onPluginInit({ setSchema }) {
89
+ // To prevent unwanted warnings from stitching
90
+ if (!('_transformedSchema' in subschema)) {
91
+ subschema.transformedSchema = applySchemaTransforms(subschema.schema, subschema);
92
+ }
93
+ subschema.transformedSchema.extensions =
94
+ subschema.transformedSchema.extensions || subschema.schema.extensions || {};
95
+ Object.assign(subschema.transformedSchema.extensions, subschema.schema.extensions);
96
+ setSchema(subschema.transformedSchema);
97
+ },
98
+ onExecute({ setExecuteFn }) {
99
+ setExecuteFn(executeFn);
100
+ },
101
+ onSubscribe({ setSubscribeFn }) {
102
+ setSubscribeFn(executeFn);
103
+ },
104
+ };
105
+ return plugin;
106
+ }