getbox 1.4.0 → 2.1.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
@@ -63,15 +63,15 @@ class UserService {
63
63
 
64
64
  ## Resolving multiple dependencies
65
65
 
66
- Use `injectAll` to resolve multiple constructors at once. Accepts an object or array of constructors.
66
+ Pass an array or object of constructors to `inject` to resolve multiple at once.
67
67
 
68
68
  ```ts
69
69
  withBox(() => {
70
70
  // Object form
71
- const { db, logger } = injectAll({ db: Database, logger: LoggerFactory });
71
+ const { db, logger } = inject({ db: Database, logger: LoggerFactory });
72
72
 
73
73
  // Array form
74
- const [db2, logger2] = injectAll([Database, LoggerFactory]);
74
+ const [db2, logger2] = inject([Database, LoggerFactory]);
75
75
 
76
76
  console.log(db === db2); // true (cached)
77
77
  console.log(logger === logger2); // true (cached)
@@ -80,11 +80,11 @@ withBox(() => {
80
80
 
81
81
  ## Accessing the box
82
82
 
83
- Use `useBox()` to get the current box from the scope. This is useful when you need full access to the box API.
83
+ Use `getBox()` to get the current box from the scope. This is useful when you need full access to the box API.
84
84
 
85
85
  ```ts
86
86
  withBox(() => {
87
- const box = useBox();
87
+ const box = getBox();
88
88
  const db = box.new(Database);
89
89
  });
90
90
  ```
package/README.md CHANGED
@@ -14,7 +14,7 @@ npm install getbox
14
14
 
15
15
  ## Usage
16
16
 
17
- `getbox` has a very small API surface. You typically only need `box.get()` and optionally `static init` or the `factory` helper.
17
+ `getbox` has a very small API surface. You typically only need `box.get()` and optionally `Box.init()` or the `factory` helper.
18
18
 
19
19
  For an alternative pattern using AsyncLocalStorage where classes can resolve dependencies directly, see [getbox/context](./CONTEXT.md).
20
20
 
@@ -49,7 +49,7 @@ console.log(office.printer === printer); // true
49
49
 
50
50
  ## Constructors
51
51
 
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.
52
+ Constructors define what the box resolves. `getbox` supports classes, factories, computed values, and constants. Because constructors act as interfaces, the underlying implementation can change without affecting any consumer.
53
53
 
54
54
  ### Classes
55
55
 
@@ -73,33 +73,35 @@ const service = box.get(UserService);
73
73
  service.createUser("Alice");
74
74
  ```
75
75
 
76
- `Box.init` is shorthand for writing the `static init` property yourself.
76
+ Use `Box.fn` to write the initializer manually when you need more control.
77
77
 
78
78
  ```ts
79
79
  class UserService {
80
80
  constructor(private db: Database, private logger: Logger) {}
81
81
 
82
- static init(box: Box) {
82
+ static init = Box.fn((box) => {
83
83
  return new UserService(box.get(Database), box.get(LoggerFactory));
84
- }
84
+ });
85
85
  }
86
86
  ```
87
87
 
88
- Use `box.for()` when you need custom logic alongside dependency resolution.
88
+ If a `static init` initializer is defined, it takes priority over the class constructor.
89
+
90
+ Set `static [boxCache] = false` to opt a class out of caching. The box will call the initializer on every `box.get()` instead of returning a cached instance.
89
91
 
90
92
  ```ts
91
- class UserService {
92
- constructor(private db: Database, private logger: Logger) {}
93
+ import { Box, boxCache } from "getbox";
93
94
 
94
- static init(box: Box) {
95
- const logger = box.get(LoggerFactory);
96
- logger.log("Initializing UserService");
97
- return box.for(UserService).get(Database, LoggerFactory);
98
- }
95
+ class RequestContext {
96
+ timestamp = Date.now();
97
+ static [boxCache] = false;
99
98
  }
100
- ```
101
99
 
102
- If `static init` is defined, it takes priority over the class constructor.
100
+ const box = new Box();
101
+ const ctx1 = box.get(RequestContext);
102
+ const ctx2 = box.get(RequestContext);
103
+ console.log(ctx1 === ctx2); // false
104
+ ```
103
105
 
104
106
  ### Factory functions
105
107
 
@@ -112,13 +114,11 @@ interface Logger {
112
114
  log(message: string): void;
113
115
  }
114
116
 
115
- const LoggerFactory = factory(
116
- (): Logger => ({
117
- log(message: string) {
118
- console.log(`[LOG] ${message}`);
119
- },
120
- }),
121
- );
117
+ const LoggerFactory = factory<Logger>(() => ({
118
+ log(message: string) {
119
+ console.log(`[LOG] ${message}`);
120
+ },
121
+ }));
122
122
 
123
123
  const box = new Box();
124
124
  const logger = box.get(LoggerFactory);
@@ -126,18 +126,18 @@ const logger = box.get(LoggerFactory);
126
126
  logger.log("hello world");
127
127
  ```
128
128
 
129
- ### Derived values
129
+ ### Computed values
130
130
 
131
- Use the `derive` helper to compute a value from the box without caching the result.
131
+ Use the `computed` helper to compute a value from the box without caching the result.
132
132
 
133
133
  ```ts
134
- import { Box, derive } from "getbox";
134
+ import { Box, computed } from "getbox";
135
135
 
136
136
  class Config {
137
137
  baseUrl = "https://example.com";
138
138
  }
139
139
 
140
- const RequestContext = derive((box) => ({
140
+ const RequestContext = computed((box) => ({
141
141
  baseUrl: box.get(Config).baseUrl,
142
142
  timestamp: Date.now(),
143
143
  }));
@@ -152,7 +152,7 @@ console.log(ctx1 === ctx2); // false
152
152
 
153
153
  ### Constants
154
154
 
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.
155
+ Use the `constant` helper to wrap a fixed value as a constructor. Constant values are already fixed and do not need caching.
156
156
 
157
157
  ```ts
158
158
  import { Box, constant } from "getbox";
@@ -195,21 +195,34 @@ const db4 = box.new(Database);
195
195
  console.log(db3 === db4); // false (never cached)
196
196
  ```
197
197
 
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.
198
+ Both `box.get()` and `box.new()` also accept an array or object of constructors to resolve multiple at once.
199
199
 
200
200
  ```ts
201
201
  const box = new Box();
202
202
 
203
203
  // Cached
204
- const { db, logger } = box.all.get({ db: Database, logger: LoggerFactory });
205
- const [db2, logger2] = box.all.get([Database, LoggerFactory]);
204
+ const { db, logger } = box.get({ db: Database, logger: LoggerFactory });
205
+ const [db2, logger2] = box.get([Database, LoggerFactory]);
206
206
 
207
207
  // New instances
208
- const { db3 } = box.all.new({ db3: Database });
209
- const [db4] = box.all.new([Database]);
208
+ const { db3 } = box.new({ db3: Database });
209
+ const [db4] = box.new([Database]);
210
210
  ```
211
211
 
212
- > `box.get()` does not cache `derive` or `constant` values.
212
+ > `box.get()` does not cache `computed` or `constant` values.
213
+
214
+ `Box` itself can be resolved as a dependency. `box.get(Box)` returns the current box instance.
215
+
216
+ ```ts
217
+ class ServiceLocator {
218
+ constructor(private box: Box) {}
219
+ static init = Box.init(ServiceLocator).get(Box);
220
+ }
221
+
222
+ const box = new Box();
223
+ const locator = box.get(ServiceLocator);
224
+ console.log(locator.box === box); // true
225
+ ```
213
226
 
214
227
  ## Mocking
215
228
 
@@ -243,17 +256,21 @@ console.log(mockLogger.messages); // ["Creating user: Alice"]
243
256
 
244
257
  Use `Box.clear` to remove cached instances. Pass a specific constructor to clear a single entry, or omit it to clear all cached instances.
245
258
 
259
+ Returns `true` if an instance was removed, `false` otherwise.
260
+
246
261
  ```ts
247
262
  const box = new Box();
248
263
 
249
264
  const db = box.get(Database);
250
265
 
251
266
  // Clear a specific constructor
252
- Box.clear(box, Database);
267
+ const cleared = Box.clear(box, Database);
268
+ console.log(cleared);
253
269
  console.log(box.get(Database) === db); // false (new instance)
254
270
 
255
271
  // Clear all cached instances
256
- Box.clear(box);
272
+ const clearedAll = Box.clear(box);
273
+ console.log(clearedAll);
257
274
  ```
258
275
 
259
276
  ## Circular dependencies
package/dist/context.cjs CHANGED
@@ -8,48 +8,19 @@ function withBox(boxOrFn, fn) {
8
8
  return storage.run(boxOrFn, fn);
9
9
  }
10
10
  /**
11
- * Returns the current {@link Box} from the active {@link withBox} scope.
12
- * Throws if called outside a scope.
11
+ * Returns the current Box from the active Box scope.
12
+ * Throws if called outside a Box scope.
13
13
  */
14
- function useBox() {
14
+ function getBox() {
15
15
  const box = storage.getStore();
16
- if (!box) throw new Error("useBox() must be called within a withBox() scope");
17
- return box;
16
+ if (box) return box;
17
+ throw new Error("getBox() must be called within a withBox() scope");
18
18
  }
19
- /**
20
- * Resolves a cached instance from the current {@link withBox} scope.
21
- * Shorthand for `useBox().get(constructor)`.
22
- */
23
- function inject(constructor) {
24
- return useBox().get(constructor);
25
- }
26
- /**
27
- * @deprecated Use {@link inject} instead.
28
- */
29
- function resolve(constructor) {
30
- return inject(constructor);
31
- }
32
- function injectAll(constructors) {
33
- return useBox().all.get(constructors);
34
- }
35
- function resolveAll(constructors) {
36
- return injectAll(constructors);
37
- }
38
- /**
39
- * Returns a builder for creating a class instance with resolved constructor
40
- * parameters from the current {@link withBox} scope. Shorthand for `useBox().for(constructor)`.
41
- *
42
- * @deprecated
43
- */
44
- function construct(constructor) {
45
- return useBox().for(constructor);
19
+ function inject(arg) {
20
+ return getBox().get(arg);
46
21
  }
47
22
 
48
23
  //#endregion
49
- exports.construct = construct;
24
+ exports.getBox = getBox;
50
25
  exports.inject = inject;
51
- exports.injectAll = injectAll;
52
- exports.resolve = resolve;
53
- exports.resolveAll = resolveAll;
54
- exports.useBox = useBox;
55
26
  exports.withBox = withBox;
@@ -1,44 +1,27 @@
1
- import { Box, Construct, Constructor, ConstructorInstanceType } from "./index.cjs";
1
+ import { Box, Constructor, ConstructorInstanceType } from "./index.cjs";
2
2
 
3
3
  //#region src/context.d.ts
4
4
 
5
5
  /**
6
- * Runs a function within a scoped {@link Box} context using AsyncLocalStorage.
6
+ * Runs a function within a Box scope using AsyncLocalStorage.
7
7
  * Creates a new Box if none is provided.
8
+ *
9
+ * If the callback function throws an error, the error is thrown by withBox too.
8
10
  */
9
11
  declare function withBox<T>(fn: () => T): T;
10
12
  declare function withBox<T>(box: Box, fn: () => T): T;
11
13
  /**
12
- * Returns the current {@link Box} from the active {@link withBox} scope.
13
- * Throws if called outside a scope.
14
+ * Returns the current Box from the active Box scope.
15
+ * Throws if called outside a Box scope.
14
16
  */
15
- declare function useBox(): Box;
17
+ declare function getBox(): Box;
16
18
  /**
17
- * Resolves a cached instance from the current {@link withBox} scope.
18
- * Shorthand for `useBox().get(constructor)`.
19
+ * Resolves instances from the active Box scope.
20
+ * Accepts a single constructor, an array of constructors, or an object map of constructors.
21
+ * Throws if called outside a Box scope.
19
22
  */
20
23
  declare function inject<T extends Constructor<any>>(constructor: T): ConstructorInstanceType<T>;
21
- /**
22
- * @deprecated Use {@link inject} instead.
23
- */
24
- declare function resolve<T extends Constructor<any>>(constructor: T): ConstructorInstanceType<T>;
25
- /**
26
- * Resolves multiple cached instances from the current {@link withBox} scope.
27
- * Shorthand for `useBox().all.get(constructors)`.
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
- */
34
- declare function resolveAll<const T extends Constructor<any>[]>(constructors: T): { [K in keyof T]: ConstructorInstanceType<T[K]> };
35
- declare function resolveAll<T extends Record<string, Constructor<any>>>(constructors: T): { [K in keyof T]: ConstructorInstanceType<T[K]> };
36
- /**
37
- * Returns a builder for creating a class instance with resolved constructor
38
- * parameters from the current {@link withBox} scope. Shorthand for `useBox().for(constructor)`.
39
- *
40
- * @deprecated
41
- */
42
- declare function construct<T extends new (...args: any) => any>(constructor: T): Construct<T>;
24
+ declare function inject<const T extends Constructor<any>[]>(constructors: T): { [K in keyof T]: ConstructorInstanceType<T[K]> };
25
+ declare function inject<T extends Record<string, Constructor<any>>>(constructors: T): { [K in keyof T]: ConstructorInstanceType<T[K]> };
43
26
  //#endregion
44
- export { construct, inject, injectAll, resolve, resolveAll, useBox, withBox };
27
+ export { getBox, inject, withBox };
@@ -1,44 +1,27 @@
1
- import { Box, Construct, Constructor, ConstructorInstanceType } from "./index.mjs";
1
+ import { Box, Constructor, ConstructorInstanceType } from "./index.mjs";
2
2
 
3
3
  //#region src/context.d.ts
4
4
 
5
5
  /**
6
- * Runs a function within a scoped {@link Box} context using AsyncLocalStorage.
6
+ * Runs a function within a Box scope using AsyncLocalStorage.
7
7
  * Creates a new Box if none is provided.
8
+ *
9
+ * If the callback function throws an error, the error is thrown by withBox too.
8
10
  */
9
11
  declare function withBox<T>(fn: () => T): T;
10
12
  declare function withBox<T>(box: Box, fn: () => T): T;
11
13
  /**
12
- * Returns the current {@link Box} from the active {@link withBox} scope.
13
- * Throws if called outside a scope.
14
+ * Returns the current Box from the active Box scope.
15
+ * Throws if called outside a Box scope.
14
16
  */
15
- declare function useBox(): Box;
17
+ declare function getBox(): Box;
16
18
  /**
17
- * Resolves a cached instance from the current {@link withBox} scope.
18
- * Shorthand for `useBox().get(constructor)`.
19
+ * Resolves instances from the active Box scope.
20
+ * Accepts a single constructor, an array of constructors, or an object map of constructors.
21
+ * Throws if called outside a Box scope.
19
22
  */
20
23
  declare function inject<T extends Constructor<any>>(constructor: T): ConstructorInstanceType<T>;
21
- /**
22
- * @deprecated Use {@link inject} instead.
23
- */
24
- declare function resolve<T extends Constructor<any>>(constructor: T): ConstructorInstanceType<T>;
25
- /**
26
- * Resolves multiple cached instances from the current {@link withBox} scope.
27
- * Shorthand for `useBox().all.get(constructors)`.
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
- */
34
- declare function resolveAll<const T extends Constructor<any>[]>(constructors: T): { [K in keyof T]: ConstructorInstanceType<T[K]> };
35
- declare function resolveAll<T extends Record<string, Constructor<any>>>(constructors: T): { [K in keyof T]: ConstructorInstanceType<T[K]> };
36
- /**
37
- * Returns a builder for creating a class instance with resolved constructor
38
- * parameters from the current {@link withBox} scope. Shorthand for `useBox().for(constructor)`.
39
- *
40
- * @deprecated
41
- */
42
- declare function construct<T extends new (...args: any) => any>(constructor: T): Construct<T>;
24
+ declare function inject<const T extends Constructor<any>[]>(constructors: T): { [K in keyof T]: ConstructorInstanceType<T[K]> };
25
+ declare function inject<T extends Record<string, Constructor<any>>>(constructors: T): { [K in keyof T]: ConstructorInstanceType<T[K]> };
43
26
  //#endregion
44
- export { construct, inject, injectAll, resolve, resolveAll, useBox, withBox };
27
+ export { getBox, inject, withBox };
package/dist/context.mjs CHANGED
@@ -8,42 +8,17 @@ function withBox(boxOrFn, fn) {
8
8
  return storage.run(boxOrFn, fn);
9
9
  }
10
10
  /**
11
- * Returns the current {@link Box} from the active {@link withBox} scope.
12
- * Throws if called outside a scope.
11
+ * Returns the current Box from the active Box scope.
12
+ * Throws if called outside a Box scope.
13
13
  */
14
- function useBox() {
14
+ function getBox() {
15
15
  const box = storage.getStore();
16
- if (!box) throw new Error("useBox() must be called within a withBox() scope");
17
- return box;
16
+ if (box) return box;
17
+ throw new Error("getBox() must be called within a withBox() scope");
18
18
  }
19
- /**
20
- * Resolves a cached instance from the current {@link withBox} scope.
21
- * Shorthand for `useBox().get(constructor)`.
22
- */
23
- function inject(constructor) {
24
- return useBox().get(constructor);
25
- }
26
- /**
27
- * @deprecated Use {@link inject} instead.
28
- */
29
- function resolve(constructor) {
30
- return inject(constructor);
31
- }
32
- function injectAll(constructors) {
33
- return useBox().all.get(constructors);
34
- }
35
- function resolveAll(constructors) {
36
- return injectAll(constructors);
37
- }
38
- /**
39
- * Returns a builder for creating a class instance with resolved constructor
40
- * parameters from the current {@link withBox} scope. Shorthand for `useBox().for(constructor)`.
41
- *
42
- * @deprecated
43
- */
44
- function construct(constructor) {
45
- return useBox().for(constructor);
19
+ function inject(arg) {
20
+ return getBox().get(arg);
46
21
  }
47
22
 
48
23
  //#endregion
49
- export { construct, inject, injectAll, resolve, resolveAll, useBox, withBox };
24
+ export { getBox, inject, withBox };