UNPKG

@ldhop/react

Version:

Follow your nose through linked data resources - for React

124 lines 6.02 kB
import { fetchRdfDocument, getVariableNames, LdhopEngine, } from '@ldhop/core'; import { useQueries } from '@tanstack/react-query'; import { Quad, Store } from 'n3'; import { useEffect, useMemo, useRef, useState } from 'react'; export const DEFAULT_QUERY_KEY = 'rdfDocument'; const defaultQueryKeyFn = (resource) => [ DEFAULT_QUERY_KEY, resource, ]; let globalQueryKeyFn = defaultQueryKeyFn; export const configureQueryKey = (fn) => { globalQueryKeyFn = fn; }; const getEmptyVariables = (query) => { return Object.fromEntries(Array.from(getVariableNames(query)).map(v => [v.substring(1), new Set()])); }; export const useLdhopQuery = ({ query: queryInput, variables, fetch, getQueryKey = globalQueryKeyFn, staleTime = Infinity, }) => { const [resources, setResources] = useState([]); // convert query to array format const query = useMemo(() => [...queryInput], [queryInput]); const [outputVariables, setOutputVariables] = useState(getEmptyVariables(query)); const [outputStore, setOutputStore] = useState(new Store()); const [outputQuads, setOutputQuads] = useState([]); const [isLoading, setIsLoading] = useState(true); const [isFetching, setIsFetching] = useState(true); // added resources with their hashed values const resourceRef = useRef(new Map()); const engineRef = useRef(null); useEffect(() => { setIsLoading(true); const store = new Store(); setResources([]); setOutputStore(store); setOutputQuads([]); setOutputVariables(getEmptyVariables(query)); resourceRef.current = new Map(); engineRef.current = new LdhopEngine(query, variables, store, { onNeedResource: uri => { setIsLoading(true); setResources(resources => resources.includes(uri) ? resources : [...resources, uri]); }, onDropResource: uri => { var _a; setResources(resources => resources.includes(uri) ? resources.filter(resource => resource !== uri) : resources); (_a = resourceRef.current) === null || _a === void 0 ? void 0 : _a.delete(uri); }, onVariableAdded() { const ov = this.getAllPlainVariables(); if (ov) setOutputVariables(ov); }, onVariableRemoved() { const ov = this.getAllPlainVariables(); if (ov) setOutputVariables(ov); }, onQueryComplete() { setIsLoading(false); }, onQuadsChanged() { var _a; const quads = (_a = this.store.getQuads(null, null, null, null)) !== null && _a !== void 0 ? _a : []; setOutputQuads(quads); }, }); setOutputStore(engineRef.current.store); return () => { var _a, _b, _c, _d, _e, _f; (_a = engineRef.current) === null || _a === void 0 ? true : delete _a.onDropResource; (_b = engineRef.current) === null || _b === void 0 ? true : delete _b.onNeedResource; (_c = engineRef.current) === null || _c === void 0 ? true : delete _c.onQuadsChanged; (_d = engineRef.current) === null || _d === void 0 ? true : delete _d.onQueryComplete; (_e = engineRef.current) === null || _e === void 0 ? true : delete _e.onVariableAdded; (_f = engineRef.current) === null || _f === void 0 ? true : delete _f.onVariableRemoved; engineRef.current = null; }; }, [query, variables]); const results = useQueries(useMemo(() => ({ queries: resources.map(resource => ({ queryKey: getQueryKey(resource), queryFn: () => fetchRdfDocument(resource, fetch), staleTime, })), }), [fetch, getQueryKey, resources, staleTime])); useEffect(() => { var _a, _b; const graphs = (_b = (_a = engineRef.current) === null || _a === void 0 ? void 0 : _a.getGraphs()) !== null && _b !== void 0 ? _b : new Set(); results.forEach((result, i) => { var _a, _b, _c, _d, _e, _f, _g, _h, _j; const resource = resources[i]; // if the resource is not needed, don't add it if (!graphs.has(resource)) return; if (result.isSuccess) { // if the exact same graph is already added, ignore if (((_a = resourceRef.current) === null || _a === void 0 ? void 0 : _a.get(resource)) === ((_b = result.data) === null || _b === void 0 ? void 0 : _b.hash)) return; (_c = engineRef.current) === null || _c === void 0 ? void 0 : _c.addGraph((_e = (_d = result.data.response) === null || _d === void 0 ? void 0 : _d.url) !== null && _e !== void 0 ? _e : resources[i], result.data.data, resources[i]); // remember the graph (_f = resourceRef.current) === null || _f === void 0 ? void 0 : _f.set(resource, result.data.hash); } else if (result.isError) { if (((_g = resourceRef.current) === null || _g === void 0 ? void 0 : _g.get(resource)) === 'error') return; (_h = engineRef.current) === null || _h === void 0 ? void 0 : _h.addGraph(resources[i], []); (_j = resourceRef.current) === null || _j === void 0 ? void 0 : _j.set(resource, 'error'); } }); const isFetching = results.some(r => r.isFetching); setIsFetching(isFetching); }, [resources, results]); return useMemo(() => ({ store: outputStore, quads: outputQuads, variables: outputVariables, engine: engineRef.current, isLoading, isMissing: false, isFetching, }), [isFetching, isLoading, outputQuads, outputStore, outputVariables]); }; //# sourceMappingURL=useLdhopQuery.js.map