graphql-modules 3.1.2-alpha-20260121024117-e03d9c26de1cfd3971986f82b995963e1cc77056 → 3.1.2-alpha-20260121025807-95ab4fb1994c3cf68c88a7cf234efd8f99f92ed1
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/async-context.browser.mjs +7 -0
- package/cjs/async-context.node.cjs +14 -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 +9 -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/async-context.browser.mjs +7 -0
- package/esm/async-context.node.cjs +14 -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
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { execute, } from 'graphql';
|
|
2
|
+
import { isNotSchema } from '../shared/utils';
|
|
3
|
+
export function executionCreator({ contextBuilder, }) {
|
|
4
|
+
const createExecution = (options) => {
|
|
5
|
+
// Custom or original execute function
|
|
6
|
+
const executeFn = (options === null || options === void 0 ? void 0 : options.execute) || execute;
|
|
7
|
+
return (argsOrSchema, document, rootValue, contextValue, variableValues, operationName, fieldResolver, typeResolver) => {
|
|
8
|
+
function perform({ context, ɵdestroy: destroy, }) {
|
|
9
|
+
const executionArgs = isNotSchema(argsOrSchema)
|
|
10
|
+
? {
|
|
11
|
+
...argsOrSchema,
|
|
12
|
+
contextValue: context,
|
|
13
|
+
}
|
|
14
|
+
: {
|
|
15
|
+
schema: argsOrSchema,
|
|
16
|
+
document: document,
|
|
17
|
+
rootValue,
|
|
18
|
+
contextValue: context,
|
|
19
|
+
variableValues,
|
|
20
|
+
operationName,
|
|
21
|
+
fieldResolver,
|
|
22
|
+
typeResolver,
|
|
23
|
+
};
|
|
24
|
+
// It's important to wrap the executeFn within a promise
|
|
25
|
+
// so we can easily control the end of execution (with finally)
|
|
26
|
+
return Promise.resolve()
|
|
27
|
+
.then(() => executeFn(executionArgs))
|
|
28
|
+
.finally(destroy);
|
|
29
|
+
}
|
|
30
|
+
if (options === null || options === void 0 ? void 0 : options.controller) {
|
|
31
|
+
return perform(options.controller);
|
|
32
|
+
}
|
|
33
|
+
return contextBuilder(isNotSchema(argsOrSchema)
|
|
34
|
+
? argsOrSchema.contextValue
|
|
35
|
+
: contextValue).runWithContext(perform);
|
|
36
|
+
};
|
|
37
|
+
};
|
|
38
|
+
return createExecution;
|
|
39
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export function operationControllerCreator(options) {
|
|
2
|
+
const { contextBuilder } = options;
|
|
3
|
+
return (input) => {
|
|
4
|
+
const operation = contextBuilder(input.context);
|
|
5
|
+
const ɵdestroy = input.autoDestroy ? operation.ɵdestroy : () => { };
|
|
6
|
+
return {
|
|
7
|
+
context: operation.context,
|
|
8
|
+
injector: operation.ɵinjector,
|
|
9
|
+
destroy: operation.ɵdestroy,
|
|
10
|
+
ɵdestroy,
|
|
11
|
+
};
|
|
12
|
+
};
|
|
13
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { subscribe, } from 'graphql';
|
|
2
|
+
import { tapAsyncIterator, isAsyncIterable, isNotSchema, } from '../shared/utils';
|
|
3
|
+
export function subscriptionCreator({ contextBuilder, }) {
|
|
4
|
+
const createSubscription = (options) => {
|
|
5
|
+
// Custom or original subscribe function
|
|
6
|
+
const subscribeFn = (options === null || options === void 0 ? void 0 : options.subscribe) || subscribe;
|
|
7
|
+
return (argsOrSchema, document, rootValue, contextValue, variableValues, operationName, fieldResolver, subscribeFieldResolver) => {
|
|
8
|
+
function perform({ context, ɵdestroy: destroy, }) {
|
|
9
|
+
const subscriptionArgs = isNotSchema(argsOrSchema)
|
|
10
|
+
? {
|
|
11
|
+
...argsOrSchema,
|
|
12
|
+
contextValue: context,
|
|
13
|
+
}
|
|
14
|
+
: {
|
|
15
|
+
schema: argsOrSchema,
|
|
16
|
+
document: document,
|
|
17
|
+
rootValue,
|
|
18
|
+
contextValue: context,
|
|
19
|
+
variableValues,
|
|
20
|
+
operationName,
|
|
21
|
+
fieldResolver,
|
|
22
|
+
subscribeFieldResolver,
|
|
23
|
+
};
|
|
24
|
+
let isIterable = false;
|
|
25
|
+
// It's important to wrap the subscribeFn within a promise
|
|
26
|
+
// so we can easily control the end of subscription (with finally)
|
|
27
|
+
return Promise.resolve()
|
|
28
|
+
.then(() => subscribeFn(subscriptionArgs))
|
|
29
|
+
.then((sub) => {
|
|
30
|
+
if (isAsyncIterable(sub)) {
|
|
31
|
+
isIterable = true;
|
|
32
|
+
return tapAsyncIterator(sub, destroy);
|
|
33
|
+
}
|
|
34
|
+
return sub;
|
|
35
|
+
})
|
|
36
|
+
.finally(() => {
|
|
37
|
+
if (!isIterable) {
|
|
38
|
+
destroy();
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
if (options === null || options === void 0 ? void 0 : options.controller) {
|
|
43
|
+
return perform(options.controller);
|
|
44
|
+
}
|
|
45
|
+
return contextBuilder(isNotSchema(argsOrSchema)
|
|
46
|
+
? argsOrSchema.contextValue
|
|
47
|
+
: contextValue).runWithContext(perform);
|
|
48
|
+
};
|
|
49
|
+
};
|
|
50
|
+
return createSubscription;
|
|
51
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { InjectionToken } from '../di';
|
|
2
|
+
/**
|
|
3
|
+
* @api
|
|
4
|
+
* `CONTEXT` is an InjectionToken representing the provided `GraphQLModules.GlobalContext`
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
*
|
|
8
|
+
* ```typescript
|
|
9
|
+
* import { CONTEXT, Inject, Injectable } from 'graphql-modules';
|
|
10
|
+
*
|
|
11
|
+
* (A)Injectable()
|
|
12
|
+
* export class Data {
|
|
13
|
+
* constructor((A)Inject(CONTEXT) private context: GraphQLModules.GlobalContext) {}
|
|
14
|
+
* }
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
17
|
+
export const CONTEXT = new InjectionToken('context');
|
|
File without changes
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// use async hooks
|
|
2
|
+
// TODO: typecheck
|
|
3
|
+
|
|
4
|
+
const hooks = require('async_hooks');
|
|
5
|
+
|
|
6
|
+
const alc = new hooks.AsyncLocalStorage();
|
|
7
|
+
|
|
8
|
+
// we dont use named exports (exports.getAsyncContext) because node with typescript is weird
|
|
9
|
+
|
|
10
|
+
module.exports = {
|
|
11
|
+
getAsyncContext: () => alc.getStore(),
|
|
12
|
+
runWithAsyncContext: (asyncContext, callback, ...args) =>
|
|
13
|
+
alc.run(asyncContext, callback, ...args),
|
|
14
|
+
};
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { isType } from './providers';
|
|
2
|
+
import { INJECTABLE, readInjectableMetadata, ensureInjectableMetadata, } from './metadata';
|
|
3
|
+
function ensureReflect() {
|
|
4
|
+
if (!(Reflect && Reflect.getOwnMetadata)) {
|
|
5
|
+
throw 'reflect-metadata shim is required when using class decorators';
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
export function Injectable(options) {
|
|
9
|
+
return (target) => {
|
|
10
|
+
var _a;
|
|
11
|
+
ensureReflect();
|
|
12
|
+
const params = (Reflect.getMetadata('design:paramtypes', target) || []).map((param) => (isType(param) ? param : null));
|
|
13
|
+
const existingMeta = readInjectableMetadata(target);
|
|
14
|
+
const meta = {
|
|
15
|
+
params: ((_a = existingMeta === null || existingMeta === void 0 ? void 0 : existingMeta.params) === null || _a === void 0 ? void 0 : _a.length) > 0 && params.length === 0
|
|
16
|
+
? existingMeta === null || existingMeta === void 0 ? void 0 : existingMeta.params
|
|
17
|
+
: params.map((param, i) => {
|
|
18
|
+
var _a;
|
|
19
|
+
const existingParam = (_a = existingMeta === null || existingMeta === void 0 ? void 0 : existingMeta.params) === null || _a === void 0 ? void 0 : _a[i];
|
|
20
|
+
return {
|
|
21
|
+
type: (existingParam === null || existingParam === void 0 ? void 0 : existingParam.type) || param,
|
|
22
|
+
optional: typeof (existingParam === null || existingParam === void 0 ? void 0 : existingParam.optional) === 'boolean'
|
|
23
|
+
? existingParam.optional
|
|
24
|
+
: false,
|
|
25
|
+
};
|
|
26
|
+
}),
|
|
27
|
+
options: {
|
|
28
|
+
...((existingMeta === null || existingMeta === void 0 ? void 0 : existingMeta.options) || {}),
|
|
29
|
+
...(options || {}),
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
target[INJECTABLE] = meta;
|
|
33
|
+
return target;
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
export function Optional() {
|
|
37
|
+
return (target, _, index) => {
|
|
38
|
+
ensureReflect();
|
|
39
|
+
ensureInjectableMetadata(target);
|
|
40
|
+
const meta = readInjectableMetadata(target);
|
|
41
|
+
meta.params[index] = {
|
|
42
|
+
...meta.params[index],
|
|
43
|
+
optional: true,
|
|
44
|
+
};
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
export function Inject(type) {
|
|
48
|
+
return (target, _, index) => {
|
|
49
|
+
ensureReflect();
|
|
50
|
+
ensureInjectableMetadata(target);
|
|
51
|
+
const meta = readInjectableMetadata(target);
|
|
52
|
+
meta.params[index] = {
|
|
53
|
+
type,
|
|
54
|
+
optional: false,
|
|
55
|
+
};
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
export function ExecutionContext() {
|
|
59
|
+
return (obj, propertyKey) => {
|
|
60
|
+
ensureReflect();
|
|
61
|
+
const target = obj.constructor;
|
|
62
|
+
ensureInjectableMetadata(target);
|
|
63
|
+
const meta = readInjectableMetadata(target);
|
|
64
|
+
if (!meta.options) {
|
|
65
|
+
meta.options = {};
|
|
66
|
+
}
|
|
67
|
+
if (!meta.options.executionContextIn) {
|
|
68
|
+
meta.options.executionContextIn = [];
|
|
69
|
+
}
|
|
70
|
+
meta.options.executionContextIn.push(propertyKey);
|
|
71
|
+
};
|
|
72
|
+
}
|
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();
|