graphql-modules 3.1.0-alpha-20260116100415-a3905495171800fc1548db8fefdb1b79bfd26c5e → 3.1.0-alpha-20260116100600-27f3a402a486f5305eddcf90a40aed7f0c67071b

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.
@@ -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;
@@ -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
@@ -1,9 +1,16 @@
1
1
  'use strict';
2
2
 
3
- var schema = require('@graphql-tools/schema');
4
- var graphql = require('graphql');
5
- var wrap = require('@graphql-tools/wrap');
6
- var ramda = require('ramda');
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ const schema = require('@graphql-tools/schema');
6
+ const graphql = require('graphql');
7
+ const module$1 = require('module');
8
+ const wrap = require('@graphql-tools/wrap');
9
+ const ramda = require('ramda');
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);
7
14
 
8
15
  const ERROR_ORIGINAL_ERROR = 'diOriginalError';
9
16
  function getOriginalError(error) {
@@ -836,6 +843,23 @@ function duplicatedGlobalTokenError(provider, modules) {
836
843
  ].join(' '));
837
844
  }
838
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
+
839
863
  /**
840
864
  * @api
841
865
  * `CONTEXT` is an InjectionToken representing the provided `GraphQLModules.GlobalContext`
@@ -881,11 +905,14 @@ function createContextBuilder({ appInjector, modulesMap, appLevelOperationProvid
881
905
  },
882
906
  });
883
907
  appInjector.setExecutionContextGetter(function executionContextGetter() {
884
- return appContext;
908
+ var _a;
909
+ return ((_a = getAsyncContext()) === null || _a === void 0 ? void 0 : _a.getApplicationContext()) || appContext;
885
910
  });
886
911
  function createModuleExecutionContextGetter(moduleId) {
887
912
  return function moduleExecutionContextGetter() {
888
- return getModuleContext(moduleId, context);
913
+ var _a;
914
+ return (((_a = getAsyncContext()) === null || _a === void 0 ? void 0 : _a.getModuleContext(moduleId)) ||
915
+ getModuleContext(moduleId, context));
889
916
  };
890
917
  }
891
918
  modulesMap.forEach((mod, moduleId) => {
@@ -955,7 +982,7 @@ function createContextBuilder({ appInjector, modulesMap, appLevelOperationProvid
955
982
  return getModuleContext(moduleId, sharedContext).injector;
956
983
  },
957
984
  });
958
- return {
985
+ const env = {
959
986
  ɵdestroy: once(() => {
960
987
  providersToDestroy.forEach(([injector, keyId]) => {
961
988
  // If provider was instantiated
@@ -969,6 +996,19 @@ function createContextBuilder({ appInjector, modulesMap, appLevelOperationProvid
969
996
  ɵinjector: operationAppInjector,
970
997
  context: sharedContext,
971
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
+ };
972
1012
  };
973
1013
  return contextBuilder;
974
1014
  }
@@ -978,31 +1018,34 @@ function executionCreator({ contextBuilder, }) {
978
1018
  // Custom or original execute function
979
1019
  const executeFn = (options === null || options === void 0 ? void 0 : options.execute) || graphql.execute;
980
1020
  return (argsOrSchema, document, rootValue, contextValue, variableValues, operationName, fieldResolver, typeResolver) => {
981
- var _a;
982
- // Create an execution context
983
- const { context, ɵdestroy: destroy } = (_a = options === null || options === void 0 ? void 0 : options.controller) !== null && _a !== void 0 ? _a : contextBuilder(isNotSchema(argsOrSchema)
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)
984
1047
  ? argsOrSchema.contextValue
985
- : contextValue);
986
- const executionArgs = isNotSchema(argsOrSchema)
987
- ? {
988
- ...argsOrSchema,
989
- contextValue: context,
990
- }
991
- : {
992
- schema: argsOrSchema,
993
- document: document,
994
- rootValue,
995
- contextValue: context,
996
- variableValues,
997
- operationName,
998
- fieldResolver,
999
- typeResolver,
1000
- };
1001
- // It's important to wrap the executeFn within a promise
1002
- // so we can easily control the end of execution (with finally)
1003
- return Promise.resolve()
1004
- .then(() => executeFn(executionArgs))
1005
- .finally(destroy);
1048
+ : contextValue).runWithContext(perform);
1006
1049
  };
1007
1050
  };
1008
1051
  return createExecution;
@@ -1013,43 +1056,46 @@ function subscriptionCreator({ contextBuilder, }) {
1013
1056
  // Custom or original subscribe function
1014
1057
  const subscribeFn = (options === null || options === void 0 ? void 0 : options.subscribe) || graphql.subscribe;
1015
1058
  return (argsOrSchema, document, rootValue, contextValue, variableValues, operationName, fieldResolver, subscribeFieldResolver) => {
1016
- var _a;
1017
- // Create an subscription context
1018
- const { context, ɵdestroy: destroy } = (_a = options === null || options === void 0 ? void 0 : options.controller) !== null && _a !== void 0 ? _a : contextBuilder(isNotSchema(argsOrSchema)
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)
1019
1097
  ? argsOrSchema.contextValue
1020
- : contextValue);
1021
- const subscriptionArgs = isNotSchema(argsOrSchema)
1022
- ? {
1023
- ...argsOrSchema,
1024
- contextValue: context,
1025
- }
1026
- : {
1027
- schema: argsOrSchema,
1028
- document: document,
1029
- rootValue,
1030
- contextValue: context,
1031
- variableValues,
1032
- operationName,
1033
- fieldResolver,
1034
- subscribeFieldResolver,
1035
- };
1036
- let isIterable = false;
1037
- // It's important to wrap the subscribeFn within a promise
1038
- // so we can easily control the end of subscription (with finally)
1039
- return Promise.resolve()
1040
- .then(() => subscribeFn(subscriptionArgs))
1041
- .then((sub) => {
1042
- if (isAsyncIterable(sub)) {
1043
- isIterable = true;
1044
- return tapAsyncIterator(sub, destroy);
1045
- }
1046
- return sub;
1047
- })
1048
- .finally(() => {
1049
- if (!isIterable) {
1050
- destroy();
1051
- }
1052
- });
1098
+ : contextValue).runWithContext(perform);
1053
1099
  };
1054
1100
  };
1055
1101
  return createSubscription;
@@ -1074,10 +1120,9 @@ function apolloSchemaCreator({ createSubscription, contextBuilder, schema, }) {
1074
1120
  const createApolloSchema = () => {
1075
1121
  const sessions = {};
1076
1122
  const subscription = createSubscription();
1077
- function getSession(ctx) {
1123
+ function getSession(ctx, { context, ɵdestroy: destroy }) {
1078
1124
  if (!ctx[CONTEXT_ID]) {
1079
1125
  ctx[CONTEXT_ID] = uniqueId((id) => !sessions[id]);
1080
- const { context, ɵdestroy: destroy } = contextBuilder(ctx);
1081
1126
  sessions[ctx[CONTEXT_ID]] = {
1082
1127
  count: 0,
1083
1128
  session: {
@@ -1109,20 +1154,22 @@ function apolloSchemaCreator({ createSubscription, contextBuilder, schema, }) {
1109
1154
  operationName: input.operationName,
1110
1155
  });
1111
1156
  }
1112
- // Create an execution context
1113
- const { context, destroy } = getSession(input.context);
1114
- // It's important to wrap the executeFn within a promise
1115
- // so we can easily control the end of execution (with finally)
1116
- return Promise.resolve()
1117
- .then(() => graphql.execute({
1118
- schema,
1119
- document: input.document,
1120
- contextValue: context,
1121
- variableValues: input.variables,
1122
- rootValue: input.rootValue,
1123
- operationName: input.operationName,
1124
- }))
1125
- .finally(destroy);
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
+ });
1126
1173
  },
1127
1174
  });
1128
1175
  };
package/index.mjs CHANGED
@@ -1,5 +1,6 @@
1
1
  import { makeExecutableSchema } from '@graphql-tools/schema';
2
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
- return appContext;
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
- return getModuleContext(moduleId, context);
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
- return {
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
- var _a;
980
- // Create an execution context
981
- const { context, ɵdestroy: destroy } = (_a = options === null || options === void 0 ? void 0 : options.controller) !== null && _a !== void 0 ? _a : contextBuilder(isNotSchema(argsOrSchema)
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
- var _a;
1015
- // Create an subscription context
1016
- const { context, ɵdestroy: destroy } = (_a = options === null || options === void 0 ? void 0 : options.controller) !== null && _a !== void 0 ? _a : contextBuilder(isNotSchema(argsOrSchema)
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
- const { context, destroy } = getSession(input.context);
1112
- // It's important to wrap the executeFn within a promise
1113
- // so we can easily control the end of execution (with finally)
1114
- return Promise.resolve()
1115
- .then(() => execute$1({
1116
- schema,
1117
- document: input.document,
1118
- contextValue: context,
1119
- variableValues: input.variables,
1120
- rootValue: input.rootValue,
1121
- operationName: input.operationName,
1122
- }))
1123
- .finally(destroy);
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
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "graphql-modules",
3
- "version": "3.1.0-alpha-20260116100415-a3905495171800fc1548db8fefdb1b79bfd26c5e",
3
+ "version": "3.1.0-alpha-20260116100600-27f3a402a486f5305eddcf90a40aed7f0c67071b",
4
4
  "description": "Create reusable, maintainable, testable and extendable GraphQL modules",
5
5
  "sideEffects": false,
6
6
  "peerDependencies": {