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

@ferreirasw/yoke-common

v0.5.0

Published

Shared utilities, types, and messaging infrastructure for Yoke microservices

Readme

@ferreirasw/yoke-common

Shared utilities, types, and messaging infrastructure for Yoke microservices.

Installation

npm install @ferreirasw/yoke-common

Features

  • Enums: Shared enums for business logic (Modality, TaxRegime, RiskProfile, Status enums, etc.)
  • Messaging: RabbitMQ infrastructure with exchanges, routing keys, and message types
  • DTOs: Standardized DTOs for pagination and API responses
  • Filters: Global exception filters for consistent error handling
  • Interceptors: Logging interceptors for request/response tracking
  • Utilities: Common validation and formatting utilities (CPF, CNPJ, currency, etc.)

Table of Contents

Enums

All shared enums for consistent business logic across microservices.

Usage Example

import {
  Modality,
  TaxRegime,
  RiskProfile,
  ProductStatus,
  QuotationStatus,
} from '@ferreirasw/yoke-common';

// Use in your entities
@Entity()
export class Product {
  @Column({ type: 'enum', enum: Modality })
  modality: Modality;

  @Column({ type: 'enum', enum: TaxRegime })
  taxRegime: TaxRegime;

  @Column({ type: 'enum', enum: ProductStatus, default: ProductStatus.ACTIVE })
  status: ProductStatus;
}

Available Enums

  • Modality: PGBL, VGBL, ANY
  • TaxRegime: PROGRESSIVE, REGRESSIVE, ANY
  • RiskProfile: CONSERVATIVE, MODERATE, BOLD, AGGRESSIVE
  • ProductStatus: ACTIVE, INACTIVE, SUSPENDED
  • QuotationStatus: PENDING, COMPLETED, EXPIRED, CANCELLED
  • FundStatus: ACTIVE, INACTIVE
  • InsurerStatus: ACTIVE, INACTIVE, SUSPENDED
  • CoverageType: DEATH, DISABILITY, TERM_PENSION, LIFETIME_INCOME, TEMPORARY_INCOME
  • Benchmark: CDI, SELIC, IPCA, IBOVESPA, IBRX, IGPM
  • Action (CASL): Manage, Create, Read, ReadAll, Update, UpdateAll, Delete, DeleteAll

Messaging (RabbitMQ)

Centralized RabbitMQ infrastructure for event-driven communication between microservices.

Exchanges and Routing Keys

import { EXCHANGES, ROUTING_KEYS } from '@ferreirasw/yoke-common';

// Publish an event
await eventsService.publishEvent(
  EXCHANGES.PRODUCT,
  ROUTING_KEYS.PRODUCT_CREATED,
  { productId: '123', name: 'Product A' }
);

BaseEventsService

Extend the BaseEventsService in your microservice:

import { Injectable } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { BaseEventsService, EXCHANGES } from '@ferreirasw/yoke-common';

@Injectable()
export class ProductEventsService extends BaseEventsService {
  constructor(configService: ConfigService) {
    super(configService, 'ProductEventsService');
  }

  protected async setupExchanges(channel: any): Promise<void> {
    // Assert your service's exchanges
    await channel.assertExchange(EXCHANGES.PRODUCT, 'topic', { durable: true });
    await channel.assertExchange(EXCHANGES.FUND, 'topic', { durable: true });
    await channel.assertExchange(EXCHANGES.COVERAGE, 'topic', { durable: true });
    await channel.assertExchange(EXCHANGES.INSURER, 'topic', { durable: true });
  }
}

Then register in your module:

import { Module } from '@nestjs/common';
import { ProductEventsService } from './events/product-events.service';

@Module({
  providers: [ProductEventsService],
  exports: [ProductEventsService],
})
export class EventsModule {}

Message Types

Type-safe message interfaces for all events:

import {
  ProductCreatedMessage,
  EXCHANGES,
  ROUTING_KEYS,
} from '@ferreirasw/yoke-common';

const message: ProductCreatedMessage = {
  productId: product.id,
  insurerId: product.insurerId,
  name: product.name,
  description: product.description,
  modality: product.modality,
  taxRegime: product.taxRegime,
  status: product.status,
  minContribution: product.minContribution,
  maxContribution: product.maxContribution,
  entryFee: product.entryFee,
  administrationFee: product.administrationFee,
  timestamp: Date.now(),
  source: 'product-microservice',
};

await this.eventsService.publishEvent(
  EXCHANGES.PRODUCT,
  ROUTING_KEYS.PRODUCT_CREATED,
  message
);

DTOs and Interfaces

Pagination

import {
  PaginationDto,
  PaginatedResult,
  PaginationHelper,
} from '@ferreirasw/yoke-common';

// In your controller
@Get()
async findAll(@Query() pagination: PaginationDto) {
  const [data, total] = await this.productService.findAll(pagination);

  return PaginationHelper.createResult(
    data,
    total,
    pagination.page,
    pagination.limit
  );
}

// In your service
async findAll(pagination: PaginationDto) {
  const offset = pagination.getOffset();
  const limit = pagination.getLimit();

  const [data, total] = await this.repository.findAndCount({
    skip: offset,
    take: limit,
    order: {
      [pagination.sortBy || 'createdAt']: pagination.sortOrder || 'DESC',
    },
  });

  return [data, total];
}

API Responses

import {
  ApiResponse,
  ResponseBuilder,
} from '@ferreirasw/yoke-common';

// Success response
@Post()
async create(@Body() createDto: CreateProductDto) {
  const product = await this.productService.create(createDto);
  return ResponseBuilder.success(product, 'Product created successfully');
}

// Error response (usually handled by exception filter)
throw new BadRequestException(
  ResponseBuilder.error('VALIDATION_FAILED', 'Invalid input data')
);

Filters and Interceptors

Exception Filter

// In main.ts
import { AllExceptionsFilter } from '@ferreirasw/yoke-common';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);

  // Register global exception filter
  app.useGlobalFilters(new AllExceptionsFilter());

  await app.listen(3000);
}

Logging Interceptor

// In main.ts
import { LoggingInterceptor } from '@ferreirasw/yoke-common';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);

  // Register global logging interceptor
  app.useGlobalInterceptors(
    new LoggingInterceptor({
      logRequestBody: process.env.NODE_ENV === 'development',
      logResponseData: false, // Disable in production for security
    })
  );

  await app.listen(3000);
}

Utilities

Validation Utilities

import {
  isValidCPF,
  isValidCNPJ,
  formatCPF,
  formatCNPJ,
  formatCurrency,
  calculateAge,
} from '@ferreirasw/yoke-common';

// Validate CPF
if (isValidCPF('123.456.789-09')) {
  console.log('Valid CPF');
}

// Validate CNPJ
if (isValidCNPJ('11.222.333/0001-81')) {
  console.log('Valid CNPJ');
}

// Format values
const formattedCPF = formatCPF('12345678909'); // '123.456.789-09'
const formattedCNPJ = formatCNPJ('11222333000181'); // '11.222.333/0001-81'
const formattedPrice = formatCurrency(1234.56); // 'R$ 1.234,56'

// Calculate age
const age = calculateAge(new Date('1990-01-15')); // 36 (as of 2026)

Publishing Updates

Prerequisites

  1. Login to npm with ferreirasw account:
npm login
# Enter credentials for ferreirasw
npm whoami  # Should output: ferreirasw

Publishing Workflow

  1. Make your changes to the codebase

  2. Update CHANGELOG.md with your changes

  3. Bump the version using semantic versioning:

# For bug fixes (0.1.0 -> 0.1.1)
npm version patch

# For new features (0.1.0 -> 0.2.0)
npm version minor

# For breaking changes (0.1.0 -> 1.0.0)
npm version major
  1. Build and publish:
npm run build
npm publish --access public
  1. Push to git with tags:
git push origin main --tags

Using in Microservices

After publishing, install in your microservices:

cd /path/to/account-microservice
npm install @ferreirasw/yoke-common@latest

cd /path/to/product-microservice
npm install @ferreirasw/yoke-common@latest

cd /path/to/quotation-microservice
npm install @ferreirasw/yoke-common@latest

Updating Microservices

When a new version is published:

npm update @ferreirasw/yoke-common

Or install a specific version:

npm install @ferreirasw/[email protected]

Development

Building

npm run build

Linting

npm run lint

Formatting

npm run format

License

MIT

Support

For issues or questions, please create an issue in the repository.