@k4l3b4/query-adapters
Version:
@tanstack/query fetching adapters to make your life a little bit easier.
188 lines (168 loc) • 6.43 kB
JavaScript
;Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }// src/data-fetcher/index.tsx
var _reactquery = require('@tanstack/react-query');
// src/lib/utils.ts
var buildQueryString = (params) => {
const query = Object.entries(params).filter(([_, value]) => value !== void 0 && value !== null).map(
([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`
).join("&");
return query ? `?${query}` : "";
};
// src/lib/fetcher.ts
var fetchWithSettings = async (endpoint, requestOptions = {}, queryParams, baseUrl, globalOptions) => {
const queryString = queryParams ? buildQueryString(queryParams) : "";
const url = `${baseUrl}${endpoint}${queryString}`;
const mergedOptions = {
...globalOptions,
...requestOptions,
headers: {
..._optionalChain([globalOptions, 'optionalAccess', _2 => _2.headers]) || {},
...requestOptions.headers || {}
}
};
const response = await fetch(url, mergedOptions);
if (!response.ok) {
throw new Error(`Error: ${response.status} - ${response.statusText}`);
}
return response.json();
};
// src/provider.tsx
var _react = require('react');
var _jsxruntime = require('react/jsx-runtime');
var defaultSettings = {
baseUrl: "",
headers: { "Content-Type": "application/json" }
};
var FetcherContext = _react.createContext.call(void 0, defaultSettings);
var DataFetcherProvider = ({
settings,
children
}) => {
return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, FetcherContext.Provider, { value: { ...defaultSettings, ...settings }, children });
};
var useFetcherSettings = () => {
return _react.useContext.call(void 0, FetcherContext);
};
// src/data-fetcher/index.tsx
function DataFetcher({
queryKey,
queryFn,
url,
queryParams,
options = {},
children
}) {
const { baseUrl, ...globalOptions } = useFetcherSettings();
const fetcher = queryFn ? queryFn : async () => {
if (!url) {
throw new Error("URL must be provided if no queryFn is specified");
}
return fetchWithSettings(url, void 0, queryParams, baseUrl, globalOptions);
};
const queryResult = _reactquery.useQuery.call(void 0, {
queryKey,
queryFn: fetcher,
...options
});
return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _jsxruntime.Fragment, { children: children({ ...queryResult }) });
}
// src/infinite-data-fetcher/index.tsx
function InfiniteDataFetcher({
queryKey,
queryFn,
url,
queryParams = () => ({}),
options = {
initialPageParam: 1,
getNextPageParam: (lastPage, allPages, lastPageParam, allPageParams) => {
throw new Error("This function is not implemented");
}
},
children,
enableManualFetch = false,
triggerComponent,
loadingComponent,
noMoreDataComponent,
threshold = [0.75],
rootMargin = "0px"
}) {
const { baseUrl, ...globalOptions } = useFetcherSettings();
if (!queryKey) {
throw new Error("queryKey is required.");
}
if (queryFn && url) {
throw new Error("Only one of queryFn or url should be provided.");
}
const fetcher = queryFn ? (context) => queryFn({ ...context, pageParam: _nullishCoalesce(context.pageParam, () => ( 1)) }) : url ? (context) => {
const queryParamsObj = typeof queryParams === "function" ? queryParams(_nullishCoalesce(context.pageParam, () => ( 1))) : queryParams;
return fetchWithSettings(
url,
void 0,
queryParamsObj,
baseUrl,
globalOptions
);
} : void 0;
if (!fetcher) {
throw new Error("Either queryFn or url must be provided.");
}
const {
data,
error,
isLoading,
isFetchingNextPage,
hasNextPage,
fetchNextPage,
refetch
} = _reactquery.useInfiniteQuery.call(void 0, {
queryKey,
queryFn: fetcher,
...options,
getNextPageParam: _optionalChain([options, 'optionalAccess', _3 => _3.getNextPageParam])
});
const observerRef = _react.useRef.call(void 0, null);
_react.useEffect.call(void 0, () => {
if (!observerRef.current || enableManualFetch) return;
const observer = new IntersectionObserver(
([entry]) => {
if (entry.isIntersecting && hasNextPage && !isFetchingNextPage) {
fetchNextPage();
}
},
{ threshold, rootMargin }
);
observer.observe(observerRef.current);
return () => observer.disconnect();
}, [enableManualFetch, fetchNextPage, hasNextPage, isFetchingNextPage]);
const renderFetchTrigger = _react.useMemo.call(void 0, () => {
if (isFetchingNextPage && loadingComponent) {
return loadingComponent;
}
if (!hasNextPage && noMoreDataComponent) {
return noMoreDataComponent;
}
return triggerComponent || /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
"button",
{
type: "button",
onClick: () => fetchNextPage(),
"aria-label": "Load more",
disabled: isFetchingNextPage,
children: isFetchingNextPage ? "Loading..." : "Load More"
}
);
}, [isFetchingNextPage, hasNextPage, loadingComponent, noMoreDataComponent, triggerComponent, fetchNextPage]);
return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
children({
data: _optionalChain([data, 'optionalAccess', _4 => _4.pages]),
error,
isLoading,
isFetchingNextPage,
hasNextPage,
fetchNextPage,
refetch
}),
enableManualFetch ? renderFetchTrigger : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { ref: observerRef })
] });
}
exports.DataFetcher = DataFetcher; exports.DataFetcherProvider = DataFetcherProvider; exports.InfiniteDataFetcher = InfiniteDataFetcher; exports.buildQueryString = buildQueryString; exports.fetchWithSettings = fetchWithSettings; exports.useFetcherSettings = useFetcherSettings;
//# sourceMappingURL=index.js.map