@envelop/core 2.4.0-alpha-db79afa.0 → 2.4.0-alpha-05dbec7.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.
Files changed (54) hide show
  1. package/cjs/create.js +28 -0
  2. package/cjs/enable-if.js +24 -0
  3. package/cjs/index.js +16 -0
  4. package/cjs/orchestrator.js +451 -0
  5. package/cjs/package.json +1 -0
  6. package/cjs/plugins/use-envelop.js +13 -0
  7. package/cjs/plugins/use-error-handler.js +21 -0
  8. package/cjs/plugins/use-extend-context.js +9 -0
  9. package/cjs/plugins/use-immediate-introspection.js +50 -0
  10. package/cjs/plugins/use-logger.js +45 -0
  11. package/cjs/plugins/use-masked-errors.js +90 -0
  12. package/cjs/plugins/use-payload-formatter.js +21 -0
  13. package/cjs/plugins/use-schema.js +29 -0
  14. package/cjs/plugins/use-timing.js +138 -0
  15. package/cjs/traced-orchestrator.js +134 -0
  16. package/cjs/traced-schema.js +68 -0
  17. package/cjs/utils.js +221 -0
  18. package/esm/create.js +24 -0
  19. package/esm/enable-if.js +19 -0
  20. package/esm/index.js +13 -0
  21. package/esm/orchestrator.js +447 -0
  22. package/esm/plugins/use-envelop.js +9 -0
  23. package/esm/plugins/use-error-handler.js +17 -0
  24. package/esm/plugins/use-extend-context.js +5 -0
  25. package/esm/plugins/use-immediate-introspection.js +46 -0
  26. package/esm/plugins/use-logger.js +41 -0
  27. package/esm/plugins/use-masked-errors.js +84 -0
  28. package/esm/plugins/use-payload-formatter.js +17 -0
  29. package/esm/plugins/use-schema.js +23 -0
  30. package/esm/plugins/use-timing.js +134 -0
  31. package/esm/traced-orchestrator.js +130 -0
  32. package/esm/traced-schema.js +64 -0
  33. package/esm/utils.js +207 -0
  34. package/package.json +33 -12
  35. package/{create.d.ts → typings/create.d.ts} +1 -1
  36. package/{enable-if.d.ts → typings/enable-if.d.ts} +0 -0
  37. package/typings/index.d.ts +13 -0
  38. package/{orchestrator.d.ts → typings/orchestrator.d.ts} +0 -0
  39. package/{plugins → typings/plugins}/use-envelop.d.ts +0 -0
  40. package/{plugins → typings/plugins}/use-error-handler.d.ts +0 -0
  41. package/{plugins → typings/plugins}/use-extend-context.d.ts +0 -0
  42. package/{plugins → typings/plugins}/use-immediate-introspection.d.ts +0 -0
  43. package/{plugins → typings/plugins}/use-logger.d.ts +1 -1
  44. package/{plugins → typings/plugins}/use-masked-errors.d.ts +3 -3
  45. package/{plugins → typings/plugins}/use-payload-formatter.d.ts +0 -0
  46. package/{plugins → typings/plugins}/use-schema.d.ts +0 -0
  47. package/{plugins → typings/plugins}/use-timing.d.ts +2 -2
  48. package/{traced-orchestrator.d.ts → typings/traced-orchestrator.d.ts} +1 -1
  49. package/{traced-schema.d.ts → typings/traced-schema.d.ts} +0 -0
  50. package/{utils.d.ts → typings/utils.d.ts} +0 -13
  51. package/README.md +0 -15
  52. package/index.d.ts +0 -13
  53. package/index.js +0 -1359
  54. package/index.mjs +0 -1317
@@ -0,0 +1,447 @@
1
+ import { execute, parse, specifiedRules, subscribe, validate, } from 'graphql';
2
+ import { prepareTracedSchema, resolversHooksSymbol } from './traced-schema.js';
3
+ import { errorAsyncIterator, finalAsyncIterator, makeExecute, makeSubscribe, mapAsyncIterator, isAsyncIterable, } from './utils.js';
4
+ export function createEnvelopOrchestrator(plugins) {
5
+ let schema = null;
6
+ let initDone = false;
7
+ const onResolversHandlers = [];
8
+ for (const plugin of plugins) {
9
+ if (plugin.onResolverCalled) {
10
+ onResolversHandlers.push(plugin.onResolverCalled);
11
+ }
12
+ }
13
+ // Define the initial method for replacing the GraphQL schema, this is needed in order
14
+ // to allow setting the schema from the onPluginInit callback. We also need to make sure
15
+ // here not to call the same plugin that initiated the schema switch.
16
+ const replaceSchema = (newSchema, ignorePluginIndex = -1) => {
17
+ if (onResolversHandlers.length) {
18
+ prepareTracedSchema(newSchema);
19
+ }
20
+ schema = newSchema;
21
+ if (initDone) {
22
+ for (const [i, plugin] of plugins.entries()) {
23
+ if (i !== ignorePluginIndex) {
24
+ plugin.onSchemaChange &&
25
+ plugin.onSchemaChange({
26
+ schema,
27
+ replaceSchema: schemaToSet => {
28
+ replaceSchema(schemaToSet, i);
29
+ },
30
+ });
31
+ }
32
+ }
33
+ }
34
+ };
35
+ const contextErrorHandlers = [];
36
+ // Iterate all plugins and trigger onPluginInit
37
+ for (const [i, plugin] of plugins.entries()) {
38
+ plugin.onPluginInit &&
39
+ plugin.onPluginInit({
40
+ plugins,
41
+ addPlugin: newPlugin => {
42
+ plugins.push(newPlugin);
43
+ },
44
+ setSchema: modifiedSchema => replaceSchema(modifiedSchema, i),
45
+ registerContextErrorHandler: handler => contextErrorHandlers.push(handler),
46
+ });
47
+ }
48
+ // A set of before callbacks defined here in order to allow it to be used later
49
+ const beforeCallbacks = {
50
+ init: [],
51
+ parse: [],
52
+ validate: [],
53
+ subscribe: [],
54
+ execute: [],
55
+ context: [],
56
+ };
57
+ for (const { onContextBuilding, onExecute, onParse, onSubscribe, onValidate, onEnveloped } of plugins) {
58
+ onEnveloped && beforeCallbacks.init.push(onEnveloped);
59
+ onContextBuilding && beforeCallbacks.context.push(onContextBuilding);
60
+ onExecute && beforeCallbacks.execute.push(onExecute);
61
+ onParse && beforeCallbacks.parse.push(onParse);
62
+ onSubscribe && beforeCallbacks.subscribe.push(onSubscribe);
63
+ onValidate && beforeCallbacks.validate.push(onValidate);
64
+ }
65
+ const init = initialContext => {
66
+ for (const [i, onEnveloped] of beforeCallbacks.init.entries()) {
67
+ onEnveloped({
68
+ context: initialContext,
69
+ extendContext: extension => {
70
+ if (!initialContext) {
71
+ return;
72
+ }
73
+ Object.assign(initialContext, extension);
74
+ },
75
+ setSchema: modifiedSchema => replaceSchema(modifiedSchema, i),
76
+ });
77
+ }
78
+ };
79
+ const customParse = beforeCallbacks.parse.length
80
+ ? initialContext => (source, parseOptions) => {
81
+ let result = null;
82
+ let parseFn = parse;
83
+ const context = initialContext;
84
+ const afterCalls = [];
85
+ for (const onParse of beforeCallbacks.parse) {
86
+ const afterFn = onParse({
87
+ context,
88
+ extendContext: extension => {
89
+ Object.assign(context, extension);
90
+ },
91
+ params: { source, options: parseOptions },
92
+ parseFn,
93
+ setParseFn: newFn => {
94
+ parseFn = newFn;
95
+ },
96
+ setParsedDocument: newDoc => {
97
+ result = newDoc;
98
+ },
99
+ });
100
+ afterFn && afterCalls.push(afterFn);
101
+ }
102
+ if (result === null) {
103
+ try {
104
+ result = parseFn(source, parseOptions);
105
+ }
106
+ catch (e) {
107
+ result = e;
108
+ }
109
+ }
110
+ for (const afterCb of afterCalls) {
111
+ afterCb({
112
+ context,
113
+ extendContext: extension => {
114
+ Object.assign(context, extension);
115
+ },
116
+ replaceParseResult: newResult => {
117
+ result = newResult;
118
+ },
119
+ result,
120
+ });
121
+ }
122
+ if (result === null) {
123
+ throw new Error(`Failed to parse document.`);
124
+ }
125
+ if (result instanceof Error) {
126
+ throw result;
127
+ }
128
+ return result;
129
+ }
130
+ : () => parse;
131
+ const customValidate = beforeCallbacks.validate.length
132
+ ? initialContext => (schema, documentAST, rules, typeInfo, validationOptions) => {
133
+ let actualRules = rules ? [...rules] : undefined;
134
+ let validateFn = validate;
135
+ let result = null;
136
+ const context = initialContext;
137
+ const afterCalls = [];
138
+ for (const onValidate of beforeCallbacks.validate) {
139
+ const afterFn = onValidate({
140
+ context,
141
+ extendContext: extension => {
142
+ Object.assign(context, extension);
143
+ },
144
+ params: {
145
+ schema,
146
+ documentAST,
147
+ rules: actualRules,
148
+ typeInfo,
149
+ options: validationOptions,
150
+ },
151
+ validateFn,
152
+ addValidationRule: rule => {
153
+ if (!actualRules) {
154
+ actualRules = [...specifiedRules];
155
+ }
156
+ actualRules.push(rule);
157
+ },
158
+ setValidationFn: newFn => {
159
+ validateFn = newFn;
160
+ },
161
+ setResult: newResults => {
162
+ result = newResults;
163
+ },
164
+ });
165
+ afterFn && afterCalls.push(afterFn);
166
+ }
167
+ if (!result) {
168
+ result = validateFn(schema, documentAST, actualRules, typeInfo, validationOptions);
169
+ }
170
+ const valid = result.length === 0;
171
+ for (const afterCb of afterCalls) {
172
+ afterCb({
173
+ valid,
174
+ result,
175
+ context,
176
+ extendContext: extension => {
177
+ Object.assign(context, extension);
178
+ },
179
+ setResult: newResult => {
180
+ result = newResult;
181
+ },
182
+ });
183
+ }
184
+ return result;
185
+ }
186
+ : () => validate;
187
+ const customContextFactory = beforeCallbacks.context.length
188
+ ? initialContext => async (orchestratorCtx) => {
189
+ const afterCalls = [];
190
+ // In order to have access to the "last working" context object we keep this outside of the try block:
191
+ let context = orchestratorCtx ? { ...initialContext, ...orchestratorCtx } : initialContext;
192
+ try {
193
+ let isBreakingContextBuilding = false;
194
+ for (const onContext of beforeCallbacks.context) {
195
+ const afterHookResult = await onContext({
196
+ context,
197
+ extendContext: extension => {
198
+ context = { ...context, ...extension };
199
+ },
200
+ breakContextBuilding: () => {
201
+ isBreakingContextBuilding = true;
202
+ },
203
+ });
204
+ if (typeof afterHookResult === 'function') {
205
+ afterCalls.push(afterHookResult);
206
+ }
207
+ if (isBreakingContextBuilding === true) {
208
+ break;
209
+ }
210
+ }
211
+ for (const afterCb of afterCalls) {
212
+ afterCb({
213
+ context,
214
+ extendContext: extension => {
215
+ context = { ...context, ...extension };
216
+ },
217
+ });
218
+ }
219
+ return context;
220
+ }
221
+ catch (err) {
222
+ let error = err;
223
+ for (const errorCb of contextErrorHandlers) {
224
+ errorCb({
225
+ context,
226
+ error,
227
+ setError: err => {
228
+ error = err;
229
+ },
230
+ });
231
+ }
232
+ throw error;
233
+ }
234
+ }
235
+ : initialContext => orchestratorCtx => orchestratorCtx ? { ...initialContext, ...orchestratorCtx } : initialContext;
236
+ const useCustomSubscribe = beforeCallbacks.subscribe.length || onResolversHandlers.length;
237
+ const customSubscribe = useCustomSubscribe
238
+ ? makeSubscribe(async (args) => {
239
+ let subscribeFn = subscribe;
240
+ const afterCalls = [];
241
+ const subscribeErrorHandlers = [];
242
+ let context = args.contextValue || {};
243
+ let result;
244
+ for (const onSubscribe of beforeCallbacks.subscribe) {
245
+ const after = await onSubscribe({
246
+ subscribeFn,
247
+ setSubscribeFn: newSubscribeFn => {
248
+ subscribeFn = newSubscribeFn;
249
+ },
250
+ extendContext: extension => {
251
+ context = { ...context, ...extension };
252
+ },
253
+ args: args,
254
+ setResultAndStopExecution: stopResult => {
255
+ result = stopResult;
256
+ },
257
+ });
258
+ if (after) {
259
+ if (after.onSubscribeResult) {
260
+ afterCalls.push(after.onSubscribeResult);
261
+ }
262
+ if (after.onSubscribeError) {
263
+ subscribeErrorHandlers.push(after.onSubscribeError);
264
+ }
265
+ }
266
+ if (result !== undefined) {
267
+ break;
268
+ }
269
+ }
270
+ if (onResolversHandlers.length) {
271
+ context[resolversHooksSymbol] = onResolversHandlers;
272
+ }
273
+ if (result === undefined) {
274
+ result = await subscribeFn({
275
+ ...args,
276
+ contextValue: context,
277
+ // Casted for GraphQL.js 15 compatibility
278
+ // Can be removed once we drop support for GraphQL.js 15
279
+ });
280
+ }
281
+ const onNextHandler = [];
282
+ const onEndHandler = [];
283
+ for (const afterCb of afterCalls) {
284
+ const hookResult = afterCb({
285
+ args: args,
286
+ result,
287
+ setResult: newResult => {
288
+ result = newResult;
289
+ },
290
+ });
291
+ if (hookResult) {
292
+ if (hookResult.onNext) {
293
+ onNextHandler.push(hookResult.onNext);
294
+ }
295
+ if (hookResult.onEnd) {
296
+ onEndHandler.push(hookResult.onEnd);
297
+ }
298
+ }
299
+ }
300
+ if (onNextHandler.length && isAsyncIterable(result)) {
301
+ result = mapAsyncIterator(result, async (result) => {
302
+ for (const onNext of onNextHandler) {
303
+ await onNext({
304
+ args: args,
305
+ result,
306
+ setResult: newResult => (result = newResult),
307
+ });
308
+ }
309
+ return result;
310
+ });
311
+ }
312
+ if (onEndHandler.length && isAsyncIterable(result)) {
313
+ result = finalAsyncIterator(result, () => {
314
+ for (const onEnd of onEndHandler) {
315
+ onEnd();
316
+ }
317
+ });
318
+ }
319
+ if (subscribeErrorHandlers.length && isAsyncIterable(result)) {
320
+ result = errorAsyncIterator(result, err => {
321
+ let error = err;
322
+ for (const handler of subscribeErrorHandlers) {
323
+ handler({
324
+ error,
325
+ setError: err => {
326
+ error = err;
327
+ },
328
+ });
329
+ }
330
+ throw error;
331
+ });
332
+ }
333
+ return result;
334
+ })
335
+ : makeSubscribe(subscribe);
336
+ const useCustomExecute = beforeCallbacks.execute.length || onResolversHandlers.length;
337
+ const customExecute = useCustomExecute
338
+ ? makeExecute(async (args) => {
339
+ let executeFn = execute;
340
+ let result;
341
+ const afterCalls = [];
342
+ let context = args.contextValue || {};
343
+ for (const onExecute of beforeCallbacks.execute) {
344
+ const after = await onExecute({
345
+ executeFn,
346
+ setExecuteFn: newExecuteFn => {
347
+ executeFn = newExecuteFn;
348
+ },
349
+ setResultAndStopExecution: stopResult => {
350
+ result = stopResult;
351
+ },
352
+ extendContext: extension => {
353
+ if (typeof extension === 'object') {
354
+ context = {
355
+ ...(context || {}),
356
+ ...extension,
357
+ };
358
+ }
359
+ else {
360
+ throw new Error(`Invalid context extension provided! Expected "object", got: "${JSON.stringify(extension)}" (${typeof extension})`);
361
+ }
362
+ },
363
+ args: args,
364
+ });
365
+ if (after === null || after === void 0 ? void 0 : after.onExecuteDone) {
366
+ afterCalls.push(after.onExecuteDone);
367
+ }
368
+ if (result !== undefined) {
369
+ break;
370
+ }
371
+ }
372
+ if (onResolversHandlers.length) {
373
+ context[resolversHooksSymbol] = onResolversHandlers;
374
+ }
375
+ if (result === undefined) {
376
+ result = (await executeFn({
377
+ ...args,
378
+ contextValue: context,
379
+ }));
380
+ }
381
+ const onNextHandler = [];
382
+ const onEndHandler = [];
383
+ for (const afterCb of afterCalls) {
384
+ const hookResult = await afterCb({
385
+ args: args,
386
+ result,
387
+ setResult: newResult => {
388
+ result = newResult;
389
+ },
390
+ });
391
+ if (hookResult) {
392
+ if (hookResult.onNext) {
393
+ onNextHandler.push(hookResult.onNext);
394
+ }
395
+ if (hookResult.onEnd) {
396
+ onEndHandler.push(hookResult.onEnd);
397
+ }
398
+ }
399
+ }
400
+ if (onNextHandler.length && isAsyncIterable(result)) {
401
+ result = mapAsyncIterator(result, async (result) => {
402
+ for (const onNext of onNextHandler) {
403
+ await onNext({
404
+ args: args,
405
+ result,
406
+ setResult: newResult => {
407
+ result = newResult;
408
+ },
409
+ });
410
+ }
411
+ return result;
412
+ });
413
+ }
414
+ if (onEndHandler.length && isAsyncIterable(result)) {
415
+ result = finalAsyncIterator(result, () => {
416
+ for (const onEnd of onEndHandler) {
417
+ onEnd();
418
+ }
419
+ });
420
+ }
421
+ return result;
422
+ })
423
+ : makeExecute(execute);
424
+ initDone = true;
425
+ // This is done in order to trigger the first schema available, to allow plugins that needs the schema
426
+ // eagerly to have it.
427
+ if (schema) {
428
+ for (const [i, plugin] of plugins.entries()) {
429
+ plugin.onSchemaChange &&
430
+ plugin.onSchemaChange({
431
+ schema,
432
+ replaceSchema: modifiedSchema => replaceSchema(modifiedSchema, i),
433
+ });
434
+ }
435
+ }
436
+ return {
437
+ getCurrentSchema() {
438
+ return schema;
439
+ },
440
+ init,
441
+ parse: customParse,
442
+ validate: customValidate,
443
+ execute: customExecute,
444
+ subscribe: customSubscribe,
445
+ contextFactory: customContextFactory,
446
+ };
447
+ }
@@ -0,0 +1,9 @@
1
+ export const useEnvelop = (envelop) => {
2
+ return {
3
+ onPluginInit({ addPlugin }) {
4
+ for (const plugin of envelop._plugins) {
5
+ addPlugin(plugin);
6
+ }
7
+ },
8
+ };
9
+ };
@@ -0,0 +1,17 @@
1
+ import { handleStreamOrSingleExecutionResult } from '../utils.js';
2
+ const makeHandleResult = (errorHandler) => ({ result, args }) => {
3
+ var _a;
4
+ if ((_a = result.errors) === null || _a === void 0 ? void 0 : _a.length) {
5
+ errorHandler(result.errors, args);
6
+ }
7
+ };
8
+ export const useErrorHandler = (errorHandler) => ({
9
+ onExecute() {
10
+ const handleResult = makeHandleResult(errorHandler);
11
+ return {
12
+ onExecuteDone(payload) {
13
+ return handleStreamOrSingleExecutionResult(payload, handleResult);
14
+ },
15
+ };
16
+ },
17
+ });
@@ -0,0 +1,5 @@
1
+ export const useExtendContext = (contextFactory) => ({
2
+ async onContextBuilding({ context, extendContext }) {
3
+ extendContext((await contextFactory(context)));
4
+ },
5
+ });
@@ -0,0 +1,46 @@
1
+ import { BREAK } from 'graphql';
2
+ const OnNonIntrospectionFieldReachedValidationRule = (onNonIntrospectionField) => ctx => {
3
+ const rootQueryType = ctx.getSchema().getQueryType();
4
+ const rootMutationType = ctx.getSchema().getMutationType();
5
+ const rootSubscriptionType = ctx.getSchema().getSubscriptionType();
6
+ return {
7
+ Field(field) {
8
+ const parentType = ctx.getParentType();
9
+ const isQuery = parentType === rootQueryType;
10
+ const isMutation = parentType === rootMutationType;
11
+ const isSubscription = parentType === rootSubscriptionType;
12
+ if ((isQuery && !field.name.value.startsWith('__')) || isMutation || isSubscription) {
13
+ onNonIntrospectionField();
14
+ return BREAK;
15
+ }
16
+ return undefined;
17
+ },
18
+ };
19
+ };
20
+ const fastIntroSpectionSymbol = Symbol('fastIntrospection');
21
+ /**
22
+ * In case a GraphQL operation only contains introspection fields the context building can be skipped completely.
23
+ * With this plugin any further context extensions will be skipped.
24
+ */
25
+ export const useImmediateIntrospection = () => {
26
+ return {
27
+ onValidate({ addValidationRule }) {
28
+ let isIntrospectionOnly = true;
29
+ addValidationRule(OnNonIntrospectionFieldReachedValidationRule(() => {
30
+ isIntrospectionOnly = false;
31
+ }));
32
+ return function afterValidate({ extendContext }) {
33
+ if (isIntrospectionOnly) {
34
+ extendContext({ [fastIntroSpectionSymbol]: true });
35
+ }
36
+ };
37
+ },
38
+ onContextBuilding({ context, breakContextBuilding }) {
39
+ if (context[fastIntroSpectionSymbol]) {
40
+ // hijack and skip all other context related stuff.
41
+ // We dont need a context!
42
+ breakContextBuilding();
43
+ }
44
+ },
45
+ };
46
+ };
@@ -0,0 +1,41 @@
1
+ import { envelopIsIntrospectionSymbol, isIntrospectionOperationString } from '../utils.js';
2
+ const DEFAULT_OPTIONS = {
3
+ logFn: console.log,
4
+ };
5
+ export const useLogger = (rawOptions = DEFAULT_OPTIONS) => {
6
+ const options = {
7
+ DEFAULT_OPTIONS,
8
+ ...rawOptions,
9
+ };
10
+ return {
11
+ onParse({ extendContext, params }) {
12
+ if (options.skipIntrospection && isIntrospectionOperationString(params.source)) {
13
+ extendContext({
14
+ [envelopIsIntrospectionSymbol]: true,
15
+ });
16
+ }
17
+ },
18
+ onExecute({ args }) {
19
+ if (args.contextValue[envelopIsIntrospectionSymbol]) {
20
+ return;
21
+ }
22
+ options.logFn('execute-start', { args });
23
+ return {
24
+ onExecuteDone: ({ result }) => {
25
+ options.logFn('execute-end', { args, result });
26
+ },
27
+ };
28
+ },
29
+ onSubscribe({ args }) {
30
+ if (args.contextValue[envelopIsIntrospectionSymbol]) {
31
+ return;
32
+ }
33
+ options.logFn('subscribe-start', { args });
34
+ return {
35
+ onSubscribeResult: ({ result }) => {
36
+ options.logFn('subscribe-end', { args, result });
37
+ },
38
+ };
39
+ },
40
+ };
41
+ };
@@ -0,0 +1,84 @@
1
+ import { GraphQLError } from 'graphql';
2
+ import { handleStreamOrSingleExecutionResult } from '../utils.js';
3
+ export const DEFAULT_ERROR_MESSAGE = 'Unexpected error.';
4
+ export class EnvelopError extends GraphQLError {
5
+ constructor(message, extensions) {
6
+ super(message, undefined, undefined, undefined, undefined, undefined, extensions);
7
+ }
8
+ }
9
+ export const formatError = (err, message, isDev) => {
10
+ var _a, _b, _c, _d;
11
+ if (err instanceof GraphQLError) {
12
+ if (
13
+ /** execution error */
14
+ (err.originalError && err.originalError instanceof EnvelopError === false) ||
15
+ /** validate and parse errors */
16
+ (err.originalError === undefined && err instanceof EnvelopError === false)) {
17
+ return new GraphQLError(message, err.nodes, err.source, err.positions, err.path, undefined, isDev
18
+ ? {
19
+ originalError: {
20
+ message: (_b = (_a = err.originalError) === null || _a === void 0 ? void 0 : _a.message) !== null && _b !== void 0 ? _b : err.message,
21
+ stack: (_d = (_c = err.originalError) === null || _c === void 0 ? void 0 : _c.stack) !== null && _d !== void 0 ? _d : err.stack,
22
+ },
23
+ }
24
+ : undefined);
25
+ }
26
+ return err;
27
+ }
28
+ return new GraphQLError(message);
29
+ };
30
+ const makeHandleResult = (format, message, isDev) => ({ result, setResult }) => {
31
+ if (result.errors != null) {
32
+ setResult({ ...result, errors: result.errors.map(error => format(error, message, isDev)) });
33
+ }
34
+ };
35
+ export const useMaskedErrors = (opts) => {
36
+ var _a, _b;
37
+ const format = (_a = opts === null || opts === void 0 ? void 0 : opts.formatError) !== null && _a !== void 0 ? _a : formatError;
38
+ const message = (opts === null || opts === void 0 ? void 0 : opts.errorMessage) || DEFAULT_ERROR_MESSAGE;
39
+ // eslint-disable-next-line dot-notation
40
+ 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);
41
+ const handleResult = makeHandleResult(format, message, isDev);
42
+ return {
43
+ onParse: (opts === null || opts === void 0 ? void 0 : opts.handleParseErrors) === true
44
+ ? function onParse() {
45
+ return function onParseEnd({ result, replaceParseResult }) {
46
+ if (result instanceof Error) {
47
+ replaceParseResult(format(result, message, isDev));
48
+ }
49
+ };
50
+ }
51
+ : undefined,
52
+ onValidate: (opts === null || opts === void 0 ? void 0 : opts.handleValidationErrors) === true
53
+ ? function onValidate() {
54
+ return function onValidateEnd({ valid, result, setResult }) {
55
+ if (valid === false) {
56
+ setResult(result.map(error => format(error, message, isDev)));
57
+ }
58
+ };
59
+ }
60
+ : undefined,
61
+ onPluginInit(context) {
62
+ context.registerContextErrorHandler(({ error, setError }) => {
63
+ setError(formatError(error, message, isDev));
64
+ });
65
+ },
66
+ onExecute() {
67
+ return {
68
+ onExecuteDone(payload) {
69
+ return handleStreamOrSingleExecutionResult(payload, handleResult);
70
+ },
71
+ };
72
+ },
73
+ onSubscribe() {
74
+ return {
75
+ onSubscribeResult(payload) {
76
+ return handleStreamOrSingleExecutionResult(payload, handleResult);
77
+ },
78
+ onSubscribeError({ error, setError }) {
79
+ setError(formatError(error, message, isDev));
80
+ },
81
+ };
82
+ },
83
+ };
84
+ };
@@ -0,0 +1,17 @@
1
+ import { handleStreamOrSingleExecutionResult } from '../utils.js';
2
+ const makeHandleResult = (formatter) => ({ args, result, setResult, }) => {
3
+ const modified = formatter(result, args);
4
+ if (modified !== false) {
5
+ setResult(modified);
6
+ }
7
+ };
8
+ export const usePayloadFormatter = (formatter) => ({
9
+ onExecute() {
10
+ const handleResult = makeHandleResult(formatter);
11
+ return {
12
+ onExecuteDone(payload) {
13
+ return handleStreamOrSingleExecutionResult(payload, handleResult);
14
+ },
15
+ };
16
+ },
17
+ });