@savvagent/angular 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/LICENSE +21 -0
  3. package/README.md +484 -0
  4. package/coverage/base.css +224 -0
  5. package/coverage/block-navigation.js +87 -0
  6. package/coverage/favicon.png +0 -0
  7. package/coverage/index.html +131 -0
  8. package/coverage/lcov-report/base.css +224 -0
  9. package/coverage/lcov-report/block-navigation.js +87 -0
  10. package/coverage/lcov-report/favicon.png +0 -0
  11. package/coverage/lcov-report/index.html +131 -0
  12. package/coverage/lcov-report/module.ts.html +289 -0
  13. package/coverage/lcov-report/prettify.css +1 -0
  14. package/coverage/lcov-report/prettify.js +2 -0
  15. package/coverage/lcov-report/service.ts.html +1846 -0
  16. package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  17. package/coverage/lcov-report/sorter.js +210 -0
  18. package/coverage/lcov.info +242 -0
  19. package/coverage/module.ts.html +289 -0
  20. package/coverage/prettify.css +1 -0
  21. package/coverage/prettify.js +2 -0
  22. package/coverage/service.ts.html +1846 -0
  23. package/coverage/sort-arrow-sprite.png +0 -0
  24. package/coverage/sorter.js +210 -0
  25. package/dist/README.md +484 -0
  26. package/dist/esm2022/index.mjs +15 -0
  27. package/dist/esm2022/module.mjs +75 -0
  28. package/dist/esm2022/savvagent-angular.mjs +5 -0
  29. package/dist/esm2022/service.mjs +473 -0
  30. package/dist/fesm2022/savvagent-angular.mjs +563 -0
  31. package/dist/fesm2022/savvagent-angular.mjs.map +1 -0
  32. package/dist/index.d.ts +13 -0
  33. package/dist/module.d.ts +57 -0
  34. package/dist/service.d.ts +319 -0
  35. package/jest.config.js +40 -0
  36. package/ng-package.json +8 -0
  37. package/package.json +73 -0
  38. package/setup-jest.ts +2 -0
  39. package/src/index.spec.ts +144 -0
  40. package/src/index.ts +38 -0
  41. package/src/module.spec.ts +283 -0
  42. package/src/module.ts +68 -0
  43. package/src/service.spec.ts +945 -0
  44. package/src/service.ts +587 -0
  45. package/test-utils/angular-core-mock.ts +28 -0
  46. package/test-utils/angular-testing-mock.ts +87 -0
  47. package/tsconfig.json +33 -0
  48. package/tsconfig.spec.json +11 -0
@@ -0,0 +1,563 @@
1
+ import * as i0 from '@angular/core';
2
+ import { InjectionToken, Optional, Inject, Injectable, NgModule } from '@angular/core';
3
+ import { Subject, BehaviorSubject, of, from } from 'rxjs';
4
+ import { takeUntil, distinctUntilChanged, map, catchError } from 'rxjs/operators';
5
+ import { FlagClient } from '@savvagent/sdk';
6
+ export { FlagClient } from '@savvagent/sdk';
7
+
8
+ /**
9
+ * Injection token for Savvagent configuration
10
+ */
11
+ const SAVVAGENT_CONFIG = new InjectionToken('SAVVAGENT_CONFIG');
12
+ /**
13
+ * Angular service for Savvagent feature flags.
14
+ * Provides reactive flag evaluation using RxJS Observables.
15
+ *
16
+ * @example
17
+ * ```typescript
18
+ * // In your component
19
+ * @Component({...})
20
+ * export class MyComponent {
21
+ * newFeature$ = this.savvagent.flag$('new-feature');
22
+ *
23
+ * constructor(private savvagent: SavvagentService) {}
24
+ * }
25
+ *
26
+ * // In your template
27
+ * <div *ngIf="(newFeature$ | async)?.value">
28
+ * New feature content!
29
+ * </div>
30
+ * ```
31
+ */
32
+ class SavvagentService {
33
+ client = null;
34
+ destroy$ = new Subject();
35
+ isReady$ = new BehaviorSubject(false);
36
+ defaultContext = {};
37
+ flagSubjects = new Map();
38
+ constructor(config) {
39
+ if (config) {
40
+ this.initialize(config);
41
+ }
42
+ }
43
+ /**
44
+ * Initialize the Savvagent client with configuration.
45
+ * Call this if not using the SAVVAGENT_CONFIG injection token.
46
+ *
47
+ * @param savvagentConfig - Configuration including API key and default context
48
+ *
49
+ * @example
50
+ * ```typescript
51
+ * @Component({...})
52
+ * export class AppComponent implements OnInit {
53
+ * constructor(private savvagent: SavvagentService) {}
54
+ *
55
+ * ngOnInit() {
56
+ * this.savvagent.initialize({
57
+ * config: { apiKey: 'sdk_...' },
58
+ * defaultContext: {
59
+ * applicationId: 'my-app',
60
+ * environment: 'development',
61
+ * userId: 'user-123'
62
+ * }
63
+ * });
64
+ * }
65
+ * }
66
+ * ```
67
+ */
68
+ initialize(savvagentConfig) {
69
+ if (this.client) {
70
+ console.warn('[Savvagent] Client already initialized. Call close() first to reinitialize.');
71
+ return;
72
+ }
73
+ try {
74
+ this.client = new FlagClient(savvagentConfig.config);
75
+ // Convert DefaultFlagContext to FlagContext format (camelCase to snake_case)
76
+ if (savvagentConfig.defaultContext) {
77
+ this.defaultContext = {
78
+ application_id: savvagentConfig.defaultContext.applicationId,
79
+ environment: savvagentConfig.defaultContext.environment,
80
+ organization_id: savvagentConfig.defaultContext.organizationId,
81
+ user_id: savvagentConfig.defaultContext.userId,
82
+ anonymous_id: savvagentConfig.defaultContext.anonymousId,
83
+ session_id: savvagentConfig.defaultContext.sessionId,
84
+ language: savvagentConfig.defaultContext.language,
85
+ attributes: savvagentConfig.defaultContext.attributes,
86
+ };
87
+ }
88
+ this.isReady$.next(true);
89
+ // Subscribe to override changes to re-evaluate all active flags
90
+ this.client.onOverrideChange(() => {
91
+ this.reEvaluateAllFlags();
92
+ });
93
+ }
94
+ catch (error) {
95
+ console.error('[Savvagent] Failed to initialize client:', error);
96
+ savvagentConfig.config.onError?.(error);
97
+ }
98
+ }
99
+ /**
100
+ * Observable that emits true when the client is ready.
101
+ */
102
+ get ready$() {
103
+ return this.isReady$.asObservable();
104
+ }
105
+ /**
106
+ * Check if the client is ready.
107
+ */
108
+ get isReady() {
109
+ return this.isReady$.value;
110
+ }
111
+ /**
112
+ * Get the underlying FlagClient instance for advanced use cases.
113
+ */
114
+ get flagClient() {
115
+ return this.client;
116
+ }
117
+ /**
118
+ * Merge default context with per-call context.
119
+ */
120
+ mergeContext(context) {
121
+ return {
122
+ ...this.defaultContext,
123
+ ...context,
124
+ attributes: {
125
+ ...this.defaultContext.attributes,
126
+ ...context?.attributes,
127
+ },
128
+ };
129
+ }
130
+ /**
131
+ * Get a reactive Observable for a feature flag.
132
+ * Automatically updates when the flag value changes.
133
+ *
134
+ * @param flagKey - The feature flag key to evaluate
135
+ * @param options - Configuration options
136
+ * @returns Observable of flag evaluation state
137
+ *
138
+ * @example
139
+ * ```typescript
140
+ * // In your component
141
+ * newFeature$ = this.savvagent.flag$('new-feature', {
142
+ * defaultValue: false,
143
+ * realtime: true,
144
+ * context: { attributes: { plan: 'pro' } }
145
+ * });
146
+ *
147
+ * // In template
148
+ * <ng-container *ngIf="newFeature$ | async as flag">
149
+ * <app-loading *ngIf="flag.loading"></app-loading>
150
+ * <app-new-feature *ngIf="flag.value"></app-new-feature>
151
+ * <app-old-feature *ngIf="!flag.value && !flag.loading"></app-old-feature>
152
+ * </ng-container>
153
+ * ```
154
+ */
155
+ flag$(flagKey, options = {}) {
156
+ const { context, defaultValue = false, realtime = true } = options;
157
+ const mergedContext = this.mergeContext(context);
158
+ const cacheKey = this.getCacheKey(flagKey, mergedContext);
159
+ // Check if we already have a subject for this flag+context
160
+ if (!this.flagSubjects.has(cacheKey)) {
161
+ const subject = new BehaviorSubject({
162
+ value: defaultValue,
163
+ loading: true,
164
+ error: null,
165
+ result: null,
166
+ });
167
+ this.flagSubjects.set(cacheKey, subject);
168
+ // Initial evaluation
169
+ this.evaluateAndEmit(flagKey, mergedContext, defaultValue, subject);
170
+ // Set up real-time subscription if enabled
171
+ if (realtime && this.client) {
172
+ const unsubscribe = this.client.subscribe(flagKey, () => {
173
+ this.evaluateAndEmit(flagKey, mergedContext, defaultValue, subject);
174
+ });
175
+ // Clean up subscription when subject is complete
176
+ subject.pipe(takeUntil(this.destroy$)).subscribe({
177
+ complete: () => unsubscribe(),
178
+ });
179
+ }
180
+ }
181
+ return this.flagSubjects.get(cacheKey).asObservable().pipe(takeUntil(this.destroy$), distinctUntilChanged((a, b) => a.value === b.value &&
182
+ a.loading === b.loading &&
183
+ a.error === b.error));
184
+ }
185
+ /**
186
+ * Generate a cache key for a flag+context combination.
187
+ */
188
+ getCacheKey(flagKey, context) {
189
+ return `${flagKey}:${JSON.stringify(context)}`;
190
+ }
191
+ /**
192
+ * Evaluate a flag and emit the result to a subject.
193
+ */
194
+ async evaluateAndEmit(flagKey, context, defaultValue, subject) {
195
+ if (!this.client) {
196
+ subject.next({
197
+ value: defaultValue,
198
+ loading: false,
199
+ error: new Error('Savvagent client not initialized'),
200
+ result: null,
201
+ });
202
+ return;
203
+ }
204
+ try {
205
+ const result = await this.client.evaluate(flagKey, context);
206
+ subject.next({
207
+ value: result.value,
208
+ loading: false,
209
+ error: null,
210
+ result,
211
+ });
212
+ }
213
+ catch (error) {
214
+ subject.next({
215
+ value: defaultValue,
216
+ loading: false,
217
+ error: error,
218
+ result: null,
219
+ });
220
+ }
221
+ }
222
+ /**
223
+ * Re-evaluate all active flag subscriptions.
224
+ * Called when overrides change.
225
+ */
226
+ reEvaluateAllFlags() {
227
+ this.flagSubjects.forEach((subject, cacheKey) => {
228
+ const [flagKey, contextJson] = cacheKey.split(':', 2);
229
+ const context = JSON.parse(contextJson || '{}');
230
+ const currentValue = subject.value;
231
+ this.evaluateAndEmit(flagKey, context, currentValue.value, subject);
232
+ });
233
+ }
234
+ /**
235
+ * Get a flag value as a simple Observable<boolean>.
236
+ * Useful when you only need the value without loading/error states.
237
+ *
238
+ * @param flagKey - The feature flag key to evaluate
239
+ * @param options - Configuration options
240
+ * @returns Observable of boolean flag value
241
+ *
242
+ * @example
243
+ * ```typescript
244
+ * isFeatureEnabled$ = this.savvagent.flagValue$('my-feature');
245
+ *
246
+ * // In template
247
+ * <button *ngIf="isFeatureEnabled$ | async">New Button</button>
248
+ * ```
249
+ */
250
+ flagValue$(flagKey, options = {}) {
251
+ return this.flag$(flagKey, options).pipe(map((result) => result.value), distinctUntilChanged());
252
+ }
253
+ /**
254
+ * Evaluate a feature flag once (non-reactive).
255
+ * For reactive updates, use flag$() instead.
256
+ *
257
+ * @param flagKey - The feature flag key to evaluate
258
+ * @param context - Optional context for targeting
259
+ * @returns Promise with detailed evaluation result
260
+ *
261
+ * @example
262
+ * ```typescript
263
+ * async checkFeature() {
264
+ * const result = await this.savvagent.evaluate('new-feature');
265
+ * if (result.value) {
266
+ * // Feature is enabled
267
+ * }
268
+ * }
269
+ * ```
270
+ */
271
+ async evaluate(flagKey, context) {
272
+ if (!this.client) {
273
+ throw new Error('Savvagent client not initialized');
274
+ }
275
+ return this.client.evaluate(flagKey, this.mergeContext(context));
276
+ }
277
+ /**
278
+ * Check if a feature flag is enabled (non-reactive).
279
+ *
280
+ * @param flagKey - The feature flag key to evaluate
281
+ * @param context - Optional context for targeting
282
+ * @returns Promise<boolean>
283
+ */
284
+ async isEnabled(flagKey, context) {
285
+ if (!this.client) {
286
+ return false;
287
+ }
288
+ return this.client.isEnabled(flagKey, this.mergeContext(context));
289
+ }
290
+ /**
291
+ * Execute code conditionally based on flag value.
292
+ *
293
+ * @param flagKey - The flag key to check
294
+ * @param callback - Function to execute if flag is enabled
295
+ * @param context - Optional context for targeting
296
+ *
297
+ * @example
298
+ * ```typescript
299
+ * await this.savvagent.withFlag('analytics-enabled', async () => {
300
+ * await this.analytics.track('page_view');
301
+ * });
302
+ * ```
303
+ */
304
+ async withFlag(flagKey, callback, context) {
305
+ if (!this.client) {
306
+ return null;
307
+ }
308
+ return this.client.withFlag(flagKey, callback, this.mergeContext(context));
309
+ }
310
+ /**
311
+ * Track an error with flag context.
312
+ *
313
+ * @param flagKey - The flag key associated with the error
314
+ * @param error - The error that occurred
315
+ * @param context - Optional context
316
+ */
317
+ trackError(flagKey, error, context) {
318
+ this.client?.trackError(flagKey, error, this.mergeContext(context));
319
+ }
320
+ /**
321
+ * Set the user ID for logged-in users.
322
+ *
323
+ * @param userId - The user ID (or null to clear)
324
+ */
325
+ setUserId(userId) {
326
+ this.client?.setUserId(userId);
327
+ }
328
+ /**
329
+ * Get the current user ID.
330
+ */
331
+ getUserId() {
332
+ return this.client?.getUserId() || null;
333
+ }
334
+ /**
335
+ * Get the current anonymous ID.
336
+ */
337
+ getAnonymousId() {
338
+ return this.client?.getAnonymousId() || null;
339
+ }
340
+ /**
341
+ * Set a custom anonymous ID.
342
+ */
343
+ setAnonymousId(id) {
344
+ this.client?.setAnonymousId(id);
345
+ }
346
+ // =====================
347
+ // Local Override Methods
348
+ // =====================
349
+ /**
350
+ * Set a local override for a flag.
351
+ * Overrides take precedence over server values.
352
+ *
353
+ * @param flagKey - The flag key to override
354
+ * @param value - The override value
355
+ */
356
+ setOverride(flagKey, value) {
357
+ this.client?.setOverride(flagKey, value);
358
+ }
359
+ /**
360
+ * Clear a local override for a flag.
361
+ */
362
+ clearOverride(flagKey) {
363
+ this.client?.clearOverride(flagKey);
364
+ }
365
+ /**
366
+ * Clear all local overrides.
367
+ */
368
+ clearAllOverrides() {
369
+ this.client?.clearAllOverrides();
370
+ }
371
+ /**
372
+ * Check if a flag has a local override.
373
+ */
374
+ hasOverride(flagKey) {
375
+ return this.client?.hasOverride(flagKey) || false;
376
+ }
377
+ /**
378
+ * Get the override value for a flag.
379
+ */
380
+ getOverride(flagKey) {
381
+ return this.client?.getOverride(flagKey);
382
+ }
383
+ /**
384
+ * Get all current overrides.
385
+ */
386
+ getOverrides() {
387
+ return this.client?.getOverrides() || {};
388
+ }
389
+ /**
390
+ * Set multiple overrides at once.
391
+ */
392
+ setOverrides(overrides) {
393
+ this.client?.setOverrides(overrides);
394
+ }
395
+ // =====================
396
+ // Flag Discovery Methods
397
+ // =====================
398
+ /**
399
+ * Get all flags for the application.
400
+ *
401
+ * @param environment - Environment to evaluate (default: 'development')
402
+ * @returns Observable of flag definitions
403
+ */
404
+ getAllFlags$(environment = 'development') {
405
+ if (!this.client) {
406
+ return of([]);
407
+ }
408
+ return from(this.client.getAllFlags(environment)).pipe(catchError((error) => {
409
+ console.error('[Savvagent] Failed to fetch all flags:', error);
410
+ return of([]);
411
+ }));
412
+ }
413
+ /**
414
+ * Get all flags for the application (Promise-based).
415
+ */
416
+ async getAllFlags(environment = 'development') {
417
+ if (!this.client) {
418
+ return [];
419
+ }
420
+ return this.client.getAllFlags(environment);
421
+ }
422
+ /**
423
+ * Get enterprise-scoped flags only.
424
+ */
425
+ async getEnterpriseFlags(environment = 'development') {
426
+ if (!this.client) {
427
+ return [];
428
+ }
429
+ return this.client.getEnterpriseFlags(environment);
430
+ }
431
+ // =====================
432
+ // Cache & Connection
433
+ // =====================
434
+ /**
435
+ * Clear the flag cache.
436
+ */
437
+ clearCache() {
438
+ this.client?.clearCache();
439
+ }
440
+ /**
441
+ * Check if real-time connection is active.
442
+ */
443
+ isRealtimeConnected() {
444
+ return this.client?.isRealtimeConnected() || false;
445
+ }
446
+ /**
447
+ * Close the client and cleanup resources.
448
+ */
449
+ close() {
450
+ this.client?.close();
451
+ this.client = null;
452
+ this.isReady$.next(false);
453
+ this.flagSubjects.forEach((subject) => subject.complete());
454
+ this.flagSubjects.clear();
455
+ }
456
+ ngOnDestroy() {
457
+ this.destroy$.next();
458
+ this.destroy$.complete();
459
+ this.close();
460
+ }
461
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: SavvagentService, deps: [{ token: SAVVAGENT_CONFIG, optional: true }], target: i0.ɵɵFactoryTarget.Injectable });
462
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: SavvagentService, providedIn: 'root' });
463
+ }
464
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: SavvagentService, decorators: [{
465
+ type: Injectable,
466
+ args: [{
467
+ providedIn: 'root'
468
+ }]
469
+ }], ctorParameters: () => [{ type: undefined, decorators: [{
470
+ type: Optional
471
+ }, {
472
+ type: Inject,
473
+ args: [SAVVAGENT_CONFIG]
474
+ }] }] });
475
+
476
+ /**
477
+ * Angular module for Savvagent feature flags.
478
+ *
479
+ * @example
480
+ * ```typescript
481
+ * // app.module.ts
482
+ * import { SavvagentModule } from '@savvagent/angular';
483
+ *
484
+ * @NgModule({
485
+ * imports: [
486
+ * SavvagentModule.forRoot({
487
+ * config: {
488
+ * apiKey: 'sdk_your_api_key',
489
+ * baseUrl: 'https://api.savvagent.com'
490
+ * },
491
+ * defaultContext: {
492
+ * applicationId: 'my-app',
493
+ * environment: 'production',
494
+ * userId: 'user-123'
495
+ * }
496
+ * })
497
+ * ]
498
+ * })
499
+ * export class AppModule {}
500
+ * ```
501
+ *
502
+ * @example
503
+ * ```typescript
504
+ * // For standalone components (Angular 14+)
505
+ * import { SavvagentModule } from '@savvagent/angular';
506
+ *
507
+ * bootstrapApplication(AppComponent, {
508
+ * providers: [
509
+ * importProvidersFrom(
510
+ * SavvagentModule.forRoot({
511
+ * config: { apiKey: 'sdk_...' }
512
+ * })
513
+ * )
514
+ * ]
515
+ * });
516
+ * ```
517
+ */
518
+ class SavvagentModule {
519
+ /**
520
+ * Configure the Savvagent module with API key and default context.
521
+ *
522
+ * @param savvagentConfig - Configuration including API key and optional default context
523
+ * @returns Module with providers
524
+ */
525
+ static forRoot(savvagentConfig) {
526
+ return {
527
+ ngModule: SavvagentModule,
528
+ providers: [
529
+ {
530
+ provide: SAVVAGENT_CONFIG,
531
+ useValue: savvagentConfig
532
+ },
533
+ SavvagentService
534
+ ]
535
+ };
536
+ }
537
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: SavvagentModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
538
+ static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.14", ngImport: i0, type: SavvagentModule });
539
+ static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: SavvagentModule, providers: [SavvagentService] });
540
+ }
541
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: SavvagentModule, decorators: [{
542
+ type: NgModule,
543
+ args: [{
544
+ providers: [SavvagentService]
545
+ }]
546
+ }] });
547
+
548
+ /**
549
+ * @savvagent/angular - Angular SDK for Savvagent feature flags
550
+ *
551
+ * This package provides Angular services and modules for easy integration
552
+ * of Savvagent feature flags into Angular applications.
553
+ *
554
+ * @packageDocumentation
555
+ */
556
+ // Module
557
+
558
+ /**
559
+ * Generated bundle index. Do not edit.
560
+ */
561
+
562
+ export { SAVVAGENT_CONFIG, SavvagentModule, SavvagentService };
563
+ //# sourceMappingURL=savvagent-angular.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"savvagent-angular.mjs","sources":["../../src/service.ts","../../src/module.ts","../../src/index.ts","../../src/savvagent-angular.ts"],"sourcesContent":["import { Injectable, OnDestroy, Inject, InjectionToken, Optional } from '@angular/core';\nimport { BehaviorSubject, Observable, from, of, Subject } from 'rxjs';\nimport { map, takeUntil, catchError, distinctUntilChanged } from 'rxjs/operators';\nimport { FlagClient, FlagClientConfig, FlagContext, FlagEvaluationResult, FlagDefinition } from '@savvagent/sdk';\n\n/**\n * Default context values that apply to all flag evaluations\n * Per SDK Developer Guide: https://docs.savvagent.com/sdk-developer-guide\n */\nexport interface DefaultFlagContext {\n /** Application ID for application-scoped flags */\n applicationId?: string;\n /** Environment (development, staging, production) */\n environment?: string;\n /** Organization ID for multi-tenant apps */\n organizationId?: string;\n /** Default user ID (required for percentage rollouts) */\n userId?: string;\n /** Default anonymous ID (alternative to userId for anonymous users) */\n anonymousId?: string;\n /** Session ID as fallback identifier */\n sessionId?: string;\n /** User's language code (e.g., \"en\", \"es\") */\n language?: string;\n /** Default attributes for targeting */\n attributes?: Record<string, any>;\n}\n\n/**\n * Configuration for the Savvagent Angular service\n */\nexport interface SavvagentConfig {\n /** SDK API key configuration */\n config: FlagClientConfig;\n /** Default context values applied to all flag evaluations */\n defaultContext?: DefaultFlagContext;\n}\n\n/**\n * Injection token for Savvagent configuration\n */\nexport const SAVVAGENT_CONFIG = new InjectionToken<SavvagentConfig>('SAVVAGENT_CONFIG');\n\n/**\n * Result from flag evaluation as an Observable\n */\nexport interface FlagObservableResult {\n /** Current flag value */\n value: boolean;\n /** Whether the flag is currently being evaluated */\n loading: boolean;\n /** Error if evaluation failed */\n error: Error | null;\n /** Detailed evaluation result */\n result: FlagEvaluationResult | null;\n}\n\n/**\n * Options for flag evaluation\n */\nexport interface FlagOptions {\n /** Context for flag evaluation (user_id, attributes, etc.) */\n context?: FlagContext;\n /** Default value to use while loading or on error */\n defaultValue?: boolean;\n /** Enable real-time updates for this flag */\n realtime?: boolean;\n}\n\n/**\n * Angular service for Savvagent feature flags.\n * Provides reactive flag evaluation using RxJS Observables.\n *\n * @example\n * ```typescript\n * // In your component\n * @Component({...})\n * export class MyComponent {\n * newFeature$ = this.savvagent.flag$('new-feature');\n *\n * constructor(private savvagent: SavvagentService) {}\n * }\n *\n * // In your template\n * <div *ngIf=\"(newFeature$ | async)?.value\">\n * New feature content!\n * </div>\n * ```\n */\n@Injectable({\n providedIn: 'root'\n})\nexport class SavvagentService implements OnDestroy {\n private client: FlagClient | null = null;\n private destroy$ = new Subject<void>();\n private isReady$ = new BehaviorSubject<boolean>(false);\n private defaultContext: FlagContext = {};\n private flagSubjects = new Map<string, BehaviorSubject<FlagObservableResult>>();\n\n constructor(\n @Optional() @Inject(SAVVAGENT_CONFIG) config?: SavvagentConfig\n ) {\n if (config) {\n this.initialize(config);\n }\n }\n\n /**\n * Initialize the Savvagent client with configuration.\n * Call this if not using the SAVVAGENT_CONFIG injection token.\n *\n * @param savvagentConfig - Configuration including API key and default context\n *\n * @example\n * ```typescript\n * @Component({...})\n * export class AppComponent implements OnInit {\n * constructor(private savvagent: SavvagentService) {}\n *\n * ngOnInit() {\n * this.savvagent.initialize({\n * config: { apiKey: 'sdk_...' },\n * defaultContext: {\n * applicationId: 'my-app',\n * environment: 'development',\n * userId: 'user-123'\n * }\n * });\n * }\n * }\n * ```\n */\n initialize(savvagentConfig: SavvagentConfig): void {\n if (this.client) {\n console.warn('[Savvagent] Client already initialized. Call close() first to reinitialize.');\n return;\n }\n\n try {\n this.client = new FlagClient(savvagentConfig.config);\n\n // Convert DefaultFlagContext to FlagContext format (camelCase to snake_case)\n if (savvagentConfig.defaultContext) {\n this.defaultContext = {\n application_id: savvagentConfig.defaultContext.applicationId,\n environment: savvagentConfig.defaultContext.environment,\n organization_id: savvagentConfig.defaultContext.organizationId,\n user_id: savvagentConfig.defaultContext.userId,\n anonymous_id: savvagentConfig.defaultContext.anonymousId,\n session_id: savvagentConfig.defaultContext.sessionId,\n language: savvagentConfig.defaultContext.language,\n attributes: savvagentConfig.defaultContext.attributes,\n };\n }\n\n this.isReady$.next(true);\n\n // Subscribe to override changes to re-evaluate all active flags\n this.client.onOverrideChange(() => {\n this.reEvaluateAllFlags();\n });\n } catch (error) {\n console.error('[Savvagent] Failed to initialize client:', error);\n savvagentConfig.config.onError?.(error as Error);\n }\n }\n\n /**\n * Observable that emits true when the client is ready.\n */\n get ready$(): Observable<boolean> {\n return this.isReady$.asObservable();\n }\n\n /**\n * Check if the client is ready.\n */\n get isReady(): boolean {\n return this.isReady$.value;\n }\n\n /**\n * Get the underlying FlagClient instance for advanced use cases.\n */\n get flagClient(): FlagClient | null {\n return this.client;\n }\n\n /**\n * Merge default context with per-call context.\n */\n private mergeContext(context?: FlagContext): FlagContext {\n return {\n ...this.defaultContext,\n ...context,\n attributes: {\n ...this.defaultContext.attributes,\n ...context?.attributes,\n },\n };\n }\n\n /**\n * Get a reactive Observable for a feature flag.\n * Automatically updates when the flag value changes.\n *\n * @param flagKey - The feature flag key to evaluate\n * @param options - Configuration options\n * @returns Observable of flag evaluation state\n *\n * @example\n * ```typescript\n * // In your component\n * newFeature$ = this.savvagent.flag$('new-feature', {\n * defaultValue: false,\n * realtime: true,\n * context: { attributes: { plan: 'pro' } }\n * });\n *\n * // In template\n * <ng-container *ngIf=\"newFeature$ | async as flag\">\n * <app-loading *ngIf=\"flag.loading\"></app-loading>\n * <app-new-feature *ngIf=\"flag.value\"></app-new-feature>\n * <app-old-feature *ngIf=\"!flag.value && !flag.loading\"></app-old-feature>\n * </ng-container>\n * ```\n */\n flag$(flagKey: string, options: FlagOptions = {}): Observable<FlagObservableResult> {\n const { context, defaultValue = false, realtime = true } = options;\n const mergedContext = this.mergeContext(context);\n const cacheKey = this.getCacheKey(flagKey, mergedContext);\n\n // Check if we already have a subject for this flag+context\n if (!this.flagSubjects.has(cacheKey)) {\n const subject = new BehaviorSubject<FlagObservableResult>({\n value: defaultValue,\n loading: true,\n error: null,\n result: null,\n });\n this.flagSubjects.set(cacheKey, subject);\n\n // Initial evaluation\n this.evaluateAndEmit(flagKey, mergedContext, defaultValue, subject);\n\n // Set up real-time subscription if enabled\n if (realtime && this.client) {\n const unsubscribe = this.client.subscribe(flagKey, () => {\n this.evaluateAndEmit(flagKey, mergedContext, defaultValue, subject);\n });\n\n // Clean up subscription when subject is complete\n subject.pipe(takeUntil(this.destroy$)).subscribe({\n complete: () => unsubscribe(),\n });\n }\n }\n\n return this.flagSubjects.get(cacheKey)!.asObservable().pipe(\n takeUntil(this.destroy$),\n distinctUntilChanged((a, b) =>\n a.value === b.value &&\n a.loading === b.loading &&\n a.error === b.error\n )\n );\n }\n\n /**\n * Generate a cache key for a flag+context combination.\n */\n private getCacheKey(flagKey: string, context: FlagContext): string {\n return `${flagKey}:${JSON.stringify(context)}`;\n }\n\n /**\n * Evaluate a flag and emit the result to a subject.\n */\n private async evaluateAndEmit(\n flagKey: string,\n context: FlagContext,\n defaultValue: boolean,\n subject: BehaviorSubject<FlagObservableResult>\n ): Promise<void> {\n if (!this.client) {\n subject.next({\n value: defaultValue,\n loading: false,\n error: new Error('Savvagent client not initialized'),\n result: null,\n });\n return;\n }\n\n try {\n const result = await this.client.evaluate(flagKey, context);\n subject.next({\n value: result.value,\n loading: false,\n error: null,\n result,\n });\n } catch (error) {\n subject.next({\n value: defaultValue,\n loading: false,\n error: error as Error,\n result: null,\n });\n }\n }\n\n /**\n * Re-evaluate all active flag subscriptions.\n * Called when overrides change.\n */\n private reEvaluateAllFlags(): void {\n this.flagSubjects.forEach((subject, cacheKey) => {\n const [flagKey, contextJson] = cacheKey.split(':', 2);\n const context = JSON.parse(contextJson || '{}');\n const currentValue = subject.value;\n this.evaluateAndEmit(flagKey, context, currentValue.value, subject);\n });\n }\n\n /**\n * Get a flag value as a simple Observable<boolean>.\n * Useful when you only need the value without loading/error states.\n *\n * @param flagKey - The feature flag key to evaluate\n * @param options - Configuration options\n * @returns Observable of boolean flag value\n *\n * @example\n * ```typescript\n * isFeatureEnabled$ = this.savvagent.flagValue$('my-feature');\n *\n * // In template\n * <button *ngIf=\"isFeatureEnabled$ | async\">New Button</button>\n * ```\n */\n flagValue$(flagKey: string, options: FlagOptions = {}): Observable<boolean> {\n return this.flag$(flagKey, options).pipe(\n map((result) => result.value),\n distinctUntilChanged()\n );\n }\n\n /**\n * Evaluate a feature flag once (non-reactive).\n * For reactive updates, use flag$() instead.\n *\n * @param flagKey - The feature flag key to evaluate\n * @param context - Optional context for targeting\n * @returns Promise with detailed evaluation result\n *\n * @example\n * ```typescript\n * async checkFeature() {\n * const result = await this.savvagent.evaluate('new-feature');\n * if (result.value) {\n * // Feature is enabled\n * }\n * }\n * ```\n */\n async evaluate(flagKey: string, context?: FlagContext): Promise<FlagEvaluationResult> {\n if (!this.client) {\n throw new Error('Savvagent client not initialized');\n }\n return this.client.evaluate(flagKey, this.mergeContext(context));\n }\n\n /**\n * Check if a feature flag is enabled (non-reactive).\n *\n * @param flagKey - The feature flag key to evaluate\n * @param context - Optional context for targeting\n * @returns Promise<boolean>\n */\n async isEnabled(flagKey: string, context?: FlagContext): Promise<boolean> {\n if (!this.client) {\n return false;\n }\n return this.client.isEnabled(flagKey, this.mergeContext(context));\n }\n\n /**\n * Execute code conditionally based on flag value.\n *\n * @param flagKey - The flag key to check\n * @param callback - Function to execute if flag is enabled\n * @param context - Optional context for targeting\n *\n * @example\n * ```typescript\n * await this.savvagent.withFlag('analytics-enabled', async () => {\n * await this.analytics.track('page_view');\n * });\n * ```\n */\n async withFlag<T>(\n flagKey: string,\n callback: () => T | Promise<T>,\n context?: FlagContext\n ): Promise<T | null> {\n if (!this.client) {\n return null;\n }\n return this.client.withFlag(flagKey, callback, this.mergeContext(context));\n }\n\n /**\n * Track an error with flag context.\n *\n * @param flagKey - The flag key associated with the error\n * @param error - The error that occurred\n * @param context - Optional context\n */\n trackError(flagKey: string, error: Error, context?: FlagContext): void {\n this.client?.trackError(flagKey, error, this.mergeContext(context));\n }\n\n /**\n * Set the user ID for logged-in users.\n *\n * @param userId - The user ID (or null to clear)\n */\n setUserId(userId: string | null): void {\n this.client?.setUserId(userId);\n }\n\n /**\n * Get the current user ID.\n */\n getUserId(): string | null {\n return this.client?.getUserId() || null;\n }\n\n /**\n * Get the current anonymous ID.\n */\n getAnonymousId(): string | null {\n return this.client?.getAnonymousId() || null;\n }\n\n /**\n * Set a custom anonymous ID.\n */\n setAnonymousId(id: string): void {\n this.client?.setAnonymousId(id);\n }\n\n // =====================\n // Local Override Methods\n // =====================\n\n /**\n * Set a local override for a flag.\n * Overrides take precedence over server values.\n *\n * @param flagKey - The flag key to override\n * @param value - The override value\n */\n setOverride(flagKey: string, value: boolean): void {\n this.client?.setOverride(flagKey, value);\n }\n\n /**\n * Clear a local override for a flag.\n */\n clearOverride(flagKey: string): void {\n this.client?.clearOverride(flagKey);\n }\n\n /**\n * Clear all local overrides.\n */\n clearAllOverrides(): void {\n this.client?.clearAllOverrides();\n }\n\n /**\n * Check if a flag has a local override.\n */\n hasOverride(flagKey: string): boolean {\n return this.client?.hasOverride(flagKey) || false;\n }\n\n /**\n * Get the override value for a flag.\n */\n getOverride(flagKey: string): boolean | undefined {\n return this.client?.getOverride(flagKey);\n }\n\n /**\n * Get all current overrides.\n */\n getOverrides(): Record<string, boolean> {\n return this.client?.getOverrides() || {};\n }\n\n /**\n * Set multiple overrides at once.\n */\n setOverrides(overrides: Record<string, boolean>): void {\n this.client?.setOverrides(overrides);\n }\n\n // =====================\n // Flag Discovery Methods\n // =====================\n\n /**\n * Get all flags for the application.\n *\n * @param environment - Environment to evaluate (default: 'development')\n * @returns Observable of flag definitions\n */\n getAllFlags$(environment: string = 'development'): Observable<FlagDefinition[]> {\n if (!this.client) {\n return of([]);\n }\n return from(this.client.getAllFlags(environment)).pipe(\n catchError((error) => {\n console.error('[Savvagent] Failed to fetch all flags:', error);\n return of([]);\n })\n );\n }\n\n /**\n * Get all flags for the application (Promise-based).\n */\n async getAllFlags(environment: string = 'development'): Promise<FlagDefinition[]> {\n if (!this.client) {\n return [];\n }\n return this.client.getAllFlags(environment);\n }\n\n /**\n * Get enterprise-scoped flags only.\n */\n async getEnterpriseFlags(environment: string = 'development'): Promise<FlagDefinition[]> {\n if (!this.client) {\n return [];\n }\n return this.client.getEnterpriseFlags(environment);\n }\n\n // =====================\n // Cache & Connection\n // =====================\n\n /**\n * Clear the flag cache.\n */\n clearCache(): void {\n this.client?.clearCache();\n }\n\n /**\n * Check if real-time connection is active.\n */\n isRealtimeConnected(): boolean {\n return this.client?.isRealtimeConnected() || false;\n }\n\n /**\n * Close the client and cleanup resources.\n */\n close(): void {\n this.client?.close();\n this.client = null;\n this.isReady$.next(false);\n this.flagSubjects.forEach((subject) => subject.complete());\n this.flagSubjects.clear();\n }\n\n ngOnDestroy(): void {\n this.destroy$.next();\n this.destroy$.complete();\n this.close();\n }\n}\n","import { NgModule, ModuleWithProviders } from '@angular/core';\nimport { SavvagentService, SavvagentConfig, SAVVAGENT_CONFIG } from './service';\n\n/**\n * Angular module for Savvagent feature flags.\n *\n * @example\n * ```typescript\n * // app.module.ts\n * import { SavvagentModule } from '@savvagent/angular';\n *\n * @NgModule({\n * imports: [\n * SavvagentModule.forRoot({\n * config: {\n * apiKey: 'sdk_your_api_key',\n * baseUrl: 'https://api.savvagent.com'\n * },\n * defaultContext: {\n * applicationId: 'my-app',\n * environment: 'production',\n * userId: 'user-123'\n * }\n * })\n * ]\n * })\n * export class AppModule {}\n * ```\n *\n * @example\n * ```typescript\n * // For standalone components (Angular 14+)\n * import { SavvagentModule } from '@savvagent/angular';\n *\n * bootstrapApplication(AppComponent, {\n * providers: [\n * importProvidersFrom(\n * SavvagentModule.forRoot({\n * config: { apiKey: 'sdk_...' }\n * })\n * )\n * ]\n * });\n * ```\n */\n@NgModule({\n providers: [SavvagentService]\n})\nexport class SavvagentModule {\n /**\n * Configure the Savvagent module with API key and default context.\n *\n * @param savvagentConfig - Configuration including API key and optional default context\n * @returns Module with providers\n */\n static forRoot(savvagentConfig: SavvagentConfig): ModuleWithProviders<SavvagentModule> {\n return {\n ngModule: SavvagentModule,\n providers: [\n {\n provide: SAVVAGENT_CONFIG,\n useValue: savvagentConfig\n },\n SavvagentService\n ]\n };\n }\n}\n","/**\n * @savvagent/angular - Angular SDK for Savvagent feature flags\n *\n * This package provides Angular services and modules for easy integration\n * of Savvagent feature flags into Angular applications.\n *\n * @packageDocumentation\n */\n\n// Module\nexport { SavvagentModule } from './module';\n\n// Service and types\nexport { SavvagentService, SAVVAGENT_CONFIG } from './service';\nexport type {\n SavvagentConfig,\n DefaultFlagContext,\n FlagObservableResult,\n FlagOptions,\n} from './service';\n\n// Re-export types from core SDK\nexport type {\n FlagClientConfig,\n FlagContext,\n FlagEvaluationResult,\n EvaluationEvent,\n ErrorEvent,\n FlagUpdateEvent,\n FlagDefinition,\n FlagListResponse,\n // Generated API types for advanced users\n ApiTypes,\n components,\n} from '@savvagent/sdk';\n\n// Re-export FlagClient for advanced use cases\nexport { FlagClient } from '@savvagent/sdk';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * @savvagent/angular - Angular SDK for Savvagent feature flags
3
+ *
4
+ * This package provides Angular services and modules for easy integration
5
+ * of Savvagent feature flags into Angular applications.
6
+ *
7
+ * @packageDocumentation
8
+ */
9
+ export { SavvagentModule } from './module';
10
+ export { SavvagentService, SAVVAGENT_CONFIG } from './service';
11
+ export type { SavvagentConfig, DefaultFlagContext, FlagObservableResult, FlagOptions, } from './service';
12
+ export type { FlagClientConfig, FlagContext, FlagEvaluationResult, EvaluationEvent, ErrorEvent, FlagUpdateEvent, FlagDefinition, FlagListResponse, ApiTypes, components, } from '@savvagent/sdk';
13
+ export { FlagClient } from '@savvagent/sdk';