mirror of
https://github.com/NoFxAiOS/nofx.git
synced 2026-07-09 22:10:57 +08:00
Initial commit: NOFX AI Trading System
- Multi-AI competition mode (Qwen vs DeepSeek) - Binance Futures integration - AI self-learning mechanism - Professional web dashboard - Complete risk management system
This commit is contained in:
6
web/node_modules/swr/dist/index/config-client-Bi4rgVRk.mjs
generated
vendored
Normal file
6
web/node_modules/swr/dist/index/config-client-Bi4rgVRk.mjs
generated
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
'use client';
|
||||
import { SWRConfig as SWRConfig$1 } from '../_internal/index.mjs';
|
||||
|
||||
const SWRConfig = SWRConfig$1;
|
||||
|
||||
export { SWRConfig as S };
|
||||
33
web/node_modules/swr/dist/index/index.d.mts
generated
vendored
Normal file
33
web/node_modules/swr/dist/index/index.d.mts
generated
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
import { Key, SWRHook, SWRConfiguration, FullConfiguration } from '../_internal/index.mjs';
|
||||
export { Arguments, BareFetcher, Cache, Fetcher, Key, KeyLoader, KeyedMutator, Middleware, MutatorCallback, MutatorOptions, Revalidator, RevalidatorOptions, SWRConfiguration, SWRHook, SWRResponse, ScopedMutator, State, mutate, preload, useSWRConfig } from '../_internal/index.mjs';
|
||||
import React from 'react';
|
||||
|
||||
declare const unstable_serialize: (key: Key) => string;
|
||||
|
||||
declare const SWRConfig: React.FC<React.PropsWithChildren<{
|
||||
value?: SWRConfiguration | ((parentConfig?: SWRConfiguration | undefined) => SWRConfiguration) | undefined;
|
||||
}>> & {
|
||||
defaultValue: FullConfiguration;
|
||||
};
|
||||
|
||||
/**
|
||||
* A hook to fetch data.
|
||||
*
|
||||
* @link https://swr.vercel.app
|
||||
* @example
|
||||
* ```jsx
|
||||
* import useSWR from 'swr'
|
||||
* function Profile() {
|
||||
* const { data, error, isLoading } = useSWR('/api/user', fetcher)
|
||||
* if (error) return <div>failed to load</div>
|
||||
* if (isLoading) return <div>loading...</div>
|
||||
* return <div>hello {data.name}!</div>
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
declare const useSWR: SWRHook;
|
||||
|
||||
interface SWRGlobalConfig {
|
||||
}
|
||||
|
||||
export { SWRConfig, type SWRGlobalConfig, useSWR as default, unstable_serialize };
|
||||
33
web/node_modules/swr/dist/index/index.d.ts
generated
vendored
Normal file
33
web/node_modules/swr/dist/index/index.d.ts
generated
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
import { Key, SWRHook, SWRConfiguration, FullConfiguration } from '../_internal/index.js';
|
||||
export { Arguments, BareFetcher, Cache, Fetcher, Key, KeyLoader, KeyedMutator, Middleware, MutatorCallback, MutatorOptions, Revalidator, RevalidatorOptions, SWRConfiguration, SWRHook, SWRResponse, ScopedMutator, State, mutate, preload, useSWRConfig } from '../_internal/index.js';
|
||||
import React from 'react';
|
||||
|
||||
declare const unstable_serialize: (key: Key) => string;
|
||||
|
||||
declare const SWRConfig: React.FC<React.PropsWithChildren<{
|
||||
value?: SWRConfiguration | ((parentConfig?: SWRConfiguration | undefined) => SWRConfiguration) | undefined;
|
||||
}>> & {
|
||||
defaultValue: FullConfiguration;
|
||||
};
|
||||
|
||||
/**
|
||||
* A hook to fetch data.
|
||||
*
|
||||
* @link https://swr.vercel.app
|
||||
* @example
|
||||
* ```jsx
|
||||
* import useSWR from 'swr'
|
||||
* function Profile() {
|
||||
* const { data, error, isLoading } = useSWR('/api/user', fetcher)
|
||||
* if (error) return <div>failed to load</div>
|
||||
* if (isLoading) return <div>loading...</div>
|
||||
* return <div>hello {data.name}!</div>
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
declare const useSWR: SWRHook;
|
||||
|
||||
interface SWRGlobalConfig {
|
||||
}
|
||||
|
||||
export { SWRConfig, type SWRGlobalConfig, useSWR as default, unstable_serialize };
|
||||
674
web/node_modules/swr/dist/index/index.js
generated
vendored
Normal file
674
web/node_modules/swr/dist/index/index.js
generated
vendored
Normal file
@@ -0,0 +1,674 @@
|
||||
Object.defineProperty(exports, '__esModule', { value: true });
|
||||
|
||||
var React = require('react');
|
||||
var index_js$1 = require('use-sync-external-store/shim/index.js');
|
||||
var index_js = require('../_internal/index.js');
|
||||
|
||||
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
||||
|
||||
var React__default = /*#__PURE__*/_interopDefault(React);
|
||||
|
||||
// Shared state between server components and client components
|
||||
const noop = ()=>{};
|
||||
// Using noop() as the undefined value as undefined can be replaced
|
||||
// by something else. Prettier ignore and extra parentheses are necessary here
|
||||
// to ensure that tsc doesn't remove the __NOINLINE__ comment.
|
||||
// prettier-ignore
|
||||
const UNDEFINED = /*#__NOINLINE__*/ noop();
|
||||
const OBJECT = Object;
|
||||
const isUndefined = (v)=>v === UNDEFINED;
|
||||
const isFunction = (v)=>typeof v == 'function';
|
||||
|
||||
// use WeakMap to store the object->key mapping
|
||||
// so the objects can be garbage collected.
|
||||
// WeakMap uses a hashtable under the hood, so the lookup
|
||||
// complexity is almost O(1).
|
||||
const table = new WeakMap();
|
||||
const getTypeName = (value)=>OBJECT.prototype.toString.call(value);
|
||||
const isObjectTypeName = (typeName, type)=>typeName === `[object ${type}]`;
|
||||
// counter of the key
|
||||
let counter = 0;
|
||||
// A stable hash implementation that supports:
|
||||
// - Fast and ensures unique hash properties
|
||||
// - Handles unserializable values
|
||||
// - Handles object key ordering
|
||||
// - Generates short results
|
||||
//
|
||||
// This is not a serialization function, and the result is not guaranteed to be
|
||||
// parsable.
|
||||
const stableHash = (arg)=>{
|
||||
const type = typeof arg;
|
||||
const typeName = getTypeName(arg);
|
||||
const isDate = isObjectTypeName(typeName, 'Date');
|
||||
const isRegex = isObjectTypeName(typeName, 'RegExp');
|
||||
const isPlainObject = isObjectTypeName(typeName, 'Object');
|
||||
let result;
|
||||
let index;
|
||||
if (OBJECT(arg) === arg && !isDate && !isRegex) {
|
||||
// Object/function, not null/date/regexp. Use WeakMap to store the id first.
|
||||
// If it's already hashed, directly return the result.
|
||||
result = table.get(arg);
|
||||
if (result) return result;
|
||||
// Store the hash first for circular reference detection before entering the
|
||||
// recursive `stableHash` calls.
|
||||
// For other objects like set and map, we use this id directly as the hash.
|
||||
result = ++counter + '~';
|
||||
table.set(arg, result);
|
||||
if (Array.isArray(arg)) {
|
||||
// Array.
|
||||
result = '@';
|
||||
for(index = 0; index < arg.length; index++){
|
||||
result += stableHash(arg[index]) + ',';
|
||||
}
|
||||
table.set(arg, result);
|
||||
}
|
||||
if (isPlainObject) {
|
||||
// Object, sort keys.
|
||||
result = '#';
|
||||
const keys = OBJECT.keys(arg).sort();
|
||||
while(!isUndefined(index = keys.pop())){
|
||||
if (!isUndefined(arg[index])) {
|
||||
result += index + ':' + stableHash(arg[index]) + ',';
|
||||
}
|
||||
}
|
||||
table.set(arg, result);
|
||||
}
|
||||
} else {
|
||||
result = isDate ? arg.toJSON() : type == 'symbol' ? arg.toString() : type == 'string' ? JSON.stringify(arg) : '' + arg;
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
const serialize = (key)=>{
|
||||
if (isFunction(key)) {
|
||||
try {
|
||||
key = key();
|
||||
} catch (err) {
|
||||
// dependencies not ready
|
||||
key = '';
|
||||
}
|
||||
}
|
||||
// Use the original key as the argument of fetcher. This can be a string or an
|
||||
// array of values.
|
||||
const args = key;
|
||||
// If key is not falsy, or not an empty array, hash it.
|
||||
key = typeof key == 'string' ? key : (Array.isArray(key) ? key.length : key) ? stableHash(key) : '';
|
||||
return [
|
||||
key,
|
||||
args
|
||||
];
|
||||
};
|
||||
|
||||
const unstable_serialize = (key)=>serialize(key)[0];
|
||||
|
||||
/// <reference types="react/experimental" />
|
||||
const use = React__default.default.use || // This extra generic is to avoid TypeScript mixing up the generic and JSX sytax
|
||||
// and emitting an error.
|
||||
// We assume that this is only for the `use(thenable)` case, not `use(context)`.
|
||||
// https://github.com/facebook/react/blob/aed00dacfb79d17c53218404c52b1c7aa59c4a89/packages/react-server/src/ReactFizzThenable.js#L45
|
||||
((thenable)=>{
|
||||
switch(thenable.status){
|
||||
case 'pending':
|
||||
throw thenable;
|
||||
case 'fulfilled':
|
||||
return thenable.value;
|
||||
case 'rejected':
|
||||
throw thenable.reason;
|
||||
default:
|
||||
thenable.status = 'pending';
|
||||
thenable.then((v)=>{
|
||||
thenable.status = 'fulfilled';
|
||||
thenable.value = v;
|
||||
}, (e)=>{
|
||||
thenable.status = 'rejected';
|
||||
thenable.reason = e;
|
||||
});
|
||||
throw thenable;
|
||||
}
|
||||
});
|
||||
const WITH_DEDUPE = {
|
||||
dedupe: true
|
||||
};
|
||||
const resolvedUndef = Promise.resolve(index_js.UNDEFINED);
|
||||
const useSWRHandler = (_key, fetcher, config)=>{
|
||||
const { cache, compare, suspense, fallbackData, revalidateOnMount, revalidateIfStale, refreshInterval, refreshWhenHidden, refreshWhenOffline, keepPreviousData } = config;
|
||||
const [EVENT_REVALIDATORS, MUTATION, FETCH, PRELOAD] = index_js.SWRGlobalState.get(cache);
|
||||
// `key` is the identifier of the SWR internal state,
|
||||
// `fnArg` is the argument/arguments parsed from the key, which will be passed
|
||||
// to the fetcher.
|
||||
// All of them are derived from `_key`.
|
||||
const [key, fnArg] = index_js.serialize(_key);
|
||||
// If it's the initial render of this hook.
|
||||
const initialMountedRef = React.useRef(false);
|
||||
// If the hook is unmounted already. This will be used to prevent some effects
|
||||
// to be called after unmounting.
|
||||
const unmountedRef = React.useRef(false);
|
||||
// Refs to keep the key and config.
|
||||
const keyRef = React.useRef(key);
|
||||
const fetcherRef = React.useRef(fetcher);
|
||||
const configRef = React.useRef(config);
|
||||
const getConfig = ()=>configRef.current;
|
||||
const isActive = ()=>getConfig().isVisible() && getConfig().isOnline();
|
||||
const [getCache, setCache, subscribeCache, getInitialCache] = index_js.createCacheHelper(cache, key);
|
||||
const stateDependencies = React.useRef({}).current;
|
||||
// Resolve the fallback data from either the inline option, or the global provider.
|
||||
// If it's a promise, we simply let React suspend and resolve it for us.
|
||||
const fallback = index_js.isUndefined(fallbackData) ? index_js.isUndefined(config.fallback) ? index_js.UNDEFINED : config.fallback[key] : fallbackData;
|
||||
const isEqual = (prev, current)=>{
|
||||
for(const _ in stateDependencies){
|
||||
const t = _;
|
||||
if (t === 'data') {
|
||||
if (!compare(prev[t], current[t])) {
|
||||
if (!index_js.isUndefined(prev[t])) {
|
||||
return false;
|
||||
}
|
||||
if (!compare(returnedData, current[t])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (current[t] !== prev[t]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
};
|
||||
const getSnapshot = React.useMemo(()=>{
|
||||
const shouldStartRequest = (()=>{
|
||||
if (!key) return false;
|
||||
if (!fetcher) return false;
|
||||
// If `revalidateOnMount` is set, we take the value directly.
|
||||
if (!index_js.isUndefined(revalidateOnMount)) return revalidateOnMount;
|
||||
// If it's paused, we skip revalidation.
|
||||
if (getConfig().isPaused()) return false;
|
||||
if (suspense) return false;
|
||||
return revalidateIfStale !== false;
|
||||
})();
|
||||
// Get the cache and merge it with expected states.
|
||||
const getSelectedCache = (state)=>{
|
||||
// We only select the needed fields from the state.
|
||||
const snapshot = index_js.mergeObjects(state);
|
||||
delete snapshot._k;
|
||||
if (!shouldStartRequest) {
|
||||
return snapshot;
|
||||
}
|
||||
return {
|
||||
isValidating: true,
|
||||
isLoading: true,
|
||||
...snapshot
|
||||
};
|
||||
};
|
||||
const cachedData = getCache();
|
||||
const initialData = getInitialCache();
|
||||
const clientSnapshot = getSelectedCache(cachedData);
|
||||
const serverSnapshot = cachedData === initialData ? clientSnapshot : getSelectedCache(initialData);
|
||||
// To make sure that we are returning the same object reference to avoid
|
||||
// unnecessary re-renders, we keep the previous snapshot and use deep
|
||||
// comparison to check if we need to return a new one.
|
||||
let memorizedSnapshot = clientSnapshot;
|
||||
return [
|
||||
()=>{
|
||||
const newSnapshot = getSelectedCache(getCache());
|
||||
const compareResult = isEqual(newSnapshot, memorizedSnapshot);
|
||||
if (compareResult) {
|
||||
// Mentally, we should always return the `memorizedSnapshot` here
|
||||
// as there's no change between the new and old snapshots.
|
||||
// However, since the `isEqual` function only compares selected fields,
|
||||
// the values of the unselected fields might be changed. That's
|
||||
// simply because we didn't track them.
|
||||
// To support the case in https://github.com/vercel/swr/pull/2576,
|
||||
// we need to update these fields in the `memorizedSnapshot` too
|
||||
// with direct mutations to ensure the snapshot is always up-to-date
|
||||
// even for the unselected fields, but only trigger re-renders when
|
||||
// the selected fields are changed.
|
||||
memorizedSnapshot.data = newSnapshot.data;
|
||||
memorizedSnapshot.isLoading = newSnapshot.isLoading;
|
||||
memorizedSnapshot.isValidating = newSnapshot.isValidating;
|
||||
memorizedSnapshot.error = newSnapshot.error;
|
||||
return memorizedSnapshot;
|
||||
} else {
|
||||
memorizedSnapshot = newSnapshot;
|
||||
return newSnapshot;
|
||||
}
|
||||
},
|
||||
()=>serverSnapshot
|
||||
];
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [
|
||||
cache,
|
||||
key
|
||||
]);
|
||||
// Get the current state that SWR should return.
|
||||
const cached = index_js$1.useSyncExternalStore(React.useCallback((callback)=>subscribeCache(key, (current, prev)=>{
|
||||
if (!isEqual(prev, current)) callback();
|
||||
}), // eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
[
|
||||
cache,
|
||||
key
|
||||
]), getSnapshot[0], getSnapshot[1]);
|
||||
const isInitialMount = !initialMountedRef.current;
|
||||
const hasRevalidator = EVENT_REVALIDATORS[key] && EVENT_REVALIDATORS[key].length > 0;
|
||||
const cachedData = cached.data;
|
||||
const data = index_js.isUndefined(cachedData) ? fallback && index_js.isPromiseLike(fallback) ? use(fallback) : fallback : cachedData;
|
||||
const error = cached.error;
|
||||
// Use a ref to store previously returned data. Use the initial data as its initial value.
|
||||
const laggyDataRef = React.useRef(data);
|
||||
const returnedData = keepPreviousData ? index_js.isUndefined(cachedData) ? index_js.isUndefined(laggyDataRef.current) ? data : laggyDataRef.current : cachedData : data;
|
||||
// - Suspense mode and there's stale data for the initial render.
|
||||
// - Not suspense mode and there is no fallback data and `revalidateIfStale` is enabled.
|
||||
// - `revalidateIfStale` is enabled but `data` is not defined.
|
||||
const shouldDoInitialRevalidation = (()=>{
|
||||
// if a key already has revalidators and also has error, we should not trigger revalidation
|
||||
if (hasRevalidator && !index_js.isUndefined(error)) return false;
|
||||
// If `revalidateOnMount` is set, we take the value directly.
|
||||
if (isInitialMount && !index_js.isUndefined(revalidateOnMount)) return revalidateOnMount;
|
||||
// If it's paused, we skip revalidation.
|
||||
if (getConfig().isPaused()) return false;
|
||||
// Under suspense mode, it will always fetch on render if there is no
|
||||
// stale data so no need to revalidate immediately mount it again.
|
||||
// If data exists, only revalidate if `revalidateIfStale` is true.
|
||||
if (suspense) return index_js.isUndefined(data) ? false : revalidateIfStale;
|
||||
// If there is no stale data, we need to revalidate when mount;
|
||||
// If `revalidateIfStale` is set to true, we will always revalidate.
|
||||
return index_js.isUndefined(data) || revalidateIfStale;
|
||||
})();
|
||||
// Resolve the default validating state:
|
||||
// If it's able to validate, and it should revalidate when mount, this will be true.
|
||||
const defaultValidatingState = !!(key && fetcher && isInitialMount && shouldDoInitialRevalidation);
|
||||
const isValidating = index_js.isUndefined(cached.isValidating) ? defaultValidatingState : cached.isValidating;
|
||||
const isLoading = index_js.isUndefined(cached.isLoading) ? defaultValidatingState : cached.isLoading;
|
||||
// The revalidation function is a carefully crafted wrapper of the original
|
||||
// `fetcher`, to correctly handle the many edge cases.
|
||||
const revalidate = React.useCallback(async (revalidateOpts)=>{
|
||||
const currentFetcher = fetcherRef.current;
|
||||
if (!key || !currentFetcher || unmountedRef.current || getConfig().isPaused()) {
|
||||
return false;
|
||||
}
|
||||
let newData;
|
||||
let startAt;
|
||||
let loading = true;
|
||||
const opts = revalidateOpts || {};
|
||||
// If there is no ongoing concurrent request, or `dedupe` is not set, a
|
||||
// new request should be initiated.
|
||||
const shouldStartNewRequest = !FETCH[key] || !opts.dedupe;
|
||||
/*
|
||||
For React 17
|
||||
Do unmount check for calls:
|
||||
If key has changed during the revalidation, or the component has been
|
||||
unmounted, old dispatch and old event callbacks should not take any
|
||||
effect
|
||||
|
||||
For React 18
|
||||
only check if key has changed
|
||||
https://github.com/reactwg/react-18/discussions/82
|
||||
*/ const callbackSafeguard = ()=>{
|
||||
if (index_js.IS_REACT_LEGACY) {
|
||||
return !unmountedRef.current && key === keyRef.current && initialMountedRef.current;
|
||||
}
|
||||
return key === keyRef.current;
|
||||
};
|
||||
// The final state object when the request finishes.
|
||||
const finalState = {
|
||||
isValidating: false,
|
||||
isLoading: false
|
||||
};
|
||||
const finishRequestAndUpdateState = ()=>{
|
||||
setCache(finalState);
|
||||
};
|
||||
const cleanupState = ()=>{
|
||||
// Check if it's still the same request before deleting it.
|
||||
const requestInfo = FETCH[key];
|
||||
if (requestInfo && requestInfo[1] === startAt) {
|
||||
delete FETCH[key];
|
||||
}
|
||||
};
|
||||
// Start fetching. Change the `isValidating` state, update the cache.
|
||||
const initialState = {
|
||||
isValidating: true
|
||||
};
|
||||
// It is in the `isLoading` state, if and only if there is no cached data.
|
||||
// This bypasses fallback data and laggy data.
|
||||
if (index_js.isUndefined(getCache().data)) {
|
||||
initialState.isLoading = true;
|
||||
}
|
||||
try {
|
||||
if (shouldStartNewRequest) {
|
||||
setCache(initialState);
|
||||
// If no cache is being rendered currently (it shows a blank page),
|
||||
// we trigger the loading slow event.
|
||||
if (config.loadingTimeout && index_js.isUndefined(getCache().data)) {
|
||||
setTimeout(()=>{
|
||||
if (loading && callbackSafeguard()) {
|
||||
getConfig().onLoadingSlow(key, config);
|
||||
}
|
||||
}, config.loadingTimeout);
|
||||
}
|
||||
// Start the request and save the timestamp.
|
||||
// Key must be truthy if entering here.
|
||||
FETCH[key] = [
|
||||
currentFetcher(fnArg),
|
||||
index_js.getTimestamp()
|
||||
];
|
||||
}
|
||||
// Wait until the ongoing request is done. Deduplication is also
|
||||
// considered here.
|
||||
;
|
||||
[newData, startAt] = FETCH[key];
|
||||
newData = await newData;
|
||||
if (shouldStartNewRequest) {
|
||||
// If the request isn't interrupted, clean it up after the
|
||||
// deduplication interval.
|
||||
setTimeout(cleanupState, config.dedupingInterval);
|
||||
}
|
||||
// If there're other ongoing request(s), started after the current one,
|
||||
// we need to ignore the current one to avoid possible race conditions:
|
||||
// req1------------------>res1 (current one)
|
||||
// req2---------------->res2
|
||||
// the request that fired later will always be kept.
|
||||
// The timestamp maybe be `undefined` or a number
|
||||
if (!FETCH[key] || FETCH[key][1] !== startAt) {
|
||||
if (shouldStartNewRequest) {
|
||||
if (callbackSafeguard()) {
|
||||
getConfig().onDiscarded(key);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
// Clear error.
|
||||
finalState.error = index_js.UNDEFINED;
|
||||
// If there're other mutations(s), that overlapped with the current revalidation:
|
||||
// case 1:
|
||||
// req------------------>res
|
||||
// mutate------>end
|
||||
// case 2:
|
||||
// req------------>res
|
||||
// mutate------>end
|
||||
// case 3:
|
||||
// req------------------>res
|
||||
// mutate-------...---------->
|
||||
// we have to ignore the revalidation result (res) because it's no longer fresh.
|
||||
// meanwhile, a new revalidation should be triggered when the mutation ends.
|
||||
const mutationInfo = MUTATION[key];
|
||||
if (!index_js.isUndefined(mutationInfo) && // case 1
|
||||
(startAt <= mutationInfo[0] || // case 2
|
||||
startAt <= mutationInfo[1] || // case 3
|
||||
mutationInfo[1] === 0)) {
|
||||
finishRequestAndUpdateState();
|
||||
if (shouldStartNewRequest) {
|
||||
if (callbackSafeguard()) {
|
||||
getConfig().onDiscarded(key);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
// Deep compare with the latest state to avoid extra re-renders.
|
||||
// For local state, compare and assign.
|
||||
const cacheData = getCache().data;
|
||||
// Since the compare fn could be custom fn
|
||||
// cacheData might be different from newData even when compare fn returns True
|
||||
finalState.data = compare(cacheData, newData) ? cacheData : newData;
|
||||
// Trigger the successful callback if it's the original request.
|
||||
if (shouldStartNewRequest) {
|
||||
if (callbackSafeguard()) {
|
||||
getConfig().onSuccess(newData, key, config);
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
cleanupState();
|
||||
const currentConfig = getConfig();
|
||||
const { shouldRetryOnError } = currentConfig;
|
||||
// Not paused, we continue handling the error. Otherwise, discard it.
|
||||
if (!currentConfig.isPaused()) {
|
||||
// Get a new error, don't use deep comparison for errors.
|
||||
finalState.error = err;
|
||||
// Error event and retry logic. Only for the actual request, not
|
||||
// deduped ones.
|
||||
if (shouldStartNewRequest && callbackSafeguard()) {
|
||||
currentConfig.onError(err, key, currentConfig);
|
||||
if (shouldRetryOnError === true || index_js.isFunction(shouldRetryOnError) && shouldRetryOnError(err)) {
|
||||
if (!getConfig().revalidateOnFocus || !getConfig().revalidateOnReconnect || isActive()) {
|
||||
// If it's inactive, stop. It will auto-revalidate when
|
||||
// refocusing or reconnecting.
|
||||
// When retrying, deduplication is always enabled.
|
||||
currentConfig.onErrorRetry(err, key, currentConfig, (_opts)=>{
|
||||
const revalidators = EVENT_REVALIDATORS[key];
|
||||
if (revalidators && revalidators[0]) {
|
||||
revalidators[0](index_js.revalidateEvents.ERROR_REVALIDATE_EVENT, _opts);
|
||||
}
|
||||
}, {
|
||||
retryCount: (opts.retryCount || 0) + 1,
|
||||
dedupe: true
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Mark loading as stopped.
|
||||
loading = false;
|
||||
// Update the current hook's state.
|
||||
finishRequestAndUpdateState();
|
||||
return true;
|
||||
}, // `setState` is immutable, and `eventsCallback`, `fnArg`, and
|
||||
// `keyValidating` are depending on `key`, so we can exclude them from
|
||||
// the deps array.
|
||||
//
|
||||
// FIXME:
|
||||
// `fn` and `config` might be changed during the lifecycle,
|
||||
// but they might be changed every render like this.
|
||||
// `useSWR('key', () => fetch('/api/'), { suspense: true })`
|
||||
// So we omit the values from the deps array
|
||||
// even though it might cause unexpected behaviors.
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
[
|
||||
key,
|
||||
cache
|
||||
]);
|
||||
// Similar to the global mutate but bound to the current cache and key.
|
||||
// `cache` isn't allowed to change during the lifecycle.
|
||||
const boundMutate = React.useCallback(// Use callback to make sure `keyRef.current` returns latest result every time
|
||||
(...args)=>{
|
||||
return index_js.internalMutate(cache, keyRef.current, ...args);
|
||||
}, // eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
[]);
|
||||
// The logic for updating refs.
|
||||
index_js.useIsomorphicLayoutEffect(()=>{
|
||||
fetcherRef.current = fetcher;
|
||||
configRef.current = config;
|
||||
// Handle laggy data updates. If there's cached data of the current key,
|
||||
// it'll be the correct reference.
|
||||
if (!index_js.isUndefined(cachedData)) {
|
||||
laggyDataRef.current = cachedData;
|
||||
}
|
||||
});
|
||||
// After mounted or key changed.
|
||||
index_js.useIsomorphicLayoutEffect(()=>{
|
||||
if (!key) return;
|
||||
const softRevalidate = revalidate.bind(index_js.UNDEFINED, WITH_DEDUPE);
|
||||
let nextFocusRevalidatedAt = 0;
|
||||
if (getConfig().revalidateOnFocus) {
|
||||
const initNow = Date.now();
|
||||
nextFocusRevalidatedAt = initNow + getConfig().focusThrottleInterval;
|
||||
}
|
||||
// Expose revalidators to global event listeners. So we can trigger
|
||||
// revalidation from the outside.
|
||||
const onRevalidate = (type, opts = {})=>{
|
||||
if (type == index_js.revalidateEvents.FOCUS_EVENT) {
|
||||
const now = Date.now();
|
||||
if (getConfig().revalidateOnFocus && now > nextFocusRevalidatedAt && isActive()) {
|
||||
nextFocusRevalidatedAt = now + getConfig().focusThrottleInterval;
|
||||
softRevalidate();
|
||||
}
|
||||
} else if (type == index_js.revalidateEvents.RECONNECT_EVENT) {
|
||||
if (getConfig().revalidateOnReconnect && isActive()) {
|
||||
softRevalidate();
|
||||
}
|
||||
} else if (type == index_js.revalidateEvents.MUTATE_EVENT) {
|
||||
return revalidate();
|
||||
} else if (type == index_js.revalidateEvents.ERROR_REVALIDATE_EVENT) {
|
||||
return revalidate(opts);
|
||||
}
|
||||
return;
|
||||
};
|
||||
const unsubEvents = index_js.subscribeCallback(key, EVENT_REVALIDATORS, onRevalidate);
|
||||
// Mark the component as mounted and update corresponding refs.
|
||||
unmountedRef.current = false;
|
||||
keyRef.current = key;
|
||||
initialMountedRef.current = true;
|
||||
// Keep the original key in the cache.
|
||||
setCache({
|
||||
_k: fnArg
|
||||
});
|
||||
// Trigger a revalidation
|
||||
if (shouldDoInitialRevalidation) {
|
||||
// Performance optimization: if a request is already in progress for this key,
|
||||
// skip the revalidation to avoid redundant work
|
||||
if (!FETCH[key]) {
|
||||
if (index_js.isUndefined(data) || index_js.IS_SERVER) {
|
||||
// Revalidate immediately.
|
||||
softRevalidate();
|
||||
} else {
|
||||
// Delay the revalidate if we have data to return so we won't block
|
||||
// rendering.
|
||||
index_js.rAF(softRevalidate);
|
||||
}
|
||||
}
|
||||
}
|
||||
return ()=>{
|
||||
// Mark it as unmounted.
|
||||
unmountedRef.current = true;
|
||||
unsubEvents();
|
||||
};
|
||||
}, [
|
||||
key
|
||||
]);
|
||||
// Polling
|
||||
index_js.useIsomorphicLayoutEffect(()=>{
|
||||
let timer;
|
||||
function next() {
|
||||
// Use the passed interval
|
||||
// ...or invoke the function with the updated data to get the interval
|
||||
const interval = index_js.isFunction(refreshInterval) ? refreshInterval(getCache().data) : refreshInterval;
|
||||
// We only start the next interval if `refreshInterval` is not 0, and:
|
||||
// - `force` is true, which is the start of polling
|
||||
// - or `timer` is not 0, which means the effect wasn't canceled
|
||||
if (interval && timer !== -1) {
|
||||
timer = setTimeout(execute, interval);
|
||||
}
|
||||
}
|
||||
function execute() {
|
||||
// Check if it's OK to execute:
|
||||
// Only revalidate when the page is visible, online, and not errored.
|
||||
if (!getCache().error && (refreshWhenHidden || getConfig().isVisible()) && (refreshWhenOffline || getConfig().isOnline())) {
|
||||
revalidate(WITH_DEDUPE).then(next);
|
||||
} else {
|
||||
// Schedule the next interval to check again.
|
||||
next();
|
||||
}
|
||||
}
|
||||
next();
|
||||
return ()=>{
|
||||
if (timer) {
|
||||
clearTimeout(timer);
|
||||
timer = -1;
|
||||
}
|
||||
};
|
||||
}, [
|
||||
refreshInterval,
|
||||
refreshWhenHidden,
|
||||
refreshWhenOffline,
|
||||
key
|
||||
]);
|
||||
// Display debug info in React DevTools.
|
||||
React.useDebugValue(returnedData);
|
||||
// In Suspense mode, we can't return the empty `data` state.
|
||||
// If there is an `error`, the `error` needs to be thrown to the error boundary.
|
||||
// If there is no `error`, the `revalidation` promise needs to be thrown to
|
||||
// the suspense boundary.
|
||||
if (suspense) {
|
||||
const hasKeyButNoData = key && index_js.isUndefined(data);
|
||||
// SWR should throw when trying to use Suspense on the server with React 18,
|
||||
// without providing any fallback data. This causes hydration errors. See:
|
||||
// https://github.com/vercel/swr/issues/1832
|
||||
if (!index_js.IS_REACT_LEGACY && index_js.IS_SERVER && hasKeyButNoData) {
|
||||
throw new Error('Fallback data is required when using Suspense in SSR.');
|
||||
}
|
||||
// Always update fetcher and config refs even with the Suspense mode.
|
||||
if (hasKeyButNoData) {
|
||||
fetcherRef.current = fetcher;
|
||||
configRef.current = config;
|
||||
unmountedRef.current = false;
|
||||
}
|
||||
const req = PRELOAD[key];
|
||||
const mutateReq = !index_js.isUndefined(req) && hasKeyButNoData ? boundMutate(req) : resolvedUndef;
|
||||
use(mutateReq);
|
||||
if (!index_js.isUndefined(error) && hasKeyButNoData) {
|
||||
throw error;
|
||||
}
|
||||
const revalidation = hasKeyButNoData ? revalidate(WITH_DEDUPE) : resolvedUndef;
|
||||
if (!index_js.isUndefined(returnedData) && hasKeyButNoData) {
|
||||
// @ts-ignore modify react promise status
|
||||
revalidation.status = 'fulfilled';
|
||||
// @ts-ignore modify react promise value
|
||||
revalidation.value = true;
|
||||
}
|
||||
use(revalidation);
|
||||
}
|
||||
const swrResponse = {
|
||||
mutate: boundMutate,
|
||||
get data () {
|
||||
stateDependencies.data = true;
|
||||
return returnedData;
|
||||
},
|
||||
get error () {
|
||||
stateDependencies.error = true;
|
||||
return error;
|
||||
},
|
||||
get isValidating () {
|
||||
stateDependencies.isValidating = true;
|
||||
return isValidating;
|
||||
},
|
||||
get isLoading () {
|
||||
stateDependencies.isLoading = true;
|
||||
return isLoading;
|
||||
}
|
||||
};
|
||||
return swrResponse;
|
||||
};
|
||||
const SWRConfig = index_js.OBJECT.defineProperty(index_js.SWRConfig, 'defaultValue', {
|
||||
value: index_js.defaultConfig
|
||||
});
|
||||
/**
|
||||
* A hook to fetch data.
|
||||
*
|
||||
* @link https://swr.vercel.app
|
||||
* @example
|
||||
* ```jsx
|
||||
* import useSWR from 'swr'
|
||||
* function Profile() {
|
||||
* const { data, error, isLoading } = useSWR('/api/user', fetcher)
|
||||
* if (error) return <div>failed to load</div>
|
||||
* if (isLoading) return <div>loading...</div>
|
||||
* return <div>hello {data.name}!</div>
|
||||
* }
|
||||
* ```
|
||||
*/ const useSWR = index_js.withArgs(useSWRHandler);
|
||||
|
||||
// useSWR
|
||||
|
||||
Object.defineProperty(exports, "mutate", {
|
||||
enumerable: true,
|
||||
get: function () { return index_js.mutate; }
|
||||
});
|
||||
Object.defineProperty(exports, "preload", {
|
||||
enumerable: true,
|
||||
get: function () { return index_js.preload; }
|
||||
});
|
||||
Object.defineProperty(exports, "useSWRConfig", {
|
||||
enumerable: true,
|
||||
get: function () { return index_js.useSWRConfig; }
|
||||
});
|
||||
exports.SWRConfig = SWRConfig;
|
||||
exports.default = useSWR;
|
||||
exports.unstable_serialize = unstable_serialize;
|
||||
655
web/node_modules/swr/dist/index/index.mjs
generated
vendored
Normal file
655
web/node_modules/swr/dist/index/index.mjs
generated
vendored
Normal file
@@ -0,0 +1,655 @@
|
||||
import React, { useRef, useMemo, useCallback, useDebugValue } from 'react';
|
||||
import { useSyncExternalStore } from 'use-sync-external-store/shim/index.js';
|
||||
import { UNDEFINED as UNDEFINED$1, OBJECT as OBJECT$1, SWRConfig as SWRConfig$1, defaultConfig, withArgs, SWRGlobalState, serialize as serialize$1, createCacheHelper, isUndefined as isUndefined$1, isPromiseLike, getTimestamp, isFunction as isFunction$1, revalidateEvents, internalMutate, useIsomorphicLayoutEffect, subscribeCallback, IS_SERVER, rAF, IS_REACT_LEGACY, mergeObjects } from '../_internal/index.mjs';
|
||||
export { mutate, preload, useSWRConfig } from '../_internal/index.mjs';
|
||||
|
||||
// Shared state between server components and client components
|
||||
const noop = ()=>{};
|
||||
// Using noop() as the undefined value as undefined can be replaced
|
||||
// by something else. Prettier ignore and extra parentheses are necessary here
|
||||
// to ensure that tsc doesn't remove the __NOINLINE__ comment.
|
||||
// prettier-ignore
|
||||
const UNDEFINED = /*#__NOINLINE__*/ noop();
|
||||
const OBJECT = Object;
|
||||
const isUndefined = (v)=>v === UNDEFINED;
|
||||
const isFunction = (v)=>typeof v == 'function';
|
||||
|
||||
// use WeakMap to store the object->key mapping
|
||||
// so the objects can be garbage collected.
|
||||
// WeakMap uses a hashtable under the hood, so the lookup
|
||||
// complexity is almost O(1).
|
||||
const table = new WeakMap();
|
||||
const getTypeName = (value)=>OBJECT.prototype.toString.call(value);
|
||||
const isObjectTypeName = (typeName, type)=>typeName === `[object ${type}]`;
|
||||
// counter of the key
|
||||
let counter = 0;
|
||||
// A stable hash implementation that supports:
|
||||
// - Fast and ensures unique hash properties
|
||||
// - Handles unserializable values
|
||||
// - Handles object key ordering
|
||||
// - Generates short results
|
||||
//
|
||||
// This is not a serialization function, and the result is not guaranteed to be
|
||||
// parsable.
|
||||
const stableHash = (arg)=>{
|
||||
const type = typeof arg;
|
||||
const typeName = getTypeName(arg);
|
||||
const isDate = isObjectTypeName(typeName, 'Date');
|
||||
const isRegex = isObjectTypeName(typeName, 'RegExp');
|
||||
const isPlainObject = isObjectTypeName(typeName, 'Object');
|
||||
let result;
|
||||
let index;
|
||||
if (OBJECT(arg) === arg && !isDate && !isRegex) {
|
||||
// Object/function, not null/date/regexp. Use WeakMap to store the id first.
|
||||
// If it's already hashed, directly return the result.
|
||||
result = table.get(arg);
|
||||
if (result) return result;
|
||||
// Store the hash first for circular reference detection before entering the
|
||||
// recursive `stableHash` calls.
|
||||
// For other objects like set and map, we use this id directly as the hash.
|
||||
result = ++counter + '~';
|
||||
table.set(arg, result);
|
||||
if (Array.isArray(arg)) {
|
||||
// Array.
|
||||
result = '@';
|
||||
for(index = 0; index < arg.length; index++){
|
||||
result += stableHash(arg[index]) + ',';
|
||||
}
|
||||
table.set(arg, result);
|
||||
}
|
||||
if (isPlainObject) {
|
||||
// Object, sort keys.
|
||||
result = '#';
|
||||
const keys = OBJECT.keys(arg).sort();
|
||||
while(!isUndefined(index = keys.pop())){
|
||||
if (!isUndefined(arg[index])) {
|
||||
result += index + ':' + stableHash(arg[index]) + ',';
|
||||
}
|
||||
}
|
||||
table.set(arg, result);
|
||||
}
|
||||
} else {
|
||||
result = isDate ? arg.toJSON() : type == 'symbol' ? arg.toString() : type == 'string' ? JSON.stringify(arg) : '' + arg;
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
const serialize = (key)=>{
|
||||
if (isFunction(key)) {
|
||||
try {
|
||||
key = key();
|
||||
} catch (err) {
|
||||
// dependencies not ready
|
||||
key = '';
|
||||
}
|
||||
}
|
||||
// Use the original key as the argument of fetcher. This can be a string or an
|
||||
// array of values.
|
||||
const args = key;
|
||||
// If key is not falsy, or not an empty array, hash it.
|
||||
key = typeof key == 'string' ? key : (Array.isArray(key) ? key.length : key) ? stableHash(key) : '';
|
||||
return [
|
||||
key,
|
||||
args
|
||||
];
|
||||
};
|
||||
|
||||
const unstable_serialize = (key)=>serialize(key)[0];
|
||||
|
||||
/// <reference types="react/experimental" />
|
||||
const use = React.use || // This extra generic is to avoid TypeScript mixing up the generic and JSX sytax
|
||||
// and emitting an error.
|
||||
// We assume that this is only for the `use(thenable)` case, not `use(context)`.
|
||||
// https://github.com/facebook/react/blob/aed00dacfb79d17c53218404c52b1c7aa59c4a89/packages/react-server/src/ReactFizzThenable.js#L45
|
||||
((thenable)=>{
|
||||
switch(thenable.status){
|
||||
case 'pending':
|
||||
throw thenable;
|
||||
case 'fulfilled':
|
||||
return thenable.value;
|
||||
case 'rejected':
|
||||
throw thenable.reason;
|
||||
default:
|
||||
thenable.status = 'pending';
|
||||
thenable.then((v)=>{
|
||||
thenable.status = 'fulfilled';
|
||||
thenable.value = v;
|
||||
}, (e)=>{
|
||||
thenable.status = 'rejected';
|
||||
thenable.reason = e;
|
||||
});
|
||||
throw thenable;
|
||||
}
|
||||
});
|
||||
const WITH_DEDUPE = {
|
||||
dedupe: true
|
||||
};
|
||||
const resolvedUndef = Promise.resolve(UNDEFINED$1);
|
||||
const useSWRHandler = (_key, fetcher, config)=>{
|
||||
const { cache, compare, suspense, fallbackData, revalidateOnMount, revalidateIfStale, refreshInterval, refreshWhenHidden, refreshWhenOffline, keepPreviousData } = config;
|
||||
const [EVENT_REVALIDATORS, MUTATION, FETCH, PRELOAD] = SWRGlobalState.get(cache);
|
||||
// `key` is the identifier of the SWR internal state,
|
||||
// `fnArg` is the argument/arguments parsed from the key, which will be passed
|
||||
// to the fetcher.
|
||||
// All of them are derived from `_key`.
|
||||
const [key, fnArg] = serialize$1(_key);
|
||||
// If it's the initial render of this hook.
|
||||
const initialMountedRef = useRef(false);
|
||||
// If the hook is unmounted already. This will be used to prevent some effects
|
||||
// to be called after unmounting.
|
||||
const unmountedRef = useRef(false);
|
||||
// Refs to keep the key and config.
|
||||
const keyRef = useRef(key);
|
||||
const fetcherRef = useRef(fetcher);
|
||||
const configRef = useRef(config);
|
||||
const getConfig = ()=>configRef.current;
|
||||
const isActive = ()=>getConfig().isVisible() && getConfig().isOnline();
|
||||
const [getCache, setCache, subscribeCache, getInitialCache] = createCacheHelper(cache, key);
|
||||
const stateDependencies = useRef({}).current;
|
||||
// Resolve the fallback data from either the inline option, or the global provider.
|
||||
// If it's a promise, we simply let React suspend and resolve it for us.
|
||||
const fallback = isUndefined$1(fallbackData) ? isUndefined$1(config.fallback) ? UNDEFINED$1 : config.fallback[key] : fallbackData;
|
||||
const isEqual = (prev, current)=>{
|
||||
for(const _ in stateDependencies){
|
||||
const t = _;
|
||||
if (t === 'data') {
|
||||
if (!compare(prev[t], current[t])) {
|
||||
if (!isUndefined$1(prev[t])) {
|
||||
return false;
|
||||
}
|
||||
if (!compare(returnedData, current[t])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (current[t] !== prev[t]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
};
|
||||
const getSnapshot = useMemo(()=>{
|
||||
const shouldStartRequest = (()=>{
|
||||
if (!key) return false;
|
||||
if (!fetcher) return false;
|
||||
// If `revalidateOnMount` is set, we take the value directly.
|
||||
if (!isUndefined$1(revalidateOnMount)) return revalidateOnMount;
|
||||
// If it's paused, we skip revalidation.
|
||||
if (getConfig().isPaused()) return false;
|
||||
if (suspense) return false;
|
||||
return revalidateIfStale !== false;
|
||||
})();
|
||||
// Get the cache and merge it with expected states.
|
||||
const getSelectedCache = (state)=>{
|
||||
// We only select the needed fields from the state.
|
||||
const snapshot = mergeObjects(state);
|
||||
delete snapshot._k;
|
||||
if (!shouldStartRequest) {
|
||||
return snapshot;
|
||||
}
|
||||
return {
|
||||
isValidating: true,
|
||||
isLoading: true,
|
||||
...snapshot
|
||||
};
|
||||
};
|
||||
const cachedData = getCache();
|
||||
const initialData = getInitialCache();
|
||||
const clientSnapshot = getSelectedCache(cachedData);
|
||||
const serverSnapshot = cachedData === initialData ? clientSnapshot : getSelectedCache(initialData);
|
||||
// To make sure that we are returning the same object reference to avoid
|
||||
// unnecessary re-renders, we keep the previous snapshot and use deep
|
||||
// comparison to check if we need to return a new one.
|
||||
let memorizedSnapshot = clientSnapshot;
|
||||
return [
|
||||
()=>{
|
||||
const newSnapshot = getSelectedCache(getCache());
|
||||
const compareResult = isEqual(newSnapshot, memorizedSnapshot);
|
||||
if (compareResult) {
|
||||
// Mentally, we should always return the `memorizedSnapshot` here
|
||||
// as there's no change between the new and old snapshots.
|
||||
// However, since the `isEqual` function only compares selected fields,
|
||||
// the values of the unselected fields might be changed. That's
|
||||
// simply because we didn't track them.
|
||||
// To support the case in https://github.com/vercel/swr/pull/2576,
|
||||
// we need to update these fields in the `memorizedSnapshot` too
|
||||
// with direct mutations to ensure the snapshot is always up-to-date
|
||||
// even for the unselected fields, but only trigger re-renders when
|
||||
// the selected fields are changed.
|
||||
memorizedSnapshot.data = newSnapshot.data;
|
||||
memorizedSnapshot.isLoading = newSnapshot.isLoading;
|
||||
memorizedSnapshot.isValidating = newSnapshot.isValidating;
|
||||
memorizedSnapshot.error = newSnapshot.error;
|
||||
return memorizedSnapshot;
|
||||
} else {
|
||||
memorizedSnapshot = newSnapshot;
|
||||
return newSnapshot;
|
||||
}
|
||||
},
|
||||
()=>serverSnapshot
|
||||
];
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [
|
||||
cache,
|
||||
key
|
||||
]);
|
||||
// Get the current state that SWR should return.
|
||||
const cached = useSyncExternalStore(useCallback((callback)=>subscribeCache(key, (current, prev)=>{
|
||||
if (!isEqual(prev, current)) callback();
|
||||
}), // eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
[
|
||||
cache,
|
||||
key
|
||||
]), getSnapshot[0], getSnapshot[1]);
|
||||
const isInitialMount = !initialMountedRef.current;
|
||||
const hasRevalidator = EVENT_REVALIDATORS[key] && EVENT_REVALIDATORS[key].length > 0;
|
||||
const cachedData = cached.data;
|
||||
const data = isUndefined$1(cachedData) ? fallback && isPromiseLike(fallback) ? use(fallback) : fallback : cachedData;
|
||||
const error = cached.error;
|
||||
// Use a ref to store previously returned data. Use the initial data as its initial value.
|
||||
const laggyDataRef = useRef(data);
|
||||
const returnedData = keepPreviousData ? isUndefined$1(cachedData) ? isUndefined$1(laggyDataRef.current) ? data : laggyDataRef.current : cachedData : data;
|
||||
// - Suspense mode and there's stale data for the initial render.
|
||||
// - Not suspense mode and there is no fallback data and `revalidateIfStale` is enabled.
|
||||
// - `revalidateIfStale` is enabled but `data` is not defined.
|
||||
const shouldDoInitialRevalidation = (()=>{
|
||||
// if a key already has revalidators and also has error, we should not trigger revalidation
|
||||
if (hasRevalidator && !isUndefined$1(error)) return false;
|
||||
// If `revalidateOnMount` is set, we take the value directly.
|
||||
if (isInitialMount && !isUndefined$1(revalidateOnMount)) return revalidateOnMount;
|
||||
// If it's paused, we skip revalidation.
|
||||
if (getConfig().isPaused()) return false;
|
||||
// Under suspense mode, it will always fetch on render if there is no
|
||||
// stale data so no need to revalidate immediately mount it again.
|
||||
// If data exists, only revalidate if `revalidateIfStale` is true.
|
||||
if (suspense) return isUndefined$1(data) ? false : revalidateIfStale;
|
||||
// If there is no stale data, we need to revalidate when mount;
|
||||
// If `revalidateIfStale` is set to true, we will always revalidate.
|
||||
return isUndefined$1(data) || revalidateIfStale;
|
||||
})();
|
||||
// Resolve the default validating state:
|
||||
// If it's able to validate, and it should revalidate when mount, this will be true.
|
||||
const defaultValidatingState = !!(key && fetcher && isInitialMount && shouldDoInitialRevalidation);
|
||||
const isValidating = isUndefined$1(cached.isValidating) ? defaultValidatingState : cached.isValidating;
|
||||
const isLoading = isUndefined$1(cached.isLoading) ? defaultValidatingState : cached.isLoading;
|
||||
// The revalidation function is a carefully crafted wrapper of the original
|
||||
// `fetcher`, to correctly handle the many edge cases.
|
||||
const revalidate = useCallback(async (revalidateOpts)=>{
|
||||
const currentFetcher = fetcherRef.current;
|
||||
if (!key || !currentFetcher || unmountedRef.current || getConfig().isPaused()) {
|
||||
return false;
|
||||
}
|
||||
let newData;
|
||||
let startAt;
|
||||
let loading = true;
|
||||
const opts = revalidateOpts || {};
|
||||
// If there is no ongoing concurrent request, or `dedupe` is not set, a
|
||||
// new request should be initiated.
|
||||
const shouldStartNewRequest = !FETCH[key] || !opts.dedupe;
|
||||
/*
|
||||
For React 17
|
||||
Do unmount check for calls:
|
||||
If key has changed during the revalidation, or the component has been
|
||||
unmounted, old dispatch and old event callbacks should not take any
|
||||
effect
|
||||
|
||||
For React 18
|
||||
only check if key has changed
|
||||
https://github.com/reactwg/react-18/discussions/82
|
||||
*/ const callbackSafeguard = ()=>{
|
||||
if (IS_REACT_LEGACY) {
|
||||
return !unmountedRef.current && key === keyRef.current && initialMountedRef.current;
|
||||
}
|
||||
return key === keyRef.current;
|
||||
};
|
||||
// The final state object when the request finishes.
|
||||
const finalState = {
|
||||
isValidating: false,
|
||||
isLoading: false
|
||||
};
|
||||
const finishRequestAndUpdateState = ()=>{
|
||||
setCache(finalState);
|
||||
};
|
||||
const cleanupState = ()=>{
|
||||
// Check if it's still the same request before deleting it.
|
||||
const requestInfo = FETCH[key];
|
||||
if (requestInfo && requestInfo[1] === startAt) {
|
||||
delete FETCH[key];
|
||||
}
|
||||
};
|
||||
// Start fetching. Change the `isValidating` state, update the cache.
|
||||
const initialState = {
|
||||
isValidating: true
|
||||
};
|
||||
// It is in the `isLoading` state, if and only if there is no cached data.
|
||||
// This bypasses fallback data and laggy data.
|
||||
if (isUndefined$1(getCache().data)) {
|
||||
initialState.isLoading = true;
|
||||
}
|
||||
try {
|
||||
if (shouldStartNewRequest) {
|
||||
setCache(initialState);
|
||||
// If no cache is being rendered currently (it shows a blank page),
|
||||
// we trigger the loading slow event.
|
||||
if (config.loadingTimeout && isUndefined$1(getCache().data)) {
|
||||
setTimeout(()=>{
|
||||
if (loading && callbackSafeguard()) {
|
||||
getConfig().onLoadingSlow(key, config);
|
||||
}
|
||||
}, config.loadingTimeout);
|
||||
}
|
||||
// Start the request and save the timestamp.
|
||||
// Key must be truthy if entering here.
|
||||
FETCH[key] = [
|
||||
currentFetcher(fnArg),
|
||||
getTimestamp()
|
||||
];
|
||||
}
|
||||
// Wait until the ongoing request is done. Deduplication is also
|
||||
// considered here.
|
||||
;
|
||||
[newData, startAt] = FETCH[key];
|
||||
newData = await newData;
|
||||
if (shouldStartNewRequest) {
|
||||
// If the request isn't interrupted, clean it up after the
|
||||
// deduplication interval.
|
||||
setTimeout(cleanupState, config.dedupingInterval);
|
||||
}
|
||||
// If there're other ongoing request(s), started after the current one,
|
||||
// we need to ignore the current one to avoid possible race conditions:
|
||||
// req1------------------>res1 (current one)
|
||||
// req2---------------->res2
|
||||
// the request that fired later will always be kept.
|
||||
// The timestamp maybe be `undefined` or a number
|
||||
if (!FETCH[key] || FETCH[key][1] !== startAt) {
|
||||
if (shouldStartNewRequest) {
|
||||
if (callbackSafeguard()) {
|
||||
getConfig().onDiscarded(key);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
// Clear error.
|
||||
finalState.error = UNDEFINED$1;
|
||||
// If there're other mutations(s), that overlapped with the current revalidation:
|
||||
// case 1:
|
||||
// req------------------>res
|
||||
// mutate------>end
|
||||
// case 2:
|
||||
// req------------>res
|
||||
// mutate------>end
|
||||
// case 3:
|
||||
// req------------------>res
|
||||
// mutate-------...---------->
|
||||
// we have to ignore the revalidation result (res) because it's no longer fresh.
|
||||
// meanwhile, a new revalidation should be triggered when the mutation ends.
|
||||
const mutationInfo = MUTATION[key];
|
||||
if (!isUndefined$1(mutationInfo) && // case 1
|
||||
(startAt <= mutationInfo[0] || // case 2
|
||||
startAt <= mutationInfo[1] || // case 3
|
||||
mutationInfo[1] === 0)) {
|
||||
finishRequestAndUpdateState();
|
||||
if (shouldStartNewRequest) {
|
||||
if (callbackSafeguard()) {
|
||||
getConfig().onDiscarded(key);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
// Deep compare with the latest state to avoid extra re-renders.
|
||||
// For local state, compare and assign.
|
||||
const cacheData = getCache().data;
|
||||
// Since the compare fn could be custom fn
|
||||
// cacheData might be different from newData even when compare fn returns True
|
||||
finalState.data = compare(cacheData, newData) ? cacheData : newData;
|
||||
// Trigger the successful callback if it's the original request.
|
||||
if (shouldStartNewRequest) {
|
||||
if (callbackSafeguard()) {
|
||||
getConfig().onSuccess(newData, key, config);
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
cleanupState();
|
||||
const currentConfig = getConfig();
|
||||
const { shouldRetryOnError } = currentConfig;
|
||||
// Not paused, we continue handling the error. Otherwise, discard it.
|
||||
if (!currentConfig.isPaused()) {
|
||||
// Get a new error, don't use deep comparison for errors.
|
||||
finalState.error = err;
|
||||
// Error event and retry logic. Only for the actual request, not
|
||||
// deduped ones.
|
||||
if (shouldStartNewRequest && callbackSafeguard()) {
|
||||
currentConfig.onError(err, key, currentConfig);
|
||||
if (shouldRetryOnError === true || isFunction$1(shouldRetryOnError) && shouldRetryOnError(err)) {
|
||||
if (!getConfig().revalidateOnFocus || !getConfig().revalidateOnReconnect || isActive()) {
|
||||
// If it's inactive, stop. It will auto-revalidate when
|
||||
// refocusing or reconnecting.
|
||||
// When retrying, deduplication is always enabled.
|
||||
currentConfig.onErrorRetry(err, key, currentConfig, (_opts)=>{
|
||||
const revalidators = EVENT_REVALIDATORS[key];
|
||||
if (revalidators && revalidators[0]) {
|
||||
revalidators[0](revalidateEvents.ERROR_REVALIDATE_EVENT, _opts);
|
||||
}
|
||||
}, {
|
||||
retryCount: (opts.retryCount || 0) + 1,
|
||||
dedupe: true
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Mark loading as stopped.
|
||||
loading = false;
|
||||
// Update the current hook's state.
|
||||
finishRequestAndUpdateState();
|
||||
return true;
|
||||
}, // `setState` is immutable, and `eventsCallback`, `fnArg`, and
|
||||
// `keyValidating` are depending on `key`, so we can exclude them from
|
||||
// the deps array.
|
||||
//
|
||||
// FIXME:
|
||||
// `fn` and `config` might be changed during the lifecycle,
|
||||
// but they might be changed every render like this.
|
||||
// `useSWR('key', () => fetch('/api/'), { suspense: true })`
|
||||
// So we omit the values from the deps array
|
||||
// even though it might cause unexpected behaviors.
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
[
|
||||
key,
|
||||
cache
|
||||
]);
|
||||
// Similar to the global mutate but bound to the current cache and key.
|
||||
// `cache` isn't allowed to change during the lifecycle.
|
||||
const boundMutate = useCallback(// Use callback to make sure `keyRef.current` returns latest result every time
|
||||
(...args)=>{
|
||||
return internalMutate(cache, keyRef.current, ...args);
|
||||
}, // eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
[]);
|
||||
// The logic for updating refs.
|
||||
useIsomorphicLayoutEffect(()=>{
|
||||
fetcherRef.current = fetcher;
|
||||
configRef.current = config;
|
||||
// Handle laggy data updates. If there's cached data of the current key,
|
||||
// it'll be the correct reference.
|
||||
if (!isUndefined$1(cachedData)) {
|
||||
laggyDataRef.current = cachedData;
|
||||
}
|
||||
});
|
||||
// After mounted or key changed.
|
||||
useIsomorphicLayoutEffect(()=>{
|
||||
if (!key) return;
|
||||
const softRevalidate = revalidate.bind(UNDEFINED$1, WITH_DEDUPE);
|
||||
let nextFocusRevalidatedAt = 0;
|
||||
if (getConfig().revalidateOnFocus) {
|
||||
const initNow = Date.now();
|
||||
nextFocusRevalidatedAt = initNow + getConfig().focusThrottleInterval;
|
||||
}
|
||||
// Expose revalidators to global event listeners. So we can trigger
|
||||
// revalidation from the outside.
|
||||
const onRevalidate = (type, opts = {})=>{
|
||||
if (type == revalidateEvents.FOCUS_EVENT) {
|
||||
const now = Date.now();
|
||||
if (getConfig().revalidateOnFocus && now > nextFocusRevalidatedAt && isActive()) {
|
||||
nextFocusRevalidatedAt = now + getConfig().focusThrottleInterval;
|
||||
softRevalidate();
|
||||
}
|
||||
} else if (type == revalidateEvents.RECONNECT_EVENT) {
|
||||
if (getConfig().revalidateOnReconnect && isActive()) {
|
||||
softRevalidate();
|
||||
}
|
||||
} else if (type == revalidateEvents.MUTATE_EVENT) {
|
||||
return revalidate();
|
||||
} else if (type == revalidateEvents.ERROR_REVALIDATE_EVENT) {
|
||||
return revalidate(opts);
|
||||
}
|
||||
return;
|
||||
};
|
||||
const unsubEvents = subscribeCallback(key, EVENT_REVALIDATORS, onRevalidate);
|
||||
// Mark the component as mounted and update corresponding refs.
|
||||
unmountedRef.current = false;
|
||||
keyRef.current = key;
|
||||
initialMountedRef.current = true;
|
||||
// Keep the original key in the cache.
|
||||
setCache({
|
||||
_k: fnArg
|
||||
});
|
||||
// Trigger a revalidation
|
||||
if (shouldDoInitialRevalidation) {
|
||||
// Performance optimization: if a request is already in progress for this key,
|
||||
// skip the revalidation to avoid redundant work
|
||||
if (!FETCH[key]) {
|
||||
if (isUndefined$1(data) || IS_SERVER) {
|
||||
// Revalidate immediately.
|
||||
softRevalidate();
|
||||
} else {
|
||||
// Delay the revalidate if we have data to return so we won't block
|
||||
// rendering.
|
||||
rAF(softRevalidate);
|
||||
}
|
||||
}
|
||||
}
|
||||
return ()=>{
|
||||
// Mark it as unmounted.
|
||||
unmountedRef.current = true;
|
||||
unsubEvents();
|
||||
};
|
||||
}, [
|
||||
key
|
||||
]);
|
||||
// Polling
|
||||
useIsomorphicLayoutEffect(()=>{
|
||||
let timer;
|
||||
function next() {
|
||||
// Use the passed interval
|
||||
// ...or invoke the function with the updated data to get the interval
|
||||
const interval = isFunction$1(refreshInterval) ? refreshInterval(getCache().data) : refreshInterval;
|
||||
// We only start the next interval if `refreshInterval` is not 0, and:
|
||||
// - `force` is true, which is the start of polling
|
||||
// - or `timer` is not 0, which means the effect wasn't canceled
|
||||
if (interval && timer !== -1) {
|
||||
timer = setTimeout(execute, interval);
|
||||
}
|
||||
}
|
||||
function execute() {
|
||||
// Check if it's OK to execute:
|
||||
// Only revalidate when the page is visible, online, and not errored.
|
||||
if (!getCache().error && (refreshWhenHidden || getConfig().isVisible()) && (refreshWhenOffline || getConfig().isOnline())) {
|
||||
revalidate(WITH_DEDUPE).then(next);
|
||||
} else {
|
||||
// Schedule the next interval to check again.
|
||||
next();
|
||||
}
|
||||
}
|
||||
next();
|
||||
return ()=>{
|
||||
if (timer) {
|
||||
clearTimeout(timer);
|
||||
timer = -1;
|
||||
}
|
||||
};
|
||||
}, [
|
||||
refreshInterval,
|
||||
refreshWhenHidden,
|
||||
refreshWhenOffline,
|
||||
key
|
||||
]);
|
||||
// Display debug info in React DevTools.
|
||||
useDebugValue(returnedData);
|
||||
// In Suspense mode, we can't return the empty `data` state.
|
||||
// If there is an `error`, the `error` needs to be thrown to the error boundary.
|
||||
// If there is no `error`, the `revalidation` promise needs to be thrown to
|
||||
// the suspense boundary.
|
||||
if (suspense) {
|
||||
const hasKeyButNoData = key && isUndefined$1(data);
|
||||
// SWR should throw when trying to use Suspense on the server with React 18,
|
||||
// without providing any fallback data. This causes hydration errors. See:
|
||||
// https://github.com/vercel/swr/issues/1832
|
||||
if (!IS_REACT_LEGACY && IS_SERVER && hasKeyButNoData) {
|
||||
throw new Error('Fallback data is required when using Suspense in SSR.');
|
||||
}
|
||||
// Always update fetcher and config refs even with the Suspense mode.
|
||||
if (hasKeyButNoData) {
|
||||
fetcherRef.current = fetcher;
|
||||
configRef.current = config;
|
||||
unmountedRef.current = false;
|
||||
}
|
||||
const req = PRELOAD[key];
|
||||
const mutateReq = !isUndefined$1(req) && hasKeyButNoData ? boundMutate(req) : resolvedUndef;
|
||||
use(mutateReq);
|
||||
if (!isUndefined$1(error) && hasKeyButNoData) {
|
||||
throw error;
|
||||
}
|
||||
const revalidation = hasKeyButNoData ? revalidate(WITH_DEDUPE) : resolvedUndef;
|
||||
if (!isUndefined$1(returnedData) && hasKeyButNoData) {
|
||||
// @ts-ignore modify react promise status
|
||||
revalidation.status = 'fulfilled';
|
||||
// @ts-ignore modify react promise value
|
||||
revalidation.value = true;
|
||||
}
|
||||
use(revalidation);
|
||||
}
|
||||
const swrResponse = {
|
||||
mutate: boundMutate,
|
||||
get data () {
|
||||
stateDependencies.data = true;
|
||||
return returnedData;
|
||||
},
|
||||
get error () {
|
||||
stateDependencies.error = true;
|
||||
return error;
|
||||
},
|
||||
get isValidating () {
|
||||
stateDependencies.isValidating = true;
|
||||
return isValidating;
|
||||
},
|
||||
get isLoading () {
|
||||
stateDependencies.isLoading = true;
|
||||
return isLoading;
|
||||
}
|
||||
};
|
||||
return swrResponse;
|
||||
};
|
||||
const SWRConfig = OBJECT$1.defineProperty(SWRConfig$1, 'defaultValue', {
|
||||
value: defaultConfig
|
||||
});
|
||||
/**
|
||||
* A hook to fetch data.
|
||||
*
|
||||
* @link https://swr.vercel.app
|
||||
* @example
|
||||
* ```jsx
|
||||
* import useSWR from 'swr'
|
||||
* function Profile() {
|
||||
* const { data, error, isLoading } = useSWR('/api/user', fetcher)
|
||||
* if (error) return <div>failed to load</div>
|
||||
* if (isLoading) return <div>loading...</div>
|
||||
* return <div>hello {data.name}!</div>
|
||||
* }
|
||||
* ```
|
||||
*/ const useSWR = withArgs(useSWRHandler);
|
||||
|
||||
// useSWR
|
||||
|
||||
export { SWRConfig, useSWR as default, unstable_serialize };
|
||||
96
web/node_modules/swr/dist/index/react-server.mjs
generated
vendored
Normal file
96
web/node_modules/swr/dist/index/react-server.mjs
generated
vendored
Normal file
@@ -0,0 +1,96 @@
|
||||
export { S as SWRConfig } from './config-client-Bi4rgVRk.mjs';
|
||||
|
||||
// Shared state between server components and client components
|
||||
const noop = ()=>{};
|
||||
// Using noop() as the undefined value as undefined can be replaced
|
||||
// by something else. Prettier ignore and extra parentheses are necessary here
|
||||
// to ensure that tsc doesn't remove the __NOINLINE__ comment.
|
||||
// prettier-ignore
|
||||
const UNDEFINED = /*#__NOINLINE__*/ noop();
|
||||
const OBJECT = Object;
|
||||
const isUndefined = (v)=>v === UNDEFINED;
|
||||
const isFunction = (v)=>typeof v == 'function';
|
||||
|
||||
// use WeakMap to store the object->key mapping
|
||||
// so the objects can be garbage collected.
|
||||
// WeakMap uses a hashtable under the hood, so the lookup
|
||||
// complexity is almost O(1).
|
||||
const table = new WeakMap();
|
||||
const getTypeName = (value)=>OBJECT.prototype.toString.call(value);
|
||||
const isObjectTypeName = (typeName, type)=>typeName === `[object ${type}]`;
|
||||
// counter of the key
|
||||
let counter = 0;
|
||||
// A stable hash implementation that supports:
|
||||
// - Fast and ensures unique hash properties
|
||||
// - Handles unserializable values
|
||||
// - Handles object key ordering
|
||||
// - Generates short results
|
||||
//
|
||||
// This is not a serialization function, and the result is not guaranteed to be
|
||||
// parsable.
|
||||
const stableHash = (arg)=>{
|
||||
const type = typeof arg;
|
||||
const typeName = getTypeName(arg);
|
||||
const isDate = isObjectTypeName(typeName, 'Date');
|
||||
const isRegex = isObjectTypeName(typeName, 'RegExp');
|
||||
const isPlainObject = isObjectTypeName(typeName, 'Object');
|
||||
let result;
|
||||
let index;
|
||||
if (OBJECT(arg) === arg && !isDate && !isRegex) {
|
||||
// Object/function, not null/date/regexp. Use WeakMap to store the id first.
|
||||
// If it's already hashed, directly return the result.
|
||||
result = table.get(arg);
|
||||
if (result) return result;
|
||||
// Store the hash first for circular reference detection before entering the
|
||||
// recursive `stableHash` calls.
|
||||
// For other objects like set and map, we use this id directly as the hash.
|
||||
result = ++counter + '~';
|
||||
table.set(arg, result);
|
||||
if (Array.isArray(arg)) {
|
||||
// Array.
|
||||
result = '@';
|
||||
for(index = 0; index < arg.length; index++){
|
||||
result += stableHash(arg[index]) + ',';
|
||||
}
|
||||
table.set(arg, result);
|
||||
}
|
||||
if (isPlainObject) {
|
||||
// Object, sort keys.
|
||||
result = '#';
|
||||
const keys = OBJECT.keys(arg).sort();
|
||||
while(!isUndefined(index = keys.pop())){
|
||||
if (!isUndefined(arg[index])) {
|
||||
result += index + ':' + stableHash(arg[index]) + ',';
|
||||
}
|
||||
}
|
||||
table.set(arg, result);
|
||||
}
|
||||
} else {
|
||||
result = isDate ? arg.toJSON() : type == 'symbol' ? arg.toString() : type == 'string' ? JSON.stringify(arg) : '' + arg;
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
const serialize = (key)=>{
|
||||
if (isFunction(key)) {
|
||||
try {
|
||||
key = key();
|
||||
} catch (err) {
|
||||
// dependencies not ready
|
||||
key = '';
|
||||
}
|
||||
}
|
||||
// Use the original key as the argument of fetcher. This can be a string or an
|
||||
// array of values.
|
||||
const args = key;
|
||||
// If key is not falsy, or not an empty array, hash it.
|
||||
key = typeof key == 'string' ? key : (Array.isArray(key) ? key.length : key) ? stableHash(key) : '';
|
||||
return [
|
||||
key,
|
||||
args
|
||||
];
|
||||
};
|
||||
|
||||
const unstable_serialize = (key)=>serialize(key)[0];
|
||||
|
||||
export { unstable_serialize };
|
||||
Reference in New Issue
Block a user