@openfeature/server-sdk 1.19.0 → 1.20.0

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.
package/dist/cjs/index.js CHANGED
@@ -58,15 +58,24 @@ var __async = (__this, __arguments, generator) => {
58
58
  // src/index.ts
59
59
  var index_exports = {};
60
60
  __export(index_exports, {
61
+ AggregateError: () => AggregateError,
61
62
  AsyncLocalStorageTransactionContextPropagator: () => AsyncLocalStorageTransactionContextPropagator,
63
+ BaseEvaluationStrategy: () => BaseEvaluationStrategy,
64
+ ComparisonStrategy: () => ComparisonStrategy,
65
+ ErrorWithCode: () => ErrorWithCode,
66
+ FirstMatchStrategy: () => FirstMatchStrategy,
67
+ FirstSuccessfulStrategy: () => FirstSuccessfulStrategy,
62
68
  InMemoryProvider: () => InMemoryProvider,
69
+ MultiProvider: () => MultiProvider,
63
70
  NOOP_PROVIDER: () => NOOP_PROVIDER,
64
71
  NOOP_TRANSACTION_CONTEXT_PROPAGATOR: () => NOOP_TRANSACTION_CONTEXT_PROPAGATOR,
65
72
  OpenFeature: () => OpenFeature,
66
73
  OpenFeatureAPI: () => OpenFeatureAPI,
67
74
  OpenFeatureEventEmitter: () => OpenFeatureEventEmitter,
68
75
  ProviderEvents: () => import_core6.ServerProviderEvents,
69
- ProviderStatus: () => import_core.ServerProviderStatus
76
+ ProviderStatus: () => import_core.ServerProviderStatus,
77
+ constructAggregateError: () => constructAggregateError,
78
+ throwAggregateErrorFromPromiseResults: () => throwAggregateErrorFromPromiseResults
70
79
  });
71
80
  module.exports = __toCommonJS(index_exports);
72
81
 
@@ -194,11 +203,555 @@ var InMemoryProvider = class {
194
203
  }
195
204
  };
196
205
 
197
- // src/open-feature.ts
206
+ // src/provider/multi-provider/multi-provider.ts
207
+ var import_core9 = require("@openfeature/core");
208
+
209
+ // src/events/open-feature-event-emitter.ts
210
+ var import_core4 = require("@openfeature/core");
211
+ var import_node_events = require("node:events");
212
+ var OpenFeatureEventEmitter = class extends import_core4.GenericEventEmitter {
213
+ constructor() {
214
+ super();
215
+ this.eventEmitter = new import_node_events.EventEmitter({ captureRejections: true });
216
+ this.eventEmitter.on("error", (err) => {
217
+ var _a;
218
+ (_a = this._logger) == null ? void 0 : _a.error("Error running event handler:", err);
219
+ });
220
+ }
221
+ };
222
+
223
+ // src/provider/multi-provider/errors.ts
224
+ var import_core5 = require("@openfeature/core");
225
+ var ErrorWithCode = class extends import_core5.OpenFeatureError {
226
+ constructor(code, message) {
227
+ super(message);
228
+ this.code = code;
229
+ }
230
+ };
231
+ var AggregateError = class extends import_core5.GeneralError {
232
+ constructor(message, originalErrors) {
233
+ super(message);
234
+ this.originalErrors = originalErrors;
235
+ }
236
+ };
237
+ var constructAggregateError = (providerErrors) => {
238
+ const errorsWithSource = providerErrors.map(({ providerName, error }) => {
239
+ return { source: providerName, error };
240
+ }).flat();
241
+ return new AggregateError(
242
+ `Provider errors occurred: ${errorsWithSource[0].source}: ${errorsWithSource[0].error}`,
243
+ errorsWithSource
244
+ );
245
+ };
246
+ var throwAggregateErrorFromPromiseResults = (result, providerEntries) => {
247
+ const errors = result.map((r, i) => {
248
+ if (r.status === "rejected") {
249
+ return { error: r.reason, providerName: providerEntries[i].name };
250
+ }
251
+ return null;
252
+ }).filter((val) => Boolean(val));
253
+ if (errors.length) {
254
+ throw constructAggregateError(errors);
255
+ }
256
+ };
257
+
258
+ // src/provider/multi-provider/hook-executor.ts
259
+ var HookExecutor = class {
260
+ constructor(logger) {
261
+ this.logger = logger;
262
+ }
263
+ beforeHooks(hooks, hookContext, hints) {
264
+ return __async(this, null, function* () {
265
+ var _a;
266
+ for (const hook of hooks != null ? hooks : []) {
267
+ Object.freeze(hookContext);
268
+ Object.assign(hookContext.context, __spreadValues({}, yield (_a = hook == null ? void 0 : hook.before) == null ? void 0 : _a.call(hook, hookContext, Object.freeze(hints))));
269
+ }
270
+ return Object.freeze(hookContext.context);
271
+ });
272
+ }
273
+ afterHooks(hooks, hookContext, evaluationDetails, hints) {
274
+ return __async(this, null, function* () {
275
+ var _a;
276
+ for (const hook of hooks != null ? hooks : []) {
277
+ yield (_a = hook == null ? void 0 : hook.after) == null ? void 0 : _a.call(hook, hookContext, evaluationDetails, hints);
278
+ }
279
+ });
280
+ }
281
+ errorHooks(hooks, hookContext, err, hints) {
282
+ return __async(this, null, function* () {
283
+ var _a;
284
+ for (const hook of hooks != null ? hooks : []) {
285
+ try {
286
+ yield (_a = hook == null ? void 0 : hook.error) == null ? void 0 : _a.call(hook, hookContext, err, hints);
287
+ } catch (err2) {
288
+ this.logger.error(`Unhandled error during 'error' hook: ${err2}`);
289
+ if (err2 instanceof Error) {
290
+ this.logger.error(err2.stack);
291
+ }
292
+ this.logger.error(err2 == null ? void 0 : err2.stack);
293
+ }
294
+ }
295
+ });
296
+ }
297
+ finallyHooks(hooks, hookContext, evaluationDetails, hints) {
298
+ return __async(this, null, function* () {
299
+ var _a;
300
+ for (const hook of hooks != null ? hooks : []) {
301
+ try {
302
+ yield (_a = hook == null ? void 0 : hook.finally) == null ? void 0 : _a.call(hook, hookContext, evaluationDetails, hints);
303
+ } catch (err) {
304
+ this.logger.error(`Unhandled error during 'finally' hook: ${err}`);
305
+ if (err instanceof Error) {
306
+ this.logger.error(err.stack);
307
+ }
308
+ this.logger.error(err == null ? void 0 : err.stack);
309
+ }
310
+ }
311
+ });
312
+ }
313
+ };
314
+
315
+ // src/events/events.ts
316
+ var import_core6 = require("@openfeature/core");
317
+
318
+ // src/provider/multi-provider/status-tracker.ts
319
+ var StatusTracker = class {
320
+ constructor(events) {
321
+ this.events = events;
322
+ this.providerStatuses = {};
323
+ }
324
+ wrapEventHandler(providerEntry) {
325
+ var _a, _b, _c, _d;
326
+ const provider = providerEntry.provider;
327
+ (_a = provider.events) == null ? void 0 : _a.addHandler(import_core6.ServerProviderEvents.Error, (details) => {
328
+ this.changeProviderStatus(providerEntry.name, import_core.ServerProviderStatus.ERROR, details);
329
+ });
330
+ (_b = provider.events) == null ? void 0 : _b.addHandler(import_core6.ServerProviderEvents.Stale, (details) => {
331
+ this.changeProviderStatus(providerEntry.name, import_core.ServerProviderStatus.STALE, details);
332
+ });
333
+ (_c = provider.events) == null ? void 0 : _c.addHandler(import_core6.ServerProviderEvents.ConfigurationChanged, (details) => {
334
+ this.events.emit(import_core6.ServerProviderEvents.ConfigurationChanged, details);
335
+ });
336
+ (_d = provider.events) == null ? void 0 : _d.addHandler(import_core6.ServerProviderEvents.Ready, (details) => {
337
+ this.changeProviderStatus(providerEntry.name, import_core.ServerProviderStatus.READY, details);
338
+ });
339
+ }
340
+ providerStatus(name) {
341
+ return this.providerStatuses[name];
342
+ }
343
+ getStatusFromProviderStatuses() {
344
+ const statuses = Object.values(this.providerStatuses);
345
+ if (statuses.includes(import_core.ServerProviderStatus.FATAL)) {
346
+ return import_core.ServerProviderStatus.FATAL;
347
+ } else if (statuses.includes(import_core.ServerProviderStatus.NOT_READY)) {
348
+ return import_core.ServerProviderStatus.NOT_READY;
349
+ } else if (statuses.includes(import_core.ServerProviderStatus.ERROR)) {
350
+ return import_core.ServerProviderStatus.ERROR;
351
+ } else if (statuses.includes(import_core.ServerProviderStatus.STALE)) {
352
+ return import_core.ServerProviderStatus.STALE;
353
+ }
354
+ return import_core.ServerProviderStatus.READY;
355
+ }
356
+ changeProviderStatus(name, status, details) {
357
+ const currentStatus = this.getStatusFromProviderStatuses();
358
+ this.providerStatuses[name] = status;
359
+ const newStatus = this.getStatusFromProviderStatuses();
360
+ if (currentStatus !== newStatus) {
361
+ if (newStatus === import_core.ServerProviderStatus.FATAL || newStatus === import_core.ServerProviderStatus.ERROR) {
362
+ this.events.emit(import_core6.ServerProviderEvents.Error, details);
363
+ } else if (newStatus === import_core.ServerProviderStatus.STALE) {
364
+ this.events.emit(import_core6.ServerProviderEvents.Stale, details);
365
+ } else if (newStatus === import_core.ServerProviderStatus.READY) {
366
+ this.events.emit(import_core6.ServerProviderEvents.Ready, details);
367
+ }
368
+ }
369
+ }
370
+ };
371
+
372
+ // src/provider/multi-provider/strategies/base-evaluation-strategy.ts
373
+ var BaseEvaluationStrategy = class {
374
+ constructor() {
375
+ this.runMode = "sequential";
376
+ }
377
+ shouldEvaluateThisProvider(strategyContext, _evalContext) {
378
+ if (strategyContext.providerStatus === import_core.ServerProviderStatus.NOT_READY || strategyContext.providerStatus === import_core.ServerProviderStatus.FATAL) {
379
+ return false;
380
+ }
381
+ return true;
382
+ }
383
+ shouldEvaluateNextProvider(_strategyContext, _context, _result) {
384
+ return true;
385
+ }
386
+ shouldTrackWithThisProvider(strategyContext, _context, _trackingEventName, _trackingEventDetails) {
387
+ if (strategyContext.providerStatus === import_core.ServerProviderStatus.NOT_READY || strategyContext.providerStatus === import_core.ServerProviderStatus.FATAL) {
388
+ return false;
389
+ }
390
+ return true;
391
+ }
392
+ hasError(resolution) {
393
+ return "thrownError" in resolution || !!resolution.details.errorCode;
394
+ }
395
+ hasErrorWithCode(resolution, code) {
396
+ var _a;
397
+ return "thrownError" in resolution ? ((_a = resolution.thrownError) == null ? void 0 : _a.code) === code : resolution.details.errorCode === code;
398
+ }
399
+ collectProviderErrors(resolutions) {
400
+ var _a;
401
+ const errors = [];
402
+ for (const resolution of resolutions) {
403
+ if ("thrownError" in resolution) {
404
+ errors.push({ providerName: resolution.providerName, error: resolution.thrownError });
405
+ } else if (resolution.details.errorCode) {
406
+ errors.push({
407
+ providerName: resolution.providerName,
408
+ error: new ErrorWithCode(resolution.details.errorCode, (_a = resolution.details.errorMessage) != null ? _a : "unknown error")
409
+ });
410
+ }
411
+ }
412
+ return { errors };
413
+ }
414
+ resolutionToFinalResult(resolution) {
415
+ return { details: resolution.details, provider: resolution.provider, providerName: resolution.providerName };
416
+ }
417
+ };
418
+
419
+ // src/provider/multi-provider/strategies/first-match-strategy.ts
198
420
  var import_core7 = require("@openfeature/core");
421
+ var FirstMatchStrategy = class extends BaseEvaluationStrategy {
422
+ shouldEvaluateNextProvider(strategyContext, context, result) {
423
+ if (this.hasErrorWithCode(result, import_core7.ErrorCode.FLAG_NOT_FOUND)) {
424
+ return true;
425
+ }
426
+ if (this.hasError(result)) {
427
+ return false;
428
+ }
429
+ return false;
430
+ }
431
+ determineFinalResult(strategyContext, context, resolutions) {
432
+ const finalResolution = resolutions[resolutions.length - 1];
433
+ if (this.hasError(finalResolution)) {
434
+ return this.collectProviderErrors(resolutions);
435
+ }
436
+ return this.resolutionToFinalResult(finalResolution);
437
+ }
438
+ };
439
+
440
+ // src/provider/multi-provider/strategies/first-successful-strategy.ts
441
+ var FirstSuccessfulStrategy = class extends BaseEvaluationStrategy {
442
+ shouldEvaluateNextProvider(strategyContext, context, result) {
443
+ return this.hasError(result);
444
+ }
445
+ determineFinalResult(strategyContext, context, resolutions) {
446
+ const finalResolution = resolutions[resolutions.length - 1];
447
+ if (this.hasError(finalResolution)) {
448
+ return this.collectProviderErrors(resolutions);
449
+ }
450
+ return this.resolutionToFinalResult(finalResolution);
451
+ }
452
+ };
453
+
454
+ // src/provider/multi-provider/strategies/comparison-strategy.ts
455
+ var import_core8 = require("@openfeature/core");
456
+ var ComparisonStrategy = class extends BaseEvaluationStrategy {
457
+ constructor(fallbackProvider, onMismatch) {
458
+ super();
459
+ this.fallbackProvider = fallbackProvider;
460
+ this.onMismatch = onMismatch;
461
+ this.runMode = "parallel";
462
+ }
463
+ determineFinalResult(strategyContext, context, resolutions) {
464
+ var _a;
465
+ let value;
466
+ let fallbackResolution;
467
+ let finalResolution;
468
+ let mismatch = false;
469
+ for (const [i, resolution] of resolutions.entries()) {
470
+ if (this.hasError(resolution)) {
471
+ return this.collectProviderErrors(resolutions);
472
+ }
473
+ if (resolution.provider === this.fallbackProvider) {
474
+ fallbackResolution = resolution;
475
+ }
476
+ if (i === 0) {
477
+ finalResolution = resolution;
478
+ }
479
+ if (typeof value !== "undefined" && value !== resolution.details.value) {
480
+ mismatch = true;
481
+ } else {
482
+ value = resolution.details.value;
483
+ }
484
+ }
485
+ if (!fallbackResolution) {
486
+ throw new import_core8.GeneralError("Fallback provider not found in resolution results");
487
+ }
488
+ if (!finalResolution) {
489
+ throw new import_core8.GeneralError("Final resolution not found in resolution results");
490
+ }
491
+ if (mismatch) {
492
+ (_a = this.onMismatch) == null ? void 0 : _a.call(this, resolutions);
493
+ return {
494
+ details: fallbackResolution.details,
495
+ provider: fallbackResolution.provider
496
+ };
497
+ }
498
+ return this.resolutionToFinalResult(finalResolution);
499
+ }
500
+ };
501
+
502
+ // src/provider/multi-provider/multi-provider.ts
503
+ var MultiProvider = class _MultiProvider {
504
+ constructor(constructorProviders, evaluationStrategy = new FirstMatchStrategy(), logger = new import_core9.DefaultLogger()) {
505
+ this.constructorProviders = constructorProviders;
506
+ this.evaluationStrategy = evaluationStrategy;
507
+ this.logger = logger;
508
+ this.runsOn = "server";
509
+ this.events = new OpenFeatureEventEmitter();
510
+ this.hookContexts = /* @__PURE__ */ new WeakMap();
511
+ this.hookHints = /* @__PURE__ */ new WeakMap();
512
+ this.providerEntries = [];
513
+ this.providerEntriesByName = {};
514
+ this.statusTracker = new StatusTracker(this.events);
515
+ this.hookExecutor = new HookExecutor(this.logger);
516
+ this.registerProviders(constructorProviders);
517
+ const aggregateMetadata = Object.keys(this.providerEntriesByName).reduce((acc, name) => {
518
+ return __spreadProps(__spreadValues({}, acc), { [name]: this.providerEntriesByName[name].provider.metadata });
519
+ }, {});
520
+ this.metadata = __spreadProps(__spreadValues({}, aggregateMetadata), {
521
+ name: _MultiProvider.name
522
+ });
523
+ }
524
+ registerProviders(constructorProviders) {
525
+ var _a, _b;
526
+ const providersByName = {};
527
+ for (const constructorProvider of constructorProviders) {
528
+ const providerName = constructorProvider.provider.metadata.name;
529
+ const candidateName = (_a = constructorProvider.name) != null ? _a : providerName;
530
+ if (constructorProvider.name && providersByName[constructorProvider.name]) {
531
+ throw new Error("Provider names must be unique");
532
+ }
533
+ (_b = providersByName[candidateName]) != null ? _b : providersByName[candidateName] = [];
534
+ providersByName[candidateName].push(constructorProvider.provider);
535
+ }
536
+ for (const name of Object.keys(providersByName)) {
537
+ const useIndexedNames = providersByName[name].length > 1;
538
+ for (let i = 0; i < providersByName[name].length; i++) {
539
+ const indexedName = useIndexedNames ? `${name}-${i + 1}` : name;
540
+ this.providerEntriesByName[indexedName] = { provider: providersByName[name][i], name: indexedName };
541
+ this.providerEntries.push(this.providerEntriesByName[indexedName]);
542
+ this.statusTracker.wrapEventHandler(this.providerEntriesByName[indexedName]);
543
+ }
544
+ }
545
+ Object.freeze(this.providerEntries);
546
+ Object.freeze(this.providerEntriesByName);
547
+ }
548
+ initialize(context) {
549
+ return __async(this, null, function* () {
550
+ const result = yield Promise.allSettled(
551
+ this.providerEntries.map((provider) => {
552
+ var _a, _b;
553
+ return (_b = (_a = provider.provider).initialize) == null ? void 0 : _b.call(_a, context);
554
+ })
555
+ );
556
+ throwAggregateErrorFromPromiseResults(result, this.providerEntries);
557
+ });
558
+ }
559
+ onClose() {
560
+ return __async(this, null, function* () {
561
+ const result = yield Promise.allSettled(this.providerEntries.map((provider) => {
562
+ var _a, _b;
563
+ return (_b = (_a = provider.provider).onClose) == null ? void 0 : _b.call(_a);
564
+ }));
565
+ throwAggregateErrorFromPromiseResults(result, this.providerEntries);
566
+ });
567
+ }
568
+ resolveBooleanEvaluation(flagKey, defaultValue, context) {
569
+ return this.flagResolutionProxy(flagKey, "boolean", defaultValue, context);
570
+ }
571
+ resolveStringEvaluation(flagKey, defaultValue, context) {
572
+ return this.flagResolutionProxy(flagKey, "string", defaultValue, context);
573
+ }
574
+ resolveNumberEvaluation(flagKey, defaultValue, context) {
575
+ return this.flagResolutionProxy(flagKey, "number", defaultValue, context);
576
+ }
577
+ resolveObjectEvaluation(flagKey, defaultValue, context) {
578
+ return this.flagResolutionProxy(flagKey, "object", defaultValue, context);
579
+ }
580
+ flagResolutionProxy(flagKey, flagType, defaultValue, context) {
581
+ return __async(this, null, function* () {
582
+ var _a;
583
+ const hookContext = this.hookContexts.get(context);
584
+ const hookHints = this.hookHints.get(context);
585
+ if (!hookContext || !hookHints) {
586
+ throw new import_core9.GeneralError("Hook context not available for evaluation");
587
+ }
588
+ const tasks = [];
589
+ for (const providerEntry of this.providerEntries) {
590
+ const task = this.evaluateProviderEntry(
591
+ flagKey,
592
+ flagType,
593
+ defaultValue,
594
+ providerEntry,
595
+ hookContext,
596
+ hookHints,
597
+ context
598
+ );
599
+ tasks.push(task);
600
+ if (this.evaluationStrategy.runMode === "sequential") {
601
+ const [shouldEvaluateNext] = yield task;
602
+ if (!shouldEvaluateNext) {
603
+ break;
604
+ }
605
+ }
606
+ }
607
+ const results = yield Promise.all(tasks);
608
+ const resolutions = results.map(([, resolution]) => resolution).filter((r) => Boolean(r));
609
+ const finalResult = this.evaluationStrategy.determineFinalResult({ flagKey, flagType }, context, resolutions);
610
+ if ((_a = finalResult.errors) == null ? void 0 : _a.length) {
611
+ throw constructAggregateError(finalResult.errors);
612
+ }
613
+ if (!finalResult.details) {
614
+ throw new import_core9.GeneralError("No result was returned from any provider");
615
+ }
616
+ return finalResult.details;
617
+ });
618
+ }
619
+ evaluateProviderEntry(flagKey, flagType, defaultValue, providerEntry, hookContext, hookHints, context) {
620
+ return __async(this, null, function* () {
621
+ let evaluationResult = void 0;
622
+ const provider = providerEntry.provider;
623
+ const strategyContext = {
624
+ flagKey,
625
+ flagType,
626
+ provider,
627
+ providerName: providerEntry.name,
628
+ providerStatus: this.statusTracker.providerStatus(providerEntry.name)
629
+ };
630
+ if (!this.evaluationStrategy.shouldEvaluateThisProvider(strategyContext, context)) {
631
+ return [true, null];
632
+ }
633
+ let resolution;
634
+ try {
635
+ evaluationResult = yield this.evaluateProviderAndHooks(flagKey, defaultValue, provider, hookContext, hookHints);
636
+ resolution = {
637
+ details: evaluationResult,
638
+ provider,
639
+ providerName: providerEntry.name
640
+ };
641
+ } catch (error) {
642
+ resolution = {
643
+ thrownError: error,
644
+ provider,
645
+ providerName: providerEntry.name
646
+ };
647
+ }
648
+ return [
649
+ this.evaluationStrategy.runMode === "sequential" ? this.evaluationStrategy.shouldEvaluateNextProvider(strategyContext, context, resolution) : true,
650
+ resolution
651
+ ];
652
+ });
653
+ }
654
+ evaluateProviderAndHooks(flagKey, defaultValue, provider, hookContext, hookHints) {
655
+ return __async(this, null, function* () {
656
+ var _a;
657
+ let providerContext = void 0;
658
+ let evaluationDetails;
659
+ const hookContextCopy = __spreadProps(__spreadValues({}, hookContext), { context: __spreadValues({}, hookContext.context) });
660
+ try {
661
+ providerContext = yield this.hookExecutor.beforeHooks(provider.hooks, hookContextCopy, hookHints);
662
+ const resolutionDetails = yield this.callProviderResolve(
663
+ provider,
664
+ flagKey,
665
+ defaultValue,
666
+ providerContext || {}
667
+ );
668
+ evaluationDetails = __spreadProps(__spreadValues({}, resolutionDetails), {
669
+ flagMetadata: Object.freeze((_a = resolutionDetails.flagMetadata) != null ? _a : {}),
670
+ flagKey
671
+ });
672
+ yield this.hookExecutor.afterHooks(provider.hooks, hookContextCopy, evaluationDetails, hookHints);
673
+ } catch (error) {
674
+ yield this.hookExecutor.errorHooks(provider.hooks, hookContextCopy, error, hookHints);
675
+ evaluationDetails = this.getErrorEvaluationDetails(flagKey, defaultValue, error);
676
+ }
677
+ yield this.hookExecutor.finallyHooks(provider.hooks, hookContextCopy, evaluationDetails, hookHints);
678
+ return evaluationDetails;
679
+ });
680
+ }
681
+ callProviderResolve(provider, flagKey, defaultValue, context) {
682
+ return __async(this, null, function* () {
683
+ switch (typeof defaultValue) {
684
+ case "string":
685
+ return yield provider.resolveStringEvaluation(flagKey, defaultValue, context, this.logger);
686
+ case "number":
687
+ return yield provider.resolveNumberEvaluation(flagKey, defaultValue, context, this.logger);
688
+ case "object":
689
+ return yield provider.resolveObjectEvaluation(flagKey, defaultValue, context, this.logger);
690
+ case "boolean":
691
+ return yield provider.resolveBooleanEvaluation(flagKey, defaultValue, context, this.logger);
692
+ default:
693
+ throw new import_core9.GeneralError("Invalid flag evaluation type");
694
+ }
695
+ });
696
+ }
697
+ get hooks() {
698
+ return [
699
+ {
700
+ before: (hookContext, hints) => __async(this, null, function* () {
701
+ this.hookContexts.set(hookContext.context, hookContext);
702
+ this.hookHints.set(hookContext.context, hints != null ? hints : {});
703
+ return hookContext.context;
704
+ })
705
+ }
706
+ ];
707
+ }
708
+ track(trackingEventName, context, trackingEventDetails) {
709
+ var _a, _b;
710
+ for (const providerEntry of this.providerEntries) {
711
+ if (!providerEntry.provider.track) {
712
+ continue;
713
+ }
714
+ const strategyContext = {
715
+ provider: providerEntry.provider,
716
+ providerName: providerEntry.name,
717
+ providerStatus: this.statusTracker.providerStatus(providerEntry.name)
718
+ };
719
+ if (this.evaluationStrategy.shouldTrackWithThisProvider(
720
+ strategyContext,
721
+ context,
722
+ trackingEventName,
723
+ trackingEventDetails
724
+ )) {
725
+ try {
726
+ (_b = (_a = providerEntry.provider).track) == null ? void 0 : _b.call(_a, trackingEventName, context, trackingEventDetails);
727
+ } catch (error) {
728
+ this.logger.error(
729
+ `Error tracking event "${trackingEventName}" with provider "${providerEntry.name}":`,
730
+ error
731
+ );
732
+ }
733
+ }
734
+ }
735
+ }
736
+ getErrorEvaluationDetails(flagKey, defaultValue, err, flagMetadata = {}) {
737
+ const errorMessage = err == null ? void 0 : err.message;
738
+ const errorCode = (err == null ? void 0 : err.code) || import_core9.ErrorCode.GENERAL;
739
+ return {
740
+ errorCode,
741
+ errorMessage,
742
+ value: defaultValue,
743
+ reason: import_core9.StandardResolutionReasons.ERROR,
744
+ flagMetadata: Object.freeze(flagMetadata),
745
+ flagKey
746
+ };
747
+ }
748
+ };
749
+
750
+ // src/open-feature.ts
751
+ var import_core11 = require("@openfeature/core");
199
752
 
200
753
  // src/client/internal/open-feature-client.ts
201
- var import_core4 = require("@openfeature/core");
754
+ var import_core10 = require("@openfeature/core");
202
755
  var OpenFeatureClient = class {
203
756
  constructor(providerAccessor, providerStatusAccessor, emitterAccessor, apiContextAccessor, apiHooksAccessor, transactionContextAccessor, globalLogger, options, context = {}) {
204
757
  this.providerAccessor = providerAccessor;
@@ -228,7 +781,7 @@ var OpenFeatureClient = class {
228
781
  addHandler(eventType, handler, options) {
229
782
  var _a;
230
783
  this.emitterAccessor().addHandler(eventType, handler);
231
- const shouldRunNow = (0, import_core4.statusMatchesEvent)(eventType, this._providerStatus);
784
+ const shouldRunNow = (0, import_core10.statusMatchesEvent)(eventType, this._providerStatus);
232
785
  if (shouldRunNow) {
233
786
  try {
234
787
  handler({
@@ -253,7 +806,7 @@ var OpenFeatureClient = class {
253
806
  return this.emitterAccessor().getHandlers(eventType);
254
807
  }
255
808
  setLogger(logger) {
256
- this._clientLogger = new import_core4.SafeLogger(logger);
809
+ this._clientLogger = new import_core10.SafeLogger(logger);
257
810
  return this;
258
811
  }
259
812
  setContext(context) {
@@ -363,7 +916,7 @@ var OpenFeatureClient = class {
363
916
  providerMetadata: this._provider.metadata,
364
917
  context: mergedContext,
365
918
  logger: this._logger,
366
- hookData: new import_core4.MapHookData()
919
+ hookData: new import_core10.MapHookData()
367
920
  })
368
921
  );
369
922
  let evaluationDetails;
@@ -376,7 +929,7 @@ var OpenFeatureClient = class {
376
929
  flagKey
377
930
  });
378
931
  if (resolutionDetails.errorCode) {
379
- const err = (0, import_core4.instantiateErrorByErrorCode)(resolutionDetails.errorCode, resolutionDetails.errorMessage);
932
+ const err = (0, import_core10.instantiateErrorByErrorCode)(resolutionDetails.errorCode, resolutionDetails.errorMessage);
380
933
  yield this.errorHooks(allHooksReversed, hookContexts, err, options);
381
934
  evaluationDetails = this.getErrorEvaluationDetails(flagKey, defaultValue, err, resolutionDetails.flagMetadata);
382
935
  } else {
@@ -467,42 +1020,25 @@ var OpenFeatureClient = class {
467
1020
  }
468
1021
  shortCircuitIfNotReady() {
469
1022
  if (this.providerStatus === import_core.ServerProviderStatus.NOT_READY) {
470
- throw new import_core4.ProviderNotReadyError("provider has not yet initialized");
1023
+ throw new import_core10.ProviderNotReadyError("provider has not yet initialized");
471
1024
  } else if (this.providerStatus === import_core.ServerProviderStatus.FATAL) {
472
- throw new import_core4.ProviderFatalError("provider is in an irrecoverable error state");
1025
+ throw new import_core10.ProviderFatalError("provider is in an irrecoverable error state");
473
1026
  }
474
1027
  }
475
1028
  getErrorEvaluationDetails(flagKey, defaultValue, err, flagMetadata = {}) {
476
1029
  const errorMessage = err == null ? void 0 : err.message;
477
- const errorCode = (err == null ? void 0 : err.code) || import_core4.ErrorCode.GENERAL;
1030
+ const errorCode = (err == null ? void 0 : err.code) || import_core10.ErrorCode.GENERAL;
478
1031
  return {
479
1032
  errorCode,
480
1033
  errorMessage,
481
1034
  value: defaultValue,
482
- reason: import_core4.StandardResolutionReasons.ERROR,
1035
+ reason: import_core10.StandardResolutionReasons.ERROR,
483
1036
  flagMetadata: Object.freeze(flagMetadata),
484
1037
  flagKey
485
1038
  };
486
1039
  }
487
1040
  };
488
1041
 
489
- // src/events/open-feature-event-emitter.ts
490
- var import_core5 = require("@openfeature/core");
491
- var import_node_events = require("node:events");
492
- var OpenFeatureEventEmitter = class extends import_core5.GenericEventEmitter {
493
- constructor() {
494
- super();
495
- this.eventEmitter = new import_node_events.EventEmitter({ captureRejections: true });
496
- this.eventEmitter.on("error", (err) => {
497
- var _a;
498
- (_a = this._logger) == null ? void 0 : _a.error("Error running event handler:", err);
499
- });
500
- }
501
- };
502
-
503
- // src/events/events.ts
504
- var import_core6 = require("@openfeature/core");
505
-
506
1042
  // src/transaction-context/no-op-transaction-context-propagator.ts
507
1043
  var NoopTransactionContextPropagator = class {
508
1044
  getTransactionContext() {
@@ -532,12 +1068,12 @@ var AsyncLocalStorageTransactionContextPropagator = class {
532
1068
  // src/open-feature.ts
533
1069
  var GLOBAL_OPENFEATURE_API_KEY = Symbol.for("@openfeature/js-sdk/api");
534
1070
  var _globalThis = globalThis;
535
- var OpenFeatureAPI = class _OpenFeatureAPI extends import_core7.OpenFeatureCommonAPI {
1071
+ var OpenFeatureAPI = class _OpenFeatureAPI extends import_core11.OpenFeatureCommonAPI {
536
1072
  constructor() {
537
1073
  super("server");
538
1074
  this._statusEnumType = import_core.ServerProviderStatus;
539
1075
  this._apiEmitter = new OpenFeatureEventEmitter();
540
- this._defaultProvider = new import_core7.ProviderWrapper(
1076
+ this._defaultProvider = new import_core11.ProviderWrapper(
541
1077
  NOOP_PROVIDER,
542
1078
  import_core.ServerProviderStatus.NOT_READY,
543
1079
  this._statusEnumType
@@ -569,14 +1105,14 @@ var OpenFeatureAPI = class _OpenFeatureAPI extends import_core7.OpenFeatureCommo
569
1105
  }
570
1106
  setProviderAndWait(domainOrProvider, providerOrUndefined) {
571
1107
  return __async(this, null, function* () {
572
- const domain = (0, import_core7.stringOrUndefined)(domainOrProvider);
573
- const provider = domain ? (0, import_core7.objectOrUndefined)(providerOrUndefined) : (0, import_core7.objectOrUndefined)(domainOrProvider);
1108
+ const domain = (0, import_core11.stringOrUndefined)(domainOrProvider);
1109
+ const provider = domain ? (0, import_core11.objectOrUndefined)(providerOrUndefined) : (0, import_core11.objectOrUndefined)(domainOrProvider);
574
1110
  yield this.setAwaitableProvider(domain, provider);
575
1111
  });
576
1112
  }
577
1113
  setProvider(clientOrProvider, providerOrUndefined) {
578
- const domain = (0, import_core7.stringOrUndefined)(clientOrProvider);
579
- const provider = domain ? (0, import_core7.objectOrUndefined)(providerOrUndefined) : (0, import_core7.objectOrUndefined)(clientOrProvider);
1114
+ const domain = (0, import_core11.stringOrUndefined)(clientOrProvider);
1115
+ const provider = domain ? (0, import_core11.objectOrUndefined)(providerOrUndefined) : (0, import_core11.objectOrUndefined)(clientOrProvider);
580
1116
  const maybePromise = this.setAwaitableProvider(domain, provider);
581
1117
  Promise.resolve(maybePromise).catch((err) => {
582
1118
  this._logger.error("Error during provider initialization:", err);
@@ -595,9 +1131,9 @@ var OpenFeatureAPI = class _OpenFeatureAPI extends import_core7.OpenFeatureCommo
595
1131
  }
596
1132
  getClient(domainOrContext, versionOrContext, contextOrUndefined) {
597
1133
  var _a, _b;
598
- const domain = (0, import_core7.stringOrUndefined)(domainOrContext);
599
- const version = (0, import_core7.stringOrUndefined)(versionOrContext);
600
- const context = (_b = (_a = (0, import_core7.objectOrUndefined)(domainOrContext)) != null ? _a : (0, import_core7.objectOrUndefined)(versionOrContext)) != null ? _b : (0, import_core7.objectOrUndefined)(contextOrUndefined);
1134
+ const domain = (0, import_core11.stringOrUndefined)(domainOrContext);
1135
+ const version = (0, import_core11.stringOrUndefined)(versionOrContext);
1136
+ const context = (_b = (_a = (0, import_core11.objectOrUndefined)(domainOrContext)) != null ? _a : (0, import_core11.objectOrUndefined)(versionOrContext)) != null ? _b : (0, import_core11.objectOrUndefined)(contextOrUndefined);
601
1137
  return new OpenFeatureClient(
602
1138
  () => this.getProviderForClient(domain),
603
1139
  () => this.getProviderStatus(domain),
@@ -648,8 +1184,15 @@ var OpenFeature = OpenFeatureAPI.getInstance();
648
1184
  __reExport(index_exports, require("@openfeature/core"), module.exports);
649
1185
  // Annotate the CommonJS export names for ESM import in node:
650
1186
  0 && (module.exports = {
1187
+ AggregateError,
651
1188
  AsyncLocalStorageTransactionContextPropagator,
1189
+ BaseEvaluationStrategy,
1190
+ ComparisonStrategy,
1191
+ ErrorWithCode,
1192
+ FirstMatchStrategy,
1193
+ FirstSuccessfulStrategy,
652
1194
  InMemoryProvider,
1195
+ MultiProvider,
653
1196
  NOOP_PROVIDER,
654
1197
  NOOP_TRANSACTION_CONTEXT_PROPAGATOR,
655
1198
  OpenFeature,
@@ -657,6 +1200,8 @@ __reExport(index_exports, require("@openfeature/core"), module.exports);
657
1200
  OpenFeatureEventEmitter,
658
1201
  ProviderEvents,
659
1202
  ProviderStatus,
1203
+ constructAggregateError,
1204
+ throwAggregateErrorFromPromiseResults,
660
1205
  ...require("@openfeature/core")
661
1206
  });
662
1207
  //# sourceMappingURL=index.js.map