getbox 1.1.0 → 1.3.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/CONTEXT.md CHANGED
@@ -57,9 +57,7 @@ import { Box } from "getbox";
57
57
  class UserService {
58
58
  constructor(private db: Database, private logger: Logger) {}
59
59
 
60
- static init(box: Box) {
61
- return box.for(UserService).get(Database, LoggerFactory);
62
- }
60
+ static init = Box.init(UserService).get(Database, LoggerFactory);
63
61
  }
64
62
  ```
65
63
 
package/README.md CHANGED
@@ -43,10 +43,7 @@ import { Printer } from "./printer";
43
43
  export class Office {
44
44
  constructor(public printer: Printer) {}
45
45
 
46
- static init(box: Box) {
47
- const printer = box.get(Printer);
48
- return new Office(printer);
49
- }
46
+ static init = Box.init(Office).get(Printer);
50
47
  }
51
48
  ```
52
49
 
@@ -125,10 +122,7 @@ import { Logger, LoggerFactory } from "./logger";
125
122
  export class UserService {
126
123
  constructor(private logger: Logger) {}
127
124
 
128
- static init(box: Box) {
129
- const logger = box.get(LoggerFactory);
130
- return new UserService(logger);
131
- }
125
+ static init = Box.init(UserService).get(LoggerFactory);
132
126
 
133
127
  createUser(name: string) {
134
128
  this.logger.log(`Creating user: ${name}`);
@@ -172,6 +166,23 @@ const ApiUrl = factory((box: Box) => {
172
166
  const apiUrl = box.get(ApiUrl); // "https://example.com/api"
173
167
  ```
174
168
 
169
+ ## Transient factories
170
+
171
+ Use the `transient` helper to create a factory whose result is never cached. The factory is called on every resolution, even when retrieved via `box.get()`.
172
+
173
+ ```ts
174
+ import { Box, transient } from "getbox";
175
+
176
+ const RequestId = transient(() => crypto.randomUUID());
177
+
178
+ const box = new Box();
179
+
180
+ const id1 = box.get(RequestId);
181
+ const id2 = box.get(RequestId);
182
+
183
+ console.log(id1 === id2); // false
184
+ ```
185
+
175
186
  ## Resolving multiple constructors
176
187
 
177
188
  Use `box.all.get()` to resolve multiple constructors at once. Pass an object to get an object of instances, or an array to get an array of instances.
@@ -202,18 +213,15 @@ console.log(db === db2); // false (transient)
202
213
 
203
214
  ## Class constructors
204
215
 
205
- Use `box.for()` inside a class's `static init` method to resolve constructor dependencies automatically. The instance returned by the builder is cached or transient depending on whether the class is retrieved via `box.get()` or `box.new()`.
216
+ Use `Box.init` to allow resolving classes that have constructor parameters.
206
217
 
207
218
  ```ts
208
- import { Box, factory } from "getbox";
219
+ import { Box } from "getbox";
209
220
 
210
221
  class UserService {
211
222
  constructor(private db: Database, private logger: Logger) {}
212
223
 
213
- static init(box: Box) {
214
- // Create new instance with cached dependencies
215
- return box.for(UserService).get(Database, LoggerFactory);
216
- }
224
+ static init = Box.init(UserService).get(Database, LoggerFactory);
217
225
 
218
226
  createUser(name: string) {
219
227
  this.logger.log(`Creating user: ${name}`);
@@ -225,6 +233,34 @@ const service = box.get(UserService);
225
233
  service.createUser("Alice");
226
234
  ```
227
235
 
236
+ `Box.init` is shorthand for writing the `static init` method yourself.
237
+
238
+ ```ts
239
+ class UserService {
240
+ constructor(private db: Database, private logger: Logger) {}
241
+
242
+ static init(box: Box) {
243
+ return new UserService(box.get(Database), box.get(LoggerFactory));
244
+ }
245
+ }
246
+ ```
247
+
248
+ Use `box.for()` when you need custom logic alongside dependency resolution.
249
+
250
+ ```ts
251
+ class UserService {
252
+ constructor(private db: Database, private logger: Logger) {}
253
+
254
+ static init(box: Box) {
255
+ const logger = box.get(LoggerFactory);
256
+ logger.log("Initializing UserService");
257
+ return box.for(UserService).get(Database, LoggerFactory);
258
+ }
259
+ }
260
+ ```
261
+
262
+ Classes with no constructor parameters are resolved automatically without needing `static init`. If `static init` is defined, it takes priority over the default constructor.
263
+
228
264
  ## Mocking
229
265
 
230
266
  You can mock dependencies for testing using `Box.mock`. This is particularly useful with factories and interfaces.
@@ -17,7 +17,7 @@ declare function useBox(): Box;
17
17
  * Resolves a cached instance from the current {@link withBox} scope.
18
18
  * Shorthand for `useBox().get(constructor)`.
19
19
  */
20
- declare function resolve<T>(constructor: Constructor<T>): T;
20
+ declare function resolve<T extends Constructor<any>>(constructor: T): ConstructorInstanceType<T>;
21
21
  /**
22
22
  * Resolves multiple cached instances from the current {@link withBox} scope.
23
23
  * Shorthand for `useBox().all.get(constructors)`.
@@ -17,7 +17,7 @@ declare function useBox(): Box;
17
17
  * Resolves a cached instance from the current {@link withBox} scope.
18
18
  * Shorthand for `useBox().get(constructor)`.
19
19
  */
20
- declare function resolve<T>(constructor: Constructor<T>): T;
20
+ declare function resolve<T extends Constructor<any>>(constructor: T): ConstructorInstanceType<T>;
21
21
  /**
22
22
  * Resolves multiple cached instances from the current {@link withBox} scope.
23
23
  * Shorthand for `useBox().all.get(constructors)`.
package/dist/index.cjs CHANGED
@@ -16,7 +16,26 @@
16
16
  function factory(init) {
17
17
  return { init };
18
18
  }
19
- const constantSymbol = Symbol("Box constant");
19
+ const noCacheSymbol = Symbol("Box.noCache");
20
+ /**
21
+ * Creates a {@link Constructor} from a factory function whose result is never cached.
22
+ * The factory is called on every resolution, always returning a fresh value
23
+ * even when retrieved via {@link Box.get}.
24
+ *
25
+ * @example
26
+ * ```ts
27
+ * const RequestId = transient(() => crypto.randomUUID());
28
+ * const id1 = box.get(RequestId);
29
+ * const id2 = box.get(RequestId);
30
+ * console.log(id1 === id2); // false
31
+ * ```
32
+ */
33
+ function transient(init) {
34
+ return {
35
+ init,
36
+ [noCacheSymbol]: true
37
+ };
38
+ }
20
39
  /**
21
40
  * Creates a {@link Constructor} that always resolves to the given constant value.
22
41
  * Constant values are never cached since they are already fixed.
@@ -30,7 +49,7 @@ const constantSymbol = Symbol("Box constant");
30
49
  function constant(value) {
31
50
  return {
32
51
  init: () => value,
33
- [constantSymbol]: true
52
+ [noCacheSymbol]: true
34
53
  };
35
54
  }
36
55
  /**
@@ -79,7 +98,7 @@ var Box = class {
79
98
  get(constructor) {
80
99
  if (this.cache.has(constructor)) return this.cache.get(constructor);
81
100
  const value = this.new(constructor);
82
- if (!(constantSymbol in constructor && constructor[constantSymbol])) this.cache.set(constructor, value);
101
+ if (!(noCacheSymbol in constructor && constructor[noCacheSymbol])) this.cache.set(constructor, value);
83
102
  return value;
84
103
  }
85
104
  /** Resolves multiple constructors at once. */
@@ -96,6 +115,21 @@ var Box = class {
96
115
  return new Construct(this, constructor);
97
116
  }
98
117
  /**
118
+ * Returns a {@link StaticConstruct} builder for defining a `static init` method.
119
+ * The result can be assigned directly to `static init`.
120
+ *
121
+ * @example
122
+ * ```ts
123
+ * class UserService {
124
+ * constructor(private db: Database, private logger: Logger) {}
125
+ * static init = Box.init(UserService).get(Database, LoggerFactory);
126
+ * }
127
+ * ```
128
+ */
129
+ static init(constructor) {
130
+ return new StaticConstruct(constructor);
131
+ }
132
+ /**
99
133
  * Registers a mock value in the box's cache for a given constructor.
100
134
  * Useful for replacing dependencies in tests.
101
135
  */
@@ -178,9 +212,64 @@ var Construct = class {
178
212
  return new this.construct(...instances);
179
213
  }
180
214
  };
215
+ /**
216
+ * Builder for creating a `static init` function with constructor dependencies
217
+ * resolved from a {@link Box}.
218
+ */
219
+ var StaticConstruct = class {
220
+ constructor(construct) {
221
+ this.construct = construct;
222
+ }
223
+ /**
224
+ * Resolves each dependency as a new transient instance via {@link Box.new},
225
+ * meaning dependencies are not cached or shared.
226
+ * Returns a function compatible with `static init` that can be assigned directly.
227
+ *
228
+ * The returned instance is cached or transient depending on whether the
229
+ * class is retrieved via {@link Box.get} or {@link Box.new}.
230
+ *
231
+ * @example
232
+ * ```ts
233
+ * class UserService {
234
+ * constructor(private db: Database, private logger: Logger) {}
235
+ * static init = Box.init(UserService).get(Database, LoggerFactory);
236
+ * }
237
+ * ```
238
+ */
239
+ new(...args) {
240
+ return (box) => {
241
+ const instances = args.map((arg) => box.new(arg));
242
+ return new this.construct(...instances);
243
+ };
244
+ }
245
+ /**
246
+ * Resolves each dependency as a cached instance via {@link Box.get},
247
+ * meaning dependencies are shared across the box.
248
+ * Returns a function compatible with `static init` that can be assigned directly.
249
+ *
250
+ * The returned instance is cached or transient depending on whether the
251
+ * class is retrieved via {@link Box.get} or {@link Box.new}.
252
+ *
253
+ * @example
254
+ * ```ts
255
+ * class UserService {
256
+ * constructor(private db: Database, private logger: Logger) {}
257
+ * static init = Box.init(UserService).get(Database, LoggerFactory);
258
+ * }
259
+ * ```
260
+ */
261
+ get(...args) {
262
+ return (box) => {
263
+ const instances = args.map((arg) => box.get(arg));
264
+ return new this.construct(...instances);
265
+ };
266
+ }
267
+ };
181
268
 
182
269
  //#endregion
183
270
  exports.Box = Box;
184
271
  exports.Construct = Construct;
272
+ exports.StaticConstruct = StaticConstruct;
185
273
  exports.constant = constant;
186
- exports.factory = factory;
274
+ exports.factory = factory;
275
+ exports.transient = transient;
package/dist/index.d.cts CHANGED
@@ -10,7 +10,11 @@ type Constructor<T> = {
10
10
  new (): T;
11
11
  };
12
12
  /** Extracts the instance type from a {@link Constructor}. */
13
- type ConstructorInstanceType<T> = T extends Constructor<infer U> ? U : never;
13
+ type ConstructorInstanceType<T> = T extends {
14
+ init(box: Box): infer U;
15
+ } ? U : T extends {
16
+ new (): infer U;
17
+ } ? U : never;
14
18
  /**
15
19
  * Creates a {@link Constructor} from a factory function.
16
20
  * The factory receives the box as an argument, allowing it to resolve other dependencies.
@@ -25,6 +29,20 @@ type ConstructorInstanceType<T> = T extends Constructor<infer U> ? U : never;
25
29
  * ```
26
30
  */
27
31
  declare function factory<T>(init: (box: Box) => T): Constructor<T>;
32
+ /**
33
+ * Creates a {@link Constructor} from a factory function whose result is never cached.
34
+ * The factory is called on every resolution, always returning a fresh value
35
+ * even when retrieved via {@link Box.get}.
36
+ *
37
+ * @example
38
+ * ```ts
39
+ * const RequestId = transient(() => crypto.randomUUID());
40
+ * const id1 = box.get(RequestId);
41
+ * const id2 = box.get(RequestId);
42
+ * console.log(id1 === id2); // false
43
+ * ```
44
+ */
45
+ declare function transient<T>(init: (box: Box) => T): Constructor<T>;
28
46
  /**
29
47
  * Creates a {@link Constructor} that always resolves to the given constant value.
30
48
  * Constant values are never cached since they are already fixed.
@@ -72,12 +90,12 @@ declare class Box {
72
90
  * Creates a new (transient) instance without caching. Useful for instances
73
91
  * that should not be shared.
74
92
  */
75
- new<T>(constructor: Constructor<T>): T;
93
+ new<T extends Constructor<any>>(constructor: T): ConstructorInstanceType<T>;
76
94
  /**
77
95
  * Resolves an instance from the cache, or creates and caches a new one.
78
96
  * Subsequent calls with the same constructor return the cached instance.
79
97
  */
80
- get<T>(constructor: Constructor<T>): T;
98
+ get<T extends Constructor<any>>(constructor: T): ConstructorInstanceType<T>;
81
99
  /** Resolves multiple constructors at once. */
82
100
  readonly all: BoxAll;
83
101
  /**
@@ -89,6 +107,19 @@ declare class Box {
89
107
  * the class is retrieved via {@link Box.get} or kept transient via {@link Box.new}.
90
108
  */
91
109
  for<T extends ClassConstructor<any>>(constructor: T): Construct<T>;
110
+ /**
111
+ * Returns a {@link StaticConstruct} builder for defining a `static init` method.
112
+ * The result can be assigned directly to `static init`.
113
+ *
114
+ * @example
115
+ * ```ts
116
+ * class UserService {
117
+ * constructor(private db: Database, private logger: Logger) {}
118
+ * static init = Box.init(UserService).get(Database, LoggerFactory);
119
+ * }
120
+ * ```
121
+ */
122
+ static init<T extends ClassConstructor<any>>(constructor: T): StaticConstruct<T>;
92
123
  /**
93
124
  * Registers a mock value in the box's cache for a given constructor.
94
125
  * Useful for replacing dependencies in tests.
@@ -159,6 +190,48 @@ declare class Construct<T extends ClassConstructor<any>> {
159
190
  */
160
191
  get(...args: ClassConstructorArgs<T>): InstanceType<T>;
161
192
  }
193
+ /**
194
+ * Builder for creating a `static init` function with constructor dependencies
195
+ * resolved from a {@link Box}.
196
+ */
197
+ declare class StaticConstruct<T extends ClassConstructor<any>> {
198
+ private construct;
199
+ constructor(construct: T);
200
+ /**
201
+ * Resolves each dependency as a new transient instance via {@link Box.new},
202
+ * meaning dependencies are not cached or shared.
203
+ * Returns a function compatible with `static init` that can be assigned directly.
204
+ *
205
+ * The returned instance is cached or transient depending on whether the
206
+ * class is retrieved via {@link Box.get} or {@link Box.new}.
207
+ *
208
+ * @example
209
+ * ```ts
210
+ * class UserService {
211
+ * constructor(private db: Database, private logger: Logger) {}
212
+ * static init = Box.init(UserService).get(Database, LoggerFactory);
213
+ * }
214
+ * ```
215
+ */
216
+ new(...args: ClassConstructorArgs<T>): (box: Box) => InstanceType<T>;
217
+ /**
218
+ * Resolves each dependency as a cached instance via {@link Box.get},
219
+ * meaning dependencies are shared across the box.
220
+ * Returns a function compatible with `static init` that can be assigned directly.
221
+ *
222
+ * The returned instance is cached or transient depending on whether the
223
+ * class is retrieved via {@link Box.get} or {@link Box.new}.
224
+ *
225
+ * @example
226
+ * ```ts
227
+ * class UserService {
228
+ * constructor(private db: Database, private logger: Logger) {}
229
+ * static init = Box.init(UserService).get(Database, LoggerFactory);
230
+ * }
231
+ * ```
232
+ */
233
+ get(...args: ClassConstructorArgs<T>): (box: Box) => InstanceType<T>;
234
+ }
162
235
  /** A class with any constructor signature. */
163
236
  type ClassConstructor<T> = {
164
237
  new (...args: any): T;
@@ -166,4 +239,4 @@ type ClassConstructor<T> = {
166
239
  /** Maps each constructor parameter to its corresponding {@link Constructor} type. */
167
240
  type ClassConstructorArgs<T extends ClassConstructor<any>, Args = ConstructorParameters<T>> = { [K in keyof Args]: Constructor<Args[K]> };
168
241
  //#endregion
169
- export { Box, Construct, Constructor, ConstructorInstanceType, constant, factory };
242
+ export { Box, Construct, Constructor, ConstructorInstanceType, StaticConstruct, constant, factory, transient };
package/dist/index.d.mts CHANGED
@@ -10,7 +10,11 @@ type Constructor<T> = {
10
10
  new (): T;
11
11
  };
12
12
  /** Extracts the instance type from a {@link Constructor}. */
13
- type ConstructorInstanceType<T> = T extends Constructor<infer U> ? U : never;
13
+ type ConstructorInstanceType<T> = T extends {
14
+ init(box: Box): infer U;
15
+ } ? U : T extends {
16
+ new (): infer U;
17
+ } ? U : never;
14
18
  /**
15
19
  * Creates a {@link Constructor} from a factory function.
16
20
  * The factory receives the box as an argument, allowing it to resolve other dependencies.
@@ -25,6 +29,20 @@ type ConstructorInstanceType<T> = T extends Constructor<infer U> ? U : never;
25
29
  * ```
26
30
  */
27
31
  declare function factory<T>(init: (box: Box) => T): Constructor<T>;
32
+ /**
33
+ * Creates a {@link Constructor} from a factory function whose result is never cached.
34
+ * The factory is called on every resolution, always returning a fresh value
35
+ * even when retrieved via {@link Box.get}.
36
+ *
37
+ * @example
38
+ * ```ts
39
+ * const RequestId = transient(() => crypto.randomUUID());
40
+ * const id1 = box.get(RequestId);
41
+ * const id2 = box.get(RequestId);
42
+ * console.log(id1 === id2); // false
43
+ * ```
44
+ */
45
+ declare function transient<T>(init: (box: Box) => T): Constructor<T>;
28
46
  /**
29
47
  * Creates a {@link Constructor} that always resolves to the given constant value.
30
48
  * Constant values are never cached since they are already fixed.
@@ -72,12 +90,12 @@ declare class Box {
72
90
  * Creates a new (transient) instance without caching. Useful for instances
73
91
  * that should not be shared.
74
92
  */
75
- new<T>(constructor: Constructor<T>): T;
93
+ new<T extends Constructor<any>>(constructor: T): ConstructorInstanceType<T>;
76
94
  /**
77
95
  * Resolves an instance from the cache, or creates and caches a new one.
78
96
  * Subsequent calls with the same constructor return the cached instance.
79
97
  */
80
- get<T>(constructor: Constructor<T>): T;
98
+ get<T extends Constructor<any>>(constructor: T): ConstructorInstanceType<T>;
81
99
  /** Resolves multiple constructors at once. */
82
100
  readonly all: BoxAll;
83
101
  /**
@@ -89,6 +107,19 @@ declare class Box {
89
107
  * the class is retrieved via {@link Box.get} or kept transient via {@link Box.new}.
90
108
  */
91
109
  for<T extends ClassConstructor<any>>(constructor: T): Construct<T>;
110
+ /**
111
+ * Returns a {@link StaticConstruct} builder for defining a `static init` method.
112
+ * The result can be assigned directly to `static init`.
113
+ *
114
+ * @example
115
+ * ```ts
116
+ * class UserService {
117
+ * constructor(private db: Database, private logger: Logger) {}
118
+ * static init = Box.init(UserService).get(Database, LoggerFactory);
119
+ * }
120
+ * ```
121
+ */
122
+ static init<T extends ClassConstructor<any>>(constructor: T): StaticConstruct<T>;
92
123
  /**
93
124
  * Registers a mock value in the box's cache for a given constructor.
94
125
  * Useful for replacing dependencies in tests.
@@ -159,6 +190,48 @@ declare class Construct<T extends ClassConstructor<any>> {
159
190
  */
160
191
  get(...args: ClassConstructorArgs<T>): InstanceType<T>;
161
192
  }
193
+ /**
194
+ * Builder for creating a `static init` function with constructor dependencies
195
+ * resolved from a {@link Box}.
196
+ */
197
+ declare class StaticConstruct<T extends ClassConstructor<any>> {
198
+ private construct;
199
+ constructor(construct: T);
200
+ /**
201
+ * Resolves each dependency as a new transient instance via {@link Box.new},
202
+ * meaning dependencies are not cached or shared.
203
+ * Returns a function compatible with `static init` that can be assigned directly.
204
+ *
205
+ * The returned instance is cached or transient depending on whether the
206
+ * class is retrieved via {@link Box.get} or {@link Box.new}.
207
+ *
208
+ * @example
209
+ * ```ts
210
+ * class UserService {
211
+ * constructor(private db: Database, private logger: Logger) {}
212
+ * static init = Box.init(UserService).get(Database, LoggerFactory);
213
+ * }
214
+ * ```
215
+ */
216
+ new(...args: ClassConstructorArgs<T>): (box: Box) => InstanceType<T>;
217
+ /**
218
+ * Resolves each dependency as a cached instance via {@link Box.get},
219
+ * meaning dependencies are shared across the box.
220
+ * Returns a function compatible with `static init` that can be assigned directly.
221
+ *
222
+ * The returned instance is cached or transient depending on whether the
223
+ * class is retrieved via {@link Box.get} or {@link Box.new}.
224
+ *
225
+ * @example
226
+ * ```ts
227
+ * class UserService {
228
+ * constructor(private db: Database, private logger: Logger) {}
229
+ * static init = Box.init(UserService).get(Database, LoggerFactory);
230
+ * }
231
+ * ```
232
+ */
233
+ get(...args: ClassConstructorArgs<T>): (box: Box) => InstanceType<T>;
234
+ }
162
235
  /** A class with any constructor signature. */
163
236
  type ClassConstructor<T> = {
164
237
  new (...args: any): T;
@@ -166,4 +239,4 @@ type ClassConstructor<T> = {
166
239
  /** Maps each constructor parameter to its corresponding {@link Constructor} type. */
167
240
  type ClassConstructorArgs<T extends ClassConstructor<any>, Args = ConstructorParameters<T>> = { [K in keyof Args]: Constructor<Args[K]> };
168
241
  //#endregion
169
- export { Box, Construct, Constructor, ConstructorInstanceType, constant, factory };
242
+ export { Box, Construct, Constructor, ConstructorInstanceType, StaticConstruct, constant, factory, transient };
package/dist/index.mjs CHANGED
@@ -15,7 +15,26 @@
15
15
  function factory(init) {
16
16
  return { init };
17
17
  }
18
- const constantSymbol = Symbol("Box constant");
18
+ const noCacheSymbol = Symbol("Box.noCache");
19
+ /**
20
+ * Creates a {@link Constructor} from a factory function whose result is never cached.
21
+ * The factory is called on every resolution, always returning a fresh value
22
+ * even when retrieved via {@link Box.get}.
23
+ *
24
+ * @example
25
+ * ```ts
26
+ * const RequestId = transient(() => crypto.randomUUID());
27
+ * const id1 = box.get(RequestId);
28
+ * const id2 = box.get(RequestId);
29
+ * console.log(id1 === id2); // false
30
+ * ```
31
+ */
32
+ function transient(init) {
33
+ return {
34
+ init,
35
+ [noCacheSymbol]: true
36
+ };
37
+ }
19
38
  /**
20
39
  * Creates a {@link Constructor} that always resolves to the given constant value.
21
40
  * Constant values are never cached since they are already fixed.
@@ -29,7 +48,7 @@ const constantSymbol = Symbol("Box constant");
29
48
  function constant(value) {
30
49
  return {
31
50
  init: () => value,
32
- [constantSymbol]: true
51
+ [noCacheSymbol]: true
33
52
  };
34
53
  }
35
54
  /**
@@ -78,7 +97,7 @@ var Box = class {
78
97
  get(constructor) {
79
98
  if (this.cache.has(constructor)) return this.cache.get(constructor);
80
99
  const value = this.new(constructor);
81
- if (!(constantSymbol in constructor && constructor[constantSymbol])) this.cache.set(constructor, value);
100
+ if (!(noCacheSymbol in constructor && constructor[noCacheSymbol])) this.cache.set(constructor, value);
82
101
  return value;
83
102
  }
84
103
  /** Resolves multiple constructors at once. */
@@ -95,6 +114,21 @@ var Box = class {
95
114
  return new Construct(this, constructor);
96
115
  }
97
116
  /**
117
+ * Returns a {@link StaticConstruct} builder for defining a `static init` method.
118
+ * The result can be assigned directly to `static init`.
119
+ *
120
+ * @example
121
+ * ```ts
122
+ * class UserService {
123
+ * constructor(private db: Database, private logger: Logger) {}
124
+ * static init = Box.init(UserService).get(Database, LoggerFactory);
125
+ * }
126
+ * ```
127
+ */
128
+ static init(constructor) {
129
+ return new StaticConstruct(constructor);
130
+ }
131
+ /**
98
132
  * Registers a mock value in the box's cache for a given constructor.
99
133
  * Useful for replacing dependencies in tests.
100
134
  */
@@ -177,6 +211,59 @@ var Construct = class {
177
211
  return new this.construct(...instances);
178
212
  }
179
213
  };
214
+ /**
215
+ * Builder for creating a `static init` function with constructor dependencies
216
+ * resolved from a {@link Box}.
217
+ */
218
+ var StaticConstruct = class {
219
+ constructor(construct) {
220
+ this.construct = construct;
221
+ }
222
+ /**
223
+ * Resolves each dependency as a new transient instance via {@link Box.new},
224
+ * meaning dependencies are not cached or shared.
225
+ * Returns a function compatible with `static init` that can be assigned directly.
226
+ *
227
+ * The returned instance is cached or transient depending on whether the
228
+ * class is retrieved via {@link Box.get} or {@link Box.new}.
229
+ *
230
+ * @example
231
+ * ```ts
232
+ * class UserService {
233
+ * constructor(private db: Database, private logger: Logger) {}
234
+ * static init = Box.init(UserService).get(Database, LoggerFactory);
235
+ * }
236
+ * ```
237
+ */
238
+ new(...args) {
239
+ return (box) => {
240
+ const instances = args.map((arg) => box.new(arg));
241
+ return new this.construct(...instances);
242
+ };
243
+ }
244
+ /**
245
+ * Resolves each dependency as a cached instance via {@link Box.get},
246
+ * meaning dependencies are shared across the box.
247
+ * Returns a function compatible with `static init` that can be assigned directly.
248
+ *
249
+ * The returned instance is cached or transient depending on whether the
250
+ * class is retrieved via {@link Box.get} or {@link Box.new}.
251
+ *
252
+ * @example
253
+ * ```ts
254
+ * class UserService {
255
+ * constructor(private db: Database, private logger: Logger) {}
256
+ * static init = Box.init(UserService).get(Database, LoggerFactory);
257
+ * }
258
+ * ```
259
+ */
260
+ get(...args) {
261
+ return (box) => {
262
+ const instances = args.map((arg) => box.get(arg));
263
+ return new this.construct(...instances);
264
+ };
265
+ }
266
+ };
180
267
 
181
268
  //#endregion
182
- export { Box, Construct, constant, factory };
269
+ export { Box, Construct, StaticConstruct, constant, factory, transient };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "getbox",
3
- "version": "1.1.0",
3
+ "version": "1.3.0",
4
4
  "description": "Lightweight dependency injection for TypeScript",
5
5
  "private": false,
6
6
  "main": "./dist/index.cjs",