nestjs-feature
v1.0.1
Published
A powerful and flexible feature flag library for NestJS applications that allows you to control feature rollouts, A/B testing, and feature toggles with ease.
Downloads
6
Maintainers
Readme
NestJS Feature Flags
A powerful and flexible feature flag library for NestJS applications that allows you to control feature rollouts, A/B testing, and feature toggles with ease.
Features
- 🚀 Easy Integration - Simple setup with NestJS applications
- 🎯 Hierarchical Features - Support for nested feature flags
- 🔄 Runtime Control - Enable/disable features at runtime
- 🌍 Environment-based - Load features from environment variables
- 📝 TypeScript Support - Full TypeScript support with type safety
- 🎛️ Flexible API - Intuitive methods for feature management
Installation
bun add nestjs-featureQuick Start
1. Define your features
import { defineFeature } from 'nestjs-feature';
export const features = registerFeatures({
userManagement: defineFeature('user-management', {
registration: defineFeature('registration'),
profile: defineFeature('profile', {
avatar: defineFeature('avatar'),
preferences: defineFeature('preferences')
})
}),
analytics: defineFeature('analytics'),
newUI: defineFeature('new-ui')
});2. Use features in your code
import { isFeatureEnabled } from 'nestjs-feature';
import { features } from './features';
@Controller('users')
export class UsersController {
@Get()
getUsers() {
if (isFeatureEnabled(features.userManagement)) {
// New user management logic
return this.getUsersV2();
}
// Fallback to old logic
return this.getUsersV1();
}
@Post('register')
registerUser(@Body() userData: any) {
if (!isFeatureEnabled(features.userManagement.registration)) {
throw new ForbiddenException('Registration is currently disabled');
}
return this.createUser(userData);
}
}Environment-based Feature Loading
You can enable features using environment variables:
# Enable specific features
FEATURES="user-management,analytics,user-management.profile.avatar"
# Or in your .env file
FEATURES=user-management,analytics,new-uiimport { loadFeaturesFromString } from 'nestjs-feature';
// Load features from environment
const featuresEnv = process.env.FEATURES;
if (featuresEnv) {
loadFeaturesFromString(featuresEnv);
}API Reference
defineFeature(name, subfeatures?)
Creates a new feature definition.
const myFeature = defineFeature('my-feature', {
subFeature: defineFeature('sub-feature')
});Parameters:
name(string): The feature namesubfeatures(object, optional): Nested sub-features
Returns: FeatureObjectWithMethods
registerFeatures(features, override?)
Registers features in the global registry.
registerFeatures(features, true); // Override existing featuresParameters:
features: Object containing feature definitionsoverride(boolean, default: true): Whether to override existing features
loadFeatures(features, override?)
Loads and enables specific features.
loadFeatures([features.userManagement, features.analytics]);loadFeaturesFromString(featuresString)
Loads features from a comma-separated string.
loadFeaturesFromString('user-management,analytics,new-ui');isFeatureEnabled(feature)
Checks if a feature is currently enabled.
if (isFeatureEnabled(features.userManagement)) {
// Feature is enabled
}getFeature(featureName)
Retrieves a feature by name from the registry.
const feature = getFeature('user-management');Feature Object Methods
Each feature object comes with built-in methods:
const feature = defineFeature('my-feature');
// Get feature name
feature.$name(); // Returns: 'my-feature'
// Enable/disable feature
feature.$enable();
feature.$disable();
// Check status
feature.$isEnabled(); // Returns: boolean
feature.$isDisabled(); // Returns: boolean
// Create disabled version
const disabledFeature = feature.$asDisabled();Advanced Usage
Conditional Feature Loading
import { registerFeatures, loadFeatures } from 'nestjs-feature';
// Register all possible features
registerFeatures(features);
// Load features based on environment
if (process.env.NODE_ENV === 'development') {
loadFeatures([
features.userManagement,
features.analytics,
features.newUI
]);
} else if (process.env.NODE_ENV === 'production') {
loadFeatures([
features.userManagement,
features.analytics
]);
}Feature Guards
Create guards to protect routes based on feature flags:
import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common';
import { isFeatureEnabled } from 'nestjs-feature';
import { features } from './features';
@Injectable()
export class FeatureGuard implements CanActivate {
constructor(private feature: any) {}
canActivate(context: ExecutionContext): boolean {
return isFeatureEnabled(this.feature);
}
}
// Usage in controller
@UseGuards(new FeatureGuard(features.userManagement))
@Controller('admin')
export class AdminController {
// This controller is only accessible when user-management feature is enabled
}Feature Decorators
Create custom decorators for cleaner code:
import { SetMetadata } from '@nestjs/common';
export const RequireFeature = (feature: any) => SetMetadata('feature', feature);
// Usage
@RequireFeature(features.userManagement)
@Get('users')
getUsers() {
// This endpoint requires user-management feature
}Best Practices
Organize Features Hierarchically: Use nested features to group related functionality
const features = { ecommerce: defineFeature('ecommerce', { cart: defineFeature('cart'), payment: defineFeature('payment', { creditCard: defineFeature('credit-card'), paypal: defineFeature('paypal') }) }) };Use Environment Variables: Load features from environment variables for different environments
loadFeaturesFromString(process.env.FEATURES || '');Feature Naming: Use kebab-case for feature names to ensure consistency
defineFeature('user-management') // ✅ Good defineFeature('userManagement') // ❌ AvoidGraceful Fallbacks: Always provide fallback behavior when features are disabled
if (isFeatureEnabled(features.newDashboard)) { return this.renderNewDashboard(); } return this.renderLegacyDashboard(); // Fallback
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
License
This project is licensed under the UNLICENSED License - see the package.json file for details.
Support
If you have any questions or run into issues, please open an issue on GitHub.
