graphql-modules 3.1.2-alpha-20260121023952-c6236f99446644c787494ddb1a9a973180bab70e → 3.1.2-alpha-20260121024633-8af430e29a180a1d00c50c4bf74d342b3518267c
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/cjs/application/apollo.js +81 -0
- package/cjs/application/application.js +149 -0
- package/cjs/application/context.js +144 -0
- package/cjs/application/di.js +48 -0
- package/cjs/application/execution.js +42 -0
- package/cjs/application/operation-controller.js +16 -0
- package/cjs/application/subscription.js +54 -0
- package/cjs/application/tokens.js +20 -0
- package/cjs/application/types.js +0 -0
- package/cjs/di/decorators.js +78 -0
- package/cjs/di/errors.js +87 -0
- package/cjs/di/forward-ref.js +26 -0
- package/cjs/di/index.js +19 -0
- package/cjs/di/injector.js +173 -0
- package/cjs/di/metadata.js +22 -0
- package/cjs/di/providers.js +60 -0
- package/cjs/di/registry.js +44 -0
- package/cjs/di/resolution.js +166 -0
- package/cjs/di/utils.js +44 -0
- package/cjs/index.js +31 -0
- package/cjs/module/factory.js +71 -0
- package/cjs/module/metadata.js +110 -0
- package/cjs/module/module.js +27 -0
- package/cjs/module/resolvers.js +341 -0
- package/cjs/module/tokens.js +21 -0
- package/cjs/module/type-defs.js +24 -0
- package/cjs/module/types.js +0 -0
- package/cjs/package.json +1 -0
- package/cjs/shared/di.js +0 -0
- package/cjs/shared/errors.js +82 -0
- package/cjs/shared/gql.js +12 -0
- package/cjs/shared/middleware.js +109 -0
- package/cjs/shared/types.js +0 -0
- package/cjs/shared/utils.js +115 -0
- package/cjs/testing/di.js +9 -0
- package/cjs/testing/graphql.js +10 -0
- package/cjs/testing/index.js +17 -0
- package/cjs/testing/test-application.js +65 -0
- package/cjs/testing/test-injector.js +22 -0
- package/cjs/testing/test-module.js +270 -0
- package/esm/application/apollo.js +77 -0
- package/esm/application/application.js +146 -0
- package/esm/application/context.js +140 -0
- package/esm/application/di.js +42 -0
- package/esm/application/execution.js +39 -0
- package/esm/application/operation-controller.js +13 -0
- package/esm/application/subscription.js +51 -0
- package/esm/application/tokens.js +17 -0
- package/esm/application/types.js +0 -0
- package/esm/di/decorators.js +72 -0
- package/esm/di/errors.js +79 -0
- package/esm/di/forward-ref.js +22 -0
- package/esm/di/index.js +4 -0
- package/esm/di/injector.js +168 -0
- package/esm/di/metadata.js +17 -0
- package/esm/di/providers.js +50 -0
- package/esm/di/registry.js +40 -0
- package/esm/di/resolution.js +159 -0
- package/esm/di/utils.js +36 -0
- package/esm/index.js +16 -0
- package/esm/module/factory.js +68 -0
- package/esm/module/metadata.js +107 -0
- package/esm/module/module.js +24 -0
- package/esm/module/resolvers.js +337 -0
- package/esm/module/tokens.js +18 -0
- package/esm/module/type-defs.js +21 -0
- package/esm/module/types.js +0 -0
- package/esm/shared/di.js +0 -0
- package/esm/shared/errors.js +69 -0
- package/esm/shared/gql.js +9 -0
- package/esm/shared/middleware.js +103 -0
- package/esm/shared/types.js +0 -0
- package/esm/shared/utils.js +101 -0
- package/esm/testing/di.js +6 -0
- package/esm/testing/graphql.js +7 -0
- package/esm/testing/index.js +14 -0
- package/esm/testing/test-application.js +62 -0
- package/esm/testing/test-injector.js +18 -0
- package/esm/testing/test-module.js +266 -0
- package/package.json +29 -9
- package/typings/application/apollo.d.ts +22 -0
- package/typings/application/application.d.ts +32 -0
- package/typings/application/context.d.ts +24 -0
- package/typings/application/di.d.ts +22 -0
- package/typings/application/execution.d.ts +8 -0
- package/typings/application/operation-controller.d.ts +5 -0
- package/typings/application/subscription.d.ts +8 -0
- package/typings/application/tokens.d.ts +17 -0
- package/typings/application/types.d.ts +130 -0
- package/typings/di/decorators.d.ts +11 -0
- package/typings/di/errors.d.ts +16 -0
- package/typings/di/forward-ref.d.ts +7 -0
- package/typings/di/index.d.ts +5 -0
- package/typings/di/injector.d.ts +50 -0
- package/typings/di/metadata.d.ts +12 -0
- package/typings/di/providers.d.ts +44 -0
- package/typings/di/registry.d.ts +11 -0
- package/typings/di/resolution.d.ts +63 -0
- package/typings/di/utils.d.ts +8 -0
- package/typings/index.d.ts +13 -0
- package/typings/module/factory.d.ts +16 -0
- package/typings/module/metadata.d.ts +12 -0
- package/typings/module/module.d.ts +22 -0
- package/typings/module/resolvers.d.ts +13 -0
- package/typings/module/tokens.d.ts +18 -0
- package/typings/module/type-defs.d.ts +7 -0
- package/typings/module/types.d.ts +51 -0
- package/typings/shared/di.d.ts +3 -0
- package/typings/shared/errors.d.ts +36 -0
- package/typings/shared/gql.d.ts +2 -0
- package/typings/shared/middleware.d.ts +21 -0
- package/typings/shared/types.d.ts +22 -0
- package/typings/shared/utils.d.ts +12 -0
- package/typings/testing/di.d.ts +2 -0
- package/typings/testing/graphql.d.ts +14 -0
- package/typings/testing/index.d.ts +14 -0
- package/typings/testing/test-application.d.ts +2 -0
- package/typings/testing/test-injector.d.ts +4 -0
- package/typings/testing/test-module.d.ts +10 -0
- package/LICENSE.md +0 -21
- package/index.js +0 -2359
- package/index.mjs +0 -2344
- /package/{application/apollo.d.ts → typings/application/apollo.d.cts} +0 -0
- /package/{application/application.d.ts → typings/application/application.d.cts} +0 -0
- /package/{application/context.d.ts → typings/application/context.d.cts} +0 -0
- /package/{application/di.d.ts → typings/application/di.d.cts} +0 -0
- /package/{application/execution.d.ts → typings/application/execution.d.cts} +0 -0
- /package/{application/operation-controller.d.ts → typings/application/operation-controller.d.cts} +0 -0
- /package/{application/subscription.d.ts → typings/application/subscription.d.cts} +0 -0
- /package/{application/tokens.d.ts → typings/application/tokens.d.cts} +0 -0
- /package/{application/types.d.ts → typings/application/types.d.cts} +0 -0
- /package/{di/decorators.d.ts → typings/di/decorators.d.cts} +0 -0
- /package/{di/errors.d.ts → typings/di/errors.d.cts} +0 -0
- /package/{di/forward-ref.d.ts → typings/di/forward-ref.d.cts} +0 -0
- /package/{di/index.d.ts → typings/di/index.d.cts} +0 -0
- /package/{di/injector.d.ts → typings/di/injector.d.cts} +0 -0
- /package/{di/metadata.d.ts → typings/di/metadata.d.cts} +0 -0
- /package/{di/providers.d.ts → typings/di/providers.d.cts} +0 -0
- /package/{di/registry.d.ts → typings/di/registry.d.cts} +0 -0
- /package/{di/resolution.d.ts → typings/di/resolution.d.cts} +0 -0
- /package/{di/utils.d.ts → typings/di/utils.d.cts} +0 -0
- /package/{index.d.ts → typings/index.d.cts} +0 -0
- /package/{module/factory.d.ts → typings/module/factory.d.cts} +0 -0
- /package/{module/metadata.d.ts → typings/module/metadata.d.cts} +0 -0
- /package/{module/module.d.ts → typings/module/module.d.cts} +0 -0
- /package/{module/resolvers.d.ts → typings/module/resolvers.d.cts} +0 -0
- /package/{module/tokens.d.ts → typings/module/tokens.d.cts} +0 -0
- /package/{module/type-defs.d.ts → typings/module/type-defs.d.cts} +0 -0
- /package/{module/types.d.ts → typings/module/types.d.cts} +0 -0
- /package/{shared/di.d.ts → typings/shared/di.d.cts} +0 -0
- /package/{shared/errors.d.ts → typings/shared/errors.d.cts} +0 -0
- /package/{shared/gql.d.ts → typings/shared/gql.d.cts} +0 -0
- /package/{shared/middleware.d.ts → typings/shared/middleware.d.cts} +0 -0
- /package/{shared/types.d.ts → typings/shared/types.d.cts} +0 -0
- /package/{shared/utils.d.ts → typings/shared/utils.d.cts} +0 -0
- /package/{testing/di.d.ts → typings/testing/di.d.cts} +0 -0
- /package/{testing/graphql.d.ts → typings/testing/graphql.d.cts} +0 -0
- /package/{testing/index.d.ts → typings/testing/index.d.cts} +0 -0
- /package/{testing/test-application.d.ts → typings/testing/test-application.d.cts} +0 -0
- /package/{testing/test-injector.d.ts → typings/testing/test-injector.d.cts} +0 -0
- /package/{testing/test-module.d.ts → typings/testing/test-module.d.cts} +0 -0
package/esm/di/errors.js
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { stringify, wrappedError, ERROR_ORIGINAL_ERROR, getOriginalError, } from './utils';
|
|
2
|
+
export function invalidProviderError(provider) {
|
|
3
|
+
return Error(`Invalid provider - only instances of Provider and Type are allowed, got: ${provider}`);
|
|
4
|
+
}
|
|
5
|
+
export function noInjectableError(type) {
|
|
6
|
+
return Error(`Missing @Injectable decorator for '${stringify(type)}'`);
|
|
7
|
+
}
|
|
8
|
+
export function noAnnotationError(typeOrFunc, params) {
|
|
9
|
+
const signature = [];
|
|
10
|
+
for (let i = 0, len = params.length; i < len; i++) {
|
|
11
|
+
const parameter = params[i];
|
|
12
|
+
if (!parameter.type) {
|
|
13
|
+
signature.push('?');
|
|
14
|
+
}
|
|
15
|
+
else {
|
|
16
|
+
signature.push(stringify(parameter.type));
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
return Error("Cannot resolve all parameters for '" +
|
|
20
|
+
stringify(typeOrFunc) +
|
|
21
|
+
"'(" +
|
|
22
|
+
signature.join(', ') +
|
|
23
|
+
'). ' +
|
|
24
|
+
"Make sure that all the parameters are decorated with Inject or have valid type annotations and that '" +
|
|
25
|
+
stringify(typeOrFunc) +
|
|
26
|
+
"' is decorated with Injectable.");
|
|
27
|
+
}
|
|
28
|
+
export function cyclicDependencyError(injector, key) {
|
|
29
|
+
return injectionError(injector, key, function () {
|
|
30
|
+
return `Cannot instantiate cyclic dependency!${constructResolvingPath(this.keys)}`;
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
export function noProviderError(injector, key) {
|
|
34
|
+
return injectionError(injector, key, function () {
|
|
35
|
+
const first = stringify(this.keys[0].token);
|
|
36
|
+
return `No provider for ${first}!${constructResolvingPath(this.keys)}`;
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
export function instantiationError(injector, originalException, key) {
|
|
40
|
+
return injectionError(injector, key, function () {
|
|
41
|
+
const first = stringify(this.keys[0].token);
|
|
42
|
+
return `Error during instantiation of ${first}: ${getOriginalError(this).message}${constructResolvingPath(this.keys)}`;
|
|
43
|
+
}, originalException);
|
|
44
|
+
}
|
|
45
|
+
function injectionError(injector, key, constructResolvingMessage, originalError) {
|
|
46
|
+
const error = (originalError ? wrappedError('', originalError) : Error());
|
|
47
|
+
error.addKey = addKey;
|
|
48
|
+
error.keys = [key];
|
|
49
|
+
error.constructResolvingMessage =
|
|
50
|
+
function wrappedConstructResolvingMessage() {
|
|
51
|
+
return (constructResolvingMessage.call(this) + ` - in ${injector.displayName}`);
|
|
52
|
+
};
|
|
53
|
+
error.message = error.constructResolvingMessage();
|
|
54
|
+
error[ERROR_ORIGINAL_ERROR] = originalError;
|
|
55
|
+
return error;
|
|
56
|
+
}
|
|
57
|
+
function constructResolvingPath(keys) {
|
|
58
|
+
if (keys.length > 1) {
|
|
59
|
+
const reversed = findFirstClosedCycle(keys.slice().reverse());
|
|
60
|
+
const tokenStrs = reversed.map((k) => stringify(k.token));
|
|
61
|
+
return ' (' + tokenStrs.join(' -> ') + ')';
|
|
62
|
+
}
|
|
63
|
+
return '';
|
|
64
|
+
}
|
|
65
|
+
function findFirstClosedCycle(keys) {
|
|
66
|
+
const res = [];
|
|
67
|
+
for (let i = 0; i < keys.length; ++i) {
|
|
68
|
+
if (res.indexOf(keys[i]) > -1) {
|
|
69
|
+
res.push(keys[i]);
|
|
70
|
+
return res;
|
|
71
|
+
}
|
|
72
|
+
res.push(keys[i]);
|
|
73
|
+
}
|
|
74
|
+
return res;
|
|
75
|
+
}
|
|
76
|
+
function addKey(key) {
|
|
77
|
+
this.keys.push(key);
|
|
78
|
+
this.message = this.constructResolvingMessage();
|
|
79
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { stringify } from './utils';
|
|
2
|
+
const forwardRefSymbol = Symbol('__forward_ref__');
|
|
3
|
+
/**
|
|
4
|
+
* Useful in "circular dependencies of modules" situation
|
|
5
|
+
*/
|
|
6
|
+
export function forwardRef(forwardRefFn) {
|
|
7
|
+
forwardRefFn[forwardRefSymbol] = forwardRef;
|
|
8
|
+
forwardRefFn.toString = function () {
|
|
9
|
+
return stringify(this());
|
|
10
|
+
};
|
|
11
|
+
return forwardRefFn;
|
|
12
|
+
}
|
|
13
|
+
export function resolveForwardRef(type) {
|
|
14
|
+
if (typeof type === 'function' &&
|
|
15
|
+
type.hasOwnProperty(forwardRefSymbol) &&
|
|
16
|
+
type[forwardRefSymbol] === forwardRef) {
|
|
17
|
+
return type();
|
|
18
|
+
}
|
|
19
|
+
else {
|
|
20
|
+
return type;
|
|
21
|
+
}
|
|
22
|
+
}
|
package/esm/di/index.js
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { Injectable, Optional, Inject, ExecutionContext } from './decorators';
|
|
2
|
+
export { forwardRef } from './forward-ref';
|
|
3
|
+
export { InjectionToken, Type, Scope, onlySingletonProviders, onlyOperationProviders, } from './providers';
|
|
4
|
+
export { Injector, ReflectiveInjector } from './injector';
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import { resolveProviders, } from './resolution';
|
|
2
|
+
import { Key } from './registry';
|
|
3
|
+
import { noProviderError, cyclicDependencyError, instantiationError, } from './errors';
|
|
4
|
+
const _THROW_IF_NOT_FOUND = new Object();
|
|
5
|
+
const UNDEFINED = new Object();
|
|
6
|
+
const NOT_FOUND = new Object();
|
|
7
|
+
function notInExecutionContext() {
|
|
8
|
+
throw new Error('Not in execution context');
|
|
9
|
+
}
|
|
10
|
+
// Publicly available Injector.
|
|
11
|
+
// We use ReflectiveInjector everywhere
|
|
12
|
+
// but we don't want to leak its API to everyone
|
|
13
|
+
export class Injector {
|
|
14
|
+
}
|
|
15
|
+
export class ReflectiveInjector {
|
|
16
|
+
constructor({ name, providers, parent, fallbackParent, globalProvidersMap = new Map(), }) {
|
|
17
|
+
this._constructionCounter = 0;
|
|
18
|
+
this._executionContextGetter = notInExecutionContext;
|
|
19
|
+
this.displayName = name;
|
|
20
|
+
this._parent = parent || null;
|
|
21
|
+
this._fallbackParent = fallbackParent || null;
|
|
22
|
+
this._providers = providers;
|
|
23
|
+
this._globalProvidersMap = globalProvidersMap;
|
|
24
|
+
const len = this._providers.length;
|
|
25
|
+
this._keyIds = new Array(len);
|
|
26
|
+
this._objs = new Array(len);
|
|
27
|
+
for (let i = 0; i < len; i++) {
|
|
28
|
+
this._keyIds[i] = this._providers[i].key.id;
|
|
29
|
+
this._objs[i] = UNDEFINED;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
static createFromResolved({ name, providers, parent, fallbackParent, globalProvidersMap, }) {
|
|
33
|
+
return new ReflectiveInjector({
|
|
34
|
+
name,
|
|
35
|
+
providers,
|
|
36
|
+
parent,
|
|
37
|
+
fallbackParent,
|
|
38
|
+
globalProvidersMap,
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
static resolve(providers) {
|
|
42
|
+
return resolveProviders(providers);
|
|
43
|
+
}
|
|
44
|
+
get parent() {
|
|
45
|
+
return this._parent;
|
|
46
|
+
}
|
|
47
|
+
get fallbackParent() {
|
|
48
|
+
return this._fallbackParent;
|
|
49
|
+
}
|
|
50
|
+
get(token, notFoundValue = _THROW_IF_NOT_FOUND) {
|
|
51
|
+
return this._getByKey(Key.get(token), notFoundValue);
|
|
52
|
+
}
|
|
53
|
+
setExecutionContextGetter(getter) {
|
|
54
|
+
this._executionContextGetter = getter;
|
|
55
|
+
}
|
|
56
|
+
_getByKey(key, notFoundValue) {
|
|
57
|
+
let inj = this;
|
|
58
|
+
function getObj() {
|
|
59
|
+
while (inj instanceof ReflectiveInjector) {
|
|
60
|
+
const inj_ = inj;
|
|
61
|
+
const obj = inj_._getObjByKeyId(key.id);
|
|
62
|
+
if (obj !== UNDEFINED) {
|
|
63
|
+
return obj;
|
|
64
|
+
}
|
|
65
|
+
inj = inj_._parent;
|
|
66
|
+
}
|
|
67
|
+
return NOT_FOUND;
|
|
68
|
+
}
|
|
69
|
+
const resolvedValue = getObj();
|
|
70
|
+
if (resolvedValue !== NOT_FOUND) {
|
|
71
|
+
return resolvedValue;
|
|
72
|
+
}
|
|
73
|
+
// search in fallback Injector
|
|
74
|
+
if (this._fallbackParent) {
|
|
75
|
+
inj = this._fallbackParent;
|
|
76
|
+
const resolvedFallbackValue = getObj();
|
|
77
|
+
if (resolvedFallbackValue !== NOT_FOUND) {
|
|
78
|
+
return resolvedFallbackValue;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
if (inj !== null) {
|
|
82
|
+
return inj.get(key.token, notFoundValue);
|
|
83
|
+
}
|
|
84
|
+
return this._throwOrNull(key, notFoundValue);
|
|
85
|
+
}
|
|
86
|
+
_isObjectDefinedByKeyId(keyId) {
|
|
87
|
+
for (let i = 0; i < this._keyIds.length; i++) {
|
|
88
|
+
if (this._keyIds[i] === keyId) {
|
|
89
|
+
return this._objs[i] !== UNDEFINED;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
_getObjByKeyId(keyId) {
|
|
95
|
+
var _a, _b;
|
|
96
|
+
if ((_a = this._globalProvidersMap) === null || _a === void 0 ? void 0 : _a.has(keyId)) {
|
|
97
|
+
return (_b = this._globalProvidersMap.get(keyId)) === null || _b === void 0 ? void 0 : _b._getObjByKeyId(keyId);
|
|
98
|
+
}
|
|
99
|
+
for (let i = 0; i < this._keyIds.length; i++) {
|
|
100
|
+
if (this._keyIds[i] === keyId) {
|
|
101
|
+
if (this._objs[i] === UNDEFINED) {
|
|
102
|
+
this._objs[i] = this._new(this._providers[i]);
|
|
103
|
+
}
|
|
104
|
+
return this._objs[i];
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
return UNDEFINED;
|
|
108
|
+
}
|
|
109
|
+
_throwOrNull(key, notFoundValue) {
|
|
110
|
+
if (notFoundValue !== _THROW_IF_NOT_FOUND) {
|
|
111
|
+
return notFoundValue;
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
throw noProviderError(this, key);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
instantiateAll() {
|
|
118
|
+
this._providers.forEach((provider) => {
|
|
119
|
+
this._getByKey(provider.key, _THROW_IF_NOT_FOUND);
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
_instantiateProvider(provider) {
|
|
123
|
+
const factory = provider.factory.factory;
|
|
124
|
+
let deps;
|
|
125
|
+
try {
|
|
126
|
+
deps = provider.factory.dependencies.map((dep) => this._getByDependency(dep));
|
|
127
|
+
}
|
|
128
|
+
catch (e) {
|
|
129
|
+
if (e.addKey) {
|
|
130
|
+
e.addKey(provider.key);
|
|
131
|
+
}
|
|
132
|
+
throw e;
|
|
133
|
+
}
|
|
134
|
+
let obj;
|
|
135
|
+
try {
|
|
136
|
+
obj = factory(...deps);
|
|
137
|
+
// attach execution context getter
|
|
138
|
+
if (provider.factory.executionContextIn.length > 0) {
|
|
139
|
+
for (const prop of provider.factory.executionContextIn) {
|
|
140
|
+
Object.defineProperty(obj, prop, {
|
|
141
|
+
get: () => {
|
|
142
|
+
return this._executionContextGetter();
|
|
143
|
+
},
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
catch (e) {
|
|
149
|
+
throw instantiationError(this, e, provider.key);
|
|
150
|
+
}
|
|
151
|
+
return obj;
|
|
152
|
+
}
|
|
153
|
+
_getByDependency(dep) {
|
|
154
|
+
return this._getByKey(dep.key, dep.optional ? null : _THROW_IF_NOT_FOUND);
|
|
155
|
+
}
|
|
156
|
+
_new(provider) {
|
|
157
|
+
if (this._constructionCounter++ > this._getMaxNumberOfObjects()) {
|
|
158
|
+
throw cyclicDependencyError(this, provider.key);
|
|
159
|
+
}
|
|
160
|
+
return this._instantiateProvider(provider);
|
|
161
|
+
}
|
|
162
|
+
_getMaxNumberOfObjects() {
|
|
163
|
+
return this._objs.length;
|
|
164
|
+
}
|
|
165
|
+
toString() {
|
|
166
|
+
return this.displayName;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { noInjectableError } from './errors';
|
|
2
|
+
export const INJECTABLE = Symbol('di:injectable');
|
|
3
|
+
export function readInjectableMetadata(type, throwOnMissing) {
|
|
4
|
+
const meta = type[INJECTABLE];
|
|
5
|
+
if (!meta && throwOnMissing) {
|
|
6
|
+
throw noInjectableError(type);
|
|
7
|
+
}
|
|
8
|
+
return meta;
|
|
9
|
+
}
|
|
10
|
+
export function ensureInjectableMetadata(type) {
|
|
11
|
+
if (!readInjectableMetadata(type)) {
|
|
12
|
+
const meta = {
|
|
13
|
+
params: [],
|
|
14
|
+
};
|
|
15
|
+
type[INJECTABLE] = meta;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { readInjectableMetadata } from './metadata';
|
|
2
|
+
export const Type = Function;
|
|
3
|
+
/// @ts-ignore
|
|
4
|
+
export class InjectionToken {
|
|
5
|
+
constructor(_desc) {
|
|
6
|
+
this._desc = _desc;
|
|
7
|
+
}
|
|
8
|
+
toString() {
|
|
9
|
+
return `InjectionToken ${this._desc}`;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
export function isToken(v) {
|
|
13
|
+
return v && v instanceof InjectionToken;
|
|
14
|
+
}
|
|
15
|
+
export function isType(v) {
|
|
16
|
+
return typeof v === 'function' && v !== Object;
|
|
17
|
+
}
|
|
18
|
+
export var Scope;
|
|
19
|
+
(function (Scope) {
|
|
20
|
+
Scope[Scope["Singleton"] = 0] = "Singleton";
|
|
21
|
+
Scope[Scope["Operation"] = 1] = "Operation";
|
|
22
|
+
})(Scope || (Scope = {}));
|
|
23
|
+
export function onlySingletonProviders(providers = []) {
|
|
24
|
+
return providers.filter((provider) => {
|
|
25
|
+
if (isType(provider)) {
|
|
26
|
+
const { options } = readInjectableMetadata(provider, true);
|
|
27
|
+
return (options === null || options === void 0 ? void 0 : options.scope) !== Scope.Operation;
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
return provider.scope !== Scope.Operation;
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
export function onlyOperationProviders(providers = []) {
|
|
35
|
+
return providers.filter((provider) => {
|
|
36
|
+
if (isType(provider)) {
|
|
37
|
+
const { options } = readInjectableMetadata(provider, true);
|
|
38
|
+
return (options === null || options === void 0 ? void 0 : options.scope) === Scope.Operation;
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
return provider.scope === Scope.Operation;
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
export function isClassProvider(provider) {
|
|
46
|
+
return typeof provider.useClass !== 'undefined';
|
|
47
|
+
}
|
|
48
|
+
export function isFactoryProvider(provider) {
|
|
49
|
+
return typeof provider.useFactory !== 'undefined';
|
|
50
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { stringify } from './utils';
|
|
2
|
+
import { resolveForwardRef } from './forward-ref';
|
|
3
|
+
export class Key {
|
|
4
|
+
constructor(token, id) {
|
|
5
|
+
this.token = token;
|
|
6
|
+
this.id = id;
|
|
7
|
+
if (!token) {
|
|
8
|
+
throw new Error('Token must be defined!');
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Returns a stringified token.
|
|
13
|
+
*/
|
|
14
|
+
get displayName() {
|
|
15
|
+
return stringify(this.token);
|
|
16
|
+
}
|
|
17
|
+
static get(token) {
|
|
18
|
+
return _globalKeyRegistry.get(resolveForwardRef(token));
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
class GlobalKeyRegistry {
|
|
22
|
+
constructor() {
|
|
23
|
+
this._allKeys = new Map();
|
|
24
|
+
}
|
|
25
|
+
get(token) {
|
|
26
|
+
if (token instanceof Key) {
|
|
27
|
+
return token;
|
|
28
|
+
}
|
|
29
|
+
if (this._allKeys.has(token)) {
|
|
30
|
+
return this._allKeys.get(token);
|
|
31
|
+
}
|
|
32
|
+
const newKey = new Key(token, _globalKeyRegistry.numberOfKeys);
|
|
33
|
+
this._allKeys.set(token, newKey);
|
|
34
|
+
return newKey;
|
|
35
|
+
}
|
|
36
|
+
get numberOfKeys() {
|
|
37
|
+
return this._allKeys.size;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
const _globalKeyRegistry = new GlobalKeyRegistry();
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import { Type, isClassProvider, isFactoryProvider, } from './providers';
|
|
2
|
+
import { invalidProviderError, noAnnotationError } from './errors';
|
|
3
|
+
import { Key } from './registry';
|
|
4
|
+
import { resolveForwardRef } from './forward-ref';
|
|
5
|
+
import { readInjectableMetadata } from './metadata';
|
|
6
|
+
const _EMPTY_LIST = [];
|
|
7
|
+
export class ResolvedProvider {
|
|
8
|
+
constructor(key, factory) {
|
|
9
|
+
this.key = key;
|
|
10
|
+
this.factory = factory;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
export class ResolvedFactory {
|
|
14
|
+
constructor(
|
|
15
|
+
/**
|
|
16
|
+
* Factory function which can return an instance of an object represented by a key.
|
|
17
|
+
*/
|
|
18
|
+
factory,
|
|
19
|
+
/**
|
|
20
|
+
* Arguments (dependencies) to the `factory` function.
|
|
21
|
+
*/
|
|
22
|
+
dependencies,
|
|
23
|
+
/**
|
|
24
|
+
* Methods invoked within ExecutionContext.
|
|
25
|
+
*/
|
|
26
|
+
executionContextIn,
|
|
27
|
+
/**
|
|
28
|
+
* Has onDestroy hook
|
|
29
|
+
*/
|
|
30
|
+
hasOnDestroyHook,
|
|
31
|
+
/**
|
|
32
|
+
* Is Global
|
|
33
|
+
*/
|
|
34
|
+
isGlobal) {
|
|
35
|
+
this.factory = factory;
|
|
36
|
+
this.dependencies = dependencies;
|
|
37
|
+
this.executionContextIn = executionContextIn;
|
|
38
|
+
this.hasOnDestroyHook = hasOnDestroyHook;
|
|
39
|
+
this.isGlobal = isGlobal;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
export class Dependency {
|
|
43
|
+
constructor(key, optional) {
|
|
44
|
+
this.key = key;
|
|
45
|
+
this.optional = optional;
|
|
46
|
+
}
|
|
47
|
+
static fromKey(key) {
|
|
48
|
+
return new Dependency(key, false);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
export function resolveProviders(providers) {
|
|
52
|
+
const normalized = normalizeProviders(providers, []);
|
|
53
|
+
const resolved = normalized.map(resolveProvider);
|
|
54
|
+
const resolvedProviderMap = mergeResolvedProviders(resolved, new Map());
|
|
55
|
+
return Array.from(resolvedProviderMap.values());
|
|
56
|
+
}
|
|
57
|
+
function resolveProvider(provider) {
|
|
58
|
+
return new ResolvedProvider(Key.get(provider.provide), resolveFactory(provider));
|
|
59
|
+
}
|
|
60
|
+
function mergeResolvedProviders(providers, normalizedProvidersMap) {
|
|
61
|
+
for (let i = 0; i < providers.length; i++) {
|
|
62
|
+
const provider = providers[i];
|
|
63
|
+
normalizedProvidersMap.set(provider.key.id, provider);
|
|
64
|
+
}
|
|
65
|
+
return normalizedProvidersMap;
|
|
66
|
+
}
|
|
67
|
+
function normalizeProviders(providers, res) {
|
|
68
|
+
providers.forEach((token) => {
|
|
69
|
+
if (token instanceof Type) {
|
|
70
|
+
res.push({ provide: token, useClass: token });
|
|
71
|
+
}
|
|
72
|
+
else if (token &&
|
|
73
|
+
typeof token === 'object' &&
|
|
74
|
+
token.provide !== undefined) {
|
|
75
|
+
res.push(token);
|
|
76
|
+
}
|
|
77
|
+
else if (token instanceof Array) {
|
|
78
|
+
normalizeProviders(token, res);
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
throw invalidProviderError(token);
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
return res;
|
|
85
|
+
}
|
|
86
|
+
function resolveFactory(provider) {
|
|
87
|
+
let factoryFn;
|
|
88
|
+
let resolvedDeps = _EMPTY_LIST;
|
|
89
|
+
let executionContextIn = _EMPTY_LIST;
|
|
90
|
+
let hasOnDestroyHook = false;
|
|
91
|
+
let isGlobal;
|
|
92
|
+
if (isClassProvider(provider)) {
|
|
93
|
+
const useClass = resolveForwardRef(provider.useClass);
|
|
94
|
+
factoryFn = makeFactory(useClass);
|
|
95
|
+
resolvedDeps = dependenciesFor(useClass);
|
|
96
|
+
executionContextIn = executionContextInFor(useClass);
|
|
97
|
+
isGlobal = globalFor(useClass);
|
|
98
|
+
hasOnDestroyHook = typeof useClass.prototype.onDestroy === 'function';
|
|
99
|
+
}
|
|
100
|
+
else if (isFactoryProvider(provider)) {
|
|
101
|
+
factoryFn = provider.useFactory;
|
|
102
|
+
resolvedDeps = constructDependencies(provider.useFactory, provider.deps || []);
|
|
103
|
+
isGlobal = provider.global;
|
|
104
|
+
if (provider.executionContextIn) {
|
|
105
|
+
executionContextIn = provider.executionContextIn;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
factoryFn = () => provider.useValue;
|
|
110
|
+
resolvedDeps = _EMPTY_LIST;
|
|
111
|
+
isGlobal = provider.global;
|
|
112
|
+
}
|
|
113
|
+
return new ResolvedFactory(factoryFn, resolvedDeps, executionContextIn, hasOnDestroyHook, isGlobal !== null && isGlobal !== void 0 ? isGlobal : false);
|
|
114
|
+
}
|
|
115
|
+
function dependenciesFor(type) {
|
|
116
|
+
const { params } = readInjectableMetadata(type, true);
|
|
117
|
+
if (!params) {
|
|
118
|
+
return [];
|
|
119
|
+
}
|
|
120
|
+
if (params.some((p) => p.type == null)) {
|
|
121
|
+
throw noAnnotationError(type, params);
|
|
122
|
+
}
|
|
123
|
+
return params.map((p) => extractToken(p, params));
|
|
124
|
+
}
|
|
125
|
+
function executionContextInFor(type) {
|
|
126
|
+
const { options } = readInjectableMetadata(type, true);
|
|
127
|
+
if ((options === null || options === void 0 ? void 0 : options.executionContextIn) &&
|
|
128
|
+
options.executionContextIn !== _EMPTY_LIST) {
|
|
129
|
+
return options === null || options === void 0 ? void 0 : options.executionContextIn;
|
|
130
|
+
}
|
|
131
|
+
return [];
|
|
132
|
+
}
|
|
133
|
+
function globalFor(type) {
|
|
134
|
+
var _a;
|
|
135
|
+
const { options } = readInjectableMetadata(type);
|
|
136
|
+
return (_a = options === null || options === void 0 ? void 0 : options.global) !== null && _a !== void 0 ? _a : false;
|
|
137
|
+
}
|
|
138
|
+
function constructDependencies(typeOrFunc, dependencies) {
|
|
139
|
+
if (!dependencies) {
|
|
140
|
+
return dependenciesFor(typeOrFunc);
|
|
141
|
+
}
|
|
142
|
+
else {
|
|
143
|
+
const params = dependencies.map((d) => ({ type: d, optional: false }));
|
|
144
|
+
return params.map((t) => extractToken(t, params));
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
function extractToken(param, params) {
|
|
148
|
+
const token = resolveForwardRef(param.type);
|
|
149
|
+
if (token) {
|
|
150
|
+
return createDependency(token, param.optional);
|
|
151
|
+
}
|
|
152
|
+
throw noAnnotationError(param.type, params);
|
|
153
|
+
}
|
|
154
|
+
function createDependency(token, optional) {
|
|
155
|
+
return new Dependency(Key.get(token), optional);
|
|
156
|
+
}
|
|
157
|
+
function makeFactory(t) {
|
|
158
|
+
return (...args) => new t(...args);
|
|
159
|
+
}
|
package/esm/di/utils.js
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
export const ERROR_TYPE = 'diType';
|
|
2
|
+
export const ERROR_ORIGINAL_ERROR = 'diOriginalError';
|
|
3
|
+
export const ERROR_LOGGER = 'diErrorLogger';
|
|
4
|
+
export function getType(error) {
|
|
5
|
+
return error[ERROR_TYPE];
|
|
6
|
+
}
|
|
7
|
+
export function getOriginalError(error) {
|
|
8
|
+
return error[ERROR_ORIGINAL_ERROR];
|
|
9
|
+
}
|
|
10
|
+
function defaultErrorLogger(console, ...values) {
|
|
11
|
+
// eslint-disable-next-line no-console
|
|
12
|
+
console.error(...values);
|
|
13
|
+
}
|
|
14
|
+
export function getErrorLogger(error) {
|
|
15
|
+
return error[ERROR_LOGGER] || defaultErrorLogger;
|
|
16
|
+
}
|
|
17
|
+
export function wrappedError(message, originalError) {
|
|
18
|
+
const msg = `${message} caused by: ${originalError instanceof Error ? originalError.message : originalError}`;
|
|
19
|
+
const error = Error(msg);
|
|
20
|
+
error[ERROR_ORIGINAL_ERROR] = originalError;
|
|
21
|
+
return error;
|
|
22
|
+
}
|
|
23
|
+
export function stringify(token) {
|
|
24
|
+
if (typeof token === 'string') {
|
|
25
|
+
return token;
|
|
26
|
+
}
|
|
27
|
+
if (token == null) {
|
|
28
|
+
return '' + token;
|
|
29
|
+
}
|
|
30
|
+
if (token.name) {
|
|
31
|
+
return `${token.name}`;
|
|
32
|
+
}
|
|
33
|
+
const res = token.toString();
|
|
34
|
+
const newLineIndex = res.indexOf('\n');
|
|
35
|
+
return newLineIndex === -1 ? res : res.substring(0, newLineIndex);
|
|
36
|
+
}
|
package/esm/index.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// application
|
|
2
|
+
export { createApplication } from './application/application';
|
|
3
|
+
export * from './application/tokens';
|
|
4
|
+
export * from './application/types';
|
|
5
|
+
// modules
|
|
6
|
+
export { createModule } from './module/module';
|
|
7
|
+
export * from './module/types';
|
|
8
|
+
export * from './module/metadata';
|
|
9
|
+
export * from './module/tokens';
|
|
10
|
+
// di
|
|
11
|
+
export { Injector, Inject, Injectable, Optional, ExecutionContext, forwardRef, InjectionToken, Scope, } from './di';
|
|
12
|
+
import './shared/types';
|
|
13
|
+
export { gql } from './shared/gql';
|
|
14
|
+
export * from './shared/di';
|
|
15
|
+
// testing
|
|
16
|
+
export * from './testing';
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { metadataFactory } from './metadata';
|
|
2
|
+
import { createResolvers } from './resolvers';
|
|
3
|
+
import { createTypeDefs } from './type-defs';
|
|
4
|
+
import { MODULE_ID } from './tokens';
|
|
5
|
+
import { ReflectiveInjector, onlySingletonProviders, onlyOperationProviders, } from '../di';
|
|
6
|
+
import { resolveProviders } from './../di/resolution';
|
|
7
|
+
function lazy(getter) {
|
|
8
|
+
let called = false;
|
|
9
|
+
let computedValue;
|
|
10
|
+
return {
|
|
11
|
+
get value() {
|
|
12
|
+
if (!called) {
|
|
13
|
+
called = true;
|
|
14
|
+
computedValue = getter();
|
|
15
|
+
}
|
|
16
|
+
return computedValue;
|
|
17
|
+
},
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
export function moduleFactory(config) {
|
|
21
|
+
const typeDefs = createTypeDefs(config);
|
|
22
|
+
const metadata = metadataFactory(typeDefs, config);
|
|
23
|
+
const providers = lazy(() => typeof config.providers === 'function'
|
|
24
|
+
? config.providers()
|
|
25
|
+
: config.providers);
|
|
26
|
+
// Filter providers and keep them this way
|
|
27
|
+
// so we don't do this filtering multiple times.
|
|
28
|
+
// Providers don't change over time, so it's safe to do it.
|
|
29
|
+
const operationProviders = lazy(() => ReflectiveInjector.resolve(onlyOperationProviders(providers.value)));
|
|
30
|
+
const singletonProviders = lazy(() => ReflectiveInjector.resolve(onlySingletonProviders(providers.value)));
|
|
31
|
+
const mod = {
|
|
32
|
+
id: config.id,
|
|
33
|
+
config,
|
|
34
|
+
metadata,
|
|
35
|
+
typeDefs,
|
|
36
|
+
// Factory is called once on application creation,
|
|
37
|
+
// before we even handle GraphQL Operation
|
|
38
|
+
factory(app) {
|
|
39
|
+
const resolvedModule = mod;
|
|
40
|
+
resolvedModule.singletonProviders = singletonProviders.value;
|
|
41
|
+
resolvedModule.operationProviders = operationProviders.value;
|
|
42
|
+
// Create a module-level Singleton injector
|
|
43
|
+
const injector = ReflectiveInjector.createFromResolved({
|
|
44
|
+
name: `Module "${config.id}" (Singleton Scope)`,
|
|
45
|
+
providers: resolvedModule.singletonProviders.concat(resolveProviders([
|
|
46
|
+
{
|
|
47
|
+
// with module's id, useful in Logging and stuff
|
|
48
|
+
provide: MODULE_ID,
|
|
49
|
+
useValue: config.id,
|
|
50
|
+
},
|
|
51
|
+
])),
|
|
52
|
+
parent: app.injector,
|
|
53
|
+
});
|
|
54
|
+
// We attach injector property to existing `mod` object
|
|
55
|
+
// because we want to keep references
|
|
56
|
+
// that are later on used in testing utils
|
|
57
|
+
resolvedModule.injector = injector;
|
|
58
|
+
// Create resolvers object based on module's config
|
|
59
|
+
// It involves wrapping a resolver with middlewares
|
|
60
|
+
// and other things like validation
|
|
61
|
+
resolvedModule.resolvers = createResolvers(config, metadata, {
|
|
62
|
+
middlewareMap: app.middlewares,
|
|
63
|
+
});
|
|
64
|
+
return resolvedModule;
|
|
65
|
+
},
|
|
66
|
+
};
|
|
67
|
+
return mod;
|
|
68
|
+
}
|