@deliverart/sdk-js-error-handler

中文文档
3.0.1发布于 2026/11/11TypeScriptESM + CJS近 30 天下载 3036

Error handling utilities for Deliverart SDK in JavaScript

原始使用文档
文档目录24 节
  1. Installation
  2. Exported Types
  3. ErrorHandlerPlugin
  4. ApiError
  5. ApiErrorData
  6. ValidationErrorData
  7. FormState
  8. FormStateError
  9. Usage
  10. Basic Setup
  11. Handling Validation Errors
  12. Displaying Validation Errors in Forms
  13. Handling Different HTTP Status Codes
  14. Using FormState with React Server Actions
  15. Global Error Handler
  16. Type Guards
  17. Converting FormState Errors Back to Exceptions
  18. How It Works
  19. Best Practices
  20. 1. Centralized Error Handling
  21. 2. Field-Level Error Mapping
  22. 3. Toast Notifications
  23. License
  24. Safe diagnostics

@deliverart/sdk-js-error-handler

Error handling plugin for the DeliverArt JavaScript SDK. Automatically handles API errors and transforms them into typed exceptions.

Installation

npm install @deliverart/sdk-js-error-handler @deliverart/sdk-js-core
# or
pnpm add @deliverart/sdk-js-error-handler @deliverart/sdk-js-core
# or
yarn add @deliverart/sdk-js-error-handler @deliverart/sdk-js-core

Exported Types

ErrorHandlerPlugin

class ErrorHandlerPlugin implements ApiClientPlugin<{}>

Plugin that intercepts API responses and transforms error responses into typed exceptions.

Constructor:

  • constructor() - No configuration required

ApiError

class ApiError extends Error {
  readonly name = 'ApiError'
  readonly code?: string
  readonly request?: RequestInit
  readonly response?: Response
  readonly status?: number
  readonly data?: ApiErrorData
}

Main error class for API errors.

Properties:

  • name: 'ApiError' - Error name
  • code?: string - Error code from the API
  • request?: RequestInit - Original request init
  • response?: Response - HTTP response object
  • status?: number - HTTP status code
  • data?: ApiErrorData - Typed error data

ApiErrorData

type ApiErrorData =
  | {
      type: 'VALIDATION_ERROR'
      value: ValidationErrorData
    }
  | {
      type: 'UNKNOWN_ERROR'
      value: unknown
    }

Discriminated union type for different error types.

VALIDATION_ERROR - Returned when API responds with 422 status (validation failed)

  • value: ValidationErrorData - Contains validation violations

UNKNOWN_ERROR - Returned for all other error responses

  • value: unknown - Contains the raw error response

ValidationErrorData

interface ValidationErrorData {
  status: number
  violations: Array<{
    propertyPath: string
    message: string
    code: string | null
  }>
  detail: string
  type: string
  title: string
}

Structured validation error data from the API.

Properties:

  • status: number - HTTP status code (422)
  • violations: Array - List of validation violations
    • propertyPath: string - Field path that failed validation (e.g., "email", "address.city")
    • message: string - Human-readable error message
    • code: string | null - Validation error code
  • detail: string - Detailed error description
  • type: string - Error type identifier
  • title: string - Error title

FormState

type FormState<T> =
  | {
      success: true
      data: T
    }
  | {
      success: false
      error: ApiErrorData
    }

Utility type for handling form submission states (useful for React Server Actions).

FormStateError

class FormStateError extends Error {
  constructor(public readonly error: ApiErrorData)
}

Error wrapper for form state errors.

Usage

Basic Setup

import { createApiClient } from '@deliverart/sdk-js-core';
import { ErrorHandlerPlugin } from '@deliverart/sdk-js-error-handler';

const client = createApiClient({ 
  baseUrl: 'https://api.deliverart.com' 
})
  .addPlugin(new ErrorHandlerPlugin());

Handling Validation Errors

import { ApiError } from '@deliverart/sdk-js-error-handler';
import { CreateUser } from './requests';

try {
  await client.call(new CreateUser({
    email: 'invalid-email',
    name: ''
  }));
} catch (error) {
  if (error instanceof ApiError && error.data?.type === 'VALIDATION_ERROR') {
    const violations = error.data.value.violations;
    
    violations.forEach(violation => {
      console.error(`${violation.propertyPath}: ${violation.message}`);
    });
    
    // Output:
    // email: This value is not a valid email address.
    // name: This value should not be blank.
  }
}

Displaying Validation Errors in Forms

React Example

import { useState } from 'react';
import { ApiError } from '@deliverart/sdk-js-error-handler';

function CreateUserForm() {
  const [errors, setErrors] = useState<Record<string, string>>({});
  
  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();
    setErrors({});
    
    try {
      await client.call(new CreateUser(formData));
      // Success!
    } catch (error) {
      if (error instanceof ApiError && error.data?.type === 'VALIDATION_ERROR') {
        const newErrors: Record<string, string> = {};
        
        error.data.value.violations.forEach(violation => {
          newErrors[violation.propertyPath] = violation.message;
        });
        
        setErrors(newErrors);
      }
    }
  };
  
  return (
    <form onSubmit={handleSubmit}>
      <input name="email" />
      {errors.email && <span className="error">{errors.email}</span>}
      
      <input name="name" />
      {errors.name && <span className="error">{errors.name}</span>}
      
      <button type="submit">Create User</button>
    </form>
  );
}

Handling Different HTTP Status Codes

import { ApiError } from '@deliverart/sdk-js-error-handler';

try {
  await client.call(new GetUser('123'));
} catch (error) {
  if (error instanceof ApiError) {
    switch (error.status) {
      case 400:
        console.error('Bad Request:', error.message);
        break;
      case 401:
        console.error('Unauthorized - please login');
        window.location.href = '/login';
        break;
      case 403:
        console.error('Forbidden - insufficient permissions');
        break;
      case 404:
        console.error('User not found');
        break;
      case 422:
        // Validation error - handled above
        break;
      case 500:
        console.error('Server error');
        break;
      default:
        console.error('Unknown error:', error);
    }
  }
}

Using FormState with React Server Actions

FormState is particularly useful for Next.js Server Actions:

// app/actions/create-user.ts
'use server';

import { throwableToFormState, FormState } from '@deliverart/sdk-js-error-handler';
import { sdk } from '@/lib/sdk';
import { CreateUser } from '@deliverart/sdk-js-user';

export async function createUserAction(
  formData: FormData
): Promise<FormState<{ id: string }>> {
  return throwableToFormState(async () => {
    const result = await sdk.call(new CreateUser({
      name: formData.get('name') as string,
      email: formData.get('email') as string,
    }));
    
    return { id: result.id };
  });
}
// app/components/CreateUserForm.tsx
'use client';

import { useFormState } from 'react-dom';
import { createUserAction } from '../actions/create-user';

export function CreateUserForm() {
  const [state, formAction] = useFormState(createUserAction, null);
  
  return (
    <form action={formAction}>
      <input name="name" required />
      {state?.success === false && 
       state.error.type === 'VALIDATION_ERROR' && 
       state.error.value.violations
         .filter(v => v.propertyPath === 'name')
         .map(v => <span key={v.code} className="error">{v.message}</span>)
      }
      
      <input name="email" type="email" required />
      {state?.success === false && 
       state.error.type === 'VALIDATION_ERROR' && 
       state.error.value.violations
         .filter(v => v.propertyPath === 'email')
         .map(v => <span key={v.code} className="error">{v.message}</span>)
      }
      
      <button type="submit">Create User</button>
      
      {state?.success === true && (
        <p className="success">User created with ID: {state.data.id}</p>
      )}
    </form>
  );
}

Global Error Handler

Set up a global error handler for all API errors:

// lib/error-handler.ts
import { ApiError } from '@deliverart/sdk-js-error-handler';

export function handleApiError(error: unknown) {
  if (!(error instanceof ApiError)) {
    console.error('Non-API error:', error);
    return;
  }
  
  // Log to error tracking service (e.g., Sentry)
  console.error('API Error:', {
    status: error.status,
    code: error.code,
    message: error.message,
    data: error.data,
  });
  
  // Show user-friendly message
  if (error.status === 401) {
    alert('Please login to continue');
    window.location.href = '/login';
  } else if (error.status === 403) {
    alert('You do not have permission to perform this action');
  } else if (error.status === 404) {
    alert('The requested resource was not found');
  } else if (error.data?.type === 'VALIDATION_ERROR') {
    const firstViolation = error.data.value.violations[0];
    alert(`Validation error: ${firstViolation.message}`);
  } else {
    alert('An unexpected error occurred. Please try again.');
  }
}
// Usage in your app
try {
  await client.call(request);
} catch (error) {
  handleApiError(error);
}

Type Guards

Create type guards for cleaner error handling:

import { ApiError, ApiErrorData } from '@deliverart/sdk-js-error-handler';

function isValidationError(error: unknown): error is ApiError & { 
  data: { type: 'VALIDATION_ERROR', value: ValidationErrorData } 
} {
  return error instanceof ApiError && 
         error.data?.type === 'VALIDATION_ERROR';
}

function isUnauthorizedError(error: unknown): error is ApiError {
  return error instanceof ApiError && error.status === 401;
}

function isNotFoundError(error: unknown): error is ApiError {
  return error instanceof ApiError && error.status === 404;
}

// Usage
try {
  await client.call(request);
} catch (error) {
  if (isValidationError(error)) {
    // TypeScript knows error.data.value is ValidationErrorData
    error.data.value.violations.forEach(v => {
      console.log(v.propertyPath, v.message);
    });
  } else if (isUnauthorizedError(error)) {
    redirectToLogin();
  } else if (isNotFoundError(error)) {
    show404Page();
  }
}

Converting FormState Errors Back to Exceptions

import { formStateErrorToThrowable, FormState } from '@deliverart/sdk-js-error-handler';

const result: FormState<User> = await createUserAction(formData);

if (!result.success) {
  // Convert FormState error back to throwable error
  throw formStateErrorToThrowable(result.error);
}

// TypeScript knows result.data is User
console.log(result.data.id);

How It Works

The plugin adds a response middleware that:

  1. Checks if the response is not OK (!response.ok)
  2. If status is 422, attempts to parse the response as validation error
  3. If parsing succeeds, throws ApiError with VALIDATION_ERROR type
  4. For all other error responses, throws ApiError with UNKNOWN_ERROR type
  5. Includes the original request, response, and parsed body in the error

Best Practices

1. Centralized Error Handling

Create a utility function for consistent error handling across your app:

export function getErrorMessage(error: unknown): string {
  if (error instanceof ApiError) {
    if (error.data?.type === 'VALIDATION_ERROR') {
      const firstViolation = error.data.value.violations[0];
      return firstViolation?.message ?? 'Validation failed';
    }
    return error.message;
  }
  
  if (error instanceof Error) {
    return error.message;
  }
  
  return 'An unexpected error occurred';
}

2. Field-Level Error Mapping

Create a helper to map violations to form fields:

import { ValidationErrorData } from '@deliverart/sdk-js-error-handler';

export function violationsToFieldErrors(
  violations: ValidationErrorData['violations']
): Record<string, string> {
  return violations.reduce((acc, violation) => {
    acc[violation.propertyPath] = violation.message;
    return acc;
  }, {} as Record<string, string>);
}

// Usage
if (error.data?.type === 'VALIDATION_ERROR') {
  const fieldErrors = violationsToFieldErrors(error.data.value.violations);
  setErrors(fieldErrors);
}

3. Toast Notifications

Integrate with toast notification libraries:

import { toast } from 'sonner';
import { ApiError } from '@deliverart/sdk-js-error-handler';

try {
  await client.call(request);
  toast.success('Operation completed successfully');
} catch (error) {
  if (error instanceof ApiError && error.data?.type === 'VALIDATION_ERROR') {
    error.data.value.violations.forEach(v => {
      toast.error(v.message);
    });
  } else {
    toast.error('An error occurred');
  }
}

License

MIT

Safe diagnostics

ApiError keeps its original request, response, data, code, status and message readable for typed consumers and form-state conversion. Transport objects, raw bodies and status/code fields are non-enumerable. Default Node inspection, string formatting and JSON serialization expose only an allowlisted diagnostic: stable classification, HTTP status/code, method and a pathname without query, fragment, origin or user information. The plugin captures that pathname from the actual request context. Validation field messages remain available programmatically and are not included in these diagnostics.

Do not log raw error.request, error.response, error.data, custom caller messages or arbitrary stack/exception serializers. This SDK behavior does not sanitize Next.js access logs, OAuth callback URLs logged elsewhere, or independent telemetry request contexts.

The focused built-artifact tests exercise ESM and CommonJS diagnostics, secret omission, actual response middleware and form-state compatibility. Build this package and its workspace dependencies first, then run pnpm --filter @deliverart/sdk-js-error-handler test. No test runner dependency is added: tests use Node's built-in runner.

版本与发布记录

@deliverart/sdk-js-error-handler 共发布 321 个版本,首次发布于 2025/06/16;过去 12 个月发布了 230 个版本。

版本发布日期距今
3.0.1latest2026/11/111 天前
3.0.02026/11/092 天前
3.0.0-dev.1dev2026/11/092 天前
2.48.12026/10/2518 天前
2.48.02026/10/2319 天前
2.47.02026/10/2319 天前

关于 @deliverart/sdk-js-error-handler 的常见问题

@deliverart/sdk-js-error-handler 是什么?

Error handling utilities for Deliverart SDK in JavaScript

如何安装 @deliverart/sdk-js-error-handler?

在项目目录运行 npm install @deliverart/sdk-js-error-handler,或使用 pnpm add / yarn add / bun add。

@deliverart/sdk-js-error-handler 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@deliverart/sdk-js-error-handler 支持 ESM 还是 CommonJS?

同时提供 ES Module 与 CommonJS 入口,import 和 require() 都可以使用,打包工具会自动选择合适的版本。

@deliverart/sdk-js-error-handler 可以商用吗?

@deliverart/sdk-js-error-handler 使用 未声明 许可。package.json 没有声明许可证。没有许可证的代码默认保留全部权利,商用前请联系作者或查看仓库中的 LICENSE 文件。以上为概括,不构成法律意见,请以许可原文为准。

@deliverart/sdk-js-error-handler 的下载量有多少?

根据 npm 官方下载统计,@deliverart/sdk-js-error-handler 在 2026/10/12 – 2026/11/10 这 30 天内被下载 3,036 次,日均约 101 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@deliverart/sdk-js-error-handler 还在维护吗?

最新版本 3.0.1 发布于 2026/11/11(1 天前);至今共发布 321 个版本,其中过去 12 个月发布了 230 个;首次发布于 2025/06/16。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。