ts-ioc-container 54.0.0 → 54.1.0
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/cjm/container/Container.js +16 -0
- package/cjm/container/EmptyContainer.js +7 -0
- package/cjm/errors/ContainerNotFoundError.js +12 -0
- package/cjm/hooks/hook.js +26 -7
- package/cjm/index.js +4 -2
- package/esm/container/Container.js +16 -0
- package/esm/container/EmptyContainer.js +7 -0
- package/esm/errors/ContainerNotFoundError.js +8 -0
- package/esm/hooks/hook.js +26 -7
- package/esm/index.js +1 -0
- package/package.json +1 -1
- package/typings/container/Container.d.ts +2 -0
- package/typings/container/EmptyContainer.d.ts +2 -0
- package/typings/container/IContainer.d.ts +2 -0
- package/typings/errors/ContainerNotFoundError.d.ts +5 -0
- package/typings/index.d.ts +1 -0
|
@@ -6,6 +6,7 @@ const ContainerDisposedError_1 = require("../errors/ContainerDisposedError");
|
|
|
6
6
|
const MetadataInjector_1 = require("../injector/MetadataInjector");
|
|
7
7
|
const AliasMap_1 = require("./AliasMap");
|
|
8
8
|
const DependencyNotFoundError_1 = require("../errors/DependencyNotFoundError");
|
|
9
|
+
const ContainerNotFoundError_1 = require("../errors/ContainerNotFoundError");
|
|
9
10
|
const basic_1 = require("../utils/basic");
|
|
10
11
|
const array_1 = require("../utils/array");
|
|
11
12
|
class Container {
|
|
@@ -131,6 +132,21 @@ class Container {
|
|
|
131
132
|
getScopes() {
|
|
132
133
|
return [...this.scopes];
|
|
133
134
|
}
|
|
135
|
+
hasInstance(instance) {
|
|
136
|
+
return this.instances.includes(instance);
|
|
137
|
+
}
|
|
138
|
+
getScopeByInstanceOrFail(instance) {
|
|
139
|
+
this.validateContainer();
|
|
140
|
+
const queue = [this];
|
|
141
|
+
while (queue.length > 0) {
|
|
142
|
+
const scope = queue.shift();
|
|
143
|
+
if (scope.hasInstance(instance)) {
|
|
144
|
+
return scope;
|
|
145
|
+
}
|
|
146
|
+
queue.push(...scope.getScopes());
|
|
147
|
+
}
|
|
148
|
+
throw new ContainerNotFoundError_1.ContainerNotFoundError('Cannot find scope for the given instance');
|
|
149
|
+
}
|
|
134
150
|
removeScope(child) {
|
|
135
151
|
this.scopes = this.scopes.filter((s) => s !== child);
|
|
136
152
|
}
|
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.EmptyContainer = void 0;
|
|
4
4
|
const MethodNotImplementedError_1 = require("../errors/MethodNotImplementedError");
|
|
5
5
|
const DependencyNotFoundError_1 = require("../errors/DependencyNotFoundError");
|
|
6
|
+
const ContainerNotFoundError_1 = require("../errors/ContainerNotFoundError");
|
|
6
7
|
class EmptyContainer {
|
|
7
8
|
get isDisposed() {
|
|
8
9
|
throw new MethodNotImplementedError_1.MethodNotImplementedError();
|
|
@@ -14,9 +15,15 @@ class EmptyContainer {
|
|
|
14
15
|
getScopes() {
|
|
15
16
|
return [];
|
|
16
17
|
}
|
|
18
|
+
getScopeByInstanceOrFail(instance) {
|
|
19
|
+
throw new ContainerNotFoundError_1.ContainerNotFoundError('Cannot find scope for the given instance');
|
|
20
|
+
}
|
|
17
21
|
getInstances() {
|
|
18
22
|
return [];
|
|
19
23
|
}
|
|
24
|
+
hasInstance(instance) {
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
20
27
|
createScope() {
|
|
21
28
|
throw new MethodNotImplementedError_1.MethodNotImplementedError();
|
|
22
29
|
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ContainerNotFoundError = void 0;
|
|
4
|
+
const ContainerError_1 = require("./ContainerError");
|
|
5
|
+
class ContainerNotFoundError extends ContainerError_1.ContainerError {
|
|
6
|
+
name = 'ContainerNotFoundError';
|
|
7
|
+
constructor(message) {
|
|
8
|
+
super(message);
|
|
9
|
+
Object.setPrototypeOf(this, ContainerNotFoundError.prototype);
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
exports.ContainerNotFoundError = ContainerNotFoundError;
|
package/cjm/hooks/hook.js
CHANGED
|
@@ -13,21 +13,40 @@ exports.toHookFn = toHookFn;
|
|
|
13
13
|
const getReflectionTarget = (target) => {
|
|
14
14
|
return (0, proxy_1.isProxy)(target) ? (0, proxy_1.getProxyTarget)(target) : target;
|
|
15
15
|
};
|
|
16
|
-
//
|
|
16
|
+
// Walk the constructor's prototype chain (most-derived first) collecting each class.
|
|
17
|
+
const getConstructorChain = (ctor) => {
|
|
18
|
+
const chain = [];
|
|
19
|
+
let current = ctor;
|
|
20
|
+
while (typeof current === 'function' && current !== Function.prototype) {
|
|
21
|
+
chain.push(current);
|
|
22
|
+
current = Object.getPrototypeOf(current);
|
|
23
|
+
}
|
|
24
|
+
return chain;
|
|
25
|
+
};
|
|
26
|
+
// Get hooks metadata, merging hooks declared on parent (extended-from) classes.
|
|
27
|
+
// Hooks are collected from base to derived so a derived class's hooks for the same
|
|
28
|
+
// method name take precedence over (replace) the parent's.
|
|
17
29
|
function getHooks(target, key) {
|
|
18
30
|
const reflectionTarget = getReflectionTarget(target);
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
31
|
+
const merged = new Map();
|
|
32
|
+
for (const ctor of getConstructorChain(reflectionTarget.constructor).reverse()) {
|
|
33
|
+
const ownHooks = Reflect.getOwnMetadata(key, ctor);
|
|
34
|
+
if (ownHooks) {
|
|
35
|
+
for (const [methodName, fns] of ownHooks) {
|
|
36
|
+
merged.set(methodName, fns);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return merged;
|
|
22
41
|
}
|
|
23
42
|
function hasHooks(target, key) {
|
|
24
43
|
const reflectionTarget = getReflectionTarget(target);
|
|
25
|
-
return Reflect.
|
|
44
|
+
return getConstructorChain(reflectionTarget.constructor).some((ctor) => Reflect.hasOwnMetadata(key, ctor));
|
|
26
45
|
}
|
|
27
46
|
// Hook decorator
|
|
28
47
|
const hook = (key, ...fns) => (target, propertyKey) => {
|
|
29
|
-
const hooks = Reflect.
|
|
30
|
-
? Reflect.
|
|
48
|
+
const hooks = Reflect.hasOwnMetadata(key, target.constructor)
|
|
49
|
+
? Reflect.getOwnMetadata(key, target.constructor)
|
|
31
50
|
: new Map();
|
|
32
51
|
hooks.set(propertyKey, (hooks.get(propertyKey) ?? []).concat(fns));
|
|
33
52
|
Reflect.defineMetadata(key, hooks, target.constructor);
|
package/cjm/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
4
|
-
exports.resolveConstructor = exports.Is = exports.pipe = exports.select = exports.once = exports.shallowCache = exports.debounce = exports.throttle = exports.handleAsyncError = exports.handleError = exports.getMethodTags = exports.methodTag = exports.getMethodLabels = exports.methodLabel = exports.getMethodMeta = exports.methodMeta = exports.getParamTags = exports.paramTag = exports.getParamLabels = exports.paramLabel = exports.getParamMeta = exports.paramMeta = exports.getClassTags = exports.classTag = exports.getClassLabels = exports.classLabel = exports.getClassMeta = exports.classMeta = exports.GroupInstanceToken = exports.ConstantToken = exports.FunctionToken = void 0;
|
|
3
|
+
exports.ClassToken = exports.toSingleAlias = exports.SingleAliasToken = exports.toGroupAlias = exports.GroupAliasToken = exports.InjectionToken = exports.HooksRunner = exports.AddOnDisposeHookModule = exports.onDispose = exports.onDisposeHooksRunner = exports.AddOnConstructHookModule = exports.onConstruct = exports.onConstructHooksRunner = exports.injectProp = exports.createHookContext = exports.createHookContextFactory = exports.HookContext = exports.hasHooks = exports.hook = exports.getHooks = exports.CannonSingletonApplyTwiceError = exports.UnexpectedHookResultError = exports.ProviderDisposedError = exports.ContainerDisposedError = exports.MethodNotImplementedError = exports.DependencyMissingKeyError = exports.ContainerNotFoundError = exports.DependencyNotFoundError = exports.Registration = exports.appendArgsFn = exports.appendArgs = exports.decorate = exports.singleton = exports.lazy = exports.scopeAccess = exports.scope = exports.bindTo = exports.register = exports.Provider = exports.ProxyInjector = exports.SimpleInjector = exports.resolveArgs = exports.argsFn = exports.args = exports.inject = exports.MetadataInjector = exports.Injector = exports.EmptyContainer = exports.Container = exports.isDependencyKey = void 0;
|
|
4
|
+
exports.resolveConstructor = exports.Is = exports.pipe = exports.select = exports.once = exports.shallowCache = exports.debounce = exports.throttle = exports.handleAsyncError = exports.handleError = exports.getMethodTags = exports.methodTag = exports.getMethodLabels = exports.methodLabel = exports.getMethodMeta = exports.methodMeta = exports.getParamTags = exports.paramTag = exports.getParamLabels = exports.paramLabel = exports.getParamMeta = exports.paramMeta = exports.getClassTags = exports.classTag = exports.getClassLabels = exports.classLabel = exports.getClassMeta = exports.classMeta = exports.GroupInstanceToken = exports.ConstantToken = exports.FunctionToken = exports.SingleToken = void 0;
|
|
5
5
|
// Containers
|
|
6
6
|
var IContainer_1 = require("./container/IContainer");
|
|
7
7
|
Object.defineProperty(exports, "isDependencyKey", { enumerable: true, get: function () { return IContainer_1.isDependencyKey; } });
|
|
@@ -40,6 +40,8 @@ Object.defineProperty(exports, "Registration", { enumerable: true, get: function
|
|
|
40
40
|
// Errors
|
|
41
41
|
var DependencyNotFoundError_1 = require("./errors/DependencyNotFoundError");
|
|
42
42
|
Object.defineProperty(exports, "DependencyNotFoundError", { enumerable: true, get: function () { return DependencyNotFoundError_1.DependencyNotFoundError; } });
|
|
43
|
+
var ContainerNotFoundError_1 = require("./errors/ContainerNotFoundError");
|
|
44
|
+
Object.defineProperty(exports, "ContainerNotFoundError", { enumerable: true, get: function () { return ContainerNotFoundError_1.ContainerNotFoundError; } });
|
|
43
45
|
var DependencyMissingKeyError_1 = require("./errors/DependencyMissingKeyError");
|
|
44
46
|
Object.defineProperty(exports, "DependencyMissingKeyError", { enumerable: true, get: function () { return DependencyMissingKeyError_1.DependencyMissingKeyError; } });
|
|
45
47
|
var MethodNotImplementedError_1 = require("./errors/MethodNotImplementedError");
|
|
@@ -3,6 +3,7 @@ import { ContainerDisposedError } from '../errors/ContainerDisposedError';
|
|
|
3
3
|
import { MetadataInjector } from '../injector/MetadataInjector';
|
|
4
4
|
import { AliasMap } from './AliasMap';
|
|
5
5
|
import { DependencyNotFoundError } from '../errors/DependencyNotFoundError';
|
|
6
|
+
import { ContainerNotFoundError } from '../errors/ContainerNotFoundError';
|
|
6
7
|
import { Is } from '../utils/basic';
|
|
7
8
|
import { Filter as F } from '../utils/array';
|
|
8
9
|
export class Container {
|
|
@@ -128,6 +129,21 @@ export class Container {
|
|
|
128
129
|
getScopes() {
|
|
129
130
|
return [...this.scopes];
|
|
130
131
|
}
|
|
132
|
+
hasInstance(instance) {
|
|
133
|
+
return this.instances.includes(instance);
|
|
134
|
+
}
|
|
135
|
+
getScopeByInstanceOrFail(instance) {
|
|
136
|
+
this.validateContainer();
|
|
137
|
+
const queue = [this];
|
|
138
|
+
while (queue.length > 0) {
|
|
139
|
+
const scope = queue.shift();
|
|
140
|
+
if (scope.hasInstance(instance)) {
|
|
141
|
+
return scope;
|
|
142
|
+
}
|
|
143
|
+
queue.push(...scope.getScopes());
|
|
144
|
+
}
|
|
145
|
+
throw new ContainerNotFoundError('Cannot find scope for the given instance');
|
|
146
|
+
}
|
|
131
147
|
removeScope(child) {
|
|
132
148
|
this.scopes = this.scopes.filter((s) => s !== child);
|
|
133
149
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { MethodNotImplementedError } from '../errors/MethodNotImplementedError';
|
|
2
2
|
import { DependencyNotFoundError } from '../errors/DependencyNotFoundError';
|
|
3
|
+
import { ContainerNotFoundError } from '../errors/ContainerNotFoundError';
|
|
3
4
|
export class EmptyContainer {
|
|
4
5
|
get isDisposed() {
|
|
5
6
|
throw new MethodNotImplementedError();
|
|
@@ -11,9 +12,15 @@ export class EmptyContainer {
|
|
|
11
12
|
getScopes() {
|
|
12
13
|
return [];
|
|
13
14
|
}
|
|
15
|
+
getScopeByInstanceOrFail(instance) {
|
|
16
|
+
throw new ContainerNotFoundError('Cannot find scope for the given instance');
|
|
17
|
+
}
|
|
14
18
|
getInstances() {
|
|
15
19
|
return [];
|
|
16
20
|
}
|
|
21
|
+
hasInstance(instance) {
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
17
24
|
createScope() {
|
|
18
25
|
throw new MethodNotImplementedError();
|
|
19
26
|
}
|
package/esm/hooks/hook.js
CHANGED
|
@@ -7,21 +7,40 @@ export const toHookFn = (execute) => isHookClassConstructor(execute) ? (context)
|
|
|
7
7
|
const getReflectionTarget = (target) => {
|
|
8
8
|
return isProxy(target) ? getProxyTarget(target) : target;
|
|
9
9
|
};
|
|
10
|
-
//
|
|
10
|
+
// Walk the constructor's prototype chain (most-derived first) collecting each class.
|
|
11
|
+
const getConstructorChain = (ctor) => {
|
|
12
|
+
const chain = [];
|
|
13
|
+
let current = ctor;
|
|
14
|
+
while (typeof current === 'function' && current !== Function.prototype) {
|
|
15
|
+
chain.push(current);
|
|
16
|
+
current = Object.getPrototypeOf(current);
|
|
17
|
+
}
|
|
18
|
+
return chain;
|
|
19
|
+
};
|
|
20
|
+
// Get hooks metadata, merging hooks declared on parent (extended-from) classes.
|
|
21
|
+
// Hooks are collected from base to derived so a derived class's hooks for the same
|
|
22
|
+
// method name take precedence over (replace) the parent's.
|
|
11
23
|
export function getHooks(target, key) {
|
|
12
24
|
const reflectionTarget = getReflectionTarget(target);
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
25
|
+
const merged = new Map();
|
|
26
|
+
for (const ctor of getConstructorChain(reflectionTarget.constructor).reverse()) {
|
|
27
|
+
const ownHooks = Reflect.getOwnMetadata(key, ctor);
|
|
28
|
+
if (ownHooks) {
|
|
29
|
+
for (const [methodName, fns] of ownHooks) {
|
|
30
|
+
merged.set(methodName, fns);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return merged;
|
|
16
35
|
}
|
|
17
36
|
export function hasHooks(target, key) {
|
|
18
37
|
const reflectionTarget = getReflectionTarget(target);
|
|
19
|
-
return Reflect.
|
|
38
|
+
return getConstructorChain(reflectionTarget.constructor).some((ctor) => Reflect.hasOwnMetadata(key, ctor));
|
|
20
39
|
}
|
|
21
40
|
// Hook decorator
|
|
22
41
|
export const hook = (key, ...fns) => (target, propertyKey) => {
|
|
23
|
-
const hooks = Reflect.
|
|
24
|
-
? Reflect.
|
|
42
|
+
const hooks = Reflect.hasOwnMetadata(key, target.constructor)
|
|
43
|
+
? Reflect.getOwnMetadata(key, target.constructor)
|
|
25
44
|
: new Map();
|
|
26
45
|
hooks.set(propertyKey, (hooks.get(propertyKey) ?? []).concat(fns));
|
|
27
46
|
Reflect.defineMetadata(key, hooks, target.constructor);
|
package/esm/index.js
CHANGED
|
@@ -13,6 +13,7 @@ export { register, bindTo, scope, scopeAccess, lazy, singleton, decorate, append
|
|
|
13
13
|
export { Registration } from './registration/Registration';
|
|
14
14
|
// Errors
|
|
15
15
|
export { DependencyNotFoundError } from './errors/DependencyNotFoundError';
|
|
16
|
+
export { ContainerNotFoundError } from './errors/ContainerNotFoundError';
|
|
16
17
|
export { DependencyMissingKeyError } from './errors/DependencyMissingKeyError';
|
|
17
18
|
export { MethodNotImplementedError } from './errors/MethodNotImplementedError';
|
|
18
19
|
export { ContainerDisposedError } from './errors/ContainerDisposedError';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ts-ioc-container",
|
|
3
|
-
"version": "54.
|
|
3
|
+
"version": "54.1.0",
|
|
4
4
|
"description": "Fast, lightweight TypeScript dependency injection container with a clean API, scoped lifecycles, decorators, tokens, hooks, lazy injection, customizable providers, and no global container objects.",
|
|
5
5
|
"workspaces": [
|
|
6
6
|
"docs"
|
|
@@ -35,6 +35,8 @@ export declare class Container implements IContainer {
|
|
|
35
35
|
addOnDisposeHook(...hooks: OnDisposeHook[]): this;
|
|
36
36
|
addInstance(instance: Instance): void;
|
|
37
37
|
getScopes(): IContainer[];
|
|
38
|
+
hasInstance(instance: object): boolean;
|
|
39
|
+
getScopeByInstanceOrFail(instance: object): IContainer;
|
|
38
40
|
removeScope(child: IContainer): void;
|
|
39
41
|
useModule(module: IContainerModule): this;
|
|
40
42
|
getParent(): IContainer;
|
|
@@ -9,7 +9,9 @@ export declare class EmptyContainer implements IContainer {
|
|
|
9
9
|
addInstance(instance: Instance): void;
|
|
10
10
|
getParent(): undefined;
|
|
11
11
|
getScopes(): never[];
|
|
12
|
+
getScopeByInstanceOrFail(instance: object): IContainer;
|
|
12
13
|
getInstances(): never[];
|
|
14
|
+
hasInstance(instance: object): boolean;
|
|
13
15
|
createScope(): IContainer;
|
|
14
16
|
dispose(): void;
|
|
15
17
|
register(key: DependencyKey, value: IProvider): this;
|
|
@@ -44,10 +44,12 @@ export interface IContainer extends Tagged {
|
|
|
44
44
|
resolveOneByAlias<T>(alias: DependencyKey, options?: ResolveOneOptions): T;
|
|
45
45
|
createScope(options?: CreateScopeOptions): IContainer;
|
|
46
46
|
getScopes(): IContainer[];
|
|
47
|
+
getScopeByInstanceOrFail(instance: object): IContainer;
|
|
47
48
|
removeScope(child: IContainer): void;
|
|
48
49
|
useModule(module: IContainerModule): this;
|
|
49
50
|
getParent(): IContainer | undefined;
|
|
50
51
|
getInstances(cascade?: boolean): Instance[];
|
|
52
|
+
hasInstance(instance: object): boolean;
|
|
51
53
|
dispose(): void;
|
|
52
54
|
addInstance(instance: Instance): void;
|
|
53
55
|
}
|
package/typings/index.d.ts
CHANGED
|
@@ -10,6 +10,7 @@ export { Provider } from './provider/Provider';
|
|
|
10
10
|
export { type IRegistration, type ReturnTypeOfRegistration, type ScopeMatchRule, type ProviderPipe, register, bindTo, scope, scopeAccess, lazy, singleton, decorate, appendArgs, appendArgsFn, } from './registration/IRegistration';
|
|
11
11
|
export { Registration } from './registration/Registration';
|
|
12
12
|
export { DependencyNotFoundError } from './errors/DependencyNotFoundError';
|
|
13
|
+
export { ContainerNotFoundError } from './errors/ContainerNotFoundError';
|
|
13
14
|
export { DependencyMissingKeyError } from './errors/DependencyMissingKeyError';
|
|
14
15
|
export { MethodNotImplementedError } from './errors/MethodNotImplementedError';
|
|
15
16
|
export { ContainerDisposedError } from './errors/ContainerDisposedError';
|