getbox 1.4.0 → 2.0.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 +5 -5
- package/README.md +24 -36
- package/dist/context.cjs +8 -37
- package/dist/context.d.cts +13 -30
- package/dist/context.d.mts +13 -30
- package/dist/context.mjs +8 -33
- package/dist/index.cjs +55 -133
- package/dist/index.d.cts +23 -90
- package/dist/index.d.mts +23 -90
- package/dist/index.mjs +53 -129
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
//#region src/index.ts
|
|
2
|
+
const cacheSymbol = Symbol("Box.cache");
|
|
3
|
+
const isClass = (fn) => fn.prototype !== void 0 && Function.prototype.toString.call(fn).startsWith("class");
|
|
2
4
|
/**
|
|
3
5
|
* Creates a {@link Constructor} from a factory function.
|
|
4
6
|
* The factory receives the box as an argument, allowing it to resolve other dependencies.
|
|
@@ -13,9 +15,11 @@
|
|
|
13
15
|
* ```
|
|
14
16
|
*/
|
|
15
17
|
function factory(init) {
|
|
16
|
-
return {
|
|
18
|
+
return {
|
|
19
|
+
[cacheSymbol]: true,
|
|
20
|
+
init
|
|
21
|
+
};
|
|
17
22
|
}
|
|
18
|
-
const noCacheSymbol = Symbol("Box.noCache");
|
|
19
23
|
/**
|
|
20
24
|
* Creates a {@link Constructor} that computes a value from the box without caching the result.
|
|
21
25
|
*
|
|
@@ -25,7 +29,7 @@ const noCacheSymbol = Symbol("Box.noCache");
|
|
|
25
29
|
* baseUrl = "https://example.com";
|
|
26
30
|
* }
|
|
27
31
|
*
|
|
28
|
-
* const RequestContext =
|
|
32
|
+
* const RequestContext = computed((box) => ({
|
|
29
33
|
* baseUrl: box.get(Config).baseUrl,
|
|
30
34
|
* timestamp: Date.now(),
|
|
31
35
|
* }));
|
|
@@ -35,21 +39,12 @@ const noCacheSymbol = Symbol("Box.noCache");
|
|
|
35
39
|
* console.log(ctx1 === ctx2); // false
|
|
36
40
|
* ```
|
|
37
41
|
*/
|
|
38
|
-
function
|
|
39
|
-
return {
|
|
40
|
-
init,
|
|
41
|
-
[noCacheSymbol]: true
|
|
42
|
-
};
|
|
43
|
-
}
|
|
44
|
-
/**
|
|
45
|
-
* @deprecated Use {@link derive} instead.
|
|
46
|
-
*/
|
|
47
|
-
function transient(init) {
|
|
48
|
-
return derive(init);
|
|
42
|
+
function computed(init) {
|
|
43
|
+
return { init };
|
|
49
44
|
}
|
|
50
45
|
/**
|
|
51
46
|
* Creates a {@link Constructor} that always resolves to the given constant value.
|
|
52
|
-
* Constant values are
|
|
47
|
+
* Constant values are already fixed and do not need caching.
|
|
53
48
|
*
|
|
54
49
|
* @example
|
|
55
50
|
* ```ts
|
|
@@ -58,19 +53,15 @@ function transient(init) {
|
|
|
58
53
|
* ```
|
|
59
54
|
*/
|
|
60
55
|
function constant(value) {
|
|
61
|
-
return {
|
|
62
|
-
init: () => value,
|
|
63
|
-
[noCacheSymbol]: true
|
|
64
|
-
};
|
|
56
|
+
return { init: () => value };
|
|
65
57
|
}
|
|
66
58
|
/**
|
|
67
59
|
* Dependency injection container that resolves and caches instances from
|
|
68
60
|
* a {@link Constructor}.
|
|
69
61
|
*
|
|
70
|
-
* A constructor is
|
|
71
|
-
*
|
|
72
|
-
*
|
|
73
|
-
* create constructors from functions and values respectively.
|
|
62
|
+
* A constructor is a class with a `static init` function, a class with a
|
|
63
|
+
* no-argument constructor, or a function-based constructor created by
|
|
64
|
+
* {@link factory}, {@link computed}, or {@link constant}.
|
|
74
65
|
*
|
|
75
66
|
* @example
|
|
76
67
|
* ```ts
|
|
@@ -92,38 +83,34 @@ function constant(value) {
|
|
|
92
83
|
*/
|
|
93
84
|
var Box = class {
|
|
94
85
|
cache = /* @__PURE__ */ new Map();
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
* Resolves an instance from the cache, or creates and caches a new one.
|
|
103
|
-
* Subsequent calls with the same constructor return the cached instance.
|
|
104
|
-
*/
|
|
105
|
-
get(constructor) {
|
|
106
|
-
if (this.cache.has(constructor)) return this.cache.get(constructor);
|
|
107
|
-
const value = this.new(constructor);
|
|
108
|
-
if (!(noCacheSymbol in constructor && constructor[noCacheSymbol])) this.cache.set(constructor, value);
|
|
109
|
-
return value;
|
|
86
|
+
new(arg) {
|
|
87
|
+
if (Array.isArray(arg)) return arg.map((c) => this.new(c));
|
|
88
|
+
if (typeof arg === "function") return "init" in arg ? arg.init(this) : new arg();
|
|
89
|
+
if ("init" in arg && !isClass(arg.init)) return arg.init(this);
|
|
90
|
+
const result = {};
|
|
91
|
+
for (const [key, constructor] of Object.entries(arg)) result[key] = this.new(constructor);
|
|
92
|
+
return result;
|
|
110
93
|
}
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
94
|
+
get(arg) {
|
|
95
|
+
if (Array.isArray(arg)) return arg.map((c) => this.get(c));
|
|
96
|
+
if (typeof arg === "function") {
|
|
97
|
+
if (this.cache.has(arg)) return this.cache.get(arg);
|
|
98
|
+
const value = "init" in arg ? arg.init(this) : new arg();
|
|
99
|
+
this.cache.set(arg, value);
|
|
100
|
+
return value;
|
|
101
|
+
}
|
|
102
|
+
if ("init" in arg && !isClass(arg.init)) {
|
|
103
|
+
if (this.cache.has(arg)) return this.cache.get(arg);
|
|
104
|
+
const value = arg.init(this);
|
|
105
|
+
if (cacheSymbol in arg) this.cache.set(arg, value);
|
|
106
|
+
return value;
|
|
107
|
+
}
|
|
108
|
+
const result = {};
|
|
109
|
+
for (const [key, constructor] of Object.entries(arg)) result[key] = this.get(constructor);
|
|
110
|
+
return result;
|
|
123
111
|
}
|
|
124
112
|
/**
|
|
125
|
-
* Returns a
|
|
126
|
-
* The result can be assigned directly to `static init`.
|
|
113
|
+
* Returns a `static init` function builder.
|
|
127
114
|
*
|
|
128
115
|
* @example
|
|
129
116
|
* ```ts
|
|
@@ -134,7 +121,7 @@ var Box = class {
|
|
|
134
121
|
* ```
|
|
135
122
|
*/
|
|
136
123
|
static init(constructor) {
|
|
137
|
-
return new
|
|
124
|
+
return new StaticInit(constructor);
|
|
138
125
|
}
|
|
139
126
|
/**
|
|
140
127
|
* Registers a mock value in the box's cache for a given constructor.
|
|
@@ -146,84 +133,23 @@ var Box = class {
|
|
|
146
133
|
/**
|
|
147
134
|
* Removes the instance from the box's cache for a given constructor.
|
|
148
135
|
* Removes all instances if no constructor is provided.
|
|
149
|
-
*/
|
|
150
|
-
static clear(box, constructor) {
|
|
151
|
-
if (!constructor) return box.cache.clear();
|
|
152
|
-
box.cache.delete(constructor);
|
|
153
|
-
}
|
|
154
|
-
};
|
|
155
|
-
/** Resolves multiple constructors at once from a {@link Box}. */
|
|
156
|
-
var BoxAll = class {
|
|
157
|
-
constructor(box) {
|
|
158
|
-
this.box = box;
|
|
159
|
-
}
|
|
160
|
-
new(constructors) {
|
|
161
|
-
if (Array.isArray(constructors)) return constructors.map((c) => this.box.new(c));
|
|
162
|
-
const result = {};
|
|
163
|
-
for (const [key, constructor] of Object.entries(constructors)) result[key] = this.box.new(constructor);
|
|
164
|
-
return result;
|
|
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
|
-
}
|
|
172
|
-
};
|
|
173
|
-
/** Builder for creating class instances with constructor dependencies resolved from a {@link Box}. */
|
|
174
|
-
var Construct = class {
|
|
175
|
-
constructor(box, construct) {
|
|
176
|
-
this.box = box;
|
|
177
|
-
this.construct = construct;
|
|
178
|
-
}
|
|
179
|
-
/**
|
|
180
|
-
* Resolves each dependency as a new instance via {@link Box.new},
|
|
181
|
-
* meaning dependencies are not cached or shared.
|
|
182
|
-
*
|
|
183
|
-
* The returned instance is cached or new depending on whether the
|
|
184
|
-
* class is retrieved via {@link Box.get} or {@link Box.new}.
|
|
185
|
-
*
|
|
186
|
-
* @example
|
|
187
|
-
* ```ts
|
|
188
|
-
* class UserService {
|
|
189
|
-
* constructor(private db: Database, private logger: Logger) {}
|
|
190
|
-
* static init(box: Box) {
|
|
191
|
-
* return box.for(UserService).new(Database, LoggerFactory);
|
|
192
|
-
* }
|
|
193
|
-
* }
|
|
194
|
-
* ```
|
|
195
|
-
*/
|
|
196
|
-
new(...args) {
|
|
197
|
-
const instances = args.map((arg) => this.box.new(arg));
|
|
198
|
-
return new this.construct(...instances);
|
|
199
|
-
}
|
|
200
|
-
/**
|
|
201
|
-
* Resolves each dependency as a cached instance via {@link Box.get},
|
|
202
|
-
* meaning dependencies are shared across the box.
|
|
203
136
|
*
|
|
204
|
-
*
|
|
205
|
-
* class is retrieved via {@link Box.get} or {@link Box.new}.
|
|
206
|
-
*
|
|
207
|
-
* @example
|
|
208
|
-
* ```ts
|
|
209
|
-
* class UserService {
|
|
210
|
-
* constructor(private db: Database, private logger: Logger) {}
|
|
211
|
-
* static init(box: Box) {
|
|
212
|
-
* return box.for(UserService).get(Database, LoggerFactory);
|
|
213
|
-
* }
|
|
214
|
-
* }
|
|
215
|
-
* ```
|
|
137
|
+
* Returns true if an instance existed and has been removed from the box's cache.
|
|
216
138
|
*/
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
139
|
+
static clear(box, constructor) {
|
|
140
|
+
if (!constructor) {
|
|
141
|
+
const size = box.cache.size;
|
|
142
|
+
box.cache.clear();
|
|
143
|
+
return size > 0;
|
|
144
|
+
}
|
|
145
|
+
return box.cache.delete(constructor);
|
|
220
146
|
}
|
|
221
147
|
};
|
|
222
148
|
/**
|
|
223
149
|
* Builder for creating a `static init` function with constructor dependencies
|
|
224
150
|
* resolved from a {@link Box}.
|
|
225
151
|
*/
|
|
226
|
-
var
|
|
152
|
+
var StaticInit = class {
|
|
227
153
|
constructor(construct) {
|
|
228
154
|
this.construct = construct;
|
|
229
155
|
}
|
|
@@ -239,14 +165,13 @@ var StaticConstruct = class {
|
|
|
239
165
|
* ```ts
|
|
240
166
|
* class UserService {
|
|
241
167
|
* constructor(private db: Database, private logger: Logger) {}
|
|
242
|
-
* static init = Box.init(UserService).
|
|
168
|
+
* static init = Box.init(UserService).new(Database, LoggerFactory);
|
|
243
169
|
* }
|
|
244
170
|
* ```
|
|
245
171
|
*/
|
|
246
172
|
new(...args) {
|
|
247
173
|
return (box) => {
|
|
248
|
-
|
|
249
|
-
return new this.construct(...instances);
|
|
174
|
+
return new this.construct(...box.new(args));
|
|
250
175
|
};
|
|
251
176
|
}
|
|
252
177
|
/**
|
|
@@ -267,11 +192,10 @@ var StaticConstruct = class {
|
|
|
267
192
|
*/
|
|
268
193
|
get(...args) {
|
|
269
194
|
return (box) => {
|
|
270
|
-
|
|
271
|
-
return new this.construct(...instances);
|
|
195
|
+
return new this.construct(...box.get(args));
|
|
272
196
|
};
|
|
273
197
|
}
|
|
274
198
|
};
|
|
275
199
|
|
|
276
200
|
//#endregion
|
|
277
|
-
export { Box,
|
|
201
|
+
export { Box, StaticInit, computed, constant, factory };
|