diff --git a/ui/src/applet-core/hooks/useAppletExtensions.ts b/ui/src/applet-core/hooks/useAppletExtensions.ts new file mode 100644 index 0000000..b24ad52 --- /dev/null +++ b/ui/src/applet-core/hooks/useAppletExtensions.ts @@ -0,0 +1,13 @@ +import { useMemo } from 'react'; +import { useAppletContext } from '../context/AppletContext'; + +export function useAppletExtensions< + TExtensions extends Record = Record, +>(): TExtensions { + const { extensions } = useAppletContext(); + + return useMemo( + () => ((extensions ?? {}) as TExtensions), + [extensions], + ); +} diff --git a/ui/src/applet-core/hooks/useAppletRPCClient.ts b/ui/src/applet-core/hooks/useAppletRPCClient.ts new file mode 100644 index 0000000..0718268 --- /dev/null +++ b/ui/src/applet-core/hooks/useAppletRPCClient.ts @@ -0,0 +1,43 @@ +import { useMemo } from 'react'; +import { createAppletRPCClient, type AppletRPCSchema } from '../../applet-host/rpc'; +import { useAppletContext } from '../context/AppletContext'; + +export interface UseAppletRPCClientOptions { + endpoint?: string + timeoutMs?: number + fetcher?: typeof fetch +} + +export function useAppletRPCClient< + TRouter extends AppletRPCSchema = AppletRPCSchema, +>(options: UseAppletRPCClientOptions = {}) { + const { config, session } = useAppletContext(); + const endpoint = options.endpoint ?? config.rpcUIEndpoint ?? '/rpc'; + const baseFetcher = options.fetcher ?? fetch; + const csrfToken = session.csrfToken; + + return useMemo(() => { + const fetcher: typeof fetch = async (input, init) => { + const headers = new Headers(init?.headers ?? undefined); + if (csrfToken !== '' && !headers.has('X-CSRF-Token')) { + headers.set('X-CSRF-Token', csrfToken); + } + + return baseFetcher(input, { + ...init, + headers, + }); + }; + + return createAppletRPCClient({ + endpoint, + timeoutMs: options.timeoutMs, + fetcher, + }) as ReturnType & { + callTyped( + method: TMethod, + params: TRouter[TMethod]['params'] + ): Promise + }; + }, [baseFetcher, csrfToken, endpoint, options.timeoutMs]); +} diff --git a/ui/src/applet-core/index.ts b/ui/src/applet-core/index.ts index a23497c..1405132 100644 --- a/ui/src/applet-core/index.ts +++ b/ui/src/applet-core/index.ts @@ -11,6 +11,8 @@ export { ConfigProvider, useConfigContext } from './context/ConfigProvider'; // Hooks export { useAppletContext as useAppletContextDirect } from './hooks/useAppletContext'; +export { useAppletExtensions } from './hooks/useAppletExtensions'; +export { useAppletRPCClient, type UseAppletRPCClientOptions } from './hooks/useAppletRPCClient'; export { useConfig } from './hooks/useConfig'; export { useUser } from './hooks/useUser'; export { usePermissions } from './hooks/usePermissions';