@envelop/core 1.7.2-alpha-7ca7cb8.0 → 1.8.0-alpha-2354554.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/index.js CHANGED
@@ -27,8 +27,69 @@ function enableIf(condition, plugin) {
27
27
  }
28
28
  }
29
29
 
30
- // import { AfterResolverHook, OnResolverCalledHook, ResolverFn } from '@envelop/types';
30
+ const trackedSchemaSymbol = Symbol('TRACKED_SCHEMA');
31
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
+ }
32
93
 
33
94
  const envelopIsIntrospectionSymbol = Symbol('ENVELOP_IS_INTROSPECTION');
34
95
  function isOperationDefinition(def) {
@@ -246,6 +307,7 @@ function createEnvelopOrchestrator(plugins) {
246
307
  // to allow setting the schema from the onPluginInit callback. We also need to make sure
247
308
  // here not to call the same plugin that initiated the schema switch.
248
309
  const replaceSchema = (newSchema, ignorePluginIndex = -1) => {
310
+ prepareTracedSchema(newSchema);
249
311
  schema = newSchema;
250
312
  if (initDone) {
251
313
  for (const [i, plugin] of plugins.entries()) {
@@ -415,16 +477,23 @@ function createEnvelopOrchestrator(plugins) {
415
477
  const afterCalls = [];
416
478
  try {
417
479
  let context = orchestratorCtx ? { ...initialContext, ...orchestratorCtx } : initialContext;
480
+ let isBreakingContextBuilding = false;
418
481
  for (const onContext of beforeCallbacks.context) {
419
482
  const afterHookResult = await onContext({
420
483
  context,
421
484
  extendContext: extension => {
422
485
  context = { ...context, ...extension };
423
486
  },
487
+ breakContextBuilding: () => {
488
+ isBreakingContextBuilding = true;
489
+ },
424
490
  });
425
491
  if (typeof afterHookResult === 'function') {
426
492
  afterCalls.push(afterHookResult);
427
493
  }
494
+ if (isBreakingContextBuilding === true) {
495
+ break;
496
+ }
428
497
  }
429
498
  for (const afterCb of afterCalls) {
430
499
  afterCb({
package/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  export * from '@envelop/types';
2
- import { Kind, visit, BREAK, parse, specifiedRules, validate, execute, subscribe, GraphQLSchema, getOperationAST, GraphQLError } from 'graphql';
2
+ import { isIntrospectionType, isObjectType, defaultFieldResolver, Kind, visit, BREAK, parse, specifiedRules, validate, execute, subscribe, GraphQLSchema, getOperationAST, GraphQLError } from 'graphql';
3
3
 
4
4
  /**
5
5
  * This enum is used only internally in order to create nominal type for the disabled plugin
@@ -23,8 +23,69 @@ function enableIf(condition, plugin) {
23
23
  }
24
24
  }
25
25
 
26
- // import { AfterResolverHook, OnResolverCalledHook, ResolverFn } from '@envelop/types';
26
+ const trackedSchemaSymbol = Symbol('TRACKED_SCHEMA');
27
27
  const resolversHooksSymbol = Symbol('RESOLVERS_HOOKS');
28
+ function prepareTracedSchema(schema) {
29
+ if (!schema || schema[trackedSchemaSymbol]) {
30
+ return;
31
+ }
32
+ schema[trackedSchemaSymbol] = true;
33
+ const entries = Object.values(schema.getTypeMap());
34
+ for (const type of entries) {
35
+ if (!isIntrospectionType(type) && isObjectType(type)) {
36
+ const fields = Object.values(type.getFields());
37
+ for (const field of fields) {
38
+ let resolverFn = (field.resolve || defaultFieldResolver);
39
+ field.resolve = async (root, args, context, info) => {
40
+ if (context && context[resolversHooksSymbol]) {
41
+ const hooks = context[resolversHooksSymbol];
42
+ const afterCalls = [];
43
+ for (const hook of hooks) {
44
+ const afterFn = await hook({
45
+ root,
46
+ args,
47
+ context,
48
+ info,
49
+ resolverFn,
50
+ replaceResolverFn: newFn => {
51
+ resolverFn = newFn;
52
+ },
53
+ });
54
+ afterFn && afterCalls.push(afterFn);
55
+ }
56
+ try {
57
+ let result = await resolverFn(root, args, context, info);
58
+ for (const afterFn of afterCalls) {
59
+ afterFn({
60
+ result,
61
+ setResult: newResult => {
62
+ result = newResult;
63
+ },
64
+ });
65
+ }
66
+ return result;
67
+ }
68
+ catch (e) {
69
+ let resultErr = e;
70
+ for (const afterFn of afterCalls) {
71
+ afterFn({
72
+ result: resultErr,
73
+ setResult: newResult => {
74
+ resultErr = newResult;
75
+ },
76
+ });
77
+ }
78
+ throw resultErr;
79
+ }
80
+ }
81
+ else {
82
+ return resolverFn(root, args, context, info);
83
+ }
84
+ };
85
+ }
86
+ }
87
+ }
88
+ }
28
89
 
29
90
  const envelopIsIntrospectionSymbol = Symbol('ENVELOP_IS_INTROSPECTION');
30
91
  function isOperationDefinition(def) {
@@ -242,6 +303,7 @@ function createEnvelopOrchestrator(plugins) {
242
303
  // to allow setting the schema from the onPluginInit callback. We also need to make sure
243
304
  // here not to call the same plugin that initiated the schema switch.
244
305
  const replaceSchema = (newSchema, ignorePluginIndex = -1) => {
306
+ prepareTracedSchema(newSchema);
245
307
  schema = newSchema;
246
308
  if (initDone) {
247
309
  for (const [i, plugin] of plugins.entries()) {
@@ -411,16 +473,23 @@ function createEnvelopOrchestrator(plugins) {
411
473
  const afterCalls = [];
412
474
  try {
413
475
  let context = orchestratorCtx ? { ...initialContext, ...orchestratorCtx } : initialContext;
476
+ let isBreakingContextBuilding = false;
414
477
  for (const onContext of beforeCallbacks.context) {
415
478
  const afterHookResult = await onContext({
416
479
  context,
417
480
  extendContext: extension => {
418
481
  context = { ...context, ...extension };
419
482
  },
483
+ breakContextBuilding: () => {
484
+ isBreakingContextBuilding = true;
485
+ },
420
486
  });
421
487
  if (typeof afterHookResult === 'function') {
422
488
  afterCalls.push(afterHookResult);
423
489
  }
490
+ if (isBreakingContextBuilding === true) {
491
+ break;
492
+ }
424
493
  }
425
494
  for (const afterCb of afterCalls) {
426
495
  afterCb({
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@envelop/core",
3
- "version": "1.7.2-alpha-7ca7cb8.0",
3
+ "version": "1.8.0-alpha-2354554.0",
4
4
  "sideEffects": false,
5
5
  "peerDependencies": {
6
6
  "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0"
7
7
  },
8
8
  "dependencies": {
9
- "@envelop/types": "1.5.1"
9
+ "@envelop/types": "1.6.0-alpha-2354554.0"
10
10
  },
11
11
  "repository": {
12
12
  "type": "git",
@@ -0,0 +1,6 @@
1
+ import type { Plugin } from '@envelop/types';
2
+ /**
3
+ * In case a GraphQL operation only contains introspection fields the context building can be skipped completely.
4
+ * With this plugin any further context extensions will be skipped.
5
+ */
6
+ export declare const useImmediateIntrospection: () => Plugin;