Logo

Kode$word

I Published My First npm Package: Karos

I Published My First npm Package: Karos

How I built a small, opinionated library to enforce consistent API responses and error handling in Node.js

69 views
0
0

Introduction

Publishing your first npm package is not about building something revolutionary.

If you think it is, you’ll either overbuild it or never ship it.

Karos exists because I kept running into the same boring, frustrating problem across backend projects — inconsistent API responses and messy error handling.


The Problem I Kept Seeing

In most Express or Node.js backends:

  1. Every route formats responses differently
  2. Some errors are strings, some are objects, some leak stack traces
  3. Status codes are inconsistent or guessed
  4. Frontend logic becomes defensive and conditional-heavy
  5. Teams rewrite the same response boilerplate in every project

There is no enforced backend–frontend contract.

Just “best practices” that slowly decay over time.


Why I Didn’t Use Existing Solutions

There are libraries that help with errors.

There are frameworks that encourage conventions.

But most of them:

  1. Add heavy abstractions
  2. Require configuration files
  3. Lock you into a framework style
  4. Mix business logic with infrastructure

I didn’t want help.

I wanted enforcement — and nothing more.


What Karos Does (And Only This)

Karos enforces one predictable JSON response contract across your API.

That’s it.

Success Response

{
"success": true,
"data": {}
}

Error Response

{
"success": false,
"error": {
"code": "NOT_FOUND",
"message": "User not found"
}
}

No special cases.

No custom shapes per route.

If a response doesn’t match this structure, it’s wrong.


Stop Returning Errors. Start Throwing Them.

Instead of this pattern everywhere:

if (!user) {
return res.status(404).json({ error: 'User not found' });
}

Karos forces a different mindset:

if (!user) {
notFoundError('User not found');
}

The error is thrown, not returned.

A single global handler catches it, formats it, and sends the response.

  1. No repeated try/catch
  2. No duplicated error formatting
  3. No forgotten status codes

KarosError: One Error Model to Rule Them All

At the core of Karos is a single class: KarosError.

Every error has:

  1. A strict error code (TypeScript-safe)
  2. An explicit HTTP status
  3. Optional structured details
  4. A guaranteed JSON shape

This makes backend behavior predictable and frontend handling trivial.


Database Errors Are Normalized Automatically

Raw database errors should never reach the client.

Karos automatically detects and normalizes common DB errors:

  1. Prisma unique constraint → CONFLICT (409)
  2. Prisma record not found → NOT_FOUND (404)
  3. MongoDB duplicate key → CONFLICT (409)
  4. Mongoose validation errors → VALIDATION_FAILED (400)

The frontend never needs to know which database you’re using.

It only cares about the contract.


Express and Next.js Share the Same Contract

Karos supports:

  1. Express via middleware
  2. Next.js (App Router) via Web-standard helpers

Both produce the exact same response format.

That means you can switch frameworks or mix them — and your frontend logic stays unchanged.


Karos API – All Methods in One Place

Core API Reference

CategoryFunction / ClassDescription
Successok(res, data, message?, meta?)Sends a standardized success response (Express)
Error BaseKarosErrorBase error class with code, status, details
Error HelpersnotFoundError()Throws 404 NOT_FOUND

validationError()Throws 400 VALIDATION_FAILED

unauthorizedError()Throws 401 UNAUTHORIZED

forbiddenError()Throws 403 FORBIDDEN

conflictError()Throws 409 CONFLICT

internalError()Throws 500 INTERNAL_ERROR

httpError()Custom error with any status
MiddlewareerrorHandlerGlobal Express error handler
DB HandlingresolveDbError()Normalizes Prisma/Mongo errors
Next.jsnextOk()Success response for App Router

nextFail()Error response for App Router

handleNextError()Global Next.js error handler
TypesErrorCodeEnum-style error codes
TypesApiSuccessResponseSuccess response type
TypesApiErrorResponseError response type


What Karos Is Not

This matters more than features.

Karos is not:

  1. A validation library
  2. A logging framework
  3. A request lifecycle manager
  4. A replacement for good architecture
  5. A silver bullet

It solves one problem and refuses to grow beyond that.


How You Can Publish Your First npm Package Too

If you’re thinking “this looks doable” — it is.

Here are the actual steps, no fluff.

1. Create an npm Account

  1. Go to https://www.npmjs.com
  2. Sign up and verify your email

2. Prepare Your Package

npm init

Make sure:

  1. name is unique
  2. main points to your build output
  3. types points to .d.ts if using TypeScript

3. Build Your Package

npm run build

(Usually outputs to dist/)

4. Login to npm

npm login

Enter:

  1. Username
  2. Password
  3. Email
  4. OTP (if 2FA enabled)

5. Publish

npm publish

That’s it.

No approval process. No gatekeepers.

You are officially an npm package author.


Links

  1. GitHub Repository: https://github.com/Krishna-Shrivastava-1/Karos
  2. npm Package: https://www.npmjs.com/package/karos


Why Shipping This Mattered to Me

Karos won’t make headlines.

It won’t go viral.

But it forced me to:

  1. Design a real API contract
  2. Think about DX instead of just code
  3. Handle edge cases like DB errors properly
  4. Ship something other people can actually use

For a first npm package, that’s a win.


Final Thought

Most backend bugs don’t come from complex logic.

They come from inconsistency.

Karos doesn’t make your API smarter.

It makes it disciplined.

And sometimes, that’s exactly what you need.