@joist/di 4.2.3-next.9 → 4.2.4-next.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/README.md +85 -34
- package/package.json +1 -1
- package/src/lib/dom/injectable-el.ts +4 -2
- package/src/lib/lifecycle.test.ts +165 -1
- package/src/lib/lifecycle.ts +30 -13
- package/src/lib/metadata.ts +12 -7
- package/target/lib/dom/injectable-el.d.ts +3 -2
- package/target/lib/dom/injectable-el.js.map +1 -1
- package/target/lib/lifecycle.d.ts +4 -4
- package/target/lib/lifecycle.js +19 -7
- package/target/lib/lifecycle.js.map +1 -1
- package/target/lib/lifecycle.test.js +239 -0
- package/target/lib/lifecycle.test.js.map +1 -1
- package/target/lib/metadata.d.ts +14 -4
- package/target/lib/metadata.js.map +1 -1
package/README.md
CHANGED
|
@@ -38,6 +38,7 @@ npm i @joist/di
|
|
|
38
38
|
## Injectors
|
|
39
39
|
|
|
40
40
|
Injectors are the core of the dependency injection system. They:
|
|
41
|
+
|
|
41
42
|
- Create and manage service instances
|
|
42
43
|
- Handle dependency resolution
|
|
43
44
|
- Maintain a hierarchy of injectors
|
|
@@ -103,7 +104,7 @@ class ApiService {
|
|
|
103
104
|
|
|
104
105
|
getData() {
|
|
105
106
|
return this.#http()
|
|
106
|
-
.fetch(
|
|
107
|
+
.fetch("/api/v1/users")
|
|
107
108
|
.then((res) => res.json());
|
|
108
109
|
}
|
|
109
110
|
}
|
|
@@ -111,22 +112,22 @@ class ApiService {
|
|
|
111
112
|
|
|
112
113
|
```ts
|
|
113
114
|
// services.test.ts
|
|
114
|
-
test(
|
|
115
|
+
test("should return json", async () => {
|
|
115
116
|
class MockHttpService extends HttpService {
|
|
116
117
|
async fetch() {
|
|
117
|
-
return Response.json({ fname:
|
|
118
|
+
return Response.json({ fname: "Danny", lname: "Blue" });
|
|
118
119
|
}
|
|
119
120
|
}
|
|
120
121
|
|
|
121
122
|
const app = new Injector({
|
|
122
|
-
providers: [[HttpService, { use: MockHttpService }]]
|
|
123
|
+
providers: [[HttpService, { use: MockHttpService }]],
|
|
123
124
|
});
|
|
124
125
|
const api = app.inject(ApiService);
|
|
125
126
|
|
|
126
127
|
const res = await api.getData();
|
|
127
128
|
|
|
128
|
-
assert.equals(res.fname,
|
|
129
|
-
assert.equals(res.lname,
|
|
129
|
+
assert.equals(res.fname, "Danny");
|
|
130
|
+
assert.equals(res.lname, "Blue");
|
|
130
131
|
});
|
|
131
132
|
```
|
|
132
133
|
|
|
@@ -148,7 +149,7 @@ class ConsoleLogger implements Logger {
|
|
|
148
149
|
}
|
|
149
150
|
|
|
150
151
|
@injectable({
|
|
151
|
-
providers: [[Logger, { use: ConsoleLogger }]]
|
|
152
|
+
providers: [[Logger, { use: ConsoleLogger }]],
|
|
152
153
|
})
|
|
153
154
|
class MyService {}
|
|
154
155
|
```
|
|
@@ -168,13 +169,13 @@ const app = new Injector([
|
|
|
168
169
|
factory() {
|
|
169
170
|
const params = new URLSearchParams(window.location.search);
|
|
170
171
|
|
|
171
|
-
if (params.has(
|
|
172
|
+
if (params.has("debug")) {
|
|
172
173
|
return console;
|
|
173
174
|
}
|
|
174
175
|
|
|
175
176
|
return new Logger(); // noop logger
|
|
176
|
-
}
|
|
177
|
-
}
|
|
177
|
+
},
|
|
178
|
+
},
|
|
178
179
|
]);
|
|
179
180
|
```
|
|
180
181
|
|
|
@@ -204,9 +205,9 @@ const app = new Injector([
|
|
|
204
205
|
factory(i) {
|
|
205
206
|
const logger = i.inject(Logger);
|
|
206
207
|
return new Feature(logger);
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
]
|
|
208
|
+
},
|
|
209
|
+
},
|
|
210
|
+
],
|
|
210
211
|
]);
|
|
211
212
|
```
|
|
212
213
|
|
|
@@ -216,15 +217,15 @@ In most cases, a token is any constructable class. There are cases where you mig
|
|
|
216
217
|
|
|
217
218
|
```ts
|
|
218
219
|
// Token that resolves to a string
|
|
219
|
-
const URL_TOKEN = new StaticToken<string>(
|
|
220
|
+
const URL_TOKEN = new StaticToken<string>("app_url");
|
|
220
221
|
|
|
221
222
|
const app = new Injector([
|
|
222
223
|
[
|
|
223
224
|
URL_TOKEN,
|
|
224
225
|
{
|
|
225
|
-
factory: () =>
|
|
226
|
-
}
|
|
227
|
-
]
|
|
226
|
+
factory: () => "/my-app-url/",
|
|
227
|
+
},
|
|
228
|
+
],
|
|
228
229
|
]);
|
|
229
230
|
```
|
|
230
231
|
|
|
@@ -233,7 +234,7 @@ const app = new Injector([
|
|
|
233
234
|
A static token can be provided a default factory function to use on creation.
|
|
234
235
|
|
|
235
236
|
```ts
|
|
236
|
-
const URL_TOKEN = new StaticToken(
|
|
237
|
+
const URL_TOKEN = new StaticToken("app_url", () => "/default-url/");
|
|
237
238
|
```
|
|
238
239
|
|
|
239
240
|
### Async Values
|
|
@@ -242,7 +243,7 @@ Static tokens can also leverage promises for cases when you need to asynchronous
|
|
|
242
243
|
|
|
243
244
|
```ts
|
|
244
245
|
// StaticToken<Promise<string>>
|
|
245
|
-
const URL_TOKEN = new StaticToken(
|
|
246
|
+
const URL_TOKEN = new StaticToken("app_url", async () => "/default-url/");
|
|
246
247
|
|
|
247
248
|
const app = new Injector();
|
|
248
249
|
|
|
@@ -252,8 +253,8 @@ const url: string = await app.inject(URL_TOKEN);
|
|
|
252
253
|
This allows you to dynamically import services:
|
|
253
254
|
|
|
254
255
|
```ts
|
|
255
|
-
const HttpService = new StaticToken(
|
|
256
|
-
return import(
|
|
256
|
+
const HttpService = new StaticToken("HTTP_SERVICE", () => {
|
|
257
|
+
return import("./http.service.js").then((m) => new m.HttpService());
|
|
257
258
|
});
|
|
258
259
|
|
|
259
260
|
class HackerNewsService {
|
|
@@ -262,9 +263,9 @@ class HackerNewsService {
|
|
|
262
263
|
async getData() {
|
|
263
264
|
const http = await this.#http();
|
|
264
265
|
|
|
265
|
-
const url = new URL(
|
|
266
|
-
url.searchParams.set(
|
|
267
|
-
url.searchParams.set(
|
|
266
|
+
const url = new URL("https://hacker-news.firebaseio.com/v0/beststories.json");
|
|
267
|
+
url.searchParams.set("limitToFirst", count.toString());
|
|
268
|
+
url.searchParams.set("orderBy", '"$key"');
|
|
268
269
|
|
|
269
270
|
return http.fetchJson<string[]>(url);
|
|
270
271
|
}
|
|
@@ -289,6 +290,56 @@ class MyService {
|
|
|
289
290
|
}
|
|
290
291
|
```
|
|
291
292
|
|
|
293
|
+
### Conditional Lifecycle Hooks
|
|
294
|
+
|
|
295
|
+
You can control when lifecycle callbacks are executed by providing a condition function. The condition function receives the current injector:
|
|
296
|
+
|
|
297
|
+
```ts
|
|
298
|
+
class MyService {
|
|
299
|
+
@created((injector) => ({ enabled: true }))
|
|
300
|
+
onCreated() {
|
|
301
|
+
// This will execute because enabled is true
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
@injected((injector) => {
|
|
305
|
+
return {
|
|
306
|
+
enabled: process.env.NODE_ENV === "development",
|
|
307
|
+
};
|
|
308
|
+
})
|
|
309
|
+
onInjected() {
|
|
310
|
+
// will only execute when NODE_ENV is development
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
The condition function can return an object with an `enabled` property that determines whether the callback should execute:
|
|
316
|
+
|
|
317
|
+
- `{ enabled: true }` - The callback will execute
|
|
318
|
+
- `{ enabled: false }` - The callback will not execute
|
|
319
|
+
- `{}` - The callback will execute (default behavior)
|
|
320
|
+
|
|
321
|
+
You can use the injector to access other services or check the injector's configuration:
|
|
322
|
+
|
|
323
|
+
```ts
|
|
324
|
+
class MyService {
|
|
325
|
+
@created((injector) => {
|
|
326
|
+
const config = injector.inject(ConfigService);
|
|
327
|
+
return { enabled: config.featureEnabled };
|
|
328
|
+
})
|
|
329
|
+
onCreated() {
|
|
330
|
+
// Only executes if feature is enabled in config
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
Lifecycle conditions are useful when you need to:
|
|
336
|
+
|
|
337
|
+
- Execute callbacks only in specific environments
|
|
338
|
+
- Control callback execution based on injector state
|
|
339
|
+
- Implement feature flags for lifecycle hooks
|
|
340
|
+
- Conditionally initialize services based on configuration
|
|
341
|
+
- Make decisions based on other services in the injector
|
|
342
|
+
|
|
292
343
|
## Hierarchical Injectors
|
|
293
344
|
|
|
294
345
|
Injectors can be defined with a parent. The top-most parent will (by default) be where services are constructed and cached. Only if manually defined providers are found earlier in the chain will services be constructed lower. The injector resolution algorithm behaves as follows:
|
|
@@ -331,8 +382,8 @@ const app = new DOMInjector();
|
|
|
331
382
|
app.attach(document.body); // Anything rendered in the body will have access to this injector.
|
|
332
383
|
|
|
333
384
|
class Colors {
|
|
334
|
-
primary =
|
|
335
|
-
secondary =
|
|
385
|
+
primary = "red";
|
|
386
|
+
secondary = "green";
|
|
336
387
|
}
|
|
337
388
|
|
|
338
389
|
@injectable()
|
|
@@ -345,12 +396,12 @@ class MyElement extends HTMLElement {
|
|
|
345
396
|
}
|
|
346
397
|
}
|
|
347
398
|
|
|
348
|
-
customElements.define(
|
|
399
|
+
customElements.define("my-element", MyElement);
|
|
349
400
|
```
|
|
350
401
|
|
|
351
402
|
### Context Elements
|
|
352
403
|
|
|
353
|
-
Context elements are where Hierarchical Injectors can really shine as they allow you to define React/Preact-esque "context" elements.
|
|
404
|
+
Context elements are where Hierarchical Injectors can really shine as they allow you to define React/Preact-esque "context" elements.
|
|
354
405
|
Since custom elements are treated the same as any other class, they can define providers for their local scope. The `provideSelfAs` property will provide the current class for the tokens given.
|
|
355
406
|
This also makes it easy to use attributes to define values for the service.
|
|
356
407
|
|
|
@@ -361,16 +412,16 @@ class ColorCtx {
|
|
|
361
412
|
}
|
|
362
413
|
|
|
363
414
|
@injectable({
|
|
364
|
-
name:
|
|
365
|
-
provideSelfAs: [ColorCtx]
|
|
415
|
+
name: "color-ctx",
|
|
416
|
+
provideSelfAs: [ColorCtx],
|
|
366
417
|
})
|
|
367
418
|
class ColorCtx extends HTMLElement implements ColorCtx {
|
|
368
419
|
get primary() {
|
|
369
|
-
return this.getAttribute("primary") ?? "red"
|
|
420
|
+
return this.getAttribute("primary") ?? "red";
|
|
370
421
|
}
|
|
371
422
|
|
|
372
423
|
get secondary() {
|
|
373
|
-
return this.getAttribute("secondary") ?? "green"
|
|
424
|
+
return this.getAttribute("secondary") ?? "green";
|
|
374
425
|
}
|
|
375
426
|
}
|
|
376
427
|
|
|
@@ -385,8 +436,8 @@ class MyElement extends HTMLElement {
|
|
|
385
436
|
}
|
|
386
437
|
|
|
387
438
|
// Note: To use parent providers, the parent elements need to be defined first!
|
|
388
|
-
customElements.define(
|
|
389
|
-
customElements.define(
|
|
439
|
+
customElements.define("color-ctx", ColorCtx);
|
|
440
|
+
customElements.define("my-element", MyElement);
|
|
390
441
|
```
|
|
391
442
|
|
|
392
443
|
```html
|
package/package.json
CHANGED
|
@@ -6,10 +6,12 @@ import { callLifecycle } from "../lifecycle.js";
|
|
|
6
6
|
import type { InjectableMetadata } from "../metadata.js";
|
|
7
7
|
import type { ConstructableToken } from "../provider.js";
|
|
8
8
|
|
|
9
|
+
export type InjectableEl = HTMLElement & { [INJECTOR]: Injector };
|
|
10
|
+
|
|
9
11
|
export function injectableEl<
|
|
10
|
-
T extends ConstructableToken<
|
|
12
|
+
T extends ConstructableToken<InjectableEl>,
|
|
11
13
|
>(Base: T, ctx: ClassDecoratorContext): T {
|
|
12
|
-
const metadata: InjectableMetadata = ctx.metadata;
|
|
14
|
+
const metadata: InjectableMetadata<InjectableEl> = ctx.metadata;
|
|
13
15
|
|
|
14
16
|
const def = {
|
|
15
17
|
[Base.name]: class extends Base {
|
|
@@ -4,7 +4,8 @@ import { inject } from "./inject.js";
|
|
|
4
4
|
import { injectable } from "./injectable.js";
|
|
5
5
|
import { Injector } from "./injector.js";
|
|
6
6
|
import { created, injected } from "./lifecycle.js";
|
|
7
|
-
import { readInjector } from "./metadata.js";
|
|
7
|
+
import { LifecycleCallback, readInjector } from "./metadata.js";
|
|
8
|
+
import { StaticToken } from "./provider.js";
|
|
8
9
|
|
|
9
10
|
it("should call onInit and onInject when a service is first created", () => {
|
|
10
11
|
const i = new Injector();
|
|
@@ -128,3 +129,166 @@ it("should call onInject and on init when injected from another service", () =>
|
|
|
128
129
|
onInjected: 2,
|
|
129
130
|
});
|
|
130
131
|
});
|
|
132
|
+
|
|
133
|
+
it("should respect enabled=false condition in lifecycle callbacks", () => {
|
|
134
|
+
const i = new Injector();
|
|
135
|
+
|
|
136
|
+
@injectable()
|
|
137
|
+
class MyService {
|
|
138
|
+
res = {
|
|
139
|
+
onCreated: 0,
|
|
140
|
+
onInjected: 0,
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
@created(() => ({ enabled: false }))
|
|
144
|
+
onCreated() {
|
|
145
|
+
this.res.onCreated++;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
@injected(() => ({ enabled: false }))
|
|
149
|
+
onInjected() {
|
|
150
|
+
this.res.onInjected++;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
const service = i.inject(MyService);
|
|
155
|
+
|
|
156
|
+
assert.deepEqual(service.res, {
|
|
157
|
+
onCreated: 0,
|
|
158
|
+
onInjected: 0,
|
|
159
|
+
});
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
it("should respect enabled=true condition in lifecycle callbacks", () => {
|
|
163
|
+
const i = new Injector();
|
|
164
|
+
|
|
165
|
+
@injectable()
|
|
166
|
+
class MyService {
|
|
167
|
+
res = {
|
|
168
|
+
onCreated: 0,
|
|
169
|
+
onInjected: 0,
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
@created(() => ({ enabled: true }))
|
|
173
|
+
onCreated() {
|
|
174
|
+
this.res.onCreated++;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
@injected(() => ({ enabled: true }))
|
|
178
|
+
onInjected() {
|
|
179
|
+
this.res.onInjected++;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
const service = i.inject(MyService);
|
|
184
|
+
|
|
185
|
+
assert.deepEqual(service.res, {
|
|
186
|
+
onCreated: 1,
|
|
187
|
+
onInjected: 1,
|
|
188
|
+
});
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
it("should execute callbacks when condition returns undefined enabled", () => {
|
|
192
|
+
const i = new Injector();
|
|
193
|
+
|
|
194
|
+
@injectable()
|
|
195
|
+
class MyService {
|
|
196
|
+
res = {
|
|
197
|
+
onCreated: 0,
|
|
198
|
+
onInjected: 0,
|
|
199
|
+
};
|
|
200
|
+
|
|
201
|
+
@created(() => ({ enabled: undefined }))
|
|
202
|
+
onCreated() {
|
|
203
|
+
this.res.onCreated++;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
@injected(() => ({ enabled: undefined }))
|
|
207
|
+
onInjected() {
|
|
208
|
+
this.res.onInjected++;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
const service = i.inject(MyService);
|
|
213
|
+
|
|
214
|
+
assert.deepEqual(service.res, {
|
|
215
|
+
onCreated: 1,
|
|
216
|
+
onInjected: 1,
|
|
217
|
+
});
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
it("should execute callbacks when condition returns empty object", () => {
|
|
221
|
+
const i = new Injector();
|
|
222
|
+
|
|
223
|
+
@injectable()
|
|
224
|
+
class MyService {
|
|
225
|
+
res = {
|
|
226
|
+
onCreated: 0,
|
|
227
|
+
onInjected: 0,
|
|
228
|
+
};
|
|
229
|
+
|
|
230
|
+
@created(() => ({}))
|
|
231
|
+
onCreated() {
|
|
232
|
+
this.res.onCreated++;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
@injected(() => ({}))
|
|
236
|
+
onInjected() {
|
|
237
|
+
this.res.onInjected++;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
const service = i.inject(MyService);
|
|
242
|
+
|
|
243
|
+
assert.deepEqual(service.res, {
|
|
244
|
+
onCreated: 1,
|
|
245
|
+
onInjected: 1,
|
|
246
|
+
});
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
it("should pass the injector to the condition", () => {
|
|
251
|
+
const IS_PROD = new StaticToken("isProd", () => false);
|
|
252
|
+
|
|
253
|
+
const i = new Injector();
|
|
254
|
+
|
|
255
|
+
function isProd() {
|
|
256
|
+
return (val: LifecycleCallback, ctx: ClassMethodDecoratorContext) => {
|
|
257
|
+
created(({ injector }) => {
|
|
258
|
+
const enabled = injector.inject(IS_PROD);
|
|
259
|
+
return { enabled };
|
|
260
|
+
})(val, ctx);
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
@injectable()
|
|
265
|
+
class MyService {
|
|
266
|
+
count = 0;
|
|
267
|
+
|
|
268
|
+
@isProd()
|
|
269
|
+
onCreated() {
|
|
270
|
+
this.count++;
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
const service = i.inject(MyService);
|
|
275
|
+
assert.equal(service.count, 0); // Not called because count is 0
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
it("should pass the instance to the condition", () => {
|
|
279
|
+
const i = new Injector();
|
|
280
|
+
|
|
281
|
+
@injectable()
|
|
282
|
+
class MyService {
|
|
283
|
+
enabled = false;
|
|
284
|
+
count = 0;
|
|
285
|
+
|
|
286
|
+
@created(({ instance }) => ({ enabled: instance.enabled }))
|
|
287
|
+
onCreated() {
|
|
288
|
+
this.count++;
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
const service = i.inject(MyService);
|
|
293
|
+
assert.equal(service.count, 0); // not called because instance.enabled is false
|
|
294
|
+
});
|
package/src/lib/lifecycle.ts
CHANGED
|
@@ -1,36 +1,53 @@
|
|
|
1
1
|
import type { Injector } from "./injector.js";
|
|
2
|
-
import type {
|
|
2
|
+
import type {
|
|
3
|
+
InjectableMetadata,
|
|
4
|
+
LifecycleCallback,
|
|
5
|
+
LifecycleCondition,
|
|
6
|
+
LifecycleMethod,
|
|
7
|
+
} from "./metadata.js";
|
|
3
8
|
|
|
4
|
-
export function injected() {
|
|
9
|
+
export function injected<T>(condition?: LifecycleCondition<T>) {
|
|
5
10
|
return function onInjectDecorator(
|
|
6
11
|
val: LifecycleCallback,
|
|
7
|
-
ctx: ClassMethodDecoratorContext
|
|
12
|
+
ctx: ClassMethodDecoratorContext<T>,
|
|
8
13
|
): void {
|
|
9
|
-
const metadata: InjectableMetadata = ctx.metadata;
|
|
14
|
+
const metadata: InjectableMetadata<T> = ctx.metadata;
|
|
10
15
|
metadata.onInjected ??= [];
|
|
11
|
-
metadata.onInjected.push(
|
|
16
|
+
metadata.onInjected.push({
|
|
17
|
+
callback: val,
|
|
18
|
+
condition,
|
|
19
|
+
});
|
|
12
20
|
};
|
|
13
21
|
}
|
|
14
22
|
|
|
15
|
-
export function created() {
|
|
23
|
+
export function created<T>(condition?: LifecycleCondition<T>) {
|
|
16
24
|
return function onInjectDecorator(
|
|
17
25
|
val: LifecycleCallback,
|
|
18
|
-
ctx: ClassMethodDecoratorContext
|
|
26
|
+
ctx: ClassMethodDecoratorContext<T>,
|
|
19
27
|
): void {
|
|
20
|
-
const metadata: InjectableMetadata = ctx.metadata;
|
|
28
|
+
const metadata: InjectableMetadata<T> = ctx.metadata;
|
|
21
29
|
metadata.onCreated ??= [];
|
|
22
|
-
metadata.onCreated.push(
|
|
30
|
+
metadata.onCreated.push({
|
|
31
|
+
callback: val,
|
|
32
|
+
condition,
|
|
33
|
+
});
|
|
23
34
|
};
|
|
24
35
|
}
|
|
25
36
|
|
|
26
37
|
export function callLifecycle(
|
|
27
38
|
instance: object,
|
|
28
|
-
|
|
29
|
-
methods?:
|
|
39
|
+
injector: Injector,
|
|
40
|
+
methods?: LifecycleMethod<any>[],
|
|
30
41
|
): void {
|
|
31
42
|
if (methods) {
|
|
32
|
-
for (const
|
|
33
|
-
|
|
43
|
+
for (const { callback, condition } of methods) {
|
|
44
|
+
if (condition) {
|
|
45
|
+
const result = condition({ injector, instance });
|
|
46
|
+
if (result.enabled === false) {
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
callback.call(instance, injector);
|
|
34
51
|
}
|
|
35
52
|
}
|
|
36
53
|
}
|
package/src/lib/metadata.ts
CHANGED
|
@@ -5,15 +5,20 @@ import type { InjectionToken } from "./provider.js";
|
|
|
5
5
|
|
|
6
6
|
export type LifecycleCallback = (i: Injector) => void;
|
|
7
7
|
|
|
8
|
-
export
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
export type LifecycleCondition<T> = (ctx:{injector: Injector, instance: T}) => { enabled?: boolean };
|
|
9
|
+
|
|
10
|
+
export interface LifecycleMethod<T> {
|
|
11
|
+
callback: LifecycleCallback;
|
|
12
|
+
condition?: LifecycleCondition<T>;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface InjectableMetadata<T> {
|
|
16
|
+
onCreated?: LifecycleMethod<T>[];
|
|
17
|
+
onInjected?: LifecycleMethod<T>[];
|
|
11
18
|
}
|
|
12
19
|
|
|
13
|
-
export function readMetadata<T>(
|
|
14
|
-
|
|
15
|
-
): InjectableMetadata | null {
|
|
16
|
-
const metadata: InjectableMetadata | null = target[Symbol.metadata];
|
|
20
|
+
export function readMetadata<T>(target: InjectionToken<T>): InjectableMetadata<T> | null {
|
|
21
|
+
const metadata: InjectableMetadata<T> | null = target[Symbol.metadata];
|
|
17
22
|
|
|
18
23
|
return metadata;
|
|
19
24
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { INJECTOR } from "../injector.js";
|
|
2
2
|
import type { Injector } from "../injector.js";
|
|
3
3
|
import type { ConstructableToken } from "../provider.js";
|
|
4
|
-
export
|
|
4
|
+
export type InjectableEl = HTMLElement & {
|
|
5
5
|
[INJECTOR]: Injector;
|
|
6
|
-
}
|
|
6
|
+
};
|
|
7
|
+
export declare function injectableEl<T extends ConstructableToken<InjectableEl>>(Base: T, ctx: ClassDecoratorContext): T;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"injectable-el.js","sourceRoot":"","sources":["../../../src/lib/dom/injectable-el.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE1C,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"injectable-el.js","sourceRoot":"","sources":["../../../src/lib/dom/injectable-el.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE1C,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAMhD,MAAM,UAAU,YAAY,CAE1B,IAAO,EAAE,GAA0B;IACnC,MAAM,QAAQ,GAAqC,GAAG,CAAC,QAAQ,CAAC;IAEhE,MAAM,GAAG,GAAG;QACV,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,KAAM,SAAQ,IAAI;YAC7B,YAAY,GAAG,CAAQ;gBACrB,KAAK,EAAE,CAAC;gBAER,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC;gBAEhC,IAAI,CAAC,gBAAgB,CAAC,iBAAiB,EAAE,CAAC,CAAC,EAAE,EAAE;oBAC7C,IAAI,CAAC,CAAC,MAAM,KAAK,IAAI,IAAI,CAAC,CAAC,OAAO,KAAK,YAAY,EAAE,CAAC;wBACpD,CAAC,CAAC,eAAe,EAAE,CAAC;wBAEpB,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;oBACvB,CAAC;gBACH,CAAC,CAAC,CAAC;gBAEH,aAAa,CAAC,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,SAAS,CAAC,CAAC;YACrD,CAAC;YAED,iBAAiB;gBACf,IAAI,CAAC,aAAa,CAChB,IAAI,mBAAmB,CAAC,YAAY,EAAE,CAAC,GAAG,EAAE,EAAE;oBAC5C,IAAI,CAAC,QAAQ,CAAC,CAAC,MAAM,GAAG,GAAG,CAAC;gBAC9B,CAAC,CAAC,CACH,CAAC;gBAEF,aAAa,CAAC,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC,EAAE,QAAQ,EAAE,UAAU,CAAC,CAAC;gBAE1D,IAAI,KAAK,CAAC,iBAAiB,EAAE,CAAC;oBAC5B,KAAK,CAAC,iBAAiB,EAAE,CAAC;gBAC5B,CAAC;YACH,CAAC;YAED,oBAAoB;gBAIlB,IAAI,KAAK,CAAC,oBAAoB,EAAE,CAAC;oBAC/B,KAAK,CAAC,oBAAoB,EAAE,CAAC;gBAC/B,CAAC;gBAED,IAAI,CAAC,QAAQ,CAAC,CAAC,MAAM,GAAG,SAAS,CAAC;YACpC,CAAC;SACF;KACF,CAAC;IAEF,OAAO,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACxB,CAAC"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Injector } from "./injector.js";
|
|
2
|
-
import type { LifecycleCallback } from "./metadata.js";
|
|
3
|
-
export declare function injected(): (val: LifecycleCallback, ctx: ClassMethodDecoratorContext) => void;
|
|
4
|
-
export declare function created(): (val: LifecycleCallback, ctx: ClassMethodDecoratorContext) => void;
|
|
5
|
-
export declare function callLifecycle(instance: object,
|
|
2
|
+
import type { LifecycleCallback, LifecycleCondition, LifecycleMethod } from "./metadata.js";
|
|
3
|
+
export declare function injected<T>(condition?: LifecycleCondition<T>): (val: LifecycleCallback, ctx: ClassMethodDecoratorContext<T>) => void;
|
|
4
|
+
export declare function created<T>(condition?: LifecycleCondition<T>): (val: LifecycleCallback, ctx: ClassMethodDecoratorContext<T>) => void;
|
|
5
|
+
export declare function callLifecycle(instance: object, injector: Injector, methods?: LifecycleMethod<any>[]): void;
|
package/target/lib/lifecycle.js
CHANGED
|
@@ -1,21 +1,33 @@
|
|
|
1
|
-
export function injected() {
|
|
1
|
+
export function injected(condition) {
|
|
2
2
|
return function onInjectDecorator(val, ctx) {
|
|
3
3
|
const metadata = ctx.metadata;
|
|
4
4
|
metadata.onInjected ??= [];
|
|
5
|
-
metadata.onInjected.push(
|
|
5
|
+
metadata.onInjected.push({
|
|
6
|
+
callback: val,
|
|
7
|
+
condition,
|
|
8
|
+
});
|
|
6
9
|
};
|
|
7
10
|
}
|
|
8
|
-
export function created() {
|
|
11
|
+
export function created(condition) {
|
|
9
12
|
return function onInjectDecorator(val, ctx) {
|
|
10
13
|
const metadata = ctx.metadata;
|
|
11
14
|
metadata.onCreated ??= [];
|
|
12
|
-
metadata.onCreated.push(
|
|
15
|
+
metadata.onCreated.push({
|
|
16
|
+
callback: val,
|
|
17
|
+
condition,
|
|
18
|
+
});
|
|
13
19
|
};
|
|
14
20
|
}
|
|
15
|
-
export function callLifecycle(instance,
|
|
21
|
+
export function callLifecycle(instance, injector, methods) {
|
|
16
22
|
if (methods) {
|
|
17
|
-
for (const
|
|
18
|
-
|
|
23
|
+
for (const { callback, condition } of methods) {
|
|
24
|
+
if (condition) {
|
|
25
|
+
const result = condition({ injector, instance });
|
|
26
|
+
if (result.enabled === false) {
|
|
27
|
+
continue;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
callback.call(instance, injector);
|
|
19
31
|
}
|
|
20
32
|
}
|
|
21
33
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lifecycle.js","sourceRoot":"","sources":["../../src/lib/lifecycle.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"lifecycle.js","sourceRoot":"","sources":["../../src/lib/lifecycle.ts"],"names":[],"mappings":"AAQA,MAAM,UAAU,QAAQ,CAAI,SAAiC;IAC3D,OAAO,SAAS,iBAAiB,CAC/B,GAAsB,EACtB,GAAmC;QAEnC,MAAM,QAAQ,GAA0B,GAAG,CAAC,QAAQ,CAAC;QACrD,QAAQ,CAAC,UAAU,KAAK,EAAE,CAAC;QAC3B,QAAQ,CAAC,UAAU,CAAC,IAAI,CAAC;YACvB,QAAQ,EAAE,GAAG;YACb,SAAS;SACV,CAAC,CAAC;IACL,CAAC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,OAAO,CAAI,SAAiC;IAC1D,OAAO,SAAS,iBAAiB,CAC/B,GAAsB,EACtB,GAAmC;QAEnC,MAAM,QAAQ,GAA0B,GAAG,CAAC,QAAQ,CAAC;QACrD,QAAQ,CAAC,SAAS,KAAK,EAAE,CAAC;QAC1B,QAAQ,CAAC,SAAS,CAAC,IAAI,CAAC;YACtB,QAAQ,EAAE,GAAG;YACb,SAAS;SACV,CAAC,CAAC;IACL,CAAC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,aAAa,CAC3B,QAAgB,EAChB,QAAkB,EAClB,OAAgC;IAEhC,IAAI,OAAO,EAAE,CAAC;QACZ,KAAK,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,IAAI,OAAO,EAAE,CAAC;YAC9C,IAAI,SAAS,EAAE,CAAC;gBACd,MAAM,MAAM,GAAG,SAAS,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC,CAAC;gBACjD,IAAI,MAAM,CAAC,OAAO,KAAK,KAAK,EAAE,CAAC;oBAC7B,SAAS;gBACX,CAAC;YACH,CAAC;YACD,QAAQ,CAAC,IAAI,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QACpC,CAAC;IACH,CAAC;AACH,CAAC"}
|
|
@@ -5,6 +5,7 @@ import { injectable } from "./injectable.js";
|
|
|
5
5
|
import { Injector } from "./injector.js";
|
|
6
6
|
import { created, injected } from "./lifecycle.js";
|
|
7
7
|
import { readInjector } from "./metadata.js";
|
|
8
|
+
import { StaticToken } from "./provider.js";
|
|
8
9
|
it("should call onInit and onInject when a service is first created", () => {
|
|
9
10
|
const i = new Injector();
|
|
10
11
|
let MyService = (() => {
|
|
@@ -193,4 +194,242 @@ it("should call onInject and on init when injected from another service", () =>
|
|
|
193
194
|
onInjected: 2,
|
|
194
195
|
});
|
|
195
196
|
});
|
|
197
|
+
it("should respect enabled=false condition in lifecycle callbacks", () => {
|
|
198
|
+
const i = new Injector();
|
|
199
|
+
let MyService = (() => {
|
|
200
|
+
let _classDecorators = [injectable()];
|
|
201
|
+
let _classDescriptor;
|
|
202
|
+
let _classExtraInitializers = [];
|
|
203
|
+
let _classThis;
|
|
204
|
+
let _instanceExtraInitializers = [];
|
|
205
|
+
let _onCreated_decorators;
|
|
206
|
+
let _onInjected_decorators;
|
|
207
|
+
var MyService = class {
|
|
208
|
+
static { _classThis = this; }
|
|
209
|
+
static {
|
|
210
|
+
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0;
|
|
211
|
+
_onCreated_decorators = [created(() => ({ enabled: false }))];
|
|
212
|
+
_onInjected_decorators = [injected(() => ({ enabled: false }))];
|
|
213
|
+
__esDecorate(this, null, _onCreated_decorators, { kind: "method", name: "onCreated", static: false, private: false, access: { has: obj => "onCreated" in obj, get: obj => obj.onCreated }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
214
|
+
__esDecorate(this, null, _onInjected_decorators, { kind: "method", name: "onInjected", static: false, private: false, access: { has: obj => "onInjected" in obj, get: obj => obj.onInjected }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
215
|
+
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
|
|
216
|
+
MyService = _classThis = _classDescriptor.value;
|
|
217
|
+
if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
218
|
+
__runInitializers(_classThis, _classExtraInitializers);
|
|
219
|
+
}
|
|
220
|
+
res = (__runInitializers(this, _instanceExtraInitializers), {
|
|
221
|
+
onCreated: 0,
|
|
222
|
+
onInjected: 0,
|
|
223
|
+
});
|
|
224
|
+
onCreated() {
|
|
225
|
+
this.res.onCreated++;
|
|
226
|
+
}
|
|
227
|
+
onInjected() {
|
|
228
|
+
this.res.onInjected++;
|
|
229
|
+
}
|
|
230
|
+
};
|
|
231
|
+
return MyService = _classThis;
|
|
232
|
+
})();
|
|
233
|
+
const service = i.inject(MyService);
|
|
234
|
+
assert.deepEqual(service.res, {
|
|
235
|
+
onCreated: 0,
|
|
236
|
+
onInjected: 0,
|
|
237
|
+
});
|
|
238
|
+
});
|
|
239
|
+
it("should respect enabled=true condition in lifecycle callbacks", () => {
|
|
240
|
+
const i = new Injector();
|
|
241
|
+
let MyService = (() => {
|
|
242
|
+
let _classDecorators = [injectable()];
|
|
243
|
+
let _classDescriptor;
|
|
244
|
+
let _classExtraInitializers = [];
|
|
245
|
+
let _classThis;
|
|
246
|
+
let _instanceExtraInitializers = [];
|
|
247
|
+
let _onCreated_decorators;
|
|
248
|
+
let _onInjected_decorators;
|
|
249
|
+
var MyService = class {
|
|
250
|
+
static { _classThis = this; }
|
|
251
|
+
static {
|
|
252
|
+
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0;
|
|
253
|
+
_onCreated_decorators = [created(() => ({ enabled: true }))];
|
|
254
|
+
_onInjected_decorators = [injected(() => ({ enabled: true }))];
|
|
255
|
+
__esDecorate(this, null, _onCreated_decorators, { kind: "method", name: "onCreated", static: false, private: false, access: { has: obj => "onCreated" in obj, get: obj => obj.onCreated }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
256
|
+
__esDecorate(this, null, _onInjected_decorators, { kind: "method", name: "onInjected", static: false, private: false, access: { has: obj => "onInjected" in obj, get: obj => obj.onInjected }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
257
|
+
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
|
|
258
|
+
MyService = _classThis = _classDescriptor.value;
|
|
259
|
+
if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
260
|
+
__runInitializers(_classThis, _classExtraInitializers);
|
|
261
|
+
}
|
|
262
|
+
res = (__runInitializers(this, _instanceExtraInitializers), {
|
|
263
|
+
onCreated: 0,
|
|
264
|
+
onInjected: 0,
|
|
265
|
+
});
|
|
266
|
+
onCreated() {
|
|
267
|
+
this.res.onCreated++;
|
|
268
|
+
}
|
|
269
|
+
onInjected() {
|
|
270
|
+
this.res.onInjected++;
|
|
271
|
+
}
|
|
272
|
+
};
|
|
273
|
+
return MyService = _classThis;
|
|
274
|
+
})();
|
|
275
|
+
const service = i.inject(MyService);
|
|
276
|
+
assert.deepEqual(service.res, {
|
|
277
|
+
onCreated: 1,
|
|
278
|
+
onInjected: 1,
|
|
279
|
+
});
|
|
280
|
+
});
|
|
281
|
+
it("should execute callbacks when condition returns undefined enabled", () => {
|
|
282
|
+
const i = new Injector();
|
|
283
|
+
let MyService = (() => {
|
|
284
|
+
let _classDecorators = [injectable()];
|
|
285
|
+
let _classDescriptor;
|
|
286
|
+
let _classExtraInitializers = [];
|
|
287
|
+
let _classThis;
|
|
288
|
+
let _instanceExtraInitializers = [];
|
|
289
|
+
let _onCreated_decorators;
|
|
290
|
+
let _onInjected_decorators;
|
|
291
|
+
var MyService = class {
|
|
292
|
+
static { _classThis = this; }
|
|
293
|
+
static {
|
|
294
|
+
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0;
|
|
295
|
+
_onCreated_decorators = [created(() => ({ enabled: undefined }))];
|
|
296
|
+
_onInjected_decorators = [injected(() => ({ enabled: undefined }))];
|
|
297
|
+
__esDecorate(this, null, _onCreated_decorators, { kind: "method", name: "onCreated", static: false, private: false, access: { has: obj => "onCreated" in obj, get: obj => obj.onCreated }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
298
|
+
__esDecorate(this, null, _onInjected_decorators, { kind: "method", name: "onInjected", static: false, private: false, access: { has: obj => "onInjected" in obj, get: obj => obj.onInjected }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
299
|
+
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
|
|
300
|
+
MyService = _classThis = _classDescriptor.value;
|
|
301
|
+
if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
302
|
+
__runInitializers(_classThis, _classExtraInitializers);
|
|
303
|
+
}
|
|
304
|
+
res = (__runInitializers(this, _instanceExtraInitializers), {
|
|
305
|
+
onCreated: 0,
|
|
306
|
+
onInjected: 0,
|
|
307
|
+
});
|
|
308
|
+
onCreated() {
|
|
309
|
+
this.res.onCreated++;
|
|
310
|
+
}
|
|
311
|
+
onInjected() {
|
|
312
|
+
this.res.onInjected++;
|
|
313
|
+
}
|
|
314
|
+
};
|
|
315
|
+
return MyService = _classThis;
|
|
316
|
+
})();
|
|
317
|
+
const service = i.inject(MyService);
|
|
318
|
+
assert.deepEqual(service.res, {
|
|
319
|
+
onCreated: 1,
|
|
320
|
+
onInjected: 1,
|
|
321
|
+
});
|
|
322
|
+
});
|
|
323
|
+
it("should execute callbacks when condition returns empty object", () => {
|
|
324
|
+
const i = new Injector();
|
|
325
|
+
let MyService = (() => {
|
|
326
|
+
let _classDecorators = [injectable()];
|
|
327
|
+
let _classDescriptor;
|
|
328
|
+
let _classExtraInitializers = [];
|
|
329
|
+
let _classThis;
|
|
330
|
+
let _instanceExtraInitializers = [];
|
|
331
|
+
let _onCreated_decorators;
|
|
332
|
+
let _onInjected_decorators;
|
|
333
|
+
var MyService = class {
|
|
334
|
+
static { _classThis = this; }
|
|
335
|
+
static {
|
|
336
|
+
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0;
|
|
337
|
+
_onCreated_decorators = [created(() => ({}))];
|
|
338
|
+
_onInjected_decorators = [injected(() => ({}))];
|
|
339
|
+
__esDecorate(this, null, _onCreated_decorators, { kind: "method", name: "onCreated", static: false, private: false, access: { has: obj => "onCreated" in obj, get: obj => obj.onCreated }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
340
|
+
__esDecorate(this, null, _onInjected_decorators, { kind: "method", name: "onInjected", static: false, private: false, access: { has: obj => "onInjected" in obj, get: obj => obj.onInjected }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
341
|
+
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
|
|
342
|
+
MyService = _classThis = _classDescriptor.value;
|
|
343
|
+
if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
344
|
+
__runInitializers(_classThis, _classExtraInitializers);
|
|
345
|
+
}
|
|
346
|
+
res = (__runInitializers(this, _instanceExtraInitializers), {
|
|
347
|
+
onCreated: 0,
|
|
348
|
+
onInjected: 0,
|
|
349
|
+
});
|
|
350
|
+
onCreated() {
|
|
351
|
+
this.res.onCreated++;
|
|
352
|
+
}
|
|
353
|
+
onInjected() {
|
|
354
|
+
this.res.onInjected++;
|
|
355
|
+
}
|
|
356
|
+
};
|
|
357
|
+
return MyService = _classThis;
|
|
358
|
+
})();
|
|
359
|
+
const service = i.inject(MyService);
|
|
360
|
+
assert.deepEqual(service.res, {
|
|
361
|
+
onCreated: 1,
|
|
362
|
+
onInjected: 1,
|
|
363
|
+
});
|
|
364
|
+
});
|
|
365
|
+
it("should pass the injector to the condition", () => {
|
|
366
|
+
const IS_PROD = new StaticToken("isProd", () => false);
|
|
367
|
+
const i = new Injector();
|
|
368
|
+
function isProd() {
|
|
369
|
+
return (val, ctx) => {
|
|
370
|
+
created(({ injector }) => {
|
|
371
|
+
const enabled = injector.inject(IS_PROD);
|
|
372
|
+
return { enabled };
|
|
373
|
+
})(val, ctx);
|
|
374
|
+
};
|
|
375
|
+
}
|
|
376
|
+
let MyService = (() => {
|
|
377
|
+
let _classDecorators = [injectable()];
|
|
378
|
+
let _classDescriptor;
|
|
379
|
+
let _classExtraInitializers = [];
|
|
380
|
+
let _classThis;
|
|
381
|
+
let _instanceExtraInitializers = [];
|
|
382
|
+
let _onCreated_decorators;
|
|
383
|
+
var MyService = class {
|
|
384
|
+
static { _classThis = this; }
|
|
385
|
+
static {
|
|
386
|
+
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0;
|
|
387
|
+
_onCreated_decorators = [isProd()];
|
|
388
|
+
__esDecorate(this, null, _onCreated_decorators, { kind: "method", name: "onCreated", static: false, private: false, access: { has: obj => "onCreated" in obj, get: obj => obj.onCreated }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
389
|
+
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
|
|
390
|
+
MyService = _classThis = _classDescriptor.value;
|
|
391
|
+
if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
392
|
+
__runInitializers(_classThis, _classExtraInitializers);
|
|
393
|
+
}
|
|
394
|
+
count = (__runInitializers(this, _instanceExtraInitializers), 0);
|
|
395
|
+
onCreated() {
|
|
396
|
+
this.count++;
|
|
397
|
+
}
|
|
398
|
+
};
|
|
399
|
+
return MyService = _classThis;
|
|
400
|
+
})();
|
|
401
|
+
const service = i.inject(MyService);
|
|
402
|
+
assert.equal(service.count, 0);
|
|
403
|
+
});
|
|
404
|
+
it("should pass the instance to the condition", () => {
|
|
405
|
+
const i = new Injector();
|
|
406
|
+
let MyService = (() => {
|
|
407
|
+
let _classDecorators = [injectable()];
|
|
408
|
+
let _classDescriptor;
|
|
409
|
+
let _classExtraInitializers = [];
|
|
410
|
+
let _classThis;
|
|
411
|
+
let _instanceExtraInitializers = [];
|
|
412
|
+
let _onCreated_decorators;
|
|
413
|
+
var MyService = class {
|
|
414
|
+
static { _classThis = this; }
|
|
415
|
+
static {
|
|
416
|
+
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0;
|
|
417
|
+
_onCreated_decorators = [created(({ instance }) => ({ enabled: instance.enabled }))];
|
|
418
|
+
__esDecorate(this, null, _onCreated_decorators, { kind: "method", name: "onCreated", static: false, private: false, access: { has: obj => "onCreated" in obj, get: obj => obj.onCreated }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
419
|
+
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
|
|
420
|
+
MyService = _classThis = _classDescriptor.value;
|
|
421
|
+
if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
422
|
+
__runInitializers(_classThis, _classExtraInitializers);
|
|
423
|
+
}
|
|
424
|
+
enabled = (__runInitializers(this, _instanceExtraInitializers), false);
|
|
425
|
+
count = 0;
|
|
426
|
+
onCreated() {
|
|
427
|
+
this.count++;
|
|
428
|
+
}
|
|
429
|
+
};
|
|
430
|
+
return MyService = _classThis;
|
|
431
|
+
})();
|
|
432
|
+
const service = i.inject(MyService);
|
|
433
|
+
assert.equal(service.count, 0);
|
|
434
|
+
});
|
|
196
435
|
//# sourceMappingURL=lifecycle.test.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lifecycle.test.js","sourceRoot":"","sources":["../../src/lib/lifecycle.test.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAE9B,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,
|
|
1
|
+
{"version":3,"file":"lifecycle.test.js","sourceRoot":"","sources":["../../src/lib/lifecycle.test.ts"],"names":[],"mappings":"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"}
|
package/target/lib/metadata.d.ts
CHANGED
|
@@ -1,9 +1,19 @@
|
|
|
1
1
|
import { type Injector } from "./injector.js";
|
|
2
2
|
import type { InjectionToken } from "./provider.js";
|
|
3
3
|
export type LifecycleCallback = (i: Injector) => void;
|
|
4
|
-
export
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
export type LifecycleCondition<T> = (ctx: {
|
|
5
|
+
injector: Injector;
|
|
6
|
+
instance: T;
|
|
7
|
+
}) => {
|
|
8
|
+
enabled?: boolean;
|
|
9
|
+
};
|
|
10
|
+
export interface LifecycleMethod<T> {
|
|
11
|
+
callback: LifecycleCallback;
|
|
12
|
+
condition?: LifecycleCondition<T>;
|
|
7
13
|
}
|
|
8
|
-
export
|
|
14
|
+
export interface InjectableMetadata<T> {
|
|
15
|
+
onCreated?: LifecycleMethod<T>[];
|
|
16
|
+
onInjected?: LifecycleMethod<T>[];
|
|
17
|
+
}
|
|
18
|
+
export declare function readMetadata<T>(target: InjectionToken<T>): InjectableMetadata<T> | null;
|
|
9
19
|
export declare function readInjector<T>(target: T): Injector | null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"metadata.js","sourceRoot":"","sources":["../../src/lib/metadata.ts"],"names":[],"mappings":"AAAC,MAAc,CAAC,QAAQ,KAAK,MAAM,CAAC,iBAAiB,CAAC,CAAC;AAEvD,OAAO,EAAE,QAAQ,EAAiB,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"metadata.js","sourceRoot":"","sources":["../../src/lib/metadata.ts"],"names":[],"mappings":"AAAC,MAAc,CAAC,QAAQ,KAAK,MAAM,CAAC,iBAAiB,CAAC,CAAC;AAEvD,OAAO,EAAE,QAAQ,EAAiB,MAAM,eAAe,CAAC;AAiBxD,MAAM,UAAU,YAAY,CAAI,MAAyB;IACvD,MAAM,QAAQ,GAAiC,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAEvE,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,MAAM,UAAU,YAAY,CAAI,MAAS;IACvC,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;QAClD,IAAI,QAAQ,IAAI,MAAM,EAAE,CAAC;YACvB,OAAO,MAAM,CAAC,QAAQ,CAAa,CAAC;QACtC,CAAC;IACH,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC"}
|