ts-ioc-container 53.0.0 → 54.0.1

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/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
- // Get hooks metadata
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
- return Reflect.hasMetadata(key, reflectionTarget.constructor)
20
- ? Reflect.getMetadata(key, reflectionTarget.constructor)
21
- : new Map();
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.hasMetadata(key, reflectionTarget.constructor);
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.hasMetadata(key, target.constructor)
30
- ? Reflect.getMetadata(key, target.constructor)
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/utils/once.js CHANGED
@@ -1,11 +1,14 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.once = void 0;
4
- const once = (target, propertyKey, descriptor) => {
4
+ const once = ({ onRepeat } = {}) => (target, propertyKey, descriptor) => {
5
5
  const originalMethod = descriptor.value;
6
6
  const cacheMap = new WeakMap();
7
+ let index = 0;
7
8
  descriptor.value = function (...args) {
9
+ index++;
8
10
  if (cacheMap.has(this)) {
11
+ onRepeat?.({ index: index - 1, args });
9
12
  return cacheMap.get(this);
10
13
  }
11
14
  const result = originalMethod.apply(this, args);
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
- // Get hooks metadata
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
- return Reflect.hasMetadata(key, reflectionTarget.constructor)
14
- ? Reflect.getMetadata(key, reflectionTarget.constructor)
15
- : new Map();
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.hasMetadata(key, reflectionTarget.constructor);
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.hasMetadata(key, target.constructor)
24
- ? Reflect.getMetadata(key, target.constructor)
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/utils/once.js CHANGED
@@ -1,8 +1,11 @@
1
- export const once = (target, propertyKey, descriptor) => {
1
+ export const once = ({ onRepeat } = {}) => (target, propertyKey, descriptor) => {
2
2
  const originalMethod = descriptor.value;
3
3
  const cacheMap = new WeakMap();
4
+ let index = 0;
4
5
  descriptor.value = function (...args) {
6
+ index++;
5
7
  if (cacheMap.has(this)) {
8
+ onRepeat?.({ index: index - 1, args });
6
9
  return cacheMap.get(this);
7
10
  }
8
11
  const result = originalMethod.apply(this, args);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ts-ioc-container",
3
- "version": "53.0.0",
3
+ "version": "54.0.1",
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"
@@ -1 +1,8 @@
1
- export declare const once: MethodDecorator;
1
+ type RepeatOptions = {
2
+ index: number;
3
+ args: unknown[];
4
+ };
5
+ export declare const once: ({ onRepeat }?: {
6
+ onRepeat?: (options: RepeatOptions) => void;
7
+ }) => MethodDecorator;
8
+ export {};