@daysmart/angular-launch-darkly-service
v0.2.1
Published
[![npm downloads](https://img.shields.io/npm/dm/@daysmart/angular-launch-darkly-service.svg)](https://npmjs.org/@daysmart/angular-launch-darkly-service) [![npm bundle size (minified + gzip)](https://img.shields.io/bundlephobia/minzip/@daysmart/angular-la
Downloads
52
Maintainers
Keywords
Readme
Setup
Step 1 - Import the LaunchDarklyModule
Add the LaunchDarklyModule
to your AppModule
in order to start accessing your feature flags. You will need to provide your Launch Darkly API key in the forRoot module function. This should ONLY be imported into the AppModule
and nowhere else. It is meant to be used by your entire application. If it's imported into more than one location, you will create multiple instances of the service it contains.
...
import { LaunchDarklyModule } from '@daysmart/angular-launch-darkly-service';
...
@NgModule({
declarations: [
SomeComponent
],
imports: [
...
LaunchDarklyModule.forRoot({ apiKey: environment.launchdarklyApiKey }),
...
],
providers: []
})
export class AppModule {}
Step 2 - Set the current user's data once it's known
When your Angular page first loads, the LaunchDarkly user initialized will be an anonymous user with a key of anonymous_user
. While linked with the anonymous user, all feature flags will be returned as false. Once you know the current user's actual identity, the LaunchDarklyService.setUser
should be called.
setUser
is deprecated use setContext
instead.
I suggest calling setUser
from your top-most app guard if you have one so that all guards that run after it will be able to check feature flags reliably. If you do it elsewhere (even the AppComponent), the guards may run first and not get accurate flag information. The AppComponent does run ngOnInit in parallel with the guards running, so you won't be able to reliably check flags in your AppComponent. You might be able to duplicate the setUser
call into your AppComponent too to get around this, just make sure to check what user is already set by calling getUser
prior to setting it so that you are re-setting it over and over.
setUser
takes in an LDUser
specified here: https://launchdarkly.github.io/js-client-sdk/interfaces/launchdarkly_js_client_sdk.lduser.html
export class CanActivateAppGuard implements CanActivate {
constructor(private launchDarklyService: LaunchDarklyService) {}
async canActivate(
next: ActivatedRouteSnapshot,
state: RouterStateSnapshot
):
| Observable<boolean | UrlTree>
| Promise<boolean | UrlTree>
| boolean
| UrlTree {
const existingLDUser: LDUser = this.launchDarklyService.getUser();
if (
result.data.webAccountInfo?.customerID > 0 &&
(!existingLDUser ||
existingLDUser.key !== result.data.webAccountInfo.customerID)
) {
await this.launchDarklyService.setUser({
key: result.data.webAccountInfo.customerID,
});
}
if (someReasonToRedirect) {
return this.router.parseUrl('/not_found');
} else {
return true;
}
}
}
Step 3 - Prevent the service from breaking your tests
Import the LaunchDarklyMockModule
into the test module that tests whatever object you added the service to in the previous step. See the Testing section further down for more information.
Usage
Add the LaunchDarklyService
to any component/directive/guard/etc. you'd like to have check a feature, call isFeatureActive
and pass in the feature key associated with the flag.
Example
export class SomeComponent {
constructor(private launchDarklyService: LaunchDarklyService) {}
isMyAwesomeNewFeatureActive(): boolean {
return this.launchDarklyService.isFeatureActive(
'awesome_new_feature_key'
);
}
}
<div class="some-stuff">
<div class="existing-stuff">...</div>
<div class="awesome-new-stuff" *ngIf="isMyAwesomeNewFeatureActive()">
...
</div>
</div>
Testing
You will need to import the LaunchDarklyMockModule
into any test modules that will be testing an object that has the LaunchDarklyService
in its constructor. Without doing this, your tests will try to make calls to LaunchDarkly over the internet and fail.
Example
describe('AppComponent', () => {
let component: AppComponent;
let fixture: ComponentFixture<AppComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [AppComponent],
imports: [
...
LaunchDarklyMockModule,
...
],
}).compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(AppComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});