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

caserita-infra

v0.13.4

Published

Library infra caserita

Readme

🗺️ Índice

Caserita Infra

NestJS is a utility and package library designed to simplify and standardize the development of microservices with a hexagonal or n-tier architecture, using NestJS and TypeScript. Package management is handled with pnpm, ensuring rapid installation and efficient use of disk space.

📄 Requirements

  • Node.js >= 22.14.0
  • pnpm >= 10.x

🚀 Installation

# Install dependencies
pnpm install

# Development
pnpm run start:dev

# Production
pnpm run start:prod

# Build
pnpm run build

🌎 Publication

# Increase a version path (1.0.0) -> (1.0.1)
$ pnpm version patch

# Increase a minor version (1.0.0) -> (1.1.0)
$ pnpm version minor

# Increase a major version (1.0.0) -> (2.0.0)
$ pnpm version major

# Increase a specific version (1.0.0) -> (3.1.1)
$ pnpm version <version>

# Publish the package
$ pnpm publish

📖 Project Structure

The repository is organized into two main directories:

  • libs/: Contains reusable modules and packages for various functionalities.
  • src/: Includes the source code for how to use these libraries and how to test them.
[libs]/
├── [adapter]/           # [Adapters for external transport services, such as NATS, Kafka, SMTP, for microservices.]
├── [cdecorator]/        # [Provides custom decorators for NestJS.]
├── [common-cache]/      # [Functions for cache management, such as REDIS or local.]
├── [common-database]/   # [This module facilitates interaction with the database]
├── [common-encrypted]/  # [Utilities for data encryption and decryption.]
├── [common-http]/       # [Centralizes utilities for handling HTTP requests and responses]
├── [common-logger]/     # [Provides a unified logging system, crucial for application monitoring and debugging.]
├── [common-response]/   # [Standardized response structures for APIs, Events, such as success and error.]
├── [common-search]/     # [Advanced search logic, with respect to databases.]
└── index.ts             # [Main entry point]

Usage/Examples

adapter

Adapters for external transport services, such as NATS, Kafka, SMTP, for microservices.

Use:

The way to inject the module:

natsTransport.module.ts

import { Module } from '@nestjs/common';
import { ClientsModule } from '@nestjs/microservices';
import { AdapterModule, Adapter } from 'caserita-infra/packages/adapter';
import { NATS_MS_SERVICE_INJECT } from '@app/utils/constants.util'

@Module({
  imports: [
    AdapterModule,
    ClientsModule.registerAsync([
      {
        name: NATS_MS_SERVICE_INJECT,
        useFactory: (adapter: Adapter) => {
          const natsConfig = adapter.config();
          return natsConfig;
        },
        inject: [Adapter],
      },
    ]),
  ],
  exports: [ClientsModule],
})
export class NatsTransportModule {}

How to use the module on the client:

caseritaTaxidentityvalidationMsEvent.client.ts

import { Inject, Injectable } from "@nestjs/common";
import { ConfigService } from '@nestjs/config';
import { ClientProxy } from '@nestjs/microservices';
import { firstValueFrom } from 'rxjs';
import { NATS_MS_SERVICE_INJECT } from '@app/utils/constants.util';
import { CaseritaTaxidentityvalidationMsService } from "@domain/caseritaTaxidentityvalidationMs.service";
import { CaseritaTaxidentityvalidationMsFindCompanyByRucRequest } from "@domain/interfaces/caseritaTaxidentityvalidationMsFindCompanyByRucRequest.interface";
import { CaseritaTaxidentityvalidationMsFindCompanyByRucResponse } from "@domain/interfaces/caseritaTaxidentityvalidationMsFindCompanyByRucResponse.interface";

@Injectable()
export class CaseritaTaxidentityvalidationMsEventClient implements CaseritaTaxidentityvalidationMsService {
  private caseritaTaxIdentityValidationMsFindCompayByRuc: string;
  private caseritaTaxIdentityValidationMsFindLegalRepresentativeByRuc: string;
  private caseritaTaxIdentityValidationMsFindPersonByDni: string;

  constructor(
    private readonly configService: ConfigService,
    @Inject(NATS_MS_SERVICE_INJECT) private readonly client: ClientProxy
  ) {
    this.caseritaTaxIdentityValidationMsFindCompayByRuc = this.configService.get<string>('CASERITA_TAXIDENTITYVALIDATION_MS_FIND_COMPANY_BY_RUC');
    this.caseritaTaxIdentityValidationMsFindLegalRepresentativeByRuc = this.configService.get<string>('CASERITA_TAXIDENTITYVALIDATION_MS_FIND_LEGAL_REPRESENTATIVE_BY_RUC');
    this.caseritaTaxIdentityValidationMsFindPersonByDni = this.configService.get<string>('CASERITA_TAXIDENTITYVALIDATION_MS_FIND_PERSON_BY_DNI');
  }

  findCompanyByRuc(input: CaseritaTaxidentityvalidationMsFindCompanyByRucRequest): Promise<CaseritaTaxidentityvalidationMsFindCompanyByRucResponse> {
    const { ruc } = input;
    return firstValueFrom(this.client.send({ cmd: this.caseritaTaxIdentityValidationMsFindCompayByRuc }, { ruc }));
  }
}

Environments:

This package uses the following variables:

.env  .env.development.local

NATS_SERVERS="nats://localhost:4222"

cdecorator

Provides custom decorators for NestJS.

Use:

How to use the module on the controller:

store.controller.ts

import { Controller,  Post } from '@nestjs/common';
import { CommandBus, QueryBus } from '@nestjs/cqrs';
import { ValidateBody } from 'caserita-infra/packages/cdecorator';
import { CreateCommandImpl } from '@app/commands/impl/create-command.impl';
import { CreateInputValidator } from '@infra/validators/create.input.validator';
import { CreateStoreRequest } from '@domain/interfaces/createStoreRequest.interface';

@Controller('stores')
export class StoreController {
  constructor(
    private readonly commandBus: CommandBus,
    private readonly queryBus: QueryBus,
  ) {}

  @Post('/create')
  create(@ValidateBody(CreateInputValidator) input: CreateStoreRequest) {
    return this.commandBus.execute(new CreateCommandImpl(input));
  }
}

common-cache

Functions for cache management, such as REDIS or local.

Use:

The way to inject the module:

app.module.ts

import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import { CommonCacheModule } from '@caserita/common-cache';
import { AppController } from './app.controller';
import { AppHandler } from './app.handler';
import { AppService } from './app.service';
import { AppRepository } from './app.repository';

@Module({
  imports: [
    ConfigModule.forRoot({ isGlobal: true, cache: true }),
    CommonCacheModule,
  ],
  controllers: [AppController, AppHandler],
  providers: [AppService, AppRepository],
})
export class AppModule {}

How to use the module on the service:

app.service.ts

import { ConfigService } from '@nestjs/config';
import { Injectable } from '@nestjs/common';
import { RedisCacheService } from '@caserita/common-cache';
import { AppRepository } from './app.repository';

@Injectable()
export class AppService {
  private baseUrl: string;
  constructor(
    private readonly configService: ConfigService,
    private readonly cacheService: RedisCacheService,
    private readonly appRepository: AppRepository,
  ) {
    this.baseUrl = this.configService.get<string>('BASE_URL_DATTEBAYO');
  }

  async getRedisCloud() {
    return this.cacheService.get('HOLA:1236');
  }

  async setRedisCloud() {
    await this.cacheService.set('HOLA:1239', { A: '1234', B: 'xyz' }, 300); //ttl 300 equivale a 5 minutos
  }
}

Environments:

This package uses the following variables:

.env  .env.development.local

REDIS_CLOUD_HOST=example.redis-cloud.com
REDIS_CLOUD_PORT=18472
REDIS_CLOUD_PASSWORD=vHqWgOtqqZXoA18km0Y76XiI4iNnr8DZ
REDIS_CLOUD_TTL= 300
REDIS_NUMBER_DB=

common-database

This module facilitates interaction with the database

Use:

The way to inject the module:

app.module.ts

import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import {
  CommonDatabaseModule,
  DatabaseConnectionType,
  DatabaseEnumType,
} from '@caserita/common-database';
// import { CommonCacheModule } from '@caserita/common-cache';
import { CommonEncryptedModule, EncryptedProviderType, ValueTransformer, HashTransformer } from '@caserita/common-encrypted';
import { AppController } from './app.controller';
import { AppHandler } from './app.handler';
import { EntityModule } from './entity/entity.module';
import { AppService } from './app.service';
import { AppRepository } from './app.repository';
import { AppEntity } from './entity/app.entity';
import { AppPostgresEntity } from './entity/appPostgres.entity';

@Module({
  imports: [
    ConfigModule.forRoot({ isGlobal: true, cache: true }),
    CommonDatabaseModule.register([
      {
        name: DatabaseConnectionType.MONGODB_CONNECTION,
        type: DatabaseEnumType.MONGODB,
        entities: [AppEntity],
      },
      {
        name: DatabaseConnectionType.POSTGRES_CONNECTION,
        type: DatabaseEnumType.POSTGES,
        entities: [AppPostgresEntity],

        // If you need to encrypt data in SQL
        imports: [CommonEncryptedModule.register(EncryptedProviderType.DATABASE)],
        inject: [ValueTransformer, HashTransformer],
        columnsTransformers: ['fieldencrypt', 'fieldencrypt_index', 'fieldencrypttwo'],
      },
    ]),
    EntityModule,
  ],
  controllers: [AppController, AppHandler],
  providers: [AppService, AppRepository],
})
export class AppModule {}

How to use the module on the entity:

entity.module.ts

import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { DatabaseConnectionType } from '@caserita/common-database';
import { AppEntity } from './app.entity';
import { AppPostgresEntity } from './appPostgres.entity';

// The "forFeature" already creates the providers (the repositories)
const mongoRepositoryModule = TypeOrmModule.forFeature([AppEntity], DatabaseConnectionType.MONGODB_CONNECTION);
const postgresRepositoryModule = TypeOrmModule.forFeature([AppPostgresEntity], DatabaseConnectionType.POSTGRES_CONNECTION);

@Module({
  imports: [mongoRepositoryModule, postgresRepositoryModule],
  // This is where the change lies: you must export the entity classes that act as
  // tokens for the repositories. This causes TypeOrmModule to expose the repositories
  // created in the "imports" process.
  exports: [mongoRepositoryModule, postgresRepositoryModule],
})
export class EntityModule {}

Environments:

This package uses the following variables:

.env  .env.development.local

# MONGO DATABASE
DB_USER_MONGO=example
DB_KEY_MONGO=7247uriu2482rw247
DB_HOST_MONGO=example.mongodb.net
DB_CONTAINER_NAME_MONGO=cstainfradbdev
DB_SYNCHRONIZE_MONGO=true

# POSTGRES DATABASE
DB_HOST_POSTGRES=example.supabase.com
DB_PORT_POSTGRES=6543
DB_USERNAME_POSTGRES=postgres.qsyvlxmwyodpyevujbgx
DB_PASSWORD_POSTGRES=7247uriu2482rw247
DB_CONTAINER_NAME_POSTGRES=cstainfradbdev
DB_SYNCHRONIZE_POSTGRES=true

# ENCRYPTION DATBASE SQL
ENCRYPT_DATABASE_SECRET_KEY=xDkjHdp132nRLBjUOcvHGAJzb7dGmt

common-encrypted

Utilities for data encryption and decryption.

Use:

The way to inject the module:

app.module.ts

import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import { CommonEncryptedModule, EncryptedProviderType } from '@caserita/common-encrypted';
import { AppController } from './app.controller';
import { AppHandler } from './app.handler';
import { AppService } from './app.service';
import { AppRepository } from './app.repository';

@Module({
  imports: [
    ConfigModule.forRoot({ isGlobal: true, cache: true }),
    CommonEncryptedModule.register(EncryptedProviderType.APP),
  ],
  controllers: [AppController, AppHandler],
  providers: [AppService, AppRepository],
})
export class AppModule {}

How to use the module on the service:

app.service.ts

import { ConfigService } from '@nestjs/config';
import { Injectable } from '@nestjs/common';
import { CipherEngine } from '@caserita/common-encrypted';
import { AppRepository } from './app.repository';

@Injectable()
export class AppService {
  private baseUrl: string;
  constructor(
    private readonly configService: ConfigService,
    private readonly cipherEngine: CipherEngine,
    private readonly appRepository: AppRepository,
  ) {
    this.baseUrl = this.configService.get<string>('BASE_URL_DATTEBAYO');
  }

  async encryption(entry: string) {
    return this.cipherEngine.encrypt(entry);
  }

  async decryptyion(entry: string) {
    return this.cipherEngine.decrypt(entry);
  }
}

Environments:

This package uses the following variables:

.env  .env.development.local

ENCRYPT_SECRET_KEY=WwMIK54FypnmSR1JPSCdcwxcwCl2cA
ENCRYPT_DATABASE_SECRET_KEY=xDkjHdp132nRLBjUOcvHGAJzb7dGmt

common-http

Centralizes utilities for handling HTTP requests and responses

Use:

The way to inject the module:

app.module.ts

import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import { CommonHttpModule } from '@caserita/common-http';
import { AppController } from './app.controller';
import { AppHandler } from './app.handler';
import { AppService } from './app.service';
import { AppRepository } from './app.repository';

@Module({
  imports: [
    ConfigModule.forRoot({ isGlobal: true, cache: true }),
    CommonHttpModule,
  ],
  controllers: [AppController, AppHandler],
  providers: [AppService, AppRepository],
})
export class AppModule {}

How to use the module on the client:

app.service.ts

import { ConfigService } from '@nestjs/config';
import { HttpException, Injectable } from '@nestjs/common';
import { catchError, firstValueFrom } from 'rxjs';
import { AxiosError } from 'axios';
import { HttpClient } from '@caserita/common-http';

@Injectable()
export class AppService {
  private baseUrl: string;
  constructor(
    private readonly httpClient: HttpClient,
    private readonly configService: ConfigService,
  ) {
    this.baseUrl = this.configService.get<string>('BASE_URL_DATTEBAYO');
  }

  async proxy() {
    return firstValueFrom(
      this.httpClient.get(`${this.baseUrl}/characters/1344`).pipe(
        catchError((error: AxiosError) => {
          throw new HttpException(
            {
              errorCode: error.code,
              message: error.response.data,
              stack: error.stack,
            },
            error.status,
          );
        }),
      ),
    );
  }
}

common-logger

Provides a unified logging system, crucial for application monitoring and debugging.

Use:

The way to inject the module:

app.module.ts

import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import { CommonLoggerModule } from '@caserita/common-logger';
import { AppController } from './app.controller';
import { AppHandler } from './app.handler';
import { AppService } from './app.service';
import { AppRepository } from './app.repository';

@Module({
  imports: [
    ConfigModule.forRoot({ isGlobal: true, cache: true }),
    CommonLoggerModule,
  ],
  controllers: [AppController, AppHandler],
  providers: [AppService, AppRepository],
})
export class AppModule {}

How to use the module on the use-case:

create-command.handler.ts

import { CommandHandler, ICommandHandler } from '@nestjs/cqrs';
import { Logger } from '@nestjs/common';
import { CreateCommandImpl } from '@app/commands/impl/create-command.impl';
import { ExpedientService } from '@domain/expedient.service';
import { CaseritaBusinessAccountMsService } from '@domain/caseritaBusinessAccountMs.service';
import { Expedient } from '@domain/entities/expedient.entity';
import { ExpedientTracing } from '@domain/entities/expedientTracing.entity';
import { DatosEmpresa } from '@domain/entities/datosEmpresa';
import { DatosRepresentanteLegal } from '@domain/entities/datosRepresentanteLegal';
import { Archivo } from '@domain/entities/archivo.entity';
import { EstadoExpediente } from '@domain/emun/estadoExpediente.enum';
import { TipoDocumento } from '@domain/emun/tipoDocumento.enum';

@CommandHandler(CreateCommandImpl)
export class CreateCommandHandler implements ICommandHandler<CreateCommandImpl> {
  private readonly logger = new Logger('CreateCommandHandler');

  constructor(
    private readonly service: ExpedientService,
    private readonly caseritaBusinessAccountMs: CaseritaBusinessAccountMsService,
  ) {}

  async execute({ command }: CreateCommandImpl): Promise<void> {
    const expedient = new Expedient();
    const expedientTracing = new ExpedientTracing();
    const datosEmpresa = new DatosEmpresa();
    const datosRepresentanteLegal = new DatosRepresentanteLegal();
    const archivo = new Archivo();
    const archivos: Archivo[] = [];

    expedient.estado = EstadoExpediente.CREADO;
    expedient.codigoExpediente = this.generateCodeExpediente(
      command.datosEmpresa.numeroDocumento,
      command.datosRepresentanteLegal.numeroDocumento,
    );

    datosEmpresa.tipoDocumento = TipoDocumento.RUC;
    datosEmpresa.numeroDocumento = command.datosEmpresa.numeroDocumento;

    datosRepresentanteLegal.tipoDocumento = TipoDocumento.DNI;
    datosRepresentanteLegal.numeroDocumento = command.datosRepresentanteLegal.numeroDocumento;
    datosRepresentanteLegal.fechaNacimiento = command.datosRepresentanteLegal.fechaNacimiento;
    datosRepresentanteLegal.correoElectronico = command.datosRepresentanteLegal.correoElectronico;
    datosRepresentanteLegal.direccion = command.datosRepresentanteLegal.direccion;
    datosRepresentanteLegal.telefono = command.datosRepresentanteLegal.telefono;

    for (const a of command.archivos) {
      archivo.nombreArchivo = a.nombreArchivo;
      archivo.url = a.url;
      archivo.tipoArchivo = a.tipoArchivo;
      archivo.fechaSubida = a.fechaSubida;

      archivos.push(archivo);
    }

    expedient.datosEmpresa = datosEmpresa;
    expedient.datosRepresentanteLegal = datosRepresentanteLegal;
    expedient.archivos = archivos;

    const result = await this.service.create(expedient);
    this.logger.log('[CreateCommandImpl - CREATE EXPEDIENTE]: Se creo el expediente con éxito');

    // Envio mensaje service bus para proceso asincrono de creacion de cuenta negocio
    this.logger.log('[CreateCommandImpl - SEND CREATE ASYNC BUSINESS ACCOUNT]');
    this.caseritaBusinessAccountMs.create({ idExpediente: expedient.idExpediente, idEmpresa: expedient.codigoExpediente });

    expedientTracing.codigoExpediente = result.codigoExpediente;
    expedientTracing.estado = EstadoExpediente.CREADO;
    expedientTracing.ruc = datosEmpresa.numeroDocumento;
    expedientTracing.dni = datosRepresentanteLegal.numeroDocumento;
    expedientTracing.fechaCreacion = result.fechaCreacion.toISOString();

    await this.service.createTracing(expedientTracing);
    this.logger.log(
      '[CreateCommandImpl - CREATE EXPEDIENTE TRACING]: Se creo el trazado del expediente con éxito',
    );
  }

  private generateCodeExpediente(rucNumber: string, dniNumber: string) {
    return `${TipoDocumento.RUC}${rucNumber}${TipoDocumento.DNI}${dniNumber}`;
  }
}

Environments:

This package uses the following variables:

.env  .env.development.local

LOGGER_LEVEL=info
LOGGER_ENABLED=true    # false
LOGGER_CLOUD=logtail   # local -> TOKEN_LOGTAIL_LOGGER is empty
TOKEN_LOGTAIL_LOGGER=82jk4y28y283yru2734728

common-response

Standardized response structures for APIs, Events, such as success and error.

common-response

Advanced search logic, with respect to databases.

📝 Environment Variables

To run this project, you will need to add the following environment variables to your .env.development.local file

.env.development.local

# APP
MICROSERVICE_NAME=INFRA
APP_RUNNING_ENV=HTTP # NATS
NODE_ENV=development # production
PORT=8080

# NATS
NATS_SERVERS="nats://localhost:4222"

# LOGGER
LOGGER_LEVEL=info
LOGGER_ENABLED=true
LOGGER_CLOUD=logtail
TOKEN_LOGTAIL_LOGGER=******

# DATABASE
DB_USER_MONGO=******
DB_KEY_MONGO=******
DB_HOST_MONGO=******
DB_CONTAINER_NAME_MONGO=******

# POSTGRES DATABASE
DB_HOST_POSTGRES=******
DB_PORT_POSTGRES=******
DB_USERNAME_POSTGRES=******
DB_PASSWORD_POSTGRES=******
DB_CONTAINER_NAME_POSTGRES=******
DB_SYNCHRONIZE_POSTGRES=******

# ENCRYPTION
ENCRYPT_SECRET_KEY=******
ENCRYPT_DATABASE_SECRET_KEY=******

# CACHE REDIS
REDIS_CLOUD_HOST=******
REDIS_CLOUD_PORT=******
REDIS_CLOUD_PASSWORD=******
REDIS_CLOUD_TTL= 300
REDIS_NUMBER_DB=

# PROXIES
BASE_URL_DATTEBAYO=https://dattebayo-api.onrender.com

🛠️ Scripts Disponibles

Here are some related projects

# Desarrollo
pnpm run start:dev      # Ejecuta en modo desarrollo con watch
pnpm run start          # Ejecuta en modo normal
pnpm run start:prod     # Ejecuta en modo producción

# Build
pnpm run build          # Compila el proyecto

# Testing
pnpm run test           # Ejecuta tests unitarios
pnpm run test:watch     # Ejecuta tests en modo watch
pnpm run test:e2e       # Ejecuta tests end-to-end
pnpm run test:cov       # Ejecuta tests con coverage

# Linting y Formato
pnpm run lint           # Ejecuta ESLint
pnpm run format         # Formatea código con Prettier

🚀 Deployment

To deploy this project with docker:


FROM node:18-alpine

WORKDIR /app

# Instalar pnpm
RUN npm install -g pnpm

# Copiar archivos de dependencias
COPY package.json pnpm-lock.yaml ./

# Instalar dependencias
RUN pnpm install --frozen-lockfile

# Copiar código fuente
COPY . .

# Build
RUN pnpm run build

# Exponer puerto
EXPOSE 3000

# Comando de inicio
CMD ["pnpm", "run", "start:prod"]

docker-compose:


version: '3.8'
services:
  app:
    build: .
    ports:
      - "3000:3000"
    environment:
      - NODE_ENV=production
      - DATABASE_URL=postgresql://postgres:password@db:5432/caserita
    depends_on:
      - db
      - redis

  db:
    image: postgres:15
    environment:
      POSTGRES_DB: caserita
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: password
    ports:
      - "5432:5432"
    volumes:
      - postgres_data:/var/lib/postgresql/data

  redis:
    image: redis:7-alpine
    ports:
      - "6379:6379"

volumes:
  postgres_data:

😁 Authors