@forge/feature-flags
v1.0.2
Published
Feature Flags Node SDK for Atlassian Forge apps running on Node Runtime
Readme
@forge/feature-flags
A feature flag SDK for Atlassian Forge apps running on Forge Node Runtime. This package provides a simple interface for evaluating feature flags.
Installation
yarn add @forge/feature-flagsUsage
Basic Usage
import { getAppContext } from "@forge/api";
import { FeatureFlags } from "@forge/feature-flags";
export const handler = async (payload, context) => {
// Get app context values
const {
appVersion,
license: appLicense,
environmentType,
} = getAppContext();
// Determine license value based on trialEndDate and isActive
let licenseValue = "INACTIVE";
const trialEndDate = appLicense?.trialEndDate;
const isActive = appLicense?.isActive;
if (trialEndDate) {
const now = new Date();
const trialEnd = new Date(trialEndDate);
if (trialEnd > now) {
licenseValue = "TRIAL";
} else if (isActive) {
licenseValue = "ACTIVE";
}
} else if (isActive) {
licenseValue = "ACTIVE";
}
// Determine capabilitySet value (enum)
let capabilitySetValue = "capabilityStandard";
if (appLicense?.capabilitySet === "capabilityAdvanced") {
capabilitySetValue = "capabilityAdvanced";
}
// Initialize the feature flags SDK
const featureFlags = new FeatureFlags();
await featureFlags.initialize({
environment: environmentType?.toLowerCase() || "development"
});
// Define a user with all possible attributes that will be used in the feature flag rules
const user = {
identifiers: {
accountId: context?.principal?.accountId,
},
attributes: {
installContext: context?.installContext,
accountId: context?.principal?.accountId,
appVersion: appVersion,
license: licenseValue, // "ACTIVE", "INACTIVE", "TRIAL"
capabilitySet: capabilitySetValue // "capabilityAdvanced", "capabilityStandard"
}
};
// Check a feature flag (synchronous after initialization)
const isEnabled = featureFlags.checkFlag(user, "new-feature");
// Check with a default value if flag doesn't exist
const isEnabledWithDefault = featureFlags.checkFlag(user, "another-feature", true);
// Get all available flag IDs
const allFlagIds = featureFlags.getAllFlagIds();
// Shutdown when done (cleans up polling and resources)
featureFlags.shutdown();
}
⚠️ Important: Initialization Best Practices
ALWAYS initialize the FeatureFlags SDK inside your handler function, NEVER initialize globally as it will use the stale feature flags
✅ Correct Pattern - Initialize Inside Handler
import { getAppContext } from "@forge/api";
import { FeatureFlags } from "@forge/feature-flags";
export const handler = async (payload, context) => {
// ✅ Initialize inside the handler function
const featureFlags = new FeatureFlags();
await featureFlags.initialize({
environment: getAppContext().environmentType?.toLowerCase() || "development"
});
// Define a user
const user = {
identifiers: {
installContext: context?.installContext,
},
attributes: {
issues: 4
}
};
// Use feature flags...
const isEnabled = featureFlags.checkFlag(user, "new-feature");
// Shutdown when done (synchronous)
featureFlags.shutdown();
}❌ Incorrect Pattern - Global Initialization
// ❌ NEVER do this - Global initialization
const featureFlags = new FeatureFlags();
await featureFlags.initialize(); // This will cause problems!
export const handler = async (payload, context) => {
// This will fail if token expires or network issues occur
const isEnabled = featureFlags.checkFlag(user, "new-feature");
}Polling Behavior
The package automatically polls for feature flag updates every 60 seconds:
- Cache Updates: New data is cached for fallback purposes
- Error Resilience: If a fetch fails, the package falls back to cached data
- Immediate Updates: Feature flag changes are reflected within 60 seconds
// Polling happens automatically in the background
const featureFlags = new FeatureFlags();
await featureFlags.initialize();
// Feature flags are automatically updated every 60 seconds
// No manual intervention requiredAPI Reference
FeatureFlags
constructor()
Creates a new instance of the FeatureFlags class.
initialize(config?: ForgeFeatureFlagConfig): Promise<void>
Initializes the feature flags service with the provided configuration.
interface ForgeFeatureFlagConfig {
environment?: 'development' | 'staging' | 'production';
}checkFlag(user: User, flagId: string, defaultValue?: boolean): boolean
Checks if a feature flag is enabled for the given user. Returns the defaultValue (defaults to false) if the flag doesn't exist. Synchronous after initialization.
getFlag(user: User, flagId: string): FeatureFlag | undefined
Gets a specific flag's evaluation details. Useful for debugging purposes.
getAllFlagIds(): string[]
Returns an array of all available flag IDs.
refresh(): Promise<void>
Forces a refresh of feature flag configurations from the server.
getLastFetchTime(): number
Returns the timestamp of the last successful fetch from the server.
isInitialized(): boolean
Checks if the service is initialized.
shutdown(): void
Shuts down the feature flags service, stops polling, and cleans up resources. Synchronous.
User Interface
interface User {
attributes?: Record<string, string | number>;
identifiers?: {
installContext?: string;
accountId?: string;
};
}Configuration Options
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| environment | 'development' \| 'staging' \| 'production' | 'development' | Environment tier for feature flag evaluation |
