UNPKG

@devcycle/nextjs-sdk

Version:

The Next.js SDK for DevCycle!

89 lines 4.31 kB
'use client'; import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; import { Suspense, use, useRef } from 'react'; import { initializeDevCycle } from '@devcycle/js-client-sdk'; import { invalidateConfig } from '../../common/invalidateConfig'; import { DevCycleProviderContext } from './context'; import { useRouter } from 'next/navigation'; const isServer = typeof window === 'undefined'; /** * keep the clientside instance of the SDK up-to-date with new data coming from the server during realtime updates * @param serverDataPromise * @param client * @param enableStreaming * @constructor */ const SynchronizeClientData = ({ serverDataPromise, client, enableStreaming, }) => { const serverData = use(serverDataPromise); const dataRef = useRef( // when streaming is disabled, we run synchronization on the initial server data in the // InternalDevCycleClientsideProvider component so we don't need to do it again immediately. // In streaming mode we want to synchronize on that initial server data since we aren't doing it above // Therefore set this ref to the initial server data so the below check won't run when not in streaming mode !enableStreaming ? serverData : null); const clientRef = useRef(client); if (dataRef.current !== serverData || clientRef.current !== client) { dataRef.current = serverData; clientRef.current = client; // do this in a timeout to avoid setting React state in components that are subscribed to variables as a // side effect of the current render, since this causes errors. Instead schedule the update to occur after // render completes setTimeout(() => client.synchronizeBootstrapData(serverData.config, serverData.user)); } return null; }; export const InternalDevCycleClientsideProvider = ({ context, children, }) => { const clientRef = useRef(); const router = useRouter(); const { serverDataPromise, serverData, clientSDKKey, enableStreaming } = context; const revalidateConfig = async (lastModified) => { var _a; if (context.realtimeDelay) { // wait configured delay before checking for new config await new Promise((resolve) => setTimeout(resolve, context.realtimeDelay)); } try { await invalidateConfig(clientSDKKey, (_a = serverData === null || serverData === void 0 ? void 0 : serverData.user.user_id) !== null && _a !== void 0 ? _a : null); } catch { // do nothing on failure, this is best effort } if (context.realtimeDelay) { // if delay is configured, assume that the server action invalidation won't update any content and just // call for a full in-place refresh router.refresh(); } }; if (!clientRef.current) { clientRef.current = initializeDevCycle(clientSDKKey, { ...context.options, sdkPlatform: 'nextjs', deferInitialization: true, disableConfigCache: true, ...(isServer ? { disableAutomaticEventLogging: true, disableCustomEventLogging: true, } : {}), next: { configRefreshHandler: revalidateConfig, }, }); if (!enableStreaming) { // we expect that in non-streaming mode, the serverside portion of this provider should have awaited // the serverDataPromise and passed in the result here if (!serverData) { throw new Error('Server data should be available. Please contact DevCycle support.'); } clientRef.current.synchronizeBootstrapData(serverData.config, serverData.user, serverData.userAgent); } } return (_jsxs(DevCycleProviderContext.Provider, { value: { client: clientRef.current, clientSDKKey, enableStreaming, serverDataPromise, }, children: [_jsx(Suspense, { fallback: null, children: _jsx(SynchronizeClientData, { serverDataPromise: serverDataPromise, client: clientRef.current, enableStreaming: enableStreaming }) }), children] })); }; //# sourceMappingURL=InternalDevCycleClientsideProvider.js.map