diff --git a/README.md b/README.md index 939311f..ce28178 100644 --- a/README.md +++ b/README.md @@ -339,18 +339,18 @@ try { - Use the [parseRejected][api-reference] option to throw a custom error instead. - Use the [reject][api-reference] option to decide **when** to throw. -#### 👉 ValidationError +#### 👉 ResponseValidationError Raised when schema validation fails. \ -Use `isValidationError` to identify this error type. +Use `isResponseValidationError` to identify this error type. ```ts -import { isValidationError } from 'up-fetch' +import { isResponseValidationError } from 'up-fetch' try { await upfetch('/todos/1', { schema: todoSchema }) } catch (error) { - if (isValidationError(error)) { + if (isResponseValidationError(error)) { console.log(error.issues) } } @@ -553,7 +553,7 @@ const upfetch = up(fetch, () => ({ // custom error message const message = `Request failed with status ${status}: ${JSON.stringify(data)}` // you can return a custom error class as well - return new ResponseError({ message, data, request, response }) + return new ResponseError({ message, status, data }) }, })) ``` @@ -725,9 +725,9 @@ Options: Checks if the error is a `ResponseError`. -### isValidationError(error) +### isResponseValidationError(error) -Checks if the error is a `ValidationError`. +Checks if the error is a `ResponseValidationError`. ### isJsonifiable(value) diff --git a/README_ZH.md b/README_ZH.md index 76f7bed..924ab7f 100644 --- a/README_ZH.md +++ b/README_ZH.md @@ -335,18 +335,18 @@ try { - 使用 [parseRejected][api-reference] 选项抛出自定义错误。 - 使用 [reject][api-reference] 选项决定**何时**抛出错误。 -#### 👉 ValidationError +#### 👉 ResponseValidationError 当模式验证失败时抛出。\ -使用 `isValidationError` 识别此错误类型。 +使用 `isResponseValidationError` 识别此错误类型。 ```ts -import { isValidationError } from 'up-fetch' +import { isResponseValidationError } from 'up-fetch' try { await upfetch('/todos/1', { schema: todoSchema }) } catch (error) { - if (isValidationError(error)) { + if (isResponseValidationError(error)) { console.log(error.issues) } } @@ -549,7 +549,7 @@ const upfetch = up(fetch, () => ({ // 自定义错误消息 const message = `Request failed with status ${status}: ${JSON.stringify(data)}` // 你也可以返回自定义错误类 - return new ResponseError({ message, data, request, response }) + return new ResponseError({ message, status, data }) }, })) ``` @@ -719,9 +719,9 @@ function upfetch( 检查错误是否为 `ResponseError`。 -### isValidationError(error) +### isResponseValidationError(error) -检查错误是否为 `ValidationError`。 +检查错误是否为 `ResponseValidationError`。 ### isJsonifiable(value) diff --git a/package-lock.json b/package-lock.json index 2a2ce3d..ecffbe6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "up-fetch", - "version": "2.5.1-beta.1", + "version": "2.5.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "up-fetch", - "version": "2.5.1-beta.1", + "version": "2.5.1", "license": "MIT", "devDependencies": { "@biomejs/biome": "^2.2.5", diff --git a/src/fallback-options.ts b/src/fallback-options.ts index 90afa12..bbd11ae 100644 --- a/src/fallback-options.ts +++ b/src/fallback-options.ts @@ -13,9 +13,8 @@ export const fallbackOptions: FallbackOptions = { parseRejected: async (response, request) => new ResponseError({ message: `[${response.status}] ${response.statusText}`, + status: response.status, data: await fallbackOptions.parseResponse(response, request), - response, - request, }), // TODO: find a lighter way to do this with about the same amount of code diff --git a/src/index.ts b/src/index.ts index 5be388e..f00b4e2 100644 --- a/src/index.ts +++ b/src/index.ts @@ -10,4 +10,15 @@ export type { } from './types' export { up } from './up' export { isJsonifiable } from './utils' -export { isValidationError, ValidationError } from './validation-error' +export { + isResponseValidationError, + /** + * @deprecated Use `isResponseValidationError` instead. + */ + isResponseValidationError as isValidationError, + ResponseValidationError, + /** + * @deprecated Use `ResponseValidationError` instead. + */ + ResponseValidationError as ValidationError, +} from './validation-error' diff --git a/src/response-error.ts b/src/response-error.ts index c476b51..58b6180 100644 --- a/src/response-error.ts +++ b/src/response-error.ts @@ -1,25 +1,17 @@ export class ResponseError extends Error { - response: Response - request: Request data: TData status: number + kind: 'response' - constructor(props: { - message: string - response: Response - data: TData - request: Request - }) { - // super(`[${response.status}] ${response.statusText}`) + constructor(props: { message: string; status: number; data: TData }) { super(props.message) - this.name = 'ResponseError' - this.response = props.response - this.request = props.request + this.kind = 'response' this.data = props.data - this.status = props.response.status + this.status = props.status } } export const isResponseError = ( error: unknown, -): error is ResponseError => error instanceof ResponseError +): error is ResponseError => + typeof error === 'object' && (error as ResponseError)?.kind === 'response' diff --git a/src/tests/dist.spec.ts b/src/tests/dist.spec.ts index cbed543..9d9aef4 100644 --- a/src/tests/dist.spec.ts +++ b/src/tests/dist.spec.ts @@ -1,6 +1,12 @@ -import { expectTypeOf, test } from 'vitest' +import { expect, expectTypeOf, test } from 'vitest' import { z } from 'zod' -import { up } from '../../dist' +import { + isResponseValidationError, + isValidationError, + ResponseValidationError, + up, + ValidationError, +} from '../../dist' /** * testing the build output with `declaration: true` in tsconfig.json @@ -26,3 +32,14 @@ test('type inference should still work after the build', () => { noop(testCase) }) + +test('legacy validation error exports should remain available after the build', () => { + expect(ValidationError).toBe(ResponseValidationError) + expect(isValidationError).toBe(isResponseValidationError) + expectTypeOf().toEqualTypeOf< + typeof ResponseValidationError + >() + expectTypeOf().toEqualTypeOf< + typeof isResponseValidationError + >() +}) diff --git a/src/tests/fallback-options.spec.ts b/src/tests/fallback-options.spec.ts index e8f22a9..2eeae89 100644 --- a/src/tests/fallback-options.spec.ts +++ b/src/tests/fallback-options.spec.ts @@ -58,8 +58,7 @@ describe('parseRejected', () => { ) expect(responseError instanceof ResponseError).toBeTruthy() expect(responseError.data).toStrictEqual(output) - expect(responseError.response).toStrictEqual(response) - expect(responseError.request).toBe(request) - expect(responseError.name).toStrictEqual('ResponseError') + expect(responseError.status).toStrictEqual(200) + expect(responseError.kind).toStrictEqual('response') }) }) diff --git a/src/tests/on-error.spec.ts b/src/tests/on-error.spec.ts index 1947c23..e2e144e 100644 --- a/src/tests/on-error.spec.ts +++ b/src/tests/on-error.spec.ts @@ -12,10 +12,10 @@ import { import { z } from 'zod' import { isResponseError, - isValidationError, + isResponseValidationError, type ResponseError, + type ResponseValidationError, up, - type ValidationError, } from '..' const server = setupServer() @@ -37,9 +37,9 @@ describe('onError', () => { const upfetch = up(fetch, () => ({ baseUrl: baseUrl, onError(error, request) { - if (isValidationError(error)) { + if (isResponseValidationError(error)) { exec++ - expectTypeOf(error).toEqualTypeOf() + expectTypeOf(error).toEqualTypeOf() } }, })) @@ -47,9 +47,9 @@ describe('onError', () => { await upfetch('', { schema: z.object({ hello: z.number() }), onError(error, request) { - if (isValidationError(error)) { + if (isResponseValidationError(error)) { exec++ - expectTypeOf(error).toEqualTypeOf() + expectTypeOf(error).toEqualTypeOf() } }, }).catch(() => {}) diff --git a/src/utils.ts b/src/utils.ts index 461b1a6..7ded1f0 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -8,7 +8,7 @@ import type { Params, SerializeParams, } from './types' -import { ValidationError } from './validation-error' +import { ResponseValidationError } from './validation-error' export const mergeHeaders = ( headerInits: (HeadersInit | HeadersObject | undefined)[], @@ -112,6 +112,6 @@ export async function validate( data: StandardSchemaV1.InferInput, ): Promise> { const result = await schema['~standard'].validate(data) - if (result.issues) throw new ValidationError(result, data) + if (result.issues) throw new ResponseValidationError(result, data) return result.value } diff --git a/src/validation-error.ts b/src/validation-error.ts index d62e67c..cb8bd1a 100644 --- a/src/validation-error.ts +++ b/src/validation-error.ts @@ -1,17 +1,20 @@ import type { StandardSchemaV1 } from '@standard-schema/spec' -export class ValidationError extends Error { - override name: 'ValidationError' +export class ResponseValidationError extends Error { issues: readonly StandardSchemaV1.Issue[] + kind: 'validation' data: TData constructor(result: StandardSchemaV1.FailureResult, data: TData) { super(JSON.stringify(result.issues)) - this.name = 'ValidationError' + this.kind = 'validation' this.issues = result.issues this.data = data } } -export const isValidationError = (error: unknown): error is ValidationError => - error instanceof ValidationError +export const isResponseValidationError = ( + error: unknown, +): error is ResponseValidationError => + typeof error === 'object' && + (error as ResponseValidationError)?.kind === 'validation'