getbox 1.3.0 → 1.4.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
@@ -11,8 +11,8 @@ import { withBox } from "getbox/context";
11
11
 
12
12
  withBox(() => {
13
13
  // All code in this scope can resolve dependencies
14
- const app = resolve(App);
15
- app.start();
14
+ const service = inject(UserService);
15
+ service.createUser("Alice");
16
16
  });
17
17
  ```
18
18
 
@@ -23,24 +23,24 @@ import { Box } from "getbox";
23
23
  import { withBox } from "getbox/context";
24
24
 
25
25
  const box = new Box();
26
- Box.mock(box, LoggerFactory, new TestLogger());
26
+ Box.mock(box, LoggerFactory, new MockLogger());
27
27
 
28
28
  withBox(box, () => {
29
- const app = resolve(App);
30
- app.start();
29
+ const service = inject(UserService);
30
+ service.createUser("Alice");
31
31
  });
32
32
  ```
33
33
 
34
34
  ## Resolving dependencies
35
35
 
36
- With the context pattern, classes can use `resolve` directly as field initializers. No `static init` method is needed.
36
+ With the context pattern, classes can use `inject` directly as field initializers. No `static init` property is needed.
37
37
 
38
38
  ```ts
39
- import { resolve } from "getbox/context";
39
+ import { inject } from "getbox/context";
40
40
 
41
41
  class UserService {
42
- public db = resolve(Database);
43
- public logger = resolve(LoggerFactory);
42
+ public db = inject(Database);
43
+ public logger = inject(LoggerFactory);
44
44
 
45
45
  createUser(name: string) {
46
46
  this.logger.log(`Creating user: ${name}`);
@@ -63,36 +63,21 @@ class UserService {
63
63
 
64
64
  ## Resolving multiple dependencies
65
65
 
66
- Use `resolveAll` to resolve multiple constructors at once. Accepts an object or array of constructors.
66
+ Use `injectAll` to resolve multiple constructors at once. Accepts an object or array of constructors.
67
67
 
68
68
  ```ts
69
69
  withBox(() => {
70
70
  // Object form
71
- const { db, logger } = resolveAll({ db: Database, logger: LoggerFactory });
71
+ const { db, logger } = injectAll({ db: Database, logger: LoggerFactory });
72
72
 
73
73
  // Array form
74
- const [db2, logger2] = resolveAll([Database, LoggerFactory]);
74
+ const [db2, logger2] = injectAll([Database, LoggerFactory]);
75
75
 
76
76
  console.log(db === db2); // true (cached)
77
77
  console.log(logger === logger2); // true (cached)
78
78
  });
79
79
  ```
80
80
 
81
- ## Resolving constructor parameters
82
-
83
- Use `construct` to create a class instance with resolved constructor parameters.
84
-
85
- ```ts
86
- class UserService {
87
- constructor(private db: Database, private logger: Logger) {}
88
- }
89
-
90
- withBox(() => {
91
- const service = construct(UserService).get(Database, LoggerFactory);
92
- service.createUser("Alice");
93
- });
94
- ```
95
-
96
81
  ## Accessing the box
97
82
 
98
83
  Use `useBox()` to get the current box from the scope. This is useful when you need full access to the box API.
@@ -110,11 +95,11 @@ Each `withBox` call creates an independent scope. Nested scopes do not share the
110
95
 
111
96
  ```ts
112
97
  withBox(() => {
113
- const db = resolve(Database);
98
+ const db = inject(Database);
114
99
 
115
- // Inner scope gets a fresh box
100
+ // Inner scope gets a new box
116
101
  withBox(() => {
117
- const db2 = resolve(Database);
102
+ const db2 = inject(Database);
118
103
  console.log(db === db2); // false (different scope)
119
104
  });
120
105
  });
package/README.md CHANGED
@@ -2,11 +2,9 @@
2
2
 
3
3
  ### Lightweight dependency injection for TypeScript.
4
4
 
5
- `getbox` provides a simple way of managing dependencies in TypeScript applications. Dependencies are defined as constructors that act as interfaces for the values they resolve.
5
+ `getbox` is a lightweight inversion of control container for TypeScript. Constructors declare their own dependencies, keeping instantiation logic colocated with the type that owns it.
6
6
 
7
- Callers know the type of the value they need, but not how it will be derived. The box resolves constructors lazily and caches instances automatically.
8
-
9
- For an alternative pattern using AsyncLocalStorage where classes can resolve dependencies directly in their constructors, see [getbox/context](./CONTEXT.md).
7
+ Callers depend on types, not implementations. The box resolves and caches instances automatically on first use.
10
8
 
11
9
  ## Installation
12
10
 
@@ -16,254 +14,206 @@ npm install getbox
16
14
 
17
15
  ## Usage
18
16
 
19
- `getbox` has a very small API surface. You typically only need to use the `Box.get()` and optionally static init methods or the `factory` helper.
17
+ `getbox` has a very small API surface. You typically only need `box.get()` and optionally `static init` or the `factory` helper.
18
+
19
+ For an alternative pattern using AsyncLocalStorage where classes can resolve dependencies directly, see [getbox/context](./CONTEXT.md).
20
20
 
21
- ### Create a class
21
+ ### Quick start
22
22
 
23
- Classes are instantiated once and cached. Subsequent calls return the cached instance.
23
+ Create a `Box` instance and call `box.get()` to resolve instances. The box automatically resolves dependencies and caches every instance, so shared dependencies always point to the same reference.
24
24
 
25
25
  ```ts
26
- // printer.ts
27
- export class Printer {
28
- print(text: string): string {
26
+ import { Box } from "getbox";
27
+
28
+ class Printer {
29
+ print(text: string) {
29
30
  return text.toUpperCase();
30
31
  }
31
32
  }
32
- ```
33
33
 
34
- ### Use in another class
35
-
36
- Retrieve instances by calling `box.get(Constructor)` within your class constructor or factory function.
37
-
38
- ```ts
39
- // office.ts
40
- import { Box, factory } from "getbox";
41
- import { Printer } from "./printer";
42
-
43
- export class Office {
34
+ class Office {
44
35
  constructor(public printer: Printer) {}
45
36
 
46
37
  static init = Box.init(Office).get(Printer);
47
38
  }
48
- ```
49
-
50
- ### Use in application
51
-
52
- Create a Box instance to hold cached instances.
53
-
54
- When initializing a class, any dependencies it has will also be cached, ensuring that shared dependencies use the same instance.
55
-
56
- ```ts
57
- // main.ts
58
- import { Box } from "getbox";
59
- import { Office } from "./office";
60
- import { Printer } from "./printer";
61
39
 
62
40
  const box = new Box();
63
41
 
64
42
  const office = box.get(Office);
65
43
  office.printer.print("hello world");
66
44
 
67
- // Instances are cached and shared
45
+ // Dependencies are cached and shared
68
46
  const printer = box.get(Printer);
69
47
  console.log(office.printer === printer); // true
70
48
  ```
71
49
 
72
- ## Transient instances
50
+ ## Constructors
73
51
 
74
- Use `box.new()` to create a new instance each time without caching. This is useful for instances that should not be shared.
52
+ Constructors define what the box resolves. `getbox` supports classes, factories, derived values, and constants. Because constructors act as interfaces, the underlying implementation can change without affecting any consumer.
53
+
54
+ ### Classes
55
+
56
+ Define a `static init` property to allow the box to resolve classes that have constructor parameters. Classes with no parameters do not require it.
75
57
 
76
58
  ```ts
77
- // main.ts
78
59
  import { Box } from "getbox";
79
60
 
80
- class Database {
81
- connect() {
82
- /* ... */
61
+ class UserService {
62
+ constructor(private db: Database, private logger: Logger) {}
63
+
64
+ static init = Box.init(UserService).get(Database, LoggerFactory);
65
+
66
+ createUser(name: string) {
67
+ this.logger.log(`Creating user: ${name}`);
83
68
  }
84
69
  }
85
70
 
86
71
  const box = new Box();
87
-
88
- const db1 = box.new(Database);
89
- const db2 = box.new(Database);
90
-
91
- console.log(db1 === db2); // false
72
+ const service = box.get(UserService);
73
+ service.createUser("Alice");
92
74
  ```
93
75
 
94
- ## Factory functions
95
-
96
- Use the `factory` helper to create function-based constructors instead of classes. Factories work well with interfaces for better abstraction.
76
+ `Box.init` is shorthand for writing the `static init` property yourself.
97
77
 
98
78
  ```ts
99
- // logger.ts
100
- import { Box, factory } from "getbox";
101
-
102
- export interface Logger {
103
- log(message: string): void;
104
- }
79
+ class UserService {
80
+ constructor(private db: Database, private logger: Logger) {}
105
81
 
106
- export class ConsoleLogger implements Logger {
107
- log(message: string): void {
108
- console.log(`[LOG] ${message}`);
82
+ static init(box: Box) {
83
+ return new UserService(box.get(Database), box.get(LoggerFactory));
109
84
  }
110
85
  }
111
-
112
- const LoggerFactory = factory((box: Box): Logger => {
113
- return new ConsoleLogger();
114
- });
115
86
  ```
116
87
 
117
- ```ts
118
- // service.ts
119
- import { Box } from "getbox";
120
- import { Logger, LoggerFactory } from "./logger";
121
-
122
- export class UserService {
123
- constructor(private logger: Logger) {}
88
+ Use `box.for()` when you need custom logic alongside dependency resolution.
124
89
 
125
- static init = Box.init(UserService).get(LoggerFactory);
90
+ ```ts
91
+ class UserService {
92
+ constructor(private db: Database, private logger: Logger) {}
126
93
 
127
- createUser(name: string) {
128
- this.logger.log(`Creating user: ${name}`);
94
+ static init(box: Box) {
95
+ const logger = box.get(LoggerFactory);
96
+ logger.log("Initializing UserService");
97
+ return box.for(UserService).get(Database, LoggerFactory);
129
98
  }
130
99
  }
131
100
  ```
132
101
 
133
- ## Constants
134
-
135
- Use the `constant` helper to register constant values without needing a factory or class. Constant values are never cached since they are already fixed.
136
-
137
- ```ts
138
- import { Box, constant } from "getbox";
102
+ If `static init` is defined, it takes priority over the class constructor.
139
103
 
140
- const ApiUrl = constant("https://api.example.com");
141
- const Port = constant(3000);
142
- const Config = constant({
143
- baseUrl: "https://example.com",
144
- timeout: 5000,
145
- });
104
+ ### Factory functions
146
105
 
147
- const box = new Box();
106
+ Use the `factory` helper to create function-based constructors instead of classes. Factories work well with interfaces for better abstraction.
148
107
 
149
- const apiUrl = box.get(ApiUrl);
150
- const port = box.get(Port);
151
- const config = box.get(Config);
108
+ ```ts
109
+ import { Box, factory } from "getbox";
152
110
 
153
- console.log(apiUrl); // "https://api.example.com"
154
- console.log(port); // 3000
155
- console.log(config.timeout); // 5000
156
- ```
111
+ interface Logger {
112
+ log(message: string): void;
113
+ }
157
114
 
158
- Since constructors act as interfaces, a `constant` can later be replaced with a `factory` without changing any callers.
115
+ const LoggerFactory = factory(
116
+ (): Logger => ({
117
+ log(message: string) {
118
+ console.log(`[LOG] ${message}`);
119
+ },
120
+ }),
121
+ );
159
122
 
160
- ```ts
161
- const ApiUrl = factory((box: Box) => {
162
- const config = box.get(Config);
163
- return `${config.baseUrl}/api`;
164
- });
123
+ const box = new Box();
124
+ const logger = box.get(LoggerFactory);
165
125
 
166
- const apiUrl = box.get(ApiUrl); // "https://example.com/api"
126
+ logger.log("hello world");
167
127
  ```
168
128
 
169
- ## Transient factories
129
+ ### Derived values
170
130
 
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()`.
131
+ Use the `derive` helper to compute a value from the box without caching the result.
172
132
 
173
133
  ```ts
174
- import { Box, transient } from "getbox";
134
+ import { Box, derive } from "getbox";
175
135
 
176
- const RequestId = transient(() => crypto.randomUUID());
136
+ class Config {
137
+ baseUrl = "https://example.com";
138
+ }
139
+
140
+ const RequestContext = derive((box) => ({
141
+ baseUrl: box.get(Config).baseUrl,
142
+ timestamp: Date.now(),
143
+ }));
177
144
 
178
145
  const box = new Box();
179
146
 
180
- const id1 = box.get(RequestId);
181
- const id2 = box.get(RequestId);
147
+ const ctx1 = box.get(RequestContext);
148
+ const ctx2 = box.get(RequestContext);
182
149
 
183
- console.log(id1 === id2); // false
150
+ console.log(ctx1 === ctx2); // false
184
151
  ```
185
152
 
186
- ## Resolving multiple constructors
153
+ ### Constants
187
154
 
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.
155
+ Use the `constant` helper to wrap a fixed value as a constructor. Constant values are never cached and always return the same stable reference.
189
156
 
190
157
  ```ts
191
- import { Box } from "getbox";
192
-
193
- const box = new Box();
194
-
195
- // Object form
196
- const { db, logger } = box.all.get({ db: Database, logger: LoggerFactory });
197
-
198
- // Array form
199
- const [db2, logger2] = box.all.get([Database, LoggerFactory]);
200
-
201
- console.log(db === db2); // true (cached)
202
- console.log(logger === logger2); // true (cached)
203
- ```
158
+ import { Box, constant } from "getbox";
204
159
 
205
- Use `box.all.new()` to resolve multiple constructors as transient instances.
160
+ const ApiUrl = constant("https://api.example.com");
161
+ const Port = constant(3000);
162
+ const Config = constant({
163
+ baseUrl: "https://example.com",
164
+ timeout: 5000,
165
+ });
206
166
 
207
- ```ts
208
- const { db } = box.all.new({ db: Database });
209
- const [db2] = box.all.new([Database]);
167
+ const box = new Box();
210
168
 
211
- console.log(db === db2); // false (transient)
169
+ console.log(box.get(ApiUrl)); // "https://api.example.com"
170
+ console.log(box.get(Port)); // 3000
171
+ console.log(box.get(Config).timeout); // 5000
212
172
  ```
213
173
 
214
- ## Class constructors
174
+ ## Resolving instances
215
175
 
216
- Use `Box.init` to allow resolving classes that have constructor parameters.
176
+ Use `box.get()` to resolve a cached instance. The box resolves the constructor on first call and returns the same instance on every subsequent call. Use `box.new()` to always get a new instance without caching.
217
177
 
218
178
  ```ts
219
179
  import { Box } from "getbox";
220
180
 
221
- class UserService {
222
- constructor(private db: Database, private logger: Logger) {}
223
-
224
- static init = Box.init(UserService).get(Database, LoggerFactory);
225
-
226
- createUser(name: string) {
227
- this.logger.log(`Creating user: ${name}`);
181
+ class Database {
182
+ connect() {
183
+ /* ... */
228
184
  }
229
185
  }
230
186
 
231
187
  const box = new Box();
232
- const service = box.get(UserService);
233
- service.createUser("Alice");
234
- ```
235
-
236
- `Box.init` is shorthand for writing the `static init` method yourself.
237
188
 
238
- ```ts
239
- class UserService {
240
- constructor(private db: Database, private logger: Logger) {}
189
+ const db1 = box.get(Database);
190
+ const db2 = box.get(Database);
191
+ console.log(db1 === db2); // true (cached)
241
192
 
242
- static init(box: Box) {
243
- return new UserService(box.get(Database), box.get(LoggerFactory));
244
- }
245
- }
193
+ const db3 = box.new(Database);
194
+ const db4 = box.new(Database);
195
+ console.log(db3 === db4); // false (never cached)
246
196
  ```
247
197
 
248
- Use `box.for()` when you need custom logic alongside dependency resolution.
198
+ Use `box.all.get()` or `box.all.new()` to resolve multiple constructors at once. Pass an array to get an array of instances, or an object to get an object of instances.
249
199
 
250
200
  ```ts
251
- class UserService {
252
- constructor(private db: Database, private logger: Logger) {}
201
+ const box = new Box();
253
202
 
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
- }
203
+ // Cached
204
+ const { db, logger } = box.all.get({ db: Database, logger: LoggerFactory });
205
+ const [db2, logger2] = box.all.get([Database, LoggerFactory]);
206
+
207
+ // New instances
208
+ const { db3 } = box.all.new({ db3: Database });
209
+ const [db4] = box.all.new([Database]);
260
210
  ```
261
211
 
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.
212
+ > `box.get()` does not cache `derive` or `constant` values.
263
213
 
264
214
  ## Mocking
265
215
 
266
- You can mock dependencies for testing using `Box.mock`. This is particularly useful with factories and interfaces.
216
+ You can mock dependencies for testing using `Box.mock`.
267
217
 
268
218
  ```ts
269
219
  // service.test.ts
@@ -308,7 +258,7 @@ Box.clear(box);
308
258
 
309
259
  ## Circular dependencies
310
260
 
311
- `getbox` does not prevent circular dependencies. You should structure your code to avoid circular imports between modules.
261
+ `getbox` does not prevent circular dependencies. You should structure your code to avoid them.
312
262
 
313
263
  ## License
314
264
 
package/dist/context.cjs CHANGED
@@ -20,15 +20,26 @@ function useBox() {
20
20
  * Resolves a cached instance from the current {@link withBox} scope.
21
21
  * Shorthand for `useBox().get(constructor)`.
22
22
  */
23
- function resolve(constructor) {
23
+ function inject(constructor) {
24
24
  return useBox().get(constructor);
25
25
  }
26
- function resolveAll(constructors) {
26
+ /**
27
+ * @deprecated Use {@link inject} instead.
28
+ */
29
+ function resolve(constructor) {
30
+ return inject(constructor);
31
+ }
32
+ function injectAll(constructors) {
27
33
  return useBox().all.get(constructors);
28
34
  }
35
+ function resolveAll(constructors) {
36
+ return injectAll(constructors);
37
+ }
29
38
  /**
30
39
  * Returns a builder for creating a class instance with resolved constructor
31
40
  * parameters from the current {@link withBox} scope. Shorthand for `useBox().for(constructor)`.
41
+ *
42
+ * @deprecated
32
43
  */
33
44
  function construct(constructor) {
34
45
  return useBox().for(constructor);
@@ -36,6 +47,8 @@ function construct(constructor) {
36
47
 
37
48
  //#endregion
38
49
  exports.construct = construct;
50
+ exports.inject = inject;
51
+ exports.injectAll = injectAll;
39
52
  exports.resolve = resolve;
40
53
  exports.resolveAll = resolveAll;
41
54
  exports.useBox = useBox;
@@ -4,7 +4,7 @@ import { Box, Construct, Constructor, ConstructorInstanceType } from "./index.cj
4
4
 
5
5
  /**
6
6
  * Runs a function within a scoped {@link Box} context using AsyncLocalStorage.
7
- * Creates a fresh Box if none is provided.
7
+ * Creates a new Box if none is provided.
8
8
  */
9
9
  declare function withBox<T>(fn: () => T): T;
10
10
  declare function withBox<T>(box: Box, fn: () => T): T;
@@ -17,17 +17,28 @@ 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 inject<T extends Constructor<any>>(constructor: T): ConstructorInstanceType<T>;
21
+ /**
22
+ * @deprecated Use {@link inject} instead.
23
+ */
20
24
  declare function resolve<T extends Constructor<any>>(constructor: T): ConstructorInstanceType<T>;
21
25
  /**
22
26
  * Resolves multiple cached instances from the current {@link withBox} scope.
23
27
  * Shorthand for `useBox().all.get(constructors)`.
24
28
  */
29
+ declare function injectAll<const T extends Constructor<any>[]>(constructors: T): { [K in keyof T]: ConstructorInstanceType<T[K]> };
30
+ declare function injectAll<T extends Record<string, Constructor<any>>>(constructors: T): { [K in keyof T]: ConstructorInstanceType<T[K]> };
31
+ /**
32
+ * @deprecated Use {@link injectAll} instead.
33
+ */
25
34
  declare function resolveAll<const T extends Constructor<any>[]>(constructors: T): { [K in keyof T]: ConstructorInstanceType<T[K]> };
26
35
  declare function resolveAll<T extends Record<string, Constructor<any>>>(constructors: T): { [K in keyof T]: ConstructorInstanceType<T[K]> };
27
36
  /**
28
37
  * Returns a builder for creating a class instance with resolved constructor
29
38
  * parameters from the current {@link withBox} scope. Shorthand for `useBox().for(constructor)`.
39
+ *
40
+ * @deprecated
30
41
  */
31
42
  declare function construct<T extends new (...args: any) => any>(constructor: T): Construct<T>;
32
43
  //#endregion
33
- export { construct, resolve, resolveAll, useBox, withBox };
44
+ export { construct, inject, injectAll, resolve, resolveAll, useBox, withBox };
@@ -4,7 +4,7 @@ import { Box, Construct, Constructor, ConstructorInstanceType } from "./index.mj
4
4
 
5
5
  /**
6
6
  * Runs a function within a scoped {@link Box} context using AsyncLocalStorage.
7
- * Creates a fresh Box if none is provided.
7
+ * Creates a new Box if none is provided.
8
8
  */
9
9
  declare function withBox<T>(fn: () => T): T;
10
10
  declare function withBox<T>(box: Box, fn: () => T): T;
@@ -17,17 +17,28 @@ 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 inject<T extends Constructor<any>>(constructor: T): ConstructorInstanceType<T>;
21
+ /**
22
+ * @deprecated Use {@link inject} instead.
23
+ */
20
24
  declare function resolve<T extends Constructor<any>>(constructor: T): ConstructorInstanceType<T>;
21
25
  /**
22
26
  * Resolves multiple cached instances from the current {@link withBox} scope.
23
27
  * Shorthand for `useBox().all.get(constructors)`.
24
28
  */
29
+ declare function injectAll<const T extends Constructor<any>[]>(constructors: T): { [K in keyof T]: ConstructorInstanceType<T[K]> };
30
+ declare function injectAll<T extends Record<string, Constructor<any>>>(constructors: T): { [K in keyof T]: ConstructorInstanceType<T[K]> };
31
+ /**
32
+ * @deprecated Use {@link injectAll} instead.
33
+ */
25
34
  declare function resolveAll<const T extends Constructor<any>[]>(constructors: T): { [K in keyof T]: ConstructorInstanceType<T[K]> };
26
35
  declare function resolveAll<T extends Record<string, Constructor<any>>>(constructors: T): { [K in keyof T]: ConstructorInstanceType<T[K]> };
27
36
  /**
28
37
  * Returns a builder for creating a class instance with resolved constructor
29
38
  * parameters from the current {@link withBox} scope. Shorthand for `useBox().for(constructor)`.
39
+ *
40
+ * @deprecated
30
41
  */
31
42
  declare function construct<T extends new (...args: any) => any>(constructor: T): Construct<T>;
32
43
  //#endregion
33
- export { construct, resolve, resolveAll, useBox, withBox };
44
+ export { construct, inject, injectAll, resolve, resolveAll, useBox, withBox };
package/dist/context.mjs CHANGED
@@ -20,19 +20,30 @@ function useBox() {
20
20
  * Resolves a cached instance from the current {@link withBox} scope.
21
21
  * Shorthand for `useBox().get(constructor)`.
22
22
  */
23
- function resolve(constructor) {
23
+ function inject(constructor) {
24
24
  return useBox().get(constructor);
25
25
  }
26
- function resolveAll(constructors) {
26
+ /**
27
+ * @deprecated Use {@link inject} instead.
28
+ */
29
+ function resolve(constructor) {
30
+ return inject(constructor);
31
+ }
32
+ function injectAll(constructors) {
27
33
  return useBox().all.get(constructors);
28
34
  }
35
+ function resolveAll(constructors) {
36
+ return injectAll(constructors);
37
+ }
29
38
  /**
30
39
  * Returns a builder for creating a class instance with resolved constructor
31
40
  * parameters from the current {@link withBox} scope. Shorthand for `useBox().for(constructor)`.
41
+ *
42
+ * @deprecated
32
43
  */
33
44
  function construct(constructor) {
34
45
  return useBox().for(constructor);
35
46
  }
36
47
 
37
48
  //#endregion
38
- export { construct, resolve, resolveAll, useBox, withBox };
49
+ export { construct, inject, injectAll, resolve, resolveAll, useBox, withBox };
package/dist/index.cjs CHANGED
@@ -18,25 +18,37 @@ function factory(init) {
18
18
  }
19
19
  const noCacheSymbol = Symbol("Box.noCache");
20
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}.
21
+ * Creates a {@link Constructor} that computes a value from the box without caching the result.
24
22
  *
25
23
  * @example
26
24
  * ```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
25
+ * class Config {
26
+ * baseUrl = "https://example.com";
27
+ * }
28
+ *
29
+ * const RequestContext = derive((box) => ({
30
+ * baseUrl: box.get(Config).baseUrl,
31
+ * timestamp: Date.now(),
32
+ * }));
33
+ *
34
+ * const ctx1 = box.get(RequestContext);
35
+ * const ctx2 = box.get(RequestContext);
36
+ * console.log(ctx1 === ctx2); // false
31
37
  * ```
32
38
  */
33
- function transient(init) {
39
+ function derive(init) {
34
40
  return {
35
41
  init,
36
42
  [noCacheSymbol]: true
37
43
  };
38
44
  }
39
45
  /**
46
+ * @deprecated Use {@link derive} instead.
47
+ */
48
+ function transient(init) {
49
+ return derive(init);
50
+ }
51
+ /**
40
52
  * Creates a {@link Constructor} that always resolves to the given constant value.
41
53
  * Constant values are never cached since they are already fixed.
42
54
  *
@@ -69,9 +81,7 @@ function constant(value) {
69
81
  *
70
82
  * class UserService {
71
83
  * constructor(private db: Database) {}
72
- * static init(box: Box) {
73
- * return new UserService(box.get(Database));
74
- * }
84
+ * static init = Box.init(UserService).get(Database);
75
85
  * }
76
86
  *
77
87
  * const box = new Box();
@@ -79,14 +89,12 @@ function constant(value) {
79
89
  * const db = box.get(Database);
80
90
  *
81
91
  * console.log(service.db === db); // true (cached)
82
- * console.log(box.new(Database) === db); // false (transient)
83
92
  * ```
84
93
  */
85
94
  var Box = class {
86
95
  cache = /* @__PURE__ */ new Map();
87
96
  /**
88
- * Creates a new (transient) instance without caching. Useful for instances
89
- * that should not be shared.
97
+ * Creates a new instance without caching.
90
98
  */
91
99
  new(constructor) {
92
100
  return "init" in constructor ? constructor.init(this) : new constructor();
@@ -109,7 +117,7 @@ var Box = class {
109
117
  *
110
118
  * Intended to be used inside a class's `static init` method. The instance
111
119
  * returned by the builder is never cached itself, but can be cached when
112
- * the class is retrieved via {@link Box.get} or kept transient via {@link Box.new}.
120
+ * the class is retrieved via {@link Box.get} or new via {@link Box.new}.
113
121
  */
114
122
  for(constructor) {
115
123
  return new Construct(this, constructor);
@@ -150,18 +158,18 @@ var BoxAll = class {
150
158
  constructor(box) {
151
159
  this.box = box;
152
160
  }
153
- get(constructors) {
154
- if (Array.isArray(constructors)) return constructors.map((c) => this.box.get(c));
155
- const result = {};
156
- for (const [key, constructor] of Object.entries(constructors)) result[key] = this.box.get(constructor);
157
- return result;
158
- }
159
161
  new(constructors) {
160
162
  if (Array.isArray(constructors)) return constructors.map((c) => this.box.new(c));
161
163
  const result = {};
162
164
  for (const [key, constructor] of Object.entries(constructors)) result[key] = this.box.new(constructor);
163
165
  return result;
164
166
  }
167
+ get(constructors) {
168
+ if (Array.isArray(constructors)) return constructors.map((c) => this.box.get(c));
169
+ const result = {};
170
+ for (const [key, constructor] of Object.entries(constructors)) result[key] = this.box.get(constructor);
171
+ return result;
172
+ }
165
173
  };
166
174
  /** Builder for creating class instances with constructor dependencies resolved from a {@link Box}. */
167
175
  var Construct = class {
@@ -170,10 +178,10 @@ var Construct = class {
170
178
  this.construct = construct;
171
179
  }
172
180
  /**
173
- * Resolves each dependency as a new transient instance via {@link Box.new},
181
+ * Resolves each dependency as a new instance via {@link Box.new},
174
182
  * meaning dependencies are not cached or shared.
175
183
  *
176
- * The returned instance is cached or transient depending on whether the
184
+ * The returned instance is cached or new depending on whether the
177
185
  * class is retrieved via {@link Box.get} or {@link Box.new}.
178
186
  *
179
187
  * @example
@@ -194,7 +202,7 @@ var Construct = class {
194
202
  * Resolves each dependency as a cached instance via {@link Box.get},
195
203
  * meaning dependencies are shared across the box.
196
204
  *
197
- * The returned instance is cached or transient depending on whether the
205
+ * The returned instance is cached or new depending on whether the
198
206
  * class is retrieved via {@link Box.get} or {@link Box.new}.
199
207
  *
200
208
  * @example
@@ -221,11 +229,11 @@ var StaticConstruct = class {
221
229
  this.construct = construct;
222
230
  }
223
231
  /**
224
- * Resolves each dependency as a new transient instance via {@link Box.new},
232
+ * Resolves each dependency as a new instance via {@link Box.new},
225
233
  * meaning dependencies are not cached or shared.
226
234
  * Returns a function compatible with `static init` that can be assigned directly.
227
235
  *
228
- * The returned instance is cached or transient depending on whether the
236
+ * The returned instance is cached or new depending on whether the
229
237
  * class is retrieved via {@link Box.get} or {@link Box.new}.
230
238
  *
231
239
  * @example
@@ -247,7 +255,7 @@ var StaticConstruct = class {
247
255
  * meaning dependencies are shared across the box.
248
256
  * Returns a function compatible with `static init` that can be assigned directly.
249
257
  *
250
- * The returned instance is cached or transient depending on whether the
258
+ * The returned instance is cached or new depending on whether the
251
259
  * class is retrieved via {@link Box.get} or {@link Box.new}.
252
260
  *
253
261
  * @example
@@ -271,5 +279,6 @@ exports.Box = Box;
271
279
  exports.Construct = Construct;
272
280
  exports.StaticConstruct = StaticConstruct;
273
281
  exports.constant = constant;
282
+ exports.derive = derive;
274
283
  exports.factory = factory;
275
284
  exports.transient = transient;
package/dist/index.d.cts CHANGED
@@ -30,18 +30,28 @@ type ConstructorInstanceType<T> = T extends {
30
30
  */
31
31
  declare function factory<T>(init: (box: Box) => T): Constructor<T>;
32
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}.
33
+ * Creates a {@link Constructor} that computes a value from the box without caching the result.
36
34
  *
37
35
  * @example
38
36
  * ```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
37
+ * class Config {
38
+ * baseUrl = "https://example.com";
39
+ * }
40
+ *
41
+ * const RequestContext = derive((box) => ({
42
+ * baseUrl: box.get(Config).baseUrl,
43
+ * timestamp: Date.now(),
44
+ * }));
45
+ *
46
+ * const ctx1 = box.get(RequestContext);
47
+ * const ctx2 = box.get(RequestContext);
48
+ * console.log(ctx1 === ctx2); // false
43
49
  * ```
44
50
  */
51
+ declare function derive<T>(init: (box: Box) => T): Constructor<T>;
52
+ /**
53
+ * @deprecated Use {@link derive} instead.
54
+ */
45
55
  declare function transient<T>(init: (box: Box) => T): Constructor<T>;
46
56
  /**
47
57
  * Creates a {@link Constructor} that always resolves to the given constant value.
@@ -71,9 +81,7 @@ declare function constant<const T>(value: T): Constructor<T>;
71
81
  *
72
82
  * class UserService {
73
83
  * constructor(private db: Database) {}
74
- * static init(box: Box) {
75
- * return new UserService(box.get(Database));
76
- * }
84
+ * static init = Box.init(UserService).get(Database);
77
85
  * }
78
86
  *
79
87
  * const box = new Box();
@@ -81,14 +89,12 @@ declare function constant<const T>(value: T): Constructor<T>;
81
89
  * const db = box.get(Database);
82
90
  *
83
91
  * console.log(service.db === db); // true (cached)
84
- * console.log(box.new(Database) === db); // false (transient)
85
92
  * ```
86
93
  */
87
94
  declare class Box {
88
- private cache;
95
+ protected cache: Map<Constructor<any>, any>;
89
96
  /**
90
- * Creates a new (transient) instance without caching. Useful for instances
91
- * that should not be shared.
97
+ * Creates a new instance without caching.
92
98
  */
93
99
  new<T extends Constructor<any>>(constructor: T): ConstructorInstanceType<T>;
94
100
  /**
@@ -104,7 +110,7 @@ declare class Box {
104
110
  *
105
111
  * Intended to be used inside a class's `static init` method. The instance
106
112
  * returned by the builder is never cached itself, but can be cached when
107
- * the class is retrieved via {@link Box.get} or kept transient via {@link Box.new}.
113
+ * the class is retrieved via {@link Box.get} or new via {@link Box.new}.
108
114
  */
109
115
  for<T extends ClassConstructor<any>>(constructor: T): Construct<T>;
110
116
  /**
@@ -136,17 +142,17 @@ declare class BoxAll {
136
142
  private box;
137
143
  constructor(box: Box);
138
144
  /**
139
- * Resolves each constructor as a cached instance via {@link Box.get}.
145
+ * Resolves each constructor as a new instance via {@link Box.new}.
140
146
  * Accepts an array or object of constructors and returns instances in the same shape.
141
147
  */
142
- get<const T extends Constructor<any>[]>(constructors: T): { [K in keyof T]: ConstructorInstanceType<T[K]> };
143
- get<T extends Record<string, Constructor<any>>>(constructors: T): { [K in keyof T]: ConstructorInstanceType<T[K]> };
148
+ new<const T extends Constructor<any>[]>(constructors: T): { [K in keyof T]: ConstructorInstanceType<T[K]> };
149
+ new<T extends Record<string, Constructor<any>>>(constructors: T): { [K in keyof T]: ConstructorInstanceType<T[K]> };
144
150
  /**
145
- * Resolves each constructor as a new transient instance via {@link Box.new}.
151
+ * Resolves each constructor as a cached instance via {@link Box.get}.
146
152
  * Accepts an array or object of constructors and returns instances in the same shape.
147
153
  */
148
- new<const T extends Constructor<any>[]>(constructors: T): { [K in keyof T]: ConstructorInstanceType<T[K]> };
149
- new<T extends Record<string, Constructor<any>>>(constructors: T): { [K in keyof T]: ConstructorInstanceType<T[K]> };
154
+ get<const T extends Constructor<any>[]>(constructors: T): { [K in keyof T]: ConstructorInstanceType<T[K]> };
155
+ get<T extends Record<string, Constructor<any>>>(constructors: T): { [K in keyof T]: ConstructorInstanceType<T[K]> };
150
156
  }
151
157
  /** Builder for creating class instances with constructor dependencies resolved from a {@link Box}. */
152
158
  declare class Construct<T extends ClassConstructor<any>> {
@@ -154,10 +160,10 @@ declare class Construct<T extends ClassConstructor<any>> {
154
160
  private construct;
155
161
  constructor(box: Box, construct: T);
156
162
  /**
157
- * Resolves each dependency as a new transient instance via {@link Box.new},
163
+ * Resolves each dependency as a new instance via {@link Box.new},
158
164
  * meaning dependencies are not cached or shared.
159
165
  *
160
- * The returned instance is cached or transient depending on whether the
166
+ * The returned instance is cached or new depending on whether the
161
167
  * class is retrieved via {@link Box.get} or {@link Box.new}.
162
168
  *
163
169
  * @example
@@ -175,7 +181,7 @@ declare class Construct<T extends ClassConstructor<any>> {
175
181
  * Resolves each dependency as a cached instance via {@link Box.get},
176
182
  * meaning dependencies are shared across the box.
177
183
  *
178
- * The returned instance is cached or transient depending on whether the
184
+ * The returned instance is cached or new depending on whether the
179
185
  * class is retrieved via {@link Box.get} or {@link Box.new}.
180
186
  *
181
187
  * @example
@@ -198,11 +204,11 @@ declare class StaticConstruct<T extends ClassConstructor<any>> {
198
204
  private construct;
199
205
  constructor(construct: T);
200
206
  /**
201
- * Resolves each dependency as a new transient instance via {@link Box.new},
207
+ * Resolves each dependency as a new instance via {@link Box.new},
202
208
  * meaning dependencies are not cached or shared.
203
209
  * Returns a function compatible with `static init` that can be assigned directly.
204
210
  *
205
- * The returned instance is cached or transient depending on whether the
211
+ * The returned instance is cached or new depending on whether the
206
212
  * class is retrieved via {@link Box.get} or {@link Box.new}.
207
213
  *
208
214
  * @example
@@ -219,7 +225,7 @@ declare class StaticConstruct<T extends ClassConstructor<any>> {
219
225
  * meaning dependencies are shared across the box.
220
226
  * Returns a function compatible with `static init` that can be assigned directly.
221
227
  *
222
- * The returned instance is cached or transient depending on whether the
228
+ * The returned instance is cached or new depending on whether the
223
229
  * class is retrieved via {@link Box.get} or {@link Box.new}.
224
230
  *
225
231
  * @example
@@ -239,4 +245,4 @@ type ClassConstructor<T> = {
239
245
  /** Maps each constructor parameter to its corresponding {@link Constructor} type. */
240
246
  type ClassConstructorArgs<T extends ClassConstructor<any>, Args = ConstructorParameters<T>> = { [K in keyof Args]: Constructor<Args[K]> };
241
247
  //#endregion
242
- export { Box, Construct, Constructor, ConstructorInstanceType, StaticConstruct, constant, factory, transient };
248
+ export { Box, Construct, Constructor, ConstructorInstanceType, StaticConstruct, constant, derive, factory, transient };
package/dist/index.d.mts CHANGED
@@ -30,18 +30,28 @@ type ConstructorInstanceType<T> = T extends {
30
30
  */
31
31
  declare function factory<T>(init: (box: Box) => T): Constructor<T>;
32
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}.
33
+ * Creates a {@link Constructor} that computes a value from the box without caching the result.
36
34
  *
37
35
  * @example
38
36
  * ```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
37
+ * class Config {
38
+ * baseUrl = "https://example.com";
39
+ * }
40
+ *
41
+ * const RequestContext = derive((box) => ({
42
+ * baseUrl: box.get(Config).baseUrl,
43
+ * timestamp: Date.now(),
44
+ * }));
45
+ *
46
+ * const ctx1 = box.get(RequestContext);
47
+ * const ctx2 = box.get(RequestContext);
48
+ * console.log(ctx1 === ctx2); // false
43
49
  * ```
44
50
  */
51
+ declare function derive<T>(init: (box: Box) => T): Constructor<T>;
52
+ /**
53
+ * @deprecated Use {@link derive} instead.
54
+ */
45
55
  declare function transient<T>(init: (box: Box) => T): Constructor<T>;
46
56
  /**
47
57
  * Creates a {@link Constructor} that always resolves to the given constant value.
@@ -71,9 +81,7 @@ declare function constant<const T>(value: T): Constructor<T>;
71
81
  *
72
82
  * class UserService {
73
83
  * constructor(private db: Database) {}
74
- * static init(box: Box) {
75
- * return new UserService(box.get(Database));
76
- * }
84
+ * static init = Box.init(UserService).get(Database);
77
85
  * }
78
86
  *
79
87
  * const box = new Box();
@@ -81,14 +89,12 @@ declare function constant<const T>(value: T): Constructor<T>;
81
89
  * const db = box.get(Database);
82
90
  *
83
91
  * console.log(service.db === db); // true (cached)
84
- * console.log(box.new(Database) === db); // false (transient)
85
92
  * ```
86
93
  */
87
94
  declare class Box {
88
- private cache;
95
+ protected cache: Map<Constructor<any>, any>;
89
96
  /**
90
- * Creates a new (transient) instance without caching. Useful for instances
91
- * that should not be shared.
97
+ * Creates a new instance without caching.
92
98
  */
93
99
  new<T extends Constructor<any>>(constructor: T): ConstructorInstanceType<T>;
94
100
  /**
@@ -104,7 +110,7 @@ declare class Box {
104
110
  *
105
111
  * Intended to be used inside a class's `static init` method. The instance
106
112
  * returned by the builder is never cached itself, but can be cached when
107
- * the class is retrieved via {@link Box.get} or kept transient via {@link Box.new}.
113
+ * the class is retrieved via {@link Box.get} or new via {@link Box.new}.
108
114
  */
109
115
  for<T extends ClassConstructor<any>>(constructor: T): Construct<T>;
110
116
  /**
@@ -136,17 +142,17 @@ declare class BoxAll {
136
142
  private box;
137
143
  constructor(box: Box);
138
144
  /**
139
- * Resolves each constructor as a cached instance via {@link Box.get}.
145
+ * Resolves each constructor as a new instance via {@link Box.new}.
140
146
  * Accepts an array or object of constructors and returns instances in the same shape.
141
147
  */
142
- get<const T extends Constructor<any>[]>(constructors: T): { [K in keyof T]: ConstructorInstanceType<T[K]> };
143
- get<T extends Record<string, Constructor<any>>>(constructors: T): { [K in keyof T]: ConstructorInstanceType<T[K]> };
148
+ new<const T extends Constructor<any>[]>(constructors: T): { [K in keyof T]: ConstructorInstanceType<T[K]> };
149
+ new<T extends Record<string, Constructor<any>>>(constructors: T): { [K in keyof T]: ConstructorInstanceType<T[K]> };
144
150
  /**
145
- * Resolves each constructor as a new transient instance via {@link Box.new}.
151
+ * Resolves each constructor as a cached instance via {@link Box.get}.
146
152
  * Accepts an array or object of constructors and returns instances in the same shape.
147
153
  */
148
- new<const T extends Constructor<any>[]>(constructors: T): { [K in keyof T]: ConstructorInstanceType<T[K]> };
149
- new<T extends Record<string, Constructor<any>>>(constructors: T): { [K in keyof T]: ConstructorInstanceType<T[K]> };
154
+ get<const T extends Constructor<any>[]>(constructors: T): { [K in keyof T]: ConstructorInstanceType<T[K]> };
155
+ get<T extends Record<string, Constructor<any>>>(constructors: T): { [K in keyof T]: ConstructorInstanceType<T[K]> };
150
156
  }
151
157
  /** Builder for creating class instances with constructor dependencies resolved from a {@link Box}. */
152
158
  declare class Construct<T extends ClassConstructor<any>> {
@@ -154,10 +160,10 @@ declare class Construct<T extends ClassConstructor<any>> {
154
160
  private construct;
155
161
  constructor(box: Box, construct: T);
156
162
  /**
157
- * Resolves each dependency as a new transient instance via {@link Box.new},
163
+ * Resolves each dependency as a new instance via {@link Box.new},
158
164
  * meaning dependencies are not cached or shared.
159
165
  *
160
- * The returned instance is cached or transient depending on whether the
166
+ * The returned instance is cached or new depending on whether the
161
167
  * class is retrieved via {@link Box.get} or {@link Box.new}.
162
168
  *
163
169
  * @example
@@ -175,7 +181,7 @@ declare class Construct<T extends ClassConstructor<any>> {
175
181
  * Resolves each dependency as a cached instance via {@link Box.get},
176
182
  * meaning dependencies are shared across the box.
177
183
  *
178
- * The returned instance is cached or transient depending on whether the
184
+ * The returned instance is cached or new depending on whether the
179
185
  * class is retrieved via {@link Box.get} or {@link Box.new}.
180
186
  *
181
187
  * @example
@@ -198,11 +204,11 @@ declare class StaticConstruct<T extends ClassConstructor<any>> {
198
204
  private construct;
199
205
  constructor(construct: T);
200
206
  /**
201
- * Resolves each dependency as a new transient instance via {@link Box.new},
207
+ * Resolves each dependency as a new instance via {@link Box.new},
202
208
  * meaning dependencies are not cached or shared.
203
209
  * Returns a function compatible with `static init` that can be assigned directly.
204
210
  *
205
- * The returned instance is cached or transient depending on whether the
211
+ * The returned instance is cached or new depending on whether the
206
212
  * class is retrieved via {@link Box.get} or {@link Box.new}.
207
213
  *
208
214
  * @example
@@ -219,7 +225,7 @@ declare class StaticConstruct<T extends ClassConstructor<any>> {
219
225
  * meaning dependencies are shared across the box.
220
226
  * Returns a function compatible with `static init` that can be assigned directly.
221
227
  *
222
- * The returned instance is cached or transient depending on whether the
228
+ * The returned instance is cached or new depending on whether the
223
229
  * class is retrieved via {@link Box.get} or {@link Box.new}.
224
230
  *
225
231
  * @example
@@ -239,4 +245,4 @@ type ClassConstructor<T> = {
239
245
  /** Maps each constructor parameter to its corresponding {@link Constructor} type. */
240
246
  type ClassConstructorArgs<T extends ClassConstructor<any>, Args = ConstructorParameters<T>> = { [K in keyof Args]: Constructor<Args[K]> };
241
247
  //#endregion
242
- export { Box, Construct, Constructor, ConstructorInstanceType, StaticConstruct, constant, factory, transient };
248
+ export { Box, Construct, Constructor, ConstructorInstanceType, StaticConstruct, constant, derive, factory, transient };
package/dist/index.mjs CHANGED
@@ -17,25 +17,37 @@ function factory(init) {
17
17
  }
18
18
  const noCacheSymbol = Symbol("Box.noCache");
19
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}.
20
+ * Creates a {@link Constructor} that computes a value from the box without caching the result.
23
21
  *
24
22
  * @example
25
23
  * ```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
24
+ * class Config {
25
+ * baseUrl = "https://example.com";
26
+ * }
27
+ *
28
+ * const RequestContext = derive((box) => ({
29
+ * baseUrl: box.get(Config).baseUrl,
30
+ * timestamp: Date.now(),
31
+ * }));
32
+ *
33
+ * const ctx1 = box.get(RequestContext);
34
+ * const ctx2 = box.get(RequestContext);
35
+ * console.log(ctx1 === ctx2); // false
30
36
  * ```
31
37
  */
32
- function transient(init) {
38
+ function derive(init) {
33
39
  return {
34
40
  init,
35
41
  [noCacheSymbol]: true
36
42
  };
37
43
  }
38
44
  /**
45
+ * @deprecated Use {@link derive} instead.
46
+ */
47
+ function transient(init) {
48
+ return derive(init);
49
+ }
50
+ /**
39
51
  * Creates a {@link Constructor} that always resolves to the given constant value.
40
52
  * Constant values are never cached since they are already fixed.
41
53
  *
@@ -68,9 +80,7 @@ function constant(value) {
68
80
  *
69
81
  * class UserService {
70
82
  * constructor(private db: Database) {}
71
- * static init(box: Box) {
72
- * return new UserService(box.get(Database));
73
- * }
83
+ * static init = Box.init(UserService).get(Database);
74
84
  * }
75
85
  *
76
86
  * const box = new Box();
@@ -78,14 +88,12 @@ function constant(value) {
78
88
  * const db = box.get(Database);
79
89
  *
80
90
  * console.log(service.db === db); // true (cached)
81
- * console.log(box.new(Database) === db); // false (transient)
82
91
  * ```
83
92
  */
84
93
  var Box = class {
85
94
  cache = /* @__PURE__ */ new Map();
86
95
  /**
87
- * Creates a new (transient) instance without caching. Useful for instances
88
- * that should not be shared.
96
+ * Creates a new instance without caching.
89
97
  */
90
98
  new(constructor) {
91
99
  return "init" in constructor ? constructor.init(this) : new constructor();
@@ -108,7 +116,7 @@ var Box = class {
108
116
  *
109
117
  * Intended to be used inside a class's `static init` method. The instance
110
118
  * returned by the builder is never cached itself, but can be cached when
111
- * the class is retrieved via {@link Box.get} or kept transient via {@link Box.new}.
119
+ * the class is retrieved via {@link Box.get} or new via {@link Box.new}.
112
120
  */
113
121
  for(constructor) {
114
122
  return new Construct(this, constructor);
@@ -149,18 +157,18 @@ var BoxAll = class {
149
157
  constructor(box) {
150
158
  this.box = box;
151
159
  }
152
- get(constructors) {
153
- if (Array.isArray(constructors)) return constructors.map((c) => this.box.get(c));
154
- const result = {};
155
- for (const [key, constructor] of Object.entries(constructors)) result[key] = this.box.get(constructor);
156
- return result;
157
- }
158
160
  new(constructors) {
159
161
  if (Array.isArray(constructors)) return constructors.map((c) => this.box.new(c));
160
162
  const result = {};
161
163
  for (const [key, constructor] of Object.entries(constructors)) result[key] = this.box.new(constructor);
162
164
  return result;
163
165
  }
166
+ get(constructors) {
167
+ if (Array.isArray(constructors)) return constructors.map((c) => this.box.get(c));
168
+ const result = {};
169
+ for (const [key, constructor] of Object.entries(constructors)) result[key] = this.box.get(constructor);
170
+ return result;
171
+ }
164
172
  };
165
173
  /** Builder for creating class instances with constructor dependencies resolved from a {@link Box}. */
166
174
  var Construct = class {
@@ -169,10 +177,10 @@ var Construct = class {
169
177
  this.construct = construct;
170
178
  }
171
179
  /**
172
- * Resolves each dependency as a new transient instance via {@link Box.new},
180
+ * Resolves each dependency as a new instance via {@link Box.new},
173
181
  * meaning dependencies are not cached or shared.
174
182
  *
175
- * The returned instance is cached or transient depending on whether the
183
+ * The returned instance is cached or new depending on whether the
176
184
  * class is retrieved via {@link Box.get} or {@link Box.new}.
177
185
  *
178
186
  * @example
@@ -193,7 +201,7 @@ var Construct = class {
193
201
  * Resolves each dependency as a cached instance via {@link Box.get},
194
202
  * meaning dependencies are shared across the box.
195
203
  *
196
- * The returned instance is cached or transient depending on whether the
204
+ * The returned instance is cached or new depending on whether the
197
205
  * class is retrieved via {@link Box.get} or {@link Box.new}.
198
206
  *
199
207
  * @example
@@ -220,11 +228,11 @@ var StaticConstruct = class {
220
228
  this.construct = construct;
221
229
  }
222
230
  /**
223
- * Resolves each dependency as a new transient instance via {@link Box.new},
231
+ * Resolves each dependency as a new instance via {@link Box.new},
224
232
  * meaning dependencies are not cached or shared.
225
233
  * Returns a function compatible with `static init` that can be assigned directly.
226
234
  *
227
- * The returned instance is cached or transient depending on whether the
235
+ * The returned instance is cached or new depending on whether the
228
236
  * class is retrieved via {@link Box.get} or {@link Box.new}.
229
237
  *
230
238
  * @example
@@ -246,7 +254,7 @@ var StaticConstruct = class {
246
254
  * meaning dependencies are shared across the box.
247
255
  * Returns a function compatible with `static init` that can be assigned directly.
248
256
  *
249
- * The returned instance is cached or transient depending on whether the
257
+ * The returned instance is cached or new depending on whether the
250
258
  * class is retrieved via {@link Box.get} or {@link Box.new}.
251
259
  *
252
260
  * @example
@@ -266,4 +274,4 @@ var StaticConstruct = class {
266
274
  };
267
275
 
268
276
  //#endregion
269
- export { Box, Construct, StaticConstruct, constant, factory, transient };
277
+ export { Box, Construct, StaticConstruct, constant, derive, factory, transient };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "getbox",
3
- "version": "1.3.0",
3
+ "version": "1.4.0",
4
4
  "description": "Lightweight dependency injection for TypeScript",
5
5
  "private": false,
6
6
  "main": "./dist/index.cjs",