From 2eb30fd72e1c8dca031ba9527df82b92c0d26682 Mon Sep 17 00:00:00 2001 From: YongGit <1013588891@qq.com> Date: Sun, 12 May 2024 15:34:56 +0800 Subject: [PATCH] feat: v2 (#196) * type: format result type * type: sync * type: format result type * chore: upgrade v2 * feat: upgrade use-request plugin * docs: add use-request format result docs * docs: add migrate v2 * docs: opt * docs: demo * docs: add route * test: use-request plugin unit test --- package.json | 6 +- packages/hooks/docs/.vitepress/router.ts | 19 ++++-- packages/hooks/docs/migrate/index.en-US.md | 41 +++++++++++++ packages/hooks/docs/migrate/index.zh-CN.md | 41 +++++++++++++ packages/hooks/package.json | 2 +- packages/hooks/src/useRequest/Fetch.ts | 11 ++-- .../src/useRequest/__tests__/plugin.spec.ts | 18 +++--- .../hooks/src/useRequest/devtools/devtools.ts | 6 +- .../src/useRequest/docs/basic/index.en-US.md | 10 +--- .../src/useRequest/docs/basic/index.zh-CN.md | 8 +-- .../docs/formatResult/demo/demo.vue | 27 +++++++++ .../docs/formatResult/index.en-US.md | 30 ++++++++++ .../docs/formatResult/index.zh-CN.md | 30 ++++++++++ .../useRequest/docs/pluginDoc/demo/demo.vue | 22 +++---- .../useRequest/docs/pluginDoc/index.en-US.md | 40 ++++++++++++- .../useRequest/docs/pluginDoc/index.zh-CN.md | 40 ++++++++++++- .../plugins/broadcastChannel/demo/demo.vue | 10 ++-- .../docs/plugins/fetchsing/demo/demo.vue | 36 ++++++----- .../docs/plugins/fetchsing/demo/demo3.vue | 60 ++++++++++--------- packages/hooks/src/useRequest/types.ts | 26 +++++--- packages/hooks/src/useRequest/useRequest.ts | 41 ++++++++++--- .../src/useRequest/useRequestImplement.ts | 2 +- packages/types/package.json | 2 +- packages/use-request-plugins/package.json | 2 +- .../useBroadcastChannel.ts | 3 +- .../src/useFetchingPlugin/useFetching.ts | 3 +- packages/use-request/package.json | 2 +- packages/use-request/src/Fetch.ts | 11 ++-- packages/use-request/src/devtools/devtools.ts | 8 +-- packages/use-request/src/types.ts | 28 ++++++--- packages/use-request/src/useRequest.ts | 41 ++++++++++--- .../use-request/src/useRequestImplement.ts | 2 +- pnpm-lock.yaml | 15 +++-- 33 files changed, 490 insertions(+), 153 deletions(-) create mode 100644 packages/hooks/docs/migrate/index.en-US.md create mode 100644 packages/hooks/docs/migrate/index.zh-CN.md create mode 100644 packages/hooks/src/useRequest/docs/formatResult/demo/demo.vue create mode 100644 packages/hooks/src/useRequest/docs/formatResult/index.en-US.md create mode 100644 packages/hooks/src/useRequest/docs/formatResult/index.zh-CN.md diff --git a/package.json b/package.json index 43cbe279..b1d7e95c 100644 --- a/package.json +++ b/package.json @@ -36,9 +36,9 @@ "@vue-hooks-plus/vitepress-demo-block": "workspace:^1.0.0", "@vue-hooks-plus/use-immer":"workspace:^1.0.0", "@vue-hooks-plus/use-worker":"workspace:^1.0.0", - "@vue-hooks-plus/use-request":"workspace:^1.0.0", - "@vue-hooks-plus/use-request-plugins":"workspace:^1.0.0", - "@vue-hooks-plus/types":"workspace:^1.0.0", + "@vue-hooks-plus/use-request":"workspace:^2.0.0", + "@vue-hooks-plus/use-request-plugins":"workspace:^2.0.0", + "@vue-hooks-plus/types":"workspace:^2.0.0", "@vue-hooks-plus/eslint-config":"workspace:^1.0.0", "@vue/test-utils": "^2.1.0", "@vitest/coverage-c8":"^0.25.7", diff --git a/packages/hooks/docs/.vitepress/router.ts b/packages/hooks/docs/.vitepress/router.ts index 2eea9217..a985dcd6 100644 --- a/packages/hooks/docs/.vitepress/router.ts +++ b/packages/hooks/docs/.vitepress/router.ts @@ -137,7 +137,10 @@ const useRequestRouter = [ text: '错误重试', link: '/useRequest/retry/', }, - + { + text: '格式化数据', + link: '/useRequest/formatResult/', + }, { text: '缓存 & SWR', link: '/useRequest/cache/', @@ -155,7 +158,7 @@ const useRequestRouter = [ link: '/useRequest/scroll/', }, { - text: '中间件·Beta', + text: '中间件', link: '/useRequest/middleware/', }, { @@ -250,7 +253,10 @@ const useRequestRouterEN = [ text: 'Retry', link: '/en/useRequest/retry/', }, - + { + text: 'Format Result', + link: '/en/useRequest/formatResult/', + }, { text: 'Cache & SWR', link: '/en/useRequest/cache/', @@ -268,7 +274,7 @@ const useRequestRouterEN = [ link: '/en/useRequest/scroll/', }, { - text: 'Middleware·Beta', + text: 'Middleware', link: '/en/useRequest/middleware/', }, { @@ -310,6 +316,11 @@ export function getRouterConfig(langPrefix = '/') { text: langPrefix === '/' ? '📐 UseRequest规范' : '📐 UseRequest specification', link: `${langPrefix}useRequest/guide/`, }, + { + text: langPrefix === '/' ? '🫶 迁移到 v2 版本' : '🫶 Migrate to v2 version', + link: `${langPrefix}migrate/`, + }, + // { // text: langPrefix === '/' ? '🧑‍🏫 在线教程' : '🧑‍🏫 Online Teaching', // link: `${langPrefix}onlineTeaching/`, diff --git a/packages/hooks/docs/migrate/index.en-US.md b/packages/hooks/docs/migrate/index.en-US.md new file mode 100644 index 00000000..4027ce62 --- /dev/null +++ b/packages/hooks/docs/migrate/index.en-US.md @@ -0,0 +1,41 @@ +# 🫶 Migrate to v2 version + +:::info + +- useRequest plugin option + +::: + +## 1、useRequest plugin option + +In order to have good type hints and subsequent expansion in the v2 version of useRequest plug-in system, we have redesigned the usage of plugin option. You only need to make simple changes to achieve migration. + +## v1 use + +```typescript +const { data } = useRequest( + () => serviceFn(), + { + ...option, + ...pluginOption, + }, + [useFormatterPlugin, ...otherPlugins], +) +``` + +## v2 use + +```typescript +const { data } = useRequest( + () => serviceFn(), + { + ...option, + pluginOptions: { + ...pluginOption, + }, + }, + [useFormatterPlugin, ...otherPlugins], +) +``` + +Just migrate it to `pluginOptions` based on the original plugin option. diff --git a/packages/hooks/docs/migrate/index.zh-CN.md b/packages/hooks/docs/migrate/index.zh-CN.md new file mode 100644 index 00000000..89d0c54d --- /dev/null +++ b/packages/hooks/docs/migrate/index.zh-CN.md @@ -0,0 +1,41 @@ +# 🫶 迁移到 v2 版本 + +:::info + +- useRequest plugin option + +::: + +## 1、useRequest plugin option + +v2 版本的 useRequest 插件系统为了有良好的类型提示以及后续拓展,我们重新设计了 plugin option 的使用方式,你只需要进行简单的改变即可达到迁移。 + +## v1 use + +```typescript +const { data } = useRequest( + () => serviceFn(), + { + ...option, + ...pluginOption, + }, + [useFormatterPlugin, ...otherPlugins], +) +``` + +## v2 use + +```typescript +const { data } = useRequest( + () => serviceFn(), + { + ...option, + pluginOptions: { + ...pluginOption, + }, + }, + [useFormatterPlugin, ...otherPlugins], +) +``` + +只需要在原来的 plugin option 的基础上,将其迁移到 `pluginOptions` 下即可。 diff --git a/packages/hooks/package.json b/packages/hooks/package.json index 6dda7bd8..07e0fba0 100644 --- a/packages/hooks/package.json +++ b/packages/hooks/package.json @@ -1,6 +1,6 @@ { "name": "vue-hooks-plus", - "version": "1.9.0", + "version": "2.0.0", "description": "Vue hooks library", "files": [ "dist", diff --git a/packages/hooks/src/useRequest/Fetch.ts b/packages/hooks/src/useRequest/Fetch.ts index 4b8aa310..5edabd9e 100644 --- a/packages/hooks/src/useRequest/Fetch.ts +++ b/packages/hooks/src/useRequest/Fetch.ts @@ -5,6 +5,7 @@ import { UseRequestOptions, UseRequestPluginReturn, UseRequestService, + UseRequestOptionsWithFormatResult } from './types' export default class Fetch { @@ -23,7 +24,7 @@ export default class Fetch { constructor( public serviceRef: Ref>, - public options: UseRequestOptions, + public options: Partial & UseRequestOptionsWithFormatResult>, public setUpdateData: ( currentState: unknown, key?: keyof UseRequestFetchState, @@ -116,7 +117,7 @@ export default class Fetch { ) // Do you want to stop the request if (stopNow) { - return new Promise(() => {}) + return new Promise(() => { }) } this.setState({ @@ -144,7 +145,7 @@ export default class Fetch { this.runPluginHandler('onError', error, params) // Manually intercept the error and return a Promise with an empty status - return new Promise(() => {}) + return new Promise(() => { }) } try { @@ -154,7 +155,7 @@ export default class Fetch { const requestReturnResponse = (res: any) => { // The request has been cancelled, and the count will be inconsistent with the currentCount if (currentCount !== this.count) { - return new Promise(() => {}) + return new Promise(() => { }) } // Format data const formattedResult = this.options.formatResult ? this.options.formatResult(res) : res @@ -188,7 +189,7 @@ export default class Fetch { return requestReturnResponse(servicePromiseResult) } catch (error) { if (currentCount !== this.count) { - return new Promise(() => {}) + return new Promise(() => { }) } this.setState({ diff --git a/packages/hooks/src/useRequest/__tests__/plugin.spec.ts b/packages/hooks/src/useRequest/__tests__/plugin.spec.ts index c49cebaa..755d4848 100644 --- a/packages/hooks/src/useRequest/__tests__/plugin.spec.ts +++ b/packages/hooks/src/useRequest/__tests__/plugin.spec.ts @@ -24,10 +24,10 @@ const useFormatterPlugin: UseRequestPlugin< { formatter?: (params?: { name: string; age: number }) => any } -> = (fetchInstance, { formatter }) => { +> = (fetchInstance, { pluginOptions }) => { return { onSuccess: () => { - fetchInstance.setData(formatter?.(fetchInstance.state.data), 'data') + fetchInstance.setData(pluginOptions?.formatter?.(fetchInstance.state.data), 'data') }, } } @@ -37,12 +37,14 @@ describe('useRequest/Plugin', () => { useRequest( () => getUsername(), { - formatter: (data: any) => { - return { - name: `${data.name} - plugins update`, - age: 20, - } - }, + pluginOptions: { + formatter: (data) => { + return { + name: `${data?.name} - plugins update`, + age: 20, + } + }, + } }, [useFormatterPlugin], ), diff --git a/packages/hooks/src/useRequest/devtools/devtools.ts b/packages/hooks/src/useRequest/devtools/devtools.ts index 4ad337c9..27d0d4a4 100644 --- a/packages/hooks/src/useRequest/devtools/devtools.ts +++ b/packages/hooks/src/useRequest/devtools/devtools.ts @@ -1,9 +1,9 @@ import { setupDevtoolsPlugin } from '@vue/devtools-api' -import { unref } from 'vue' import { getRequestTagBg } from './utils' import devToolsStore from './store' import Fetch from '../Fetch' +import { unref } from 'vue' const pluginId = 'vue-hooks-plus' const pluginName = 'Vue Hooks Plus 🍭' @@ -163,11 +163,11 @@ export function setupDevtools(app: any) { 'Data Explorer': Object.keys(currentSource.instance.state).map(item => ({ key: item, value: - currentSource.instance.state[item as keyof typeof currentSource.instance.state], + unref(currentSource.instance.state[item as keyof typeof currentSource.instance.state]), })), Option: Object.keys(currentSource.instance.options).map(item => ({ key: item, - value: unref(currentSource.instance.options[item]), + value: currentSource.instance.options[item as keyof typeof currentSource.instance.options], })), ["Plugins 🧩"]: currentSource.instance.pluginImpls?.map((_, index) => { diff --git a/packages/hooks/src/useRequest/docs/basic/index.en-US.md b/packages/hooks/src/useRequest/docs/basic/index.en-US.md index 55d0ca57..a9c870ce 100644 --- a/packages/hooks/src/useRequest/docs/basic/index.en-US.md +++ b/packages/hooks/src/useRequest/docs/basic/index.en-US.md @@ -113,7 +113,7 @@ In the following example, we demonstrate a scenario of `mutate`. We have modified the user name, but we do not want to wait for the request to be successful before giving feedback to the user. Instead, modify the data directly, then call the modify request in background, and provide additional feedback after the request returns. -### error rollback `1.7.7.alpha.4` +### error rollback When you use `mutate`, it is possible that the remote data change fails after the optimistic data is displayed to the user. In this case, you can enable `rollbackOnError`, which restores the local cache to its previous state, ensuring that the user sees Got the correct data. @@ -149,12 +149,6 @@ If we set `options.manual = false`, the parameters of calling `service` for the title="" desc=""> -## Format the request data - -Since `useRequest` needs to guarantee a good plug-in system, format is too invasive for the system, the formatting here is `useFormatResult`, format data to `useFormatResult` after the request data is completed, `useFormatResult` can well support `typescript` type prompt.
- -Jump to useFormatResult - ## API ```ts @@ -205,7 +199,7 @@ const { | initialData | Init data | `TData` \| `undefined` | | manual |
  • The default is `false`. That is, the service is automatically executed during initialization.
  • If set to `true`, you need to manually call `run` or `runAsync` to trigger execution.
| `boolean` | `false` | | defaultParams | The parameters passed to the service at the first default execution | `TParams` | - | -| formatResult | Format the request results, which recommend to use `useFormatResult` | `(response: TData) => any` | - | +| formatResult | Format the request results,v1 which recommend to use `useFormatResult` | `(response: TData) => FormatData` | - | | onBefore | Triggered before service execution | `(params: TParams) => void` | - | | onSuccess | Triggered when service resolve | `(data: TData, params: TParams) => void` | - | | onError | Triggered when service reject | `(e: Error, params: TParams) => void` | - | diff --git a/packages/hooks/src/useRequest/docs/basic/index.zh-CN.md b/packages/hooks/src/useRequest/docs/basic/index.zh-CN.md index a1f96d90..96bbd158 100644 --- a/packages/hooks/src/useRequest/docs/basic/index.zh-CN.md +++ b/packages/hooks/src/useRequest/docs/basic/index.zh-CN.md @@ -146,12 +146,6 @@ runAsync() title="" desc=""> -## 格式化请求数据 - -由于 `useRequest` 需要保证良好的插件系统,format 对于系统来说侵入性太大,这里格式化使用的的是 `useFormatResult`,在请求数据完成后将 data 传入 `useFormatResult` 进行格式化, `useFormatResult` 可以很好的支持 `typescript` 类型提示。
- -跳转至 useFormatResult - ## API ```ts @@ -202,7 +196,7 @@ const { | initialData | 初始化的数据 | `TData` \| `undefined` | | manual |
  • 默认 `false`。 即在初始化时自动执行 service。
  • 如果设置为 `true`,则需要手动调用 `run` 或 `runAsync` 触发执行。
| `boolean` | `false` | | defaultParams | 首次默认执行时,传递给 service 的参数 | `TParams` | - | -| formatResult | 格式化请求结果,建议使用 `useFormatResult` | `(response: TData) => any` | - | +| formatResult | 格式化请求结果,v1 建议使用 `useFormatResult` | `(response: TData) => FormatData` | - | | onBefore | service 执行前触发 | `(params: TParams) => void` | - | | onSuccess | service resolve 时触发 | `(data: TData, params: TParams) => void` | - | | onError | service reject 时触发 | `(e: Error, params: TParams) => void` | - | diff --git a/packages/hooks/src/useRequest/docs/formatResult/demo/demo.vue b/packages/hooks/src/useRequest/docs/formatResult/demo/demo.vue new file mode 100644 index 00000000..73ddc5da --- /dev/null +++ b/packages/hooks/src/useRequest/docs/formatResult/demo/demo.vue @@ -0,0 +1,27 @@ + + + diff --git a/packages/hooks/src/useRequest/docs/formatResult/index.en-US.md b/packages/hooks/src/useRequest/docs/formatResult/index.en-US.md new file mode 100644 index 00000000..5b7471a2 --- /dev/null +++ b/packages/hooks/src/useRequest/docs/formatResult/index.en-US.md @@ -0,0 +1,30 @@ +--- +map: + # 映射到docs的路径 + path: /useRequest/formatResult/ +source: + show: false +--- + +# Format the request result + +## v1 use + +Since v1 version `useRequest` needs to guarantee a good plug-in system, format is too invasive for the system, the formatting here is `useFormatResult`, format data to `useFormatResult` after the request data is completed, `useFormatResult` can well support `typescript` type prompt.
+ +Jump to useFormatResult + +## v2 use + +It now supports ts types very well. + + + +## Options + +| Property | Description | Type | Default | +| ------------ | ------------------------- | --------------------------------- | ------- | +| formatResult | format the request result | `(response: TData) => FormatData` | - | diff --git a/packages/hooks/src/useRequest/docs/formatResult/index.zh-CN.md b/packages/hooks/src/useRequest/docs/formatResult/index.zh-CN.md new file mode 100644 index 00000000..66496b79 --- /dev/null +++ b/packages/hooks/src/useRequest/docs/formatResult/index.zh-CN.md @@ -0,0 +1,30 @@ +--- +map: + # 映射到docs的路径 + path: /useRequest/formatResult/ +source: + show: false +--- + +# 格式化请求数据 + +## v1 use + +由于 v1 版本 `useRequest` 需要保证良好的插件系统,format 对于系统来说侵入性太大,这里格式化使用的的是 `useFormatResult`,在请求数据完成后将 data 传入 `useFormatResult` 进行格式化, `useFormatResult` 可以很好的支持 `typescript` 类型提示。
+ +跳转至 useFormatResult + +## v2 use + +它现在能够很好的支持 ts 类型。 + + + +## Options + +| 参数 | 说明 | 类型 | 默认值 | +| ------------ | -------------- | --------------------------------- | ------ | +| formatResult | 格式化请求结果 | `(response: TData) => FormatData` | - | diff --git a/packages/hooks/src/useRequest/docs/pluginDoc/demo/demo.vue b/packages/hooks/src/useRequest/docs/pluginDoc/demo/demo.vue index 7d5b8e08..55a0eae7 100644 --- a/packages/hooks/src/useRequest/docs/pluginDoc/demo/demo.vue +++ b/packages/hooks/src/useRequest/docs/pluginDoc/demo/demo.vue @@ -14,20 +14,20 @@ } interface CustomPluginFieldType { - formatter: (data?: FormatterDataType) => { name: string; age: number } + formatter: (data: FormatterDataType) => { name: string; age: number } } const useFormatterPlugin: UseRequestPlugin< - FormatterDataType, + any, [], { - formatter: CustomPluginFieldType['formatter'] + formatter?: CustomPluginFieldType['formatter'] } - > = (fetchInstance, { formatter }) => { + > = (fetchInstance, { pluginOptions }) => { return { name: 'formatterPlugin', onSuccess: () => { - fetchInstance.setFetchState(formatter?.(fetchInstance.state.data), 'data') + fetchInstance.setFetchState(pluginOptions?.formatter?.(fetchInstance.state.data), 'data') }, } } @@ -47,11 +47,13 @@ () => getUsername(), { debugKey: 'plugindemo', - formatter: (params?: FormatterDataType) => { - return { - name: `${params?.name} - plugins update`, - age: 20, - } + pluginOptions: { + formatter: data => { + return { + name: `formatter ${data.name}`, + age: data.age + 1, + } + }, }, }, [useFormatterPlugin], diff --git a/packages/hooks/src/useRequest/docs/pluginDoc/index.en-US.md b/packages/hooks/src/useRequest/docs/pluginDoc/index.en-US.md index 5d56b7a2..4d161542 100644 --- a/packages/hooks/src/useRequest/docs/pluginDoc/index.en-US.md +++ b/packages/hooks/src/useRequest/docs/pluginDoc/index.en-US.md @@ -97,6 +97,8 @@ Need to setup `data`, `params`, `loading`, `error` Change requires use using the Return the results after the request data has processed the data, call `setFetchState` to reset the value. +### V1 example + ```typescript const useFormatterPlugin: UseRequestPlugin< { @@ -116,7 +118,28 @@ const useFormatterPlugin: UseRequestPlugin< } ``` -## API +### V2 example + +```typescript +const useFormatterPlugin: UseRequestPlugin< + { + name: string + age: number + }, + [], + { + formatter?: ({ name, age }?: { name: string; age: number }) => any + } +> = (fetchInstance, { pluginOptions }) => { + return { + onSuccess: () => { + fetchInstance.setFetchState(pluginOptions?.formatter?.(fetchInstance.state.data), 'data') + }, + } +} +``` + +## V1 API ```typescript const { data } = useRequest( @@ -129,6 +152,21 @@ const { data } = useRequest( ) ``` +## V2 API + +```typescript +const { data } = useRequest( + () => serviceFn(), + { + ...option, + pluginOptions: { + ...pluginOption, + }, + }, + [useFormatterPlugin, ...otherPlugins], +) +``` + ## Options | Property | Description | Type | Default | diff --git a/packages/hooks/src/useRequest/docs/pluginDoc/index.zh-CN.md b/packages/hooks/src/useRequest/docs/pluginDoc/index.zh-CN.md index d8535c84..4ee8e755 100644 --- a/packages/hooks/src/useRequest/docs/pluginDoc/index.zh-CN.md +++ b/packages/hooks/src/useRequest/docs/pluginDoc/index.zh-CN.md @@ -100,6 +100,8 @@ interface UseRequestPluginReturn { 在请求数据完成后将 外部传入的 `formatter` 处理完数据后将结果返回,调用 `setFetchState` 重新设置值。 +### V1 示例 + ```typescript const useFormatterPlugin: UseRequestPlugin< { @@ -119,7 +121,28 @@ const useFormatterPlugin: UseRequestPlugin< } ``` -## API +### V2 示例 + +```typescript +const useFormatterPlugin: UseRequestPlugin< + { + name: string + age: number + }, + [], + { + formatter?: ({ name, age }?: { name: string; age: number }) => any + } +> = (fetchInstance, { pluginOptions }) => { + return { + onSuccess: () => { + fetchInstance.setFetchState(pluginOptions?.formatter?.(fetchInstance.state.data), 'data') + }, + } +} +``` + +## V1 API ```typescript const { data } = useRequest( @@ -132,6 +155,21 @@ const { data } = useRequest( ) ``` +## V2 API + +```typescript +const { data } = useRequest( + () => serviceFn(), + { + ...option, + pluginOptions: { + ...pluginOption, + }, + }, + [useFormatterPlugin, ...otherPlugins], +) +``` + ## Options | 参数 | 说明 | 类型 | 默认值 | diff --git a/packages/hooks/src/useRequest/docs/plugins/broadcastChannel/demo/demo.vue b/packages/hooks/src/useRequest/docs/plugins/broadcastChannel/demo/demo.vue index 994634f2..c668690e 100644 --- a/packages/hooks/src/useRequest/docs/plugins/broadcastChannel/demo/demo.vue +++ b/packages/hooks/src/useRequest/docs/plugins/broadcastChannel/demo/demo.vue @@ -5,7 +5,7 @@ Refresh

Desc

- + Send
@@ -40,9 +40,11 @@ () => getUsername({ desc: desc.value }), { refreshDeps: true, - broadcastChannel: 'nice-broadcastChannel', - onBroadcastChannel: (message: any, channel: any) => { - other.value.push(message.data) + pluginOptions: { + broadcastChannel: 'nice-broadcastChannel', + onBroadcastChannel: (message: any, channel: any) => { + other.value.push(message.data) + }, }, }, [useBroadcastChannelPlugin], diff --git a/packages/hooks/src/useRequest/docs/plugins/fetchsing/demo/demo.vue b/packages/hooks/src/useRequest/docs/plugins/fetchsing/demo/demo.vue index 2621bd7a..5be06337 100644 --- a/packages/hooks/src/useRequest/docs/plugins/fetchsing/demo/demo.vue +++ b/packages/hooks/src/useRequest/docs/plugins/fetchsing/demo/demo.vue @@ -22,15 +22,17 @@ const { data, loading } = useRequest( () => getUsername({ desc: 'good' }), { - fetchingKey: () => { - return 'one' - }, - onFetching: (current: any, record: any) => { - console.log(current) - console.log(record) - }, - isFetching: (v: any) => { - console.log(v) + pluginOptions: { + fetchingKey: () => { + return 'one' + }, + onFetching: (current: any, record: any) => { + console.log(current) + console.log(record) + }, + isFetching: (v: any) => { + console.log(v) + }, }, }, [useFetchingPlugin], @@ -56,13 +58,15 @@ const { data, loading } = useRequest( () => getUsername({ desc: 'good' }), { - // manual: true, - fetchingKey: () => { - return 'two' - }, - onFetching: (current: any, record: any) => { - console.log(current) - console.log(record) + pluginOptions: { + // manual: true, + fetchingKey: () => { + return 'two' + }, + onFetching: (current: any, record: any) => { + console.log(current) + console.log(record) + }, }, }, [useFetchingPlugin], diff --git a/packages/hooks/src/useRequest/docs/plugins/fetchsing/demo/demo3.vue b/packages/hooks/src/useRequest/docs/plugins/fetchsing/demo/demo3.vue index 70d622a7..46c2992a 100644 --- a/packages/hooks/src/useRequest/docs/plugins/fetchsing/demo/demo3.vue +++ b/packages/hooks/src/useRequest/docs/plugins/fetchsing/demo/demo3.vue @@ -1,35 +1,41 @@ - \ No newline at end of file + diff --git a/packages/hooks/src/useRequest/types.ts b/packages/hooks/src/useRequest/types.ts index 26790740..4bb55308 100644 --- a/packages/hooks/src/useRequest/types.ts +++ b/packages/hooks/src/useRequest/types.ts @@ -52,7 +52,7 @@ export type UseRequestMiddleware = ( useRequestNext: RequestHook ) => RequestHook -export interface UseRequestBasicOptions { +export type UseRequestBasicOptions = { /** * Init data. */ @@ -128,7 +128,7 @@ export interface UseRequestBasicOptions { * @param data TData * @returns unknown need cover TData */ - formatResult?: (data?: TData) => unknown + // formatResult?: (data?: TData) => any /** * Polling interval, in milliseconds. If the value is greater than 0, the polling mode is activated. @@ -246,14 +246,24 @@ export interface UseRequestBasicOptions { * Middleware */ use?: UseRequestMiddleware[] + + rollbackOnError?: boolean | ((params: TParams) => boolean) +} + +export type UseRequestOptions = UseRequestBasicOptions & +{ + pluginOptions?: TPlugin +} + +export type UseRequestOptionsWithFormatResult< + TData, + TParams extends any[] = any[], + TPlugin = any, + SR = any, +> = UseRequestOptions & { + formatResult: (res: SR) => TData; } -export type UseRequestOptions = { - [K in keyof UseRequestBasicOptions]: UseRequestBasicOptions[K] -} & - { - [K in keyof TPlugin]: TPlugin[K] - } export interface UseRequestPlugin { ( diff --git a/packages/hooks/src/useRequest/useRequest.ts b/packages/hooks/src/useRequest/useRequest.ts index 8fb62bc2..b7dc83ff 100644 --- a/packages/hooks/src/useRequest/useRequest.ts +++ b/packages/hooks/src/useRequest/useRequest.ts @@ -10,24 +10,45 @@ import useThrottlePlugin from './plugins/useThrottlePlugin' import useRequestImplement from './useRequestImplement' -import { UseRequestOptions, UseRequestPlugin, UseRequestService } from './types' +import { UseRequestOptions, UseRequestOptionsWithFormatResult, UseRequestPlugin, useRequestResult, UseRequestService } from './types' import { withArgs } from './utils/resolve-args' -function useRequest< + +// 有 formatResult +export function useRequest< + TData, + TParams extends unknown[] = unknown[], + PluginsOptions extends UseRequestPlugin[] = UseRequestPlugin[], + SR = any, +>(service: UseRequestService, options?: UseRequestOptionsWithFormatResult + ? R + : never + : never, SR>, plugins?: PluginsOptions): useRequestResult + + +// 无 formatResults +export function useRequest< TData, TParams extends unknown[] = unknown[], - PluginsOptions extends UseRequestPlugin[] = UseRequestPlugin[] + PluginsOptions extends UseRequestPlugin[] = UseRequestPlugin[], +>(service: UseRequestService, options?: UseRequestOptions + ? R + : never + : never>, plugins?: PluginsOptions): useRequestResult + +export function useRequest< + TData, + TParams extends unknown[] = unknown[], + PluginsOptions extends UseRequestPlugin[] = UseRequestPlugin[], >( service: UseRequestService, - options?: UseRequestOptions< - TData, - TParams, - PluginsOptions extends (infer P)[] + options?: UseRequestOptions ? R : never - : never - >, + : never>, plugins?: PluginsOptions, ) { @@ -49,4 +70,6 @@ function useRequest< ] as UseRequestPlugin[]) } + + export default useRequest diff --git a/packages/hooks/src/useRequest/useRequestImplement.ts b/packages/hooks/src/useRequest/useRequestImplement.ts index 3dd60691..901ea6f3 100644 --- a/packages/hooks/src/useRequest/useRequestImplement.ts +++ b/packages/hooks/src/useRequest/useRequestImplement.ts @@ -18,7 +18,7 @@ function isUseRequestFetchState( function useRequestImplement( service: UseRequestService, - options: UseRequestOptions = {}, + options: UseRequestOptions = {}, plugins: UseRequestPlugin[] = [], ) { // global option diff --git a/packages/types/package.json b/packages/types/package.json index f1ce08cb..249549cd 100644 --- a/packages/types/package.json +++ b/packages/types/package.json @@ -1,6 +1,6 @@ { "name": "@vue-hooks-plus/types", - "version": "1.8.0", + "version": "2.0.0", "description": "", "files": [ "index.d.ts", diff --git a/packages/use-request-plugins/package.json b/packages/use-request-plugins/package.json index dba31e51..7ea2939d 100644 --- a/packages/use-request-plugins/package.json +++ b/packages/use-request-plugins/package.json @@ -1,6 +1,6 @@ { "name": "@vue-hooks-plus/use-request-plugins", - "version": "1.8.0", + "version": "2.0.0", "description": "", "files": [ "dist", diff --git a/packages/use-request-plugins/src/useBroadcastChannelPlugin/useBroadcastChannel.ts b/packages/use-request-plugins/src/useBroadcastChannelPlugin/useBroadcastChannel.ts index 24295268..70583439 100644 --- a/packages/use-request-plugins/src/useBroadcastChannelPlugin/useBroadcastChannel.ts +++ b/packages/use-request-plugins/src/useBroadcastChannelPlugin/useBroadcastChannel.ts @@ -15,7 +15,8 @@ export interface BroadcastChannelType { onBroadcastChannel?: (value?: MessageType, channel?: BroadcastChannel, setFetchState?: Fetch['setFetchState']) => void } -export const useBroadcastChannelPlugin: UseRequestPlugin = (fetchInstance, { broadcastChannel, broadcastChannelKey, broadcastChannelOptions = { webWorkerSupport: false }, customPostMessage, onBroadcastChannel }) => { +export const useBroadcastChannelPlugin: UseRequestPlugin = (fetchInstance, { pluginOptions }) => { + const { broadcastChannel, broadcastChannelKey, broadcastChannelOptions = { webWorkerSupport: false }, customPostMessage, onBroadcastChannel } = pluginOptions ?? {} let transaction = false const channel = ref() diff --git a/packages/use-request-plugins/src/useFetchingPlugin/useFetching.ts b/packages/use-request-plugins/src/useFetchingPlugin/useFetching.ts index f39833f3..e357ecc6 100644 --- a/packages/use-request-plugins/src/useFetchingPlugin/useFetching.ts +++ b/packages/use-request-plugins/src/useFetchingPlugin/useFetching.ts @@ -30,8 +30,9 @@ export interface FetchingPluginType { export const useFetchingPlugin: UseRequestPlugin = ( _, - { fetchingKey, onFetching, isFetching }, + { pluginOptions }, ) => { + const { fetchingKey, onFetching, isFetching } = pluginOptions ?? {} const store = useFetchingGlobalStore() let currentFetchingKey: string | undefined diff --git a/packages/use-request/package.json b/packages/use-request/package.json index 3079fad2..07a67653 100644 --- a/packages/use-request/package.json +++ b/packages/use-request/package.json @@ -1,6 +1,6 @@ { "name": "@vue-hooks-plus/use-request", - "version": "1.6.2", + "version": "2.0.0", "description": "Vue use-request hooks library", "files": [ "dist", diff --git a/packages/use-request/src/Fetch.ts b/packages/use-request/src/Fetch.ts index 4b8aa310..5edabd9e 100644 --- a/packages/use-request/src/Fetch.ts +++ b/packages/use-request/src/Fetch.ts @@ -5,6 +5,7 @@ import { UseRequestOptions, UseRequestPluginReturn, UseRequestService, + UseRequestOptionsWithFormatResult } from './types' export default class Fetch { @@ -23,7 +24,7 @@ export default class Fetch { constructor( public serviceRef: Ref>, - public options: UseRequestOptions, + public options: Partial & UseRequestOptionsWithFormatResult>, public setUpdateData: ( currentState: unknown, key?: keyof UseRequestFetchState, @@ -116,7 +117,7 @@ export default class Fetch { ) // Do you want to stop the request if (stopNow) { - return new Promise(() => {}) + return new Promise(() => { }) } this.setState({ @@ -144,7 +145,7 @@ export default class Fetch { this.runPluginHandler('onError', error, params) // Manually intercept the error and return a Promise with an empty status - return new Promise(() => {}) + return new Promise(() => { }) } try { @@ -154,7 +155,7 @@ export default class Fetch { const requestReturnResponse = (res: any) => { // The request has been cancelled, and the count will be inconsistent with the currentCount if (currentCount !== this.count) { - return new Promise(() => {}) + return new Promise(() => { }) } // Format data const formattedResult = this.options.formatResult ? this.options.formatResult(res) : res @@ -188,7 +189,7 @@ export default class Fetch { return requestReturnResponse(servicePromiseResult) } catch (error) { if (currentCount !== this.count) { - return new Promise(() => {}) + return new Promise(() => { }) } this.setState({ diff --git a/packages/use-request/src/devtools/devtools.ts b/packages/use-request/src/devtools/devtools.ts index d7639ae2..27d0d4a4 100644 --- a/packages/use-request/src/devtools/devtools.ts +++ b/packages/use-request/src/devtools/devtools.ts @@ -1,9 +1,9 @@ import { setupDevtoolsPlugin } from '@vue/devtools-api' -import { unref } from 'vue' import { getRequestTagBg } from './utils' import devToolsStore from './store' import Fetch from '../Fetch' +import { unref } from 'vue' const pluginId = 'vue-hooks-plus' const pluginName = 'Vue Hooks Plus 🍭' @@ -163,13 +163,13 @@ export function setupDevtools(app: any) { 'Data Explorer': Object.keys(currentSource.instance.state).map(item => ({ key: item, value: - currentSource.instance.state[item as keyof typeof currentSource.instance.state], + unref(currentSource.instance.state[item as keyof typeof currentSource.instance.state]), })), Option: Object.keys(currentSource.instance.options).map(item => ({ key: item, - value: unref(currentSource.instance.options[item]), + value: currentSource.instance.options[item as keyof typeof currentSource.instance.options], })), - Plugins: + ["Plugins 🧩"]: currentSource.instance.pluginImpls?.map((_, index) => { const pluginName = currentSource?.instance?.pluginImpls?.[index]?.name if (!pluginName) { diff --git a/packages/use-request/src/types.ts b/packages/use-request/src/types.ts index 26790740..12849499 100644 --- a/packages/use-request/src/types.ts +++ b/packages/use-request/src/types.ts @@ -52,11 +52,11 @@ export type UseRequestMiddleware = ( useRequestNext: RequestHook ) => RequestHook -export interface UseRequestBasicOptions { +export type UseRequestBasicOptions = { /** * Init data. */ - initialData?: TData + // initialData?: TData /** * - The default is `false.` That is, the service is automatically executed during initialization. @@ -128,7 +128,7 @@ export interface UseRequestBasicOptions { * @param data TData * @returns unknown need cover TData */ - formatResult?: (data?: TData) => unknown + // formatResult?: (data?: TData) => any /** * Polling interval, in milliseconds. If the value is greater than 0, the polling mode is activated. @@ -246,14 +246,24 @@ export interface UseRequestBasicOptions { * Middleware */ use?: UseRequestMiddleware[] + + rollbackOnError?: boolean | ((params: TParams) => boolean) +} + +export type UseRequestOptions = UseRequestBasicOptions & +{ + pluginOptions?: TPlugin +} + +export type UseRequestOptionsWithFormatResult< + TData, + TParams extends any[] = any[], + TPlugin = any, + SR = any, +> = UseRequestOptions & { + formatResult: (res: SR) => TData; } -export type UseRequestOptions = { - [K in keyof UseRequestBasicOptions]: UseRequestBasicOptions[K] -} & - { - [K in keyof TPlugin]: TPlugin[K] - } export interface UseRequestPlugin { ( diff --git a/packages/use-request/src/useRequest.ts b/packages/use-request/src/useRequest.ts index 8fb62bc2..b7dc83ff 100644 --- a/packages/use-request/src/useRequest.ts +++ b/packages/use-request/src/useRequest.ts @@ -10,24 +10,45 @@ import useThrottlePlugin from './plugins/useThrottlePlugin' import useRequestImplement from './useRequestImplement' -import { UseRequestOptions, UseRequestPlugin, UseRequestService } from './types' +import { UseRequestOptions, UseRequestOptionsWithFormatResult, UseRequestPlugin, useRequestResult, UseRequestService } from './types' import { withArgs } from './utils/resolve-args' -function useRequest< + +// 有 formatResult +export function useRequest< + TData, + TParams extends unknown[] = unknown[], + PluginsOptions extends UseRequestPlugin[] = UseRequestPlugin[], + SR = any, +>(service: UseRequestService, options?: UseRequestOptionsWithFormatResult + ? R + : never + : never, SR>, plugins?: PluginsOptions): useRequestResult + + +// 无 formatResults +export function useRequest< TData, TParams extends unknown[] = unknown[], - PluginsOptions extends UseRequestPlugin[] = UseRequestPlugin[] + PluginsOptions extends UseRequestPlugin[] = UseRequestPlugin[], +>(service: UseRequestService, options?: UseRequestOptions + ? R + : never + : never>, plugins?: PluginsOptions): useRequestResult + +export function useRequest< + TData, + TParams extends unknown[] = unknown[], + PluginsOptions extends UseRequestPlugin[] = UseRequestPlugin[], >( service: UseRequestService, - options?: UseRequestOptions< - TData, - TParams, - PluginsOptions extends (infer P)[] + options?: UseRequestOptions ? R : never - : never - >, + : never>, plugins?: PluginsOptions, ) { @@ -49,4 +70,6 @@ function useRequest< ] as UseRequestPlugin[]) } + + export default useRequest diff --git a/packages/use-request/src/useRequestImplement.ts b/packages/use-request/src/useRequestImplement.ts index 3dd60691..901ea6f3 100644 --- a/packages/use-request/src/useRequestImplement.ts +++ b/packages/use-request/src/useRequestImplement.ts @@ -18,7 +18,7 @@ function isUseRequestFetchState( function useRequestImplement( service: UseRequestService, - options: UseRequestOptions = {}, + options: UseRequestOptions = {}, plugins: UseRequestPlugin[] = [], ) { // global option diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 73c1a794..de4f8da3 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -20,10 +20,10 @@ importers: '@vitest/ui': ^0.25.3 '@vue-hooks-plus/eslint-config': workspace:^1.0.0 '@vue-hooks-plus/md-demo-plugins': ^1.0.0 - '@vue-hooks-plus/types': workspace:^1.0.0 + '@vue-hooks-plus/types': workspace:^2.0.0 '@vue-hooks-plus/use-immer': workspace:^1.0.0 - '@vue-hooks-plus/use-request': workspace:^1.0.0 - '@vue-hooks-plus/use-request-plugins': workspace:^1.0.0 + '@vue-hooks-plus/use-request': workspace:^2.0.0 + '@vue-hooks-plus/use-request-plugins': workspace:^2.0.0 '@vue-hooks-plus/use-worker': workspace:^1.0.0 '@vue-hooks-plus/vite-plugin-gen-temp': ^2.6.6 '@vue-hooks-plus/vitepress': ^1.2.4 @@ -195,7 +195,7 @@ importers: specifiers: '@vue-hooks-plus/use-request': ^1.3.2 devDependencies: - '@vue-hooks-plus/use-request': link:../use-request + '@vue-hooks-plus/use-request': 1.6.2 packages/use-worker: specifiers: @@ -1887,6 +1887,13 @@ packages: - stylus dev: true + /@vue-hooks-plus/use-request/1.6.2: + resolution: {integrity: sha512-LDkfuDMSsETLcB2cBUUmitOX+IfDsdjgK7Q1J1R9Md9eZpfaj/WMP3VqUuY5urcwfILOWMUEakih7wc/7uvzGg==} + dependencies: + '@vue/devtools-api': 6.5.0 + lodash: 4.17.21 + dev: true + /@vue-hooks-plus/vite-plugin-gen-temp/2.6.6_6dxxgtbrz56s2zkljf2kg4oim4: resolution: {integrity: sha512-3fvLDq4TDMmHj6ZzeAie8Gw75U2KSE2V/lVy3aAeuxRtAqCQfigXNTIz6sPSfrJZrOARe4sxVok3qbWjP3m9vw==} hasBin: true