@envelop/core 1.3.1-alpha-7b77923.0 → 1.4.0-alpha-e8998c9.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
@@ -22,7 +22,69 @@ function enableIf(condition, plugin) {
22
22
  return condition ? plugin : EnableIfBranded.DisabledPlugin;
23
23
  }
24
24
 
25
+ const trackedSchemaSymbol = Symbol('TRACKED_SCHEMA');
25
26
  const resolversHooksSymbol = Symbol('RESOLVERS_HOOKS');
27
+ function prepareTracedSchema(schema) {
28
+ if (!schema || schema[trackedSchemaSymbol]) {
29
+ return;
30
+ }
31
+ schema[trackedSchemaSymbol] = true;
32
+ const entries = Object.values(schema.getTypeMap());
33
+ for (const type of entries) {
34
+ if (!graphql.isIntrospectionType(type) && graphql.isObjectType(type)) {
35
+ const fields = Object.values(type.getFields());
36
+ for (const field of fields) {
37
+ let resolverFn = (field.resolve || graphql.defaultFieldResolver);
38
+ field.resolve = async (root, args, context, info) => {
39
+ if (context && context[resolversHooksSymbol]) {
40
+ const hooks = context[resolversHooksSymbol];
41
+ const afterCalls = [];
42
+ for (const hook of hooks) {
43
+ const afterFn = await hook({
44
+ root,
45
+ args,
46
+ context,
47
+ info,
48
+ resolverFn,
49
+ replaceResolverFn: newFn => {
50
+ resolverFn = newFn;
51
+ },
52
+ });
53
+ afterFn && afterCalls.push(afterFn);
54
+ }
55
+ try {
56
+ let result = await resolverFn(root, args, context, info);
57
+ for (const afterFn of afterCalls) {
58
+ afterFn({
59
+ result,
60
+ setResult: newResult => {
61
+ result = newResult;
62
+ },
63
+ });
64
+ }
65
+ return result;
66
+ }
67
+ catch (e) {
68
+ let resultErr = e;
69
+ for (const afterFn of afterCalls) {
70
+ afterFn({
71
+ result: resultErr,
72
+ setResult: newResult => {
73
+ resultErr = newResult;
74
+ },
75
+ });
76
+ }
77
+ throw resultErr;
78
+ }
79
+ }
80
+ else {
81
+ return resolverFn(root, args, context, info);
82
+ }
83
+ };
84
+ }
85
+ }
86
+ }
87
+ }
26
88
 
27
89
  const envelopIsIntrospectionSymbol = Symbol('ENVELOP_IS_INTROSPECTION');
28
90
  function isOperationDefinition(def) {
@@ -115,7 +177,7 @@ function createEnvelopOrchestrator(plugins) {
115
177
  // to allow setting the schema from the onPluginInit callback. We also need to make sure
116
178
  // here not to call the same plugin that initiated the schema switch.
117
179
  const replaceSchema = (newSchema, ignorePluginIndex = -1) => {
118
- // prepareTracedSchema(newSchema);
180
+ prepareTracedSchema(newSchema);
119
181
  schema = newSchema;
120
182
  if (initDone) {
121
183
  for (const [i, plugin] of plugins.entries()) {
@@ -355,6 +417,8 @@ function createEnvelopOrchestrator(plugins) {
355
417
  let result = await subscribeFn({
356
418
  ...args,
357
419
  contextValue: context,
420
+ // Casted for GraphQL.js 15 compatibility
421
+ // Can be removed once we drop support for GraphQL.js 15
358
422
  });
359
423
  const onNextHandler = [];
360
424
  const onEndHandler = [];
@@ -592,12 +656,16 @@ function traceOrchestrator(orchestrator) {
592
656
  typeResolver,
593
657
  }
594
658
  : argsOrSchema;
659
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
660
+ // @ts-ignore GraphQL.js types contextValue as unknown
595
661
  const done = createTracer('execute', args.contextValue || {});
596
662
  try {
597
663
  const result = await orchestrator.execute(args);
598
664
  done();
599
665
  if (!types.isAsyncIterable(result)) {
600
666
  result.extensions = result.extensions || {};
667
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
668
+ // @ts-ignore GraphQL.js types contextValue as unknown
601
669
  result.extensions.envelopTracing = args.contextValue._envelopTracing;
602
670
  }
603
671
  else {
@@ -624,6 +692,8 @@ function traceOrchestrator(orchestrator) {
624
692
  subscribeFieldResolver,
625
693
  }
626
694
  : argsOrSchema;
695
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
696
+ // @ts-ignore GraphQL.js types contextValue as unknown
627
697
  const done = createTracer('subscribe', args.contextValue || {});
628
698
  try {
629
699
  return await orchestrator.subscribe(args);
package/index.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  import { isAsyncIterable, handleStreamOrSingleExecutionResult } from '@envelop/types';
2
2
  export * from '@envelop/types';
3
- import { Kind, visit, BREAK, parse, specifiedRules, validate, execute, subscribe, GraphQLSchema, getOperationAST, GraphQLError } from 'graphql';
3
+ import { isIntrospectionType, isObjectType, defaultFieldResolver, Kind, visit, BREAK, parse, specifiedRules, validate, execute, subscribe, GraphQLSchema, getOperationAST, GraphQLError } from 'graphql';
4
4
 
5
5
  /**
6
6
  * This enum is used only internally in order to create nominal type for the disabled plugin
@@ -19,7 +19,69 @@ function enableIf(condition, plugin) {
19
19
  return condition ? plugin : EnableIfBranded.DisabledPlugin;
20
20
  }
21
21
 
22
+ const trackedSchemaSymbol = Symbol('TRACKED_SCHEMA');
22
23
  const resolversHooksSymbol = Symbol('RESOLVERS_HOOKS');
24
+ function prepareTracedSchema(schema) {
25
+ if (!schema || schema[trackedSchemaSymbol]) {
26
+ return;
27
+ }
28
+ schema[trackedSchemaSymbol] = true;
29
+ const entries = Object.values(schema.getTypeMap());
30
+ for (const type of entries) {
31
+ if (!isIntrospectionType(type) && isObjectType(type)) {
32
+ const fields = Object.values(type.getFields());
33
+ for (const field of fields) {
34
+ let resolverFn = (field.resolve || defaultFieldResolver);
35
+ field.resolve = async (root, args, context, info) => {
36
+ if (context && context[resolversHooksSymbol]) {
37
+ const hooks = context[resolversHooksSymbol];
38
+ const afterCalls = [];
39
+ for (const hook of hooks) {
40
+ const afterFn = await hook({
41
+ root,
42
+ args,
43
+ context,
44
+ info,
45
+ resolverFn,
46
+ replaceResolverFn: newFn => {
47
+ resolverFn = newFn;
48
+ },
49
+ });
50
+ afterFn && afterCalls.push(afterFn);
51
+ }
52
+ try {
53
+ let result = await resolverFn(root, args, context, info);
54
+ for (const afterFn of afterCalls) {
55
+ afterFn({
56
+ result,
57
+ setResult: newResult => {
58
+ result = newResult;
59
+ },
60
+ });
61
+ }
62
+ return result;
63
+ }
64
+ catch (e) {
65
+ let resultErr = e;
66
+ for (const afterFn of afterCalls) {
67
+ afterFn({
68
+ result: resultErr,
69
+ setResult: newResult => {
70
+ resultErr = newResult;
71
+ },
72
+ });
73
+ }
74
+ throw resultErr;
75
+ }
76
+ }
77
+ else {
78
+ return resolverFn(root, args, context, info);
79
+ }
80
+ };
81
+ }
82
+ }
83
+ }
84
+ }
23
85
 
24
86
  const envelopIsIntrospectionSymbol = Symbol('ENVELOP_IS_INTROSPECTION');
25
87
  function isOperationDefinition(def) {
@@ -112,7 +174,7 @@ function createEnvelopOrchestrator(plugins) {
112
174
  // to allow setting the schema from the onPluginInit callback. We also need to make sure
113
175
  // here not to call the same plugin that initiated the schema switch.
114
176
  const replaceSchema = (newSchema, ignorePluginIndex = -1) => {
115
- // prepareTracedSchema(newSchema);
177
+ prepareTracedSchema(newSchema);
116
178
  schema = newSchema;
117
179
  if (initDone) {
118
180
  for (const [i, plugin] of plugins.entries()) {
@@ -352,6 +414,8 @@ function createEnvelopOrchestrator(plugins) {
352
414
  let result = await subscribeFn({
353
415
  ...args,
354
416
  contextValue: context,
417
+ // Casted for GraphQL.js 15 compatibility
418
+ // Can be removed once we drop support for GraphQL.js 15
355
419
  });
356
420
  const onNextHandler = [];
357
421
  const onEndHandler = [];
@@ -589,12 +653,16 @@ function traceOrchestrator(orchestrator) {
589
653
  typeResolver,
590
654
  }
591
655
  : argsOrSchema;
656
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
657
+ // @ts-ignore GraphQL.js types contextValue as unknown
592
658
  const done = createTracer('execute', args.contextValue || {});
593
659
  try {
594
660
  const result = await orchestrator.execute(args);
595
661
  done();
596
662
  if (!isAsyncIterable(result)) {
597
663
  result.extensions = result.extensions || {};
664
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
665
+ // @ts-ignore GraphQL.js types contextValue as unknown
598
666
  result.extensions.envelopTracing = args.contextValue._envelopTracing;
599
667
  }
600
668
  else {
@@ -621,6 +689,8 @@ function traceOrchestrator(orchestrator) {
621
689
  subscribeFieldResolver,
622
690
  }
623
691
  : argsOrSchema;
692
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
693
+ // @ts-ignore GraphQL.js types contextValue as unknown
624
694
  const done = createTracer('subscribe', args.contextValue || {});
625
695
  try {
626
696
  return await orchestrator.subscribe(args);
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@envelop/core",
3
- "version": "1.3.1-alpha-7b77923.0",
3
+ "version": "1.4.0-alpha-e8998c9.0",
4
4
  "sideEffects": false,
5
5
  "peerDependencies": {
6
- "graphql": "^14.0.0 || ^15.0.0"
6
+ "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0"
7
7
  },
8
8
  "dependencies": {
9
- "@envelop/types": "1.2.0"
9
+ "@envelop/types": "1.3.0-alpha-e8998c9.0"
10
10
  },
11
11
  "repository": {
12
12
  "type": "git",
package/utils.d.ts CHANGED
@@ -9,11 +9,11 @@ export declare function isIntrospectionOperationString(operation: string | Sourc
9
9
  /**
10
10
  * Utility function for making a subscribe function that handles polymorphic arguments.
11
11
  */
12
- export declare const makeSubscribe: (subscribeFn: (args: SubscriptionArgs) => PromiseOrValue<AsyncIterableIterator<ExecutionResult> | ExecutionResult>) => SubscribeFunction;
13
- export declare function mapAsyncIterator<TInput, TOutput = TInput>(asyncIterable: AsyncIterableIterator<TInput>, map: (input: TInput) => Promise<TOutput> | TOutput): AsyncIterableIterator<TOutput>;
12
+ export declare const makeSubscribe: (subscribeFn: (args: SubscriptionArgs) => PromiseOrValue<AsyncIterableIterator<ExecutionResult>>) => SubscribeFunction;
13
+ export declare function mapAsyncIterator<TInput, TOutput = TInput>(asyncIterable: AsyncIterable<TInput>, map: (input: TInput) => Promise<TOutput> | TOutput): AsyncIterableIterator<TOutput>;
14
14
  /**
15
15
  * Utility function for making a execute function that handles polymorphic arguments.
16
16
  */
17
17
  export declare const makeExecute: (executeFn: (args: ExecutionArgs) => PromiseOrValue<AsyncIterableIteratorOrValue<ExecutionResult>>) => ExecuteFunction;
18
- export declare function finalAsyncIterator<TInput>(asyncIterable: AsyncIterableIterator<TInput>, onFinal: () => void): AsyncIterableIterator<TInput>;
19
- export declare function errorAsyncIterator<TInput>(asyncIterable: AsyncIterableIterator<TInput>, onError: (err: unknown) => void): AsyncIterableIterator<TInput>;
18
+ export declare function finalAsyncIterator<TInput>(asyncIterable: AsyncIterable<TInput>, onFinal: () => void): AsyncIterableIterator<TInput>;
19
+ export declare function errorAsyncIterator<TInput>(asyncIterable: AsyncIterable<TInput>, onError: (err: unknown) => void): AsyncIterableIterator<TInput>;