Skip to content

Commit dec5c2c

Browse files
wingsbobMatthew Bull
andauthored
feat(core): support proxying functions with explicit properties (#389)
* feat: support proxying functions with explicit properties --------- Co-authored-by: Matthew Bull <matt.bull@beautypie.com>
1 parent 4461b45 commit dec5c2c

File tree

2 files changed

+93
-1
lines changed

2 files changed

+93
-1
lines changed
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
import { globalClsService } from '../cls-service.globals';
2+
import { ProxyProviderManager } from './proxy-provider-manager';
3+
4+
describe('ProxyProviderManager', () => {
5+
afterEach(() => ProxyProviderManager.reset());
6+
describe('createProxyProvider', () => {
7+
it('is defined', () => {
8+
expect(ProxyProviderManager.createProxyProvider).toBeDefined();
9+
});
10+
11+
it('returns a provider', () => {
12+
const providerToken = Symbol('example-provider');
13+
14+
expect(
15+
ProxyProviderManager.createProxyProvider({
16+
provide: providerToken,
17+
useFactory: () => ({}),
18+
}),
19+
).toEqual(
20+
expect.objectContaining({
21+
provide: providerToken,
22+
useFactory: expect.any(Function),
23+
}),
24+
);
25+
});
26+
27+
describe('the provider factory', () => {
28+
it('allows access to the underlying provider properties', async () => {
29+
await globalClsService.run(async () => {
30+
const provider = {
31+
key: 'value',
32+
};
33+
const providerToken = Symbol('example-provider');
34+
const { useFactory } =
35+
ProxyProviderManager.createProxyProvider({
36+
provide: providerToken,
37+
useFactory: () => provider,
38+
});
39+
40+
const instance = useFactory();
41+
42+
ProxyProviderManager.init();
43+
await ProxyProviderManager.resolveProxyProviders();
44+
45+
expect(instance.key).toBe(provider.key);
46+
});
47+
});
48+
it('binds function properties', async () => {
49+
await globalClsService.run(async () => {
50+
const provider = {
51+
fn() {
52+
return this;
53+
},
54+
};
55+
const providerToken = Symbol('example-provider');
56+
const { useFactory } =
57+
ProxyProviderManager.createProxyProvider({
58+
provide: providerToken,
59+
useFactory: () => provider,
60+
});
61+
62+
const instance = useFactory();
63+
64+
ProxyProviderManager.init();
65+
await ProxyProviderManager.resolveProxyProviders();
66+
67+
expect(instance.fn()).toBe(provider);
68+
});
69+
});
70+
it('preserves properties on function properties', async () => {
71+
await globalClsService.run(async () => {
72+
const provider = {
73+
fn: Object.assign(() => 'hello', { info: () => null }),
74+
};
75+
const providerToken = Symbol('example-provider');
76+
const { useFactory } =
77+
ProxyProviderManager.createProxyProvider({
78+
provide: providerToken,
79+
useFactory: () => provider,
80+
});
81+
82+
const instance = useFactory();
83+
84+
ProxyProviderManager.init();
85+
await ProxyProviderManager.resolveProxyProviders();
86+
87+
expect(instance.fn.info).toEqual(expect.any(Function));
88+
});
89+
});
90+
});
91+
});
92+
});

packages/core/src/lib/proxy-provider/proxy-provider-manager.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ export class ProxyProviderManager {
173173
const provider = getProvider() ?? checkAccess(propName);
174174
const prop = provider[propName];
175175
if (typeof prop === 'function') {
176-
return prop.bind(provider);
176+
return Object.assign(prop.bind(provider), prop);
177177
} else {
178178
return prop;
179179
}

0 commit comments

Comments
 (0)