HbarSuite Docs
  • Welcome to HbarSuite
  • HbarSuite Developer Documentation
    • HbarSuite Smart Engine Applications
      • @hsuite/cross-chain-exchange
      • @hsuite/dao
        • DAO Application Testing
      • @hsuite/exchange
      • @hsuite/launchpad
      • @hsuite/multisig
      • @hsuite/nft-exchange
      • HSuite Smart App - Enterprise Hedera Application Framework
    • HSuite Libraries
      • @hsuite/api-key - Enterprise API Key Authentication System
      • @hsuite/auth-types
      • @hsuite/auth - Authentication Module
      • @hsuite/client-types
      • @hsuite/client - Client Service Module
      • @hsuite/dkg-types - Distributed Key Generation Type Definitions
      • @hsuite/hashgraph-types - Hedera Hashgraph Type Definitions
      • @hsuite/health - Comprehensive System Health Monitoring
      • @hsuite/helpers - Utility Library
      • @hsuite/ipfs - InterPlanetary File System Integration
      • @hsuite/shared-types - Shared Type Definitions
      • @hsuite/smart-config - Configuration Management
      • @hsuite/smart-ledgers - Multi-Ledger Management
      • @hsuite/smart-network-types - Smart Network Type Definitions
      • @hsuite/smart-transaction-types - Smart Transaction Type Definitions
      • @hsuite/smartnode-sdk - SmartNode Software Development Kit
      • @hsuite/snapshots - Multi-Ledger Token Snapshot Management
      • @hsuite/subscriptions-types - Subscription Management Type Definitions
      • @hsuite/subscriptions - Enterprise Subscription Management System
      • @hsuite/throttler-types - Rate Limiting Type Definitions
      • @hsuite/throttler - Advanced Rate Limiting for NestJS
      • @hsuite/users-types - User Type Definitions
      • @hsuite/users - User Management Module
      • @hsuite/validators-types
  • General Documentation
    • Smart Apps and Interaction
      • Subscription-Based Model
      • Token-Gate Model
    • The Smart Node Network
      • security-layer
      • Type of Validators Explained
      • Understanding Validators in Our System
      • Automating Responses to Network Changes & Key Rotation
      • Ensuring Continuous Operation and Recovery
      • Generating and Sharing Keys Collaboratively
      • Handling Node Expulsion and Replacement
      • Managing Cluster Membership
      • Protecting Secrets with Shamir's Method
      • Security Layer Integration
      • Setting Up Secure Clusters
    • Tokenomics
      • Tokenomics v1
      • Tokenomics V2
    • What is a Smart Node?
  • Restful APIs Documentation
Powered by GitBook
On this page
  • Table of Contents
  • Quick Start
  • Installation
  • Basic Setup
  • Basic Usage
  • Architecture
  • Core Components
  • Module Structure
  • API Reference
  • SmartConfigModule
  • SmartConfigService
  • Guides
  • Environment Configuration Guide
  • Dynamic Updates Guide
  • Validation Guide
  • Examples
  • Complete Module Configuration
  • Environment-Specific Configuration
  • Dynamic Configuration Updates
  • Configuration Validation Service
  • Integration
  • Required Dependencies
  • Environment File Structure
  • Production Environment
  • 🔄 Dynamic: Runtime configuration updates with validation and event emission.
  1. HbarSuite Developer Documentation
  2. HSuite Libraries

@hsuite/smart-config - Configuration Management

Previous@hsuite/shared-types - Shared Type DefinitionsNext@hsuite/smart-ledgers - Multi-Ledger Management

Last updated 2 days ago

⚙️ Dynamic configuration management for HSuite applications

Advanced configuration management module providing environment-based settings, secure credential management, and dynamic configuration updates for distributed blockchain applications.


Table of Contents


Quick Start

Installation

npm install @hsuite/smart-config

Basic Setup

import { SmartConfigModule } from '@hsuite/smart-config';

@Module({
  imports: [
    SmartConfigModule.forRoot({
      envFilePath: ['.env.local', '.env'],
      isGlobal: true,
      expandVariables: true
    })
  ]
})
export class AppModule {}

Basic Usage

@Injectable()
export class ConfigService {
  constructor(private smartConfig: SmartConfigService) {}

  getApiKey(): string {
    return this.smartConfig.get('API_KEY');
  }

  getDatabaseConfig(): DatabaseConfig {
    return this.smartConfig.getDatabaseConfig();
  }
}

Architecture

Core Components

⚙️ Configuration Management

  • SmartConfigService - Core configuration service with type safety

  • Environment Loading - Multi-environment configuration support

  • Dynamic Updates - Runtime configuration updates

🔒 Security Features

  • Credential Encryption - Automatic encryption for sensitive values

  • Secret Management - Secure handling of API keys and passwords

  • Environment Isolation - Separate configs for different environments

🔄 Dynamic Configuration

  • Hot Reloading - Configuration updates without restart

  • Validation - Schema-based configuration validation

  • Type Safety - Full TypeScript support for configuration objects

Module Structure

src/
├── interfaces/            # Configuration interfaces
├── services/             # Configuration services
├── decorators/           # Configuration decorators
├── validators/           # Configuration validators
├── smart-config.service.ts # Core configuration service
├── smart-config.module.ts  # Module configuration
└── index.ts             # Public API exports

API Reference

SmartConfigModule

Static Methods

forRoot(options: SmartConfigOptions): DynamicModule

Configures the smart config module with static options.

interface SmartConfigOptions {
  envFilePath?: string | string[];
  isGlobal?: boolean;
  expandVariables?: boolean;
  validationSchema?: any;
  cache?: boolean;
}

forRootAsync(options: SmartConfigAsyncOptions): DynamicModule

Configures the smart config module with async dependency injection.

SmartConfigService

Core Methods

get<T = any>(key: string, defaultValue?: T): T

  • Retrieves configuration value by key

  • Parameters: key - Configuration key, defaultValue - Fallback value

  • Returns: Configuration value or default

getOrThrow<T = any>(key: string): T

  • Gets configuration value or throws error if not found

  • Parameters: key - Configuration key

  • Throws: Error if key not found

getDatabaseConfig(): DatabaseConfig

  • Returns typed database configuration

  • Returns: Complete database configuration object

getAuthConfig(): AuthConfig

  • Returns authentication configuration

  • Returns: Authentication settings with type safety

getNetworkConfig(): NetworkConfig

  • Returns network and blockchain configuration

  • Returns: Network configuration for all supported chains


Guides

Environment Configuration Guide

Learn how to set up environment-specific configurations and secrets. Configure validation schemas, environment variable management, and secure credential handling.

Dynamic Updates Guide

Implement runtime configuration updates and hot reloading. Set up configuration watchers, event-driven updates, and real-time configuration management.

Validation Guide

Set up configuration validation schemas and type safety. Implement Joi validation, custom validators, and configuration error handling.


Examples

Complete Module Configuration

import { SmartConfigModule } from '@hsuite/smart-config';
import * as Joi from 'joi';

@Module({
  imports: [
    SmartConfigModule.forRoot({
      envFilePath: ['.env.local', '.env', '.env.production'],
      isGlobal: true,
      expandVariables: true,
      cache: true,
      validationSchema: Joi.object({
        NODE_ENV: Joi.string()
          .valid('development', 'production', 'test')
          .default('development'),
        PORT: Joi.number().default(3000),
        DATABASE_URL: Joi.string().required(),
        JWT_SECRET: Joi.string().required().min(32),
        HEDERA_ACCOUNT_ID: Joi.string().pattern(/^0\.0\.\d+$/),
        HEDERA_PRIVATE_KEY: Joi.string().required(),
        API_RATE_LIMIT: Joi.number().default(100),
        ENABLE_CORS: Joi.boolean().default(true)
      })
    })
  ]
})
export class AppModule {}

Environment-Specific Configuration

import { Injectable } from '@nestjs/common';
import { SmartConfigService } from '@hsuite/smart-config';

@Injectable()
export class EnvironmentConfigService {
  constructor(private config: SmartConfigService) {}

  // Database Configuration
  getDatabaseConfig() {
    return {
      type: 'postgres',
      host: this.config.get('DB_HOST', 'localhost'),
      port: this.config.get('DB_PORT', 5432),
      username: this.config.get('DB_USERNAME'),
      password: this.config.get('DB_PASSWORD'),
      database: this.config.get('DB_DATABASE'),
      ssl: this.config.get('DB_SSL', false),
      synchronize: this.config.get('DB_SYNCHRONIZE', false),
      logging: this.config.get('DB_LOGGING', false),
      entities: ['dist/**/*.entity{.ts,.js}'],
      migrations: ['dist/migrations/*{.ts,.js}']
    };
  }

  // JWT Configuration
  getJwtConfig() {
    return {
      secret: this.config.getOrThrow('JWT_SECRET'),
      signOptions: {
        expiresIn: this.config.get('JWT_EXPIRES_IN', '24h'),
        issuer: this.config.get('JWT_ISSUER', 'hsuite'),
        audience: this.config.get('JWT_AUDIENCE', 'hsuite-users')
      },
      refreshTokenExpiresIn: this.config.get('JWT_REFRESH_EXPIRES_IN', '7d')
    };
  }

  // Hedera Configuration
  getHederaConfig() {
    return {
      network: this.config.get('HEDERA_NETWORK', 'testnet'),
      accountId: this.config.getOrThrow('HEDERA_ACCOUNT_ID'),
      privateKey: this.config.getOrThrow('HEDERA_PRIVATE_KEY'),
      publicKey: this.config.get('HEDERA_PUBLIC_KEY'),
      mirrorNodeUrl: this.config.get(
        'HEDERA_MIRROR_NODE_URL', 
        'https://testnet.mirrornode.hedera.com'
      ),
      consensusNodeUrl: this.config.get(
        'HEDERA_CONSENSUS_NODE_URL',
        'https://testnet.hedera.com'
      )
    };
  }

  // Redis Configuration
  getRedisConfig() {
    return {
      host: this.config.get('REDIS_HOST', 'localhost'),
      port: this.config.get('REDIS_PORT', 6379),
      password: this.config.get('REDIS_PASSWORD'),
      db: this.config.get('REDIS_DB', 0),
      keyPrefix: this.config.get('REDIS_KEY_PREFIX', 'hsuite:'),
      ttl: this.config.get('REDIS_TTL', 3600),
      maxRetriesPerRequest: this.config.get('REDIS_MAX_RETRIES', 3)
    };
  }

  // API Configuration
  getApiConfig() {
    return {
      port: this.config.get('PORT', 3000),
      host: this.config.get('HOST', '0.0.0.0'),
      globalPrefix: this.config.get('API_PREFIX', 'api'),
      version: this.config.get('API_VERSION', 'v1'),
      documentation: {
        enabled: this.config.get('API_DOCS_ENABLED', true),
        path: this.config.get('API_DOCS_PATH', 'docs')
      },
      rateLimit: {
        windowMs: this.config.get('RATE_LIMIT_WINDOW', 15 * 60 * 1000), // 15 minutes
        max: this.config.get('RATE_LIMIT_MAX', 100),
        message: 'Too many requests from this IP'
      },
      cors: {
        enabled: this.config.get('ENABLE_CORS', true),
        origin: this.config.get('CORS_ORIGIN', '*'),
        credentials: this.config.get('CORS_CREDENTIALS', true)
      }
    };
  }

  // Mail Configuration
  getMailConfig() {
    return {
      transport: {
        host: this.config.get('SMTP_HOST'),
        port: this.config.get('SMTP_PORT', 587),
        secure: this.config.get('SMTP_SECURE', false),
        auth: {
          user: this.config.get('SMTP_USER'),
          pass: this.config.get('SMTP_PASS')
        }
      },
      defaults: {
        from: this.config.get('SMTP_FROM', '[email protected]')
      },
      template: {
        dir: this.config.get('MAIL_TEMPLATE_DIR', './templates'),
        adapter: 'handlebars',
        options: {
          strict: true
        }
      }
    };
  }
}

Dynamic Configuration Updates

import { Injectable, OnModuleInit } from '@nestjs/common';
import { SmartConfigService } from '@hsuite/smart-config';
import { EventEmitter2 } from '@nestjs/event-emitter';

@Injectable()
export class DynamicConfigService implements OnModuleInit {
  private configCache = new Map<string, any>();

  constructor(
    private config: SmartConfigService,
    private eventEmitter: EventEmitter2
  ) {}

  onModuleInit() {
    this.setupConfigWatchers();
  }

  async updateConfiguration(key: string, value: any) {
    // Validate new configuration value
    await this.validateConfigUpdate(key, value);

    // Update in cache
    this.configCache.set(key, value);

    // Emit configuration change event
    this.eventEmitter.emit('config.updated', { key, value, timestamp: new Date() });

    // Persist to external config store if needed
    await this.persistConfigChange(key, value);

    return {
      success: true,
      key,
      newValue: value,
      updatedAt: new Date()
    };
  }

  getConfigWithFallback<T>(key: string, fallback: T): T {
    // Check cache first
    if (this.configCache.has(key)) {
      return this.configCache.get(key);
    }

    // Fall back to environment variables
    const envValue = this.config.get(key);
    if (envValue !== undefined) {
      this.configCache.set(key, envValue);
      return envValue;
    }

    // Use provided fallback
    this.configCache.set(key, fallback);
    return fallback;
  }

  async reloadConfiguration() {
    try {
      // Clear cache
      this.configCache.clear();

      // Reload environment variables
      await this.config.reload();

      // Emit reload event
      this.eventEmitter.emit('config.reloaded', { timestamp: new Date() });

      return {
        success: true,
        message: 'Configuration reloaded successfully',
        reloadedAt: new Date()
      };
    } catch (error) {
      throw new Error(`Failed to reload configuration: ${error.message}`);
    }
  }

  getFeatureFlags() {
    return {
      enableNewUI: this.getConfigWithFallback('FEATURE_NEW_UI', false),
      enableBetaFeatures: this.getConfigWithFallback('FEATURE_BETA', false),
      enableAnalytics: this.getConfigWithFallback('FEATURE_ANALYTICS', true),
      enableCaching: this.getConfigWithFallback('FEATURE_CACHING', true),
      maintenanceMode: this.getConfigWithFallback('MAINTENANCE_MODE', false)
    };
  }

  private setupConfigWatchers() {
    // Watch for configuration file changes
    if (this.config.get('ENABLE_CONFIG_WATCHING', false)) {
      // Implementation for file system watching
      console.log('Configuration watching enabled');
    }
  }

  private async validateConfigUpdate(key: string, value: any) {
    // Define validation rules for different config keys
    const validationRules = {
      'API_RATE_LIMIT': (val: any) => Number.isInteger(val) && val > 0,
      'JWT_EXPIRES_IN': (val: any) => typeof val === 'string' && /^\d+[smhd]$/.test(val),
      'HEDERA_ACCOUNT_ID': (val: any) => typeof val === 'string' && /^0\.0\.\d+$/.test(val)
    };

    const validator = validationRules[key];
    if (validator && !validator(value)) {
      throw new Error(`Invalid value for configuration key: ${key}`);
    }
  }

  private async persistConfigChange(key: string, value: any) {
    // Implementation for persisting config changes
    // Could be database, external config service, etc.
    console.log(`Persisting config change: ${key} = ${value}`);
  }
}

Configuration Validation Service

import { Injectable } from '@nestjs/common';
import { SmartConfigService } from '@hsuite/smart-config';
import * as Joi from 'joi';

@Injectable()
export class ConfigValidationService {
  constructor(private config: SmartConfigService) {}

  validateAllConfigurations(): ValidationResult {
    const errors: string[] = [];
    const warnings: string[] = [];

    // Validate required environment variables
    const requiredConfigs = [
      'JWT_SECRET',
      'DATABASE_URL',
      'HEDERA_ACCOUNT_ID',
      'HEDERA_PRIVATE_KEY'
    ];

    for (const configKey of requiredConfigs) {
      if (!this.config.get(configKey)) {
        errors.push(`Missing required configuration: ${configKey}`);
      }
    }

    // Validate configuration formats
    this.validateJwtSecret(errors);
    this.validateDatabaseUrl(errors);
    this.validateHederaConfig(errors, warnings);
    this.validateApiConfig(warnings);

    return {
      isValid: errors.length === 0,
      errors,
      warnings,
      validatedAt: new Date()
    };
  }

  private validateJwtSecret(errors: string[]) {
    const jwtSecret = this.config.get('JWT_SECRET');
    if (jwtSecret && jwtSecret.length < 32) {
      errors.push('JWT_SECRET must be at least 32 characters long');
    }
  }

  private validateDatabaseUrl(errors: string[]) {
    const dbUrl = this.config.get('DATABASE_URL');
    if (dbUrl && !dbUrl.startsWith('postgresql://')) {
      errors.push('DATABASE_URL must be a valid PostgreSQL connection string');
    }
  }

  private validateHederaConfig(errors: string[], warnings: string[]) {
    const accountId = this.config.get('HEDERA_ACCOUNT_ID');
    if (accountId && !/^0\.0\.\d+$/.test(accountId)) {
      errors.push('HEDERA_ACCOUNT_ID must be in format 0.0.xxx');
    }

    const network = this.config.get('HEDERA_NETWORK', 'testnet');
    if (network === 'mainnet') {
      warnings.push('Using Hedera mainnet - ensure this is intentional');
    }
  }

  private validateApiConfig(warnings: string[]) {
    const port = this.config.get('PORT', 3000);
    if (port < 1024) {
      warnings.push('API port is below 1024 - may require elevated privileges');
    }

    if (this.config.get('ENABLE_CORS', true) && this.config.get('CORS_ORIGIN') === '*') {
      warnings.push('CORS is enabled for all origins - consider restricting in production');
    }
  }
}

interface ValidationResult {
  isValid: boolean;
  errors: string[];
  warnings: string[];
  validatedAt: Date;
}

Integration

Required Dependencies

{
  "@nestjs/config": "^3.0.0",
  "joi": "^17.0.0",
  "dotenv": "^16.0.0"
}

Environment File Structure

# .env.local (development)
NODE_ENV=development
PORT=3000
LOG_LEVEL=debug

# Database
DATABASE_URL=postgresql://user:pass@localhost:5432/hsuite_dev
DB_SYNCHRONIZE=true
DB_LOGGING=true

# JWT
JWT_SECRET=your-super-secret-jwt-key-minimum-32-characters
JWT_EXPIRES_IN=24h

# Hedera Testnet
HEDERA_NETWORK=testnet
HEDERA_ACCOUNT_ID=0.0.123456
HEDERA_PRIVATE_KEY=302e020100300506032b657004220420...

# Redis
REDIS_HOST=localhost
REDIS_PORT=6379
REDIS_PASSWORD=

# Feature Flags
FEATURE_NEW_UI=true
FEATURE_BETA=true
ENABLE_CONFIG_WATCHING=true

Production Environment

# .env.production
NODE_ENV=production
PORT=8080
LOG_LEVEL=info

# Database
DATABASE_URL=postgresql://user:securepass@prod-db:5432/hsuite
DB_SYNCHRONIZE=false
DB_LOGGING=false

# JWT
JWT_SECRET=production-jwt-secret-very-long-and-secure
JWT_EXPIRES_IN=1h

# Hedera Mainnet
HEDERA_NETWORK=mainnet
HEDERA_ACCOUNT_ID=0.0.987654
HEDERA_PRIVATE_KEY=encrypted_private_key_here

# Redis
REDIS_HOST=redis-cluster
REDIS_PORT=6379
REDIS_PASSWORD=secure_redis_password

# Security
ENABLE_CORS=false
API_RATE_LIMIT=50

⚙️ Type Safety: Full TypeScript support with configuration interfaces and validation.

🔒 Security: Encrypted credential storage and environment-based configuration isolation.

🔄 Dynamic: Runtime configuration updates with validation and event emission.

Built with ❤️ by the HbarSuite Team Copyright © 2024 HbarSuite. All rights reserved.

Quick Start
Architecture
API Reference
Guides
Examples
Integration