@tsed/di 8.19.4 → 8.20.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.
@@ -66,7 +66,7 @@ export function Controller(options) {
66
66
  if (path) {
67
67
  factory.store().set("path", path);
68
68
  }
69
- factory.store().set("childrenControllers", children);
69
+ factory.children(children);
70
70
  children.forEach((childToken) => {
71
71
  Store.from(childToken).set("parentController", classOf(target));
72
72
  });
@@ -1,4 +1,5 @@
1
- import { GlobalProviders } from "../registries/GlobalProviders.js";
1
+ import { nameOf } from "@tsed/core";
2
+ import { Provider } from "../domain/Provider.js";
2
3
  /**
3
4
  * Override an existing provider registration with a new implementation.
4
5
  *
@@ -41,6 +42,13 @@ import { GlobalProviders } from "../registries/GlobalProviders.js";
41
42
  */
42
43
  export function OverrideProvider(originalProvider) {
43
44
  return (target) => {
44
- GlobalProviders.get(originalProvider).useClass = target;
45
+ const provider = Provider.Registry.get(originalProvider);
46
+ if (provider) {
47
+ provider.useClass = target;
48
+ }
49
+ else {
50
+ throw new Error(`Cannot override provider ${nameOf(originalProvider)}: Provider not found in registry. ` +
51
+ `Ensure the original provider is decorated with @Injectable() or registered before applying @OverrideProvider.`);
52
+ }
45
53
  };
46
54
  }
@@ -1,4 +1,3 @@
1
- import { GlobalProviders } from "../registries/GlobalProviders.js";
2
1
  import { Provider } from "./Provider.js";
3
2
  /**
4
3
  * Provider container managing registered providers and their metadata.
@@ -27,7 +26,7 @@ export class Container extends Map {
27
26
  * @param settings
28
27
  */
29
28
  add(token, settings = {}) {
30
- const provider = GlobalProviders.get(token)?.clone() || new Provider(token);
29
+ const provider = Provider.Registry.get(token)?.clone() || new Provider(token);
31
30
  Object.assign(provider, settings);
32
31
  return super.set(token, provider);
33
32
  }
@@ -1,5 +1,4 @@
1
1
  import { Provider } from "./Provider.js";
2
- import { ProviderType } from "./ProviderType.js";
3
2
  /**
4
3
  * Specialized provider for HTTP controllers.
5
4
  *
@@ -21,33 +20,6 @@ import { ProviderType } from "./ProviderType.js";
21
20
  *
22
21
  * @typeParam T - The type of controller class
23
22
  * @public
23
+ * @deprecated Use Provider instead.
24
24
  */
25
- export class ControllerProvider extends Provider {
26
- constructor(token, options = {}) {
27
- super(token, options);
28
- this.type = ProviderType.CONTROLLER;
29
- }
30
- /**
31
- *
32
- * @returns {any[]}
33
- */
34
- get middlewares() {
35
- return Object.assign({
36
- use: [],
37
- useAfter: [],
38
- useBefore: []
39
- }, this.store.get("middlewares", {}));
40
- }
41
- /**
42
- *
43
- * @param middlewares
44
- */
45
- set middlewares(middlewares) {
46
- const mdlwrs = this.middlewares;
47
- const concat = (key, a, b) => (a[key] = a[key].concat(b[key]));
48
- Object.keys(middlewares).forEach((key) => {
49
- concat(key, mdlwrs, middlewares);
50
- });
51
- this.store.set("middlewares", mdlwrs);
52
- }
53
- }
25
+ export const ControllerProvider = Provider;
@@ -27,15 +27,40 @@ import { ProviderType } from "./ProviderType.js";
27
27
  * @public
28
28
  */
29
29
  export class Provider {
30
+ /**
31
+ * Global registry for storing all providers in the dependency injection system.
32
+ * Maps provider tokens to their Provider instances.
33
+ */
34
+ static { this.Registry = new Map(); }
35
+ /**
36
+ * The class type used to instantiate this provider
37
+ */
30
38
  #useClass;
39
+ /**
40
+ * The token used to identify this provider
41
+ */
31
42
  #token;
43
+ /**
44
+ * Store instance for provider metadata
45
+ */
32
46
  #store;
47
+ /**
48
+ * Store instance for token-specific metadata
49
+ */
33
50
  #tokenStore;
51
+ /**
52
+ * Creates a new Provider instance
53
+ * @param token - The token used to identify this provider
54
+ * @param options - Optional configuration options for the provider
55
+ */
34
56
  constructor(token, options = {}) {
35
57
  /**
36
- * Token group provider to retrieve all provider from the same type
58
+ * Token group provider to retrieve all providers from the same type
37
59
  */
38
60
  this.type = ProviderType.PROVIDER;
61
+ /**
62
+ * Map of lifecycle hook callbacks for this provider
63
+ */
39
64
  this.hooks = {};
40
65
  this.token = token;
41
66
  this.useClass = token;
@@ -46,9 +71,16 @@ export class Provider {
46
71
  this.#tokenStore = options.#tokenStore;
47
72
  }
48
73
  }
74
+ /**
75
+ * Get the provider's token
76
+ */
49
77
  get token() {
50
78
  return this.#token;
51
79
  }
80
+ /**
81
+ * Set the provider's token and initialize stores
82
+ * @param value - The token to set
83
+ */
52
84
  set token(value) {
53
85
  if (value) {
54
86
  this.#token = getClassOrSymbol(value);
@@ -68,12 +100,15 @@ export class Provider {
68
100
  set provide(value) {
69
101
  this.token = value;
70
102
  }
103
+ /**
104
+ * Gets the class type used to instantiate this provider
105
+ */
71
106
  get useClass() {
72
107
  return this.#useClass;
73
108
  }
74
109
  /**
75
- * Create a new store if the given value is a class. Otherwise, the value is ignored.
76
- * @param value
110
+ * Sets the class type and initializes store/hooks for this provider
111
+ * @param value - The class type to use for instantiation
77
112
  */
78
113
  set useClass(value) {
79
114
  if (isClass(value)) {
@@ -119,9 +154,16 @@ export class Provider {
119
154
  set scope(scope) {
120
155
  this.store.set("scope", scope);
121
156
  }
157
+ /**
158
+ * Gets the provider configuration settings
159
+ */
122
160
  get configuration() {
123
161
  return this.get("configuration");
124
162
  }
163
+ /**
164
+ * Sets the provider configuration settings
165
+ * @param configuration - The configuration object to set
166
+ */
125
167
  set configuration(configuration) {
126
168
  this.store.set("configuration", configuration);
127
169
  }
@@ -131,6 +173,28 @@ export class Provider {
131
173
  set children(children) {
132
174
  this.store.set("childrenControllers", children);
133
175
  }
176
+ /**
177
+ * Gets the configured middleware stack for this provider
178
+ */
179
+ get middlewares() {
180
+ return Object.assign({
181
+ use: [],
182
+ useAfter: [],
183
+ useBefore: []
184
+ }, this.store.get("middlewares", {}));
185
+ }
186
+ /**
187
+ * Sets middleware configuration, merging with existing middlewares
188
+ * @param middlewares - The middleware configuration to apply
189
+ */
190
+ set middlewares(middlewares) {
191
+ const mdlwrs = this.middlewares;
192
+ const concat = (key, a, b) => (a[key] = a[key].concat(b[key]));
193
+ Object.keys(middlewares).forEach((key) => {
194
+ concat(key, mdlwrs, middlewares);
195
+ });
196
+ this.store.set("middlewares", mdlwrs);
197
+ }
134
198
  getArgOpts(index) {
135
199
  return this.store.get(`${DI_USE_PARAM_OPTIONS}:${index}`);
136
200
  }
@@ -144,19 +208,23 @@ export class Provider {
144
208
  return new (classOf(this))(this.token, this);
145
209
  }
146
210
  /**
147
- *
148
- * @returns {boolean}
211
+ * Checks if this provider has any child controllers
212
+ * @returns True if provider has children, false otherwise
149
213
  */
150
214
  hasChildren() {
151
215
  return !!this.children.length;
152
216
  }
153
217
  /**
154
- *
155
- * @returns {boolean}
218
+ * Checks if this provider has a parent controller
219
+ * @returns True if provider has a parent, false otherwise
156
220
  */
157
221
  hasParent() {
158
222
  return !!this.store.get("parentController");
159
223
  }
224
+ /**
225
+ * Returns a string representation of this provider
226
+ * @returns A string containing the provider's token, class and factory information
227
+ */
160
228
  toString() {
161
229
  return [
162
230
  "Token",
@@ -169,6 +237,11 @@ export class Provider {
169
237
  .filter(Boolean)
170
238
  .join(":");
171
239
  }
240
+ /**
241
+ * Resets the provider's factory configuration
242
+ * Clears useValue, useFactory and useAsyncFactory
243
+ * @returns This provider instance
244
+ */
172
245
  reset() {
173
246
  this.useValue = undefined;
174
247
  this.useFactory = undefined;
@@ -0,0 +1,213 @@
1
+ import { Provider } from "../domain/Provider.js";
2
+ import { ProviderType } from "../domain/ProviderType.js";
3
+ import { injector } from "../fn/injector.js";
4
+ export class ProviderBuilder {
5
+ /**
6
+ * Creates a new Provider Builder instance
7
+ * @param options - Provider options including token and configuration
8
+ */
9
+ constructor(options) {
10
+ options.global ||= !injector().isLoaded();
11
+ let provider = Provider.Registry.get(options.token);
12
+ if (!provider) {
13
+ provider = new Provider(options.token, options);
14
+ options.global && Provider.Registry.set(options.token, provider);
15
+ }
16
+ else {
17
+ Object.keys(options).forEach((key) => {
18
+ provider[key] = options[key];
19
+ });
20
+ }
21
+ if (!options.global) {
22
+ injector().setProvider(options.token, provider);
23
+ }
24
+ this.provider = provider;
25
+ }
26
+ static add(property, method) {
27
+ Object.defineProperty(ProviderBuilder.prototype, property, {
28
+ value: method
29
+ });
30
+ return ProviderBuilder;
31
+ }
32
+ /**
33
+ * Sets the provider scope
34
+ * @param scope - The scope to set for this provider
35
+ * @returns Current builder instance
36
+ */
37
+ scope(scope) {
38
+ this.provider.scope = scope;
39
+ return this;
40
+ }
41
+ /**
42
+ * Sets the provider path
43
+ * @param path - The path to set for this provider
44
+ * @returns Current builder instance
45
+ */
46
+ path(path) {
47
+ this.provider.path = path;
48
+ return this;
49
+ }
50
+ /**
51
+ * Sets the provider alias
52
+ * @param alias - The alias to set for this provider
53
+ * @returns Current builder instance
54
+ */
55
+ alias(alias) {
56
+ this.provider.alias = alias;
57
+ return this;
58
+ }
59
+ /**
60
+ * Sets the provider hooks
61
+ * @param hooks - The hooks to set for this provider
62
+ * @returns Current builder instance
63
+ */
64
+ hooks(hooks) {
65
+ this.provider.hooks = hooks;
66
+ return this;
67
+ }
68
+ /**
69
+ * Sets the provider dependencies
70
+ * @param deps - The dependencies to set for this provider
71
+ * @returns Current builder instance
72
+ */
73
+ deps(deps) {
74
+ this.provider.deps = deps;
75
+ return this;
76
+ }
77
+ /**
78
+ * Sets the provider imports
79
+ * @param imports - The imports to set for this provider
80
+ * @returns Current builder instance
81
+ */
82
+ imports(imports) {
83
+ this.provider.imports = imports;
84
+ return this;
85
+ }
86
+ /**
87
+ * Sets the provider configuration
88
+ * @param configuration - The configuration to set for this provider
89
+ * @returns Current builder instance
90
+ */
91
+ configuration(configuration) {
92
+ this.provider.configuration = configuration;
93
+ return this;
94
+ }
95
+ /**
96
+ * Sets the provider priority
97
+ * @param priority - The priority to set for this provider
98
+ * @returns Current builder instance
99
+ */
100
+ priority(priority) {
101
+ this.provider.priority = priority;
102
+ return this;
103
+ }
104
+ /**
105
+ * Sets the provider type
106
+ * @param type - The type to set for this provider
107
+ * @returns Current builder instance
108
+ */
109
+ type(type) {
110
+ this.provider.type = type;
111
+ return this;
112
+ }
113
+ /**
114
+ * Sets the provider children
115
+ * @param children - The children to set for this provider
116
+ * @returns Current builder instance
117
+ */
118
+ children(children) {
119
+ this.provider.children = children;
120
+ return this;
121
+ }
122
+ /**
123
+ * Sets the provider middlewares
124
+ * @param middlewares - The middlewares to set for this provider
125
+ * @returns Current builder instance
126
+ */
127
+ middlewares(middlewares) {
128
+ this.provider.middlewares = middlewares;
129
+ return this;
130
+ }
131
+ /**
132
+ * Sets a factory function for the provider
133
+ * @param factory - Factory function that creates provider instances
134
+ * @returns Builder instance with updated factory type
135
+ */
136
+ factory(factory) {
137
+ this.provider.reset();
138
+ this.provider.useFactory = factory;
139
+ return this;
140
+ }
141
+ /**
142
+ * Sets an async factory function for the provider
143
+ * @param asyncFactory - Async factory function that creates provider instances
144
+ * @returns Builder instance with updated factory type
145
+ */
146
+ asyncFactory(asyncFactory) {
147
+ this.provider.reset();
148
+ this.provider.useAsyncFactory = asyncFactory;
149
+ return this;
150
+ }
151
+ /**
152
+ * Sets a static value for the provider
153
+ * @param value - Value to be provided
154
+ * @returns Builder instance with value type
155
+ */
156
+ value(value) {
157
+ this.provider.reset();
158
+ this.provider.useValue = value;
159
+ this.provider.type = ProviderType.VALUE;
160
+ return this;
161
+ }
162
+ /**
163
+ * Sets the class to be used by the provider
164
+ * @param k - Class type to be provided
165
+ * @returns Builder instance with class type
166
+ */
167
+ class(k) {
168
+ this.provider.reset();
169
+ this.provider.useClass = k;
170
+ return this;
171
+ }
172
+ /**
173
+ * Gets the provider's store
174
+ * @returns Provider store instance
175
+ */
176
+ store() {
177
+ return this.provider.store;
178
+ }
179
+ /**
180
+ * Gets the underlying provider instance
181
+ * @returns Provider instance
182
+ */
183
+ inspect() {
184
+ return this.provider;
185
+ }
186
+ /**
187
+ * Gets the provider's token
188
+ * @returns Provider token
189
+ */
190
+ token() {
191
+ return this.provider.token;
192
+ }
193
+ /**
194
+ * Sets a value in the provider's store
195
+ * @param key - Key to store the value under
196
+ * @param value - Value to store
197
+ * @returns Current builder instance
198
+ */
199
+ set(key, value) {
200
+ this.store().set(key, value);
201
+ return this;
202
+ }
203
+ }
204
+ export function providerBuilder(baseOpts = {}) {
205
+ function factory(token, options = {}) {
206
+ return new ProviderBuilder({
207
+ token,
208
+ ...baseOpts,
209
+ ...options
210
+ });
211
+ }
212
+ return factory;
213
+ }
@@ -0,0 +1,7 @@
1
+ import { classOf } from "@tsed/core";
2
+ import { bindIntercept } from "../decorators/intercept.js";
3
+ import { ProviderBuilder } from "../domain/ProviderBuilder.js";
4
+ ProviderBuilder.add("intercept", function intercept(propertyKey, interceptorToken, options) {
5
+ bindIntercept(classOf(this.inspect().useClass), propertyKey, interceptorToken, options);
6
+ return this;
7
+ });
@@ -1,6 +1,5 @@
1
+ import { providerBuilder } from "../domain/ProviderBuilder.js";
1
2
  import { ProviderType } from "../domain/ProviderType.js";
2
- import { providerBuilder } from "../utils/providerBuilder.js";
3
- const Props = ["type", "scope", "path", "alias", "hooks", "deps", "imports", "configuration", "priority"];
4
3
  /**
5
4
  * Fluent builder for registering providers programmatically.
6
5
  *
@@ -25,7 +24,7 @@ const Props = ["type", "scope", "path", "alias", "hooks", "deps", "imports", "co
25
24
  *
26
25
  * @public
27
26
  */
28
- export const injectable = providerBuilder(Props);
27
+ export const injectable = providerBuilder({ type: ProviderType.PROVIDER });
29
28
  /**
30
29
  * Fluent builder for registering interceptor providers.
31
30
  *
@@ -41,7 +40,7 @@ export const injectable = providerBuilder(Props);
41
40
  *
42
41
  * @public
43
42
  */
44
- export const interceptor = providerBuilder(Props, {
43
+ export const interceptor = providerBuilder({
45
44
  type: ProviderType.INTERCEPTOR
46
45
  });
47
46
  /**
@@ -62,6 +61,16 @@ export const interceptor = providerBuilder(Props, {
62
61
  *
63
62
  * @public
64
63
  */
65
- export const controller = providerBuilder([...Props, "middlewares"], {
64
+ export const controller = providerBuilder({
66
65
  type: ProviderType.CONTROLLER
67
66
  });
67
+ /**
68
+ * Register a provider configuration.
69
+ * @deprecated Since v8. Use injectable() function instead.
70
+ */
71
+ export function registerProvider({ token, provide, ...opts }) {
72
+ return injectable(token || provide, {
73
+ ...opts,
74
+ token: token || provide
75
+ }).inspect();
76
+ }
@@ -25,10 +25,12 @@ export * from "./domain/DIContext.js";
25
25
  export * from "./domain/InjectablePropertyType.js";
26
26
  export * from "./domain/LocalsContainer.js";
27
27
  export * from "./domain/Provider.js";
28
+ export * from "./domain/ProviderBuilder.js";
28
29
  export * from "./domain/ProviderScope.js";
29
30
  export * from "./domain/ProviderType.js";
30
31
  export * from "./errors/InjectionError.js";
31
32
  export * from "./errors/InvalidPropertyTokenError.js";
33
+ export * from "./extends/intercept.js";
32
34
  export * from "./fn/configuration.js";
33
35
  export * from "./fn/constant.js";
34
36
  export * from "./fn/inject.js";
@@ -55,7 +57,6 @@ export * from "./interfaces/ResolvedInvokeOptions.js";
55
57
  export * from "./interfaces/TokenProvider.js";
56
58
  export * from "./interfaces/TokenRoute.js";
57
59
  export * from "./registries/GlobalProviders.js";
58
- export * from "./registries/ProviderRegistry.js";
59
60
  export * from "./services/DIConfiguration.js";
60
61
  export * from "./services/DILogger.js";
61
62
  export * from "./services/InjectorService.js";
@@ -65,7 +66,6 @@ export * from "./utils/createContainer.js";
65
66
  export * from "./utils/discoverHooks.js";
66
67
  export * from "./utils/getConfiguration.js";
67
68
  export * from "./utils/getConstructorDependencies.js";
68
- export * from "./utils/providerBuilder.js";
69
69
  export * from "./utils/setLoggerConfiguration.js";
70
70
  export * from "./utils/setLoggerFormat.js";
71
71
  export * from "./utils/setLoggerLevel.js";
@@ -1,102 +1,8 @@
1
- import { getClassOrSymbol } from "@tsed/core/utils/getClassOrSymbol.js";
2
1
  import { Provider } from "../domain/Provider.js";
3
- import { ProviderType } from "../domain/ProviderType.js";
4
- export class GlobalProviderRegistry extends Map {
5
- #settings = new Map();
6
- /**
7
- * The get() method returns a specified element from a Map object.
8
- * @param key Required. The key of the element to return from the Map object.
9
- * @returns {T} Returns the element associated with the specified key or undefined if the key can't be found in the Map object.
10
- */
11
- get(key) {
12
- return super.get(getClassOrSymbol(key));
13
- }
14
- /**
15
- * The has() method returns a boolean indicating whether an element with the specified key exists or not.
16
- * @param key
17
- * @returns {boolean}
18
- */
19
- has(key) {
20
- return super.has(getClassOrSymbol(key));
21
- }
22
- /**
23
- * The set() method adds or updates an element with a specified key and value to a Map object.
24
- * @param key Required. The key of the element to add to the Map object.
25
- * @param metadata Required. The value of the element to add to the Map object.
26
- */
27
- set(key, metadata) {
28
- super.set(getClassOrSymbol(key), metadata);
29
- return this;
30
- }
31
- /**
32
- *
33
- * @param target
34
- * @param options
35
- */
36
- merge(target, options) {
37
- if (options.global === false) {
38
- return GlobalProviders.createProvider(target, options);
39
- }
40
- const meta = this.createIfNotExists(target, options);
41
- Object.keys(options).forEach((key) => {
42
- meta[key] = options[key];
43
- });
44
- this.set(target, meta);
45
- return meta;
46
- }
47
- /**
48
- * The delete() method removes the specified element from a Map object.
49
- * @param key Required. The key of the element to remove from the Map object.
50
- * @returns {boolean} Returns true if an element in the Map object existed and has been removed, or false if the element does not exist.
51
- */
52
- delete(key) {
53
- return super.delete(getClassOrSymbol(key));
54
- }
55
- createRegistry(type, model, options = {}) {
56
- const defaultOptions = this.getRegistrySettings(type);
57
- options = Object.assign(defaultOptions, {
58
- ...options,
59
- model
60
- });
61
- this.#settings.set(type, options);
62
- return this;
63
- }
64
- getRegistrySettings(target) {
65
- let type = ProviderType.PROVIDER;
66
- if (typeof target === "string") {
67
- type = target;
68
- }
69
- else {
70
- const provider = this.get(target);
71
- if (provider) {
72
- type = provider.type;
73
- }
74
- }
75
- return (this.#settings.get(type) || {
76
- model: Provider
77
- });
78
- }
79
- createProvider(key, options) {
80
- const type = options.type || ProviderType.PROVIDER;
81
- const { model = Provider } = this.#settings.get(type) || {};
82
- return new model(key, options);
83
- }
84
- /**
85
- *
86
- * @param key
87
- * @param options
88
- */
89
- createIfNotExists(key, options) {
90
- if (!this.has(key)) {
91
- const item = this.createProvider(key, options);
92
- this.set(key, item);
93
- }
94
- return this.get(key);
95
- }
96
- }
97
2
  /**
98
- *
99
- * @type {GlobalProviders}
3
+ * Registry for managing global providers in the dependency injection system.
4
+ * Extends the Map class to store TokenProvider-Provider pairs.
5
+ * @deprecated Use Provider.Registry instead
100
6
  */
101
7
  // tslint:disable-next-line: variable-name
102
- export const GlobalProviders = new GlobalProviderRegistry();
8
+ export const GlobalProviders = Provider.Registry;
@@ -15,7 +15,6 @@ import { LocalsContainer } from "../domain/LocalsContainer.js";
15
15
  import { Provider } from "../domain/Provider.js";
16
16
  import { ProviderScope } from "../domain/ProviderScope.js";
17
17
  import { InjectionError } from "../errors/InjectionError.js";
18
- import { GlobalProviders } from "../registries/GlobalProviders.js";
19
18
  import { createContainer } from "../utils/createContainer.js";
20
19
  import { getConstructorDependencies } from "../utils/getConstructorDependencies.js";
21
20
  import { DIConfiguration } from "./DIConfiguration.js";
@@ -361,7 +360,7 @@ export class InjectorService extends Container {
361
360
  return this;
362
361
  }
363
362
  ensureProvider(token, force = false) {
364
- if (!this.hasProvider(token) && (GlobalProviders.has(token) || force)) {
363
+ if (!this.hasProvider(token) && (Provider.Registry.has(token) || force)) {
365
364
  this.addProvider(token);
366
365
  }
367
366
  return this.getProvider(token);
@@ -534,7 +533,7 @@ export class InjectorService extends Container {
534
533
  setToCache(provider, instance) {
535
534
  const set = (instance) => {
536
535
  this.#cache.set(provider.token, instance);
537
- provider?.alias && this.alias(provider.token, provider.alias);
536
+ provider.alias && this.alias(provider.token, provider.alias);
538
537
  };
539
538
  if ("isAsync" in provider && !provider.isAsync() && !isPromise(instance)) {
540
539
  set(instance);
@@ -1,7 +1,7 @@
1
1
  import { Container } from "../domain/Container.js";
2
- import { GlobalProviders } from "../registries/GlobalProviders.js";
2
+ import { Provider } from "../domain/Provider.js";
3
3
  export function createContainer(rootModule) {
4
- const container = new Container(GlobalProviders.entries());
4
+ const container = new Container(Provider.Registry.entries());
5
5
  if (rootModule) {
6
6
  container.delete(rootModule);
7
7
  }