@openfeature/web-sdk 0.4.7 → 0.4.9
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 +2 -2
- package/dist/cjs/index.js +142 -61
- package/dist/cjs/index.js.map +4 -4
- package/dist/esm/index.js +126 -42
- package/dist/esm/index.js.map +4 -4
- package/dist/types.d.ts +157 -60
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -16,8 +16,8 @@
|
|
|
16
16
|
<img alt="Specification" src="https://img.shields.io/static/v1?label=specification&message=v0.7.0&color=yellow&style=for-the-badge" />
|
|
17
17
|
</a>
|
|
18
18
|
<!-- x-release-please-start-version -->
|
|
19
|
-
<a href="https://github.com/open-feature/js-sdk/releases/tag/web-sdk-v0.4.
|
|
20
|
-
<img alt="Release" src="https://img.shields.io/static/v1?label=release&message=v0.4.
|
|
19
|
+
<a href="https://github.com/open-feature/js-sdk/releases/tag/web-sdk-v0.4.9">
|
|
20
|
+
<img alt="Release" src="https://img.shields.io/static/v1?label=release&message=v0.4.9&color=blue&style=for-the-badge" />
|
|
21
21
|
</a>
|
|
22
22
|
<!-- x-release-please-end -->
|
|
23
23
|
<br/>
|
package/dist/cjs/index.js
CHANGED
|
@@ -9,6 +9,7 @@ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
|
9
9
|
var __getProtoOf = Object.getPrototypeOf;
|
|
10
10
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
11
11
|
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
12
|
+
var __reflectGet = Reflect.get;
|
|
12
13
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
13
14
|
var __spreadValues = (a, b) => {
|
|
14
15
|
for (var prop in b || (b = {}))
|
|
@@ -47,6 +48,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
47
48
|
mod
|
|
48
49
|
));
|
|
49
50
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
51
|
+
var __superGet = (cls, obj, key) => __reflectGet(__getProtoOf(cls), key, obj);
|
|
50
52
|
var __async = (__this, __arguments, generator) => {
|
|
51
53
|
return new Promise((resolve, reject) => {
|
|
52
54
|
var fulfilled = (value) => {
|
|
@@ -448,18 +450,36 @@ __export(src_exports, {
|
|
|
448
450
|
OpenFeature: () => OpenFeature,
|
|
449
451
|
OpenFeatureAPI: () => OpenFeatureAPI,
|
|
450
452
|
OpenFeatureClient: () => OpenFeatureClient,
|
|
451
|
-
OpenFeatureEventEmitter: () => OpenFeatureEventEmitter
|
|
453
|
+
OpenFeatureEventEmitter: () => OpenFeatureEventEmitter,
|
|
454
|
+
ProviderEvents: () => import_core2.ClientProviderEvents
|
|
452
455
|
});
|
|
453
456
|
module.exports = __toCommonJS(src_exports);
|
|
454
457
|
|
|
455
458
|
// src/client/open-feature-client.ts
|
|
456
|
-
var
|
|
459
|
+
var import_core7 = require("@openfeature/core");
|
|
457
460
|
|
|
458
461
|
// src/open-feature.ts
|
|
459
|
-
var
|
|
462
|
+
var import_core6 = require("@openfeature/core");
|
|
460
463
|
|
|
461
|
-
// src/
|
|
464
|
+
// src/events/open-feature-event-emitter.ts
|
|
462
465
|
var import_core = require("@openfeature/core");
|
|
466
|
+
var import_events = __toESM(require_events());
|
|
467
|
+
var OpenFeatureEventEmitter = class extends import_core.GenericEventEmitter {
|
|
468
|
+
constructor() {
|
|
469
|
+
super();
|
|
470
|
+
this.eventEmitter = new import_events.default({ captureRejections: true });
|
|
471
|
+
this.eventEmitter.on("error", (err) => {
|
|
472
|
+
var _a;
|
|
473
|
+
(_a = this._logger) == null ? void 0 : _a.error("Error running event handler:", err);
|
|
474
|
+
});
|
|
475
|
+
}
|
|
476
|
+
};
|
|
477
|
+
|
|
478
|
+
// src/events/events.ts
|
|
479
|
+
var import_core2 = require("@openfeature/core");
|
|
480
|
+
|
|
481
|
+
// src/provider/no-op-provider.ts
|
|
482
|
+
var import_core3 = require("@openfeature/core");
|
|
463
483
|
var REASON_NO_OP = "No-op";
|
|
464
484
|
var NoopFeatureProvider = class {
|
|
465
485
|
constructor() {
|
|
@@ -468,7 +488,7 @@ var NoopFeatureProvider = class {
|
|
|
468
488
|
};
|
|
469
489
|
}
|
|
470
490
|
get status() {
|
|
471
|
-
return
|
|
491
|
+
return import_core3.ProviderStatus.NOT_READY;
|
|
472
492
|
}
|
|
473
493
|
resolveBooleanEvaluation(_, defaultValue) {
|
|
474
494
|
return this.noOp(defaultValue);
|
|
@@ -492,30 +512,16 @@ var NoopFeatureProvider = class {
|
|
|
492
512
|
var NOOP_PROVIDER = new NoopFeatureProvider();
|
|
493
513
|
|
|
494
514
|
// src/provider/in-memory-provider/in-memory-provider.ts
|
|
495
|
-
var
|
|
496
|
-
|
|
497
|
-
// src/events/open-feature-event-emitter.ts
|
|
498
|
-
var import_core2 = require("@openfeature/core");
|
|
499
|
-
var import_events = __toESM(require_events());
|
|
500
|
-
var OpenFeatureEventEmitter = class extends import_core2.GenericEventEmitter {
|
|
501
|
-
constructor() {
|
|
502
|
-
super();
|
|
503
|
-
this.eventEmitter = new import_events.default({ captureRejections: true });
|
|
504
|
-
this.eventEmitter.on("error", (err) => {
|
|
505
|
-
var _a;
|
|
506
|
-
(_a = this._logger) == null ? void 0 : _a.error("Error running event handler:", err);
|
|
507
|
-
});
|
|
508
|
-
}
|
|
509
|
-
};
|
|
515
|
+
var import_core5 = require("@openfeature/core");
|
|
510
516
|
|
|
511
517
|
// src/provider/in-memory-provider/variant-not-found-error.ts
|
|
512
|
-
var
|
|
513
|
-
var VariantNotFoundError = class extends
|
|
518
|
+
var import_core4 = require("@openfeature/core");
|
|
519
|
+
var VariantNotFoundError = class extends import_core4.OpenFeatureError {
|
|
514
520
|
constructor(message) {
|
|
515
521
|
super(message);
|
|
516
522
|
Object.setPrototypeOf(this, VariantNotFoundError.prototype);
|
|
517
523
|
this.name = "VariantNotFoundError";
|
|
518
|
-
this.code =
|
|
524
|
+
this.code = import_core4.ErrorCode.GENERAL;
|
|
519
525
|
}
|
|
520
526
|
};
|
|
521
527
|
|
|
@@ -524,7 +530,7 @@ var InMemoryProvider = class {
|
|
|
524
530
|
constructor(flagConfiguration = {}) {
|
|
525
531
|
this.events = new OpenFeatureEventEmitter();
|
|
526
532
|
this.runsOn = "client";
|
|
527
|
-
this.status =
|
|
533
|
+
this.status = import_core5.ProviderStatus.NOT_READY;
|
|
528
534
|
this.metadata = {
|
|
529
535
|
name: "in-memory"
|
|
530
536
|
};
|
|
@@ -537,9 +543,9 @@ var InMemoryProvider = class {
|
|
|
537
543
|
this.resolveFlagWithReason(key, context);
|
|
538
544
|
}
|
|
539
545
|
this._context = context;
|
|
540
|
-
this.status =
|
|
546
|
+
this.status = import_core5.ProviderStatus.READY;
|
|
541
547
|
} catch (error) {
|
|
542
|
-
this.status =
|
|
548
|
+
this.status = import_core5.ProviderStatus.ERROR;
|
|
543
549
|
throw error;
|
|
544
550
|
}
|
|
545
551
|
});
|
|
@@ -551,15 +557,15 @@ var InMemoryProvider = class {
|
|
|
551
557
|
putConfiguration(flagConfiguration) {
|
|
552
558
|
return __async(this, null, function* () {
|
|
553
559
|
const flagsChanged = Object.entries(flagConfiguration).filter(([key, value]) => this._flagConfiguration[key] !== value).map(([key]) => key);
|
|
554
|
-
this.status =
|
|
555
|
-
this.events.emit(
|
|
560
|
+
this.status = import_core5.ProviderStatus.STALE;
|
|
561
|
+
this.events.emit(import_core2.ClientProviderEvents.Stale);
|
|
556
562
|
this._flagConfiguration = __spreadValues({}, flagConfiguration);
|
|
557
|
-
this.events.emit(
|
|
563
|
+
this.events.emit(import_core2.ClientProviderEvents.ConfigurationChanged, { flagsChanged });
|
|
558
564
|
try {
|
|
559
565
|
yield this.initialize(this._context);
|
|
560
|
-
this.events.emit(
|
|
566
|
+
this.events.emit(import_core2.ClientProviderEvents.Ready);
|
|
561
567
|
} catch (err) {
|
|
562
|
-
this.events.emit(
|
|
568
|
+
this.events.emit(import_core2.ClientProviderEvents.Error);
|
|
563
569
|
throw err;
|
|
564
570
|
}
|
|
565
571
|
});
|
|
@@ -580,10 +586,10 @@ var InMemoryProvider = class {
|
|
|
580
586
|
if (!(flagKey in this._flagConfiguration)) {
|
|
581
587
|
const message = `no flag found with key ${flagKey}`;
|
|
582
588
|
logger == null ? void 0 : logger.debug(message);
|
|
583
|
-
throw new
|
|
589
|
+
throw new import_core5.FlagNotFoundError(message);
|
|
584
590
|
}
|
|
585
591
|
if (this._flagConfiguration[flagKey].disabled) {
|
|
586
|
-
return { value: defaultValue, reason:
|
|
592
|
+
return { value: defaultValue, reason: import_core5.StandardResolutionReasons.DISABLED };
|
|
587
593
|
}
|
|
588
594
|
const resolvedFlag = this.resolveFlagWithReason(flagKey, context);
|
|
589
595
|
if (resolvedFlag.value === void 0) {
|
|
@@ -592,7 +598,7 @@ var InMemoryProvider = class {
|
|
|
592
598
|
throw new VariantNotFoundError(message);
|
|
593
599
|
}
|
|
594
600
|
if (typeof resolvedFlag.value != typeof defaultValue) {
|
|
595
|
-
throw new
|
|
601
|
+
throw new import_core5.TypeMismatchError();
|
|
596
602
|
}
|
|
597
603
|
return resolvedFlag;
|
|
598
604
|
}
|
|
@@ -601,8 +607,8 @@ var InMemoryProvider = class {
|
|
|
601
607
|
const resolutionResult = this.lookupFlagValue(flagKey, ctx);
|
|
602
608
|
return resolutionResult;
|
|
603
609
|
} catch (error) {
|
|
604
|
-
if (!(error instanceof
|
|
605
|
-
throw new
|
|
610
|
+
if (!(error instanceof import_core5.OpenFeatureError)) {
|
|
611
|
+
throw new import_core5.GeneralError((error == null ? void 0 : error.message) || "unknown error");
|
|
606
612
|
}
|
|
607
613
|
throw error;
|
|
608
614
|
}
|
|
@@ -613,8 +619,8 @@ var InMemoryProvider = class {
|
|
|
613
619
|
const isContextEval = ctx && (flagSpec == null ? void 0 : flagSpec.contextEvaluator);
|
|
614
620
|
const variant = isContextEval ? (_a = flagSpec.contextEvaluator) == null ? void 0 : _a.call(flagSpec, ctx) : flagSpec.defaultVariant;
|
|
615
621
|
const value = variant && (flagSpec == null ? void 0 : flagSpec.variants[variant]);
|
|
616
|
-
const evalReason = isContextEval ?
|
|
617
|
-
const reason = this.status ===
|
|
622
|
+
const evalReason = isContextEval ? import_core5.StandardResolutionReasons.TARGETING_MATCH : import_core5.StandardResolutionReasons.STATIC;
|
|
623
|
+
const reason = this.status === import_core5.ProviderStatus.STALE ? import_core5.StandardResolutionReasons.CACHED : evalReason;
|
|
618
624
|
return __spreadProps(__spreadValues({
|
|
619
625
|
value
|
|
620
626
|
}, variant && { variant }), {
|
|
@@ -626,13 +632,13 @@ var InMemoryProvider = class {
|
|
|
626
632
|
// src/open-feature.ts
|
|
627
633
|
var GLOBAL_OPENFEATURE_API_KEY = Symbol.for("@openfeature/web-sdk/api");
|
|
628
634
|
var _globalThis = globalThis;
|
|
629
|
-
var OpenFeatureAPI = class extends
|
|
630
|
-
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
635
|
+
var OpenFeatureAPI = class extends import_core6.OpenFeatureCommonAPI {
|
|
631
636
|
constructor() {
|
|
632
637
|
super("client");
|
|
633
638
|
this._events = new OpenFeatureEventEmitter();
|
|
634
639
|
this._defaultProvider = NOOP_PROVIDER;
|
|
635
640
|
this._createEventEmitter = () => new OpenFeatureEventEmitter();
|
|
641
|
+
this._namedProviderContext = /* @__PURE__ */ new Map();
|
|
636
642
|
}
|
|
637
643
|
/**
|
|
638
644
|
* Gets a singleton instance of the OpenFeature API.
|
|
@@ -648,26 +654,74 @@ var OpenFeatureAPI = class extends import_core5.OpenFeatureCommonAPI {
|
|
|
648
654
|
_globalThis[GLOBAL_OPENFEATURE_API_KEY] = instance;
|
|
649
655
|
return instance;
|
|
650
656
|
}
|
|
651
|
-
setContext(
|
|
657
|
+
setContext(nameOrContext, contextOrUndefined) {
|
|
652
658
|
return __async(this, null, function* () {
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
const
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
}
|
|
665
|
-
|
|
659
|
+
var _a, _b;
|
|
660
|
+
const clientName = (0, import_core6.stringOrUndefined)(nameOrContext);
|
|
661
|
+
const context = (_b = (_a = (0, import_core6.objectOrUndefined)(nameOrContext)) != null ? _a : (0, import_core6.objectOrUndefined)(contextOrUndefined)) != null ? _b : {};
|
|
662
|
+
if (clientName) {
|
|
663
|
+
const provider = this._clientProviders.get(clientName);
|
|
664
|
+
if (provider) {
|
|
665
|
+
const oldContext = this.getContext(clientName);
|
|
666
|
+
this._namedProviderContext.set(clientName, context);
|
|
667
|
+
yield this.runProviderContextChangeHandler(clientName, provider, oldContext, context);
|
|
668
|
+
} else {
|
|
669
|
+
this._namedProviderContext.set(clientName, context);
|
|
670
|
+
}
|
|
671
|
+
} else {
|
|
672
|
+
const oldContext = this._context;
|
|
673
|
+
this._context = context;
|
|
674
|
+
const providersWithoutContextOverride = Array.from(this._clientProviders.entries()).filter(([name]) => !this._namedProviderContext.has(name)).reduce((acc, [, provider]) => {
|
|
675
|
+
acc.push(provider);
|
|
676
|
+
return acc;
|
|
677
|
+
}, []);
|
|
678
|
+
const allProviders = [this._defaultProvider, ...providersWithoutContextOverride];
|
|
679
|
+
yield Promise.all(
|
|
680
|
+
allProviders.map((provider) => this.runProviderContextChangeHandler(void 0, provider, oldContext, context))
|
|
681
|
+
);
|
|
682
|
+
}
|
|
666
683
|
});
|
|
667
684
|
}
|
|
668
|
-
getContext() {
|
|
685
|
+
getContext(nameOrUndefined) {
|
|
686
|
+
const clientName = (0, import_core6.stringOrUndefined)(nameOrUndefined);
|
|
687
|
+
if (clientName) {
|
|
688
|
+
const context = this._namedProviderContext.get(clientName);
|
|
689
|
+
if (context) {
|
|
690
|
+
return context;
|
|
691
|
+
} else {
|
|
692
|
+
this._logger.debug(`Unable to find context for '${clientName}'.`);
|
|
693
|
+
}
|
|
694
|
+
}
|
|
669
695
|
return this._context;
|
|
670
696
|
}
|
|
697
|
+
clearContext(nameOrUndefined) {
|
|
698
|
+
return __async(this, null, function* () {
|
|
699
|
+
const clientName = (0, import_core6.stringOrUndefined)(nameOrUndefined);
|
|
700
|
+
if (clientName) {
|
|
701
|
+
const provider = this._clientProviders.get(clientName);
|
|
702
|
+
if (provider) {
|
|
703
|
+
const oldContext = this.getContext(clientName);
|
|
704
|
+
this._namedProviderContext.delete(clientName);
|
|
705
|
+
const newContext = this.getContext();
|
|
706
|
+
yield this.runProviderContextChangeHandler(clientName, provider, oldContext, newContext);
|
|
707
|
+
} else {
|
|
708
|
+
this._namedProviderContext.delete(clientName);
|
|
709
|
+
}
|
|
710
|
+
} else {
|
|
711
|
+
return this.setContext({});
|
|
712
|
+
}
|
|
713
|
+
});
|
|
714
|
+
}
|
|
715
|
+
/**
|
|
716
|
+
* Resets the global evaluation context and removes the evaluation context for
|
|
717
|
+
* all named clients.
|
|
718
|
+
*/
|
|
719
|
+
clearContexts() {
|
|
720
|
+
return __async(this, null, function* () {
|
|
721
|
+
yield this.clearContext();
|
|
722
|
+
yield Promise.allSettled(Array.from(this._clientProviders.keys()).map((name) => this.clearContext(name)));
|
|
723
|
+
});
|
|
724
|
+
}
|
|
671
725
|
/**
|
|
672
726
|
* A factory function for creating new named OpenFeature clients. Clients can contain
|
|
673
727
|
* their own state (e.g. logger, hook, context). Multiple clients can be used
|
|
@@ -694,7 +748,30 @@ var OpenFeatureAPI = class extends import_core5.OpenFeatureCommonAPI {
|
|
|
694
748
|
* @returns {Promise<void>}
|
|
695
749
|
*/
|
|
696
750
|
clearProviders() {
|
|
697
|
-
return
|
|
751
|
+
return __async(this, null, function* () {
|
|
752
|
+
yield __superGet(OpenFeatureAPI.prototype, this, "clearProvidersAndSetDefault").call(this, NOOP_PROVIDER);
|
|
753
|
+
this._namedProviderContext.clear();
|
|
754
|
+
});
|
|
755
|
+
}
|
|
756
|
+
runProviderContextChangeHandler(clientName, provider, oldContext, newContext) {
|
|
757
|
+
return __async(this, null, function* () {
|
|
758
|
+
var _a;
|
|
759
|
+
const providerName = provider.metadata.name;
|
|
760
|
+
return (_a = provider.onContextChange) == null ? void 0 : _a.call(provider, oldContext, newContext).then(() => {
|
|
761
|
+
var _a2;
|
|
762
|
+
this.getAssociatedEventEmitters(clientName).forEach((emitter) => {
|
|
763
|
+
emitter == null ? void 0 : emitter.emit(import_core2.ClientProviderEvents.ContextChanged, { clientName, providerName });
|
|
764
|
+
});
|
|
765
|
+
(_a2 = this._events) == null ? void 0 : _a2.emit(import_core2.ClientProviderEvents.ContextChanged, { clientName, providerName });
|
|
766
|
+
}).catch((err) => {
|
|
767
|
+
var _a2, _b;
|
|
768
|
+
(_a2 = this._logger) == null ? void 0 : _a2.error(`Error running ${provider.metadata.name}'s context change handler:`, err);
|
|
769
|
+
this.getAssociatedEventEmitters(clientName).forEach((emitter) => {
|
|
770
|
+
emitter == null ? void 0 : emitter.emit(import_core2.ClientProviderEvents.Error, { clientName, providerName, message: err == null ? void 0 : err.message });
|
|
771
|
+
});
|
|
772
|
+
(_b = this._events) == null ? void 0 : _b.emit(import_core2.ClientProviderEvents.Error, { clientName, providerName, message: err == null ? void 0 : err.message });
|
|
773
|
+
});
|
|
774
|
+
});
|
|
698
775
|
}
|
|
699
776
|
};
|
|
700
777
|
var OpenFeature = OpenFeatureAPI.getInstance();
|
|
@@ -715,11 +792,15 @@ var OpenFeatureClient = class {
|
|
|
715
792
|
providerMetadata: this.providerAccessor().metadata
|
|
716
793
|
};
|
|
717
794
|
}
|
|
795
|
+
get providerStatus() {
|
|
796
|
+
var _a;
|
|
797
|
+
return ((_a = this.providerAccessor()) == null ? void 0 : _a.status) || import_core7.ProviderStatus.READY;
|
|
798
|
+
}
|
|
718
799
|
addHandler(eventType, handler) {
|
|
719
800
|
var _a;
|
|
720
801
|
this.emitterAccessor().addHandler(eventType, handler);
|
|
721
|
-
const
|
|
722
|
-
if (
|
|
802
|
+
const shouldRunNow = (0, import_core7.statusMatchesEvent)(eventType, this._provider.status);
|
|
803
|
+
if (shouldRunNow) {
|
|
723
804
|
try {
|
|
724
805
|
handler({ clientName: this.metadata.name, providerName: this._provider.metadata.name });
|
|
725
806
|
} catch (err) {
|
|
@@ -734,7 +815,7 @@ var OpenFeatureClient = class {
|
|
|
734
815
|
return this.emitterAccessor().getHandlers(eventType);
|
|
735
816
|
}
|
|
736
817
|
setLogger(logger) {
|
|
737
|
-
this._clientLogger = new
|
|
818
|
+
this._clientLogger = new import_core7.SafeLogger(logger);
|
|
738
819
|
return this;
|
|
739
820
|
}
|
|
740
821
|
addHooks(...hooks) {
|
|
@@ -816,13 +897,13 @@ var OpenFeatureClient = class {
|
|
|
816
897
|
return evaluationDetails;
|
|
817
898
|
} catch (err) {
|
|
818
899
|
const errorMessage = err == null ? void 0 : err.message;
|
|
819
|
-
const errorCode = (err == null ? void 0 : err.code) ||
|
|
900
|
+
const errorCode = (err == null ? void 0 : err.code) || import_core7.ErrorCode.GENERAL;
|
|
820
901
|
this.errorHooks(allHooksReversed, hookContext, err, options);
|
|
821
902
|
return {
|
|
822
903
|
errorCode,
|
|
823
904
|
errorMessage,
|
|
824
905
|
value: defaultValue,
|
|
825
|
-
reason:
|
|
906
|
+
reason: import_core7.StandardResolutionReasons.ERROR,
|
|
826
907
|
flagMetadata: Object.freeze({}),
|
|
827
908
|
flagKey
|
|
828
909
|
};
|