@zudojs/container 1.2.0 → 1.2.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/README.md CHANGED
@@ -162,9 +162,13 @@ container.register(API, {
162
162
  });
163
163
  ```
164
164
 
165
- Classes without an `inject` list are constructed with zero arguments. There
166
- is no reflection/decorator magic — dependencies are exactly the tokens you
167
- list, resolved in order.
165
+ Classes without an `inject` list are constructed with zero arguments, so
166
+ only a constructor that declares no parameters may omit it (parameters with
167
+ a default value do not count). Registering such a class without `inject`
168
+ is allowed, but resolving it throws a `ProviderResolutionError` naming the
169
+ class and the `inject: [...]` fix, instead of building it with `undefined`
170
+ dependencies. There is no reflection/decorator magic — dependencies are
171
+ exactly the tokens you list, resolved in order.
168
172
 
169
173
  ## Duplicate registrations
170
174
 
@@ -1,9 +1,9 @@
1
1
  /**
2
2
  * @zudojs/container/containerResolution/containerResolution.autoRegister
3
3
  *
4
- * Guards for `autoRegisterClasses`: resolving an unregistered class builds
5
- * it with no arguments, which is only correct for a constructor that
6
- * declares none.
4
+ * Guards against building a class with no arguments when its constructor
5
+ * declares some: an unregistered class under `autoRegisterClasses`, and a
6
+ * class registration with no `inject` list.
7
7
  */
8
8
  /**
9
9
  * Whether an unregistered token may be auto-registered: a class whose
@@ -24,4 +24,19 @@ export declare function isAutoRegistrable(token: unknown): boolean;
24
24
  export declare function assertAutoRegistrable(token: {
25
25
  readonly length: number;
26
26
  }): void;
27
+ /**
28
+ * Throws when a class registration has no `inject` list but its constructor
29
+ * declares parameters. Without one the class is built with no arguments,
30
+ * so every dependency would be `undefined`. Registering it is allowed;
31
+ * resolving it is what fails.
32
+ *
33
+ * Parameters with a default value do not count (`Function.length` stops at
34
+ * the first one).
35
+ *
36
+ * @throws {ProviderResolutionError} naming the class and the `inject` fix.
37
+ */
38
+ export declare function assertClassInjectable(token: string, ctor: {
39
+ readonly length: number;
40
+ readonly name: string;
41
+ }, inject: readonly unknown[]): void;
27
42
  //# sourceMappingURL=containerResolution.autoRegister.d.ts.map
@@ -1,11 +1,11 @@
1
1
  /**
2
2
  * @zudojs/container/containerResolution/containerResolution.autoRegister
3
3
  *
4
- * Guards for `autoRegisterClasses`: resolving an unregistered class builds
5
- * it with no arguments, which is only correct for a constructor that
6
- * declares none.
4
+ * Guards against building a class with no arguments when its constructor
5
+ * declares some: an unregistered class under `autoRegisterClasses`, and a
6
+ * class registration with no `inject` list.
7
7
  */
8
- import { RegistrationNotFoundError } from "@zudojs/errors";
8
+ import { ProviderResolutionError, RegistrationNotFoundError, } from "@zudojs/errors";
9
9
  import { describeToken } from "../containerToken/containerToken.type.js";
10
10
  /**
11
11
  * Whether an unregistered token may be auto-registered: a class whose
@@ -37,4 +37,26 @@ export function assertAutoRegistrable(token) {
37
37
  `{ inject: [/* one token per parameter */] }) or ` +
38
38
  `container.registerFactory(${name}, (...deps) => new ${name}(...deps), [/* tokens */]).`);
39
39
  }
40
+ /**
41
+ * Throws when a class registration has no `inject` list but its constructor
42
+ * declares parameters. Without one the class is built with no arguments,
43
+ * so every dependency would be `undefined`. Registering it is allowed;
44
+ * resolving it is what fails.
45
+ *
46
+ * Parameters with a default value do not count (`Function.length` stops at
47
+ * the first one).
48
+ *
49
+ * @throws {ProviderResolutionError} naming the class and the `inject` fix.
50
+ */
51
+ export function assertClassInjectable(token, ctor, inject) {
52
+ const count = ctor.length;
53
+ if (inject.length > 0 || count === 0)
54
+ return;
55
+ const name = ctor.name || "anonymous class";
56
+ throw new ProviderResolutionError(token, `Cannot build class "${name}" for token "${token}": its constructor ` +
57
+ `declares ${count} parameter${count === 1 ? "" : "s"} and the ` +
58
+ `registration has no inject list, so it would be built with undefined ` +
59
+ `dependencies. Register it with container.registerClass(${token}, ` +
60
+ `${name}, { inject: [/* one token per parameter */] }).`);
61
+ }
40
62
  //# sourceMappingURL=containerResolution.autoRegister.js.map
@@ -35,7 +35,7 @@ import { unwrapToken } from "../containerToken/containerToken.type.js";
35
35
  import { CircularDependencyError, ContainerError, ProviderResolutionError, RegistrationNotFoundError, } from "@zudojs/errors";
36
36
  import { AsyncProviderError, CaptiveDependencyError, DependencyResolutionError, MaxResolutionDepthError, ScopedResolutionError, } from "./containerResolution.error.js";
37
37
  import { describeToken } from "../containerToken/containerToken.type.js";
38
- import { assertAutoRegistrable, isAutoRegistrable, } from "./containerResolution.autoRegister.js";
38
+ import { assertAutoRegistrable, assertClassInjectable, isAutoRegistrable, } from "./containerResolution.autoRegister.js";
39
39
  import { DependentIndex } from "./containerResolution.dependents.js";
40
40
  /**
41
41
  * Scope cache that falls back to its parent scope's cache for lookups while
@@ -239,6 +239,7 @@ export class ContainerResolver {
239
239
  }
240
240
  if (isClassProvider(provider)) {
241
241
  const deps = provider.inject ?? [];
242
+ assertClassInjectable(describeToken(token), provider.useClass, deps);
242
243
  const args = deps.map((d) => this.resolveInternal(unwrapToken(d), state, singletonAncestor)
243
244
  .value);
244
245
  const ctor = provider.useClass;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zudojs/container",
3
- "version": "1.2.0",
3
+ "version": "1.2.1",
4
4
  "description": "Token-based dependency injection container for managing application dependencies and service lifetimes.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",