graphql-modules 3.0.0-alpha-20231018163544-36199b68 → 3.0.0-alpha-20250219090434-d6cc8940d97c7ef3dba3f59c56376d7cbab77c83

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 CHANGED
@@ -1,4 +1,7 @@
1
- [![modules](https://user-images.githubusercontent.com/25294569/64067074-ed185b80-cc2a-11e9-8f4d-5f1e19feaa0a.gif)](https://graphql-modules.com/)
1
+ [![GraphQLConf 2024 Banner: September 10-12, San Francisco. Hosted by the GraphQL Foundation](https://github.com/user-attachments/assets/bdb8cd5d-5186-4ece-b06b-b00a499b7868)](https://graphql.org/conf/2024/?utm_source=github&utm_medium=graphql_modules&utm_campaign=readme)
2
+
3
+ <!-- Uncomment when we remove GraphQL Conf banner -->
4
+ <!-- [![modules](https://user-images.githubusercontent.com/25294569/64067074-ed185b80-cc2a-11e9-8f4d-5f1e19feaa0a.gif)](https://graphql-modules.com/) -->
2
5
 
3
6
  [![npm version](https://badge.fury.io/js/graphql-modules.svg)](https://www.npmjs.com/package/graphql-modules)
4
7
  ![CI](https://github.com/Urigo/graphql-modules/workflows/CI/badge.svg)
@@ -1,4 +1,5 @@
1
- import { DocumentNode, ExecutionResult, GraphQLSchema } from 'graphql';
1
+ import { DocumentNode, GraphQLSchema } from 'graphql';
2
+ import { ExecutionContextBuilder } from './context';
2
3
  import { Application } from './types';
3
4
  export interface ApolloRequestContext {
4
5
  document: DocumentNode;
@@ -11,20 +12,11 @@ export interface ApolloRequestContext {
11
12
  } | null;
12
13
  };
13
14
  }
14
- export interface ApolloGatewayLoadResult {
15
- executor: ApolloExecutor;
16
- }
17
- export type ApolloExecutor = (requestContext: ApolloRequestContext) => Promise<ExecutionResult>;
18
- export interface ApolloGatewayInterface {
19
- onSchemaLoadOrUpdate(callback: (schemaContext: {
20
- apiSchema: GraphQLSchema;
21
- coreSupergraphSdl: string;
22
- }) => void): () => void;
23
- load(): Promise<ApolloGatewayLoadResult>;
24
- stop(): Promise<void>;
25
- }
26
- export declare function apolloGatewayCreator({ schema, typeDefs, createExecution, }: {
27
- schema: Application['schema'];
28
- typeDefs: Application['typeDefs'];
15
+ export declare function apolloExecutorCreator({ createExecution, }: {
29
16
  createExecution: Application['createExecution'];
30
- }): Application['createApolloGateway'];
17
+ }): Application['createApolloExecutor'];
18
+ export declare function apolloSchemaCreator({ createSubscription, contextBuilder, schema, }: {
19
+ createSubscription: Application['createSubscription'];
20
+ contextBuilder: ExecutionContextBuilder;
21
+ schema: GraphQLSchema;
22
+ }): () => GraphQLSchema;
@@ -3,6 +3,6 @@ import { ExecutionContextBuilder } from './context';
3
3
  export declare function executionCreator({ contextBuilder, }: {
4
4
  contextBuilder: ExecutionContextBuilder;
5
5
  }): (options?: {
6
- execute?: typeof execute | undefined;
7
- controller?: import("./types").OperationController | undefined;
8
- } | undefined) => typeof execute;
6
+ execute?: typeof execute;
7
+ controller?: import("./types").OperationController;
8
+ }) => typeof execute;
@@ -3,6 +3,6 @@ import { ExecutionContextBuilder } from './context';
3
3
  export declare function subscriptionCreator({ contextBuilder, }: {
4
4
  contextBuilder: ExecutionContextBuilder;
5
5
  }): (options?: {
6
- subscribe?: typeof subscribe | undefined;
7
- controller?: import("./types").OperationController | undefined;
8
- } | undefined) => typeof subscribe;
6
+ subscribe?: typeof subscribe;
7
+ controller?: import("./types").OperationController;
8
+ }) => typeof subscribe;
@@ -2,7 +2,7 @@ import { execute, subscribe, DocumentNode, GraphQLSchema, ExecutionResult } from
2
2
  import type { Provider, Injector } from '../di';
3
3
  import type { Resolvers, Module, MockedModule } from '../module/types';
4
4
  import type { MiddlewareMap } from '../shared/middleware';
5
- import type { ApolloGatewayInterface, ApolloRequestContext } from './apollo';
5
+ import type { ApolloRequestContext } from './apollo';
6
6
  import type { Single } from '../shared/types';
7
7
  import type { InternalAppContext } from './application';
8
8
  type Execution = typeof execute;
@@ -56,9 +56,16 @@ export interface Application {
56
56
  execute?: typeof execute;
57
57
  controller?: OperationController;
58
58
  }): Execution;
59
- createApolloGateway(options?: {
59
+ /**
60
+ * @deprecated Use `createApolloExecutor`, `createExecution` and `createSubscription` methods instead.
61
+ */
62
+ createSchemaForApollo(): GraphQLSchema;
63
+ /**
64
+ * Experimental
65
+ */
66
+ createApolloExecutor(options?: {
60
67
  controller?: OperationController;
61
- }): ApolloGatewayInterface;
68
+ }): ApolloExecutor;
62
69
  /**
63
70
  * @internal
64
71
  */
package/di/injector.d.ts CHANGED
@@ -1,10 +1,10 @@
1
- import { Type, InjectionToken, Provider } from './providers';
1
+ import { Type, InjectionToken, Provider, AbstractType } from './providers';
2
2
  import { ResolvedProvider, GlobalProviderMap } from './resolution';
3
3
  import { Key } from './registry';
4
4
  import { ExecutionContext } from './decorators';
5
5
  type ExecutionContextGetter = () => ExecutionContext | never;
6
6
  export declare abstract class Injector {
7
- abstract get<T>(token: Type<T> | InjectionToken<T>, notFoundValue?: any): T;
7
+ abstract get<T>(token: Type<T> | InjectionToken<T> | AbstractType<T>, notFoundValue?: any): T;
8
8
  }
9
9
  export declare class ReflectiveInjector implements Injector {
10
10
  displayName: string;
package/di/providers.d.ts CHANGED
@@ -24,7 +24,7 @@ export interface FactoryProvider<T> extends BaseProvider<T> {
24
24
  deps?: any[];
25
25
  }
26
26
  export interface BaseProvider<T> extends ProviderOptions {
27
- provide: Type<T> | InjectionToken<T>;
27
+ provide: Type<T> | InjectionToken<T> | AbstractType<T>;
28
28
  }
29
29
  export interface TypeProvider<T> extends Type<T> {
30
30
  }
package/index.js CHANGED
@@ -3,8 +3,8 @@
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  const schema = require('@graphql-tools/schema');
6
- const async_hooks = require('async_hooks');
7
6
  const graphql = require('graphql');
7
+ const wrap = require('@graphql-tools/wrap');
8
8
  const ramda = require('ramda');
9
9
 
10
10
  const ERROR_ORIGINAL_ERROR = 'diOriginalError';
@@ -174,85 +174,6 @@ function isFactoryProvider(provider) {
174
174
  return typeof provider.useFactory !== 'undefined';
175
175
  }
176
176
 
177
- const executionContextStore = new Map();
178
- const executionContextDependencyStore = new Map();
179
- const executionContextHook = async_hooks.createHook({
180
- init(asyncId, _, triggerAsyncId) {
181
- var _a;
182
- // Store same context data for child async resources
183
- const ctx = executionContextStore.get(triggerAsyncId);
184
- if (ctx) {
185
- const dependencies = (_a = executionContextDependencyStore.get(triggerAsyncId)) !== null && _a !== void 0 ? _a : executionContextDependencyStore
186
- .set(triggerAsyncId, new Set())
187
- .get(triggerAsyncId);
188
- dependencies.add(asyncId);
189
- executionContextStore.set(asyncId, ctx);
190
- }
191
- },
192
- destroy(asyncId) {
193
- if (executionContextStore.has(asyncId)) {
194
- executionContextStore.delete(asyncId);
195
- }
196
- },
197
- });
198
- function destroyContextAndItsChildren(id) {
199
- if (executionContextStore.has(id)) {
200
- executionContextStore.delete(id);
201
- }
202
- const deps = executionContextDependencyStore.get(id);
203
- if (deps) {
204
- for (const dep of deps) {
205
- destroyContextAndItsChildren(dep);
206
- }
207
- executionContextDependencyStore.delete(id);
208
- }
209
- }
210
- const executionContext = {
211
- create(picker) {
212
- const id = async_hooks.executionAsyncId();
213
- executionContextStore.set(id, picker);
214
- return function destroyContext() {
215
- destroyContextAndItsChildren(id);
216
- };
217
- },
218
- getModuleContext(moduleId) {
219
- const picker = executionContextStore.get(async_hooks.executionAsyncId());
220
- return picker.getModuleContext(moduleId);
221
- },
222
- getApplicationContext() {
223
- const picker = executionContextStore.get(async_hooks.executionAsyncId());
224
- return picker.getApplicationContext();
225
- },
226
- };
227
- function enableExecutionContext() {
228
- {
229
- executionContextHook.enable();
230
- }
231
- }
232
-
233
- const executionContextStore$1 = async_hooks.AsyncLocalStorage
234
- ? new async_hooks.AsyncLocalStorage()
235
- : undefined;
236
- const executionContext$1 = {
237
- create(picker) {
238
- executionContextStore$1.enterWith(picker);
239
- return function destroyContext() { };
240
- },
241
- getModuleContext(moduleId) {
242
- return executionContextStore$1.getStore().getModuleContext(moduleId);
243
- },
244
- getApplicationContext() {
245
- return executionContextStore$1.getStore().getApplicationContext();
246
- },
247
- };
248
-
249
- const executionContext$2 = async_hooks.AsyncLocalStorage
250
- ? executionContext$1
251
- : executionContext;
252
- const enableExecutionContext$1 = async_hooks.AsyncLocalStorage
253
- ? () => undefined
254
- : enableExecutionContext;
255
-
256
177
  function ensureReflect() {
257
178
  if (!(Reflect && Reflect.getOwnMetadata)) {
258
179
  throw 'reflect-metadata shim is required when using class decorators';
@@ -262,7 +183,6 @@ function Injectable(options) {
262
183
  return (target) => {
263
184
  var _a;
264
185
  ensureReflect();
265
- enableExecutionContext$1();
266
186
  const params = (Reflect.getMetadata('design:paramtypes', target) || []).map((param) => (isType(param) ? param : null));
267
187
  const existingMeta = readInjectableMetadata(target);
268
188
  const meta = {
@@ -812,9 +732,9 @@ function tapAsyncIterator(iterable, doneCallback) {
812
732
  throw error;
813
733
  }
814
734
  },
815
- async return() {
735
+ async return(value) {
816
736
  try {
817
- const result = await iterator.return();
737
+ const result = await iterator.return(value);
818
738
  return mapResult(result);
819
739
  }
820
740
  catch (error) {
@@ -822,7 +742,7 @@ function tapAsyncIterator(iterable, doneCallback) {
822
742
  throw error;
823
743
  }
824
744
  },
825
- async throw(error) {
745
+ throw(error) {
826
746
  doneCallback();
827
747
  return iterator.throw(error);
828
748
  },
@@ -849,6 +769,11 @@ function share(factory) {
849
769
  return cached;
850
770
  };
851
771
  }
772
+ function uniqueId(isNotUsed) {
773
+ let id;
774
+ while (!isNotUsed((id = Math.random().toString(16).substr(2)))) { }
775
+ return id;
776
+ }
852
777
  function isNotSchema(obj) {
853
778
  return obj instanceof graphql.GraphQLSchema === false;
854
779
  }
@@ -956,24 +881,17 @@ function createContextBuilder({ appInjector, modulesMap, appLevelOperationProvid
956
881
  return modulesMap.get(moduleId).injector;
957
882
  },
958
883
  });
959
- appInjector.setExecutionContextGetter(executionContext$2.getApplicationContext);
884
+ appInjector.setExecutionContextGetter(function executionContextGetter() {
885
+ return appContext;
886
+ });
960
887
  function createModuleExecutionContextGetter(moduleId) {
961
888
  return function moduleExecutionContextGetter() {
962
- return executionContext$2.getModuleContext(moduleId);
889
+ return getModuleContext(moduleId, context);
963
890
  };
964
891
  }
965
892
  modulesMap.forEach((mod, moduleId) => {
966
893
  mod.injector.setExecutionContextGetter(createModuleExecutionContextGetter(moduleId));
967
894
  });
968
- const executionContextPicker = {
969
- getApplicationContext() {
970
- return appContext;
971
- },
972
- getModuleContext(moduleId) {
973
- return getModuleContext(moduleId, context);
974
- },
975
- };
976
- const destroyExecutionContext = executionContext$2.create(executionContextPicker);
977
895
  // As the name of the Injector says, it's an Operation scoped Injector
978
896
  // Application level
979
897
  // Operation scoped - means it's created and destroyed on every GraphQL Operation
@@ -1047,7 +965,6 @@ function createContextBuilder({ appInjector, modulesMap, appLevelOperationProvid
1047
965
  injector._getObjByKeyId(keyId).onDestroy();
1048
966
  }
1049
967
  });
1050
- destroyExecutionContext();
1051
968
  contextCache = {};
1052
969
  }),
1053
970
  ɵinjector: operationAppInjector,
@@ -1139,33 +1056,78 @@ function subscriptionCreator({ contextBuilder, }) {
1139
1056
  return createSubscription;
1140
1057
  }
1141
1058
 
1142
- function apolloGatewayCreator({ schema, typeDefs, createExecution, }) {
1143
- return function createApolloGateway(options) {
1059
+ const CONTEXT_ID = Symbol.for('context-id');
1060
+ function apolloExecutorCreator({ createExecution, }) {
1061
+ return function createApolloExecutor(options) {
1144
1062
  const executor = createExecution(options);
1145
- return {
1146
- onSchemaLoadOrUpdate(callback) {
1147
- callback({
1148
- apiSchema: schema,
1149
- coreSupergraphSdl: graphql.print(graphql.concatAST(typeDefs)),
1150
- });
1151
- return () => { };
1152
- },
1153
- async load() {
1154
- return {
1155
- async executor(requestContext) {
1156
- return executor({
1157
- schema: requestContext.schema,
1158
- document: requestContext.document,
1159
- operationName: requestContext.operationName,
1160
- variableValues: requestContext.request.variables,
1161
- contextValue: requestContext.context,
1162
- });
1063
+ return async function executorAdapter(requestContext) {
1064
+ return executor({
1065
+ schema: requestContext.schema,
1066
+ document: requestContext.document,
1067
+ operationName: requestContext.operationName,
1068
+ variableValues: requestContext.request.variables,
1069
+ contextValue: requestContext.context,
1070
+ });
1071
+ };
1072
+ };
1073
+ }
1074
+ function apolloSchemaCreator({ createSubscription, contextBuilder, schema, }) {
1075
+ const createApolloSchema = () => {
1076
+ const sessions = {};
1077
+ const subscription = createSubscription();
1078
+ function getSession(ctx) {
1079
+ if (!ctx[CONTEXT_ID]) {
1080
+ ctx[CONTEXT_ID] = uniqueId((id) => !sessions[id]);
1081
+ const { context, ɵdestroy: destroy } = contextBuilder(ctx);
1082
+ sessions[ctx[CONTEXT_ID]] = {
1083
+ count: 0,
1084
+ session: {
1085
+ context,
1086
+ destroy() {
1087
+ if (--sessions[ctx[CONTEXT_ID]].count === 0) {
1088
+ destroy();
1089
+ delete sessions[ctx[CONTEXT_ID]];
1090
+ delete ctx[CONTEXT_ID];
1091
+ }
1092
+ },
1163
1093
  },
1164
1094
  };
1095
+ }
1096
+ sessions[ctx[CONTEXT_ID]].count++;
1097
+ return sessions[ctx[CONTEXT_ID]].session;
1098
+ }
1099
+ return wrap.wrapSchema({
1100
+ schema,
1101
+ batch: true,
1102
+ executor(input) {
1103
+ if (input.operationType === 'subscription') {
1104
+ return subscription({
1105
+ schema,
1106
+ document: input.document,
1107
+ variableValues: input.variables,
1108
+ contextValue: input.context,
1109
+ rootValue: input.rootValue,
1110
+ operationName: input.operationName,
1111
+ });
1112
+ }
1113
+ // Create an execution context
1114
+ const { context, destroy } = getSession(input.context);
1115
+ // It's important to wrap the executeFn within a promise
1116
+ // so we can easily control the end of execution (with finally)
1117
+ return Promise.resolve()
1118
+ .then(() => graphql.execute({
1119
+ schema,
1120
+ document: input.document,
1121
+ contextValue: context,
1122
+ variableValues: input.variables,
1123
+ rootValue: input.rootValue,
1124
+ operationName: input.operationName,
1125
+ }))
1126
+ .finally(destroy);
1165
1127
  },
1166
- async stop() { },
1167
- };
1128
+ });
1168
1129
  };
1130
+ return createApolloSchema;
1169
1131
  }
1170
1132
 
1171
1133
  function operationControllerCreator(options) {
@@ -1262,9 +1224,12 @@ function createApplication(applicationConfig) {
1262
1224
  });
1263
1225
  const createSubscription = subscriptionCreator({ contextBuilder });
1264
1226
  const createExecution = executionCreator({ contextBuilder });
1265
- const createApolloGateway = apolloGatewayCreator({
1227
+ const createSchemaForApollo = apolloSchemaCreator({
1228
+ createSubscription,
1229
+ contextBuilder,
1266
1230
  schema: schema$1,
1267
- typeDefs,
1231
+ });
1232
+ const createApolloExecutor = apolloExecutorCreator({
1268
1233
  createExecution,
1269
1234
  });
1270
1235
  instantiateSingletonProviders({
@@ -1279,7 +1244,8 @@ function createApplication(applicationConfig) {
1279
1244
  createOperationController,
1280
1245
  createSubscription,
1281
1246
  createExecution,
1282
- createApolloGateway,
1247
+ createSchemaForApollo,
1248
+ createApolloExecutor,
1283
1249
  ɵfactory: applicationFactory,
1284
1250
  ɵconfig: config,
1285
1251
  };
@@ -1597,7 +1563,11 @@ function wrapResolver({ resolver, config, path, middlewareMap, isTypeResolver, i
1597
1563
  const wrappedResolver = (root, context, info) => {
1598
1564
  const ctx = {
1599
1565
  root,
1600
- context: context.ɵgetModuleContext(config.id, context),
1566
+ context: isReferenceResolver
1567
+ ? context.ɵgetModuleContext(config.id, context)
1568
+ : // We mark the context object as possibly undefined,
1569
+ // because graphql-jit for some reason doesn't pass it for isTypeOf or resolveType methods
1570
+ context === null || context === void 0 ? void 0 : context.ɵgetModuleContext(config.id, context),
1601
1571
  info,
1602
1572
  };
1603
1573
  return resolver(ctx.root, ctx.context, ctx.info);
@@ -1872,31 +1842,41 @@ function ensureDocumentNode(config, typeDefs) {
1872
1842
  */
1873
1843
  const MODULE_ID = new InjectionToken('module-id');
1874
1844
 
1845
+ function lazy(getter) {
1846
+ let called = false;
1847
+ let computedValue;
1848
+ return {
1849
+ get value() {
1850
+ if (!called) {
1851
+ called = true;
1852
+ computedValue = getter();
1853
+ }
1854
+ return computedValue;
1855
+ },
1856
+ };
1857
+ }
1875
1858
  function moduleFactory(config) {
1876
1859
  const typeDefs = createTypeDefs(config);
1877
1860
  const metadata = metadataFactory(typeDefs, config);
1878
- const providers = typeof config.providers === 'function'
1861
+ const providers = lazy(() => typeof config.providers === 'function'
1879
1862
  ? config.providers()
1880
- : config.providers;
1863
+ : config.providers);
1881
1864
  // Filter providers and keep them this way
1882
1865
  // so we don't do this filtering multiple times.
1883
1866
  // Providers don't change over time, so it's safe to do it.
1884
- const operationProviders = ReflectiveInjector.resolve(onlyOperationProviders(providers));
1885
- const singletonProviders = ReflectiveInjector.resolve(onlySingletonProviders(providers));
1867
+ const operationProviders = lazy(() => ReflectiveInjector.resolve(onlyOperationProviders(providers.value)));
1868
+ const singletonProviders = lazy(() => ReflectiveInjector.resolve(onlySingletonProviders(providers.value)));
1886
1869
  const mod = {
1887
1870
  id: config.id,
1888
1871
  config,
1889
1872
  metadata,
1890
1873
  typeDefs,
1891
- providers,
1892
- operationProviders,
1893
- singletonProviders,
1894
1874
  // Factory is called once on application creation,
1895
1875
  // before we even handle GraphQL Operation
1896
1876
  factory(app) {
1897
1877
  const resolvedModule = mod;
1898
- resolvedModule.singletonProviders = singletonProviders;
1899
- resolvedModule.operationProviders = operationProviders;
1878
+ resolvedModule.singletonProviders = singletonProviders.value;
1879
+ resolvedModule.operationProviders = operationProviders.value;
1900
1880
  // Create a module-level Singleton injector
1901
1881
  const injector = ReflectiveInjector.createFromResolved({
1902
1882
  name: `Module "${config.id}" (Singleton Scope)`,
@@ -1983,8 +1963,11 @@ function mockApplication(app) {
1983
1963
  createExecution(options) {
1984
1964
  return sharedFactory().createExecution(options);
1985
1965
  },
1986
- createApolloGateway() {
1987
- return sharedFactory().createApolloGateway();
1966
+ createSchemaForApollo() {
1967
+ return sharedFactory().createSchemaForApollo();
1968
+ },
1969
+ createApolloExecutor() {
1970
+ return sharedFactory().createApolloExecutor();
1988
1971
  },
1989
1972
  get ɵfactory() {
1990
1973
  return sharedFactory().ɵfactory;
package/index.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  import { makeExecutableSchema } from '@graphql-tools/schema';
2
- import { createHook, executionAsyncId, AsyncLocalStorage } from 'async_hooks';
3
- import { GraphQLSchema, execute as execute$1, subscribe, print, concatAST, visit, Kind, GraphQLScalarType, defaultFieldResolver, parse } from 'graphql';
2
+ import { GraphQLSchema, execute as execute$1, subscribe, visit, Kind, GraphQLScalarType, concatAST, defaultFieldResolver, parse } from 'graphql';
3
+ import { wrapSchema } from '@graphql-tools/wrap';
4
4
  import { mergeDeepWith } from 'ramda';
5
5
 
6
6
  const ERROR_ORIGINAL_ERROR = 'diOriginalError';
@@ -171,85 +171,6 @@ function isFactoryProvider(provider) {
171
171
  return typeof provider.useFactory !== 'undefined';
172
172
  }
173
173
 
174
- const executionContextStore = new Map();
175
- const executionContextDependencyStore = new Map();
176
- const executionContextHook = createHook({
177
- init(asyncId, _, triggerAsyncId) {
178
- var _a;
179
- // Store same context data for child async resources
180
- const ctx = executionContextStore.get(triggerAsyncId);
181
- if (ctx) {
182
- const dependencies = (_a = executionContextDependencyStore.get(triggerAsyncId)) !== null && _a !== void 0 ? _a : executionContextDependencyStore
183
- .set(triggerAsyncId, new Set())
184
- .get(triggerAsyncId);
185
- dependencies.add(asyncId);
186
- executionContextStore.set(asyncId, ctx);
187
- }
188
- },
189
- destroy(asyncId) {
190
- if (executionContextStore.has(asyncId)) {
191
- executionContextStore.delete(asyncId);
192
- }
193
- },
194
- });
195
- function destroyContextAndItsChildren(id) {
196
- if (executionContextStore.has(id)) {
197
- executionContextStore.delete(id);
198
- }
199
- const deps = executionContextDependencyStore.get(id);
200
- if (deps) {
201
- for (const dep of deps) {
202
- destroyContextAndItsChildren(dep);
203
- }
204
- executionContextDependencyStore.delete(id);
205
- }
206
- }
207
- const executionContext = {
208
- create(picker) {
209
- const id = executionAsyncId();
210
- executionContextStore.set(id, picker);
211
- return function destroyContext() {
212
- destroyContextAndItsChildren(id);
213
- };
214
- },
215
- getModuleContext(moduleId) {
216
- const picker = executionContextStore.get(executionAsyncId());
217
- return picker.getModuleContext(moduleId);
218
- },
219
- getApplicationContext() {
220
- const picker = executionContextStore.get(executionAsyncId());
221
- return picker.getApplicationContext();
222
- },
223
- };
224
- function enableExecutionContext() {
225
- {
226
- executionContextHook.enable();
227
- }
228
- }
229
-
230
- const executionContextStore$1 = AsyncLocalStorage
231
- ? new AsyncLocalStorage()
232
- : undefined;
233
- const executionContext$1 = {
234
- create(picker) {
235
- executionContextStore$1.enterWith(picker);
236
- return function destroyContext() { };
237
- },
238
- getModuleContext(moduleId) {
239
- return executionContextStore$1.getStore().getModuleContext(moduleId);
240
- },
241
- getApplicationContext() {
242
- return executionContextStore$1.getStore().getApplicationContext();
243
- },
244
- };
245
-
246
- const executionContext$2 = AsyncLocalStorage
247
- ? executionContext$1
248
- : executionContext;
249
- const enableExecutionContext$1 = AsyncLocalStorage
250
- ? () => undefined
251
- : enableExecutionContext;
252
-
253
174
  function ensureReflect() {
254
175
  if (!(Reflect && Reflect.getOwnMetadata)) {
255
176
  throw 'reflect-metadata shim is required when using class decorators';
@@ -259,7 +180,6 @@ function Injectable(options) {
259
180
  return (target) => {
260
181
  var _a;
261
182
  ensureReflect();
262
- enableExecutionContext$1();
263
183
  const params = (Reflect.getMetadata('design:paramtypes', target) || []).map((param) => (isType(param) ? param : null));
264
184
  const existingMeta = readInjectableMetadata(target);
265
185
  const meta = {
@@ -809,9 +729,9 @@ function tapAsyncIterator(iterable, doneCallback) {
809
729
  throw error;
810
730
  }
811
731
  },
812
- async return() {
732
+ async return(value) {
813
733
  try {
814
- const result = await iterator.return();
734
+ const result = await iterator.return(value);
815
735
  return mapResult(result);
816
736
  }
817
737
  catch (error) {
@@ -819,7 +739,7 @@ function tapAsyncIterator(iterable, doneCallback) {
819
739
  throw error;
820
740
  }
821
741
  },
822
- async throw(error) {
742
+ throw(error) {
823
743
  doneCallback();
824
744
  return iterator.throw(error);
825
745
  },
@@ -846,6 +766,11 @@ function share(factory) {
846
766
  return cached;
847
767
  };
848
768
  }
769
+ function uniqueId(isNotUsed) {
770
+ let id;
771
+ while (!isNotUsed((id = Math.random().toString(16).substr(2)))) { }
772
+ return id;
773
+ }
849
774
  function isNotSchema(obj) {
850
775
  return obj instanceof GraphQLSchema === false;
851
776
  }
@@ -953,24 +878,17 @@ function createContextBuilder({ appInjector, modulesMap, appLevelOperationProvid
953
878
  return modulesMap.get(moduleId).injector;
954
879
  },
955
880
  });
956
- appInjector.setExecutionContextGetter(executionContext$2.getApplicationContext);
881
+ appInjector.setExecutionContextGetter(function executionContextGetter() {
882
+ return appContext;
883
+ });
957
884
  function createModuleExecutionContextGetter(moduleId) {
958
885
  return function moduleExecutionContextGetter() {
959
- return executionContext$2.getModuleContext(moduleId);
886
+ return getModuleContext(moduleId, context);
960
887
  };
961
888
  }
962
889
  modulesMap.forEach((mod, moduleId) => {
963
890
  mod.injector.setExecutionContextGetter(createModuleExecutionContextGetter(moduleId));
964
891
  });
965
- const executionContextPicker = {
966
- getApplicationContext() {
967
- return appContext;
968
- },
969
- getModuleContext(moduleId) {
970
- return getModuleContext(moduleId, context);
971
- },
972
- };
973
- const destroyExecutionContext = executionContext$2.create(executionContextPicker);
974
892
  // As the name of the Injector says, it's an Operation scoped Injector
975
893
  // Application level
976
894
  // Operation scoped - means it's created and destroyed on every GraphQL Operation
@@ -1044,7 +962,6 @@ function createContextBuilder({ appInjector, modulesMap, appLevelOperationProvid
1044
962
  injector._getObjByKeyId(keyId).onDestroy();
1045
963
  }
1046
964
  });
1047
- destroyExecutionContext();
1048
965
  contextCache = {};
1049
966
  }),
1050
967
  ɵinjector: operationAppInjector,
@@ -1136,33 +1053,78 @@ function subscriptionCreator({ contextBuilder, }) {
1136
1053
  return createSubscription;
1137
1054
  }
1138
1055
 
1139
- function apolloGatewayCreator({ schema, typeDefs, createExecution, }) {
1140
- return function createApolloGateway(options) {
1056
+ const CONTEXT_ID = Symbol.for('context-id');
1057
+ function apolloExecutorCreator({ createExecution, }) {
1058
+ return function createApolloExecutor(options) {
1141
1059
  const executor = createExecution(options);
1142
- return {
1143
- onSchemaLoadOrUpdate(callback) {
1144
- callback({
1145
- apiSchema: schema,
1146
- coreSupergraphSdl: print(concatAST(typeDefs)),
1147
- });
1148
- return () => { };
1149
- },
1150
- async load() {
1151
- return {
1152
- async executor(requestContext) {
1153
- return executor({
1154
- schema: requestContext.schema,
1155
- document: requestContext.document,
1156
- operationName: requestContext.operationName,
1157
- variableValues: requestContext.request.variables,
1158
- contextValue: requestContext.context,
1159
- });
1060
+ return async function executorAdapter(requestContext) {
1061
+ return executor({
1062
+ schema: requestContext.schema,
1063
+ document: requestContext.document,
1064
+ operationName: requestContext.operationName,
1065
+ variableValues: requestContext.request.variables,
1066
+ contextValue: requestContext.context,
1067
+ });
1068
+ };
1069
+ };
1070
+ }
1071
+ function apolloSchemaCreator({ createSubscription, contextBuilder, schema, }) {
1072
+ const createApolloSchema = () => {
1073
+ const sessions = {};
1074
+ const subscription = createSubscription();
1075
+ function getSession(ctx) {
1076
+ if (!ctx[CONTEXT_ID]) {
1077
+ ctx[CONTEXT_ID] = uniqueId((id) => !sessions[id]);
1078
+ const { context, ɵdestroy: destroy } = contextBuilder(ctx);
1079
+ sessions[ctx[CONTEXT_ID]] = {
1080
+ count: 0,
1081
+ session: {
1082
+ context,
1083
+ destroy() {
1084
+ if (--sessions[ctx[CONTEXT_ID]].count === 0) {
1085
+ destroy();
1086
+ delete sessions[ctx[CONTEXT_ID]];
1087
+ delete ctx[CONTEXT_ID];
1088
+ }
1089
+ },
1160
1090
  },
1161
1091
  };
1092
+ }
1093
+ sessions[ctx[CONTEXT_ID]].count++;
1094
+ return sessions[ctx[CONTEXT_ID]].session;
1095
+ }
1096
+ return wrapSchema({
1097
+ schema,
1098
+ batch: true,
1099
+ executor(input) {
1100
+ if (input.operationType === 'subscription') {
1101
+ return subscription({
1102
+ schema,
1103
+ document: input.document,
1104
+ variableValues: input.variables,
1105
+ contextValue: input.context,
1106
+ rootValue: input.rootValue,
1107
+ operationName: input.operationName,
1108
+ });
1109
+ }
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);
1162
1124
  },
1163
- async stop() { },
1164
- };
1125
+ });
1165
1126
  };
1127
+ return createApolloSchema;
1166
1128
  }
1167
1129
 
1168
1130
  function operationControllerCreator(options) {
@@ -1259,9 +1221,12 @@ function createApplication(applicationConfig) {
1259
1221
  });
1260
1222
  const createSubscription = subscriptionCreator({ contextBuilder });
1261
1223
  const createExecution = executionCreator({ contextBuilder });
1262
- const createApolloGateway = apolloGatewayCreator({
1224
+ const createSchemaForApollo = apolloSchemaCreator({
1225
+ createSubscription,
1226
+ contextBuilder,
1263
1227
  schema,
1264
- typeDefs,
1228
+ });
1229
+ const createApolloExecutor = apolloExecutorCreator({
1265
1230
  createExecution,
1266
1231
  });
1267
1232
  instantiateSingletonProviders({
@@ -1276,7 +1241,8 @@ function createApplication(applicationConfig) {
1276
1241
  createOperationController,
1277
1242
  createSubscription,
1278
1243
  createExecution,
1279
- createApolloGateway,
1244
+ createSchemaForApollo,
1245
+ createApolloExecutor,
1280
1246
  ɵfactory: applicationFactory,
1281
1247
  ɵconfig: config,
1282
1248
  };
@@ -1594,7 +1560,11 @@ function wrapResolver({ resolver, config, path, middlewareMap, isTypeResolver, i
1594
1560
  const wrappedResolver = (root, context, info) => {
1595
1561
  const ctx = {
1596
1562
  root,
1597
- context: context.ɵgetModuleContext(config.id, context),
1563
+ context: isReferenceResolver
1564
+ ? context.ɵgetModuleContext(config.id, context)
1565
+ : // We mark the context object as possibly undefined,
1566
+ // because graphql-jit for some reason doesn't pass it for isTypeOf or resolveType methods
1567
+ context === null || context === void 0 ? void 0 : context.ɵgetModuleContext(config.id, context),
1598
1568
  info,
1599
1569
  };
1600
1570
  return resolver(ctx.root, ctx.context, ctx.info);
@@ -1869,31 +1839,41 @@ function ensureDocumentNode(config, typeDefs) {
1869
1839
  */
1870
1840
  const MODULE_ID = new InjectionToken('module-id');
1871
1841
 
1842
+ function lazy(getter) {
1843
+ let called = false;
1844
+ let computedValue;
1845
+ return {
1846
+ get value() {
1847
+ if (!called) {
1848
+ called = true;
1849
+ computedValue = getter();
1850
+ }
1851
+ return computedValue;
1852
+ },
1853
+ };
1854
+ }
1872
1855
  function moduleFactory(config) {
1873
1856
  const typeDefs = createTypeDefs(config);
1874
1857
  const metadata = metadataFactory(typeDefs, config);
1875
- const providers = typeof config.providers === 'function'
1858
+ const providers = lazy(() => typeof config.providers === 'function'
1876
1859
  ? config.providers()
1877
- : config.providers;
1860
+ : config.providers);
1878
1861
  // Filter providers and keep them this way
1879
1862
  // so we don't do this filtering multiple times.
1880
1863
  // Providers don't change over time, so it's safe to do it.
1881
- const operationProviders = ReflectiveInjector.resolve(onlyOperationProviders(providers));
1882
- const singletonProviders = ReflectiveInjector.resolve(onlySingletonProviders(providers));
1864
+ const operationProviders = lazy(() => ReflectiveInjector.resolve(onlyOperationProviders(providers.value)));
1865
+ const singletonProviders = lazy(() => ReflectiveInjector.resolve(onlySingletonProviders(providers.value)));
1883
1866
  const mod = {
1884
1867
  id: config.id,
1885
1868
  config,
1886
1869
  metadata,
1887
1870
  typeDefs,
1888
- providers,
1889
- operationProviders,
1890
- singletonProviders,
1891
1871
  // Factory is called once on application creation,
1892
1872
  // before we even handle GraphQL Operation
1893
1873
  factory(app) {
1894
1874
  const resolvedModule = mod;
1895
- resolvedModule.singletonProviders = singletonProviders;
1896
- resolvedModule.operationProviders = operationProviders;
1875
+ resolvedModule.singletonProviders = singletonProviders.value;
1876
+ resolvedModule.operationProviders = operationProviders.value;
1897
1877
  // Create a module-level Singleton injector
1898
1878
  const injector = ReflectiveInjector.createFromResolved({
1899
1879
  name: `Module "${config.id}" (Singleton Scope)`,
@@ -1980,8 +1960,11 @@ function mockApplication(app) {
1980
1960
  createExecution(options) {
1981
1961
  return sharedFactory().createExecution(options);
1982
1962
  },
1983
- createApolloGateway() {
1984
- return sharedFactory().createApolloGateway();
1963
+ createSchemaForApollo() {
1964
+ return sharedFactory().createSchemaForApollo();
1965
+ },
1966
+ createApolloExecutor() {
1967
+ return sharedFactory().createApolloExecutor();
1985
1968
  },
1986
1969
  get ɵfactory() {
1987
1970
  return sharedFactory().ɵfactory;
package/module/types.d.ts CHANGED
@@ -4,7 +4,6 @@ import { ID, Plural } from '../shared/types';
4
4
  import { ModuleMetadata } from './metadata';
5
5
  import { Provider } from '../di';
6
6
  import { MiddlewareMap } from '../shared/middleware';
7
- import { ResolvedProvider } from '../di/resolution';
8
7
  export type TypeDefs = Plural<DocumentNode>;
9
8
  export type Resolvers = Plural<Record<string, any>>;
10
9
  /**
@@ -39,12 +38,9 @@ export interface ModuleConfig {
39
38
  }
40
39
  export interface Module {
41
40
  id: ID;
42
- providers?: Provider[];
43
41
  typeDefs: DocumentNode[];
44
42
  metadata: ModuleMetadata;
45
43
  factory: ModuleFactory;
46
- operationProviders: ResolvedProvider[];
47
- singletonProviders: ResolvedProvider[];
48
44
  config: ModuleConfig;
49
45
  }
50
46
  export interface MockedModule extends Module {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "graphql-modules",
3
- "version": "3.0.0-alpha-20231018163544-36199b68",
3
+ "version": "3.0.0-alpha-20250219090434-d6cc8940d97c7ef3dba3f59c56376d7cbab77c83",
4
4
  "description": "Create reusable, maintainable, testable and extendable GraphQL modules",
5
5
  "sideEffects": false,
6
6
  "peerDependencies": {
@@ -8,8 +8,9 @@
8
8
  },
9
9
  "dependencies": {
10
10
  "@graphql-tools/schema": "^10.0.0",
11
+ "@graphql-tools/wrap": "^10.0.0",
11
12
  "@graphql-typed-document-node/core": "^3.1.0",
12
- "ramda": "^0.29.0"
13
+ "ramda": "^0.30.0"
13
14
  },
14
15
  "keywords": [
15
16
  "graphql",
@@ -16,6 +16,6 @@ export type MiddlewareMap = {
16
16
  [field: string]: Middleware[];
17
17
  };
18
18
  };
19
- export declare function createMiddleware(path: string[], middlewareMap?: MiddlewareMap): (context: MiddlewareContext, next: Next<any>) => Promise<any>;
19
+ export declare function createMiddleware(path: string[], middlewareMap?: MiddlewareMap): (context: MiddlewareContext, next: Next) => Promise<any>;
20
20
  export declare function mergeMiddlewareMaps(app: MiddlewareMap, mod: MiddlewareMap): MiddlewareMap;
21
21
  export declare function validateMiddlewareMap(middlewareMap: MiddlewareMap, metadata: ModuleMetadata): void;
package/shared/utils.d.ts CHANGED
@@ -4,7 +4,7 @@ export declare function isNil<T>(val: T | null | undefined): val is null | undef
4
4
  export declare function isObject(val: any): boolean;
5
5
  export declare function isPrimitive(val: any): val is number | string | boolean | symbol | bigint;
6
6
  export declare function isAsyncIterable(obj: any): obj is AsyncIterableIterator<any>;
7
- export declare function tapAsyncIterator<T>(iterable: AsyncIterable<T>, doneCallback: () => void): AsyncGenerator<T>;
7
+ export declare function tapAsyncIterator<T, TAsyncIterableIterator extends AsyncIterableIterator<T>>(iterable: TAsyncIterableIterator, doneCallback: () => void): TAsyncIterableIterator;
8
8
  export declare function once(cb: () => void): () => void;
9
9
  export declare function share<T, A>(factory: (arg?: A) => T): (arg?: A) => T;
10
10
  export declare function uniqueId(isNotUsed: (id: string) => boolean): string;
@@ -1,10 +0,0 @@
1
- /// <reference types="node" />
2
- import { AsyncLocalStorage } from 'async_hooks';
3
- import { type ExecutionContextPicker } from './execution-context.interface';
4
- export declare const executionContext: {
5
- create(picker: ExecutionContextPicker): () => void;
6
- getModuleContext: ExecutionContextPicker['getModuleContext'];
7
- getApplicationContext: ExecutionContextPicker['getApplicationContext'];
8
- };
9
- export declare function enableExecutionContext(): void;
10
- export declare function getExecutionContextStore(): AsyncLocalStorage<ExecutionContextPicker> | undefined;
@@ -1,9 +0,0 @@
1
- import { type ExecutionContextPicker } from './execution-context.interface';
2
- export declare const executionContext: {
3
- create(picker: ExecutionContextPicker): () => void;
4
- getModuleContext: ExecutionContextPicker['getModuleContext'];
5
- getApplicationContext: ExecutionContextPicker['getApplicationContext'];
6
- };
7
- export declare function enableExecutionContext(): void;
8
- export declare function getExecutionContextStore(): Map<number, ExecutionContextPicker>;
9
- export declare function getExecutionContextDependencyStore(): Map<number, Set<number>>;
@@ -1,8 +0,0 @@
1
- import * as Hooks from './execution-context-hooks';
2
- export type { ExecutionContextPicker } from './execution-context.interface';
3
- export declare const executionContext: {
4
- create(picker: import("./execution-context.interface").ExecutionContextPicker): () => void;
5
- getModuleContext: (moduleId: string) => GraphQLModules.ModuleContext;
6
- getApplicationContext: () => GraphQLModules.AppContext;
7
- };
8
- export declare const enableExecutionContext: typeof Hooks.enableExecutionContext;
@@ -1,4 +0,0 @@
1
- export interface ExecutionContextPicker {
2
- getModuleContext(moduleId: string): GraphQLModules.ModuleContext;
3
- getApplicationContext(): GraphQLModules.AppContext;
4
- }