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

wallet-be-framework

v0.0.6

Published

Wallet backend framework for building scalable microservices with NestJS.

Downloads

4

Readme

Wallet Backend Framework

A modern, modular backend framework built on NestJS for scalable microservices architecture. This framework provides standardized modules for common backend functionality including messaging, caching, and database operations.

Introduction

The Wallet Backend Framework is designed to accelerate development of microservices by providing pre-built, configurable modules for common backend requirements. The framework includes several key modules:

  • Messaging: Kafka for scalable and resilient message processing
  • Caching: Dragonfly for high-performance caching with improved memory efficiency
  • Analytics: ClickHouse for high-performance data analytics and time-series storage
  • Audit: Comprehensive audit logging capabilities
  • Indexer: Efficient data indexing services
  • Bucket: Object storage integration
  • Logging: Structured logging with context tracking

Each module follows a consistent pattern with async configuration options, making them easy to integrate into any NestJS application.

Installation

npm install wallet-be-framework

Or using yarn:

yarn add wallet-be-framework

Getting Started

To use the Wallet Backend Framework in your NestJS application, import the modules you need and configure them in your application module:

Bucket Module

Module Registration

import { BucketModule } from 'wallet-be-framework';

@Module({
  imports: [
    BucketModule.forRootAsync({
        imports: [AppConfigModule],
        inject: [AppConfigService],
        useFactory: (config: AppConfigService) => ({
            provider: 'minio',
            endpoint: config.bucketEndpoint,
            cdnEndpoint: config.bucketCdnEndpoint,
            key: config.bucketKey,
            secret: config.bucketSecret,
            defaultConf: {
                defaultBucket: config.bucketDefaultBucket,
                defaultPrefix: config.bucketDefaultPrefix,
            },
            env: config.env,
        }),
    }),
 ]
})
export class AppModule {}

Available Methods

  • getSignedUrl(key: string, options: SignedUrlOptions): Promise<string>
  • getSignedPutUrl(key: string, options: SignedUrlOptions): Promise<string>
  • upload(key: string, content: string | Buffer, options: UploadOptions): Promise<string>
  • uploadFile(file: Buffer, key: string, options?: UploadOptions): Promise<string>
  • getObject(key: string): Promise<Buffer>
  • delete(key: string, options: SignedUrlOptions): Promise<void>
  • deleteObject(key: string): Promise<void>

Kafka Module

The Kafka module provides a robust messaging system for your microservices architecture, replacing traditional RabbitMQ with Kafka's more scalable approach.

Module Registration

import { KafkaModule } from 'wallet-be-framework';

@Module({
  imports: [
    KafkaModule.forRootAsync({
      imports: [ConfigModule],
      inject: [ConfigService],
      useFactory: (configService: ConfigService) => ({
        clientId: configService.get('KAFKA_CLIENT_ID'),
        brokers: configService.get('KAFKA_BROKERS').split(','),
        ssl: configService.get('KAFKA_SSL') === 'true',
        sasl: configService.get('KAFKA_SASL') === 'true' ? {
          mechanism: 'plain',
          username: configService.get('KAFKA_USERNAME'),
          password: configService.get('KAFKA_PASSWORD'),
        } : undefined,
      }),
    }),
  ],
})
export class AppModule {}

Using the KafkaService

import { Injectable } from '@nestjs/common';
import { KafkaService } from 'wallet-be-framework';

@Injectable()
export class YourService {
  constructor(private readonly kafkaService: KafkaService) {}

  async sendMessage(topic: string, message: any): Promise<void> {
    await this.kafkaService.produce(topic, message);
  }

  async setupConsumer(topic: string, groupId: string): Promise<void> {
    await this.kafkaService.consume(
      topic,
      groupId,
      async (message) => {
        // Process the message
        console.log('Received message:', message.value.toString());
      },
    );
  }
}

Dragonfly Cache Module

The Dragonfly Cache module provides high-performance caching capabilities, replacing traditional Redis with the more memory-efficient Dragonfly.

Module Registration

import { DragonflyCacheModule } from 'wallet-be-framework';

@Module({
  imports: [
    DragonflyCacheModule.forRootAsync({
      imports: [ConfigModule],
      inject: [ConfigService],
      useFactory: (configService: ConfigService) => ({
        url: configService.get('DRAGONFLY_URL'),
        ttl: parseInt(configService.get('DRAGONFLY_TTL') || '3600', 10),
      }),
    }),
  ],
})
export class AppModule {}

Using the DragonflyCacheService

import { Injectable } from '@nestjs/common';
import { DragonflyCacheService } from 'wallet-be-framework';

@Injectable()
export class YourService {
  constructor(private readonly cacheService: DragonflyCacheService) {}

  async getData(key: string): Promise<any> {
    // Try to get data from cache first
    const cachedData = await this.cacheService.get(key);
    if (cachedData) {
      return cachedData;
    }

    // If not in cache, get from source and cache it
    const data = await this.fetchDataFromSource();
    await this.cacheService.set(key, data, 3600); // Cache for 1 hour
    return data;
  }

  private async fetchDataFromSource(): Promise<any> {
    // Your implementation to fetch data from the source
    return { example: 'data' };
  }
}

Using the Caching Decorator

import { Injectable } from '@nestjs/common';
import { Cacheable } from 'wallet-be-framework';

@Injectable()
export class YourService {
  @Cacheable('your-cache-key', 3600) // Cache for 1 hour
  async getExpensiveData(id: string): Promise<any> {
    // This function will be cached automatically
    // It will only execute if the cache doesn't have the result
    return this.fetchExpensiveDataFromSource(id);
  }

  private async fetchExpensiveDataFromSource(id: string): Promise<any> {
    // Your implementation
    return { id, data: 'expensive data' };
  }
}

ClickHouse Module

The ClickHouse module provides high-performance analytics and time-series data storage capabilities.

Module Registration

import { ClickHouseModule } from 'wallet-be-framework';

@Module({
  imports: [
    ClickHouseModule.forRootAsync({
      imports: [ConfigModule],
      inject: [ConfigService],
      useFactory: (configService: ConfigService) => ({
        host: configService.get('CLICKHOUSE_HOST'),
        port: parseInt(configService.get('CLICKHOUSE_PORT') || '8123', 10),
        username: configService.get('CLICKHOUSE_USERNAME'),
        password: configService.get('CLICKHOUSE_PASSWORD'),
        database: configService.get('CLICKHOUSE_DATABASE'),
      }),
    }),
  ],
})
export class AppModule {}

Using the ClickHouseService

import { Injectable } from '@nestjs/common';
import { ClickHouseService } from 'wallet-be-framework';

@Injectable()
export class AnalyticsService {
  constructor(private readonly clickhouseService: ClickHouseService) {}

  async logEvent(event: any): Promise<void> {
    await this.clickhouseService.insert('events', [event]);
  }

  async getAnalytics(startDate: Date, endDate: Date): Promise<any[]> {
    const query = `
      SELECT 
        event_type, 
        count() as count 
      FROM events 
      WHERE event_date BETWEEN {startDate: Date} AND {endDate: Date} 
      GROUP BY event_type
    `;
    
    return this.clickhouseService.query(query, {
      startDate,
      endDate,
    });
  }
}

Audit Module

The Audit module provides comprehensive audit logging capabilities for tracking changes and actions within your application.

Module Registration

import { AuditModule } from 'wallet-be-framework';

@Module({
  imports: [
    AuditModule.forRootAsync({
      imports: [ConfigModule],
      inject: [ConfigService],
      useFactory: (configService: ConfigService) => ({
        serviceName: configService.get('SERVICE_NAME'),
        storage: {
          type: 'clickhouse',
          options: {
            host: configService.get('CLICKHOUSE_HOST'),
            port: parseInt(configService.get('CLICKHOUSE_PORT') || '8123', 10),
            username: configService.get('CLICKHOUSE_USERNAME'),
            password: configService.get('CLICKHOUSE_PASSWORD'),
            database: configService.get('CLICKHOUSE_DATABASE'),
            table: 'audit_logs',
          },
        },
      }),
    }),
  ],
})
export class AppModule {}

Using the AuditService

import { Injectable } from '@nestjs/common';
import { AuditService } from 'wallet-be-framework';

@Injectable()
export class UserService {
  constructor(private readonly auditService: AuditService) {}

  async updateUser(userId: string, data: any, requestContext: any): Promise<void> {
    // Get current state
    const currentUser = await this.getUserById(userId);
    
    // Perform update
    const updatedUser = await this.performUpdate(userId, data);
    
    // Log the audit event
    await this.auditService.log({
      action: 'UPDATE_USER',
      entityType: 'USER',
      entityId: userId,
      oldValue: currentUser,
      newValue: updatedUser,
      metadata: {
        requestId: requestContext.requestId,
        userId: requestContext.userId,
        ipAddress: requestContext.ipAddress,
      },
    });
    
    return updatedUser;
  }
  
  private async getUserById(userId: string): Promise<any> {
    // Implementation
  }
  
  private async performUpdate(userId: string, data: any): Promise<any> {
    // Implementation
  }
}

Additional Modules

The framework also includes several other modules:

  • Indexer Module: For efficient data indexing services
  • Logging Module: For structured logging with context tracking

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

License

This project is licensed under the MIT License - see the LICENSE file for details.

  • getSignedPutUrl(key: string, options: SignedUrlOptions): Promise<string>
  • upload(key: string, content: string | Buffer, options: UploadOptions): Promise<string>
  • delete(key: string, options: SignedUrlOptions): Promise<string>
  • buildUrl(key: string): string

Dragonfly Cache Module

Module Registration

import { DragonflyModule } from '@mosu/be-framework';

@Module({
  imports: [
    DragonflyModule.forRootAsync({
        imports: [AppConfigModule],
        inject: [AppConfigService],
        useFactory: (config: AppConfigService) => ({
            url: config.redisUrl, // Works with both Redis and Dragonfly servers
            ttl: 5 * 60 * 1000, // 5 minutes
            maxReconnectAttempts: 5,
            reconnectDelay: 5000, // 5 seconds
            pingInterval: 5000, // 5 seconds
            crashOnConnectFailure: true,
        }),
    }),
  ],
})
export class AppModule {}

Available Methods

  • get<T>(key: string): Promise<T | undefined>
  • set<T>(key: string, value: T, ttl?: number): Promise<void>
  • del(key: string): Promise<void>
  • reset(): Promise<void>
  • wrap<T>(key: string, fn: () => Promise<T>, ttl?: number): Promise<T>
  • mset<T>(keyValuePairs: Array<[string, T]>, ttl?: number): Promise<void>
  • mget<T>(keys: string[]): Promise<(T | null)[]>
  • exists(key: string): Promise<boolean>

Location Module

Module Registration

import { LocationModule } from '@mosu/be-framework';

@Module({
  imports: [
    LocationModule.forRootAsync({
        imports: [AppConfigModule],
        inject: [AppConfigService],
        useFactory: (config: AppConfigService) => ({
            apiKey: config.apiKey,
        }),
    }),
 ]
})
export class AppModule {}

Available Methods

  • validateAddress(address: string): Promise<AddressValidationOutput>
  • autocompleteAddress(payload: AddressAutocompleteInput): Promise<AddressValidationOutput[]>

Kafka Module

Module Registration

import { KafkaModule } from '@mosu/be-framework';

@Module({
  imports: [
    KafkaModule.forRootAsync({
        imports: [AppConfigModule],
        inject: [AppConfigService],
        useFactory: (config: AppConfigService) => ({
            clientId: 'my-app',
            brokers: config.kafkaBrokers,
            ssl: config.kafkaUseSsl,
            topics: [
              { name: 'user-events', numPartitions: 3, replicationFactor: 2 },
            ],
            consumerGroups: [
              { groupId: 'user-events-group', topics: ['user-events'] },
            ],
        }),
    }),
  ]
})
export class AppModule {}

Available Methods

  • createProducer(config?: ProducerConfig): Promise<void>
  • createTopic(topicConfig: KafkaTopicConfig): Promise<void>
  • publish<T>(topic: string, message: T, key?: string): Promise<void>
  • consume(groupId: string, topics: string[], config?: ConsumerConfig): Promise<ConsumerSubject>
  • subscribeConsumer(consumerGroup: string, topic: string, messageKey?: string): Promise<ConsumerSubject>
  • checkHealth(): Promise<KafkaHealthStatus>

ClickHouse Module

Module Registration

import { ClickHouseModule } from '@mosu/be-framework';

@Module({
  imports: [
    ClickHouseModule.forRootAsync({
        imports: [AppConfigModule],
        inject: [AppConfigService],
        useFactory: (config: AppConfigService) => ({
            host: config.clickhouseHost,
            port: config.clickhousePort,
            username: config.clickhouseUsername,
            password: config.clickhousePassword,
            database: config.clickhouseDatabase,
        }),
    }),
  ]
})
export class AppModule {}

Available Methods

  • query<T>(sql: string, params?: Record<string, any>): Promise<T[]>
  • insert<T>(table: string, data: T | T[]): Promise<void>
  • createTable(tableName: string, schema: Record<string, string>): Promise<void>
  • checkHealth(): Promise<{ status: 'ok' | 'error', details?: string }>