npm.io
1.0.0 • Published yesterday

@owskar/backend-toolkit

Licence
ISC
Version
1.0.0
Deps
8
Size
46 kB
Vulns
0
Weekly
0

backend-toolkit

Small, dependency-light utilities for Node.js backend developers — response helpers, async error handling, JWT, password hashing, dates, pagination, validation, logging, and env loading. One package, no boilerplate.

Install

npm install backend-toolkit

Quick start

const { success, error, asyncHandler } = require("backend-toolkit");

app.get(
  "/users/:id",
  asyncHandler(async (req, res) => {
    const user = await findUser(req.params.id);
    if (!user) return res.status(404).json(error("User not found", 404));
    res.json(success(user, "User fetched"));
  })
);

Everything is also available as named imports (works via Node's ESM interop for CommonJS packages):

import { success, error, asyncHandler } from "backend-toolkit";

Modules

Response

Consistent success/error response envelopes for your API.

const { success, error } = require("backend-toolkit");

success({ id: 1 }, "User fetched");
// { success: true, statusCode: 200, message: "User fetched", data: { id: 1 }, timestamp: "..." }

error("Invalid credentials", 401);
// { success: false, statusCode: 401, message: "Invalid credentials", errors: null, timestamp: "..." }
  • success(data?, message?, statusCode?)
  • error(message?, statusCode?, errors?)
Async handling

Wraps an async route handler so thrown errors and rejected promises are forwarded to next() instead of crashing the process or requiring a try/catch in every controller.

const { asyncHandler } = require("backend-toolkit");

app.get(
  "/orders",
  asyncHandler(async (req, res) => {
    const orders = await Order.find();
    res.json(orders);
  })
);
JWT

Thin wrapper around jsonwebtoken.

const { signToken, verifyToken, decodeToken } = require("backend-toolkit");

const token = signToken({ userId: 1 }, process.env.JWT_SECRET, { expiresIn: "1h" });
const payload = verifyToken(token, process.env.JWT_SECRET); // throws on invalid/expired
const claims = decodeToken(token); // reads claims without verifying the signature
Password

Thin wrapper around bcryptjs.

const { hashPassword, comparePassword } = require("backend-toolkit");

const hash = await hashPassword("Sup3rSecret!"); // default 10 salt rounds
const matches = await comparePassword("Sup3rSecret!", hash); // true
Date

Thin wrapper around dayjs.

const {
  now,
  formatDate,
  addTime,
  subtractTime,
  diff,
  isBefore,
  isAfter,
} = require("backend-toolkit");

formatDate(new Date(), "YYYY-MM-DD");
addTime(new Date(), 7, "day");
diff("2024-01-10", "2024-01-01", "day"); // 9
isBefore("2024-01-01", "2024-02-01"); // true
Pagination
const { paginate, getPaginationParams } = require("backend-toolkit");

const { page, limit } = getPaginationParams(req.query); // parses & clamps req.query
const meta = paginate({ page, limit, totalItems: await User.countDocuments() });
// { page, limit, offset, totalItems, totalPages, hasNextPage, hasPrevPage }
Validation

Built on zod. validate() never throws — it returns a normalized result.

const { validate, rules } = require("backend-toolkit");
const { z } = require("zod");

const schema = z.object({ email: rules.email, password: rules.password });
const result = validate(schema, req.body);

if (!result.success) {
  return res.status(400).json(error("Validation failed", 400, result.errors));
}
// result.data is the parsed, type-coerced payload

Built-in rules: email, password (min 8 chars, 1 uppercase, 1 number), mongoId, uuid, pagination ({ page, limit } with defaults).

Logger

Structured JSON logging (pino) in production; colorized, readable console output in development — no extra pino-pretty dependency required.

const { logger, createLogger } = require("backend-toolkit");

logger.info("Server started");
logger.error("Something went wrong", err);

const requestLogger = createLogger({ level: "debug" });

Controlled by NODE_ENV (production → pino JSON) and LOG_LEVEL (defaults to info).

Env

Loads .env via dotenv and, optionally, validates process.env against a Zod schema — so misconfiguration fails fast at startup.

const { loadEnv } = require("backend-toolkit");
const { z } = require("zod");

const env = loadEnv(
  z.object({
    PORT: z.coerce.number().default(3000),
    JWT_SECRET: z.string().min(1),
  })
);
// throws a descriptive error if PORT/JWT_SECRET are missing or invalid

Full runnable examples

See examples/express.js and examples/fastify.js for complete apps wiring several modules together (signup with validation + password hashing + JWT, paginated listing, centralized error handling).

Development

npm install
npm test          # run the test suite
npm run lint       # lint
npm run format     # format with prettier
npm run build      # bundle to dist/ (CJS + type declarations)

License

ISC Owskar

Keywords