@gears-frontx/react 0.2.0-alpha.5 → 0.2.0-alpha.7
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/CLAUDE.md +30 -2
- package/dist/index.cjs +19 -12
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +79 -17
- package/dist/index.d.ts +79 -17
- package/dist/index.js +20 -13
- package/dist/index.js.map +1 -1
- package/llms.txt +21 -1
- package/package.json +18 -12
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/FrontXProvider.tsx","../src/FrontXContext.tsx","../src/mfe/MfeContext.tsx","../src/mfe/MfeProvider.tsx","../src/queryClient.tsx","../src/hooks/QueryCache.ts","../src/hooks/useLatest.ts","../src/hooks/useCanAccess.ts","../src/components/CanAccess.tsx","../src/hooks/useAppDispatch.ts","../src/hooks/useAppSelector.ts","../src/hooks/useTranslation.ts","../src/hooks/useScreenTranslations.ts","../src/hooks/useFormatters.ts","../src/hooks/useTheme.ts","../src/hooks/useApiQuery.ts","../src/hooks/useApiSuspenseQuery.ts","../src/hooks/useApiInfiniteQuery.ts","../src/hooks/useApiSuspenseInfiniteQuery.ts","../src/hooks/useApiMutation.ts","../src/hooks/useApiStream.ts","../src/hooks/useQueryCache.ts","../src/mfe/hooks/useMfeBridge.ts","../src/mfe/hooks/useSharedProperty.ts","../src/mfe/hooks/useHostAction.ts","../src/mfe/hooks/useDomainExtensions.ts","../src/mfe/hooks/useMountedExtensions.ts","../src/mfe/hooks/useRegisteredPackages.ts","../src/mfe/ThemeAwareReactLifecycle.tsx","../src/mfe/components/ExtensionDomainSlot.tsx","../src/index.ts"],"sourcesContent":["/**\n * FrontX Provider - Main provider component for FrontX applications\n *\n * React Layer: L3 (Depends on @gears-frontx/framework)\n *\n * Query cache lifecycle is owned by the queryCache() framework plugin (L2).\n * FrontXProvider reads the plugin-owned QueryClient from the app and mounts the\n * internal React provider around the tree when it is available.\n */\n// @cpt-flow:cpt-frontx-flow-react-bindings-bootstrap-provider:p1\n// @cpt-algo:cpt-frontx-algo-react-bindings-resolve-app:p1\n// @cpt-algo:cpt-frontx-algo-react-bindings-build-provider-tree:p1\n// @cpt-dod:cpt-frontx-dod-react-bindings-provider:p1\n// @cpt-dod:cpt-frontx-dod-request-lifecycle-query-provider:p2\n// @cpt-flow:cpt-frontx-flow-request-lifecycle-query-client-lifecycle:p2\n// @cpt-FEATURE:implement-endpoint-descriptors:p3\n\nimport React, { useMemo, useEffect, useState } from 'react';\nimport { Provider as ReduxProvider } from 'react-redux';\nimport type { Store } from '@reduxjs/toolkit';\nimport {\n createFrontXApp,\n microfrontends,\n} from '@gears-frontx/framework';\nimport type { FrontXApp } from '@gears-frontx/framework';\nimport { FrontXContext } from './FrontXContext';\nimport { MfeProvider } from './mfe/MfeProvider';\nimport {\n hasFrontXQueryClientActivator,\n FrontXQueryClientProvider,\n useBootstrappedFrontXQueryClient,\n} from './queryClient';\nimport type { FrontXProviderProps } from './types';\n\n/**\n * Shallow-compare two plain objects by own-enumerable values (Object.is).\n * Prevents unnecessary app recreation when callers pass inline config literals\n * whose values haven't actually changed between renders.\n */\nfunction shallowEqual(\n a: Record<string, unknown> | undefined,\n b: Record<string, unknown> | undefined,\n): boolean {\n if (a === b) return true;\n if (!a || !b) return false;\n const keysA = Object.keys(a);\n if (keysA.length !== Object.keys(b).length) return false;\n return keysA.every((k) => Object.is(a[k], b[k]));\n}\n\ntype ProviderOwnedAppConfig = FrontXProviderProps['config'] & {\n microfrontends?: Parameters<typeof microfrontends>[0];\n};\n\nfunction createProviderOwnedApp(\n config: ProviderOwnedAppConfig | undefined\n): FrontXApp {\n return createFrontXApp(config);\n}\n\n/**\n * FrontX Provider Component\n *\n * Provides the FrontX application context to all child components.\n * Creates the FrontX app instance with the full preset by default.\n *\n * @example\n * ```tsx\n * // Default - creates app with full preset\n * <FrontXProvider>\n * <App />\n * </FrontXProvider>\n *\n * // With configuration\n * <FrontXProvider config={{ devMode: true }}>\n * <App />\n * </FrontXProvider>\n *\n * // With pre-built app\n * const app = createFrontX().use(queryCache()).build();\n * <FrontXProvider app={app}>\n * <App />\n * </FrontXProvider>\n *\n * // With MFE bridge (for MFE components)\n * <FrontXProvider mfeBridge={{ bridge, extensionId, domainId }}>\n * <MyMfeApp />\n * </FrontXProvider>\n *\n * // QueryCache is resolved from the app's plugin composition\n * <FrontXProvider app={app}>\n * <MyMfeApp />\n * </FrontXProvider>\n * ```\n */\n// @cpt-begin:cpt-frontx-flow-react-bindings-bootstrap-provider:p1:inst-render-provider\n// @cpt-begin:cpt-frontx-dod-react-bindings-provider:p1:inst-render-provider\n// @cpt-begin:cpt-frontx-dod-request-lifecycle-query-provider:p2:inst-render-provider\nexport const FrontXProvider: React.FC<FrontXProviderProps> = ({\n children,\n config,\n app: providedApp,\n mfeBridge,\n}) => {\n // @cpt-begin:cpt-frontx-flow-react-bindings-bootstrap-provider:p1:inst-resolve-app\n // @cpt-begin:cpt-frontx-algo-react-bindings-resolve-app:p1:inst-use-provided-app\n // @cpt-begin:cpt-frontx-algo-react-bindings-resolve-app:p1:inst-create-app\n // @cpt-begin:cpt-frontx-algo-react-bindings-resolve-app:p1:inst-memoize-app\n // @cpt-begin:cpt-frontx-algo-react-bindings-build-provider-tree:p1:inst-resolve-app-tree\n // Stabilize config by shallow value without mutating a ref during render.\n // When the incoming config shallow-differs, a render-phase setState triggers an\n // immediate re-render so useMemo sees the updated stable reference in the same\n // turn as a reference-changing (but value-equal) prop would be ignored.\n const [stableConfig, setStableConfig] = useState(config);\n if (\n !shallowEqual(\n stableConfig as Record<string, unknown> | undefined,\n config as Record<string, unknown> | undefined,\n )\n ) {\n setStableConfig(config);\n }\n\n const app = useMemo<FrontXApp>(() => {\n if (providedApp) {\n return providedApp;\n }\n\n return createProviderOwnedApp(stableConfig as ProviderOwnedAppConfig | undefined);\n }, [providedApp, stableConfig]);\n // @cpt-end:cpt-frontx-algo-react-bindings-resolve-app:p1:inst-use-provided-app\n // @cpt-end:cpt-frontx-algo-react-bindings-resolve-app:p1:inst-create-app\n // @cpt-end:cpt-frontx-algo-react-bindings-resolve-app:p1:inst-memoize-app\n // @cpt-end:cpt-frontx-algo-react-bindings-build-provider-tree:p1:inst-resolve-app-tree\n // @cpt-end:cpt-frontx-flow-react-bindings-bootstrap-provider:p1:inst-resolve-app\n\n const queryClient = useBootstrappedFrontXQueryClient(app);\n const deferQuerySubtree =\n hasFrontXQueryClientActivator(app) && queryClient === undefined;\n\n useEffect(() => {\n if (\n queryClient ||\n hasFrontXQueryClientActivator(app) ||\n process.env.NODE_ENV === 'production' ||\n process.env.NODE_ENV === 'test' ||\n process.env.VITEST === 'true'\n ) {\n return;\n }\n\n console.warn(\n '[FrontXProvider] No query cache available. Add queryCache() or queryCacheShared() to your plugin composition. ' +\n 'useApiQuery/useApiMutation will fail without it.'\n );\n }, [app, queryClient]);\n\n // @cpt-begin:cpt-frontx-flow-react-bindings-bootstrap-provider:p1:inst-destroy-app\n // Cleanup on unmount\n useEffect(() => {\n return () => {\n // Only destroy if we created the app (not provided externally)\n if (!providedApp) {\n app.destroy();\n }\n };\n }, [app, providedApp]);\n // @cpt-end:cpt-frontx-flow-react-bindings-bootstrap-provider:p1:inst-destroy-app\n\n // @cpt-begin:cpt-frontx-algo-react-bindings-build-provider-tree:p1:inst-wrap-frontx-context\n // @cpt-begin:cpt-frontx-algo-react-bindings-build-provider-tree:p1:inst-wrap-redux\n // @cpt-begin:cpt-frontx-flow-react-bindings-bootstrap-provider:p1:inst-set-frontx-context\n // @cpt-begin:cpt-frontx-flow-react-bindings-bootstrap-provider:p1:inst-set-redux-provider\n // @cpt-begin:cpt-frontx-flow-react-bindings-bootstrap-provider:p1:inst-render-query-provider\n // @cpt-begin:cpt-frontx-flow-react-bindings-bootstrap-provider:p1:inst-render-children\n // @cpt-begin:cpt-frontx-flow-request-lifecycle-query-client-lifecycle:p2:inst-render-query-provider\n // Provider order (outer to inner):\n // FrontXContext -> ReduxProvider -> QueryClientProvider -> children\n // queryCache()/queryCacheShared() own the shared QueryClient lifecycle.\n const content = (\n <FrontXContext.Provider value={app}>\n <ReduxProvider store={app.store as Store}>\n {/* app.store is FrontX-owned but Redux-compatible. Cast keeps react-redux happy. */}\n <FrontXQueryClientProvider queryClient={queryClient}>\n {deferQuerySubtree ? null : children}\n </FrontXQueryClientProvider>\n </ReduxProvider>\n </FrontXContext.Provider>\n );\n // @cpt-end:cpt-frontx-flow-request-lifecycle-query-client-lifecycle:p2:inst-render-query-provider\n // @cpt-end:cpt-frontx-flow-react-bindings-bootstrap-provider:p1:inst-render-children\n // @cpt-end:cpt-frontx-flow-react-bindings-bootstrap-provider:p1:inst-render-query-provider\n // @cpt-end:cpt-frontx-flow-react-bindings-bootstrap-provider:p1:inst-set-redux-provider\n // @cpt-end:cpt-frontx-flow-react-bindings-bootstrap-provider:p1:inst-set-frontx-context\n // @cpt-end:cpt-frontx-algo-react-bindings-build-provider-tree:p1:inst-wrap-redux\n // @cpt-end:cpt-frontx-algo-react-bindings-build-provider-tree:p1:inst-wrap-frontx-context\n\n // @cpt-begin:cpt-frontx-algo-react-bindings-build-provider-tree:p1:inst-wrap-mfe-conditional\n // @cpt-begin:cpt-frontx-flow-react-bindings-bootstrap-provider:p2:inst-wrap-mfe-provider\n // Wrap with MfeProvider if bridge is provided\n if (mfeBridge) {\n return (\n <MfeProvider value={mfeBridge}>\n {content}\n </MfeProvider>\n );\n }\n // @cpt-end:cpt-frontx-algo-react-bindings-build-provider-tree:p1:inst-wrap-mfe-conditional\n // @cpt-end:cpt-frontx-flow-react-bindings-bootstrap-provider:p2:inst-wrap-mfe-provider\n\n return content;\n};\n// @cpt-end:cpt-frontx-flow-react-bindings-bootstrap-provider:p1:inst-render-provider\n// @cpt-end:cpt-frontx-dod-react-bindings-provider:p1:inst-render-provider\n// @cpt-end:cpt-frontx-dod-request-lifecycle-query-provider:p2:inst-render-provider\n","/**\n * FrontX Context - React context for FrontX application\n *\n * React Layer: L3 (Depends on @gears-frontx/framework)\n */\n// @cpt-flow:cpt-frontx-flow-react-bindings-use-frontx:p2\n// @cpt-algo:cpt-frontx-algo-react-bindings-mfe-context-guard:p1\n\nimport { createContext, useContext } from 'react';\nimport type { FrontXApp } from '@gears-frontx/framework';\n\n// ============================================================================\n// Context Definition\n// ============================================================================\n\n/**\n * FrontX Context\n * Holds the FrontX app instance for the application.\n */\nexport const FrontXContext = createContext<FrontXApp | null>(null);\n\n/**\n * Use the FrontX context.\n * Throws if used outside of FrontXProvider.\n *\n * @returns The FrontX app instance\n */\n// @cpt-begin:cpt-frontx-flow-react-bindings-use-frontx:p2:inst-call-use-frontx\n// @cpt-begin:cpt-frontx-algo-react-bindings-mfe-context-guard:p1:inst-throw-no-frontx-context\nexport function useFrontX(): FrontXApp {\n const context = useContext(FrontXContext);\n\n // @cpt-begin:cpt-frontx-flow-react-bindings-use-frontx:p2:inst-guard-frontx-context\n if (!context) {\n throw new Error(\n 'useFrontX must be used within a FrontXProvider. ' +\n 'Wrap your application with <FrontXProvider> to access Gears FrontX features.'\n );\n }\n // @cpt-end:cpt-frontx-flow-react-bindings-use-frontx:p2:inst-guard-frontx-context\n\n // @cpt-begin:cpt-frontx-flow-react-bindings-use-frontx:p2:inst-return-frontx-app\n return context;\n // @cpt-end:cpt-frontx-flow-react-bindings-use-frontx:p2:inst-return-frontx-app\n}\n// @cpt-end:cpt-frontx-flow-react-bindings-use-frontx:p2:inst-call-use-frontx\n// @cpt-end:cpt-frontx-algo-react-bindings-mfe-context-guard:p1:inst-throw-no-frontx-context\n","/**\n * MFE Context - React context for MFE state\n *\n * Provides MFE bridge and metadata to child components.\n * Used by MFE components to access their runtime context.\n *\n * React Layer: L3 (Depends on @gears-frontx/framework)\n */\n// @cpt-flow:cpt-frontx-flow-react-bindings-mfe-provider:p1\n// @cpt-algo:cpt-frontx-algo-react-bindings-mfe-context-guard:p1\n// @cpt-dod:cpt-frontx-dod-react-bindings-mfe-hooks:p1\n\nimport { createContext, useContext } from 'react';\nimport type { ChildMfeBridge } from '@gears-frontx/framework';\n\n// ============================================================================\n// Context Value Types\n// ============================================================================\n\n/**\n * MFE Context Value\n * Contains bridge and metadata about the MFE instance.\n */\nexport interface MfeContextValue {\n /** Child bridge for communication with host */\n bridge: ChildMfeBridge;\n /** Extension ID */\n extensionId: string;\n /** Domain ID where MFE is mounted */\n domainId: string;\n}\n\n// ============================================================================\n// Context Definition\n// ============================================================================\n\n/**\n * MFE Context\n * Holds the MFE bridge and metadata for child components.\n */\nexport const MfeContext = createContext<MfeContextValue | null>(null);\n\n/**\n * Use the MFE context.\n * Throws if used outside of MFE context.\n *\n * @returns The MFE context value\n */\n// @cpt-begin:cpt-frontx-flow-react-bindings-mfe-provider:p1:inst-use-mfe-context\n// @cpt-begin:cpt-frontx-algo-react-bindings-mfe-context-guard:p1:inst-throw-no-mfe-context\n// @cpt-begin:cpt-frontx-dod-react-bindings-mfe-hooks:p1:inst-use-mfe-context\nexport function useMfeContext(): MfeContextValue {\n const context = useContext(MfeContext);\n\n if (!context) {\n throw new Error(\n 'useMfeContext must be used within a MfeProvider. ' +\n 'This hook can only be used inside MFE components.'\n );\n }\n\n return context;\n}\n// @cpt-end:cpt-frontx-flow-react-bindings-mfe-provider:p1:inst-use-mfe-context\n// @cpt-end:cpt-frontx-algo-react-bindings-mfe-context-guard:p1:inst-throw-no-mfe-context\n// @cpt-end:cpt-frontx-dod-react-bindings-mfe-hooks:p1:inst-use-mfe-context\n","/**\n * MFE Provider - Provides MFE context to child components\n *\n * Wraps MFE components with bridge and metadata.\n * Used by the MFE mounting system.\n *\n * MfeProvider does not create or own the shared QueryClient. When the host uses\n * queryCache() and the child app uses queryCacheShared(), overlapping queries\n * (same query key) are deduplicated and cached once across MFE boundaries.\n * Each MFE still uses its own apiRegistry and service instances in queryFn.\n *\n * React Layer: L3 (Depends on @gears-frontx/framework)\n */\n// @cpt-flow:cpt-frontx-flow-react-bindings-mfe-provider:p1\n// @cpt-dod:cpt-frontx-dod-react-bindings-mfe-hooks:p1\n// @cpt-flow:cpt-frontx-flow-request-lifecycle-query-client-lifecycle:p2\n\nimport React from 'react';\nimport { MfeContext, type MfeContextValue } from './MfeContext';\n\n// ============================================================================\n// Provider Props\n// ============================================================================\n\n/**\n * MFE Provider Props\n */\nexport interface MfeProviderProps {\n /** MFE context value */\n value: MfeContextValue;\n /** Child components */\n children: React.ReactNode;\n}\n\n// ============================================================================\n// Provider Component\n// ============================================================================\n\n/**\n * MFE Provider Component\n *\n * Provides MFE bridge and metadata to child components.\n * Used by the MFE mounting system to wrap MFE components.\n *\n * @example\n * ```tsx\n * <MfeProvider value={{ bridge, extensionId, domainId }}>\n * <MyMfeComponent />\n * </MfeProvider>\n * ```\n */\n// @cpt-begin:cpt-frontx-flow-react-bindings-mfe-provider:p1:inst-render-mfe-provider\n// @cpt-begin:cpt-frontx-flow-react-bindings-mfe-provider:p1:inst-set-mfe-context\n// @cpt-begin:cpt-frontx-dod-react-bindings-mfe-hooks:p1:inst-render-mfe-provider\n// @cpt-begin:cpt-frontx-flow-request-lifecycle-query-client-lifecycle:p2:inst-mfe-query-client\nexport const MfeProvider: React.FC<MfeProviderProps> = ({ value, children }) => {\n // MfeProvider only supplies the bridge context. Shared cache depends on\n // plugin-owned QueryClient reuse across each MFE root's FrontXProvider.\n return (\n <MfeContext.Provider value={value}>\n {children}\n </MfeContext.Provider>\n );\n};\n// @cpt-end:cpt-frontx-flow-react-bindings-mfe-provider:p1:inst-render-mfe-provider\n// @cpt-end:cpt-frontx-flow-react-bindings-mfe-provider:p1:inst-set-mfe-context\n// @cpt-end:cpt-frontx-dod-react-bindings-mfe-hooks:p1:inst-render-mfe-provider\n// @cpt-end:cpt-frontx-flow-request-lifecycle-query-client-lifecycle:p2:inst-mfe-query-client\n","import React, {\n createContext,\n useContext,\n useEffect,\n useLayoutEffect,\n useMemo,\n useState,\n} from 'react';\nimport {\n QueryClientContext,\n QueryClientProvider,\n type QueryClient,\n useInfiniteQuery,\n useMutation,\n useQuery,\n useSuspenseInfiniteQuery,\n useSuspenseQuery,\n type MutationFunctionContext,\n} from '@tanstack/react-query';\nimport {\n subscribeQueryCacheRuntimeChanged,\n type EndpointDescriptor,\n type FrontXApp,\n} from '@gears-frontx/framework';\nimport type { ApiQueryOverrides } from './hooks/useApiQuery';\nimport type {\n ApiInfiniteQueryOptions,\n ApiInfiniteQueryPageContext,\n} from './hooks/useApiInfiniteQuery';\nimport type { UseApiMutationOptions } from './hooks/useApiMutation';\nimport { createQueryCache, type MutationCallbackContext, type QueryCacheKey } from './hooks/QueryCache';\nimport { useLatest } from './hooks/useLatest';\n\n// @cpt-FEATURE:implement-endpoint-descriptors:p3\n// @cpt-dod:cpt-frontx-dod-request-lifecycle-query-provider:p2\n// @cpt-flow:cpt-frontx-flow-request-lifecycle-query-client-lifecycle:p2\n// @cpt-flow:cpt-frontx-flow-request-lifecycle-use-api-query:p2\n// @cpt-flow:cpt-frontx-flow-request-lifecycle-use-api-mutation:p2\n\n// @cpt-begin:cpt-frontx-flow-request-lifecycle-query-client-lifecycle:p2:inst-react-query-client-symbols\nconst APP_QUERY_CLIENT_SYMBOL = Symbol.for('frontx:query-cache:app-client');\nconst APP_QUERY_CLIENT_RESOLVER_SYMBOL = Symbol.for('frontx:query-cache:app-client-resolver');\nconst APP_QUERY_CLIENT_ACTIVATOR_SYMBOL = Symbol.for('frontx:query-cache:app-client-activator');\n\ntype QueryClientApp = FrontXApp & {\n [APP_QUERY_CLIENT_SYMBOL]?: QueryClient;\n [APP_QUERY_CLIENT_RESOLVER_SYMBOL]?: () => QueryClient | undefined;\n [APP_QUERY_CLIENT_ACTIVATOR_SYMBOL]?: () => QueryClient | undefined;\n};\n\nconst FrontXQueryClientContext = createContext<QueryClient | undefined>(undefined);\n// @cpt-end:cpt-frontx-flow-request-lifecycle-query-client-lifecycle:p2:inst-react-query-client-symbols\n\n// @cpt-begin:cpt-frontx-flow-request-lifecycle-query-client-lifecycle:p2:inst-resolve-app-query-client\ntype RuntimeAwareEndpointDescriptor<TData> = EndpointDescriptor<TData> & {\n fetch(options?: { signal?: AbortSignal; staleTime?: number }): Promise<TData>;\n};\n\ntype AppResolvedQueryClient = {\n app: FrontXApp;\n queryClient: QueryClient;\n};\n\nconst useCommitEffect = typeof globalThis.window === 'undefined' ? useEffect : useLayoutEffect;\n\nexport function resolveFrontXQueryClient(app: FrontXApp): QueryClient | undefined {\n const clientApp = app as QueryClientApp;\n return clientApp[APP_QUERY_CLIENT_SYMBOL] ?? clientApp[APP_QUERY_CLIENT_RESOLVER_SYMBOL]?.();\n}\n\nexport function hasFrontXQueryClientActivator(app: FrontXApp): boolean {\n return typeof (app as QueryClientApp)[APP_QUERY_CLIENT_ACTIVATOR_SYMBOL] === 'function';\n}\n\nexport function activateFrontXQueryClient(app: FrontXApp): QueryClient | undefined {\n const clientApp = app as QueryClientApp;\n return clientApp[APP_QUERY_CLIENT_SYMBOL] ?? clientApp[APP_QUERY_CLIENT_ACTIVATOR_SYMBOL]?.();\n}\n// @cpt-end:cpt-frontx-flow-request-lifecycle-query-client-lifecycle:p2:inst-resolve-app-query-client\n\n// @cpt-begin:cpt-frontx-flow-request-lifecycle-query-client-lifecycle:p2:inst-imperative-cache-bootstrap\n/**\n * Imperatively invalidates cache entries for `target` on the QueryClient bound to `app`.\n * Use from non-React code (e.g. MFE actions); in components prefer `useQueryCache().invalidate`.\n */\nexport async function invalidateQueryCacheForApp(\n app: FrontXApp,\n target: EndpointDescriptor<unknown> | QueryCacheKey\n): Promise<void> {\n const queryClient = resolveFrontXQueryClient(app) ?? activateFrontXQueryClient(app);\n if (!queryClient) {\n throw new Error(\n '[invalidateQueryCacheForApp] No QueryClient on app. Ensure queryCache() or queryCacheShared() is in the plugin chain.'\n );\n }\n await createQueryCache(queryClient).invalidate(target);\n}\n\n/** Resolves the app-bound QueryClient without triggering plugin activation during render. */\nexport function bootstrapFrontXQueryClient(app: FrontXApp): QueryClient | undefined {\n return resolveFrontXQueryClient(app);\n}\n// @cpt-end:cpt-frontx-flow-request-lifecycle-query-client-lifecycle:p2:inst-imperative-cache-bootstrap\n\n// @cpt-begin:cpt-frontx-flow-request-lifecycle-query-client-lifecycle:p2:inst-use-bootstrapped-query-client\nexport function useBootstrappedFrontXQueryClient(app: FrontXApp): QueryClient | undefined {\n const fromApp = useMemo(() => bootstrapFrontXQueryClient(app), [app]);\n const [eventResolvedClient, setEventResolvedClient] = useState<AppResolvedQueryClient | undefined>(\n undefined\n );\n const queryClient =\n fromApp ?? (eventResolvedClient?.app === app ? eventResolvedClient.queryClient : undefined);\n\n useCommitEffect(() => {\n if (fromApp || !hasFrontXQueryClientActivator(app)) {\n return;\n }\n\n const tryResolveQueryClient = () => {\n const nextQueryClient = resolveFrontXQueryClient(app) ?? activateFrontXQueryClient(app);\n if (nextQueryClient) {\n setEventResolvedClient((current) => {\n if (current?.app === app && current.queryClient === nextQueryClient) {\n return current;\n }\n\n return {\n app,\n queryClient: nextQueryClient,\n };\n });\n }\n };\n\n // Only activate after commit so abandoned renders cannot leak retainers/listeners.\n tryResolveQueryClient();\n\n const subscription = subscribeQueryCacheRuntimeChanged(() => {\n tryResolveQueryClient();\n });\n\n return () => {\n subscription.unsubscribe();\n };\n }, [app, fromApp]);\n\n return queryClient;\n}\n// @cpt-end:cpt-frontx-flow-request-lifecycle-query-client-lifecycle:p2:inst-use-bootstrapped-query-client\n\n// @cpt-begin:cpt-frontx-dod-request-lifecycle-query-provider:p2:inst-frontx-query-client-provider\nexport function FrontXQueryClientProvider({\n queryClient,\n children,\n}: Readonly<{\n queryClient: QueryClient | undefined;\n children: React.ReactNode;\n}>) {\n if (!queryClient) {\n return (\n <FrontXQueryClientContext.Provider value={undefined}>\n <QueryClientContext.Provider value={undefined}>{children}</QueryClientContext.Provider>\n </FrontXQueryClientContext.Provider>\n );\n }\n\n return (\n <FrontXQueryClientContext.Provider value={queryClient}>\n <QueryClientProvider client={queryClient}>{children}</QueryClientProvider>\n </FrontXQueryClientContext.Provider>\n );\n}\n// @cpt-end:cpt-frontx-dod-request-lifecycle-query-provider:p2:inst-frontx-query-client-provider\n\n// @cpt-begin:cpt-frontx-dod-request-lifecycle-query-provider:p2:inst-query-client-context-hooks\nexport function useOptionalFrontXQueryClient(): QueryClient | undefined {\n return useContext(FrontXQueryClientContext);\n}\n\nexport function useRequiredFrontXQueryClient(): QueryClient {\n const queryClient = useOptionalFrontXQueryClient();\n if (!queryClient) {\n throw new Error(\n '[FrontXProvider] No query cache available. Add queryCache() or queryCacheShared() to your plugin composition.'\n );\n }\n\n return queryClient;\n}\n// @cpt-end:cpt-frontx-dod-request-lifecycle-query-provider:p2:inst-query-client-context-hooks\n\n// @cpt-begin:implement-endpoint-descriptors:p3:inst-descriptor-fetch-stale-helpers\nfunction buildPageContext<TPage>(\n page: TPage,\n pages: readonly TPage[],\n descriptor: EndpointDescriptor<TPage>,\n descriptors: readonly EndpointDescriptor<TPage>[]\n): ApiInfiniteQueryPageContext<TPage> {\n return {\n page,\n pages,\n descriptor,\n descriptors,\n };\n}\n\nfunction normalizeFetchStaleTime(staleTime: unknown): number | undefined {\n if (staleTime === 'static') {\n return Number.POSITIVE_INFINITY;\n }\n\n return typeof staleTime === 'number' ? staleTime : undefined;\n}\n\nfunction resolveFetchStaleTime<TData>(\n queryClient: QueryClient,\n descriptor: EndpointDescriptor<TData>,\n overrideStaleTime?: number\n): number | undefined {\n return normalizeFetchStaleTime(\n overrideStaleTime ??\n descriptor.staleTime ??\n queryClient.getDefaultOptions().queries?.staleTime\n );\n}\n\nfunction fetchDescriptor<TData>(\n descriptor: EndpointDescriptor<TData>,\n options?: { signal?: AbortSignal; staleTime?: number }\n): Promise<TData> {\n return (descriptor as RuntimeAwareEndpointDescriptor<TData>).fetch(options);\n}\n// @cpt-end:implement-endpoint-descriptors:p3:inst-descriptor-fetch-stale-helpers\n\n// @cpt-begin:cpt-frontx-flow-request-lifecycle-use-api-query:p2:inst-delegate-frontx-use-query\nexport function useFrontXQuery<TData = unknown, TError = Error>(\n descriptor: EndpointDescriptor<TData>,\n overrides?: ApiQueryOverrides\n) {\n const queryClient = useRequiredFrontXQueryClient();\n const staleTime = resolveFetchStaleTime(queryClient, descriptor, overrides?.staleTime);\n const result = useQuery<TData, TError>({\n queryKey: descriptor.key as unknown[],\n queryFn: ({ signal }) => fetchDescriptor(descriptor, { signal, staleTime }),\n staleTime: overrides?.staleTime ?? descriptor.staleTime,\n gcTime: overrides?.gcTime ?? descriptor.gcTime,\n });\n\n return {\n data: result.data,\n error: result.error,\n isLoading: result.isLoading,\n isFetching: result.isFetching,\n isError: result.isError,\n refetch: result.refetch,\n };\n}\n// @cpt-end:cpt-frontx-flow-request-lifecycle-use-api-query:p2:inst-delegate-frontx-use-query\n\n// @cpt-begin:cpt-frontx-flow-request-lifecycle-use-api-query:p2:inst-delegate-frontx-use-suspense-query\nexport function useFrontXSuspenseQuery<TData = unknown, TError = Error>(\n descriptor: EndpointDescriptor<TData>,\n overrides?: ApiQueryOverrides\n) {\n const queryClient = useRequiredFrontXQueryClient();\n const staleTime = resolveFetchStaleTime(queryClient, descriptor, overrides?.staleTime);\n const result = useSuspenseQuery<TData, TError>({\n queryKey: descriptor.key as unknown[],\n queryFn: ({ signal }) => fetchDescriptor(descriptor, { signal, staleTime }),\n staleTime: overrides?.staleTime ?? descriptor.staleTime,\n gcTime: overrides?.gcTime ?? descriptor.gcTime,\n });\n\n return {\n data: result.data,\n error: result.error,\n isFetching: result.isFetching,\n refetch: async () => {\n await result.refetch();\n },\n };\n}\n// @cpt-end:cpt-frontx-flow-request-lifecycle-use-api-query:p2:inst-delegate-frontx-use-suspense-query\n\n// @cpt-begin:cpt-frontx-flow-request-lifecycle-use-api-query:p2:inst-delegate-frontx-use-infinite-query\nexport function useFrontXInfiniteQuery<TPage = unknown, TError = Error>(\n options: ApiInfiniteQueryOptions<TPage>\n) {\n const queryClient = useRequiredFrontXQueryClient();\n const result = useInfiniteQuery<\n TPage,\n TError,\n readonly TPage[],\n readonly unknown[],\n EndpointDescriptor<TPage>\n >({\n queryKey: options.initialPage.key,\n initialPageParam: options.initialPage,\n queryFn: ({ pageParam, signal }) =>\n fetchDescriptor(pageParam, {\n signal,\n staleTime: resolveFetchStaleTime(queryClient, pageParam, options.staleTime),\n }),\n getNextPageParam: (\n lastPage,\n allPages,\n lastPageDescriptor,\n allPageDescriptors\n ) =>\n options.getNextPage(\n buildPageContext(\n lastPage,\n allPages,\n lastPageDescriptor,\n allPageDescriptors\n )\n ),\n getPreviousPageParam: options.getPreviousPage\n ? (firstPage, allPages, firstPageDescriptor, allPageDescriptors) =>\n options.getPreviousPage?.(\n buildPageContext(\n firstPage,\n allPages,\n firstPageDescriptor,\n allPageDescriptors\n )\n )\n : undefined,\n select: (data) => data.pages,\n staleTime: options.staleTime ?? options.initialPage.staleTime,\n gcTime: options.gcTime ?? options.initialPage.gcTime,\n maxPages: options.maxPages,\n });\n\n return {\n data: result.data,\n error: result.error,\n isLoading: result.isLoading,\n isFetching: result.isFetching,\n isError: result.isError,\n hasNextPage: result.hasNextPage ?? false,\n hasPreviousPage: result.hasPreviousPage ?? false,\n isFetchingNextPage: result.isFetchingNextPage,\n isFetchingPreviousPage: result.isFetchingPreviousPage,\n fetchNextPage: async () => {\n await result.fetchNextPage();\n },\n fetchPreviousPage: async () => {\n await result.fetchPreviousPage();\n },\n refetch: async () => {\n await result.refetch();\n },\n };\n}\n// @cpt-end:cpt-frontx-flow-request-lifecycle-use-api-query:p2:inst-delegate-frontx-use-infinite-query\n\n// @cpt-begin:cpt-frontx-flow-request-lifecycle-use-api-query:p2:inst-delegate-frontx-use-suspense-infinite-query\nexport function useFrontXSuspenseInfiniteQuery<TPage = unknown, TError = Error>(\n options: ApiInfiniteQueryOptions<TPage>\n) {\n const queryClient = useRequiredFrontXQueryClient();\n const result = useSuspenseInfiniteQuery<\n TPage,\n TError,\n readonly TPage[],\n readonly unknown[],\n EndpointDescriptor<TPage>\n >({\n queryKey: options.initialPage.key,\n initialPageParam: options.initialPage,\n queryFn: ({ pageParam, signal }) =>\n fetchDescriptor(pageParam, {\n signal,\n staleTime: resolveFetchStaleTime(queryClient, pageParam, options.staleTime),\n }),\n getNextPageParam: (\n lastPage,\n allPages,\n lastPageDescriptor,\n allPageDescriptors\n ) =>\n options.getNextPage(\n buildPageContext(\n lastPage,\n allPages,\n lastPageDescriptor,\n allPageDescriptors\n )\n ),\n getPreviousPageParam: options.getPreviousPage\n ? (firstPage, allPages, firstPageDescriptor, allPageDescriptors) =>\n options.getPreviousPage?.(\n buildPageContext(\n firstPage,\n allPages,\n firstPageDescriptor,\n allPageDescriptors\n )\n )\n : undefined,\n select: (data) => data.pages,\n staleTime: options.staleTime ?? options.initialPage.staleTime,\n gcTime: options.gcTime ?? options.initialPage.gcTime,\n maxPages: options.maxPages,\n });\n\n return {\n data: result.data,\n error: result.error,\n isFetching: result.isFetching,\n hasNextPage: result.hasNextPage ?? false,\n hasPreviousPage: result.hasPreviousPage ?? false,\n isFetchingNextPage: result.isFetchingNextPage,\n isFetchingPreviousPage: result.isFetchingPreviousPage,\n fetchNextPage: async () => {\n await result.fetchNextPage();\n },\n fetchPreviousPage: async () => {\n await result.fetchPreviousPage();\n },\n refetch: async () => {\n await result.refetch();\n },\n };\n}\n// @cpt-end:cpt-frontx-flow-request-lifecycle-use-api-query:p2:inst-delegate-frontx-use-suspense-infinite-query\n\n// @cpt-begin:cpt-frontx-flow-request-lifecycle-use-api-mutation:p2:inst-delegate-frontx-use-mutation\nexport function useFrontXMutation<\n TData = unknown,\n TError = Error,\n TVariables = void,\n TContext = unknown,\n>(\n options: UseApiMutationOptions<TData, TError, TVariables, TContext>,\n callbackCtx: MutationCallbackContext\n) {\n useRequiredFrontXQueryClient();\n\n const latestRef = useLatest({ options, callbackCtx });\n const fetchAbortControllersRef = React.useRef<Set<AbortController>>(new Set());\n\n // Effect event: reads abortOnUnmount from the most recent render, not\n // whatever option value was current when the unmount effect was set up.\n const abortFetchesOnUnmount = React.useEffectEvent(() => {\n if (options.abortOnUnmount) {\n for (const controller of fetchAbortControllersRef.current) {\n controller.abort();\n }\n fetchAbortControllersRef.current.clear();\n }\n });\n\n React.useEffect(() => {\n return () => {\n abortFetchesOnUnmount();\n };\n }, []);\n\n const mutationFn = React.useCallback((variables: TVariables, context: MutationFunctionContext) => {\n const cancelOnSupersede = latestRef.current.options.cancelOnSupersede;\n if (cancelOnSupersede) {\n for (const controller of fetchAbortControllersRef.current) {\n controller.abort();\n }\n fetchAbortControllersRef.current.clear();\n }\n\n const controller = new AbortController();\n fetchAbortControllersRef.current.add(controller);\n\n const librarySignal = (context as MutationFunctionContext & { signal?: AbortSignal }).signal;\n if (cancelOnSupersede && librarySignal) {\n if (librarySignal.aborted) {\n controller.abort();\n } else {\n librarySignal.addEventListener('abort', () => controller.abort(), { once: true });\n }\n }\n\n return latestRef.current.options.endpoint\n .fetch(variables, { signal: controller.signal })\n .finally(() => {\n fetchAbortControllersRef.current.delete(controller);\n });\n // latestRef's identity never changes (useLatest returns a stable ref\n // object) — listing it satisfies exhaustive-deps without recreating this\n // callback on every render.\n }, [latestRef]);\n\n const onMutate = React.useCallback((variables: TVariables, _context: MutationFunctionContext) => {\n const current = latestRef.current;\n if (!current.options.onMutate) {\n return undefined as TContext;\n }\n\n return current.options.onMutate(variables, current.callbackCtx);\n // latestRef's identity never changes — see mutationFn above.\n }, [latestRef]);\n\n const onSuccess = React.useCallback((data: TData, variables: TVariables, context: TContext | undefined) => {\n const current = latestRef.current;\n return current.options.onSuccess?.(data, variables, context, current.callbackCtx);\n // latestRef's identity never changes — see mutationFn above.\n }, [latestRef]);\n\n const onError = React.useCallback((error: TError, variables: TVariables, context: TContext | undefined) => {\n const current = latestRef.current;\n return current.options.onError?.(error, variables, context, current.callbackCtx);\n // latestRef's identity never changes — see mutationFn above.\n }, [latestRef]);\n\n const onSettled = React.useCallback((\n data: TData | undefined,\n error: TError | null,\n variables: TVariables,\n context: TContext | undefined\n ) => {\n const current = latestRef.current;\n return current.options.onSettled?.(\n data,\n error,\n variables,\n context,\n current.callbackCtx\n );\n // latestRef's identity never changes — see mutationFn above.\n }, [latestRef]);\n\n const mutation = useMutation<TData, TError, TVariables, TContext>({\n mutationFn,\n onMutate: options.onMutate ? onMutate : undefined,\n onSuccess: options.onSuccess ? onSuccess : undefined,\n onError: options.onError ? onError : undefined,\n onSettled: options.onSettled ? onSettled : undefined,\n });\n\n return {\n mutate: mutation.mutate as (variables: TVariables) => void,\n mutateAsync: mutation.mutateAsync as (variables: TVariables) => Promise<TData>,\n isPending: mutation.isPending,\n error: mutation.error,\n data: mutation.data,\n reset: mutation.reset,\n };\n}\n// @cpt-end:cpt-frontx-flow-request-lifecycle-use-api-mutation:p2:inst-delegate-frontx-use-mutation\n","/**\n * QueryCache — restricted interface for interacting with the shared QueryClient.\n *\n * MFEs and screen-set components access the cache only through this sanctioned\n * public interface. It is injected as { queryCache } into useApiMutation\n * callbacks and also returned by useQueryCache() for controlled imperative\n * cache access.\n */\n// @cpt-dod:cpt-frontx-dod-request-lifecycle-use-api-mutation:p2\n// @cpt-flow:cpt-frontx-flow-request-lifecycle-use-api-mutation:p2:inst-create-query-cache\n// @cpt-FEATURE:implement-endpoint-descriptors:p3\n\nimport type { EndpointDescriptor } from '@gears-frontx/framework';\nimport { eventBus } from '@gears-frontx/framework';\nimport { type QueryClient, type QueryState } from '@tanstack/react-query';\n\nexport type QueryCacheKey = readonly unknown[];\nexport type QueryCacheRefetchMode = 'active' | 'inactive' | 'all' | 'none';\nexport type QueryCacheInvalidateTarget =\n | EndpointDescriptor<unknown>\n | QueryCacheKey\n | null\n | undefined;\n\nexport interface QueryCacheState<TData = unknown, TError = Error> {\n data: TData | undefined;\n dataUpdatedAt: number;\n error: TError | null;\n errorUpdatedAt: number;\n fetchFailureCount: number;\n fetchFailureReason: TError | null;\n fetchStatus: 'fetching' | 'paused' | 'idle';\n isInvalidated: boolean;\n status: 'pending' | 'error' | 'success';\n}\n\nexport type QueryCacheInvalidateFilters = {\n queryKey?: QueryCacheInvalidateTarget;\n exact?: boolean;\n refetchType?: QueryCacheRefetchMode;\n};\n\ntype QueryCacheUpdater<T> = T | ((old: T | undefined) => T | undefined);\n\ntype CacheInvalidateEvent = {\n queryKey: QueryCacheKey;\n exact?: boolean;\n refetchType?: QueryCacheRefetchMode;\n source?: string;\n};\n\ntype CacheSetEvent = {\n queryKey: QueryCacheKey;\n dataOrUpdater: QueryCacheUpdater<unknown>;\n source?: string;\n};\n\ntype CacheRemoveEvent = {\n queryKey: QueryCacheKey;\n source?: string;\n};\n\nconst QUERY_CLIENT_BROADCAST_TARGET = Symbol.for('frontx:query-cache:broadcast-target');\nconst QUERY_CLIENT_BROADCAST_COUNTER = Symbol.for('frontx:query-cache:broadcast-counter');\n\ntype QueryClientWithMetadata = QueryClient & {\n [QUERY_CLIENT_BROADCAST_TARGET]?: string;\n};\n\ntype QueryClientCounterHost = typeof globalThis & {\n [QUERY_CLIENT_BROADCAST_COUNTER]?: number;\n};\n\nfunction emitCacheEvent(event: string, payload: unknown): void {\n (eventBus.emit as (eventType: string, payload: unknown) => void)(event, payload);\n}\n\nfunction ensureBroadcastSource(queryClient: QueryClient): string {\n const clientWithMetadata = queryClient as QueryClientWithMetadata;\n const existingSource = clientWithMetadata[QUERY_CLIENT_BROADCAST_TARGET];\n if (typeof existingSource === 'string' && existingSource.length > 0) {\n return existingSource;\n }\n\n const host = globalThis as QueryClientCounterHost;\n const nextCounter = (host[QUERY_CLIENT_BROADCAST_COUNTER] ?? 0) + 1;\n host[QUERY_CLIENT_BROADCAST_COUNTER] = nextCounter;\n\n const source = `query-cache-${nextCounter}`;\n clientWithMetadata[QUERY_CLIENT_BROADCAST_TARGET] = source;\n return source;\n}\n\n// @cpt-begin:implement-endpoint-descriptors:p3:inst-resolve-key\nexport function resolveKey(target: EndpointDescriptor<unknown> | QueryCacheKey): readonly unknown[] {\n if (\n target !== null &&\n typeof target === 'object' &&\n !Array.isArray(target) &&\n 'key' in target &&\n 'fetch' in target &&\n Array.isArray(target.key) &&\n typeof target.fetch === 'function'\n ) {\n return target.key;\n }\n\n return target as readonly unknown[];\n}\n// @cpt-end:implement-endpoint-descriptors:p3:inst-resolve-key\n\n// @cpt-begin:cpt-frontx-dod-request-lifecycle-use-api-mutation:p2:inst-query-cache-interface\nexport interface QueryCache {\n get<T>(queryKey: EndpointDescriptor<unknown> | QueryCacheKey): T | undefined;\n getState<TData = unknown, TError = Error>(\n queryKey: EndpointDescriptor<unknown> | QueryCacheKey\n ): QueryCacheState<TData, TError> | undefined;\n set<T>(\n queryKey: EndpointDescriptor<unknown> | QueryCacheKey,\n dataOrUpdater: T | ((old: T | undefined) => T | undefined)\n ): void;\n cancel(queryKey: EndpointDescriptor<unknown> | QueryCacheKey): Promise<void>;\n invalidate(queryKey: EndpointDescriptor<unknown> | QueryCacheKey): Promise<void>;\n invalidateMany(filters?: QueryCacheInvalidateFilters | null): Promise<void>;\n remove(queryKey: EndpointDescriptor<unknown> | QueryCacheKey): void;\n}\n// @cpt-end:cpt-frontx-dod-request-lifecycle-use-api-mutation:p2:inst-query-cache-interface\n\n// @cpt-begin:cpt-frontx-dod-request-lifecycle-use-api-mutation:p2:inst-mutation-callback-context\nexport interface MutationCallbackContext {\n queryCache: QueryCache;\n}\n// @cpt-end:cpt-frontx-dod-request-lifecycle-use-api-mutation:p2:inst-mutation-callback-context\n\nfunction toQueryUpdater<T>(\n dataOrUpdater: QueryCacheUpdater<T>\n): (old: T | undefined) => T | undefined {\n if (typeof dataOrUpdater === 'function') {\n return dataOrUpdater as (old: T | undefined) => T | undefined;\n }\n\n return () => dataOrUpdater;\n}\n\nfunction mapQueryState<TData, TError = Error>(\n state: QueryState<TData, TError>\n): QueryCacheState<TData, TError> {\n return {\n data: state.data,\n dataUpdatedAt: state.dataUpdatedAt,\n error: state.error,\n errorUpdatedAt: state.errorUpdatedAt,\n fetchFailureCount: state.fetchFailureCount,\n fetchFailureReason: state.fetchFailureReason,\n fetchStatus: state.fetchStatus,\n isInvalidated: state.isInvalidated,\n status: state.status,\n };\n}\n\n// @cpt-begin:implement-endpoint-descriptors:p3:inst-create-query-cache\nexport function createQueryCache(queryClient: QueryClient): QueryCache {\n return {\n get: <T,>(key: EndpointDescriptor<unknown> | QueryCacheKey): T | undefined => {\n return queryClient.getQueryData<T>(resolveKey(key));\n },\n getState: <TData = unknown, TError = Error>(key: EndpointDescriptor<unknown> | QueryCacheKey) => {\n const state = queryClient.getQueryState<TData, TError>(resolveKey(key));\n return state ? mapQueryState(state) : undefined;\n },\n set: <T,>(key: EndpointDescriptor<unknown> | QueryCacheKey, dataOrUpdater: QueryCacheUpdater<T>): void => {\n const resolvedKey = resolveKey(key);\n queryClient.setQueryData<T>(resolvedKey, toQueryUpdater(dataOrUpdater));\n emitCacheEvent('cache/set', {\n queryKey: resolvedKey,\n dataOrUpdater: dataOrUpdater as QueryCacheUpdater<unknown>,\n source: ensureBroadcastSource(queryClient),\n } satisfies CacheSetEvent);\n },\n cancel: (key: EndpointDescriptor<unknown> | QueryCacheKey): Promise<void> => {\n return queryClient.cancelQueries({ queryKey: resolveKey(key) });\n },\n invalidate: (key: EndpointDescriptor<unknown> | QueryCacheKey): Promise<void> => {\n const resolvedKey = resolveKey(key);\n const result = queryClient.invalidateQueries({ queryKey: resolvedKey });\n emitCacheEvent('cache/invalidate', {\n queryKey: resolvedKey,\n source: ensureBroadcastSource(queryClient),\n } satisfies CacheInvalidateEvent);\n return result;\n },\n invalidateMany: (filters): Promise<void> => {\n if (filters?.queryKey == null) {\n return Promise.resolve();\n }\n\n const resolvedKey = resolveKey(filters.queryKey);\n if (!Array.isArray(resolvedKey) || resolvedKey.length === 0) {\n return Promise.resolve();\n }\n\n const payload = {\n ...filters,\n queryKey: resolvedKey,\n };\n const result = queryClient.invalidateQueries(payload);\n emitCacheEvent('cache/invalidate', {\n ...payload,\n source: ensureBroadcastSource(queryClient),\n } satisfies CacheInvalidateEvent);\n return result;\n },\n remove: (key: EndpointDescriptor<unknown> | QueryCacheKey): void => {\n const resolvedKey = resolveKey(key);\n queryClient.removeQueries({ queryKey: resolvedKey });\n emitCacheEvent('cache/remove', {\n queryKey: resolvedKey,\n source: ensureBroadcastSource(queryClient),\n } satisfies CacheRemoveEvent);\n },\n };\n}\n// @cpt-end:implement-endpoint-descriptors:p3:inst-create-query-cache\n","/**\n * useLatest - keeps a ref pinned to the most recently rendered value\n *\n * A handful of hooks/components in this package need to read the current\n * value of a prop or option from inside a callback or effect-cleanup closure\n * that must NOT re-run every time that value changes (e.g. a stable\n * useCallback with `[]` deps, or a mount/unmount effect keyed on identity\n * rather than on every option). Stashing the value in a ref sidesteps the\n * closure staleness without pulling the value into the dependency array.\n *\n * The write happens inside a deps-less effect (runs after every commit)\n * rather than during render, because refs must not be mutated while\n * rendering: render can be invoked more than once per commit (React\n * StrictMode's double-invoke, and future concurrent-rendering paths that\n * may discard a render), so a render-time write can leave the ref out of\n * sync with what was actually committed to the DOM. A deps-less effect\n * runs exactly once per real commit, so the ref always reflects the value\n * that was last rendered.\n */\n\nimport { useEffect, useRef, type RefObject } from 'react';\n\n/**\n * Returns a ref that always holds the most recently rendered `value`.\n *\n * The ref identity is stable across renders (same object returned every\n * time), so it is safe to add to a `useCallback`/`useEffect` dependency\n * array without causing the callback/effect to be recreated.\n */\nexport function useLatest<T>(value: T): RefObject<T> {\n const ref = useRef(value);\n\n // Deps-less: must run after every render so `ref.current` never lags\n // behind the value that was just committed. See module doc for why this\n // write cannot happen during render itself.\n useEffect(() => {\n ref.current = value;\n });\n\n return ref;\n}\n","import { useEffect, useState } from 'react';\nimport type {\n AccessQuery,\n AccessRecord,\n AuthRuntime,\n FrontXApp,\n} from '@gears-frontx/framework';\nimport { useFrontX } from '../FrontXContext';\nimport type { UseCanAccessResult } from '../types';\n\n/**\n * Stable string key for an AccessQuery.\n * Record keys are sorted so { b:1, a:2 } and { a:2, b:1 } yield the same key.\n * Values include an explicit type prefix to avoid collisions:\n * 1 !== \"1\", null !== \"null\", true !== \"true\".\n */\nfunction serializeRecordValue(value: AccessRecord[string]): string {\n if (value === null) return 'n:';\n if (typeof value === 'string') return `s:${value}`;\n if (typeof value === 'number') {\n // Preserve -0 distinction for completeness.\n return `d:${Object.is(value, -0) ? '-0' : String(value)}`;\n }\n return value ? 'b:1' : 'b:0';\n}\n\nfunction accessQueryKey(query: AccessQuery): string {\n const { action, resource, record } = query;\n // JSON-encode the tuple so delimiter characters in any component\n // (action / resource / record keys / string values) cannot collide.\n // Using Object.entries avoids dynamic bracket access on `record` (static\n // analyzers flag `record[k]` as a potential object-injection sink).\n const normalizedRecord = record\n ? Object.entries(record)\n .sort(([a], [b]) => a.localeCompare(b))\n .map(([k, v]) => [k, serializeRecordValue(v)] as const)\n : null;\n return JSON.stringify([action, resource, normalizedRecord]);\n}\n\ntype FrontXAuthAppContract = FrontXApp & {\n auth?: AuthRuntime;\n};\n\nfunction getAuthRuntime(app: FrontXApp): AuthRuntime | null {\n return (app as FrontXAuthAppContract).auth ?? null;\n}\n\n// Module-level constant so the no-auth-runtime denial keeps a stable identity\n// across renders — consumers can put the hook result in dependency lists\n// without re-firing every render.\nconst DENIED_NO_AUTH: UseCanAccessResult = { allow: false, isResolving: false };\n\n/**\n * Declarative RBAC guard hook.\n *\n * Pessimistic: `allow` is false until an explicit 'allow' decision arrives.\n * Aborts the in-flight canAccess call on unmount and on query change.\n *\n * State machine:\n * mount -> Pending (allow=false, isResolving=true)\n * Pending -> 'allow' -> Allowed (allow=true, isResolving=false)\n * Pending -> 'deny' -> Denied (allow=false, isResolving=false)\n * Pending -> error -> Denied (allow=false, isResolving=false)\n * Allowed -> query-change -> Pending (re-pessimize)\n * Denied -> query-change -> Pending (re-pessimize)\n */\nexport function useCanAccess<TRecord extends AccessRecord = AccessRecord>(\n query: AccessQuery<TRecord>,\n): UseCanAccessResult {\n const app = useFrontX();\n\n // Resolved once per `app` change; read here (not just inside the effect) so both the\n // \"no auth runtime\" case and the \"pending\" reset below can be derived/adjusted at\n // render time instead of requiring a synchronous setState from the effect.\n const auth = getAuthRuntime(app);\n\n const stableKey = accessQueryKey(query as AccessQuery);\n\n // Derived state: store the query value whose key matches `stableKey`. We\n // refresh it during render whenever `stableKey` changes (React derived-state\n // pattern) so the effect can depend on the stored value directly — its\n // referential identity tracks the access intent, not the parent render cycle.\n const [stableQuery, setStableQuery] = useState<AccessQuery>(() => query as AccessQuery);\n // Tracks the (auth, stableKey) combination the effect below was last run for —\n // exactly its dependency list — so every input that would restart the access check\n // also re-pessimizes `result` here, during render, instead of via a setState call\n // inside the effect.\n //\n // `app` is not part of it. The decision is the auth runtime's, and a host that\n // rebuilds its app object around the same runtime has changed nothing the check\n // reads; tracking it would re-pessimize an answered guard back to Pending and\n // ask the same question again.\n const [runState, setRunState] = useState({ auth, stableKey });\n const [result, setResult] = useState<UseCanAccessResult>({ allow: false, isResolving: true });\n\n if (runState.auth !== auth || runState.stableKey !== stableKey) {\n setRunState({ auth, stableKey });\n setStableQuery(query as AccessQuery);\n // Re-pessimize at render time: every (auth, stableKey) combination\n // the effect below runs for enters Pending here, before the async\n // decision starts.\n setResult({ allow: false, isResolving: true });\n }\n\n useEffect(() => {\n if (!auth) {\n // No auth runtime on the app: the returned result is derived below\n // (`auth ? result : DENIED_NO_AUTH`), so there is nothing to synchronize here.\n return;\n }\n\n // `result` is re-pessimized during render above for every\n // (auth, stableKey) combination this effect runs for — no setState needed\n // here before starting the async decision.\n let alive = true;\n const controller = new AbortController();\n\n void auth\n .canAccess(stableQuery, { signal: controller.signal })\n .then((decision) => {\n if (alive) {\n setResult({ allow: decision === 'allow', isResolving: false });\n }\n })\n .catch(() => {\n if (alive) {\n setResult({ allow: false, isResolving: false });\n }\n });\n\n return () => {\n alive = false;\n controller.abort();\n };\n }, [auth, stableQuery]);\n\n return auth ? result : DENIED_NO_AUTH;\n}\n","// @cpt-FEATURE:cpt-frontx-feature-auth-plugin:p1\n// @cpt-flow:cpt-frontx-flow-auth-plugin-rbac-guard:p1\nimport type { ReactElement } from 'react';\nimport type { AccessRecord } from '@gears-frontx/framework';\nimport { useCanAccess } from '../hooks/useCanAccess';\nimport type { CanAccessProps } from '../types';\n\n/**\n * Declarative RBAC guard component.\n *\n * Pessimistic: renders `denied` (or `loading` if provided) until an explicit\n * 'allow' decision arrives from app.auth.canAccess. Only renders `allowed`\n * after a confirmed allow.\n *\n * Example:\n * <CanAccess\n * query={{ action: AppAction.InvoicesRead, resource: ResourceKind.Invoice }}\n * allowed={<InvoiceList />}\n * denied={<AccessDenied />}\n * loading={<Spinner />}\n * />\n */\nexport function CanAccess<TRecord extends AccessRecord = AccessRecord>({\n query,\n allowed,\n denied = null,\n loading,\n}: CanAccessProps<TRecord>): ReactElement | null {\n // @cpt-begin:cpt-frontx-flow-auth-plugin-rbac-guard:p1:inst-component-render\n const { allow, isResolving } = useCanAccess(query);\n\n if (isResolving) {\n return (loading !== undefined ? loading : denied) as ReactElement | null;\n }\n\n return (allow ? allowed : denied) as ReactElement | null;\n // @cpt-end:cpt-frontx-flow-auth-plugin-rbac-guard:p1:inst-component-render\n}\n","/**\n * useAppDispatch Hook - Type-safe dispatch hook\n *\n * React Layer: L3\n */\n// @cpt-flow:cpt-frontx-flow-react-bindings-use-dispatch:p1\n// @cpt-dod:cpt-frontx-dod-react-bindings-redux-hooks:p1\n\nimport { useDispatch } from 'react-redux';\nimport type { AppDispatch } from '@gears-frontx/framework';\n\n/**\n * Type-safe dispatch hook.\n *\n * @returns The typed dispatch function\n *\n * @example\n * ```tsx\n * const dispatch = useAppDispatch();\n * dispatch(someAction());\n * ```\n */\n// @cpt-begin:cpt-frontx-flow-react-bindings-use-dispatch:p1:inst-call-dispatch\n// @cpt-begin:cpt-frontx-flow-react-bindings-use-dispatch:p1:inst-delegate-dispatch\n// @cpt-begin:cpt-frontx-flow-react-bindings-use-dispatch:p1:inst-use-dispatch\n// @cpt-begin:cpt-frontx-dod-react-bindings-redux-hooks:p1:inst-use-dispatch\nexport function useAppDispatch(): AppDispatch {\n // Use untyped useDispatch and cast the result\n // This avoids type constraint issues with react-redux's generic\n return useDispatch() as AppDispatch;\n}\n// @cpt-end:cpt-frontx-flow-react-bindings-use-dispatch:p1:inst-call-dispatch\n// @cpt-end:cpt-frontx-flow-react-bindings-use-dispatch:p1:inst-delegate-dispatch\n// @cpt-end:cpt-frontx-flow-react-bindings-use-dispatch:p1:inst-use-dispatch\n// @cpt-end:cpt-frontx-dod-react-bindings-redux-hooks:p1:inst-use-dispatch\n","/**\n * useAppSelector Hook - Type-safe selector hook\n *\n * React Layer: L3\n */\n// @cpt-flow:cpt-frontx-flow-react-bindings-use-selector:p1\n// @cpt-dod:cpt-frontx-dod-react-bindings-redux-hooks:p1\n\nimport { useSelector, type TypedUseSelectorHook } from 'react-redux';\nimport type { RootState } from '@gears-frontx/framework';\n\n/**\n * Type-safe selector hook.\n *\n * @example\n * ```tsx\n * const activeScreen = useAppSelector(selectActiveScreen);\n * const menuCollapsed = useAppSelector(selectMenuCollapsed);\n * ```\n */\n// @cpt-begin:cpt-frontx-flow-react-bindings-use-selector:p1:inst-call-selector\n// @cpt-begin:cpt-frontx-flow-react-bindings-use-selector:p1:inst-delegate-selector\n// @cpt-begin:cpt-frontx-flow-react-bindings-use-selector:p1:inst-return-state\n// @cpt-begin:cpt-frontx-flow-react-bindings-use-selector:p1:inst-rerender-on-change\n// @cpt-begin:cpt-frontx-dod-react-bindings-redux-hooks:p1:inst-use-selector\nexport const useAppSelector: TypedUseSelectorHook<RootState> = useSelector;\n// @cpt-end:cpt-frontx-flow-react-bindings-use-selector:p1:inst-call-selector\n// @cpt-end:cpt-frontx-flow-react-bindings-use-selector:p1:inst-delegate-selector\n// @cpt-end:cpt-frontx-flow-react-bindings-use-selector:p1:inst-return-state\n// @cpt-end:cpt-frontx-flow-react-bindings-use-selector:p1:inst-rerender-on-change\n// @cpt-end:cpt-frontx-dod-react-bindings-redux-hooks:p1:inst-use-selector\n","/**\n * useTranslation Hook - Translation utilities\n *\n * React Layer: L3\n */\n// @cpt-flow:cpt-frontx-flow-react-bindings-use-translation:p1\n// @cpt-dod:cpt-frontx-dod-react-bindings-translation-hook:p1\n\nimport { useMemo, useCallback, useSyncExternalStore } from 'react';\nimport type { Language } from '@gears-frontx/framework';\nimport { useFrontX } from '../FrontXContext';\nimport type { UseTranslationReturn } from '../types';\n\n/**\n * Hook for accessing translation utilities.\n *\n * @returns Translation utilities\n *\n * @example\n * ```tsx\n * const { t, language, setLanguage, isRTL } = useTranslation();\n *\n * return (\n * <div dir={isRTL ? 'rtl' : 'ltr'}>\n * <h1>{t('common:app.title')}</h1>\n * <p>{t('common:app.welcome', { name: 'John' })}</p>\n * </div>\n * );\n * ```\n */\n// @cpt-begin:cpt-frontx-flow-react-bindings-use-translation:p1:inst-call-translation\n// @cpt-begin:cpt-frontx-dod-react-bindings-translation-hook:p1:inst-call-translation\nexport function useTranslation(): UseTranslationReturn {\n // @cpt-begin:cpt-frontx-flow-react-bindings-use-translation:p1:inst-read-i18n-registry\n const app = useFrontX();\n const { i18nRegistry } = app;\n // @cpt-end:cpt-frontx-flow-react-bindings-use-translation:p1:inst-read-i18n-registry\n\n // @cpt-begin:cpt-frontx-flow-react-bindings-use-translation:p1:inst-subscribe-i18n\n // @cpt-begin:cpt-frontx-flow-react-bindings-use-translation:p1:inst-rerender-on-lang-change\n // Subscribe to translation changes using useSyncExternalStore\n // Uses version counter to trigger re-renders when translations change\n const version = useSyncExternalStore(\n useCallback(\n (callback: () => void) => {\n // Subscribe to translation changes (new translations registered)\n return i18nRegistry.subscribe(callback);\n },\n [i18nRegistry]\n ),\n () => i18nRegistry.getVersion(),\n () => i18nRegistry.getVersion()\n );\n // @cpt-end:cpt-frontx-flow-react-bindings-use-translation:p1:inst-subscribe-i18n\n // @cpt-end:cpt-frontx-flow-react-bindings-use-translation:p1:inst-rerender-on-lang-change\n\n // Get current language (memoized to avoid unnecessary recalculations)\n // version is used to trigger recalculation when translations change\n const language = useMemo(() => {\n void version; // Trigger recalculation when version changes\n return i18nRegistry.getLanguage();\n }, [i18nRegistry, version]);\n\n // Translation function\n const t = useCallback(\n (key: string, params?: Record<string, string | number | boolean>) => {\n return i18nRegistry.t(key, params);\n },\n [i18nRegistry]\n );\n\n // @cpt-begin:cpt-frontx-flow-react-bindings-use-translation:p1:inst-set-language\n // Set language via framework action (emits event bus for MFE propagation)\n const setLanguage = useCallback(\n (lang: Language) => {\n if (app.actions.setLanguage) {\n app.actions.setLanguage({ language: lang });\n }\n },\n [app.actions]\n );\n // @cpt-end:cpt-frontx-flow-react-bindings-use-translation:p1:inst-set-language\n\n // Check RTL - recomputes when language changes\n const isRTL = useMemo(() => {\n // Reference language to trigger recalculation on language change\n void language;\n return i18nRegistry.isRTL();\n }, [i18nRegistry, language]);\n\n // @cpt-begin:cpt-frontx-flow-react-bindings-use-translation:p1:inst-return-translation-api\n return {\n t,\n language,\n setLanguage,\n isRTL,\n };\n // @cpt-end:cpt-frontx-flow-react-bindings-use-translation:p1:inst-return-translation-api\n}\n// @cpt-end:cpt-frontx-flow-react-bindings-use-translation:p1:inst-call-translation\n// @cpt-end:cpt-frontx-dod-react-bindings-translation-hook:p1:inst-call-translation\n","/**\n * useScreenTranslations Hook - Screen-level translation loading\n *\n * React Layer: L3\n */\n// @cpt-flow:cpt-frontx-flow-react-bindings-use-screen-translations:p1\n// @cpt-algo:cpt-frontx-algo-react-bindings-load-screen-translations:p1\n// @cpt-state:cpt-frontx-state-react-bindings-screen-translation:p1\n// @cpt-dod:cpt-frontx-dod-react-bindings-screen-translation-hook:p1\n\nimport { useState, useEffect, useMemo, useCallback, useSyncExternalStore } from 'react';\nimport type { TranslationMap, TranslationLoader } from '@gears-frontx/framework';\nimport { useFrontX } from '../FrontXContext';\nimport type { UseScreenTranslationsReturn } from '../types';\n\n// Re-export TranslationMap for consumers who need it\nexport type { TranslationMap };\n\n/**\n * Check if the input is a TranslationLoader function (from I18nRegistry.createLoader)\n * vs a TranslationMap object\n */\nfunction isTranslationLoader(\n input: TranslationMap | TranslationLoader\n): input is TranslationLoader {\n return typeof input === 'function';\n}\n\n/**\n * Hook for loading screen-level translations.\n * Use this in screen components to lazy-load translations.\n * Automatically reloads translations when language changes.\n *\n * @param screensetId - The screenset ID\n * @param screenId - The screen ID\n * @param translations - Either a TranslationMap object or a TranslationLoader function\n * (from I18nRegistry.createLoader)\n * @returns Loading state\n *\n * @example\n * ```tsx\n * // Option 1: Using I18nRegistry.createLoader (recommended)\n * const translations = I18nRegistry.createLoader({\n * en: () => import('./i18n/en.json'),\n * es: () => import('./i18n/es.json'),\n * });\n *\n * // Option 2: Using raw TranslationMap\n * const translations = {\n * en: () => import('./i18n/en.json'),\n * es: () => import('./i18n/es.json'),\n * };\n *\n * export const HomeScreen: React.FC = () => {\n * const { isLoaded, error } = useScreenTranslations(\n * 'demo',\n * 'home',\n * translations\n * );\n *\n * if (!isLoaded) return <LoadingSpinner />;\n * if (error) return <ErrorMessage error={error} />;\n *\n * return <div>...</div>;\n * };\n * ```\n */\n// @cpt-begin:cpt-frontx-flow-react-bindings-use-screen-translations:p1:inst-call-screen-translations\n// @cpt-begin:cpt-frontx-dod-react-bindings-screen-translation-hook:p1:inst-call-screen-translations\nexport function useScreenTranslations(\n screensetId: string,\n screenId: string,\n translations: TranslationMap | TranslationLoader\n): UseScreenTranslationsReturn {\n const app = useFrontX();\n const { i18nRegistry } = app;\n\n // Track loading state per language to handle language changes. No\n // inst-begin-load marker here: nothing in this state pair signals \"load\n // began\" — loading-in-progress is derived as\n // (currentLanguage !== loadedLanguage), see the comment on `isLoaded`.\n // @cpt-begin:cpt-frontx-state-react-bindings-screen-translation:p1:inst-load-success\n // @cpt-begin:cpt-frontx-state-react-bindings-screen-translation:p1:inst-load-error\n // @cpt-begin:cpt-frontx-state-react-bindings-screen-translation:p1:inst-reload-on-lang-change\n // @cpt-begin:cpt-frontx-state-react-bindings-screen-translation:p2:inst-retry-on-lang-change\n const [loadedLanguage, setLoadedLanguage] = useState<string | null>(null);\n const [error, setError] = useState<Error | null>(null);\n // @cpt-end:cpt-frontx-state-react-bindings-screen-translation:p1:inst-load-success\n // @cpt-end:cpt-frontx-state-react-bindings-screen-translation:p1:inst-load-error\n // @cpt-end:cpt-frontx-state-react-bindings-screen-translation:p1:inst-reload-on-lang-change\n // @cpt-end:cpt-frontx-state-react-bindings-screen-translation:p2:inst-retry-on-lang-change\n\n // @cpt-begin:cpt-frontx-flow-react-bindings-use-screen-translations:p1:inst-subscribe-lang-change\n // Subscribe to translation changes using useSyncExternalStore\n // This ensures we reload when language changes\n const version = useSyncExternalStore(\n useCallback(\n (callback: () => void) => i18nRegistry.subscribe(callback),\n [i18nRegistry]\n ),\n () => i18nRegistry.getVersion(),\n () => i18nRegistry.getVersion()\n );\n // @cpt-end:cpt-frontx-flow-react-bindings-use-screen-translations:p1:inst-subscribe-lang-change\n\n // @cpt-begin:cpt-frontx-algo-react-bindings-load-screen-translations:p1:inst-get-current-lang\n // Get current language (changes when version changes)\n // version is used to trigger recalculation when translations change\n const currentLanguage = useMemo(() => {\n void version; // Trigger recalculation when version changes\n return i18nRegistry.getLanguage();\n }, [i18nRegistry, version]);\n // @cpt-end:cpt-frontx-algo-react-bindings-load-screen-translations:p1:inst-get-current-lang\n\n // @cpt-begin:cpt-frontx-algo-react-bindings-load-screen-translations:p1:inst-resolve-loader\n // Create a TranslationLoader function from the translation map or use directly if already a loader\n const loader: TranslationLoader = useMemo(() => {\n if (isTranslationLoader(translations)) {\n // Already a loader function (from I18nRegistry.createLoader)\n return translations;\n }\n\n // Convert TranslationMap to TranslationLoader\n return async (language: string) => {\n const importFn = translations[language as keyof typeof translations];\n if (!importFn) {\n // Return empty dictionary if language not in map\n return {};\n }\n const module = await importFn();\n return module.default;\n };\n }, [translations]);\n // @cpt-end:cpt-frontx-algo-react-bindings-load-screen-translations:p1:inst-resolve-loader\n\n // @cpt-begin:cpt-frontx-flow-react-bindings-use-screen-translations:p1:inst-run-load-screen-translations\n useEffect(() => {\n // @cpt-begin:cpt-frontx-algo-react-bindings-load-screen-translations:p1:inst-skip-if-loaded\n // Skip if no language or already loaded for this language\n if (!currentLanguage || currentLanguage === loadedLanguage) {\n return;\n }\n // @cpt-end:cpt-frontx-algo-react-bindings-load-screen-translations:p1:inst-skip-if-loaded\n\n let cancelled = false;\n\n const loadTranslations = async () => {\n try {\n const namespace = `screen.${screensetId}.${screenId}`;\n\n // @cpt-begin:cpt-frontx-algo-react-bindings-load-screen-translations:p1:inst-register-loader\n // Register the loader for future language changes\n i18nRegistry.registerLoader(namespace, loader);\n // @cpt-end:cpt-frontx-algo-react-bindings-load-screen-translations:p1:inst-register-loader\n\n // @cpt-begin:cpt-frontx-algo-react-bindings-load-screen-translations:p1:inst-call-loader\n // Actually load the translations for current language\n const loadedTranslations = await loader(currentLanguage);\n // @cpt-end:cpt-frontx-algo-react-bindings-load-screen-translations:p1:inst-call-loader\n\n // @cpt-begin:cpt-frontx-algo-react-bindings-load-screen-translations:p1:inst-register-translations\n i18nRegistry.register(namespace, currentLanguage, loadedTranslations);\n // @cpt-end:cpt-frontx-algo-react-bindings-load-screen-translations:p1:inst-register-translations\n\n // @cpt-begin:cpt-frontx-algo-react-bindings-load-screen-translations:p1:inst-cancel-on-unmount\n if (!cancelled) {\n setLoadedLanguage(currentLanguage);\n setError(null);\n }\n // @cpt-end:cpt-frontx-algo-react-bindings-load-screen-translations:p1:inst-cancel-on-unmount\n } catch (err) {\n // @cpt-begin:cpt-frontx-algo-react-bindings-load-screen-translations:p1:inst-handle-load-error\n if (!cancelled) {\n setError(err instanceof Error ? err : new Error(String(err)));\n }\n // @cpt-end:cpt-frontx-algo-react-bindings-load-screen-translations:p1:inst-handle-load-error\n }\n };\n\n loadTranslations();\n\n // @cpt-begin:cpt-frontx-algo-react-bindings-load-screen-translations:p1:inst-cancel-stale-load\n return () => {\n cancelled = true;\n };\n // @cpt-end:cpt-frontx-algo-react-bindings-load-screen-translations:p1:inst-cancel-stale-load\n }, [screensetId, screenId, loader, i18nRegistry, currentLanguage, loadedLanguage]);\n // @cpt-end:cpt-frontx-flow-react-bindings-use-screen-translations:p1:inst-run-load-screen-translations\n\n // @cpt-begin:cpt-frontx-flow-react-bindings-use-screen-translations:p1:inst-return-loading-state\n // Derived, not a stored flag: on error, loadedLanguage is never advanced to\n // currentLanguage, so the mismatch alone already gates isLoaded false.\n const isLoaded = currentLanguage !== null && currentLanguage === loadedLanguage;\n\n // @cpt-begin:cpt-frontx-flow-react-bindings-use-screen-translations:p1:inst-gate-render\n // isLoaded is the gate value: consumers must check this before rendering translation-dependent UI\n return { isLoaded, error };\n // @cpt-end:cpt-frontx-flow-react-bindings-use-screen-translations:p1:inst-gate-render\n // @cpt-end:cpt-frontx-flow-react-bindings-use-screen-translations:p1:inst-return-loading-state\n}\n// @cpt-end:cpt-frontx-flow-react-bindings-use-screen-translations:p1:inst-call-screen-translations\n// @cpt-end:cpt-frontx-dod-react-bindings-screen-translation-hook:p1:inst-call-screen-translations\n","/**\n * useFormatters Hook - Locale-aware formatters\n *\n * Returns formatters that use i18nRegistry.getLanguage() internally.\n * Calls useTranslation() so the component re-renders when language changes.\n *\n * React Layer: L3\n */\n// @cpt-flow:cpt-frontx-flow-react-bindings-use-formatters:p1\n// @cpt-dod:cpt-frontx-dod-react-bindings-formatters-hook:p1\n\nimport { useMemo } from 'react';\nimport {\n formatDate as formatDateFn,\n formatTime as formatTimeFn,\n formatDateTime as formatDateTimeFn,\n formatRelative as formatRelativeFn,\n formatNumber as formatNumberFn,\n formatPercent as formatPercentFn,\n formatCompact as formatCompactFn,\n formatCurrency as formatCurrencyFn,\n compareStrings as compareStringsFn,\n createCollator as createCollatorFn,\n} from '@gears-frontx/framework';\nimport type { UseFormattersReturn } from '../types';\nimport { useTranslation } from './useTranslation';\n\n/**\n * Hook for accessing locale-aware formatters (date, number, currency, sort).\n *\n * Formatters use the current app language from i18nRegistry.getLanguage().\n * Re-renders when language changes via useTranslation() subscription.\n *\n * @returns Object with formatDate, formatTime, formatDateTime, formatRelative,\n * formatNumber, formatPercent, formatCompact, formatCurrency, compareStrings, createCollator\n *\n * @example\n * ```tsx\n * const { formatDate, formatCurrency } = useFormatters();\n * return (\n * <span>{formatDate(new Date(), 'short')}</span>\n * <span>{formatCurrency(99.99, 'USD')}</span>\n * );\n * ```\n */\n// @cpt-begin:cpt-frontx-flow-react-bindings-use-formatters:p1:inst-call-formatters\n// @cpt-begin:cpt-frontx-dod-react-bindings-formatters-hook:p1:inst-call-formatters\nexport function useFormatters(): UseFormattersReturn {\n // @cpt-begin:cpt-frontx-flow-react-bindings-use-formatters:p1:inst-subscribe-via-translation\n // useTranslation() subscribes to language changes so this component re-renders\n // when language changes; formatters read i18nRegistry.getLanguage() at call time\n const { language } = useTranslation();\n // @cpt-end:cpt-frontx-flow-react-bindings-use-formatters:p1:inst-subscribe-via-translation\n\n // @cpt-begin:cpt-frontx-flow-react-bindings-use-formatters:p1:inst-return-formatters\n // @cpt-begin:cpt-frontx-flow-react-bindings-use-formatters:p1:inst-formatters-read-locale\n // @cpt-begin:cpt-frontx-flow-react-bindings-use-formatters:p1:inst-recompute-on-lang\n return useMemo<UseFormattersReturn>(\n () => {\n void language; // re-run when language changes so formatters see new locale\n return {\n formatDate: formatDateFn,\n formatTime: formatTimeFn,\n formatDateTime: formatDateTimeFn,\n formatRelative: formatRelativeFn,\n formatNumber: formatNumberFn,\n formatPercent: formatPercentFn,\n formatCompact: formatCompactFn,\n formatCurrency: formatCurrencyFn,\n compareStrings: compareStringsFn,\n createCollator: createCollatorFn,\n };\n },\n [language]\n );\n // @cpt-end:cpt-frontx-flow-react-bindings-use-formatters:p1:inst-return-formatters\n // @cpt-end:cpt-frontx-flow-react-bindings-use-formatters:p1:inst-formatters-read-locale\n // @cpt-end:cpt-frontx-flow-react-bindings-use-formatters:p1:inst-recompute-on-lang\n}\n// @cpt-end:cpt-frontx-flow-react-bindings-use-formatters:p1:inst-call-formatters\n// @cpt-end:cpt-frontx-dod-react-bindings-formatters-hook:p1:inst-call-formatters\n","/**\n * useTheme Hook - Theme utilities\n *\n * React Layer: L3\n */\n// @cpt-flow:cpt-frontx-flow-react-bindings-use-theme:p1\n// @cpt-dod:cpt-frontx-dod-react-bindings-theme-hook:p1\n\nimport { useCallback, useMemo, useSyncExternalStore } from 'react';\nimport { useFrontX } from '../FrontXContext';\nimport type { UseThemeReturn } from '../types';\n\n/**\n * Hook for theme utilities.\n *\n * @returns Theme utilities\n *\n * @example\n * ```tsx\n * const { currentTheme, themes, setTheme } = useTheme();\n *\n * return (\n * <select\n * value={currentTheme}\n * onChange={(e) => setTheme(e.target.value)}\n * >\n * {themes.map((theme) => (\n * <option key={theme.id} value={theme.id}>\n * {theme.name}\n * </option>\n * ))}\n * </select>\n * );\n * ```\n */\n// @cpt-begin:cpt-frontx-flow-react-bindings-use-theme:p1:inst-call-theme\n// @cpt-begin:cpt-frontx-dod-react-bindings-theme-hook:p1:inst-call-theme\nexport function useTheme(): UseThemeReturn {\n // @cpt-begin:cpt-frontx-flow-react-bindings-use-theme:p1:inst-read-theme-registry\n const app = useFrontX();\n const { themeRegistry } = app;\n // @cpt-end:cpt-frontx-flow-react-bindings-use-theme:p1:inst-read-theme-registry\n\n // @cpt-begin:cpt-frontx-flow-react-bindings-use-theme:p1:inst-subscribe-theme\n // @cpt-begin:cpt-frontx-flow-react-bindings-use-theme:p1:inst-rerender-on-theme-change\n // Subscribe to theme changes using useSyncExternalStore\n // Uses version counter to trigger re-renders when theme changes\n const version = useSyncExternalStore(\n useCallback(\n (callback: () => void) => {\n return themeRegistry.subscribe(callback);\n },\n [themeRegistry]\n ),\n () => themeRegistry.getVersion(),\n () => themeRegistry.getVersion()\n );\n // @cpt-end:cpt-frontx-flow-react-bindings-use-theme:p1:inst-subscribe-theme\n // @cpt-end:cpt-frontx-flow-react-bindings-use-theme:p1:inst-rerender-on-theme-change\n\n // Get current theme (memoized, recalculates on version change)\n const currentTheme = useMemo(() => {\n // Reference version to trigger recalculation on theme change\n void version;\n const theme = themeRegistry.getCurrent();\n return theme?.id;\n }, [themeRegistry, version]);\n\n // Get all themes\n const themes = useMemo(() => {\n return themeRegistry.getAll().map((theme) => ({\n id: theme.id,\n name: theme.name,\n }));\n }, [themeRegistry]);\n\n // @cpt-begin:cpt-frontx-flow-react-bindings-use-theme:p1:inst-dispatch-change-theme\n // Set theme\n const setTheme = useCallback(\n (themeId: string) => {\n if (app.actions.changeTheme) {\n app.actions.changeTheme({ themeId });\n }\n },\n [app.actions]\n );\n // @cpt-end:cpt-frontx-flow-react-bindings-use-theme:p1:inst-dispatch-change-theme\n\n // @cpt-begin:cpt-frontx-flow-react-bindings-use-theme:p1:inst-return-theme-api\n return {\n currentTheme,\n themes,\n setTheme,\n };\n // @cpt-end:cpt-frontx-flow-react-bindings-use-theme:p1:inst-return-theme-api\n}\n// @cpt-end:cpt-frontx-flow-react-bindings-use-theme:p1:inst-call-theme\n// @cpt-end:cpt-frontx-dod-react-bindings-theme-hook:p1:inst-call-theme\n","/**\n * useApiQuery - Declarative data fetching hook\n *\n * Accepts an EndpointDescriptor from @gears-frontx/api and returns a Gears FrontX-owned\n * ApiQueryResult. AbortSignal for request cancellation is threaded automatically\n * through the shared QueryClient integration.\n *\n * Cache config cascade: component overrides > descriptor defaults > plugin defaults.\n * Omit overrides to rely on the descriptor's staleTime/gcTime, which in turn\n * fall back to the plugin-level query-cache defaults.\n */\n// @cpt-dod:cpt-frontx-dod-request-lifecycle-use-api-query:p2\n// @cpt-flow:cpt-frontx-flow-request-lifecycle-use-api-query:p2\n// @cpt-state:cpt-frontx-state-request-lifecycle-query:p2\n// @cpt-FEATURE:implement-endpoint-descriptors:p3\n\nimport type { EndpointDescriptor } from '@gears-frontx/framework';\nimport type { ApiQueryResult } from '../types';\nimport { useFrontXQuery } from '../queryClient';\n\n/** Per-call cache overrides. Cascade: these > descriptor > plugin defaults. */\nexport interface ApiQueryOverrides {\n /** Override staleTime for this specific call site. */\n staleTime?: number;\n /** Override gcTime for this specific call site. */\n gcTime?: number;\n}\n\n// @cpt-begin:cpt-frontx-flow-request-lifecycle-use-api-query:p2:inst-delegate-use-query\nexport function useApiQuery<TData = unknown, TError = Error>(\n descriptor: EndpointDescriptor<TData>,\n overrides?: ApiQueryOverrides\n): ApiQueryResult<TData, TError> {\n return useFrontXQuery(descriptor, overrides);\n}\n// @cpt-end:cpt-frontx-flow-request-lifecycle-use-api-query:p2:inst-delegate-use-query\n","/**\n * useApiSuspenseQuery - Suspense declarative data fetching hook\n *\n * Mirrors useApiQuery but integrates with React Suspense so the initial load is\n * handled by a Suspense boundary.\n */\n// @cpt-dod:cpt-frontx-dod-request-lifecycle-use-api-query:p2\n// @cpt-flow:cpt-frontx-flow-request-lifecycle-use-api-query:p2\n// @cpt-state:cpt-frontx-state-request-lifecycle-query:p2\n\nimport type { EndpointDescriptor } from '@gears-frontx/framework';\nimport type { ApiSuspenseQueryResult } from '../types';\nimport type { ApiQueryOverrides } from './useApiQuery';\nimport { useFrontXSuspenseQuery } from '../queryClient';\n\n// @cpt-begin:cpt-frontx-flow-request-lifecycle-use-api-query:p2:inst-delegate-use-suspense-query\nexport function useApiSuspenseQuery<TData = unknown, TError = Error>(\n descriptor: EndpointDescriptor<TData>,\n overrides?: ApiQueryOverrides\n): ApiSuspenseQueryResult<TData, TError> {\n return useFrontXSuspenseQuery<TData, TError>(descriptor, overrides);\n}\n// @cpt-end:cpt-frontx-flow-request-lifecycle-use-api-query:p2:inst-delegate-use-suspense-query\n","/**\n * useApiInfiniteQuery - Declarative paginated data fetching hook\n *\n * Accepts an initial EndpointDescriptor plus descriptor resolvers for adjacent\n * pages. Each page remains a standard service descriptor so MFE code does not\n * need raw TanStack query keys or query functions.\n */\n// @cpt-dod:cpt-frontx-dod-request-lifecycle-use-api-query:p2\n// @cpt-flow:cpt-frontx-flow-request-lifecycle-use-api-query:p2\n\nimport type { EndpointDescriptor } from '@gears-frontx/framework';\nimport type { ApiInfiniteQueryResult } from '../types';\nimport type { ApiQueryOverrides } from './useApiQuery';\nimport { useFrontXInfiniteQuery } from '../queryClient';\n\nexport interface ApiInfiniteQueryPageContext<TPage> {\n page: TPage;\n pages: readonly TPage[];\n descriptor: EndpointDescriptor<TPage>;\n descriptors: readonly EndpointDescriptor<TPage>[];\n}\n\nexport interface ApiInfiniteQueryOptions<TPage> extends ApiQueryOverrides {\n /** Descriptor for the first page in the sequence. */\n initialPage: EndpointDescriptor<TPage>;\n /**\n * Resolve the next page descriptor from the current page payload.\n * Return undefined when there is no next page.\n */\n getNextPage: (\n context: ApiInfiniteQueryPageContext<TPage>\n ) => EndpointDescriptor<TPage> | undefined;\n /**\n * Resolve the previous page descriptor from the current first page payload.\n * Return undefined when backward pagination is not available.\n */\n getPreviousPage?: (\n context: ApiInfiniteQueryPageContext<TPage>\n ) => EndpointDescriptor<TPage> | undefined;\n /** Optional TanStack maxPages passthrough for bounded page windows. */\n maxPages?: number;\n}\n\nexport function useApiInfiniteQuery<TPage = unknown, TError = Error>(\n options: ApiInfiniteQueryOptions<TPage>\n): ApiInfiniteQueryResult<TPage, TError> {\n return useFrontXInfiniteQuery<TPage, TError>(options);\n}\n","/**\n * useApiSuspenseInfiniteQuery - Suspense paginated data fetching hook\n *\n * Mirrors useApiInfiniteQuery but integrates with React Suspense so the initial\n * page load is handled by a Suspense boundary while pagination stays\n * descriptor-driven.\n */\n// @cpt-dod:cpt-frontx-dod-request-lifecycle-use-api-query:p2\n// @cpt-flow:cpt-frontx-flow-request-lifecycle-use-api-query:p2\n\nimport type { ApiSuspenseInfiniteQueryResult } from '../types';\nimport type {\n ApiInfiniteQueryOptions,\n} from './useApiInfiniteQuery';\nimport { useFrontXSuspenseInfiniteQuery } from '../queryClient';\n\nexport function useApiSuspenseInfiniteQuery<TPage = unknown, TError = Error>(\n options: ApiInfiniteQueryOptions<TPage>\n): ApiSuspenseInfiniteQueryResult<TPage, TError> {\n return useFrontXSuspenseInfiniteQuery<TPage, TError>(options);\n}\n","/**\n * useApiMutation - Declarative mutation hook with restricted QueryCache injection\n *\n * Accepts { endpoint: MutationDescriptor, callbacks } and returns a Gears FrontX-owned\n * ApiMutationResult. Supports optimistic updates, rollback, and cache invalidation\n * through the QueryCache interface injected into each callback.\n *\n * Optimistic update pattern:\n * onMutate -> cancel outgoing refetches, snapshot via queryCache.get,\n * apply optimistic data via queryCache.set, return snapshot\n * onError -> restore snapshot via queryCache.set(key, context.snapshot)\n * onSettled -> invalidate to refetch authoritative state\n *\n * TanStack Query is used internally only and is NOT re-exported.\n * MFEs interact with the cache through QueryCache, not the raw QueryClient.\n */\n// @cpt-dod:cpt-frontx-dod-request-lifecycle-use-api-mutation:p2\n// @cpt-flow:cpt-frontx-flow-request-lifecycle-use-api-mutation:p2\n// @cpt-algo:cpt-frontx-algo-request-lifecycle-optimistic-update:p2\n// @cpt-algo:cpt-frontx-algo-request-lifecycle-query-invalidation:p2\n// @cpt-state:cpt-frontx-state-request-lifecycle-mutation:p2\n// @cpt-FEATURE:implement-endpoint-descriptors:p3\n\nimport type { MutationDescriptor } from '@gears-frontx/framework';\nimport type { MutationCallbackContext } from './QueryCache';\nimport type { ApiMutationResult } from '../types';\nimport { useFrontXMutation, useRequiredFrontXQueryClient } from '../queryClient';\nimport { createQueryCache } from './QueryCache';\nimport { useMemo } from 'react';\n\nexport type { QueryCache, MutationCallbackContext } from './QueryCache';\n\n// @cpt-begin:cpt-frontx-dod-request-lifecycle-use-api-mutation:p2:inst-type-alias\n/**\n * Options for useApiMutation.\n *\n * Each callback receives { queryCache } as an additional final parameter,\n * providing controlled access to the shared cache without exposing the\n * raw QueryClient. TContext is the return type of onMutate, passed as\n * context to onSuccess, onError, and onSettled.\n */\nexport type UseApiMutationOptions<\n TData = unknown,\n TError = Error,\n TVariables = void,\n TContext = unknown,\n> = {\n endpoint: MutationDescriptor<TData, TVariables>;\n cancelOnSupersede?: boolean;\n abortOnUnmount?: boolean;\n onMutate?: (variables: TVariables, ctx: MutationCallbackContext) => Promise<TContext> | TContext;\n onSuccess?: (data: TData, variables: TVariables, context: TContext | undefined, ctx: MutationCallbackContext) => unknown;\n onError?: (error: TError, variables: TVariables, context: TContext | undefined, ctx: MutationCallbackContext) => unknown;\n onSettled?: (data: TData | undefined, error: TError | null, variables: TVariables, context: TContext | undefined, ctx: MutationCallbackContext) => unknown;\n};\n// @cpt-end:cpt-frontx-dod-request-lifecycle-use-api-mutation:p2:inst-type-alias\n\n// @cpt-begin:cpt-frontx-flow-request-lifecycle-use-api-mutation:p2:inst-delegate-use-mutation\nexport function useApiMutation<\n TData = unknown,\n TError = Error,\n TVariables = void,\n TContext = unknown,\n>(\n options: UseApiMutationOptions<TData, TError, TVariables, TContext>\n): ApiMutationResult<TData, TError, TVariables> {\n const queryClient = useRequiredFrontXQueryClient();\n const queryCache = useMemo(() => createQueryCache(queryClient), [queryClient]);\n const callbackCtx: MutationCallbackContext = useMemo(() => ({ queryCache }), [queryCache]);\n return useFrontXMutation<TData, TError, TVariables, TContext>(options, callbackCtx);\n}\n// @cpt-end:cpt-frontx-flow-request-lifecycle-use-api-mutation:p2:inst-delegate-use-mutation\n","/**\n * useApiStream - Declarative SSE streaming hook\n *\n * Accepts a StreamDescriptor from @gears-frontx/api and returns the latest\n * event, accumulated events, connection status, and a manual disconnect\n * function.\n *\n * @example\n * ```tsx\n * const { data, events, status, error } = useApiStream(\n * service.messageStream,\n * { mode: 'latest' } // default — data holds last event\n * );\n *\n * // Accumulate all events\n * const { events, status } = useApiStream(service.messageStream, { mode: 'accumulate' });\n * ```\n */\n\nimport { useEffect, useMemo, useRef, useState, useCallback } from 'react';\nimport type { StreamDescriptor, StreamStatus } from '@gears-frontx/framework';\nimport { useLatest } from './useLatest';\n\n/** Configuration options for useApiStream. */\nexport interface ApiStreamOptions {\n /**\n * `'latest'` (default) — `data` holds the most recent event.\n * `'accumulate'` — `events` holds all received events in order.\n */\n mode?: 'latest' | 'accumulate';\n /** When false the connection is deferred (no connect on mount). Default true. */\n enabled?: boolean;\n}\n\n/** Return type of useApiStream. */\nexport interface ApiStreamResult<TEvent> {\n /** Latest event payload, set in both modes — `undefined` until the first event and after each connect attempt resets it. */\n data: TEvent | undefined;\n /** All received events when `mode: 'accumulate'`; empty array in `'latest'` mode. */\n events: TEvent[];\n /** Connection lifecycle status. */\n status: StreamStatus;\n /** Last connect error — set when a connect attempt rejects, cleared when the next attempt starts. */\n error: Error | null;\n /** Manually close the connection. */\n disconnect: () => void;\n}\n\n/**\n * Manages the status lifecycle for a single SSE stream connection.\n *\n * **Status values**\n * - `'idle'` — no connection is being attempted. This is the status whenever\n * `enabled` is `false`, including on mount: a hook that mounts disabled\n * never reports anything but `'idle'` until `enabled` flips to `true`. A\n * hook that mounts enabled skips `'idle'` entirely — the status is set\n * during render, so its very first render already reports `'connecting'`.\n * Consumers must not assume `'idle'` means \"never\n * connected\" — a stream that is disabled after having connected returns to\n * `'idle'` too, and `data`/`events` from the earlier connection are not\n * cleared by that transition alone (they are cleared by mode/key changes,\n * see below).\n * - `'connecting'` — a connection attempt is committed to but has not settled.\n * It is published during the render that turns the stream on, which is\n * before `descriptor.connect()` runs: the call is made from an effect after\n * that render commits. So `'connecting'` means \"this stream is being\n * opened\", not \"the connect promise is pending\" — for one render the two\n * differ, and a consumer that reads the status as proof a request is already\n * in flight is reading it too strongly.\n * - `'connected'` — set both when `connect()` resolves (unless a disconnect\n * was requested while it was pending) and, independently, whenever the\n * `onEvent` callback delivers a new event. Because every event re-asserts\n * `'connected'`, this status also serves as \"still receiving events.\"\n * - `'disconnected'` — reached via any of: the descriptor's `onComplete`\n * callback firing (the stream ended normally), `connect()` rejecting while\n * a disconnect was requested concurrently, or the manual `disconnect()`\n * function being called. `disconnect()` has no `enabled` guard, but calling\n * it while the stream is disabled is not observable: the stored status moves\n * to `'disconnected'` while the published one stays `'idle'`, and flipping\n * `enabled` back to `true` sets `'connecting'` during that render, so the\n * stored `'disconnected'` is overwritten before it is ever returned.\n * - `'error'` — `connect()` rejected and no disconnect was requested while it\n * was pending. `error` holds the rejection, coerced to an `Error` if it\n * wasn't one already.\n *\n * **Transitions**\n * - Mounting enabled, `enabled` becoming `true`, or `descriptor.key` / `mode`\n * changing while `enabled` is `true`: `data`, `events`, and `error` are reset\n * and status is set to `'connecting'` synchronously during render (not from\n * an effect); `connect()` is then called from an effect that runs after that\n * render commits.\n * - `descriptor.key` or `mode` changing while `enabled` is `false`: `data`,\n * `events`, and `error` are reset all the same, since that reset is not gated\n * on `enabled`, but the status write is - so no `'connecting'` is written and\n * the published status stays `'idle'`; `connect()` is not called. The skipped\n * `'connecting'` is not owed later either: the change counts as handled when\n * it happens, so what publishes `'connecting'` is the subsequent flip of\n * `enabled` to `true`, once, for whichever key and mode are in force by then.\n * - `enabled` becomes `false` (or starts `false`): the published status is\n * `'idle'` for as long as `enabled` stays `false` — it is derived from\n * `enabled` rather than written, so nothing a prior connection stored can\n * surface through it — and `connect()` is never called; no other field is\n * reset by this transition alone.\n * - Unmount, `descriptor.key` change, `mode` change, or `enabled` flipping to\n * `false` while connected or connecting: the previous connection is torn\n * down via `descriptor.disconnect()` once its `connect()` promise settles\n * (or immediately skipped if it rejected). All four share the same cleanup\n * path: the effect's cleanup runs on every dependency change and on unmount.\n * - Calling `disconnect()`: if a connection id is already resolved, it is\n * disconnected immediately and status becomes `'disconnected'`. If\n * `connect()` is still pending, the request is recorded and honored when\n * the promise settles — the newly resolved connection is torn down instead\n * of being adopted, and status is `'disconnected'`. One caveat:\n * `disconnect()` does not cancel the event callback, so a buffered or\n * in-flight event landing after the call re-asserts `'connected'` — and in\n * the pending-connect case the settle handler tears the connection down\n * without touching status, so that stray `'connected'` persists.\n * - Stream completion while `connect()` is still pending: the current\n * implementation lets `onComplete` set `'disconnected'`, then the settle\n * handler adopts the connection id and re-asserts `'connected'` anyway.\n * This is known current behavior, not a durable guarantee: a pending\n * upstream derived-status rewrite is expected to remove this transition.\n *\n * `enabled` (default `true`) is the only way to defer connecting past mount;\n * flipping it back to `true` re-runs the same connect sequence as a fresh\n * mount would.\n */\nexport function useApiStream<TEvent>(\n descriptor: StreamDescriptor<TEvent>,\n options?: ApiStreamOptions,\n): ApiStreamResult<TEvent> {\n const mode = options?.mode ?? 'latest';\n const enabled = options?.enabled ?? true;\n\n const [data, setData] = useState<TEvent | undefined>(undefined);\n const [events, setEvents] = useState<TEvent[]>([]);\n // Lazy initializer mirrors what the \"connecting\" render-adjustment below would set on\n // a later (descriptorKey, mode, enabled) change — the adjustment's before/after\n // comparison can't itself detect \"this is the very first render\", since its own\n // `prevConnectKey` state is seeded from the same initial connectKey.\n const [status, setStatus] = useState<StreamStatus>(() => (enabled ? 'connecting' : 'idle'));\n const [error, setError] = useState<Error | null>(null);\n\n // Tracks the in-flight connect() promise so cleanup can await it.\n const connectPromiseRef = useRef<Promise<string> | null>(null);\n // Tracks the resolved connectionId for the manual disconnect() callback.\n const connectionIdRef = useRef<string | null>(null);\n /** When true, connect's promise resolution must tear down the new id instead of adopting it. */\n const disconnectRequestedRef = useRef(false);\n // Latest descriptor for connect/disconnect without tying effect or callbacks to object identity.\n const descriptorRef = useLatest(descriptor);\n\n // Stable identity derived from descriptor key — used as effect dependency.\n // JSON.stringify avoids join('/') collisions when a segment contains '/'.\n const descriptorKey = useMemo(() => JSON.stringify(descriptor.key), [descriptor.key]);\n\n // Resets stream state when the descriptor or mode changes, using the \"adjusting state\n // during render\" pattern (react.dev) instead of an effect: this clears stale data\n // before paint in the same render pass rather than committing once with old data and\n // scheduling a second render from an effect.\n const resetKey = `${descriptorKey}:${mode}`;\n const [prevResetKey, setPrevResetKey] = useState(resetKey);\n if (resetKey !== prevResetKey) {\n setPrevResetKey(resetKey);\n setData(undefined);\n setEvents([]);\n setError(null);\n }\n\n // Same pattern, scoped to when the connect effect below is about to (re)start a\n // connection: also flips `status` to 'connecting' up front, exactly once per\n // (descriptorKey, mode, enabled) combination — matching the effect's dependency list\n // — instead of the effect setting it synchronously on every run.\n const connectKey = `${resetKey}:${enabled}`;\n const [prevConnectKey, setPrevConnectKey] = useState(connectKey);\n if (connectKey !== prevConnectKey) {\n setPrevConnectKey(connectKey);\n if (enabled) {\n setData(undefined);\n setEvents([]);\n setStatus('connecting');\n setError(null);\n }\n }\n\n const disconnect = useCallback(() => {\n disconnectRequestedRef.current = true;\n if (connectionIdRef.current) {\n descriptorRef.current.disconnect(connectionIdRef.current);\n connectionIdRef.current = null;\n disconnectRequestedRef.current = false;\n }\n setStatus('disconnected');\n // descriptorRef's identity never changes (useLatest returns a stable ref\n // object) — listing it here satisfies exhaustive-deps without altering\n // when this callback is recreated.\n }, [descriptorRef]);\n\n useEffect(() => {\n // Disabled: no connection attempt. `status` is displayed as 'idle' via the\n // derived value below instead of writing it here — the stored `status` from a\n // prior connection is left untouched so a later re-enable has nothing stale to\n // clean up, and no synchronous setState is needed in this effect.\n if (!enabled) {\n return;\n }\n\n let cancelled = false;\n\n disconnectRequestedRef.current = false;\n\n const d = descriptorRef.current;\n // data/events/status/error were already reset to the 'connecting' state above,\n // during render, for this exact (descriptorKey, mode, enabled) combination.\n\n const connectPromise = d.connect(\n (event) => {\n if (cancelled) return;\n setData(event);\n setStatus('connected');\n if (mode === 'accumulate') {\n setEvents((prev) => [...prev, event]);\n }\n },\n () => {\n if (cancelled) return;\n setStatus('disconnected');\n connectionIdRef.current = null;\n },\n );\n\n connectPromiseRef.current = connectPromise;\n\n connectPromise\n .then((id) => {\n if (cancelled) return;\n if (disconnectRequestedRef.current) {\n d.disconnect(id);\n disconnectRequestedRef.current = false;\n return;\n }\n connectionIdRef.current = id;\n setStatus('connected');\n })\n .catch((err) => {\n if (cancelled) return;\n if (disconnectRequestedRef.current) {\n disconnectRequestedRef.current = false;\n setStatus('disconnected');\n return;\n }\n setError(err instanceof Error ? err : new Error(String(err)));\n setStatus('error');\n });\n\n return () => {\n cancelled = true;\n connectPromise.then(\n (id) => d.disconnect(id),\n () => { /* connect failed — nothing to disconnect */ },\n );\n connectPromiseRef.current = null;\n connectionIdRef.current = null;\n };\n // descriptorRef's identity never changes (useLatest returns a stable ref\n // object) — listing it here satisfies exhaustive-deps without causing\n // this effect to re-run on every render.\n }, [descriptorKey, enabled, mode, descriptorRef]);\n\n // Derived: while disabled the connection is deliberately not attempted, so the\n // publicly visible status is always 'idle' regardless of what a prior connection\n // left in `status` state.\n return { data, events, status: enabled ? status : 'idle', error, disconnect };\n}\n","import { useMemo } from 'react';\nimport { createQueryCache } from './QueryCache';\nimport { useOptionalFrontXQueryClient } from '../queryClient';\n\n/**\n * Exposes the sanctioned imperative cache API for app and MFE code without\n * leaking the raw QueryClient.\n *\n * Preferred usage:\n * - useApiQuery() for declarative reads\n * - useApiMutation() for writes\n * - useQueryCache() for controlled imperative cache inspection and invalidation\n */\nexport function useQueryCache() {\n const queryClient = useOptionalFrontXQueryClient();\n\n if (!queryClient) {\n throw new Error(\n '[FrontXProvider] No query cache available. Add queryCache() or queryCacheShared() to your plugin composition.'\n );\n }\n\n return useMemo(() => createQueryCache(queryClient), [queryClient]);\n}\n","/**\n * useMfeBridge Hook - MFE bridge access\n *\n * Returns the ChildMfeBridge from context for communication with host.\n *\n * React Layer: L3\n */\n// @cpt-flow:cpt-frontx-flow-react-bindings-mfe-provider:p1\n// @cpt-algo:cpt-frontx-algo-react-bindings-mfe-context-guard:p1\n// @cpt-dod:cpt-frontx-dod-react-bindings-mfe-hooks:p1\n\nimport { useMfeContext } from '../MfeContext';\nimport type { ChildMfeBridge } from '@gears-frontx/framework';\n\n// ============================================================================\n// Hook Implementation\n// ============================================================================\n\n/**\n * Hook for accessing the MFE bridge.\n *\n * Returns the ChildMfeBridge instance for communication with the host.\n * Must be used within a MfeProvider (i.e., inside an MFE component).\n *\n * @returns Child MFE bridge\n *\n * @example\n * ```tsx\n * function MyMfeComponent() {\n * const bridge = useMfeBridge();\n *\n * // Bridge methods:\n * // bridge.executeActionsChain(chain);\n * // bridge.subscribeToProperty(propertyTypeId, callback);\n *\n * return <div>Domain: {bridge.extDomainId}</div>;\n * }\n * ```\n */\n// @cpt-begin:cpt-frontx-flow-react-bindings-mfe-provider:p1:inst-use-bridge\n// @cpt-begin:cpt-frontx-algo-react-bindings-mfe-context-guard:p1:inst-throw-no-mfe-context\n// @cpt-begin:cpt-frontx-dod-react-bindings-mfe-hooks:p1:inst-use-bridge\nexport function useMfeBridge(): ChildMfeBridge {\n const { bridge } = useMfeContext();\n return bridge;\n}\n// @cpt-end:cpt-frontx-flow-react-bindings-mfe-provider:p1:inst-use-bridge\n// @cpt-end:cpt-frontx-algo-react-bindings-mfe-context-guard:p1:inst-throw-no-mfe-context\n// @cpt-end:cpt-frontx-dod-react-bindings-mfe-hooks:p1:inst-use-bridge\n","/**\n * useSharedProperty Hook - Shared property subscription\n *\n * Subscribes to shared property updates from the host.\n *\n * React Layer: L3\n */\n// @cpt-flow:cpt-frontx-flow-react-bindings-use-shared-property:p1\n// @cpt-algo:cpt-frontx-algo-react-bindings-mfe-context-guard:p1\n// @cpt-dod:cpt-frontx-dod-react-bindings-mfe-hooks:p1\n\nimport { useSyncExternalStore, useCallback } from 'react';\nimport { useMfeContext } from '../MfeContext';\n\n// ============================================================================\n// Hook Implementation\n// ============================================================================\n\n/**\n * Hook for subscribing to a shared property.\n *\n * Subscribes to property updates from the host and returns the current value.\n * Must be used within a MfeProvider (i.e., inside an MFE component).\n *\n * NOTE: This hook provides the interface and uses useSyncExternalStore with a stub subscription.\n * Full bridge subscription should be implemented when bridge methods are available.\n *\n * @param _propertyTypeId - Type ID of the shared property to subscribe to (currently unused)\n * @returns Current property value\n *\n * @example\n * ```tsx\n * function MyMfeComponent() {\n * const userData = useSharedProperty('gts.frontx.mfes.comm.shared_property.v1~myapp.user_data.v1');\n *\n * return <div>User: {userData?.name}</div>;\n * }\n * ```\n */\n// @cpt-begin:cpt-frontx-flow-react-bindings-use-shared-property:p1:inst-call-shared-property\n// @cpt-begin:cpt-frontx-dod-react-bindings-mfe-hooks:p1:inst-call-shared-property\nexport function useSharedProperty<T = unknown>(propertyTypeId: string): T | undefined {\n // @cpt-begin:cpt-frontx-flow-react-bindings-use-shared-property:p1:inst-read-bridge\n // @cpt-begin:cpt-frontx-algo-react-bindings-mfe-context-guard:p1:inst-throw-no-mfe-context\n // Enforce MfeProvider context requirement\n const { bridge } = useMfeContext(); // Throws if not in MfeProvider\n // @cpt-end:cpt-frontx-flow-react-bindings-use-shared-property:p1:inst-read-bridge\n // @cpt-end:cpt-frontx-algo-react-bindings-mfe-context-guard:p1:inst-throw-no-mfe-context\n\n // @cpt-begin:cpt-frontx-flow-react-bindings-use-shared-property:p1:inst-subscribe-property\n // @cpt-begin:cpt-frontx-flow-react-bindings-use-shared-property:p1:inst-rerender-on-property-change\n // Subscribe to property updates via bridge\n const subscribe = useCallback((callback: () => void) => {\n return bridge.subscribeToProperty(propertyTypeId, () => {\n // When property changes, trigger React re-render\n callback();\n });\n }, [bridge, propertyTypeId]);\n // @cpt-end:cpt-frontx-flow-react-bindings-use-shared-property:p1:inst-subscribe-property\n // @cpt-end:cpt-frontx-flow-react-bindings-use-shared-property:p1:inst-rerender-on-property-change\n\n // @cpt-begin:cpt-frontx-flow-react-bindings-use-shared-property:p1:inst-return-property-value\n const getSnapshot = useCallback(() => {\n const property = bridge.getProperty(propertyTypeId);\n // Type narrowing: caller specifies expected type T (standard React hook pattern)\n // Similar to useState<T>, useContext<T> - type safety is caller's responsibility\n return property?.value as T | undefined;\n }, [bridge, propertyTypeId]);\n\n const value = useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n\n return value;\n // @cpt-end:cpt-frontx-flow-react-bindings-use-shared-property:p1:inst-return-property-value\n}\n// @cpt-end:cpt-frontx-flow-react-bindings-use-shared-property:p1:inst-call-shared-property\n// @cpt-end:cpt-frontx-dod-react-bindings-mfe-hooks:p1:inst-call-shared-property\n","/**\n * useHostAction Hook - Host action requests\n *\n * Returns a callback to request host actions via the bridge.\n *\n * React Layer: L3\n */\n// @cpt-flow:cpt-frontx-flow-react-bindings-use-host-action:p1\n// @cpt-algo:cpt-frontx-algo-react-bindings-mfe-context-guard:p1\n// @cpt-dod:cpt-frontx-dod-react-bindings-mfe-hooks:p1\n\nimport { useCallback } from 'react';\nimport { useMfeContext } from '../MfeContext';\n\n// ============================================================================\n// Hook Implementation\n// ============================================================================\n\n/**\n * Hook for requesting host actions.\n *\n * Returns a callback function that sends an actions chain to the host.\n * Must be used within a MfeProvider (i.e., inside an MFE component).\n *\n * NOTE: This hook provides the interface. Bridge executeActionsChain() delegates to the registry.\n *\n * @param actionTypeId - Type ID of the action to request\n * @returns Callback function to request the action with payload\n *\n * @example\n * ```tsx\n * function MyMfeComponent() {\n * const requestNavigation = useHostAction('gts.frontx.mfes.comm.action.v1~myapp.navigate.v1');\n *\n * const handleClick = () => {\n * requestNavigation({ path: '/dashboard' });\n * };\n *\n * return <button onClick={handleClick}>Navigate</button>;\n * }\n * ```\n */\n// @cpt-begin:cpt-frontx-flow-react-bindings-use-host-action:p1:inst-call-host-action\n// @cpt-begin:cpt-frontx-dod-react-bindings-mfe-hooks:p1:inst-call-host-action\nexport function useHostAction<TPayload extends Record<string, unknown> = Record<string, unknown>>(\n actionTypeId: string\n): (payload?: TPayload) => void {\n // @cpt-begin:cpt-frontx-flow-react-bindings-use-host-action:p1:inst-read-bridge-for-action\n // @cpt-begin:cpt-frontx-algo-react-bindings-mfe-context-guard:p1:inst-throw-no-mfe-context\n // Enforce MfeProvider context requirement\n const { bridge } = useMfeContext(); // Throws if not in MfeProvider\n // @cpt-end:cpt-frontx-flow-react-bindings-use-host-action:p1:inst-read-bridge-for-action\n // @cpt-end:cpt-frontx-algo-react-bindings-mfe-context-guard:p1:inst-throw-no-mfe-context\n\n // @cpt-begin:cpt-frontx-flow-react-bindings-use-host-action:p1:inst-return-action-callback\n return useCallback((payload?: TPayload) => {\n // Construct an ActionsChain with the action\n // With the constraint, TPayload extends Record<string, unknown>,\n // so this is a safe widening from specific to general\n const chain = {\n action: {\n type: actionTypeId,\n target: bridge.extDomainId,\n payload: payload as Record<string, unknown> | undefined,\n },\n };\n\n // @cpt-begin:cpt-frontx-flow-react-bindings-use-host-action:p1:inst-log-action-error\n // Send the chain to the host\n bridge.executeActionsChain(chain).catch((error: Error) => {\n console.error(\n `[useHostAction] Failed to send action '${actionTypeId}':`,\n error\n );\n });\n // @cpt-end:cpt-frontx-flow-react-bindings-use-host-action:p1:inst-log-action-error\n }, [actionTypeId, bridge]);\n // @cpt-end:cpt-frontx-flow-react-bindings-use-host-action:p1:inst-return-action-callback\n}\n// @cpt-end:cpt-frontx-flow-react-bindings-use-host-action:p1:inst-call-host-action\n// @cpt-end:cpt-frontx-dod-react-bindings-mfe-hooks:p1:inst-call-host-action\n","/**\n * useDomainExtensions Hook - Domain extension list subscription\n *\n * Subscribes to store changes to detect when extensions are registered or unregistered,\n * and returns the current list of extensions for a domain.\n *\n * React Layer: L3\n */\n// @cpt-flow:cpt-frontx-flow-react-bindings-use-domain-extensions:p1\n// @cpt-algo:cpt-frontx-algo-react-bindings-mfe-context-guard:p1\n// @cpt-algo:cpt-frontx-algo-react-bindings-stable-snapshots:p1\n// @cpt-dod:cpt-frontx-dod-react-bindings-observation-hooks:p1\n\nimport { useSyncExternalStore, useCallback, useRef } from 'react';\nimport { useFrontX } from '../../FrontXContext';\nimport type { Extension } from '@gears-frontx/framework';\n\n// ============================================================================\n// Hook Implementation\n// ============================================================================\n\n/**\n * Hook for observing extensions registered for a domain.\n *\n * Subscribes to the FrontX store to detect registration state changes,\n * and returns the current list of extensions for the specified domain.\n *\n * @param domainId - Domain ID to query extensions for\n * @returns Array of extensions currently registered for the domain\n *\n * @example\n * ```tsx\n * function SidebarExtensions() {\n * const extensions = useDomainExtensions('gts.frontx.mfes.ext.domain.v1~frontx.screensets.layout.sidebar.v1');\n *\n * return (\n * <div>\n * {extensions.map(ext => (\n * <div key={ext.id}>{ext.id}</div>\n * ))}\n * </div>\n * );\n * }\n * ```\n */\n// @cpt-begin:cpt-frontx-flow-react-bindings-use-domain-extensions:p1:inst-call-domain-extensions\n// @cpt-begin:cpt-frontx-dod-react-bindings-observation-hooks:p1:inst-call-domain-extensions\nexport function useDomainExtensions(domainId: string): Extension[] {\n const app = useFrontX();\n const registry = app.mfeRegistry;\n\n // @cpt-begin:cpt-frontx-flow-react-bindings-use-domain-extensions:p1:inst-guard-registry\n // @cpt-begin:cpt-frontx-algo-react-bindings-mfe-context-guard:p1:inst-throw-no-registry\n if (!registry) {\n throw new Error(\n 'useDomainExtensions requires the microfrontends plugin. ' +\n 'Add microfrontends() to your Gears FrontX app configuration.'\n );\n }\n // @cpt-end:cpt-frontx-flow-react-bindings-use-domain-extensions:p1:inst-guard-registry\n // @cpt-end:cpt-frontx-algo-react-bindings-mfe-context-guard:p1:inst-throw-no-registry\n\n // @cpt-begin:cpt-frontx-flow-react-bindings-use-domain-extensions:p1:inst-subscribe-store\n // Subscribe to store changes.\n // Any dispatch (including registration state updates) triggers a snapshot check.\n // The snapshot comparison ensures only actual extension list changes cause re-renders.\n const subscribe = useCallback(\n (onStoreChange: () => void) => {\n return app.store.subscribe(onStoreChange);\n },\n [app.store]\n );\n // @cpt-end:cpt-frontx-flow-react-bindings-use-domain-extensions:p1:inst-subscribe-store\n\n // @cpt-begin:cpt-frontx-algo-react-bindings-stable-snapshots:p1:inst-cache-ref\n // Cache the snapshot to maintain referential stability for useSyncExternalStore.\n // Only update when the extension IDs actually change.\n const cacheRef = useRef<{ ids: string; extensions: Extension[] }>({ ids: '', extensions: [] });\n // @cpt-end:cpt-frontx-algo-react-bindings-stable-snapshots:p1:inst-cache-ref\n\n // @cpt-begin:cpt-frontx-flow-react-bindings-use-domain-extensions:p1:inst-diff-extensions\n // @cpt-begin:cpt-frontx-flow-react-bindings-use-domain-extensions:p1:inst-stable-reference\n const getSnapshot = useCallback(() => {\n const extensions = registry.getExtensionsForDomain(domainId);\n // @cpt-begin:cpt-frontx-algo-react-bindings-stable-snapshots:p1:inst-compute-cache-key\n const ids = extensions.map(e => e.id).join(',');\n // @cpt-end:cpt-frontx-algo-react-bindings-stable-snapshots:p1:inst-compute-cache-key\n // @cpt-begin:cpt-frontx-algo-react-bindings-stable-snapshots:p1:inst-return-cached\n // @cpt-begin:cpt-frontx-algo-react-bindings-stable-snapshots:p1:inst-update-cache\n if (ids !== cacheRef.current.ids) {\n cacheRef.current = { ids, extensions };\n }\n return cacheRef.current.extensions;\n // @cpt-end:cpt-frontx-algo-react-bindings-stable-snapshots:p1:inst-return-cached\n // @cpt-end:cpt-frontx-algo-react-bindings-stable-snapshots:p1:inst-update-cache\n }, [registry, domainId]);\n // @cpt-end:cpt-frontx-flow-react-bindings-use-domain-extensions:p1:inst-diff-extensions\n // @cpt-end:cpt-frontx-flow-react-bindings-use-domain-extensions:p1:inst-stable-reference\n\n return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n}\n// @cpt-end:cpt-frontx-flow-react-bindings-use-domain-extensions:p1:inst-call-domain-extensions\n// @cpt-end:cpt-frontx-dod-react-bindings-observation-hooks:p1:inst-call-domain-extensions\n","/**\n * useMountedExtensions Hook - Mounted extension observation for any domain\n *\n * Domain-agnostic hook that returns the currently-mounted Extension instances\n * for any registered domain, including multi-mount domains backed by\n * ConcurrentMountStrategy.\n *\n * React Layer: L3\n */\n// @cpt-flow:cpt-frontx-flow-react-bindings-use-mounted-extensions:p1\n// @cpt-algo:cpt-frontx-algo-react-bindings-mfe-context-guard:p1\n// @cpt-algo:cpt-frontx-algo-react-bindings-stable-snapshots:p1\n// @cpt-dod:cpt-frontx-dod-react-bindings-observation-hooks:p1\n\nimport { useSyncExternalStore, useCallback, useRef } from 'react';\nimport { useFrontX } from '../../FrontXContext';\nimport type { Extension } from '@gears-frontx/framework';\n\n// ============================================================================\n// Hook Implementation\n// ============================================================================\n\n/**\n * Hook for observing the currently-mounted extensions in any domain.\n *\n * Subscribes to the FrontX store to detect mount state changes, and returns\n * the array of Extension instances currently mounted in the specified domain.\n *\n * Pairs with getMountedExtensions(domainId) on the registry and resolves each\n * mounted extension ID to its Extension instance. IDs that have been unregistered\n * concurrently (race against unregister) are filtered out.\n *\n * Returns a referentially stable array when the underlying ID list is unchanged.\n *\n * For multi-mount domains (ConcurrentMountStrategy), may return more than one entry.\n * For single-mount domains (ExclusiveMountStrategy), the returned array has at most one entry.\n *\n * @param domainId - Domain ID to query mounted extensions for\n * @returns Array of Extension instances currently mounted in the domain\n *\n * @example\n * ```tsx\n * function MountedWidgets() {\n * const mounted = useMountedExtensions('gts.frontx.mfes.ext.domain.v1~frontx.screensets.layout.sidebar.v1');\n *\n * return (\n * <ul>\n * {mounted.map(ext => (\n * <li key={ext.id}>{ext.id}</li>\n * ))}\n * </ul>\n * );\n * }\n * ```\n */\n// @cpt-begin:cpt-frontx-flow-react-bindings-use-mounted-extensions:p1:inst-call-mounted-extensions\n// @cpt-begin:cpt-frontx-dod-react-bindings-observation-hooks:p1:inst-call-mounted-extensions\nexport function useMountedExtensions(domainId: string): Extension[] {\n const app = useFrontX();\n const registry = app.mfeRegistry;\n\n // @cpt-begin:cpt-frontx-flow-react-bindings-use-mounted-extensions:p1:inst-guard-registry-mounted\n // @cpt-begin:cpt-frontx-algo-react-bindings-mfe-context-guard:p1:inst-throw-no-registry\n if (!registry) {\n throw new Error(\n 'useMountedExtensions requires the microfrontends plugin. ' +\n 'Add microfrontends() to your Gears FrontX app configuration.'\n );\n }\n // @cpt-end:cpt-frontx-flow-react-bindings-use-mounted-extensions:p1:inst-guard-registry-mounted\n // @cpt-end:cpt-frontx-algo-react-bindings-mfe-context-guard:p1:inst-throw-no-registry\n\n // @cpt-begin:cpt-frontx-flow-react-bindings-use-mounted-extensions:p1:inst-subscribe-store-mounted\n // Subscribe to store changes. Any dispatch (including mount state updates) triggers\n // a snapshot check. The cache key comparison ensures only actual mount-set changes\n // cause re-renders.\n const subscribe = useCallback(\n (onStoreChange: () => void) => {\n return app.store.subscribe(onStoreChange);\n },\n [app.store]\n );\n // @cpt-end:cpt-frontx-flow-react-bindings-use-mounted-extensions:p1:inst-subscribe-store-mounted\n\n // @cpt-begin:cpt-frontx-algo-react-bindings-stable-snapshots:p1:inst-cache-ref\n // Cache the snapshot to maintain referential stability for useSyncExternalStore.\n // Only update when the mounted ID list actually changes.\n const cacheRef = useRef<{ key: string; extensions: Extension[] }>({ key: '', extensions: [] });\n // @cpt-end:cpt-frontx-algo-react-bindings-stable-snapshots:p1:inst-cache-ref\n\n const getSnapshot = useCallback(() => {\n // @cpt-begin:cpt-frontx-flow-react-bindings-use-mounted-extensions:p1:inst-use-mounted-extensions-snapshot\n const ids = registry.getMountedExtensions(domainId);\n const resolved = ids\n .map(id => registry.getExtension(id))\n .filter((ext): ext is Extension => ext !== undefined);\n // @cpt-end:cpt-frontx-flow-react-bindings-use-mounted-extensions:p1:inst-use-mounted-extensions-snapshot\n\n // @cpt-begin:cpt-frontx-flow-react-bindings-use-mounted-extensions:p1:inst-mounted-extensions-stable-ref\n // @cpt-begin:cpt-frontx-algo-react-bindings-stable-snapshots:p1:inst-compute-cache-key\n const key = ids.join(',');\n // @cpt-end:cpt-frontx-algo-react-bindings-stable-snapshots:p1:inst-compute-cache-key\n\n // @cpt-begin:cpt-frontx-algo-react-bindings-stable-snapshots:p1:inst-return-cached\n // @cpt-begin:cpt-frontx-algo-react-bindings-stable-snapshots:p1:inst-update-cache\n if (key !== cacheRef.current.key) {\n cacheRef.current = { key, extensions: resolved };\n }\n return cacheRef.current.extensions;\n // @cpt-end:cpt-frontx-algo-react-bindings-stable-snapshots:p1:inst-return-cached\n // @cpt-end:cpt-frontx-algo-react-bindings-stable-snapshots:p1:inst-update-cache\n // @cpt-end:cpt-frontx-flow-react-bindings-use-mounted-extensions:p1:inst-mounted-extensions-stable-ref\n }, [registry, domainId]);\n\n return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n}\n// @cpt-end:cpt-frontx-flow-react-bindings-use-mounted-extensions:p1:inst-call-mounted-extensions\n// @cpt-end:cpt-frontx-dod-react-bindings-observation-hooks:p1:inst-call-mounted-extensions\n","/**\n * useRegisteredPackages Hook - Registered GTS packages subscription\n *\n * Subscribes to store changes to detect when extensions are registered or unregistered,\n * and returns the current list of registered GTS packages.\n *\n * React Layer: L3\n */\n// @cpt-flow:cpt-frontx-flow-react-bindings-use-registered-packages:p1\n// @cpt-algo:cpt-frontx-algo-react-bindings-mfe-context-guard:p1\n// @cpt-algo:cpt-frontx-algo-react-bindings-stable-snapshots:p1\n// @cpt-dod:cpt-frontx-dod-react-bindings-observation-hooks:p1\n\nimport { useSyncExternalStore, useCallback, useRef } from 'react';\nimport { useFrontX } from '../../FrontXContext';\n\n// ============================================================================\n// Hook Implementation\n// ============================================================================\n\n/**\n * Hook for observing registered GTS packages.\n *\n * Subscribes to the FrontX store to detect registration state changes,\n * and returns the current list of GTS packages extracted from registered\n * extensions.\n *\n * ARCHITECTURAL NOTE ON STORE SUBSCRIPTION COUPLING:\n * This hook uses `useSyncExternalStore` with `app.store.subscribe`, which\n * fires on any Redux dispatch. Since `registerExtension()` dispatches to\n * the mfe store slice, the subscription WILL trigger when packages change.\n * The `getSnapshot` function calls `mfeRegistry.getRegisteredPackages()`\n * which reads the private `packages` Map. This works because every package\n * map mutation (in registerExtension/unregisterExtension) is always\n * accompanied by a store dispatch in the same serializer callback.\n *\n * IMPORTANT: If a future change mutates the packages map WITHOUT a store\n * dispatch, this hook would fail to re-render. Keep this coupling documented.\n *\n * @returns Array of GTS package strings currently registered\n *\n * @example\n * ```tsx\n * function PackageList() {\n * const packages = useRegisteredPackages();\n *\n * return (\n * <div>\n * {packages.map(pkg => (\n * <div key={pkg}>{pkg}</div>\n * ))}\n * </div>\n * );\n * }\n * ```\n */\n// @cpt-begin:cpt-frontx-flow-react-bindings-use-registered-packages:p1:inst-call-registered-packages\n// @cpt-begin:cpt-frontx-dod-react-bindings-observation-hooks:p1:inst-call-registered-packages\nexport function useRegisteredPackages(): string[] {\n const app = useFrontX();\n const registry = app.mfeRegistry;\n\n // @cpt-begin:cpt-frontx-flow-react-bindings-use-registered-packages:p1:inst-guard-registry-packages\n // @cpt-begin:cpt-frontx-algo-react-bindings-mfe-context-guard:p1:inst-throw-no-registry\n if (!registry) {\n throw new Error(\n 'useRegisteredPackages requires the microfrontends plugin. ' +\n 'Add microfrontends() to your Gears FrontX app configuration.'\n );\n }\n // @cpt-end:cpt-frontx-flow-react-bindings-use-registered-packages:p1:inst-guard-registry-packages\n // @cpt-end:cpt-frontx-algo-react-bindings-mfe-context-guard:p1:inst-throw-no-registry\n\n // @cpt-begin:cpt-frontx-flow-react-bindings-use-registered-packages:p1:inst-subscribe-store-packages\n // Subscribe to store changes.\n // Any dispatch (including registration state updates) triggers a snapshot check.\n // The snapshot comparison ensures only actual package list changes cause re-renders.\n const subscribe = useCallback(\n (onStoreChange: () => void) => {\n return app.store.subscribe(onStoreChange);\n },\n [app.store]\n );\n // @cpt-end:cpt-frontx-flow-react-bindings-use-registered-packages:p1:inst-subscribe-store-packages\n\n // @cpt-begin:cpt-frontx-algo-react-bindings-stable-snapshots:p1:inst-cache-ref\n // Cache the snapshot to maintain referential stability for useSyncExternalStore.\n // Only update when the package list actually changes.\n const cacheRef = useRef<{ packages: string; list: string[] }>({ packages: '', list: [] });\n // @cpt-end:cpt-frontx-algo-react-bindings-stable-snapshots:p1:inst-cache-ref\n\n // @cpt-begin:cpt-frontx-flow-react-bindings-use-registered-packages:p1:inst-diff-packages\n const getSnapshot = useCallback(() => {\n const list = registry.getRegisteredPackages();\n // @cpt-begin:cpt-frontx-algo-react-bindings-stable-snapshots:p1:inst-compute-cache-key\n const packages = list.join(',');\n // @cpt-end:cpt-frontx-algo-react-bindings-stable-snapshots:p1:inst-compute-cache-key\n // @cpt-begin:cpt-frontx-algo-react-bindings-stable-snapshots:p1:inst-return-cached\n // @cpt-begin:cpt-frontx-algo-react-bindings-stable-snapshots:p1:inst-update-cache\n if (packages !== cacheRef.current.packages) {\n cacheRef.current = { packages, list };\n }\n return cacheRef.current.list;\n // @cpt-end:cpt-frontx-algo-react-bindings-stable-snapshots:p1:inst-return-cached\n // @cpt-end:cpt-frontx-algo-react-bindings-stable-snapshots:p1:inst-update-cache\n }, [registry]);\n // @cpt-end:cpt-frontx-flow-react-bindings-use-registered-packages:p1:inst-diff-packages\n\n return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n}\n// @cpt-end:cpt-frontx-flow-react-bindings-use-registered-packages:p1:inst-call-registered-packages\n// @cpt-end:cpt-frontx-dod-react-bindings-observation-hooks:p1:inst-call-registered-packages\n","import React from 'react';\nimport { createRoot, type Root } from 'react-dom/client';\nimport type {\n FrontXApp,\n MfeEntryLifecycle,\n ChildMfeBridge,\n MfeMountContext,\n} from '@gears-frontx/framework';\nimport { FrontXProvider } from '../FrontXProvider';\nimport { hasFrontXQueryClientActivator, resolveFrontXQueryClient } from '../queryClient';\n\n/**\n * Marks every node `adoptHostStylesIntoShadowRoot` puts into a shadow root, so\n * a later mount can find its own previous block and replace it.\n *\n * A marker attribute rather than the single `id` that\n * `injectStylesheet`/`injectCssVariables` key on in `@gears-frontx/mfes`'\n * shadow utilities, because the adopted block is many nodes whose order\n * relative to each other is load-bearing: one id can only name one of them.\n */\nconst ADOPTED_HOST_STYLE_ATTR = 'data-frontx-adopted-host-style';\n\n/** Identity of the base-resets node, so a remount reuses it instead of adding a second. */\nconst BASE_RESETS_STYLE_ID = '__frontx-base-resets__';\n\n/**\n * Ids of the style nodes `@gears-frontx/mfes` puts in a shadow root itself -\n * the isolation block from `createShadowRoot` and the theme variables from\n * `injectCssVariables`. Together with the adopted block they are the\n * shell-owned head of the shadow root, and the base resets belong at its end:\n * after them, ahead of the MFE's own CSS.\n *\n * Mirrored here rather than imported because those utilities keep the ids as\n * local constants. The values are what the shell puts in the shadow root, so\n * they change only when the shell changes them - and the remount test pins\n * this list against the ids those utilities actually emit.\n */\nconst SHELL_OWNED_SHADOW_STYLE_IDS = ['__frontx-shadow-isolation__', '__frontx-css-variables__'];\n\ninterface ProviderMountOptions {\n mfeBridge?: {\n bridge: ChildMfeBridge;\n extensionId: string;\n domainId: string;\n };\n}\n\nfunction resolveProviderMountOptions(\n app: FrontXApp,\n bridge: ChildMfeBridge,\n mountContext?: MfeMountContext\n): ProviderMountOptions {\n const extensionId = mountContext?.extensionId;\n const domainId = mountContext?.domainId;\n const isMountedMfe = typeof extensionId === 'string' && typeof domainId === 'string';\n\n if (\n isMountedMfe &&\n !resolveFrontXQueryClient(app) &&\n !hasFrontXQueryClientActivator(app)\n ) {\n throw new Error(\n '[FrontXProvider] Mounted MFEs require queryCacheShared() in the child app and queryCache() in the host app before loading the MFE app.'\n );\n }\n\n return {\n mfeBridge:\n isMountedMfe\n ? { bridge, extensionId, domainId }\n : undefined,\n };\n}\n\ninterface MountRuntimeAwareProviderProps {\n readonly app: FrontXApp;\n readonly mfeBridge?: Readonly<{\n readonly bridge: ChildMfeBridge;\n readonly extensionId: string;\n readonly domainId: string;\n }>;\n readonly children: React.ReactNode;\n}\n\nfunction MountRuntimeAwareProvider({\n app,\n mfeBridge,\n children,\n}: Readonly<MountRuntimeAwareProviderProps>): React.JSX.Element {\n return (\n <FrontXProvider app={app} mfeBridge={mfeBridge}>\n {children}\n </FrontXProvider>\n );\n}\n\n/**\n * Abstract base class for React-based MFE lifecycle implementations.\n *\n * Styling strategy:\n * 1. adoptHostStylesIntoShadowRoot() clones all host <style> and <link> into the\n * front of the shadow root, bringing the full compiled Tailwind CSS (including\n * MFE utilities, since the host's content paths cover src-app/mfe_packages/**) and\n * the ui-kit component CSS (the host entry side-effect-imports\n * @gears-frontx/ui-kit so that CSS exists in the host document; the kit's\n * CSS-module class names are stable per kit version, so they match the\n * classes MFE bundles reference only while host and MFE install the same\n * kit version - the template-pin-drift policy check is what guarantees\n * that; a drifted MFE renders its kit components unstyled with no error).\n * Front, not back, so the MFE's own stylesheets\n * outrank them - see the method. Design tokens must therefore be full CSS\n * colors - both Tailwind utilities (var(--x)) and ui-kit component CSS\n * consume them directly.\n * 2. injectBaseResets() adds box-model resets and :host defaults that aren't part\n * of Tailwind's compiled output but are needed for consistent rendering, and\n * positions them at the end of the shell-owned head - after the adopted block\n * and the isolation style, ahead of the MFE's own CSS.\n * 3. Subclasses may override initializeStyles() to inject additional CSS that is\n * not covered by the host stylesheet (e.g., MFE-specific @font-face rules).\n *\n * Every mount therefore leaves the same sequence - adopted host block, shadow\n * isolation, base resets, then the MFE's stylesheets - so the shell's CSS is\n * context and the MFE wins every specificity tie against all three shell blocks.\n * Steps 1 and 2 both position what they own rather than appending beside it,\n * because a remounted container arrives with its shadow root intact and the MFE's\n * own stylesheet removed and re-appended around the remount - see each method.\n *\n * Theme CSS variables are delivered via CSS inheritance from :root (Shadow DOM)\n * or via MountManager injection (iframe). MFE lifecycles do NOT need to subscribe\n * to theme changes or call applyThemeToShadowRoot.\n *\n * Concrete subclasses must provide:\n * - `renderContent(bridge)` - screen component rendering\n */\nexport abstract class ThemeAwareReactLifecycle implements MfeEntryLifecycle<ChildMfeBridge> {\n private root: Root | null = null;\n\n constructor(private readonly app: FrontXApp) { }\n\n mount(container: Element | ShadowRoot, bridge: ChildMfeBridge, mountContext?: MfeMountContext): void {\n if (container instanceof ShadowRoot) {\n this.adoptHostStylesIntoShadowRoot(container);\n }\n\n this.injectBaseResets(container);\n this.initializeStyles(container);\n\n const providerMountOptions = resolveProviderMountOptions(this.app, bridge, mountContext);\n this.root = createRoot(container);\n this.root.render(\n <MountRuntimeAwareProvider\n app={this.app}\n mfeBridge={providerMountOptions.mfeBridge}\n >\n {this.renderContent(bridge)}\n </MountRuntimeAwareProvider>\n );\n }\n\n unmount(_container: Element | ShadowRoot): void {\n if (this.root) {\n this.root.unmount();\n this.root = null;\n }\n }\n\n /**\n * Copy all inline <style> and <link rel=\"stylesheet\"> from the host document\n * into the shadow root so that Tailwind and component styles apply inside the MFE.\n *\n * The clones are inserted ahead of everything already in the shadow root, never\n * appended, because adopted host styles are context rather than authority: where\n * they and the MFE's own CSS declare the same property at equal specificity, the\n * MFE has to win. Appending inverted that. `MfeHandlerMF` injects the MFE's\n * compiled stylesheet into the shadow root before it calls mount, so an appended\n * clone of the shell's Tailwind preflight - whose\n * `button, [type='button'], [type='reset'], [type='submit']` rule sets\n * `background-color: transparent` at specificity (0,1,0) - tied with\n * `@gears-frontx/ui-kit`'s single-class button rule and won on document order,\n * leaving every kit Button transparent until it was hovered.\n *\n * Inserting at the front rather than pushing MFE styles to the back is what makes\n * the invariant hold for stylesheets that appear after mount too - a lazily\n * imported component's CSS module, or whatever initializeStyles() adds - since\n * those land behind the adopted block by construction.\n *\n * A cascade layer around the adopted CSS was the alternative and is rejected:\n * layered rules lose to unlayered ones at *any* specificity, so a host utility\n * class would stop overriding an MFE element selector. Document order keeps\n * specificity in charge and only settles the ties.\n *\n * The block replaces its predecessor instead of stacking on it, the same\n * upsert shape `injectStylesheet` and `injectCssVariables` use in\n * `@gears-frontx/mfes`' shadow utilities, widened from one id-keyed node to a\n * marked block. Replacement is required rather than tidy: `createShadowRoot`\n * hands back an existing `element.shadowRoot` instead of attaching a new one,\n * so remounting the same container runs this method again on a shadow root\n * that already holds a full adopted block, and appending would grow it once\n * per mount with no bound. It does not save re-resolving the cloned `<link>`s -\n * every mount clones them afresh and the browser resolves each clone; what\n * replacement buys is that the count stays at one block instead of one per\n * mount.\n *\n * The block is rebuilt from the host head rather than left in place, because\n * the head is not fixed: a lazily imported chunk adds stylesheets to it after\n * the first mount, and the second mount has to pick those up.\n *\n * The fresh block goes in before the previous one comes out. Removing first\n * leaves the shadow root with no host CSS at all, and everything between that\n * removal and the insertion is synchronous work in this same task - so the gap\n * never reaches a paint, but any code that reads computed styles from the tree\n * in between sees an unstyled one. Inserting first costs one moment with two\n * blocks present, which changes nothing: the old block is a clone of the same\n * host head and loses every tie to the new one on document order anyway.\n */\n protected adoptHostStylesIntoShadowRoot(shadowRoot: ShadowRoot): void {\n // Collected before the insertion, so the marked nodes this removes are only\n // the ones already there: the fresh clones below carry the same marker and\n // a selector query after the insertion would match them too.\n const supersededStyles = Array.from(shadowRoot.querySelectorAll(`[${ADOPTED_HOST_STYLE_ATTR}]`));\n\n const adoptedStyles = document.createDocumentFragment();\n\n // One query covering both kinds, because querySelectorAll returns document\n // order: querying <style> and <link> separately would concatenate the two\n // groups instead, so a host declaring <link A> before <style B> would get\n // them adopted as B then A. That reordering decides which rule wins every\n // specificity tie between them, which is the tie this whole method exists\n // to settle - so the adopted block has to preserve the host's own order,\n // not just sit ahead of the MFE's CSS.\n const hostStyleNodes = document.head.querySelectorAll('style, link[rel=\"stylesheet\"]');\n hostStyleNodes.forEach((el) => {\n if (el instanceof HTMLStyleElement) {\n const clone = document.createElement('style');\n clone.textContent = el.textContent ?? '';\n clone.setAttribute(ADOPTED_HOST_STYLE_ATTR, '');\n adoptedStyles.appendChild(clone);\n return;\n }\n const linkClone = el.cloneNode(true) as Element;\n linkClone.setAttribute(ADOPTED_HOST_STYLE_ATTR, '');\n adoptedStyles.appendChild(linkClone);\n });\n\n // Staged in a fragment so the adopted pieces keep their host-document order\n // relative to each other while moving as one block to the front.\n shadowRoot.insertBefore(adoptedStyles, shadowRoot.firstChild);\n supersededStyles.forEach((el) => el.remove());\n }\n\n /**\n * Box-model resets and :host defaults needed inside every shadow root.\n * These aren't part of Tailwind's compiled output but are required for\n * consistent rendering across browsers.\n *\n * Reuses the node a previous mount left behind, exactly as `injectStylesheet`\n * does in `@gears-frontx/mfes`' shadow utilities: a remount runs against a\n * shadow root that `createShadowRoot` handed back intact, and appending a\n * second copy would add one node per mount forever.\n *\n * Reuse alone is not enough, which is why the node is also positioned on every\n * mount rather than left where the previous one sat. These resets are context\n * like the adopted block is - `border-color: currentColor` on `*` is a 0-0-0\n * declaration that beats an MFE preflight's own 0-0-0 reset purely on document\n * order - so they have to stay ahead of the MFE's CSS, and where they land is\n * not stable on its own. `MfeHandlerMF.wrapLifecycleWithStylesheets` removes the\n * MFE's stylesheet on unmount and appends a fresh one before the next mount, so\n * a node merely left in place ends up ahead of that stylesheet on a remount and\n * behind it on the first mount: two different cascades for one component.\n * Anchoring it to the end of the shell-owned head gives every mount the same\n * order - adopted block, isolation, resets, MFE - which is also the order the\n * adoption method's invariant is written against.\n *\n * With no shell-owned node to anchor to, the resets go to the front. That is the\n * plain-`Element` container: no adopted block, no isolation style, and the MFE\n * stylesheet already appended by the handler, so the front is again the only\n * position that leaves the MFE winning ties.\n *\n * Looked up by attribute-selector form rather than `getElementById`, which\n * `ShadowRoot` has but `Element` does not, and this hook takes either.\n */\n private injectBaseResets(container: Element | ShadowRoot): void {\n const existing = container.querySelector<HTMLStyleElement>(\n `style[id=\"${BASE_RESETS_STYLE_ID}\"]`\n );\n const style = existing ?? document.createElement('style');\n style.id = BASE_RESETS_STYLE_ID;\n style.textContent = `\n *, *::before, *::after {\n box-sizing: border-box;\n border-width: 0;\n border-style: solid;\n border-color: currentColor;\n }\n * { margin: 0; padding: 0; }\n :host {\n font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;\n line-height: 1.5;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n color: var(--foreground);\n background-color: var(--background);\n }\n `;\n // Runs whether the node is new or reused: `insertBefore` moves a node that\n // is already in the tree, and is a no-op when it already sits there.\n const shellOwnedHead = container.querySelectorAll(\n [\n `[${ADOPTED_HOST_STYLE_ATTR}]`,\n ...SHELL_OWNED_SHADOW_STYLE_IDS.map((id) => `[id=\"${id}\"]`),\n ].join(', ')\n );\n const lastShellOwnedNode = shellOwnedHead[shellOwnedHead.length - 1];\n container.insertBefore(\n style,\n lastShellOwnedNode ? lastShellOwnedNode.nextSibling : container.firstChild\n );\n }\n\n /**\n * Hook for subclasses to inject additional CSS not covered by the adopted host\n * stylesheet (e.g., MFE-specific @font-face rules or custom animations).\n * No-op by default: host styles adopted in adoptHostStylesIntoShadowRoot()\n * already include all Tailwind utilities compiled from MFE source files.\n */\n protected initializeStyles(_container: Element | ShadowRoot): void {\n // No-op by default.\n }\n\n /**\n * Return the screen-specific React component tree.\n */\n protected abstract renderContent(bridge: ChildMfeBridge): React.ReactNode;\n}\n","/**\n * Extension Domain Slot Component\n *\n * Per-domain React component that provides the DOM root for a registered domain.\n * Delegates root attachment to the per-domain ExtensionMounter obtained from the\n * registry. What extensions live inside the root is a domain-policy concern (the\n * active MountStrategy plus the domain implementation's ContainerHooks), not a\n * slot-API concern.\n *\n * The slot is uniform across all cardinalities (Exclusive / Optional / Concurrent).\n * Mount and unmount actions are dispatched by the host application via\n * registry.executeActionsChain — NOT by this component.\n *\n * @packageDocumentation\n */\n// @cpt-flow:cpt-frontx-flow-react-bindings-extension-domain-slot:p1\n// @cpt-state:cpt-frontx-state-react-bindings-extension-slot:p1\n// @cpt-dod:cpt-frontx-dod-react-bindings-extension-slot:p1\n\nimport React, { useEffect, useEffectEvent, useRef, useState } from 'react';\nimport type { MfeRegistry } from '@gears-frontx/framework';\n\n/**\n * Props for ExtensionDomainSlot component\n */\nexport interface ExtensionDomainSlotProps {\n /**\n * The screensets registry instance.\n */\n registry: MfeRegistry;\n\n /**\n * The domain ID for this slot.\n */\n domainId: string;\n\n /**\n * Optional CSS class name for the root container div.\n */\n className?: string;\n\n /**\n * Optional callback invoked after mounter.attach(element) returns.\n * Receives the root element that was attached.\n */\n onAttached?: (root: Element) => void;\n\n /**\n * Optional callback invoked after mounter.detach() returns on cleanup.\n */\n onDetached?: () => void;\n\n /**\n * Optional loading placeholder rendered before the mounter has been attached.\n * Defaults to null (no visual placeholder).\n */\n loadingComponent?: React.ReactNode;\n}\n\n/**\n * Extension Domain Slot Component\n *\n * Renders a single root `<div>` per domain instance. On ref-attach, resolves the\n * per-domain mounter via registry.getMounter(domainId) and calls mounter.attach(element).\n * On cleanup, calls mounter.detach() which mass-unmounts every currently-mounted\n * extension in the domain so no orphan DOM trees or slice/registry desync remain.\n *\n * @example\n * ```tsx\n * <ExtensionDomainSlot\n * registry={registry}\n * domainId={FRONTX_SCREEN_DOMAIN}\n * loadingComponent={<Loading />}\n * onAttached={(root) => console.log('Root attached:', root)}\n * />\n * ```\n */\n// @cpt-begin:cpt-frontx-flow-react-bindings-extension-domain-slot:p1:inst-render-slot\n// @cpt-begin:cpt-frontx-dod-react-bindings-extension-slot:p1:inst-render-slot\nexport function ExtensionDomainSlot(props: ExtensionDomainSlotProps): React.ReactElement {\n const {\n registry,\n domainId,\n className,\n onAttached,\n onDetached,\n loadingComponent = null,\n } = props;\n\n const rootRef = useRef<HTMLDivElement | null>(null);\n\n // Effect events so effect deps stay minimal — inline parent handlers do not\n // re-run the attach/detach effect on every parent render, yet each call\n // sees the latest committed onAttached/onDetached prop.\n const emitAttached = useEffectEvent((root: Element) => {\n onAttached?.(root);\n });\n const emitDetached = useEffectEvent(() => {\n onDetached?.();\n });\n\n // @cpt-begin:cpt-frontx-state-react-bindings-extension-slot:p1:inst-slot-attached\n // Tracks whether the mounter has been attached to the DOM root.\n // The loading placeholder is shown until attached becomes true.\n const [attached, setAttached] = useState(false);\n // @cpt-end:cpt-frontx-state-react-bindings-extension-slot:p1:inst-slot-attached\n\n useEffect(() => {\n const root = rootRef.current;\n if (!root) {\n return;\n }\n\n // @cpt-begin:cpt-frontx-flow-react-bindings-extension-domain-slot:p1:inst-attach-root\n // Resolve the per-domain mounter and attach the DOM root.\n // The mounter owns all per-extension container placement under this root.\n const mounter = registry.getMounter(domainId);\n mounter.attach(root);\n // @cpt-end:cpt-frontx-flow-react-bindings-extension-domain-slot:p1:inst-attach-root\n\n // @cpt-begin:cpt-frontx-state-react-bindings-extension-slot:p1:inst-slot-attached\n setAttached(true);\n // @cpt-end:cpt-frontx-state-react-bindings-extension-slot:p1:inst-slot-attached\n\n emitAttached(root);\n\n // @cpt-begin:cpt-frontx-flow-react-bindings-extension-domain-slot:p1:inst-detach-root\n return () => {\n // Mass-unmount every extension currently mounted in the domain.\n // detach() is async (awaits per-extension unmounts) but React cleanup is\n // synchronous; we deliberately fire-and-forget here.\n void mounter.detach();\n\n // @cpt-begin:cpt-frontx-state-react-bindings-extension-slot:p1:inst-slot-detached\n setAttached(false);\n // @cpt-end:cpt-frontx-state-react-bindings-extension-slot:p1:inst-slot-detached\n\n // emitDetached is an effect event: it always calls the onDetached prop\n // from the latest committed render, not whatever prop was current when\n // this effect instance was originally set up.\n emitDetached();\n };\n // @cpt-end:cpt-frontx-flow-react-bindings-extension-domain-slot:p1:inst-detach-root\n // @cpt-begin:cpt-frontx-state-react-bindings-extension-slot:p2:inst-slot-stable-rerender\n // ATTACHED → ATTACHED (no-op) when parent supplies the same domainId and\n // registry on re-render: useEffect dep equality short-circuits the attach/detach pair.\n // emitAttached/emitDetached are effect events — non-reactive by contract,\n // so they are excluded from deps and the effect does not re-run when the\n // parent passes new inline handlers.\n }, [registry, domainId]);\n // @cpt-end:cpt-frontx-state-react-bindings-extension-slot:p2:inst-slot-stable-rerender\n\n // @cpt-begin:cpt-frontx-flow-react-bindings-extension-domain-slot:p1:inst-show-loading\n // Render the loading placeholder until the mounter has been attached.\n // Once attached, render the root div with null children — multi-mount children\n // are placed imperatively under this root by the per-domain mounter.\n return (\n <div\n ref={rootRef}\n className={className}\n data-domain-id={domainId}\n >\n {!attached ? loadingComponent : null}\n </div>\n );\n // @cpt-end:cpt-frontx-flow-react-bindings-extension-domain-slot:p1:inst-show-loading\n}\n// @cpt-end:cpt-frontx-flow-react-bindings-extension-domain-slot:p1:inst-render-slot\n// @cpt-end:cpt-frontx-dod-react-bindings-extension-slot:p1:inst-render-slot\n","/**\n * @gears-frontx/react - React Bindings\n *\n * This package provides:\n * - FrontXProvider context provider\n * - Type-safe hooks for state and actions\n * - MFE context, hooks, and components\n *\n * Layer: L3 (Depends on @gears-frontx/framework)\n */\n\n// ============================================================================\n// Provider\n// ============================================================================\n\nexport { FrontXProvider } from './FrontXProvider';\nexport { FrontXContext, useFrontX } from './FrontXContext';\nexport { invalidateQueryCacheForApp } from './queryClient';\nexport { CanAccess } from './components/CanAccess';\nexport type { CanAccessProps } from './types';\n\n// ============================================================================\n// Hooks\n// ============================================================================\n\nexport {\n useAppDispatch,\n useAppSelector,\n useTranslation,\n useScreenTranslations,\n useFormatters,\n useTheme,\n useApiQuery,\n useApiSuspenseQuery,\n useApiInfiniteQuery,\n useApiSuspenseInfiniteQuery,\n useApiMutation,\n useApiStream,\n useQueryCache,\n} from './hooks';\nexport { useCanAccess } from './hooks/useCanAccess';\n\nexport type { ApiQueryOverrides } from './hooks/useApiQuery';\nexport type {\n ApiInfiniteQueryOptions,\n ApiInfiniteQueryPageContext,\n} from './hooks/useApiInfiniteQuery';\nexport type { UseApiMutationOptions } from './hooks/useApiMutation';\nexport type { ApiStreamOptions, ApiStreamResult } from './hooks/useApiStream';\nexport type {\n QueryCache,\n QueryCacheInvalidateFilters,\n QueryCacheState,\n MutationCallbackContext,\n} from './hooks/QueryCache';\n\n// ============================================================================\n// MFE Context and Hooks\n// ============================================================================\n\nexport {\n MfeContext,\n useMfeContext,\n MfeProvider,\n useMfeBridge,\n ThemeAwareReactLifecycle,\n useSharedProperty,\n useHostAction,\n useDomainExtensions,\n useMountedExtensions,\n useRegisteredPackages,\n ExtensionDomainSlot,\n} from './mfe';\n\nexport type {\n MfeContextValue,\n MfeProviderProps,\n ExtensionDomainSlotProps,\n} from './mfe';\n\n// ============================================================================\n// Type Exports\n// ============================================================================\n\nexport type {\n FrontXProviderProps,\n UseFrontXReturn,\n UseAppSelector,\n UseAppDispatchReturn,\n UseTranslationReturn,\n UseScreenTranslationsReturn,\n UseFormattersReturn,\n UseThemeReturn,\n ApiQueryResult,\n ApiSuspenseQueryResult,\n ApiInfiniteQueryResult,\n ApiSuspenseInfiniteQueryResult,\n ApiMutationResult,\n UseCanAccessResult,\n} from './types';\n\n// ============================================================================\n// Re-exports from @gears-frontx/framework for convenience\n// ============================================================================\n\n// These re-exports allow users to import everything from @gears-frontx/react\n// without needing to import from @gears-frontx/framework directly\n\nexport {\n // Core\n createFrontX,\n createFrontXApp,\n presets,\n\n // Backward compatibility constants\n ACCOUNTS_DOMAIN,\n\n // I18nRegistry class (capital I for backward compat)\n I18nRegistry,\n\n // Plugins\n themes,\n layout,\n i18n,\n effects,\n queryCache,\n queryCacheShared,\n subscribeQueryCacheRuntimeChanged,\n\n // Registries\n createThemeRegistry,\n\n // Flux (Event bus + Store)\n // NOTE: eventBus is re-exported separately below with augmented EventPayloadMap type\n\n // Store\n createStore,\n getStore,\n registerSlice,\n hasSlice,\n createSlice,\n\n // Layout domain exports\n layoutReducer,\n layoutDomainReducers,\n LAYOUT_SLICE_NAME,\n headerSlice,\n footerSlice,\n menuSlice,\n sidebarSlice,\n popupSlice,\n overlaySlice,\n headerActions,\n footerActions,\n menuActions,\n sidebarActions,\n popupActions,\n overlayActions,\n // Individual reducer functions - header\n setUser,\n setHeaderLoading,\n clearUser,\n // Individual reducer functions - footer\n setFooterVisible,\n setFooterConfig,\n toggleMenu,\n setMenuCollapsed,\n setMenuItems,\n setMenuVisible,\n setMenuConfig,\n toggleSidebar,\n setSidebarCollapsed,\n setSidebarPosition,\n setSidebarTitle,\n setSidebarContent,\n setSidebarVisible,\n setSidebarWidth,\n setSidebarConfig,\n openPopup,\n closePopup,\n closeTopPopup,\n closeAllPopups,\n showOverlay,\n hideOverlay,\n setOverlayVisible,\n\n // Tenant (app-level, not layout)\n TENANT_SLICE_NAME,\n tenantSlice,\n tenantActions,\n tenantReducer,\n setTenant,\n setTenantLoading,\n clearTenant,\n // Tenant effects and events\n initTenantEffects,\n changeTenant,\n clearTenantAction,\n setTenantLoadingState,\n TenantEvents,\n\n // Mock (app-level, not layout)\n mockSlice,\n mockActions,\n setMockEnabled,\n // Mock effects and events\n initMockEffects,\n toggleMockMode,\n MockEvents,\n\n // Auth\n auth,\n frontxApiTransport,\n\n // API\n apiRegistry,\n BaseApiService,\n RestProtocol,\n RestEndpointProtocol,\n SseProtocol,\n SseStreamProtocol,\n // Plugin base classes\n ApiPluginBase,\n ApiPlugin,\n ApiProtocol,\n RestPlugin,\n RestPluginWithConfig,\n SsePlugin,\n SsePluginWithConfig,\n // Type guards\n isShortCircuit,\n isRestShortCircuit,\n isSseShortCircuit,\n // Mock plugin identification\n MOCK_PLUGIN,\n isMockPlugin,\n\n // I18n\n i18nRegistry,\n I18nRegistryImpl,\n createI18nRegistry,\n SUPPORTED_LANGUAGES,\n getLanguageMetadata,\n} from '@gears-frontx/framework';\n\n// Re-export i18n types from @gears-frontx/framework (correct layer access)\nexport { Language, TextDirection, LanguageDisplayMode } from '@gears-frontx/framework';\n\n// Re-export types from @gears-frontx/framework\nexport type {\n // Config\n FrontXConfig,\n FrontXPlugin,\n FrontXAppBuilder,\n FrontXApp,\n // Endpoint descriptors — L3 components import from @gears-frontx/react\n EndpointOptions,\n EndpointDescriptor,\n ParameterizedEndpointDescriptor,\n MutationDescriptor,\n // Stream descriptors\n StreamDescriptor,\n StreamStatus,\n PluginFactory,\n PluginProvides,\n PluginLifecycle,\n ThemeRegistry,\n ThemeConfig,\n Preset,\n Presets,\n ShowPopupPayload,\n ChangeThemePayload,\n SetLanguagePayload,\n AuthPluginConfig,\n AuthRuntime,\n\n // Auth contract types\n AuthProvider,\n AuthSession,\n AuthContext,\n AuthCheckResult,\n AuthLoginInput,\n AuthCallbackInput,\n AuthTransition,\n AuthPermissions,\n AccessQuery,\n AccessDecision,\n AuthCapabilities,\n AuthState,\n AuthStateEvent,\n AuthStateListener,\n AuthUnsubscribe,\n\n // Flux (Events + Store)\n EventHandler,\n Subscription,\n\n // Store\n RootState,\n AppDispatch,\n SliceObject,\n FrontXStore,\n ReducerPayload,\n\n // Layout\n LayoutDomainState,\n HeaderUser,\n HeaderConfig,\n HeaderState,\n FooterConfig,\n FooterState,\n MenuItem,\n MenuState,\n SidebarPosition,\n SidebarState,\n PopupConfig,\n PopupState,\n PopupSliceState,\n OverlayConfig,\n OverlayState,\n LayoutState,\n RootStateWithLayout,\n LayoutDomainReducers,\n\n // Tenant types\n Tenant,\n TenantState,\n TenantChangedPayload,\n TenantClearedPayload,\n\n // Mock types\n MockState,\n MockTogglePayload,\n\n // API\n MockMap,\n ApiServiceConfig,\n JsonValue,\n JsonObject,\n JsonPrimitive,\n JsonCompatible,\n SseProtocolConfig,\n RestProtocolConfig,\n // Plugin context types (class-based plugin system)\n ApiRequestContext,\n ApiResponseContext,\n ShortCircuitResponse,\n PluginClass,\n ProtocolClass,\n ProtocolPluginType,\n BasePluginHooks,\n // Protocol-specific types\n RestPluginHooks,\n SsePluginHooks,\n RestRequestContext,\n RestResponseContext,\n ApiPluginErrorContext,\n SseConnectContext,\n EventSourceLike,\n RestShortCircuitResponse,\n SseShortCircuitResponse,\n\n // I18n\n I18nConfig,\n TranslationLoader,\n TranslationMap,\n TranslationDictionary,\n LanguageMetadata,\n I18nRegistryType,\n} from '@gears-frontx/framework';\n\n// ============================================================================\n// MFE Re-exports from @gears-frontx/framework (Layering Compliance)\n// ============================================================================\n\n// MFE Plugin factories\nexport {\n microfrontends,\n mock,\n} from '@gears-frontx/framework';\n\n// MFE Action functions\nexport {\n loadExtension,\n mountExtension,\n unmountExtension,\n registerExtension,\n unregisterExtension,\n} from '@gears-frontx/framework';\n\n// MFE Selectors\nexport {\n selectExtensionState,\n selectRegisteredExtensions,\n selectExtensionError,\n selectMountedExtensions,\n} from '@gears-frontx/framework';\n\n// MFE Domain constants\nexport {\n FRONTX_POPUP_DOMAIN,\n FRONTX_SIDEBAR_DOMAIN,\n FRONTX_SCREEN_DOMAIN,\n FRONTX_OVERLAY_DOMAIN,\n // Base ExtensionDomain constants\n screenDomain,\n sidebarDomain,\n popupDomain,\n overlayDomain,\n} from '@gears-frontx/framework';\n\n// MFE Type constants\nexport {\n FRONTX_SCREEN_EXTENSION_TYPE,\n FRONTX_MFE_ENTRY_MF,\n} from '@gears-frontx/framework';\n\n// MFE Action constants\nexport {\n FRONTX_ACTION_LOAD_EXT,\n FRONTX_ACTION_MOUNT_EXT,\n FRONTX_ACTION_UNMOUNT_EXT,\n} from '@gears-frontx/framework';\n\n// MFE Shared Property constants\nexport {\n FRONTX_SHARED_PROPERTY_THEME,\n FRONTX_SHARED_PROPERTY_LANGUAGE,\n} from '@gears-frontx/framework';\n\n// MFE Types\nexport type {\n MfeMountContext,\n Extension,\n ScreenExtension,\n ExtensionPresentation,\n ExtensionDomain,\n ActionsChain,\n Action,\n SharedProperty,\n LifecycleStage,\n LifecycleHook,\n MfeEntryLifecycle,\n MfeEntry,\n MfeEntryMF,\n JSONSchema,\n LoadExtPayload,\n MountExtPayload,\n UnmountExtPayload,\n MfeRegistryConfig,\n TypeSystemPlugin,\n // MF2 manifest types\n MfManifest,\n MfManifestMetaData,\n MfManifestRemoteEntry,\n MfManifestBuildInfo,\n MfManifestShared,\n MfManifestAssets,\n} from '@gears-frontx/framework';\n\n// MFE Abstract classes\nexport {\n ChildMfeBridge,\n ParentMfeBridge,\n MfeHandler,\n MfeBridgeFactory,\n MfeRegistry,\n MfeRegistryFactory,\n mfeRegistryFactory,\n ActionHandler,\n ExtensionDomainImplementation,\n ExtensionDomainImplementationFactory,\n ExtensionMounter,\n MountStrategy,\n ConcurrentMountStrategy,\n OptionalMountStrategy,\n ExclusiveMountStrategy,\n} from '@gears-frontx/framework';\n\nexport type {\n ContainerHooks,\n DomainContext,\n ActionPayload,\n} from '@gears-frontx/framework';\n\n// MFE Concrete implementations\nexport { MfeHandlerMF, gtsPlugin } from '@gears-frontx/framework';\n\n// GTS derived schemas (themeSchema, languageSchema, extensionScreenSchema) and the\n// protocol-specific mock plugins (RestMockPlugin, SseMockPlugin, MockEventSource)\n// are application-layer symbols owned by @gears-frontx/frontx-template-shell and\n// are no longer re-exported here — import them from the template package (#601).\n\n// MFE Utilities\nexport {\n createShadowRoot,\n injectCssVariables,\n extractGtsPackage,\n} from '@gears-frontx/framework';\n\n// MFE Plugin types\nexport type {\n MfeState,\n ExtensionRegistrationState,\n RegisterExtensionPayload,\n UnregisterExtensionPayload,\n} from '@gears-frontx/framework';\n\n// ============================================================================\n// Module Augmentation Support - EventPayloadMap Re-declaration\n// ============================================================================\n\n/**\n * Re-declare EventPayloadMap to enable module augmentation on @gears-frontx/react\n *\n * This creates a new declaration site in @gears-frontx/react that TypeScript can augment.\n * App-layer code can now use `declare module '@gears-frontx/react'` instead of importing\n * from L1 packages directly, maintaining proper layer architecture.\n *\n * ARCHITECTURE: This pattern allows L3+ code to augment event types without\n * violating layer boundaries by importing from L1 (@gears-frontx/state).\n *\n * IMPORTANT: We must also re-export eventBus with the augmented type to ensure\n * type safety. The eventBus instance uses this augmented EventPayloadMap.\n *\n * @example\n * ```typescript\n * // In app-layer code (e.g., src/app/events/bootstrapEvents.ts)\n * import '@gears-frontx/react';\n *\n * declare module '@gears-frontx/react' {\n * interface EventPayloadMap {\n * 'app/user/fetch': void;\n * 'app/user/loaded': { user: ApiUser };\n * }\n * }\n * ```\n */\nimport type { EventPayloadMap as FrameworkEventPayloadMap, EventBus } from '@gears-frontx/framework';\nimport { eventBus as frameworkEventBus } from '@gears-frontx/framework';\n\n// @cpt-dod:cpt-frontx-dod-react-bindings-event-payload-map:p2\n// @cpt-begin:cpt-frontx-dod-react-bindings-event-payload-map:p2:inst-event-payload-map\nexport interface EventPayloadMap extends FrameworkEventPayloadMap { }\n\n/**\n * Re-export eventBus with augmented EventPayloadMap type.\n * This ensures that code importing eventBus from @gears-frontx/react gets\n * type-safe access to both framework events and app-layer augmented events.\n */\nexport const eventBus: EventBus<EventPayloadMap> = frameworkEventBus as EventBus<EventPayloadMap>;\n// @cpt-end:cpt-frontx-dod-react-bindings-event-payload-map:p2:inst-event-payload-map\n"],"mappings":"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","names":["useMemo","useEffect","useState","createContext","useContext","createContext","useContext","useEffect","jsx","createContext","useEffect","useContext","controller","jsx","useState","useMemo","useEffect","useEffect","useState","auth","useState","useEffect","useMemo","i18nRegistry","useMemo","useState","useEffect","useMemo","useCallback","useSyncExternalStore","i18nRegistry","useState","useSyncExternalStore","useCallback","useMemo","useEffect","useMemo","useMemo","useCallback","useMemo","useSyncExternalStore","useSyncExternalStore","useCallback","useMemo","themes","useMemo","queryCache","useEffect","useMemo","useRef","useState","useCallback","useState","useRef","useMemo","useCallback","useEffect","useMemo","useMemo","useSyncExternalStore","useCallback","useCallback","useSyncExternalStore","useCallback","useCallback","useSyncExternalStore","useCallback","useRef","useCallback","useRef","useSyncExternalStore","useSyncExternalStore","useCallback","useRef","useCallback","useRef","useSyncExternalStore","useSyncExternalStore","useCallback","useRef","useCallback","useRef","useSyncExternalStore","jsx","useEffect","useRef","useState","jsx","createFrontXApp","subscribeQueryCacheRuntimeChanged","microfrontends","eventBus"]}
|
|
1
|
+
{"version":3,"sources":["../src/FrontXProvider.tsx","../src/FrontXContext.tsx","../src/mfe/MfeContext.tsx","../src/mfe/MfeProvider.tsx","../src/queryClient.tsx","../src/hooks/QueryCache.ts","../src/hooks/useLatest.ts","../src/hooks/useCanAccess.ts","../src/components/CanAccess.tsx","../src/hooks/useAppDispatch.ts","../src/hooks/useAppSelector.ts","../src/hooks/useTranslation.ts","../src/hooks/useScreenTranslations.ts","../src/hooks/useFormatters.ts","../src/hooks/useTheme.ts","../src/hooks/useApiQuery.ts","../src/hooks/useApiSuspenseQuery.ts","../src/hooks/useApiInfiniteQuery.ts","../src/hooks/useApiSuspenseInfiniteQuery.ts","../src/hooks/useApiMutation.ts","../src/hooks/useApiStream.ts","../src/hooks/useQueryCache.ts","../src/mfe/hooks/useMfeBridge.ts","../src/mfe/hooks/useSharedProperty.ts","../src/mfe/hooks/useHostAction.ts","../src/mfe/hooks/useDomainExtensions.ts","../src/mfe/hooks/useMountedExtensions.ts","../src/mfe/hooks/useRegisteredPackages.ts","../src/mfe/ThemeAwareReactLifecycle.tsx","../src/mfe/components/ExtensionDomainSlot.tsx","../src/index.ts"],"sourcesContent":["/**\n * FrontX Provider - Main provider component for FrontX applications\n *\n * React Layer: L3 (Depends on @gears-frontx/framework)\n *\n * Query cache lifecycle is owned by the queryCache() framework plugin (L2).\n * FrontXProvider reads the plugin-owned QueryClient from the app and mounts the\n * internal React provider around the tree when it is available.\n */\n// @cpt-flow:cpt-frontx-flow-react-bindings-bootstrap-provider:p1\n// @cpt-algo:cpt-frontx-algo-react-bindings-resolve-app:p1\n// @cpt-algo:cpt-frontx-algo-react-bindings-build-provider-tree:p1\n// @cpt-dod:cpt-frontx-dod-react-bindings-provider:p1\n// @cpt-dod:cpt-frontx-dod-request-lifecycle-query-provider:p2\n// @cpt-flow:cpt-frontx-flow-request-lifecycle-query-client-lifecycle:p2\n// @cpt-FEATURE:implement-endpoint-descriptors:p3\n\nimport React, { useMemo, useEffect, useState } from 'react';\nimport { Provider as ReduxProvider } from 'react-redux';\nimport type { Store } from '@reduxjs/toolkit';\nimport {\n createFrontXApp,\n microfrontends,\n} from '@gears-frontx/framework';\nimport type { FrontXApp } from '@gears-frontx/framework';\nimport { FrontXContext } from './FrontXContext';\nimport { MfeProvider } from './mfe/MfeProvider';\nimport {\n hasFrontXQueryClientActivator,\n FrontXQueryClientProvider,\n useBootstrappedFrontXQueryClient,\n} from './queryClient';\nimport type { FrontXProviderProps } from './types';\n\n/**\n * Shallow-compare two plain objects by own-enumerable values (Object.is).\n * Prevents unnecessary app recreation when callers pass inline config literals\n * whose values haven't actually changed between renders.\n */\nfunction shallowEqual(\n a: Record<string, unknown> | undefined,\n b: Record<string, unknown> | undefined,\n): boolean {\n if (a === b) return true;\n if (!a || !b) return false;\n const keysA = Object.keys(a);\n if (keysA.length !== Object.keys(b).length) return false;\n return keysA.every((k) => Object.is(a[k], b[k]));\n}\n\ntype ProviderOwnedAppConfig = FrontXProviderProps['config'] & {\n microfrontends?: Parameters<typeof microfrontends>[0];\n};\n\nfunction createProviderOwnedApp(\n config: ProviderOwnedAppConfig | undefined\n): FrontXApp {\n return createFrontXApp(config);\n}\n\n/**\n * FrontX Provider Component\n *\n * Provides the FrontX application context to all child components.\n * Creates the FrontX app instance with the full preset by default.\n *\n * @example\n * ```tsx\n * // Default - creates app with full preset\n * <FrontXProvider>\n * <App />\n * </FrontXProvider>\n *\n * // With configuration\n * <FrontXProvider config={{ devMode: true }}>\n * <App />\n * </FrontXProvider>\n *\n * // With pre-built app\n * const app = createFrontX().use(queryCache()).build();\n * <FrontXProvider app={app}>\n * <App />\n * </FrontXProvider>\n *\n * // With MFE bridge (for MFE components)\n * <FrontXProvider mfeBridge={{ bridge, extensionId, domainId }}>\n * <MyMfeApp />\n * </FrontXProvider>\n *\n * // QueryCache is resolved from the app's plugin composition\n * <FrontXProvider app={app}>\n * <MyMfeApp />\n * </FrontXProvider>\n * ```\n */\n// @cpt-begin:cpt-frontx-flow-react-bindings-bootstrap-provider:p1:inst-render-provider\n// @cpt-begin:cpt-frontx-dod-react-bindings-provider:p1:inst-render-provider\n// @cpt-begin:cpt-frontx-dod-request-lifecycle-query-provider:p2:inst-render-provider\nexport const FrontXProvider: React.FC<FrontXProviderProps> = ({\n children,\n config,\n app: providedApp,\n mfeBridge,\n}) => {\n // @cpt-begin:cpt-frontx-flow-react-bindings-bootstrap-provider:p1:inst-resolve-app\n // @cpt-begin:cpt-frontx-algo-react-bindings-resolve-app:p1:inst-use-provided-app\n // @cpt-begin:cpt-frontx-algo-react-bindings-resolve-app:p1:inst-create-app\n // @cpt-begin:cpt-frontx-algo-react-bindings-resolve-app:p1:inst-memoize-app\n // @cpt-begin:cpt-frontx-algo-react-bindings-build-provider-tree:p1:inst-resolve-app-tree\n // Stabilize config by shallow value without mutating a ref during render.\n // When the incoming config shallow-differs, a render-phase setState triggers an\n // immediate re-render so useMemo sees the updated stable reference in the same\n // turn as a reference-changing (but value-equal) prop would be ignored.\n const [stableConfig, setStableConfig] = useState(config);\n if (\n !shallowEqual(\n stableConfig as Record<string, unknown> | undefined,\n config as Record<string, unknown> | undefined,\n )\n ) {\n setStableConfig(config);\n }\n\n const app = useMemo<FrontXApp>(() => {\n if (providedApp) {\n return providedApp;\n }\n\n return createProviderOwnedApp(stableConfig as ProviderOwnedAppConfig | undefined);\n }, [providedApp, stableConfig]);\n // @cpt-end:cpt-frontx-algo-react-bindings-resolve-app:p1:inst-use-provided-app\n // @cpt-end:cpt-frontx-algo-react-bindings-resolve-app:p1:inst-create-app\n // @cpt-end:cpt-frontx-algo-react-bindings-resolve-app:p1:inst-memoize-app\n // @cpt-end:cpt-frontx-algo-react-bindings-build-provider-tree:p1:inst-resolve-app-tree\n // @cpt-end:cpt-frontx-flow-react-bindings-bootstrap-provider:p1:inst-resolve-app\n\n const queryClient = useBootstrappedFrontXQueryClient(app);\n const deferQuerySubtree =\n hasFrontXQueryClientActivator(app) && queryClient === undefined;\n\n useEffect(() => {\n if (\n queryClient ||\n hasFrontXQueryClientActivator(app) ||\n process.env.NODE_ENV === 'production' ||\n process.env.NODE_ENV === 'test' ||\n process.env.VITEST === 'true'\n ) {\n return;\n }\n\n console.warn(\n '[FrontXProvider] No query cache available. Add queryCache() or queryCacheShared() to your plugin composition. ' +\n 'useApiQuery/useApiMutation will fail without it.'\n );\n }, [app, queryClient]);\n\n // @cpt-begin:cpt-frontx-flow-react-bindings-bootstrap-provider:p1:inst-destroy-app\n // Cleanup on unmount\n useEffect(() => {\n return () => {\n // Only destroy if we created the app (not provided externally)\n if (!providedApp) {\n app.destroy();\n }\n };\n }, [app, providedApp]);\n // @cpt-end:cpt-frontx-flow-react-bindings-bootstrap-provider:p1:inst-destroy-app\n\n // @cpt-begin:cpt-frontx-algo-react-bindings-build-provider-tree:p1:inst-wrap-frontx-context\n // @cpt-begin:cpt-frontx-algo-react-bindings-build-provider-tree:p1:inst-wrap-redux\n // @cpt-begin:cpt-frontx-flow-react-bindings-bootstrap-provider:p1:inst-set-frontx-context\n // @cpt-begin:cpt-frontx-flow-react-bindings-bootstrap-provider:p1:inst-set-redux-provider\n // @cpt-begin:cpt-frontx-flow-react-bindings-bootstrap-provider:p1:inst-render-query-provider\n // @cpt-begin:cpt-frontx-flow-react-bindings-bootstrap-provider:p1:inst-render-children\n // @cpt-begin:cpt-frontx-flow-request-lifecycle-query-client-lifecycle:p2:inst-render-query-provider\n // Provider order (outer to inner):\n // FrontXContext -> ReduxProvider -> QueryClientProvider -> children\n // queryCache()/queryCacheShared() own the shared QueryClient lifecycle.\n const content = (\n <FrontXContext.Provider value={app}>\n <ReduxProvider store={app.store as Store}>\n {/* app.store is FrontX-owned but Redux-compatible. Cast keeps react-redux happy. */}\n <FrontXQueryClientProvider queryClient={queryClient}>\n {deferQuerySubtree ? null : children}\n </FrontXQueryClientProvider>\n </ReduxProvider>\n </FrontXContext.Provider>\n );\n // @cpt-end:cpt-frontx-flow-request-lifecycle-query-client-lifecycle:p2:inst-render-query-provider\n // @cpt-end:cpt-frontx-flow-react-bindings-bootstrap-provider:p1:inst-render-children\n // @cpt-end:cpt-frontx-flow-react-bindings-bootstrap-provider:p1:inst-render-query-provider\n // @cpt-end:cpt-frontx-flow-react-bindings-bootstrap-provider:p1:inst-set-redux-provider\n // @cpt-end:cpt-frontx-flow-react-bindings-bootstrap-provider:p1:inst-set-frontx-context\n // @cpt-end:cpt-frontx-algo-react-bindings-build-provider-tree:p1:inst-wrap-redux\n // @cpt-end:cpt-frontx-algo-react-bindings-build-provider-tree:p1:inst-wrap-frontx-context\n\n // @cpt-begin:cpt-frontx-algo-react-bindings-build-provider-tree:p1:inst-wrap-mfe-conditional\n // @cpt-begin:cpt-frontx-flow-react-bindings-bootstrap-provider:p2:inst-wrap-mfe-provider\n // Wrap with MfeProvider if bridge is provided\n if (mfeBridge) {\n return (\n <MfeProvider value={mfeBridge}>\n {content}\n </MfeProvider>\n );\n }\n // @cpt-end:cpt-frontx-algo-react-bindings-build-provider-tree:p1:inst-wrap-mfe-conditional\n // @cpt-end:cpt-frontx-flow-react-bindings-bootstrap-provider:p2:inst-wrap-mfe-provider\n\n return content;\n};\n// @cpt-end:cpt-frontx-flow-react-bindings-bootstrap-provider:p1:inst-render-provider\n// @cpt-end:cpt-frontx-dod-react-bindings-provider:p1:inst-render-provider\n// @cpt-end:cpt-frontx-dod-request-lifecycle-query-provider:p2:inst-render-provider\n","/**\n * FrontX Context - React context for FrontX application\n *\n * React Layer: L3 (Depends on @gears-frontx/framework)\n */\n// @cpt-flow:cpt-frontx-flow-react-bindings-use-frontx:p2\n// @cpt-algo:cpt-frontx-algo-react-bindings-mfe-context-guard:p1\n\nimport { createContext, useContext } from 'react';\nimport type { FrontXApp } from '@gears-frontx/framework';\n\n// ============================================================================\n// Context Definition\n// ============================================================================\n\n/**\n * FrontX Context\n * Holds the FrontX app instance for the application.\n */\nexport const FrontXContext = createContext<FrontXApp | null>(null);\n\n/**\n * Use the FrontX context.\n * Throws if used outside of FrontXProvider.\n *\n * @returns The FrontX app instance\n */\n// @cpt-begin:cpt-frontx-flow-react-bindings-use-frontx:p2:inst-call-use-frontx\n// @cpt-begin:cpt-frontx-algo-react-bindings-mfe-context-guard:p1:inst-throw-no-frontx-context\nexport function useFrontX(): FrontXApp {\n const context = useContext(FrontXContext);\n\n // @cpt-begin:cpt-frontx-flow-react-bindings-use-frontx:p2:inst-guard-frontx-context\n if (!context) {\n throw new Error(\n 'useFrontX must be used within a FrontXProvider. ' +\n 'Wrap your application with <FrontXProvider> to access Gears FrontX features.'\n );\n }\n // @cpt-end:cpt-frontx-flow-react-bindings-use-frontx:p2:inst-guard-frontx-context\n\n // @cpt-begin:cpt-frontx-flow-react-bindings-use-frontx:p2:inst-return-frontx-app\n return context;\n // @cpt-end:cpt-frontx-flow-react-bindings-use-frontx:p2:inst-return-frontx-app\n}\n// @cpt-end:cpt-frontx-flow-react-bindings-use-frontx:p2:inst-call-use-frontx\n// @cpt-end:cpt-frontx-algo-react-bindings-mfe-context-guard:p1:inst-throw-no-frontx-context\n","/**\n * MFE Context - React context for MFE state\n *\n * Provides MFE bridge and metadata to child components.\n * Used by MFE components to access their runtime context.\n *\n * React Layer: L3 (Depends on @gears-frontx/framework)\n */\n// @cpt-flow:cpt-frontx-flow-react-bindings-mfe-provider:p1\n// @cpt-algo:cpt-frontx-algo-react-bindings-mfe-context-guard:p1\n// @cpt-dod:cpt-frontx-dod-react-bindings-mfe-hooks:p1\n\nimport { createContext, useContext } from 'react';\nimport type { ChildMfeBridge } from '@gears-frontx/framework';\n\n// ============================================================================\n// Context Value Types\n// ============================================================================\n\n/**\n * MFE Context Value\n * Contains bridge and metadata about the MFE instance.\n */\nexport interface MfeContextValue {\n /** Child bridge for communication with host */\n bridge: ChildMfeBridge;\n /** Extension ID */\n extensionId: string;\n /** Domain ID where MFE is mounted */\n domainId: string;\n}\n\n// ============================================================================\n// Context Definition\n// ============================================================================\n\n/**\n * MFE Context\n * Holds the MFE bridge and metadata for child components.\n */\nexport const MfeContext = createContext<MfeContextValue | null>(null);\n\n/**\n * Use the MFE context.\n * Throws if used outside of MFE context.\n *\n * @returns The MFE context value\n */\n// @cpt-begin:cpt-frontx-flow-react-bindings-mfe-provider:p1:inst-use-mfe-context\n// @cpt-begin:cpt-frontx-algo-react-bindings-mfe-context-guard:p1:inst-throw-no-mfe-context\n// @cpt-begin:cpt-frontx-dod-react-bindings-mfe-hooks:p1:inst-use-mfe-context\nexport function useMfeContext(): MfeContextValue {\n const context = useContext(MfeContext);\n\n if (!context) {\n throw new Error(\n 'useMfeContext must be used within a MfeProvider. ' +\n 'This hook can only be used inside MFE components.'\n );\n }\n\n return context;\n}\n// @cpt-end:cpt-frontx-flow-react-bindings-mfe-provider:p1:inst-use-mfe-context\n// @cpt-end:cpt-frontx-algo-react-bindings-mfe-context-guard:p1:inst-throw-no-mfe-context\n// @cpt-end:cpt-frontx-dod-react-bindings-mfe-hooks:p1:inst-use-mfe-context\n","/**\n * MFE Provider - Provides MFE context to child components\n *\n * Wraps MFE components with bridge and metadata.\n * Used by the MFE mounting system.\n *\n * MfeProvider does not create or own the shared QueryClient. When the host uses\n * queryCache() and the child app uses queryCacheShared(), overlapping queries\n * (same query key) are deduplicated and cached once across MFE boundaries.\n * Each MFE still uses its own apiRegistry and service instances in queryFn.\n *\n * React Layer: L3 (Depends on @gears-frontx/framework)\n */\n// @cpt-flow:cpt-frontx-flow-react-bindings-mfe-provider:p1\n// @cpt-dod:cpt-frontx-dod-react-bindings-mfe-hooks:p1\n// @cpt-flow:cpt-frontx-flow-request-lifecycle-query-client-lifecycle:p2\n\nimport React from 'react';\nimport { MfeContext, type MfeContextValue } from './MfeContext';\n\n// ============================================================================\n// Provider Props\n// ============================================================================\n\n/**\n * MFE Provider Props\n */\nexport interface MfeProviderProps {\n /** MFE context value */\n value: MfeContextValue;\n /** Child components */\n children: React.ReactNode;\n}\n\n// ============================================================================\n// Provider Component\n// ============================================================================\n\n/**\n * MFE Provider Component\n *\n * Provides MFE bridge and metadata to child components.\n * Used by the MFE mounting system to wrap MFE components.\n *\n * @example\n * ```tsx\n * <MfeProvider value={{ bridge, extensionId, domainId }}>\n * <MyMfeComponent />\n * </MfeProvider>\n * ```\n */\n// @cpt-begin:cpt-frontx-flow-react-bindings-mfe-provider:p1:inst-render-mfe-provider\n// @cpt-begin:cpt-frontx-flow-react-bindings-mfe-provider:p1:inst-set-mfe-context\n// @cpt-begin:cpt-frontx-dod-react-bindings-mfe-hooks:p1:inst-render-mfe-provider\n// @cpt-begin:cpt-frontx-flow-request-lifecycle-query-client-lifecycle:p2:inst-mfe-query-client\nexport const MfeProvider: React.FC<MfeProviderProps> = ({ value, children }) => {\n // MfeProvider only supplies the bridge context. Shared cache depends on\n // plugin-owned QueryClient reuse across each MFE root's FrontXProvider.\n return (\n <MfeContext.Provider value={value}>\n {children}\n </MfeContext.Provider>\n );\n};\n// @cpt-end:cpt-frontx-flow-react-bindings-mfe-provider:p1:inst-render-mfe-provider\n// @cpt-end:cpt-frontx-flow-react-bindings-mfe-provider:p1:inst-set-mfe-context\n// @cpt-end:cpt-frontx-dod-react-bindings-mfe-hooks:p1:inst-render-mfe-provider\n// @cpt-end:cpt-frontx-flow-request-lifecycle-query-client-lifecycle:p2:inst-mfe-query-client\n","import React, {\n createContext,\n useContext,\n useEffect,\n useLayoutEffect,\n useMemo,\n useState,\n} from 'react';\nimport {\n QueryClientContext,\n QueryClientProvider,\n type QueryClient,\n useInfiniteQuery,\n useMutation,\n useQuery,\n useSuspenseInfiniteQuery,\n useSuspenseQuery,\n type MutationFunctionContext,\n} from '@tanstack/react-query';\nimport {\n subscribeQueryCacheRuntimeChanged,\n type EndpointDescriptor,\n type FrontXApp,\n} from '@gears-frontx/framework';\nimport type { ApiQueryOverrides } from './hooks/useApiQuery';\nimport type {\n ApiInfiniteQueryOptions,\n ApiInfiniteQueryPageContext,\n} from './hooks/useApiInfiniteQuery';\nimport type { UseApiMutationOptions } from './hooks/useApiMutation';\nimport { createQueryCache, type MutationCallbackContext, type QueryCacheKey } from './hooks/QueryCache';\nimport { useLatest } from './hooks/useLatest';\n\n// @cpt-FEATURE:implement-endpoint-descriptors:p3\n// @cpt-dod:cpt-frontx-dod-request-lifecycle-query-provider:p2\n// @cpt-flow:cpt-frontx-flow-request-lifecycle-query-client-lifecycle:p2\n// @cpt-flow:cpt-frontx-flow-request-lifecycle-use-api-query:p2\n// @cpt-flow:cpt-frontx-flow-request-lifecycle-use-api-mutation:p2\n\n// @cpt-begin:cpt-frontx-flow-request-lifecycle-query-client-lifecycle:p2:inst-react-query-client-symbols\nconst APP_QUERY_CLIENT_SYMBOL = Symbol.for('frontx:query-cache:app-client');\nconst APP_QUERY_CLIENT_RESOLVER_SYMBOL = Symbol.for('frontx:query-cache:app-client-resolver');\nconst APP_QUERY_CLIENT_ACTIVATOR_SYMBOL = Symbol.for('frontx:query-cache:app-client-activator');\n\ntype QueryClientApp = FrontXApp & {\n [APP_QUERY_CLIENT_SYMBOL]?: QueryClient;\n [APP_QUERY_CLIENT_RESOLVER_SYMBOL]?: () => QueryClient | undefined;\n [APP_QUERY_CLIENT_ACTIVATOR_SYMBOL]?: () => QueryClient | undefined;\n};\n\nconst FrontXQueryClientContext = createContext<QueryClient | undefined>(undefined);\n// @cpt-end:cpt-frontx-flow-request-lifecycle-query-client-lifecycle:p2:inst-react-query-client-symbols\n\n// @cpt-begin:cpt-frontx-flow-request-lifecycle-query-client-lifecycle:p2:inst-resolve-app-query-client\ntype RuntimeAwareEndpointDescriptor<TData> = EndpointDescriptor<TData> & {\n fetch(options?: { signal?: AbortSignal; staleTime?: number }): Promise<TData>;\n};\n\ntype AppResolvedQueryClient = {\n app: FrontXApp;\n queryClient: QueryClient;\n};\n\nconst useCommitEffect = typeof globalThis.window === 'undefined' ? useEffect : useLayoutEffect;\n\nexport function resolveFrontXQueryClient(app: FrontXApp): QueryClient | undefined {\n const clientApp = app as QueryClientApp;\n return clientApp[APP_QUERY_CLIENT_SYMBOL] ?? clientApp[APP_QUERY_CLIENT_RESOLVER_SYMBOL]?.();\n}\n\nexport function hasFrontXQueryClientActivator(app: FrontXApp): boolean {\n return typeof (app as QueryClientApp)[APP_QUERY_CLIENT_ACTIVATOR_SYMBOL] === 'function';\n}\n\nexport function activateFrontXQueryClient(app: FrontXApp): QueryClient | undefined {\n const clientApp = app as QueryClientApp;\n return clientApp[APP_QUERY_CLIENT_SYMBOL] ?? clientApp[APP_QUERY_CLIENT_ACTIVATOR_SYMBOL]?.();\n}\n// @cpt-end:cpt-frontx-flow-request-lifecycle-query-client-lifecycle:p2:inst-resolve-app-query-client\n\n// @cpt-begin:cpt-frontx-flow-request-lifecycle-query-client-lifecycle:p2:inst-imperative-cache-bootstrap\n/**\n * Imperatively invalidates cache entries for `target` on the QueryClient bound to `app`.\n * Use from non-React code (e.g. MFE actions); in components prefer `useQueryCache().invalidate`.\n */\nexport async function invalidateQueryCacheForApp(\n app: FrontXApp,\n target: EndpointDescriptor<unknown> | QueryCacheKey\n): Promise<void> {\n const queryClient = resolveFrontXQueryClient(app) ?? activateFrontXQueryClient(app);\n if (!queryClient) {\n throw new Error(\n '[invalidateQueryCacheForApp] No QueryClient on app. Ensure queryCache() or queryCacheShared() is in the plugin chain.'\n );\n }\n await createQueryCache(queryClient).invalidate(target);\n}\n\n/** Resolves the app-bound QueryClient without triggering plugin activation during render. */\nexport function bootstrapFrontXQueryClient(app: FrontXApp): QueryClient | undefined {\n return resolveFrontXQueryClient(app);\n}\n// @cpt-end:cpt-frontx-flow-request-lifecycle-query-client-lifecycle:p2:inst-imperative-cache-bootstrap\n\n// @cpt-begin:cpt-frontx-flow-request-lifecycle-query-client-lifecycle:p2:inst-use-bootstrapped-query-client\nexport function useBootstrappedFrontXQueryClient(app: FrontXApp): QueryClient | undefined {\n const fromApp = useMemo(() => bootstrapFrontXQueryClient(app), [app]);\n const [eventResolvedClient, setEventResolvedClient] = useState<AppResolvedQueryClient | undefined>(\n undefined\n );\n const queryClient =\n fromApp ?? (eventResolvedClient?.app === app ? eventResolvedClient.queryClient : undefined);\n\n useCommitEffect(() => {\n if (fromApp || !hasFrontXQueryClientActivator(app)) {\n return;\n }\n\n const tryResolveQueryClient = () => {\n const nextQueryClient = resolveFrontXQueryClient(app) ?? activateFrontXQueryClient(app);\n if (nextQueryClient) {\n setEventResolvedClient((current) => {\n if (current?.app === app && current.queryClient === nextQueryClient) {\n return current;\n }\n\n return {\n app,\n queryClient: nextQueryClient,\n };\n });\n }\n };\n\n // Only activate after commit so abandoned renders cannot leak retainers/listeners.\n tryResolveQueryClient();\n\n const subscription = subscribeQueryCacheRuntimeChanged(() => {\n tryResolveQueryClient();\n });\n\n return () => {\n subscription.unsubscribe();\n };\n }, [app, fromApp]);\n\n return queryClient;\n}\n// @cpt-end:cpt-frontx-flow-request-lifecycle-query-client-lifecycle:p2:inst-use-bootstrapped-query-client\n\n// @cpt-begin:cpt-frontx-dod-request-lifecycle-query-provider:p2:inst-frontx-query-client-provider\nexport function FrontXQueryClientProvider({\n queryClient,\n children,\n}: Readonly<{\n queryClient: QueryClient | undefined;\n children: React.ReactNode;\n}>) {\n if (!queryClient) {\n return (\n <FrontXQueryClientContext.Provider value={undefined}>\n <QueryClientContext.Provider value={undefined}>{children}</QueryClientContext.Provider>\n </FrontXQueryClientContext.Provider>\n );\n }\n\n return (\n <FrontXQueryClientContext.Provider value={queryClient}>\n <QueryClientProvider client={queryClient}>{children}</QueryClientProvider>\n </FrontXQueryClientContext.Provider>\n );\n}\n// @cpt-end:cpt-frontx-dod-request-lifecycle-query-provider:p2:inst-frontx-query-client-provider\n\n// @cpt-begin:cpt-frontx-dod-request-lifecycle-query-provider:p2:inst-query-client-context-hooks\nexport function useOptionalFrontXQueryClient(): QueryClient | undefined {\n return useContext(FrontXQueryClientContext);\n}\n\nexport function useRequiredFrontXQueryClient(): QueryClient {\n const queryClient = useOptionalFrontXQueryClient();\n if (!queryClient) {\n throw new Error(\n '[FrontXProvider] No query cache available. Add queryCache() or queryCacheShared() to your plugin composition.'\n );\n }\n\n return queryClient;\n}\n// @cpt-end:cpt-frontx-dod-request-lifecycle-query-provider:p2:inst-query-client-context-hooks\n\n// @cpt-begin:implement-endpoint-descriptors:p3:inst-descriptor-fetch-stale-helpers\nfunction buildPageContext<TPage>(\n page: TPage,\n pages: readonly TPage[],\n descriptor: EndpointDescriptor<TPage>,\n descriptors: readonly EndpointDescriptor<TPage>[]\n): ApiInfiniteQueryPageContext<TPage> {\n return {\n page,\n pages,\n descriptor,\n descriptors,\n };\n}\n\nfunction normalizeFetchStaleTime(staleTime: unknown): number | undefined {\n if (staleTime === 'static') {\n return Number.POSITIVE_INFINITY;\n }\n\n return typeof staleTime === 'number' ? staleTime : undefined;\n}\n\nfunction resolveFetchStaleTime<TData>(\n queryClient: QueryClient,\n descriptor: EndpointDescriptor<TData>,\n overrideStaleTime?: number\n): number | undefined {\n return normalizeFetchStaleTime(\n overrideStaleTime ??\n descriptor.staleTime ??\n queryClient.getDefaultOptions().queries?.staleTime\n );\n}\n\nfunction fetchDescriptor<TData>(\n descriptor: EndpointDescriptor<TData>,\n options?: { signal?: AbortSignal; staleTime?: number }\n): Promise<TData> {\n return (descriptor as RuntimeAwareEndpointDescriptor<TData>).fetch(options);\n}\n// @cpt-end:implement-endpoint-descriptors:p3:inst-descriptor-fetch-stale-helpers\n\n// @cpt-begin:cpt-frontx-flow-request-lifecycle-use-api-query:p2:inst-delegate-frontx-use-query\nexport function useFrontXQuery<TData = unknown, TError = Error>(\n descriptor: EndpointDescriptor<TData>,\n overrides?: ApiQueryOverrides\n) {\n const queryClient = useRequiredFrontXQueryClient();\n const staleTime = resolveFetchStaleTime(queryClient, descriptor, overrides?.staleTime);\n const result = useQuery<TData, TError>({\n queryKey: descriptor.key as unknown[],\n queryFn: ({ signal }) => fetchDescriptor(descriptor, { signal, staleTime }),\n staleTime: overrides?.staleTime ?? descriptor.staleTime,\n gcTime: overrides?.gcTime ?? descriptor.gcTime,\n });\n\n return {\n data: result.data,\n error: result.error,\n isLoading: result.isLoading,\n isFetching: result.isFetching,\n isError: result.isError,\n refetch: result.refetch,\n };\n}\n// @cpt-end:cpt-frontx-flow-request-lifecycle-use-api-query:p2:inst-delegate-frontx-use-query\n\n// @cpt-begin:cpt-frontx-flow-request-lifecycle-use-api-query:p2:inst-delegate-frontx-use-suspense-query\nexport function useFrontXSuspenseQuery<TData = unknown, TError = Error>(\n descriptor: EndpointDescriptor<TData>,\n overrides?: ApiQueryOverrides\n) {\n const queryClient = useRequiredFrontXQueryClient();\n const staleTime = resolveFetchStaleTime(queryClient, descriptor, overrides?.staleTime);\n const result = useSuspenseQuery<TData, TError>({\n queryKey: descriptor.key as unknown[],\n queryFn: ({ signal }) => fetchDescriptor(descriptor, { signal, staleTime }),\n staleTime: overrides?.staleTime ?? descriptor.staleTime,\n gcTime: overrides?.gcTime ?? descriptor.gcTime,\n });\n\n return {\n data: result.data,\n error: result.error,\n isFetching: result.isFetching,\n refetch: async () => {\n await result.refetch();\n },\n };\n}\n// @cpt-end:cpt-frontx-flow-request-lifecycle-use-api-query:p2:inst-delegate-frontx-use-suspense-query\n\n// @cpt-begin:cpt-frontx-flow-request-lifecycle-use-api-query:p2:inst-delegate-frontx-use-infinite-query\nexport function useFrontXInfiniteQuery<TPage = unknown, TError = Error>(\n options: ApiInfiniteQueryOptions<TPage>\n) {\n const queryClient = useRequiredFrontXQueryClient();\n const result = useInfiniteQuery<\n TPage,\n TError,\n readonly TPage[],\n readonly unknown[],\n EndpointDescriptor<TPage>\n >({\n queryKey: options.initialPage.key,\n initialPageParam: options.initialPage,\n queryFn: ({ pageParam, signal }) =>\n fetchDescriptor(pageParam, {\n signal,\n staleTime: resolveFetchStaleTime(queryClient, pageParam, options.staleTime),\n }),\n getNextPageParam: (\n lastPage,\n allPages,\n lastPageDescriptor,\n allPageDescriptors\n ) =>\n options.getNextPage(\n buildPageContext(\n lastPage,\n allPages,\n lastPageDescriptor,\n allPageDescriptors\n )\n ),\n getPreviousPageParam: options.getPreviousPage\n ? (firstPage, allPages, firstPageDescriptor, allPageDescriptors) =>\n options.getPreviousPage?.(\n buildPageContext(\n firstPage,\n allPages,\n firstPageDescriptor,\n allPageDescriptors\n )\n )\n : undefined,\n select: (data) => data.pages,\n staleTime: options.staleTime ?? options.initialPage.staleTime,\n gcTime: options.gcTime ?? options.initialPage.gcTime,\n maxPages: options.maxPages,\n });\n\n return {\n data: result.data,\n error: result.error,\n isLoading: result.isLoading,\n isFetching: result.isFetching,\n isError: result.isError,\n hasNextPage: result.hasNextPage ?? false,\n hasPreviousPage: result.hasPreviousPage ?? false,\n isFetchingNextPage: result.isFetchingNextPage,\n isFetchingPreviousPage: result.isFetchingPreviousPage,\n fetchNextPage: async () => {\n await result.fetchNextPage();\n },\n fetchPreviousPage: async () => {\n await result.fetchPreviousPage();\n },\n refetch: async () => {\n await result.refetch();\n },\n };\n}\n// @cpt-end:cpt-frontx-flow-request-lifecycle-use-api-query:p2:inst-delegate-frontx-use-infinite-query\n\n// @cpt-begin:cpt-frontx-flow-request-lifecycle-use-api-query:p2:inst-delegate-frontx-use-suspense-infinite-query\nexport function useFrontXSuspenseInfiniteQuery<TPage = unknown, TError = Error>(\n options: ApiInfiniteQueryOptions<TPage>\n) {\n const queryClient = useRequiredFrontXQueryClient();\n const result = useSuspenseInfiniteQuery<\n TPage,\n TError,\n readonly TPage[],\n readonly unknown[],\n EndpointDescriptor<TPage>\n >({\n queryKey: options.initialPage.key,\n initialPageParam: options.initialPage,\n queryFn: ({ pageParam, signal }) =>\n fetchDescriptor(pageParam, {\n signal,\n staleTime: resolveFetchStaleTime(queryClient, pageParam, options.staleTime),\n }),\n getNextPageParam: (\n lastPage,\n allPages,\n lastPageDescriptor,\n allPageDescriptors\n ) =>\n options.getNextPage(\n buildPageContext(\n lastPage,\n allPages,\n lastPageDescriptor,\n allPageDescriptors\n )\n ),\n getPreviousPageParam: options.getPreviousPage\n ? (firstPage, allPages, firstPageDescriptor, allPageDescriptors) =>\n options.getPreviousPage?.(\n buildPageContext(\n firstPage,\n allPages,\n firstPageDescriptor,\n allPageDescriptors\n )\n )\n : undefined,\n select: (data) => data.pages,\n staleTime: options.staleTime ?? options.initialPage.staleTime,\n gcTime: options.gcTime ?? options.initialPage.gcTime,\n maxPages: options.maxPages,\n });\n\n return {\n data: result.data,\n error: result.error,\n isFetching: result.isFetching,\n hasNextPage: result.hasNextPage ?? false,\n hasPreviousPage: result.hasPreviousPage ?? false,\n isFetchingNextPage: result.isFetchingNextPage,\n isFetchingPreviousPage: result.isFetchingPreviousPage,\n fetchNextPage: async () => {\n await result.fetchNextPage();\n },\n fetchPreviousPage: async () => {\n await result.fetchPreviousPage();\n },\n refetch: async () => {\n await result.refetch();\n },\n };\n}\n// @cpt-end:cpt-frontx-flow-request-lifecycle-use-api-query:p2:inst-delegate-frontx-use-suspense-infinite-query\n\n// @cpt-begin:cpt-frontx-flow-request-lifecycle-use-api-mutation:p2:inst-delegate-frontx-use-mutation\nexport function useFrontXMutation<\n TData = unknown,\n TError = Error,\n TVariables = void,\n TContext = unknown,\n>(\n options: UseApiMutationOptions<TData, TError, TVariables, TContext>,\n callbackCtx: MutationCallbackContext\n) {\n useRequiredFrontXQueryClient();\n\n const latestRef = useLatest({ options, callbackCtx });\n const fetchAbortControllersRef = React.useRef<Set<AbortController>>(new Set());\n\n // Effect event: reads abortOnUnmount from the most recent render, not\n // whatever option value was current when the unmount effect was set up.\n const abortFetchesOnUnmount = React.useEffectEvent(() => {\n if (options.abortOnUnmount) {\n for (const controller of fetchAbortControllersRef.current) {\n controller.abort();\n }\n fetchAbortControllersRef.current.clear();\n }\n });\n\n React.useEffect(() => {\n return () => {\n abortFetchesOnUnmount();\n };\n }, []);\n\n const mutationFn = React.useCallback((variables: TVariables, context: MutationFunctionContext) => {\n const cancelOnSupersede = latestRef.current.options.cancelOnSupersede;\n if (cancelOnSupersede) {\n for (const controller of fetchAbortControllersRef.current) {\n controller.abort();\n }\n fetchAbortControllersRef.current.clear();\n }\n\n const controller = new AbortController();\n fetchAbortControllersRef.current.add(controller);\n\n const librarySignal = (context as MutationFunctionContext & { signal?: AbortSignal }).signal;\n if (cancelOnSupersede && librarySignal) {\n if (librarySignal.aborted) {\n controller.abort();\n } else {\n librarySignal.addEventListener('abort', () => controller.abort(), { once: true });\n }\n }\n\n return latestRef.current.options.endpoint\n .fetch(variables, { signal: controller.signal })\n .finally(() => {\n fetchAbortControllersRef.current.delete(controller);\n });\n // latestRef's identity never changes (useLatest returns a stable ref\n // object) — listing it satisfies exhaustive-deps without recreating this\n // callback on every render.\n }, [latestRef]);\n\n const onMutate = React.useCallback((variables: TVariables, _context: MutationFunctionContext) => {\n const current = latestRef.current;\n if (!current.options.onMutate) {\n return undefined as TContext;\n }\n\n return current.options.onMutate(variables, current.callbackCtx);\n // latestRef's identity never changes — see mutationFn above.\n }, [latestRef]);\n\n const onSuccess = React.useCallback((data: TData, variables: TVariables, context: TContext | undefined) => {\n const current = latestRef.current;\n return current.options.onSuccess?.(data, variables, context, current.callbackCtx);\n // latestRef's identity never changes — see mutationFn above.\n }, [latestRef]);\n\n const onError = React.useCallback((error: TError, variables: TVariables, context: TContext | undefined) => {\n const current = latestRef.current;\n return current.options.onError?.(error, variables, context, current.callbackCtx);\n // latestRef's identity never changes — see mutationFn above.\n }, [latestRef]);\n\n const onSettled = React.useCallback((\n data: TData | undefined,\n error: TError | null,\n variables: TVariables,\n context: TContext | undefined\n ) => {\n const current = latestRef.current;\n return current.options.onSettled?.(\n data,\n error,\n variables,\n context,\n current.callbackCtx\n );\n // latestRef's identity never changes — see mutationFn above.\n }, [latestRef]);\n\n const mutation = useMutation<TData, TError, TVariables, TContext>({\n mutationFn,\n onMutate: options.onMutate ? onMutate : undefined,\n onSuccess: options.onSuccess ? onSuccess : undefined,\n onError: options.onError ? onError : undefined,\n onSettled: options.onSettled ? onSettled : undefined,\n });\n\n return {\n mutate: mutation.mutate as (variables: TVariables) => void,\n mutateAsync: mutation.mutateAsync as (variables: TVariables) => Promise<TData>,\n isPending: mutation.isPending,\n error: mutation.error,\n data: mutation.data,\n reset: mutation.reset,\n };\n}\n// @cpt-end:cpt-frontx-flow-request-lifecycle-use-api-mutation:p2:inst-delegate-frontx-use-mutation\n","/**\n * QueryCache — restricted interface for interacting with the shared QueryClient.\n *\n * MFEs and screen-set components access the cache only through this sanctioned\n * public interface. It is injected as { queryCache } into useApiMutation\n * callbacks and also returned by useQueryCache() for controlled imperative\n * cache access.\n */\n// @cpt-dod:cpt-frontx-dod-request-lifecycle-use-api-mutation:p2\n// @cpt-flow:cpt-frontx-flow-request-lifecycle-use-api-mutation:p2:inst-create-query-cache\n// @cpt-FEATURE:implement-endpoint-descriptors:p3\n\nimport type { EndpointDescriptor } from '@gears-frontx/framework';\nimport { eventBus } from '@gears-frontx/framework';\nimport { type QueryClient, type QueryState } from '@tanstack/react-query';\n\nexport type QueryCacheKey = readonly unknown[];\nexport type QueryCacheRefetchMode = 'active' | 'inactive' | 'all' | 'none';\nexport type QueryCacheInvalidateTarget =\n | EndpointDescriptor<unknown>\n | QueryCacheKey\n | null\n | undefined;\n\nexport interface QueryCacheState<TData = unknown, TError = Error> {\n data: TData | undefined;\n dataUpdatedAt: number;\n error: TError | null;\n errorUpdatedAt: number;\n fetchFailureCount: number;\n fetchFailureReason: TError | null;\n fetchStatus: 'fetching' | 'paused' | 'idle';\n isInvalidated: boolean;\n status: 'pending' | 'error' | 'success';\n}\n\nexport type QueryCacheInvalidateFilters = {\n queryKey?: QueryCacheInvalidateTarget;\n exact?: boolean;\n refetchType?: QueryCacheRefetchMode;\n};\n\ntype QueryCacheUpdater<T> = T | ((old: T | undefined) => T | undefined);\n\ntype CacheInvalidateEvent = {\n queryKey: QueryCacheKey;\n exact?: boolean;\n refetchType?: QueryCacheRefetchMode;\n source?: string;\n};\n\ntype CacheSetEvent = {\n queryKey: QueryCacheKey;\n dataOrUpdater: QueryCacheUpdater<unknown>;\n source?: string;\n};\n\ntype CacheRemoveEvent = {\n queryKey: QueryCacheKey;\n source?: string;\n};\n\nconst QUERY_CLIENT_BROADCAST_TARGET = Symbol.for('frontx:query-cache:broadcast-target');\nconst QUERY_CLIENT_BROADCAST_COUNTER = Symbol.for('frontx:query-cache:broadcast-counter');\n\ntype QueryClientWithMetadata = QueryClient & {\n [QUERY_CLIENT_BROADCAST_TARGET]?: string;\n};\n\ntype QueryClientCounterHost = typeof globalThis & {\n [QUERY_CLIENT_BROADCAST_COUNTER]?: number;\n};\n\nfunction emitCacheEvent(event: string, payload: unknown): void {\n (eventBus.emit as (eventType: string, payload: unknown) => void)(event, payload);\n}\n\nfunction ensureBroadcastSource(queryClient: QueryClient): string {\n const clientWithMetadata = queryClient as QueryClientWithMetadata;\n const existingSource = clientWithMetadata[QUERY_CLIENT_BROADCAST_TARGET];\n if (typeof existingSource === 'string' && existingSource.length > 0) {\n return existingSource;\n }\n\n const host = globalThis as QueryClientCounterHost;\n const nextCounter = (host[QUERY_CLIENT_BROADCAST_COUNTER] ?? 0) + 1;\n host[QUERY_CLIENT_BROADCAST_COUNTER] = nextCounter;\n\n const source = `query-cache-${nextCounter}`;\n clientWithMetadata[QUERY_CLIENT_BROADCAST_TARGET] = source;\n return source;\n}\n\n// @cpt-begin:implement-endpoint-descriptors:p3:inst-resolve-key\nexport function resolveKey(target: EndpointDescriptor<unknown> | QueryCacheKey): readonly unknown[] {\n if (\n target !== null &&\n typeof target === 'object' &&\n !Array.isArray(target) &&\n 'key' in target &&\n 'fetch' in target &&\n Array.isArray(target.key) &&\n typeof target.fetch === 'function'\n ) {\n return target.key;\n }\n\n return target as readonly unknown[];\n}\n// @cpt-end:implement-endpoint-descriptors:p3:inst-resolve-key\n\n// @cpt-begin:cpt-frontx-dod-request-lifecycle-use-api-mutation:p2:inst-query-cache-interface\nexport interface QueryCache {\n get<T>(queryKey: EndpointDescriptor<unknown> | QueryCacheKey): T | undefined;\n getState<TData = unknown, TError = Error>(\n queryKey: EndpointDescriptor<unknown> | QueryCacheKey\n ): QueryCacheState<TData, TError> | undefined;\n set<T>(\n queryKey: EndpointDescriptor<unknown> | QueryCacheKey,\n dataOrUpdater: T | ((old: T | undefined) => T | undefined)\n ): void;\n cancel(queryKey: EndpointDescriptor<unknown> | QueryCacheKey): Promise<void>;\n invalidate(queryKey: EndpointDescriptor<unknown> | QueryCacheKey): Promise<void>;\n invalidateMany(filters?: QueryCacheInvalidateFilters | null): Promise<void>;\n remove(queryKey: EndpointDescriptor<unknown> | QueryCacheKey): void;\n}\n// @cpt-end:cpt-frontx-dod-request-lifecycle-use-api-mutation:p2:inst-query-cache-interface\n\n// @cpt-begin:cpt-frontx-dod-request-lifecycle-use-api-mutation:p2:inst-mutation-callback-context\nexport interface MutationCallbackContext {\n queryCache: QueryCache;\n}\n// @cpt-end:cpt-frontx-dod-request-lifecycle-use-api-mutation:p2:inst-mutation-callback-context\n\nfunction toQueryUpdater<T>(\n dataOrUpdater: QueryCacheUpdater<T>\n): (old: T | undefined) => T | undefined {\n if (typeof dataOrUpdater === 'function') {\n return dataOrUpdater as (old: T | undefined) => T | undefined;\n }\n\n return () => dataOrUpdater;\n}\n\nfunction mapQueryState<TData, TError = Error>(\n state: QueryState<TData, TError>\n): QueryCacheState<TData, TError> {\n return {\n data: state.data,\n dataUpdatedAt: state.dataUpdatedAt,\n error: state.error,\n errorUpdatedAt: state.errorUpdatedAt,\n fetchFailureCount: state.fetchFailureCount,\n fetchFailureReason: state.fetchFailureReason,\n fetchStatus: state.fetchStatus,\n isInvalidated: state.isInvalidated,\n status: state.status,\n };\n}\n\n// @cpt-begin:implement-endpoint-descriptors:p3:inst-create-query-cache\nexport function createQueryCache(queryClient: QueryClient): QueryCache {\n return {\n get: <T,>(key: EndpointDescriptor<unknown> | QueryCacheKey): T | undefined => {\n return queryClient.getQueryData<T>(resolveKey(key));\n },\n getState: <TData = unknown, TError = Error>(key: EndpointDescriptor<unknown> | QueryCacheKey) => {\n const state = queryClient.getQueryState<TData, TError>(resolveKey(key));\n return state ? mapQueryState(state) : undefined;\n },\n set: <T,>(key: EndpointDescriptor<unknown> | QueryCacheKey, dataOrUpdater: QueryCacheUpdater<T>): void => {\n const resolvedKey = resolveKey(key);\n queryClient.setQueryData<T>(resolvedKey, toQueryUpdater(dataOrUpdater));\n emitCacheEvent('cache/set', {\n queryKey: resolvedKey,\n dataOrUpdater: dataOrUpdater as QueryCacheUpdater<unknown>,\n source: ensureBroadcastSource(queryClient),\n } satisfies CacheSetEvent);\n },\n cancel: (key: EndpointDescriptor<unknown> | QueryCacheKey): Promise<void> => {\n return queryClient.cancelQueries({ queryKey: resolveKey(key) });\n },\n invalidate: (key: EndpointDescriptor<unknown> | QueryCacheKey): Promise<void> => {\n const resolvedKey = resolveKey(key);\n const result = queryClient.invalidateQueries({ queryKey: resolvedKey });\n emitCacheEvent('cache/invalidate', {\n queryKey: resolvedKey,\n source: ensureBroadcastSource(queryClient),\n } satisfies CacheInvalidateEvent);\n return result;\n },\n invalidateMany: (filters): Promise<void> => {\n if (filters?.queryKey == null) {\n return Promise.resolve();\n }\n\n const resolvedKey = resolveKey(filters.queryKey);\n if (!Array.isArray(resolvedKey) || resolvedKey.length === 0) {\n return Promise.resolve();\n }\n\n const payload = {\n ...filters,\n queryKey: resolvedKey,\n };\n const result = queryClient.invalidateQueries(payload);\n emitCacheEvent('cache/invalidate', {\n ...payload,\n source: ensureBroadcastSource(queryClient),\n } satisfies CacheInvalidateEvent);\n return result;\n },\n remove: (key: EndpointDescriptor<unknown> | QueryCacheKey): void => {\n const resolvedKey = resolveKey(key);\n queryClient.removeQueries({ queryKey: resolvedKey });\n emitCacheEvent('cache/remove', {\n queryKey: resolvedKey,\n source: ensureBroadcastSource(queryClient),\n } satisfies CacheRemoveEvent);\n },\n };\n}\n// @cpt-end:implement-endpoint-descriptors:p3:inst-create-query-cache\n","/**\n * useLatest - keeps a ref pinned to the most recently rendered value\n *\n * A handful of hooks/components in this package need to read the current\n * value of a prop or option from inside a callback or effect-cleanup closure\n * that must NOT re-run every time that value changes (e.g. a stable\n * useCallback with `[]` deps, or a mount/unmount effect keyed on identity\n * rather than on every option). Stashing the value in a ref sidesteps the\n * closure staleness without pulling the value into the dependency array.\n *\n * The write happens inside a deps-less effect (runs after every commit)\n * rather than during render, because refs must not be mutated while\n * rendering: render can be invoked more than once per commit (React\n * StrictMode's double-invoke, and future concurrent-rendering paths that\n * may discard a render), so a render-time write can leave the ref out of\n * sync with what was actually committed to the DOM. A deps-less effect\n * runs exactly once per real commit, so the ref always reflects the value\n * that was last rendered.\n */\n\nimport { useEffect, useRef, type RefObject } from 'react';\n\n/**\n * Returns a ref that always holds the most recently rendered `value`.\n *\n * The ref identity is stable across renders (same object returned every\n * time), so it is safe to add to a `useCallback`/`useEffect` dependency\n * array without causing the callback/effect to be recreated.\n */\nexport function useLatest<T>(value: T): RefObject<T> {\n const ref = useRef(value);\n\n // Deps-less: must run after every render so `ref.current` never lags\n // behind the value that was just committed. See module doc for why this\n // write cannot happen during render itself.\n useEffect(() => {\n ref.current = value;\n });\n\n return ref;\n}\n","import { useEffect, useState } from 'react';\nimport type {\n AccessQuery,\n AccessRecord,\n AuthRuntime,\n FrontXApp,\n} from '@gears-frontx/framework';\nimport { useFrontX } from '../FrontXContext';\nimport type { UseCanAccessResult } from '../types';\n\n/**\n * Stable string key for an AccessQuery.\n * Record keys are sorted so { b:1, a:2 } and { a:2, b:1 } yield the same key.\n * Values include an explicit type prefix to avoid collisions:\n * 1 !== \"1\", null !== \"null\", true !== \"true\".\n */\nfunction serializeRecordValue(value: AccessRecord[string]): string {\n if (value === null) return 'n:';\n if (typeof value === 'string') return `s:${value}`;\n if (typeof value === 'number') {\n // Preserve -0 distinction for completeness.\n return `d:${Object.is(value, -0) ? '-0' : String(value)}`;\n }\n return value ? 'b:1' : 'b:0';\n}\n\nfunction accessQueryKey(query: AccessQuery): string {\n const { action, resource, record } = query;\n // JSON-encode the tuple so delimiter characters in any component\n // (action / resource / record keys / string values) cannot collide.\n // Using Object.entries avoids dynamic bracket access on `record` (static\n // analyzers flag `record[k]` as a potential object-injection sink).\n const normalizedRecord = record\n ? Object.entries(record)\n .sort(([a], [b]) => a.localeCompare(b))\n .map(([k, v]) => [k, serializeRecordValue(v)] as const)\n : null;\n return JSON.stringify([action, resource, normalizedRecord]);\n}\n\ntype FrontXAuthAppContract = FrontXApp & {\n auth?: AuthRuntime;\n};\n\nfunction getAuthRuntime(app: FrontXApp): AuthRuntime | null {\n return (app as FrontXAuthAppContract).auth ?? null;\n}\n\n// Module-level constant so the no-auth-runtime denial keeps a stable identity\n// across renders — consumers can put the hook result in dependency lists\n// without re-firing every render.\nconst DENIED_NO_AUTH: UseCanAccessResult = { allow: false, isResolving: false };\n\n/**\n * Declarative RBAC guard hook.\n *\n * Pessimistic: `allow` is false until an explicit 'allow' decision arrives.\n * Aborts the in-flight canAccess call on unmount and on query change.\n *\n * State machine:\n * mount -> Pending (allow=false, isResolving=true)\n * Pending -> 'allow' -> Allowed (allow=true, isResolving=false)\n * Pending -> 'deny' -> Denied (allow=false, isResolving=false)\n * Pending -> error -> Denied (allow=false, isResolving=false)\n * Allowed -> query-change -> Pending (re-pessimize)\n * Denied -> query-change -> Pending (re-pessimize)\n */\nexport function useCanAccess<TRecord extends AccessRecord = AccessRecord>(\n query: AccessQuery<TRecord>,\n): UseCanAccessResult {\n const app = useFrontX();\n\n // Resolved once per `app` change; read here (not just inside the effect) so both the\n // \"no auth runtime\" case and the \"pending\" reset below can be derived/adjusted at\n // render time instead of requiring a synchronous setState from the effect.\n const auth = getAuthRuntime(app);\n\n const stableKey = accessQueryKey(query as AccessQuery);\n\n // Derived state: store the query value whose key matches `stableKey`. We\n // refresh it during render whenever `stableKey` changes (React derived-state\n // pattern) so the effect can depend on the stored value directly — its\n // referential identity tracks the access intent, not the parent render cycle.\n const [stableQuery, setStableQuery] = useState<AccessQuery>(() => query as AccessQuery);\n // Tracks the (auth, stableKey) combination the effect below was last run for —\n // exactly its dependency list — so every input that would restart the access check\n // also re-pessimizes `result` here, during render, instead of via a setState call\n // inside the effect.\n //\n // `app` is not part of it. The decision is the auth runtime's, and a host that\n // rebuilds its app object around the same runtime has changed nothing the check\n // reads; tracking it would re-pessimize an answered guard back to Pending and\n // ask the same question again.\n const [runState, setRunState] = useState({ auth, stableKey });\n const [result, setResult] = useState<UseCanAccessResult>({ allow: false, isResolving: true });\n\n if (runState.auth !== auth || runState.stableKey !== stableKey) {\n setRunState({ auth, stableKey });\n setStableQuery(query as AccessQuery);\n // Re-pessimize at render time: every (auth, stableKey) combination\n // the effect below runs for enters Pending here, before the async\n // decision starts.\n setResult({ allow: false, isResolving: true });\n }\n\n useEffect(() => {\n if (!auth) {\n // No auth runtime on the app: the returned result is derived below\n // (`auth ? result : DENIED_NO_AUTH`), so there is nothing to synchronize here.\n return;\n }\n\n // `result` is re-pessimized during render above for every\n // (auth, stableKey) combination this effect runs for — no setState needed\n // here before starting the async decision.\n let alive = true;\n const controller = new AbortController();\n\n void auth\n .canAccess(stableQuery, { signal: controller.signal })\n .then((decision) => {\n if (alive) {\n setResult({ allow: decision === 'allow', isResolving: false });\n }\n })\n .catch(() => {\n if (alive) {\n setResult({ allow: false, isResolving: false });\n }\n });\n\n return () => {\n alive = false;\n controller.abort();\n };\n }, [auth, stableQuery]);\n\n return auth ? result : DENIED_NO_AUTH;\n}\n","// @cpt-FEATURE:cpt-frontx-feature-auth-plugin:p1\n// @cpt-flow:cpt-frontx-flow-auth-plugin-rbac-guard:p1\nimport type { ReactElement } from 'react';\nimport type { AccessRecord } from '@gears-frontx/framework';\nimport { useCanAccess } from '../hooks/useCanAccess';\nimport type { CanAccessProps } from '../types';\n\n/**\n * Declarative RBAC guard component.\n *\n * Pessimistic: renders `denied` (or `loading` if provided) until an explicit\n * 'allow' decision arrives from app.auth.canAccess. Only renders `allowed`\n * after a confirmed allow.\n *\n * Example:\n * <CanAccess\n * query={{ action: AppAction.InvoicesRead, resource: ResourceKind.Invoice }}\n * allowed={<InvoiceList />}\n * denied={<AccessDenied />}\n * loading={<Spinner />}\n * />\n */\nexport function CanAccess<TRecord extends AccessRecord = AccessRecord>({\n query,\n allowed,\n denied = null,\n loading,\n}: CanAccessProps<TRecord>): ReactElement | null {\n // @cpt-begin:cpt-frontx-flow-auth-plugin-rbac-guard:p1:inst-component-render\n const { allow, isResolving } = useCanAccess(query);\n\n if (isResolving) {\n return (loading !== undefined ? loading : denied) as ReactElement | null;\n }\n\n return (allow ? allowed : denied) as ReactElement | null;\n // @cpt-end:cpt-frontx-flow-auth-plugin-rbac-guard:p1:inst-component-render\n}\n","/**\n * useAppDispatch Hook - Type-safe dispatch hook\n *\n * React Layer: L3\n */\n// @cpt-flow:cpt-frontx-flow-react-bindings-use-dispatch:p1\n// @cpt-dod:cpt-frontx-dod-react-bindings-redux-hooks:p1\n\nimport { useDispatch } from 'react-redux';\nimport type { AppDispatch } from '@gears-frontx/framework';\n\n/**\n * Type-safe dispatch hook.\n *\n * @returns The typed dispatch function\n *\n * @example\n * ```tsx\n * const dispatch = useAppDispatch();\n * dispatch(someAction());\n * ```\n */\n// @cpt-begin:cpt-frontx-flow-react-bindings-use-dispatch:p1:inst-call-dispatch\n// @cpt-begin:cpt-frontx-flow-react-bindings-use-dispatch:p1:inst-delegate-dispatch\n// @cpt-begin:cpt-frontx-flow-react-bindings-use-dispatch:p1:inst-use-dispatch\n// @cpt-begin:cpt-frontx-dod-react-bindings-redux-hooks:p1:inst-use-dispatch\nexport function useAppDispatch(): AppDispatch {\n // Use untyped useDispatch and cast the result\n // This avoids type constraint issues with react-redux's generic\n return useDispatch() as AppDispatch;\n}\n// @cpt-end:cpt-frontx-flow-react-bindings-use-dispatch:p1:inst-call-dispatch\n// @cpt-end:cpt-frontx-flow-react-bindings-use-dispatch:p1:inst-delegate-dispatch\n// @cpt-end:cpt-frontx-flow-react-bindings-use-dispatch:p1:inst-use-dispatch\n// @cpt-end:cpt-frontx-dod-react-bindings-redux-hooks:p1:inst-use-dispatch\n","/**\n * useAppSelector Hook - Type-safe selector hook\n *\n * React Layer: L3\n */\n// @cpt-flow:cpt-frontx-flow-react-bindings-use-selector:p1\n// @cpt-dod:cpt-frontx-dod-react-bindings-redux-hooks:p1\n\nimport { useSelector, type TypedUseSelectorHook } from 'react-redux';\nimport type { RootState } from '@gears-frontx/framework';\n\n/**\n * Type-safe selector hook.\n *\n * @example\n * ```tsx\n * const activeScreen = useAppSelector(selectActiveScreen);\n * const menuCollapsed = useAppSelector(selectMenuCollapsed);\n * ```\n */\n// @cpt-begin:cpt-frontx-flow-react-bindings-use-selector:p1:inst-call-selector\n// @cpt-begin:cpt-frontx-flow-react-bindings-use-selector:p1:inst-delegate-selector\n// @cpt-begin:cpt-frontx-flow-react-bindings-use-selector:p1:inst-return-state\n// @cpt-begin:cpt-frontx-flow-react-bindings-use-selector:p1:inst-rerender-on-change\n// @cpt-begin:cpt-frontx-dod-react-bindings-redux-hooks:p1:inst-use-selector\nexport const useAppSelector: TypedUseSelectorHook<RootState> = useSelector;\n// @cpt-end:cpt-frontx-flow-react-bindings-use-selector:p1:inst-call-selector\n// @cpt-end:cpt-frontx-flow-react-bindings-use-selector:p1:inst-delegate-selector\n// @cpt-end:cpt-frontx-flow-react-bindings-use-selector:p1:inst-return-state\n// @cpt-end:cpt-frontx-flow-react-bindings-use-selector:p1:inst-rerender-on-change\n// @cpt-end:cpt-frontx-dod-react-bindings-redux-hooks:p1:inst-use-selector\n","/**\n * useTranslation Hook - Translation utilities\n *\n * React Layer: L3\n */\n// @cpt-flow:cpt-frontx-flow-react-bindings-use-translation:p1\n// @cpt-dod:cpt-frontx-dod-react-bindings-translation-hook:p1\n\nimport { useMemo, useCallback, useSyncExternalStore } from 'react';\nimport type { Language } from '@gears-frontx/framework';\nimport { useFrontX } from '../FrontXContext';\nimport type { UseTranslationReturn } from '../types';\n\n/**\n * Hook for accessing translation utilities.\n *\n * @returns Translation utilities\n *\n * @example\n * ```tsx\n * const { t, language, setLanguage, isRTL } = useTranslation();\n *\n * return (\n * <div dir={isRTL ? 'rtl' : 'ltr'}>\n * <h1>{t('common:app.title')}</h1>\n * <p>{t('common:app.welcome', { name: 'John' })}</p>\n * </div>\n * );\n * ```\n */\n// @cpt-begin:cpt-frontx-flow-react-bindings-use-translation:p1:inst-call-translation\n// @cpt-begin:cpt-frontx-dod-react-bindings-translation-hook:p1:inst-call-translation\nexport function useTranslation(): UseTranslationReturn {\n // @cpt-begin:cpt-frontx-flow-react-bindings-use-translation:p1:inst-read-i18n-registry\n const app = useFrontX();\n const { i18nRegistry } = app;\n // @cpt-end:cpt-frontx-flow-react-bindings-use-translation:p1:inst-read-i18n-registry\n\n // @cpt-begin:cpt-frontx-flow-react-bindings-use-translation:p1:inst-subscribe-i18n\n // @cpt-begin:cpt-frontx-flow-react-bindings-use-translation:p1:inst-rerender-on-lang-change\n // Subscribe to translation changes using useSyncExternalStore\n // Uses version counter to trigger re-renders when translations change\n const version = useSyncExternalStore(\n useCallback(\n (callback: () => void) => {\n // Subscribe to translation changes (new translations registered)\n return i18nRegistry.subscribe(callback);\n },\n [i18nRegistry]\n ),\n () => i18nRegistry.getVersion(),\n () => i18nRegistry.getVersion()\n );\n // @cpt-end:cpt-frontx-flow-react-bindings-use-translation:p1:inst-subscribe-i18n\n // @cpt-end:cpt-frontx-flow-react-bindings-use-translation:p1:inst-rerender-on-lang-change\n\n // Get current language (memoized to avoid unnecessary recalculations)\n // version is used to trigger recalculation when translations change\n const language = useMemo(() => {\n void version; // Trigger recalculation when version changes\n return i18nRegistry.getLanguage();\n }, [i18nRegistry, version]);\n\n // Translation function\n const t = useCallback(\n (key: string, params?: Record<string, string | number | boolean>) => {\n return i18nRegistry.t(key, params);\n },\n [i18nRegistry]\n );\n\n // @cpt-begin:cpt-frontx-flow-react-bindings-use-translation:p1:inst-set-language\n // Set language via framework action (emits event bus for MFE propagation)\n const setLanguage = useCallback(\n (lang: Language) => {\n if (app.actions.setLanguage) {\n app.actions.setLanguage({ language: lang });\n }\n },\n [app.actions]\n );\n // @cpt-end:cpt-frontx-flow-react-bindings-use-translation:p1:inst-set-language\n\n // Check RTL - recomputes when language changes\n const isRTL = useMemo(() => {\n // Reference language to trigger recalculation on language change\n void language;\n return i18nRegistry.isRTL();\n }, [i18nRegistry, language]);\n\n // @cpt-begin:cpt-frontx-flow-react-bindings-use-translation:p1:inst-return-translation-api\n return {\n t,\n language,\n setLanguage,\n isRTL,\n };\n // @cpt-end:cpt-frontx-flow-react-bindings-use-translation:p1:inst-return-translation-api\n}\n// @cpt-end:cpt-frontx-flow-react-bindings-use-translation:p1:inst-call-translation\n// @cpt-end:cpt-frontx-dod-react-bindings-translation-hook:p1:inst-call-translation\n","/**\n * useScreenTranslations Hook - Screen-level translation loading\n *\n * React Layer: L3\n */\n// @cpt-flow:cpt-frontx-flow-react-bindings-use-screen-translations:p1\n// @cpt-algo:cpt-frontx-algo-react-bindings-load-screen-translations:p1\n// @cpt-state:cpt-frontx-state-react-bindings-screen-translation:p1\n// @cpt-dod:cpt-frontx-dod-react-bindings-screen-translation-hook:p1\n\nimport { useState, useEffect, useMemo, useCallback, useSyncExternalStore } from 'react';\nimport type { TranslationMap, TranslationLoader } from '@gears-frontx/framework';\nimport { useFrontX } from '../FrontXContext';\nimport type { UseScreenTranslationsReturn } from '../types';\n\n// Re-export TranslationMap for consumers who need it\nexport type { TranslationMap };\n\n/**\n * Check if the input is a TranslationLoader function (from I18nRegistry.createLoader)\n * vs a TranslationMap object\n */\nfunction isTranslationLoader(\n input: TranslationMap | TranslationLoader\n): input is TranslationLoader {\n return typeof input === 'function';\n}\n\n/**\n * Hook for loading screen-level translations.\n * Use this in screen components to lazy-load translations.\n * Automatically reloads translations when language changes.\n *\n * @param screensetId - The screenset ID\n * @param screenId - The screen ID\n * @param translations - Either a TranslationMap object or a TranslationLoader function\n * (from I18nRegistry.createLoader)\n * @returns Loading state\n *\n * @example\n * ```tsx\n * // Option 1: Using I18nRegistry.createLoader (recommended)\n * const translations = I18nRegistry.createLoader({\n * en: () => import('./i18n/en.json'),\n * es: () => import('./i18n/es.json'),\n * });\n *\n * // Option 2: Using raw TranslationMap\n * const translations = {\n * en: () => import('./i18n/en.json'),\n * es: () => import('./i18n/es.json'),\n * };\n *\n * export const HomeScreen: React.FC = () => {\n * const { isLoaded, error } = useScreenTranslations(\n * 'demo',\n * 'home',\n * translations\n * );\n *\n * if (!isLoaded) return <LoadingSpinner />;\n * if (error) return <ErrorMessage error={error} />;\n *\n * return <div>...</div>;\n * };\n * ```\n */\n// @cpt-begin:cpt-frontx-flow-react-bindings-use-screen-translations:p1:inst-call-screen-translations\n// @cpt-begin:cpt-frontx-dod-react-bindings-screen-translation-hook:p1:inst-call-screen-translations\nexport function useScreenTranslations(\n screensetId: string,\n screenId: string,\n translations: TranslationMap | TranslationLoader\n): UseScreenTranslationsReturn {\n const app = useFrontX();\n const { i18nRegistry } = app;\n\n // Track loading state per language to handle language changes. No\n // inst-begin-load marker here: nothing in this state pair signals \"load\n // began\" — loading-in-progress is derived as\n // (currentLanguage !== loadedLanguage), see the comment on `isLoaded`.\n // @cpt-begin:cpt-frontx-state-react-bindings-screen-translation:p1:inst-load-success\n // @cpt-begin:cpt-frontx-state-react-bindings-screen-translation:p1:inst-load-error\n // @cpt-begin:cpt-frontx-state-react-bindings-screen-translation:p1:inst-reload-on-lang-change\n // @cpt-begin:cpt-frontx-state-react-bindings-screen-translation:p2:inst-retry-on-lang-change\n const [loadedLanguage, setLoadedLanguage] = useState<string | null>(null);\n const [error, setError] = useState<Error | null>(null);\n // @cpt-end:cpt-frontx-state-react-bindings-screen-translation:p1:inst-load-success\n // @cpt-end:cpt-frontx-state-react-bindings-screen-translation:p1:inst-load-error\n // @cpt-end:cpt-frontx-state-react-bindings-screen-translation:p1:inst-reload-on-lang-change\n // @cpt-end:cpt-frontx-state-react-bindings-screen-translation:p2:inst-retry-on-lang-change\n\n // @cpt-begin:cpt-frontx-flow-react-bindings-use-screen-translations:p1:inst-subscribe-lang-change\n // Subscribe to translation changes using useSyncExternalStore\n // This ensures we reload when language changes\n const version = useSyncExternalStore(\n useCallback(\n (callback: () => void) => i18nRegistry.subscribe(callback),\n [i18nRegistry]\n ),\n () => i18nRegistry.getVersion(),\n () => i18nRegistry.getVersion()\n );\n // @cpt-end:cpt-frontx-flow-react-bindings-use-screen-translations:p1:inst-subscribe-lang-change\n\n // @cpt-begin:cpt-frontx-algo-react-bindings-load-screen-translations:p1:inst-get-current-lang\n // Get current language (changes when version changes)\n // version is used to trigger recalculation when translations change\n const currentLanguage = useMemo(() => {\n void version; // Trigger recalculation when version changes\n return i18nRegistry.getLanguage();\n }, [i18nRegistry, version]);\n // @cpt-end:cpt-frontx-algo-react-bindings-load-screen-translations:p1:inst-get-current-lang\n\n // @cpt-begin:cpt-frontx-algo-react-bindings-load-screen-translations:p1:inst-resolve-loader\n // Create a TranslationLoader function from the translation map or use directly if already a loader\n const loader: TranslationLoader = useMemo(() => {\n if (isTranslationLoader(translations)) {\n // Already a loader function (from I18nRegistry.createLoader)\n return translations;\n }\n\n // Convert TranslationMap to TranslationLoader\n return async (language: string) => {\n const importFn = translations[language as keyof typeof translations];\n if (!importFn) {\n // Return empty dictionary if language not in map\n return {};\n }\n const module = await importFn();\n return module.default;\n };\n }, [translations]);\n // @cpt-end:cpt-frontx-algo-react-bindings-load-screen-translations:p1:inst-resolve-loader\n\n // @cpt-begin:cpt-frontx-flow-react-bindings-use-screen-translations:p1:inst-run-load-screen-translations\n useEffect(() => {\n // @cpt-begin:cpt-frontx-algo-react-bindings-load-screen-translations:p1:inst-skip-if-loaded\n // Skip if no language or already loaded for this language\n if (!currentLanguage || currentLanguage === loadedLanguage) {\n return;\n }\n // @cpt-end:cpt-frontx-algo-react-bindings-load-screen-translations:p1:inst-skip-if-loaded\n\n let cancelled = false;\n\n const loadTranslations = async () => {\n try {\n const namespace = `screen.${screensetId}.${screenId}`;\n\n // @cpt-begin:cpt-frontx-algo-react-bindings-load-screen-translations:p1:inst-register-loader\n // Register the loader for future language changes\n i18nRegistry.registerLoader(namespace, loader);\n // @cpt-end:cpt-frontx-algo-react-bindings-load-screen-translations:p1:inst-register-loader\n\n // @cpt-begin:cpt-frontx-algo-react-bindings-load-screen-translations:p1:inst-call-loader\n // Actually load the translations for current language\n const loadedTranslations = await loader(currentLanguage);\n // @cpt-end:cpt-frontx-algo-react-bindings-load-screen-translations:p1:inst-call-loader\n\n // @cpt-begin:cpt-frontx-algo-react-bindings-load-screen-translations:p1:inst-register-translations\n i18nRegistry.register(namespace, currentLanguage, loadedTranslations);\n // @cpt-end:cpt-frontx-algo-react-bindings-load-screen-translations:p1:inst-register-translations\n\n // @cpt-begin:cpt-frontx-algo-react-bindings-load-screen-translations:p1:inst-cancel-on-unmount\n if (!cancelled) {\n setLoadedLanguage(currentLanguage);\n setError(null);\n }\n // @cpt-end:cpt-frontx-algo-react-bindings-load-screen-translations:p1:inst-cancel-on-unmount\n } catch (err) {\n // @cpt-begin:cpt-frontx-algo-react-bindings-load-screen-translations:p1:inst-handle-load-error\n if (!cancelled) {\n setError(err instanceof Error ? err : new Error(String(err)));\n }\n // @cpt-end:cpt-frontx-algo-react-bindings-load-screen-translations:p1:inst-handle-load-error\n }\n };\n\n loadTranslations();\n\n // @cpt-begin:cpt-frontx-algo-react-bindings-load-screen-translations:p1:inst-cancel-stale-load\n return () => {\n cancelled = true;\n };\n // @cpt-end:cpt-frontx-algo-react-bindings-load-screen-translations:p1:inst-cancel-stale-load\n }, [screensetId, screenId, loader, i18nRegistry, currentLanguage, loadedLanguage]);\n // @cpt-end:cpt-frontx-flow-react-bindings-use-screen-translations:p1:inst-run-load-screen-translations\n\n // @cpt-begin:cpt-frontx-flow-react-bindings-use-screen-translations:p1:inst-return-loading-state\n // Derived, not a stored flag: on error, loadedLanguage is never advanced to\n // currentLanguage, so the mismatch alone already gates isLoaded false.\n const isLoaded = currentLanguage !== null && currentLanguage === loadedLanguage;\n\n // @cpt-begin:cpt-frontx-flow-react-bindings-use-screen-translations:p1:inst-gate-render\n // isLoaded is the gate value: consumers must check this before rendering translation-dependent UI\n return { isLoaded, error };\n // @cpt-end:cpt-frontx-flow-react-bindings-use-screen-translations:p1:inst-gate-render\n // @cpt-end:cpt-frontx-flow-react-bindings-use-screen-translations:p1:inst-return-loading-state\n}\n// @cpt-end:cpt-frontx-flow-react-bindings-use-screen-translations:p1:inst-call-screen-translations\n// @cpt-end:cpt-frontx-dod-react-bindings-screen-translation-hook:p1:inst-call-screen-translations\n","/**\n * useFormatters Hook - Locale-aware formatters\n *\n * Returns formatters that use i18nRegistry.getLanguage() internally.\n * Calls useTranslation() so the component re-renders when language changes.\n *\n * React Layer: L3\n */\n// @cpt-flow:cpt-frontx-flow-react-bindings-use-formatters:p1\n// @cpt-dod:cpt-frontx-dod-react-bindings-formatters-hook:p1\n\nimport { useMemo } from 'react';\nimport {\n formatDate as formatDateFn,\n formatTime as formatTimeFn,\n formatDateTime as formatDateTimeFn,\n formatRelative as formatRelativeFn,\n formatNumber as formatNumberFn,\n formatPercent as formatPercentFn,\n formatCompact as formatCompactFn,\n formatCurrency as formatCurrencyFn,\n compareStrings as compareStringsFn,\n createCollator as createCollatorFn,\n} from '@gears-frontx/framework';\nimport type { UseFormattersReturn } from '../types';\nimport { useTranslation } from './useTranslation';\n\n/**\n * Hook for accessing locale-aware formatters (date, number, currency, sort).\n *\n * Formatters use the current app language from i18nRegistry.getLanguage().\n * Re-renders when language changes via useTranslation() subscription.\n *\n * @returns Object with formatDate, formatTime, formatDateTime, formatRelative,\n * formatNumber, formatPercent, formatCompact, formatCurrency, compareStrings, createCollator\n *\n * @example\n * ```tsx\n * const { formatDate, formatCurrency } = useFormatters();\n * return (\n * <span>{formatDate(new Date(), 'short')}</span>\n * <span>{formatCurrency(99.99, 'USD')}</span>\n * );\n * ```\n */\n// @cpt-begin:cpt-frontx-flow-react-bindings-use-formatters:p1:inst-call-formatters\n// @cpt-begin:cpt-frontx-dod-react-bindings-formatters-hook:p1:inst-call-formatters\nexport function useFormatters(): UseFormattersReturn {\n // @cpt-begin:cpt-frontx-flow-react-bindings-use-formatters:p1:inst-subscribe-via-translation\n // useTranslation() subscribes to language changes so this component re-renders\n // when language changes; formatters read i18nRegistry.getLanguage() at call time\n const { language } = useTranslation();\n // @cpt-end:cpt-frontx-flow-react-bindings-use-formatters:p1:inst-subscribe-via-translation\n\n // @cpt-begin:cpt-frontx-flow-react-bindings-use-formatters:p1:inst-return-formatters\n // @cpt-begin:cpt-frontx-flow-react-bindings-use-formatters:p1:inst-formatters-read-locale\n // @cpt-begin:cpt-frontx-flow-react-bindings-use-formatters:p1:inst-recompute-on-lang\n return useMemo<UseFormattersReturn>(\n () => {\n void language; // re-run when language changes so formatters see new locale\n return {\n formatDate: formatDateFn,\n formatTime: formatTimeFn,\n formatDateTime: formatDateTimeFn,\n formatRelative: formatRelativeFn,\n formatNumber: formatNumberFn,\n formatPercent: formatPercentFn,\n formatCompact: formatCompactFn,\n formatCurrency: formatCurrencyFn,\n compareStrings: compareStringsFn,\n createCollator: createCollatorFn,\n };\n },\n [language]\n );\n // @cpt-end:cpt-frontx-flow-react-bindings-use-formatters:p1:inst-return-formatters\n // @cpt-end:cpt-frontx-flow-react-bindings-use-formatters:p1:inst-formatters-read-locale\n // @cpt-end:cpt-frontx-flow-react-bindings-use-formatters:p1:inst-recompute-on-lang\n}\n// @cpt-end:cpt-frontx-flow-react-bindings-use-formatters:p1:inst-call-formatters\n// @cpt-end:cpt-frontx-dod-react-bindings-formatters-hook:p1:inst-call-formatters\n","/**\n * useTheme Hook - Theme utilities\n *\n * React Layer: L3\n */\n// @cpt-flow:cpt-frontx-flow-react-bindings-use-theme:p1\n// @cpt-dod:cpt-frontx-dod-react-bindings-theme-hook:p1\n\nimport { useCallback, useMemo, useSyncExternalStore } from 'react';\nimport { useFrontX } from '../FrontXContext';\nimport type { UseThemeReturn } from '../types';\n\n/**\n * Hook for theme utilities.\n *\n * @returns Theme utilities\n *\n * @example\n * ```tsx\n * const { currentTheme, themes, setTheme } = useTheme();\n *\n * return (\n * <select\n * value={currentTheme}\n * onChange={(e) => setTheme(e.target.value)}\n * >\n * {themes.map((theme) => (\n * <option key={theme.id} value={theme.id}>\n * {theme.name}\n * </option>\n * ))}\n * </select>\n * );\n * ```\n */\n// @cpt-begin:cpt-frontx-flow-react-bindings-use-theme:p1:inst-call-theme\n// @cpt-begin:cpt-frontx-dod-react-bindings-theme-hook:p1:inst-call-theme\nexport function useTheme(): UseThemeReturn {\n // @cpt-begin:cpt-frontx-flow-react-bindings-use-theme:p1:inst-read-theme-registry\n const app = useFrontX();\n const { themeRegistry } = app;\n // @cpt-end:cpt-frontx-flow-react-bindings-use-theme:p1:inst-read-theme-registry\n\n // @cpt-begin:cpt-frontx-flow-react-bindings-use-theme:p1:inst-subscribe-theme\n // @cpt-begin:cpt-frontx-flow-react-bindings-use-theme:p1:inst-rerender-on-theme-change\n // Subscribe to theme changes using useSyncExternalStore\n // Uses version counter to trigger re-renders when theme changes\n const version = useSyncExternalStore(\n useCallback(\n (callback: () => void) => {\n return themeRegistry.subscribe(callback);\n },\n [themeRegistry]\n ),\n () => themeRegistry.getVersion(),\n () => themeRegistry.getVersion()\n );\n // @cpt-end:cpt-frontx-flow-react-bindings-use-theme:p1:inst-subscribe-theme\n // @cpt-end:cpt-frontx-flow-react-bindings-use-theme:p1:inst-rerender-on-theme-change\n\n // Get current theme (memoized, recalculates on version change)\n const currentTheme = useMemo(() => {\n // Reference version to trigger recalculation on theme change\n void version;\n const theme = themeRegistry.getCurrent();\n return theme?.id;\n }, [themeRegistry, version]);\n\n // Get all themes\n const themes = useMemo(() => {\n return themeRegistry.getAll().map((theme) => ({\n id: theme.id,\n name: theme.name,\n }));\n }, [themeRegistry]);\n\n // @cpt-begin:cpt-frontx-flow-react-bindings-use-theme:p1:inst-dispatch-change-theme\n // Set theme\n const setTheme = useCallback(\n (themeId: string) => {\n if (app.actions.changeTheme) {\n app.actions.changeTheme({ themeId });\n }\n },\n [app.actions]\n );\n // @cpt-end:cpt-frontx-flow-react-bindings-use-theme:p1:inst-dispatch-change-theme\n\n // @cpt-begin:cpt-frontx-flow-react-bindings-use-theme:p1:inst-return-theme-api\n return {\n currentTheme,\n themes,\n setTheme,\n };\n // @cpt-end:cpt-frontx-flow-react-bindings-use-theme:p1:inst-return-theme-api\n}\n// @cpt-end:cpt-frontx-flow-react-bindings-use-theme:p1:inst-call-theme\n// @cpt-end:cpt-frontx-dod-react-bindings-theme-hook:p1:inst-call-theme\n","/**\n * useApiQuery - Declarative data fetching hook\n *\n * Accepts an EndpointDescriptor from @gears-frontx/api and returns a Gears FrontX-owned\n * ApiQueryResult. AbortSignal for request cancellation is threaded automatically\n * through the shared QueryClient integration.\n *\n * Cache config cascade: component overrides > descriptor defaults > plugin defaults.\n * Omit overrides to rely on the descriptor's staleTime/gcTime, which in turn\n * fall back to the plugin-level query-cache defaults.\n */\n// @cpt-dod:cpt-frontx-dod-request-lifecycle-use-api-query:p2\n// @cpt-flow:cpt-frontx-flow-request-lifecycle-use-api-query:p2\n// @cpt-state:cpt-frontx-state-request-lifecycle-query:p2\n// @cpt-FEATURE:implement-endpoint-descriptors:p3\n\nimport type { EndpointDescriptor } from '@gears-frontx/framework';\nimport type { ApiQueryResult } from '../types';\nimport { useFrontXQuery } from '../queryClient';\n\n/** Per-call cache overrides. Cascade: these > descriptor > plugin defaults. */\nexport interface ApiQueryOverrides {\n /** Override staleTime for this specific call site. */\n staleTime?: number;\n /** Override gcTime for this specific call site. */\n gcTime?: number;\n}\n\n// @cpt-begin:cpt-frontx-flow-request-lifecycle-use-api-query:p2:inst-delegate-use-query\nexport function useApiQuery<TData = unknown, TError = Error>(\n descriptor: EndpointDescriptor<TData>,\n overrides?: ApiQueryOverrides\n): ApiQueryResult<TData, TError> {\n return useFrontXQuery(descriptor, overrides);\n}\n// @cpt-end:cpt-frontx-flow-request-lifecycle-use-api-query:p2:inst-delegate-use-query\n","/**\n * useApiSuspenseQuery - Suspense declarative data fetching hook\n *\n * Mirrors useApiQuery but integrates with React Suspense so the initial load is\n * handled by a Suspense boundary.\n */\n// @cpt-dod:cpt-frontx-dod-request-lifecycle-use-api-query:p2\n// @cpt-flow:cpt-frontx-flow-request-lifecycle-use-api-query:p2\n// @cpt-state:cpt-frontx-state-request-lifecycle-query:p2\n\nimport type { EndpointDescriptor } from '@gears-frontx/framework';\nimport type { ApiSuspenseQueryResult } from '../types';\nimport type { ApiQueryOverrides } from './useApiQuery';\nimport { useFrontXSuspenseQuery } from '../queryClient';\n\n// @cpt-begin:cpt-frontx-flow-request-lifecycle-use-api-query:p2:inst-delegate-use-suspense-query\nexport function useApiSuspenseQuery<TData = unknown, TError = Error>(\n descriptor: EndpointDescriptor<TData>,\n overrides?: ApiQueryOverrides\n): ApiSuspenseQueryResult<TData, TError> {\n return useFrontXSuspenseQuery<TData, TError>(descriptor, overrides);\n}\n// @cpt-end:cpt-frontx-flow-request-lifecycle-use-api-query:p2:inst-delegate-use-suspense-query\n","/**\n * useApiInfiniteQuery - Declarative paginated data fetching hook\n *\n * Accepts an initial EndpointDescriptor plus descriptor resolvers for adjacent\n * pages. Each page remains a standard service descriptor so MFE code does not\n * need raw TanStack query keys or query functions.\n */\n// @cpt-dod:cpt-frontx-dod-request-lifecycle-use-api-query:p2\n// @cpt-flow:cpt-frontx-flow-request-lifecycle-use-api-query:p2\n\nimport type { EndpointDescriptor } from '@gears-frontx/framework';\nimport type { ApiInfiniteQueryResult } from '../types';\nimport type { ApiQueryOverrides } from './useApiQuery';\nimport { useFrontXInfiniteQuery } from '../queryClient';\n\nexport interface ApiInfiniteQueryPageContext<TPage> {\n page: TPage;\n pages: readonly TPage[];\n descriptor: EndpointDescriptor<TPage>;\n descriptors: readonly EndpointDescriptor<TPage>[];\n}\n\nexport interface ApiInfiniteQueryOptions<TPage> extends ApiQueryOverrides {\n /** Descriptor for the first page in the sequence. */\n initialPage: EndpointDescriptor<TPage>;\n /**\n * Resolve the next page descriptor from the current page payload.\n * Return undefined when there is no next page.\n */\n getNextPage: (\n context: ApiInfiniteQueryPageContext<TPage>\n ) => EndpointDescriptor<TPage> | undefined;\n /**\n * Resolve the previous page descriptor from the current first page payload.\n * Return undefined when backward pagination is not available.\n */\n getPreviousPage?: (\n context: ApiInfiniteQueryPageContext<TPage>\n ) => EndpointDescriptor<TPage> | undefined;\n /** Optional TanStack maxPages passthrough for bounded page windows. */\n maxPages?: number;\n}\n\nexport function useApiInfiniteQuery<TPage = unknown, TError = Error>(\n options: ApiInfiniteQueryOptions<TPage>\n): ApiInfiniteQueryResult<TPage, TError> {\n return useFrontXInfiniteQuery<TPage, TError>(options);\n}\n","/**\n * useApiSuspenseInfiniteQuery - Suspense paginated data fetching hook\n *\n * Mirrors useApiInfiniteQuery but integrates with React Suspense so the initial\n * page load is handled by a Suspense boundary while pagination stays\n * descriptor-driven.\n */\n// @cpt-dod:cpt-frontx-dod-request-lifecycle-use-api-query:p2\n// @cpt-flow:cpt-frontx-flow-request-lifecycle-use-api-query:p2\n\nimport type { ApiSuspenseInfiniteQueryResult } from '../types';\nimport type {\n ApiInfiniteQueryOptions,\n} from './useApiInfiniteQuery';\nimport { useFrontXSuspenseInfiniteQuery } from '../queryClient';\n\nexport function useApiSuspenseInfiniteQuery<TPage = unknown, TError = Error>(\n options: ApiInfiniteQueryOptions<TPage>\n): ApiSuspenseInfiniteQueryResult<TPage, TError> {\n return useFrontXSuspenseInfiniteQuery<TPage, TError>(options);\n}\n","/**\n * useApiMutation - Declarative mutation hook with restricted QueryCache injection\n *\n * Accepts { endpoint: MutationDescriptor, callbacks } and returns a Gears FrontX-owned\n * ApiMutationResult. Supports optimistic updates, rollback, and cache invalidation\n * through the QueryCache interface injected into each callback.\n *\n * Optimistic update pattern:\n * onMutate -> cancel outgoing refetches, snapshot via queryCache.get,\n * apply optimistic data via queryCache.set, return snapshot\n * onError -> restore snapshot via queryCache.set(key, context.snapshot)\n * onSettled -> invalidate to refetch authoritative state\n *\n * TanStack Query is used internally only and is NOT re-exported.\n * MFEs interact with the cache through QueryCache, not the raw QueryClient.\n */\n// @cpt-dod:cpt-frontx-dod-request-lifecycle-use-api-mutation:p2\n// @cpt-flow:cpt-frontx-flow-request-lifecycle-use-api-mutation:p2\n// @cpt-algo:cpt-frontx-algo-request-lifecycle-optimistic-update:p2\n// @cpt-algo:cpt-frontx-algo-request-lifecycle-query-invalidation:p2\n// @cpt-state:cpt-frontx-state-request-lifecycle-mutation:p2\n// @cpt-FEATURE:implement-endpoint-descriptors:p3\n\nimport type { MutationDescriptor } from '@gears-frontx/framework';\nimport type { MutationCallbackContext } from './QueryCache';\nimport type { ApiMutationResult } from '../types';\nimport { useFrontXMutation, useRequiredFrontXQueryClient } from '../queryClient';\nimport { createQueryCache } from './QueryCache';\nimport { useMemo } from 'react';\n\nexport type { QueryCache, MutationCallbackContext } from './QueryCache';\n\n// @cpt-begin:cpt-frontx-dod-request-lifecycle-use-api-mutation:p2:inst-type-alias\n/**\n * Options for useApiMutation.\n *\n * Each callback receives { queryCache } as an additional final parameter,\n * providing controlled access to the shared cache without exposing the\n * raw QueryClient. TContext is the return type of onMutate, passed as\n * context to onSuccess, onError, and onSettled.\n */\nexport type UseApiMutationOptions<\n TData = unknown,\n TError = Error,\n TVariables = void,\n TContext = unknown,\n> = {\n endpoint: MutationDescriptor<TData, TVariables>;\n cancelOnSupersede?: boolean;\n abortOnUnmount?: boolean;\n onMutate?: (variables: TVariables, ctx: MutationCallbackContext) => Promise<TContext> | TContext;\n onSuccess?: (data: TData, variables: TVariables, context: TContext | undefined, ctx: MutationCallbackContext) => unknown;\n onError?: (error: TError, variables: TVariables, context: TContext | undefined, ctx: MutationCallbackContext) => unknown;\n onSettled?: (data: TData | undefined, error: TError | null, variables: TVariables, context: TContext | undefined, ctx: MutationCallbackContext) => unknown;\n};\n// @cpt-end:cpt-frontx-dod-request-lifecycle-use-api-mutation:p2:inst-type-alias\n\n// @cpt-begin:cpt-frontx-flow-request-lifecycle-use-api-mutation:p2:inst-delegate-use-mutation\nexport function useApiMutation<\n TData = unknown,\n TError = Error,\n TVariables = void,\n TContext = unknown,\n>(\n options: UseApiMutationOptions<TData, TError, TVariables, TContext>\n): ApiMutationResult<TData, TError, TVariables> {\n const queryClient = useRequiredFrontXQueryClient();\n const queryCache = useMemo(() => createQueryCache(queryClient), [queryClient]);\n const callbackCtx: MutationCallbackContext = useMemo(() => ({ queryCache }), [queryCache]);\n return useFrontXMutation<TData, TError, TVariables, TContext>(options, callbackCtx);\n}\n// @cpt-end:cpt-frontx-flow-request-lifecycle-use-api-mutation:p2:inst-delegate-use-mutation\n","/**\n * useApiStream - Declarative SSE streaming hook\n *\n * Accepts a StreamDescriptor from @gears-frontx/api and returns the latest\n * event, accumulated events, connection status, and a manual disconnect\n * function.\n *\n * @example\n * ```tsx\n * const { data, events, status, error } = useApiStream(\n * service.messageStream,\n * { mode: 'latest' } // default — data holds last event\n * );\n *\n * // Accumulate all events\n * const { events, status } = useApiStream(service.messageStream, { mode: 'accumulate' });\n * ```\n */\n\nimport { useEffect, useMemo, useRef, useState, useCallback } from 'react';\nimport type { StreamDescriptor, StreamStatus } from '@gears-frontx/framework';\nimport { useLatest } from './useLatest';\n\n/** Configuration options for useApiStream. */\nexport interface ApiStreamOptions {\n /**\n * `'latest'` (default) — `data` holds the most recent event.\n * `'accumulate'` — `events` holds all received events in order.\n */\n mode?: 'latest' | 'accumulate';\n /** When false the connection is deferred (no connect on mount). Default true. */\n enabled?: boolean;\n}\n\n/** Return type of useApiStream. */\nexport interface ApiStreamResult<TEvent> {\n /** Latest event payload, set in both modes — `undefined` until the first event and after each connect attempt resets it. */\n data: TEvent | undefined;\n /** All received events when `mode: 'accumulate'`; empty array in `'latest'` mode. */\n events: TEvent[];\n /** Connection lifecycle status. */\n status: StreamStatus;\n /** Last connect error — set when a connect attempt rejects, cleared when the next attempt starts. */\n error: Error | null;\n /** Manually close the connection. */\n disconnect: () => void;\n}\n\n/**\n * Manages the status lifecycle for a single SSE stream connection.\n *\n * **Status values**\n * - `'idle'` — no connection is being attempted. This is the status whenever\n * `enabled` is `false`, including on mount: a hook that mounts disabled\n * never reports anything but `'idle'` until `enabled` flips to `true`. A\n * hook that mounts enabled skips `'idle'` entirely — the status is set\n * during render, so its very first render already reports `'connecting'`.\n * Consumers must not assume `'idle'` means \"never\n * connected\" — a stream that is disabled after having connected returns to\n * `'idle'` too, and `data`/`events` from the earlier connection are not\n * cleared by that transition alone (they are cleared by mode/key changes,\n * see below).\n * - `'connecting'` — a connection attempt is committed to but has not settled.\n * It is published during the render that turns the stream on, which is\n * before `descriptor.connect()` runs: the call is made from an effect after\n * that render commits. So `'connecting'` means \"this stream is being\n * opened\", not \"the connect promise is pending\" — for one render the two\n * differ, and a consumer that reads the status as proof a request is already\n * in flight is reading it too strongly.\n * - `'connected'` — set both when `connect()` resolves (unless a disconnect\n * was requested while it was pending) and, independently, whenever the\n * `onEvent` callback delivers a new event. Because every event re-asserts\n * `'connected'`, this status also serves as \"still receiving events.\"\n * - `'disconnected'` — reached via any of: the descriptor's `onComplete`\n * callback firing (the stream ended normally), `connect()` rejecting while\n * a disconnect was requested concurrently, or the manual `disconnect()`\n * function being called. `disconnect()` has no `enabled` guard, but calling\n * it while the stream is disabled is not observable: the stored status moves\n * to `'disconnected'` while the published one stays `'idle'`, and flipping\n * `enabled` back to `true` sets `'connecting'` during that render, so the\n * stored `'disconnected'` is overwritten before it is ever returned.\n * - `'error'` — `connect()` rejected and no disconnect was requested while it\n * was pending. `error` holds the rejection, coerced to an `Error` if it\n * wasn't one already.\n *\n * **Transitions**\n * - Mounting enabled, `enabled` becoming `true`, or `descriptor.key` / `mode`\n * changing while `enabled` is `true`: `data`, `events`, and `error` are reset\n * and status is set to `'connecting'` synchronously during render (not from\n * an effect); `connect()` is then called from an effect that runs after that\n * render commits.\n * - `descriptor.key` or `mode` changing while `enabled` is `false`: `data`,\n * `events`, and `error` are reset all the same, since that reset is not gated\n * on `enabled`, but the status write is - so no `'connecting'` is written and\n * the published status stays `'idle'`; `connect()` is not called. The skipped\n * `'connecting'` is not owed later either: the change counts as handled when\n * it happens, so what publishes `'connecting'` is the subsequent flip of\n * `enabled` to `true`, once, for whichever key and mode are in force by then.\n * - `enabled` becomes `false` (or starts `false`): the published status is\n * `'idle'` for as long as `enabled` stays `false` — it is derived from\n * `enabled` rather than written, so nothing a prior connection stored can\n * surface through it — and `connect()` is never called; no other field is\n * reset by this transition alone.\n * - Unmount, `descriptor.key` change, `mode` change, or `enabled` flipping to\n * `false` while connected or connecting: the previous connection is torn\n * down via `descriptor.disconnect()` once its `connect()` promise settles\n * (or immediately skipped if it rejected). All four share the same cleanup\n * path: the effect's cleanup runs on every dependency change and on unmount.\n * - Calling `disconnect()`: if a connection id is already resolved, it is\n * disconnected immediately and status becomes `'disconnected'`. If\n * `connect()` is still pending, the request is recorded and honored when\n * the promise settles — the newly resolved connection is torn down instead\n * of being adopted, and status is `'disconnected'`. One caveat:\n * `disconnect()` does not cancel the event callback, so a buffered or\n * in-flight event landing after the call re-asserts `'connected'` — and in\n * the pending-connect case the settle handler tears the connection down\n * without touching status, so that stray `'connected'` persists.\n * - Stream completion while `connect()` is still pending: the current\n * implementation lets `onComplete` set `'disconnected'`, then the settle\n * handler adopts the connection id and re-asserts `'connected'` anyway.\n * This is known current behavior, not a durable guarantee: a pending\n * upstream derived-status rewrite is expected to remove this transition.\n *\n * `enabled` (default `true`) is the only way to defer connecting past mount;\n * flipping it back to `true` re-runs the same connect sequence as a fresh\n * mount would.\n */\nexport function useApiStream<TEvent>(\n descriptor: StreamDescriptor<TEvent>,\n options?: ApiStreamOptions,\n): ApiStreamResult<TEvent> {\n const mode = options?.mode ?? 'latest';\n const enabled = options?.enabled ?? true;\n\n const [data, setData] = useState<TEvent | undefined>(undefined);\n const [events, setEvents] = useState<TEvent[]>([]);\n // Lazy initializer mirrors what the \"connecting\" render-adjustment below would set on\n // a later (descriptorKey, mode, enabled) change — the adjustment's before/after\n // comparison can't itself detect \"this is the very first render\", since its own\n // `prevConnectKey` state is seeded from the same initial connectKey.\n const [status, setStatus] = useState<StreamStatus>(() => (enabled ? 'connecting' : 'idle'));\n const [error, setError] = useState<Error | null>(null);\n\n // Tracks the in-flight connect() promise so cleanup can await it.\n const connectPromiseRef = useRef<Promise<string> | null>(null);\n // Tracks the resolved connectionId for the manual disconnect() callback.\n const connectionIdRef = useRef<string | null>(null);\n /** When true, connect's promise resolution must tear down the new id instead of adopting it. */\n const disconnectRequestedRef = useRef(false);\n // Latest descriptor for connect/disconnect without tying effect or callbacks to object identity.\n const descriptorRef = useLatest(descriptor);\n\n // Stable identity derived from descriptor key — used as effect dependency.\n // JSON.stringify avoids join('/') collisions when a segment contains '/'.\n const descriptorKey = useMemo(() => JSON.stringify(descriptor.key), [descriptor.key]);\n\n // Resets stream state when the descriptor or mode changes, using the \"adjusting state\n // during render\" pattern (react.dev) instead of an effect: this clears stale data\n // before paint in the same render pass rather than committing once with old data and\n // scheduling a second render from an effect.\n const resetKey = `${descriptorKey}:${mode}`;\n const [prevResetKey, setPrevResetKey] = useState(resetKey);\n if (resetKey !== prevResetKey) {\n setPrevResetKey(resetKey);\n setData(undefined);\n setEvents([]);\n setError(null);\n }\n\n // Same pattern, scoped to when the connect effect below is about to (re)start a\n // connection: also flips `status` to 'connecting' up front, exactly once per\n // (descriptorKey, mode, enabled) combination — matching the effect's dependency list\n // — instead of the effect setting it synchronously on every run.\n const connectKey = `${resetKey}:${enabled}`;\n const [prevConnectKey, setPrevConnectKey] = useState(connectKey);\n if (connectKey !== prevConnectKey) {\n setPrevConnectKey(connectKey);\n if (enabled) {\n setData(undefined);\n setEvents([]);\n setStatus('connecting');\n setError(null);\n }\n }\n\n const disconnect = useCallback(() => {\n disconnectRequestedRef.current = true;\n if (connectionIdRef.current) {\n descriptorRef.current.disconnect(connectionIdRef.current);\n connectionIdRef.current = null;\n disconnectRequestedRef.current = false;\n }\n setStatus('disconnected');\n // descriptorRef's identity never changes (useLatest returns a stable ref\n // object) — listing it here satisfies exhaustive-deps without altering\n // when this callback is recreated.\n }, [descriptorRef]);\n\n useEffect(() => {\n // Disabled: no connection attempt. `status` is displayed as 'idle' via the\n // derived value below instead of writing it here — the stored `status` from a\n // prior connection is left untouched so a later re-enable has nothing stale to\n // clean up, and no synchronous setState is needed in this effect.\n if (!enabled) {\n return;\n }\n\n let cancelled = false;\n\n disconnectRequestedRef.current = false;\n\n const d = descriptorRef.current;\n // data/events/status/error were already reset to the 'connecting' state above,\n // during render, for this exact (descriptorKey, mode, enabled) combination.\n\n const connectPromise = d.connect(\n (event) => {\n if (cancelled) return;\n setData(event);\n setStatus('connected');\n if (mode === 'accumulate') {\n setEvents((prev) => [...prev, event]);\n }\n },\n () => {\n if (cancelled) return;\n setStatus('disconnected');\n connectionIdRef.current = null;\n },\n );\n\n connectPromiseRef.current = connectPromise;\n\n connectPromise\n .then((id) => {\n if (cancelled) return;\n if (disconnectRequestedRef.current) {\n d.disconnect(id);\n disconnectRequestedRef.current = false;\n return;\n }\n connectionIdRef.current = id;\n setStatus('connected');\n })\n .catch((err) => {\n if (cancelled) return;\n if (disconnectRequestedRef.current) {\n disconnectRequestedRef.current = false;\n setStatus('disconnected');\n return;\n }\n setError(err instanceof Error ? err : new Error(String(err)));\n setStatus('error');\n });\n\n return () => {\n cancelled = true;\n connectPromise.then(\n (id) => d.disconnect(id),\n () => { /* connect failed — nothing to disconnect */ },\n );\n connectPromiseRef.current = null;\n connectionIdRef.current = null;\n };\n // descriptorRef's identity never changes (useLatest returns a stable ref\n // object) — listing it here satisfies exhaustive-deps without causing\n // this effect to re-run on every render.\n }, [descriptorKey, enabled, mode, descriptorRef]);\n\n // Derived: while disabled the connection is deliberately not attempted, so the\n // publicly visible status is always 'idle' regardless of what a prior connection\n // left in `status` state.\n return { data, events, status: enabled ? status : 'idle', error, disconnect };\n}\n","import { useMemo } from 'react';\nimport { createQueryCache } from './QueryCache';\nimport { useOptionalFrontXQueryClient } from '../queryClient';\n\n/**\n * Exposes the sanctioned imperative cache API for app and MFE code without\n * leaking the raw QueryClient.\n *\n * Preferred usage:\n * - useApiQuery() for declarative reads\n * - useApiMutation() for writes\n * - useQueryCache() for controlled imperative cache inspection and invalidation\n */\nexport function useQueryCache() {\n const queryClient = useOptionalFrontXQueryClient();\n\n if (!queryClient) {\n throw new Error(\n '[FrontXProvider] No query cache available. Add queryCache() or queryCacheShared() to your plugin composition.'\n );\n }\n\n return useMemo(() => createQueryCache(queryClient), [queryClient]);\n}\n","/**\n * useMfeBridge Hook - MFE bridge access\n *\n * Returns the ChildMfeBridge from context for communication with host.\n *\n * React Layer: L3\n */\n// @cpt-flow:cpt-frontx-flow-react-bindings-mfe-provider:p1\n// @cpt-algo:cpt-frontx-algo-react-bindings-mfe-context-guard:p1\n// @cpt-dod:cpt-frontx-dod-react-bindings-mfe-hooks:p1\n\nimport { useMfeContext } from '../MfeContext';\nimport type { ChildMfeBridge } from '@gears-frontx/framework';\n\n// ============================================================================\n// Hook Implementation\n// ============================================================================\n\n/**\n * Hook for accessing the MFE bridge.\n *\n * Returns the ChildMfeBridge instance for communication with the host.\n * Must be used within a MfeProvider (i.e., inside an MFE component).\n *\n * @returns Child MFE bridge\n *\n * @example\n * ```tsx\n * function MyMfeComponent() {\n * const bridge = useMfeBridge();\n *\n * // Bridge methods:\n * // bridge.executeActionsChain(chain);\n * // bridge.subscribeToProperty(propertyTypeId, callback);\n *\n * return <div>Domain: {bridge.extDomainId}</div>;\n * }\n * ```\n */\n// @cpt-begin:cpt-frontx-flow-react-bindings-mfe-provider:p1:inst-use-bridge\n// @cpt-begin:cpt-frontx-algo-react-bindings-mfe-context-guard:p1:inst-throw-no-mfe-context\n// @cpt-begin:cpt-frontx-dod-react-bindings-mfe-hooks:p1:inst-use-bridge\nexport function useMfeBridge(): ChildMfeBridge {\n const { bridge } = useMfeContext();\n return bridge;\n}\n// @cpt-end:cpt-frontx-flow-react-bindings-mfe-provider:p1:inst-use-bridge\n// @cpt-end:cpt-frontx-algo-react-bindings-mfe-context-guard:p1:inst-throw-no-mfe-context\n// @cpt-end:cpt-frontx-dod-react-bindings-mfe-hooks:p1:inst-use-bridge\n","/**\n * useSharedProperty Hook - Shared property subscription\n *\n * Subscribes to shared property updates from the host, either through the\n * ambient MfeProvider context or through an explicitly supplied bridge.\n *\n * React Layer: L3\n */\n\nimport { useCallback, useContext, useSyncExternalStore } from 'react';\nimport type { ChildMfeBridge } from '@gears-frontx/framework';\nimport { MfeContext } from '../MfeContext';\n\n// ============================================================================\n// Option Types\n// ============================================================================\n\n/**\n * Options for {@link useSharedProperty}.\n */\nexport interface UseSharedPropertyOptions<T> {\n /**\n * Bridge to read the property from, bypassing `MfeContext`.\n *\n * Pass this when the calling component never mounts `MfeProvider` (for\n * example, a component that receives its bridge directly as a prop or from\n * a non-React entry point). When omitted, the hook falls back to the\n * bridge from `MfeContext` and throws if no `MfeProvider` is mounted,\n * matching the zero-argument form.\n *\n * `bridge` and `propertyTypeId` identify the subscription: changing either\n * one unsubscribes from the old source and subscribes to the new one, and\n * the returned value reflects the new source on the same render.\n */\n bridge?: ChildMfeBridge;\n\n /**\n * Value returned while the host has not published the property yet\n * (`bridge.getProperty()` returns `undefined`).\n *\n * Only the `undefined` sentinel is substituted: a published `null` is a\n * real value and is returned as-is. The host validates every published\n * value against the property's schema before it reaches any MFE\n * (`TypeSystemPlugin.register()` throws on a schema mismatch and the\n * update is never stored or delivered), so no consumer-side filtering is\n * needed -- `T` is simply the caller's declaration of that schema.\n *\n * `fallback` may be passed inline on every render; it does not affect the\n * host subscription.\n */\n fallback?: T;\n}\n\n// ============================================================================\n// Hook Implementation\n// ============================================================================\n\n/**\n * Subscribe to a shared property from the host.\n *\n * Two forms:\n *\n * 1. **Context form** -- `useSharedProperty(propertyTypeId)`. Reads the\n * bridge from `MfeContext` and throws if no `MfeProvider` is mounted.\n * 2. **Options form** -- `useSharedProperty(propertyTypeId, options)`. Pass\n * `options.bridge` for components that never mount `MfeProvider`, and/or\n * `options.fallback` for a value to show until the host publishes one.\n * `options.bridge` may be omitted, in which case the hook still falls\n * back to `MfeContext`.\n *\n * Both forms read through `useSyncExternalStore`: the bridge is the store,\n * `bridge.getProperty()` is the snapshot, so the first render already shows\n * the host's current value, a publish between render and commit is picked\n * up when React re-reads the snapshot after subscribing, and the value is\n * tearing-protected under concurrent rendering.\n *\n * @param propertyTypeId - GTS type ID of the shared property to subscribe to\n * @param options - Optional bridge override and fallback\n * @returns The current property value; `T` when `options.fallback` is set,\n * otherwise `T | undefined`\n *\n * @example Context form (inside MfeProvider)\n * ```tsx\n * function ThemedComponent() {\n * const theme = useSharedProperty<{ primaryColor: string }>(THEME_PROPERTY_ID);\n * return <div style={{ color: theme?.primaryColor }} />;\n * }\n * ```\n *\n * @example Explicit bridge with fallback (no MfeProvider)\n * ```tsx\n * function StandaloneComponent({ bridge }: { bridge: ChildMfeBridge }) {\n * const label = useSharedProperty<string>(LABEL_PROPERTY_ID, {\n * bridge,\n * fallback: 'Untitled',\n * });\n * return <span>{label}</span>;\n * }\n * ```\n */\nexport function useSharedProperty<T = unknown>(propertyTypeId: string): T | undefined;\nexport function useSharedProperty<T>(\n propertyTypeId: string,\n options: UseSharedPropertyOptions<T> & { fallback: T }\n): T;\nexport function useSharedProperty<T = unknown>(\n propertyTypeId: string,\n options?: UseSharedPropertyOptions<T>\n): T | undefined;\nexport function useSharedProperty<T = unknown>(\n propertyTypeId: string,\n options?: UseSharedPropertyOptions<T>\n): T | undefined {\n // useContext is called unconditionally (Rules of Hooks) regardless of whether\n // an explicit bridge was supplied; only the *result* is used conditionally below.\n const contextValue = useContext(MfeContext);\n const bridge = options?.bridge ?? contextValue?.bridge;\n const fallback = options?.fallback;\n\n if (!bridge) {\n throw new Error(\n 'useSharedProperty must be used within a MfeProvider, or given an explicit ' +\n '`bridge` option, for components that never mount MfeProvider.'\n );\n }\n\n const subscribe = useCallback(\n (onStoreChange: () => void) =>\n bridge.subscribeToProperty(propertyTypeId, () => {\n onStoreChange();\n }),\n [bridge, propertyTypeId]\n );\n\n const getSnapshot = useCallback(() => {\n const raw = bridge.getProperty(propertyTypeId)?.value;\n // `undefined` is the only \"not published\" sentinel; `null` is a real value.\n // The caller specifies the expected `T` (as with `useState<T>`/\n // `useContext<T>`); the host has already validated the value against the\n // property's schema, so the assertion states the schema, not a hope.\n return raw === undefined ? fallback : (raw as T);\n }, [bridge, propertyTypeId, fallback]);\n\n return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n}\n","/**\n * useHostAction Hook - Host action requests\n *\n * Returns a callback to request host actions via the bridge.\n *\n * React Layer: L3\n */\n// @cpt-flow:cpt-frontx-flow-react-bindings-use-host-action:p1\n// @cpt-algo:cpt-frontx-algo-react-bindings-mfe-context-guard:p1\n// @cpt-dod:cpt-frontx-dod-react-bindings-mfe-hooks:p1\n\nimport { useCallback } from 'react';\nimport { useMfeContext } from '../MfeContext';\n\n// ============================================================================\n// Hook Implementation\n// ============================================================================\n\n/**\n * Hook for requesting host actions.\n *\n * Returns a callback function that sends an actions chain to the host.\n * Must be used within a MfeProvider (i.e., inside an MFE component).\n *\n * NOTE: This hook provides the interface. Bridge executeActionsChain() delegates to the registry.\n *\n * @param actionTypeId - Type ID of the action to request\n * @returns Callback function to request the action with payload\n *\n * @example\n * ```tsx\n * function MyMfeComponent() {\n * const requestNavigation = useHostAction('gts.frontx.mfes.comm.action.v1~myapp.navigate.v1');\n *\n * const handleClick = () => {\n * requestNavigation({ path: '/dashboard' });\n * };\n *\n * return <button onClick={handleClick}>Navigate</button>;\n * }\n * ```\n */\n// @cpt-begin:cpt-frontx-flow-react-bindings-use-host-action:p1:inst-call-host-action\n// @cpt-begin:cpt-frontx-dod-react-bindings-mfe-hooks:p1:inst-call-host-action\nexport function useHostAction<TPayload extends Record<string, unknown> = Record<string, unknown>>(\n actionTypeId: string\n): (payload?: TPayload) => void {\n // @cpt-begin:cpt-frontx-flow-react-bindings-use-host-action:p1:inst-read-bridge-for-action\n // @cpt-begin:cpt-frontx-algo-react-bindings-mfe-context-guard:p1:inst-throw-no-mfe-context\n // Enforce MfeProvider context requirement\n const { bridge } = useMfeContext(); // Throws if not in MfeProvider\n // @cpt-end:cpt-frontx-flow-react-bindings-use-host-action:p1:inst-read-bridge-for-action\n // @cpt-end:cpt-frontx-algo-react-bindings-mfe-context-guard:p1:inst-throw-no-mfe-context\n\n // @cpt-begin:cpt-frontx-flow-react-bindings-use-host-action:p1:inst-return-action-callback\n return useCallback((payload?: TPayload) => {\n // Construct an ActionsChain with the action\n // With the constraint, TPayload extends Record<string, unknown>,\n // so this is a safe widening from specific to general\n const chain = {\n action: {\n type: actionTypeId,\n target: bridge.extDomainId,\n payload: payload as Record<string, unknown> | undefined,\n },\n };\n\n // @cpt-begin:cpt-frontx-flow-react-bindings-use-host-action:p1:inst-log-action-error\n // Send the chain to the host\n bridge.executeActionsChain(chain).catch((error: Error) => {\n console.error(\n `[useHostAction] Failed to send action '${actionTypeId}':`,\n error\n );\n });\n // @cpt-end:cpt-frontx-flow-react-bindings-use-host-action:p1:inst-log-action-error\n }, [actionTypeId, bridge]);\n // @cpt-end:cpt-frontx-flow-react-bindings-use-host-action:p1:inst-return-action-callback\n}\n// @cpt-end:cpt-frontx-flow-react-bindings-use-host-action:p1:inst-call-host-action\n// @cpt-end:cpt-frontx-dod-react-bindings-mfe-hooks:p1:inst-call-host-action\n","/**\n * useDomainExtensions Hook - Domain extension list subscription\n *\n * Subscribes to store changes to detect when extensions are registered or unregistered,\n * and returns the current list of extensions for a domain.\n *\n * React Layer: L3\n */\n// @cpt-flow:cpt-frontx-flow-react-bindings-use-domain-extensions:p1\n// @cpt-algo:cpt-frontx-algo-react-bindings-mfe-context-guard:p1\n// @cpt-algo:cpt-frontx-algo-react-bindings-stable-snapshots:p1\n// @cpt-dod:cpt-frontx-dod-react-bindings-observation-hooks:p1\n\nimport { useSyncExternalStore, useCallback, useRef } from 'react';\nimport { useFrontX } from '../../FrontXContext';\nimport type { Extension } from '@gears-frontx/framework';\n\n// ============================================================================\n// Hook Implementation\n// ============================================================================\n\n/**\n * Hook for observing extensions registered for a domain.\n *\n * Subscribes to the FrontX store to detect registration state changes,\n * and returns the current list of extensions for the specified domain.\n *\n * @param domainId - Domain ID to query extensions for\n * @returns Array of extensions currently registered for the domain\n *\n * @example\n * ```tsx\n * function SidebarExtensions() {\n * const extensions = useDomainExtensions('gts.frontx.mfes.ext.domain.v1~frontx.screensets.layout.sidebar.v1');\n *\n * return (\n * <div>\n * {extensions.map(ext => (\n * <div key={ext.id}>{ext.id}</div>\n * ))}\n * </div>\n * );\n * }\n * ```\n */\n// @cpt-begin:cpt-frontx-flow-react-bindings-use-domain-extensions:p1:inst-call-domain-extensions\n// @cpt-begin:cpt-frontx-dod-react-bindings-observation-hooks:p1:inst-call-domain-extensions\nexport function useDomainExtensions(domainId: string): Extension[] {\n const app = useFrontX();\n const registry = app.mfeRegistry;\n\n // @cpt-begin:cpt-frontx-flow-react-bindings-use-domain-extensions:p1:inst-guard-registry\n // @cpt-begin:cpt-frontx-algo-react-bindings-mfe-context-guard:p1:inst-throw-no-registry\n if (!registry) {\n throw new Error(\n 'useDomainExtensions requires the microfrontends plugin. ' +\n 'Add microfrontends() to your Gears FrontX app configuration.'\n );\n }\n // @cpt-end:cpt-frontx-flow-react-bindings-use-domain-extensions:p1:inst-guard-registry\n // @cpt-end:cpt-frontx-algo-react-bindings-mfe-context-guard:p1:inst-throw-no-registry\n\n // @cpt-begin:cpt-frontx-flow-react-bindings-use-domain-extensions:p1:inst-subscribe-store\n // Subscribe to store changes.\n // Any dispatch (including registration state updates) triggers a snapshot check.\n // The snapshot comparison ensures only actual extension list changes cause re-renders.\n const subscribe = useCallback(\n (onStoreChange: () => void) => {\n return app.store.subscribe(onStoreChange);\n },\n [app.store]\n );\n // @cpt-end:cpt-frontx-flow-react-bindings-use-domain-extensions:p1:inst-subscribe-store\n\n // @cpt-begin:cpt-frontx-algo-react-bindings-stable-snapshots:p1:inst-cache-ref\n // Cache the snapshot to maintain referential stability for useSyncExternalStore.\n // Only update when the extension IDs actually change.\n const cacheRef = useRef<{ ids: string; extensions: Extension[] }>({ ids: '', extensions: [] });\n // @cpt-end:cpt-frontx-algo-react-bindings-stable-snapshots:p1:inst-cache-ref\n\n // @cpt-begin:cpt-frontx-flow-react-bindings-use-domain-extensions:p1:inst-diff-extensions\n // @cpt-begin:cpt-frontx-flow-react-bindings-use-domain-extensions:p1:inst-stable-reference\n const getSnapshot = useCallback(() => {\n const extensions = registry.getExtensionsForDomain(domainId);\n // @cpt-begin:cpt-frontx-algo-react-bindings-stable-snapshots:p1:inst-compute-cache-key\n const ids = extensions.map(e => e.id).join(',');\n // @cpt-end:cpt-frontx-algo-react-bindings-stable-snapshots:p1:inst-compute-cache-key\n // @cpt-begin:cpt-frontx-algo-react-bindings-stable-snapshots:p1:inst-return-cached\n // @cpt-begin:cpt-frontx-algo-react-bindings-stable-snapshots:p1:inst-update-cache\n if (ids !== cacheRef.current.ids) {\n cacheRef.current = { ids, extensions };\n }\n return cacheRef.current.extensions;\n // @cpt-end:cpt-frontx-algo-react-bindings-stable-snapshots:p1:inst-return-cached\n // @cpt-end:cpt-frontx-algo-react-bindings-stable-snapshots:p1:inst-update-cache\n }, [registry, domainId]);\n // @cpt-end:cpt-frontx-flow-react-bindings-use-domain-extensions:p1:inst-diff-extensions\n // @cpt-end:cpt-frontx-flow-react-bindings-use-domain-extensions:p1:inst-stable-reference\n\n return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n}\n// @cpt-end:cpt-frontx-flow-react-bindings-use-domain-extensions:p1:inst-call-domain-extensions\n// @cpt-end:cpt-frontx-dod-react-bindings-observation-hooks:p1:inst-call-domain-extensions\n","/**\n * useMountedExtensions Hook - Mounted extension observation for any domain\n *\n * Domain-agnostic hook that returns the currently-mounted Extension instances\n * for any registered domain, including multi-mount domains backed by\n * ConcurrentMountStrategy.\n *\n * React Layer: L3\n */\n// @cpt-flow:cpt-frontx-flow-react-bindings-use-mounted-extensions:p1\n// @cpt-algo:cpt-frontx-algo-react-bindings-mfe-context-guard:p1\n// @cpt-algo:cpt-frontx-algo-react-bindings-stable-snapshots:p1\n// @cpt-dod:cpt-frontx-dod-react-bindings-observation-hooks:p1\n\nimport { useSyncExternalStore, useCallback, useRef } from 'react';\nimport { useFrontX } from '../../FrontXContext';\nimport type { Extension } from '@gears-frontx/framework';\n\n// ============================================================================\n// Hook Implementation\n// ============================================================================\n\n/**\n * Hook for observing the currently-mounted extensions in any domain.\n *\n * Subscribes to the FrontX store to detect mount state changes, and returns\n * the array of Extension instances currently mounted in the specified domain.\n *\n * Pairs with getMountedExtensions(domainId) on the registry and resolves each\n * mounted extension ID to its Extension instance. IDs that have been unregistered\n * concurrently (race against unregister) are filtered out.\n *\n * Returns a referentially stable array when the underlying ID list is unchanged.\n *\n * For multi-mount domains (ConcurrentMountStrategy), may return more than one entry.\n * For single-mount domains (ExclusiveMountStrategy), the returned array has at most one entry.\n *\n * @param domainId - Domain ID to query mounted extensions for\n * @returns Array of Extension instances currently mounted in the domain\n *\n * @example\n * ```tsx\n * function MountedWidgets() {\n * const mounted = useMountedExtensions('gts.frontx.mfes.ext.domain.v1~frontx.screensets.layout.sidebar.v1');\n *\n * return (\n * <ul>\n * {mounted.map(ext => (\n * <li key={ext.id}>{ext.id}</li>\n * ))}\n * </ul>\n * );\n * }\n * ```\n */\n// @cpt-begin:cpt-frontx-flow-react-bindings-use-mounted-extensions:p1:inst-call-mounted-extensions\n// @cpt-begin:cpt-frontx-dod-react-bindings-observation-hooks:p1:inst-call-mounted-extensions\nexport function useMountedExtensions(domainId: string): Extension[] {\n const app = useFrontX();\n const registry = app.mfeRegistry;\n\n // @cpt-begin:cpt-frontx-flow-react-bindings-use-mounted-extensions:p1:inst-guard-registry-mounted\n // @cpt-begin:cpt-frontx-algo-react-bindings-mfe-context-guard:p1:inst-throw-no-registry\n if (!registry) {\n throw new Error(\n 'useMountedExtensions requires the microfrontends plugin. ' +\n 'Add microfrontends() to your Gears FrontX app configuration.'\n );\n }\n // @cpt-end:cpt-frontx-flow-react-bindings-use-mounted-extensions:p1:inst-guard-registry-mounted\n // @cpt-end:cpt-frontx-algo-react-bindings-mfe-context-guard:p1:inst-throw-no-registry\n\n // @cpt-begin:cpt-frontx-flow-react-bindings-use-mounted-extensions:p1:inst-subscribe-store-mounted\n // Subscribe to store changes. Any dispatch (including mount state updates) triggers\n // a snapshot check. The cache key comparison ensures only actual mount-set changes\n // cause re-renders.\n const subscribe = useCallback(\n (onStoreChange: () => void) => {\n return app.store.subscribe(onStoreChange);\n },\n [app.store]\n );\n // @cpt-end:cpt-frontx-flow-react-bindings-use-mounted-extensions:p1:inst-subscribe-store-mounted\n\n // @cpt-begin:cpt-frontx-algo-react-bindings-stable-snapshots:p1:inst-cache-ref\n // Cache the snapshot to maintain referential stability for useSyncExternalStore.\n // Only update when the mounted ID list actually changes.\n const cacheRef = useRef<{ key: string; extensions: Extension[] }>({ key: '', extensions: [] });\n // @cpt-end:cpt-frontx-algo-react-bindings-stable-snapshots:p1:inst-cache-ref\n\n const getSnapshot = useCallback(() => {\n // @cpt-begin:cpt-frontx-flow-react-bindings-use-mounted-extensions:p1:inst-use-mounted-extensions-snapshot\n const ids = registry.getMountedExtensions(domainId);\n const resolved = ids\n .map(id => registry.getExtension(id))\n .filter((ext): ext is Extension => ext !== undefined);\n // @cpt-end:cpt-frontx-flow-react-bindings-use-mounted-extensions:p1:inst-use-mounted-extensions-snapshot\n\n // @cpt-begin:cpt-frontx-flow-react-bindings-use-mounted-extensions:p1:inst-mounted-extensions-stable-ref\n // @cpt-begin:cpt-frontx-algo-react-bindings-stable-snapshots:p1:inst-compute-cache-key\n const key = ids.join(',');\n // @cpt-end:cpt-frontx-algo-react-bindings-stable-snapshots:p1:inst-compute-cache-key\n\n // @cpt-begin:cpt-frontx-algo-react-bindings-stable-snapshots:p1:inst-return-cached\n // @cpt-begin:cpt-frontx-algo-react-bindings-stable-snapshots:p1:inst-update-cache\n if (key !== cacheRef.current.key) {\n cacheRef.current = { key, extensions: resolved };\n }\n return cacheRef.current.extensions;\n // @cpt-end:cpt-frontx-algo-react-bindings-stable-snapshots:p1:inst-return-cached\n // @cpt-end:cpt-frontx-algo-react-bindings-stable-snapshots:p1:inst-update-cache\n // @cpt-end:cpt-frontx-flow-react-bindings-use-mounted-extensions:p1:inst-mounted-extensions-stable-ref\n }, [registry, domainId]);\n\n return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n}\n// @cpt-end:cpt-frontx-flow-react-bindings-use-mounted-extensions:p1:inst-call-mounted-extensions\n// @cpt-end:cpt-frontx-dod-react-bindings-observation-hooks:p1:inst-call-mounted-extensions\n","/**\n * useRegisteredPackages Hook - Registered GTS packages subscription\n *\n * Subscribes to store changes to detect when extensions are registered or unregistered,\n * and returns the current list of registered GTS packages.\n *\n * React Layer: L3\n */\n// @cpt-flow:cpt-frontx-flow-react-bindings-use-registered-packages:p1\n// @cpt-algo:cpt-frontx-algo-react-bindings-mfe-context-guard:p1\n// @cpt-algo:cpt-frontx-algo-react-bindings-stable-snapshots:p1\n// @cpt-dod:cpt-frontx-dod-react-bindings-observation-hooks:p1\n\nimport { useSyncExternalStore, useCallback, useRef } from 'react';\nimport { useFrontX } from '../../FrontXContext';\n\n// ============================================================================\n// Hook Implementation\n// ============================================================================\n\n/**\n * Hook for observing registered GTS packages.\n *\n * Subscribes to the FrontX store to detect registration state changes,\n * and returns the current list of GTS packages extracted from registered\n * extensions.\n *\n * ARCHITECTURAL NOTE ON STORE SUBSCRIPTION COUPLING:\n * This hook uses `useSyncExternalStore` with `app.store.subscribe`, which\n * fires on any Redux dispatch. Since `registerExtension()` dispatches to\n * the mfe store slice, the subscription WILL trigger when packages change.\n * The `getSnapshot` function calls `mfeRegistry.getRegisteredPackages()`\n * which reads the private `packages` Map. This works because every package\n * map mutation (in registerExtension/unregisterExtension) is always\n * accompanied by a store dispatch in the same serializer callback.\n *\n * IMPORTANT: If a future change mutates the packages map WITHOUT a store\n * dispatch, this hook would fail to re-render. Keep this coupling documented.\n *\n * @returns Array of GTS package strings currently registered\n *\n * @example\n * ```tsx\n * function PackageList() {\n * const packages = useRegisteredPackages();\n *\n * return (\n * <div>\n * {packages.map(pkg => (\n * <div key={pkg}>{pkg}</div>\n * ))}\n * </div>\n * );\n * }\n * ```\n */\n// @cpt-begin:cpt-frontx-flow-react-bindings-use-registered-packages:p1:inst-call-registered-packages\n// @cpt-begin:cpt-frontx-dod-react-bindings-observation-hooks:p1:inst-call-registered-packages\nexport function useRegisteredPackages(): string[] {\n const app = useFrontX();\n const registry = app.mfeRegistry;\n\n // @cpt-begin:cpt-frontx-flow-react-bindings-use-registered-packages:p1:inst-guard-registry-packages\n // @cpt-begin:cpt-frontx-algo-react-bindings-mfe-context-guard:p1:inst-throw-no-registry\n if (!registry) {\n throw new Error(\n 'useRegisteredPackages requires the microfrontends plugin. ' +\n 'Add microfrontends() to your Gears FrontX app configuration.'\n );\n }\n // @cpt-end:cpt-frontx-flow-react-bindings-use-registered-packages:p1:inst-guard-registry-packages\n // @cpt-end:cpt-frontx-algo-react-bindings-mfe-context-guard:p1:inst-throw-no-registry\n\n // @cpt-begin:cpt-frontx-flow-react-bindings-use-registered-packages:p1:inst-subscribe-store-packages\n // Subscribe to store changes.\n // Any dispatch (including registration state updates) triggers a snapshot check.\n // The snapshot comparison ensures only actual package list changes cause re-renders.\n const subscribe = useCallback(\n (onStoreChange: () => void) => {\n return app.store.subscribe(onStoreChange);\n },\n [app.store]\n );\n // @cpt-end:cpt-frontx-flow-react-bindings-use-registered-packages:p1:inst-subscribe-store-packages\n\n // @cpt-begin:cpt-frontx-algo-react-bindings-stable-snapshots:p1:inst-cache-ref\n // Cache the snapshot to maintain referential stability for useSyncExternalStore.\n // Only update when the package list actually changes.\n const cacheRef = useRef<{ packages: string; list: string[] }>({ packages: '', list: [] });\n // @cpt-end:cpt-frontx-algo-react-bindings-stable-snapshots:p1:inst-cache-ref\n\n // @cpt-begin:cpt-frontx-flow-react-bindings-use-registered-packages:p1:inst-diff-packages\n const getSnapshot = useCallback(() => {\n const list = registry.getRegisteredPackages();\n // @cpt-begin:cpt-frontx-algo-react-bindings-stable-snapshots:p1:inst-compute-cache-key\n const packages = list.join(',');\n // @cpt-end:cpt-frontx-algo-react-bindings-stable-snapshots:p1:inst-compute-cache-key\n // @cpt-begin:cpt-frontx-algo-react-bindings-stable-snapshots:p1:inst-return-cached\n // @cpt-begin:cpt-frontx-algo-react-bindings-stable-snapshots:p1:inst-update-cache\n if (packages !== cacheRef.current.packages) {\n cacheRef.current = { packages, list };\n }\n return cacheRef.current.list;\n // @cpt-end:cpt-frontx-algo-react-bindings-stable-snapshots:p1:inst-return-cached\n // @cpt-end:cpt-frontx-algo-react-bindings-stable-snapshots:p1:inst-update-cache\n }, [registry]);\n // @cpt-end:cpt-frontx-flow-react-bindings-use-registered-packages:p1:inst-diff-packages\n\n return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n}\n// @cpt-end:cpt-frontx-flow-react-bindings-use-registered-packages:p1:inst-call-registered-packages\n// @cpt-end:cpt-frontx-dod-react-bindings-observation-hooks:p1:inst-call-registered-packages\n","import React from 'react';\nimport { createRoot, type Root } from 'react-dom/client';\nimport type {\n FrontXApp,\n MfeEntryLifecycle,\n ChildMfeBridge,\n MfeMountContext,\n} from '@gears-frontx/framework';\nimport { FrontXProvider } from '../FrontXProvider';\nimport { hasFrontXQueryClientActivator, resolveFrontXQueryClient } from '../queryClient';\n\n/**\n * Marks every node `adoptHostStylesIntoShadowRoot` puts into a shadow root, so\n * a later mount can find its own previous block and replace it.\n *\n * A marker attribute rather than the single `id` that\n * `injectStylesheet`/`injectCssVariables` key on in `@gears-frontx/mfes`'\n * shadow utilities, because the adopted block is many nodes whose order\n * relative to each other is load-bearing: one id can only name one of them.\n */\nconst ADOPTED_HOST_STYLE_ATTR = 'data-frontx-adopted-host-style';\n\n/** Identity of the base-resets node, so a remount reuses it instead of adding a second. */\nconst BASE_RESETS_STYLE_ID = '__frontx-base-resets__';\n\n/**\n * Ids of the style nodes `@gears-frontx/mfes` puts in a shadow root itself -\n * the isolation block from `createShadowRoot` and the theme variables from\n * `injectCssVariables`. Together with the adopted block they are the\n * shell-owned head of the shadow root, and the base resets belong at its end:\n * after them, ahead of the MFE's own CSS.\n *\n * Mirrored here rather than imported because those utilities keep the ids as\n * local constants. The values are what the shell puts in the shadow root, so\n * they change only when the shell changes them - and the remount test pins\n * this list against the ids those utilities actually emit.\n */\nconst SHELL_OWNED_SHADOW_STYLE_IDS = ['__frontx-shadow-isolation__', '__frontx-css-variables__'];\n\ninterface ProviderMountOptions {\n mfeBridge?: {\n bridge: ChildMfeBridge;\n extensionId: string;\n domainId: string;\n };\n}\n\nfunction resolveProviderMountOptions(\n app: FrontXApp,\n bridge: ChildMfeBridge,\n mountContext?: MfeMountContext\n): ProviderMountOptions {\n const extensionId = mountContext?.extensionId;\n const domainId = mountContext?.domainId;\n const isMountedMfe = typeof extensionId === 'string' && typeof domainId === 'string';\n\n if (\n isMountedMfe &&\n !resolveFrontXQueryClient(app) &&\n !hasFrontXQueryClientActivator(app)\n ) {\n throw new Error(\n '[FrontXProvider] Mounted MFEs require queryCacheShared() in the child app and queryCache() in the host app before loading the MFE app.'\n );\n }\n\n return {\n mfeBridge:\n isMountedMfe\n ? { bridge, extensionId, domainId }\n : undefined,\n };\n}\n\ninterface MountRuntimeAwareProviderProps {\n readonly app: FrontXApp;\n readonly mfeBridge?: Readonly<{\n readonly bridge: ChildMfeBridge;\n readonly extensionId: string;\n readonly domainId: string;\n }>;\n readonly children: React.ReactNode;\n}\n\nfunction MountRuntimeAwareProvider({\n app,\n mfeBridge,\n children,\n}: Readonly<MountRuntimeAwareProviderProps>): React.JSX.Element {\n return (\n <FrontXProvider app={app} mfeBridge={mfeBridge}>\n {children}\n </FrontXProvider>\n );\n}\n\n/**\n * Abstract base class for React-based MFE lifecycle implementations.\n *\n * Styling strategy:\n * 1. adoptHostStylesIntoShadowRoot() clones all host <style> and <link> into the\n * front of the shadow root, bringing the full compiled Tailwind CSS (including\n * MFE utilities, since the host's content paths cover src-app/mfe_packages/**) and\n * the ui-kit component CSS (the host entry side-effect-imports\n * @gears-frontx/ui-kit so that CSS exists in the host document; the kit's\n * CSS-module class names are stable per kit version, so they match the\n * classes MFE bundles reference only while host and MFE install the same\n * kit version - the template-pin-drift policy check is what guarantees\n * that; a drifted MFE renders its kit components unstyled with no error).\n * Front, not back, so the MFE's own stylesheets\n * outrank them - see the method. Design tokens must therefore be full CSS\n * colors - both Tailwind utilities (var(--x)) and ui-kit component CSS\n * consume them directly.\n * 2. injectBaseResets() adds box-model resets and :host defaults that aren't part\n * of Tailwind's compiled output but are needed for consistent rendering, and\n * positions them at the end of the shell-owned head - after the adopted block\n * and the isolation style, ahead of the MFE's own CSS.\n * 3. Subclasses may override initializeStyles() to inject additional CSS that is\n * not covered by the host stylesheet (e.g., MFE-specific @font-face rules).\n *\n * Every mount therefore leaves the same sequence - adopted host block, shadow\n * isolation, base resets, then the MFE's stylesheets - so the shell's CSS is\n * context and the MFE wins every specificity tie against all three shell blocks.\n * Steps 1 and 2 both position what they own rather than appending beside it,\n * because a remounted container arrives with its shadow root intact and the MFE's\n * own stylesheet removed and re-appended around the remount - see each method.\n *\n * Theme CSS variables are delivered via CSS inheritance from :root (Shadow DOM)\n * or via MountManager injection (iframe). MFE lifecycles do NOT need to subscribe\n * to theme changes or call applyThemeToShadowRoot.\n *\n * Concrete subclasses must provide:\n * - `renderContent(bridge)` - screen component rendering\n */\nexport abstract class ThemeAwareReactLifecycle implements MfeEntryLifecycle<ChildMfeBridge> {\n private root: Root | null = null;\n\n constructor(private readonly app: FrontXApp) { }\n\n mount(container: Element | ShadowRoot, bridge: ChildMfeBridge, mountContext?: MfeMountContext): void {\n if (container instanceof ShadowRoot) {\n this.adoptHostStylesIntoShadowRoot(container);\n }\n\n this.injectBaseResets(container);\n this.initializeStyles(container);\n\n const providerMountOptions = resolveProviderMountOptions(this.app, bridge, mountContext);\n this.root = createRoot(container);\n this.root.render(\n <MountRuntimeAwareProvider\n app={this.app}\n mfeBridge={providerMountOptions.mfeBridge}\n >\n {this.renderContent(bridge)}\n </MountRuntimeAwareProvider>\n );\n }\n\n unmount(_container: Element | ShadowRoot): void {\n if (this.root) {\n this.root.unmount();\n this.root = null;\n }\n }\n\n /**\n * Copy all inline <style> and <link rel=\"stylesheet\"> from the host document\n * into the shadow root so that Tailwind and component styles apply inside the MFE.\n *\n * The clones are inserted ahead of everything already in the shadow root, never\n * appended, because adopted host styles are context rather than authority: where\n * they and the MFE's own CSS declare the same property at equal specificity, the\n * MFE has to win. Appending inverted that. `MfeHandlerMF` injects the MFE's\n * compiled stylesheet into the shadow root before it calls mount, so an appended\n * clone of the shell's Tailwind preflight - whose\n * `button, [type='button'], [type='reset'], [type='submit']` rule sets\n * `background-color: transparent` at specificity (0,1,0) - tied with\n * `@gears-frontx/ui-kit`'s single-class button rule and won on document order,\n * leaving every kit Button transparent until it was hovered.\n *\n * Inserting at the front rather than pushing MFE styles to the back is what makes\n * the invariant hold for stylesheets that appear after mount too - a lazily\n * imported component's CSS module, or whatever initializeStyles() adds - since\n * those land behind the adopted block by construction.\n *\n * A cascade layer around the adopted CSS was the alternative and is rejected:\n * layered rules lose to unlayered ones at *any* specificity, so a host utility\n * class would stop overriding an MFE element selector. Document order keeps\n * specificity in charge and only settles the ties.\n *\n * The block replaces its predecessor instead of stacking on it, the same\n * upsert shape `injectStylesheet` and `injectCssVariables` use in\n * `@gears-frontx/mfes`' shadow utilities, widened from one id-keyed node to a\n * marked block. Replacement is required rather than tidy: `createShadowRoot`\n * hands back an existing `element.shadowRoot` instead of attaching a new one,\n * so remounting the same container runs this method again on a shadow root\n * that already holds a full adopted block, and appending would grow it once\n * per mount with no bound. It does not save re-resolving the cloned `<link>`s -\n * every mount clones them afresh and the browser resolves each clone; what\n * replacement buys is that the count stays at one block instead of one per\n * mount.\n *\n * The block is rebuilt from the host head rather than left in place, because\n * the head is not fixed: a lazily imported chunk adds stylesheets to it after\n * the first mount, and the second mount has to pick those up.\n *\n * The fresh block goes in before the previous one comes out. Removing first\n * leaves the shadow root with no host CSS at all, and everything between that\n * removal and the insertion is synchronous work in this same task - so the gap\n * never reaches a paint, but any code that reads computed styles from the tree\n * in between sees an unstyled one. Inserting first costs one moment with two\n * blocks present, which changes nothing: the old block is a clone of the same\n * host head and loses every tie to the new one on document order anyway.\n */\n protected adoptHostStylesIntoShadowRoot(shadowRoot: ShadowRoot): void {\n // Collected before the insertion, so the marked nodes this removes are only\n // the ones already there: the fresh clones below carry the same marker and\n // a selector query after the insertion would match them too.\n const supersededStyles = Array.from(shadowRoot.querySelectorAll(`[${ADOPTED_HOST_STYLE_ATTR}]`));\n\n const adoptedStyles = document.createDocumentFragment();\n\n // One query covering both kinds, because querySelectorAll returns document\n // order: querying <style> and <link> separately would concatenate the two\n // groups instead, so a host declaring <link A> before <style B> would get\n // them adopted as B then A. That reordering decides which rule wins every\n // specificity tie between them, which is the tie this whole method exists\n // to settle - so the adopted block has to preserve the host's own order,\n // not just sit ahead of the MFE's CSS.\n const hostStyleNodes = document.head.querySelectorAll('style, link[rel=\"stylesheet\"]');\n hostStyleNodes.forEach((el) => {\n if (el instanceof HTMLStyleElement) {\n const clone = document.createElement('style');\n clone.textContent = el.textContent ?? '';\n clone.setAttribute(ADOPTED_HOST_STYLE_ATTR, '');\n adoptedStyles.appendChild(clone);\n return;\n }\n const linkClone = el.cloneNode(true) as Element;\n linkClone.setAttribute(ADOPTED_HOST_STYLE_ATTR, '');\n adoptedStyles.appendChild(linkClone);\n });\n\n // Staged in a fragment so the adopted pieces keep their host-document order\n // relative to each other while moving as one block to the front.\n shadowRoot.insertBefore(adoptedStyles, shadowRoot.firstChild);\n supersededStyles.forEach((el) => el.remove());\n }\n\n /**\n * Box-model resets and :host defaults needed inside every shadow root.\n * These aren't part of Tailwind's compiled output but are required for\n * consistent rendering across browsers.\n *\n * Reuses the node a previous mount left behind, exactly as `injectStylesheet`\n * does in `@gears-frontx/mfes`' shadow utilities: a remount runs against a\n * shadow root that `createShadowRoot` handed back intact, and appending a\n * second copy would add one node per mount forever.\n *\n * Reuse alone is not enough, which is why the node is also positioned on every\n * mount rather than left where the previous one sat. These resets are context\n * like the adopted block is - `border-color: currentColor` on `*` is a 0-0-0\n * declaration that beats an MFE preflight's own 0-0-0 reset purely on document\n * order - so they have to stay ahead of the MFE's CSS, and where they land is\n * not stable on its own. `MfeHandlerMF.wrapLifecycleWithStylesheets` removes the\n * MFE's stylesheet on unmount and appends a fresh one before the next mount, so\n * a node merely left in place ends up ahead of that stylesheet on a remount and\n * behind it on the first mount: two different cascades for one component.\n * Anchoring it to the end of the shell-owned head gives every mount the same\n * order - adopted block, isolation, resets, MFE - which is also the order the\n * adoption method's invariant is written against.\n *\n * With no shell-owned node to anchor to, the resets go to the front. That is the\n * plain-`Element` container: no adopted block, no isolation style, and the MFE\n * stylesheet already appended by the handler, so the front is again the only\n * position that leaves the MFE winning ties.\n *\n * Looked up by attribute-selector form rather than `getElementById`, which\n * `ShadowRoot` has but `Element` does not, and this hook takes either.\n */\n private injectBaseResets(container: Element | ShadowRoot): void {\n const existing = container.querySelector<HTMLStyleElement>(\n `style[id=\"${BASE_RESETS_STYLE_ID}\"]`\n );\n const style = existing ?? document.createElement('style');\n style.id = BASE_RESETS_STYLE_ID;\n style.textContent = `\n *, *::before, *::after {\n box-sizing: border-box;\n border-width: 0;\n border-style: solid;\n border-color: currentColor;\n }\n * { margin: 0; padding: 0; }\n :host {\n font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;\n line-height: 1.5;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n color: var(--foreground);\n background-color: var(--background);\n }\n `;\n // Runs whether the node is new or reused: `insertBefore` moves a node that\n // is already in the tree, and is a no-op when it already sits there.\n const shellOwnedHead = container.querySelectorAll(\n [\n `[${ADOPTED_HOST_STYLE_ATTR}]`,\n ...SHELL_OWNED_SHADOW_STYLE_IDS.map((id) => `[id=\"${id}\"]`),\n ].join(', ')\n );\n const lastShellOwnedNode = shellOwnedHead[shellOwnedHead.length - 1];\n container.insertBefore(\n style,\n lastShellOwnedNode ? lastShellOwnedNode.nextSibling : container.firstChild\n );\n }\n\n /**\n * Hook for subclasses to inject additional CSS not covered by the adopted host\n * stylesheet (e.g., MFE-specific @font-face rules or custom animations).\n * No-op by default: host styles adopted in adoptHostStylesIntoShadowRoot()\n * already include all Tailwind utilities compiled from MFE source files.\n */\n protected initializeStyles(_container: Element | ShadowRoot): void {\n // No-op by default.\n }\n\n /**\n * Return the screen-specific React component tree.\n */\n protected abstract renderContent(bridge: ChildMfeBridge): React.ReactNode;\n}\n","/**\n * Extension Domain Slot Component\n *\n * Per-domain React component that provides the DOM root for a registered domain.\n * Delegates root attachment to the per-domain ExtensionMounter obtained from the\n * registry. What extensions live inside the root is a domain-policy concern (the\n * active MountStrategy plus the domain implementation's ContainerHooks), not a\n * slot-API concern.\n *\n * The slot is uniform across all cardinalities (Exclusive / Optional / Concurrent).\n * Mount and unmount actions are dispatched by the host application via\n * registry.executeActionsChain — NOT by this component.\n *\n * @packageDocumentation\n */\n// @cpt-flow:cpt-frontx-flow-react-bindings-extension-domain-slot:p1\n// @cpt-state:cpt-frontx-state-react-bindings-extension-slot:p1\n// @cpt-dod:cpt-frontx-dod-react-bindings-extension-slot:p1\n\nimport React, { useEffect, useEffectEvent, useRef, useState } from 'react';\nimport type { MfeRegistry } from '@gears-frontx/framework';\n\n/**\n * Props for ExtensionDomainSlot component\n */\nexport interface ExtensionDomainSlotProps {\n /**\n * The screensets registry instance.\n */\n registry: MfeRegistry;\n\n /**\n * The domain ID for this slot.\n */\n domainId: string;\n\n /**\n * Optional CSS class name for the root container div.\n */\n className?: string;\n\n /**\n * Optional callback invoked after mounter.attach(element) returns.\n * Receives the root element that was attached.\n */\n onAttached?: (root: Element) => void;\n\n /**\n * Optional callback invoked after mounter.detach() returns on cleanup.\n */\n onDetached?: () => void;\n\n /**\n * Optional loading placeholder rendered before the mounter has been attached.\n * Defaults to null (no visual placeholder).\n */\n loadingComponent?: React.ReactNode;\n}\n\n/**\n * Extension Domain Slot Component\n *\n * Renders a single root `<div>` per domain instance. On ref-attach, resolves the\n * per-domain mounter via registry.getMounter(domainId) and calls mounter.attach(element).\n * On cleanup, calls mounter.detach() which mass-unmounts every currently-mounted\n * extension in the domain so no orphan DOM trees or slice/registry desync remain.\n *\n * @example\n * ```tsx\n * <ExtensionDomainSlot\n * registry={registry}\n * domainId={FRONTX_SCREEN_DOMAIN}\n * loadingComponent={<Loading />}\n * onAttached={(root) => console.log('Root attached:', root)}\n * />\n * ```\n */\n// @cpt-begin:cpt-frontx-flow-react-bindings-extension-domain-slot:p1:inst-render-slot\n// @cpt-begin:cpt-frontx-dod-react-bindings-extension-slot:p1:inst-render-slot\nexport function ExtensionDomainSlot(props: ExtensionDomainSlotProps): React.ReactElement {\n const {\n registry,\n domainId,\n className,\n onAttached,\n onDetached,\n loadingComponent = null,\n } = props;\n\n const rootRef = useRef<HTMLDivElement | null>(null);\n\n // Effect events so effect deps stay minimal — inline parent handlers do not\n // re-run the attach/detach effect on every parent render, yet each call\n // sees the latest committed onAttached/onDetached prop.\n const emitAttached = useEffectEvent((root: Element) => {\n onAttached?.(root);\n });\n const emitDetached = useEffectEvent(() => {\n onDetached?.();\n });\n\n // @cpt-begin:cpt-frontx-state-react-bindings-extension-slot:p1:inst-slot-attached\n // Tracks whether the mounter has been attached to the DOM root.\n // The loading placeholder is shown until attached becomes true.\n const [attached, setAttached] = useState(false);\n // @cpt-end:cpt-frontx-state-react-bindings-extension-slot:p1:inst-slot-attached\n\n useEffect(() => {\n const root = rootRef.current;\n if (!root) {\n return;\n }\n\n // @cpt-begin:cpt-frontx-flow-react-bindings-extension-domain-slot:p1:inst-attach-root\n // Resolve the per-domain mounter and attach the DOM root.\n // The mounter owns all per-extension container placement under this root.\n const mounter = registry.getMounter(domainId);\n mounter.attach(root);\n // @cpt-end:cpt-frontx-flow-react-bindings-extension-domain-slot:p1:inst-attach-root\n\n // @cpt-begin:cpt-frontx-state-react-bindings-extension-slot:p1:inst-slot-attached\n setAttached(true);\n // @cpt-end:cpt-frontx-state-react-bindings-extension-slot:p1:inst-slot-attached\n\n emitAttached(root);\n\n // @cpt-begin:cpt-frontx-flow-react-bindings-extension-domain-slot:p1:inst-detach-root\n return () => {\n // Mass-unmount every extension currently mounted in the domain.\n // detach() is async (awaits per-extension unmounts) but React cleanup is\n // synchronous; we deliberately fire-and-forget here.\n void mounter.detach();\n\n // @cpt-begin:cpt-frontx-state-react-bindings-extension-slot:p1:inst-slot-detached\n setAttached(false);\n // @cpt-end:cpt-frontx-state-react-bindings-extension-slot:p1:inst-slot-detached\n\n // emitDetached is an effect event: it always calls the onDetached prop\n // from the latest committed render, not whatever prop was current when\n // this effect instance was originally set up.\n emitDetached();\n };\n // @cpt-end:cpt-frontx-flow-react-bindings-extension-domain-slot:p1:inst-detach-root\n // @cpt-begin:cpt-frontx-state-react-bindings-extension-slot:p2:inst-slot-stable-rerender\n // ATTACHED → ATTACHED (no-op) when parent supplies the same domainId and\n // registry on re-render: useEffect dep equality short-circuits the attach/detach pair.\n // emitAttached/emitDetached are effect events — non-reactive by contract,\n // so they are excluded from deps and the effect does not re-run when the\n // parent passes new inline handlers.\n }, [registry, domainId]);\n // @cpt-end:cpt-frontx-state-react-bindings-extension-slot:p2:inst-slot-stable-rerender\n\n // @cpt-begin:cpt-frontx-flow-react-bindings-extension-domain-slot:p1:inst-show-loading\n // Render the loading placeholder until the mounter has been attached.\n // Once attached, render the root div with null children — multi-mount children\n // are placed imperatively under this root by the per-domain mounter.\n return (\n <div\n ref={rootRef}\n className={className}\n data-domain-id={domainId}\n >\n {!attached ? loadingComponent : null}\n </div>\n );\n // @cpt-end:cpt-frontx-flow-react-bindings-extension-domain-slot:p1:inst-show-loading\n}\n// @cpt-end:cpt-frontx-flow-react-bindings-extension-domain-slot:p1:inst-render-slot\n// @cpt-end:cpt-frontx-dod-react-bindings-extension-slot:p1:inst-render-slot\n","/**\n * @gears-frontx/react - React Bindings\n *\n * This package provides:\n * - FrontXProvider context provider\n * - Type-safe hooks for state and actions\n * - MFE context, hooks, and components\n *\n * Layer: L3 (Depends on @gears-frontx/framework)\n */\n\n// ============================================================================\n// Provider\n// ============================================================================\n\nexport { FrontXProvider } from './FrontXProvider';\nexport { FrontXContext, useFrontX } from './FrontXContext';\nexport { invalidateQueryCacheForApp } from './queryClient';\nexport { CanAccess } from './components/CanAccess';\nexport type { CanAccessProps } from './types';\n\n// ============================================================================\n// Hooks\n// ============================================================================\n\nexport {\n useAppDispatch,\n useAppSelector,\n useTranslation,\n useScreenTranslations,\n useFormatters,\n useTheme,\n useApiQuery,\n useApiSuspenseQuery,\n useApiInfiniteQuery,\n useApiSuspenseInfiniteQuery,\n useApiMutation,\n useApiStream,\n useQueryCache,\n} from './hooks';\nexport { useCanAccess } from './hooks/useCanAccess';\n\nexport type { ApiQueryOverrides } from './hooks/useApiQuery';\nexport type {\n ApiInfiniteQueryOptions,\n ApiInfiniteQueryPageContext,\n} from './hooks/useApiInfiniteQuery';\nexport type { UseApiMutationOptions } from './hooks/useApiMutation';\nexport type { ApiStreamOptions, ApiStreamResult } from './hooks/useApiStream';\nexport type {\n QueryCache,\n QueryCacheInvalidateFilters,\n QueryCacheState,\n MutationCallbackContext,\n} from './hooks/QueryCache';\n\n// ============================================================================\n// MFE Context and Hooks\n// ============================================================================\n\nexport {\n MfeContext,\n useMfeContext,\n MfeProvider,\n useMfeBridge,\n ThemeAwareReactLifecycle,\n useSharedProperty,\n useHostAction,\n useDomainExtensions,\n useMountedExtensions,\n useRegisteredPackages,\n ExtensionDomainSlot,\n} from './mfe';\n\nexport type {\n MfeContextValue,\n MfeProviderProps,\n ExtensionDomainSlotProps,\n UseSharedPropertyOptions,\n} from './mfe';\n\n// ============================================================================\n// Type Exports\n// ============================================================================\n\nexport type {\n FrontXProviderProps,\n UseFrontXReturn,\n UseAppSelector,\n UseAppDispatchReturn,\n UseTranslationReturn,\n UseScreenTranslationsReturn,\n UseFormattersReturn,\n UseThemeReturn,\n ApiQueryResult,\n ApiSuspenseQueryResult,\n ApiInfiniteQueryResult,\n ApiSuspenseInfiniteQueryResult,\n ApiMutationResult,\n UseCanAccessResult,\n} from './types';\n\n// ============================================================================\n// Re-exports from @gears-frontx/framework for convenience\n// ============================================================================\n\n// These re-exports allow users to import everything from @gears-frontx/react\n// without needing to import from @gears-frontx/framework directly\n\nexport {\n // Core\n createFrontX,\n createFrontXApp,\n presets,\n\n // Backward compatibility constants\n ACCOUNTS_DOMAIN,\n\n // I18nRegistry class (capital I for backward compat)\n I18nRegistry,\n\n // Plugins\n themes,\n layout,\n i18n,\n effects,\n queryCache,\n queryCacheShared,\n subscribeQueryCacheRuntimeChanged,\n\n // Registries\n createThemeRegistry,\n\n // Flux (Event bus + Store)\n // NOTE: eventBus is re-exported separately below with augmented EventPayloadMap type\n\n // Store\n createStore,\n getStore,\n registerSlice,\n hasSlice,\n createSlice,\n\n // Layout domain exports\n layoutReducer,\n layoutDomainReducers,\n LAYOUT_SLICE_NAME,\n headerSlice,\n footerSlice,\n menuSlice,\n sidebarSlice,\n popupSlice,\n overlaySlice,\n headerActions,\n footerActions,\n menuActions,\n sidebarActions,\n popupActions,\n overlayActions,\n // Individual reducer functions - header\n setUser,\n setHeaderLoading,\n clearUser,\n // Individual reducer functions - footer\n setFooterVisible,\n setFooterConfig,\n toggleMenu,\n setMenuCollapsed,\n setMenuItems,\n setMenuVisible,\n setMenuConfig,\n toggleSidebar,\n setSidebarCollapsed,\n setSidebarPosition,\n setSidebarTitle,\n setSidebarContent,\n setSidebarVisible,\n setSidebarWidth,\n setSidebarConfig,\n openPopup,\n closePopup,\n closeTopPopup,\n closeAllPopups,\n showOverlay,\n hideOverlay,\n setOverlayVisible,\n\n // Tenant (app-level, not layout)\n TENANT_SLICE_NAME,\n tenantSlice,\n tenantActions,\n tenantReducer,\n setTenant,\n setTenantLoading,\n clearTenant,\n // Tenant effects and events\n initTenantEffects,\n changeTenant,\n clearTenantAction,\n setTenantLoadingState,\n TenantEvents,\n\n // Mock (app-level, not layout)\n mockSlice,\n mockActions,\n setMockEnabled,\n // Mock effects and events\n initMockEffects,\n toggleMockMode,\n MockEvents,\n\n // Auth\n auth,\n frontxApiTransport,\n\n // API\n apiRegistry,\n BaseApiService,\n RestProtocol,\n RestEndpointProtocol,\n SseProtocol,\n SseStreamProtocol,\n // Plugin base classes\n ApiPluginBase,\n ApiPlugin,\n ApiProtocol,\n RestPlugin,\n RestPluginWithConfig,\n SsePlugin,\n SsePluginWithConfig,\n // Type guards\n isShortCircuit,\n isRestShortCircuit,\n isSseShortCircuit,\n // Mock plugin identification\n MOCK_PLUGIN,\n isMockPlugin,\n\n // I18n\n i18nRegistry,\n I18nRegistryImpl,\n createI18nRegistry,\n SUPPORTED_LANGUAGES,\n getLanguageMetadata,\n} from '@gears-frontx/framework';\n\n// Re-export i18n types from @gears-frontx/framework (correct layer access)\nexport { Language, TextDirection, LanguageDisplayMode } from '@gears-frontx/framework';\n\n// Re-export types from @gears-frontx/framework\nexport type {\n // Config\n FrontXConfig,\n FrontXPlugin,\n FrontXAppBuilder,\n FrontXApp,\n // Endpoint descriptors — L3 components import from @gears-frontx/react\n EndpointOptions,\n EndpointDescriptor,\n ParameterizedEndpointDescriptor,\n MutationDescriptor,\n // Stream descriptors\n StreamDescriptor,\n StreamStatus,\n PluginFactory,\n PluginProvides,\n PluginLifecycle,\n ThemeRegistry,\n ThemeConfig,\n Preset,\n Presets,\n ShowPopupPayload,\n ChangeThemePayload,\n SetLanguagePayload,\n AuthPluginConfig,\n AuthRuntime,\n\n // Auth contract types\n AuthProvider,\n AuthSession,\n AuthContext,\n AuthCheckResult,\n AuthLoginInput,\n AuthCallbackInput,\n AuthTransition,\n AuthPermissions,\n AccessQuery,\n AccessDecision,\n AuthCapabilities,\n AuthState,\n AuthStateEvent,\n AuthStateListener,\n AuthUnsubscribe,\n\n // Flux (Events + Store)\n EventHandler,\n Subscription,\n\n // Store\n RootState,\n AppDispatch,\n SliceObject,\n FrontXStore,\n ReducerPayload,\n\n // Layout\n LayoutDomainState,\n HeaderUser,\n HeaderConfig,\n HeaderState,\n FooterConfig,\n FooterState,\n MenuItem,\n MenuState,\n SidebarPosition,\n SidebarState,\n PopupConfig,\n PopupState,\n PopupSliceState,\n OverlayConfig,\n OverlayState,\n LayoutState,\n RootStateWithLayout,\n LayoutDomainReducers,\n\n // Tenant types\n Tenant,\n TenantState,\n TenantChangedPayload,\n TenantClearedPayload,\n\n // Mock types\n MockState,\n MockTogglePayload,\n\n // API\n MockMap,\n ApiServiceConfig,\n JsonValue,\n JsonObject,\n JsonPrimitive,\n JsonCompatible,\n SseProtocolConfig,\n RestProtocolConfig,\n // Plugin context types (class-based plugin system)\n ApiRequestContext,\n ApiResponseContext,\n ShortCircuitResponse,\n PluginClass,\n ProtocolClass,\n ProtocolPluginType,\n BasePluginHooks,\n // Protocol-specific types\n RestPluginHooks,\n SsePluginHooks,\n RestRequestContext,\n RestResponseContext,\n ApiPluginErrorContext,\n SseConnectContext,\n EventSourceLike,\n RestShortCircuitResponse,\n SseShortCircuitResponse,\n\n // I18n\n I18nConfig,\n TranslationLoader,\n TranslationMap,\n TranslationDictionary,\n LanguageMetadata,\n I18nRegistryType,\n} from '@gears-frontx/framework';\n\n// ============================================================================\n// MFE Re-exports from @gears-frontx/framework (Layering Compliance)\n// ============================================================================\n\n// MFE Plugin factories\nexport {\n microfrontends,\n mock,\n} from '@gears-frontx/framework';\n\n// MFE Action functions\nexport {\n loadExtension,\n mountExtension,\n unmountExtension,\n registerExtension,\n unregisterExtension,\n} from '@gears-frontx/framework';\n\n// MFE Selectors\nexport {\n selectExtensionState,\n selectRegisteredExtensions,\n selectExtensionError,\n selectMountedExtensions,\n} from '@gears-frontx/framework';\n\n// MFE Domain constants\nexport {\n FRONTX_POPUP_DOMAIN,\n FRONTX_SIDEBAR_DOMAIN,\n FRONTX_SCREEN_DOMAIN,\n FRONTX_OVERLAY_DOMAIN,\n // Base ExtensionDomain constants\n screenDomain,\n sidebarDomain,\n popupDomain,\n overlayDomain,\n} from '@gears-frontx/framework';\n\n// MFE Type constants\nexport {\n FRONTX_SCREEN_EXTENSION_TYPE,\n FRONTX_MFE_ENTRY_MF,\n} from '@gears-frontx/framework';\n\n// MFE Action constants\nexport {\n FRONTX_ACTION_LOAD_EXT,\n FRONTX_ACTION_MOUNT_EXT,\n FRONTX_ACTION_UNMOUNT_EXT,\n} from '@gears-frontx/framework';\n\n// MFE Shared Property constants\nexport {\n FRONTX_SHARED_PROPERTY_THEME,\n FRONTX_SHARED_PROPERTY_LANGUAGE,\n} from '@gears-frontx/framework';\n\n// MFE Types\nexport type {\n MfeMountContext,\n Extension,\n ScreenExtension,\n ExtensionPresentation,\n ExtensionDomain,\n ActionsChain,\n Action,\n SharedProperty,\n LifecycleStage,\n LifecycleHook,\n MfeEntryLifecycle,\n MfeEntry,\n MfeEntryMF,\n JSONSchema,\n LoadExtPayload,\n MountExtPayload,\n UnmountExtPayload,\n MfeRegistryConfig,\n TypeSystemPlugin,\n // MF2 manifest types\n MfManifest,\n MfManifestMetaData,\n MfManifestRemoteEntry,\n MfManifestBuildInfo,\n MfManifestShared,\n MfManifestAssets,\n} from '@gears-frontx/framework';\n\n// MFE Abstract classes\nexport {\n ChildMfeBridge,\n ParentMfeBridge,\n MfeHandler,\n MfeBridgeFactory,\n MfeRegistry,\n MfeRegistryFactory,\n mfeRegistryFactory,\n ActionHandler,\n ExtensionDomainImplementation,\n ExtensionDomainImplementationFactory,\n ExtensionMounter,\n MountStrategy,\n ConcurrentMountStrategy,\n OptionalMountStrategy,\n ExclusiveMountStrategy,\n} from '@gears-frontx/framework';\n\nexport type {\n ContainerHooks,\n DomainContext,\n ActionPayload,\n} from '@gears-frontx/framework';\n\n// MFE Concrete implementations\nexport { MfeHandlerMF, gtsPlugin } from '@gears-frontx/framework';\n\n// GTS derived schemas (themeSchema, languageSchema, extensionScreenSchema) and the\n// protocol-specific mock plugins (RestMockPlugin, SseMockPlugin, MockEventSource)\n// are application-layer symbols owned by @gears-frontx/frontx-template-shell and\n// are no longer re-exported here — import them from the template package (#601).\n\n// MFE Utilities\nexport {\n createShadowRoot,\n injectCssVariables,\n extractGtsPackage,\n} from '@gears-frontx/framework';\n\n// MFE Plugin types\nexport type {\n MfeState,\n ExtensionRegistrationState,\n RegisterExtensionPayload,\n UnregisterExtensionPayload,\n} from '@gears-frontx/framework';\n\n// ============================================================================\n// Module Augmentation Support - EventPayloadMap Re-declaration\n// ============================================================================\n\n/**\n * Re-declare EventPayloadMap to enable module augmentation on @gears-frontx/react\n *\n * This creates a new declaration site in @gears-frontx/react that TypeScript can augment.\n * App-layer code can now use `declare module '@gears-frontx/react'` instead of importing\n * from L1 packages directly, maintaining proper layer architecture.\n *\n * ARCHITECTURE: This pattern allows L3+ code to augment event types without\n * violating layer boundaries by importing from L1 (@gears-frontx/state).\n *\n * IMPORTANT: We must also re-export eventBus with the augmented type to ensure\n * type safety. The eventBus instance uses this augmented EventPayloadMap.\n *\n * @example\n * ```typescript\n * // In app-layer code (e.g., src/app/events/bootstrapEvents.ts)\n * import '@gears-frontx/react';\n *\n * declare module '@gears-frontx/react' {\n * interface EventPayloadMap {\n * 'app/user/fetch': void;\n * 'app/user/loaded': { user: ApiUser };\n * }\n * }\n * ```\n */\nimport type { EventPayloadMap as FrameworkEventPayloadMap, EventBus } from '@gears-frontx/framework';\nimport { eventBus as frameworkEventBus } from '@gears-frontx/framework';\n\nexport interface EventPayloadMap extends FrameworkEventPayloadMap { }\n\n/**\n * Re-export eventBus with augmented EventPayloadMap type.\n * This ensures that code importing eventBus from @gears-frontx/react gets\n * type-safe access to both framework events and app-layer augmented events.\n */\nexport const eventBus: EventBus<EventPayloadMap> = frameworkEventBus as EventBus<EventPayloadMap>;\n"],"mappings":"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","names":["useMemo","useEffect","useState","createContext","useContext","createContext","useContext","useEffect","jsx","createContext","useEffect","useContext","controller","jsx","useState","useMemo","useEffect","useEffect","useState","auth","useState","useEffect","useMemo","i18nRegistry","useMemo","useState","useEffect","useMemo","useCallback","useSyncExternalStore","i18nRegistry","useState","useSyncExternalStore","useCallback","useMemo","useEffect","useMemo","useMemo","useCallback","useMemo","useSyncExternalStore","useSyncExternalStore","useCallback","useMemo","themes","useMemo","queryCache","useEffect","useMemo","useRef","useState","useCallback","useState","useRef","useMemo","useCallback","useEffect","useMemo","useMemo","useCallback","useContext","useSyncExternalStore","useContext","useCallback","useSyncExternalStore","useCallback","useCallback","useSyncExternalStore","useCallback","useRef","useCallback","useRef","useSyncExternalStore","useSyncExternalStore","useCallback","useRef","useCallback","useRef","useSyncExternalStore","useSyncExternalStore","useCallback","useRef","useCallback","useRef","useSyncExternalStore","jsx","useEffect","useRef","useState","jsx","createFrontXApp","subscribeQueryCacheRuntimeChanged","microfrontends","eventBus"]}
|