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

@thekosmix/node-decorators

v1.2.1

Published

A production-grade Spring-Boot-inspired TypeScript decorator suite for caching (Memory & Redis), logging, resiliency, metrics, and API exposure.

Readme

@thekosmix/node-decorators

A production-grade, Spring-Boot-inspired TypeScript decorator suite for Node.js. Carve out boilerplate like caching (In-Memory & Redis), logging, resiliency, metrics, validation, distributed locking, circuit breaking, idempotency, transactions, authorization, and audit trails with clean annotations.

npm version Tests License: MIT


Table of Contents


Overview

In Java's Spring Boot ecosystem, developers use annotations to separate cross-cutting concerns (caching, logging, retries, rate limits, locks, transactions) from business logic. node-decorators brings that exact ergonomic power to TypeScript and Node.js.

Instead of writing repetitive boilerplate inside your services:

// Without decorators: repetitive boilerplate mixed into business logic
async function getUsernameById(userId: string) {
  const cached = await redis.get(`users:${userId}`);
  if (cached) return JSON.parse(cached);

  const start = Date.now();
  try {
    const user = await UserModel.findById(userId);
    await redis.set(`users:${userId}`, JSON.stringify(user.name), 'EX', 3600);
    logger.info(`getUsernameById took ${Date.now() - start}ms`);
    return user.name;
  } catch (err) {
    logger.error('Failed to get user', err);
    throw err;
  }
}

Decorate your methods cleanly:

import { Cache, Log, Retry, Lock } from '@thekosmix/node-decorators';

class UserService {
  @Cache({ store: 'redis', bucket: 'users', ttl: 3600 })
  @Log()
  @Retry({ maxAttempts: 3 })
  @Lock({ key: (userId) => `user:${userId}` })
  async getUsernameById(userId: string) {
    const user = await UserModel.findById(userId);
    return user.name;
  }
}

What's New in v1.1.0

Version 1.1.0 expands the suite with 10 enterprise utilities for distributed systems, security, transactions, and performance:

  • 🔒 Distributed Concurrency & Failsafe: Added @Lock (Redis atomic SET NX PX distributed mutex & in-memory fallback) and @CircuitBreaker (automated CLOSED → OPEN → HALF_OPEN outage protection).
  • 🔁 API & Data Integrity: Added @Idempotent (deduplication of retried requests/webhooks) and @Transactional (declarative database transactions with Node.js AsyncLocalStorage context propagation).
  • 🛡️ Security & Compliance: Added @Authorize / @Roles (declarative RBAC and permission checking), @Audit (automatic compliance audit trails), and @FeatureFlag (dynamic runtime feature toggles).
  • ⚡ Traffic & Performance: Added @SingleFlight (eliminates the thundering herd by coalescing concurrent in-flight calls), @Debounce, and @Throttle.
  • ✅ Test Coverage & Reliability: 20 complete test suites with 70 passing automated tests covering all decorators and edge cases.

How to Use in an Existing Node.js Project

Step 1: Install the Package

npm install @thekosmix/node-decorators reflect-metadata

If you plan to use Redis caching or Redis distributed locking, install ioredis:

npm install ioredis

Step 2: Configure TypeScript (tsconfig.json)

Decorators require experimental decorator support and decorator metadata. Ensure your tsconfig.json contains:

{
  "compilerOptions": {
    "target": "ES2022",
    "module": "NodeNext",
    "moduleResolution": "NodeNext",
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true,
    "useDefineForClassFields": false
  }
}

Step 3: Initialize reflect-metadata at Application Entry

Import reflect-metadata once at the very top of your application entry file (index.ts, server.ts, app.ts):

// src/index.ts or server.ts
import 'reflect-metadata';

Step 4: Use Decorators in Your Services (ESM & CommonJS)

In ES Modules (import):

import { Cache, Log, Retry, Lock, CircuitBreaker } from '@thekosmix/node-decorators';

export class OrderService {
  @Lock({ key: (orderId) => `order:${orderId}` })
  @CircuitBreaker({ failureThreshold: 3, resetTimeoutMs: 5000 })
  @Retry({ maxAttempts: 3, delayMs: 200 })
  async processOrder(orderId: string, amount: number) {
    return paymentGateway.charge(orderId, amount);
  }
}

In CommonJS (require):

const { Cache, Log, Retry } = require('@thekosmix/node-decorators');

Step 5: (Optional) Connect Redis or File Logging

import Redis from 'ioredis';
import { CacheManager, RedisCacheStore, LoggerManager } from '@thekosmix/node-decorators';

// Connect Redis (enables both Redis Caching and Redis Distributed Locking)
const redis = new Redis(process.env.REDIS_URL || 'redis://localhost:6379');
CacheManager.registerStore('redis', new RedisCacheStore(redis));

// Enable disk file logging
LoggerManager.enableFileLogging('./logs/app.log', 'json');

Testing Locally in Another Project via npm link

  1. In node-decorators:
    npm run build
    npm link
  2. In your consumer project:
    npm link @thekosmix/node-decorators

How to Test & Build

Running the Test Suite

# Run all 20 test suites (70 unit & integration tests)
npm test

# Run tests in interactive watch mode
npm run test:watch

Running Specific Test Specs

npx vitest tests/lock.spec.ts
npx vitest tests/circuit-breaker.spec.ts
npx vitest tests/idempotent.spec.ts
npx vitest tests/transactional.spec.ts
npx vitest tests/validate.spec.ts
npx vitest tests/authorize.spec.ts
npx vitest tests/audit.spec.ts
npx vitest tests/feature-flag.spec.ts
npx vitest tests/single-flight.spec.ts
npx vitest tests/debounce.spec.ts

Running the Sample Demo Runner

npx ts-node test.ts

Building for Production (ESM + CommonJS + Types)

npm run build

Generates:

  • dist/index.js (CommonJS bundle)
  • dist/index.mjs (ES Module bundle)
  • dist/index.d.ts & dist/index.d.mts (Complete TypeScript typings)

Verifying the npm Package

npm pack --dry-run

Features & API Reference

1. Caching Suite

Supports multiple named stores, asynchronous and synchronous execution, automatic bucket partitioning, and custom key generation.

In-Memory Caching (Default)

import { Cache } from '@thekosmix/node-decorators';

class ProductService {
  @Cache('products')
  getProduct(id: string) {
    return db.products.findById(id);
  }
}

Redis Caching

import Redis from 'ioredis';
import { Cache, CacheManager, RedisCacheStore } from '@thekosmix/node-decorators';

CacheManager.registerStore('redis', new RedisCacheStore(new Redis()));

class OrderService {
  @Cache({ store: 'redis', bucket: 'orders', ttl: 600 })
  async getOrder(orderId: string) {
    return db.orders.findById(orderId);
  }
}

Cache Eviction & Updates

import { Cache, CacheEvict, CachePut } from '@thekosmix/node-decorators';

class UserService {
  @Cache('users')
  getUser(id: string) { ... }

  @CachePut({ bucket: 'users', keyGenerator: (user) => user.id })
  updateUser(user: { id: string; name: string }) { ... }

  @CacheEvict('users')
  deleteUser(id: string) { ... }

  @CacheEvict({ bucket: 'users', allEntries: true })
  flushUserCache() {}
}

2. Logging Suite

The @Log decorator captures invocation arguments, execution duration ([12.45ms]), return values, and exceptions with stack traces.

import { Log, LoggerManager } from '@thekosmix/node-decorators';

// Optional: Enable disk logs or external logger
LoggerManager.enableFileLogging('./logs/app.log', 'json');

class AuthService {
  @Log({ maskParams: ['password', 'token'] })
  login(payload: { username: string; password: string }) { ... }
}

3. Resiliency Suite

@Retry

Retries failed operations with configurable attempts, delays, and exponential backoff:

import { Retry } from '@thekosmix/node-decorators';

class ExternalApi {
  @Retry({ maxAttempts: 3, delayMs: 200, backoffMultiplier: 2 })
  async callWebhook(payload: any) { ... }
}

@Timeout

Aborts and rejects with TimeoutError if a method takes longer than the threshold:

import { Timeout } from '@thekosmix/node-decorators';

class SearchService {
  @Timeout(3000)
  async searchIndex(query: string) { ... }
}

@RateLimit

Enforces sliding window call limits globally or per user:

import { RateLimit } from '@thekosmix/node-decorators';

class NotificationService {
  @RateLimit({ maxCalls: 5, windowMs: 60000, keyGenerator: (userId) => userId })
  sendPush(userId: string, message: string) { ... }
}

4. Distributed Systems & Concurrency

@Lock

Distributed mutex across processes (via Redis atomic SET NX PX and Lua unlock) or in-memory Promise queue:

import { Lock } from '@thekosmix/node-decorators';

class PaymentService {
  @Lock({ key: (userId) => `payment:${userId}`, ttlMs: 5000, wait: true })
  async processPayment(userId: string, amount: number) {
    // Guaranteed single-execution across distributed workers
  }
}

@CircuitBreaker

Fail-fast protection against cascading downstream outages:

import { CircuitBreaker } from '@thekosmix/node-decorators';

class RecommendationService {
  @CircuitBreaker({
    failureThreshold: 5,
    resetTimeoutMs: 10000,
    fallback: () => ({ cached: true, items: [] }),
  })
  async getRemoteRecommendations(userId: string) {
    return remoteClient.fetch(userId);
  }
}

5. API & Data Integrity

@Idempotent

Prevents duplicate processing of retried network calls or duplicate webhooks:

import { Idempotent } from '@thekosmix/node-decorators';

class CheckoutService {
  @Idempotent({ keyGenerator: (orderId) => orderId, ttlSeconds: 86400 })
  async chargeOrder(orderId: string, amount: number) {
    // If called twice with the same orderId, returns the cached result without charging again
  }
}

@Transactional

Automated database transaction management with atomic commit and rollback on error, propagated via Node.js AsyncLocalStorage:

import { Transactional, TransactionManager } from '@thekosmix/node-decorators';

// Setup your ORM/query runner provider once
TransactionManager.setProvider({
  beginTransaction: () => db.startTransaction(),
  commit: (tx) => tx.commit(),
  rollback: (tx) => tx.rollback(),
});

class AccountService {
  @Transactional()
  async transfer(fromId: string, toId: string, amount: number) {
    const tx = TransactionManager.getTransaction();
    await db.debit(fromId, amount, tx);
    await db.credit(toId, amount, tx);
  }
}

6. Security & Governance

@Authorize & @Roles

Declarative role-based access control and permission checking:

import { Authorize, Roles, SecurityContext } from '@thekosmix/node-decorators';

class DocumentService {
  @Roles('ADMIN', 'EDITOR')
  editDocument(docId: string) { ... }

  @Authorize({ permissions: ['docs:publish'] })
  publishDocument(docId: string) { ... }
}

@Audit

Automatic compliance audit logging:

import { Audit, AuditManager } from '@thekosmix/node-decorators';

AuditManager.setHandler(async (record) => {
  await auditDb.insert(record);
});

class AdminService {
  @Audit({ action: 'PROMOTE_USER', actor: (adminId) => adminId, target: (_, userId) => userId })
  promoteUser(adminId: string, userId: string, newRole: string) { ... }
}

@FeatureFlag

Dynamic feature toggling and fallback routing:

import { FeatureFlag, FeatureFlagManager } from '@thekosmix/node-decorators';

FeatureFlagManager.setFlag('v2-pricing', true);

class BillingService {
  @FeatureFlag('v2-pricing', { fallback: () => 100 })
  calculatePricing(plan: string) {
    return 150;
  }
}

7. Traffic Management & Performance

@SingleFlight

Coalesces concurrent in-flight calls for identical keys into a single execution to prevent the "thundering herd" problem:

import { SingleFlight } from '@thekosmix/node-decorators';

class NewsService {
  @SingleFlight((articleId) => articleId)
  async getTrendingArticle(articleId: string) {
    // 50 simultaneous callers will only execute this query once!
    return db.queryArticle(articleId);
  }
}

@Debounce & @Throttle

import { Debounce, Throttle } from '@thekosmix/node-decorators';

class EditorService {
  @Debounce(300)
  autoSave(document: any) { ... }

  @Throttle(1000)
  syncCursor(position: any) { ... }
}

8. Validation, Diagnostics & Fallback

  • @Validate(schema): Validates arguments before execution (supports Zod, Joi, or custom predicates).
  • @Timed() / @MeasureTime(): High-precision execution duration tracking.
  • @Catch(handler) & @Fallback(value): Intercept exceptions and return graceful fallbacks without try/catch.
  • @Length(min, max): Validates property length constraints.
  • @Async: Defer method execution to the next event loop tick and return a Promise.
  • @Rest: Expose methods as REST endpoints with startRestServer(3000).

License

MIT