Skip to content

Commit f40de70

Browse files
authored
Lazy module providers (#2563)
BREAKING Providers of each module are now resolved of upon application creation. This makes Dependency Injection less strict and not dependent on the order of module imports (hello circular imports). BREAKING Removed providers, operationProviders and singletonProviders from the Module interface (unlikely you were using them).
1 parent ec6354c commit f40de70

File tree

3 files changed

+34
-15
lines changed

3 files changed

+34
-15
lines changed

Diff for: .changeset/orange-geese-hide.md

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
---
2+
'graphql-modules': major
3+
---
4+
5+
**BREAKING** Providers of each module are now resolved of upon application creation.
6+
7+
This makes Dependency Injection less strict and not dependent on the order of module imports (hello circular imports).
8+
9+
**BREAKING** Removed `providers`, `operationProviders` and `singletonProviders` from the `Module` interface (unlikely you were using them).

Diff for: packages/graphql-modules/src/module/factory.ts

+25-11
Original file line numberDiff line numberDiff line change
@@ -24,38 +24,52 @@ export type ModuleFactory = (app: {
2424
middlewares: MiddlewareMap;
2525
}) => ResolvedModule;
2626

27+
function lazy<T>(getter: () => T) {
28+
let called = false;
29+
let computedValue: T;
30+
31+
return {
32+
get value() {
33+
if (!called) {
34+
called = true;
35+
computedValue = getter();
36+
}
37+
38+
return computedValue;
39+
},
40+
};
41+
}
42+
2743
export function moduleFactory(config: ModuleConfig): Module {
2844
const typeDefs = createTypeDefs(config);
2945
const metadata = metadataFactory(typeDefs, config);
30-
const providers =
46+
const providers = lazy(() =>
3147
typeof config.providers === 'function'
3248
? config.providers()
33-
: config.providers;
49+
: config.providers
50+
);
3451

3552
// Filter providers and keep them this way
3653
// so we don't do this filtering multiple times.
3754
// Providers don't change over time, so it's safe to do it.
38-
const operationProviders = ReflectiveInjector.resolve(
39-
onlyOperationProviders(providers)
55+
const operationProviders = lazy(() =>
56+
ReflectiveInjector.resolve(onlyOperationProviders(providers.value))
4057
);
41-
const singletonProviders = ReflectiveInjector.resolve(
42-
onlySingletonProviders(providers)
58+
const singletonProviders = lazy(() =>
59+
ReflectiveInjector.resolve(onlySingletonProviders(providers.value))
4360
);
4461

4562
const mod: Module = {
4663
id: config.id,
4764
config,
4865
metadata,
4966
typeDefs,
50-
providers,
51-
operationProviders,
52-
singletonProviders,
5367
// Factory is called once on application creation,
5468
// before we even handle GraphQL Operation
5569
factory(app) {
5670
const resolvedModule: Partial<ResolvedModule> = mod;
57-
resolvedModule.singletonProviders = singletonProviders;
58-
resolvedModule.operationProviders = operationProviders;
71+
resolvedModule.singletonProviders = singletonProviders.value;
72+
resolvedModule.operationProviders = operationProviders.value;
5973

6074
// Create a module-level Singleton injector
6175
const injector = ReflectiveInjector.createFromResolved({

Diff for: packages/graphql-modules/src/module/types.ts

-4
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import { ID, Plural } from '../shared/types';
44
import { ModuleMetadata } from './metadata';
55
import { Provider } from '../di';
66
import { MiddlewareMap } from '../shared/middleware';
7-
import { ResolvedProvider } from '../di/resolution';
87

98
export type TypeDefs = Plural<DocumentNode>;
109
export type Resolvers = Plural<Record<string, any>>;
@@ -42,12 +41,9 @@ export interface ModuleConfig {
4241

4342
export interface Module {
4443
id: ID;
45-
providers?: Provider[];
4644
typeDefs: DocumentNode[];
4745
metadata: ModuleMetadata;
4846
factory: ModuleFactory;
49-
operationProviders: ResolvedProvider[];
50-
singletonProviders: ResolvedProvider[];
5147
config: ModuleConfig;
5248
}
5349

0 commit comments

Comments
 (0)