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 🙏

© 2025 – Pkg Stats / Ryan Hefner

@cargolift-cdi/common

v1.0.93

Published

Common utilities and error handling for Cargolift CDI projects

Readme

@cargolift-cdi/common

Utilidades comuns e padronização de erros para projetos Cargolift CDI (NestJS).

Este pacote provê:

  • Classes de erro de domínio (BusinessError) com código, dados adicionais e causa encadeada
  • Filtro global de exceções para APIs (APIExceptionsFilter) já integrado ao util-logger

Instalação

Requisitos:

  • Node.js LTS (18+) e npm
  • Peer dependency: @nestjs/common@^11

Instale:

npm i @cargolift-cdi/common

O pacote depende de @cargolift-cdi/util-logger (instalado automaticamente).

Uso rápido

1) Aplicar o filtro global de exceções (NestJS)

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { APIExceptionsFilter } from '@cargolift-cdi/common';
import { LoggerContextService } from '@cargolift-cdi/util-logger';

async function bootstrap() {
  const app = await NestFactory.create(AppModule, { bufferLogs: true });

  // Usa o LoggerContextService já registrado no container
  const logger = app.get(LoggerContextService);
  app.useGlobalFilters(new APIExceptionsFilter(logger));

  await app.listen(3000);
}

bootstrap();

O filtro padroniza o payload de erro, enriquece logs com correlation_id e trata mensagens conhecidas (ex.: erros de rede).

Alternativa: registrar via provider global (APP_FILTER):

import { Module } from '@nestjs/common';
import { APP_FILTER } from '@nestjs/core';
import { APIExceptionsFilter } from '@cargolift-cdi/common';
// Certifique-se de que o LoggerContextService esteja disponível no container
import { LoggerContextService } from '@cargolift-cdi/util-logger';

@Module({
  providers: [
    LoggerContextService, // ou importe o módulo que o fornece, se existir
    { provide: APP_FILTER, useClass: APIExceptionsFilter },
  ],
})
export class AppModule {}

2) Lançar erros de negócio no seu código

import { NotFoundBusinessError, GenericBusinessError } from '@cargolift-cdi/common';

// Recurso não encontrado
throw new NotFoundBusinessError('Order', '12345');

// Erro de negócio genérico com código e dados extras
throw new GenericBusinessError('Falha no provedor', {
  code: 'PAYMENT_PROVIDER_ERROR',
  data: { context: 'Pagamento', errorCode: 'PX-999', provider: 'AcmePay' },
});

API pública (exportada por index)

  • BusinessError (abstrata)
    • Base para erros de domínio. Suporta code?: string, data?: Record<string, unknown>, cause?: unknown e serialização segura via toJSON().
  • GenericBusinessError
    • Erro de negócio genérico (mensagem padrão "Generic Business error" quando não informada). Útil para normalizar exceções desconhecidas.
  • NotFoundBusinessError
    • Especialização para recursos não encontrados: construtor (resourceType: string, resourceId: string|number, message?, options?).
  • APIExceptionsFilter (NestJS)
    • Filtro global de exceções. Decide tipo do erro (business/application), aplica códigos padrão e registra logs estruturados via LoggerContextService.

Observação: existem classes internas adicionais (ex.: ApplicationError, GenericApplicationError) que podem evoluir; utilize apenas a API pública acima para evitar quebras.

Contexto de Logs com AsyncLocalStorage (v2)

A partir da versão que introduz esta seção, o LoggerContextService passou a ser singleton (escopo DEFAULT) e o isolamento por requisição/mensagem é garantido via AsyncLocalStorage.

Benefícios:

  • Menos alocações de instâncias (melhor para alto throughput)
  • Propagação automática de contexto por callbacks/promises sem passar manualmente
  • Publishers/clients apenas usam logger.getContext()

Helpers exportados:

import { runWithLoggerContext, getLoggerContext, updateLoggerContext } from '@cargolift-cdi/common';

runWithLoggerContext({ correlation_id: 'abc' }, () => {
  // Tudo aqui dentro (e awaits) mantém o contexto
});

Fluxo HTTP (middleware APILoggerMiddleware):

  1. Abre runWithLoggerContext({})
  2. Chama logger.setContextRequest(req) (gera/propaga correlation_id e trace)
  3. Todos os logs subsequentes compartilham o mesmo contexto

Fluxo RabbitMQ (consumer):

  1. Cria um child logger a partir dos headers da mensagem (childFromRabbit)
  2. Semeia o ALS com runWithLoggerContext(child.getContext(), processMessage)
  3. Dentro do processamento usa-se o logger base normalmente

Caso precise anexar dados adicionais no meio da execução:

updateLoggerContext({ caller_info: { type: 'user', id: 'u-1' } });

Se um log for emitido fora de um escopo ALS (ex.: antes de bootstrap), o logger ainda funcionará, porém sem correlation_id fixo (um novo poderá ser gerado quando o contexto for definido).

Detalhes das classes

BusinessError

Contrato básico:

  • name: string — Nome da classe (ex.: NotFoundBusinessError)
  • message?: string — Mensagem humana
  • code?: string — Ex.: BUSINESS_RESOURCE_NOT_FOUND, INVALID_PAYLOAD
  • data?: Record<string, unknown> — Dados serializáveis extras
  • cause?: unknown — Erro original para encadeamento
  • toJSON() — Retorna objeto serializável, inclusive com stack enumerável e cause segura

BusinessErrorOptions:

type BusinessErrorOptions = {
  code?: string;
  cause?: unknown;
  data?: Record<string, unknown>;
};

NotFoundBusinessError

  • Código padrão: BUSINESS_RESOURCE_NOT_FOUND
  • data: { resourceType: string, resourceId: string|number }

GenericBusinessError

  • Código padrão: BUSINESS_ERROR
  • Permite enviar data adicional e causa original (cause).

APIExceptionsFilter

  • Inspeciona exceções do NestJS (HttpException) e erros comuns de infraestrutura (ex.: ECONNREFUSED, ETIMEDOUT)
  • Cria/propaga correlation_id no contexto de log
  • Resposta JSON padrão:
{
  "message": "<mensagem>",
  "error": {
    "statusCode": 500,
    "timestamp": "2025-01-01T00:00:00.000Z",
    "path": "/rota",
    "errorCode": "INTERNAL_ERROR"
  }
}

App Logger (Global)

Use AppLoggerModule para configurar um log global com contexto.

import { AppLoggerModule, APP_LOGGER, LoggerContextService } from '@cargolift-cdi/common';

@Module({
  imports: [
    AppLoggerModule.forRoot({
      application: {
        name: 'middleware-esb',
        function: 'service',
      },
    }),
  ],
})
export class AppModule {}

@Injectable()
export class SomeService {
  constructor(@Inject(APP_LOGGER) private readonly appLogger: LoggerContextService) {}

  doStuff() {
    this.appLogger.log('App level log');
  }
}

Notes:

  • Este log possui um contexto único; não chame setContext.
  • Para logs por mensagem/requisição , use a versão de escopo TRANSIENT LoggerContextService e chame setContextRabbitMQ/setContextRequest.

Scripts do projeto

  • npm run build — Compila TypeScript para dist/
  • npm publish — Publica (executa build no prepublishOnly)

Contribuição

  • Abra issues e PRs no GitHub: https://github.com/cargolift-cdi/common
  • Padrões: TypeScript, NestJS 11, commits claros, linters/formatters do seu editor

Licença

MIT © Cargolift CDI