UNPKG

@apollo/client-react-streaming

Version:

This package provides building blocks to create framework-level integration of Apollo Client with React's streaming SSR. See the [@apollo/client-integration-nextjs](https://github.com/apollographql/apollo-client-integrations/tree/main/packages/nextjs) pac

194 lines (186 loc) 6.03 kB
import React, { useRef, useMemo, useId } from 'react'; import { resetApolloSingletons, DataTransportContext } from '@apollo/client-react-streaming'; import { invariant } from '@apollo/client/utilities/invariant'; // src/ManualDataTransport/ManualDataTransport.tsx // src/ManualDataTransport/ApolloRehydrateSymbols.tsx var ApolloSSRDataTransport = /* @__PURE__ */ Symbol.for( "ApolloSSRDataTransport" ); var ApolloHookRehydrationCache = /* @__PURE__ */ Symbol.for( "apollo.hookRehydrationCache" ); // src/ManualDataTransport/lateInitializingQueue.ts function registerLateInitializingQueue(key, callback) { const previousData = window[key] || []; if (Array.isArray(previousData)) { window[key] = { push: (...data) => { for (const value of data) { callback(value); } } }; window[key].push(...previousData); } } // src/ManualDataTransport/htmlescape.ts var ESCAPE_LOOKUP = { "&": "\\u0026", ">": "\\u003e", "<": "\\u003c", "\u2028": "\\u2028", "\u2029": "\\u2029" }; var ESCAPE_REGEX = /[&><\u2028\u2029]/g; function htmlEscapeJsonString(str) { return str.replace(ESCAPE_REGEX, (match) => ESCAPE_LOOKUP[match]); } // src/ManualDataTransport/dataTransport.ts function transportDataToJS(data, stringify2) { const key = Symbol.keyFor(ApolloSSRDataTransport); return `(window[Symbol.for("${key}")] ??= []).push(${htmlEscapeJsonString( stringify2(data) )})`; } function buildApolloRehydrationContext({ insertHtml, stringify: stringify2, extraScriptProps }) { function ensureInserted() { if (!rehydrationContext.currentlyInjected) { rehydrationContext.currentlyInjected = true; insertHtml(() => /* @__PURE__ */ React.createElement(rehydrationContext.RehydrateOnClient, null)); } } const rehydrationContext = { currentlyInjected: false, transportValueData: getTransportObject(ensureInserted), transportedValues: {}, incomingEvents: getTransportArray(ensureInserted), RehydrateOnClient() { rehydrationContext.currentlyInjected = false; if (!Object.keys(rehydrationContext.transportValueData).length && !Object.keys(rehydrationContext.incomingEvents).length) return /* @__PURE__ */ React.createElement(React.Fragment, null); invariant.debug( "transporting data", rehydrationContext.transportValueData ); invariant.debug("transporting events", rehydrationContext.incomingEvents); const __html = transportDataToJS( { rehydrate: Object.fromEntries( Object.entries(rehydrationContext.transportValueData).filter( ([key, value]) => rehydrationContext.transportedValues[key] !== value ) ), events: rehydrationContext.incomingEvents }, stringify2 ); Object.assign( rehydrationContext.transportedValues, rehydrationContext.transportValueData ); rehydrationContext.transportValueData = getTransportObject(ensureInserted); rehydrationContext.incomingEvents = getTransportArray(ensureInserted); return /* @__PURE__ */ React.createElement( "script", { ...extraScriptProps, dangerouslySetInnerHTML: { __html } } ); } }; return rehydrationContext; } function getTransportObject(ensureInserted) { return new Proxy( {}, { set(...args) { ensureInserted(); return Reflect.set(...args); } } ); } function getTransportArray(ensureInserted) { return new Proxy([], { get(...args) { if (args[1] === "push") { return (...values) => { ensureInserted(); return args[0].push(...values); }; } return Reflect.get(...args); } }); } // src/ManualDataTransport/serialization.ts function stringify(value) { let undefinedPlaceholder = "$apollo.undefined$"; const stringified = JSON.stringify(value); while (stringified.includes(JSON.stringify(undefinedPlaceholder))) { undefinedPlaceholder = "$" + undefinedPlaceholder; } return JSON.stringify( value, (_, v) => v === undefined ? undefinedPlaceholder : v ).replaceAll(JSON.stringify(undefinedPlaceholder), "undefined"); } // src/ManualDataTransport/ManualDataTransport.tsx var buildManualDataTransportSSRImpl = ({ useInsertHtml, stringifyForStream = stringify, dangerous_disableHookValueTransportation: disableHookValueTransportation }) => function ManualDataTransportSSRImpl({ extraScriptProps, children, registerDispatchRequestStarted }) { const insertHtml = useInsertHtml(); const rehydrationContext = useRef(undefined); if (!rehydrationContext.current) { rehydrationContext.current = buildApolloRehydrationContext({ insertHtml, extraScriptProps, stringify: stringifyForStream }); } registerDispatchRequestStarted(({ event, observable }) => { rehydrationContext.current.incomingEvents.push(event); observable.subscribe({ next(event2) { rehydrationContext.current.incomingEvents.push(event2); } }); }); const contextValue = useMemo( () => ({ useStaticValueRef: function useStaticValueRef(value) { const id = useId(); if (!disableHookValueTransportation) { rehydrationContext.current.transportValueData[id] = value; } return { current: value }; } }), [] ); return /* @__PURE__ */ React.createElement(DataTransportContext.Provider, { value: contextValue }, children); }; var buildManualDataTransport = buildManualDataTransportSSRImpl ; function resetManualSSRApolloSingletons() { resetApolloSingletons(); delete window[ApolloHookRehydrationCache]; delete window[ApolloSSRDataTransport]; } const built_for_ssr = true; export { buildManualDataTransport, built_for_ssr, registerLateInitializingQueue, resetManualSSRApolloSingletons }; //# sourceMappingURL=out.js.map //# sourceMappingURL=manual-transport.ssr.js.map