@openfeature/web-sdk 0.4.0 → 0.4.2

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/esm/index.js CHANGED
@@ -550,6 +550,15 @@ var InvalidContextError = class extends OpenFeatureError {
550
550
  }
551
551
  };
552
552
 
553
+ // ../shared/src/provider/provider.ts
554
+ var ProviderStatus = /* @__PURE__ */ ((ProviderStatus2) => {
555
+ ProviderStatus2["NOT_READY"] = "NOT_READY";
556
+ ProviderStatus2["READY"] = "READY";
557
+ ProviderStatus2["ERROR"] = "ERROR";
558
+ ProviderStatus2["STALE"] = "STALE";
559
+ return ProviderStatus2;
560
+ })(ProviderStatus || {});
561
+
553
562
  // ../shared/src/events/events.ts
554
563
  var ProviderEvents = /* @__PURE__ */ ((ProviderEvents2) => {
555
564
  ProviderEvents2["Ready"] = "PROVIDER_READY";
@@ -559,6 +568,20 @@ var ProviderEvents = /* @__PURE__ */ ((ProviderEvents2) => {
559
568
  return ProviderEvents2;
560
569
  })(ProviderEvents || {});
561
570
 
571
+ // ../shared/src/events/event-utils.ts
572
+ var eventStatusMap = {
573
+ ["READY" /* READY */]: "PROVIDER_READY" /* Ready */,
574
+ ["ERROR" /* ERROR */]: "PROVIDER_ERROR" /* Error */,
575
+ ["STALE" /* STALE */]: "PROVIDER_STALE" /* Stale */,
576
+ ["NOT_READY" /* NOT_READY */]: void 0
577
+ };
578
+ var statusMatchesEvent = (event, status) => {
579
+ return !status && event === "PROVIDER_READY" /* Ready */ || eventStatusMap[status] === event;
580
+ };
581
+
582
+ // ../shared/src/events/open-feature-event-emitter.ts
583
+ var import_events2 = __toESM(require_events());
584
+
562
585
  // ../shared/src/logger/default-logger.ts
563
586
  var DefaultLogger = class {
564
587
  error(...args) {
@@ -613,13 +636,12 @@ var SafeLogger = class {
613
636
  };
614
637
 
615
638
  // ../shared/src/events/open-feature-event-emitter.ts
616
- var import_events = __toESM(require_events());
617
639
  var GenericEventEmitter = class {
618
640
  constructor(globalLogger) {
619
641
  this.globalLogger = globalLogger;
620
642
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
621
643
  this._handlers = /* @__PURE__ */ new WeakMap();
622
- this.eventEmitter = new import_events.default({ captureRejections: true });
644
+ this.eventEmitter = new import_events2.default({ captureRejections: true });
623
645
  this.eventEmitter.on("error", (err) => {
624
646
  var _a;
625
647
  (_a = this._logger) == null ? void 0 : _a.error("Error running event handler:", err);
@@ -629,8 +651,8 @@ var GenericEventEmitter = class {
629
651
  this.eventEmitter.emit(eventType, context);
630
652
  }
631
653
  addHandler(eventType, handler) {
632
- const asyncHandler = (context) => __async(this, null, function* () {
633
- yield handler(context);
654
+ const asyncHandler = (details) => __async(this, null, function* () {
655
+ yield handler(details);
634
656
  });
635
657
  this._handlers.set(handler, asyncHandler);
636
658
  this.eventEmitter.on(eventType, asyncHandler);
@@ -666,25 +688,6 @@ var OpenFeatureEventEmitter = class extends GenericEventEmitter {
666
688
  var InternalEventEmitter = class extends GenericEventEmitter {
667
689
  };
668
690
 
669
- // ../shared/src/provider/provider.ts
670
- var ProviderStatus = /* @__PURE__ */ ((ProviderStatus2) => {
671
- ProviderStatus2["NOT_READY"] = "NOT_READY";
672
- ProviderStatus2["READY"] = "READY";
673
- ProviderStatus2["ERROR"] = "ERROR";
674
- return ProviderStatus2;
675
- })(ProviderStatus || {});
676
-
677
- // ../shared/src/transaction-context/no-op-transaction-context-propagator.ts
678
- var NoopTransactionContextPropagator = class {
679
- getTransactionContext() {
680
- return {};
681
- }
682
- setTransactionContext(_, callback) {
683
- callback();
684
- }
685
- };
686
- var NOOP_TRANSACTION_CONTEXT_PROPAGATOR = new NoopTransactionContextPropagator();
687
-
688
691
  // ../shared/src/type-guards.ts
689
692
  function isString(value) {
690
693
  return typeof value === "string";
@@ -706,15 +709,15 @@ function isDefined(input) {
706
709
 
707
710
  // ../shared/src/open-feature.ts
708
711
  var OpenFeatureCommonAPI = class {
709
- constructor() {
712
+ constructor(category) {
710
713
  this._hooks = [];
711
- this._transactionContextPropagator = NOOP_TRANSACTION_CONTEXT_PROPAGATOR;
712
714
  this._context = {};
713
715
  this._logger = new DefaultLogger();
714
716
  this._events = new InternalEventEmitter(() => this._logger);
715
717
  this._clientEventHandlers = /* @__PURE__ */ new Map();
716
718
  this._clientProviders = /* @__PURE__ */ new Map();
717
719
  this._clientEvents = /* @__PURE__ */ new Map();
720
+ this._runsOn = category;
718
721
  }
719
722
  addHooks(...hooks) {
720
723
  this._hooks = [...this._hooks, ...hooks];
@@ -741,11 +744,24 @@ var OpenFeatureCommonAPI = class {
741
744
  /**
742
745
  * Adds a handler for the given provider event type.
743
746
  * The handlers are called in the order they have been added.
744
- * When changing the provider, the currently attached handlers will listen to the events of the new provider.
747
+ * API (global) events run for all providers.
745
748
  * @param {ProviderEvents} eventType The provider event type to listen to
746
749
  * @param {EventHandler} handler The handler to run on occurrence of the event type
747
750
  */
748
751
  addHandler(eventType, handler) {
752
+ [.../* @__PURE__ */ new Map([[void 0, this._defaultProvider]]), ...this._clientProviders].forEach((keyProviderTuple) => {
753
+ var _a;
754
+ const clientName = keyProviderTuple[0];
755
+ const provider = keyProviderTuple[1];
756
+ const shouldRunNow = statusMatchesEvent(eventType, keyProviderTuple[1].status);
757
+ if (shouldRunNow) {
758
+ try {
759
+ handler({ clientName, providerName: provider.metadata.name });
760
+ } catch (err) {
761
+ (_a = this._logger) == null ? void 0 : _a.error("Error running event handler:", err);
762
+ }
763
+ }
764
+ });
749
765
  this._events.addHandler(eventType, handler);
750
766
  }
751
767
  /**
@@ -764,43 +780,66 @@ var OpenFeatureCommonAPI = class {
764
780
  getHandlers(eventType) {
765
781
  return this._events.getHandlers(eventType);
766
782
  }
783
+ setProviderAndWait(clientOrProvider, providerOrUndefined) {
784
+ return __async(this, null, function* () {
785
+ yield this.setAwaitableProvider(clientOrProvider, providerOrUndefined);
786
+ });
787
+ }
767
788
  setProvider(clientOrProvider, providerOrUndefined) {
768
- var _a, _b, _c, _d, _e, _f, _g;
789
+ const maybePromise = this.setAwaitableProvider(clientOrProvider, providerOrUndefined);
790
+ if (maybePromise) {
791
+ maybePromise.catch(() => {
792
+ });
793
+ }
794
+ return this;
795
+ }
796
+ setAwaitableProvider(clientOrProvider, providerOrUndefined) {
797
+ var _a, _b, _c, _d, _e, _f;
769
798
  const clientName = stringOrUndefined(clientOrProvider);
770
799
  const provider = (_a = objectOrUndefined(clientOrProvider)) != null ? _a : objectOrUndefined(providerOrUndefined);
771
800
  if (!provider) {
772
- return this;
801
+ this._logger.debug("No provider defined, ignoring setProvider call");
802
+ return;
773
803
  }
774
804
  const oldProvider = this.getProviderForClient(clientName);
805
+ const providerName = provider.metadata.name;
775
806
  if (oldProvider === provider) {
776
- return this;
807
+ this._logger.debug("Provider is already set, ignoring setProvider call");
808
+ return;
809
+ }
810
+ if (!provider.runsOn) {
811
+ this._logger.debug(`Provider '${provider.metadata.name}' has not defined its intended use.`);
812
+ } else if (provider.runsOn !== this._runsOn) {
813
+ throw new GeneralError(`Provider '${provider.metadata.name}' is intended for use on the ${provider.runsOn}.`);
777
814
  }
778
815
  const emitters = this.getAssociatedEventEmitters(clientName);
779
816
  if (typeof provider.initialize === "function" && provider.status === void 0) {
780
817
  const activeLogger = this._logger || console;
781
818
  activeLogger.warn(
782
- `Provider ${(_b = provider == null ? void 0 : provider.metadata) == null ? void 0 : _b.name} implements 'initialize' but not 'status'. Please implement 'status'.`
819
+ `Provider ${providerName} implements 'initialize' but not 'status'. Please implement 'status'.`
783
820
  );
784
821
  }
822
+ let initializationPromise = void 0;
785
823
  if ((provider == null ? void 0 : provider.status) === "NOT_READY" /* NOT_READY */ && typeof provider.initialize === "function") {
786
- (_e = (_d = (_c = provider.initialize) == null ? void 0 : _c.call(provider, this._context)) == null ? void 0 : _d.then(() => {
824
+ initializationPromise = (_d = (_c = (_b = provider.initialize) == null ? void 0 : _b.call(provider, this._context)) == null ? void 0 : _c.then(() => {
787
825
  var _a2;
788
826
  this.getAssociatedEventEmitters(clientName).forEach((emitter) => {
789
- emitter == null ? void 0 : emitter.emit("PROVIDER_READY" /* Ready */, { clientName });
827
+ emitter == null ? void 0 : emitter.emit("PROVIDER_READY" /* Ready */, { clientName, providerName });
790
828
  });
791
- (_a2 = this._events) == null ? void 0 : _a2.emit("PROVIDER_READY" /* Ready */, { clientName });
792
- })) == null ? void 0 : _e.catch((error) => {
829
+ (_a2 = this._events) == null ? void 0 : _a2.emit("PROVIDER_READY" /* Ready */, { clientName, providerName });
830
+ })) == null ? void 0 : _d.catch((error) => {
793
831
  var _a2;
794
832
  this.getAssociatedEventEmitters(clientName).forEach((emitter) => {
795
- emitter == null ? void 0 : emitter.emit("PROVIDER_ERROR" /* Error */, { clientName, message: error.message });
833
+ emitter == null ? void 0 : emitter.emit("PROVIDER_ERROR" /* Error */, { clientName, providerName, message: error.message });
796
834
  });
797
- (_a2 = this._events) == null ? void 0 : _a2.emit("PROVIDER_ERROR" /* Error */, { clientName, message: error.message });
835
+ (_a2 = this._events) == null ? void 0 : _a2.emit("PROVIDER_ERROR" /* Error */, { clientName, providerName, message: error.message });
836
+ throw error;
798
837
  });
799
838
  } else {
800
839
  emitters.forEach((emitter) => {
801
- emitter == null ? void 0 : emitter.emit("PROVIDER_READY" /* Ready */, { clientName });
840
+ emitter == null ? void 0 : emitter.emit("PROVIDER_READY" /* Ready */, { clientName, providerName });
802
841
  });
803
- (_f = this._events) == null ? void 0 : _f.emit("PROVIDER_READY" /* Ready */, { clientName });
842
+ (_e = this._events) == null ? void 0 : _e.emit("PROVIDER_READY" /* Ready */, { clientName, providerName });
804
843
  }
805
844
  if (clientName) {
806
845
  this._clientProviders.set(clientName, provider);
@@ -809,9 +848,9 @@ var OpenFeatureCommonAPI = class {
809
848
  }
810
849
  this.transferListeners(oldProvider, provider, clientName, emitters);
811
850
  if (![...this._clientProviders.values(), this._defaultProvider].includes(oldProvider)) {
812
- (_g = oldProvider == null ? void 0 : oldProvider.onClose) == null ? void 0 : _g.call(oldProvider);
851
+ (_f = oldProvider == null ? void 0 : oldProvider.onClose) == null ? void 0 : _f.call(oldProvider);
813
852
  }
814
- return this;
853
+ return initializationPromise;
815
854
  }
816
855
  getProviderForClient(name) {
817
856
  var _a;
@@ -832,7 +871,7 @@ var OpenFeatureCommonAPI = class {
832
871
  (eventType) => {
833
872
  var _a;
834
873
  return (_a = clientProvider.events) == null ? void 0 : _a.addHandler(eventType, (details) => __async(this, null, function* () {
835
- newEmitter.emit(eventType, __spreadProps(__spreadValues({}, details), { clientName: name }));
874
+ newEmitter.emit(eventType, __spreadProps(__spreadValues({}, details), { clientName: name, providerName: clientProvider.metadata.name }));
836
875
  }));
837
876
  }
838
877
  );
@@ -861,9 +900,9 @@ var OpenFeatureCommonAPI = class {
861
900
  const newClientHandlers = Object.values(ProviderEvents).map((eventType) => {
862
901
  const handler = (details) => __async(this, null, function* () {
863
902
  emitters.forEach((emitter) => {
864
- emitter == null ? void 0 : emitter.emit(eventType, __spreadProps(__spreadValues({}, details), { clientName }));
903
+ emitter == null ? void 0 : emitter.emit(eventType, __spreadProps(__spreadValues({}, details), { clientName, providerName: newProvider.metadata.name }));
865
904
  });
866
- this._events.emit(eventType, __spreadProps(__spreadValues({}, details), { clientName }));
905
+ this._events.emit(eventType, __spreadProps(__spreadValues({}, details), { clientName, providerName: newProvider.metadata.name }));
867
906
  });
868
907
  return [eventType, handler];
869
908
  });
@@ -888,40 +927,28 @@ var OpenFeatureCommonAPI = class {
888
927
  try {
889
928
  yield (_a2 = provider.onClose) == null ? void 0 : _a2.call(provider);
890
929
  } catch (err) {
891
- this.handleShutdownError(this._defaultProvider, err);
930
+ this.handleShutdownError(provider, err);
892
931
  }
893
932
  }))
894
933
  );
895
934
  });
896
935
  }
936
+ clearProvidersAndSetDefault(defaultProvider) {
937
+ return __async(this, null, function* () {
938
+ try {
939
+ yield this.close();
940
+ } catch (err) {
941
+ this._logger.error("Unable to cleanly close providers. Resetting to the default configuration.");
942
+ } finally {
943
+ this._clientProviders.clear();
944
+ this._defaultProvider = defaultProvider;
945
+ }
946
+ });
947
+ }
897
948
  handleShutdownError(provider, err) {
898
949
  this._logger.error(`Error during shutdown of provider ${provider.metadata.name}: ${err}`);
899
950
  this._logger.error(err == null ? void 0 : err.stack);
900
951
  }
901
- setTransactionContextPropagator(transactionContextPropagator) {
902
- const baseMessage = "Invalid TransactionContextPropagator, will not be set: ";
903
- if (typeof (transactionContextPropagator == null ? void 0 : transactionContextPropagator.getTransactionContext) !== "function") {
904
- this._logger.error(`${baseMessage}: getTransactionContext is not a function.`);
905
- } else if (typeof (transactionContextPropagator == null ? void 0 : transactionContextPropagator.setTransactionContext) !== "function") {
906
- this._logger.error(`${baseMessage}: setTransactionContext is not a function.`);
907
- } else {
908
- this._transactionContextPropagator = transactionContextPropagator;
909
- }
910
- return this;
911
- }
912
- setTransactionContext(transactionContext, callback, ...args) {
913
- this._transactionContextPropagator.setTransactionContext(transactionContext, callback, ...args);
914
- }
915
- getTransactionContext() {
916
- try {
917
- return this._transactionContextPropagator.getTransactionContext();
918
- } catch (err) {
919
- const error = err;
920
- this._logger.error(`Error getting transaction context: ${error == null ? void 0 : error.message}, returning empty context.`);
921
- this._logger.error(error == null ? void 0 : error.stack);
922
- return {};
923
- }
924
- }
925
952
  };
926
953
 
927
954
  // src/provider/no-op-provider.ts
@@ -962,7 +989,7 @@ var _globalThis = globalThis;
962
989
  var OpenFeatureAPI = class extends OpenFeatureCommonAPI {
963
990
  // eslint-disable-next-line @typescript-eslint/no-empty-function
964
991
  constructor() {
965
- super();
992
+ super("client");
966
993
  this._defaultProvider = NOOP_PROVIDER;
967
994
  }
968
995
  /**
@@ -1020,6 +1047,13 @@ var OpenFeatureAPI = class extends OpenFeatureCommonAPI {
1020
1047
  { name, version }
1021
1048
  );
1022
1049
  }
1050
+ /**
1051
+ * Clears all registered providers and resets the default provider.
1052
+ * @returns {Promise<void>}
1053
+ */
1054
+ clearProviders() {
1055
+ return super.clearProvidersAndSetDefault(NOOP_PROVIDER);
1056
+ }
1023
1057
  };
1024
1058
  var OpenFeature = OpenFeatureAPI.getInstance();
1025
1059
 
@@ -1045,7 +1079,7 @@ var OpenFeatureClient = class {
1045
1079
  const providerReady = !this._provider.status || this._provider.status === "READY" /* READY */;
1046
1080
  if (eventType === "PROVIDER_READY" /* Ready */ && providerReady) {
1047
1081
  try {
1048
- handler({ clientName: this.metadata.name });
1082
+ handler({ clientName: this.metadata.name, providerName: this._provider.metadata.name });
1049
1083
  } catch (err) {
1050
1084
  (_a = this._logger) == null ? void 0 : _a.error("Error running event handler:", err);
1051
1085
  }
@@ -1212,7 +1246,6 @@ export {
1212
1246
  InvalidContextError,
1213
1247
  LOG_LEVELS,
1214
1248
  NOOP_PROVIDER,
1215
- NOOP_TRANSACTION_CONTEXT_PROPAGATOR,
1216
1249
  OpenFeature,
1217
1250
  OpenFeatureAPI,
1218
1251
  OpenFeatureClient,
@@ -1229,6 +1262,7 @@ export {
1229
1262
  isObject,
1230
1263
  isString,
1231
1264
  objectOrUndefined,
1265
+ statusMatchesEvent,
1232
1266
  stringOrUndefined
1233
1267
  };
1234
1268
  //# sourceMappingURL=index.js.map