Skip to content

Commit

Permalink
feat: add sendArgs inference to common use hooks. (#64)
Browse files Browse the repository at this point in the history
* fix: check type error

* chore: update loading unit tests

* chore: fetch request init type

* chore: on message generics fix

* chore: remove tsconfig typings/general.ts

* fix: the type arg of usecaptcha useautorequest useretriablerequest useserialrequest are added to

---------

Co-authored-by: chenzhilin <[email protected]>
Co-authored-by: Scott Hu <[email protected]>
  • Loading branch information
3 people authored Jun 12, 2024
1 parent edff32e commit dbeec71
Show file tree
Hide file tree
Showing 24 changed files with 600 additions and 586 deletions.
8 changes: 8 additions & 0 deletions .vscode/extensions.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"recommendations": [
"dbaeumer.vscode-eslint",
"esbenp.prettier-vscode",
"Orta.vscode-jest",
"EditorConfig.EditorConfig"
]
}
20 changes: 10 additions & 10 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
"@typescript-eslint/eslint-plugin": "^5.43.0",
"@typescript-eslint/parser": "^5.43.0",
"@vue/vue3-jest": "^29.2.4",
"alova": "^2.18.2",
"alova": "^2.21.0",
"babel-jest": "^29.2.2",
"commitizen": "^4.3.0",
"commitlint": "^17.5.1",
Expand Down
10 changes: 5 additions & 5 deletions packages/scene-react/test/useRetriableRequest.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ describe('react => useRetriableRequest', () => {
expect(mockCompleteFn).toHaveBeenCalledTimes(4);
expect(mockSuccessFn).not.toBeCalled();
expect(mockFailFn).toHaveBeenCalledTimes(1);
expect(mockLoadingChangeFn).toHaveBeenCalledTimes(2); // 分别在初始化、恢复为false两次被调用(立即发起请求时loading默认为true)
expect(mockLoadingChangeFn).toHaveBeenCalledTimes(3); // 分别在初始化、设置为true、恢复为false三次被调用(立即发起请求时loading默认为true)
},
{
timeout: 4000
Expand Down Expand Up @@ -476,7 +476,7 @@ describe('react => useRetriableRequest', () => {
expect(screen.getByRole('error')).toHaveTextContent('[alova/useRetriableRequest]stop retry manually');
expect(mockRetryFn).toHaveBeenCalledTimes(2);
expect(mockFailFn).toHaveBeenCalledTimes(1);
expect(mockLoadingChangeFn).toHaveBeenCalledTimes(2); // 分别在初始化、恢复为false两次被调用(立即发起请求时loading默认为true)
expect(mockLoadingChangeFn).toHaveBeenCalledTimes(3); // 分别在初始化、设置为true、恢复为false三次被调用
},
{
timeout: 4000
Expand All @@ -489,7 +489,7 @@ describe('react => useRetriableRequest', () => {
expect(screen.getByRole('error')).toHaveTextContent('[alova/useRetriableRequest]stop retry manually');
expect(mockRetryFn).toHaveBeenCalledTimes(4);
expect(mockFailFn).toHaveBeenCalledTimes(2);
expect(mockLoadingChangeFn).toHaveBeenCalledTimes(4); // 设置为true、设置回false两次被调用
expect(mockLoadingChangeFn).toHaveBeenCalledTimes(5); // 设置为true、设置回false两次被调用
},
{
timeout: 4000
Expand Down Expand Up @@ -550,7 +550,7 @@ describe('react => useRetriableRequest', () => {
expect(mockCompleteFn).toHaveBeenCalledTimes(4);
expect(mockSuccessFn).not.toBeCalled();
expect(mockFailFn).toHaveBeenCalledTimes(1);
expect(mockLoadingChangeFn).toHaveBeenCalledTimes(2); // 分别在初始化、恢复为false两次被调用(立即发起请求时loading默认为true)
expect(mockLoadingChangeFn).toHaveBeenCalledTimes(3); // 分别在初始化、设置为true、恢复为false三次被调用
},
{
timeout: 4000
Expand All @@ -565,7 +565,7 @@ describe('react => useRetriableRequest', () => {
expect(mockCompleteFn).toHaveBeenCalledTimes(8);
expect(mockSuccessFn).not.toBeCalled();
expect(mockFailFn).toHaveBeenCalledTimes(2);
expect(mockLoadingChangeFn).toHaveBeenCalledTimes(4); // 设置为true、恢复为false两次被调用
expect(mockLoadingChangeFn).toHaveBeenCalledTimes(5); // 设置为true、恢复为false两次被调用
},
{
timeout: 4000
Expand Down
4 changes: 2 additions & 2 deletions packages/scene-react/test/useSSE.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,16 @@ import { undefinedValue } from '@/helper/variables';
import '@testing-library/jest-dom';
import { fireEvent, render, screen, waitFor } from '@testing-library/react';
import { Alova, createAlova } from 'alova';
import GlobalFetch, { FetchRequestInit } from 'alova/GlobalFetch';
import GlobalFetch from 'alova/GlobalFetch';
import ReactHook from 'alova/react';
import ES from 'eventsource';
import { AddressInfo } from 'net';
import React, { ReactElement } from 'react';
import { IntervalEventName, IntervalMessage, TriggerEventName, server, send as serverSend } from '~/test/sseServer';
import { getAlovaInstance, untilCbCalled } from '~/test/utils';
import { FetchRequestInit } from '~/typings/general';
import { ReactState, useSSE } from '..';
import { AlovaSSEMessageEvent, SSEHookReadyState } from '../typings/general';

Object.defineProperty(global, 'EventSource', { value: ES, writable: false });

let alovaInst: Alova<ReactState<any>, unknown, FetchRequestInit, any, any>;
Expand Down
51 changes: 26 additions & 25 deletions packages/scene-react/typings/general.d.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
import {
Alova,
AlovaCompleteEvent,
Expand Down Expand Up @@ -472,18 +471,18 @@ type SilentQueueMap = Record<string, SilentMethod[]>;
/**
* useCaptcha配置
*/
type CaptchaHookConfig<S, E, R, T, RC, RE, RH> = {
type CaptchaHookConfig<S, E, R, T, RC, RE, RH, ARG extends any[]> = {
/**
* 初始倒计时,当验证码发送成功时将会以此数据来开始倒计时
* @default 60
*/
initialCountdown?: number;
} & RequestHookConfig<S, E, R, T, RC, RE, RH>;
} & RequestHookConfig<S, E, R, T, RC, RE, RH, ARG>;

/**
* useCaptcha返回值
*/
type CaptchaReturnType<S, E, R, T, RC, RE, RH> = UseHookReturnType<S, E, R, T, RC, RE, RH> & {
type CaptchaReturnType<S, E, R, T, RC, RE, RH, ARG extends any[]> = UseHookReturnType<S, E, R, T, RC, RE, RH, ARG> & {
/**
* 当前倒计时,每秒-1,当倒计时到0时可再次发送验证码
*/
Expand Down Expand Up @@ -572,7 +571,7 @@ type FormReturnType<S, E, R, T, RC, RE, RH, F> = UseHookReturnType<S, E, R, T, R
/**
* useRetriableRequest配置
*/
type RetriableHookConfig<S, E, R, T, RC, RE, RH> = {
type RetriableHookConfig<S, E, R, T, RC, RE, RH, ARG extends any[]> = {
/**
* 最大重试次数,也可以设置为返回 boolean 值的函数,来动态判断是否继续重试。
* @default 3
Expand All @@ -583,12 +582,12 @@ type RetriableHookConfig<S, E, R, T, RC, RE, RH> = {
* 避让策略
*/
backoff?: BackoffPolicy;
} & RequestHookConfig<S, E, R, T, RC, RE, RH>;
} & RequestHookConfig<S, E, R, T, RC, RE, RH, ARG>;

/**
* useRetriableRequest onRetry回调事件实例
*/
interface RetriableRetryEvent<S, E, R, T, RC, RE, RH> extends AlovaEvent<S, E, R, T, RC, RE, RH> {
interface RetriableRetryEvent<S, E, R, T, RC, RE, RH, ARG extends any[]> extends AlovaEvent<S, E, R, T, RC, RE, RH, ARG> {
/**
* 当前的重试次数
*/
Expand All @@ -602,7 +601,7 @@ interface RetriableRetryEvent<S, E, R, T, RC, RE, RH> extends AlovaEvent<S, E, R
/**
* useRetriableRequest onFail回调事件实例
*/
interface RetriableFailEvent<S, E, R, T, RC, RE, RH> extends AlovaErrorEvent<S, E, R, T, RC, RE, RH> {
interface RetriableFailEvent<S, E, R, T, RC, RE, RH, ARG extends any[]> extends AlovaErrorEvent<S, E, R, T, RC, RE, RH, ARG> {
/**
* 失败时的重试次数
*/
Expand All @@ -611,7 +610,7 @@ interface RetriableFailEvent<S, E, R, T, RC, RE, RH> extends AlovaErrorEvent<S,
/**
* useRetriableRequest返回值
*/
type RetriableReturnType<S, E, R, T, RC, RE, RH> = UseHookReturnType<S, E, R, T, RC, RE, RH> & {
type RetriableReturnType<S, E, R, T, RC, RE, RH, ARG extends any[]> = UseHookReturnType<S, E, R, T, RC, RE, RH, ARG> & {
/**
* 停止重试,只在重试期间调用有效
* 停止后将立即触发onFail事件
Expand All @@ -624,7 +623,7 @@ type RetriableReturnType<S, E, R, T, RC, RE, RH> = UseHookReturnType<S, E, R, T,
* 它们将在重试发起后触发
* @param handler 重试事件回调
*/
onRetry(handler: (event: RetriableRetryEvent<S, E, R, T, RC, RE, RH>) => void): void;
onRetry(handler: (event: RetriableRetryEvent<S, E, R, T, RC, RE, RH, ARG>) => void): void;

/**
* 失败事件绑定
Expand All @@ -635,7 +634,7 @@ type RetriableReturnType<S, E, R, T, RC, RE, RH> = UseHookReturnType<S, E, R, T,
*
* @param handler 失败事件回调
*/
onFail(handler: (event: RetriableFailEvent<S, E, R, T, RC, RE, RH>) => void): void;
onFail(handler: (event: RetriableFailEvent<S, E, R, T, RC, RE, RH, ARG>) => void): void;
};

// middlewares
Expand All @@ -650,14 +649,14 @@ interface Actions {
* @param id 委托者id
* @returns alova中间件函数
*/
type ActionDelegationMiddleware = (id: string | number | symbol) => <S, E, R, T, RC, RE, RH>(
type ActionDelegationMiddleware = (id: string | number | symbol) => <S, E, R, T, RC, RE, RH, ARG extends any[]>(
context: (
| AlovaFrontMiddlewareContext<S, E, R, T, RC, RE, RH>
| AlovaFetcherMiddlewareContext<S, E, R, T, RC, RE, RH>
| AlovaFrontMiddlewareContext<S, E, R, T, RC, RE, RH, ARG>
| AlovaFetcherMiddlewareContext<S, E, R, T, RC, RE, RH, ARG>
) & {
delegatingActions?: Actions;
},
next: AlovaGuardNext<S, E, R, T, RC, RE, RH>
next: AlovaGuardNext<S, E, R, T, RC, RE, RH, ARG>
) => Promise<any>;

/**
Expand Down Expand Up @@ -810,7 +809,7 @@ type AlovaRequestAdapterUnified<
/**
* useAutoRequest配置
*/
type AutoRequestHookConfig<S, E, R, T, RC, RE, RH> = {
type AutoRequestHookConfig<S, E, R, T, RC, RE, RH, ARG extends any[]> = {
/**
* 轮询事件,单位ms,0表示不开启
* @default 0
Expand All @@ -836,7 +835,7 @@ type AutoRequestHookConfig<S, E, R, T, RC, RE, RH> = {
* @default 1000
*/
throttle?: number;
} & RequestHookConfig<S, E, R, T, RC, RE, RH>;
} & RequestHookConfig<S, E, R, T, RC, RE, RH, ARG>;

const enum SSEHookReadyState {
CONNECTING = 0,
Expand All @@ -859,9 +858,9 @@ type SSEOnMessageTrigger<Data, S, E, R, T, RC, RE, RH> = (
event: AlovaSSEMessageEvent<Data, S, E, R, T, RC, RE, RH>
) => void;
type SSEOnErrorTrigger<S, E, R, T, RC, RE, RH> = (event: AlovaSSEErrorEvent<S, E, R, T, RC, RE, RH>) => void;
type SSEOn<S, E, R, T, RC, RE, RH> = (
type SSEOn<S, E, R, T, RC, RE, RH, Data> = (
eventName: string,
handler: (event: AlovaSSEMessageEvent<S, E, R, T, RC, RE, RH>) => void
handler: (event: AlovaSSEMessageEvent<Data, S, E, R, T, RC, RE, RH>) => void
) => () => void;

type NotifyHandler = () => void;
Expand Down Expand Up @@ -904,7 +903,7 @@ type SSEHookConfig = {
/**
* useSSE() 返回类型
*/
type SSEReturnType<S, Data> = {
type SSEReturnType<S, Data, E, R, T, RC, RE, RH> = {
readyState: ExportedType<SSEHookReadyState, S>;
data: ExportedType<Data | undefined, S>;
eventSource: ExportedType<EventSource | undefined, S>;
Expand All @@ -922,33 +921,35 @@ type SSEReturnType<S, Data> = {
* @param callback 回调函数
* @returns 取消注册函数
*/
onOpen(callback: SSEOnOpenTrigger): () => void;
onOpen(callback: SSEOnOpenTrigger<S, E, R, T, RC, RE, RH>): () => void;

/**
* 注册 EventSource message 的回调函数
* @param callback 回调函数
* @returns 取消注册函数
*/
onMessage<T = Data>(callback: SSEOnMessageTrigger<T>): () => void;
onMessage<D = Data>(callback: SSEOnMessageTrigger<D, S, E, R, T, RC, RE, RH>): () => void;

/**
* 注册 EventSource error 的回调函数
* @param callback 回调函数
* @returns 取消注册函数
*/
onError(callback: SSEOnErrorTrigger): () => void;
onError(callback: SSEOnErrorTrigger<S, E, R, T, RC, RE, RH>): () => void;

/**
* @param eventName 事件名称,默认存在 `open` | `error` | `message`
* @param handler 事件处理器
*/
on: SSEOn;
on: SSEOn<S, E, R, T, RC, RE, RH, Data>;
};

type AnyFn<T = Any> = (...args: any[]) => T;
type AnyFn<T = any> = (...args: any[]) => T;

type UsePromiseReturnType<T> = {
promise: Promise<T>;
resolve: (value: T | PromiseLike<T>) => void;
reject: (reason?: any) => void;
};

type FetchRequestInit = Omit<RequestInit, 'body' | 'headers' | 'method'>;
Loading

0 comments on commit dbeec71

Please sign in to comment.