Skip to content

Commit c1de2d5

Browse files
authored
feat(core): support injection token values to config provider (#3277)
1 parent 15b5749 commit c1de2d5

File tree

3 files changed

+52
-17
lines changed

3 files changed

+52
-17
lines changed

libs/core/src/injection-tokens/config.factory.spec.ts

+38-7
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { InjectionToken } from '@angular/core';
2+
import { TestBed } from '@angular/core/testing';
13
import { faker } from '@faker-js/faker/locale/en_US';
24

35
import { DaffConfigInjectionToken } from '@daffodil/core';
@@ -11,13 +13,16 @@ interface Config {
1113

1214
describe('@daffodil/core | createConfigInjectionToken', () => {
1315
let name: string;
14-
let value: number;
16+
let value: Partial<Config>;
1517
let defaultConfig: Config;
1618

1719
let result: DaffConfigInjectionToken<Config>;
1820

1921
beforeEach(() => {
2022
name = faker.random.word();
23+
value = {
24+
field: faker.random.word(),
25+
};
2126
defaultConfig = {
2227
field: faker.random.word(),
2328
other: faker.random.word(),
@@ -29,13 +34,39 @@ describe('@daffodil/core | createConfigInjectionToken', () => {
2934
expect(result.token.toString()).toContain(name);
3035
});
3136

32-
it('should return a provider that spreads in passed values with the default', () => {
33-
const val = faker.random.word();
34-
const res = result.provider({
35-
field: val,
37+
describe('when the provided value is an injection token', () => {
38+
let token: InjectionToken<Partial<Config>>;
39+
let defaultToken: InjectionToken<Config>;
40+
41+
beforeEach(() => {
42+
token = new InjectionToken('test');
43+
defaultToken = new InjectionToken('default');
44+
TestBed.configureTestingModule({
45+
providers: [
46+
{
47+
provide: token,
48+
useValue: value,
49+
},
50+
{
51+
provide: defaultToken,
52+
useValue: defaultConfig,
53+
},
54+
],
55+
});
3656
});
57+
58+
it('should return a provider that spreads in passed values with the default', () => {
59+
const res = result.provider(token);
60+
expect(res.provide).toEqual(result.token);
61+
expect(TestBed.runInInjectionContext<Config>(<any>res.useFactory).field).toEqual(value.field);
62+
expect(TestBed.runInInjectionContext<Config>(<any>res.useFactory).other).toEqual(defaultConfig.other);
63+
});
64+
});
65+
66+
it('should return a provider that spreads in passed values with the default', () => {
67+
const res = result.provider(value);
3768
expect(res.provide).toEqual(result.token);
38-
expect(res.useValue.field).toEqual(val);
39-
expect(res.useValue.other).toEqual(defaultConfig.other);
69+
expect(TestBed.runInInjectionContext<Config>(<any>res.useFactory).field).toEqual(value.field);
70+
expect(TestBed.runInInjectionContext<Config>(<any>res.useFactory).other).toEqual(defaultConfig.other);
4071
});
4172
});

libs/core/src/injection-tokens/config.factory.ts

+11-8
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
import { InjectionToken } from '@angular/core';
1+
import {
2+
inject,
3+
InjectionToken,
4+
} from '@angular/core';
25

36
import { DaffConfigInjectionToken } from './config.type';
47
import {
@@ -12,23 +15,23 @@ import {
1215
* See {@link DaffConfigInjectionToken}.
1316
*/
1417
export const createConfigInjectionToken = <T = unknown>(
15-
defaultConfig: T,
18+
defaultConfig: T | InjectionToken<T>,
1619
desc: TokenDesc<T>,
1720
options?: Partial<TokenOptions<T>>,
1821
): DaffConfigInjectionToken<T> => {
1922
const token = new InjectionToken<T>(
2023
desc,
2124
{
22-
factory: () => defaultConfig,
25+
factory: () => defaultConfig instanceof InjectionToken ? inject(defaultConfig) : defaultConfig,
2326
...options,
2427
},
2528
);
26-
const provider = <R extends T = T>(config: Partial<R>) => ({
29+
const provider = <R extends T = T>(config: Partial<R> | InjectionToken<Partial<R>>) => ({
2730
provide: token,
28-
useValue: {
29-
...defaultConfig,
30-
...config,
31-
},
31+
useFactory: () => ({
32+
...(defaultConfig instanceof InjectionToken ? inject(defaultConfig) : defaultConfig),
33+
...(config instanceof InjectionToken ? inject(config) : config),
34+
}),
3235
});
3336

3437
return {

libs/core/src/injection-tokens/config.type.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import {
22
InjectionToken,
3-
ValueProvider,
3+
FactoryProvider,
44
} from '@angular/core';
55

66
/**
@@ -17,6 +17,7 @@ export interface DaffConfigInjectionToken<T = unknown> {
1717
* A helper function to provide a value to the token.
1818
* It will shallow merge the passed config with the default config
1919
* with the passed config keys taking precedence.
20+
* An injection token containing a config may also be passed.
2021
*/
21-
provider: <R extends T = T>(config: Partial<R>) => ValueProvider;
22+
provider: <R extends T = T>(config: Partial<R> | InjectionToken<Partial<R>>) => FactoryProvider;
2223
}

0 commit comments

Comments
 (0)