graphql-modules
Version:
Create reusable, maintainable, testable and extendable GraphQL modules
167 lines (166 loc) • 5.68 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.Dependency = exports.ResolvedFactory = exports.ResolvedProvider = void 0;
exports.resolveProviders = resolveProviders;
const providers_1 = require("./providers");
const errors_1 = require("./errors");
const registry_1 = require("./registry");
const forward_ref_1 = require("./forward-ref");
const metadata_1 = require("./metadata");
const _EMPTY_LIST = [];
class ResolvedProvider {
constructor(key, factory) {
this.key = key;
this.factory = factory;
}
}
exports.ResolvedProvider = ResolvedProvider;
class ResolvedFactory {
constructor(
/**
* Factory function which can return an instance of an object represented by a key.
*/
factory,
/**
* Arguments (dependencies) to the `factory` function.
*/
dependencies,
/**
* Methods invoked within ExecutionContext.
*/
executionContextIn,
/**
* Has onDestroy hook
*/
hasOnDestroyHook,
/**
* Is Global
*/
isGlobal) {
this.factory = factory;
this.dependencies = dependencies;
this.executionContextIn = executionContextIn;
this.hasOnDestroyHook = hasOnDestroyHook;
this.isGlobal = isGlobal;
}
}
exports.ResolvedFactory = ResolvedFactory;
class Dependency {
constructor(key, optional) {
this.key = key;
this.optional = optional;
}
static fromKey(key) {
return new Dependency(key, false);
}
}
exports.Dependency = Dependency;
function resolveProviders(providers) {
const normalized = normalizeProviders(providers, []);
const resolved = normalized.map(resolveProvider);
const resolvedProviderMap = mergeResolvedProviders(resolved, new Map());
return Array.from(resolvedProviderMap.values());
}
function resolveProvider(provider) {
return new ResolvedProvider(registry_1.Key.get(provider.provide), resolveFactory(provider));
}
function mergeResolvedProviders(providers, normalizedProvidersMap) {
for (let i = 0; i < providers.length; i++) {
const provider = providers[i];
normalizedProvidersMap.set(provider.key.id, provider);
}
return normalizedProvidersMap;
}
function normalizeProviders(providers, res) {
providers.forEach((token) => {
if (token instanceof providers_1.Type) {
res.push({ provide: token, useClass: token });
}
else if (token &&
typeof token === 'object' &&
token.provide !== undefined) {
res.push(token);
}
else if (token instanceof Array) {
normalizeProviders(token, res);
}
else {
throw (0, errors_1.invalidProviderError)(token);
}
});
return res;
}
function resolveFactory(provider) {
let factoryFn;
let resolvedDeps = _EMPTY_LIST;
let executionContextIn = _EMPTY_LIST;
let hasOnDestroyHook = false;
let isGlobal;
if ((0, providers_1.isClassProvider)(provider)) {
const useClass = (0, forward_ref_1.resolveForwardRef)(provider.useClass);
factoryFn = makeFactory(useClass);
resolvedDeps = dependenciesFor(useClass);
executionContextIn = executionContextInFor(useClass);
isGlobal = globalFor(useClass);
hasOnDestroyHook = typeof useClass.prototype.onDestroy === 'function';
}
else if ((0, providers_1.isFactoryProvider)(provider)) {
factoryFn = provider.useFactory;
resolvedDeps = constructDependencies(provider.useFactory, provider.deps || []);
isGlobal = provider.global;
if (provider.executionContextIn) {
executionContextIn = provider.executionContextIn;
}
}
else {
factoryFn = () => provider.useValue;
resolvedDeps = _EMPTY_LIST;
isGlobal = provider.global;
}
return new ResolvedFactory(factoryFn, resolvedDeps, executionContextIn, hasOnDestroyHook, isGlobal !== null && isGlobal !== void 0 ? isGlobal : false);
}
function dependenciesFor(type) {
const { params } = (0, metadata_1.readInjectableMetadata)(type, true);
if (!params) {
return [];
}
if (params.some((p) => p.type == null)) {
throw (0, errors_1.noAnnotationError)(type, params);
}
return params.map((p) => extractToken(p, params));
}
function executionContextInFor(type) {
const { options } = (0, metadata_1.readInjectableMetadata)(type, true);
if ((options === null || options === void 0 ? void 0 : options.executionContextIn) &&
options.executionContextIn !== _EMPTY_LIST) {
return options === null || options === void 0 ? void 0 : options.executionContextIn;
}
return [];
}
function globalFor(type) {
var _a;
const { options } = (0, metadata_1.readInjectableMetadata)(type);
return (_a = options === null || options === void 0 ? void 0 : options.global) !== null && _a !== void 0 ? _a : false;
}
function constructDependencies(typeOrFunc, dependencies) {
if (!dependencies) {
return dependenciesFor(typeOrFunc);
}
else {
const params = dependencies.map((d) => ({ type: d, optional: false }));
return params.map((t) => extractToken(t, params));
}
}
function extractToken(param, params) {
const token = (0, forward_ref_1.resolveForwardRef)(param.type);
if (token) {
return createDependency(token, param.optional);
}
throw (0, errors_1.noAnnotationError)(param.type, params);
}
function createDependency(token, optional) {
return new Dependency(registry_1.Key.get(token), optional);
}
function makeFactory(t) {
return (...args) => new t(...args);
}