Update test framework: fix run_tests.py to support all test files, add auto-import-check for test files

This commit is contained in:
qiaoxinjiu
2026-05-09 15:11:30 +08:00
parent eb053a347f
commit eaba8328da
21739 changed files with 2236758 additions and 719 deletions

159
node_modules/swr/dist/mutation/index.d.mts generated vendored Normal file
View File

@@ -0,0 +1,159 @@
import { Key, Arguments, SWRResponse } from '../index/index.mjs';
type FetcherResponse<Data> = Data | Promise<Data>;
type FetcherOptions<ExtraArg = unknown> = Readonly<{
arg: ExtraArg;
}>;
type MutationFetcher<Data = unknown, SWRKey extends Key = Key, ExtraArg = unknown> = SWRKey extends () => infer Arg | null | undefined | false ? (key: Arg, options: FetcherOptions<ExtraArg>) => FetcherResponse<Data> : SWRKey extends null | undefined | false ? never : SWRKey extends infer Arg ? (key: Arg, options: FetcherOptions<ExtraArg>) => FetcherResponse<Data> : never;
type SWRMutationConfiguration<Data, Error, SWRMutationKey extends Key = Key, ExtraArg = any, SWRData = any> = {
revalidate?: boolean | ((data: Data, key: Arguments) => boolean);
populateCache?: boolean | ((result: Data, currentData: SWRData | undefined) => SWRData);
optimisticData?: SWRData | ((currentData?: SWRData) => SWRData);
rollbackOnError?: boolean | ((error: unknown) => boolean);
fetcher?: MutationFetcher<Data, SWRMutationKey, ExtraArg>;
onSuccess?: (data: Data, key: string, config: Readonly<SWRMutationConfiguration<Data, Error, SWRMutationKey, ExtraArg, SWRData>>) => void;
onError?: (err: Error, key: string, config: Readonly<SWRMutationConfiguration<Data, Error, SWRMutationKey, ExtraArg, SWRData>>) => void;
};
type RemoveUndefined<T> = T extends undefined ? never : T;
type IsUndefinedIncluded<T> = undefined extends T ? true : false;
interface TriggerWithArgs<Data = any, Error = any, SWRMutationKey extends Key = Key, ExtraArg = never> {
<SWRData = Data>(extraArgument: ExtraArg, options?: SWRMutationConfiguration<Data, Error, SWRMutationKey, ExtraArg, SWRData>): Promise<Data>;
<SWRData = Data>(extraArgument: ExtraArg, options?: SWRMutationConfiguration<Data, Error, SWRMutationKey, ExtraArg, SWRData> & {
throwOnError: true;
}): Promise<RemoveUndefined<Data>>;
<SWRData = Data>(extraArgument: ExtraArg, options?: SWRMutationConfiguration<Data, Error, SWRMutationKey, ExtraArg, SWRData> & {
throwOnError: false;
}): Promise<Data | undefined>;
}
interface TriggerWithOptionsArgs<Data = any, Error = any, SWRMutationKey extends Key = Key, ExtraArg = never> {
<SWRData = Data>(extraArgument?: ExtraArg, options?: SWRMutationConfiguration<Data, Error, SWRMutationKey, ExtraArg, SWRData>): Promise<Data>;
<SWRData = Data>(extraArgument?: ExtraArg, options?: SWRMutationConfiguration<Data, Error, SWRMutationKey, ExtraArg, SWRData> & {
throwOnError: true;
}): Promise<RemoveUndefined<Data>>;
<SWRData = Data>(extraArgument?: ExtraArg, options?: SWRMutationConfiguration<Data, Error, SWRMutationKey, ExtraArg, SWRData> & {
throwOnError: false;
}): Promise<Data | undefined>;
}
interface TriggerWithoutArgs<Data = any, Error = any, SWRMutationKey extends Key = Key, ExtraArg = never> {
<SWRData = Data>(extraArgument?: null, options?: SWRMutationConfiguration<Data, Error, SWRMutationKey, ExtraArg, SWRData>): Promise<Data>;
<SWRData = Data>(extraArgument?: null, options?: SWRMutationConfiguration<Data, Error, SWRMutationKey, ExtraArg, SWRData> & {
throwOnError: true;
}): Promise<RemoveUndefined<Data>>;
<SWRData = Data>(extraArgument?: null, options?: SWRMutationConfiguration<Data, Error, SWRMutationKey, ExtraArg, SWRData> & {
throwOnError: false;
}): Promise<Data>;
}
interface SWRMutationResponse<Data = any, Error = any, SWRMutationKey extends Key = Key, ExtraArg = never> extends Pick<SWRResponse<Data, Error>, 'data' | 'error'> {
/**
* Indicates if the mutation is in progress.
*/
isMutating: boolean;
/**
* Function to trigger the mutation. You can also pass an extra argument to
* the fetcher, and override the options for the mutation hook.
*/
trigger: [ExtraArg] extends [never] ? TriggerWithoutArgs<Data, Error, SWRMutationKey, ExtraArg> : IsUndefinedIncluded<ExtraArg> extends true ? TriggerWithOptionsArgs<Data, Error, SWRMutationKey, ExtraArg> : TriggerWithArgs<Data, Error, SWRMutationKey, ExtraArg>;
/**
* Function to reset the mutation state (`data`, `error`, and `isMutating`).
*/
reset: () => void;
}
interface SWRMutationHook {
<Data = any, Error = any, SWRMutationKey extends Key = Key, ExtraArg = never, SWRData = Data>(
/**
* The key of the resource that will be mutated. It should be the same key
* used in the `useSWR` hook so SWR can handle revalidation and race
* conditions for that resource.
*/
key: SWRMutationKey,
/**
* The function to trigger the mutation that accepts the key, extra argument
* and options. For example:
*
* ```jsx
* (api, data) => fetch(api, {
* method: 'POST',
* body: JSON.stringify(data)
* })
* ```
*/
fetcher: MutationFetcher<Data, SWRMutationKey, ExtraArg>,
/**
* Extra options for the mutation hook.
*/
options?: SWRMutationConfiguration<Data, Error, SWRMutationKey, ExtraArg, SWRData> & {
throwOnError?: boolean;
}): SWRMutationResponse<Data, Error, SWRMutationKey, ExtraArg>;
<Data = any, Error = any, SWRMutationKey extends Key = Key, ExtraArg = never, SWRData = Data>(
/**
* The key of the resource that will be mutated. It should be the same key
* used in the `useSWR` hook so SWR can handle revalidation and race
* conditions for that resource.
*/
key: SWRMutationKey,
/**
* The function to trigger the mutation that accepts the key, extra argument
* and options. For example:
*
* ```jsx
* (api, data) => fetch(api, {
* method: 'POST',
* body: JSON.stringify(data)
* })
* ```
*/
fetcher: MutationFetcher<Data, SWRMutationKey, ExtraArg>,
/**
* Extra options for the mutation hook.
*/
options?: SWRMutationConfiguration<Data, Error, SWRMutationKey, ExtraArg, SWRData> & {
throwOnError: false;
}): SWRMutationResponse<Data | undefined, Error, SWRMutationKey, ExtraArg>;
<Data = any, Error = any, SWRMutationKey extends Key = Key, ExtraArg = never, SWRData = Data>(
/**
* The key of the resource that will be mutated. It should be the same key
* used in the `useSWR` hook so SWR can handle revalidation and race
* conditions for that resource.
*/
key: SWRMutationKey,
/**
* The function to trigger the mutation that accepts the key, extra argument
* and options. For example:
*
* ```jsx
* (api, data) => fetch(api, {
* method: 'POST',
* body: JSON.stringify(data)
* })
* ```
*/
fetcher: MutationFetcher<Data, SWRMutationKey, ExtraArg>,
/**
* Extra options for the mutation hook.
*/
options?: SWRMutationConfiguration<Data, Error, SWRMutationKey, ExtraArg, SWRData> & {
throwOnError: true;
}): SWRMutationResponse<Data, Error, SWRMutationKey, ExtraArg>;
}
/**
* A hook to define and manually trigger remote mutations like POST, PUT, DELETE and PATCH use cases.
*
* @link https://swr.vercel.app/docs/mutation
* @example
* ```jsx
* import useSWRMutation from 'swr/mutation'
*
* const {
* data,
* error,
* trigger,
* reset,
* isMutating
* } = useSWRMutation(key, fetcher, options?)
* ```
*/
declare const useSWRMutation: SWRMutationHook;
export { useSWRMutation as default };
export type { MutationFetcher, SWRMutationConfiguration, SWRMutationHook, SWRMutationResponse, TriggerWithArgs, TriggerWithOptionsArgs, TriggerWithoutArgs };

159
node_modules/swr/dist/mutation/index.d.ts generated vendored Normal file
View File

@@ -0,0 +1,159 @@
import { Key, Arguments, SWRResponse } from '../index/index.js';
type FetcherResponse<Data> = Data | Promise<Data>;
type FetcherOptions<ExtraArg = unknown> = Readonly<{
arg: ExtraArg;
}>;
type MutationFetcher<Data = unknown, SWRKey extends Key = Key, ExtraArg = unknown> = SWRKey extends () => infer Arg | null | undefined | false ? (key: Arg, options: FetcherOptions<ExtraArg>) => FetcherResponse<Data> : SWRKey extends null | undefined | false ? never : SWRKey extends infer Arg ? (key: Arg, options: FetcherOptions<ExtraArg>) => FetcherResponse<Data> : never;
type SWRMutationConfiguration<Data, Error, SWRMutationKey extends Key = Key, ExtraArg = any, SWRData = any> = {
revalidate?: boolean | ((data: Data, key: Arguments) => boolean);
populateCache?: boolean | ((result: Data, currentData: SWRData | undefined) => SWRData);
optimisticData?: SWRData | ((currentData?: SWRData) => SWRData);
rollbackOnError?: boolean | ((error: unknown) => boolean);
fetcher?: MutationFetcher<Data, SWRMutationKey, ExtraArg>;
onSuccess?: (data: Data, key: string, config: Readonly<SWRMutationConfiguration<Data, Error, SWRMutationKey, ExtraArg, SWRData>>) => void;
onError?: (err: Error, key: string, config: Readonly<SWRMutationConfiguration<Data, Error, SWRMutationKey, ExtraArg, SWRData>>) => void;
};
type RemoveUndefined<T> = T extends undefined ? never : T;
type IsUndefinedIncluded<T> = undefined extends T ? true : false;
interface TriggerWithArgs<Data = any, Error = any, SWRMutationKey extends Key = Key, ExtraArg = never> {
<SWRData = Data>(extraArgument: ExtraArg, options?: SWRMutationConfiguration<Data, Error, SWRMutationKey, ExtraArg, SWRData>): Promise<Data>;
<SWRData = Data>(extraArgument: ExtraArg, options?: SWRMutationConfiguration<Data, Error, SWRMutationKey, ExtraArg, SWRData> & {
throwOnError: true;
}): Promise<RemoveUndefined<Data>>;
<SWRData = Data>(extraArgument: ExtraArg, options?: SWRMutationConfiguration<Data, Error, SWRMutationKey, ExtraArg, SWRData> & {
throwOnError: false;
}): Promise<Data | undefined>;
}
interface TriggerWithOptionsArgs<Data = any, Error = any, SWRMutationKey extends Key = Key, ExtraArg = never> {
<SWRData = Data>(extraArgument?: ExtraArg, options?: SWRMutationConfiguration<Data, Error, SWRMutationKey, ExtraArg, SWRData>): Promise<Data>;
<SWRData = Data>(extraArgument?: ExtraArg, options?: SWRMutationConfiguration<Data, Error, SWRMutationKey, ExtraArg, SWRData> & {
throwOnError: true;
}): Promise<RemoveUndefined<Data>>;
<SWRData = Data>(extraArgument?: ExtraArg, options?: SWRMutationConfiguration<Data, Error, SWRMutationKey, ExtraArg, SWRData> & {
throwOnError: false;
}): Promise<Data | undefined>;
}
interface TriggerWithoutArgs<Data = any, Error = any, SWRMutationKey extends Key = Key, ExtraArg = never> {
<SWRData = Data>(extraArgument?: null, options?: SWRMutationConfiguration<Data, Error, SWRMutationKey, ExtraArg, SWRData>): Promise<Data>;
<SWRData = Data>(extraArgument?: null, options?: SWRMutationConfiguration<Data, Error, SWRMutationKey, ExtraArg, SWRData> & {
throwOnError: true;
}): Promise<RemoveUndefined<Data>>;
<SWRData = Data>(extraArgument?: null, options?: SWRMutationConfiguration<Data, Error, SWRMutationKey, ExtraArg, SWRData> & {
throwOnError: false;
}): Promise<Data>;
}
interface SWRMutationResponse<Data = any, Error = any, SWRMutationKey extends Key = Key, ExtraArg = never> extends Pick<SWRResponse<Data, Error>, 'data' | 'error'> {
/**
* Indicates if the mutation is in progress.
*/
isMutating: boolean;
/**
* Function to trigger the mutation. You can also pass an extra argument to
* the fetcher, and override the options for the mutation hook.
*/
trigger: [ExtraArg] extends [never] ? TriggerWithoutArgs<Data, Error, SWRMutationKey, ExtraArg> : IsUndefinedIncluded<ExtraArg> extends true ? TriggerWithOptionsArgs<Data, Error, SWRMutationKey, ExtraArg> : TriggerWithArgs<Data, Error, SWRMutationKey, ExtraArg>;
/**
* Function to reset the mutation state (`data`, `error`, and `isMutating`).
*/
reset: () => void;
}
interface SWRMutationHook {
<Data = any, Error = any, SWRMutationKey extends Key = Key, ExtraArg = never, SWRData = Data>(
/**
* The key of the resource that will be mutated. It should be the same key
* used in the `useSWR` hook so SWR can handle revalidation and race
* conditions for that resource.
*/
key: SWRMutationKey,
/**
* The function to trigger the mutation that accepts the key, extra argument
* and options. For example:
*
* ```jsx
* (api, data) => fetch(api, {
* method: 'POST',
* body: JSON.stringify(data)
* })
* ```
*/
fetcher: MutationFetcher<Data, SWRMutationKey, ExtraArg>,
/**
* Extra options for the mutation hook.
*/
options?: SWRMutationConfiguration<Data, Error, SWRMutationKey, ExtraArg, SWRData> & {
throwOnError?: boolean;
}): SWRMutationResponse<Data, Error, SWRMutationKey, ExtraArg>;
<Data = any, Error = any, SWRMutationKey extends Key = Key, ExtraArg = never, SWRData = Data>(
/**
* The key of the resource that will be mutated. It should be the same key
* used in the `useSWR` hook so SWR can handle revalidation and race
* conditions for that resource.
*/
key: SWRMutationKey,
/**
* The function to trigger the mutation that accepts the key, extra argument
* and options. For example:
*
* ```jsx
* (api, data) => fetch(api, {
* method: 'POST',
* body: JSON.stringify(data)
* })
* ```
*/
fetcher: MutationFetcher<Data, SWRMutationKey, ExtraArg>,
/**
* Extra options for the mutation hook.
*/
options?: SWRMutationConfiguration<Data, Error, SWRMutationKey, ExtraArg, SWRData> & {
throwOnError: false;
}): SWRMutationResponse<Data | undefined, Error, SWRMutationKey, ExtraArg>;
<Data = any, Error = any, SWRMutationKey extends Key = Key, ExtraArg = never, SWRData = Data>(
/**
* The key of the resource that will be mutated. It should be the same key
* used in the `useSWR` hook so SWR can handle revalidation and race
* conditions for that resource.
*/
key: SWRMutationKey,
/**
* The function to trigger the mutation that accepts the key, extra argument
* and options. For example:
*
* ```jsx
* (api, data) => fetch(api, {
* method: 'POST',
* body: JSON.stringify(data)
* })
* ```
*/
fetcher: MutationFetcher<Data, SWRMutationKey, ExtraArg>,
/**
* Extra options for the mutation hook.
*/
options?: SWRMutationConfiguration<Data, Error, SWRMutationKey, ExtraArg, SWRData> & {
throwOnError: true;
}): SWRMutationResponse<Data, Error, SWRMutationKey, ExtraArg>;
}
/**
* A hook to define and manually trigger remote mutations like POST, PUT, DELETE and PATCH use cases.
*
* @link https://swr.vercel.app/docs/mutation
* @example
* ```jsx
* import useSWRMutation from 'swr/mutation'
*
* const {
* data,
* error,
* trigger,
* reset,
* isMutating
* } = useSWRMutation(key, fetcher, options?)
* ```
*/
declare const useSWRMutation: SWRMutationHook;
export { useSWRMutation as default };
export type { MutationFetcher, SWRMutationConfiguration, SWRMutationHook, SWRMutationResponse, TriggerWithArgs, TriggerWithOptionsArgs, TriggerWithoutArgs };

201
node_modules/swr/dist/mutation/index.js generated vendored Normal file
View File

@@ -0,0 +1,201 @@
Object.defineProperty(exports, '__esModule', { value: true });
var React = require('react');
var useSWR = require('../index/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);
var useSWR__default = /*#__PURE__*/_interopDefault(useSWR);
const startTransition = index_js.IS_REACT_LEGACY ? (cb)=>{
cb();
} : React__default.default.startTransition;
/**
* An implementation of state with dependency-tracking.
* @param initialState - The initial state object.
*/ const useStateWithDeps = (initialState)=>{
const [, rerender] = React.useState({});
const unmountedRef = React.useRef(false);
const stateRef = React.useRef(initialState);
// If a state property (data, error, or isValidating) is accessed by the render
// function, we mark the property as a dependency so if it is updated again
// in the future, we trigger a rerender.
// This is also known as dependency-tracking.
const stateDependenciesRef = React.useRef({
data: false,
error: false,
isValidating: false
});
/**
* Updates state and triggers re-render if necessary.
* @param payload To change stateRef, pass the values explicitly to setState:
* @example
* ```js
* setState({
* isValidating: false
* data: newData // set data to newData
* error: undefined // set error to undefined
* })
*
* setState({
* isValidating: false
* data: undefined // set data to undefined
* error: err // set error to err
* })
* ```
*/ const setState = React.useCallback((payload)=>{
let shouldRerender = false;
const currentState = stateRef.current;
for(const key in payload){
if (Object.prototype.hasOwnProperty.call(payload, key)) {
const k = key;
// If the property has changed, update the state and mark rerender as
// needed.
if (currentState[k] !== payload[k]) {
currentState[k] = payload[k];
// If the property is accessed by the component, a rerender should be
// triggered.
if (stateDependenciesRef.current[k]) {
shouldRerender = true;
}
}
}
}
if (shouldRerender && !unmountedRef.current) {
rerender({});
}
}, []);
index_js.useIsomorphicLayoutEffect(()=>{
unmountedRef.current = false;
return ()=>{
unmountedRef.current = true;
};
});
return [
stateRef,
stateDependenciesRef.current,
setState
];
};
const mutation = ()=>(key, fetcher, config = {})=>{
const { mutate } = useSWR.useSWRConfig();
const keyRef = React.useRef(key);
const fetcherRef = React.useRef(fetcher);
const configRef = React.useRef(config);
// Ditch all mutation results that happened earlier than this timestamp.
const ditchMutationsUntilRef = React.useRef(0);
const [stateRef, stateDependencies, setState] = useStateWithDeps({
data: index_js.UNDEFINED,
error: index_js.UNDEFINED,
isMutating: false
});
const currentState = stateRef.current;
const trigger = React.useCallback(async (arg, opts)=>{
const [serializedKey, resolvedKey] = index_js.serialize(keyRef.current);
if (!fetcherRef.current) {
throw new Error('Cant trigger the mutation: missing fetcher.');
}
if (!serializedKey) {
throw new Error('Cant trigger the mutation: missing key.');
}
// Disable cache population by default.
const options = index_js.mergeObjects(index_js.mergeObjects({
populateCache: false,
throwOnError: true
}, configRef.current), opts);
// Trigger a mutation, and also track the timestamp. Any mutation that happened
// earlier this timestamp should be ignored.
const mutationStartedAt = index_js.getTimestamp();
ditchMutationsUntilRef.current = mutationStartedAt;
setState({
isMutating: true
});
try {
const data = await mutate(serializedKey, fetcherRef.current(resolvedKey, {
arg
}), // We must throw the error here so we can catch and update the states.
index_js.mergeObjects(options, {
throwOnError: true
}));
// If it's reset after the mutation, we don't broadcast any state change.
if (ditchMutationsUntilRef.current <= mutationStartedAt) {
startTransition(()=>setState({
data,
isMutating: false,
error: undefined
}));
options.onSuccess == null ? void 0 : options.onSuccess.call(options, data, serializedKey, options);
}
return data;
} catch (error) {
// If it's reset after the mutation, we don't broadcast any state change
// or throw because it's discarded.
if (ditchMutationsUntilRef.current <= mutationStartedAt) {
startTransition(()=>setState({
error: error,
isMutating: false
}));
options.onError == null ? void 0 : options.onError.call(options, error, serializedKey, options);
if (options.throwOnError) {
throw error;
}
}
}
}, // eslint-disable-next-line react-hooks/exhaustive-deps
[]);
const reset = React.useCallback(()=>{
ditchMutationsUntilRef.current = index_js.getTimestamp();
setState({
data: index_js.UNDEFINED,
error: index_js.UNDEFINED,
isMutating: false
});
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
index_js.useIsomorphicLayoutEffect(()=>{
keyRef.current = key;
fetcherRef.current = fetcher;
configRef.current = config;
});
// We don't return `mutate` here as it can be pretty confusing (e.g. people
// calling `mutate` but they actually mean `trigger`).
// And also, `mutate` relies on the useSWR hook to exist too.
return {
trigger,
reset,
get data () {
stateDependencies.data = true;
return currentState.data;
},
get error () {
stateDependencies.error = true;
return currentState.error;
},
get isMutating () {
stateDependencies.isMutating = true;
return currentState.isMutating;
}
};
};
/**
* A hook to define and manually trigger remote mutations like POST, PUT, DELETE and PATCH use cases.
*
* @link https://swr.vercel.app/docs/mutation
* @example
* ```jsx
* import useSWRMutation from 'swr/mutation'
*
* const {
* data,
* error,
* trigger,
* reset,
* isMutating
* } = useSWRMutation(key, fetcher, options?)
* ```
*/ const useSWRMutation = index_js.withMiddleware(useSWR__default.default, mutation);
exports.default = useSWRMutation;

194
node_modules/swr/dist/mutation/index.mjs generated vendored Normal file
View File

@@ -0,0 +1,194 @@
import React, { useState, useRef, useCallback } from 'react';
import useSWR, { useSWRConfig } from '../index/index.mjs';
import { IS_REACT_LEGACY, useIsomorphicLayoutEffect, withMiddleware, serialize, mergeObjects, getTimestamp, UNDEFINED } from '../_internal/index.mjs';
const startTransition = IS_REACT_LEGACY ? (cb)=>{
cb();
} : React.startTransition;
/**
* An implementation of state with dependency-tracking.
* @param initialState - The initial state object.
*/ const useStateWithDeps = (initialState)=>{
const [, rerender] = useState({});
const unmountedRef = useRef(false);
const stateRef = useRef(initialState);
// If a state property (data, error, or isValidating) is accessed by the render
// function, we mark the property as a dependency so if it is updated again
// in the future, we trigger a rerender.
// This is also known as dependency-tracking.
const stateDependenciesRef = useRef({
data: false,
error: false,
isValidating: false
});
/**
* Updates state and triggers re-render if necessary.
* @param payload To change stateRef, pass the values explicitly to setState:
* @example
* ```js
* setState({
* isValidating: false
* data: newData // set data to newData
* error: undefined // set error to undefined
* })
*
* setState({
* isValidating: false
* data: undefined // set data to undefined
* error: err // set error to err
* })
* ```
*/ const setState = useCallback((payload)=>{
let shouldRerender = false;
const currentState = stateRef.current;
for(const key in payload){
if (Object.prototype.hasOwnProperty.call(payload, key)) {
const k = key;
// If the property has changed, update the state and mark rerender as
// needed.
if (currentState[k] !== payload[k]) {
currentState[k] = payload[k];
// If the property is accessed by the component, a rerender should be
// triggered.
if (stateDependenciesRef.current[k]) {
shouldRerender = true;
}
}
}
}
if (shouldRerender && !unmountedRef.current) {
rerender({});
}
}, []);
useIsomorphicLayoutEffect(()=>{
unmountedRef.current = false;
return ()=>{
unmountedRef.current = true;
};
});
return [
stateRef,
stateDependenciesRef.current,
setState
];
};
const mutation = ()=>(key, fetcher, config = {})=>{
const { mutate } = useSWRConfig();
const keyRef = useRef(key);
const fetcherRef = useRef(fetcher);
const configRef = useRef(config);
// Ditch all mutation results that happened earlier than this timestamp.
const ditchMutationsUntilRef = useRef(0);
const [stateRef, stateDependencies, setState] = useStateWithDeps({
data: UNDEFINED,
error: UNDEFINED,
isMutating: false
});
const currentState = stateRef.current;
const trigger = useCallback(async (arg, opts)=>{
const [serializedKey, resolvedKey] = serialize(keyRef.current);
if (!fetcherRef.current) {
throw new Error('Cant trigger the mutation: missing fetcher.');
}
if (!serializedKey) {
throw new Error('Cant trigger the mutation: missing key.');
}
// Disable cache population by default.
const options = mergeObjects(mergeObjects({
populateCache: false,
throwOnError: true
}, configRef.current), opts);
// Trigger a mutation, and also track the timestamp. Any mutation that happened
// earlier this timestamp should be ignored.
const mutationStartedAt = getTimestamp();
ditchMutationsUntilRef.current = mutationStartedAt;
setState({
isMutating: true
});
try {
const data = await mutate(serializedKey, fetcherRef.current(resolvedKey, {
arg
}), // We must throw the error here so we can catch and update the states.
mergeObjects(options, {
throwOnError: true
}));
// If it's reset after the mutation, we don't broadcast any state change.
if (ditchMutationsUntilRef.current <= mutationStartedAt) {
startTransition(()=>setState({
data,
isMutating: false,
error: undefined
}));
options.onSuccess == null ? void 0 : options.onSuccess.call(options, data, serializedKey, options);
}
return data;
} catch (error) {
// If it's reset after the mutation, we don't broadcast any state change
// or throw because it's discarded.
if (ditchMutationsUntilRef.current <= mutationStartedAt) {
startTransition(()=>setState({
error: error,
isMutating: false
}));
options.onError == null ? void 0 : options.onError.call(options, error, serializedKey, options);
if (options.throwOnError) {
throw error;
}
}
}
}, // eslint-disable-next-line react-hooks/exhaustive-deps
[]);
const reset = useCallback(()=>{
ditchMutationsUntilRef.current = getTimestamp();
setState({
data: UNDEFINED,
error: UNDEFINED,
isMutating: false
});
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
useIsomorphicLayoutEffect(()=>{
keyRef.current = key;
fetcherRef.current = fetcher;
configRef.current = config;
});
// We don't return `mutate` here as it can be pretty confusing (e.g. people
// calling `mutate` but they actually mean `trigger`).
// And also, `mutate` relies on the useSWR hook to exist too.
return {
trigger,
reset,
get data () {
stateDependencies.data = true;
return currentState.data;
},
get error () {
stateDependencies.error = true;
return currentState.error;
},
get isMutating () {
stateDependencies.isMutating = true;
return currentState.isMutating;
}
};
};
/**
* A hook to define and manually trigger remote mutations like POST, PUT, DELETE and PATCH use cases.
*
* @link https://swr.vercel.app/docs/mutation
* @example
* ```jsx
* import useSWRMutation from 'swr/mutation'
*
* const {
* data,
* error,
* trigger,
* reset,
* isMutating
* } = useSWRMutation(key, fetcher, options?)
* ```
*/ const useSWRMutation = withMiddleware(useSWR, mutation);
export { useSWRMutation as default };