ts-ioc-container 32.10.0 → 32.11.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/README.md CHANGED
@@ -785,7 +785,7 @@ import {
785
785
  Registration as R,
786
786
  scope,
787
787
  } from 'ts-ioc-container';
788
- import { constant } from '../../lib/utils.ts';
788
+ import { constant } from '../../lib/utils';
789
789
 
790
790
  describe('alias', () => {
791
791
  const IMiddlewareKey = 'IMiddleware';
@@ -1145,23 +1145,23 @@ import 'reflect-metadata';
1145
1145
  import {
1146
1146
  constructor,
1147
1147
  Container,
1148
- key,
1149
1148
  hook,
1150
1149
  IContainer,
1151
1150
  IInjector,
1151
+ InjectOptions,
1152
+ key,
1152
1153
  MetadataInjector,
1153
- Registration as R,
1154
1154
  register,
1155
- executeHooks,
1155
+ Registration as R,
1156
+ runHooks,
1156
1157
  } from 'ts-ioc-container';
1157
- import { InjectOptions } from '../lib/injector/IInjector.ts';
1158
1158
 
1159
1159
  class MyInjector implements IInjector {
1160
1160
  private injector = new MetadataInjector();
1161
1161
 
1162
1162
  resolve<T>(container: IContainer, value: constructor<T>, options: InjectOptions): T {
1163
1163
  const instance = this.injector.resolve(container, value, options);
1164
- executeHooks(instance as object, 'onConstruct', { scope: container });
1164
+ void runHooks(instance as object, 'onConstruct', { scope: container, handleError: jest.fn() });
1165
1165
  return instance;
1166
1166
  }
1167
1167
  }
@@ -1170,7 +1170,9 @@ class MyInjector implements IInjector {
1170
1170
  class Logger {
1171
1171
  isReady = false;
1172
1172
 
1173
- @hook('onConstruct', (context) => context.invokeMethod({ args: [] })) // <--- or extract it to @onConstruct
1173
+ @hook('onConstruct', (context) => {
1174
+ context.invokeMethod({ args: [] });
1175
+ }) // <--- or extract it to @onConstruct
1174
1176
  initialize() {
1175
1177
  this.isReady = true;
1176
1178
  }
@@ -1196,17 +1198,17 @@ describe('onConstruct', function () {
1196
1198
  ```typescript
1197
1199
  import 'reflect-metadata';
1198
1200
  import {
1199
- singleton,
1200
1201
  by,
1201
1202
  Container,
1202
- key,
1203
1203
  hook,
1204
1204
  inject,
1205
- provider,
1206
- Registration as R,
1205
+ key,
1207
1206
  MetadataInjector,
1207
+ provider,
1208
1208
  register,
1209
- executeHooks,
1209
+ Registration as R,
1210
+ runHooks,
1211
+ singleton,
1210
1212
  } from 'ts-ioc-container';
1211
1213
 
1212
1214
  @register(key('logsRepo'))
@@ -1237,7 +1239,9 @@ class Logger {
1237
1239
  return this.messages.length;
1238
1240
  }
1239
1241
 
1240
- @hook('onDispose', (c) => c.invokeMethod({ args: [] })) // <--- or extract it to @onDispose
1242
+ @hook('onDispose', (c) => {
1243
+ c.invokeMethod({ args: [] });
1244
+ }) // <--- or extract it to @onDispose
1241
1245
  async save(): Promise<void> {
1242
1246
  this.logsRepo.saveLogs(this.messages);
1243
1247
  }
@@ -1251,7 +1255,7 @@ describe('onDispose', function () {
1251
1255
  logger.log('Hello');
1252
1256
 
1253
1257
  for (const instance of container.getInstances()) {
1254
- executeHooks(instance as object, 'onDispose', { scope: container });
1258
+ void runHooks(instance as object, 'onDispose', { scope: container, handleError: jest.fn() });
1255
1259
  }
1256
1260
 
1257
1261
  expect(container.resolve<LogsRepo>('logsRepo').savedLogs.join(',')).toBe('Hello,world');
@@ -1263,7 +1267,7 @@ describe('onDispose', function () {
1263
1267
  ### Inject property
1264
1268
 
1265
1269
  ```typescript
1266
- import { by, Container, executeHooks, hook, injectProp, MetadataInjector, Registration } from 'ts-ioc-container';
1270
+ import { by, Container, hook, injectProp, MetadataInjector, Registration, runHooks } from 'ts-ioc-container';
1267
1271
 
1268
1272
  describe('inject property', () => {
1269
1273
  it('should inject property', () => {
@@ -1275,7 +1279,7 @@ describe('inject property', () => {
1275
1279
 
1276
1280
  const container = new Container(new MetadataInjector()).add(Registration.fromValue(expected).to('greeting'));
1277
1281
  const app = container.resolve(App);
1278
- executeHooks(app, 'onInit', { scope: container });
1282
+ runHooks(app as object, 'onInit', { scope: container, handleError: jest.fn() });
1279
1283
 
1280
1284
  expect(app.greeting).toBe(expected);
1281
1285
  });
@@ -1286,7 +1290,7 @@ describe('inject property', () => {
1286
1290
  ### Inject method
1287
1291
 
1288
1292
  ```typescript
1289
- import { by, Container, executeHooks, hook, inject, invokeExecution, MetadataInjector, Registration } from 'ts-ioc-container';
1293
+ import { by, Container, runHooks, hook, inject, invokeExecution, MetadataInjector, Registration } from 'ts-ioc-container';
1290
1294
 
1291
1295
  describe('inject method', () => {
1292
1296
  const sleep = (number: number) => new Promise((resolve) => setTimeout(resolve, number));
@@ -1304,7 +1308,7 @@ describe('inject method', () => {
1304
1308
 
1305
1309
  const container = new Container(new MetadataInjector()).add(Registration.fromValue(expected).to('greeting'));
1306
1310
  const app = container.resolve(App);
1307
- await executeHooks(app, 'onInit', { scope: container, handleError: jest.fn() });
1311
+ await runHooks(app, 'onInit', { scope: container, handleError: jest.fn() });
1308
1312
 
1309
1313
  expect(app.greeting).toBe(expected);
1310
1314
  });
@@ -1324,7 +1328,7 @@ describe('inject method', () => {
1324
1328
  .add(Registration.fromFn(() => sleep(25).then(() => 'world')).to('person'));
1325
1329
 
1326
1330
  const app = container.resolve(App);
1327
- await executeHooks(app, 'onInit', { scope: container, handleError: jest.fn() });
1331
+ await runHooks(app, 'onInit', { scope: container, handleError: jest.fn() });
1328
1332
 
1329
1333
  expect(app.greeting).toBe('Hello,world');
1330
1334
  });
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.hookMetaKey = exports.createHookContext = exports.HookContext = void 0;
4
+ const inject_1 = require("../injector/inject");
5
+ class HookContext {
6
+ constructor(instance, scope, methodName) {
7
+ this.instance = instance;
8
+ this.scope = scope;
9
+ this.methodName = methodName;
10
+ }
11
+ resolveArgs(...args) {
12
+ return (0, inject_1.resolveArgs)(this.instance.constructor, this.methodName)(this.scope, ...args);
13
+ }
14
+ invokeMethod({ args = this.resolveArgs() }) {
15
+ // @ts-ignore
16
+ return this.instance[this.methodName](...args);
17
+ }
18
+ injectProperty(fn) {
19
+ // @ts-ignore
20
+ this.instance[this.methodName] = fn(this.scope);
21
+ }
22
+ }
23
+ exports.HookContext = HookContext;
24
+ const createHookContext = (Target, scope, methodName = 'constructor') => new HookContext(Target, scope, methodName);
25
+ exports.createHookContext = createHookContext;
26
+ const hookMetaKey = (methodName = 'constructor') => `inject:${methodName}`;
27
+ exports.hookMetaKey = hookMetaKey;
package/cjm/hooks/hook.js CHANGED
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.invokeExecution = exports.injectProp = exports.executeHooks = exports.hasHooks = exports.getHooks = exports.hook = void 0;
4
- const ExecutionContext_1 = require("./ExecutionContext");
3
+ exports.executeHooks = exports.invokeExecution = exports.injectProp = exports.runHooks = exports.hasHooks = exports.getHooks = exports.hook = void 0;
4
+ const HookContext_1 = require("./HookContext");
5
5
  const utils_1 = require("../utils");
6
6
  const hook = (key, ...fns) => (target, propertyKey) => {
7
7
  const hooks = Reflect.hasMetadata(key, target.constructor)
@@ -19,13 +19,12 @@ function hasHooks(target, key) {
19
19
  return Reflect.hasMetadata(key, target.constructor);
20
20
  }
21
21
  exports.hasHooks = hasHooks;
22
- const executeHooks = (target, key, { scope, decorateContext = (c) => c, handleError, }) => {
22
+ const runHooks = (target, key, { scope, createContext = HookContext_1.createHookContext, handleError, }) => {
23
23
  const hooks = Array.from(getHooks(target, key).entries());
24
- const createContext = (methodName) => decorateContext(new ExecutionContext_1.ExecutionContext(target, methodName, scope));
25
24
  const runExecution = (execute, context) => (0, utils_1.promisify)(execute(context)).catch((e) => handleError(e, scope));
26
- return Promise.all(hooks.flatMap(([methodName, executions]) => executions.map((execute) => runExecution(execute, createContext(methodName)))));
25
+ return Promise.all(hooks.flatMap(([methodName, executions]) => executions.map((execute) => runExecution(execute, createContext(target, scope, methodName)))));
27
26
  };
28
- exports.executeHooks = executeHooks;
27
+ exports.runHooks = runHooks;
29
28
  const injectProp = (fn) => (context) => context.injectProperty(fn);
30
29
  exports.injectProp = injectProp;
31
30
  const invokeExecution = ({ handleResult }) => async (context) => {
@@ -33,3 +32,8 @@ const invokeExecution = ({ handleResult }) => async (context) => {
33
32
  return handleResult(context.invokeMethod({ args }), context);
34
33
  };
35
34
  exports.invokeExecution = invokeExecution;
35
+ /**
36
+ * @deprecated Use `runHooks` instead
37
+ * @TODO: Remove in v33
38
+ */
39
+ exports.executeHooks = exports.runHooks;
package/cjm/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getParameterMetadata = exports.getMethodMetadata = exports.setMethodMetadata = exports.setParameterMetadata = exports.getMetadata = exports.setMetadata = exports.byAliases = exports.byAlias = exports.IMemoKey = exports.by = exports.ExecutionContext = exports.invokeExecution = exports.injectProp = exports.executeHooks = exports.hasHooks = exports.hook = exports.getHooks = exports.ContainerDisposedError = exports.MethodNotImplementedError = exports.DependencyNotFoundError = exports.Registration = exports.register = exports.scope = exports.key = exports.decorate = exports.multiCache = exports.MultiCache = exports.SingletonProvider = exports.singleton = exports.Provider = exports.ProviderDecorator = exports.args = exports.argsFn = exports.alias = exports.visible = exports.provider = exports.ProxyInjector = exports.SimpleInjector = exports.getInjectFns = exports.resolveArgs = exports.inject = exports.MetadataInjector = exports.AutoMockedContainer = exports.EmptyContainer = exports.Container = exports.isDependencyKey = void 0;
3
+ exports.getParameterMetadata = exports.getMethodMetadata = exports.setMethodMetadata = exports.setParameterMetadata = exports.getMetadata = exports.setMetadata = exports.byAliases = exports.byAlias = exports.IMemoKey = exports.by = exports.HookContext = exports.invokeExecution = exports.injectProp = exports.runHooks = exports.executeHooks = exports.hasHooks = exports.hook = exports.getHooks = exports.ContainerDisposedError = exports.MethodNotImplementedError = exports.DependencyNotFoundError = exports.Registration = exports.register = exports.scope = exports.key = exports.decorate = exports.multiCache = exports.MultiCache = exports.SingletonProvider = exports.singleton = exports.Provider = exports.ProviderDecorator = exports.args = exports.argsFn = exports.alias = exports.visible = exports.provider = exports.ProxyInjector = exports.SimpleInjector = exports.MetadataInjector = exports.resolveArgs = exports.inject = exports.AutoMockedContainer = exports.EmptyContainer = exports.Container = exports.isDependencyKey = void 0;
4
4
  // Containers
5
5
  var IContainer_1 = require("./container/IContainer");
6
6
  Object.defineProperty(exports, "isDependencyKey", { enumerable: true, get: function () { return IContainer_1.isDependencyKey; } });
@@ -10,11 +10,12 @@ var EmptyContainer_1 = require("./container/EmptyContainer");
10
10
  Object.defineProperty(exports, "EmptyContainer", { enumerable: true, get: function () { return EmptyContainer_1.EmptyContainer; } });
11
11
  var AutoMockedContainer_1 = require("./container/AutoMockedContainer");
12
12
  Object.defineProperty(exports, "AutoMockedContainer", { enumerable: true, get: function () { return AutoMockedContainer_1.AutoMockedContainer; } });
13
+ // Injectors
14
+ var inject_1 = require("./injector/inject");
15
+ Object.defineProperty(exports, "inject", { enumerable: true, get: function () { return inject_1.inject; } });
16
+ Object.defineProperty(exports, "resolveArgs", { enumerable: true, get: function () { return inject_1.resolveArgs; } });
13
17
  var MetadataInjector_1 = require("./injector/MetadataInjector");
14
18
  Object.defineProperty(exports, "MetadataInjector", { enumerable: true, get: function () { return MetadataInjector_1.MetadataInjector; } });
15
- Object.defineProperty(exports, "inject", { enumerable: true, get: function () { return MetadataInjector_1.inject; } });
16
- Object.defineProperty(exports, "resolveArgs", { enumerable: true, get: function () { return MetadataInjector_1.resolveArgs; } });
17
- Object.defineProperty(exports, "getInjectFns", { enumerable: true, get: function () { return MetadataInjector_1.getInjectFns; } });
18
19
  var SimpleInjector_1 = require("./injector/SimpleInjector");
19
20
  Object.defineProperty(exports, "SimpleInjector", { enumerable: true, get: function () { return SimpleInjector_1.SimpleInjector; } });
20
21
  var ProxyInjector_1 = require("./injector/ProxyInjector");
@@ -57,10 +58,11 @@ Object.defineProperty(exports, "getHooks", { enumerable: true, get: function ()
57
58
  Object.defineProperty(exports, "hook", { enumerable: true, get: function () { return hook_1.hook; } });
58
59
  Object.defineProperty(exports, "hasHooks", { enumerable: true, get: function () { return hook_1.hasHooks; } });
59
60
  Object.defineProperty(exports, "executeHooks", { enumerable: true, get: function () { return hook_1.executeHooks; } });
61
+ Object.defineProperty(exports, "runHooks", { enumerable: true, get: function () { return hook_1.runHooks; } });
60
62
  Object.defineProperty(exports, "injectProp", { enumerable: true, get: function () { return hook_1.injectProp; } });
61
63
  Object.defineProperty(exports, "invokeExecution", { enumerable: true, get: function () { return hook_1.invokeExecution; } });
62
- var ExecutionContext_1 = require("./hooks/ExecutionContext");
63
- Object.defineProperty(exports, "ExecutionContext", { enumerable: true, get: function () { return ExecutionContext_1.ExecutionContext; } });
64
+ var HookContext_1 = require("./hooks/HookContext");
65
+ Object.defineProperty(exports, "HookContext", { enumerable: true, get: function () { return HookContext_1.HookContext; } });
64
66
  // Others
65
67
  var by_1 = require("./by");
66
68
  Object.defineProperty(exports, "by", { enumerable: true, get: function () { return by_1.by; } });
@@ -1,27 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.MetadataInjector = exports.resolveArgs = exports.inject = exports.getInjectFns = void 0;
4
- const utils_1 = require("../utils");
5
- const metadata_1 = require("../metadata");
6
- const METADATA_KEY = 'inject';
7
- const getInjectFns = (Target, methodName) => (0, metadata_1.getParameterMetadata)(metaKey(methodName), Target);
8
- exports.getInjectFns = getInjectFns;
9
- const metaKey = (methodName = 'constructor') => `${METADATA_KEY}:${methodName}`;
10
- function isInstance(target) {
11
- return Object.prototype.hasOwnProperty.call(target, 'constructor');
12
- }
13
- const inject = (fn) => (target, propertyKey, parameterIndex) => {
14
- (0, metadata_1.setParameterMetadata)(metaKey(propertyKey), fn)(isInstance(target) ? target.constructor : target, propertyKey, parameterIndex);
15
- };
16
- exports.inject = inject;
17
- const resolveArgs = (Target, methodName) => {
18
- const argsFns = (0, exports.getInjectFns)(Target, methodName);
19
- return (scope, ...deps) => (0, utils_1.fillEmptyIndexes)(argsFns, deps.map(utils_1.constant)).map((fn) => fn(scope));
20
- };
21
- exports.resolveArgs = resolveArgs;
3
+ exports.MetadataInjector = void 0;
4
+ const inject_1 = require("./inject");
22
5
  class MetadataInjector {
23
- resolve(container, Target, { args: deps }) {
24
- const args = (0, exports.resolveArgs)(Target)(container, ...deps);
6
+ resolve(scope, Target, { args: deps }) {
7
+ const args = (0, inject_1.resolveArgs)(Target)(scope, ...deps);
25
8
  return new Target(...args);
26
9
  }
27
10
  }
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.resolveArgs = exports.inject = void 0;
4
+ const metadata_1 = require("../metadata");
5
+ const utils_1 = require("../utils");
6
+ const HookContext_1 = require("../hooks/HookContext");
7
+ const inject = (fn) => (target, propertyKey, parameterIndex) => {
8
+ (0, metadata_1.setParameterMetadata)((0, HookContext_1.hookMetaKey)(propertyKey), fn)((0, utils_1.isInstance)(target) ? target.constructor : target, propertyKey, parameterIndex);
9
+ };
10
+ exports.inject = inject;
11
+ const resolveArgs = (Target, methodName) => {
12
+ const argsFns = getInjectFns(Target, methodName);
13
+ return (scope, ...deps) => (0, utils_1.fillEmptyIndexes)(argsFns, deps.map(utils_1.constant)).map((fn) => fn(scope));
14
+ };
15
+ exports.resolveArgs = resolveArgs;
16
+ const getInjectFns = (Target, methodName) => (0, metadata_1.getParameterMetadata)((0, HookContext_1.hookMetaKey)(methodName), Target);
package/cjm/utils.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.promisify = exports.lazyProxy = exports.isConstructor = exports.constant = exports.fillEmptyIndexes = exports.pipe = void 0;
3
+ exports.isInstance = exports.promisify = exports.lazyProxy = exports.isConstructor = exports.constant = exports.fillEmptyIndexes = exports.pipe = void 0;
4
4
  const pipe = (...mappers) => (value) => mappers.reduce((acc, current) => current(acc), value);
5
5
  exports.pipe = pipe;
6
6
  function fillEmptyIndexes(baseArr, insertArr) {
@@ -31,3 +31,7 @@ function lazyProxy(resolveInstance) {
31
31
  exports.lazyProxy = lazyProxy;
32
32
  const promisify = (arg) => (arg instanceof Promise ? arg : Promise.resolve(arg));
33
33
  exports.promisify = promisify;
34
+ function isInstance(target) {
35
+ return Object.prototype.hasOwnProperty.call(target, 'constructor');
36
+ }
37
+ exports.isInstance = isInstance;
@@ -1,9 +1,9 @@
1
- import { resolveArgs } from '../injector/MetadataInjector';
2
- export class ExecutionContext {
3
- constructor(instance, methodName, scope) {
1
+ import { resolveArgs } from '../injector/inject';
2
+ export class HookContext {
3
+ constructor(instance, scope, methodName) {
4
4
  this.instance = instance;
5
- this.methodName = methodName;
6
5
  this.scope = scope;
6
+ this.methodName = methodName;
7
7
  }
8
8
  resolveArgs(...args) {
9
9
  return resolveArgs(this.instance.constructor, this.methodName)(this.scope, ...args);
@@ -17,3 +17,5 @@ export class ExecutionContext {
17
17
  this.instance[this.methodName] = fn(this.scope);
18
18
  }
19
19
  }
20
+ export const createHookContext = (Target, scope, methodName = 'constructor') => new HookContext(Target, scope, methodName);
21
+ export const hookMetaKey = (methodName = 'constructor') => `inject:${methodName}`;
package/esm/hooks/hook.js CHANGED
@@ -1,4 +1,4 @@
1
- import { ExecutionContext } from './ExecutionContext';
1
+ import { createHookContext } from './HookContext';
2
2
  import { promisify } from '../utils';
3
3
  export const hook = (key, ...fns) => (target, propertyKey) => {
4
4
  const hooks = Reflect.hasMetadata(key, target.constructor)
@@ -13,14 +13,18 @@ export function getHooks(target, key) {
13
13
  export function hasHooks(target, key) {
14
14
  return Reflect.hasMetadata(key, target.constructor);
15
15
  }
16
- export const executeHooks = (target, key, { scope, decorateContext = (c) => c, handleError, }) => {
16
+ export const runHooks = (target, key, { scope, createContext = createHookContext, handleError, }) => {
17
17
  const hooks = Array.from(getHooks(target, key).entries());
18
- const createContext = (methodName) => decorateContext(new ExecutionContext(target, methodName, scope));
19
18
  const runExecution = (execute, context) => promisify(execute(context)).catch((e) => handleError(e, scope));
20
- return Promise.all(hooks.flatMap(([methodName, executions]) => executions.map((execute) => runExecution(execute, createContext(methodName)))));
19
+ return Promise.all(hooks.flatMap(([methodName, executions]) => executions.map((execute) => runExecution(execute, createContext(target, scope, methodName)))));
21
20
  };
22
21
  export const injectProp = (fn) => (context) => context.injectProperty(fn);
23
22
  export const invokeExecution = ({ handleResult }) => async (context) => {
24
23
  const args = await Promise.all(context.resolveArgs().map(promisify));
25
24
  return handleResult(context.invokeMethod({ args }), context);
26
25
  };
26
+ /**
27
+ * @deprecated Use `runHooks` instead
28
+ * @TODO: Remove in v33
29
+ */
30
+ export const executeHooks = runHooks;
package/esm/index.js CHANGED
@@ -3,7 +3,9 @@ export { isDependencyKey, } from './container/IContainer';
3
3
  export { Container } from './container/Container';
4
4
  export { EmptyContainer } from './container/EmptyContainer';
5
5
  export { AutoMockedContainer } from './container/AutoMockedContainer';
6
- export { MetadataInjector, inject, resolveArgs, getInjectFns } from './injector/MetadataInjector';
6
+ // Injectors
7
+ export { inject, resolveArgs } from './injector/inject';
8
+ export { MetadataInjector } from './injector/MetadataInjector';
7
9
  export { SimpleInjector } from './injector/SimpleInjector';
8
10
  export { ProxyInjector } from './injector/ProxyInjector';
9
11
  // Providers
@@ -20,8 +22,8 @@ export { DependencyNotFoundError } from './errors/DependencyNotFoundError';
20
22
  export { MethodNotImplementedError } from './errors/MethodNotImplementedError';
21
23
  export { ContainerDisposedError } from './errors/ContainerDisposedError';
22
24
  // Hooks
23
- export { getHooks, hook, hasHooks, executeHooks, injectProp, invokeExecution } from './hooks/hook';
24
- export { ExecutionContext } from './hooks/ExecutionContext';
25
+ export { getHooks, hook, hasHooks, executeHooks, runHooks, injectProp, invokeExecution } from './hooks/hook';
26
+ export { HookContext } from './hooks/HookContext';
25
27
  // Others
26
28
  export { by, IMemoKey, byAlias, byAliases } from './by';
27
29
  export { setMetadata, getMetadata, setParameterMetadata, setMethodMetadata, getMethodMetadata, getParameterMetadata, } from './metadata';
@@ -1,21 +1,7 @@
1
- import { constant, fillEmptyIndexes } from '../utils';
2
- import { setParameterMetadata, getParameterMetadata } from '../metadata';
3
- const METADATA_KEY = 'inject';
4
- export const getInjectFns = (Target, methodName) => getParameterMetadata(metaKey(methodName), Target);
5
- const metaKey = (methodName = 'constructor') => `${METADATA_KEY}:${methodName}`;
6
- function isInstance(target) {
7
- return Object.prototype.hasOwnProperty.call(target, 'constructor');
8
- }
9
- export const inject = (fn) => (target, propertyKey, parameterIndex) => {
10
- setParameterMetadata(metaKey(propertyKey), fn)(isInstance(target) ? target.constructor : target, propertyKey, parameterIndex);
11
- };
12
- export const resolveArgs = (Target, methodName) => {
13
- const argsFns = getInjectFns(Target, methodName);
14
- return (scope, ...deps) => fillEmptyIndexes(argsFns, deps.map(constant)).map((fn) => fn(scope));
15
- };
1
+ import { resolveArgs } from './inject';
16
2
  export class MetadataInjector {
17
- resolve(container, Target, { args: deps }) {
18
- const args = resolveArgs(Target)(container, ...deps);
3
+ resolve(scope, Target, { args: deps }) {
4
+ const args = resolveArgs(Target)(scope, ...deps);
19
5
  return new Target(...args);
20
6
  }
21
7
  }
@@ -0,0 +1,11 @@
1
+ import { getParameterMetadata, setParameterMetadata } from '../metadata';
2
+ import { constant, fillEmptyIndexes, isInstance } from '../utils';
3
+ import { hookMetaKey } from '../hooks/HookContext';
4
+ export const inject = (fn) => (target, propertyKey, parameterIndex) => {
5
+ setParameterMetadata(hookMetaKey(propertyKey), fn)(isInstance(target) ? target.constructor : target, propertyKey, parameterIndex);
6
+ };
7
+ export const resolveArgs = (Target, methodName) => {
8
+ const argsFns = getInjectFns(Target, methodName);
9
+ return (scope, ...deps) => fillEmptyIndexes(argsFns, deps.map(constant)).map((fn) => fn(scope));
10
+ };
11
+ const getInjectFns = (Target, methodName) => getParameterMetadata(hookMetaKey(methodName), Target);
package/esm/utils.js CHANGED
@@ -22,3 +22,6 @@ export function lazyProxy(resolveInstance) {
22
22
  });
23
23
  }
24
24
  export const promisify = (arg) => (arg instanceof Promise ? arg : Promise.resolve(arg));
25
+ export function isInstance(target) {
26
+ return Object.prototype.hasOwnProperty.call(target, 'constructor');
27
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ts-ioc-container",
3
- "version": "32.10.0",
3
+ "version": "32.11.0",
4
4
  "description": "Typescript IoC container",
5
5
  "publishConfig": {
6
6
  "access": "public",
@@ -59,5 +59,5 @@
59
59
  "ts-node": "^10.9.1",
60
60
  "typescript": "5.4.3"
61
61
  },
62
- "gitHead": "1feb3be27939265fa91d93aabc3c08fd5c235c27"
62
+ "gitHead": "75d723a20c55049f12bbc0cebe816edf4b4b30a1"
63
63
  }
package/typings/by.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { DependencyKey, IContainer, InjectionToken } from './container/IContainer';
2
2
  import { ProviderResolveOptions } from './provider/IProvider';
3
- import { InjectFn } from './injector/MetadataInjector';
3
+ import { InjectFn } from './hooks/HookContext';
4
4
  export type InstancePredicate = (dep: unknown) => boolean;
5
5
  export declare const all: InstancePredicate;
6
6
  export type IMemo = Map<string, DependencyKey[]>;
@@ -18,7 +18,7 @@ export declare const by: {
18
18
  args?: unknown[] | undefined;
19
19
  lazy?: boolean | undefined;
20
20
  }) => (c: IContainer, ...args: unknown[]) => T;
21
- instances: (predicate?: InstancePredicate) => (l: IContainer) => unknown[];
21
+ instances: (predicate?: InstancePredicate) => (l: IContainer) => object[];
22
22
  scope: {
23
23
  current: (container: IContainer) => IContainer;
24
24
  create: (...tags: string[]) => (l: IContainer) => IContainer;
@@ -7,7 +7,7 @@ export declare abstract class AutoMockedContainer implements IContainer {
7
7
  abstract resolve<T>(key: InjectionToken<T>, options?: ResolveOptions): T;
8
8
  dispose(): void;
9
9
  register(): this;
10
- getInstances(): unknown[];
10
+ getInstances(): object[];
11
11
  removeScope(): void;
12
12
  use(): this;
13
13
  getRegistrations(): never[];
@@ -20,7 +20,7 @@ export declare class Container implements IContainer {
20
20
  resolve<T>(token: InjectionToken<T>, { args, child, lazy }?: ResolveOptions): T;
21
21
  createScope(...tags: Tag[]): Container;
22
22
  dispose(): void;
23
- getInstances(): unknown[];
23
+ getInstances(): object[];
24
24
  hasTag(tag: Tag): boolean;
25
25
  use(module: IContainerModule): this;
26
26
  hasDependency(key: DependencyKey): boolean;
@@ -10,7 +10,7 @@ export declare class EmptyContainer implements IContainer {
10
10
  register(key: DependencyKey, value: IProvider): this;
11
11
  resolve<T>(key: InjectionToken<T>, options: ResolveOptions): T;
12
12
  getRegistrations(): never[];
13
- getInstances(): unknown[];
13
+ getInstances(): object[];
14
14
  removeScope(): void;
15
15
  use(module: IContainerModule): this;
16
16
  add(registration: IRegistration): this;
@@ -28,7 +28,7 @@ export interface IContainer extends Resolvable, Tagged {
28
28
  register(key: DependencyKey, value: IProvider): this;
29
29
  add(registration: IRegistration): this;
30
30
  removeScope(child: IContainer): void;
31
- getInstances(): unknown[];
31
+ getInstances(): object[];
32
32
  dispose(): void;
33
33
  use(module: IContainerModule): this;
34
34
  getRegistrations(): IRegistration[];
@@ -0,0 +1,25 @@
1
+ import { IContainer } from '../container/IContainer';
2
+ export type InjectFn<T = unknown> = (l: IContainer) => T;
3
+ export interface IHookContext {
4
+ instance: object;
5
+ scope: IContainer;
6
+ methodName?: string;
7
+ resolveArgs(...args: unknown[]): unknown[];
8
+ invokeMethod({ args }: {
9
+ args?: unknown[];
10
+ }): unknown;
11
+ injectProperty(fn: InjectFn): void;
12
+ }
13
+ export declare class HookContext implements IHookContext {
14
+ instance: object;
15
+ scope: IContainer;
16
+ methodName?: string | undefined;
17
+ constructor(instance: object, scope: IContainer, methodName?: string | undefined);
18
+ resolveArgs(...args: unknown[]): unknown[];
19
+ invokeMethod({ args }: {
20
+ args?: unknown[];
21
+ }): unknown;
22
+ injectProperty(fn: InjectFn): void;
23
+ }
24
+ export declare const createHookContext: (Target: object, scope: IContainer, methodName?: string) => IHookContext;
25
+ export declare const hookMetaKey: (methodName?: string) => string;
@@ -1,20 +1,27 @@
1
1
  import { IContainer } from '../container/IContainer';
2
- import { ExecutionContext } from './ExecutionContext';
3
- import { InjectFn } from '../injector/MetadataInjector';
4
- export type Execution<T extends ExecutionContext = ExecutionContext> = (context: T) => void | Promise<void>;
5
- type HookList = Execution[];
6
- type Hooks = Map<string, HookList>;
7
- export declare const hook: (key: string | symbol, ...fns: HookList) => (target: object, propertyKey: string | symbol) => void;
8
- export declare function getHooks(target: object, key: string | symbol): Hooks;
2
+ import { createHookContext, IHookContext, InjectFn } from './HookContext';
3
+ export type Hook<T extends IHookContext = IHookContext> = (context: T) => void | Promise<void>;
4
+ type HooksOfClass = Map<string, Hook[]>;
5
+ export declare const hook: (key: string | symbol, ...fns: Hook[]) => (target: object, propertyKey: string | symbol) => void;
6
+ export declare function getHooks(target: object, key: string | symbol): HooksOfClass;
9
7
  export declare function hasHooks(target: object, key: string | symbol): boolean;
10
- export declare const executeHooks: <Context extends ExecutionContext>(target: object, key: string | symbol, { scope, decorateContext, handleError, }: {
8
+ export declare const runHooks: (target: object, key: string | symbol, { scope, createContext, handleError, }: {
11
9
  scope: IContainer;
12
- decorateContext?: ((c: ExecutionContext) => Context) | undefined;
10
+ createContext?: ((Target: object, scope: IContainer, methodName?: string) => IHookContext) | undefined;
13
11
  handleError: (e: Error, s: IContainer) => void;
14
- }) => Promise<any[]>;
15
- export declare const injectProp: (fn: InjectFn) => Execution;
16
- type HandleResult = (result: unknown, context: ExecutionContext) => void | Promise<void>;
12
+ }) => Promise<void[]>;
13
+ export declare const injectProp: (fn: InjectFn) => Hook;
14
+ type HandleResult = (result: unknown, context: IHookContext) => void | Promise<void>;
17
15
  export declare const invokeExecution: ({ handleResult }: {
18
16
  handleResult: HandleResult;
19
- }) => Execution;
17
+ }) => Hook;
18
+ /**
19
+ * @deprecated Use `runHooks` instead
20
+ * @TODO: Remove in v33
21
+ */
22
+ export declare const executeHooks: (target: object, key: string | symbol, { scope, createContext, handleError, }: {
23
+ scope: IContainer;
24
+ createContext?: ((Target: object, scope: IContainer, methodName?: string) => IHookContext) | undefined;
25
+ handleError: (e: Error, s: IContainer) => void;
26
+ }) => Promise<void[]>;
20
27
  export {};
@@ -2,8 +2,9 @@ export { IContainer, Resolvable, IContainerModule, isDependencyKey, DependencyKe
2
2
  export { Container } from './container/Container';
3
3
  export { EmptyContainer } from './container/EmptyContainer';
4
4
  export { AutoMockedContainer } from './container/AutoMockedContainer';
5
- export { IInjector } from './injector/IInjector';
6
- export { MetadataInjector, inject, resolveArgs, getInjectFns, InjectFn } from './injector/MetadataInjector';
5
+ export { inject, resolveArgs } from './injector/inject';
6
+ export { IInjector, InjectOptions } from './injector/IInjector';
7
+ export { MetadataInjector } from './injector/MetadataInjector';
7
8
  export { SimpleInjector } from './injector/SimpleInjector';
8
9
  export { ProxyInjector } from './injector/ProxyInjector';
9
10
  export { ResolveDependency, IProvider, provider, visible, alias, argsFn, args, ArgsFn, ProviderDecorator, ProviderResolveOptions, } from './provider/IProvider';
@@ -17,8 +18,8 @@ export { Registration } from './registration/Registration';
17
18
  export { DependencyNotFoundError } from './errors/DependencyNotFoundError';
18
19
  export { MethodNotImplementedError } from './errors/MethodNotImplementedError';
19
20
  export { ContainerDisposedError } from './errors/ContainerDisposedError';
20
- export { getHooks, hook, hasHooks, Execution, executeHooks, injectProp, invokeExecution } from './hooks/hook';
21
- export { ExecutionContext } from './hooks/ExecutionContext';
21
+ export { getHooks, hook, hasHooks, Hook, executeHooks, runHooks, injectProp, invokeExecution } from './hooks/hook';
22
+ export { HookContext, InjectFn } from './hooks/HookContext';
22
23
  export { by, InstancePredicate, IMemo, IMemoKey, byAlias, byAliases } from './by';
23
24
  export { constructor } from './utils';
24
25
  export { setMetadata, getMetadata, setParameterMetadata, setMethodMetadata, getMethodMetadata, getParameterMetadata, } from './metadata';
@@ -1,10 +1,6 @@
1
1
  import { IInjector, InjectOptions } from './IInjector';
2
2
  import { IContainer } from '../container/IContainer';
3
3
  import { constructor } from '../utils';
4
- export type InjectFn<T = unknown> = (l: IContainer) => T;
5
- export declare const getInjectFns: (Target: constructor<unknown>, methodName?: string) => InjectFn<unknown>[];
6
- export declare const inject: (fn: InjectFn) => ParameterDecorator;
7
- export declare const resolveArgs: (Target: constructor<unknown>, methodName?: string) => (scope: IContainer, ...deps: unknown[]) => unknown[];
8
4
  export declare class MetadataInjector implements IInjector {
9
- resolve<T>(container: IContainer, Target: constructor<T>, { args: deps }: InjectOptions): T;
5
+ resolve<T>(scope: IContainer, Target: constructor<T>, { args: deps }: InjectOptions): T;
10
6
  }
@@ -0,0 +1,5 @@
1
+ import { constructor } from '../utils';
2
+ import { IContainer } from '../container/IContainer';
3
+ import { InjectFn } from '../hooks/HookContext';
4
+ export declare const inject: (fn: InjectFn) => ParameterDecorator;
5
+ export declare const resolveArgs: (Target: constructor<unknown>, methodName?: string) => (scope: IContainer, ...deps: unknown[]) => unknown[];
@@ -5,4 +5,8 @@ export declare function fillEmptyIndexes<T>(baseArr: (T | undefined)[], insertAr
5
5
  export declare const constant: <T>(value: T) => () => T;
6
6
  export declare const isConstructor: (T: unknown) => T is constructor<unknown>;
7
7
  export declare function lazyProxy<T>(resolveInstance: () => T): T;
8
- export declare const promisify: (arg: unknown) => Promise<any>;
8
+ export declare const promisify: <T>(arg: T | Promise<T>) => Promise<T>;
9
+ export interface InstanceOfClass<T = unknown> {
10
+ new (...args: unknown[]): T;
11
+ }
12
+ export declare function isInstance(target: object): target is InstanceOfClass<unknown>;
@@ -1,23 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ExecutionContext = void 0;
4
- const MetadataInjector_1 = require("../injector/MetadataInjector");
5
- class ExecutionContext {
6
- constructor(instance, methodName, scope) {
7
- this.instance = instance;
8
- this.methodName = methodName;
9
- this.scope = scope;
10
- }
11
- resolveArgs(...args) {
12
- return (0, MetadataInjector_1.resolveArgs)(this.instance.constructor, this.methodName)(this.scope, ...args);
13
- }
14
- invokeMethod({ args = this.resolveArgs() }) {
15
- // @ts-ignore
16
- return this.instance[this.methodName](...args);
17
- }
18
- injectProperty(fn) {
19
- // @ts-ignore
20
- this.instance[this.methodName] = fn(this.scope);
21
- }
22
- }
23
- exports.ExecutionContext = ExecutionContext;
@@ -1,13 +0,0 @@
1
- import { InjectFn } from '../injector/MetadataInjector';
2
- import { IContainer } from '../container/IContainer';
3
- export declare class ExecutionContext {
4
- instance: object;
5
- methodName: string;
6
- scope: IContainer;
7
- constructor(instance: object, methodName: string, scope: IContainer);
8
- resolveArgs(...args: unknown[]): unknown[];
9
- invokeMethod({ args }: {
10
- args: unknown[];
11
- }): unknown;
12
- injectProperty(fn: InjectFn): void;
13
- }