@navios/di-react 0.8.0 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +45 -0
- package/README.md +14 -67
- package/lib/index.d.mts +3 -57
- package/lib/index.d.mts.map +1 -1
- package/lib/index.d.ts +8 -62
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +41 -51
- package/lib/index.js.map +1 -1
- package/lib/index.mjs +42 -51
- package/lib/index.mjs.map +1 -1
- package/package.json +3 -3
- package/src/hooks/__tests__/use-container.spec.mts +3 -2
- package/src/hooks/__tests__/use-invalidate.spec.mts +10 -146
- package/src/hooks/__tests__/use-service.spec.mts +2 -2
- package/src/hooks/index.mts +1 -1
- package/src/hooks/use-container.mts +6 -3
- package/src/hooks/use-invalidate.mts +1 -82
- package/src/hooks/use-optional-service.mts +17 -25
- package/src/hooks/use-service.mts +25 -26
- package/src/hooks/use-suspense-service.mts +10 -17
- package/src/providers/__tests__/scope-provider.spec.mts +5 -2
- package/src/providers/scope-provider.mts +1 -8
package/lib/index.js
CHANGED
|
@@ -46,14 +46,14 @@ function ContainerProvider({ container, children }) {
|
|
|
46
46
|
* ))}
|
|
47
47
|
* ```
|
|
48
48
|
*/
|
|
49
|
-
function ScopeProvider({ scopeId, metadata,
|
|
49
|
+
function ScopeProvider({ scopeId, metadata, children }) {
|
|
50
50
|
const container = (0, react.useContext)(ContainerContext);
|
|
51
51
|
if (!container) throw new Error("ScopeProvider must be used within a ContainerProvider");
|
|
52
52
|
const generatedId = (0, react.useId)();
|
|
53
53
|
const effectiveScopeId = scopeId ?? generatedId;
|
|
54
54
|
const scopedContainerRef = (0, react.useRef)(null);
|
|
55
55
|
if (!scopedContainerRef.current) {
|
|
56
|
-
if (!container.hasActiveRequest(effectiveScopeId)) scopedContainerRef.current = container.beginRequest(effectiveScopeId, metadata
|
|
56
|
+
if (!container.hasActiveRequest(effectiveScopeId)) scopedContainerRef.current = container.beginRequest(effectiveScopeId, metadata);
|
|
57
57
|
}
|
|
58
58
|
(0, react.useEffect)(() => {
|
|
59
59
|
const scopedContainer = scopedContainerRef.current;
|
|
@@ -120,7 +120,7 @@ function serviceReducer(state, action) {
|
|
|
120
120
|
}
|
|
121
121
|
function useService(token, args) {
|
|
122
122
|
const container = useContainer();
|
|
123
|
-
const
|
|
123
|
+
const rootContainer = useRootContainer();
|
|
124
124
|
const initialSyncInstanceRef = (0, react.useRef)(void 0);
|
|
125
125
|
const isFirstRenderRef = (0, react.useRef)(true);
|
|
126
126
|
if (isFirstRenderRef.current) {
|
|
@@ -149,20 +149,20 @@ function useService(token, args) {
|
|
|
149
149
|
}, [args]);
|
|
150
150
|
}
|
|
151
151
|
(0, react.useEffect)(() => {
|
|
152
|
-
const eventBus =
|
|
152
|
+
const eventBus = rootContainer.getEventBus();
|
|
153
153
|
let unsubscribe;
|
|
154
154
|
let isMounted = true;
|
|
155
155
|
const fetchAndSubscribe = async () => {
|
|
156
156
|
try {
|
|
157
157
|
const instance = await container.get(token, args);
|
|
158
158
|
if (!isMounted) return;
|
|
159
|
-
const instanceName =
|
|
160
|
-
instanceNameRef.current = instanceName;
|
|
159
|
+
const instanceName = container.calculateInstanceName(token, args);
|
|
160
|
+
if (instanceName) instanceNameRef.current = instanceName;
|
|
161
161
|
dispatch({
|
|
162
162
|
type: "success",
|
|
163
163
|
data: instance
|
|
164
164
|
});
|
|
165
|
-
unsubscribe = eventBus.on(instanceName, "destroy", () => {
|
|
165
|
+
if (instanceName) unsubscribe = eventBus.on(instanceName, "destroy", () => {
|
|
166
166
|
if (isMounted) {
|
|
167
167
|
dispatch({ type: "loading" });
|
|
168
168
|
fetchAndSubscribe();
|
|
@@ -176,14 +176,16 @@ function useService(token, args) {
|
|
|
176
176
|
}
|
|
177
177
|
};
|
|
178
178
|
if (initialSyncInstanceRef.current && refetchCounter === 0) {
|
|
179
|
-
const instanceName =
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
179
|
+
const instanceName = container.calculateInstanceName(token, args);
|
|
180
|
+
if (instanceName) {
|
|
181
|
+
instanceNameRef.current = instanceName;
|
|
182
|
+
unsubscribe = eventBus.on(instanceName, "destroy", () => {
|
|
183
|
+
if (isMounted) {
|
|
184
|
+
dispatch({ type: "loading" });
|
|
185
|
+
fetchAndSubscribe();
|
|
186
|
+
}
|
|
187
|
+
});
|
|
188
|
+
}
|
|
187
189
|
} else {
|
|
188
190
|
dispatch({ type: "loading" });
|
|
189
191
|
fetchAndSubscribe();
|
|
@@ -194,7 +196,7 @@ function useService(token, args) {
|
|
|
194
196
|
};
|
|
195
197
|
}, [
|
|
196
198
|
container,
|
|
197
|
-
|
|
199
|
+
rootContainer,
|
|
198
200
|
token,
|
|
199
201
|
args,
|
|
200
202
|
refetchCounter
|
|
@@ -230,9 +232,9 @@ function getCache(container) {
|
|
|
230
232
|
* Sets up invalidation subscription for a cache entry if not already subscribed.
|
|
231
233
|
* When the service is destroyed, clears the cache and notifies subscribers.
|
|
232
234
|
*/
|
|
233
|
-
function setupInvalidationSubscription(entry,
|
|
235
|
+
function setupInvalidationSubscription(entry, rootContainer) {
|
|
234
236
|
if (entry.unsubscribe || !entry.instanceName) return;
|
|
235
|
-
entry.unsubscribe =
|
|
237
|
+
entry.unsubscribe = rootContainer.getEventBus().on(entry.instanceName, "destroy", () => {
|
|
236
238
|
entry.result = void 0;
|
|
237
239
|
entry.error = void 0;
|
|
238
240
|
entry.status = "pending";
|
|
@@ -242,7 +244,7 @@ function setupInvalidationSubscription(entry, serviceLocator) {
|
|
|
242
244
|
}
|
|
243
245
|
function useSuspenseService(token, args) {
|
|
244
246
|
const container = useContainer();
|
|
245
|
-
const
|
|
247
|
+
const rootContainer = useRootContainer();
|
|
246
248
|
const cache = getCache(container);
|
|
247
249
|
const cacheKey = getCacheKey(token, args);
|
|
248
250
|
const entryRef = (0, react.useRef)(null);
|
|
@@ -263,6 +265,7 @@ function useSuspenseService(token, args) {
|
|
|
263
265
|
}
|
|
264
266
|
if (!cache.has(cacheKey)) {
|
|
265
267
|
const syncInstance = container.tryGetSync(token, args);
|
|
268
|
+
const instanceName = container.calculateInstanceName(token, args);
|
|
266
269
|
const entry$1 = {
|
|
267
270
|
promise: null,
|
|
268
271
|
result: syncInstance ?? void 0,
|
|
@@ -270,7 +273,7 @@ function useSuspenseService(token, args) {
|
|
|
270
273
|
status: syncInstance ? "resolved" : "pending",
|
|
271
274
|
version: 0,
|
|
272
275
|
subscribers: /* @__PURE__ */ new Set(),
|
|
273
|
-
instanceName
|
|
276
|
+
instanceName,
|
|
274
277
|
unsubscribe: void 0
|
|
275
278
|
};
|
|
276
279
|
cache.set(cacheKey, entry$1);
|
|
@@ -285,8 +288,7 @@ function useSuspenseService(token, args) {
|
|
|
285
288
|
currentEntry.promise = container.get(token, args).then((instance) => {
|
|
286
289
|
currentEntry.result = instance;
|
|
287
290
|
currentEntry.status = "resolved";
|
|
288
|
-
currentEntry
|
|
289
|
-
setupInvalidationSubscription(currentEntry, serviceLocator);
|
|
291
|
+
setupInvalidationSubscription(currentEntry, rootContainer);
|
|
290
292
|
currentEntry.subscribers.forEach((callback) => callback());
|
|
291
293
|
return instance;
|
|
292
294
|
}).catch((error) => {
|
|
@@ -297,7 +299,7 @@ function useSuspenseService(token, args) {
|
|
|
297
299
|
return currentEntry.promise;
|
|
298
300
|
}, [
|
|
299
301
|
container,
|
|
300
|
-
|
|
302
|
+
rootContainer,
|
|
301
303
|
token,
|
|
302
304
|
args
|
|
303
305
|
]);
|
|
@@ -313,8 +315,8 @@ function useSuspenseService(token, args) {
|
|
|
313
315
|
(0, react.useSyncExternalStore)(subscribe, getSnapshot, getSnapshot);
|
|
314
316
|
(0, react.useEffect)(() => {
|
|
315
317
|
const currentEntry = entryRef.current;
|
|
316
|
-
if (currentEntry && currentEntry.status === "resolved" && currentEntry.instanceName && !currentEntry.unsubscribe) setupInvalidationSubscription(currentEntry,
|
|
317
|
-
}, [
|
|
318
|
+
if (currentEntry && currentEntry.status === "resolved" && currentEntry.instanceName && !currentEntry.unsubscribe) setupInvalidationSubscription(currentEntry, rootContainer);
|
|
319
|
+
}, [rootContainer, entry]);
|
|
318
320
|
if (entry.status === "pending" && !entry.promise) fetchService();
|
|
319
321
|
if (entry.status === "pending") throw entry.promise;
|
|
320
322
|
if (entry.status === "rejected") throw entry.error;
|
|
@@ -366,7 +368,7 @@ function optionalServiceReducer(state, action) {
|
|
|
366
368
|
*/
|
|
367
369
|
function useOptionalService(token, args) {
|
|
368
370
|
const container = useContainer();
|
|
369
|
-
const
|
|
371
|
+
const rootContainer = useRootContainer();
|
|
370
372
|
const initialSyncInstanceRef = (0, react.useRef)(void 0);
|
|
371
373
|
const isFirstRenderRef = (0, react.useRef)(true);
|
|
372
374
|
if (isFirstRenderRef.current) {
|
|
@@ -399,7 +401,8 @@ function useOptionalService(token, args) {
|
|
|
399
401
|
dispatch({ type: "loading" });
|
|
400
402
|
try {
|
|
401
403
|
const instance = await container.get(token, args);
|
|
402
|
-
|
|
404
|
+
const instanceName = container.calculateInstanceName(token, args);
|
|
405
|
+
if (instanceName) instanceNameRef.current = instanceName;
|
|
403
406
|
dispatch({
|
|
404
407
|
type: "success",
|
|
405
408
|
data: instance
|
|
@@ -415,28 +418,27 @@ function useOptionalService(token, args) {
|
|
|
415
418
|
}
|
|
416
419
|
}, [
|
|
417
420
|
container,
|
|
418
|
-
serviceLocator,
|
|
419
421
|
token,
|
|
420
422
|
args
|
|
421
423
|
]);
|
|
422
424
|
(0, react.useEffect)(() => {
|
|
423
|
-
const eventBus =
|
|
425
|
+
const eventBus = rootContainer.getEventBus();
|
|
424
426
|
let unsubscribe;
|
|
425
427
|
if (initialSyncInstanceRef.current) {
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
428
|
+
const instanceName = container.calculateInstanceName(token, args);
|
|
429
|
+
if (instanceName) {
|
|
430
|
+
instanceNameRef.current = instanceName;
|
|
431
|
+
unsubscribe = eventBus.on(instanceName, "destroy", () => {
|
|
432
|
+
fetchService();
|
|
433
|
+
});
|
|
434
|
+
}
|
|
430
435
|
} else {
|
|
431
|
-
fetchService()
|
|
432
|
-
const setupSubscription = () => {
|
|
436
|
+
fetchService().then(() => {
|
|
433
437
|
if (instanceNameRef.current) unsubscribe = eventBus.on(instanceNameRef.current, "destroy", () => {
|
|
434
438
|
fetchService();
|
|
435
439
|
});
|
|
436
|
-
};
|
|
437
|
-
const timeoutId = setTimeout(setupSubscription, 10);
|
|
440
|
+
});
|
|
438
441
|
return () => {
|
|
439
|
-
clearTimeout(timeoutId);
|
|
440
442
|
unsubscribe?.();
|
|
441
443
|
};
|
|
442
444
|
}
|
|
@@ -445,7 +447,7 @@ function useOptionalService(token, args) {
|
|
|
445
447
|
};
|
|
446
448
|
}, [
|
|
447
449
|
fetchService,
|
|
448
|
-
|
|
450
|
+
rootContainer,
|
|
449
451
|
token,
|
|
450
452
|
args
|
|
451
453
|
]);
|
|
@@ -462,17 +464,6 @@ function useOptionalService(token, args) {
|
|
|
462
464
|
|
|
463
465
|
//#endregion
|
|
464
466
|
//#region src/hooks/use-invalidate.mts
|
|
465
|
-
function useInvalidate(token, args) {
|
|
466
|
-
const serviceLocator = useRootContainer().getServiceLocator();
|
|
467
|
-
return (0, react.useCallback)(async () => {
|
|
468
|
-
const instanceName = serviceLocator.getInstanceIdentifier(token, args);
|
|
469
|
-
await serviceLocator.invalidate(instanceName);
|
|
470
|
-
}, [
|
|
471
|
-
serviceLocator,
|
|
472
|
-
token,
|
|
473
|
-
args
|
|
474
|
-
]);
|
|
475
|
-
}
|
|
476
467
|
/**
|
|
477
468
|
* Hook that returns a function to invalidate a service instance directly.
|
|
478
469
|
*
|
|
@@ -581,7 +572,6 @@ exports.ContainerProvider = ContainerProvider;
|
|
|
581
572
|
exports.ScopeProvider = ScopeProvider;
|
|
582
573
|
exports.ScopedContainerContext = ScopedContainerContext;
|
|
583
574
|
exports.useContainer = useContainer;
|
|
584
|
-
exports.useInvalidate = useInvalidate;
|
|
585
575
|
exports.useInvalidateInstance = useInvalidateInstance;
|
|
586
576
|
exports.useOptionalService = useOptionalService;
|
|
587
577
|
exports.useRootContainer = useRootContainer;
|
package/lib/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["unsubscribe: (() => void) | undefined","entry: CacheEntry<any>","entry","unsubscribe: (() => void) | undefined"],"sources":["../src/providers/context.mts","../src/providers/container-provider.mts","../src/providers/scope-provider.mts","../src/hooks/use-container.mts","../src/hooks/use-service.mts","../src/hooks/use-suspense-service.mts","../src/hooks/use-optional-service.mts","../src/hooks/use-invalidate.mts","../src/hooks/use-scope.mts"],"sourcesContent":["import { createContext } from 'react'\n\nimport type { Container, ScopedContainer } from '@navios/di'\n\n/**\n * Context for the root Container.\n * This is set by ContainerProvider and provides the base container.\n */\nexport const ContainerContext = createContext<Container | null>(null)\n\n/**\n * Context for the current ScopedContainer (if inside a ScopeProvider).\n * This allows nested components to access request-scoped services.\n */\nexport const ScopedContainerContext = createContext<ScopedContainer | null>(null)\n","import type { Container } from '@navios/di'\nimport type { ReactNode } from 'react'\n\nimport { jsx } from 'react/jsx-runtime'\n\nimport { ContainerContext } from './context.mjs'\n\nexport interface ContainerProviderProps {\n container: Container\n children: ReactNode\n}\n\nexport function ContainerProvider({\n container,\n children,\n}: ContainerProviderProps) {\n return jsx(ContainerContext.Provider, { value: container, children })\n}\n","import type { ReactNode } from 'react'\nimport type { ScopedContainer } from '@navios/di'\n\nimport { useContext, useEffect, useId, useRef } from 'react'\nimport { jsx } from 'react/jsx-runtime'\n\nimport { ContainerContext, ScopedContainerContext } from './context.mjs'\n\nexport interface ScopeProviderProps {\n /**\n * Optional explicit scope ID. If not provided, a unique ID will be generated.\n * Useful when you need to reference the scope externally.\n */\n scopeId?: string\n /**\n * Optional metadata to attach to the request context.\n * Can be used to pass data like user info, request headers, etc.\n */\n metadata?: Record<string, unknown>\n /**\n * Priority for service resolution. Higher priority scopes take precedence.\n * @default 100\n */\n priority?: number\n children: ReactNode\n}\n\n/**\n * ScopeProvider creates a new request scope for dependency injection.\n *\n * Services with `scope: 'Request'` will be instantiated once per ScopeProvider\n * and shared among all components within that provider.\n *\n * This is useful for:\n * - Table rows that need isolated state\n * - Modal dialogs with their own service instances\n * - Multi-tenant scenarios\n * - Any case where you need isolated service instances\n *\n * @example\n * ```tsx\n * // Each row gets its own RowStateService instance\n * {rows.map(row => (\n * <ScopeProvider key={row.id} scopeId={row.id} metadata={{ rowData: row }}>\n * <TableRow />\n * </ScopeProvider>\n * ))}\n * ```\n */\nexport function ScopeProvider({\n scopeId,\n metadata,\n priority = 100,\n children,\n}: ScopeProviderProps) {\n const container = useContext(ContainerContext)\n if (!container) {\n throw new Error('ScopeProvider must be used within a ContainerProvider')\n }\n\n const generatedId = useId()\n const effectiveScopeId = scopeId ?? generatedId\n const scopedContainerRef = useRef<ScopedContainer | null>(null)\n\n // Create ScopedContainer on first render only\n // We use a ref to track initialization to handle React StrictMode double-renders\n if (!scopedContainerRef.current) {\n // Check if this request ID already exists (e.g., from StrictMode double render)\n if (!container.hasActiveRequest(effectiveScopeId)) {\n scopedContainerRef.current = container.beginRequest(\n effectiveScopeId,\n metadata,\n priority,\n )\n }\n }\n\n // End request context on unmount\n useEffect(() => {\n const scopedContainer = scopedContainerRef.current\n return () => {\n if (scopedContainer) {\n void scopedContainer.endRequest()\n }\n }\n }, [])\n\n // If we don't have a scoped container (shouldn't happen normally), don't render\n if (!scopedContainerRef.current) {\n return null\n }\n\n return jsx(ScopedContainerContext.Provider, {\n value: scopedContainerRef.current,\n children,\n })\n}\n","import type { Container, IContainer, ScopedContainer } from '@navios/di'\n\nimport { useContext } from 'react'\n\nimport { ContainerContext, ScopedContainerContext } from '../providers/context.mjs'\n\n/**\n * Hook to get the current container (ScopedContainer if inside ScopeProvider, otherwise Container).\n *\n * This is the primary hook for accessing the DI container. It automatically\n * returns the correct container based on context:\n * - Inside a ScopeProvider: returns the ScopedContainer for request-scoped services\n * - Outside a ScopeProvider: returns the root Container\n *\n * @returns The current container (ScopedContainer or Container)\n */\nexport function useContainer(): IContainer {\n const scopedContainer = useContext(ScopedContainerContext)\n const container = useContext(ContainerContext)\n\n // Prefer scoped container if available (we're inside a ScopeProvider)\n if (scopedContainer) {\n return scopedContainer\n }\n\n if (!container) {\n throw new Error('useContainer must be used within a ContainerProvider')\n }\n\n return container\n}\n\n/**\n * Hook to get the root Container, regardless of whether we're inside a ScopeProvider.\n *\n * Use this when you need access to the root container specifically,\n * for example to create new request scopes programmatically.\n *\n * @returns The root Container\n */\nexport function useRootContainer(): Container {\n const container = useContext(ContainerContext)\n\n if (!container) {\n throw new Error('useRootContainer must be used within a ContainerProvider')\n }\n\n return container\n}\n\n/**\n * Hook to get the current ScopedContainer if inside a ScopeProvider.\n *\n * @returns The ScopedContainer or null if not inside a ScopeProvider\n */\nexport function useScopedContainer(): ScopedContainer | null {\n return useContext(ScopedContainerContext)\n}\n","import type {\n AnyInjectableType,\n BoundInjectionToken,\n ClassType,\n Factorable,\n FactoryInjectionToken,\n InjectionToken,\n InjectionTokenSchemaType,\n} from '@navios/di'\nimport type { z, ZodType } from 'zod/v4'\n\nimport { useCallback, useEffect, useReducer, useRef, useState } from 'react'\n\nimport type { Join, UnionToArray } from '../types.mjs'\n\nimport { useContainer, useRootContainer } from './use-container.mjs'\n\ntype ServiceState<T> =\n | { status: 'idle' }\n | { status: 'loading' }\n | { status: 'success'; data: T }\n | { status: 'error'; error: Error }\n\ntype ServiceAction<T> =\n | { type: 'loading' }\n | { type: 'success'; data: T }\n | { type: 'error'; error: Error }\n | { type: 'reset' }\n\nfunction serviceReducer<T>(\n state: ServiceState<T>,\n action: ServiceAction<T>,\n): ServiceState<T> {\n switch (action.type) {\n case 'loading':\n return { status: 'loading' }\n case 'success':\n return { status: 'success', data: action.data }\n case 'error':\n return { status: 'error', error: action.error }\n case 'reset':\n return { status: 'idle' }\n default:\n return state\n }\n}\n\nexport interface UseServiceResult<T> {\n data: T | undefined\n error: Error | undefined\n isLoading: boolean\n isSuccess: boolean\n isError: boolean\n refetch: () => void\n}\n\n// #1 Simple class\nexport function useService<T extends ClassType>(\n token: T,\n): UseServiceResult<\n InstanceType<T> extends Factorable<infer R> ? R : InstanceType<T>\n>\n\n// #2 Token with required Schema\nexport function useService<T, S extends InjectionTokenSchemaType>(\n token: InjectionToken<T, S>,\n args: z.input<S>,\n): UseServiceResult<T>\n\n// #3 Token with optional Schema\nexport function useService<\n T,\n S extends InjectionTokenSchemaType,\n R extends boolean,\n>(\n token: InjectionToken<T, S, R>,\n): R extends false\n ? UseServiceResult<T>\n : S extends ZodType<infer Type>\n ? `Error: Your token requires args: ${Join<UnionToArray<keyof Type>, ', '>}`\n : 'Error: Your token requires args'\n\n// #4 Token with no Schema\nexport function useService<T>(\n token: InjectionToken<T, undefined>,\n): UseServiceResult<T>\n\nexport function useService<T>(\n token: BoundInjectionToken<T, any>,\n): UseServiceResult<T>\n\nexport function useService<T>(\n token: FactoryInjectionToken<T, any>,\n): UseServiceResult<T>\n\nexport function useService(\n token:\n | ClassType\n | InjectionToken<any, any>\n | BoundInjectionToken<any, any>\n | FactoryInjectionToken<any, any>,\n args?: unknown,\n): UseServiceResult<any> {\n // useContainer returns ScopedContainer if inside ScopeProvider, otherwise Container\n // This automatically handles request-scoped services correctly\n const container = useContainer()\n const rootContainer = useRootContainer()\n const serviceLocator = rootContainer.getServiceLocator()\n\n // Try to get the instance synchronously first for better performance\n // This avoids the async loading state when the instance is already cached\n // We use a ref to track this so it doesn't cause effect re-runs\n const initialSyncInstanceRef = useRef<any>(undefined)\n const isFirstRenderRef = useRef(true)\n\n if (isFirstRenderRef.current) {\n initialSyncInstanceRef.current = container.tryGetSync(token, args)\n isFirstRenderRef.current = false\n }\n\n const initialState: ServiceState<any> = initialSyncInstanceRef.current\n ? { status: 'success', data: initialSyncInstanceRef.current }\n : { status: 'idle' }\n\n const [state, dispatch] = useReducer(serviceReducer, initialState)\n const instanceNameRef = useRef<string | null>(null)\n const [refetchCounter, setRefetchCounter] = useState(0)\n\n if (process.env.NODE_ENV === 'development') {\n const argsRef = useRef<unknown>(args)\n useEffect(() => {\n if (argsRef.current !== args) {\n if (JSON.stringify(argsRef.current) === JSON.stringify(args)) {\n console.log(`WARNING: useService called with args that look the same but are different instances: ${JSON.stringify(argsRef.current)} !== ${JSON.stringify(args)}!\n This is likely because you are using not memoized value that is not stable.\n Please use a memoized value or use a different approach to pass the args.\n Example:\n const args = useMemo(() => ({ userId: '123' }), [])\n return useService(UserToken, args)\n `)\n }\n argsRef.current = args\n }\n }, [args])\n }\n\n // Subscribe to invalidation events\n useEffect(() => {\n const eventBus = serviceLocator.getEventBus()\n let unsubscribe: (() => void) | undefined\n let isMounted = true\n\n // Fetch the service and set up subscription\n const fetchAndSubscribe = async () => {\n try {\n // The container (either ScopedContainer or Container) handles resolution correctly\n const instance = await container.get(\n // @ts-expect-error - token is valid\n token as AnyInjectableType,\n args as any,\n )\n\n if (!isMounted) return\n\n // Get instance name for event subscription\n const instanceName = serviceLocator.getInstanceIdentifier(\n token as AnyInjectableType,\n args,\n )\n instanceNameRef.current = instanceName\n\n dispatch({ type: 'success', data: instance })\n\n // Set up subscription after we have the instance\n unsubscribe = eventBus.on(instanceName, 'destroy', () => {\n // Re-fetch when the service is invalidated\n if (isMounted) {\n dispatch({ type: 'loading' })\n void fetchAndSubscribe()\n }\n })\n } catch (error) {\n if (isMounted) {\n dispatch({ type: 'error', error: error as Error })\n }\n }\n }\n\n // If we already have a sync instance from initial render, just set up subscription\n // Otherwise, fetch async\n const syncInstance = initialSyncInstanceRef.current\n if (syncInstance && refetchCounter === 0) {\n const instanceName = serviceLocator.getInstanceIdentifier(\n token as AnyInjectableType,\n args,\n )\n instanceNameRef.current = instanceName\n unsubscribe = eventBus.on(instanceName, 'destroy', () => {\n if (isMounted) {\n dispatch({ type: 'loading' })\n void fetchAndSubscribe()\n }\n })\n } else {\n dispatch({ type: 'loading' })\n void fetchAndSubscribe()\n }\n\n return () => {\n isMounted = false\n unsubscribe?.()\n }\n }, [container, serviceLocator, token, args, refetchCounter])\n\n const refetch = useCallback(() => {\n setRefetchCounter((c) => c + 1)\n }, [])\n\n return {\n data: state.status === 'success' ? state.data : undefined,\n error: state.status === 'error' ? state.error : undefined,\n isLoading: state.status === 'loading',\n isSuccess: state.status === 'success',\n isError: state.status === 'error',\n refetch,\n }\n}\n","import type {\n AnyInjectableType,\n BoundInjectionToken,\n ClassType,\n Factorable,\n FactoryInjectionToken,\n InjectionToken,\n InjectionTokenSchemaType,\n} from '@navios/di'\nimport type { z, ZodType } from 'zod/v4'\n\nimport { useCallback, useEffect, useRef, useSyncExternalStore } from 'react'\n\nimport type { Join, UnionToArray } from '../types.mjs'\n\nimport { useContainer, useRootContainer } from './use-container.mjs'\n\n// Cache entry for suspense\ninterface CacheEntry<T> {\n promise: Promise<T> | null\n result: T | undefined\n error: Error | undefined\n status: 'pending' | 'resolved' | 'rejected'\n version: number // Increment on each fetch to track changes\n subscribers: Set<() => void>\n instanceName: string | null\n unsubscribe: (() => void) | undefined\n}\n\n// Global cache for service instances (per container + token + args combination)\nconst cacheMap = new WeakMap<object, Map<string, CacheEntry<any>>>()\n\nfunction getCacheKey(token: any, args: unknown): string {\n const tokenId =\n typeof token === 'function'\n ? token.name\n : token.id || token.token?.id || String(token)\n return `${tokenId}:${JSON.stringify(args ?? null)}`\n}\n\nfunction getCache(container: object): Map<string, CacheEntry<any>> {\n let cache = cacheMap.get(container)\n if (!cache) {\n cache = new Map()\n cacheMap.set(container, cache)\n }\n return cache\n}\n\n/**\n * Sets up invalidation subscription for a cache entry if not already subscribed.\n * When the service is destroyed, clears the cache and notifies subscribers.\n */\nfunction setupInvalidationSubscription(\n entry: CacheEntry<any>,\n serviceLocator: ReturnType<\n import('@navios/di').Container['getServiceLocator']\n >,\n): void {\n if (entry.unsubscribe || !entry.instanceName) return\n\n const eventBus = serviceLocator.getEventBus()\n entry.unsubscribe = eventBus.on(entry.instanceName, 'destroy', () => {\n // Clear cache and notify subscribers to re-fetch\n entry.result = undefined\n entry.error = undefined\n entry.status = 'pending'\n entry.promise = null\n // Notify all subscribers\n entry.subscribers.forEach((callback) => callback())\n })\n}\n\n// #1 Simple class\nexport function useSuspenseService<T extends ClassType>(\n token: T,\n): InstanceType<T> extends Factorable<infer R> ? R : InstanceType<T>\n\n// #2 Token with required Schema\nexport function useSuspenseService<T, S extends InjectionTokenSchemaType>(\n token: InjectionToken<T, S>,\n args: z.input<S>,\n): T\n\n// #3 Token with optional Schema\nexport function useSuspenseService<\n T,\n S extends InjectionTokenSchemaType,\n R extends boolean,\n>(\n token: InjectionToken<T, S, R>,\n): R extends false\n ? T\n : S extends ZodType<infer Type>\n ? `Error: Your token requires args: ${Join<UnionToArray<keyof Type>, ', '>}`\n : 'Error: Your token requires args'\n\n// #4 Token with no Schema\nexport function useSuspenseService<T>(token: InjectionToken<T, undefined>): T\n\nexport function useSuspenseService<T>(token: BoundInjectionToken<T, any>): T\n\nexport function useSuspenseService<T>(token: FactoryInjectionToken<T, any>): T\n\nexport function useSuspenseService(\n token:\n | ClassType\n | InjectionToken<any, any>\n | BoundInjectionToken<any, any>\n | FactoryInjectionToken<any, any>,\n args?: unknown,\n): any {\n // useContainer returns ScopedContainer if inside ScopeProvider, otherwise Container\n const container = useContainer()\n const rootContainer = useRootContainer()\n const serviceLocator = rootContainer.getServiceLocator()\n const cache = getCache(container)\n const cacheKey = getCacheKey(token, args)\n const entryRef = useRef<CacheEntry<any> | null>(null)\n if (process.env.NODE_ENV === 'development') {\n const argsRef = useRef<unknown>(args)\n useEffect(() => {\n if (argsRef.current !== args) {\n if (JSON.stringify(argsRef.current) === JSON.stringify(args)) {\n console.log(`WARNING: useService called with args that look the same but are different instances: ${JSON.stringify(argsRef.current)} !== ${JSON.stringify(args)}!\n This is likely because you are using not memoized value that is not stable.\n Please use a memoized value or use a different approach to pass the args.\n Example:\n const args = useMemo(() => ({ userId: '123' }), [])\n return useService(UserToken, args)\n `)\n }\n argsRef.current = args\n }\n }, [args])\n }\n\n // Initialize or get cache entry\n if (!cache.has(cacheKey)) {\n // Try to get the instance synchronously first for better performance\n // This avoids suspense when the instance is already cached\n const syncInstance = container.tryGetSync(token, args)\n\n const entry: CacheEntry<any> = {\n promise: null,\n result: syncInstance ?? undefined,\n error: undefined,\n status: syncInstance ? 'resolved' : 'pending',\n version: 0,\n subscribers: new Set(),\n instanceName: syncInstance\n ? serviceLocator.getInstanceIdentifier(token as AnyInjectableType, args)\n : null,\n unsubscribe: undefined,\n }\n cache.set(cacheKey, entry)\n }\n\n const entry = cache.get(cacheKey)!\n entryRef.current = entry\n\n // Function to fetch the service\n const fetchService = useCallback(() => {\n const currentEntry = entryRef.current\n if (!currentEntry) return\n\n currentEntry.status = 'pending'\n currentEntry.version++ // Increment version to signal change to useSyncExternalStore\n currentEntry.promise = (container.get as any)(token, args)\n .then((instance: any) => {\n currentEntry.result = instance\n currentEntry.status = 'resolved'\n currentEntry.instanceName = serviceLocator.getInstanceIdentifier(\n token as AnyInjectableType,\n args,\n )\n\n // Subscribe to invalidation events if not already subscribed\n setupInvalidationSubscription(currentEntry, serviceLocator)\n\n // Notify subscribers\n currentEntry.subscribers.forEach((callback) => callback())\n return instance\n })\n .catch((error: Error) => {\n currentEntry.error = error\n currentEntry.status = 'rejected'\n throw error\n })\n\n return currentEntry.promise\n }, [container, serviceLocator, token, args])\n\n // Subscribe to cache changes\n const subscribe = useCallback(\n (callback: () => void) => {\n entry.subscribers.add(callback)\n return () => {\n entry.subscribers.delete(callback)\n }\n },\n [entry],\n )\n\n // Get snapshot of current state - include version to detect invalidation\n const getSnapshot = useCallback(() => {\n return `${entry.status}:${entry.version}`\n }, [entry])\n\n // Use sync external store to track cache state\n useSyncExternalStore(subscribe, getSnapshot, getSnapshot)\n\n // Set up subscription for sync instances that don't have one yet\n useEffect(() => {\n const currentEntry = entryRef.current\n if (\n currentEntry &&\n currentEntry.status === 'resolved' &&\n currentEntry.instanceName &&\n !currentEntry.unsubscribe\n ) {\n setupInvalidationSubscription(currentEntry, serviceLocator)\n }\n }, [serviceLocator, entry])\n\n // Start fetching if not already\n if (entry.status === 'pending' && !entry.promise) {\n fetchService()\n }\n\n // Suspense behavior\n if (entry.status === 'pending') {\n throw entry.promise\n }\n\n if (entry.status === 'rejected') {\n throw entry.error\n }\n\n return entry.result\n}\n","import type {\n AnyInjectableType,\n BoundInjectionToken,\n ClassType,\n Factorable,\n FactoryInjectionToken,\n InjectionToken,\n InjectionTokenSchemaType,\n} from '@navios/di'\nimport type { z, ZodType } from 'zod/v4'\n\nimport { useCallback, useEffect, useReducer, useRef } from 'react'\n\nimport type { Join, UnionToArray } from '../types.mjs'\n\nimport { useContainer, useRootContainer } from './use-container.mjs'\n\ntype OptionalServiceState<T> =\n | { status: 'idle' }\n | { status: 'loading' }\n | { status: 'success'; data: T }\n | { status: 'not-found' }\n | { status: 'error'; error: Error }\n\ntype OptionalServiceAction<T> =\n | { type: 'loading' }\n | { type: 'success'; data: T }\n | { type: 'not-found' }\n | { type: 'error'; error: Error }\n | { type: 'reset' }\n\nfunction optionalServiceReducer<T>(\n state: OptionalServiceState<T>,\n action: OptionalServiceAction<T>,\n): OptionalServiceState<T> {\n switch (action.type) {\n case 'loading':\n return { status: 'loading' }\n case 'success':\n return { status: 'success', data: action.data }\n case 'not-found':\n return { status: 'not-found' }\n case 'error':\n return { status: 'error', error: action.error }\n case 'reset':\n return { status: 'idle' }\n default:\n return state\n }\n}\n\nexport interface UseOptionalServiceResult<T> {\n /**\n * The service instance if found and loaded successfully, otherwise undefined.\n */\n data: T | undefined\n /**\n * Error that occurred during loading (excludes \"not found\" which is not an error).\n */\n error: Error | undefined\n /**\n * True while the service is being loaded.\n */\n isLoading: boolean\n /**\n * True if the service was loaded successfully.\n */\n isSuccess: boolean\n /**\n * True if the service was not found (not registered in the container).\n */\n isNotFound: boolean\n /**\n * True if an error occurred during loading.\n */\n isError: boolean\n /**\n * Function to manually re-fetch the service.\n */\n refetch: () => void\n}\n\n// #1 Simple class\nexport function useOptionalService<T extends ClassType>(\n token: T,\n): UseOptionalServiceResult<\n InstanceType<T> extends Factorable<infer R> ? R : InstanceType<T>\n>\n\n// #2 Token with required Schema\nexport function useOptionalService<T, S extends InjectionTokenSchemaType>(\n token: InjectionToken<T, S>,\n args: z.input<S>,\n): UseOptionalServiceResult<T>\n\n// #3 Token with optional Schema\nexport function useOptionalService<\n T,\n S extends InjectionTokenSchemaType,\n R extends boolean,\n>(\n token: InjectionToken<T, S, R>,\n): R extends false\n ? UseOptionalServiceResult<T>\n : S extends ZodType<infer Type>\n ? `Error: Your token requires args: ${Join<UnionToArray<keyof Type>, ', '>}`\n : 'Error: Your token requires args'\n\n// #4 Token with no Schema\nexport function useOptionalService<T>(\n token: InjectionToken<T, undefined>,\n): UseOptionalServiceResult<T>\n\nexport function useOptionalService<T>(\n token: BoundInjectionToken<T, any>,\n): UseOptionalServiceResult<T>\n\nexport function useOptionalService<T>(\n token: FactoryInjectionToken<T, any>,\n): UseOptionalServiceResult<T>\n\n/**\n * Hook to optionally load a service from the DI container.\n *\n * Unlike useService, this hook does NOT throw an error if the service is not registered.\n * Instead, it returns `isNotFound: true` when the service doesn't exist.\n *\n * This is useful for:\n * - Optional dependencies that may or may not be configured\n * - Feature flags where a service might not be available\n * - Plugins or extensions that are conditionally registered\n *\n * @example\n * ```tsx\n * function Analytics() {\n * const { data: analytics, isNotFound } = useOptionalService(AnalyticsService)\n *\n * if (isNotFound) {\n * // Analytics service not configured, skip tracking\n * return null\n * }\n *\n * return <AnalyticsTracker service={analytics} />\n * }\n * ```\n */\nexport function useOptionalService(\n token:\n | ClassType\n | InjectionToken<any, any>\n | BoundInjectionToken<any, any>\n | FactoryInjectionToken<any, any>,\n args?: unknown,\n): UseOptionalServiceResult<any> {\n // useContainer returns ScopedContainer if inside ScopeProvider, otherwise Container\n const container = useContainer()\n const rootContainer = useRootContainer()\n const serviceLocator = rootContainer.getServiceLocator()\n\n // Try to get the instance synchronously first for better performance\n // This avoids the async loading state when the instance is already cached\n // We use a ref to track this so it doesn't cause effect re-runs\n const initialSyncInstanceRef = useRef<any>(undefined)\n const isFirstRenderRef = useRef(true)\n\n if (isFirstRenderRef.current) {\n try {\n initialSyncInstanceRef.current = container.tryGetSync(token, args)\n } catch {\n // Service not registered, leave as undefined\n }\n isFirstRenderRef.current = false\n }\n\n const initialState: OptionalServiceState<any> = initialSyncInstanceRef.current\n ? { status: 'success', data: initialSyncInstanceRef.current }\n : { status: 'idle' }\n\n const [state, dispatch] = useReducer(optionalServiceReducer, initialState)\n const instanceNameRef = useRef<string | null>(null)\n\n if (process.env.NODE_ENV === 'development') {\n const argsRef = useRef<unknown>(args)\n useEffect(() => {\n if (argsRef.current !== args) {\n if (JSON.stringify(argsRef.current) === JSON.stringify(args)) {\n console.log(`WARNING: useOptionalService called with args that look the same but are different instances: ${JSON.stringify(argsRef.current)} !== ${JSON.stringify(args)}!\n This is likely because you are using not memoized value that is not stable.\n Please use a memoized value or use a different approach to pass the args.\n Example:\n const args = useMemo(() => ({ userId: '123' }), [])\n return useOptionalService(UserToken, args)\n `)\n }\n argsRef.current = args\n }\n }, [args])\n }\n\n const fetchService = useCallback(async () => {\n dispatch({ type: 'loading' })\n try {\n // Use the container (ScopedContainer or Container) for resolution\n const instance = await container.get(\n // @ts-expect-error - token is valid\n token as AnyInjectableType,\n args as any,\n )\n\n // Get instance name for event subscription\n instanceNameRef.current = serviceLocator.getInstanceIdentifier(\n token as AnyInjectableType,\n args,\n )\n dispatch({ type: 'success', data: instance })\n } catch (error) {\n // Caught exceptions are treated as errors\n const err = error as Error\n const errorMessage = err.message?.toLowerCase() ?? ''\n if (\n errorMessage.includes('not found') ||\n errorMessage.includes('not registered') ||\n errorMessage.includes('no provider')\n ) {\n dispatch({ type: 'not-found' })\n } else {\n dispatch({ type: 'error', error: err })\n }\n }\n }, [container, serviceLocator, token, args])\n\n // Subscribe to invalidation events\n useEffect(() => {\n const eventBus = serviceLocator.getEventBus()\n let unsubscribe: (() => void) | undefined\n\n // If we already have a sync instance from initial render, just set up subscription\n // Otherwise, fetch async\n const syncInstance = initialSyncInstanceRef.current\n if (syncInstance) {\n instanceNameRef.current = serviceLocator.getInstanceIdentifier(\n token as AnyInjectableType,\n args,\n )\n unsubscribe = eventBus.on(instanceNameRef.current, 'destroy', () => {\n void fetchService()\n })\n } else {\n void fetchService()\n\n // Set up subscription after we have the instance name\n const setupSubscription = () => {\n if (instanceNameRef.current) {\n unsubscribe = eventBus.on(instanceNameRef.current, 'destroy', () => {\n // Re-fetch when the service is invalidated\n void fetchService()\n })\n }\n }\n\n // Wait a tick for the instance name to be set\n const timeoutId = setTimeout(setupSubscription, 10)\n\n return () => {\n clearTimeout(timeoutId)\n unsubscribe?.()\n }\n }\n\n return () => {\n unsubscribe?.()\n }\n }, [fetchService, serviceLocator, token, args])\n\n return {\n data: state.status === 'success' ? state.data : undefined,\n error: state.status === 'error' ? state.error : undefined,\n isLoading: state.status === 'loading',\n isSuccess: state.status === 'success',\n isNotFound: state.status === 'not-found',\n isError: state.status === 'error',\n refetch: fetchService,\n }\n}\n","import type {\n BoundInjectionToken,\n ClassType,\n FactoryInjectionToken,\n InjectionToken,\n InjectionTokenSchemaType,\n} from '@navios/di'\n\nimport { useCallback } from 'react'\n\nimport { useContainer, useRootContainer } from './use-container.mjs'\n\ntype InvalidatableToken =\n | ClassType\n | InjectionToken<any, any>\n | BoundInjectionToken<any, any>\n | FactoryInjectionToken<any, any>\n\n/**\n * Hook that returns a function to invalidate a service by its token.\n *\n * When called, this will:\n * 1. Destroy the current service instance\n * 2. Trigger re-fetch in all components using useService/useSuspenseService for that token\n *\n * @example\n * ```tsx\n * function UserProfile() {\n * const { data: user } = useService(UserService)\n * const invalidateUser = useInvalidate(UserService)\n *\n * const handleRefresh = () => {\n * invalidateUser() // All components using UserService will re-fetch\n * }\n *\n * return (\n * <div>\n * <span>{user?.name}</span>\n * <button onClick={handleRefresh}>Refresh</button>\n * </div>\n * )\n * }\n * ```\n */\nexport function useInvalidate<T extends InvalidatableToken>(\n token: T,\n): () => Promise<void>\n\n/**\n * Hook that returns a function to invalidate a service by its token with args.\n *\n * @example\n * ```tsx\n * function UserProfile({ userId }: { userId: string }) {\n * const args = useMemo(() => ({ userId }), [userId])\n * const { data: user } = useService(UserToken, args)\n * const invalidateUser = useInvalidate(UserToken, args)\n *\n * return (\n * <div>\n * <span>{user?.name}</span>\n * <button onClick={() => invalidateUser()}>Refresh</button>\n * </div>\n * )\n * }\n * ```\n */\nexport function useInvalidate<T, S extends InjectionTokenSchemaType>(\n token: InjectionToken<T, S>,\n args: S extends undefined ? never : unknown,\n): () => Promise<void>\n\nexport function useInvalidate(\n token: InvalidatableToken,\n args?: unknown,\n): () => Promise<void> {\n const rootContainer = useRootContainer()\n const serviceLocator = rootContainer.getServiceLocator()\n\n return useCallback(async () => {\n const instanceName = serviceLocator.getInstanceIdentifier(token, args)\n await serviceLocator.invalidate(instanceName)\n }, [serviceLocator, token, args])\n}\n\n/**\n * Hook that returns a function to invalidate a service instance directly.\n *\n * This is useful when you have the service instance and want to invalidate it\n * without knowing its token.\n *\n * @example\n * ```tsx\n * function UserProfile() {\n * const { data: user } = useService(UserService)\n * const invalidateInstance = useInvalidateInstance()\n *\n * const handleRefresh = () => {\n * if (user) {\n * invalidateInstance(user)\n * }\n * }\n *\n * return (\n * <div>\n * <span>{user?.name}</span>\n * <button onClick={handleRefresh}>Refresh</button>\n * </div>\n * )\n * }\n * ```\n */\nexport function useInvalidateInstance(): (instance: unknown) => Promise<void> {\n const container = useContainer()\n\n return useCallback(\n async (instance: unknown) => {\n await container.invalidate(instance)\n },\n [container],\n )\n}\n","import type { ScopedContainer } from '@navios/di'\n\nimport { useContext } from 'react'\n\nimport { ScopedContainerContext } from '../providers/context.mjs'\n\n/**\n * Hook to get the current scope ID.\n * Returns null if not inside a ScopeProvider.\n */\nexport function useScope(): string | null {\n const scopedContainer = useContext(ScopedContainerContext)\n return scopedContainer?.getRequestId() ?? null\n}\n\n/**\n * Hook to get the current scope ID, throwing if not inside a ScopeProvider.\n * Use this when your component requires a scope to function correctly.\n */\nexport function useScopeOrThrow(): string {\n const scopeId = useScope()\n if (scopeId === null) {\n throw new Error(\n 'useScopeOrThrow must be used within a ScopeProvider. ' +\n 'Wrap your component tree with <ScopeProvider> to create a request scope.',\n )\n }\n return scopeId\n}\n\n/**\n * Hook to get the current ScopedContainer.\n * Returns null if not inside a ScopeProvider.\n *\n * Use this to access scope metadata or other ScopedContainer methods.\n *\n * @example\n * ```tsx\n * function TableRow() {\n * const scope = useScopedContainer()\n * const rowData = scope?.getMetadata('rowData')\n * // ...\n * }\n * ```\n */\nexport function useScopedContainer(): ScopedContainer | null {\n return useContext(ScopedContainerContext)\n}\n\n/**\n * Hook to get the current ScopedContainer, throwing if not inside a ScopeProvider.\n * Use this when your component requires a scope to function correctly.\n */\nexport function useScopedContainerOrThrow(): ScopedContainer {\n const scopedContainer = useScopedContainer()\n if (scopedContainer === null) {\n throw new Error(\n 'useScopedContainerOrThrow must be used within a ScopeProvider. ' +\n 'Wrap your component tree with <ScopeProvider> to create a request scope.',\n )\n }\n return scopedContainer\n}\n\n/**\n * Hook to get metadata from the current scope.\n * Returns undefined if not inside a ScopeProvider or if the key doesn't exist.\n *\n * @example\n * ```tsx\n * // In parent component:\n * <ScopeProvider metadata={{ userId: '123', theme: 'dark' }}>\n * <ChildComponent />\n * </ScopeProvider>\n *\n * // In child component:\n * function ChildComponent() {\n * const userId = useScopeMetadata<string>('userId')\n * const theme = useScopeMetadata<'light' | 'dark'>('theme')\n * // ...\n * }\n * ```\n */\nexport function useScopeMetadata<T = unknown>(key: string): T | undefined {\n const scopedContainer = useContext(ScopedContainerContext)\n return scopedContainer?.getMetadata(key) as T | undefined\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["unsubscribe: (() => void) | undefined","entry: CacheEntry<any>","entry","unsubscribe: (() => void) | undefined"],"sources":["../src/providers/context.mts","../src/providers/container-provider.mts","../src/providers/scope-provider.mts","../src/hooks/use-container.mts","../src/hooks/use-service.mts","../src/hooks/use-suspense-service.mts","../src/hooks/use-optional-service.mts","../src/hooks/use-invalidate.mts","../src/hooks/use-scope.mts"],"sourcesContent":["import { createContext } from 'react'\n\nimport type { Container, ScopedContainer } from '@navios/di'\n\n/**\n * Context for the root Container.\n * This is set by ContainerProvider and provides the base container.\n */\nexport const ContainerContext = createContext<Container | null>(null)\n\n/**\n * Context for the current ScopedContainer (if inside a ScopeProvider).\n * This allows nested components to access request-scoped services.\n */\nexport const ScopedContainerContext = createContext<ScopedContainer | null>(null)\n","import type { Container } from '@navios/di'\nimport type { ReactNode } from 'react'\n\nimport { jsx } from 'react/jsx-runtime'\n\nimport { ContainerContext } from './context.mjs'\n\nexport interface ContainerProviderProps {\n container: Container\n children: ReactNode\n}\n\nexport function ContainerProvider({\n container,\n children,\n}: ContainerProviderProps) {\n return jsx(ContainerContext.Provider, { value: container, children })\n}\n","import type { ScopedContainer } from '@navios/di'\nimport type { ReactNode } from 'react'\n\nimport { useContext, useEffect, useId, useRef } from 'react'\nimport { jsx } from 'react/jsx-runtime'\n\nimport { ContainerContext, ScopedContainerContext } from './context.mjs'\n\nexport interface ScopeProviderProps {\n /**\n * Optional explicit scope ID. If not provided, a unique ID will be generated.\n * Useful when you need to reference the scope externally.\n */\n scopeId?: string\n /**\n * Optional metadata to attach to the request context.\n * Can be used to pass data like user info, request headers, etc.\n */\n metadata?: Record<string, unknown>\n children: ReactNode\n}\n\n/**\n * ScopeProvider creates a new request scope for dependency injection.\n *\n * Services with `scope: 'Request'` will be instantiated once per ScopeProvider\n * and shared among all components within that provider.\n *\n * This is useful for:\n * - Table rows that need isolated state\n * - Modal dialogs with their own service instances\n * - Multi-tenant scenarios\n * - Any case where you need isolated service instances\n *\n * @example\n * ```tsx\n * // Each row gets its own RowStateService instance\n * {rows.map(row => (\n * <ScopeProvider key={row.id} scopeId={row.id} metadata={{ rowData: row }}>\n * <TableRow />\n * </ScopeProvider>\n * ))}\n * ```\n */\nexport function ScopeProvider({\n scopeId,\n metadata,\n children,\n}: ScopeProviderProps) {\n const container = useContext(ContainerContext)\n if (!container) {\n throw new Error('ScopeProvider must be used within a ContainerProvider')\n }\n\n const generatedId = useId()\n const effectiveScopeId = scopeId ?? generatedId\n const scopedContainerRef = useRef<ScopedContainer | null>(null)\n\n // Create ScopedContainer on first render only\n // We use a ref to track initialization to handle React StrictMode double-renders\n if (!scopedContainerRef.current) {\n // Check if this request ID already exists (e.g., from StrictMode double render)\n if (!container.hasActiveRequest(effectiveScopeId)) {\n scopedContainerRef.current = container.beginRequest(\n effectiveScopeId,\n metadata,\n )\n }\n }\n\n // End request context on unmount\n useEffect(() => {\n const scopedContainer = scopedContainerRef.current\n return () => {\n if (scopedContainer) {\n void scopedContainer.endRequest()\n }\n }\n }, [])\n\n // If we don't have a scoped container (shouldn't happen normally), don't render\n if (!scopedContainerRef.current) {\n return null\n }\n\n return jsx(ScopedContainerContext.Provider, {\n value: scopedContainerRef.current,\n children,\n })\n}\n","import type { Container, ScopedContainer } from '@navios/di'\n\nimport { useContext } from 'react'\n\nimport {\n ContainerContext,\n ScopedContainerContext,\n} from '../providers/context.mjs'\n\n/**\n * Hook to get the current container (ScopedContainer if inside ScopeProvider, otherwise Container).\n *\n * This is the primary hook for accessing the DI container. It automatically\n * returns the correct container based on context:\n * - Inside a ScopeProvider: returns the ScopedContainer for request-scoped services\n * - Outside a ScopeProvider: returns the root Container\n *\n * @returns The current container (ScopedContainer or Container)\n */\nexport function useContainer(): Container | ScopedContainer {\n const scopedContainer = useContext(ScopedContainerContext)\n const container = useContext(ContainerContext)\n\n // Prefer scoped container if available (we're inside a ScopeProvider)\n if (scopedContainer) {\n return scopedContainer\n }\n\n if (!container) {\n throw new Error('useContainer must be used within a ContainerProvider')\n }\n\n return container\n}\n\n/**\n * Hook to get the root Container, regardless of whether we're inside a ScopeProvider.\n *\n * Use this when you need access to the root container specifically,\n * for example to create new request scopes programmatically.\n *\n * @returns The root Container\n */\nexport function useRootContainer(): Container {\n const container = useContext(ContainerContext)\n\n if (!container) {\n throw new Error('useRootContainer must be used within a ContainerProvider')\n }\n\n return container\n}\n\n/**\n * Hook to get the current ScopedContainer if inside a ScopeProvider.\n *\n * @returns The ScopedContainer or null if not inside a ScopeProvider\n */\nexport function useScopedContainer(): ScopedContainer | null {\n return useContext(ScopedContainerContext)\n}\n","import type {\n AnyInjectableType,\n BoundInjectionToken,\n ClassType,\n Factorable,\n FactoryInjectionToken,\n InjectionToken,\n InjectionTokenSchemaType,\n} from '@navios/di'\nimport type { z, ZodType } from 'zod/v4'\n\nimport { useCallback, useEffect, useReducer, useRef, useState } from 'react'\n\nimport type { Join, UnionToArray } from '../types.mjs'\n\nimport { useContainer, useRootContainer } from './use-container.mjs'\n\ntype ServiceState<T> =\n | { status: 'idle' }\n | { status: 'loading' }\n | { status: 'success'; data: T }\n | { status: 'error'; error: Error }\n\ntype ServiceAction<T> =\n | { type: 'loading' }\n | { type: 'success'; data: T }\n | { type: 'error'; error: Error }\n | { type: 'reset' }\n\nfunction serviceReducer<T>(\n state: ServiceState<T>,\n action: ServiceAction<T>,\n): ServiceState<T> {\n switch (action.type) {\n case 'loading':\n return { status: 'loading' }\n case 'success':\n return { status: 'success', data: action.data }\n case 'error':\n return { status: 'error', error: action.error }\n case 'reset':\n return { status: 'idle' }\n default:\n return state\n }\n}\n\nexport interface UseServiceResult<T> {\n data: T | undefined\n error: Error | undefined\n isLoading: boolean\n isSuccess: boolean\n isError: boolean\n refetch: () => void\n}\n\n// #1 Simple class\nexport function useService<T extends ClassType>(\n token: T,\n): UseServiceResult<\n InstanceType<T> extends Factorable<infer R> ? R : InstanceType<T>\n>\n\n// #2 Token with required Schema\nexport function useService<T, S extends InjectionTokenSchemaType>(\n token: InjectionToken<T, S>,\n args: z.input<S>,\n): UseServiceResult<T>\n\n// #3 Token with optional Schema\nexport function useService<\n T,\n S extends InjectionTokenSchemaType,\n R extends boolean,\n>(\n token: InjectionToken<T, S, R>,\n): R extends false\n ? UseServiceResult<T>\n : S extends ZodType<infer Type>\n ? `Error: Your token requires args: ${Join<UnionToArray<keyof Type>, ', '>}`\n : 'Error: Your token requires args'\n\n// #4 Token with no Schema\nexport function useService<T>(\n token: InjectionToken<T, undefined>,\n): UseServiceResult<T>\n\nexport function useService<T>(\n token: BoundInjectionToken<T, any>,\n): UseServiceResult<T>\n\nexport function useService<T>(\n token: FactoryInjectionToken<T, any>,\n): UseServiceResult<T>\n\nexport function useService(\n token:\n | ClassType\n | InjectionToken<any, any>\n | BoundInjectionToken<any, any>\n | FactoryInjectionToken<any, any>,\n args?: unknown,\n): UseServiceResult<any> {\n // useContainer returns ScopedContainer if inside ScopeProvider, otherwise Container\n // This automatically handles request-scoped services correctly\n const container = useContainer()\n const rootContainer = useRootContainer()\n\n // Try to get the instance synchronously first for better performance\n // This avoids the async loading state when the instance is already cached\n // We use a ref to track this so it doesn't cause effect re-runs\n const initialSyncInstanceRef = useRef<any>(undefined)\n const isFirstRenderRef = useRef(true)\n\n if (isFirstRenderRef.current) {\n initialSyncInstanceRef.current = container.tryGetSync(token, args)\n isFirstRenderRef.current = false\n }\n\n const initialState: ServiceState<any> = initialSyncInstanceRef.current\n ? { status: 'success', data: initialSyncInstanceRef.current }\n : { status: 'idle' }\n\n const [state, dispatch] = useReducer(serviceReducer, initialState)\n const instanceNameRef = useRef<string | null>(null)\n const [refetchCounter, setRefetchCounter] = useState(0)\n\n if (process.env.NODE_ENV === 'development') {\n const argsRef = useRef<unknown>(args)\n useEffect(() => {\n if (argsRef.current !== args) {\n if (JSON.stringify(argsRef.current) === JSON.stringify(args)) {\n console.log(`WARNING: useService called with args that look the same but are different instances: ${JSON.stringify(argsRef.current)} !== ${JSON.stringify(args)}!\n This is likely because you are using not memoized value that is not stable.\n Please use a memoized value or use a different approach to pass the args.\n Example:\n const args = useMemo(() => ({ userId: '123' }), [])\n return useService(UserToken, args)\n `)\n }\n argsRef.current = args\n }\n }, [args])\n }\n\n // Subscribe to invalidation events\n useEffect(() => {\n const eventBus = rootContainer.getEventBus()\n let unsubscribe: (() => void) | undefined\n let isMounted = true\n\n // Fetch the service and set up subscription\n const fetchAndSubscribe = async () => {\n try {\n // The container (either ScopedContainer or Container) handles resolution correctly\n const instance = await container.get(\n // @ts-expect-error - token is valid\n token as AnyInjectableType,\n args as any,\n )\n\n if (!isMounted) return\n\n // Get instance name for event subscription\n const instanceName = container.calculateInstanceName(token, args)\n if (instanceName) {\n instanceNameRef.current = instanceName\n }\n\n dispatch({ type: 'success', data: instance })\n\n // Set up subscription after we have the instance\n if (instanceName) {\n unsubscribe = eventBus.on(instanceName, 'destroy', () => {\n // Re-fetch when the service is invalidated\n if (isMounted) {\n dispatch({ type: 'loading' })\n void fetchAndSubscribe()\n }\n })\n }\n } catch (error) {\n if (isMounted) {\n dispatch({ type: 'error', error: error as Error })\n }\n }\n }\n\n // If we already have a sync instance from initial render, just set up subscription\n // Otherwise, fetch async\n const syncInstance = initialSyncInstanceRef.current\n if (syncInstance && refetchCounter === 0) {\n const instanceName = container.calculateInstanceName(token, args)\n if (instanceName) {\n instanceNameRef.current = instanceName\n unsubscribe = eventBus.on(instanceName, 'destroy', () => {\n if (isMounted) {\n dispatch({ type: 'loading' })\n void fetchAndSubscribe()\n }\n })\n }\n } else {\n dispatch({ type: 'loading' })\n void fetchAndSubscribe()\n }\n\n return () => {\n isMounted = false\n unsubscribe?.()\n }\n }, [container, rootContainer, token, args, refetchCounter])\n\n const refetch = useCallback(() => {\n setRefetchCounter((c) => c + 1)\n }, [])\n\n return {\n data: state.status === 'success' ? state.data : undefined,\n error: state.status === 'error' ? state.error : undefined,\n isLoading: state.status === 'loading',\n isSuccess: state.status === 'success',\n isError: state.status === 'error',\n refetch,\n }\n}\n","import type {\n BoundInjectionToken,\n ClassType,\n Container,\n Factorable,\n FactoryInjectionToken,\n InjectionToken,\n InjectionTokenSchemaType,\n} from '@navios/di'\nimport type { z, ZodType } from 'zod/v4'\n\n\nimport { useCallback, useEffect, useRef, useSyncExternalStore } from 'react'\n\nimport type { Join, UnionToArray } from '../types.mjs'\n\nimport { useContainer, useRootContainer } from './use-container.mjs'\n\n// Cache entry for suspense\ninterface CacheEntry<T> {\n promise: Promise<T> | null\n result: T | undefined\n error: Error | undefined\n status: 'pending' | 'resolved' | 'rejected'\n version: number // Increment on each fetch to track changes\n subscribers: Set<() => void>\n instanceName: string | null\n unsubscribe: (() => void) | undefined\n}\n\n// Global cache for service instances (per container + token + args combination)\nconst cacheMap = new WeakMap<object, Map<string, CacheEntry<any>>>()\n\nfunction getCacheKey(token: any, args: unknown): string {\n const tokenId =\n typeof token === 'function'\n ? token.name\n : token.id || token.token?.id || String(token)\n return `${tokenId}:${JSON.stringify(args ?? null)}`\n}\n\nfunction getCache(container: object): Map<string, CacheEntry<any>> {\n let cache = cacheMap.get(container)\n if (!cache) {\n cache = new Map()\n cacheMap.set(container, cache)\n }\n return cache\n}\n\n/**\n * Sets up invalidation subscription for a cache entry if not already subscribed.\n * When the service is destroyed, clears the cache and notifies subscribers.\n */\nfunction setupInvalidationSubscription(\n entry: CacheEntry<any>,\n rootContainer: Container,\n): void {\n if (entry.unsubscribe || !entry.instanceName) return\n\n const eventBus = rootContainer.getEventBus()\n entry.unsubscribe = eventBus.on(entry.instanceName, 'destroy', () => {\n // Clear cache and notify subscribers to re-fetch\n entry.result = undefined\n entry.error = undefined\n entry.status = 'pending'\n entry.promise = null\n // Notify all subscribers\n entry.subscribers.forEach((callback) => callback())\n })\n}\n\n// #1 Simple class\nexport function useSuspenseService<T extends ClassType>(\n token: T,\n): InstanceType<T> extends Factorable<infer R> ? R : InstanceType<T>\n\n// #2 Token with required Schema\nexport function useSuspenseService<T, S extends InjectionTokenSchemaType>(\n token: InjectionToken<T, S>,\n args: z.input<S>,\n): T\n\n// #3 Token with optional Schema\nexport function useSuspenseService<\n T,\n S extends InjectionTokenSchemaType,\n R extends boolean,\n>(\n token: InjectionToken<T, S, R>,\n): R extends false\n ? T\n : S extends ZodType<infer Type>\n ? `Error: Your token requires args: ${Join<UnionToArray<keyof Type>, ', '>}`\n : 'Error: Your token requires args'\n\n// #4 Token with no Schema\nexport function useSuspenseService<T>(token: InjectionToken<T, undefined>): T\n\nexport function useSuspenseService<T>(token: BoundInjectionToken<T, any>): T\n\nexport function useSuspenseService<T>(token: FactoryInjectionToken<T, any>): T\n\nexport function useSuspenseService(\n token:\n | ClassType\n | InjectionToken<any, any>\n | BoundInjectionToken<any, any>\n | FactoryInjectionToken<any, any>,\n args?: unknown,\n): any {\n // useContainer returns ScopedContainer if inside ScopeProvider, otherwise Container\n const container = useContainer()\n const rootContainer = useRootContainer()\n const cache = getCache(container)\n const cacheKey = getCacheKey(token, args)\n const entryRef = useRef<CacheEntry<any> | null>(null)\n if (process.env.NODE_ENV === 'development') {\n const argsRef = useRef<unknown>(args)\n useEffect(() => {\n if (argsRef.current !== args) {\n if (JSON.stringify(argsRef.current) === JSON.stringify(args)) {\n console.log(`WARNING: useService called with args that look the same but are different instances: ${JSON.stringify(argsRef.current)} !== ${JSON.stringify(args)}!\n This is likely because you are using not memoized value that is not stable.\n Please use a memoized value or use a different approach to pass the args.\n Example:\n const args = useMemo(() => ({ userId: '123' }), [])\n return useService(UserToken, args)\n `)\n }\n argsRef.current = args\n }\n }, [args])\n }\n\n // Initialize or get cache entry\n if (!cache.has(cacheKey)) {\n // Try to get the instance synchronously first for better performance\n // This avoids suspense when the instance is already cached\n const syncInstance = container.tryGetSync(token, args)\n\n const instanceName = container.calculateInstanceName(token, args)\n const entry: CacheEntry<any> = {\n promise: null,\n result: syncInstance ?? undefined,\n error: undefined,\n status: syncInstance ? 'resolved' : 'pending',\n version: 0,\n subscribers: new Set(),\n instanceName,\n unsubscribe: undefined,\n }\n cache.set(cacheKey, entry)\n }\n\n const entry = cache.get(cacheKey)!\n entryRef.current = entry\n\n // Function to fetch the service\n const fetchService = useCallback(() => {\n const currentEntry = entryRef.current\n if (!currentEntry) return\n\n currentEntry.status = 'pending'\n currentEntry.version++ // Increment version to signal change to useSyncExternalStore\n currentEntry.promise = (container.get as any)(token, args)\n .then((instance: any) => {\n currentEntry.result = instance\n currentEntry.status = 'resolved'\n\n // Subscribe to invalidation events if not already subscribed\n setupInvalidationSubscription(currentEntry, rootContainer)\n\n // Notify subscribers\n currentEntry.subscribers.forEach((callback) => callback())\n return instance\n })\n .catch((error: Error) => {\n currentEntry.error = error\n currentEntry.status = 'rejected'\n throw error\n })\n\n return currentEntry.promise\n }, [container, rootContainer, token, args])\n\n // Subscribe to cache changes\n const subscribe = useCallback(\n (callback: () => void) => {\n entry.subscribers.add(callback)\n return () => {\n entry.subscribers.delete(callback)\n }\n },\n [entry],\n )\n\n // Get snapshot of current state - include version to detect invalidation\n const getSnapshot = useCallback(() => {\n return `${entry.status}:${entry.version}`\n }, [entry])\n\n // Use sync external store to track cache state\n useSyncExternalStore(subscribe, getSnapshot, getSnapshot)\n\n // Set up subscription for sync instances that don't have one yet\n useEffect(() => {\n const currentEntry = entryRef.current\n if (\n currentEntry &&\n currentEntry.status === 'resolved' &&\n currentEntry.instanceName &&\n !currentEntry.unsubscribe\n ) {\n setupInvalidationSubscription(currentEntry, rootContainer)\n }\n }, [rootContainer, entry])\n\n // Start fetching if not already\n if (entry.status === 'pending' && !entry.promise) {\n fetchService()\n }\n\n // Suspense behavior\n if (entry.status === 'pending') {\n throw entry.promise\n }\n\n if (entry.status === 'rejected') {\n throw entry.error\n }\n\n return entry.result\n}\n","import type {\n AnyInjectableType,\n BoundInjectionToken,\n ClassType,\n Factorable,\n FactoryInjectionToken,\n InjectionToken,\n InjectionTokenSchemaType,\n} from '@navios/di'\nimport type { z, ZodType } from 'zod/v4'\n\nimport { useCallback, useEffect, useReducer, useRef } from 'react'\n\nimport type { Join, UnionToArray } from '../types.mjs'\n\nimport { useContainer, useRootContainer } from './use-container.mjs'\n\ntype OptionalServiceState<T> =\n | { status: 'idle' }\n | { status: 'loading' }\n | { status: 'success'; data: T }\n | { status: 'not-found' }\n | { status: 'error'; error: Error }\n\ntype OptionalServiceAction<T> =\n | { type: 'loading' }\n | { type: 'success'; data: T }\n | { type: 'not-found' }\n | { type: 'error'; error: Error }\n | { type: 'reset' }\n\nfunction optionalServiceReducer<T>(\n state: OptionalServiceState<T>,\n action: OptionalServiceAction<T>,\n): OptionalServiceState<T> {\n switch (action.type) {\n case 'loading':\n return { status: 'loading' }\n case 'success':\n return { status: 'success', data: action.data }\n case 'not-found':\n return { status: 'not-found' }\n case 'error':\n return { status: 'error', error: action.error }\n case 'reset':\n return { status: 'idle' }\n default:\n return state\n }\n}\n\nexport interface UseOptionalServiceResult<T> {\n /**\n * The service instance if found and loaded successfully, otherwise undefined.\n */\n data: T | undefined\n /**\n * Error that occurred during loading (excludes \"not found\" which is not an error).\n */\n error: Error | undefined\n /**\n * True while the service is being loaded.\n */\n isLoading: boolean\n /**\n * True if the service was loaded successfully.\n */\n isSuccess: boolean\n /**\n * True if the service was not found (not registered in the container).\n */\n isNotFound: boolean\n /**\n * True if an error occurred during loading.\n */\n isError: boolean\n /**\n * Function to manually re-fetch the service.\n */\n refetch: () => void\n}\n\n// #1 Simple class\nexport function useOptionalService<T extends ClassType>(\n token: T,\n): UseOptionalServiceResult<\n InstanceType<T> extends Factorable<infer R> ? R : InstanceType<T>\n>\n\n// #2 Token with required Schema\nexport function useOptionalService<T, S extends InjectionTokenSchemaType>(\n token: InjectionToken<T, S>,\n args: z.input<S>,\n): UseOptionalServiceResult<T>\n\n// #3 Token with optional Schema\nexport function useOptionalService<\n T,\n S extends InjectionTokenSchemaType,\n R extends boolean,\n>(\n token: InjectionToken<T, S, R>,\n): R extends false\n ? UseOptionalServiceResult<T>\n : S extends ZodType<infer Type>\n ? `Error: Your token requires args: ${Join<UnionToArray<keyof Type>, ', '>}`\n : 'Error: Your token requires args'\n\n// #4 Token with no Schema\nexport function useOptionalService<T>(\n token: InjectionToken<T, undefined>,\n): UseOptionalServiceResult<T>\n\nexport function useOptionalService<T>(\n token: BoundInjectionToken<T, any>,\n): UseOptionalServiceResult<T>\n\nexport function useOptionalService<T>(\n token: FactoryInjectionToken<T, any>,\n): UseOptionalServiceResult<T>\n\n/**\n * Hook to optionally load a service from the DI container.\n *\n * Unlike useService, this hook does NOT throw an error if the service is not registered.\n * Instead, it returns `isNotFound: true` when the service doesn't exist.\n *\n * This is useful for:\n * - Optional dependencies that may or may not be configured\n * - Feature flags where a service might not be available\n * - Plugins or extensions that are conditionally registered\n *\n * @example\n * ```tsx\n * function Analytics() {\n * const { data: analytics, isNotFound } = useOptionalService(AnalyticsService)\n *\n * if (isNotFound) {\n * // Analytics service not configured, skip tracking\n * return null\n * }\n *\n * return <AnalyticsTracker service={analytics} />\n * }\n * ```\n */\nexport function useOptionalService(\n token:\n | ClassType\n | InjectionToken<any, any>\n | BoundInjectionToken<any, any>\n | FactoryInjectionToken<any, any>,\n args?: unknown,\n): UseOptionalServiceResult<any> {\n // useContainer returns ScopedContainer if inside ScopeProvider, otherwise Container\n const container = useContainer()\n const rootContainer = useRootContainer()\n\n // Try to get the instance synchronously first for better performance\n // This avoids the async loading state when the instance is already cached\n // We use a ref to track this so it doesn't cause effect re-runs\n const initialSyncInstanceRef = useRef<any>(undefined)\n const isFirstRenderRef = useRef(true)\n\n if (isFirstRenderRef.current) {\n try {\n initialSyncInstanceRef.current = container.tryGetSync(token, args)\n } catch {\n // Service not registered, leave as undefined\n }\n isFirstRenderRef.current = false\n }\n\n const initialState: OptionalServiceState<any> = initialSyncInstanceRef.current\n ? { status: 'success', data: initialSyncInstanceRef.current }\n : { status: 'idle' }\n\n const [state, dispatch] = useReducer(optionalServiceReducer, initialState)\n const instanceNameRef = useRef<string | null>(null)\n\n if (process.env.NODE_ENV === 'development') {\n const argsRef = useRef<unknown>(args)\n useEffect(() => {\n if (argsRef.current !== args) {\n if (JSON.stringify(argsRef.current) === JSON.stringify(args)) {\n console.log(`WARNING: useOptionalService called with args that look the same but are different instances: ${JSON.stringify(argsRef.current)} !== ${JSON.stringify(args)}!\n This is likely because you are using not memoized value that is not stable.\n Please use a memoized value or use a different approach to pass the args.\n Example:\n const args = useMemo(() => ({ userId: '123' }), [])\n return useOptionalService(UserToken, args)\n `)\n }\n argsRef.current = args\n }\n }, [args])\n }\n\n const fetchService = useCallback(async () => {\n dispatch({ type: 'loading' })\n try {\n // Use the container (ScopedContainer or Container) for resolution\n const instance = await container.get(\n // @ts-expect-error - token is valid\n token as AnyInjectableType,\n args as any,\n )\n // Get instance name for event subscription\n const instanceName = container.calculateInstanceName(token, args)\n if (instanceName) {\n instanceNameRef.current = instanceName\n }\n dispatch({ type: 'success', data: instance })\n } catch (error) {\n // Caught exceptions are treated as errors\n const err = error as Error\n const errorMessage = err.message?.toLowerCase() ?? ''\n if (\n errorMessage.includes('not found') ||\n errorMessage.includes('not registered') ||\n errorMessage.includes('no provider')\n ) {\n dispatch({ type: 'not-found' })\n } else {\n dispatch({ type: 'error', error: err })\n }\n }\n }, [container, token, args])\n\n // Subscribe to invalidation events\n useEffect(() => {\n const eventBus = rootContainer.getEventBus()\n let unsubscribe: (() => void) | undefined\n\n // If we already have a sync instance from initial render, just set up subscription\n // Otherwise, fetch async\n const syncInstance = initialSyncInstanceRef.current\n if (syncInstance) {\n const instanceName = container.calculateInstanceName(token, args)\n if (instanceName) {\n instanceNameRef.current = instanceName\n unsubscribe = eventBus.on(instanceName, 'destroy', () => {\n // Re-fetch when the service is invalidated\n void fetchService()\n })\n }\n } else {\n void fetchService().then(() => {\n if (instanceNameRef.current) {\n unsubscribe = eventBus.on(instanceNameRef.current, 'destroy', () => {\n // Re-fetch when the service is invalidated\n void fetchService()\n })\n }\n })\n\n return () => {\n unsubscribe?.()\n }\n }\n\n return () => {\n unsubscribe?.()\n }\n }, [fetchService, rootContainer, token, args])\n\n return {\n data: state.status === 'success' ? state.data : undefined,\n error: state.status === 'error' ? state.error : undefined,\n isLoading: state.status === 'loading',\n isSuccess: state.status === 'success',\n isNotFound: state.status === 'not-found',\n isError: state.status === 'error',\n refetch: fetchService,\n }\n}\n","import { useCallback } from 'react'\n\nimport { useContainer } from './use-container.mjs'\n\n/**\n * Hook that returns a function to invalidate a service instance directly.\n *\n * This is useful when you have the service instance and want to invalidate it\n * without knowing its token.\n *\n * @example\n * ```tsx\n * function UserProfile() {\n * const { data: user } = useService(UserService)\n * const invalidateInstance = useInvalidateInstance()\n *\n * const handleRefresh = () => {\n * if (user) {\n * invalidateInstance(user)\n * }\n * }\n *\n * return (\n * <div>\n * <span>{user?.name}</span>\n * <button onClick={handleRefresh}>Refresh</button>\n * </div>\n * )\n * }\n * ```\n */\nexport function useInvalidateInstance(): (instance: unknown) => Promise<void> {\n const container = useContainer()\n\n return useCallback(\n async (instance: unknown) => {\n await container.invalidate(instance)\n },\n [container],\n )\n}\n","import type { ScopedContainer } from '@navios/di'\n\nimport { useContext } from 'react'\n\nimport { ScopedContainerContext } from '../providers/context.mjs'\n\n/**\n * Hook to get the current scope ID.\n * Returns null if not inside a ScopeProvider.\n */\nexport function useScope(): string | null {\n const scopedContainer = useContext(ScopedContainerContext)\n return scopedContainer?.getRequestId() ?? null\n}\n\n/**\n * Hook to get the current scope ID, throwing if not inside a ScopeProvider.\n * Use this when your component requires a scope to function correctly.\n */\nexport function useScopeOrThrow(): string {\n const scopeId = useScope()\n if (scopeId === null) {\n throw new Error(\n 'useScopeOrThrow must be used within a ScopeProvider. ' +\n 'Wrap your component tree with <ScopeProvider> to create a request scope.',\n )\n }\n return scopeId\n}\n\n/**\n * Hook to get the current ScopedContainer.\n * Returns null if not inside a ScopeProvider.\n *\n * Use this to access scope metadata or other ScopedContainer methods.\n *\n * @example\n * ```tsx\n * function TableRow() {\n * const scope = useScopedContainer()\n * const rowData = scope?.getMetadata('rowData')\n * // ...\n * }\n * ```\n */\nexport function useScopedContainer(): ScopedContainer | null {\n return useContext(ScopedContainerContext)\n}\n\n/**\n * Hook to get the current ScopedContainer, throwing if not inside a ScopeProvider.\n * Use this when your component requires a scope to function correctly.\n */\nexport function useScopedContainerOrThrow(): ScopedContainer {\n const scopedContainer = useScopedContainer()\n if (scopedContainer === null) {\n throw new Error(\n 'useScopedContainerOrThrow must be used within a ScopeProvider. ' +\n 'Wrap your component tree with <ScopeProvider> to create a request scope.',\n )\n }\n return scopedContainer\n}\n\n/**\n * Hook to get metadata from the current scope.\n * Returns undefined if not inside a ScopeProvider or if the key doesn't exist.\n *\n * @example\n * ```tsx\n * // In parent component:\n * <ScopeProvider metadata={{ userId: '123', theme: 'dark' }}>\n * <ChildComponent />\n * </ScopeProvider>\n *\n * // In child component:\n * function ChildComponent() {\n * const userId = useScopeMetadata<string>('userId')\n * const theme = useScopeMetadata<'light' | 'dark'>('theme')\n * // ...\n * }\n * ```\n */\nexport function useScopeMetadata<T = unknown>(key: string): T | undefined {\n const scopedContainer = useContext(ScopedContainerContext)\n return scopedContainer?.getMetadata(key) as T | undefined\n}\n"],"mappings":"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"}
|