@envelop/core 2.4.0-alpha-aca44e1.0 → 2.4.0-alpha-e9434aa.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cjs/create.js +28 -0
- package/cjs/enable-if.js +24 -0
- package/cjs/index.js +16 -0
- package/cjs/orchestrator.js +451 -0
- package/cjs/package.json +1 -0
- package/cjs/plugins/use-envelop.js +13 -0
- package/cjs/plugins/use-error-handler.js +21 -0
- package/cjs/plugins/use-extend-context.js +9 -0
- package/cjs/plugins/use-immediate-introspection.js +50 -0
- package/cjs/plugins/use-logger.js +45 -0
- package/cjs/plugins/use-masked-errors.js +90 -0
- package/cjs/plugins/use-payload-formatter.js +21 -0
- package/cjs/plugins/use-schema.js +29 -0
- package/cjs/plugins/use-timing.js +138 -0
- package/cjs/traced-orchestrator.js +134 -0
- package/cjs/traced-schema.js +68 -0
- package/cjs/utils.js +221 -0
- package/esm/create.js +28 -0
- package/esm/enable-if.js +24 -0
- package/esm/index.js +29 -0
- package/esm/orchestrator.js +451 -0
- package/esm/plugins/use-envelop.js +13 -0
- package/esm/plugins/use-error-handler.js +21 -0
- package/esm/plugins/use-extend-context.js +9 -0
- package/esm/plugins/use-immediate-introspection.js +50 -0
- package/esm/plugins/use-logger.js +45 -0
- package/esm/plugins/use-masked-errors.js +90 -0
- package/esm/plugins/use-payload-formatter.js +21 -0
- package/esm/plugins/use-schema.js +29 -0
- package/esm/plugins/use-timing.js +138 -0
- package/esm/traced-orchestrator.js +134 -0
- package/esm/traced-schema.js +68 -0
- package/esm/utils.js +221 -0
- package/package.json +33 -12
- package/{create.d.ts → typings/create.d.ts} +1 -1
- package/{enable-if.d.ts → typings/enable-if.d.ts} +0 -0
- package/typings/index.d.ts +13 -0
- package/{orchestrator.d.ts → typings/orchestrator.d.ts} +0 -0
- package/{plugins → typings/plugins}/use-envelop.d.ts +0 -0
- package/{plugins → typings/plugins}/use-error-handler.d.ts +0 -0
- package/{plugins → typings/plugins}/use-extend-context.d.ts +0 -0
- package/{plugins → typings/plugins}/use-immediate-introspection.d.ts +0 -0
- package/{plugins → typings/plugins}/use-logger.d.ts +1 -1
- package/{plugins → typings/plugins}/use-masked-errors.d.ts +3 -3
- package/{plugins → typings/plugins}/use-payload-formatter.d.ts +0 -0
- package/{plugins → typings/plugins}/use-schema.d.ts +0 -0
- package/{plugins → typings/plugins}/use-timing.d.ts +2 -2
- package/{traced-orchestrator.d.ts → typings/traced-orchestrator.d.ts} +1 -1
- package/{traced-schema.d.ts → typings/traced-schema.d.ts} +0 -0
- package/{utils.d.ts → typings/utils.d.ts} +0 -13
- package/README.md +0 -15
- package/index.d.ts +0 -13
- package/index.js +0 -1359
- package/index.mjs +0 -1317
package/index.js
DELETED
|
@@ -1,1359 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
-
|
|
5
|
-
const types = require('@envelop/types');
|
|
6
|
-
const graphql = require('graphql');
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* This enum is used only internally in order to create nominal type for the disabled plugin
|
|
10
|
-
*/
|
|
11
|
-
var EnableIfBranded;
|
|
12
|
-
(function (EnableIfBranded) {
|
|
13
|
-
EnableIfBranded[EnableIfBranded["DisabledPlugin"] = 0] = "DisabledPlugin";
|
|
14
|
-
})(EnableIfBranded || (EnableIfBranded = {}));
|
|
15
|
-
function isPluginEnabled(t) {
|
|
16
|
-
return t !== EnableIfBranded.DisabledPlugin && t !== null;
|
|
17
|
-
}
|
|
18
|
-
/**
|
|
19
|
-
* Utility function to enable a plugin.
|
|
20
|
-
*/
|
|
21
|
-
function enableIf(condition, plugin) {
|
|
22
|
-
if (condition) {
|
|
23
|
-
return typeof plugin === 'function' ? plugin() : plugin;
|
|
24
|
-
}
|
|
25
|
-
else {
|
|
26
|
-
return EnableIfBranded.DisabledPlugin;
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
const trackedSchemaSymbol = Symbol('TRACKED_SCHEMA');
|
|
31
|
-
const resolversHooksSymbol = Symbol('RESOLVERS_HOOKS');
|
|
32
|
-
function prepareTracedSchema(schema) {
|
|
33
|
-
if (!schema || schema[trackedSchemaSymbol]) {
|
|
34
|
-
return;
|
|
35
|
-
}
|
|
36
|
-
schema[trackedSchemaSymbol] = true;
|
|
37
|
-
const entries = Object.values(schema.getTypeMap());
|
|
38
|
-
for (const type of entries) {
|
|
39
|
-
if (!graphql.isIntrospectionType(type) && graphql.isObjectType(type)) {
|
|
40
|
-
const fields = Object.values(type.getFields());
|
|
41
|
-
for (const field of fields) {
|
|
42
|
-
let resolverFn = (field.resolve || graphql.defaultFieldResolver);
|
|
43
|
-
field.resolve = async (root, args, context, info) => {
|
|
44
|
-
if (context && context[resolversHooksSymbol]) {
|
|
45
|
-
const hooks = context[resolversHooksSymbol];
|
|
46
|
-
const afterCalls = [];
|
|
47
|
-
for (const hook of hooks) {
|
|
48
|
-
const afterFn = await hook({
|
|
49
|
-
root,
|
|
50
|
-
args,
|
|
51
|
-
context,
|
|
52
|
-
info,
|
|
53
|
-
resolverFn,
|
|
54
|
-
replaceResolverFn: newFn => {
|
|
55
|
-
resolverFn = newFn;
|
|
56
|
-
},
|
|
57
|
-
});
|
|
58
|
-
afterFn && afterCalls.push(afterFn);
|
|
59
|
-
}
|
|
60
|
-
try {
|
|
61
|
-
let result = await resolverFn(root, args, context, info);
|
|
62
|
-
for (const afterFn of afterCalls) {
|
|
63
|
-
afterFn({
|
|
64
|
-
result,
|
|
65
|
-
setResult: newResult => {
|
|
66
|
-
result = newResult;
|
|
67
|
-
},
|
|
68
|
-
});
|
|
69
|
-
}
|
|
70
|
-
return result;
|
|
71
|
-
}
|
|
72
|
-
catch (e) {
|
|
73
|
-
let resultErr = e;
|
|
74
|
-
for (const afterFn of afterCalls) {
|
|
75
|
-
afterFn({
|
|
76
|
-
result: resultErr,
|
|
77
|
-
setResult: newResult => {
|
|
78
|
-
resultErr = newResult;
|
|
79
|
-
},
|
|
80
|
-
});
|
|
81
|
-
}
|
|
82
|
-
throw resultErr;
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
else {
|
|
86
|
-
return resolverFn(root, args, context, info);
|
|
87
|
-
}
|
|
88
|
-
};
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
const envelopIsIntrospectionSymbol = Symbol('ENVELOP_IS_INTROSPECTION');
|
|
95
|
-
function isOperationDefinition(def) {
|
|
96
|
-
return def.kind === graphql.Kind.OPERATION_DEFINITION;
|
|
97
|
-
}
|
|
98
|
-
function isIntrospectionOperation(operation) {
|
|
99
|
-
if (operation.kind === 'OperationDefinition') {
|
|
100
|
-
let hasIntrospectionField = false;
|
|
101
|
-
graphql.visit(operation, {
|
|
102
|
-
Field: node => {
|
|
103
|
-
if (node.name.value === '__schema') {
|
|
104
|
-
hasIntrospectionField = true;
|
|
105
|
-
return graphql.BREAK;
|
|
106
|
-
}
|
|
107
|
-
},
|
|
108
|
-
});
|
|
109
|
-
return hasIntrospectionField;
|
|
110
|
-
}
|
|
111
|
-
return false;
|
|
112
|
-
}
|
|
113
|
-
function isIntrospectionDocument(document) {
|
|
114
|
-
const operations = document.definitions.filter(isOperationDefinition);
|
|
115
|
-
return operations.some(op => isIntrospectionOperation(op));
|
|
116
|
-
}
|
|
117
|
-
function isIntrospectionOperationString(operation) {
|
|
118
|
-
return (typeof operation === 'string' ? operation : operation.body).indexOf('__schema') !== -1;
|
|
119
|
-
}
|
|
120
|
-
function getSubscribeArgs(args) {
|
|
121
|
-
return args.length === 1
|
|
122
|
-
? args[0]
|
|
123
|
-
: {
|
|
124
|
-
schema: args[0],
|
|
125
|
-
document: args[1],
|
|
126
|
-
rootValue: args[2],
|
|
127
|
-
contextValue: args[3],
|
|
128
|
-
variableValues: args[4],
|
|
129
|
-
operationName: args[5],
|
|
130
|
-
fieldResolver: args[6],
|
|
131
|
-
subscribeFieldResolver: args[7],
|
|
132
|
-
};
|
|
133
|
-
}
|
|
134
|
-
/**
|
|
135
|
-
* Utility function for making a subscribe function that handles polymorphic arguments.
|
|
136
|
-
*/
|
|
137
|
-
const makeSubscribe = (subscribeFn) => ((...polyArgs) => subscribeFn(getSubscribeArgs(polyArgs)));
|
|
138
|
-
function mapAsyncIterator(source, mapper) {
|
|
139
|
-
const iterator = source[Symbol.asyncIterator]();
|
|
140
|
-
async function mapResult(result) {
|
|
141
|
-
var _a;
|
|
142
|
-
if (result.done) {
|
|
143
|
-
return result;
|
|
144
|
-
}
|
|
145
|
-
try {
|
|
146
|
-
return { value: await mapper(result.value), done: false };
|
|
147
|
-
}
|
|
148
|
-
catch (error) {
|
|
149
|
-
try {
|
|
150
|
-
await ((_a = iterator.return) === null || _a === void 0 ? void 0 : _a.call(iterator));
|
|
151
|
-
}
|
|
152
|
-
catch (_error) {
|
|
153
|
-
/* ignore error */
|
|
154
|
-
}
|
|
155
|
-
throw error;
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
const stream = {
|
|
159
|
-
[Symbol.asyncIterator]() {
|
|
160
|
-
return stream;
|
|
161
|
-
},
|
|
162
|
-
async next() {
|
|
163
|
-
return await mapResult(await iterator.next());
|
|
164
|
-
},
|
|
165
|
-
async return() {
|
|
166
|
-
var _a;
|
|
167
|
-
const promise = (_a = iterator.return) === null || _a === void 0 ? void 0 : _a.call(iterator);
|
|
168
|
-
return promise ? await mapResult(await promise) : { value: undefined, done: true };
|
|
169
|
-
},
|
|
170
|
-
async throw(error) {
|
|
171
|
-
var _a;
|
|
172
|
-
const promise = (_a = iterator.throw) === null || _a === void 0 ? void 0 : _a.call(iterator);
|
|
173
|
-
if (promise) {
|
|
174
|
-
return await mapResult(await promise);
|
|
175
|
-
}
|
|
176
|
-
// if the source has no throw method we just re-throw error
|
|
177
|
-
// usually throw is not called anyways
|
|
178
|
-
throw error;
|
|
179
|
-
},
|
|
180
|
-
};
|
|
181
|
-
return stream;
|
|
182
|
-
}
|
|
183
|
-
function getExecuteArgs(args) {
|
|
184
|
-
return args.length === 1
|
|
185
|
-
? args[0]
|
|
186
|
-
: {
|
|
187
|
-
schema: args[0],
|
|
188
|
-
document: args[1],
|
|
189
|
-
rootValue: args[2],
|
|
190
|
-
contextValue: args[3],
|
|
191
|
-
variableValues: args[4],
|
|
192
|
-
operationName: args[5],
|
|
193
|
-
fieldResolver: args[6],
|
|
194
|
-
typeResolver: args[7],
|
|
195
|
-
};
|
|
196
|
-
}
|
|
197
|
-
/**
|
|
198
|
-
* Utility function for making a execute function that handles polymorphic arguments.
|
|
199
|
-
*/
|
|
200
|
-
const makeExecute = (executeFn) => ((...polyArgs) => executeFn(getExecuteArgs(polyArgs)));
|
|
201
|
-
/**
|
|
202
|
-
* Returns true if the provided object implements the AsyncIterator protocol via
|
|
203
|
-
* implementing a `Symbol.asyncIterator` method.
|
|
204
|
-
*
|
|
205
|
-
* Source: https://github.com/graphql/graphql-js/blob/main/src/jsutils/isAsyncIterable.ts
|
|
206
|
-
*/
|
|
207
|
-
function isAsyncIterable(maybeAsyncIterable) {
|
|
208
|
-
return (typeof maybeAsyncIterable === 'object' &&
|
|
209
|
-
maybeAsyncIterable != null &&
|
|
210
|
-
typeof maybeAsyncIterable[Symbol.asyncIterator] === 'function');
|
|
211
|
-
}
|
|
212
|
-
/**
|
|
213
|
-
* A utility function for handling `onExecuteDone` hook result, for simplifying the handling of AsyncIterable returned from `execute`.
|
|
214
|
-
*
|
|
215
|
-
* @param payload The payload send to `onExecuteDone` hook function
|
|
216
|
-
* @param fn The handler to be executed on each result
|
|
217
|
-
* @returns a subscription for streamed results, or undefined in case of an non-async
|
|
218
|
-
*/
|
|
219
|
-
function handleStreamOrSingleExecutionResult(payload, fn) {
|
|
220
|
-
if (isAsyncIterable(payload.result)) {
|
|
221
|
-
return { onNext: fn };
|
|
222
|
-
}
|
|
223
|
-
else {
|
|
224
|
-
fn({
|
|
225
|
-
args: payload.args,
|
|
226
|
-
result: payload.result,
|
|
227
|
-
setResult: payload.setResult,
|
|
228
|
-
});
|
|
229
|
-
return undefined;
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
function finalAsyncIterator(source, onFinal) {
|
|
233
|
-
const iterator = source[Symbol.asyncIterator]();
|
|
234
|
-
let isDone = false;
|
|
235
|
-
const stream = {
|
|
236
|
-
[Symbol.asyncIterator]() {
|
|
237
|
-
return stream;
|
|
238
|
-
},
|
|
239
|
-
async next() {
|
|
240
|
-
const result = await iterator.next();
|
|
241
|
-
if (result.done && isDone === false) {
|
|
242
|
-
isDone = true;
|
|
243
|
-
onFinal();
|
|
244
|
-
}
|
|
245
|
-
return result;
|
|
246
|
-
},
|
|
247
|
-
async return() {
|
|
248
|
-
var _a;
|
|
249
|
-
const promise = (_a = iterator.return) === null || _a === void 0 ? void 0 : _a.call(iterator);
|
|
250
|
-
if (isDone === false) {
|
|
251
|
-
isDone = true;
|
|
252
|
-
onFinal();
|
|
253
|
-
}
|
|
254
|
-
return promise ? await promise : { done: true, value: undefined };
|
|
255
|
-
},
|
|
256
|
-
async throw(error) {
|
|
257
|
-
var _a;
|
|
258
|
-
const promise = (_a = iterator.throw) === null || _a === void 0 ? void 0 : _a.call(iterator);
|
|
259
|
-
if (promise) {
|
|
260
|
-
return await promise;
|
|
261
|
-
}
|
|
262
|
-
// if the source has no throw method we just re-throw error
|
|
263
|
-
// usually throw is not called anyways
|
|
264
|
-
throw error;
|
|
265
|
-
},
|
|
266
|
-
};
|
|
267
|
-
return stream;
|
|
268
|
-
}
|
|
269
|
-
function errorAsyncIterator(source, onError) {
|
|
270
|
-
const iterator = source[Symbol.asyncIterator]();
|
|
271
|
-
const stream = {
|
|
272
|
-
[Symbol.asyncIterator]() {
|
|
273
|
-
return stream;
|
|
274
|
-
},
|
|
275
|
-
async next() {
|
|
276
|
-
try {
|
|
277
|
-
return await iterator.next();
|
|
278
|
-
}
|
|
279
|
-
catch (error) {
|
|
280
|
-
onError(error);
|
|
281
|
-
return { done: true, value: undefined };
|
|
282
|
-
}
|
|
283
|
-
},
|
|
284
|
-
async return() {
|
|
285
|
-
var _a;
|
|
286
|
-
const promise = (_a = iterator.return) === null || _a === void 0 ? void 0 : _a.call(iterator);
|
|
287
|
-
return promise ? await promise : { done: true, value: undefined };
|
|
288
|
-
},
|
|
289
|
-
async throw(error) {
|
|
290
|
-
var _a;
|
|
291
|
-
const promise = (_a = iterator.throw) === null || _a === void 0 ? void 0 : _a.call(iterator);
|
|
292
|
-
if (promise) {
|
|
293
|
-
return await promise;
|
|
294
|
-
}
|
|
295
|
-
// if the source has no throw method we just re-throw error
|
|
296
|
-
// usually throw is not called anyways
|
|
297
|
-
throw error;
|
|
298
|
-
},
|
|
299
|
-
};
|
|
300
|
-
return stream;
|
|
301
|
-
}
|
|
302
|
-
function getInMemoryLRUCache({ max = 1000, onDelete = () => { }, } = {}) {
|
|
303
|
-
let storage = {};
|
|
304
|
-
let keys = [];
|
|
305
|
-
return {
|
|
306
|
-
get(key) {
|
|
307
|
-
return storage[key];
|
|
308
|
-
},
|
|
309
|
-
set(key, value) {
|
|
310
|
-
queueMicrotask(() => {
|
|
311
|
-
if (storage[key] != null) {
|
|
312
|
-
if (keys.indexOf(key)) {
|
|
313
|
-
keys.splice(keys.indexOf(key), 1);
|
|
314
|
-
}
|
|
315
|
-
}
|
|
316
|
-
keys.push(key);
|
|
317
|
-
storage[key] = value;
|
|
318
|
-
while (keys.length > max) {
|
|
319
|
-
const key = keys.shift();
|
|
320
|
-
if (key != null) {
|
|
321
|
-
onDelete(key, storage[key]);
|
|
322
|
-
delete storage[key];
|
|
323
|
-
}
|
|
324
|
-
}
|
|
325
|
-
});
|
|
326
|
-
},
|
|
327
|
-
delete(key) {
|
|
328
|
-
queueMicrotask(() => {
|
|
329
|
-
if (storage[key] != null) {
|
|
330
|
-
keys.splice(keys.indexOf(key), 1);
|
|
331
|
-
onDelete(key, storage[key]);
|
|
332
|
-
delete storage[key];
|
|
333
|
-
}
|
|
334
|
-
});
|
|
335
|
-
},
|
|
336
|
-
clear() {
|
|
337
|
-
queueMicrotask(() => {
|
|
338
|
-
storage = {};
|
|
339
|
-
keys = [];
|
|
340
|
-
});
|
|
341
|
-
},
|
|
342
|
-
};
|
|
343
|
-
}
|
|
344
|
-
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
|
345
|
-
function isSourceObject(maybeSource) {
|
|
346
|
-
return maybeSource != null && maybeSource.body != null;
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
function createEnvelopOrchestrator(plugins) {
|
|
350
|
-
let schema = null;
|
|
351
|
-
let initDone = false;
|
|
352
|
-
const onResolversHandlers = [];
|
|
353
|
-
for (const plugin of plugins) {
|
|
354
|
-
if (plugin.onResolverCalled) {
|
|
355
|
-
onResolversHandlers.push(plugin.onResolverCalled);
|
|
356
|
-
}
|
|
357
|
-
}
|
|
358
|
-
// Define the initial method for replacing the GraphQL schema, this is needed in order
|
|
359
|
-
// to allow setting the schema from the onPluginInit callback. We also need to make sure
|
|
360
|
-
// here not to call the same plugin that initiated the schema switch.
|
|
361
|
-
const replaceSchema = (newSchema, ignorePluginIndex = -1) => {
|
|
362
|
-
if (onResolversHandlers.length) {
|
|
363
|
-
prepareTracedSchema(newSchema);
|
|
364
|
-
}
|
|
365
|
-
schema = newSchema;
|
|
366
|
-
if (initDone) {
|
|
367
|
-
for (const [i, plugin] of plugins.entries()) {
|
|
368
|
-
if (i !== ignorePluginIndex) {
|
|
369
|
-
plugin.onSchemaChange &&
|
|
370
|
-
plugin.onSchemaChange({
|
|
371
|
-
schema,
|
|
372
|
-
replaceSchema: schemaToSet => {
|
|
373
|
-
replaceSchema(schemaToSet, i);
|
|
374
|
-
},
|
|
375
|
-
});
|
|
376
|
-
}
|
|
377
|
-
}
|
|
378
|
-
}
|
|
379
|
-
};
|
|
380
|
-
const contextErrorHandlers = [];
|
|
381
|
-
// Iterate all plugins and trigger onPluginInit
|
|
382
|
-
for (const [i, plugin] of plugins.entries()) {
|
|
383
|
-
plugin.onPluginInit &&
|
|
384
|
-
plugin.onPluginInit({
|
|
385
|
-
plugins,
|
|
386
|
-
addPlugin: newPlugin => {
|
|
387
|
-
plugins.push(newPlugin);
|
|
388
|
-
},
|
|
389
|
-
setSchema: modifiedSchema => replaceSchema(modifiedSchema, i),
|
|
390
|
-
registerContextErrorHandler: handler => contextErrorHandlers.push(handler),
|
|
391
|
-
});
|
|
392
|
-
}
|
|
393
|
-
// A set of before callbacks defined here in order to allow it to be used later
|
|
394
|
-
const beforeCallbacks = {
|
|
395
|
-
init: [],
|
|
396
|
-
parse: [],
|
|
397
|
-
validate: [],
|
|
398
|
-
subscribe: [],
|
|
399
|
-
execute: [],
|
|
400
|
-
context: [],
|
|
401
|
-
};
|
|
402
|
-
for (const { onContextBuilding, onExecute, onParse, onSubscribe, onValidate, onEnveloped } of plugins) {
|
|
403
|
-
onEnveloped && beforeCallbacks.init.push(onEnveloped);
|
|
404
|
-
onContextBuilding && beforeCallbacks.context.push(onContextBuilding);
|
|
405
|
-
onExecute && beforeCallbacks.execute.push(onExecute);
|
|
406
|
-
onParse && beforeCallbacks.parse.push(onParse);
|
|
407
|
-
onSubscribe && beforeCallbacks.subscribe.push(onSubscribe);
|
|
408
|
-
onValidate && beforeCallbacks.validate.push(onValidate);
|
|
409
|
-
}
|
|
410
|
-
const init = initialContext => {
|
|
411
|
-
for (const [i, onEnveloped] of beforeCallbacks.init.entries()) {
|
|
412
|
-
onEnveloped({
|
|
413
|
-
context: initialContext,
|
|
414
|
-
extendContext: extension => {
|
|
415
|
-
if (!initialContext) {
|
|
416
|
-
return;
|
|
417
|
-
}
|
|
418
|
-
Object.assign(initialContext, extension);
|
|
419
|
-
},
|
|
420
|
-
setSchema: modifiedSchema => replaceSchema(modifiedSchema, i),
|
|
421
|
-
});
|
|
422
|
-
}
|
|
423
|
-
};
|
|
424
|
-
const customParse = beforeCallbacks.parse.length
|
|
425
|
-
? initialContext => (source, parseOptions) => {
|
|
426
|
-
let result = null;
|
|
427
|
-
let parseFn = graphql.parse;
|
|
428
|
-
const context = initialContext;
|
|
429
|
-
const afterCalls = [];
|
|
430
|
-
for (const onParse of beforeCallbacks.parse) {
|
|
431
|
-
const afterFn = onParse({
|
|
432
|
-
context,
|
|
433
|
-
extendContext: extension => {
|
|
434
|
-
Object.assign(context, extension);
|
|
435
|
-
},
|
|
436
|
-
params: { source, options: parseOptions },
|
|
437
|
-
parseFn,
|
|
438
|
-
setParseFn: newFn => {
|
|
439
|
-
parseFn = newFn;
|
|
440
|
-
},
|
|
441
|
-
setParsedDocument: newDoc => {
|
|
442
|
-
result = newDoc;
|
|
443
|
-
},
|
|
444
|
-
});
|
|
445
|
-
afterFn && afterCalls.push(afterFn);
|
|
446
|
-
}
|
|
447
|
-
if (result === null) {
|
|
448
|
-
try {
|
|
449
|
-
result = parseFn(source, parseOptions);
|
|
450
|
-
}
|
|
451
|
-
catch (e) {
|
|
452
|
-
result = e;
|
|
453
|
-
}
|
|
454
|
-
}
|
|
455
|
-
for (const afterCb of afterCalls) {
|
|
456
|
-
afterCb({
|
|
457
|
-
context,
|
|
458
|
-
extendContext: extension => {
|
|
459
|
-
Object.assign(context, extension);
|
|
460
|
-
},
|
|
461
|
-
replaceParseResult: newResult => {
|
|
462
|
-
result = newResult;
|
|
463
|
-
},
|
|
464
|
-
result,
|
|
465
|
-
});
|
|
466
|
-
}
|
|
467
|
-
if (result === null) {
|
|
468
|
-
throw new Error(`Failed to parse document.`);
|
|
469
|
-
}
|
|
470
|
-
if (result instanceof Error) {
|
|
471
|
-
throw result;
|
|
472
|
-
}
|
|
473
|
-
return result;
|
|
474
|
-
}
|
|
475
|
-
: () => graphql.parse;
|
|
476
|
-
const customValidate = beforeCallbacks.validate.length
|
|
477
|
-
? initialContext => (schema, documentAST, rules, typeInfo, validationOptions) => {
|
|
478
|
-
let actualRules = rules ? [...rules] : undefined;
|
|
479
|
-
let validateFn = graphql.validate;
|
|
480
|
-
let result = null;
|
|
481
|
-
const context = initialContext;
|
|
482
|
-
const afterCalls = [];
|
|
483
|
-
for (const onValidate of beforeCallbacks.validate) {
|
|
484
|
-
const afterFn = onValidate({
|
|
485
|
-
context,
|
|
486
|
-
extendContext: extension => {
|
|
487
|
-
Object.assign(context, extension);
|
|
488
|
-
},
|
|
489
|
-
params: {
|
|
490
|
-
schema,
|
|
491
|
-
documentAST,
|
|
492
|
-
rules: actualRules,
|
|
493
|
-
typeInfo,
|
|
494
|
-
options: validationOptions,
|
|
495
|
-
},
|
|
496
|
-
validateFn,
|
|
497
|
-
addValidationRule: rule => {
|
|
498
|
-
if (!actualRules) {
|
|
499
|
-
actualRules = [...graphql.specifiedRules];
|
|
500
|
-
}
|
|
501
|
-
actualRules.push(rule);
|
|
502
|
-
},
|
|
503
|
-
setValidationFn: newFn => {
|
|
504
|
-
validateFn = newFn;
|
|
505
|
-
},
|
|
506
|
-
setResult: newResults => {
|
|
507
|
-
result = newResults;
|
|
508
|
-
},
|
|
509
|
-
});
|
|
510
|
-
afterFn && afterCalls.push(afterFn);
|
|
511
|
-
}
|
|
512
|
-
if (!result) {
|
|
513
|
-
result = validateFn(schema, documentAST, actualRules, typeInfo, validationOptions);
|
|
514
|
-
}
|
|
515
|
-
const valid = result.length === 0;
|
|
516
|
-
for (const afterCb of afterCalls) {
|
|
517
|
-
afterCb({
|
|
518
|
-
valid,
|
|
519
|
-
result,
|
|
520
|
-
context,
|
|
521
|
-
extendContext: extension => {
|
|
522
|
-
Object.assign(context, extension);
|
|
523
|
-
},
|
|
524
|
-
setResult: newResult => {
|
|
525
|
-
result = newResult;
|
|
526
|
-
},
|
|
527
|
-
});
|
|
528
|
-
}
|
|
529
|
-
return result;
|
|
530
|
-
}
|
|
531
|
-
: () => graphql.validate;
|
|
532
|
-
const customContextFactory = beforeCallbacks.context.length
|
|
533
|
-
? initialContext => async (orchestratorCtx) => {
|
|
534
|
-
const afterCalls = [];
|
|
535
|
-
// In order to have access to the "last working" context object we keep this outside of the try block:
|
|
536
|
-
let context = orchestratorCtx ? { ...initialContext, ...orchestratorCtx } : initialContext;
|
|
537
|
-
try {
|
|
538
|
-
let isBreakingContextBuilding = false;
|
|
539
|
-
for (const onContext of beforeCallbacks.context) {
|
|
540
|
-
const afterHookResult = await onContext({
|
|
541
|
-
context,
|
|
542
|
-
extendContext: extension => {
|
|
543
|
-
context = { ...context, ...extension };
|
|
544
|
-
},
|
|
545
|
-
breakContextBuilding: () => {
|
|
546
|
-
isBreakingContextBuilding = true;
|
|
547
|
-
},
|
|
548
|
-
});
|
|
549
|
-
if (typeof afterHookResult === 'function') {
|
|
550
|
-
afterCalls.push(afterHookResult);
|
|
551
|
-
}
|
|
552
|
-
if (isBreakingContextBuilding === true) {
|
|
553
|
-
break;
|
|
554
|
-
}
|
|
555
|
-
}
|
|
556
|
-
for (const afterCb of afterCalls) {
|
|
557
|
-
afterCb({
|
|
558
|
-
context,
|
|
559
|
-
extendContext: extension => {
|
|
560
|
-
context = { ...context, ...extension };
|
|
561
|
-
},
|
|
562
|
-
});
|
|
563
|
-
}
|
|
564
|
-
return context;
|
|
565
|
-
}
|
|
566
|
-
catch (err) {
|
|
567
|
-
let error = err;
|
|
568
|
-
for (const errorCb of contextErrorHandlers) {
|
|
569
|
-
errorCb({
|
|
570
|
-
context,
|
|
571
|
-
error,
|
|
572
|
-
setError: err => {
|
|
573
|
-
error = err;
|
|
574
|
-
},
|
|
575
|
-
});
|
|
576
|
-
}
|
|
577
|
-
throw error;
|
|
578
|
-
}
|
|
579
|
-
}
|
|
580
|
-
: initialContext => orchestratorCtx => orchestratorCtx ? { ...initialContext, ...orchestratorCtx } : initialContext;
|
|
581
|
-
const useCustomSubscribe = beforeCallbacks.subscribe.length || onResolversHandlers.length;
|
|
582
|
-
const customSubscribe = useCustomSubscribe
|
|
583
|
-
? makeSubscribe(async (args) => {
|
|
584
|
-
let subscribeFn = graphql.subscribe;
|
|
585
|
-
const afterCalls = [];
|
|
586
|
-
const subscribeErrorHandlers = [];
|
|
587
|
-
let context = args.contextValue || {};
|
|
588
|
-
let result;
|
|
589
|
-
for (const onSubscribe of beforeCallbacks.subscribe) {
|
|
590
|
-
const after = await onSubscribe({
|
|
591
|
-
subscribeFn,
|
|
592
|
-
setSubscribeFn: newSubscribeFn => {
|
|
593
|
-
subscribeFn = newSubscribeFn;
|
|
594
|
-
},
|
|
595
|
-
extendContext: extension => {
|
|
596
|
-
context = { ...context, ...extension };
|
|
597
|
-
},
|
|
598
|
-
args: args,
|
|
599
|
-
setResultAndStopExecution: stopResult => {
|
|
600
|
-
result = stopResult;
|
|
601
|
-
},
|
|
602
|
-
});
|
|
603
|
-
if (after) {
|
|
604
|
-
if (after.onSubscribeResult) {
|
|
605
|
-
afterCalls.push(after.onSubscribeResult);
|
|
606
|
-
}
|
|
607
|
-
if (after.onSubscribeError) {
|
|
608
|
-
subscribeErrorHandlers.push(after.onSubscribeError);
|
|
609
|
-
}
|
|
610
|
-
}
|
|
611
|
-
if (result !== undefined) {
|
|
612
|
-
break;
|
|
613
|
-
}
|
|
614
|
-
}
|
|
615
|
-
if (onResolversHandlers.length) {
|
|
616
|
-
context[resolversHooksSymbol] = onResolversHandlers;
|
|
617
|
-
}
|
|
618
|
-
if (result === undefined) {
|
|
619
|
-
result = await subscribeFn({
|
|
620
|
-
...args,
|
|
621
|
-
contextValue: context,
|
|
622
|
-
// Casted for GraphQL.js 15 compatibility
|
|
623
|
-
// Can be removed once we drop support for GraphQL.js 15
|
|
624
|
-
});
|
|
625
|
-
}
|
|
626
|
-
const onNextHandler = [];
|
|
627
|
-
const onEndHandler = [];
|
|
628
|
-
for (const afterCb of afterCalls) {
|
|
629
|
-
const hookResult = afterCb({
|
|
630
|
-
args: args,
|
|
631
|
-
result,
|
|
632
|
-
setResult: newResult => {
|
|
633
|
-
result = newResult;
|
|
634
|
-
},
|
|
635
|
-
});
|
|
636
|
-
if (hookResult) {
|
|
637
|
-
if (hookResult.onNext) {
|
|
638
|
-
onNextHandler.push(hookResult.onNext);
|
|
639
|
-
}
|
|
640
|
-
if (hookResult.onEnd) {
|
|
641
|
-
onEndHandler.push(hookResult.onEnd);
|
|
642
|
-
}
|
|
643
|
-
}
|
|
644
|
-
}
|
|
645
|
-
if (onNextHandler.length && isAsyncIterable(result)) {
|
|
646
|
-
result = mapAsyncIterator(result, async (result) => {
|
|
647
|
-
for (const onNext of onNextHandler) {
|
|
648
|
-
await onNext({
|
|
649
|
-
args: args,
|
|
650
|
-
result,
|
|
651
|
-
setResult: newResult => (result = newResult),
|
|
652
|
-
});
|
|
653
|
-
}
|
|
654
|
-
return result;
|
|
655
|
-
});
|
|
656
|
-
}
|
|
657
|
-
if (onEndHandler.length && isAsyncIterable(result)) {
|
|
658
|
-
result = finalAsyncIterator(result, () => {
|
|
659
|
-
for (const onEnd of onEndHandler) {
|
|
660
|
-
onEnd();
|
|
661
|
-
}
|
|
662
|
-
});
|
|
663
|
-
}
|
|
664
|
-
if (subscribeErrorHandlers.length && isAsyncIterable(result)) {
|
|
665
|
-
result = errorAsyncIterator(result, err => {
|
|
666
|
-
let error = err;
|
|
667
|
-
for (const handler of subscribeErrorHandlers) {
|
|
668
|
-
handler({
|
|
669
|
-
error,
|
|
670
|
-
setError: err => {
|
|
671
|
-
error = err;
|
|
672
|
-
},
|
|
673
|
-
});
|
|
674
|
-
}
|
|
675
|
-
throw error;
|
|
676
|
-
});
|
|
677
|
-
}
|
|
678
|
-
return result;
|
|
679
|
-
})
|
|
680
|
-
: makeSubscribe(graphql.subscribe);
|
|
681
|
-
const useCustomExecute = beforeCallbacks.execute.length || onResolversHandlers.length;
|
|
682
|
-
const customExecute = useCustomExecute
|
|
683
|
-
? makeExecute(async (args) => {
|
|
684
|
-
let executeFn = graphql.execute;
|
|
685
|
-
let result;
|
|
686
|
-
const afterCalls = [];
|
|
687
|
-
let context = args.contextValue || {};
|
|
688
|
-
for (const onExecute of beforeCallbacks.execute) {
|
|
689
|
-
const after = await onExecute({
|
|
690
|
-
executeFn,
|
|
691
|
-
setExecuteFn: newExecuteFn => {
|
|
692
|
-
executeFn = newExecuteFn;
|
|
693
|
-
},
|
|
694
|
-
setResultAndStopExecution: stopResult => {
|
|
695
|
-
result = stopResult;
|
|
696
|
-
},
|
|
697
|
-
extendContext: extension => {
|
|
698
|
-
if (typeof extension === 'object') {
|
|
699
|
-
context = {
|
|
700
|
-
...(context || {}),
|
|
701
|
-
...extension,
|
|
702
|
-
};
|
|
703
|
-
}
|
|
704
|
-
else {
|
|
705
|
-
throw new Error(`Invalid context extension provided! Expected "object", got: "${JSON.stringify(extension)}" (${typeof extension})`);
|
|
706
|
-
}
|
|
707
|
-
},
|
|
708
|
-
args: args,
|
|
709
|
-
});
|
|
710
|
-
if (after === null || after === void 0 ? void 0 : after.onExecuteDone) {
|
|
711
|
-
afterCalls.push(after.onExecuteDone);
|
|
712
|
-
}
|
|
713
|
-
if (result !== undefined) {
|
|
714
|
-
break;
|
|
715
|
-
}
|
|
716
|
-
}
|
|
717
|
-
if (onResolversHandlers.length) {
|
|
718
|
-
context[resolversHooksSymbol] = onResolversHandlers;
|
|
719
|
-
}
|
|
720
|
-
if (result === undefined) {
|
|
721
|
-
result = (await executeFn({
|
|
722
|
-
...args,
|
|
723
|
-
contextValue: context,
|
|
724
|
-
}));
|
|
725
|
-
}
|
|
726
|
-
const onNextHandler = [];
|
|
727
|
-
const onEndHandler = [];
|
|
728
|
-
for (const afterCb of afterCalls) {
|
|
729
|
-
const hookResult = await afterCb({
|
|
730
|
-
args: args,
|
|
731
|
-
result,
|
|
732
|
-
setResult: newResult => {
|
|
733
|
-
result = newResult;
|
|
734
|
-
},
|
|
735
|
-
});
|
|
736
|
-
if (hookResult) {
|
|
737
|
-
if (hookResult.onNext) {
|
|
738
|
-
onNextHandler.push(hookResult.onNext);
|
|
739
|
-
}
|
|
740
|
-
if (hookResult.onEnd) {
|
|
741
|
-
onEndHandler.push(hookResult.onEnd);
|
|
742
|
-
}
|
|
743
|
-
}
|
|
744
|
-
}
|
|
745
|
-
if (onNextHandler.length && isAsyncIterable(result)) {
|
|
746
|
-
result = mapAsyncIterator(result, async (result) => {
|
|
747
|
-
for (const onNext of onNextHandler) {
|
|
748
|
-
await onNext({
|
|
749
|
-
args: args,
|
|
750
|
-
result,
|
|
751
|
-
setResult: newResult => {
|
|
752
|
-
result = newResult;
|
|
753
|
-
},
|
|
754
|
-
});
|
|
755
|
-
}
|
|
756
|
-
return result;
|
|
757
|
-
});
|
|
758
|
-
}
|
|
759
|
-
if (onEndHandler.length && isAsyncIterable(result)) {
|
|
760
|
-
result = finalAsyncIterator(result, () => {
|
|
761
|
-
for (const onEnd of onEndHandler) {
|
|
762
|
-
onEnd();
|
|
763
|
-
}
|
|
764
|
-
});
|
|
765
|
-
}
|
|
766
|
-
return result;
|
|
767
|
-
})
|
|
768
|
-
: makeExecute(graphql.execute);
|
|
769
|
-
initDone = true;
|
|
770
|
-
// This is done in order to trigger the first schema available, to allow plugins that needs the schema
|
|
771
|
-
// eagerly to have it.
|
|
772
|
-
if (schema) {
|
|
773
|
-
for (const [i, plugin] of plugins.entries()) {
|
|
774
|
-
plugin.onSchemaChange &&
|
|
775
|
-
plugin.onSchemaChange({
|
|
776
|
-
schema,
|
|
777
|
-
replaceSchema: modifiedSchema => replaceSchema(modifiedSchema, i),
|
|
778
|
-
});
|
|
779
|
-
}
|
|
780
|
-
}
|
|
781
|
-
return {
|
|
782
|
-
getCurrentSchema() {
|
|
783
|
-
return schema;
|
|
784
|
-
},
|
|
785
|
-
init,
|
|
786
|
-
parse: customParse,
|
|
787
|
-
validate: customValidate,
|
|
788
|
-
execute: customExecute,
|
|
789
|
-
subscribe: customSubscribe,
|
|
790
|
-
contextFactory: customContextFactory,
|
|
791
|
-
};
|
|
792
|
-
}
|
|
793
|
-
|
|
794
|
-
const getTimestamp = typeof performance !== 'undefined' && performance.now ? () => performance.now() : () => Date.now();
|
|
795
|
-
const measure = () => {
|
|
796
|
-
const start = getTimestamp();
|
|
797
|
-
return () => {
|
|
798
|
-
const end = getTimestamp();
|
|
799
|
-
return end - start;
|
|
800
|
-
};
|
|
801
|
-
};
|
|
802
|
-
const tracingSymbol = Symbol('envelopTracing');
|
|
803
|
-
function traceOrchestrator(orchestrator) {
|
|
804
|
-
const createTracer = (name, ctx) => {
|
|
805
|
-
const end = measure();
|
|
806
|
-
return () => {
|
|
807
|
-
ctx[tracingSymbol][name] = end();
|
|
808
|
-
};
|
|
809
|
-
};
|
|
810
|
-
return {
|
|
811
|
-
...orchestrator,
|
|
812
|
-
init: (ctx = {}) => {
|
|
813
|
-
ctx[tracingSymbol] = ctx[tracingSymbol] || {};
|
|
814
|
-
const done = createTracer('init', ctx || {});
|
|
815
|
-
try {
|
|
816
|
-
return orchestrator.init(ctx);
|
|
817
|
-
}
|
|
818
|
-
finally {
|
|
819
|
-
done();
|
|
820
|
-
}
|
|
821
|
-
},
|
|
822
|
-
parse: (ctx = {}) => {
|
|
823
|
-
ctx[tracingSymbol] = ctx[tracingSymbol] || {};
|
|
824
|
-
const actualFn = orchestrator.parse(ctx);
|
|
825
|
-
return (...args) => {
|
|
826
|
-
const done = createTracer('parse', ctx);
|
|
827
|
-
try {
|
|
828
|
-
return actualFn(...args);
|
|
829
|
-
}
|
|
830
|
-
finally {
|
|
831
|
-
done();
|
|
832
|
-
}
|
|
833
|
-
};
|
|
834
|
-
},
|
|
835
|
-
validate: (ctx = {}) => {
|
|
836
|
-
ctx[tracingSymbol] = ctx[tracingSymbol] || {};
|
|
837
|
-
const actualFn = orchestrator.validate(ctx);
|
|
838
|
-
return (...args) => {
|
|
839
|
-
const done = createTracer('validate', ctx);
|
|
840
|
-
try {
|
|
841
|
-
return actualFn(...args);
|
|
842
|
-
}
|
|
843
|
-
finally {
|
|
844
|
-
done();
|
|
845
|
-
}
|
|
846
|
-
};
|
|
847
|
-
},
|
|
848
|
-
execute: async (argsOrSchema, document, rootValue, contextValue, variableValues, operationName, fieldResolver, typeResolver) => {
|
|
849
|
-
const args = argsOrSchema instanceof graphql.GraphQLSchema
|
|
850
|
-
? {
|
|
851
|
-
schema: argsOrSchema,
|
|
852
|
-
document: document,
|
|
853
|
-
rootValue,
|
|
854
|
-
contextValue,
|
|
855
|
-
variableValues,
|
|
856
|
-
operationName,
|
|
857
|
-
fieldResolver,
|
|
858
|
-
typeResolver,
|
|
859
|
-
}
|
|
860
|
-
: argsOrSchema;
|
|
861
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
862
|
-
// @ts-ignore GraphQL.js types contextValue as unknown
|
|
863
|
-
const done = createTracer('execute', args.contextValue || {});
|
|
864
|
-
try {
|
|
865
|
-
const result = await orchestrator.execute(args);
|
|
866
|
-
done();
|
|
867
|
-
if (!isAsyncIterable(result)) {
|
|
868
|
-
result.extensions = result.extensions || {};
|
|
869
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
870
|
-
// @ts-ignore GraphQL.js types contextValue as unknown
|
|
871
|
-
result.extensions.envelopTracing = args.contextValue[tracingSymbol];
|
|
872
|
-
}
|
|
873
|
-
else {
|
|
874
|
-
// eslint-disable-next-line no-console
|
|
875
|
-
console.warn(`"traceOrchestrator" encountered a AsyncIterator which is not supported yet, so tracing data is not available for the operation.`);
|
|
876
|
-
}
|
|
877
|
-
return result;
|
|
878
|
-
}
|
|
879
|
-
catch (e) {
|
|
880
|
-
done();
|
|
881
|
-
throw e;
|
|
882
|
-
}
|
|
883
|
-
},
|
|
884
|
-
subscribe: async (argsOrSchema, document, rootValue, contextValue, variableValues, operationName, fieldResolver, subscribeFieldResolver) => {
|
|
885
|
-
const args = argsOrSchema instanceof graphql.GraphQLSchema
|
|
886
|
-
? {
|
|
887
|
-
schema: argsOrSchema,
|
|
888
|
-
document: document,
|
|
889
|
-
rootValue,
|
|
890
|
-
contextValue,
|
|
891
|
-
variableValues,
|
|
892
|
-
operationName,
|
|
893
|
-
fieldResolver,
|
|
894
|
-
subscribeFieldResolver,
|
|
895
|
-
}
|
|
896
|
-
: argsOrSchema;
|
|
897
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
898
|
-
// @ts-ignore GraphQL.js types contextValue as unknown
|
|
899
|
-
const done = createTracer('subscribe', args.contextValue || {});
|
|
900
|
-
try {
|
|
901
|
-
return await orchestrator.subscribe(args);
|
|
902
|
-
}
|
|
903
|
-
finally {
|
|
904
|
-
done();
|
|
905
|
-
}
|
|
906
|
-
},
|
|
907
|
-
contextFactory: (ctx = {}) => {
|
|
908
|
-
const actualFn = orchestrator.contextFactory(ctx);
|
|
909
|
-
return async (childCtx) => {
|
|
910
|
-
const done = createTracer('contextFactory', ctx);
|
|
911
|
-
try {
|
|
912
|
-
return await actualFn(childCtx);
|
|
913
|
-
}
|
|
914
|
-
finally {
|
|
915
|
-
done();
|
|
916
|
-
}
|
|
917
|
-
};
|
|
918
|
-
},
|
|
919
|
-
};
|
|
920
|
-
}
|
|
921
|
-
|
|
922
|
-
function envelop(options) {
|
|
923
|
-
const plugins = options.plugins.filter(isPluginEnabled);
|
|
924
|
-
let orchestrator = createEnvelopOrchestrator(plugins);
|
|
925
|
-
if (options.enableInternalTracing) {
|
|
926
|
-
orchestrator = traceOrchestrator(orchestrator);
|
|
927
|
-
}
|
|
928
|
-
const getEnveloped = (initialContext = {}) => {
|
|
929
|
-
const typedOrchestrator = orchestrator;
|
|
930
|
-
typedOrchestrator.init(initialContext);
|
|
931
|
-
return {
|
|
932
|
-
parse: typedOrchestrator.parse(initialContext),
|
|
933
|
-
validate: typedOrchestrator.validate(initialContext),
|
|
934
|
-
contextFactory: typedOrchestrator.contextFactory(initialContext),
|
|
935
|
-
execute: typedOrchestrator.execute,
|
|
936
|
-
subscribe: typedOrchestrator.subscribe,
|
|
937
|
-
schema: typedOrchestrator.getCurrentSchema(),
|
|
938
|
-
};
|
|
939
|
-
};
|
|
940
|
-
getEnveloped._plugins = plugins;
|
|
941
|
-
return getEnveloped;
|
|
942
|
-
}
|
|
943
|
-
|
|
944
|
-
const useEnvelop = (envelop) => {
|
|
945
|
-
return {
|
|
946
|
-
onPluginInit({ addPlugin }) {
|
|
947
|
-
for (const plugin of envelop._plugins) {
|
|
948
|
-
addPlugin(plugin);
|
|
949
|
-
}
|
|
950
|
-
},
|
|
951
|
-
};
|
|
952
|
-
};
|
|
953
|
-
|
|
954
|
-
const DEFAULT_OPTIONS = {
|
|
955
|
-
logFn: console.log,
|
|
956
|
-
};
|
|
957
|
-
const useLogger = (rawOptions = DEFAULT_OPTIONS) => {
|
|
958
|
-
const options = {
|
|
959
|
-
DEFAULT_OPTIONS,
|
|
960
|
-
...rawOptions,
|
|
961
|
-
};
|
|
962
|
-
return {
|
|
963
|
-
onParse({ extendContext, params }) {
|
|
964
|
-
if (options.skipIntrospection && isIntrospectionOperationString(params.source)) {
|
|
965
|
-
extendContext({
|
|
966
|
-
[envelopIsIntrospectionSymbol]: true,
|
|
967
|
-
});
|
|
968
|
-
}
|
|
969
|
-
},
|
|
970
|
-
onExecute({ args }) {
|
|
971
|
-
if (args.contextValue[envelopIsIntrospectionSymbol]) {
|
|
972
|
-
return;
|
|
973
|
-
}
|
|
974
|
-
options.logFn('execute-start', { args });
|
|
975
|
-
return {
|
|
976
|
-
onExecuteDone: ({ result }) => {
|
|
977
|
-
options.logFn('execute-end', { args, result });
|
|
978
|
-
},
|
|
979
|
-
};
|
|
980
|
-
},
|
|
981
|
-
onSubscribe({ args }) {
|
|
982
|
-
if (args.contextValue[envelopIsIntrospectionSymbol]) {
|
|
983
|
-
return;
|
|
984
|
-
}
|
|
985
|
-
options.logFn('subscribe-start', { args });
|
|
986
|
-
return {
|
|
987
|
-
onSubscribeResult: ({ result }) => {
|
|
988
|
-
options.logFn('subscribe-end', { args, result });
|
|
989
|
-
},
|
|
990
|
-
};
|
|
991
|
-
},
|
|
992
|
-
};
|
|
993
|
-
};
|
|
994
|
-
|
|
995
|
-
const HR_TO_NS = 1e9;
|
|
996
|
-
const NS_TO_MS = 1e6;
|
|
997
|
-
const DEFAULT_OPTIONS$1 = {
|
|
998
|
-
onExecutionMeasurement: (args, timing) => console.log(`Operation execution "${args.operationName}" done in ${timing.ms}ms`),
|
|
999
|
-
onSubscriptionMeasurement: (args, timing) => console.log(`Operation subscription "${args.operationName}" done in ${timing.ms}ms`),
|
|
1000
|
-
onParsingMeasurement: (source, timing) => console.log(`Parsing "${source}" done in ${timing.ms}ms`),
|
|
1001
|
-
onValidationMeasurement: (document, timing) => { var _a, _b; return console.log(`Validation "${((_b = (_a = graphql.getOperationAST(document)) === null || _a === void 0 ? void 0 : _a.name) === null || _b === void 0 ? void 0 : _b.value) || '-'}" done in ${timing.ms}ms`); },
|
|
1002
|
-
onResolverMeasurement: (info, timing) => console.log(`\tResolver of "${info.parentType.toString()}.${info.fieldName}" done in ${timing.ms}ms`),
|
|
1003
|
-
onContextBuildingMeasurement: (timing) => console.log(`Context building done in ${timing.ms}ms`),
|
|
1004
|
-
};
|
|
1005
|
-
const deltaFrom = (hrtime) => {
|
|
1006
|
-
const delta = process.hrtime(hrtime);
|
|
1007
|
-
const ns = delta[0] * HR_TO_NS + delta[1];
|
|
1008
|
-
return {
|
|
1009
|
-
ns,
|
|
1010
|
-
get ms() {
|
|
1011
|
-
return ns / NS_TO_MS;
|
|
1012
|
-
},
|
|
1013
|
-
};
|
|
1014
|
-
};
|
|
1015
|
-
const useTiming = (rawOptions) => {
|
|
1016
|
-
const options = {
|
|
1017
|
-
...DEFAULT_OPTIONS$1,
|
|
1018
|
-
...(rawOptions || {}),
|
|
1019
|
-
};
|
|
1020
|
-
const result = {};
|
|
1021
|
-
if (options.onContextBuildingMeasurement) {
|
|
1022
|
-
result.onContextBuilding = ({ context }) => {
|
|
1023
|
-
if (context[envelopIsIntrospectionSymbol]) {
|
|
1024
|
-
return;
|
|
1025
|
-
}
|
|
1026
|
-
const contextStartTime = process.hrtime();
|
|
1027
|
-
return () => {
|
|
1028
|
-
options.onContextBuildingMeasurement(deltaFrom(contextStartTime));
|
|
1029
|
-
};
|
|
1030
|
-
};
|
|
1031
|
-
}
|
|
1032
|
-
if (options.onParsingMeasurement) {
|
|
1033
|
-
result.onParse = ({ params, extendContext }) => {
|
|
1034
|
-
if (options.skipIntrospection && isIntrospectionOperationString(params.source)) {
|
|
1035
|
-
extendContext({
|
|
1036
|
-
[envelopIsIntrospectionSymbol]: true,
|
|
1037
|
-
});
|
|
1038
|
-
return;
|
|
1039
|
-
}
|
|
1040
|
-
const parseStartTime = process.hrtime();
|
|
1041
|
-
return () => {
|
|
1042
|
-
options.onParsingMeasurement(params.source, deltaFrom(parseStartTime));
|
|
1043
|
-
};
|
|
1044
|
-
};
|
|
1045
|
-
}
|
|
1046
|
-
if (options.onValidationMeasurement) {
|
|
1047
|
-
result.onValidate = ({ params, context }) => {
|
|
1048
|
-
if (context[envelopIsIntrospectionSymbol]) {
|
|
1049
|
-
return;
|
|
1050
|
-
}
|
|
1051
|
-
const validateStartTime = process.hrtime();
|
|
1052
|
-
return () => {
|
|
1053
|
-
options.onValidationMeasurement(params.documentAST, deltaFrom(validateStartTime));
|
|
1054
|
-
};
|
|
1055
|
-
};
|
|
1056
|
-
}
|
|
1057
|
-
if (options.onExecutionMeasurement) {
|
|
1058
|
-
if (options.onResolverMeasurement) {
|
|
1059
|
-
result.onExecute = ({ args }) => {
|
|
1060
|
-
if (args.contextValue[envelopIsIntrospectionSymbol]) {
|
|
1061
|
-
return;
|
|
1062
|
-
}
|
|
1063
|
-
const executeStartTime = process.hrtime();
|
|
1064
|
-
return {
|
|
1065
|
-
onExecuteDone: () => {
|
|
1066
|
-
options.onExecutionMeasurement(args, deltaFrom(executeStartTime));
|
|
1067
|
-
},
|
|
1068
|
-
};
|
|
1069
|
-
};
|
|
1070
|
-
result.onResolverCalled = ({ info }) => {
|
|
1071
|
-
const resolverStartTime = process.hrtime();
|
|
1072
|
-
return () => {
|
|
1073
|
-
options.onResolverMeasurement(info, deltaFrom(resolverStartTime));
|
|
1074
|
-
};
|
|
1075
|
-
};
|
|
1076
|
-
}
|
|
1077
|
-
else {
|
|
1078
|
-
result.onExecute = ({ args }) => {
|
|
1079
|
-
if (args.contextValue[envelopIsIntrospectionSymbol]) {
|
|
1080
|
-
return;
|
|
1081
|
-
}
|
|
1082
|
-
const executeStartTime = process.hrtime();
|
|
1083
|
-
return {
|
|
1084
|
-
onExecuteDone: () => {
|
|
1085
|
-
options.onExecutionMeasurement(args, deltaFrom(executeStartTime));
|
|
1086
|
-
},
|
|
1087
|
-
};
|
|
1088
|
-
};
|
|
1089
|
-
}
|
|
1090
|
-
}
|
|
1091
|
-
if (options.onSubscriptionMeasurement) {
|
|
1092
|
-
if (options.onResolverMeasurement) {
|
|
1093
|
-
result.onSubscribe = ({ args }) => {
|
|
1094
|
-
if (args.contextValue[envelopIsIntrospectionSymbol]) {
|
|
1095
|
-
return;
|
|
1096
|
-
}
|
|
1097
|
-
const subscribeStartTime = process.hrtime();
|
|
1098
|
-
return {
|
|
1099
|
-
onSubscribeResult: () => {
|
|
1100
|
-
options.onSubscriptionMeasurement && options.onSubscriptionMeasurement(args, deltaFrom(subscribeStartTime));
|
|
1101
|
-
},
|
|
1102
|
-
};
|
|
1103
|
-
};
|
|
1104
|
-
result.onResolverCalled = ({ info }) => {
|
|
1105
|
-
const resolverStartTime = process.hrtime();
|
|
1106
|
-
return () => {
|
|
1107
|
-
options.onResolverMeasurement && options.onResolverMeasurement(info, deltaFrom(resolverStartTime));
|
|
1108
|
-
};
|
|
1109
|
-
};
|
|
1110
|
-
}
|
|
1111
|
-
else {
|
|
1112
|
-
result.onSubscribe = ({ args }) => {
|
|
1113
|
-
if (args.contextValue[envelopIsIntrospectionSymbol]) {
|
|
1114
|
-
return;
|
|
1115
|
-
}
|
|
1116
|
-
const subscribeStartTime = process.hrtime();
|
|
1117
|
-
return {
|
|
1118
|
-
onSubscribeResult: () => {
|
|
1119
|
-
options.onSubscriptionMeasurement && options.onSubscriptionMeasurement(args, deltaFrom(subscribeStartTime));
|
|
1120
|
-
},
|
|
1121
|
-
};
|
|
1122
|
-
};
|
|
1123
|
-
}
|
|
1124
|
-
}
|
|
1125
|
-
return result;
|
|
1126
|
-
};
|
|
1127
|
-
|
|
1128
|
-
const useSchema = (schema) => {
|
|
1129
|
-
return {
|
|
1130
|
-
onPluginInit({ setSchema }) {
|
|
1131
|
-
setSchema(schema);
|
|
1132
|
-
},
|
|
1133
|
-
};
|
|
1134
|
-
};
|
|
1135
|
-
const useLazyLoadedSchema = (schemaLoader) => {
|
|
1136
|
-
return {
|
|
1137
|
-
onEnveloped({ setSchema, context }) {
|
|
1138
|
-
setSchema(schemaLoader(context));
|
|
1139
|
-
},
|
|
1140
|
-
};
|
|
1141
|
-
};
|
|
1142
|
-
const useAsyncSchema = (schemaPromise) => {
|
|
1143
|
-
return {
|
|
1144
|
-
onPluginInit({ setSchema }) {
|
|
1145
|
-
schemaPromise.then(schemaObj => {
|
|
1146
|
-
setSchema(schemaObj);
|
|
1147
|
-
});
|
|
1148
|
-
},
|
|
1149
|
-
};
|
|
1150
|
-
};
|
|
1151
|
-
|
|
1152
|
-
const makeHandleResult = (errorHandler) => ({ result, args }) => {
|
|
1153
|
-
var _a;
|
|
1154
|
-
if ((_a = result.errors) === null || _a === void 0 ? void 0 : _a.length) {
|
|
1155
|
-
errorHandler(result.errors, args);
|
|
1156
|
-
}
|
|
1157
|
-
};
|
|
1158
|
-
const useErrorHandler = (errorHandler) => ({
|
|
1159
|
-
onExecute() {
|
|
1160
|
-
const handleResult = makeHandleResult(errorHandler);
|
|
1161
|
-
return {
|
|
1162
|
-
onExecuteDone(payload) {
|
|
1163
|
-
return handleStreamOrSingleExecutionResult(payload, handleResult);
|
|
1164
|
-
},
|
|
1165
|
-
};
|
|
1166
|
-
},
|
|
1167
|
-
});
|
|
1168
|
-
|
|
1169
|
-
const useExtendContext = (contextFactory) => ({
|
|
1170
|
-
async onContextBuilding({ context, extendContext }) {
|
|
1171
|
-
extendContext((await contextFactory(context)));
|
|
1172
|
-
},
|
|
1173
|
-
});
|
|
1174
|
-
|
|
1175
|
-
const makeHandleResult$1 = (formatter) => ({ args, result, setResult, }) => {
|
|
1176
|
-
const modified = formatter(result, args);
|
|
1177
|
-
if (modified !== false) {
|
|
1178
|
-
setResult(modified);
|
|
1179
|
-
}
|
|
1180
|
-
};
|
|
1181
|
-
const usePayloadFormatter = (formatter) => ({
|
|
1182
|
-
onExecute() {
|
|
1183
|
-
const handleResult = makeHandleResult$1(formatter);
|
|
1184
|
-
return {
|
|
1185
|
-
onExecuteDone(payload) {
|
|
1186
|
-
return handleStreamOrSingleExecutionResult(payload, handleResult);
|
|
1187
|
-
},
|
|
1188
|
-
};
|
|
1189
|
-
},
|
|
1190
|
-
});
|
|
1191
|
-
|
|
1192
|
-
const DEFAULT_ERROR_MESSAGE = 'Unexpected error.';
|
|
1193
|
-
class EnvelopError extends graphql.GraphQLError {
|
|
1194
|
-
constructor(message, extensions) {
|
|
1195
|
-
super(message, undefined, undefined, undefined, undefined, undefined, extensions);
|
|
1196
|
-
}
|
|
1197
|
-
}
|
|
1198
|
-
const formatError = (err, message, isDev) => {
|
|
1199
|
-
var _a, _b, _c, _d;
|
|
1200
|
-
if (err instanceof graphql.GraphQLError) {
|
|
1201
|
-
if (
|
|
1202
|
-
/** execution error */
|
|
1203
|
-
(err.originalError && err.originalError instanceof EnvelopError === false) ||
|
|
1204
|
-
/** validate and parse errors */
|
|
1205
|
-
(err.originalError === undefined && err instanceof EnvelopError === false)) {
|
|
1206
|
-
return new graphql.GraphQLError(message, err.nodes, err.source, err.positions, err.path, undefined, isDev
|
|
1207
|
-
? {
|
|
1208
|
-
originalError: {
|
|
1209
|
-
message: (_b = (_a = err.originalError) === null || _a === void 0 ? void 0 : _a.message) !== null && _b !== void 0 ? _b : err.message,
|
|
1210
|
-
stack: (_d = (_c = err.originalError) === null || _c === void 0 ? void 0 : _c.stack) !== null && _d !== void 0 ? _d : err.stack,
|
|
1211
|
-
},
|
|
1212
|
-
}
|
|
1213
|
-
: undefined);
|
|
1214
|
-
}
|
|
1215
|
-
return err;
|
|
1216
|
-
}
|
|
1217
|
-
return new graphql.GraphQLError(message);
|
|
1218
|
-
};
|
|
1219
|
-
const makeHandleResult$2 = (format, message, isDev) => ({ result, setResult }) => {
|
|
1220
|
-
if (result.errors != null) {
|
|
1221
|
-
setResult({ ...result, errors: result.errors.map(error => format(error, message, isDev)) });
|
|
1222
|
-
}
|
|
1223
|
-
};
|
|
1224
|
-
const useMaskedErrors = (opts) => {
|
|
1225
|
-
var _a, _b;
|
|
1226
|
-
const format = (_a = opts === null || opts === void 0 ? void 0 : opts.formatError) !== null && _a !== void 0 ? _a : formatError;
|
|
1227
|
-
const message = (opts === null || opts === void 0 ? void 0 : opts.errorMessage) || DEFAULT_ERROR_MESSAGE;
|
|
1228
|
-
// eslint-disable-next-line dot-notation
|
|
1229
|
-
const isDev = (_b = opts === null || opts === void 0 ? void 0 : opts.isDev) !== null && _b !== void 0 ? _b : (typeof process !== 'undefined' ? process.env['NODE_ENV'] === 'development' : false);
|
|
1230
|
-
const handleResult = makeHandleResult$2(format, message, isDev);
|
|
1231
|
-
return {
|
|
1232
|
-
onParse: (opts === null || opts === void 0 ? void 0 : opts.handleParseErrors) === true
|
|
1233
|
-
? function onParse() {
|
|
1234
|
-
return function onParseEnd({ result, replaceParseResult }) {
|
|
1235
|
-
if (result instanceof Error) {
|
|
1236
|
-
replaceParseResult(format(result, message, isDev));
|
|
1237
|
-
}
|
|
1238
|
-
};
|
|
1239
|
-
}
|
|
1240
|
-
: undefined,
|
|
1241
|
-
onValidate: (opts === null || opts === void 0 ? void 0 : opts.handleValidationErrors) === true
|
|
1242
|
-
? function onValidate() {
|
|
1243
|
-
return function onValidateEnd({ valid, result, setResult }) {
|
|
1244
|
-
if (valid === false) {
|
|
1245
|
-
setResult(result.map(error => format(error, message, isDev)));
|
|
1246
|
-
}
|
|
1247
|
-
};
|
|
1248
|
-
}
|
|
1249
|
-
: undefined,
|
|
1250
|
-
onPluginInit(context) {
|
|
1251
|
-
context.registerContextErrorHandler(({ error, setError }) => {
|
|
1252
|
-
setError(formatError(error, message, isDev));
|
|
1253
|
-
});
|
|
1254
|
-
},
|
|
1255
|
-
onExecute() {
|
|
1256
|
-
return {
|
|
1257
|
-
onExecuteDone(payload) {
|
|
1258
|
-
return handleStreamOrSingleExecutionResult(payload, handleResult);
|
|
1259
|
-
},
|
|
1260
|
-
};
|
|
1261
|
-
},
|
|
1262
|
-
onSubscribe() {
|
|
1263
|
-
return {
|
|
1264
|
-
onSubscribeResult(payload) {
|
|
1265
|
-
return handleStreamOrSingleExecutionResult(payload, handleResult);
|
|
1266
|
-
},
|
|
1267
|
-
onSubscribeError({ error, setError }) {
|
|
1268
|
-
setError(formatError(error, message, isDev));
|
|
1269
|
-
},
|
|
1270
|
-
};
|
|
1271
|
-
},
|
|
1272
|
-
};
|
|
1273
|
-
};
|
|
1274
|
-
|
|
1275
|
-
const OnNonIntrospectionFieldReachedValidationRule = (onNonIntrospectionField) => ctx => {
|
|
1276
|
-
const rootQueryType = ctx.getSchema().getQueryType();
|
|
1277
|
-
const rootMutationType = ctx.getSchema().getMutationType();
|
|
1278
|
-
const rootSubscriptionType = ctx.getSchema().getSubscriptionType();
|
|
1279
|
-
return {
|
|
1280
|
-
Field(field) {
|
|
1281
|
-
const parentType = ctx.getParentType();
|
|
1282
|
-
const isQuery = parentType === rootQueryType;
|
|
1283
|
-
const isMutation = parentType === rootMutationType;
|
|
1284
|
-
const isSubscription = parentType === rootSubscriptionType;
|
|
1285
|
-
if ((isQuery && !field.name.value.startsWith('__')) || isMutation || isSubscription) {
|
|
1286
|
-
onNonIntrospectionField();
|
|
1287
|
-
return graphql.BREAK;
|
|
1288
|
-
}
|
|
1289
|
-
return undefined;
|
|
1290
|
-
},
|
|
1291
|
-
};
|
|
1292
|
-
};
|
|
1293
|
-
const fastIntroSpectionSymbol = Symbol('fastIntrospection');
|
|
1294
|
-
/**
|
|
1295
|
-
* In case a GraphQL operation only contains introspection fields the context building can be skipped completely.
|
|
1296
|
-
* With this plugin any further context extensions will be skipped.
|
|
1297
|
-
*/
|
|
1298
|
-
const useImmediateIntrospection = () => {
|
|
1299
|
-
return {
|
|
1300
|
-
onValidate({ addValidationRule }) {
|
|
1301
|
-
let isIntrospectionOnly = true;
|
|
1302
|
-
addValidationRule(OnNonIntrospectionFieldReachedValidationRule(() => {
|
|
1303
|
-
isIntrospectionOnly = false;
|
|
1304
|
-
}));
|
|
1305
|
-
return function afterValidate({ extendContext }) {
|
|
1306
|
-
if (isIntrospectionOnly) {
|
|
1307
|
-
extendContext({ [fastIntroSpectionSymbol]: true });
|
|
1308
|
-
}
|
|
1309
|
-
};
|
|
1310
|
-
},
|
|
1311
|
-
onContextBuilding({ context, breakContextBuilding }) {
|
|
1312
|
-
if (context[fastIntroSpectionSymbol]) {
|
|
1313
|
-
// hijack and skip all other context related stuff.
|
|
1314
|
-
// We dont need a context!
|
|
1315
|
-
breakContextBuilding();
|
|
1316
|
-
}
|
|
1317
|
-
},
|
|
1318
|
-
};
|
|
1319
|
-
};
|
|
1320
|
-
|
|
1321
|
-
Object.keys(types).forEach(function (k) {
|
|
1322
|
-
if (k !== 'default') Object.defineProperty(exports, k, {
|
|
1323
|
-
enumerable: true,
|
|
1324
|
-
get: function () {
|
|
1325
|
-
return types[k];
|
|
1326
|
-
}
|
|
1327
|
-
});
|
|
1328
|
-
});
|
|
1329
|
-
exports.DEFAULT_ERROR_MESSAGE = DEFAULT_ERROR_MESSAGE;
|
|
1330
|
-
exports.EnvelopError = EnvelopError;
|
|
1331
|
-
exports.enableIf = enableIf;
|
|
1332
|
-
exports.envelop = envelop;
|
|
1333
|
-
exports.envelopIsIntrospectionSymbol = envelopIsIntrospectionSymbol;
|
|
1334
|
-
exports.errorAsyncIterator = errorAsyncIterator;
|
|
1335
|
-
exports.finalAsyncIterator = finalAsyncIterator;
|
|
1336
|
-
exports.formatError = formatError;
|
|
1337
|
-
exports.getInMemoryLRUCache = getInMemoryLRUCache;
|
|
1338
|
-
exports.handleStreamOrSingleExecutionResult = handleStreamOrSingleExecutionResult;
|
|
1339
|
-
exports.isAsyncIterable = isAsyncIterable;
|
|
1340
|
-
exports.isIntrospectionDocument = isIntrospectionDocument;
|
|
1341
|
-
exports.isIntrospectionOperation = isIntrospectionOperation;
|
|
1342
|
-
exports.isIntrospectionOperationString = isIntrospectionOperationString;
|
|
1343
|
-
exports.isOperationDefinition = isOperationDefinition;
|
|
1344
|
-
exports.isPluginEnabled = isPluginEnabled;
|
|
1345
|
-
exports.isSourceObject = isSourceObject;
|
|
1346
|
-
exports.makeExecute = makeExecute;
|
|
1347
|
-
exports.makeSubscribe = makeSubscribe;
|
|
1348
|
-
exports.mapAsyncIterator = mapAsyncIterator;
|
|
1349
|
-
exports.useAsyncSchema = useAsyncSchema;
|
|
1350
|
-
exports.useEnvelop = useEnvelop;
|
|
1351
|
-
exports.useErrorHandler = useErrorHandler;
|
|
1352
|
-
exports.useExtendContext = useExtendContext;
|
|
1353
|
-
exports.useImmediateIntrospection = useImmediateIntrospection;
|
|
1354
|
-
exports.useLazyLoadedSchema = useLazyLoadedSchema;
|
|
1355
|
-
exports.useLogger = useLogger;
|
|
1356
|
-
exports.useMaskedErrors = useMaskedErrors;
|
|
1357
|
-
exports.usePayloadFormatter = usePayloadFormatter;
|
|
1358
|
-
exports.useSchema = useSchema;
|
|
1359
|
-
exports.useTiming = useTiming;
|