@openfeature/web-sdk 1.6.2 → 1.7.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/README.md +59 -2
- package/dist/cjs/index.js +541 -23
- package/dist/cjs/index.js.map +4 -4
- package/dist/esm/index.js +523 -5
- package/dist/esm/index.js.map +4 -4
- package/dist/global/index.js +513 -1
- package/dist/global/index.js.map +4 -4
- package/dist/global/index.min.js +1 -1
- package/dist/global/index.min.js.map +4 -4
- package/dist/types.d.ts +145 -3
- package/package.json +1 -1
package/dist/esm/index.js
CHANGED
|
@@ -378,6 +378,515 @@ var InMemoryProvider = class {
|
|
|
378
378
|
}
|
|
379
379
|
};
|
|
380
380
|
|
|
381
|
+
// src/provider/multi-provider/multi-provider-web.ts
|
|
382
|
+
import { DefaultLogger, GeneralError as GeneralError4, ErrorCode as ErrorCode3, StandardResolutionReasons as StandardResolutionReasons2 } from "@openfeature/core";
|
|
383
|
+
|
|
384
|
+
// src/provider/multi-provider/hook-executor.ts
|
|
385
|
+
var HookExecutor = class {
|
|
386
|
+
constructor(logger) {
|
|
387
|
+
this.logger = logger;
|
|
388
|
+
}
|
|
389
|
+
beforeHooks(hooks, hookContext, hints) {
|
|
390
|
+
var _a;
|
|
391
|
+
for (const hook of hooks != null ? hooks : []) {
|
|
392
|
+
(_a = hook == null ? void 0 : hook.before) == null ? void 0 : _a.call(hook, hookContext, Object.freeze(hints));
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
afterHooks(hooks, hookContext, evaluationDetails, hints) {
|
|
396
|
+
var _a;
|
|
397
|
+
for (const hook of hooks != null ? hooks : []) {
|
|
398
|
+
(_a = hook == null ? void 0 : hook.after) == null ? void 0 : _a.call(hook, hookContext, evaluationDetails, hints);
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
errorHooks(hooks, hookContext, err, hints) {
|
|
402
|
+
var _a;
|
|
403
|
+
for (const hook of hooks != null ? hooks : []) {
|
|
404
|
+
try {
|
|
405
|
+
(_a = hook == null ? void 0 : hook.error) == null ? void 0 : _a.call(hook, hookContext, err, hints);
|
|
406
|
+
} catch (err2) {
|
|
407
|
+
this.logger.error(`Unhandled error during 'error' hook: ${err2}`);
|
|
408
|
+
if (err2 instanceof Error) {
|
|
409
|
+
this.logger.error(err2.stack);
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
finallyHooks(hooks, hookContext, evaluationDetails, hints) {
|
|
415
|
+
var _a;
|
|
416
|
+
for (const hook of hooks != null ? hooks : []) {
|
|
417
|
+
try {
|
|
418
|
+
(_a = hook == null ? void 0 : hook.finally) == null ? void 0 : _a.call(hook, hookContext, evaluationDetails, hints);
|
|
419
|
+
} catch (err) {
|
|
420
|
+
this.logger.error(`Unhandled error during 'finally' hook: ${err}`);
|
|
421
|
+
if (err instanceof Error) {
|
|
422
|
+
this.logger.error(err.stack);
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
};
|
|
428
|
+
|
|
429
|
+
// src/provider/multi-provider/errors.ts
|
|
430
|
+
import { GeneralError as GeneralError2, OpenFeatureError as OpenFeatureError3 } from "@openfeature/core";
|
|
431
|
+
var ErrorWithCode = class extends OpenFeatureError3 {
|
|
432
|
+
constructor(code, message) {
|
|
433
|
+
super(message);
|
|
434
|
+
this.code = code;
|
|
435
|
+
}
|
|
436
|
+
};
|
|
437
|
+
var AggregateError = class extends GeneralError2 {
|
|
438
|
+
constructor(message, originalErrors) {
|
|
439
|
+
super(message);
|
|
440
|
+
this.originalErrors = originalErrors;
|
|
441
|
+
}
|
|
442
|
+
};
|
|
443
|
+
var constructAggregateError = (providerErrors) => {
|
|
444
|
+
const errorsWithSource = providerErrors.map(({ providerName, error }) => {
|
|
445
|
+
return { source: providerName, error };
|
|
446
|
+
}).flat();
|
|
447
|
+
return new AggregateError(
|
|
448
|
+
`Provider errors occurred: ${errorsWithSource[0].source}: ${errorsWithSource[0].error}`,
|
|
449
|
+
errorsWithSource
|
|
450
|
+
);
|
|
451
|
+
};
|
|
452
|
+
var throwAggregateErrorFromPromiseResults = (result, providerEntries) => {
|
|
453
|
+
const errors = result.map((r, i) => {
|
|
454
|
+
if (r.status === "rejected") {
|
|
455
|
+
return { error: r.reason, providerName: providerEntries[i].name };
|
|
456
|
+
}
|
|
457
|
+
return null;
|
|
458
|
+
}).filter((val) => Boolean(val));
|
|
459
|
+
if (errors.length) {
|
|
460
|
+
throw constructAggregateError(errors);
|
|
461
|
+
}
|
|
462
|
+
};
|
|
463
|
+
|
|
464
|
+
// src/provider/multi-provider/strategies/base-evaluation-strategy.ts
|
|
465
|
+
var BaseEvaluationStrategy = class {
|
|
466
|
+
shouldEvaluateThisProvider(strategyContext, _evalContext) {
|
|
467
|
+
if (strategyContext.providerStatus === ClientProviderStatus.NOT_READY || strategyContext.providerStatus === ClientProviderStatus.FATAL) {
|
|
468
|
+
return false;
|
|
469
|
+
}
|
|
470
|
+
return true;
|
|
471
|
+
}
|
|
472
|
+
shouldEvaluateNextProvider(_strategyContext, _context, _result) {
|
|
473
|
+
return true;
|
|
474
|
+
}
|
|
475
|
+
shouldTrackWithThisProvider(strategyContext, _context, _trackingEventName, _trackingEventDetails) {
|
|
476
|
+
if (strategyContext.providerStatus === ClientProviderStatus.NOT_READY || strategyContext.providerStatus === ClientProviderStatus.FATAL) {
|
|
477
|
+
return false;
|
|
478
|
+
}
|
|
479
|
+
return true;
|
|
480
|
+
}
|
|
481
|
+
hasError(resolution) {
|
|
482
|
+
return "thrownError" in resolution || !!resolution.details.errorCode;
|
|
483
|
+
}
|
|
484
|
+
hasErrorWithCode(resolution, code) {
|
|
485
|
+
var _a;
|
|
486
|
+
return "thrownError" in resolution ? ((_a = resolution.thrownError) == null ? void 0 : _a.code) === code : resolution.details.errorCode === code;
|
|
487
|
+
}
|
|
488
|
+
collectProviderErrors(resolutions) {
|
|
489
|
+
var _a;
|
|
490
|
+
const errors = [];
|
|
491
|
+
for (const resolution of resolutions) {
|
|
492
|
+
if ("thrownError" in resolution) {
|
|
493
|
+
errors.push({ providerName: resolution.providerName, error: resolution.thrownError });
|
|
494
|
+
} else if (resolution.details.errorCode) {
|
|
495
|
+
errors.push({
|
|
496
|
+
providerName: resolution.providerName,
|
|
497
|
+
error: new ErrorWithCode(resolution.details.errorCode, (_a = resolution.details.errorMessage) != null ? _a : "unknown error")
|
|
498
|
+
});
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
return { errors };
|
|
502
|
+
}
|
|
503
|
+
resolutionToFinalResult(resolution) {
|
|
504
|
+
return { details: resolution.details, provider: resolution.provider, providerName: resolution.providerName };
|
|
505
|
+
}
|
|
506
|
+
};
|
|
507
|
+
|
|
508
|
+
// src/provider/multi-provider/strategies/first-match-strategy.ts
|
|
509
|
+
import { ErrorCode as ErrorCode2 } from "@openfeature/core";
|
|
510
|
+
var FirstMatchStrategy = class extends BaseEvaluationStrategy {
|
|
511
|
+
shouldEvaluateNextProvider(strategyContext, context, result) {
|
|
512
|
+
if (this.hasErrorWithCode(result, ErrorCode2.FLAG_NOT_FOUND)) {
|
|
513
|
+
return true;
|
|
514
|
+
}
|
|
515
|
+
if (this.hasError(result)) {
|
|
516
|
+
return false;
|
|
517
|
+
}
|
|
518
|
+
return false;
|
|
519
|
+
}
|
|
520
|
+
determineFinalResult(strategyContext, context, resolutions) {
|
|
521
|
+
const finalResolution = resolutions[resolutions.length - 1];
|
|
522
|
+
if (this.hasError(finalResolution)) {
|
|
523
|
+
return this.collectProviderErrors(resolutions);
|
|
524
|
+
}
|
|
525
|
+
return this.resolutionToFinalResult(finalResolution);
|
|
526
|
+
}
|
|
527
|
+
};
|
|
528
|
+
|
|
529
|
+
// src/provider/multi-provider/strategies/first-successful-strategy.ts
|
|
530
|
+
var FirstSuccessfulStrategy = class extends BaseEvaluationStrategy {
|
|
531
|
+
shouldEvaluateNextProvider(strategyContext, context, result) {
|
|
532
|
+
return this.hasError(result);
|
|
533
|
+
}
|
|
534
|
+
determineFinalResult(strategyContext, context, resolutions) {
|
|
535
|
+
const finalResolution = resolutions[resolutions.length - 1];
|
|
536
|
+
if (this.hasError(finalResolution)) {
|
|
537
|
+
return this.collectProviderErrors(resolutions);
|
|
538
|
+
}
|
|
539
|
+
return this.resolutionToFinalResult(finalResolution);
|
|
540
|
+
}
|
|
541
|
+
};
|
|
542
|
+
|
|
543
|
+
// src/provider/multi-provider/strategies/comparison-strategy.ts
|
|
544
|
+
import { GeneralError as GeneralError3 } from "@openfeature/core";
|
|
545
|
+
var ComparisonStrategy = class extends BaseEvaluationStrategy {
|
|
546
|
+
constructor(fallbackProvider, onMismatch) {
|
|
547
|
+
super();
|
|
548
|
+
this.fallbackProvider = fallbackProvider;
|
|
549
|
+
this.onMismatch = onMismatch;
|
|
550
|
+
}
|
|
551
|
+
determineFinalResult(strategyContext, context, resolutions) {
|
|
552
|
+
var _a;
|
|
553
|
+
let value;
|
|
554
|
+
let fallbackResolution;
|
|
555
|
+
let finalResolution;
|
|
556
|
+
let mismatch = false;
|
|
557
|
+
for (const [i, resolution] of resolutions.entries()) {
|
|
558
|
+
if (this.hasError(resolution)) {
|
|
559
|
+
return this.collectProviderErrors(resolutions);
|
|
560
|
+
}
|
|
561
|
+
if (resolution.provider === this.fallbackProvider) {
|
|
562
|
+
fallbackResolution = resolution;
|
|
563
|
+
}
|
|
564
|
+
if (i === 0) {
|
|
565
|
+
finalResolution = resolution;
|
|
566
|
+
}
|
|
567
|
+
if (typeof value !== "undefined" && value !== resolution.details.value) {
|
|
568
|
+
mismatch = true;
|
|
569
|
+
} else {
|
|
570
|
+
value = resolution.details.value;
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
if (!fallbackResolution) {
|
|
574
|
+
throw new GeneralError3("Fallback provider not found in resolution results");
|
|
575
|
+
}
|
|
576
|
+
if (!finalResolution) {
|
|
577
|
+
throw new GeneralError3("Final resolution not found in resolution results");
|
|
578
|
+
}
|
|
579
|
+
if (mismatch) {
|
|
580
|
+
(_a = this.onMismatch) == null ? void 0 : _a.call(this, resolutions);
|
|
581
|
+
return {
|
|
582
|
+
details: fallbackResolution.details,
|
|
583
|
+
provider: fallbackResolution.provider
|
|
584
|
+
};
|
|
585
|
+
}
|
|
586
|
+
return this.resolutionToFinalResult(finalResolution);
|
|
587
|
+
}
|
|
588
|
+
};
|
|
589
|
+
|
|
590
|
+
// src/provider/multi-provider/status-tracker.ts
|
|
591
|
+
var StatusTracker = class {
|
|
592
|
+
constructor(events) {
|
|
593
|
+
this.events = events;
|
|
594
|
+
this.providerStatuses = {};
|
|
595
|
+
}
|
|
596
|
+
wrapEventHandler(providerEntry) {
|
|
597
|
+
var _a, _b, _c, _d, _e;
|
|
598
|
+
const provider = providerEntry.provider;
|
|
599
|
+
(_a = provider.events) == null ? void 0 : _a.addHandler(ClientProviderEvents.Error, (details) => {
|
|
600
|
+
this.changeProviderStatus(providerEntry.name, ClientProviderStatus.ERROR, details);
|
|
601
|
+
});
|
|
602
|
+
(_b = provider.events) == null ? void 0 : _b.addHandler(ClientProviderEvents.Stale, (details) => {
|
|
603
|
+
this.changeProviderStatus(providerEntry.name, ClientProviderStatus.STALE, details);
|
|
604
|
+
});
|
|
605
|
+
(_c = provider.events) == null ? void 0 : _c.addHandler(ClientProviderEvents.ConfigurationChanged, (details) => {
|
|
606
|
+
this.events.emit(ClientProviderEvents.ConfigurationChanged, details);
|
|
607
|
+
});
|
|
608
|
+
(_d = provider.events) == null ? void 0 : _d.addHandler(ClientProviderEvents.Ready, (details) => {
|
|
609
|
+
this.changeProviderStatus(providerEntry.name, ClientProviderStatus.READY, details);
|
|
610
|
+
});
|
|
611
|
+
(_e = provider.events) == null ? void 0 : _e.addHandler(ClientProviderEvents.Reconciling, (details) => {
|
|
612
|
+
this.changeProviderStatus(providerEntry.name, ClientProviderStatus.RECONCILING, details);
|
|
613
|
+
});
|
|
614
|
+
}
|
|
615
|
+
providerStatus(name) {
|
|
616
|
+
return this.providerStatuses[name];
|
|
617
|
+
}
|
|
618
|
+
getStatusFromProviderStatuses() {
|
|
619
|
+
const statuses = Object.values(this.providerStatuses);
|
|
620
|
+
if (statuses.includes(ClientProviderStatus.FATAL)) {
|
|
621
|
+
return ClientProviderStatus.FATAL;
|
|
622
|
+
} else if (statuses.includes(ClientProviderStatus.NOT_READY)) {
|
|
623
|
+
return ClientProviderStatus.NOT_READY;
|
|
624
|
+
} else if (statuses.includes(ClientProviderStatus.ERROR)) {
|
|
625
|
+
return ClientProviderStatus.ERROR;
|
|
626
|
+
} else if (statuses.includes(ClientProviderStatus.STALE)) {
|
|
627
|
+
return ClientProviderStatus.STALE;
|
|
628
|
+
} else if (statuses.includes(ClientProviderStatus.RECONCILING)) {
|
|
629
|
+
return ClientProviderStatus.RECONCILING;
|
|
630
|
+
}
|
|
631
|
+
return ClientProviderStatus.READY;
|
|
632
|
+
}
|
|
633
|
+
changeProviderStatus(name, status, details) {
|
|
634
|
+
const currentStatus = this.getStatusFromProviderStatuses();
|
|
635
|
+
this.providerStatuses[name] = status;
|
|
636
|
+
const newStatus = this.getStatusFromProviderStatuses();
|
|
637
|
+
if (currentStatus !== newStatus) {
|
|
638
|
+
if (newStatus === ClientProviderStatus.FATAL || newStatus === ClientProviderStatus.ERROR) {
|
|
639
|
+
this.events.emit(ClientProviderEvents.Error, details);
|
|
640
|
+
} else if (newStatus === ClientProviderStatus.STALE) {
|
|
641
|
+
this.events.emit(ClientProviderEvents.Stale, details);
|
|
642
|
+
} else if (newStatus === ClientProviderStatus.READY) {
|
|
643
|
+
this.events.emit(ClientProviderEvents.Ready, details);
|
|
644
|
+
} else if (newStatus === ClientProviderStatus.RECONCILING) {
|
|
645
|
+
this.events.emit(ClientProviderEvents.Reconciling, details);
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
}
|
|
649
|
+
};
|
|
650
|
+
|
|
651
|
+
// src/provider/multi-provider/multi-provider-web.ts
|
|
652
|
+
var MultiProvider = class _MultiProvider {
|
|
653
|
+
constructor(constructorProviders, evaluationStrategy = new FirstMatchStrategy(), logger = new DefaultLogger()) {
|
|
654
|
+
this.constructorProviders = constructorProviders;
|
|
655
|
+
this.evaluationStrategy = evaluationStrategy;
|
|
656
|
+
this.logger = logger;
|
|
657
|
+
this.runsOn = "client";
|
|
658
|
+
this.events = new OpenFeatureEventEmitter();
|
|
659
|
+
this.hookContexts = /* @__PURE__ */ new WeakMap();
|
|
660
|
+
this.hookHints = /* @__PURE__ */ new WeakMap();
|
|
661
|
+
this.providerEntries = [];
|
|
662
|
+
this.providerEntriesByName = {};
|
|
663
|
+
this.statusTracker = new StatusTracker(this.events);
|
|
664
|
+
this.hookExecutor = new HookExecutor(this.logger);
|
|
665
|
+
this.registerProviders(constructorProviders);
|
|
666
|
+
const aggregateMetadata = Object.keys(this.providerEntriesByName).reduce((acc, name) => {
|
|
667
|
+
return __spreadProps(__spreadValues({}, acc), { [name]: this.providerEntriesByName[name].provider.metadata });
|
|
668
|
+
}, {});
|
|
669
|
+
this.metadata = __spreadProps(__spreadValues({}, aggregateMetadata), {
|
|
670
|
+
name: _MultiProvider.name
|
|
671
|
+
});
|
|
672
|
+
}
|
|
673
|
+
registerProviders(constructorProviders) {
|
|
674
|
+
var _a, _b;
|
|
675
|
+
const providersByName = {};
|
|
676
|
+
for (const constructorProvider of constructorProviders) {
|
|
677
|
+
const providerName = constructorProvider.provider.metadata.name;
|
|
678
|
+
const candidateName = (_a = constructorProvider.name) != null ? _a : providerName;
|
|
679
|
+
if (constructorProvider.name && providersByName[constructorProvider.name]) {
|
|
680
|
+
throw new Error("Provider names must be unique");
|
|
681
|
+
}
|
|
682
|
+
(_b = providersByName[candidateName]) != null ? _b : providersByName[candidateName] = [];
|
|
683
|
+
providersByName[candidateName].push(constructorProvider.provider);
|
|
684
|
+
}
|
|
685
|
+
for (const name of Object.keys(providersByName)) {
|
|
686
|
+
const useIndexedNames = providersByName[name].length > 1;
|
|
687
|
+
for (let i = 0; i < providersByName[name].length; i++) {
|
|
688
|
+
const indexedName = useIndexedNames ? `${name}-${i + 1}` : name;
|
|
689
|
+
this.providerEntriesByName[indexedName] = { provider: providersByName[name][i], name: indexedName };
|
|
690
|
+
this.providerEntries.push(this.providerEntriesByName[indexedName]);
|
|
691
|
+
this.statusTracker.wrapEventHandler(this.providerEntriesByName[indexedName]);
|
|
692
|
+
}
|
|
693
|
+
}
|
|
694
|
+
Object.freeze(this.providerEntries);
|
|
695
|
+
Object.freeze(this.providerEntriesByName);
|
|
696
|
+
}
|
|
697
|
+
initialize(context) {
|
|
698
|
+
return __async(this, null, function* () {
|
|
699
|
+
const result = yield Promise.allSettled(
|
|
700
|
+
this.providerEntries.map((provider) => {
|
|
701
|
+
var _a, _b;
|
|
702
|
+
return (_b = (_a = provider.provider).initialize) == null ? void 0 : _b.call(_a, context);
|
|
703
|
+
})
|
|
704
|
+
);
|
|
705
|
+
throwAggregateErrorFromPromiseResults(result, this.providerEntries);
|
|
706
|
+
});
|
|
707
|
+
}
|
|
708
|
+
onClose() {
|
|
709
|
+
return __async(this, null, function* () {
|
|
710
|
+
const result = yield Promise.allSettled(this.providerEntries.map((provider) => {
|
|
711
|
+
var _a, _b;
|
|
712
|
+
return (_b = (_a = provider.provider).onClose) == null ? void 0 : _b.call(_a);
|
|
713
|
+
}));
|
|
714
|
+
throwAggregateErrorFromPromiseResults(result, this.providerEntries);
|
|
715
|
+
});
|
|
716
|
+
}
|
|
717
|
+
onContextChange(oldContext, newContext) {
|
|
718
|
+
return __async(this, null, function* () {
|
|
719
|
+
var _a, _b;
|
|
720
|
+
for (const providerEntry of this.providerEntries) {
|
|
721
|
+
yield (_b = (_a = providerEntry.provider).onContextChange) == null ? void 0 : _b.call(_a, oldContext, newContext);
|
|
722
|
+
}
|
|
723
|
+
});
|
|
724
|
+
}
|
|
725
|
+
resolveBooleanEvaluation(flagKey, defaultValue, context) {
|
|
726
|
+
return this.flagResolutionProxy(flagKey, "boolean", defaultValue, context);
|
|
727
|
+
}
|
|
728
|
+
resolveStringEvaluation(flagKey, defaultValue, context) {
|
|
729
|
+
return this.flagResolutionProxy(flagKey, "string", defaultValue, context);
|
|
730
|
+
}
|
|
731
|
+
resolveNumberEvaluation(flagKey, defaultValue, context) {
|
|
732
|
+
return this.flagResolutionProxy(flagKey, "number", defaultValue, context);
|
|
733
|
+
}
|
|
734
|
+
resolveObjectEvaluation(flagKey, defaultValue, context) {
|
|
735
|
+
return this.flagResolutionProxy(flagKey, "object", defaultValue, context);
|
|
736
|
+
}
|
|
737
|
+
track(trackingEventName, context, trackingEventDetails) {
|
|
738
|
+
var _a, _b;
|
|
739
|
+
for (const providerEntry of this.providerEntries) {
|
|
740
|
+
if (!providerEntry.provider.track) {
|
|
741
|
+
continue;
|
|
742
|
+
}
|
|
743
|
+
const strategyContext = {
|
|
744
|
+
provider: providerEntry.provider,
|
|
745
|
+
providerName: providerEntry.name,
|
|
746
|
+
providerStatus: this.statusTracker.providerStatus(providerEntry.name)
|
|
747
|
+
};
|
|
748
|
+
if (this.evaluationStrategy.shouldTrackWithThisProvider(
|
|
749
|
+
strategyContext,
|
|
750
|
+
context,
|
|
751
|
+
trackingEventName,
|
|
752
|
+
trackingEventDetails
|
|
753
|
+
)) {
|
|
754
|
+
try {
|
|
755
|
+
(_b = (_a = providerEntry.provider).track) == null ? void 0 : _b.call(_a, trackingEventName, context, trackingEventDetails);
|
|
756
|
+
} catch (error) {
|
|
757
|
+
this.logger.error(
|
|
758
|
+
`Error tracking event "${trackingEventName}" with provider "${providerEntry.name}":`,
|
|
759
|
+
error
|
|
760
|
+
);
|
|
761
|
+
}
|
|
762
|
+
}
|
|
763
|
+
}
|
|
764
|
+
}
|
|
765
|
+
flagResolutionProxy(flagKey, flagType, defaultValue, context) {
|
|
766
|
+
var _a;
|
|
767
|
+
const hookContext = this.hookContexts.get(context);
|
|
768
|
+
const hookHints = this.hookHints.get(context);
|
|
769
|
+
if (!hookContext || !hookHints) {
|
|
770
|
+
throw new GeneralError4("Hook context not available for evaluation");
|
|
771
|
+
}
|
|
772
|
+
const results = [];
|
|
773
|
+
for (const providerEntry of this.providerEntries) {
|
|
774
|
+
const [shouldEvaluateNext, result] = this.evaluateProviderEntry(
|
|
775
|
+
flagKey,
|
|
776
|
+
flagType,
|
|
777
|
+
defaultValue,
|
|
778
|
+
providerEntry,
|
|
779
|
+
hookContext,
|
|
780
|
+
hookHints,
|
|
781
|
+
context
|
|
782
|
+
);
|
|
783
|
+
results.push(result);
|
|
784
|
+
if (!shouldEvaluateNext) {
|
|
785
|
+
break;
|
|
786
|
+
}
|
|
787
|
+
}
|
|
788
|
+
const resolutions = results.filter((r) => Boolean(r));
|
|
789
|
+
const finalResult = this.evaluationStrategy.determineFinalResult({ flagKey, flagType }, context, resolutions);
|
|
790
|
+
if ((_a = finalResult.errors) == null ? void 0 : _a.length) {
|
|
791
|
+
throw constructAggregateError(finalResult.errors);
|
|
792
|
+
}
|
|
793
|
+
if (!finalResult.details) {
|
|
794
|
+
throw new GeneralError4("No result was returned from any provider");
|
|
795
|
+
}
|
|
796
|
+
return finalResult.details;
|
|
797
|
+
}
|
|
798
|
+
evaluateProviderEntry(flagKey, flagType, defaultValue, providerEntry, hookContext, hookHints, context) {
|
|
799
|
+
let evaluationResult = void 0;
|
|
800
|
+
const provider = providerEntry.provider;
|
|
801
|
+
const strategyContext = {
|
|
802
|
+
flagKey,
|
|
803
|
+
flagType,
|
|
804
|
+
provider,
|
|
805
|
+
providerName: providerEntry.name,
|
|
806
|
+
providerStatus: this.statusTracker.providerStatus(providerEntry.name)
|
|
807
|
+
};
|
|
808
|
+
if (!this.evaluationStrategy.shouldEvaluateThisProvider(strategyContext, context)) {
|
|
809
|
+
return [true, null];
|
|
810
|
+
}
|
|
811
|
+
let resolution;
|
|
812
|
+
try {
|
|
813
|
+
evaluationResult = this.evaluateProviderAndHooks(flagKey, defaultValue, provider, hookContext, hookHints);
|
|
814
|
+
resolution = {
|
|
815
|
+
details: evaluationResult,
|
|
816
|
+
provider,
|
|
817
|
+
providerName: providerEntry.name
|
|
818
|
+
};
|
|
819
|
+
} catch (error) {
|
|
820
|
+
resolution = {
|
|
821
|
+
thrownError: error,
|
|
822
|
+
provider,
|
|
823
|
+
providerName: providerEntry.name
|
|
824
|
+
};
|
|
825
|
+
}
|
|
826
|
+
return [this.evaluationStrategy.shouldEvaluateNextProvider(strategyContext, context, resolution), resolution];
|
|
827
|
+
}
|
|
828
|
+
evaluateProviderAndHooks(flagKey, defaultValue, provider, hookContext, hookHints) {
|
|
829
|
+
var _a;
|
|
830
|
+
let evaluationDetails;
|
|
831
|
+
try {
|
|
832
|
+
this.hookExecutor.beforeHooks(provider.hooks, hookContext, hookHints);
|
|
833
|
+
const resolutionDetails = this.callProviderResolve(
|
|
834
|
+
provider,
|
|
835
|
+
flagKey,
|
|
836
|
+
defaultValue,
|
|
837
|
+
hookContext.context
|
|
838
|
+
);
|
|
839
|
+
evaluationDetails = __spreadProps(__spreadValues({}, resolutionDetails), {
|
|
840
|
+
flagMetadata: Object.freeze((_a = resolutionDetails.flagMetadata) != null ? _a : {}),
|
|
841
|
+
flagKey
|
|
842
|
+
});
|
|
843
|
+
this.hookExecutor.afterHooks(provider.hooks, hookContext, evaluationDetails, hookHints);
|
|
844
|
+
} catch (error) {
|
|
845
|
+
this.hookExecutor.errorHooks(provider.hooks, hookContext, error, hookHints);
|
|
846
|
+
evaluationDetails = this.getErrorEvaluationDetails(flagKey, defaultValue, error);
|
|
847
|
+
}
|
|
848
|
+
this.hookExecutor.finallyHooks(provider.hooks, hookContext, evaluationDetails, hookHints);
|
|
849
|
+
return evaluationDetails;
|
|
850
|
+
}
|
|
851
|
+
callProviderResolve(provider, flagKey, defaultValue, context) {
|
|
852
|
+
switch (typeof defaultValue) {
|
|
853
|
+
case "string":
|
|
854
|
+
return provider.resolveStringEvaluation(flagKey, defaultValue, context, this.logger);
|
|
855
|
+
case "number":
|
|
856
|
+
return provider.resolveNumberEvaluation(flagKey, defaultValue, context, this.logger);
|
|
857
|
+
case "object":
|
|
858
|
+
return provider.resolveObjectEvaluation(flagKey, defaultValue, context, this.logger);
|
|
859
|
+
case "boolean":
|
|
860
|
+
return provider.resolveBooleanEvaluation(flagKey, defaultValue, context, this.logger);
|
|
861
|
+
default:
|
|
862
|
+
throw new GeneralError4("Invalid flag evaluation type");
|
|
863
|
+
}
|
|
864
|
+
}
|
|
865
|
+
get hooks() {
|
|
866
|
+
return [
|
|
867
|
+
{
|
|
868
|
+
before: (hookContext, hints) => {
|
|
869
|
+
this.hookContexts.set(hookContext.context, hookContext);
|
|
870
|
+
this.hookHints.set(hookContext.context, hints != null ? hints : {});
|
|
871
|
+
return hookContext.context;
|
|
872
|
+
}
|
|
873
|
+
}
|
|
874
|
+
];
|
|
875
|
+
}
|
|
876
|
+
getErrorEvaluationDetails(flagKey, defaultValue, err, flagMetadata = {}) {
|
|
877
|
+
const errorMessage = err == null ? void 0 : err.message;
|
|
878
|
+
const errorCode = (err == null ? void 0 : err.code) || ErrorCode3.GENERAL;
|
|
879
|
+
return {
|
|
880
|
+
errorCode,
|
|
881
|
+
errorMessage,
|
|
882
|
+
value: defaultValue,
|
|
883
|
+
reason: StandardResolutionReasons2.ERROR,
|
|
884
|
+
flagMetadata: Object.freeze(flagMetadata),
|
|
885
|
+
flagKey
|
|
886
|
+
};
|
|
887
|
+
}
|
|
888
|
+
};
|
|
889
|
+
|
|
381
890
|
// src/open-feature.ts
|
|
382
891
|
import {
|
|
383
892
|
OpenFeatureCommonAPI,
|
|
@@ -388,11 +897,11 @@ import {
|
|
|
388
897
|
|
|
389
898
|
// src/client/internal/open-feature-client.ts
|
|
390
899
|
import {
|
|
391
|
-
ErrorCode as
|
|
900
|
+
ErrorCode as ErrorCode4,
|
|
392
901
|
ProviderFatalError,
|
|
393
902
|
ProviderNotReadyError,
|
|
394
903
|
SafeLogger,
|
|
395
|
-
StandardResolutionReasons as
|
|
904
|
+
StandardResolutionReasons as StandardResolutionReasons3,
|
|
396
905
|
instantiateErrorByErrorCode,
|
|
397
906
|
statusMatchesEvent,
|
|
398
907
|
MapHookData
|
|
@@ -623,12 +1132,12 @@ var OpenFeatureClient = class {
|
|
|
623
1132
|
}
|
|
624
1133
|
getErrorEvaluationDetails(flagKey, defaultValue, err, flagMetadata = {}) {
|
|
625
1134
|
const errorMessage = err == null ? void 0 : err.message;
|
|
626
|
-
const errorCode = (err == null ? void 0 : err.code) ||
|
|
1135
|
+
const errorCode = (err == null ? void 0 : err.code) || ErrorCode4.GENERAL;
|
|
627
1136
|
return {
|
|
628
1137
|
errorCode,
|
|
629
1138
|
errorMessage,
|
|
630
1139
|
value: defaultValue,
|
|
631
|
-
reason:
|
|
1140
|
+
reason: StandardResolutionReasons3.ERROR,
|
|
632
1141
|
flagMetadata: Object.freeze(flagMetadata),
|
|
633
1142
|
flagKey
|
|
634
1143
|
};
|
|
@@ -859,12 +1368,21 @@ var OpenFeature = OpenFeatureAPI.getInstance();
|
|
|
859
1368
|
// src/index.ts
|
|
860
1369
|
export * from "@openfeature/core";
|
|
861
1370
|
export {
|
|
1371
|
+
AggregateError,
|
|
1372
|
+
BaseEvaluationStrategy,
|
|
1373
|
+
ComparisonStrategy,
|
|
1374
|
+
ErrorWithCode,
|
|
1375
|
+
FirstMatchStrategy,
|
|
1376
|
+
FirstSuccessfulStrategy,
|
|
862
1377
|
InMemoryProvider,
|
|
1378
|
+
MultiProvider,
|
|
863
1379
|
NOOP_PROVIDER,
|
|
864
1380
|
OpenFeature,
|
|
865
1381
|
OpenFeatureAPI,
|
|
866
1382
|
OpenFeatureEventEmitter,
|
|
867
1383
|
ClientProviderEvents as ProviderEvents,
|
|
868
|
-
ClientProviderStatus as ProviderStatus
|
|
1384
|
+
ClientProviderStatus as ProviderStatus,
|
|
1385
|
+
constructAggregateError,
|
|
1386
|
+
throwAggregateErrorFromPromiseResults
|
|
869
1387
|
};
|
|
870
1388
|
//# sourceMappingURL=index.js.map
|