@envelop/core 2.5.1-alpha-20220824165935-4720f031 → 2.6.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 (45) hide show
  1. package/cjs/create.js +5 -7
  2. package/cjs/index.js +3 -3
  3. package/cjs/orchestrator.js +16 -24
  4. package/cjs/plugins/use-immediate-introspection.js +50 -0
  5. package/cjs/plugins/use-masked-errors.js +93 -0
  6. package/cjs/plugins/use-timing.js +138 -0
  7. package/cjs/traced-orchestrator.js +136 -0
  8. package/cjs/traced-schema.js +68 -0
  9. package/cjs/utils.js +26 -1
  10. package/esm/create.js +5 -7
  11. package/esm/index.js +3 -1
  12. package/esm/orchestrator.js +5 -13
  13. package/esm/plugins/use-immediate-introspection.js +46 -0
  14. package/esm/plugins/use-masked-errors.js +87 -0
  15. package/esm/plugins/use-timing.js +134 -0
  16. package/esm/traced-orchestrator.js +132 -0
  17. package/esm/traced-schema.js +64 -0
  18. package/esm/utils.js +22 -0
  19. package/package.json +6 -2
  20. package/typings/create.d.cts +1 -5
  21. package/typings/create.d.ts +1 -5
  22. package/typings/enable-if.d.cts +1 -1
  23. package/typings/enable-if.d.ts +1 -1
  24. package/typings/index.d.cts +3 -1
  25. package/typings/index.d.ts +3 -1
  26. package/typings/orchestrator.d.cts +4 -12
  27. package/typings/orchestrator.d.ts +4 -12
  28. package/typings/plugins/use-error-handler.d.cts +3 -2
  29. package/typings/plugins/use-error-handler.d.ts +3 -2
  30. package/typings/plugins/use-immediate-introspection.d.cts +6 -0
  31. package/typings/plugins/use-immediate-introspection.d.ts +6 -0
  32. package/typings/plugins/use-masked-errors.d.cts +39 -0
  33. package/typings/plugins/use-masked-errors.d.ts +39 -0
  34. package/typings/plugins/use-payload-formatter.d.cts +2 -1
  35. package/typings/plugins/use-payload-formatter.d.ts +2 -1
  36. package/typings/plugins/use-schema.d.cts +4 -3
  37. package/typings/plugins/use-schema.d.ts +4 -3
  38. package/typings/plugins/use-timing.d.cts +21 -0
  39. package/typings/plugins/use-timing.d.ts +21 -0
  40. package/typings/traced-orchestrator.d.cts +7 -0
  41. package/typings/traced-orchestrator.d.ts +7 -0
  42. package/typings/traced-schema.d.cts +4 -0
  43. package/typings/traced-schema.d.ts +4 -0
  44. package/typings/utils.d.cts +8 -4
  45. package/typings/utils.d.ts +8 -4
package/cjs/create.js CHANGED
@@ -3,15 +3,13 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.envelop = void 0;
4
4
  const enable_if_js_1 = require("./enable-if.js");
5
5
  const orchestrator_js_1 = require("./orchestrator.js");
6
+ const traced_orchestrator_js_1 = require("./traced-orchestrator.js");
6
7
  function envelop(options) {
7
8
  const plugins = options.plugins.filter(enable_if_js_1.isPluginEnabled);
8
- const orchestrator = (0, orchestrator_js_1.createEnvelopOrchestrator)({
9
- plugins,
10
- parse: options.parse,
11
- execute: options.execute,
12
- validate: options.validate,
13
- subscribe: options.subscribe,
14
- });
9
+ let orchestrator = (0, orchestrator_js_1.createEnvelopOrchestrator)(plugins);
10
+ if (options.enableInternalTracing) {
11
+ orchestrator = (0, traced_orchestrator_js_1.traceOrchestrator)(orchestrator);
12
+ }
15
13
  const getEnveloped = (initialContext = {}) => {
16
14
  const typedOrchestrator = orchestrator;
17
15
  typedOrchestrator.init(initialContext);
package/cjs/index.js CHANGED
@@ -1,16 +1,16 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.resolversHooksSymbol = void 0;
4
3
  const tslib_1 = require("tslib");
5
4
  tslib_1.__exportStar(require("@envelop/types"), exports);
6
5
  tslib_1.__exportStar(require("./create.js"), exports);
7
6
  tslib_1.__exportStar(require("./utils.js"), exports);
8
7
  tslib_1.__exportStar(require("./plugins/use-envelop.js"), exports);
9
8
  tslib_1.__exportStar(require("./plugins/use-logger.js"), exports);
9
+ tslib_1.__exportStar(require("./plugins/use-timing.js"), exports);
10
10
  tslib_1.__exportStar(require("./plugins/use-schema.js"), exports);
11
11
  tslib_1.__exportStar(require("./plugins/use-error-handler.js"), exports);
12
12
  tslib_1.__exportStar(require("./plugins/use-extend-context.js"), exports);
13
13
  tslib_1.__exportStar(require("./plugins/use-payload-formatter.js"), exports);
14
+ tslib_1.__exportStar(require("./plugins/use-masked-errors.js"), exports);
15
+ tslib_1.__exportStar(require("./plugins/use-immediate-introspection.js"), exports);
14
16
  tslib_1.__exportStar(require("./enable-if.js"), exports);
15
- var orchestrator_js_1 = require("./orchestrator.js");
16
- Object.defineProperty(exports, "resolversHooksSymbol", { enumerable: true, get: function () { return orchestrator_js_1.resolversHooksSymbol; } });
@@ -1,9 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.createEnvelopOrchestrator = exports.resolversHooksSymbol = void 0;
3
+ exports.createEnvelopOrchestrator = void 0;
4
+ const graphql_1 = require("graphql");
5
+ const traced_schema_js_1 = require("./traced-schema.js");
4
6
  const utils_js_1 = require("./utils.js");
5
- exports.resolversHooksSymbol = Symbol('RESOLVERS_HOOKS');
6
- function createEnvelopOrchestrator({ plugins, parse, execute, subscribe, validate, }) {
7
+ function createEnvelopOrchestrator(plugins) {
7
8
  let schema = null;
8
9
  let initDone = false;
9
10
  const onResolversHandlers = [];
@@ -17,7 +18,7 @@ function createEnvelopOrchestrator({ plugins, parse, execute, subscribe, validat
17
18
  // here not to call the same plugin that initiated the schema switch.
18
19
  const replaceSchema = (newSchema, ignorePluginIndex = -1) => {
19
20
  if (onResolversHandlers.length) {
20
- // prepareTracedSchema(newSchema);
21
+ (0, traced_schema_js_1.prepareTracedSchema)(newSchema);
21
22
  }
22
23
  schema = newSchema;
23
24
  if (initDone) {
@@ -81,7 +82,7 @@ function createEnvelopOrchestrator({ plugins, parse, execute, subscribe, validat
81
82
  const customParse = beforeCallbacks.parse.length
82
83
  ? initialContext => (source, parseOptions) => {
83
84
  let result = null;
84
- let parseFn = parse;
85
+ let parseFn = graphql_1.parse;
85
86
  const context = initialContext;
86
87
  const afterCalls = [];
87
88
  for (const onParse of beforeCallbacks.parse) {
@@ -129,11 +130,11 @@ function createEnvelopOrchestrator({ plugins, parse, execute, subscribe, validat
129
130
  }
130
131
  return result;
131
132
  }
132
- : () => parse;
133
+ : () => graphql_1.parse;
133
134
  const customValidate = beforeCallbacks.validate.length
134
135
  ? initialContext => (schema, documentAST, rules, typeInfo, validationOptions) => {
135
136
  let actualRules = rules ? [...rules] : undefined;
136
- let validateFn = validate;
137
+ let validateFn = graphql_1.validate;
137
138
  let result = null;
138
139
  const context = initialContext;
139
140
  const afterCalls = [];
@@ -153,10 +154,7 @@ function createEnvelopOrchestrator({ plugins, parse, execute, subscribe, validat
153
154
  validateFn,
154
155
  addValidationRule: rule => {
155
156
  if (!actualRules) {
156
- // Ideally we should provide default validation rules here.
157
- // eslint-disable-next-line no-console
158
- console.warn('No default validation rules provided.');
159
- actualRules = [];
157
+ actualRules = [...graphql_1.specifiedRules];
160
158
  }
161
159
  actualRules.push(rule);
162
160
  },
@@ -172,9 +170,6 @@ function createEnvelopOrchestrator({ plugins, parse, execute, subscribe, validat
172
170
  if (!result) {
173
171
  result = validateFn(schema, documentAST, actualRules, typeInfo, validationOptions);
174
172
  }
175
- if (!result) {
176
- return;
177
- }
178
173
  const valid = result.length === 0;
179
174
  for (const afterCb of afterCalls) {
180
175
  afterCb({
@@ -191,7 +186,7 @@ function createEnvelopOrchestrator({ plugins, parse, execute, subscribe, validat
191
186
  }
192
187
  return result;
193
188
  }
194
- : () => validate;
189
+ : () => graphql_1.validate;
195
190
  const customContextFactory = beforeCallbacks.context
196
191
  .length
197
192
  ? initialContext => async (orchestratorCtx) => {
@@ -245,7 +240,7 @@ function createEnvelopOrchestrator({ plugins, parse, execute, subscribe, validat
245
240
  const useCustomSubscribe = beforeCallbacks.subscribe.length || onResolversHandlers.length;
246
241
  const customSubscribe = useCustomSubscribe
247
242
  ? (0, utils_js_1.makeSubscribe)(async (args) => {
248
- let subscribeFn = subscribe;
243
+ let subscribeFn = graphql_1.subscribe;
249
244
  const afterCalls = [];
250
245
  const subscribeErrorHandlers = [];
251
246
  let context = args.contextValue || {};
@@ -277,7 +272,7 @@ function createEnvelopOrchestrator({ plugins, parse, execute, subscribe, validat
277
272
  }
278
273
  }
279
274
  if (onResolversHandlers.length) {
280
- context[exports.resolversHooksSymbol] = onResolversHandlers;
275
+ context[traced_schema_js_1.resolversHooksSymbol] = onResolversHandlers;
281
276
  }
282
277
  if (result === undefined) {
283
278
  result = await subscribeFn({
@@ -287,9 +282,6 @@ function createEnvelopOrchestrator({ plugins, parse, execute, subscribe, validat
287
282
  // Can be removed once we drop support for GraphQL.js 15
288
283
  });
289
284
  }
290
- if (!result) {
291
- return;
292
- }
293
285
  const onNextHandler = [];
294
286
  const onEndHandler = [];
295
287
  for (const afterCb of afterCalls) {
@@ -344,11 +336,11 @@ function createEnvelopOrchestrator({ plugins, parse, execute, subscribe, validat
344
336
  }
345
337
  return result;
346
338
  })
347
- : (0, utils_js_1.makeSubscribe)(subscribe);
339
+ : (0, utils_js_1.makeSubscribe)(graphql_1.subscribe);
348
340
  const useCustomExecute = beforeCallbacks.execute.length || onResolversHandlers.length;
349
341
  const customExecute = useCustomExecute
350
342
  ? (0, utils_js_1.makeExecute)(async (args) => {
351
- let executeFn = execute;
343
+ let executeFn = graphql_1.execute;
352
344
  let result;
353
345
  const afterCalls = [];
354
346
  let context = args.contextValue || {};
@@ -382,7 +374,7 @@ function createEnvelopOrchestrator({ plugins, parse, execute, subscribe, validat
382
374
  }
383
375
  }
384
376
  if (onResolversHandlers.length) {
385
- context[exports.resolversHooksSymbol] = onResolversHandlers;
377
+ context[traced_schema_js_1.resolversHooksSymbol] = onResolversHandlers;
386
378
  }
387
379
  if (result === undefined) {
388
380
  result = (await executeFn({
@@ -432,7 +424,7 @@ function createEnvelopOrchestrator({ plugins, parse, execute, subscribe, validat
432
424
  }
433
425
  return result;
434
426
  })
435
- : (0, utils_js_1.makeExecute)(execute);
427
+ : (0, utils_js_1.makeExecute)(graphql_1.execute);
436
428
  initDone = true;
437
429
  // This is done in order to trigger the first schema available, to allow plugins that needs the schema
438
430
  // eagerly to have it.
@@ -0,0 +1,50 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useImmediateIntrospection = void 0;
4
+ const graphql_1 = require("graphql");
5
+ const OnNonIntrospectionFieldReachedValidationRule = (onNonIntrospectionField) => ctx => {
6
+ const rootQueryType = ctx.getSchema().getQueryType();
7
+ const rootMutationType = ctx.getSchema().getMutationType();
8
+ const rootSubscriptionType = ctx.getSchema().getSubscriptionType();
9
+ return {
10
+ Field(field) {
11
+ const parentType = ctx.getParentType();
12
+ const isQuery = parentType === rootQueryType;
13
+ const isMutation = parentType === rootMutationType;
14
+ const isSubscription = parentType === rootSubscriptionType;
15
+ if ((isQuery && !field.name.value.startsWith('__')) || isMutation || isSubscription) {
16
+ onNonIntrospectionField();
17
+ return graphql_1.BREAK;
18
+ }
19
+ return undefined;
20
+ },
21
+ };
22
+ };
23
+ const fastIntroSpectionSymbol = Symbol('fastIntrospection');
24
+ /**
25
+ * In case a GraphQL operation only contains introspection fields the context building can be skipped completely.
26
+ * With this plugin any further context extensions will be skipped.
27
+ */
28
+ const useImmediateIntrospection = () => {
29
+ return {
30
+ onValidate({ addValidationRule }) {
31
+ let isIntrospectionOnly = true;
32
+ addValidationRule(OnNonIntrospectionFieldReachedValidationRule(() => {
33
+ isIntrospectionOnly = false;
34
+ }));
35
+ return function afterValidate({ extendContext }) {
36
+ if (isIntrospectionOnly) {
37
+ extendContext({ [fastIntroSpectionSymbol]: true });
38
+ }
39
+ };
40
+ },
41
+ onContextBuilding({ context, breakContextBuilding }) {
42
+ if (context[fastIntroSpectionSymbol]) {
43
+ // hijack and skip all other context related stuff.
44
+ // We dont need a context!
45
+ breakContextBuilding();
46
+ }
47
+ },
48
+ };
49
+ };
50
+ exports.useImmediateIntrospection = useImmediateIntrospection;
@@ -0,0 +1,93 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useMaskedErrors = exports.formatError = exports.EnvelopError = exports.DEFAULT_ERROR_MESSAGE = void 0;
4
+ const graphql_1 = require("graphql");
5
+ const utils_js_1 = require("../utils.js");
6
+ exports.DEFAULT_ERROR_MESSAGE = 'Unexpected error.';
7
+ class EnvelopError extends graphql_1.GraphQLError {
8
+ constructor(message, extensions) {
9
+ super(message, undefined, undefined, undefined, undefined, undefined, extensions);
10
+ }
11
+ }
12
+ exports.EnvelopError = EnvelopError;
13
+ const formatError = (err, message, isDev) => {
14
+ var _a, _b, _c, _d;
15
+ if (err instanceof graphql_1.GraphQLError) {
16
+ if (
17
+ /** execution error */
18
+ (err.originalError && err.originalError instanceof EnvelopError === false) ||
19
+ /** validate and parse errors */
20
+ (err.originalError === undefined && err instanceof EnvelopError === false)) {
21
+ return new graphql_1.GraphQLError(message, err.nodes, err.source, err.positions, err.path, undefined, isDev
22
+ ? {
23
+ originalError: {
24
+ message: (_b = (_a = err.originalError) === null || _a === void 0 ? void 0 : _a.message) !== null && _b !== void 0 ? _b : err.message,
25
+ stack: (_d = (_c = err.originalError) === null || _c === void 0 ? void 0 : _c.stack) !== null && _d !== void 0 ? _d : err.stack,
26
+ },
27
+ }
28
+ : undefined);
29
+ }
30
+ return err;
31
+ }
32
+ return new graphql_1.GraphQLError(message);
33
+ };
34
+ exports.formatError = formatError;
35
+ const makeHandleResult = (format, message, isDev) => ({ result, setResult }) => {
36
+ if (result.errors != null) {
37
+ setResult({ ...result, errors: result.errors.map(error => format(error, message, isDev)) });
38
+ }
39
+ };
40
+ const useMaskedErrors = (opts) => {
41
+ var _a, _b;
42
+ const format = (_a = opts === null || opts === void 0 ? void 0 : opts.formatError) !== null && _a !== void 0 ? _a : exports.formatError;
43
+ const message = (opts === null || opts === void 0 ? void 0 : opts.errorMessage) || exports.DEFAULT_ERROR_MESSAGE;
44
+ // eslint-disable-next-line dot-notation
45
+ 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);
46
+ const handleResult = makeHandleResult(format, message, isDev);
47
+ return {
48
+ onParse: (opts === null || opts === void 0 ? void 0 : opts.handleParseErrors) === true
49
+ ? function onParse() {
50
+ return function onParseEnd({ result, replaceParseResult }) {
51
+ if (result instanceof Error) {
52
+ replaceParseResult(format(result, message, isDev));
53
+ }
54
+ };
55
+ }
56
+ : undefined,
57
+ onValidate: (opts === null || opts === void 0 ? void 0 : opts.handleValidationErrors) === true
58
+ ? function onValidate() {
59
+ return function onValidateEnd({ valid, result, setResult }) {
60
+ if (valid === false) {
61
+ setResult(result.map(error => format(error, message, isDev)));
62
+ }
63
+ };
64
+ }
65
+ : undefined,
66
+ onPluginInit(context) {
67
+ context.registerContextErrorHandler(({ error, setError }) => {
68
+ if (error instanceof graphql_1.GraphQLError === false && error instanceof Error) {
69
+ error = new graphql_1.GraphQLError(error.message, undefined, undefined, undefined, undefined, error);
70
+ }
71
+ setError(format(error, message, isDev));
72
+ });
73
+ },
74
+ onExecute() {
75
+ return {
76
+ onExecuteDone(payload) {
77
+ return (0, utils_js_1.handleStreamOrSingleExecutionResult)(payload, handleResult);
78
+ },
79
+ };
80
+ },
81
+ onSubscribe() {
82
+ return {
83
+ onSubscribeResult(payload) {
84
+ return (0, utils_js_1.handleStreamOrSingleExecutionResult)(payload, handleResult);
85
+ },
86
+ onSubscribeError({ error, setError }) {
87
+ setError(format(error, message, isDev));
88
+ },
89
+ };
90
+ },
91
+ };
92
+ };
93
+ exports.useMaskedErrors = useMaskedErrors;
@@ -0,0 +1,138 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useTiming = void 0;
4
+ const graphql_1 = require("graphql");
5
+ const utils_js_1 = require("../utils.js");
6
+ const HR_TO_NS = 1e9;
7
+ const NS_TO_MS = 1e6;
8
+ const DEFAULT_OPTIONS = {
9
+ onExecutionMeasurement: (args, timing) => console.log(`Operation execution "${args.operationName}" done in ${timing.ms}ms`),
10
+ onSubscriptionMeasurement: (args, timing) => console.log(`Operation subscription "${args.operationName}" done in ${timing.ms}ms`),
11
+ onParsingMeasurement: (source, timing) => console.log(`Parsing "${source}" done in ${timing.ms}ms`),
12
+ onValidationMeasurement: (document, timing) => { var _a, _b; return console.log(`Validation "${((_b = (_a = (0, graphql_1.getOperationAST)(document)) === null || _a === void 0 ? void 0 : _a.name) === null || _b === void 0 ? void 0 : _b.value) || '-'}" done in ${timing.ms}ms`); },
13
+ onResolverMeasurement: (info, timing) => console.log(`\tResolver of "${info.parentType.toString()}.${info.fieldName}" done in ${timing.ms}ms`),
14
+ onContextBuildingMeasurement: (timing) => console.log(`Context building done in ${timing.ms}ms`),
15
+ };
16
+ const deltaFrom = (hrtime) => {
17
+ const delta = process.hrtime(hrtime);
18
+ const ns = delta[0] * HR_TO_NS + delta[1];
19
+ return {
20
+ ns,
21
+ get ms() {
22
+ return ns / NS_TO_MS;
23
+ },
24
+ };
25
+ };
26
+ const useTiming = (rawOptions) => {
27
+ const options = {
28
+ ...DEFAULT_OPTIONS,
29
+ ...rawOptions,
30
+ };
31
+ const result = {};
32
+ if (options.onContextBuildingMeasurement) {
33
+ result.onContextBuilding = ({ context }) => {
34
+ if (context[utils_js_1.envelopIsIntrospectionSymbol]) {
35
+ return;
36
+ }
37
+ const contextStartTime = process.hrtime();
38
+ return () => {
39
+ options.onContextBuildingMeasurement(deltaFrom(contextStartTime));
40
+ };
41
+ };
42
+ }
43
+ if (options.onParsingMeasurement) {
44
+ result.onParse = ({ params, extendContext }) => {
45
+ if (options.skipIntrospection && (0, utils_js_1.isIntrospectionOperationString)(params.source)) {
46
+ extendContext({
47
+ [utils_js_1.envelopIsIntrospectionSymbol]: true,
48
+ });
49
+ return;
50
+ }
51
+ const parseStartTime = process.hrtime();
52
+ return () => {
53
+ options.onParsingMeasurement(params.source, deltaFrom(parseStartTime));
54
+ };
55
+ };
56
+ }
57
+ if (options.onValidationMeasurement) {
58
+ result.onValidate = ({ params, context }) => {
59
+ if (context[utils_js_1.envelopIsIntrospectionSymbol]) {
60
+ return;
61
+ }
62
+ const validateStartTime = process.hrtime();
63
+ return () => {
64
+ options.onValidationMeasurement(params.documentAST, deltaFrom(validateStartTime));
65
+ };
66
+ };
67
+ }
68
+ if (options.onExecutionMeasurement) {
69
+ if (options.onResolverMeasurement) {
70
+ result.onExecute = ({ args }) => {
71
+ if (args.contextValue[utils_js_1.envelopIsIntrospectionSymbol]) {
72
+ return;
73
+ }
74
+ const executeStartTime = process.hrtime();
75
+ return {
76
+ onExecuteDone: () => {
77
+ options.onExecutionMeasurement(args, deltaFrom(executeStartTime));
78
+ },
79
+ };
80
+ };
81
+ result.onResolverCalled = ({ info }) => {
82
+ const resolverStartTime = process.hrtime();
83
+ return () => {
84
+ options.onResolverMeasurement(info, deltaFrom(resolverStartTime));
85
+ };
86
+ };
87
+ }
88
+ else {
89
+ result.onExecute = ({ args }) => {
90
+ if (args.contextValue[utils_js_1.envelopIsIntrospectionSymbol]) {
91
+ return;
92
+ }
93
+ const executeStartTime = process.hrtime();
94
+ return {
95
+ onExecuteDone: () => {
96
+ options.onExecutionMeasurement(args, deltaFrom(executeStartTime));
97
+ },
98
+ };
99
+ };
100
+ }
101
+ }
102
+ if (options.onSubscriptionMeasurement) {
103
+ if (options.onResolverMeasurement) {
104
+ result.onSubscribe = ({ args }) => {
105
+ if (args.contextValue[utils_js_1.envelopIsIntrospectionSymbol]) {
106
+ return;
107
+ }
108
+ const subscribeStartTime = process.hrtime();
109
+ return {
110
+ onSubscribeResult: () => {
111
+ options.onSubscriptionMeasurement && options.onSubscriptionMeasurement(args, deltaFrom(subscribeStartTime));
112
+ },
113
+ };
114
+ };
115
+ result.onResolverCalled = ({ info }) => {
116
+ const resolverStartTime = process.hrtime();
117
+ return () => {
118
+ options.onResolverMeasurement && options.onResolverMeasurement(info, deltaFrom(resolverStartTime));
119
+ };
120
+ };
121
+ }
122
+ else {
123
+ result.onSubscribe = ({ args }) => {
124
+ if (args.contextValue[utils_js_1.envelopIsIntrospectionSymbol]) {
125
+ return;
126
+ }
127
+ const subscribeStartTime = process.hrtime();
128
+ return {
129
+ onSubscribeResult: () => {
130
+ options.onSubscriptionMeasurement && options.onSubscriptionMeasurement(args, deltaFrom(subscribeStartTime));
131
+ },
132
+ };
133
+ };
134
+ }
135
+ }
136
+ return result;
137
+ };
138
+ exports.useTiming = useTiming;
@@ -0,0 +1,136 @@
1
+ "use strict";
2
+ var _a;
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.traceOrchestrator = void 0;
5
+ const graphql_1 = require("graphql");
6
+ const utils_js_1 = require("./utils.js");
7
+ const getTimestamp = typeof globalThis !== 'undefined' && ((_a = globalThis === null || globalThis === void 0 ? void 0 : globalThis.performance) === null || _a === void 0 ? void 0 : _a.now)
8
+ ? () => globalThis.performance.now()
9
+ : () => Date.now();
10
+ const measure = () => {
11
+ const start = getTimestamp();
12
+ return () => {
13
+ const end = getTimestamp();
14
+ return end - start;
15
+ };
16
+ };
17
+ const tracingSymbol = Symbol('envelopTracing');
18
+ function traceOrchestrator(orchestrator) {
19
+ const createTracer = (name, ctx) => {
20
+ const end = measure();
21
+ return () => {
22
+ ctx[tracingSymbol][name] = end();
23
+ };
24
+ };
25
+ return {
26
+ ...orchestrator,
27
+ init: (ctx = {}) => {
28
+ ctx[tracingSymbol] = ctx[tracingSymbol] || {};
29
+ const done = createTracer('init', ctx || {});
30
+ try {
31
+ return orchestrator.init(ctx);
32
+ }
33
+ finally {
34
+ done();
35
+ }
36
+ },
37
+ parse: (ctx = {}) => {
38
+ ctx[tracingSymbol] = ctx[tracingSymbol] || {};
39
+ const actualFn = orchestrator.parse(ctx);
40
+ return (...args) => {
41
+ const done = createTracer('parse', ctx);
42
+ try {
43
+ return actualFn(...args);
44
+ }
45
+ finally {
46
+ done();
47
+ }
48
+ };
49
+ },
50
+ validate: (ctx = {}) => {
51
+ ctx[tracingSymbol] = ctx[tracingSymbol] || {};
52
+ const actualFn = orchestrator.validate(ctx);
53
+ return (...args) => {
54
+ const done = createTracer('validate', ctx);
55
+ try {
56
+ return actualFn(...args);
57
+ }
58
+ finally {
59
+ done();
60
+ }
61
+ };
62
+ },
63
+ execute: async (argsOrSchema, document, rootValue, contextValue, variableValues, operationName, fieldResolver, typeResolver) => {
64
+ const args = argsOrSchema instanceof graphql_1.GraphQLSchema
65
+ ? {
66
+ schema: argsOrSchema,
67
+ document: document,
68
+ rootValue,
69
+ contextValue,
70
+ variableValues,
71
+ operationName,
72
+ fieldResolver,
73
+ typeResolver,
74
+ }
75
+ : argsOrSchema;
76
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
77
+ // @ts-ignore GraphQL.js types contextValue as unknown
78
+ const done = createTracer('execute', args.contextValue || {});
79
+ try {
80
+ const result = await orchestrator.execute(args);
81
+ done();
82
+ if (!(0, utils_js_1.isAsyncIterable)(result)) {
83
+ result.extensions = result.extensions || {};
84
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
85
+ // @ts-ignore GraphQL.js types contextValue as unknown
86
+ result.extensions.envelopTracing = args.contextValue[tracingSymbol];
87
+ }
88
+ else {
89
+ // eslint-disable-next-line no-console
90
+ console.warn(`"traceOrchestrator" encountered a AsyncIterator which is not supported yet, so tracing data is not available for the operation.`);
91
+ }
92
+ return result;
93
+ }
94
+ catch (e) {
95
+ done();
96
+ throw e;
97
+ }
98
+ },
99
+ subscribe: async (argsOrSchema, document, rootValue, contextValue, variableValues, operationName, fieldResolver, subscribeFieldResolver) => {
100
+ const args = argsOrSchema instanceof graphql_1.GraphQLSchema
101
+ ? {
102
+ schema: argsOrSchema,
103
+ document: document,
104
+ rootValue,
105
+ contextValue,
106
+ variableValues,
107
+ operationName,
108
+ fieldResolver,
109
+ subscribeFieldResolver,
110
+ }
111
+ : argsOrSchema;
112
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
113
+ // @ts-ignore GraphQL.js types contextValue as unknown
114
+ const done = createTracer('subscribe', args.contextValue || {});
115
+ try {
116
+ return await orchestrator.subscribe(args);
117
+ }
118
+ finally {
119
+ done();
120
+ }
121
+ },
122
+ contextFactory: (ctx = {}) => {
123
+ const actualFn = orchestrator.contextFactory(ctx);
124
+ return async (childCtx) => {
125
+ const done = createTracer('contextFactory', ctx);
126
+ try {
127
+ return await actualFn(childCtx);
128
+ }
129
+ finally {
130
+ done();
131
+ }
132
+ };
133
+ },
134
+ };
135
+ }
136
+ exports.traceOrchestrator = traceOrchestrator;
@@ -0,0 +1,68 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.prepareTracedSchema = exports.resolversHooksSymbol = exports.trackedSchemaSymbol = void 0;
4
+ const graphql_1 = require("graphql");
5
+ exports.trackedSchemaSymbol = Symbol('TRACKED_SCHEMA');
6
+ exports.resolversHooksSymbol = Symbol('RESOLVERS_HOOKS');
7
+ function prepareTracedSchema(schema) {
8
+ if (!schema || schema[exports.trackedSchemaSymbol]) {
9
+ return;
10
+ }
11
+ schema[exports.trackedSchemaSymbol] = true;
12
+ const entries = Object.values(schema.getTypeMap());
13
+ for (const type of entries) {
14
+ if (!(0, graphql_1.isIntrospectionType)(type) && (0, graphql_1.isObjectType)(type)) {
15
+ const fields = Object.values(type.getFields());
16
+ for (const field of fields) {
17
+ let resolverFn = (field.resolve || graphql_1.defaultFieldResolver);
18
+ field.resolve = async (root, args, context, info) => {
19
+ if (context && context[exports.resolversHooksSymbol]) {
20
+ const hooks = context[exports.resolversHooksSymbol];
21
+ const afterCalls = [];
22
+ for (const hook of hooks) {
23
+ const afterFn = await hook({
24
+ root,
25
+ args,
26
+ context,
27
+ info,
28
+ resolverFn,
29
+ replaceResolverFn: newFn => {
30
+ resolverFn = newFn;
31
+ },
32
+ });
33
+ afterFn && afterCalls.push(afterFn);
34
+ }
35
+ try {
36
+ let result = await resolverFn(root, args, context, info);
37
+ for (const afterFn of afterCalls) {
38
+ afterFn({
39
+ result,
40
+ setResult: newResult => {
41
+ result = newResult;
42
+ },
43
+ });
44
+ }
45
+ return result;
46
+ }
47
+ catch (e) {
48
+ let resultErr = e;
49
+ for (const afterFn of afterCalls) {
50
+ afterFn({
51
+ result: resultErr,
52
+ setResult: newResult => {
53
+ resultErr = newResult;
54
+ },
55
+ });
56
+ }
57
+ throw resultErr;
58
+ }
59
+ }
60
+ else {
61
+ return resolverFn(root, args, context, info);
62
+ }
63
+ };
64
+ }
65
+ }
66
+ }
67
+ }
68
+ exports.prepareTracedSchema = prepareTracedSchema;