From 4c0516d380e912cc9de606544e11c5a15641b77c Mon Sep 17 00:00:00 2001 From: JounQin Date: Tue, 11 Apr 2023 23:06:35 +0800 Subject: [PATCH 1/3] feat: better interceptor implementation --- package.json | 2 +- packages/@react-enhanced/hooks/src/api.ts | 257 ++++-------------- .../@react-enhanced/hooks/test/api.spec.ts | 10 +- 3 files changed, 54 insertions(+), 215 deletions(-) diff --git a/package.json b/package.json index 545ee945..b72cd97e 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ "packages/*", "packages/@react-enhanced/*" ], - "packageManager": "pnpm@8.1.1", + "packageManager": "pnpm@8.2.0", "scripts": { "build": "run-p build:*", "build:r": "r -f cjs --esbuild {jsxFactory:'React.createElement'}", diff --git a/packages/@react-enhanced/hooks/src/api.ts b/packages/@react-enhanced/hooks/src/api.ts index f4234c96..cbd2b95b 100644 --- a/packages/@react-enhanced/hooks/src/api.ts +++ b/packages/@react-enhanced/hooks/src/api.ts @@ -1,4 +1,4 @@ -import { ApiMethod, NO_CONTENT } from '@react-enhanced/shared' +import { ApiMethod } from '@react-enhanced/shared' import type { Nilable, URLSearchParamsOptions } from '@react-enhanced/types' import { CONTENT_TYPE, @@ -8,7 +8,7 @@ import { import { isPlainObject } from 'lodash' import { useCallback, useState } from 'react' import type { Observable } from 'rxjs' -import { NEVER, catchError, from, of, switchMap, tap, throwError } from 'rxjs' +import { NEVER, from, of, switchMap, tap } from 'rxjs' import { fromFetch } from 'rxjs/fetch' import { useEnhancedEffect } from './lifecycle.js' @@ -19,23 +19,15 @@ export interface FetchApiOptions extends Omit { query?: URLSearchParamsOptions json?: boolean type?: 'arrayBuffer' | 'blob' | 'json' | 'text' | null - mock?: boolean } export interface InterceptorRequest extends FetchApiOptions { url: string } -export type RequestInterceptor = ( +export type ApiInterceptor = ( request: InterceptorRequest, -) => - | InterceptorRequest - | Observable - | PromiseLike - -export type ResponseInterceptor = ( - request: InterceptorRequest, - response: Response, + next: (request: InterceptorRequest) => Observable, ) => Observable | PromiseLike | Response export type ResponseError = T & { @@ -43,29 +35,29 @@ export type ResponseError = T & { response?: Response | null } -export type ErrorInterceptor = ( - request: InterceptorRequest, - error: ResponseError, -) => Observable | PromiseLike | Response +export class ApiInterceptors { + readonly #interceptors: ApiInterceptor[] = [] -export interface ApiInterceptors { - request: { - end(): ApiInterceptors - use(interceptor: RequestInterceptor): ApiInterceptors['request'] - eject(interceptor: RequestInterceptor): boolean + get length() { + return this.#interceptors.length } - response: { - end(): ApiInterceptors - use(interceptor: ResponseInterceptor): ApiInterceptors['response'] - use( - responseInterceptor: ResponseInterceptor | null, - errorInterceptor: ErrorInterceptor, - ): ApiInterceptors['response'] - eject(interceptor: ResponseInterceptor): boolean - eject( - responseInterceptor: ResponseInterceptor | null, - errorInterceptor: ErrorInterceptor, - ): boolean + + at(index: number): ApiInterceptor | undefined { + return this.#interceptors.at(index) + } + + use(...interceptors: ApiInterceptor[]): ApiInterceptors { + this.#interceptors.push(...interceptors) + return this + } + + eject(interceptor: ApiInterceptor): boolean { + const index = this.#interceptors.indexOf(interceptor) + if (index > -1) { + this.#interceptors.splice(index, 1) + return true + } + return false } } @@ -90,151 +82,8 @@ export interface UseApiOptions extends FetchApiOptions { url?: string } -const createInterceptors = () => { - const requestInterceptors = new Set() - const responseInterceptors = new Set() - const errorInterceptors = new Set() - - const interceptors: ApiInterceptors = { - request: { - end() { - return interceptors - }, - use(interceptor: RequestInterceptor) { - requestInterceptors.add(interceptor) - return interceptors.request - }, - eject(interceptor: RequestInterceptor) { - return requestInterceptors.delete(interceptor) - }, - }, - response: { - end() { - return interceptors - }, - use( - responseInterceptor: ResponseInterceptor | null, - errorInterceptor?: ErrorInterceptor, - ) { - if (responseInterceptor) { - responseInterceptors.add(responseInterceptor) - } - - if (errorInterceptor) { - errorInterceptors.add(errorInterceptor) - } - - return interceptors.response - }, - eject( - responseInterceptor: ResponseInterceptor | null, - errorInterceptor?: ErrorInterceptor, - ) { - if (!responseInterceptor && !errorInterceptor) { - return false - } - const resIcDeleted = - !responseInterceptor || - responseInterceptors.delete(responseInterceptor) - const errIcDeleted = - !errorInterceptor || errorInterceptors.delete(errorInterceptor) - return resIcDeleted && errIcDeleted - }, - }, - } - - return { - interceptors, - requestInterceptors, - responseInterceptors, - errorInterceptors, - } -} - -const invokeRequestInterceptors = ( - requestInterceptors: Set, - req: InterceptorRequest, -) => - [...requestInterceptors].reduce( - (acc, interceptor) => - acc.pipe( - switchMap(req => { - const next = interceptor(req) - return isObservableLike(next) ? next : of(next) - }), - ), - of(req), - ) - -const invokeResponseInterceptors = ( - responseInterceptors: Set, - req: InterceptorRequest, - res: Response, - type: FetchApiOptions['type'], -) => - [...responseInterceptors] - .reduce( - (acc, interceptor) => - acc.pipe( - switchMap(res => { - const next = interceptor(req, res) - return isObservableLike(next) ? next : of(next) - }), - ), - of(res), - ) - .pipe( - switchMap(res => - from( - res.status === NO_CONTENT - ? of(null) - : type == null - ? of(res) - : (res.clone()[type]() as Promise), - ).pipe( - catchError((err: Error) => - throwError(() => - Object.assign(new Error(err.message), { response: res }), - ), - ), - switchMap(data => { - if (res.ok) { - return of(data) - } - return throwError(() => - Object.assign(new Error(res.statusText), { - data, - response: res, - }), - ) - }), - ), - ), - ) - -const invokeErrorInterceptors = ( - errorInterceptors: Set, - req: InterceptorRequest, - err: ResponseError, -) => - [...errorInterceptors].reduce>( - (acc, interceptor) => - acc.pipe( - catchError((err: ResponseError) => { - const next = interceptor(req, err) - return isObservableLike(next) ? next : of(next) - }), - ), - throwError(() => err), - ) - export function createApi() { - const { - interceptors, - requestInterceptors, - responseInterceptors, - errorInterceptors, - } = createInterceptors() + const interceptors = new ApiInterceptors() function fetchApi( url: string, @@ -273,44 +122,34 @@ export function createApi() { headers.append(CONTENT_TYPE, 'application/json') } - const req: InterceptorRequest = { + let index = 0 + + const next = (req: InterceptorRequest) => { + if (index < interceptors.length) { + const res = interceptors.at(index++)!(req, next) + return isObservableLike(res) ? from(res) : of(res) + } + const { body, url, query, ...rest } = req + return fromFetch(normalizeUrl(url, query), { + ...rest, + body: json ? JSON.stringify(body) : (body as BodyInit), + selector: res => of(res), + }) + } + + return next({ url, method, body, headers, ...rest, - } - - return invokeRequestInterceptors(requestInterceptors, req).pipe( - switchMap(req => { - const { body, url, query, ...rest } = req - return fromFetch(normalizeUrl(url, query), { - ...rest, - body: json ? JSON.stringify(body) : (body as BodyInit), - selector: res => of(res), - }).pipe( - catchError((err: api.Error) => - invokeErrorInterceptors(errorInterceptors, req, err), - ), - switchMap(res => - invokeResponseInterceptors(responseInterceptors, req, res, type), - ), - ) + }).pipe( + switchMap(res => { + if (type == null) { + return of(res) + } + return res[type]() as Promise }), - catchError((err: ResponseError) => - invokeErrorInterceptors(errorInterceptors, req, err).pipe( - switchMap(res => { - if (type == null) { - return of(res) - } - return from(res.clone()[type]() as Promise).pipe( - catchError((err: Error) => - throwError(() => Object.assign(err, { response: res })), - ), - ) - }), - ), - ), ) } diff --git a/packages/@react-enhanced/hooks/test/api.spec.ts b/packages/@react-enhanced/hooks/test/api.spec.ts index 593ef7d2..bc03b277 100644 --- a/packages/@react-enhanced/hooks/test/api.spec.ts +++ b/packages/@react-enhanced/hooks/test/api.spec.ts @@ -2,22 +2,22 @@ import { sleep } from '@react-enhanced/shared' import { renderHook } from '@testing-library/react' import { fetch } from 'undici' -import { RequestInterceptor, interceptors, useApi } from '@react-enhanced/hooks' +import { ApiInterceptor, interceptors, useApi } from '@react-enhanced/hooks' -const requestInterceptor: RequestInterceptor = req => { +const apiInterceptor: ApiInterceptor = (req, next) => { if (!/^https?:\/\//.test(req.url)) { req.url = 'https://api.github.com/' + req.url } - return req + return next(req) } // @ts-expect-error globalThis.fetch = fetch -interceptors.request.use(requestInterceptor) +interceptors.use(apiInterceptor) afterAll(() => { - interceptors.request.eject(requestInterceptor) + interceptors.eject(apiInterceptor) }) it('should work as expected', async () => { From 54c565622e09e0aa008b0a5a1713dc88f8bfbeaa Mon Sep 17 00:00:00 2001 From: JounQin Date: Thu, 13 Apr 2023 22:50:04 +0800 Subject: [PATCH 2/3] test: use jsdom instead --- package.json | 2 +- .../@react-enhanced/hooks/test/api.spec.ts | 6 +- pnpm-lock.yaml | 302 ++++++++++++++++-- vitest.config.ts | 3 +- 4 files changed, 282 insertions(+), 31 deletions(-) diff --git a/package.json b/package.json index b72cd97e..75fe67a0 100644 --- a/package.json +++ b/package.json @@ -61,7 +61,7 @@ "@vitest/coverage-istanbul": "^0.30.0", "classnames": "^2.3.2", "github-markdown-css": "^5.2.0", - "happy-dom": "^9.1.9", + "jsdom": "^21.1.1", "lodash": "^4.17.21", "lodash-es": "^4.17.21", "prism-react-renderer": "^1.3.5", diff --git a/packages/@react-enhanced/hooks/test/api.spec.ts b/packages/@react-enhanced/hooks/test/api.spec.ts index bc03b277..a0bc133e 100644 --- a/packages/@react-enhanced/hooks/test/api.spec.ts +++ b/packages/@react-enhanced/hooks/test/api.spec.ts @@ -7,6 +7,10 @@ import { ApiInterceptor, interceptors, useApi } from '@react-enhanced/hooks' const apiInterceptor: ApiInterceptor = (req, next) => { if (!/^https?:\/\//.test(req.url)) { req.url = 'https://api.github.com/' + req.url + req.headers = { + ...req.headers, + Authorization: `Bearer ${process.env.GITHUB_TOKEN!}`, + } } return next(req) } @@ -24,7 +28,7 @@ it('should work as expected', async () => { const { result } = renderHook(() => useApi('rate_limit')) expect(result.current.data).toBeUndefined() expect(result.current.loading).toBe(true) - await sleep(1000) + await sleep(2 * 1000) expect(result.current.data).toBeTruthy() expect(result.current.loading).toBe(false) }) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e8e839c3..1018dfb0 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -82,9 +82,9 @@ importers: github-markdown-css: specifier: ^5.2.0 version: 5.2.0 - happy-dom: - specifier: ^9.1.9 - version: 9.1.9 + jsdom: + specifier: ^21.1.1 + version: 21.1.1 lodash: specifier: ^4.17.21 version: 4.17.21 @@ -165,7 +165,7 @@ importers: version: 4.2.1(@types/node@18.15.11)(sass@1.61.0) vitest: specifier: ^0.30.0 - version: 0.30.0(happy-dom@9.1.9)(sass@1.61.0) + version: 0.30.0(jsdom@21.1.1)(sass@1.61.0) packages/@react-enhanced/eslint-plugin: dependencies: @@ -3948,6 +3948,11 @@ packages: chevrotain: 4.1.1 dev: true + /@tootallnate/once@2.0.0: + resolution: {integrity: sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==} + engines: {node: '>= 10'} + dev: true + /@trysound/sax@0.2.0: resolution: {integrity: sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==} engines: {node: '>=10.13.0'} @@ -4407,7 +4412,7 @@ packages: istanbul-lib-source-maps: 4.0.1 istanbul-reports: 3.1.5 test-exclude: 6.0.0 - vitest: 0.30.0(happy-dom@9.1.9)(sass@1.61.0) + vitest: 0.30.0(jsdom@21.1.1)(sass@1.61.0) transitivePeerDependencies: - supports-color dev: true @@ -4637,11 +4642,22 @@ packages: through: 2.3.8 dev: true + /abab@2.0.6: + resolution: {integrity: sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==} + dev: true + /abbrev@2.0.0: resolution: {integrity: sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} dev: true + /acorn-globals@7.0.1: + resolution: {integrity: sha512-umOSDSDrfHbTNPuNpC2NSnnA3LUrqpevPb4T9jRx4MagXNS0rs+gwiTcAvqCRmsD6utzsrzNt+ebm00SNWiC3Q==} + dependencies: + acorn: 8.8.2 + acorn-walk: 8.2.0 + dev: true + /acorn-jsx@5.3.2(acorn@8.8.2): resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} peerDependencies: @@ -4665,6 +4681,15 @@ packages: engines: {node: '>=0.4.0'} hasBin: true + /agent-base@6.0.2: + resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} + engines: {node: '>= 6.0.0'} + dependencies: + debug: 4.3.4 + transitivePeerDependencies: + - supports-color + dev: true + /aggregate-error@3.1.0: resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==} engines: {node: '>=8'} @@ -4903,6 +4928,10 @@ packages: hasBin: true dev: true + /asynckit@0.4.0: + resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + dev: true + /atob@2.1.2: resolution: {integrity: sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==} engines: {node: '>= 4.5.0'} @@ -5555,6 +5584,13 @@ packages: resolution: {integrity: sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ==} dev: true + /combined-stream@1.0.8: + resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} + engines: {node: '>= 0.8'} + dependencies: + delayed-stream: 1.0.0 + dev: true + /comma-separated-tokens@2.0.3: resolution: {integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==} dev: true @@ -5865,10 +5901,6 @@ packages: engines: {node: '>= 6'} dev: true - /css.escape@1.5.1: - resolution: {integrity: sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==} - dev: true - /css@3.0.0: resolution: {integrity: sha512-DG9pFfwOrzc+hawpmqX/dHYHJG+Bsdb0klhyi1sDneOgGOXy9wQIC8hzyVp1e4NRYDBdxcylvywPkkXCHAzTyQ==} dependencies: @@ -5974,6 +6006,13 @@ packages: css-tree: 2.2.1 dev: true + /cssstyle@3.0.0: + resolution: {integrity: sha512-N4u2ABATi3Qplzf0hWbVCdjenim8F3ojEXpBDF5hBpjzW182MjNGLqfmQ0SkSPeQ+V86ZXgeH8aXj6kayd4jgg==} + engines: {node: '>=14'} + dependencies: + rrweb-cssom: 0.6.0 + dev: true + /csstype@3.1.2: resolution: {integrity: sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==} dev: true @@ -6033,6 +6072,15 @@ packages: engines: {node: '>=8'} dev: true + /data-urls@4.0.0: + resolution: {integrity: sha512-/mMTei/JXPqvFqQtfyTowxmJVwr2PVAeCcDxyFf6LhoOu/09TX2OX3kb2wzi4DMXcfj4OItwDOnhl5oziPnT6g==} + engines: {node: '>=14'} + dependencies: + abab: 2.0.6 + whatwg-mimetype: 3.0.0 + whatwg-url: 12.0.1 + dev: true + /dataloader@1.4.0: resolution: {integrity: sha512-68s5jYdlvasItOJnCuI2Q9s4q98g0pCyL3HrcKJu8KNugUl8ahgmZYg38ysLTgQjjXX3H8CJLkAvWrclWfcalw==} dev: true @@ -6078,6 +6126,10 @@ packages: resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==} engines: {node: '>=0.10.0'} + /decimal.js@10.4.3: + resolution: {integrity: sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==} + dev: true + /decode-named-character-reference@1.0.2: resolution: {integrity: sha512-O8x12RzrUF8xyVcY0KJowWsmaJxQbmy0/EtnNtHRpsOcT7dFk5W598coHqBVpmWo1oQQfsCqfCmkZN5DJrZVdg==} dependencies: @@ -6205,6 +6257,11 @@ packages: object-keys: 1.1.1 dev: true + /delayed-stream@1.0.0: + resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} + engines: {node: '>=0.4.0'} + dev: true + /dequal@2.0.3: resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} engines: {node: '>=6'} @@ -6304,6 +6361,13 @@ packages: resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==} dev: true + /domexception@4.0.0: + resolution: {integrity: sha512-A2is4PLG+eeSfoTMA95/s4pvAoSo2mKtiM5jlHkAVewmiO8ISFTFKZjH7UAM1Atli/OT/7JHOrJRJiMKUZKYBw==} + engines: {node: '>=12'} + dependencies: + webidl-conversions: 7.0.0 + dev: true + /domhandler@4.3.1: resolution: {integrity: sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==} engines: {node: '>= 4'} @@ -6619,6 +6683,19 @@ packages: engines: {node: '>=12'} dev: true + /escodegen@2.0.0: + resolution: {integrity: sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw==} + engines: {node: '>=6.0'} + hasBin: true + dependencies: + esprima: 4.0.1 + estraverse: 5.3.0 + esutils: 2.0.3 + optionator: 0.8.3 + optionalDependencies: + source-map: 0.6.1 + dev: true + /eslint-config-prettier@8.8.0(eslint@8.37.0): resolution: {integrity: sha512-wLbQiFre3tdGgpDv67NQKnJuTlcUVYHas3k+DZCc2U2BadthoEY4B7hLPvAxaqdyOGCzuLfii2fqGph10va7oA==} hasBin: true @@ -7710,6 +7787,15 @@ packages: is-callable: 1.2.7 dev: true + /form-data@4.0.0: + resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==} + engines: {node: '>= 6'} + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + mime-types: 2.1.35 + dev: true + /format@0.2.2: resolution: {integrity: sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww==} engines: {node: '>=0.4.x'} @@ -8148,17 +8234,6 @@ packages: /grapheme-splitter@1.0.4: resolution: {integrity: sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==} - /happy-dom@9.1.9: - resolution: {integrity: sha512-OMbnoknA7iNNG/5fwt1JckCKc53QLLFo2ljzit1pCV9SC1TYwcQj0obq0QUTeqIf2p2skbFG69bo19YoSj/1DA==} - dependencies: - css.escape: 1.5.1 - he: 1.2.0 - iconv-lite: 0.6.3 - webidl-conversions: 7.0.0 - whatwg-encoding: 2.0.0 - whatwg-mimetype: 3.0.0 - dev: true - /hard-rejection@2.1.0: resolution: {integrity: sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==} engines: {node: '>=6'} @@ -8259,11 +8334,6 @@ packages: resolution: {integrity: sha512-nAxA0v8+vXSBDt3AnRUNjyRIQ0rD+ntpbAp4LnPkumc5M9yUbSMa4XDU9Q6etY4f1Wp4bNgvc1yjiZtsTTrSng==} dev: true - /he@1.2.0: - resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} - hasBin: true - dev: true - /hoist-non-react-statics@3.3.2: resolution: {integrity: sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==} dependencies: @@ -8295,6 +8365,13 @@ packages: lru-cache: 7.18.3 dev: true + /html-encoding-sniffer@3.0.0: + resolution: {integrity: sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==} + engines: {node: '>=12'} + dependencies: + whatwg-encoding: 2.0.0 + dev: true + /html-entities@2.3.3: resolution: {integrity: sha512-DV5Ln36z34NNTDgnz0EWGBLZENelNAtkiFA4kyNOG2tDI6Mz1uSWiq1wAKdyjnJwyDiDO7Fa2SO1CTxPXL8VxA==} dev: true @@ -8326,6 +8403,27 @@ packages: resolution: {integrity: sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w==} dev: true + /http-proxy-agent@5.0.0: + resolution: {integrity: sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==} + engines: {node: '>= 6'} + dependencies: + '@tootallnate/once': 2.0.0 + agent-base: 6.0.2 + debug: 4.3.4 + transitivePeerDependencies: + - supports-color + dev: true + + /https-proxy-agent@5.0.1: + resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} + engines: {node: '>= 6'} + dependencies: + agent-base: 6.0.2 + debug: 4.3.4 + transitivePeerDependencies: + - supports-color + dev: true + /human-id@1.0.2: resolution: {integrity: sha512-UNopramDEhHJD+VR+ehk8rOslwSfByxPIZyJRfV739NDhN5LF1fa1MqnzKm2lGTQRjNrjK19Q5fhkgIfjlVUKw==} dev: true @@ -8807,6 +8905,10 @@ packages: engines: {node: '>=12'} dev: true + /is-potential-custom-element-name@1.0.1: + resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==} + dev: true + /is-promise@2.2.2: resolution: {integrity: sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==} dev: true @@ -9065,6 +9167,47 @@ packages: hasBin: true dev: true + /jsdom@21.1.1: + resolution: {integrity: sha512-Jjgdmw48RKcdAIQyUD1UdBh2ecH7VqwaXPN3ehoZN6MqgVbMn+lRm1aAT1AsdJRAJpwfa4IpwgzySn61h2qu3w==} + engines: {node: '>=14'} + peerDependencies: + canvas: ^2.5.0 + peerDependenciesMeta: + canvas: + optional: true + dependencies: + abab: 2.0.6 + acorn: 8.8.2 + acorn-globals: 7.0.1 + cssstyle: 3.0.0 + data-urls: 4.0.0 + decimal.js: 10.4.3 + domexception: 4.0.0 + escodegen: 2.0.0 + form-data: 4.0.0 + html-encoding-sniffer: 3.0.0 + http-proxy-agent: 5.0.0 + https-proxy-agent: 5.0.1 + is-potential-custom-element-name: 1.0.1 + nwsapi: 2.2.4 + parse5: 7.1.2 + rrweb-cssom: 0.6.0 + saxes: 6.0.0 + symbol-tree: 3.2.4 + tough-cookie: 4.1.2 + w3c-xmlserializer: 4.0.0 + webidl-conversions: 7.0.0 + whatwg-encoding: 2.0.0 + whatwg-mimetype: 3.0.0 + whatwg-url: 12.0.1 + ws: 8.13.0 + xml-name-validator: 4.0.0 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + dev: true + /jsesc@0.5.0: resolution: {integrity: sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==} hasBin: true @@ -10370,6 +10513,13 @@ packages: engines: {node: '>= 0.6'} dev: true + /mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + dependencies: + mime-db: 1.52.0 + dev: true + /mime@2.5.2: resolution: {integrity: sha512-tqkh47FzKeCPD2PUiPB6pkbMzsCasjxAfC62/Wap5qrUWcb+sFasXUC5I3gYM5iBM8v/Qpn4UK0x+j0iHyFPDg==} engines: {node: '>=4.0.0'} @@ -10681,6 +10831,10 @@ packages: boolbase: 1.0.0 dev: true + /nwsapi@2.2.4: + resolution: {integrity: sha512-NHj4rzRo0tQdijE9ZqAx6kYDcoRwYwSYzCA8MY3JzfxlrvEU0jhnhJT9BhqhJs7I/dKcrDm6TyulaRqZPIhN5g==} + dev: true + /object-assign@4.1.1: resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} engines: {node: '>=0.10.0'} @@ -11047,6 +11201,12 @@ packages: resolution: {integrity: sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==} dev: true + /parse5@7.1.2: + resolution: {integrity: sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==} + dependencies: + entities: 4.4.0 + dev: true + /path-exists@2.1.0: resolution: {integrity: sha512-yTltuKuhtNeFJKa1PiRzfLAU5182q1y4Eb4XCJ3PBqyzEDkAZRzBrKKBct682ls9reBVHf9udYLN5Nd+K1B9BQ==} engines: {node: '>=0.10.0'} @@ -12277,6 +12437,10 @@ packages: resolution: {integrity: sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==} dev: true + /psl@1.9.0: + resolution: {integrity: sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==} + dev: true + /pug-error@2.0.0: resolution: {integrity: sha512-sjiUsi9M4RAGHktC1drQfCr5C5eriu24Lfbt4s+7SykztEOwVZtbFk1RRq0tzLxcMxMYTBR+zMQaG07J/btayQ==} dev: true @@ -12327,6 +12491,10 @@ packages: strict-uri-encode: 1.1.0 dev: true + /querystringify@2.2.0: + resolution: {integrity: sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==} + dev: true + /queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} @@ -13411,6 +13579,10 @@ packages: /require-main-filename@2.0.0: resolution: {integrity: sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==} + /requires-port@1.0.0: + resolution: {integrity: sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==} + dev: true + /resolve-dir@1.0.1: resolution: {integrity: sha512-R7uiTjECzvOsWSfdM0QKFNBVFcK27aHOUwdvK53BcW8zqnGdYp0Fbj82cy54+2A4P2tFM22J5kRfe1R+lM/1yg==} engines: {node: '>=0.10.0'} @@ -13576,6 +13748,10 @@ packages: fsevents: 2.3.2 dev: true + /rrweb-cssom@0.6.0: + resolution: {integrity: sha512-APM0Gt1KoXBz0iIkkdB/kfvGOwC4UuJFeG/c+yV7wSc7q96cG/kJ0HiYCnzivD9SB53cLV1MlHFNfOuPaadYSw==} + dev: true + /run-parallel@1.2.0: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} dependencies: @@ -13637,6 +13813,13 @@ packages: resolution: {integrity: sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==} dev: true + /saxes@6.0.0: + resolution: {integrity: sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==} + engines: {node: '>=v12.22.7'} + dependencies: + xmlchars: 2.2.0 + dev: true + /scheduler@0.23.0: resolution: {integrity: sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==} dependencies: @@ -14490,6 +14673,10 @@ packages: picocolors: 1.0.0 dev: true + /symbol-tree@3.2.4: + resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==} + dev: true + /synckit@0.8.5: resolution: {integrity: sha512-L1dapNV6vu2s/4Sputv8xGsCdAVlb5nRDMFU/E27D44l5U6cw1g0dGd45uLc+OXjNMmF4ntiMdCimzcjFKQI8Q==} engines: {node: ^14.18.0 || >=16.0.0} @@ -14673,10 +14860,27 @@ packages: eslint-visitor-keys: 3.4.0 dev: true + /tough-cookie@4.1.2: + resolution: {integrity: sha512-G9fqXWoYFZgTc2z8Q5zaHy/vJMjm+WV0AkAeHxVCQiEB1b+dGvWzFW6QV07cY5jQ5gRkeid2qIkzkxUnmoQZUQ==} + engines: {node: '>=6'} + dependencies: + psl: 1.9.0 + punycode: 2.3.0 + universalify: 0.2.0 + url-parse: 1.5.10 + dev: true + /tr46@0.0.3: resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} dev: true + /tr46@4.1.1: + resolution: {integrity: sha512-2lv/66T7e5yNyhAAC4NaKe5nVavzuGJQVVtRYLyQ2OI8tsJ61PMLlelehb0wi2Hx6+hT/OJUWZcw8MjlSRnxvw==} + engines: {node: '>=14'} + dependencies: + punycode: 2.3.0 + dev: true + /trim-lines@3.0.1: resolution: {integrity: sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==} dev: true @@ -15104,6 +15308,11 @@ packages: engines: {node: '>= 4.0.0'} dev: true + /universalify@0.2.0: + resolution: {integrity: sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==} + engines: {node: '>= 4.0.0'} + dev: true + /universalify@2.0.0: resolution: {integrity: sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==} engines: {node: '>= 10.0.0'} @@ -15171,6 +15380,13 @@ packages: prepend-http: 2.0.0 dev: true + /url-parse@1.5.10: + resolution: {integrity: sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==} + dependencies: + querystringify: 2.2.0 + requires-port: 1.0.0 + dev: true + /url-to-options@1.0.1: resolution: {integrity: sha512-0kQLIzG4fdk/G5NONku64rSH/x32NOA39LVQqlK8Le6lvTF6GGRJpqaQFGgU+CLwySIqBSMdwYM0sYcW9f6P4A==} engines: {node: '>= 4'} @@ -15323,7 +15539,7 @@ packages: fsevents: 2.3.2 dev: true - /vitest@0.30.0(happy-dom@9.1.9)(sass@1.61.0): + /vitest@0.30.0(jsdom@21.1.1)(sass@1.61.0): resolution: {integrity: sha512-2WW4WeTHtrLFeoiuotWvEW6khozx1NvMGYoGsNz2btdddEbqvEdPJIouIdoiC5i61Rl1ctZvm9cn2R9TcPQlzw==} engines: {node: '>=v14.18.0'} hasBin: true @@ -15368,7 +15584,7 @@ packages: chai: 4.3.7 concordance: 5.0.4 debug: 4.3.4 - happy-dom: 9.1.9 + jsdom: 21.1.1 local-pkg: 0.4.3 magic-string: 0.30.0 pathe: 1.1.0 @@ -15426,6 +15642,13 @@ packages: - supports-color dev: true + /w3c-xmlserializer@4.0.0: + resolution: {integrity: sha512-d+BFHzbiCx6zGfz0HyQ6Rg69w9k19nviJspaj4yNscGjrHu94sVP+aRm75yEbCh+r2/yR+7q6hux9LVtbuTGBw==} + engines: {node: '>=14'} + dependencies: + xml-name-validator: 4.0.0 + dev: true + /walk-up-path@1.0.0: resolution: {integrity: sha512-hwj/qMDUEjCU5h0xr90KGCf0tg0/LgJbmOWgrWKYlcJZM7XvquvUJZ0G/HMGr7F7OQMOUuPHWP9JpriinkAlkg==} dev: true @@ -15475,6 +15698,14 @@ packages: engines: {node: '>=12'} dev: true + /whatwg-url@12.0.1: + resolution: {integrity: sha512-Ed/LrqB8EPlGxjS+TrsXcpUond1mhccS3pchLhzSgPCnTimUCKj3IZE75pAs5m6heB2U2TMerKFUXheyHY+VDQ==} + engines: {node: '>=14'} + dependencies: + tr46: 4.1.1 + webidl-conversions: 7.0.0 + dev: true + /whatwg-url@5.0.0: resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} dependencies: @@ -15579,11 +15810,28 @@ packages: signal-exit: 3.0.7 dev: true + /ws@8.13.0: + resolution: {integrity: sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: '>=5.0.2' + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + dev: true + /xml-name-validator@4.0.0: resolution: {integrity: sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==} engines: {node: '>=12'} dev: true + /xmlchars@2.2.0: + resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==} + dev: true + /xtend@4.0.2: resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} engines: {node: '>=0.4'} diff --git a/vitest.config.ts b/vitest.config.ts index 2de2f5e0..cbbaea49 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -5,11 +5,10 @@ export default defineConfig({ plugins: [ autoImport({ imports: ['vitest'], - dts: true, }), ], test: { - environment: 'happy-dom', + environment: 'jsdom', coverage: { provider: 'istanbul', reporter: ['lcov', 'json'], From 016f17ecfe4508d7c339d2284394969de4fc2235 Mon Sep 17 00:00:00 2001 From: JounQin Date: Thu, 13 Apr 2023 22:56:31 +0800 Subject: [PATCH 3/3] Create .changeset/little-hornets-sparkle.md --- .changeset/little-hornets-sparkle.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/little-hornets-sparkle.md diff --git a/.changeset/little-hornets-sparkle.md b/.changeset/little-hornets-sparkle.md new file mode 100644 index 00000000..9090dbc8 --- /dev/null +++ b/.changeset/little-hornets-sparkle.md @@ -0,0 +1,5 @@ +--- +"@react-enhanced/hooks": minor +--- + +feat: better interceptor implementation