npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@sidev/api-handler

v1.0.2

Published

A type-safe library for handling API responses and function returns in JS and TS applications.

Readme

@sidev/

api-handler

A type-safe library for handling API responses and function returns in JS and TS applications.

Features

  • Provides consistent return values and type safety.
  • Standardizes success and error handling for better readability.
  • Integrates easily with TypeScript and JavaScript projects.
  • Supports custom data structures and application-specific types.

TOC

Installation

You can install @sidev/api-handler using npm or yarn:

npm install @sidev/api-handler

or

yarn add @sidev/api-handler

Usage

1. Basic Setup

Import the library and create your API handler:

import { createApiHandler } from '@sidev/api-handler'

const APP_ERRORS = {
  AUTH_MEMBER_EXISTS: {
    code: 'AUTH_MEMBER_EXISTS',
    message: 'Member already exists.',
    uiMessages: ['This member already exists.', 'Please log in instead.'],
  },
  AUTH_NO_CREDENTIALS: {
    code: 'AUTH_NO_CREDENTIALS',
    message: 'No credentials provided.',
    uiMessages: ['No credentials were provided.', 'Please try again.'],
  },
}

const { apiError, apiSuccess, ERROR, CODE } = createApiHandler(APP_ERRORS)

2. Handling Errors

You can generate error responses using apiError():

const errorInstance = new Error(CODE.AUTH_MEMBER_EXISTS)
const errorResponse1 = apiError(errorInstance)

console.log('apiError(errorInstance) returns:', errorResponse1)

// Using error code as a string
const errorCode = CODE.AUTH_MEMBER_EXISTS
const errorResponse2 = apiError(errorCode)

console.log('apiError(errorCode) returns:', errorResponse2)

Note:

/*
  When using `apiError` to throw error codes, you can either pass the error code string directly or wrap it in a new `Error` object.
  While both approaches work, wrapping the error code in a new `Error` object will provide a more accurate stack trace, showing the exact location where the error was thrown. This can be a minor but useful difference for debugging purposes.
 */
try {
  // Example of throwing an error with a more accurate stack trace
  throw new Error(CODE.AUTH_MEMBER_EXISTS)

  // Example of throwing an string with error code
  throw CODE.AUTH_MEMBER_EXISTS
  //
} catch (error) {
  // return from catch block
  return apiError(error)
}

3. Handling Success Responses

To generate success responses, use apiSuccess():

const dataObj = {
  data: { key: 'value' },
  message: 'Operation successful',
}
const successResponse = apiSuccess(dataObj)
console.log(successResponse)

4. Using in Functions

Here’s an example of using apiSuccess() and apiError() in a function:

import { createApiHandler } from '@sidev/api-handler'
import { myErrors } from './my-errors'

const { apiError, apiSuccess, CODE } = createApiHandler(myErrors)

const handleRequest = (condition: string) => {
  try {
    if (condition === 'error') {
      throw new Error(CODE.NOT_AUTHORIZED)
      // or
      // throw CODE.AUTH_NO_CREDENTIALS;
    }
    // go on
    return apiSuccess({
      data: { abc: 'xyz' },
      message: 'Request handled successfully',
    })
  } catch (error) {
    // return what was thrown with apiError()
    // if any other error happen it will be handled also uniformly
    // and return expected ApiErrorResponse object
    return apiError(error)
  }
}

console.log(handleRequest('error'))
/* logs:
{
  success: false,
  error: Error: Not authorized
      at handleRequest ... ...
  message: 'Not authorized',
  code: 'NOT_AUTHORIZED',
  uiMessages: [
    'You are Not authorized',
    'This content is only available to authorized users.',
    'Look for the login button in the top right corner.'
  ]
}
*/
console.log(handleRequest('success'))
/* logs:
{
  success: true,
  data: { abc: 'xyz' },
  message: 'Request handled successfully'
}
*/

5. Example with Custom Types (TS)

You can separate your error definitions in a centralized file, even for the whole app. Use type ApiErrorsMap

// my-errors.ts

import { type ApiErrorsMap } from '@sidev/api-handler'

// Centralized error definitions
export const myErrors: ApiErrorsMap = {
  NO_ACCOUNT: {
    code: 'NO_ACCOUNT',
    message: 'Account not found',
    uiMessages: [
      'Try creating an account.',
      'If you are an admin, please contact developer team.',
    ],
  },
  NOT_AUTHORIZED: {
    code: 'NOT_AUTHORIZED',
    message: 'Not authorized',
    uiMessages: [
      'You are Not authorized',
      'This content is only available to authorized users.',
      'Look for the login button in the top right corner.',
    ],
  },
  // ... more
}

// only for this example mock function
export async function simulatedDb(id: number) {
  await new Promise((resolve) => setTimeout(resolve, 30))
  /* --- 555 id will simulate unpredicted error from db --- */
  switch (id) {
    case 555:
      throw new Error('Some error outside your definitions')
    case 10:
      return { id, name: 'John Doe', role: 'Admin' }
    case 20:
      return { id, name: 'Smith Bob', role: 'Customer' }
    default:
      return {}
  }
}

Now, in module, you can define custom types for your .data with type ApiResponseWith

// example.ts

import { createApiHandler, type ApiResponseWith } from '@sidev/api-handler'
import { myErrors, simulatedDb } from './my-errors'

const { apiError, apiSuccess, CODE } = createApiHandler(myErrors)

type UserAccount = {
  id: number
  name: string
  role: string
}

const getAdminAccount = async (
  id: number
): Promise<ApiResponseWith<UserAccount>> => {
  try {
    const userAccount = await simulatedDb(id) // a mock function
    if (userAccount.id) {
      if (userAccount.role !== 'Admin') {
        throw new Error(CODE.NOT_AUTHORIZED)
      }
      return apiSuccess({
        /* --- data property is typechecking for UserAccount --- */
        data: userAccount,
        message: 'Account fetched successfully', // optional default "Success"
      })
    }
    throw new Error(CODE.NO_ACCOUNT)
  } catch (error) {
    return apiError(error)
  }
}

/* --- call it with different id param to test outputs --- */
let response
response = await getAdminAccount(20) // success:false NOT_AUTHORIZED
response = await getAdminAccount(10) // success:true
response = await getAdminAccount(555) // success:false UNEXPECTED ERROR
response = await getAdminAccount(1000) // success:false NO_ACCOUNT

if (response.success) {
  console.log('success response', response)
} else {
  console.log('error response', response)
  /* --- do something with uiMessages on frontend --- */
  // showToast(response.uiMessages[0])
  response.uiMessages.map((message: string) => console.log(message))
}

6. apiSuccess() Important notes and .warning key

Function always returns ApiSuccessResponse object. On bad data attaches warning

import { createApiHandler } from '@sidev/api-handler'

const { apiError, apiSuccess } = createApiHandler({})

/**
 * JS runtime check in: apiSucess({ data : ValidData })
 *
 * - Call to apiSuccess() always! returns success response.
 * - In case of misuse of apiSuccess params response.warning is attached.
 * - Bad params or value, is converted to String and returned in response.data.
 *
 * _________________________________________________________________
 */

console.log(apiSuccess()) // with {warning}
console.log(apiSuccess(null)) // with {warning}
/* logs:
{
  success: true,
  data: 'null',
  message: 'Success',
  warning: 'Bad params in apiSuccess(params). Params should be { data: value } object. Got null.'
}
*/
console.log(apiSuccess({ abc: 1 })) // with {warning}
console.log(apiSuccess(100)) // with {warning}

console.log(apiSuccess({ data: null, message: 'lorem ipsum' })) // with {warning}
console.log(apiSuccess({ data: undefined })) // with {warning}
console.log(apiSuccess({ data: 888 })) // with {warning}

console.log(apiSuccess({ data: 'lorem ipsum' })) // OK
console.log(apiSuccess({ data: [4, 5, 6] })) // OK
console.log(apiSuccess({ data: { abc: 2 } })) // OK

// ---- In apiError call with bad params will return with code: UNKNOWN_ERROR

console.log(apiError())
/* logs:
{
  success: false,
  error: Error: Unknown error occurred
  message: 'Unknown error occurred',
  code: 'UNKNOWN_ERROR',
  uiMessages: [ 'An unknown error occurred.' ]
}
*/

Types Overview

ApiHandler

Represents a unified API response interface that can be either success or error response.

declare function createApiHandler(apiErrors: ApiErrorsMap): ApiHandler

export type ApiHandler = {
  apiError: (error: unknown) => ApiErrorResponse
  apiSuccess: <T extends ValidData>(params: {
    data: T
    message?: string
  }) => ApiSuccessResponse<T>
  readonly ERROR: ApiErrorsMap
  readonly CODE: Record<string, string>
}

ValidData

Represents valid types of data that can be used in success responses. It can be an object, array, or string.

type ValidData = object | any[] | string

ApiResponseBase

The base structure for all API responses, containing a success flag and an optional message.

export type ApiResponseBase = {
  success: boolean
  message?: string
}

ApiSuccessResponse

Represents a successful API response. It extends ApiResponseBase and includes the data field containing the response data. Other error-specific fields are set to never.

export type ApiSuccessResponse<T extends ValidData = object> =
  ApiResponseBase & {
    success: true
    data: T
    warning?: string // internal for misuse of apiSuccess
    error?: never
    code?: never
    uiMessages?: never
  }

ApiErrorResponse

Represents an error response. It extends ApiResponseBase and includes additional fields for error, code, and uiMessages.

export type ApiErrorResponse = ApiResponseBase & {
  success: false
  error: Error
  code: string
  uiMessages: string[]
  data?: never
  warning?: never
}

ApiResponse

A union type that can be either a success or an error response.

export type ApiResponse = ApiSuccessResponse | ApiErrorResponse

ApiResponseWith

A generic type that extends ApiResponse to include specific data types in success responses.

export type ApiResponseWith<T extends ValidData> =
  | ApiSuccessResponse<T>
  | ApiErrorResponse

AppError

Defines the structure for application-specific errors, including code, message, and uiMessages.

export type AppError = {
  code: string
  message: string
  uiMessages: string[]
}

ApiErrorsMap

A record type that maps error codes to AppError objects.

export type ApiErrorsMap = Record<string, AppError>

API Reference

createApiHandler(apiErrors: ApiErrorsMap)

  • Description: Initializes an API handler with custom error configurations.
  • Parameters:
    • apiErrors: A map of application-specific error codes to error details, including messages and UI messages.
  • Returns: An API handler object containing methods for generating standardized success and error responses.

apiError(error: unknown): ApiErrorResponse

  • Description: Processes an error and returns a structured API error response.
  • Parameters:
    • error: The error instance or code to be transformed into an API error response.
  • Returns: An ApiErrorResponse object containing error details and UI messages.

apiSuccess<T extends ValidData>(params: { data: T; message?: string }): ApiSuccessResponse<T>

  • Description: Generates a standardized API success response.
  • Parameters:
    • params: An object containing:
      • data: The data to include in the success response.
      • message: An optional message to accompany the success response.
  • Returns: An ApiSuccessResponse<T> object with the provided data and message.

About

Author

[si] Slavko Ivanovic

License

Released under the MIT License.