import type { EventManager, FrameworkReadableState, FrameworkState, IsUnknown } from '@alova/shared'; import { AlovaGenerics, FetchRequestState, FrontRequestState, MergedStatesMap, Method, Progress, ReferingObject, StatesExport } from 'alova'; import { ReactHookExportType } from '../stateshook/react'; import { SolidHookExportType } from '../stateshook/solid'; import { SvelteHookExportType } from '../stateshook/svelte'; import { VueHookExportType } from '../stateshook/vue'; import { VueDemiHookExportType } from '../stateshook/vue-demi'; export interface StateMap { Vue: VueHookExportType; Solid: SolidHookExportType; React: ReactHookExportType; Svelte: SvelteHookExportType; VueDemi: VueDemiHookExportType; } /** * alova base event */ export interface AlovaEvent { /** * params from send function */ args: [...Args, ...any[]]; /** * current method instance */ method: Method; } /** * success event object */ export interface AlovaSuccessEvent extends AlovaEvent { /** Whether data from cache */ fromCache: boolean; data: AG['Responded']; } /** error event object */ export interface AlovaErrorEvent extends AlovaEvent { error: any; } /** completion event object */ export interface AlovaCompleteEvent extends AlovaEvent { /** response status */ status: 'success' | 'error'; /** Whether the data from the cache, when the status is error, from cache is always false */ fromCache: boolean; data?: AG['Responded']; error?: any; } /** * Define the type in a way that supports React and Vue. Other types will be needed later and then change on this basis. * Use the characteristics of different libraries as parent classes for judgment */ export type ExportedState> = SE['name'] extends keyof StateMap ? StateMap[SE['name']]['StateExport'] : Responded; export type ExportedComputed> = SE['name'] extends keyof StateMap ? StateMap[SE['name']]['ComputedExport'] : Responded; export type StateUpdater, SE extends StatesExport> = (newStates: { [K in keyof ExportedStates]?: ExportedStates[K] extends ExportedState | ExportedComputed ? R : ExportedStates[K]; }) => void; export type AlovaMethodHandler = ( ...args: Args ) => Method; export type SuccessHandler = (event: AlovaSuccessEvent) => void; export type ErrorHandler = (event: AlovaErrorEvent) => void; export type CompleteHandler = ( event: AlovaCompleteEvent ) => void; /** common hook configuration */ export interface UseHookConfig { /** * force request * @default false */ force?: boolean | ((event: AlovaEvent) => boolean); /** * refering object that sharing some value with this object. */ __referingObj?: ReferingObject; /** * other attributes */ [attr: string]: any; } export interface AlovaMiddlewareContext { /** current method instance */ method: Method; /** * cache data, only has value when hit cache */ cachedResponse: AG['Responded'] | undefined; /** the config of current use hook */ config: any; /** abort request */ abort: UseHookExposure['abort']; } /** next function of middleware */ export interface MiddlewareNextGuardConfig { force?: UseHookConfig['force']; method?: Method; } /** * context parameters of useRequest and useWatcher middleware */ export interface AlovaFrontMiddlewareContext extends AlovaMiddlewareContext { /** handler to send request */ send: SendHandler; /** args response processing callback parameters, which are passed in by send of use hooks */ args: [...Args, ...any[]]; /** state proxies set */ proxyStates: FrontRequestState< FrameworkState, FrameworkState, FrameworkState, FrameworkState, FrameworkState >; /** * custom control the state `loading` and doesn't toggle `loading` internally any more. * call it with param `false` to cancel controlling. * @JOU-amjs * @param control whether to control loading, default is `true` */ controlLoading: (control?: boolean) => void; /** * pass custom data */ [attr: string]: any; } /** * alova useRequest/useWatcher middleware */ export interface AlovaFrontMiddleware { (context: AlovaFrontMiddlewareContext, next: AlovaGuardNext): any; } /** * the context param of middleware in useFetcher */ export interface AlovaFetcherMiddlewareContext extends AlovaMiddlewareContext { /** fetch data */ fetch(method: Method, ...args: [...Args, ...any[]]): Promise; /** args response processing callback parameters, which are passed in by useFetcher’s fetch */ args: [...Args, ...any[]]; /** state proxies set */ proxyStates: FetchRequestState< FrameworkState, FrameworkState, FrameworkState, FrameworkState >; /** * custom control the state `loading` and doesn't toggle `loading` internally any more. * call it with param `false` to cancel controlling. * @JOU-amjs * @param control whether to control loading, default is `true` */ controlLoading: (control?: boolean) => void; /** * pass custom data */ [attr: string]: any; } /** * alova useFetcher middleware */ export interface AlovaFetcherMiddleware { (context: AlovaFetcherMiddlewareContext, next: AlovaGuardNext): any; } export type ProxyStateGetter> = ( key: K ) => HookExportedStates[K] extends ExportedState ? FrameworkState : HookExportedStates[K] extends ExportedComputed ? FrameworkReadableState : never; export interface AlovaGuardNext { (guardNextConfig?: MiddlewareNextGuardConfig): Promise; } export type SendHandler = (...args: [...Args, ...any[]]) => Promise; export interface UseHookExportedState extends FrontRequestState< ExportedState, ExportedState, ExportedState, ExportedState, ExportedState > {} export interface UseHookExposure< AG extends AlovaGenerics = AlovaGenerics, Args extends any[] = any[], SelfType = unknown > extends UseHookExportedState { /** * abort current request * @returns a promise that resolves when the request is aborted */ abort: () => Promise; /** * update state manually * @example * ```js * update({ * data: '...', * loading: true * }); * ``` */ update: StateUpdater, AG['StatesExport']>; /** * send request and pass params */ send: SendHandler; /** * subscribe to the success event * @param handler the handler to be called when request is successful */ onSuccess(handler: SuccessHandler): IsUnknown; /** * subscribe to the error event * @param handler the handler to be called when request is failed */ onError(handler: ErrorHandler): IsUnknown; /** * subscribe to the complete event * @param handler the handler to be called when request is complete */ onComplete(handler: CompleteHandler): IsUnknown; /** * get the original proxy state object, it's a internal api */ __proxyState: ProxyStateGetter>; /** * save component refering object, it's a internal api */ __referingObj: ReferingObject; /** * send and wait for responding with `await` * this is always used in `nuxt3` and `` of `vue3` * @example * ```js * const { loading, data, error } = await useRequest(...); * const { loading, data, error } = await useWatcher(...); * ``` */ then: (onfulfilled: (value: Omit, 'then'>) => void) => void; } type EnumHookType = 1 | 2 | 3; export interface Hook { /** The method instance of the last request */ m?: Method; /** Remove states fns */ rf: Record void>; /** Front states */ fs: FrontRequestState< FrameworkState, FrameworkState, FrameworkState, FrameworkState, FrameworkState >; /** event manager */ em: EventManager<{ success: AlovaSuccessEvent; error: AlovaErrorEvent; complete: AlovaCompleteEvent; }>; /** hookType, useRequest=1, useWatcher=2, useFetcher=3 */ ht: EnumHookType; /** hook config */ c: UseHookConfig; /** refering object */ ro: ReferingObject; /** merged states */ ms: MergedStatesMap; }