UNPKG

convex

Version:

Client for the Convex Cloud

175 lines (174 loc) 5.08 kB
"use strict"; import { InternalConvexClient } from "../browser/index.js"; import React, { useContext, useMemo } from "react"; import { convexToJson } from "@convex-dev/common"; import ReactDOM from "react-dom"; import { useSubscription } from "./use_subscription.js"; if (typeof React === "undefined") { throw new Error("Required dependency 'react' not installed"); } if (typeof ReactDOM === "undefined") { throw new Error("Required dependency 'react-dom' not installed"); } function createMutation(name, sync, update = null) { function mutation(...args) { return sync().mutate(name, args, update); } mutation.withOptimisticUpdate = function withOptimisticUpdate(optimisticUpdate) { if (update !== null) { throw new Error( `Already specified optimistic update for mutation ${name}` ); } return createMutation(name, sync, optimisticUpdate); }; return mutation; } const DEFAULT_OPTIONS = { unsavedChangesWarning: true }; export class ConvexReactClient { constructor(clientConfig, options) { this.closed = false; this.clientConfig = clientConfig; this.listeners = /* @__PURE__ */ new Map(); this.options = { ...DEFAULT_OPTIONS, ...options }; } get sync() { if (this.closed) { throw new Error("ConvexReactClient has already been closed."); } if (this.cachedSync) { return this.cachedSync; } this.cachedSync = new InternalConvexClient( this.clientConfig, (updatedQueries) => this.transition(updatedQueries), this.options ); if (this.adminAuth) { this.cachedSync.setAdminAuth(this.adminAuth); } return this.cachedSync; } setAuth(token) { this.sync.setAuth(token); } clearAuth() { this.sync.clearAuth(); } setAdminAuth(token) { this.adminAuth = token; if (this.closed) { throw new Error("ConvexReactClient has already been closed."); } if (this.cachedSync) { this.sync.setAdminAuth(token); } } watchQuery(name, ...args) { return { onUpdate: (callback) => { const { queryToken, unsubscribe } = this.sync.subscribe( name, args ); const currentListeners = this.listeners.get(queryToken); if (currentListeners !== void 0) { currentListeners.add(callback); } else { this.listeners.set(queryToken, /* @__PURE__ */ new Set([callback])); } return () => { if (this.closed) { return; } const currentListeners2 = this.listeners.get(queryToken); currentListeners2.delete(callback); if (currentListeners2.size == 0) { this.listeners.delete(queryToken); } unsubscribe(); }; }, localQueryResult: () => { if (this.cachedSync) { return this.cachedSync.localQueryResult( name, args ); } return void 0; } }; } mutation(name) { return createMutation(name, () => this.sync); } async close() { this.closed = true; this.listeners = /* @__PURE__ */ new Map(); if (this.cachedSync) { const sync = this.cachedSync; this.cachedSync = void 0; await sync.close(); } } transition(updatedQueries) { ReactDOM.unstable_batchedUpdates(() => { for (const queryToken of updatedQueries) { const callbacks = this.listeners.get(queryToken); if (callbacks) { for (const callback of callbacks) { callback(); } } } }); } } const ConvexContext = React.createContext( void 0 ); export function useConvexGeneric() { return useContext(ConvexContext); } export const ConvexProvider = ({ client, children }) => { return React.createElement( ConvexContext.Provider, { value: client }, children ); }; export function useQueryGeneric(name, ...args) { const convex = useContext(ConvexContext); if (convex === void 0) { throw new Error( "Could not find Convex client! `useQuery` must be used in the React component tree under `ConvexProvider`. Did you forget it? See https://docs.convex.dev/quick-start#set-up-convex-in-your-react-app" ); } const subscription = useMemo( () => { const watch = convex.watchQuery(name, ...args); return { getCurrentValue: () => watch.localQueryResult(), subscribe: (callback) => watch.onUpdate(callback) }; }, [name, convex, JSON.stringify(convexToJson(args))] ); const queryResult = useSubscription(subscription); return queryResult; } export function useMutationGeneric(name) { const convex = useContext(ConvexContext); if (convex === void 0) { throw new Error( "Could not find Convex client! `useMutation` must be used in the React component tree under `ConvexProvider`. Did you forget it? See https://docs.convex.dev/quick-start#set-up-convex-in-your-react-app" ); } return useMemo(() => convex.mutation(name), [convex, name]); } //# sourceMappingURL=index.js.map