@apollo/client
Version:
A fully-featured caching GraphQL client.
135 lines (134 loc) • 4.36 kB
JavaScript
import { __DEV__ } from "@apollo/client/utilities/environment";
import { invariant } from "@apollo/client/utilities/invariant";
const defaultHandler = ({ client, matchesRefetchOn, }) => {
return client.refetchQueries({
include: "active",
onQueryUpdated: matchesRefetchOn,
});
};
export class RefetchEventManager {
sources;
handlers;
subscriptions = new Map();
client;
defaultHandler;
constructor(options = {}) {
this.sources = options.sources ?? {};
this.handlers = options.handlers ?? {};
this.defaultHandler = options.defaultHandler ?? defaultHandler;
}
/**
* Connects the client to this refetch event manager. Connecting a client
* calls each configured source function so they can begin listening for events.
*/
connect(client) {
if (this.client === client) {
return;
}
if (this.client) {
if (__DEV__) {
__DEV__ && invariant.warn(101);
}
this.disconnect();
}
this.client = client;
Object.entries(this.sources).forEach(([event, source]) => {
if (typeof source === "function") {
this.subscribeToSource(event, source);
}
});
}
/**
* Disconnects the client from this refetch event manager and calls the cleanup
* function for each event source.
*/
disconnect(client) {
if (client && this.client !== client) {
return;
}
this.client = undefined;
this.subscriptions.forEach((subscription) => subscription.unsubscribe());
this.subscriptions.clear();
}
/**
* Returns whether a source is configured.
*/
hasSource(source) {
return Object.hasOwn(this.sources, source);
}
/**
* Replaces the source for an event. If a source was previously configured
* for the event, its cleanup function is called before the new source is
* registered.
*/
setEventSource(name, source) {
this.sources[name] = source;
this.subscribeToSource(name, source);
}
/**
* Removes the configured source for an event and runs its cleanup function.
*/
removeEventSource(event) {
this.subscriptions.get(event)?.unsubscribe();
this.subscriptions.delete(event);
delete this.sources[event];
}
/**
* Replaces the handler for an event.
*/
setEventHandler(source, handler) {
this.handlers[source] = handler;
}
/**
* Replaces the default event handler with the provided handler.
*/
setDefaultEventHandler(handler) {
this.defaultHandler = handler;
}
/**
* Manually triggers a refetch for the provided event.
*
* @remarks
* This method warns and does not refetch if the refetch event manager is not
* connected to a client or a source is not configured for the event.
*/
emit(source, ...args) {
const [payload] = args;
if (!this.client) {
if (__DEV__) {
__DEV__ && invariant.warn(102, source);
}
return;
}
if (!this.hasSource(source)) {
if (__DEV__) {
__DEV__ && invariant.warn(103, source);
}
return;
}
const handler = this.handlers[source] ?? this.defaultHandler;
function matchesRefetchOn(oq) {
const ctx = { source, payload };
const refetchOn = oq.options.refetchOn;
if (typeof refetchOn === "boolean") {
return refetchOn;
}
if (typeof refetchOn === "function") {
return refetchOn(ctx);
}
if (typeof refetchOn?.[source] === "function") {
return refetchOn[source](ctx);
}
return refetchOn?.[source] !== false;
}
handler({ client: this.client, source, payload, matchesRefetchOn });
}
subscribeToSource(name, source) {
this.subscriptions.get(name)?.unsubscribe();
this.subscriptions.delete(name);
if (this.client) {
this.subscriptions.set(name, source().subscribe((value) => this.emit(name, value)));
}
}
}
//# sourceMappingURL=RefetchEventManager.js.map