@apollo/client-integration-tanstack-start
Version:
This package provides integrations between Apollo Client and TanStack Start to support modern streaming SSR.
238 lines (233 loc) • 7.36 kB
JavaScript
import { WrapApolloProvider, DataTransportContext, createTransportedQueryPreloader, ApolloClient as ApolloClient$1, InMemoryCache as InMemoryCache$1, isTransportedQueryRef, reviveTransportedQueryRef } from '@apollo/client-react-streaming';
import { createQueryPreloader } from '@apollo/client/react';
import React2 from 'react';
import { invariant } from '@apollo/client/utilities/invariant';
import { createSerializationAdapter } from '@tanstack/router-core';
// 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.createElement(WrappedApolloProvider, { makeClient: () => client, context }, children);
};
var WrappedApolloProvider = WrapApolloProvider((props) => {
const transport = props.context.transport;
invariant(transport, "No apolloClientTransport defined");
if ("dispatchRequestStarted" in transport) {
invariant(
props.registerDispatchRequestStarted,
"Browser bundle loaded in SSR"
);
props.registerDispatchRequestStarted(transport.dispatchRequestStarted);
} else {
invariant(
props.onQueryEvent && props.rerunSimulatedQueries,
"SSR bundle loaded in Browser"
);
transport.onQueryEvent = props.onQueryEvent;
transport.rerunSimulatedQueries = props.rerunSimulatedQueries;
}
return /* @__PURE__ */ React2.createElement(DataTransportContext.Provider, { value: transport }, props.children);
});
WrappedApolloProvider.info = bundle;
var getQueryRefSerializationAdapter = (apolloClient) => createSerializationAdapter({
key: "apollo-query-ref",
test: isTransportedQueryRef,
fromSerializable(value) {
const queryRef = {
$__apollo_queryRef: value
};
reviveTransportedQueryRef(queryRef, apolloClient);
return queryRef;
},
toSerializable(queryRef) {
return queryRef.$__apollo_queryRef;
}
});
var transportSerializationAdapter = 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.useId();
this.streamValue(id, value);
return React2.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.useId();
const streamedValue = this.getStreamedValue(id);
const dataValue = streamedValue !== undefined ? streamedValue : value;
React2.useEffect(() => {
this.deleteStreamedValue(id);
}, [id]);
return React2.useRef(dataValue);
};
};
// src/routerWithApolloClient.tsx
function routerWithApolloClient(router, apolloClient) {
router.options.context ??= {};
router.options.context.apolloClient = apolloClient;
router.options.context.preloadQuery = router.isServer ? createTransportedQueryPreloader(apolloClient, { prepareForReuse: true }) : 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.Fragment;
router.options.InnerWrap = ({ children }) => /* @__PURE__ */ React2.createElement(ApolloProvider, { client: apolloClient, context: providerContext }, /* @__PURE__ */ React2.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 ApolloClient$1 {
/**
* Information about the current package and it's export names, for use in error messages.
*
* @internal
*/
static info = bundle;
};
var InMemoryCache = class extends InMemoryCache$1 {
/**
* Information about the current package and it's export names, for use in error messages.
*
* @internal
*/
static info = bundle;
};
const built_for_browser = true;
export { ApolloClient, InMemoryCache, built_for_browser, routerWithApolloClient };
//# sourceMappingURL=out.js.map
//# sourceMappingURL=index.js.map