graphql-modules
Version:
Create reusable, maintainable, testable and extendable GraphQL modules
72 lines (71 loc) • 2.99 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.moduleFactory = moduleFactory;
const metadata_1 = require("./metadata");
const resolvers_1 = require("./resolvers");
const type_defs_1 = require("./type-defs");
const tokens_1 = require("./tokens");
const di_1 = require("../di");
const resolution_1 = require("./../di/resolution");
function lazy(getter) {
let called = false;
let computedValue;
return {
get value() {
if (!called) {
called = true;
computedValue = getter();
}
return computedValue;
},
};
}
function moduleFactory(config) {
const typeDefs = (0, type_defs_1.createTypeDefs)(config);
const metadata = (0, metadata_1.metadataFactory)(typeDefs, config);
const providers = lazy(() => typeof config.providers === 'function'
? config.providers()
: config.providers);
// Filter providers and keep them this way
// so we don't do this filtering multiple times.
// Providers don't change over time, so it's safe to do it.
const operationProviders = lazy(() => di_1.ReflectiveInjector.resolve((0, di_1.onlyOperationProviders)(providers.value)));
const singletonProviders = lazy(() => di_1.ReflectiveInjector.resolve((0, di_1.onlySingletonProviders)(providers.value)));
const mod = {
id: config.id,
config,
metadata,
typeDefs,
// Factory is called once on application creation,
// before we even handle GraphQL Operation
factory(app) {
const resolvedModule = mod;
resolvedModule.singletonProviders = singletonProviders.value;
resolvedModule.operationProviders = operationProviders.value;
// Create a module-level Singleton injector
const injector = di_1.ReflectiveInjector.createFromResolved({
name: `Module "${config.id}" (Singleton Scope)`,
providers: resolvedModule.singletonProviders.concat((0, resolution_1.resolveProviders)([
{
// with module's id, useful in Logging and stuff
provide: tokens_1.MODULE_ID,
useValue: config.id,
},
])),
parent: app.injector,
});
// We attach injector property to existing `mod` object
// because we want to keep references
// that are later on used in testing utils
resolvedModule.injector = injector;
// Create resolvers object based on module's config
// It involves wrapping a resolver with middlewares
// and other things like validation
resolvedModule.resolvers = (0, resolvers_1.createResolvers)(config, metadata, {
middlewareMap: app.middlewares,
});
return resolvedModule;
},
};
return mod;
}