@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 +71 -1
- package/index.mjs +72 -2
- package/package.json +3 -3
- package/utils.d.ts +4 -4
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
|
-
|
|
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
|
-
|
|
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
|
+
"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.
|
|
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
|
|
13
|
-
export declare function mapAsyncIterator<TInput, TOutput = TInput>(asyncIterable:
|
|
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:
|
|
19
|
-
export declare function errorAsyncIterator<TInput>(asyncIterable:
|
|
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>;
|