@adimm/x-injection-reactjs 0.1.0 → 0.1.1
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 +99 -62
- package/dist/index.cjs +8 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -2
- package/dist/index.d.ts +3 -2
- package/dist/index.js +22 -22
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -113,13 +113,18 @@ export const RandomNumberComponentModule = new ComponentProviderModule({
|
|
|
113
113
|
});
|
|
114
114
|
|
|
115
115
|
export function RandomNumberComponent(props: RandomNumberComponentProps) {
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
116
|
+
<ModuleProvider
|
|
117
|
+
module={RandomNumberComponentModule}
|
|
118
|
+
render={() => {
|
|
119
|
+
// This hook is necessary in order to expose the component instance
|
|
120
|
+
// context up to the parent component
|
|
121
|
+
useExposeComponentModuleContext();
|
|
122
|
+
|
|
123
|
+
const service = useInject(RandomNumberService);
|
|
124
|
+
|
|
125
|
+
return <h1>A random number: {service.generate()}</h1>;
|
|
126
|
+
}}
|
|
127
|
+
/>;
|
|
123
128
|
}
|
|
124
129
|
|
|
125
130
|
////////////////////////////////////////
|
|
@@ -139,39 +144,46 @@ export const ParentServiceComponentModule = new ComponentProviderModule({
|
|
|
139
144
|
});
|
|
140
145
|
|
|
141
146
|
export function ParentComponent(props: ParentComponentProps) {
|
|
142
|
-
const service = useInject(ParentService);
|
|
143
|
-
|
|
144
147
|
return (
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
148
|
+
<ModuleProvider
|
|
149
|
+
module={ParentServiceComponentModule}
|
|
150
|
+
render={() => {
|
|
151
|
+
const service = useInject(ParentService);
|
|
152
|
+
|
|
153
|
+
return (
|
|
154
|
+
<>
|
|
155
|
+
<TapIntoComponent
|
|
156
|
+
// By using the fluid syntax
|
|
157
|
+
contextInstance={() => ({
|
|
158
|
+
// If one of the children did expose the `RandomNumberComponentModule`
|
|
159
|
+
// module, we'll be able to access its instance.
|
|
160
|
+
tryGet: RandomNumberComponentModule,
|
|
161
|
+
thenDo: (ctx) => {
|
|
162
|
+
const randomNumberService_FromComponentInstance = ctx.get(RandomNumberComponentModule);
|
|
163
|
+
|
|
164
|
+
service.injectRandomNumberService(randomNumberService_FromComponentInstance);
|
|
165
|
+
},
|
|
166
|
+
})}>
|
|
167
|
+
<RandomNumberComponent />
|
|
168
|
+
</TapIntoComponent>
|
|
169
|
+
|
|
170
|
+
<TapIntoComponent
|
|
171
|
+
// By accessing the entire underlying context map which may contain even more
|
|
172
|
+
// modules exposed by more children down the tree.
|
|
173
|
+
contextInstance={(ctxMap) => {
|
|
174
|
+
const ctx = ctxMap.get(RandomNumberComponentModule.toString());
|
|
175
|
+
if (!ctx) return;
|
|
176
|
+
|
|
177
|
+
const randomNumberService_FromComponentInstance = ctx.get(RandomNumberComponentModule);
|
|
178
|
+
|
|
179
|
+
service.injectRandomNumberService(randomNumberService_FromComponentInstance);
|
|
180
|
+
}}>
|
|
181
|
+
<RandomNumberComponent />
|
|
182
|
+
</TapIntoComponent>
|
|
183
|
+
</>
|
|
184
|
+
);
|
|
185
|
+
}}
|
|
186
|
+
/>
|
|
175
187
|
);
|
|
176
188
|
}
|
|
177
189
|
```
|
|
@@ -183,32 +195,57 @@ or introduce unknown bugs, please use it carefully and with diligence!
|
|
|
183
195
|
|
|
184
196
|
```tsx
|
|
185
197
|
export function ParentComponent(props: ParentComponentProps) {
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
198
|
+
return (
|
|
199
|
+
<ModuleProvder
|
|
200
|
+
module={ParentServiceComponentModule}
|
|
201
|
+
render={() => {
|
|
202
|
+
// By using this hook, the component will always re-render whenever
|
|
203
|
+
// a child using a ProviderModule which is also imported into the parent ProviderModule,
|
|
204
|
+
// has mounted and rendered!
|
|
205
|
+
useRerenderOnChildrenModuleContextLoaded();
|
|
206
|
+
|
|
207
|
+
// We should use the `useInjectOnRender` instead of the default `useInject`
|
|
208
|
+
// hook which re-uses the same instance of the injected dependency
|
|
209
|
+
// between re-renders.
|
|
210
|
+
//
|
|
211
|
+
// Note: It may still work with the `useInject` hook too, but it may not be predictable.
|
|
212
|
+
const service = useInjectOnRender(ParentService);
|
|
213
|
+
|
|
214
|
+
// At this point the `service.randomNumberService` instance should be the one
|
|
215
|
+
// from the `RandomNumberComponent` below.
|
|
216
|
+
//
|
|
217
|
+
// Note: Expect during the 1st render cycle to not be the same instance as the one used by the child component!
|
|
218
|
+
// The `xInjection` container will still supply the correct provider to the
|
|
219
|
+
// constructor parameter, but it'll be a new transient instance.
|
|
220
|
+
console.log(service.randomNumberService.generate());
|
|
221
|
+
|
|
222
|
+
// As we are now using the `useRerenderOnChildrenModuleContextLoaded` hook
|
|
223
|
+
// there's no need anymore for the `TapIntoComponent` wrapper.
|
|
224
|
+
return <RandomNumberComponent />;
|
|
225
|
+
}}
|
|
226
|
+
/>
|
|
227
|
+
);
|
|
209
228
|
}
|
|
210
229
|
```
|
|
211
230
|
|
|
231
|
+
The `ModuleProvider` component also accepts the `children` prop, this means you can also use it like this:
|
|
232
|
+
|
|
233
|
+
```tsx
|
|
234
|
+
export function Component() {
|
|
235
|
+
return <h1>Hello World!</h1>;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
function MyApp() {
|
|
239
|
+
return (
|
|
240
|
+
<ModuleProvider module={ComponentModule}>
|
|
241
|
+
<Component />
|
|
242
|
+
</ModuleProvider>
|
|
243
|
+
);
|
|
244
|
+
}
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
> **Note:** You don't have to wrap your entire application with a `ModuleProvider` which provides the `AppModule`, the global container is already available to use and all your `ComponentProviderModule` know ouf-of-the-box how to access it when you provide them with providers registered into the `AppModule`.
|
|
248
|
+
|
|
212
249
|
## Documentation
|
|
213
250
|
|
|
214
251
|
Comprehensive, auto-generated documentation is available at:
|
package/dist/index.cjs
CHANGED
|
@@ -62,21 +62,21 @@ C.createContext)(p.AppModule), f = (0, C.createContext)(new Map), O = (0, C.crea
|
|
|
62
62
|
r: 0
|
|
63
63
|
}), x = require("react");
|
|
64
64
|
|
|
65
|
-
function M({children: e,
|
|
66
|
-
const
|
|
67
|
-
ctx:
|
|
65
|
+
function M({children: e, render: t, module: n, tryReInitModuleOnMount: o, disposeModuleOnUnmount: r}) {
|
|
66
|
+
const i = n.toNaked().isAppModule, u = (0, x.useCallback)((() => t?.()), []), s = {
|
|
67
|
+
ctx: i ? n : n.toNaked()._convertToContextualizedComponentInstance()
|
|
68
68
|
};
|
|
69
69
|
return React.createElement(m.Provider, {
|
|
70
|
-
value:
|
|
70
|
+
value: s
|
|
71
71
|
}, React.createElement(O.Provider, {
|
|
72
72
|
value: {
|
|
73
73
|
r: 0
|
|
74
74
|
}
|
|
75
75
|
}, React.createElement(_, {
|
|
76
|
-
children: e,
|
|
77
|
-
module:
|
|
78
|
-
tryReInitModuleOnMount:
|
|
79
|
-
disposeModuleOnUnmount:
|
|
76
|
+
children: e ?? React.createElement(u, null),
|
|
77
|
+
module: s,
|
|
78
|
+
tryReInitModuleOnMount: o,
|
|
79
|
+
disposeModuleOnUnmount: r
|
|
80
80
|
})));
|
|
81
81
|
}
|
|
82
82
|
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/helpers/hooks/use-once.ts","../src/helpers/hooks/use-effect-once.ts","../src/core/hooks/use-inject-on-render.ts","../src/core/providers/module-provider/react-context.ts","../src/core/providers/module-provider/module.provider.tsx","../src/core/hooks/use-inject.ts","../src/core/hooks/use-inject-many-on-render.ts","../src/core/hooks/use-inject-many.ts","../src/core/hooks/use-expose-component-module-context.ts","../src/core/hooks/use-rerender-on-children-module-context-loaded.ts","../src/core/component-provider-module.ts","../src/core/utils/tap-into-component-context/tap-into-component-context.tsx"],"sourcesContent":["export * from './core';\nexport type * from './types';\n","import { useRef } from 'react';\n\nexport function useOnce<T>(fn: () => T): T {\n const ref = useRef<OnceValue<T> | null>(null);\n\n if (ref.current === null) {\n ref.current = { value: fn() };\n }\n\n return ref.current?.value;\n}\n\ntype OnceValue<T> = { value: T };\n","import { useEffect, useRef, useState } from 'react';\n\n// Credits: https://stackoverflow.com/a/74000921\n\n/** Custom {@link useEffect} hook which will be run once. _(In `StrictMode` as well)_ */\nexport function useEffectOnce(effect: () => React.EffectCallback) {\n const destroyFunc = useRef<React.EffectCallback>(undefined);\n const effectCalled = useRef(false);\n const renderAfterCalled = useRef(false);\n const [, forceRerender] = useState(0);\n\n if (effectCalled.current) renderAfterCalled.current = true;\n\n useEffect(() => {\n // only execute the effect first time around\n if (!effectCalled.current) {\n destroyFunc.current = effect();\n effectCalled.current = true;\n }\n\n // this forces one render after the effect is run\n forceRerender((x) => x + 1);\n\n return () => {\n // if the comp didn't render since the useEffect was called,\n // we know it's the dummy React cycle\n if (!renderAfterCalled.current) return;\n\n destroyFunc.current?.();\n };\n }, []);\n}\n","import type { ProviderToken } from '@adimm/x-injection';\nimport { useContext } from 'react';\n\nimport type { UseInjectSharedOptions } from '../../types';\nimport { REACT_X_INJECTION_CONTEXT } from '../providers';\n\n/**\n * React `hook` which can be used inside a component to inject the required {@link provider | dependency}.\n *\n * **Note:** _By using this hook, the dependency will be injected on each re-render process._\n * _If you need to inject the dependency only once, you must use the `useInject` hook._\n * _It basically acts like a `Transient` scope, ensuring that a new dependency is injected on each re-render._\n *\n * @param provider The {@link ProviderToken}.\n * @param options See {@link UseInjectSharedOptions}.\n * @returns Either the {@link T | dependency} or `undefined` if {@link isOptional} is set to `true`.\n */\nexport function useInjectOnRender<T>(provider: ProviderToken<T>, options?: UseInjectOptions): T {\n const componentModule = useContext(REACT_X_INJECTION_CONTEXT);\n\n return componentModule.ctx.get(provider, options?.isOptional);\n}\n\nexport type UseInjectOptions = UseInjectSharedOptions & {\n /** When set to `false` _(default)_ an exception will be thrown when the `providerOrIdentifier` isn't bound. */\n isOptional?: boolean;\n};\n","import { AppModule } from '@adimm/x-injection';\nimport { createContext } from 'react';\n\nimport type { IComponentProviderModule } from '../../../types';\n\n/**\n * The `React.Context` value to be provided to a `React.Provider`.\n *\n * Its default value is a reference to the {@link AppModule}.\n */\nexport const REACT_X_INJECTION_CONTEXT = createContext<{ ctx: IComponentProviderModule }>(AppModule as any);\n\nexport const REACT_X_INJECTION_EXPOSED_COMPONENT_MODULE_CONTEXT = createContext<Map<string, IComponentProviderModule>>(\n new Map()\n);\n\nexport const REACT_X_INJECTION_EXPOSED_COMPONENT_RERENDER_ON_CTX_CHANGE = createContext<{ r: number }>({ r: 0 });\n","import { useContext, useMemo } from 'react';\nimport type { Except } from 'type-fest';\n\nimport { useEffectOnce } from '../../../helpers';\nimport type { IComponentProviderModule, IComponentProviderModuleNaked } from '../../../types';\nimport type { ModuleProviderProps } from './models';\nimport {\n REACT_X_INJECTION_CONTEXT,\n REACT_X_INJECTION_EXPOSED_COMPONENT_MODULE_CONTEXT,\n REACT_X_INJECTION_EXPOSED_COMPONENT_RERENDER_ON_CTX_CHANGE,\n} from './react-context';\n\nexport function ModuleProvider({\n children,\n module,\n tryReInitModuleOnMount,\n disposeModuleOnUnmount,\n}: ModuleProviderProps) {\n const isAppModule = module.toNaked().isAppModule;\n\n const moduleCtxReference = {\n ctx: useMemo(() => {\n return isAppModule ? module : module.toNaked()._convertToContextualizedComponentInstance();\n }, [children, module, tryReInitModuleOnMount, disposeModuleOnUnmount]),\n };\n\n return (\n <REACT_X_INJECTION_CONTEXT.Provider value={moduleCtxReference}>\n <REACT_X_INJECTION_EXPOSED_COMPONENT_RERENDER_ON_CTX_CHANGE.Provider value={{ r: 0 }}>\n <XInjectionChildrenRenderer\n children={children}\n module={moduleCtxReference}\n tryReInitModuleOnMount={tryReInitModuleOnMount}\n disposeModuleOnUnmount={disposeModuleOnUnmount}\n />\n </REACT_X_INJECTION_EXPOSED_COMPONENT_RERENDER_ON_CTX_CHANGE.Provider>\n </REACT_X_INJECTION_CONTEXT.Provider>\n );\n}\n\nfunction XInjectionChildrenRenderer({\n children,\n module,\n tryReInitModuleOnMount,\n disposeModuleOnUnmount = false,\n}: Except<ModuleProviderProps, 'module'> & { module: { ctx: IComponentProviderModule } }) {\n const componentModuleInstance = useContext(REACT_X_INJECTION_EXPOSED_COMPONENT_MODULE_CONTEXT);\n const rerenderParentCtx = useContext(REACT_X_INJECTION_EXPOSED_COMPONENT_RERENDER_ON_CTX_CHANGE);\n\n // We use the `useEffectOnce` custom hook in order\n // to make sure that if the developer is providing the\n // `tryReInitModuleOnMount` and/or `disposeModuleOnUnmount` options\n // we do not early dispose the module when React double re-renders the\n // component while StrictMode is enabled.\n // This hook guarantees that the same behavior is expected with or without StrictMode.\n //\n // https://react.dev/reference/react/StrictMode\n useEffectOnce(() => {\n // ON MOUNT\n\n const moduleNaked = module.ctx.toNaked();\n\n if (componentModuleInstance) {\n const contextualizedImportedModules = module.ctx.toNaked().imports.map((importedModule) => {\n const shouldReplaceImportedModuleWithContextualized =\n componentModuleInstance.get(importedModule.toString())?.toString() === importedModule.toString();\n\n /* istanbul ignore next */\n if (!shouldReplaceImportedModuleWithContextualized)\n return importedModule as unknown as IComponentProviderModuleNaked;\n\n return componentModuleInstance.get(importedModule.toString()) as IComponentProviderModuleNaked;\n });\n\n if (contextualizedImportedModules.length > 0) {\n module.ctx.toNaked()._lazyInit({\n ...module.ctx.toNaked()._initialOptions,\n imports: contextualizedImportedModules,\n });\n\n // This will force the parent to re-render when using the `useRerenderOnChildrenModuleContextLoaded` hook.\n rerenderParentCtx.r++;\n }\n }\n\n /* istanbul ignore next */\n if (moduleNaked.isDisposed && tryReInitModuleOnMount) {\n /* istanbul ignore next */\n moduleNaked._lazyInit(tryReInitModuleOnMount);\n }\n\n return () => {\n // ON UNMOUNT\n\n if (!disposeModuleOnUnmount || moduleNaked.isDisposed) return;\n\n moduleNaked._dispose();\n };\n });\n\n return children;\n}\n","import type { ProviderToken } from '@adimm/x-injection';\n\nimport { useOnce } from '../../helpers';\nimport { useInjectOnRender, type UseInjectOptions } from './use-inject-on-render';\n\n/**\n * React `hook` which can be used inside a component to inject the required {@link provider | dependency}.\n *\n * **Note:** _By using this hook, the dependency will be injected only once after the first component mount process._\n * _If you need to re-inject the dependency on each re-render, you must use the `useInjectOnRender` hook._\n * _It basically acts like a `Request` scope, ensuring that even a `Transient` dependency does not mutate during re-renders._\n *\n * @param provider The {@link ProviderToken}.\n * @param options See {@link UseInjectSharedOptions}.\n * @returns Either the {@link T | dependency} or `undefined` if {@link isOptional} is set to `true`.\n */\nexport function useInject<T>(provider: ProviderToken<T>, options?: UseInjectOptions): T {\n return useOnce(() => useInjectOnRender(provider, options));\n}\n","import type {\n ProviderModuleGetManyParam,\n ProviderModuleGetManySignature,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n ProviderToken,\n} from '@adimm/x-injection';\nimport { useContext } from 'react';\n\nimport type { UseInjectSharedOptions } from '../../types';\nimport { REACT_X_INJECTION_CONTEXT } from '../providers';\n\n/**\n * Can be used to retrieve many resolved `dependencies` from the module container at once.\n *\n * **Note:** _By using this hook, the dependencies will be injected on each re-render process._\n * _If you need to inject the dependencies only once, you must use the `useInjectMany` hook._\n *\n * @param options See {@link UseInjectSharedOptions}.\n * @param deps Either one or more {@link ProviderToken}.\n * @returns Tuple containing the {@link D | dependencies}.\n */\nexport function useInjectManyOnRender<D extends (ProviderModuleGetManyParam<any> | ProviderToken)[]>({\n deps,\n}: {\n deps: [...(D | unknown[])];\n options?: UseInjectSharedOptions;\n}): ProviderModuleGetManySignature<D> {\n const componentModule = useContext(REACT_X_INJECTION_CONTEXT);\n\n return componentModule.ctx.getMany(...deps);\n}\n","import type { ProviderModuleGetManyParam, ProviderModuleGetManySignature, ProviderToken } from '@adimm/x-injection';\n\nimport { useOnce } from '../../helpers';\nimport type { UseInjectSharedOptions } from '../../types';\nimport { useInjectManyOnRender } from './use-inject-many-on-render';\n\n/**\n * Can be used to retrieve many resolved `dependencies` from the module container at once.\n *\n * **Note:** _By using this hook, the dependencies will be injected only once after the first component mount process._\n * _If you need to re-inject the dependencies on each re-render, you must use the `useInjectManyOnRender` hook._\n *\n * @param options See {@link UseInjectSharedOptions}.\n * @param deps Either one or more {@link ProviderToken}.\n * @returns Tuple containing the {@link D | dependencies}.\n */\nexport function useInjectMany<D extends (ProviderModuleGetManyParam<any> | ProviderToken)[]>({\n deps,\n options,\n}: {\n deps: [...(D | unknown[])];\n options?: UseInjectSharedOptions;\n}): ProviderModuleGetManySignature<D> {\n return useOnce(() => useInjectManyOnRender({ options, deps }));\n}\n","import { useContext } from 'react';\n\nimport { REACT_X_INJECTION_CONTEXT, REACT_X_INJECTION_EXPOSED_COMPONENT_MODULE_CONTEXT } from '../providers';\n\nexport function useExposeComponentModuleContext(): void {\n const componentModule = useContext(REACT_X_INJECTION_CONTEXT);\n const exposed = useContext(REACT_X_INJECTION_EXPOSED_COMPONENT_MODULE_CONTEXT);\n\n exposed.set(componentModule.ctx.toString(), componentModule.ctx);\n}\n","import { useContext, useEffect, useState } from 'react';\n\nimport { REACT_X_INJECTION_EXPOSED_COMPONENT_RERENDER_ON_CTX_CHANGE } from '../providers';\n\n/**\n * This is an **experimental** hook which can be used to make sure that a component will re-render when a children\n * exposes its internal context module.\n *\n * It works best with the `useInjectOnRender` hook, as it'll re-resolve all the required dependencies\n * of the injected ProviderToken.\n *\n * **Use it carefully as it may lead to unnecessary re-render cycles or it may even not work as expected!**\n * **It's safer to use the `TapIntoComponent` wrapper component with the `contextInstance` to manually inject the**\n * **contextualized dependencies of the children into a parent component service!**\n *\n * @experimental\n */\nexport function useRerenderOnChildrenModuleContextLoaded(): void {\n const rerenderParentCtx = useContext(REACT_X_INJECTION_EXPOSED_COMPONENT_RERENDER_ON_CTX_CHANGE);\n const [, setRerender] = useState(0);\n\n useEffect(() => {\n setRerender((x) => x + 1);\n }, [rerenderParentCtx.r]);\n}\n","import {\n InjectionScope,\n isClass,\n isClassOrFunction,\n ProviderModule,\n ProviderModuleHelpers,\n type DependencyProvider,\n type IProviderModuleNaked,\n type ProviderClassToken,\n type ProviderModuleOptions,\n type ProviderValueToken,\n} from '@adimm/x-injection';\n\nimport type { IComponentProviderModule, IComponentProviderModuleNaked } from '../types';\n\n/** A superset of the {@link ProviderModule} used to integrate within a `React` component. */\nexport class ComponentProviderModule extends ProviderModule implements IComponentProviderModule {\n protected readonly _initializedFromComponent: IComponentProviderModuleNaked['_initializedFromComponent'];\n protected readonly _initialOptions: IComponentProviderModuleNaked['_initialOptions'];\n\n constructor(options: ProviderModuleOptions) {\n super(\n ProviderModuleHelpers.buildInternalConstructorParams({\n ...options,\n // By default components should have all their providers\n // defined as transient because a component may have more than one instance of itself.\n defaultScope: options.defaultScope ?? InjectionScope.Transient,\n identifier: Symbol(`Component${options.identifier.description}`),\n })\n );\n\n this._initializedFromComponent = false;\n this._initialOptions = options;\n }\n\n override toNaked(): IComponentProviderModuleNaked & IProviderModuleNaked {\n return this as any;\n }\n\n /* istanbul ignore next */\n dispose(): void {\n this._dispose();\n }\n\n /**\n * **Publicly visible when the instance is casted to {@link IComponentProviderModuleNaked}.**\n *\n * See {@link IComponentProviderModuleNaked._convertToContextualizedComponentInstance}.\n */\n /* istanbul ignore next */\n protected _convertToContextualizedComponentInstance(): IComponentProviderModule {\n if (this.isAppModule || this.isDisposed) return this;\n\n const contextualizedProviders = this._getProviders().map((provider) => {\n if (!isClassOrFunction(provider)) {\n return {\n ...provider,\n scope: InjectionScope.Singleton,\n } as DependencyProvider;\n }\n\n if (isClass(provider)) {\n return {\n scope: InjectionScope.Singleton,\n provide: provider,\n useClass: provider,\n } as ProviderClassToken<any>;\n }\n\n return {\n provide: provider,\n useValue: provider,\n } as ProviderValueToken<any>;\n });\n\n const componentModule = new ComponentProviderModule({\n ...this._initialOptions,\n providers: contextualizedProviders,\n });\n\n //@ts-expect-error Read-only property.\n componentModule._initializedFromComponent = true;\n\n return componentModule;\n }\n}\n","import { useContext, useEffect, useMemo } from 'react';\nimport type { Except } from 'type-fest';\n\nimport { REACT_X_INJECTION_EXPOSED_COMPONENT_MODULE_CONTEXT } from '../../providers';\nimport type { TapIntoComponentContextProps } from './interfaces';\n\n/**\n * This component is the standard way to \"tap into\" an instance of the component\n * in order to get access to its scoped module container and its _(exposed)_ dependencies _instances_.\n *\n * @param contextInstance See {@link TapIntoComponentContextProps.contextInstance}.\n * @param exposed See {@link TapIntoComponentContextProps.exposed}.\n */\nexport function TapIntoComponent({ children, contextInstance }: TapIntoComponentContextProps) {\n const moduleContextMap = useMemo(() => new Map(), []);\n\n return (\n <REACT_X_INJECTION_EXPOSED_COMPONENT_MODULE_CONTEXT.Provider value={moduleContextMap}>\n <CtxExposer contextInstance={contextInstance} />\n {children}\n </REACT_X_INJECTION_EXPOSED_COMPONENT_MODULE_CONTEXT.Provider>\n );\n}\n\nfunction CtxExposer({ contextInstance }: Except<TapIntoComponentContextProps, 'children'>) {\n const ctxMap = useContext(REACT_X_INJECTION_EXPOSED_COMPONENT_MODULE_CONTEXT);\n\n useEffect(() => {\n const fluidSyntax = contextInstance?.(ctxMap);\n if (!fluidSyntax) return;\n\n const moduleCtx = ctxMap.get(fluidSyntax.tryGet.toString());\n /* istanbul ignore next */\n if (!moduleCtx) return;\n\n fluidSyntax.thenDo(moduleCtx);\n }, [ctxMap]);\n\n return null;\n}\n"],"mappings":"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","names":["useOnce","fn","ref","useRef","current","value","import_react","useEffectOnce","effect","destroyFunc","useRef","undefined","effectCalled","renderAfterCalled","forceRerender","useState","current","useEffect","x","import_react","import_react","REACT_X_INJECTION_CONTEXT","createContext","AppModule","REACT_X_INJECTION_EXPOSED_COMPONENT_MODULE_CONTEXT","Map","REACT_X_INJECTION_EXPOSED_COMPONENT_RERENDER_ON_CTX_CHANGE","r","import_react","ModuleProvider","children","module","tryReInitModuleOnMount","disposeModuleOnUnmount","isAppModule","toNaked","moduleCtxReference","ctx","useMemo","_convertToContextualizedComponentInstance","REACT_X_INJECTION_CONTEXT","Provider","value","REACT_X_INJECTION_EXPOSED_COMPONENT_RERENDER_ON_CTX_CHANGE","r","XInjectionChildrenRenderer","componentModuleInstance","useContext","REACT_X_INJECTION_EXPOSED_COMPONENT_MODULE_CONTEXT","rerenderParentCtx","useEffectOnce","moduleNaked","contextualizedImportedModules","imports","map","importedModule","shouldReplaceImportedModuleWithContextualized","get","toString","length","_lazyInit","_initialOptions","isDisposed","_dispose","useInjectOnRender","provider","options","componentModule","useContext","REACT_X_INJECTION_CONTEXT","ctx","get","isOptional","useInject","provider","options","useOnce","useInjectOnRender","import_react","useInjectManyOnRender","deps","componentModule","useContext","REACT_X_INJECTION_CONTEXT","ctx","getMany","useInjectMany","deps","options","useOnce","useInjectManyOnRender","import_react","useExposeComponentModuleContext","componentModule","useContext","REACT_X_INJECTION_CONTEXT","exposed","REACT_X_INJECTION_EXPOSED_COMPONENT_MODULE_CONTEXT","set","ctx","toString","import_react","useRerenderOnChildrenModuleContextLoaded","rerenderParentCtx","useContext","REACT_X_INJECTION_EXPOSED_COMPONENT_RERENDER_ON_CTX_CHANGE","setRerender","useState","useEffect","x","r","import_x_injection","ComponentProviderModule","ProviderModule","_initializedFromComponent","_initialOptions","constructor","options","ProviderModuleHelpers","buildInternalConstructorParams","defaultScope","InjectionScope","Transient","identifier","Symbol","description","toNaked","dispose","_dispose","_convertToContextualizedComponentInstance","isAppModule","isDisposed","contextualizedProviders","_getProviders","map","provider","isClassOrFunction","scope","Singleton","isClass","provide","useClass","useValue","componentModule","providers","import_react","TapIntoComponent","children","contextInstance","moduleContextMap","useMemo","Map","REACT_X_INJECTION_EXPOSED_COMPONENT_MODULE_CONTEXT","Provider","value","CtxExposer","ctxMap","useContext","useEffect","fluidSyntax","moduleCtx","get","tryGet","toString","thenDo"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/helpers/hooks/use-once.ts","../src/helpers/hooks/use-effect-once.ts","../src/core/hooks/use-inject-on-render.ts","../src/core/providers/module-provider/react-context.ts","../src/core/providers/module-provider/module.provider.tsx","../src/core/hooks/use-inject.ts","../src/core/hooks/use-inject-many-on-render.ts","../src/core/hooks/use-inject-many.ts","../src/core/hooks/use-expose-component-module-context.ts","../src/core/hooks/use-rerender-on-children-module-context-loaded.ts","../src/core/component-provider-module.ts","../src/core/utils/tap-into-component-context/tap-into-component-context.tsx"],"sourcesContent":["export * from './core';\nexport type * from './types';\n","import { useRef } from 'react';\n\nexport function useOnce<T>(fn: () => T): T {\n const ref = useRef<OnceValue<T> | null>(null);\n\n if (ref.current === null) {\n ref.current = { value: fn() };\n }\n\n return ref.current?.value;\n}\n\ntype OnceValue<T> = { value: T };\n","import { useEffect, useRef, useState } from 'react';\n\n// Credits: https://stackoverflow.com/a/74000921\n\n/** Custom {@link useEffect} hook which will be run once. _(In `StrictMode` as well)_ */\nexport function useEffectOnce(effect: () => React.EffectCallback) {\n const destroyFunc = useRef<React.EffectCallback>(undefined);\n const effectCalled = useRef(false);\n const renderAfterCalled = useRef(false);\n const [, forceRerender] = useState(0);\n\n if (effectCalled.current) renderAfterCalled.current = true;\n\n useEffect(() => {\n // only execute the effect first time around\n if (!effectCalled.current) {\n destroyFunc.current = effect();\n effectCalled.current = true;\n }\n\n // this forces one render after the effect is run\n forceRerender((x) => x + 1);\n\n return () => {\n // if the comp didn't render since the useEffect was called,\n // we know it's the dummy React cycle\n if (!renderAfterCalled.current) return;\n\n destroyFunc.current?.();\n };\n }, []);\n}\n","import type { ProviderToken } from '@adimm/x-injection';\nimport { useContext } from 'react';\n\nimport type { UseInjectSharedOptions } from '../../types';\nimport { REACT_X_INJECTION_CONTEXT } from '../providers';\n\n/**\n * React `hook` which can be used inside a component to inject the required {@link provider | dependency}.\n *\n * **Note:** _By using this hook, the dependency will be injected on each re-render process._\n * _If you need to inject the dependency only once, you must use the `useInject` hook._\n * _It basically acts like a `Transient` scope, ensuring that a new dependency is injected on each re-render._\n *\n * @param provider The {@link ProviderToken}.\n * @param options See {@link UseInjectSharedOptions}.\n * @returns Either the {@link T | dependency} or `undefined` if {@link isOptional} is set to `true`.\n */\nexport function useInjectOnRender<T>(provider: ProviderToken<T>, options?: UseInjectOptions): T {\n const componentModule = useContext(REACT_X_INJECTION_CONTEXT);\n\n return componentModule.ctx.get(provider, options?.isOptional);\n}\n\nexport type UseInjectOptions = UseInjectSharedOptions & {\n /** When set to `false` _(default)_ an exception will be thrown when the `providerOrIdentifier` isn't bound. */\n isOptional?: boolean;\n};\n","import { AppModule } from '@adimm/x-injection';\nimport { createContext } from 'react';\n\nimport type { IComponentProviderModule } from '../../../types';\n\n/**\n * The `React.Context` value to be provided to a `React.Provider`.\n *\n * Its default value is a reference to the {@link AppModule}.\n */\nexport const REACT_X_INJECTION_CONTEXT = createContext<{ ctx: IComponentProviderModule }>(AppModule as any);\n\nexport const REACT_X_INJECTION_EXPOSED_COMPONENT_MODULE_CONTEXT = createContext<Map<string, IComponentProviderModule>>(\n new Map()\n);\n\nexport const REACT_X_INJECTION_EXPOSED_COMPONENT_RERENDER_ON_CTX_CHANGE = createContext<{ r: number }>({ r: 0 });\n","import { useCallback, useContext } from 'react';\nimport type { Except } from 'type-fest';\n\nimport { useEffectOnce } from '../../../helpers';\nimport type { IComponentProviderModule, IComponentProviderModuleNaked } from '../../../types';\nimport type { ModuleProviderProps } from './models';\nimport {\n REACT_X_INJECTION_CONTEXT,\n REACT_X_INJECTION_EXPOSED_COMPONENT_MODULE_CONTEXT,\n REACT_X_INJECTION_EXPOSED_COMPONENT_RERENDER_ON_CTX_CHANGE,\n} from './react-context';\n\nexport function ModuleProvider({\n children,\n render,\n module,\n tryReInitModuleOnMount,\n disposeModuleOnUnmount,\n}: ModuleProviderProps) {\n const isAppModule = module.toNaked().isAppModule;\n const Renderer = useCallback(() => render?.(), []);\n\n const moduleCtxReference = {\n ctx: isAppModule ? module : module.toNaked()._convertToContextualizedComponentInstance(),\n };\n\n return (\n <REACT_X_INJECTION_CONTEXT.Provider value={moduleCtxReference}>\n <REACT_X_INJECTION_EXPOSED_COMPONENT_RERENDER_ON_CTX_CHANGE.Provider value={{ r: 0 }}>\n <XInjectionChildrenRenderer\n children={children ?? <Renderer />}\n module={moduleCtxReference}\n tryReInitModuleOnMount={tryReInitModuleOnMount}\n disposeModuleOnUnmount={disposeModuleOnUnmount}\n />\n </REACT_X_INJECTION_EXPOSED_COMPONENT_RERENDER_ON_CTX_CHANGE.Provider>\n </REACT_X_INJECTION_CONTEXT.Provider>\n );\n}\n\nfunction XInjectionChildrenRenderer({\n children,\n module,\n tryReInitModuleOnMount,\n disposeModuleOnUnmount = false,\n}: Except<ModuleProviderProps, 'module'> & { module: { ctx: IComponentProviderModule } }) {\n const componentModuleInstance = useContext(REACT_X_INJECTION_EXPOSED_COMPONENT_MODULE_CONTEXT);\n const rerenderParentCtx = useContext(REACT_X_INJECTION_EXPOSED_COMPONENT_RERENDER_ON_CTX_CHANGE);\n\n // We use the `useEffectOnce` custom hook in order\n // to make sure that if the developer is providing the\n // `tryReInitModuleOnMount` and/or `disposeModuleOnUnmount` options\n // we do not early dispose the module when React double re-renders the\n // component while StrictMode is enabled.\n // This hook guarantees that the same behavior is expected with or without StrictMode.\n //\n // https://react.dev/reference/react/StrictMode\n useEffectOnce(() => {\n // ON MOUNT\n\n const moduleNaked = module.ctx.toNaked();\n\n if (componentModuleInstance) {\n const contextualizedImportedModules = module.ctx.toNaked().imports.map((importedModule) => {\n const shouldReplaceImportedModuleWithContextualized =\n componentModuleInstance.get(importedModule.toString())?.toString() === importedModule.toString();\n\n /* istanbul ignore next */\n if (!shouldReplaceImportedModuleWithContextualized)\n return importedModule as unknown as IComponentProviderModuleNaked;\n\n return componentModuleInstance.get(importedModule.toString()) as IComponentProviderModuleNaked;\n });\n\n if (contextualizedImportedModules.length > 0) {\n module.ctx.toNaked()._lazyInit({\n ...module.ctx.toNaked()._initialOptions,\n imports: contextualizedImportedModules,\n });\n\n // This will force the parent to re-render when using the `useRerenderOnChildrenModuleContextLoaded` hook.\n rerenderParentCtx.r++;\n }\n }\n\n /* istanbul ignore next */\n if (moduleNaked.isDisposed && tryReInitModuleOnMount) {\n /* istanbul ignore next */\n moduleNaked._lazyInit(tryReInitModuleOnMount);\n }\n\n return () => {\n // ON UNMOUNT\n\n if (!disposeModuleOnUnmount || moduleNaked.isDisposed) return;\n\n moduleNaked._dispose();\n };\n });\n\n return children;\n}\n","import type { ProviderToken } from '@adimm/x-injection';\n\nimport { useOnce } from '../../helpers';\nimport { useInjectOnRender, type UseInjectOptions } from './use-inject-on-render';\n\n/**\n * React `hook` which can be used inside a component to inject the required {@link provider | dependency}.\n *\n * **Note:** _By using this hook, the dependency will be injected only once after the first component mount process._\n * _If you need to re-inject the dependency on each re-render, you must use the `useInjectOnRender` hook._\n * _It basically acts like a `Request` scope, ensuring that even a `Transient` dependency does not mutate during re-renders._\n *\n * @param provider The {@link ProviderToken}.\n * @param options See {@link UseInjectSharedOptions}.\n * @returns Either the {@link T | dependency} or `undefined` if {@link isOptional} is set to `true`.\n */\nexport function useInject<T>(provider: ProviderToken<T>, options?: UseInjectOptions): T {\n return useOnce(() => useInjectOnRender(provider, options));\n}\n","import type {\n ProviderModuleGetManyParam,\n ProviderModuleGetManySignature,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n ProviderToken,\n} from '@adimm/x-injection';\nimport { useContext } from 'react';\n\nimport type { UseInjectSharedOptions } from '../../types';\nimport { REACT_X_INJECTION_CONTEXT } from '../providers';\n\n/**\n * Can be used to retrieve many resolved `dependencies` from the module container at once.\n *\n * **Note:** _By using this hook, the dependencies will be injected on each re-render process._\n * _If you need to inject the dependencies only once, you must use the `useInjectMany` hook._\n *\n * @param options See {@link UseInjectSharedOptions}.\n * @param deps Either one or more {@link ProviderToken}.\n * @returns Tuple containing the {@link D | dependencies}.\n */\nexport function useInjectManyOnRender<D extends (ProviderModuleGetManyParam<any> | ProviderToken)[]>({\n deps,\n}: {\n deps: [...(D | unknown[])];\n options?: UseInjectSharedOptions;\n}): ProviderModuleGetManySignature<D> {\n const componentModule = useContext(REACT_X_INJECTION_CONTEXT);\n\n return componentModule.ctx.getMany(...deps);\n}\n","import type { ProviderModuleGetManyParam, ProviderModuleGetManySignature, ProviderToken } from '@adimm/x-injection';\n\nimport { useOnce } from '../../helpers';\nimport type { UseInjectSharedOptions } from '../../types';\nimport { useInjectManyOnRender } from './use-inject-many-on-render';\n\n/**\n * Can be used to retrieve many resolved `dependencies` from the module container at once.\n *\n * **Note:** _By using this hook, the dependencies will be injected only once after the first component mount process._\n * _If you need to re-inject the dependencies on each re-render, you must use the `useInjectManyOnRender` hook._\n *\n * @param options See {@link UseInjectSharedOptions}.\n * @param deps Either one or more {@link ProviderToken}.\n * @returns Tuple containing the {@link D | dependencies}.\n */\nexport function useInjectMany<D extends (ProviderModuleGetManyParam<any> | ProviderToken)[]>({\n deps,\n options,\n}: {\n deps: [...(D | unknown[])];\n options?: UseInjectSharedOptions;\n}): ProviderModuleGetManySignature<D> {\n return useOnce(() => useInjectManyOnRender({ options, deps }));\n}\n","import { useContext } from 'react';\n\nimport { REACT_X_INJECTION_CONTEXT, REACT_X_INJECTION_EXPOSED_COMPONENT_MODULE_CONTEXT } from '../providers';\n\nexport function useExposeComponentModuleContext(): void {\n const componentModule = useContext(REACT_X_INJECTION_CONTEXT);\n const exposed = useContext(REACT_X_INJECTION_EXPOSED_COMPONENT_MODULE_CONTEXT);\n\n exposed.set(componentModule.ctx.toString(), componentModule.ctx);\n}\n","import { useContext, useEffect, useState } from 'react';\n\nimport { REACT_X_INJECTION_EXPOSED_COMPONENT_RERENDER_ON_CTX_CHANGE } from '../providers';\n\n/**\n * This is an **experimental** hook which can be used to make sure that a component will re-render when a children\n * exposes its internal context module.\n *\n * It works best with the `useInjectOnRender` hook, as it'll re-resolve all the required dependencies\n * of the injected ProviderToken.\n *\n * **Use it carefully as it may lead to unnecessary re-render cycles or it may even not work as expected!**\n * **It's safer to use the `TapIntoComponent` wrapper component with the `contextInstance` to manually inject the**\n * **contextualized dependencies of the children into a parent component service!**\n *\n * @experimental\n */\nexport function useRerenderOnChildrenModuleContextLoaded(): void {\n const rerenderParentCtx = useContext(REACT_X_INJECTION_EXPOSED_COMPONENT_RERENDER_ON_CTX_CHANGE);\n const [, setRerender] = useState(0);\n\n useEffect(() => {\n setRerender((x) => x + 1);\n }, [rerenderParentCtx.r]);\n}\n","import {\n InjectionScope,\n isClass,\n isClassOrFunction,\n ProviderModule,\n ProviderModuleHelpers,\n type DependencyProvider,\n type IProviderModuleNaked,\n type ProviderClassToken,\n type ProviderModuleOptions,\n type ProviderValueToken,\n} from '@adimm/x-injection';\n\nimport type { IComponentProviderModule, IComponentProviderModuleNaked } from '../types';\n\n/** A superset of the {@link ProviderModule} used to integrate within a `React` component. */\nexport class ComponentProviderModule extends ProviderModule implements IComponentProviderModule {\n protected readonly _initializedFromComponent: IComponentProviderModuleNaked['_initializedFromComponent'];\n protected readonly _initialOptions: IComponentProviderModuleNaked['_initialOptions'];\n\n constructor(options: ProviderModuleOptions) {\n super(\n ProviderModuleHelpers.buildInternalConstructorParams({\n ...options,\n // By default components should have all their providers\n // defined as transient because a component may have more than one instance of itself.\n defaultScope: options.defaultScope ?? InjectionScope.Transient,\n identifier: Symbol(`Component${options.identifier.description}`),\n })\n );\n\n this._initializedFromComponent = false;\n this._initialOptions = options;\n }\n\n override toNaked(): IComponentProviderModuleNaked & IProviderModuleNaked {\n return this as any;\n }\n\n /* istanbul ignore next */\n dispose(): void {\n this._dispose();\n }\n\n /**\n * **Publicly visible when the instance is casted to {@link IComponentProviderModuleNaked}.**\n *\n * See {@link IComponentProviderModuleNaked._convertToContextualizedComponentInstance}.\n */\n /* istanbul ignore next */\n protected _convertToContextualizedComponentInstance(): IComponentProviderModule {\n if (this.isAppModule || this.isDisposed) return this;\n\n const contextualizedProviders = this._getProviders().map((provider) => {\n if (!isClassOrFunction(provider)) {\n return {\n ...provider,\n scope: InjectionScope.Singleton,\n } as DependencyProvider;\n }\n\n if (isClass(provider)) {\n return {\n scope: InjectionScope.Singleton,\n provide: provider,\n useClass: provider,\n } as ProviderClassToken<any>;\n }\n\n return {\n provide: provider,\n useValue: provider,\n } as ProviderValueToken<any>;\n });\n\n const componentModule = new ComponentProviderModule({\n ...this._initialOptions,\n providers: contextualizedProviders,\n });\n\n //@ts-expect-error Read-only property.\n componentModule._initializedFromComponent = true;\n\n return componentModule;\n }\n}\n","import { useContext, useEffect, useMemo } from 'react';\nimport type { Except } from 'type-fest';\n\nimport { REACT_X_INJECTION_EXPOSED_COMPONENT_MODULE_CONTEXT } from '../../providers';\nimport type { TapIntoComponentContextProps } from './interfaces';\n\n/**\n * This component is the standard way to \"tap into\" an instance of the component\n * in order to get access to its scoped module container and its _(exposed)_ dependencies _instances_.\n *\n * @param contextInstance See {@link TapIntoComponentContextProps.contextInstance}.\n * @param exposed See {@link TapIntoComponentContextProps.exposed}.\n */\nexport function TapIntoComponent({ children, contextInstance }: TapIntoComponentContextProps) {\n const moduleContextMap = useMemo(() => new Map(), []);\n\n return (\n <REACT_X_INJECTION_EXPOSED_COMPONENT_MODULE_CONTEXT.Provider value={moduleContextMap}>\n <CtxExposer contextInstance={contextInstance} />\n {children}\n </REACT_X_INJECTION_EXPOSED_COMPONENT_MODULE_CONTEXT.Provider>\n );\n}\n\nfunction CtxExposer({ contextInstance }: Except<TapIntoComponentContextProps, 'children'>) {\n const ctxMap = useContext(REACT_X_INJECTION_EXPOSED_COMPONENT_MODULE_CONTEXT);\n\n useEffect(() => {\n const fluidSyntax = contextInstance?.(ctxMap);\n if (!fluidSyntax) return;\n\n const moduleCtx = ctxMap.get(fluidSyntax.tryGet.toString());\n /* istanbul ignore next */\n if (!moduleCtx) return;\n\n fluidSyntax.thenDo(moduleCtx);\n }, [ctxMap]);\n\n return null;\n}\n"],"mappings":"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","names":["useOnce","fn","ref","useRef","current","value","import_react","useEffectOnce","effect","destroyFunc","useRef","undefined","effectCalled","renderAfterCalled","forceRerender","useState","current","useEffect","x","import_react","import_react","REACT_X_INJECTION_CONTEXT","createContext","AppModule","REACT_X_INJECTION_EXPOSED_COMPONENT_MODULE_CONTEXT","Map","REACT_X_INJECTION_EXPOSED_COMPONENT_RERENDER_ON_CTX_CHANGE","r","import_react","ModuleProvider","children","render","module","tryReInitModuleOnMount","disposeModuleOnUnmount","isAppModule","toNaked","Renderer","useCallback","moduleCtxReference","ctx","_convertToContextualizedComponentInstance","REACT_X_INJECTION_CONTEXT","Provider","value","REACT_X_INJECTION_EXPOSED_COMPONENT_RERENDER_ON_CTX_CHANGE","r","XInjectionChildrenRenderer","componentModuleInstance","useContext","REACT_X_INJECTION_EXPOSED_COMPONENT_MODULE_CONTEXT","rerenderParentCtx","useEffectOnce","moduleNaked","contextualizedImportedModules","imports","map","importedModule","shouldReplaceImportedModuleWithContextualized","get","toString","length","_lazyInit","_initialOptions","isDisposed","_dispose","useInjectOnRender","provider","options","componentModule","useContext","REACT_X_INJECTION_CONTEXT","ctx","get","isOptional","useInject","provider","options","useOnce","useInjectOnRender","import_react","useInjectManyOnRender","deps","componentModule","useContext","REACT_X_INJECTION_CONTEXT","ctx","getMany","useInjectMany","deps","options","useOnce","useInjectManyOnRender","import_react","useExposeComponentModuleContext","componentModule","useContext","REACT_X_INJECTION_CONTEXT","exposed","REACT_X_INJECTION_EXPOSED_COMPONENT_MODULE_CONTEXT","set","ctx","toString","import_react","useRerenderOnChildrenModuleContextLoaded","rerenderParentCtx","useContext","REACT_X_INJECTION_EXPOSED_COMPONENT_RERENDER_ON_CTX_CHANGE","setRerender","useState","useEffect","x","r","import_x_injection","ComponentProviderModule","ProviderModule","_initializedFromComponent","_initialOptions","constructor","options","ProviderModuleHelpers","buildInternalConstructorParams","defaultScope","InjectionScope","Transient","identifier","Symbol","description","toNaked","dispose","_dispose","_convertToContextualizedComponentInstance","isAppModule","isDisposed","contextualizedProviders","_getProviders","map","provider","isClassOrFunction","scope","Singleton","isClass","provide","useClass","useValue","componentModule","providers","import_react","TapIntoComponent","children","contextInstance","moduleContextMap","useMemo","Map","REACT_X_INJECTION_EXPOSED_COMPONENT_MODULE_CONTEXT","Provider","value","CtxExposer","ctxMap","useContext","useEffect","fluidSyntax","moduleCtx","get","tryGet","toString","thenDo"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -124,7 +124,8 @@ declare const REACT_X_INJECTION_EXPOSED_COMPONENT_RERENDER_ON_CTX_CHANGE: react.
|
|
|
124
124
|
}>;
|
|
125
125
|
|
|
126
126
|
interface ModuleProviderProps {
|
|
127
|
-
children
|
|
127
|
+
children?: React.ReactNode;
|
|
128
|
+
render?: () => React.ReactNode;
|
|
128
129
|
/** The {@link IComponentProviderModule | ComponentProviderModule} instance which must be accessible by this component. */
|
|
129
130
|
module: IComponentProviderModule;
|
|
130
131
|
/**
|
|
@@ -150,7 +151,7 @@ interface ModuleProviderProps {
|
|
|
150
151
|
disposeModuleOnUnmount?: boolean;
|
|
151
152
|
}
|
|
152
153
|
|
|
153
|
-
declare function ModuleProvider({ children, module, tryReInitModuleOnMount, disposeModuleOnUnmount, }: ModuleProviderProps): react_jsx_runtime.JSX.Element;
|
|
154
|
+
declare function ModuleProvider({ children, render, module, tryReInitModuleOnMount, disposeModuleOnUnmount, }: ModuleProviderProps): react_jsx_runtime.JSX.Element;
|
|
154
155
|
|
|
155
156
|
/** A superset of the {@link ProviderModule} used to integrate within a `React` component. */
|
|
156
157
|
declare class ComponentProviderModule extends ProviderModule implements IComponentProviderModule {
|
package/dist/index.d.ts
CHANGED
|
@@ -124,7 +124,8 @@ declare const REACT_X_INJECTION_EXPOSED_COMPONENT_RERENDER_ON_CTX_CHANGE: react.
|
|
|
124
124
|
}>;
|
|
125
125
|
|
|
126
126
|
interface ModuleProviderProps {
|
|
127
|
-
children
|
|
127
|
+
children?: React.ReactNode;
|
|
128
|
+
render?: () => React.ReactNode;
|
|
128
129
|
/** The {@link IComponentProviderModule | ComponentProviderModule} instance which must be accessible by this component. */
|
|
129
130
|
module: IComponentProviderModule;
|
|
130
131
|
/**
|
|
@@ -150,7 +151,7 @@ interface ModuleProviderProps {
|
|
|
150
151
|
disposeModuleOnUnmount?: boolean;
|
|
151
152
|
}
|
|
152
153
|
|
|
153
|
-
declare function ModuleProvider({ children, module, tryReInitModuleOnMount, disposeModuleOnUnmount, }: ModuleProviderProps): react_jsx_runtime.JSX.Element;
|
|
154
|
+
declare function ModuleProvider({ children, render, module, tryReInitModuleOnMount, disposeModuleOnUnmount, }: ModuleProviderProps): react_jsx_runtime.JSX.Element;
|
|
154
155
|
|
|
155
156
|
/** A superset of the {@link ProviderModule} used to integrate within a `React` component. */
|
|
156
157
|
declare class ComponentProviderModule extends ProviderModule implements IComponentProviderModule {
|
package/dist/index.js
CHANGED
|
@@ -32,32 +32,32 @@ import { AppModule as a } from "@adimm/x-injection";
|
|
|
32
32
|
|
|
33
33
|
import { createContext as d } from "react";
|
|
34
34
|
|
|
35
|
-
var
|
|
35
|
+
var l = d(a), p = d(new Map), m = d({
|
|
36
36
|
r: 0
|
|
37
37
|
});
|
|
38
38
|
|
|
39
|
-
import {
|
|
39
|
+
import { useCallback as f, useContext as x } from "react";
|
|
40
40
|
|
|
41
|
-
function C({children: e,
|
|
42
|
-
const
|
|
43
|
-
ctx:
|
|
41
|
+
function C({children: e, render: t, module: n, tryReInitModuleOnMount: o, disposeModuleOnUnmount: r}) {
|
|
42
|
+
const i = n.toNaked().isAppModule, s = f((() => t?.()), []), c = {
|
|
43
|
+
ctx: i ? n : n.toNaked()._convertToContextualizedComponentInstance()
|
|
44
44
|
};
|
|
45
|
-
return React.createElement(
|
|
46
|
-
value:
|
|
45
|
+
return React.createElement(l.Provider, {
|
|
46
|
+
value: c
|
|
47
47
|
}, React.createElement(m.Provider, {
|
|
48
48
|
value: {
|
|
49
49
|
r: 0
|
|
50
50
|
}
|
|
51
51
|
}, React.createElement(v, {
|
|
52
|
-
children: e,
|
|
53
|
-
module:
|
|
54
|
-
tryReInitModuleOnMount:
|
|
55
|
-
disposeModuleOnUnmount:
|
|
52
|
+
children: e ?? React.createElement(s, null),
|
|
53
|
+
module: c,
|
|
54
|
+
tryReInitModuleOnMount: o,
|
|
55
|
+
disposeModuleOnUnmount: r
|
|
56
56
|
})));
|
|
57
57
|
}
|
|
58
58
|
|
|
59
59
|
function v({children: e, module: t, tryReInitModuleOnMount: n, disposeModuleOnUnmount: o = !1}) {
|
|
60
|
-
const r =
|
|
60
|
+
const r = x(p), i = x(m);
|
|
61
61
|
return c((() => {
|
|
62
62
|
const e = t.ctx.toNaked();
|
|
63
63
|
if (r) {
|
|
@@ -74,7 +74,7 @@ function v({children: e, module: t, tryReInitModuleOnMount: n, disposeModuleOnUn
|
|
|
74
74
|
}
|
|
75
75
|
|
|
76
76
|
function M(e, t) {
|
|
77
|
-
return u(
|
|
77
|
+
return u(l).ctx.get(e, t?.isOptional);
|
|
78
78
|
}
|
|
79
79
|
|
|
80
80
|
function h(e, t) {
|
|
@@ -87,7 +87,7 @@ t(h, "useInject");
|
|
|
87
87
|
import { useContext as I } from "react";
|
|
88
88
|
|
|
89
89
|
function O({deps: e}) {
|
|
90
|
-
return I(
|
|
90
|
+
return I(l).ctx.getMany(...e);
|
|
91
91
|
}
|
|
92
92
|
|
|
93
93
|
function g({deps: e, options: t}) {
|
|
@@ -99,14 +99,14 @@ function g({deps: e, options: t}) {
|
|
|
99
99
|
|
|
100
100
|
t(O, "useInjectManyOnRender"), t(g, "useInjectMany");
|
|
101
101
|
|
|
102
|
-
import { useContext as
|
|
102
|
+
import { useContext as R } from "react";
|
|
103
103
|
|
|
104
|
-
function
|
|
105
|
-
const e =
|
|
106
|
-
|
|
104
|
+
function _() {
|
|
105
|
+
const e = R(l);
|
|
106
|
+
R(p).set(e.ctx.toString(), e.ctx);
|
|
107
107
|
}
|
|
108
108
|
|
|
109
|
-
t(
|
|
109
|
+
t(_, "useExposeComponentModuleContext");
|
|
110
110
|
|
|
111
111
|
import { useContext as S, useEffect as y, useState as E } from "react";
|
|
112
112
|
|
|
@@ -164,7 +164,7 @@ import { useContext as T, useEffect as w, useMemo as F } from "react";
|
|
|
164
164
|
|
|
165
165
|
function U({children: e, contextInstance: t}) {
|
|
166
166
|
const n = F((() => new Map), []);
|
|
167
|
-
return React.createElement(
|
|
167
|
+
return React.createElement(p.Provider, {
|
|
168
168
|
value: n
|
|
169
169
|
}, React.createElement(A, {
|
|
170
170
|
contextInstance: t
|
|
@@ -172,7 +172,7 @@ function U({children: e, contextInstance: t}) {
|
|
|
172
172
|
}
|
|
173
173
|
|
|
174
174
|
function A({contextInstance: e}) {
|
|
175
|
-
const t = T(
|
|
175
|
+
const t = T(p);
|
|
176
176
|
return w((() => {
|
|
177
177
|
const n = e?.(t);
|
|
178
178
|
if (!n) return;
|
|
@@ -183,4 +183,4 @@ function A({contextInstance: e}) {
|
|
|
183
183
|
|
|
184
184
|
t(U, "TapIntoComponent"), t(A, "CtxExposer");
|
|
185
185
|
|
|
186
|
-
export { D as ComponentProviderModule, C as ModuleProvider,
|
|
186
|
+
export { D as ComponentProviderModule, C as ModuleProvider, l as REACT_X_INJECTION_CONTEXT, p as REACT_X_INJECTION_EXPOSED_COMPONENT_MODULE_CONTEXT, m as REACT_X_INJECTION_EXPOSED_COMPONENT_RERENDER_ON_CTX_CHANGE, U as TapIntoComponent, _ as useExposeComponentModuleContext, h as useInject, g as useInjectMany, O as useInjectManyOnRender, M as useInjectOnRender, j as useRerenderOnChildrenModuleContextLoaded };//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/helpers/hooks/use-once.ts","../src/helpers/hooks/use-effect-once.ts","../src/core/hooks/use-inject-on-render.ts","../src/core/providers/module-provider/react-context.ts","../src/core/providers/module-provider/module.provider.tsx","../src/core/hooks/use-inject.ts","../src/core/hooks/use-inject-many-on-render.ts","../src/core/hooks/use-inject-many.ts","../src/core/hooks/use-expose-component-module-context.ts","../src/core/hooks/use-rerender-on-children-module-context-loaded.ts","../src/core/component-provider-module.ts","../src/core/utils/tap-into-component-context/tap-into-component-context.tsx"],"sourcesContent":["import { useRef } from 'react';\n\nexport function useOnce<T>(fn: () => T): T {\n const ref = useRef<OnceValue<T> | null>(null);\n\n if (ref.current === null) {\n ref.current = { value: fn() };\n }\n\n return ref.current?.value;\n}\n\ntype OnceValue<T> = { value: T };\n","import { useEffect, useRef, useState } from 'react';\n\n// Credits: https://stackoverflow.com/a/74000921\n\n/** Custom {@link useEffect} hook which will be run once. _(In `StrictMode` as well)_ */\nexport function useEffectOnce(effect: () => React.EffectCallback) {\n const destroyFunc = useRef<React.EffectCallback>(undefined);\n const effectCalled = useRef(false);\n const renderAfterCalled = useRef(false);\n const [, forceRerender] = useState(0);\n\n if (effectCalled.current) renderAfterCalled.current = true;\n\n useEffect(() => {\n // only execute the effect first time around\n if (!effectCalled.current) {\n destroyFunc.current = effect();\n effectCalled.current = true;\n }\n\n // this forces one render after the effect is run\n forceRerender((x) => x + 1);\n\n return () => {\n // if the comp didn't render since the useEffect was called,\n // we know it's the dummy React cycle\n if (!renderAfterCalled.current) return;\n\n destroyFunc.current?.();\n };\n }, []);\n}\n","import type { ProviderToken } from '@adimm/x-injection';\nimport { useContext } from 'react';\n\nimport type { UseInjectSharedOptions } from '../../types';\nimport { REACT_X_INJECTION_CONTEXT } from '../providers';\n\n/**\n * React `hook` which can be used inside a component to inject the required {@link provider | dependency}.\n *\n * **Note:** _By using this hook, the dependency will be injected on each re-render process._\n * _If you need to inject the dependency only once, you must use the `useInject` hook._\n * _It basically acts like a `Transient` scope, ensuring that a new dependency is injected on each re-render._\n *\n * @param provider The {@link ProviderToken}.\n * @param options See {@link UseInjectSharedOptions}.\n * @returns Either the {@link T | dependency} or `undefined` if {@link isOptional} is set to `true`.\n */\nexport function useInjectOnRender<T>(provider: ProviderToken<T>, options?: UseInjectOptions): T {\n const componentModule = useContext(REACT_X_INJECTION_CONTEXT);\n\n return componentModule.ctx.get(provider, options?.isOptional);\n}\n\nexport type UseInjectOptions = UseInjectSharedOptions & {\n /** When set to `false` _(default)_ an exception will be thrown when the `providerOrIdentifier` isn't bound. */\n isOptional?: boolean;\n};\n","import { AppModule } from '@adimm/x-injection';\nimport { createContext } from 'react';\n\nimport type { IComponentProviderModule } from '../../../types';\n\n/**\n * The `React.Context` value to be provided to a `React.Provider`.\n *\n * Its default value is a reference to the {@link AppModule}.\n */\nexport const REACT_X_INJECTION_CONTEXT = createContext<{ ctx: IComponentProviderModule }>(AppModule as any);\n\nexport const REACT_X_INJECTION_EXPOSED_COMPONENT_MODULE_CONTEXT = createContext<Map<string, IComponentProviderModule>>(\n new Map()\n);\n\nexport const REACT_X_INJECTION_EXPOSED_COMPONENT_RERENDER_ON_CTX_CHANGE = createContext<{ r: number }>({ r: 0 });\n","import { useContext, useMemo } from 'react';\nimport type { Except } from 'type-fest';\n\nimport { useEffectOnce } from '../../../helpers';\nimport type { IComponentProviderModule, IComponentProviderModuleNaked } from '../../../types';\nimport type { ModuleProviderProps } from './models';\nimport {\n REACT_X_INJECTION_CONTEXT,\n REACT_X_INJECTION_EXPOSED_COMPONENT_MODULE_CONTEXT,\n REACT_X_INJECTION_EXPOSED_COMPONENT_RERENDER_ON_CTX_CHANGE,\n} from './react-context';\n\nexport function ModuleProvider({\n children,\n module,\n tryReInitModuleOnMount,\n disposeModuleOnUnmount,\n}: ModuleProviderProps) {\n const isAppModule = module.toNaked().isAppModule;\n\n const moduleCtxReference = {\n ctx: useMemo(() => {\n return isAppModule ? module : module.toNaked()._convertToContextualizedComponentInstance();\n }, [children, module, tryReInitModuleOnMount, disposeModuleOnUnmount]),\n };\n\n return (\n <REACT_X_INJECTION_CONTEXT.Provider value={moduleCtxReference}>\n <REACT_X_INJECTION_EXPOSED_COMPONENT_RERENDER_ON_CTX_CHANGE.Provider value={{ r: 0 }}>\n <XInjectionChildrenRenderer\n children={children}\n module={moduleCtxReference}\n tryReInitModuleOnMount={tryReInitModuleOnMount}\n disposeModuleOnUnmount={disposeModuleOnUnmount}\n />\n </REACT_X_INJECTION_EXPOSED_COMPONENT_RERENDER_ON_CTX_CHANGE.Provider>\n </REACT_X_INJECTION_CONTEXT.Provider>\n );\n}\n\nfunction XInjectionChildrenRenderer({\n children,\n module,\n tryReInitModuleOnMount,\n disposeModuleOnUnmount = false,\n}: Except<ModuleProviderProps, 'module'> & { module: { ctx: IComponentProviderModule } }) {\n const componentModuleInstance = useContext(REACT_X_INJECTION_EXPOSED_COMPONENT_MODULE_CONTEXT);\n const rerenderParentCtx = useContext(REACT_X_INJECTION_EXPOSED_COMPONENT_RERENDER_ON_CTX_CHANGE);\n\n // We use the `useEffectOnce` custom hook in order\n // to make sure that if the developer is providing the\n // `tryReInitModuleOnMount` and/or `disposeModuleOnUnmount` options\n // we do not early dispose the module when React double re-renders the\n // component while StrictMode is enabled.\n // This hook guarantees that the same behavior is expected with or without StrictMode.\n //\n // https://react.dev/reference/react/StrictMode\n useEffectOnce(() => {\n // ON MOUNT\n\n const moduleNaked = module.ctx.toNaked();\n\n if (componentModuleInstance) {\n const contextualizedImportedModules = module.ctx.toNaked().imports.map((importedModule) => {\n const shouldReplaceImportedModuleWithContextualized =\n componentModuleInstance.get(importedModule.toString())?.toString() === importedModule.toString();\n\n /* istanbul ignore next */\n if (!shouldReplaceImportedModuleWithContextualized)\n return importedModule as unknown as IComponentProviderModuleNaked;\n\n return componentModuleInstance.get(importedModule.toString()) as IComponentProviderModuleNaked;\n });\n\n if (contextualizedImportedModules.length > 0) {\n module.ctx.toNaked()._lazyInit({\n ...module.ctx.toNaked()._initialOptions,\n imports: contextualizedImportedModules,\n });\n\n // This will force the parent to re-render when using the `useRerenderOnChildrenModuleContextLoaded` hook.\n rerenderParentCtx.r++;\n }\n }\n\n /* istanbul ignore next */\n if (moduleNaked.isDisposed && tryReInitModuleOnMount) {\n /* istanbul ignore next */\n moduleNaked._lazyInit(tryReInitModuleOnMount);\n }\n\n return () => {\n // ON UNMOUNT\n\n if (!disposeModuleOnUnmount || moduleNaked.isDisposed) return;\n\n moduleNaked._dispose();\n };\n });\n\n return children;\n}\n","import type { ProviderToken } from '@adimm/x-injection';\n\nimport { useOnce } from '../../helpers';\nimport { useInjectOnRender, type UseInjectOptions } from './use-inject-on-render';\n\n/**\n * React `hook` which can be used inside a component to inject the required {@link provider | dependency}.\n *\n * **Note:** _By using this hook, the dependency will be injected only once after the first component mount process._\n * _If you need to re-inject the dependency on each re-render, you must use the `useInjectOnRender` hook._\n * _It basically acts like a `Request` scope, ensuring that even a `Transient` dependency does not mutate during re-renders._\n *\n * @param provider The {@link ProviderToken}.\n * @param options See {@link UseInjectSharedOptions}.\n * @returns Either the {@link T | dependency} or `undefined` if {@link isOptional} is set to `true`.\n */\nexport function useInject<T>(provider: ProviderToken<T>, options?: UseInjectOptions): T {\n return useOnce(() => useInjectOnRender(provider, options));\n}\n","import type {\n ProviderModuleGetManyParam,\n ProviderModuleGetManySignature,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n ProviderToken,\n} from '@adimm/x-injection';\nimport { useContext } from 'react';\n\nimport type { UseInjectSharedOptions } from '../../types';\nimport { REACT_X_INJECTION_CONTEXT } from '../providers';\n\n/**\n * Can be used to retrieve many resolved `dependencies` from the module container at once.\n *\n * **Note:** _By using this hook, the dependencies will be injected on each re-render process._\n * _If you need to inject the dependencies only once, you must use the `useInjectMany` hook._\n *\n * @param options See {@link UseInjectSharedOptions}.\n * @param deps Either one or more {@link ProviderToken}.\n * @returns Tuple containing the {@link D | dependencies}.\n */\nexport function useInjectManyOnRender<D extends (ProviderModuleGetManyParam<any> | ProviderToken)[]>({\n deps,\n}: {\n deps: [...(D | unknown[])];\n options?: UseInjectSharedOptions;\n}): ProviderModuleGetManySignature<D> {\n const componentModule = useContext(REACT_X_INJECTION_CONTEXT);\n\n return componentModule.ctx.getMany(...deps);\n}\n","import type { ProviderModuleGetManyParam, ProviderModuleGetManySignature, ProviderToken } from '@adimm/x-injection';\n\nimport { useOnce } from '../../helpers';\nimport type { UseInjectSharedOptions } from '../../types';\nimport { useInjectManyOnRender } from './use-inject-many-on-render';\n\n/**\n * Can be used to retrieve many resolved `dependencies` from the module container at once.\n *\n * **Note:** _By using this hook, the dependencies will be injected only once after the first component mount process._\n * _If you need to re-inject the dependencies on each re-render, you must use the `useInjectManyOnRender` hook._\n *\n * @param options See {@link UseInjectSharedOptions}.\n * @param deps Either one or more {@link ProviderToken}.\n * @returns Tuple containing the {@link D | dependencies}.\n */\nexport function useInjectMany<D extends (ProviderModuleGetManyParam<any> | ProviderToken)[]>({\n deps,\n options,\n}: {\n deps: [...(D | unknown[])];\n options?: UseInjectSharedOptions;\n}): ProviderModuleGetManySignature<D> {\n return useOnce(() => useInjectManyOnRender({ options, deps }));\n}\n","import { useContext } from 'react';\n\nimport { REACT_X_INJECTION_CONTEXT, REACT_X_INJECTION_EXPOSED_COMPONENT_MODULE_CONTEXT } from '../providers';\n\nexport function useExposeComponentModuleContext(): void {\n const componentModule = useContext(REACT_X_INJECTION_CONTEXT);\n const exposed = useContext(REACT_X_INJECTION_EXPOSED_COMPONENT_MODULE_CONTEXT);\n\n exposed.set(componentModule.ctx.toString(), componentModule.ctx);\n}\n","import { useContext, useEffect, useState } from 'react';\n\nimport { REACT_X_INJECTION_EXPOSED_COMPONENT_RERENDER_ON_CTX_CHANGE } from '../providers';\n\n/**\n * This is an **experimental** hook which can be used to make sure that a component will re-render when a children\n * exposes its internal context module.\n *\n * It works best with the `useInjectOnRender` hook, as it'll re-resolve all the required dependencies\n * of the injected ProviderToken.\n *\n * **Use it carefully as it may lead to unnecessary re-render cycles or it may even not work as expected!**\n * **It's safer to use the `TapIntoComponent` wrapper component with the `contextInstance` to manually inject the**\n * **contextualized dependencies of the children into a parent component service!**\n *\n * @experimental\n */\nexport function useRerenderOnChildrenModuleContextLoaded(): void {\n const rerenderParentCtx = useContext(REACT_X_INJECTION_EXPOSED_COMPONENT_RERENDER_ON_CTX_CHANGE);\n const [, setRerender] = useState(0);\n\n useEffect(() => {\n setRerender((x) => x + 1);\n }, [rerenderParentCtx.r]);\n}\n","import {\n InjectionScope,\n isClass,\n isClassOrFunction,\n ProviderModule,\n ProviderModuleHelpers,\n type DependencyProvider,\n type IProviderModuleNaked,\n type ProviderClassToken,\n type ProviderModuleOptions,\n type ProviderValueToken,\n} from '@adimm/x-injection';\n\nimport type { IComponentProviderModule, IComponentProviderModuleNaked } from '../types';\n\n/** A superset of the {@link ProviderModule} used to integrate within a `React` component. */\nexport class ComponentProviderModule extends ProviderModule implements IComponentProviderModule {\n protected readonly _initializedFromComponent: IComponentProviderModuleNaked['_initializedFromComponent'];\n protected readonly _initialOptions: IComponentProviderModuleNaked['_initialOptions'];\n\n constructor(options: ProviderModuleOptions) {\n super(\n ProviderModuleHelpers.buildInternalConstructorParams({\n ...options,\n // By default components should have all their providers\n // defined as transient because a component may have more than one instance of itself.\n defaultScope: options.defaultScope ?? InjectionScope.Transient,\n identifier: Symbol(`Component${options.identifier.description}`),\n })\n );\n\n this._initializedFromComponent = false;\n this._initialOptions = options;\n }\n\n override toNaked(): IComponentProviderModuleNaked & IProviderModuleNaked {\n return this as any;\n }\n\n /* istanbul ignore next */\n dispose(): void {\n this._dispose();\n }\n\n /**\n * **Publicly visible when the instance is casted to {@link IComponentProviderModuleNaked}.**\n *\n * See {@link IComponentProviderModuleNaked._convertToContextualizedComponentInstance}.\n */\n /* istanbul ignore next */\n protected _convertToContextualizedComponentInstance(): IComponentProviderModule {\n if (this.isAppModule || this.isDisposed) return this;\n\n const contextualizedProviders = this._getProviders().map((provider) => {\n if (!isClassOrFunction(provider)) {\n return {\n ...provider,\n scope: InjectionScope.Singleton,\n } as DependencyProvider;\n }\n\n if (isClass(provider)) {\n return {\n scope: InjectionScope.Singleton,\n provide: provider,\n useClass: provider,\n } as ProviderClassToken<any>;\n }\n\n return {\n provide: provider,\n useValue: provider,\n } as ProviderValueToken<any>;\n });\n\n const componentModule = new ComponentProviderModule({\n ...this._initialOptions,\n providers: contextualizedProviders,\n });\n\n //@ts-expect-error Read-only property.\n componentModule._initializedFromComponent = true;\n\n return componentModule;\n }\n}\n","import { useContext, useEffect, useMemo } from 'react';\nimport type { Except } from 'type-fest';\n\nimport { REACT_X_INJECTION_EXPOSED_COMPONENT_MODULE_CONTEXT } from '../../providers';\nimport type { TapIntoComponentContextProps } from './interfaces';\n\n/**\n * This component is the standard way to \"tap into\" an instance of the component\n * in order to get access to its scoped module container and its _(exposed)_ dependencies _instances_.\n *\n * @param contextInstance See {@link TapIntoComponentContextProps.contextInstance}.\n * @param exposed See {@link TapIntoComponentContextProps.exposed}.\n */\nexport function TapIntoComponent({ children, contextInstance }: TapIntoComponentContextProps) {\n const moduleContextMap = useMemo(() => new Map(), []);\n\n return (\n <REACT_X_INJECTION_EXPOSED_COMPONENT_MODULE_CONTEXT.Provider value={moduleContextMap}>\n <CtxExposer contextInstance={contextInstance} />\n {children}\n </REACT_X_INJECTION_EXPOSED_COMPONENT_MODULE_CONTEXT.Provider>\n );\n}\n\nfunction CtxExposer({ contextInstance }: Except<TapIntoComponentContextProps, 'children'>) {\n const ctxMap = useContext(REACT_X_INJECTION_EXPOSED_COMPONENT_MODULE_CONTEXT);\n\n useEffect(() => {\n const fluidSyntax = contextInstance?.(ctxMap);\n if (!fluidSyntax) return;\n\n const moduleCtx = ctxMap.get(fluidSyntax.tryGet.toString());\n /* istanbul ignore next */\n if (!moduleCtx) return;\n\n fluidSyntax.thenDo(moduleCtx);\n }, [ctxMap]);\n\n return null;\n}\n"],"mappings":"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","names":["useRef","useOnce","fn","ref","useRef","current","value","useEffect","useRef","useState","useEffectOnce","effect","destroyFunc","useRef","undefined","effectCalled","renderAfterCalled","forceRerender","useState","current","useEffect","x","useContext","AppModule","createContext","REACT_X_INJECTION_CONTEXT","REACT_X_INJECTION_EXPOSED_COMPONENT_MODULE_CONTEXT","Map","REACT_X_INJECTION_EXPOSED_COMPONENT_RERENDER_ON_CTX_CHANGE","r","useContext","useMemo","ModuleProvider","children","module","tryReInitModuleOnMount","disposeModuleOnUnmount","isAppModule","toNaked","moduleCtxReference","ctx","useMemo","_convertToContextualizedComponentInstance","REACT_X_INJECTION_CONTEXT","Provider","value","REACT_X_INJECTION_EXPOSED_COMPONENT_RERENDER_ON_CTX_CHANGE","r","XInjectionChildrenRenderer","componentModuleInstance","useContext","REACT_X_INJECTION_EXPOSED_COMPONENT_MODULE_CONTEXT","rerenderParentCtx","useEffectOnce","moduleNaked","contextualizedImportedModules","imports","map","importedModule","shouldReplaceImportedModuleWithContextualized","get","toString","length","_lazyInit","_initialOptions","isDisposed","_dispose","useInjectOnRender","provider","options","componentModule","useContext","REACT_X_INJECTION_CONTEXT","ctx","get","isOptional","useInject","provider","options","useOnce","useInjectOnRender","useContext","useInjectManyOnRender","deps","componentModule","useContext","REACT_X_INJECTION_CONTEXT","ctx","getMany","useInjectMany","deps","options","useOnce","useInjectManyOnRender","useContext","useExposeComponentModuleContext","componentModule","useContext","REACT_X_INJECTION_CONTEXT","exposed","REACT_X_INJECTION_EXPOSED_COMPONENT_MODULE_CONTEXT","set","ctx","toString","useContext","useEffect","useState","useRerenderOnChildrenModuleContextLoaded","rerenderParentCtx","useContext","REACT_X_INJECTION_EXPOSED_COMPONENT_RERENDER_ON_CTX_CHANGE","setRerender","useState","useEffect","x","r","InjectionScope","isClass","isClassOrFunction","ProviderModule","ProviderModuleHelpers","ComponentProviderModule","ProviderModule","_initializedFromComponent","_initialOptions","constructor","options","ProviderModuleHelpers","buildInternalConstructorParams","defaultScope","InjectionScope","Transient","identifier","Symbol","description","toNaked","dispose","_dispose","_convertToContextualizedComponentInstance","isAppModule","isDisposed","contextualizedProviders","_getProviders","map","provider","isClassOrFunction","scope","Singleton","isClass","provide","useClass","useValue","componentModule","providers","useContext","useEffect","useMemo","TapIntoComponent","children","contextInstance","moduleContextMap","useMemo","Map","REACT_X_INJECTION_EXPOSED_COMPONENT_MODULE_CONTEXT","Provider","value","CtxExposer","ctxMap","useContext","useEffect","fluidSyntax","moduleCtx","get","tryGet","toString","thenDo"]}
|
|
1
|
+
{"version":3,"sources":["../src/helpers/hooks/use-once.ts","../src/helpers/hooks/use-effect-once.ts","../src/core/hooks/use-inject-on-render.ts","../src/core/providers/module-provider/react-context.ts","../src/core/providers/module-provider/module.provider.tsx","../src/core/hooks/use-inject.ts","../src/core/hooks/use-inject-many-on-render.ts","../src/core/hooks/use-inject-many.ts","../src/core/hooks/use-expose-component-module-context.ts","../src/core/hooks/use-rerender-on-children-module-context-loaded.ts","../src/core/component-provider-module.ts","../src/core/utils/tap-into-component-context/tap-into-component-context.tsx"],"sourcesContent":["import { useRef } from 'react';\n\nexport function useOnce<T>(fn: () => T): T {\n const ref = useRef<OnceValue<T> | null>(null);\n\n if (ref.current === null) {\n ref.current = { value: fn() };\n }\n\n return ref.current?.value;\n}\n\ntype OnceValue<T> = { value: T };\n","import { useEffect, useRef, useState } from 'react';\n\n// Credits: https://stackoverflow.com/a/74000921\n\n/** Custom {@link useEffect} hook which will be run once. _(In `StrictMode` as well)_ */\nexport function useEffectOnce(effect: () => React.EffectCallback) {\n const destroyFunc = useRef<React.EffectCallback>(undefined);\n const effectCalled = useRef(false);\n const renderAfterCalled = useRef(false);\n const [, forceRerender] = useState(0);\n\n if (effectCalled.current) renderAfterCalled.current = true;\n\n useEffect(() => {\n // only execute the effect first time around\n if (!effectCalled.current) {\n destroyFunc.current = effect();\n effectCalled.current = true;\n }\n\n // this forces one render after the effect is run\n forceRerender((x) => x + 1);\n\n return () => {\n // if the comp didn't render since the useEffect was called,\n // we know it's the dummy React cycle\n if (!renderAfterCalled.current) return;\n\n destroyFunc.current?.();\n };\n }, []);\n}\n","import type { ProviderToken } from '@adimm/x-injection';\nimport { useContext } from 'react';\n\nimport type { UseInjectSharedOptions } from '../../types';\nimport { REACT_X_INJECTION_CONTEXT } from '../providers';\n\n/**\n * React `hook` which can be used inside a component to inject the required {@link provider | dependency}.\n *\n * **Note:** _By using this hook, the dependency will be injected on each re-render process._\n * _If you need to inject the dependency only once, you must use the `useInject` hook._\n * _It basically acts like a `Transient` scope, ensuring that a new dependency is injected on each re-render._\n *\n * @param provider The {@link ProviderToken}.\n * @param options See {@link UseInjectSharedOptions}.\n * @returns Either the {@link T | dependency} or `undefined` if {@link isOptional} is set to `true`.\n */\nexport function useInjectOnRender<T>(provider: ProviderToken<T>, options?: UseInjectOptions): T {\n const componentModule = useContext(REACT_X_INJECTION_CONTEXT);\n\n return componentModule.ctx.get(provider, options?.isOptional);\n}\n\nexport type UseInjectOptions = UseInjectSharedOptions & {\n /** When set to `false` _(default)_ an exception will be thrown when the `providerOrIdentifier` isn't bound. */\n isOptional?: boolean;\n};\n","import { AppModule } from '@adimm/x-injection';\nimport { createContext } from 'react';\n\nimport type { IComponentProviderModule } from '../../../types';\n\n/**\n * The `React.Context` value to be provided to a `React.Provider`.\n *\n * Its default value is a reference to the {@link AppModule}.\n */\nexport const REACT_X_INJECTION_CONTEXT = createContext<{ ctx: IComponentProviderModule }>(AppModule as any);\n\nexport const REACT_X_INJECTION_EXPOSED_COMPONENT_MODULE_CONTEXT = createContext<Map<string, IComponentProviderModule>>(\n new Map()\n);\n\nexport const REACT_X_INJECTION_EXPOSED_COMPONENT_RERENDER_ON_CTX_CHANGE = createContext<{ r: number }>({ r: 0 });\n","import { useCallback, useContext } from 'react';\nimport type { Except } from 'type-fest';\n\nimport { useEffectOnce } from '../../../helpers';\nimport type { IComponentProviderModule, IComponentProviderModuleNaked } from '../../../types';\nimport type { ModuleProviderProps } from './models';\nimport {\n REACT_X_INJECTION_CONTEXT,\n REACT_X_INJECTION_EXPOSED_COMPONENT_MODULE_CONTEXT,\n REACT_X_INJECTION_EXPOSED_COMPONENT_RERENDER_ON_CTX_CHANGE,\n} from './react-context';\n\nexport function ModuleProvider({\n children,\n render,\n module,\n tryReInitModuleOnMount,\n disposeModuleOnUnmount,\n}: ModuleProviderProps) {\n const isAppModule = module.toNaked().isAppModule;\n const Renderer = useCallback(() => render?.(), []);\n\n const moduleCtxReference = {\n ctx: isAppModule ? module : module.toNaked()._convertToContextualizedComponentInstance(),\n };\n\n return (\n <REACT_X_INJECTION_CONTEXT.Provider value={moduleCtxReference}>\n <REACT_X_INJECTION_EXPOSED_COMPONENT_RERENDER_ON_CTX_CHANGE.Provider value={{ r: 0 }}>\n <XInjectionChildrenRenderer\n children={children ?? <Renderer />}\n module={moduleCtxReference}\n tryReInitModuleOnMount={tryReInitModuleOnMount}\n disposeModuleOnUnmount={disposeModuleOnUnmount}\n />\n </REACT_X_INJECTION_EXPOSED_COMPONENT_RERENDER_ON_CTX_CHANGE.Provider>\n </REACT_X_INJECTION_CONTEXT.Provider>\n );\n}\n\nfunction XInjectionChildrenRenderer({\n children,\n module,\n tryReInitModuleOnMount,\n disposeModuleOnUnmount = false,\n}: Except<ModuleProviderProps, 'module'> & { module: { ctx: IComponentProviderModule } }) {\n const componentModuleInstance = useContext(REACT_X_INJECTION_EXPOSED_COMPONENT_MODULE_CONTEXT);\n const rerenderParentCtx = useContext(REACT_X_INJECTION_EXPOSED_COMPONENT_RERENDER_ON_CTX_CHANGE);\n\n // We use the `useEffectOnce` custom hook in order\n // to make sure that if the developer is providing the\n // `tryReInitModuleOnMount` and/or `disposeModuleOnUnmount` options\n // we do not early dispose the module when React double re-renders the\n // component while StrictMode is enabled.\n // This hook guarantees that the same behavior is expected with or without StrictMode.\n //\n // https://react.dev/reference/react/StrictMode\n useEffectOnce(() => {\n // ON MOUNT\n\n const moduleNaked = module.ctx.toNaked();\n\n if (componentModuleInstance) {\n const contextualizedImportedModules = module.ctx.toNaked().imports.map((importedModule) => {\n const shouldReplaceImportedModuleWithContextualized =\n componentModuleInstance.get(importedModule.toString())?.toString() === importedModule.toString();\n\n /* istanbul ignore next */\n if (!shouldReplaceImportedModuleWithContextualized)\n return importedModule as unknown as IComponentProviderModuleNaked;\n\n return componentModuleInstance.get(importedModule.toString()) as IComponentProviderModuleNaked;\n });\n\n if (contextualizedImportedModules.length > 0) {\n module.ctx.toNaked()._lazyInit({\n ...module.ctx.toNaked()._initialOptions,\n imports: contextualizedImportedModules,\n });\n\n // This will force the parent to re-render when using the `useRerenderOnChildrenModuleContextLoaded` hook.\n rerenderParentCtx.r++;\n }\n }\n\n /* istanbul ignore next */\n if (moduleNaked.isDisposed && tryReInitModuleOnMount) {\n /* istanbul ignore next */\n moduleNaked._lazyInit(tryReInitModuleOnMount);\n }\n\n return () => {\n // ON UNMOUNT\n\n if (!disposeModuleOnUnmount || moduleNaked.isDisposed) return;\n\n moduleNaked._dispose();\n };\n });\n\n return children;\n}\n","import type { ProviderToken } from '@adimm/x-injection';\n\nimport { useOnce } from '../../helpers';\nimport { useInjectOnRender, type UseInjectOptions } from './use-inject-on-render';\n\n/**\n * React `hook` which can be used inside a component to inject the required {@link provider | dependency}.\n *\n * **Note:** _By using this hook, the dependency will be injected only once after the first component mount process._\n * _If you need to re-inject the dependency on each re-render, you must use the `useInjectOnRender` hook._\n * _It basically acts like a `Request` scope, ensuring that even a `Transient` dependency does not mutate during re-renders._\n *\n * @param provider The {@link ProviderToken}.\n * @param options See {@link UseInjectSharedOptions}.\n * @returns Either the {@link T | dependency} or `undefined` if {@link isOptional} is set to `true`.\n */\nexport function useInject<T>(provider: ProviderToken<T>, options?: UseInjectOptions): T {\n return useOnce(() => useInjectOnRender(provider, options));\n}\n","import type {\n ProviderModuleGetManyParam,\n ProviderModuleGetManySignature,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n ProviderToken,\n} from '@adimm/x-injection';\nimport { useContext } from 'react';\n\nimport type { UseInjectSharedOptions } from '../../types';\nimport { REACT_X_INJECTION_CONTEXT } from '../providers';\n\n/**\n * Can be used to retrieve many resolved `dependencies` from the module container at once.\n *\n * **Note:** _By using this hook, the dependencies will be injected on each re-render process._\n * _If you need to inject the dependencies only once, you must use the `useInjectMany` hook._\n *\n * @param options See {@link UseInjectSharedOptions}.\n * @param deps Either one or more {@link ProviderToken}.\n * @returns Tuple containing the {@link D | dependencies}.\n */\nexport function useInjectManyOnRender<D extends (ProviderModuleGetManyParam<any> | ProviderToken)[]>({\n deps,\n}: {\n deps: [...(D | unknown[])];\n options?: UseInjectSharedOptions;\n}): ProviderModuleGetManySignature<D> {\n const componentModule = useContext(REACT_X_INJECTION_CONTEXT);\n\n return componentModule.ctx.getMany(...deps);\n}\n","import type { ProviderModuleGetManyParam, ProviderModuleGetManySignature, ProviderToken } from '@adimm/x-injection';\n\nimport { useOnce } from '../../helpers';\nimport type { UseInjectSharedOptions } from '../../types';\nimport { useInjectManyOnRender } from './use-inject-many-on-render';\n\n/**\n * Can be used to retrieve many resolved `dependencies` from the module container at once.\n *\n * **Note:** _By using this hook, the dependencies will be injected only once after the first component mount process._\n * _If you need to re-inject the dependencies on each re-render, you must use the `useInjectManyOnRender` hook._\n *\n * @param options See {@link UseInjectSharedOptions}.\n * @param deps Either one or more {@link ProviderToken}.\n * @returns Tuple containing the {@link D | dependencies}.\n */\nexport function useInjectMany<D extends (ProviderModuleGetManyParam<any> | ProviderToken)[]>({\n deps,\n options,\n}: {\n deps: [...(D | unknown[])];\n options?: UseInjectSharedOptions;\n}): ProviderModuleGetManySignature<D> {\n return useOnce(() => useInjectManyOnRender({ options, deps }));\n}\n","import { useContext } from 'react';\n\nimport { REACT_X_INJECTION_CONTEXT, REACT_X_INJECTION_EXPOSED_COMPONENT_MODULE_CONTEXT } from '../providers';\n\nexport function useExposeComponentModuleContext(): void {\n const componentModule = useContext(REACT_X_INJECTION_CONTEXT);\n const exposed = useContext(REACT_X_INJECTION_EXPOSED_COMPONENT_MODULE_CONTEXT);\n\n exposed.set(componentModule.ctx.toString(), componentModule.ctx);\n}\n","import { useContext, useEffect, useState } from 'react';\n\nimport { REACT_X_INJECTION_EXPOSED_COMPONENT_RERENDER_ON_CTX_CHANGE } from '../providers';\n\n/**\n * This is an **experimental** hook which can be used to make sure that a component will re-render when a children\n * exposes its internal context module.\n *\n * It works best with the `useInjectOnRender` hook, as it'll re-resolve all the required dependencies\n * of the injected ProviderToken.\n *\n * **Use it carefully as it may lead to unnecessary re-render cycles or it may even not work as expected!**\n * **It's safer to use the `TapIntoComponent` wrapper component with the `contextInstance` to manually inject the**\n * **contextualized dependencies of the children into a parent component service!**\n *\n * @experimental\n */\nexport function useRerenderOnChildrenModuleContextLoaded(): void {\n const rerenderParentCtx = useContext(REACT_X_INJECTION_EXPOSED_COMPONENT_RERENDER_ON_CTX_CHANGE);\n const [, setRerender] = useState(0);\n\n useEffect(() => {\n setRerender((x) => x + 1);\n }, [rerenderParentCtx.r]);\n}\n","import {\n InjectionScope,\n isClass,\n isClassOrFunction,\n ProviderModule,\n ProviderModuleHelpers,\n type DependencyProvider,\n type IProviderModuleNaked,\n type ProviderClassToken,\n type ProviderModuleOptions,\n type ProviderValueToken,\n} from '@adimm/x-injection';\n\nimport type { IComponentProviderModule, IComponentProviderModuleNaked } from '../types';\n\n/** A superset of the {@link ProviderModule} used to integrate within a `React` component. */\nexport class ComponentProviderModule extends ProviderModule implements IComponentProviderModule {\n protected readonly _initializedFromComponent: IComponentProviderModuleNaked['_initializedFromComponent'];\n protected readonly _initialOptions: IComponentProviderModuleNaked['_initialOptions'];\n\n constructor(options: ProviderModuleOptions) {\n super(\n ProviderModuleHelpers.buildInternalConstructorParams({\n ...options,\n // By default components should have all their providers\n // defined as transient because a component may have more than one instance of itself.\n defaultScope: options.defaultScope ?? InjectionScope.Transient,\n identifier: Symbol(`Component${options.identifier.description}`),\n })\n );\n\n this._initializedFromComponent = false;\n this._initialOptions = options;\n }\n\n override toNaked(): IComponentProviderModuleNaked & IProviderModuleNaked {\n return this as any;\n }\n\n /* istanbul ignore next */\n dispose(): void {\n this._dispose();\n }\n\n /**\n * **Publicly visible when the instance is casted to {@link IComponentProviderModuleNaked}.**\n *\n * See {@link IComponentProviderModuleNaked._convertToContextualizedComponentInstance}.\n */\n /* istanbul ignore next */\n protected _convertToContextualizedComponentInstance(): IComponentProviderModule {\n if (this.isAppModule || this.isDisposed) return this;\n\n const contextualizedProviders = this._getProviders().map((provider) => {\n if (!isClassOrFunction(provider)) {\n return {\n ...provider,\n scope: InjectionScope.Singleton,\n } as DependencyProvider;\n }\n\n if (isClass(provider)) {\n return {\n scope: InjectionScope.Singleton,\n provide: provider,\n useClass: provider,\n } as ProviderClassToken<any>;\n }\n\n return {\n provide: provider,\n useValue: provider,\n } as ProviderValueToken<any>;\n });\n\n const componentModule = new ComponentProviderModule({\n ...this._initialOptions,\n providers: contextualizedProviders,\n });\n\n //@ts-expect-error Read-only property.\n componentModule._initializedFromComponent = true;\n\n return componentModule;\n }\n}\n","import { useContext, useEffect, useMemo } from 'react';\nimport type { Except } from 'type-fest';\n\nimport { REACT_X_INJECTION_EXPOSED_COMPONENT_MODULE_CONTEXT } from '../../providers';\nimport type { TapIntoComponentContextProps } from './interfaces';\n\n/**\n * This component is the standard way to \"tap into\" an instance of the component\n * in order to get access to its scoped module container and its _(exposed)_ dependencies _instances_.\n *\n * @param contextInstance See {@link TapIntoComponentContextProps.contextInstance}.\n * @param exposed See {@link TapIntoComponentContextProps.exposed}.\n */\nexport function TapIntoComponent({ children, contextInstance }: TapIntoComponentContextProps) {\n const moduleContextMap = useMemo(() => new Map(), []);\n\n return (\n <REACT_X_INJECTION_EXPOSED_COMPONENT_MODULE_CONTEXT.Provider value={moduleContextMap}>\n <CtxExposer contextInstance={contextInstance} />\n {children}\n </REACT_X_INJECTION_EXPOSED_COMPONENT_MODULE_CONTEXT.Provider>\n );\n}\n\nfunction CtxExposer({ contextInstance }: Except<TapIntoComponentContextProps, 'children'>) {\n const ctxMap = useContext(REACT_X_INJECTION_EXPOSED_COMPONENT_MODULE_CONTEXT);\n\n useEffect(() => {\n const fluidSyntax = contextInstance?.(ctxMap);\n if (!fluidSyntax) return;\n\n const moduleCtx = ctxMap.get(fluidSyntax.tryGet.toString());\n /* istanbul ignore next */\n if (!moduleCtx) return;\n\n fluidSyntax.thenDo(moduleCtx);\n }, [ctxMap]);\n\n return null;\n}\n"],"mappings":"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","names":["useRef","useOnce","fn","ref","useRef","current","value","useEffect","useRef","useState","useEffectOnce","effect","destroyFunc","useRef","undefined","effectCalled","renderAfterCalled","forceRerender","useState","current","useEffect","x","useContext","AppModule","createContext","REACT_X_INJECTION_CONTEXT","REACT_X_INJECTION_EXPOSED_COMPONENT_MODULE_CONTEXT","Map","REACT_X_INJECTION_EXPOSED_COMPONENT_RERENDER_ON_CTX_CHANGE","r","useCallback","useContext","ModuleProvider","children","render","module","tryReInitModuleOnMount","disposeModuleOnUnmount","isAppModule","toNaked","Renderer","useCallback","moduleCtxReference","ctx","_convertToContextualizedComponentInstance","REACT_X_INJECTION_CONTEXT","Provider","value","REACT_X_INJECTION_EXPOSED_COMPONENT_RERENDER_ON_CTX_CHANGE","r","XInjectionChildrenRenderer","componentModuleInstance","useContext","REACT_X_INJECTION_EXPOSED_COMPONENT_MODULE_CONTEXT","rerenderParentCtx","useEffectOnce","moduleNaked","contextualizedImportedModules","imports","map","importedModule","shouldReplaceImportedModuleWithContextualized","get","toString","length","_lazyInit","_initialOptions","isDisposed","_dispose","useInjectOnRender","provider","options","componentModule","useContext","REACT_X_INJECTION_CONTEXT","ctx","get","isOptional","useInject","provider","options","useOnce","useInjectOnRender","useContext","useInjectManyOnRender","deps","componentModule","useContext","REACT_X_INJECTION_CONTEXT","ctx","getMany","useInjectMany","deps","options","useOnce","useInjectManyOnRender","useContext","useExposeComponentModuleContext","componentModule","useContext","REACT_X_INJECTION_CONTEXT","exposed","REACT_X_INJECTION_EXPOSED_COMPONENT_MODULE_CONTEXT","set","ctx","toString","useContext","useEffect","useState","useRerenderOnChildrenModuleContextLoaded","rerenderParentCtx","useContext","REACT_X_INJECTION_EXPOSED_COMPONENT_RERENDER_ON_CTX_CHANGE","setRerender","useState","useEffect","x","r","InjectionScope","isClass","isClassOrFunction","ProviderModule","ProviderModuleHelpers","ComponentProviderModule","ProviderModule","_initializedFromComponent","_initialOptions","constructor","options","ProviderModuleHelpers","buildInternalConstructorParams","defaultScope","InjectionScope","Transient","identifier","Symbol","description","toNaked","dispose","_dispose","_convertToContextualizedComponentInstance","isAppModule","isDisposed","contextualizedProviders","_getProviders","map","provider","isClassOrFunction","scope","Singleton","isClass","provide","useClass","useValue","componentModule","providers","useContext","useEffect","useMemo","TapIntoComponent","children","contextInstance","moduleContextMap","useMemo","Map","REACT_X_INJECTION_EXPOSED_COMPONENT_MODULE_CONTEXT","Provider","value","CtxExposer","ctxMap","useContext","useEffect","fluidSyntax","moduleCtx","get","tryGet","toString","thenDo"]}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adimm/x-injection-reactjs",
|
|
3
3
|
"description": "ReactJS integration of the `xInjection` library.",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.1",
|
|
5
5
|
"author": "Adi-Marian Mutu",
|
|
6
6
|
"homepage": "https://github.com/AdiMarianMutu/x-injection-reactjs#readme",
|
|
7
7
|
"bugs": "https://github.com/AdiMarianMutu/x-injection-reactjs/issues",
|