@servicetitan/react-ioc 17.1.0 → 17.3.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.
Files changed (50) hide show
  1. package/dist/await.d.ts +2 -2
  2. package/dist/await.d.ts.map +1 -1
  3. package/dist/await.js.map +1 -1
  4. package/dist/common.d.ts +10 -0
  5. package/dist/common.d.ts.map +1 -0
  6. package/dist/{container-context.js → common.js} +6 -2
  7. package/dist/common.js.map +1 -0
  8. package/dist/index.d.ts +7 -3
  9. package/dist/index.d.ts.map +1 -1
  10. package/dist/index.js +16 -16
  11. package/dist/index.js.map +1 -1
  12. package/dist/inject-dependency.d.ts +3 -0
  13. package/dist/inject-dependency.d.ts.map +1 -0
  14. package/dist/inject-dependency.js +53 -0
  15. package/dist/inject-dependency.js.map +1 -0
  16. package/dist/provide.d.ts +14 -0
  17. package/dist/provide.d.ts.map +1 -0
  18. package/dist/provide.js +7 -0
  19. package/dist/provide.js.map +1 -0
  20. package/dist/provider.d.ts +20 -0
  21. package/dist/provider.d.ts.map +1 -0
  22. package/dist/provider.js +83 -0
  23. package/dist/provider.js.map +1 -0
  24. package/dist/store.d.ts +8 -1
  25. package/dist/store.d.ts.map +1 -1
  26. package/dist/store.js +14 -2
  27. package/dist/store.js.map +1 -1
  28. package/dist/use-dependencies.d.ts +8 -0
  29. package/dist/use-dependencies.d.ts.map +1 -0
  30. package/dist/use-dependencies.js +30 -0
  31. package/dist/use-dependencies.js.map +1 -0
  32. package/package.json +4 -4
  33. package/src/__tests__/react-ioc.test.tsx +1 -1
  34. package/src/await.tsx +2 -2
  35. package/src/common.tsx +14 -0
  36. package/src/index.ts +9 -3
  37. package/src/inject-dependency.ts +66 -0
  38. package/src/provide.tsx +25 -0
  39. package/src/provider.tsx +139 -0
  40. package/src/store.ts +14 -3
  41. package/src/use-dependencies.ts +39 -0
  42. package/dist/container-context.d.ts +0 -5
  43. package/dist/container-context.d.ts.map +0 -1
  44. package/dist/container-context.js.map +0 -1
  45. package/dist/react-ioc.d.ts +0 -41
  46. package/dist/react-ioc.d.ts.map +0 -1
  47. package/dist/react-ioc.js +0 -172
  48. package/dist/react-ioc.js.map +0 -1
  49. package/src/container-context.tsx +0 -7
  50. package/src/react-ioc.tsx +0 -279
package/src/react-ioc.tsx DELETED
@@ -1,279 +0,0 @@
1
- import {
2
- Component,
3
- useRef,
4
- useContext,
5
- ReactInstance,
6
- StatelessComponent,
7
- ComponentClass,
8
- ClassicComponentClass,
9
- FC,
10
- } from 'react';
11
- import { Container, interfaces, METADATA_KEY } from 'inversify';
12
- import { ContainerContext } from './container-context';
13
- import { Store } from './store';
14
- import { Await } from './await';
15
- import 'reflect-metadata';
16
-
17
- export type Token<T> = SymbolToken<T> | interfaces.Newable<T> | interfaces.Abstract<T>;
18
-
19
- export type SymbolToken<T> = symbol & { typeRef?: T };
20
- export function symbolToken<T>(key: string, global = true): SymbolToken<T> {
21
- return global ? Symbol.for(key) : Symbol(key);
22
- }
23
-
24
- type ProviderConfigEntry<T> =
25
- | interfaces.Newable<T>
26
- | ClassProviderConfigEntry<T>
27
- | ValueProviderConfigEntry<T>;
28
-
29
- interface ClassProviderConfigEntry<T> {
30
- provide: Token<T>;
31
- useClass: interfaces.Newable<T>;
32
- }
33
-
34
- interface ValueProviderConfigEntry<T> {
35
- provide: SymbolToken<T> | interfaces.Abstract<T>;
36
- useValue: T;
37
- }
38
-
39
- function isClassProviderConfigEntry<T>(
40
- entry: ProviderConfigEntry<T>
41
- ): entry is ClassProviderConfigEntry<T> {
42
- return (
43
- Object.prototype.hasOwnProperty.call(entry, 'provide') &&
44
- Object.prototype.hasOwnProperty.call(entry, 'useClass')
45
- );
46
- }
47
-
48
- function isValueProviderConfigEntry<T>(
49
- entry: ProviderConfigEntry<T>
50
- ): entry is ValueProviderConfigEntry<T> {
51
- return (
52
- Object.prototype.hasOwnProperty.call(entry, 'provide') &&
53
- Object.prototype.hasOwnProperty.call(entry, 'useValue')
54
- );
55
- }
56
-
57
- export interface ProviderInterface {
58
- singletons?: ProviderConfigEntry<any>[];
59
- instances?: ProviderConfigEntry<any>[];
60
- fallback?: JSX.Element;
61
- }
62
-
63
- export interface ProviderComponentInterface extends ProviderInterface {
64
- parentContainer: Container;
65
- }
66
-
67
- export interface WrappedComponent<P> {
68
- wrappedComponent: ReactComponent<P>;
69
- wrappedInstance: ReactInstance | undefined;
70
- }
71
-
72
- type ReactComponent<P = any> = StatelessComponent<P> | ComponentClass<P> | ClassicComponentClass<P>;
73
-
74
- type ProvideDecorator = (
75
- stores: ProviderInterface
76
- ) => <T extends ReactComponent>(target: T) => T & WrappedComponent<T>;
77
-
78
- export const provide = (stores => (Component: ReactComponent) => props =>
79
- (
80
- <ContainerContext.Consumer>
81
- {container => (
82
- <ProviderComponent {...stores} parentContainer={container}>
83
- <Component {...props} />
84
- </ProviderComponent>
85
- )}
86
- </ContainerContext.Consumer>
87
- )) as ProvideDecorator;
88
-
89
- export const Provider: FC<ProviderInterface> = props => (
90
- <ContainerContext.Consumer>
91
- {container => (
92
- <ProviderComponent {...props} parentContainer={container}>
93
- {props.children}
94
- </ProviderComponent>
95
- )}
96
- </ContainerContext.Consumer>
97
- );
98
-
99
- class ProviderComponent extends Component<ProviderComponentInterface> {
100
- private container: Container;
101
-
102
- private promises: Promise<void>[] = [];
103
-
104
- constructor(props: ProviderComponentInterface) {
105
- super(props);
106
-
107
- const { parentContainer, singletons = [], instances = [] } = props;
108
-
109
- this.container = new Container();
110
- this.container.parent = parentContainer;
111
-
112
- singletons.map(this.bind).forEach(binding => {
113
- binding.inSingletonScope();
114
- });
115
- instances.forEach(this.bind);
116
-
117
- for (const entry of [...singletons, ...instances]) {
118
- if (isValueProviderConfigEntry(entry)) {
119
- continue;
120
- }
121
-
122
- const identifier = isClassProviderConfigEntry(entry) ? entry.provide : entry;
123
- const instance = this.container.get(identifier);
124
- if (instance instanceof Store && instance.initialize) {
125
- this.promises.push(instance.initialize());
126
- }
127
- }
128
- }
129
-
130
- componentWillUnmount() {
131
- const { singletons = [], instances = [] } = this.props;
132
-
133
- for (const entry of [...singletons, ...instances]) {
134
- this.unbind(entry);
135
- }
136
- }
137
-
138
- bind = (entry: ProviderConfigEntry<any>): interfaces.BindingInSyntax<any> => {
139
- if (isClassProviderConfigEntry(entry)) {
140
- return this.container.bind(entry.provide).to(entry.useClass);
141
- }
142
-
143
- if (isValueProviderConfigEntry(entry)) {
144
- // using toDynamicValue to return BindingInSyntax
145
- return this.container.bind(entry.provide).toDynamicValue(() => entry.useValue);
146
- }
147
-
148
- return this.container.bind(entry).to(entry);
149
- };
150
-
151
- unbind = (entry: ProviderConfigEntry<any>): void => {
152
- if (isValueProviderConfigEntry(entry)) {
153
- return this.container.unbind(entry.provide);
154
- }
155
-
156
- const identifier = isClassProviderConfigEntry(entry) ? entry.provide : entry;
157
- const instance = this.container.get(identifier);
158
- if (instance instanceof Store && instance.dispose) {
159
- instance.dispose();
160
- }
161
-
162
- return this.container.unbind(identifier);
163
- };
164
-
165
- render() {
166
- const { fallback, children } = this.props;
167
-
168
- return (
169
- <ContainerContext.Provider value={this.container}>
170
- {this.promises.length ? (
171
- <Await promises={this.promises} fallback={fallback}>
172
- {children}
173
- </Await>
174
- ) : (
175
- children
176
- )}
177
- </ContainerContext.Provider>
178
- );
179
- }
180
- }
181
-
182
- const INJECTION = Symbol.for('INJECTION');
183
-
184
- function proxyGetter(
185
- proto: any,
186
- key: string,
187
- resolve: (componentInstance: any) => any,
188
- doCache: boolean
189
- ) {
190
- function getter(this: any) {
191
- if (doCache && !Reflect.hasMetadata(INJECTION, this, key)) {
192
- Reflect.defineMetadata(INJECTION, resolve(this), this, key);
193
- }
194
- if (Reflect.hasMetadata(INJECTION, this, key)) {
195
- return Reflect.getMetadata(INJECTION, this, key);
196
- }
197
- return resolve(this);
198
- }
199
- function setter(this: any, newVal: any) {
200
- Reflect.defineMetadata(INJECTION, newVal, this, key);
201
- }
202
- Object.defineProperty(proto, key, {
203
- configurable: true,
204
- enumerable: true,
205
- get: getter,
206
- set: setter,
207
- });
208
- }
209
-
210
- export function injectDependency(serviceIdentifier: interfaces.ServiceIdentifier<any>) {
211
- return function (proto: any, key: string): void {
212
- const resolve = (componentInstance: any) => {
213
- if (!componentInstance.context) {
214
- throw new Error(
215
- "Context doesn't exist on a target class. " +
216
- 'Please make sure to pass context object to super method if you access injectable stores in constructor.'
217
- );
218
- }
219
-
220
- const metadata: Partial<interfaces.MetadataMap> =
221
- Reflect.getMetadata(METADATA_KEY.TAGGED_PROP, proto.constructor) || {};
222
-
223
- if (
224
- metadata[key]?.some(({ key, value }) => key === METADATA_KEY.OPTIONAL_TAG && value)
225
- ) {
226
- if (componentInstance.context.isBound(serviceIdentifier)) {
227
- return componentInstance.context.get(serviceIdentifier);
228
- }
229
- } else {
230
- return componentInstance.context.get(serviceIdentifier);
231
- }
232
- };
233
-
234
- if (proto.constructor.contextType && proto.constructor.contextType !== ContainerContext) {
235
- throw new Error(
236
- "injectDependency can't be used together with contextType static property"
237
- );
238
- }
239
-
240
- proto.constructor.contextType = ContainerContext;
241
- proxyGetter(proto, key, resolve, true);
242
- };
243
- }
244
-
245
- type Tokens<T> = {
246
- [P in keyof T]: Token<T[P]>;
247
- };
248
-
249
- function useDependenciesInternal<T extends any[], P extends boolean>(
250
- tokens: Tokens<T>,
251
- optional: P
252
- ) {
253
- const ref = useRef<T | Partial<T> | null>(null);
254
- const container = useContext(ContainerContext);
255
-
256
- if (!ref.current) {
257
- ref.current = tokens.map(s => {
258
- if (optional) {
259
- if (container.isBound(s)) {
260
- return container.get(s);
261
- }
262
-
263
- return undefined;
264
- }
265
-
266
- return container.get(s);
267
- }) as T;
268
- }
269
-
270
- return ref.current as P extends true ? Partial<T> : T;
271
- }
272
-
273
- export function useDependencies<T extends any[]>(...tokens: Tokens<T>) {
274
- return useDependenciesInternal(tokens, false);
275
- }
276
-
277
- export function useOptionalDependencies<T extends any[]>(...tokens: Tokens<T>) {
278
- return useDependenciesInternal(tokens, true);
279
- }