@apollo/client-integration-tanstack-start
Version:
This package provides integrations between Apollo Client and TanStack Start to support modern streaming SSR.
246 lines (238 loc) • 7.74 kB
JavaScript
;
var clientReactStreaming = require('@apollo/client-react-streaming');
var react = require('@apollo/client/react');
var React2 = require('react');
var invariant = require('@apollo/client/utilities/invariant');
var routerCore = require('@tanstack/router-core');
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
var React2__default = /*#__PURE__*/_interopDefault(React2);
// src/routerWithApolloClient.tsx
// src/bundleInfo.ts
var bundle = {
pkg: "@apollo/client-integration-tanstack-start",
client: "ApolloClient",
cache: "InMemoryCache"
};
// src/ApolloProvider.tsx
var ApolloProvider = ({
client,
context,
children
}) => {
return /* @__PURE__ */ React2__default.default.createElement(WrappedApolloProvider, { makeClient: () => client, context }, children);
};
var WrappedApolloProvider = clientReactStreaming.WrapApolloProvider((props) => {
const transport = props.context.transport;
invariant.invariant(transport, "No apolloClientTransport defined");
if ("dispatchRequestStarted" in transport) {
invariant.invariant(
props.registerDispatchRequestStarted,
"Browser bundle loaded in SSR"
);
props.registerDispatchRequestStarted(transport.dispatchRequestStarted);
} else {
invariant.invariant(
props.onQueryEvent && props.rerunSimulatedQueries,
"SSR bundle loaded in Browser"
);
transport.onQueryEvent = props.onQueryEvent;
transport.rerunSimulatedQueries = props.rerunSimulatedQueries;
}
return /* @__PURE__ */ React2__default.default.createElement(clientReactStreaming.DataTransportContext.Provider, { value: transport }, props.children);
});
WrappedApolloProvider.info = bundle;
var getQueryRefSerializationAdapter = (apolloClient) => routerCore.createSerializationAdapter({
key: "apollo-query-ref",
test: clientReactStreaming.isTransportedQueryRef,
fromSerializable(value) {
const queryRef = {
$__apollo_queryRef: value
};
clientReactStreaming.reviveTransportedQueryRef(queryRef, apolloClient);
return queryRef;
},
toSerializable(queryRef) {
return queryRef.$__apollo_queryRef;
}
});
var transportSerializationAdapter = routerCore.createSerializationAdapter({
key: "apollo-transport",
test(value) {
return value instanceof ServerTransport;
},
toSerializable(value) {
return value.stream;
},
fromSerializable(value) {
return new ClientTransport(value);
}
});
var ServerTransport = class {
stream;
controller;
ongoingStreams = /* @__PURE__ */ new Set();
constructor() {
this.stream = new ReadableStream({
start: (controller) => {
this.controller = controller;
}
});
}
shouldClose = false;
closeOnceFinished() {
this.shouldClose = true;
this.closeIfFinished();
}
closed = false;
closeIfFinished() {
if (this.shouldClose && this.ongoingStreams.size === 0 && !this.closed) {
this.controller.close();
this.closed = true;
}
}
dispatchRequestStarted = ({
event,
observable
}) => {
this.controller.enqueue(event);
this.ongoingStreams.add(event);
const finalize = () => {
this.ongoingStreams.delete(event);
this.closeIfFinished();
};
observable.subscribe({
next: (event2) => {
if (!this.closed)
this.controller.enqueue(event2);
},
error: finalize,
complete: finalize
});
};
streamValue(id, value) {
this.controller.enqueue({ type: "value", id, value });
}
useStaticValueRef = (value) => {
const id = React2__default.default.useId();
this.streamValue(id, value);
return React2__default.default.useRef(value);
};
};
var ClientTransport = class {
bufferedEvents = [];
receivedValues = {};
constructor(incomingStream) {
this.consume(incomingStream);
}
async consume(stream) {
for await (const event of stream) {
if (event.type === "value") {
this.receivedValues[event.id] = event.value;
} else {
this.bufferedEvents.push(event);
}
}
this.rerunSimulatedQueries?.();
}
// this will be set from the `WrapApolloProvider` data transport
set onQueryEvent(callback) {
let event;
while (event = this.bufferedEvents.shift()) {
callback(event);
}
this.bufferedEvents.push = (...events) => {
for (const event2 of events) {
callback(event2);
}
return 0;
};
}
// this will be set from the `WrapApolloProvider` data transport
rerunSimulatedQueries;
getStreamedValue(id) {
return this.receivedValues[id];
}
deleteStreamedValue(id) {
delete this.receivedValues[id];
}
useStaticValueRef = (value) => {
const id = React2__default.default.useId();
const streamedValue = this.getStreamedValue(id);
const dataValue = streamedValue !== undefined ? streamedValue : value;
React2__default.default.useEffect(() => {
this.deleteStreamedValue(id);
}, [id]);
return React2__default.default.useRef(dataValue);
};
};
// src/routerWithApolloClient.tsx
function routerWithApolloClient(router, apolloClient) {
router.options.context ??= {};
router.options.context.apolloClient = apolloClient;
router.options.context.preloadQuery = router.isServer ? clientReactStreaming.createTransportedQueryPreloader(apolloClient, { prepareForReuse: true }) : react.createQueryPreloader(
apolloClient
);
const providerContext = {};
const ogHydrate = router.options.hydrate;
const ogDehydrate = router.options.dehydrate;
if (router.isServer) {
const apolloClientTransport = new ServerTransport();
providerContext.transport = apolloClientTransport;
router.options.dehydrate = async () => {
router.serverSsr.onRenderFinished(
() => apolloClientTransport.closeOnceFinished()
);
return {
...await ogDehydrate?.(),
apolloClientTransport
};
};
} else {
router.options.hydrate = (dehydratedState) => {
providerContext.transport = dehydratedState.apolloClientTransport;
return ogHydrate?.(dehydratedState);
};
}
router.options.serializationAdapters = [
...router.options.serializationAdapters ?? [],
getQueryRefSerializationAdapter(apolloClient),
transportSerializationAdapter
];
const PreviousInnerWrap = router.options.InnerWrap || React2__default.default.Fragment;
router.options.InnerWrap = ({ children }) => /* @__PURE__ */ React2__default.default.createElement(ApolloProvider, { client: apolloClient, context: providerContext }, /* @__PURE__ */ React2__default.default.createElement(PreviousInnerWrap, null, children));
return router;
}
routerWithApolloClient.defaultContext = {
apolloClient: new Proxy({}, { get: contextAccess }),
preloadQuery: new Proxy(contextAccess, { get: contextAccess })
};
function contextAccess() {
throw new Error(
`
Could not find Apollo Client in router context.
Did you forget to wrap your router in a \`routerWithApolloClient\` call before returning it from \`getRouter\`?
`.trim()
);
}
var ApolloClient = class extends clientReactStreaming.ApolloClient {
/**
* Information about the current package and it's export names, for use in error messages.
*
* @internal
*/
static info = bundle;
};
var InMemoryCache = class extends clientReactStreaming.InMemoryCache {
/**
* Information about the current package and it's export names, for use in error messages.
*
* @internal
*/
static info = bundle;
};
exports.built_for_browser = true;
exports.ApolloClient = ApolloClient;
exports.InMemoryCache = InMemoryCache;
exports.routerWithApolloClient = routerWithApolloClient;
//# sourceMappingURL=out.js.map
//# sourceMappingURL=index.cjs.map