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

@devoven/common

v0.0.2

Published

Shared types and utilities for the NestJS monorepo

Downloads

18

Readme

@devoven/common

Shared types and utilities for NestJS applications. Not a NestJS module — exports individual components you import directly.

Installation

npm install @devoven/common
# or
pnpm add @devoven/common

Peer dependencies

Requires the standard NestJS peer dependencies (@nestjs/common, @nestjs/core), which any NestJS application already has. No additional peer deps are needed.

No module registration is required. Import each export directly where you need it.

PaginatedResult

A value object for paginated list responses.

import { PaginatedResult } from '@devoven/common';

const result = PaginatedResult.create(items, total, page, pageSize);
// or an empty page:
const empty = PaginatedResult.empty(1, 20);

| Property / Method | Type | Description | |-------------------|------|-------------| | data | T[] | Items on the current page | | total | number | Total number of items across all pages | | page | number | Current page (1-based) | | pageSize | number | Maximum items per page | | totalPages | number (computed) | Math.ceil(total / pageSize) | | hasNextPage | boolean (computed) | page < totalPages | | hasPreviousPage | boolean (computed) | page > 1 | | PaginatedResult.create(data, total, page, pageSize) | static | Validates inputs and returns an instance | | PaginatedResult.empty(page?, pageSize?) | static | Returns an empty result (defaults: page 1, pageSize 20) |

create throws if page < 1, pageSize < 1, or total < 0.

PaginationOptions

An interface for query parameters passed to list endpoints or repository methods.

import { PaginationOptions, ESortOrder } from '@devoven/common';

const opts: PaginationOptions = {
  page: 2,
  pageSize: 10,
  sortBy: 'createdAt',
  sortOrder: ESortOrder.DESC,
};

| Field | Type | Description | |-------|------|-------------| | page | number (optional) | Page number (1-based) | | pageSize | number (optional) | Items per page | | sortBy | string (optional) | Field name to sort by | | sortOrder | ESortOrder (optional) | ESortOrder.ASC ('asc') or ESortOrder.DESC ('desc') |

TransactionPort

An abstract interface for executing code inside a transaction. Use it as the port your use cases depend on.

import type { TransactionPort } from '@devoven/common';
import { TOKENS } from '@devoven/common';
import { Inject, Injectable } from '@nestjs/common';

@Injectable()
export class CreateOrderUseCase {
  constructor(
    @Inject(TOKENS.TransactionPort)
    private readonly tx: TransactionPort,
  ) {}

  async execute(): Promise<void> {
    await this.tx.execute(async () => {
      // all operations here run in one transaction
    });
  }
}

| Method | Signature | Description | |--------|-----------|-------------| | execute | (fn: () => Promise<T>, options?: TransactionOptions) => Promise<T> | Run the function inside a transaction |

TransactionOptions has a single optional field: timeout?: number (milliseconds).

DI token: TOKENS.TransactionPort (a Symbol).

TransactionalClientPort

A lower-level interface for ORM clients that support internal $transaction calls. Used by PrismaTransaction to create a nested transaction context.

export interface TransactionalClientPort {
  $transaction<TClient, TResult>(
    fn: (client: TransactionalClientPort & TClient) => Promise<TResult>,
    options?: TransactionOptions,
  ): Promise<TResult>;
}

PrismaTransaction

A TransactionPort implementation backed by Prisma. Uses AsyncLocalStorage to propagate the transactional Prisma client through the call stack, so nested execute calls reuse the existing transaction instead of opening a new one.

Rollback: Prisma's $transaction automatically rolls back all operations if the callback throws. No explicit rollback call is needed — simply let the error propagate out of the execute callback.

import { PrismaTransaction } from '@devoven/common';
import { TOKENS } from '@devoven/common';

// In your app module:
{
  provide: TOKENS.TransactionPort,
  useFactory: (prisma: PrismaService) => new PrismaTransaction(prisma),
  inject: [PrismaService],
}

Retrieve the active client (transactional or root) via prismaTransaction.getClient() in your repository:

@Injectable()
export class PrismaOrderRepository implements OrderRepositoryPort {
  constructor(
    private readonly prisma: PrismaService,
    private readonly tx: PrismaTransaction,
  ) {}

  async save(order: Order): Promise<void> {
    const client = this.tx.getClient(); // returns tx client if inside a transaction
    await client.order.create({ /* ... */ });
  }
}

NoopTransaction

A TransactionPort implementation that executes the callback directly without any wrapping transaction. Useful in tests or when your storage does not support transactions.

import { NoopTransaction } from '@devoven/common';
import { TOKENS } from '@devoven/common';

{
  provide: TOKENS.TransactionPort,
  useClass: NoopTransaction,
}

HttpExceptionFilter

A global ExceptionFilter that normalises all thrown exceptions into a consistent JSON error shape.

import { HttpExceptionFilter } from '@devoven/common';

// Register globally in main.ts
app.useGlobalFilters(new HttpExceptionFilter());

// Enable debug mode (logs method, path, and timestamp in the response body)
app.useGlobalFilters(new HttpExceptionFilter({ debug: true }));

Response shape:

{
  "statusCode": 404,
  "message": "Role \"editor\" not found",
  "error": "Not Found"
}

With debug: true an additional debug field is included:

{
  "statusCode": 404,
  "message": "Role \"editor\" not found",
  "error": "Not Found",
  "debug": {
    "method": "GET",
    "path": "/roles/editor",
    "timestamp": "2025-01-15T10:30:00.000Z"
  }
}

Non-HttpException errors produce a 500 response with message "Internal server error". HttpExceptionFilter logs 5xx errors at the error level and 4xx errors at the warn level.

| Option | Type | Default | Description | |--------|------|---------|-------------| | debug | boolean | false | Include request context in error responses and log the raw exception |

Architecture

@devoven/common contains only framework-agnostic value objects, port interfaces, and thin infrastructure adapters. It has no NestJS module, no controllers, and no DI wiring — consumers wire everything themselves.

Exports at a Glance

| Export | Category | |--------|----------| | PaginatedResult<T> | Domain value object | | PaginationOptions, ESortOrder | Domain types | | TransactionPort, TransactionalClientPort | Application port interfaces | | TransactionOptions | Application type | | PrismaTransaction<T> | Infrastructure adapter | | NoopTransaction | Infrastructure adapter (testing) | | HttpExceptionFilter, HttpExceptionFilterOptions | Presentation filter | | TOKENS | DI token constants |