mirror of
https://github.com/hanzoai/agency.git
synced 2026-11-02 19:13:28 +00:00
459 lines
15 KiB
Plaintext
459 lines
15 KiB
Plaintext
import {
|
|
__privateAdd,
|
|
__privateGet,
|
|
__privateMethod,
|
|
__privateSet
|
|
} from "./chunk-PXG64RU4.js";
|
|
|
|
// src/query.ts
|
|
import {
|
|
ensureQueryFn,
|
|
noop,
|
|
replaceData,
|
|
resolveEnabled,
|
|
resolveStaleTime,
|
|
skipToken,
|
|
timeUntilStale
|
|
} from "./utils.js";
|
|
import { notifyManager } from "./notifyManager.js";
|
|
import { CancelledError, canFetch, createRetryer } from "./retryer.js";
|
|
import { Removable } from "./removable.js";
|
|
var _initialState, _revertState, _cache, _client, _retryer, _defaultOptions, _abortSignalConsumed, _Query_instances, dispatch_fn;
|
|
var Query = class extends Removable {
|
|
constructor(config) {
|
|
super();
|
|
__privateAdd(this, _Query_instances);
|
|
__privateAdd(this, _initialState);
|
|
__privateAdd(this, _revertState);
|
|
__privateAdd(this, _cache);
|
|
__privateAdd(this, _client);
|
|
__privateAdd(this, _retryer);
|
|
__privateAdd(this, _defaultOptions);
|
|
__privateAdd(this, _abortSignalConsumed);
|
|
__privateSet(this, _abortSignalConsumed, false);
|
|
__privateSet(this, _defaultOptions, config.defaultOptions);
|
|
this.setOptions(config.options);
|
|
this.observers = [];
|
|
__privateSet(this, _client, config.client);
|
|
__privateSet(this, _cache, __privateGet(this, _client).getQueryCache());
|
|
this.queryKey = config.queryKey;
|
|
this.queryHash = config.queryHash;
|
|
__privateSet(this, _initialState, getDefaultState(this.options));
|
|
this.state = config.state ?? __privateGet(this, _initialState);
|
|
this.scheduleGc();
|
|
}
|
|
get meta() {
|
|
return this.options.meta;
|
|
}
|
|
get promise() {
|
|
var _a;
|
|
return (_a = __privateGet(this, _retryer)) == null ? void 0 : _a.promise;
|
|
}
|
|
setOptions(options) {
|
|
this.options = { ...__privateGet(this, _defaultOptions), ...options };
|
|
this.updateGcTime(this.options.gcTime);
|
|
if (this.state && this.state.data === void 0) {
|
|
const defaultState = getDefaultState(this.options);
|
|
if (defaultState.data !== void 0) {
|
|
this.setState(
|
|
successState(defaultState.data, defaultState.dataUpdatedAt)
|
|
);
|
|
__privateSet(this, _initialState, defaultState);
|
|
}
|
|
}
|
|
}
|
|
optionalRemove() {
|
|
if (!this.observers.length && this.state.fetchStatus === "idle") {
|
|
__privateGet(this, _cache).remove(this);
|
|
}
|
|
}
|
|
setData(newData, options) {
|
|
const data = replaceData(this.state.data, newData, this.options);
|
|
__privateMethod(this, _Query_instances, dispatch_fn).call(this, {
|
|
data,
|
|
type: "success",
|
|
dataUpdatedAt: options == null ? void 0 : options.updatedAt,
|
|
manual: options == null ? void 0 : options.manual
|
|
});
|
|
return data;
|
|
}
|
|
setState(state, setStateOptions) {
|
|
__privateMethod(this, _Query_instances, dispatch_fn).call(this, { type: "setState", state, setStateOptions });
|
|
}
|
|
cancel(options) {
|
|
var _a, _b;
|
|
const promise = (_a = __privateGet(this, _retryer)) == null ? void 0 : _a.promise;
|
|
(_b = __privateGet(this, _retryer)) == null ? void 0 : _b.cancel(options);
|
|
return promise ? promise.then(noop).catch(noop) : Promise.resolve();
|
|
}
|
|
destroy() {
|
|
super.destroy();
|
|
this.cancel({ silent: true });
|
|
}
|
|
reset() {
|
|
this.destroy();
|
|
this.setState(__privateGet(this, _initialState));
|
|
}
|
|
isActive() {
|
|
return this.observers.some(
|
|
(observer) => resolveEnabled(observer.options.enabled, this) !== false
|
|
);
|
|
}
|
|
isDisabled() {
|
|
if (this.getObserversCount() > 0) {
|
|
return !this.isActive();
|
|
}
|
|
return this.options.queryFn === skipToken || this.state.dataUpdateCount + this.state.errorUpdateCount === 0;
|
|
}
|
|
isStatic() {
|
|
if (this.getObserversCount() > 0) {
|
|
return this.observers.some(
|
|
(observer) => resolveStaleTime(observer.options.staleTime, this) === "static"
|
|
);
|
|
}
|
|
return false;
|
|
}
|
|
isStale() {
|
|
if (this.getObserversCount() > 0) {
|
|
return this.observers.some(
|
|
(observer) => observer.getCurrentResult().isStale
|
|
);
|
|
}
|
|
return this.state.data === void 0 || this.state.isInvalidated;
|
|
}
|
|
isStaleByTime(staleTime = 0) {
|
|
if (this.state.data === void 0) {
|
|
return true;
|
|
}
|
|
if (staleTime === "static") {
|
|
return false;
|
|
}
|
|
if (this.state.isInvalidated) {
|
|
return true;
|
|
}
|
|
return !timeUntilStale(this.state.dataUpdatedAt, staleTime);
|
|
}
|
|
onFocus() {
|
|
var _a;
|
|
const observer = this.observers.find((x) => x.shouldFetchOnWindowFocus());
|
|
observer == null ? void 0 : observer.refetch({ cancelRefetch: false });
|
|
(_a = __privateGet(this, _retryer)) == null ? void 0 : _a.continue();
|
|
}
|
|
onOnline() {
|
|
var _a;
|
|
const observer = this.observers.find((x) => x.shouldFetchOnReconnect());
|
|
observer == null ? void 0 : observer.refetch({ cancelRefetch: false });
|
|
(_a = __privateGet(this, _retryer)) == null ? void 0 : _a.continue();
|
|
}
|
|
addObserver(observer) {
|
|
if (!this.observers.includes(observer)) {
|
|
this.observers.push(observer);
|
|
this.clearGcTimeout();
|
|
__privateGet(this, _cache).notify({ type: "observerAdded", query: this, observer });
|
|
}
|
|
}
|
|
removeObserver(observer) {
|
|
if (this.observers.includes(observer)) {
|
|
this.observers = this.observers.filter((x) => x !== observer);
|
|
if (!this.observers.length) {
|
|
if (__privateGet(this, _retryer)) {
|
|
if (__privateGet(this, _abortSignalConsumed)) {
|
|
__privateGet(this, _retryer).cancel({ revert: true });
|
|
} else {
|
|
__privateGet(this, _retryer).cancelRetry();
|
|
}
|
|
}
|
|
this.scheduleGc();
|
|
}
|
|
__privateGet(this, _cache).notify({ type: "observerRemoved", query: this, observer });
|
|
}
|
|
}
|
|
getObserversCount() {
|
|
return this.observers.length;
|
|
}
|
|
invalidate() {
|
|
if (!this.state.isInvalidated) {
|
|
__privateMethod(this, _Query_instances, dispatch_fn).call(this, { type: "invalidate" });
|
|
}
|
|
}
|
|
async fetch(options, fetchOptions) {
|
|
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l;
|
|
if (this.state.fetchStatus !== "idle" && // If the promise in the retryer is already rejected, we have to definitely
|
|
// re-start the fetch; there is a chance that the query is still in a
|
|
// pending state when that happens
|
|
((_a = __privateGet(this, _retryer)) == null ? void 0 : _a.status()) !== "rejected") {
|
|
if (this.state.data !== void 0 && (fetchOptions == null ? void 0 : fetchOptions.cancelRefetch)) {
|
|
this.cancel({ silent: true });
|
|
} else if (__privateGet(this, _retryer)) {
|
|
__privateGet(this, _retryer).continueRetry();
|
|
return __privateGet(this, _retryer).promise;
|
|
}
|
|
}
|
|
if (options) {
|
|
this.setOptions(options);
|
|
}
|
|
if (!this.options.queryFn) {
|
|
const observer = this.observers.find((x) => x.options.queryFn);
|
|
if (observer) {
|
|
this.setOptions(observer.options);
|
|
}
|
|
}
|
|
if (process.env.NODE_ENV !== "production") {
|
|
if (!Array.isArray(this.options.queryKey)) {
|
|
console.error(
|
|
`As of v4, queryKey needs to be an Array. If you are using a string like 'repoData', please change it to an Array, e.g. ['repoData']`
|
|
);
|
|
}
|
|
}
|
|
const abortController = new AbortController();
|
|
const addSignalProperty = (object) => {
|
|
Object.defineProperty(object, "signal", {
|
|
enumerable: true,
|
|
get: () => {
|
|
__privateSet(this, _abortSignalConsumed, true);
|
|
return abortController.signal;
|
|
}
|
|
});
|
|
};
|
|
const fetchFn = () => {
|
|
const queryFn = ensureQueryFn(this.options, fetchOptions);
|
|
const createQueryFnContext = () => {
|
|
const queryFnContext2 = {
|
|
client: __privateGet(this, _client),
|
|
queryKey: this.queryKey,
|
|
meta: this.meta
|
|
};
|
|
addSignalProperty(queryFnContext2);
|
|
return queryFnContext2;
|
|
};
|
|
const queryFnContext = createQueryFnContext();
|
|
__privateSet(this, _abortSignalConsumed, false);
|
|
if (this.options.persister) {
|
|
return this.options.persister(
|
|
queryFn,
|
|
queryFnContext,
|
|
this
|
|
);
|
|
}
|
|
return queryFn(queryFnContext);
|
|
};
|
|
const createFetchContext = () => {
|
|
const context2 = {
|
|
fetchOptions,
|
|
options: this.options,
|
|
queryKey: this.queryKey,
|
|
client: __privateGet(this, _client),
|
|
state: this.state,
|
|
fetchFn
|
|
};
|
|
addSignalProperty(context2);
|
|
return context2;
|
|
};
|
|
const context = createFetchContext();
|
|
(_b = this.options.behavior) == null ? void 0 : _b.onFetch(context, this);
|
|
__privateSet(this, _revertState, this.state);
|
|
if (this.state.fetchStatus === "idle" || this.state.fetchMeta !== ((_c = context.fetchOptions) == null ? void 0 : _c.meta)) {
|
|
__privateMethod(this, _Query_instances, dispatch_fn).call(this, { type: "fetch", meta: (_d = context.fetchOptions) == null ? void 0 : _d.meta });
|
|
}
|
|
__privateSet(this, _retryer, createRetryer({
|
|
initialPromise: fetchOptions == null ? void 0 : fetchOptions.initialPromise,
|
|
fn: context.fetchFn,
|
|
onCancel: (error) => {
|
|
if (error instanceof CancelledError && error.revert) {
|
|
this.setState({
|
|
...__privateGet(this, _revertState),
|
|
fetchStatus: "idle"
|
|
});
|
|
}
|
|
abortController.abort();
|
|
},
|
|
onFail: (failureCount, error) => {
|
|
__privateMethod(this, _Query_instances, dispatch_fn).call(this, { type: "failed", failureCount, error });
|
|
},
|
|
onPause: () => {
|
|
__privateMethod(this, _Query_instances, dispatch_fn).call(this, { type: "pause" });
|
|
},
|
|
onContinue: () => {
|
|
__privateMethod(this, _Query_instances, dispatch_fn).call(this, { type: "continue" });
|
|
},
|
|
retry: context.options.retry,
|
|
retryDelay: context.options.retryDelay,
|
|
networkMode: context.options.networkMode,
|
|
canRun: () => true
|
|
}));
|
|
try {
|
|
const data = await __privateGet(this, _retryer).start();
|
|
if (data === void 0) {
|
|
if (process.env.NODE_ENV !== "production") {
|
|
console.error(
|
|
`Query data cannot be undefined. Please make sure to return a value other than undefined from your query function. Affected query key: ${this.queryHash}`
|
|
);
|
|
}
|
|
throw new Error(`${this.queryHash} data is undefined`);
|
|
}
|
|
this.setData(data);
|
|
(_f = (_e = __privateGet(this, _cache).config).onSuccess) == null ? void 0 : _f.call(_e, data, this);
|
|
(_h = (_g = __privateGet(this, _cache).config).onSettled) == null ? void 0 : _h.call(
|
|
_g,
|
|
data,
|
|
this.state.error,
|
|
this
|
|
);
|
|
return data;
|
|
} catch (error) {
|
|
if (error instanceof CancelledError) {
|
|
if (error.silent) {
|
|
return __privateGet(this, _retryer).promise;
|
|
} else if (error.revert) {
|
|
if (this.state.data === void 0) {
|
|
throw error;
|
|
}
|
|
return this.state.data;
|
|
}
|
|
}
|
|
__privateMethod(this, _Query_instances, dispatch_fn).call(this, {
|
|
type: "error",
|
|
error
|
|
});
|
|
(_j = (_i = __privateGet(this, _cache).config).onError) == null ? void 0 : _j.call(
|
|
_i,
|
|
error,
|
|
this
|
|
);
|
|
(_l = (_k = __privateGet(this, _cache).config).onSettled) == null ? void 0 : _l.call(
|
|
_k,
|
|
this.state.data,
|
|
error,
|
|
this
|
|
);
|
|
throw error;
|
|
} finally {
|
|
this.scheduleGc();
|
|
}
|
|
}
|
|
};
|
|
_initialState = new WeakMap();
|
|
_revertState = new WeakMap();
|
|
_cache = new WeakMap();
|
|
_client = new WeakMap();
|
|
_retryer = new WeakMap();
|
|
_defaultOptions = new WeakMap();
|
|
_abortSignalConsumed = new WeakMap();
|
|
_Query_instances = new WeakSet();
|
|
dispatch_fn = function(action) {
|
|
const reducer = (state) => {
|
|
switch (action.type) {
|
|
case "failed":
|
|
return {
|
|
...state,
|
|
fetchFailureCount: action.failureCount,
|
|
fetchFailureReason: action.error
|
|
};
|
|
case "pause":
|
|
return {
|
|
...state,
|
|
fetchStatus: "paused"
|
|
};
|
|
case "continue":
|
|
return {
|
|
...state,
|
|
fetchStatus: "fetching"
|
|
};
|
|
case "fetch":
|
|
return {
|
|
...state,
|
|
...fetchState(state.data, this.options),
|
|
fetchMeta: action.meta ?? null
|
|
};
|
|
case "success":
|
|
const newState = {
|
|
...state,
|
|
...successState(action.data, action.dataUpdatedAt),
|
|
dataUpdateCount: state.dataUpdateCount + 1,
|
|
...!action.manual && {
|
|
fetchStatus: "idle",
|
|
fetchFailureCount: 0,
|
|
fetchFailureReason: null
|
|
}
|
|
};
|
|
__privateSet(this, _revertState, action.manual ? newState : void 0);
|
|
return newState;
|
|
case "error":
|
|
const error = action.error;
|
|
return {
|
|
...state,
|
|
error,
|
|
errorUpdateCount: state.errorUpdateCount + 1,
|
|
errorUpdatedAt: Date.now(),
|
|
fetchFailureCount: state.fetchFailureCount + 1,
|
|
fetchFailureReason: error,
|
|
fetchStatus: "idle",
|
|
status: "error",
|
|
// flag existing data as invalidated if we get a background error
|
|
// note that "no data" always means stale so we can set unconditionally here
|
|
isInvalidated: true
|
|
};
|
|
case "invalidate":
|
|
return {
|
|
...state,
|
|
isInvalidated: true
|
|
};
|
|
case "setState":
|
|
return {
|
|
...state,
|
|
...action.state
|
|
};
|
|
}
|
|
};
|
|
this.state = reducer(this.state);
|
|
notifyManager.batch(() => {
|
|
this.observers.forEach((observer) => {
|
|
observer.onQueryUpdate();
|
|
});
|
|
__privateGet(this, _cache).notify({ query: this, type: "updated", action });
|
|
});
|
|
};
|
|
function fetchState(data, options) {
|
|
return {
|
|
fetchFailureCount: 0,
|
|
fetchFailureReason: null,
|
|
fetchStatus: canFetch(options.networkMode) ? "fetching" : "paused",
|
|
...data === void 0 && {
|
|
error: null,
|
|
status: "pending"
|
|
}
|
|
};
|
|
}
|
|
function successState(data, dataUpdatedAt) {
|
|
return {
|
|
data,
|
|
dataUpdatedAt: dataUpdatedAt ?? Date.now(),
|
|
error: null,
|
|
isInvalidated: false,
|
|
status: "success"
|
|
};
|
|
}
|
|
function getDefaultState(options) {
|
|
const data = typeof options.initialData === "function" ? options.initialData() : options.initialData;
|
|
const hasData = data !== void 0;
|
|
const initialDataUpdatedAt = hasData ? typeof options.initialDataUpdatedAt === "function" ? options.initialDataUpdatedAt() : options.initialDataUpdatedAt : 0;
|
|
return {
|
|
data,
|
|
dataUpdateCount: 0,
|
|
dataUpdatedAt: hasData ? initialDataUpdatedAt ?? Date.now() : 0,
|
|
error: null,
|
|
errorUpdateCount: 0,
|
|
errorUpdatedAt: 0,
|
|
fetchFailureCount: 0,
|
|
fetchFailureReason: null,
|
|
fetchMeta: null,
|
|
isInvalidated: false,
|
|
status: hasData ? "success" : "pending",
|
|
fetchStatus: "idle"
|
|
};
|
|
}
|
|
export {
|
|
Query,
|
|
fetchState
|
|
};
|
|
//# sourceMappingURL=query.js.map |