UNPKG

ngx-growthbook

Version:
200 lines (193 loc) 6.84 kB
import * as i0 from '@angular/core'; import { InjectionToken, Inject, Injectable, makeEnvironmentProviders, provideAppInitializer, inject } from '@angular/core'; import { GrowthBook } from '@growthbook/growthbook'; import { Subject, takeUntil, Observable } from 'rxjs'; const NGX_GROWTHBOOK_CONFIG_TOKEN = new InjectionToken('ngx-growthbook.config'); class NgxGrowthbookService { config; growthBook; growthBookSource = new Subject(); eventCount = 0; destroy$ = new Subject(); constructor(config) { this.config = config; } ngOnDestroy() { this.growthBookSource.unsubscribe(); this.destroy$.next(); this.destroy$.complete(); } async init(config, trackingService) { if (!config.clientKey) { throw new Error('GrowthBook clientKey is required'); } console.log('Initializing GrowthBook...'); this.growthBook = new GrowthBook({ trackingCallback: trackingService ? (experiment, result) => { trackingService?.trackExperiment(experiment.key, result); } : config.trackingCallback, onFeatureUsage: trackingService ? (featureKey, result) => { trackingService?.trackFeature?.(featureKey, result); } : config.onFeatureUsage, ...config, }); await this.growthBook.init({ skipCache: true, streaming: true }); this.growthBook.setRenderer(() => { this.triggerUpdate(); }); console.log('...GrowthBook initialized'); return this.growthBook; } triggerUpdate() { this.growthBookSource.next((this.eventCount += 1)); } subscribe(callback) { callback(0); return this.growthBookSource .pipe(takeUntil(this.destroy$)) .subscribe(() => { callback; }); } getFeature(featureKey, defaultValue) { return this.evaluateFeatureSync(featureKey, defaultValue); } /** * Evaluates a feature and returns an observable that will emit whenever the feature changes * @param featureKey The feature key to evaluate * @param defaultValue The default value if the feature is not found */ evaluateFeature(featureKey, defaultValue) { const evaluate = () => { const result = this.growthBook.evalFeature(featureKey); return result; }; // Initial evaluation const initial = evaluate(); // Create an observable that emits whenever features are updated return new Observable((subscriber) => { subscriber.next(initial); const subscription = this.growthBookSource .pipe(takeUntil(this.destroy$)) .subscribe(() => { subscriber.next(evaluate()); }); return () => subscription.unsubscribe(); }); } /** * Evaluates a feature and returns the current value synchronously * @param featureKey The feature key to evaluate * @param defaultValue The default value if the feature is not found */ evaluateFeatureSync(featureKey, defaultValue) { const result = this.growthBook.evalFeature(featureKey); return result; } loadFeatures() { return this.growthBook.loadFeatures(); } isOn(featureKey) { return this.growthBook.isOn(featureKey); } isOff(featureKey) { return this.growthBook.isOff(featureKey); } setFeatureValue(featureKey) { if (featureKey) { this.growthBook.setFeatures({ featureKey: { defaultValue: true }, }); } } getFeatureValue(featureKey, defaultValue) { return this.growthBook.getFeatureValue(featureKey, defaultValue); } /** * In addition to the isOn and getFeatureValue helper methods, * there is the evalFeature method that gives you more detailed * information about why the value was assigned to the user. * @param featureKey * @returns */ evalFeature(featureKey) { return this.growthBook.evalFeature(featureKey); } /** * Completely replaces attributes * @param attributes */ setAttributes(attributes) { return this.growthBook.setAttributes(attributes); } updateAttributes(attributes) { const existingAttributes = this.getAttributes(); return this.growthBook.setAttributes({ ...existingAttributes, ...attributes, }); } refreshFeatures(options) { return this.growthBook.refreshFeatures(options); } setURL(url) { return this.growthBook.setURL(url); } getAttributes() { return this.growthBook.getAttributes(); } getFeatures() { return this.growthBook.getFeatures(); } getExperiments() { return this.growthBook.getExperiments(); } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: NgxGrowthbookService, deps: [{ token: NGX_GROWTHBOOK_CONFIG_TOKEN }], target: i0.ɵɵFactoryTarget.Injectable }); static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: NgxGrowthbookService, providedIn: 'root' }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.5", ngImport: i0, type: NgxGrowthbookService, decorators: [{ type: Injectable, args: [{ providedIn: 'root', }] }], ctorParameters: () => [{ type: undefined, decorators: [{ type: Inject, args: [NGX_GROWTHBOOK_CONFIG_TOKEN] }] }] }); function provideNgxGrowthbook(config) { if (!config.clientKey) { throw new Error('GrowthBook clientKey is required'); } const providers = [ { provide: NGX_GROWTHBOOK_CONFIG_TOKEN, useValue: config, }, NgxGrowthbookService, ]; if (config.trackingService) { providers.push(config.trackingService); } return makeEnvironmentProviders([ ...providers, provideAppInitializer(async () => { const growthbookService = inject(NgxGrowthbookService); const trackingService = config.trackingService ? inject(config.trackingService) : null; await growthbookService.init(config, trackingService); }), ]); } /* * Public API Surface of ngx-growthbook */ /** * Generated bundle index. Do not edit. */ export { NGX_GROWTHBOOK_CONFIG_TOKEN, NgxGrowthbookService, provideNgxGrowthbook }; //# sourceMappingURL=ngx-growthbook.mjs.map