graphql-modules 3.0.0 → 3.1.0-alpha-20260116090824-8472185427836c94f78f09105670ec509014b5d7
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/README.md +1 -1
- package/application/async-context.d.ts +6 -0
- package/application/context.d.ts +4 -1
- package/index.js +142 -80
- package/index.mjs +138 -81
- package/module/resolvers.d.ts +2 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
<!-- [](https://graphql-modules.com/) -->
|
|
5
5
|
|
|
6
6
|
[](https://www.npmjs.com/package/graphql-modules)
|
|
7
|
-

|
|
8
8
|
[](https://the-guild.dev/discord)
|
|
9
9
|
[]()
|
|
10
10
|
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export interface AsyncContext {
|
|
2
|
+
getApplicationContext(): GraphQLModules.AppContext;
|
|
3
|
+
getModuleContext(moduleId: string): GraphQLModules.ModuleContext;
|
|
4
|
+
}
|
|
5
|
+
export declare function getAsyncContext(): AsyncContext | undefined;
|
|
6
|
+
export declare function runWithAsyncContext<R, TArgs extends any[]>(asyncContext: AsyncContext, callback: (...args: TArgs) => R, ...args: TArgs): R;
|
package/application/context.d.ts
CHANGED
|
@@ -3,7 +3,10 @@ import { ResolvedProvider } from '../di/resolution';
|
|
|
3
3
|
import type { InternalAppContext, ModulesMap } from './application';
|
|
4
4
|
export type ExecutionContextBuilder<TContext extends {
|
|
5
5
|
[key: string]: any;
|
|
6
|
-
} = {}> = (context: TContext) => {
|
|
6
|
+
} = {}> = (context: TContext) => ExecutionContextEnv & {
|
|
7
|
+
runWithContext<TReturn = any>(cb: (env: ExecutionContextEnv) => TReturn): TReturn;
|
|
8
|
+
};
|
|
9
|
+
export type ExecutionContextEnv = {
|
|
7
10
|
context: InternalAppContext;
|
|
8
11
|
ɵdestroy(): void;
|
|
9
12
|
ɵinjector: Injector;
|
package/index.js
CHANGED
|
@@ -4,9 +4,14 @@ Object.defineProperty(exports, '__esModule', { value: true });
|
|
|
4
4
|
|
|
5
5
|
const schema = require('@graphql-tools/schema');
|
|
6
6
|
const graphql = require('graphql');
|
|
7
|
+
const module$1 = require('module');
|
|
7
8
|
const wrap = require('@graphql-tools/wrap');
|
|
8
9
|
const ramda = require('ramda');
|
|
9
10
|
|
|
11
|
+
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
12
|
+
|
|
13
|
+
const module__default = /*#__PURE__*/_interopDefaultLegacy(module$1);
|
|
14
|
+
|
|
10
15
|
const ERROR_ORIGINAL_ERROR = 'diOriginalError';
|
|
11
16
|
function getOriginalError(error) {
|
|
12
17
|
return error[ERROR_ORIGINAL_ERROR];
|
|
@@ -141,6 +146,7 @@ class InjectionToken {
|
|
|
141
146
|
function isType(v) {
|
|
142
147
|
return typeof v === 'function' && v !== Object;
|
|
143
148
|
}
|
|
149
|
+
exports.Scope = void 0;
|
|
144
150
|
(function (Scope) {
|
|
145
151
|
Scope[Scope["Singleton"] = 0] = "Singleton";
|
|
146
152
|
Scope[Scope["Operation"] = 1] = "Operation";
|
|
@@ -837,6 +843,23 @@ function duplicatedGlobalTokenError(provider, modules) {
|
|
|
837
843
|
].join(' '));
|
|
838
844
|
}
|
|
839
845
|
|
|
846
|
+
let alc;
|
|
847
|
+
if (typeof process !== 'undefined') {
|
|
848
|
+
// probably nodejs runtime
|
|
849
|
+
const require = module__default["default"].createRequire('file:///' /** path is not relevant since we're only loading a builtin */);
|
|
850
|
+
const hooks = require('async_hooks');
|
|
851
|
+
alc = new hooks.AsyncLocalStorage();
|
|
852
|
+
}
|
|
853
|
+
function getAsyncContext() {
|
|
854
|
+
return alc === null || alc === void 0 ? void 0 : alc.getStore();
|
|
855
|
+
}
|
|
856
|
+
function runWithAsyncContext(asyncContext, callback, ...args) {
|
|
857
|
+
if (!alc) {
|
|
858
|
+
return callback(...args);
|
|
859
|
+
}
|
|
860
|
+
return alc.run(asyncContext, callback, ...args);
|
|
861
|
+
}
|
|
862
|
+
|
|
840
863
|
/**
|
|
841
864
|
* @api
|
|
842
865
|
* `CONTEXT` is an InjectionToken representing the provided `GraphQLModules.GlobalContext`
|
|
@@ -882,11 +905,14 @@ function createContextBuilder({ appInjector, modulesMap, appLevelOperationProvid
|
|
|
882
905
|
},
|
|
883
906
|
});
|
|
884
907
|
appInjector.setExecutionContextGetter(function executionContextGetter() {
|
|
885
|
-
|
|
908
|
+
var _a;
|
|
909
|
+
return ((_a = getAsyncContext()) === null || _a === void 0 ? void 0 : _a.getApplicationContext()) || appContext;
|
|
886
910
|
});
|
|
887
911
|
function createModuleExecutionContextGetter(moduleId) {
|
|
888
912
|
return function moduleExecutionContextGetter() {
|
|
889
|
-
|
|
913
|
+
var _a;
|
|
914
|
+
return (((_a = getAsyncContext()) === null || _a === void 0 ? void 0 : _a.getModuleContext(moduleId)) ||
|
|
915
|
+
getModuleContext(moduleId, context));
|
|
890
916
|
};
|
|
891
917
|
}
|
|
892
918
|
modulesMap.forEach((mod, moduleId) => {
|
|
@@ -956,7 +982,7 @@ function createContextBuilder({ appInjector, modulesMap, appLevelOperationProvid
|
|
|
956
982
|
return getModuleContext(moduleId, sharedContext).injector;
|
|
957
983
|
},
|
|
958
984
|
});
|
|
959
|
-
|
|
985
|
+
const env = {
|
|
960
986
|
ɵdestroy: once(() => {
|
|
961
987
|
providersToDestroy.forEach(([injector, keyId]) => {
|
|
962
988
|
// If provider was instantiated
|
|
@@ -970,6 +996,19 @@ function createContextBuilder({ appInjector, modulesMap, appLevelOperationProvid
|
|
|
970
996
|
ɵinjector: operationAppInjector,
|
|
971
997
|
context: sharedContext,
|
|
972
998
|
};
|
|
999
|
+
return {
|
|
1000
|
+
...env,
|
|
1001
|
+
runWithContext(cb) {
|
|
1002
|
+
return runWithAsyncContext({
|
|
1003
|
+
getApplicationContext() {
|
|
1004
|
+
return appContext;
|
|
1005
|
+
},
|
|
1006
|
+
getModuleContext(moduleId) {
|
|
1007
|
+
return getModuleContext(moduleId, context);
|
|
1008
|
+
},
|
|
1009
|
+
}, cb, env);
|
|
1010
|
+
},
|
|
1011
|
+
};
|
|
973
1012
|
};
|
|
974
1013
|
return contextBuilder;
|
|
975
1014
|
}
|
|
@@ -979,31 +1018,34 @@ function executionCreator({ contextBuilder, }) {
|
|
|
979
1018
|
// Custom or original execute function
|
|
980
1019
|
const executeFn = (options === null || options === void 0 ? void 0 : options.execute) || graphql.execute;
|
|
981
1020
|
return (argsOrSchema, document, rootValue, contextValue, variableValues, operationName, fieldResolver, typeResolver) => {
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
1021
|
+
function perform({ context, ɵdestroy: destroy, }) {
|
|
1022
|
+
const executionArgs = isNotSchema(argsOrSchema)
|
|
1023
|
+
? {
|
|
1024
|
+
...argsOrSchema,
|
|
1025
|
+
contextValue: context,
|
|
1026
|
+
}
|
|
1027
|
+
: {
|
|
1028
|
+
schema: argsOrSchema,
|
|
1029
|
+
document: document,
|
|
1030
|
+
rootValue,
|
|
1031
|
+
contextValue: context,
|
|
1032
|
+
variableValues,
|
|
1033
|
+
operationName,
|
|
1034
|
+
fieldResolver,
|
|
1035
|
+
typeResolver,
|
|
1036
|
+
};
|
|
1037
|
+
// It's important to wrap the executeFn within a promise
|
|
1038
|
+
// so we can easily control the end of execution (with finally)
|
|
1039
|
+
return Promise.resolve()
|
|
1040
|
+
.then(() => executeFn(executionArgs))
|
|
1041
|
+
.finally(destroy);
|
|
1042
|
+
}
|
|
1043
|
+
if (options === null || options === void 0 ? void 0 : options.controller) {
|
|
1044
|
+
return perform(options.controller);
|
|
1045
|
+
}
|
|
1046
|
+
return contextBuilder(isNotSchema(argsOrSchema)
|
|
985
1047
|
? argsOrSchema.contextValue
|
|
986
|
-
: contextValue);
|
|
987
|
-
const executionArgs = isNotSchema(argsOrSchema)
|
|
988
|
-
? {
|
|
989
|
-
...argsOrSchema,
|
|
990
|
-
contextValue: context,
|
|
991
|
-
}
|
|
992
|
-
: {
|
|
993
|
-
schema: argsOrSchema,
|
|
994
|
-
document: document,
|
|
995
|
-
rootValue,
|
|
996
|
-
contextValue: context,
|
|
997
|
-
variableValues,
|
|
998
|
-
operationName,
|
|
999
|
-
fieldResolver,
|
|
1000
|
-
typeResolver,
|
|
1001
|
-
};
|
|
1002
|
-
// It's important to wrap the executeFn within a promise
|
|
1003
|
-
// so we can easily control the end of execution (with finally)
|
|
1004
|
-
return Promise.resolve()
|
|
1005
|
-
.then(() => executeFn(executionArgs))
|
|
1006
|
-
.finally(destroy);
|
|
1048
|
+
: contextValue).runWithContext(perform);
|
|
1007
1049
|
};
|
|
1008
1050
|
};
|
|
1009
1051
|
return createExecution;
|
|
@@ -1014,43 +1056,46 @@ function subscriptionCreator({ contextBuilder, }) {
|
|
|
1014
1056
|
// Custom or original subscribe function
|
|
1015
1057
|
const subscribeFn = (options === null || options === void 0 ? void 0 : options.subscribe) || graphql.subscribe;
|
|
1016
1058
|
return (argsOrSchema, document, rootValue, contextValue, variableValues, operationName, fieldResolver, subscribeFieldResolver) => {
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1059
|
+
function perform({ context, ɵdestroy: destroy, }) {
|
|
1060
|
+
const subscriptionArgs = isNotSchema(argsOrSchema)
|
|
1061
|
+
? {
|
|
1062
|
+
...argsOrSchema,
|
|
1063
|
+
contextValue: context,
|
|
1064
|
+
}
|
|
1065
|
+
: {
|
|
1066
|
+
schema: argsOrSchema,
|
|
1067
|
+
document: document,
|
|
1068
|
+
rootValue,
|
|
1069
|
+
contextValue: context,
|
|
1070
|
+
variableValues,
|
|
1071
|
+
operationName,
|
|
1072
|
+
fieldResolver,
|
|
1073
|
+
subscribeFieldResolver,
|
|
1074
|
+
};
|
|
1075
|
+
let isIterable = false;
|
|
1076
|
+
// It's important to wrap the subscribeFn within a promise
|
|
1077
|
+
// so we can easily control the end of subscription (with finally)
|
|
1078
|
+
return Promise.resolve()
|
|
1079
|
+
.then(() => subscribeFn(subscriptionArgs))
|
|
1080
|
+
.then((sub) => {
|
|
1081
|
+
if (isAsyncIterable(sub)) {
|
|
1082
|
+
isIterable = true;
|
|
1083
|
+
return tapAsyncIterator(sub, destroy);
|
|
1084
|
+
}
|
|
1085
|
+
return sub;
|
|
1086
|
+
})
|
|
1087
|
+
.finally(() => {
|
|
1088
|
+
if (!isIterable) {
|
|
1089
|
+
destroy();
|
|
1090
|
+
}
|
|
1091
|
+
});
|
|
1092
|
+
}
|
|
1093
|
+
if (options === null || options === void 0 ? void 0 : options.controller) {
|
|
1094
|
+
return perform(options.controller);
|
|
1095
|
+
}
|
|
1096
|
+
return contextBuilder(isNotSchema(argsOrSchema)
|
|
1020
1097
|
? argsOrSchema.contextValue
|
|
1021
|
-
: contextValue);
|
|
1022
|
-
const subscriptionArgs = isNotSchema(argsOrSchema)
|
|
1023
|
-
? {
|
|
1024
|
-
...argsOrSchema,
|
|
1025
|
-
contextValue: context,
|
|
1026
|
-
}
|
|
1027
|
-
: {
|
|
1028
|
-
schema: argsOrSchema,
|
|
1029
|
-
document: document,
|
|
1030
|
-
rootValue,
|
|
1031
|
-
contextValue: context,
|
|
1032
|
-
variableValues,
|
|
1033
|
-
operationName,
|
|
1034
|
-
fieldResolver,
|
|
1035
|
-
subscribeFieldResolver,
|
|
1036
|
-
};
|
|
1037
|
-
let isIterable = false;
|
|
1038
|
-
// It's important to wrap the subscribeFn within a promise
|
|
1039
|
-
// so we can easily control the end of subscription (with finally)
|
|
1040
|
-
return Promise.resolve()
|
|
1041
|
-
.then(() => subscribeFn(subscriptionArgs))
|
|
1042
|
-
.then((sub) => {
|
|
1043
|
-
if (isAsyncIterable(sub)) {
|
|
1044
|
-
isIterable = true;
|
|
1045
|
-
return tapAsyncIterator(sub, destroy);
|
|
1046
|
-
}
|
|
1047
|
-
return sub;
|
|
1048
|
-
})
|
|
1049
|
-
.finally(() => {
|
|
1050
|
-
if (!isIterable) {
|
|
1051
|
-
destroy();
|
|
1052
|
-
}
|
|
1053
|
-
});
|
|
1098
|
+
: contextValue).runWithContext(perform);
|
|
1054
1099
|
};
|
|
1055
1100
|
};
|
|
1056
1101
|
return createSubscription;
|
|
@@ -1075,10 +1120,9 @@ function apolloSchemaCreator({ createSubscription, contextBuilder, schema, }) {
|
|
|
1075
1120
|
const createApolloSchema = () => {
|
|
1076
1121
|
const sessions = {};
|
|
1077
1122
|
const subscription = createSubscription();
|
|
1078
|
-
function getSession(ctx) {
|
|
1123
|
+
function getSession(ctx, { context, ɵdestroy: destroy }) {
|
|
1079
1124
|
if (!ctx[CONTEXT_ID]) {
|
|
1080
1125
|
ctx[CONTEXT_ID] = uniqueId((id) => !sessions[id]);
|
|
1081
|
-
const { context, ɵdestroy: destroy } = contextBuilder(ctx);
|
|
1082
1126
|
sessions[ctx[CONTEXT_ID]] = {
|
|
1083
1127
|
count: 0,
|
|
1084
1128
|
session: {
|
|
@@ -1110,20 +1154,22 @@ function apolloSchemaCreator({ createSubscription, contextBuilder, schema, }) {
|
|
|
1110
1154
|
operationName: input.operationName,
|
|
1111
1155
|
});
|
|
1112
1156
|
}
|
|
1113
|
-
// Create an execution context
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
.
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1157
|
+
// Create an execution context and run within it
|
|
1158
|
+
return contextBuilder(input.context).runWithContext((env) => {
|
|
1159
|
+
const { context, destroy } = getSession(input.context, env);
|
|
1160
|
+
// It's important to wrap the executeFn within a promise
|
|
1161
|
+
// so we can easily control the end of execution (with finally)
|
|
1162
|
+
return Promise.resolve()
|
|
1163
|
+
.then(() => graphql.execute({
|
|
1164
|
+
schema,
|
|
1165
|
+
document: input.document,
|
|
1166
|
+
contextValue: context,
|
|
1167
|
+
variableValues: input.variables,
|
|
1168
|
+
rootValue: input.rootValue,
|
|
1169
|
+
operationName: input.operationName,
|
|
1170
|
+
}))
|
|
1171
|
+
.finally(destroy);
|
|
1172
|
+
});
|
|
1127
1173
|
},
|
|
1128
1174
|
});
|
|
1129
1175
|
};
|
|
@@ -1545,6 +1591,12 @@ function createResolvers(config, metadata, app) {
|
|
|
1545
1591
|
});
|
|
1546
1592
|
resolvers[typeName][fieldName].subscribe = resolver;
|
|
1547
1593
|
}
|
|
1594
|
+
if (isDefined(obj[fieldName].extensions)) {
|
|
1595
|
+
// Do NOT add a resolve if one is not specified, it will cause
|
|
1596
|
+
// change in behavior in systems like `grafast`
|
|
1597
|
+
resolvers[typeName][fieldName].extensions =
|
|
1598
|
+
obj[fieldName].extensions;
|
|
1599
|
+
}
|
|
1548
1600
|
}
|
|
1549
1601
|
}
|
|
1550
1602
|
}
|
|
@@ -1665,6 +1717,14 @@ function addObject({ typeName, fields, container, config, }) {
|
|
|
1665
1717
|
writeResolverMetadata(resolver.subscribe, config);
|
|
1666
1718
|
container[typeName][fieldName].subscribe = resolver.subscribe;
|
|
1667
1719
|
}
|
|
1720
|
+
// extensions
|
|
1721
|
+
if (isDefined(resolver.extensions)) {
|
|
1722
|
+
if (container[typeName][fieldName].extensions) {
|
|
1723
|
+
throw new ResolverDuplicatedError(`Duplicated resolver of "${typeName}.${fieldName}" (extensions object)`, useLocation({ dirname: config.dirname, id: config.id }));
|
|
1724
|
+
}
|
|
1725
|
+
writeResolverMetadata(resolver.extensions, config);
|
|
1726
|
+
container[typeName][fieldName].extensions = resolver.extensions;
|
|
1727
|
+
}
|
|
1668
1728
|
}
|
|
1669
1729
|
}
|
|
1670
1730
|
}
|
|
@@ -1795,7 +1855,9 @@ function isResolveFn(value) {
|
|
|
1795
1855
|
return typeof value === 'function';
|
|
1796
1856
|
}
|
|
1797
1857
|
function isResolveOptions(value) {
|
|
1798
|
-
return isDefined(value.resolve) ||
|
|
1858
|
+
return (isDefined(value.resolve) ||
|
|
1859
|
+
isDefined(value.subscribe) ||
|
|
1860
|
+
isDefined(value.extensions));
|
|
1799
1861
|
}
|
|
1800
1862
|
function isScalarResolver(obj) {
|
|
1801
1863
|
return obj instanceof graphql.GraphQLScalarType;
|
package/index.mjs
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { makeExecutableSchema } from '@graphql-tools/schema';
|
|
2
|
-
import { GraphQLSchema, execute as execute$1, subscribe, visit, Kind,
|
|
2
|
+
import { GraphQLSchema, execute as execute$1, subscribe, visit, Kind, concatAST, defaultFieldResolver, GraphQLScalarType, parse } from 'graphql';
|
|
3
|
+
import module from 'module';
|
|
3
4
|
import { wrapSchema } from '@graphql-tools/wrap';
|
|
4
5
|
import { mergeDeepWith } from 'ramda';
|
|
5
6
|
|
|
@@ -834,6 +835,23 @@ function duplicatedGlobalTokenError(provider, modules) {
|
|
|
834
835
|
].join(' '));
|
|
835
836
|
}
|
|
836
837
|
|
|
838
|
+
let alc;
|
|
839
|
+
if (typeof process !== 'undefined') {
|
|
840
|
+
// probably nodejs runtime
|
|
841
|
+
const require = module.createRequire('file:///' /** path is not relevant since we're only loading a builtin */);
|
|
842
|
+
const hooks = require('async_hooks');
|
|
843
|
+
alc = new hooks.AsyncLocalStorage();
|
|
844
|
+
}
|
|
845
|
+
function getAsyncContext() {
|
|
846
|
+
return alc === null || alc === void 0 ? void 0 : alc.getStore();
|
|
847
|
+
}
|
|
848
|
+
function runWithAsyncContext(asyncContext, callback, ...args) {
|
|
849
|
+
if (!alc) {
|
|
850
|
+
return callback(...args);
|
|
851
|
+
}
|
|
852
|
+
return alc.run(asyncContext, callback, ...args);
|
|
853
|
+
}
|
|
854
|
+
|
|
837
855
|
/**
|
|
838
856
|
* @api
|
|
839
857
|
* `CONTEXT` is an InjectionToken representing the provided `GraphQLModules.GlobalContext`
|
|
@@ -879,11 +897,14 @@ function createContextBuilder({ appInjector, modulesMap, appLevelOperationProvid
|
|
|
879
897
|
},
|
|
880
898
|
});
|
|
881
899
|
appInjector.setExecutionContextGetter(function executionContextGetter() {
|
|
882
|
-
|
|
900
|
+
var _a;
|
|
901
|
+
return ((_a = getAsyncContext()) === null || _a === void 0 ? void 0 : _a.getApplicationContext()) || appContext;
|
|
883
902
|
});
|
|
884
903
|
function createModuleExecutionContextGetter(moduleId) {
|
|
885
904
|
return function moduleExecutionContextGetter() {
|
|
886
|
-
|
|
905
|
+
var _a;
|
|
906
|
+
return (((_a = getAsyncContext()) === null || _a === void 0 ? void 0 : _a.getModuleContext(moduleId)) ||
|
|
907
|
+
getModuleContext(moduleId, context));
|
|
887
908
|
};
|
|
888
909
|
}
|
|
889
910
|
modulesMap.forEach((mod, moduleId) => {
|
|
@@ -953,7 +974,7 @@ function createContextBuilder({ appInjector, modulesMap, appLevelOperationProvid
|
|
|
953
974
|
return getModuleContext(moduleId, sharedContext).injector;
|
|
954
975
|
},
|
|
955
976
|
});
|
|
956
|
-
|
|
977
|
+
const env = {
|
|
957
978
|
ɵdestroy: once(() => {
|
|
958
979
|
providersToDestroy.forEach(([injector, keyId]) => {
|
|
959
980
|
// If provider was instantiated
|
|
@@ -967,6 +988,19 @@ function createContextBuilder({ appInjector, modulesMap, appLevelOperationProvid
|
|
|
967
988
|
ɵinjector: operationAppInjector,
|
|
968
989
|
context: sharedContext,
|
|
969
990
|
};
|
|
991
|
+
return {
|
|
992
|
+
...env,
|
|
993
|
+
runWithContext(cb) {
|
|
994
|
+
return runWithAsyncContext({
|
|
995
|
+
getApplicationContext() {
|
|
996
|
+
return appContext;
|
|
997
|
+
},
|
|
998
|
+
getModuleContext(moduleId) {
|
|
999
|
+
return getModuleContext(moduleId, context);
|
|
1000
|
+
},
|
|
1001
|
+
}, cb, env);
|
|
1002
|
+
},
|
|
1003
|
+
};
|
|
970
1004
|
};
|
|
971
1005
|
return contextBuilder;
|
|
972
1006
|
}
|
|
@@ -976,31 +1010,34 @@ function executionCreator({ contextBuilder, }) {
|
|
|
976
1010
|
// Custom or original execute function
|
|
977
1011
|
const executeFn = (options === null || options === void 0 ? void 0 : options.execute) || execute$1;
|
|
978
1012
|
return (argsOrSchema, document, rootValue, contextValue, variableValues, operationName, fieldResolver, typeResolver) => {
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
1013
|
+
function perform({ context, ɵdestroy: destroy, }) {
|
|
1014
|
+
const executionArgs = isNotSchema(argsOrSchema)
|
|
1015
|
+
? {
|
|
1016
|
+
...argsOrSchema,
|
|
1017
|
+
contextValue: context,
|
|
1018
|
+
}
|
|
1019
|
+
: {
|
|
1020
|
+
schema: argsOrSchema,
|
|
1021
|
+
document: document,
|
|
1022
|
+
rootValue,
|
|
1023
|
+
contextValue: context,
|
|
1024
|
+
variableValues,
|
|
1025
|
+
operationName,
|
|
1026
|
+
fieldResolver,
|
|
1027
|
+
typeResolver,
|
|
1028
|
+
};
|
|
1029
|
+
// It's important to wrap the executeFn within a promise
|
|
1030
|
+
// so we can easily control the end of execution (with finally)
|
|
1031
|
+
return Promise.resolve()
|
|
1032
|
+
.then(() => executeFn(executionArgs))
|
|
1033
|
+
.finally(destroy);
|
|
1034
|
+
}
|
|
1035
|
+
if (options === null || options === void 0 ? void 0 : options.controller) {
|
|
1036
|
+
return perform(options.controller);
|
|
1037
|
+
}
|
|
1038
|
+
return contextBuilder(isNotSchema(argsOrSchema)
|
|
982
1039
|
? argsOrSchema.contextValue
|
|
983
|
-
: contextValue);
|
|
984
|
-
const executionArgs = isNotSchema(argsOrSchema)
|
|
985
|
-
? {
|
|
986
|
-
...argsOrSchema,
|
|
987
|
-
contextValue: context,
|
|
988
|
-
}
|
|
989
|
-
: {
|
|
990
|
-
schema: argsOrSchema,
|
|
991
|
-
document: document,
|
|
992
|
-
rootValue,
|
|
993
|
-
contextValue: context,
|
|
994
|
-
variableValues,
|
|
995
|
-
operationName,
|
|
996
|
-
fieldResolver,
|
|
997
|
-
typeResolver,
|
|
998
|
-
};
|
|
999
|
-
// It's important to wrap the executeFn within a promise
|
|
1000
|
-
// so we can easily control the end of execution (with finally)
|
|
1001
|
-
return Promise.resolve()
|
|
1002
|
-
.then(() => executeFn(executionArgs))
|
|
1003
|
-
.finally(destroy);
|
|
1040
|
+
: contextValue).runWithContext(perform);
|
|
1004
1041
|
};
|
|
1005
1042
|
};
|
|
1006
1043
|
return createExecution;
|
|
@@ -1011,43 +1048,46 @@ function subscriptionCreator({ contextBuilder, }) {
|
|
|
1011
1048
|
// Custom or original subscribe function
|
|
1012
1049
|
const subscribeFn = (options === null || options === void 0 ? void 0 : options.subscribe) || subscribe;
|
|
1013
1050
|
return (argsOrSchema, document, rootValue, contextValue, variableValues, operationName, fieldResolver, subscribeFieldResolver) => {
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1051
|
+
function perform({ context, ɵdestroy: destroy, }) {
|
|
1052
|
+
const subscriptionArgs = isNotSchema(argsOrSchema)
|
|
1053
|
+
? {
|
|
1054
|
+
...argsOrSchema,
|
|
1055
|
+
contextValue: context,
|
|
1056
|
+
}
|
|
1057
|
+
: {
|
|
1058
|
+
schema: argsOrSchema,
|
|
1059
|
+
document: document,
|
|
1060
|
+
rootValue,
|
|
1061
|
+
contextValue: context,
|
|
1062
|
+
variableValues,
|
|
1063
|
+
operationName,
|
|
1064
|
+
fieldResolver,
|
|
1065
|
+
subscribeFieldResolver,
|
|
1066
|
+
};
|
|
1067
|
+
let isIterable = false;
|
|
1068
|
+
// It's important to wrap the subscribeFn within a promise
|
|
1069
|
+
// so we can easily control the end of subscription (with finally)
|
|
1070
|
+
return Promise.resolve()
|
|
1071
|
+
.then(() => subscribeFn(subscriptionArgs))
|
|
1072
|
+
.then((sub) => {
|
|
1073
|
+
if (isAsyncIterable(sub)) {
|
|
1074
|
+
isIterable = true;
|
|
1075
|
+
return tapAsyncIterator(sub, destroy);
|
|
1076
|
+
}
|
|
1077
|
+
return sub;
|
|
1078
|
+
})
|
|
1079
|
+
.finally(() => {
|
|
1080
|
+
if (!isIterable) {
|
|
1081
|
+
destroy();
|
|
1082
|
+
}
|
|
1083
|
+
});
|
|
1084
|
+
}
|
|
1085
|
+
if (options === null || options === void 0 ? void 0 : options.controller) {
|
|
1086
|
+
return perform(options.controller);
|
|
1087
|
+
}
|
|
1088
|
+
return contextBuilder(isNotSchema(argsOrSchema)
|
|
1017
1089
|
? argsOrSchema.contextValue
|
|
1018
|
-
: contextValue);
|
|
1019
|
-
const subscriptionArgs = isNotSchema(argsOrSchema)
|
|
1020
|
-
? {
|
|
1021
|
-
...argsOrSchema,
|
|
1022
|
-
contextValue: context,
|
|
1023
|
-
}
|
|
1024
|
-
: {
|
|
1025
|
-
schema: argsOrSchema,
|
|
1026
|
-
document: document,
|
|
1027
|
-
rootValue,
|
|
1028
|
-
contextValue: context,
|
|
1029
|
-
variableValues,
|
|
1030
|
-
operationName,
|
|
1031
|
-
fieldResolver,
|
|
1032
|
-
subscribeFieldResolver,
|
|
1033
|
-
};
|
|
1034
|
-
let isIterable = false;
|
|
1035
|
-
// It's important to wrap the subscribeFn within a promise
|
|
1036
|
-
// so we can easily control the end of subscription (with finally)
|
|
1037
|
-
return Promise.resolve()
|
|
1038
|
-
.then(() => subscribeFn(subscriptionArgs))
|
|
1039
|
-
.then((sub) => {
|
|
1040
|
-
if (isAsyncIterable(sub)) {
|
|
1041
|
-
isIterable = true;
|
|
1042
|
-
return tapAsyncIterator(sub, destroy);
|
|
1043
|
-
}
|
|
1044
|
-
return sub;
|
|
1045
|
-
})
|
|
1046
|
-
.finally(() => {
|
|
1047
|
-
if (!isIterable) {
|
|
1048
|
-
destroy();
|
|
1049
|
-
}
|
|
1050
|
-
});
|
|
1090
|
+
: contextValue).runWithContext(perform);
|
|
1051
1091
|
};
|
|
1052
1092
|
};
|
|
1053
1093
|
return createSubscription;
|
|
@@ -1072,10 +1112,9 @@ function apolloSchemaCreator({ createSubscription, contextBuilder, schema, }) {
|
|
|
1072
1112
|
const createApolloSchema = () => {
|
|
1073
1113
|
const sessions = {};
|
|
1074
1114
|
const subscription = createSubscription();
|
|
1075
|
-
function getSession(ctx) {
|
|
1115
|
+
function getSession(ctx, { context, ɵdestroy: destroy }) {
|
|
1076
1116
|
if (!ctx[CONTEXT_ID]) {
|
|
1077
1117
|
ctx[CONTEXT_ID] = uniqueId((id) => !sessions[id]);
|
|
1078
|
-
const { context, ɵdestroy: destroy } = contextBuilder(ctx);
|
|
1079
1118
|
sessions[ctx[CONTEXT_ID]] = {
|
|
1080
1119
|
count: 0,
|
|
1081
1120
|
session: {
|
|
@@ -1107,20 +1146,22 @@ function apolloSchemaCreator({ createSubscription, contextBuilder, schema, }) {
|
|
|
1107
1146
|
operationName: input.operationName,
|
|
1108
1147
|
});
|
|
1109
1148
|
}
|
|
1110
|
-
// Create an execution context
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
.
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1149
|
+
// Create an execution context and run within it
|
|
1150
|
+
return contextBuilder(input.context).runWithContext((env) => {
|
|
1151
|
+
const { context, destroy } = getSession(input.context, env);
|
|
1152
|
+
// It's important to wrap the executeFn within a promise
|
|
1153
|
+
// so we can easily control the end of execution (with finally)
|
|
1154
|
+
return Promise.resolve()
|
|
1155
|
+
.then(() => execute$1({
|
|
1156
|
+
schema,
|
|
1157
|
+
document: input.document,
|
|
1158
|
+
contextValue: context,
|
|
1159
|
+
variableValues: input.variables,
|
|
1160
|
+
rootValue: input.rootValue,
|
|
1161
|
+
operationName: input.operationName,
|
|
1162
|
+
}))
|
|
1163
|
+
.finally(destroy);
|
|
1164
|
+
});
|
|
1124
1165
|
},
|
|
1125
1166
|
});
|
|
1126
1167
|
};
|
|
@@ -1542,6 +1583,12 @@ function createResolvers(config, metadata, app) {
|
|
|
1542
1583
|
});
|
|
1543
1584
|
resolvers[typeName][fieldName].subscribe = resolver;
|
|
1544
1585
|
}
|
|
1586
|
+
if (isDefined(obj[fieldName].extensions)) {
|
|
1587
|
+
// Do NOT add a resolve if one is not specified, it will cause
|
|
1588
|
+
// change in behavior in systems like `grafast`
|
|
1589
|
+
resolvers[typeName][fieldName].extensions =
|
|
1590
|
+
obj[fieldName].extensions;
|
|
1591
|
+
}
|
|
1545
1592
|
}
|
|
1546
1593
|
}
|
|
1547
1594
|
}
|
|
@@ -1662,6 +1709,14 @@ function addObject({ typeName, fields, container, config, }) {
|
|
|
1662
1709
|
writeResolverMetadata(resolver.subscribe, config);
|
|
1663
1710
|
container[typeName][fieldName].subscribe = resolver.subscribe;
|
|
1664
1711
|
}
|
|
1712
|
+
// extensions
|
|
1713
|
+
if (isDefined(resolver.extensions)) {
|
|
1714
|
+
if (container[typeName][fieldName].extensions) {
|
|
1715
|
+
throw new ResolverDuplicatedError(`Duplicated resolver of "${typeName}.${fieldName}" (extensions object)`, useLocation({ dirname: config.dirname, id: config.id }));
|
|
1716
|
+
}
|
|
1717
|
+
writeResolverMetadata(resolver.extensions, config);
|
|
1718
|
+
container[typeName][fieldName].extensions = resolver.extensions;
|
|
1719
|
+
}
|
|
1665
1720
|
}
|
|
1666
1721
|
}
|
|
1667
1722
|
}
|
|
@@ -1792,7 +1847,9 @@ function isResolveFn(value) {
|
|
|
1792
1847
|
return typeof value === 'function';
|
|
1793
1848
|
}
|
|
1794
1849
|
function isResolveOptions(value) {
|
|
1795
|
-
return isDefined(value.resolve) ||
|
|
1850
|
+
return (isDefined(value.resolve) ||
|
|
1851
|
+
isDefined(value.subscribe) ||
|
|
1852
|
+
isDefined(value.extensions));
|
|
1796
1853
|
}
|
|
1797
1854
|
function isScalarResolver(obj) {
|
|
1798
1855
|
return obj instanceof GraphQLScalarType;
|
package/module/resolvers.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { GraphQLFieldExtensions } from 'graphql';
|
|
1
2
|
import { ModuleConfig } from './types';
|
|
2
3
|
import { ModuleMetadata } from './metadata';
|
|
3
4
|
import { ResolveFn, ID } from './../shared/types';
|
|
@@ -8,5 +9,5 @@ interface ResolverMetadata {
|
|
|
8
9
|
export declare function createResolvers(config: ModuleConfig, metadata: ModuleMetadata, app: {
|
|
9
10
|
middlewareMap: MiddlewareMap;
|
|
10
11
|
}): Record<string, any>;
|
|
11
|
-
export declare function readResolverMetadata(resolver: ResolveFn): ResolverMetadata;
|
|
12
|
+
export declare function readResolverMetadata(resolver: ResolveFn | GraphQLFieldExtensions<any, any, any>): ResolverMetadata;
|
|
12
13
|
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "graphql-modules",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.1.0-alpha-20260116090824-8472185427836c94f78f09105670ec509014b5d7",
|
|
4
4
|
"description": "Create reusable, maintainable, testable and extendable GraphQL modules",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"peerDependencies": {
|