@tanstack/query-core
Version:
The framework agnostic core that powers TanStack Query
191 lines (190 loc) • 7.3 kB
JavaScript
import { timeoutManager } from "./timeoutManager.js";
//#region src/utils.ts
/** @deprecated
* use `environmentManager.isServer()` instead.
*/
const isServer = typeof window === "undefined" || "Deno" in globalThis;
function noop() {}
function functionalUpdate(updater, input) {
return typeof updater === "function" ? updater(input) : updater;
}
function isValidTimeout(value) {
return typeof value === "number" && value >= 0 && value !== Infinity;
}
function timeUntilStale(updatedAt, staleTime) {
return Math.max(updatedAt + (staleTime || 0) - Date.now(), 0);
}
function resolveQueryValue(value, query) {
return typeof value === "function" ? value(query) : value;
}
function matchQuery(filters, query) {
const { type = "all", exact, fetchStatus, predicate, queryKey, stale } = filters;
if (queryKey) {
if (exact) {
if (query.queryHash !== hashQueryKeyByOptions(queryKey, query.options)) return false;
} else if (!partialMatchKey(query.queryKey, queryKey)) return false;
}
if (type !== "all") {
const isActive = query.isActive();
if (type === "active" && !isActive) return false;
if (type === "inactive" && isActive) return false;
}
if (typeof stale === "boolean" && query.isStale() !== stale) return false;
if (fetchStatus && fetchStatus !== query.state.fetchStatus) return false;
if (predicate && !predicate(query)) return false;
return true;
}
function matchMutation(filters, mutation) {
const { exact, status, predicate, mutationKey } = filters;
if (mutationKey) {
if (!mutation.options.mutationKey) return false;
if (exact) {
if (hashKey(mutation.options.mutationKey) !== hashKey(mutationKey)) return false;
} else if (!partialMatchKey(mutation.options.mutationKey, mutationKey)) return false;
}
if (status && mutation.state.status !== status) return false;
if (predicate && !predicate(mutation)) return false;
return true;
}
function hashQueryKeyByOptions(queryKey, options) {
return ((options === null || options === void 0 ? void 0 : options.queryKeyHashFn) || hashKey)(queryKey);
}
/**
* Default query & mutation keys hash function.
* Hashes the value into a stable hash.
*/
function hashKey(queryKey) {
return JSON.stringify(queryKey, (_, val) => isPlainObject(val) ? Object.keys(val).sort().reduce((result, key) => {
result[key] = val[key];
return result;
}, {}) : val);
}
function partialMatchKey(a, b) {
if (a === b) return true;
if (typeof a !== typeof b) return false;
if (a && b && typeof a === "object" && typeof b === "object") {
if (Array.isArray(a) && Array.isArray(b)) {
for (let i = 0; i < b.length; i++) if (!partialMatchKey(a[i], b[i])) return false;
return true;
}
const bKeys = Object.keys(b);
for (const key of bKeys) if (!partialMatchKey(a[key], b[key])) return false;
return true;
}
return false;
}
const hasOwn = Object.prototype.hasOwnProperty;
function replaceEqualDeep(a, b, depth = 0) {
if (a === b) return a;
if (depth > 500) return b;
const array = isPlainArray(a) && isPlainArray(b);
if (!array && !(isPlainObject(a) && isPlainObject(b))) return b;
const aSize = (array ? a : Object.keys(a)).length;
const bItems = array ? b : Object.keys(b);
const bSize = bItems.length;
const copy = array ? new Array(bSize) : {};
let equalItems = 0;
for (let i = 0; i < bSize; i++) {
const key = array ? i : bItems[i];
const aItem = a[key];
const bItem = b[key];
if (aItem === bItem) {
copy[key] = aItem;
if (array ? i < aSize : hasOwn.call(a, key)) equalItems++;
continue;
}
if (aItem === null || bItem === null || typeof aItem !== "object" || typeof bItem !== "object") {
copy[key] = bItem;
continue;
}
const v = replaceEqualDeep(aItem, bItem, depth + 1);
copy[key] = v;
if (v === aItem) equalItems++;
}
return aSize === bSize && equalItems === aSize ? a : copy;
}
/**
* Shallow compare objects.
*/
function shallowEqualObjects(a, b) {
if (!b || Object.keys(a).length !== Object.keys(b).length) return false;
for (const key in a) if (a[key] !== b[key]) return false;
return true;
}
function isPlainArray(value) {
return Array.isArray(value) && value.length === Object.keys(value).length;
}
function isPlainObject(o) {
if (!hasObjectPrototype(o)) return false;
const ctor = o.constructor;
if (ctor === void 0) return true;
const prot = ctor.prototype;
if (!hasObjectPrototype(prot)) return false;
if (!prot.hasOwnProperty("isPrototypeOf")) return false;
if (Object.getPrototypeOf(o) !== Object.prototype) return false;
return true;
}
function hasObjectPrototype(o) {
return Object.prototype.toString.call(o) === "[object Object]";
}
function sleep(timeout) {
return new Promise((resolve) => {
timeoutManager.setTimeout(resolve, timeout);
});
}
function replaceData(prevData, data, options) {
if (typeof options.structuralSharing === "function") return options.structuralSharing(prevData, data);
else if (options.structuralSharing !== false) {
if (process.env.NODE_ENV !== "production") try {
return replaceEqualDeep(prevData, data);
} catch (error) {
console.error(`Structural sharing requires data to be JSON serializable. To fix this, turn off structuralSharing or return JSON-serializable data from your queryFn. [${options.queryHash}]: ${error}`);
throw error;
}
return replaceEqualDeep(prevData, data);
}
return data;
}
function keepPreviousData(previousData) {
return previousData;
}
function addToEnd(items, item, max = 0) {
const newItems = [...items, item];
return max && newItems.length > max ? newItems.slice(1) : newItems;
}
function addToStart(items, item, max = 0) {
const newItems = [item, ...items];
return max && newItems.length > max ? newItems.slice(0, -1) : newItems;
}
const skipToken = Symbol();
function ensureQueryFn(options, fetchOptions) {
if (process.env.NODE_ENV !== "production") {
if (options.queryFn === skipToken) console.error(`Attempted to invoke queryFn when set to skipToken. This is likely a configuration error. Query hash: '${options.queryHash}'`);
}
if (!options.queryFn && (fetchOptions === null || fetchOptions === void 0 ? void 0 : fetchOptions.initialPromise)) return () => fetchOptions.initialPromise;
if (!options.queryFn || options.queryFn === skipToken) return () => Promise.reject(/* @__PURE__ */ new Error(`Missing queryFn: '${options.queryHash}'`));
return options.queryFn;
}
function shouldThrowError(throwOnError, params) {
if (typeof throwOnError === "function") return throwOnError(...params);
return !!throwOnError;
}
function addConsumeAwareSignal(object, getSignal, onCancelled) {
let consumed = false;
let signal;
Object.defineProperty(object, "signal", {
enumerable: true,
get: () => {
signal ?? (signal = getSignal());
if (consumed) return signal;
consumed = true;
if (signal.aborted) onCancelled();
else signal.addEventListener("abort", onCancelled, { once: true });
return signal;
}
});
return object;
}
//#endregion
export { addConsumeAwareSignal, addToEnd, addToStart, ensureQueryFn, functionalUpdate, hashKey, hashQueryKeyByOptions, isPlainArray, isPlainObject, isServer, isValidTimeout, keepPreviousData, matchMutation, matchQuery, noop, partialMatchKey, replaceData, replaceEqualDeep, resolveQueryValue, shallowEqualObjects, shouldThrowError, skipToken, sleep, timeUntilStale };
//# sourceMappingURL=utils.js.map