@openfeature/web-sdk 1.0.3 → 1.2.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
@@ -1,10 +1,28 @@
1
1
  "use strict";
2
2
  var __create = Object.create;
3
3
  var __defProp = Object.defineProperty;
4
+ var __defProps = Object.defineProperties;
4
5
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
5
7
  var __getOwnPropNames = Object.getOwnPropertyNames;
8
+ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
6
9
  var __getProtoOf = Object.getPrototypeOf;
7
10
  var __hasOwnProp = Object.prototype.hasOwnProperty;
11
+ var __propIsEnum = Object.prototype.propertyIsEnumerable;
12
+ var __reflectGet = Reflect.get;
13
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
14
+ var __spreadValues = (a, b) => {
15
+ for (var prop in b || (b = {}))
16
+ if (__hasOwnProp.call(b, prop))
17
+ __defNormalProp(a, prop, b[prop]);
18
+ if (__getOwnPropSymbols)
19
+ for (var prop of __getOwnPropSymbols(b)) {
20
+ if (__propIsEnum.call(b, prop))
21
+ __defNormalProp(a, prop, b[prop]);
22
+ }
23
+ return a;
24
+ };
25
+ var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
8
26
  var __commonJS = (cb, mod) => function __require() {
9
27
  return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
10
28
  };
@@ -30,6 +48,27 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
30
48
  mod
31
49
  ));
32
50
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
51
+ var __superGet = (cls, obj, key) => __reflectGet(__getProtoOf(cls), key, obj);
52
+ var __async = (__this, __arguments, generator) => {
53
+ return new Promise((resolve, reject) => {
54
+ var fulfilled = (value) => {
55
+ try {
56
+ step(generator.next(value));
57
+ } catch (e) {
58
+ reject(e);
59
+ }
60
+ };
61
+ var rejected = (value) => {
62
+ try {
63
+ step(generator.throw(value));
64
+ } catch (e) {
65
+ reject(e);
66
+ }
67
+ };
68
+ var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
69
+ step((generator = generator.apply(__this, __arguments)).next());
70
+ });
71
+ };
33
72
 
34
73
  // ../../node_modules/eventemitter3/index.js
35
74
  var require_eventemitter3 = __commonJS({
@@ -220,45 +259,23 @@ __export(src_exports, {
220
259
  NOOP_PROVIDER: () => NOOP_PROVIDER,
221
260
  OpenFeature: () => OpenFeature,
222
261
  OpenFeatureAPI: () => OpenFeatureAPI,
223
- OpenFeatureClient: () => OpenFeatureClient,
224
262
  OpenFeatureEventEmitter: () => OpenFeatureEventEmitter,
225
- ProviderEvents: () => import_core2.ClientProviderEvents,
226
- ProviderStatus: () => import_core3.ClientProviderStatus
263
+ ProviderEvents: () => import_core3.ClientProviderEvents,
264
+ ProviderStatus: () => import_core.ClientProviderStatus
227
265
  });
228
266
  module.exports = __toCommonJS(src_exports);
229
267
 
230
- // src/client/open-feature-client.ts
231
- var import_core7 = require("@openfeature/core");
232
-
233
- // src/open-feature.ts
234
- var import_core6 = require("@openfeature/core");
235
-
236
- // src/events/open-feature-event-emitter.ts
237
- var import_core = require("@openfeature/core");
238
-
239
- // ../../node_modules/eventemitter3/index.mjs
240
- var import_index = __toESM(require_eventemitter3(), 1);
241
-
242
- // src/events/open-feature-event-emitter.ts
243
- var OpenFeatureEventEmitter = class extends import_core.GenericEventEmitter {
244
- eventEmitter = new import_index.default();
245
- constructor() {
246
- super();
247
- }
248
- };
249
-
250
- // src/events/events.ts
251
- var import_core2 = require("@openfeature/core");
252
-
253
268
  // src/provider/provider.ts
254
- var import_core3 = require("@openfeature/core");
269
+ var import_core = require("@openfeature/core");
255
270
 
256
271
  // src/provider/no-op-provider.ts
257
272
  var REASON_NO_OP = "No-op";
258
273
  var NoopFeatureProvider = class {
259
- metadata = {
260
- name: "No-op Provider"
261
- };
274
+ constructor() {
275
+ this.metadata = {
276
+ name: "No-op Provider"
277
+ };
278
+ }
262
279
  resolveBooleanEvaluation(_, defaultValue) {
263
280
  return this.noOp(defaultValue);
264
281
  }
@@ -283,10 +300,26 @@ var NOOP_PROVIDER = new NoopFeatureProvider();
283
300
  // src/provider/in-memory-provider/in-memory-provider.ts
284
301
  var import_core5 = require("@openfeature/core");
285
302
 
303
+ // src/events/open-feature-event-emitter.ts
304
+ var import_core2 = require("@openfeature/core");
305
+
306
+ // ../../node_modules/eventemitter3/index.mjs
307
+ var import_index = __toESM(require_eventemitter3(), 1);
308
+
309
+ // src/events/open-feature-event-emitter.ts
310
+ var OpenFeatureEventEmitter = class extends import_core2.GenericEventEmitter {
311
+ constructor() {
312
+ super();
313
+ this.eventEmitter = new import_index.default();
314
+ }
315
+ };
316
+
317
+ // src/events/events.ts
318
+ var import_core3 = require("@openfeature/core");
319
+
286
320
  // src/provider/in-memory-provider/variant-not-found-error.ts
287
321
  var import_core4 = require("@openfeature/core");
288
322
  var VariantNotFoundError = class _VariantNotFoundError extends import_core4.OpenFeatureError {
289
- code;
290
323
  constructor(message) {
291
324
  super(message);
292
325
  Object.setPrototypeOf(this, _VariantNotFoundError.prototype);
@@ -297,40 +330,42 @@ var VariantNotFoundError = class _VariantNotFoundError extends import_core4.Open
297
330
 
298
331
  // src/provider/in-memory-provider/in-memory-provider.ts
299
332
  var InMemoryProvider = class {
300
- events = new OpenFeatureEventEmitter();
301
- runsOn = "client";
302
- metadata = {
303
- name: "in-memory"
304
- };
305
- _flagConfiguration;
306
- _context;
307
333
  constructor(flagConfiguration = {}) {
308
- this._flagConfiguration = { ...flagConfiguration };
334
+ this.events = new OpenFeatureEventEmitter();
335
+ this.runsOn = "client";
336
+ this.metadata = {
337
+ name: "in-memory"
338
+ };
339
+ this._flagConfiguration = __spreadValues({}, flagConfiguration);
309
340
  }
310
- async initialize(context) {
311
- try {
312
- for (const key in this._flagConfiguration) {
313
- this.resolveFlagWithReason(key, context);
341
+ initialize(context) {
342
+ return __async(this, null, function* () {
343
+ try {
344
+ for (const key in this._flagConfiguration) {
345
+ this.resolveFlagWithReason(key, context);
346
+ }
347
+ this._context = context;
348
+ } catch (err) {
349
+ throw new import_core5.GeneralError("initialization failure", { cause: err });
314
350
  }
315
- this._context = context;
316
- } catch (err) {
317
- throw new Error("initialization failure", { cause: err });
318
- }
351
+ });
319
352
  }
320
353
  /**
321
354
  * Overwrites the configured flags.
322
355
  * @param { FlagConfiguration } flagConfiguration new flag configuration
323
356
  */
324
- async putConfiguration(flagConfiguration) {
325
- const flagsChanged = Object.entries(flagConfiguration).filter(([key, value]) => this._flagConfiguration[key] !== value).map(([key]) => key);
326
- this._flagConfiguration = { ...flagConfiguration };
327
- try {
328
- await this.initialize(this._context);
329
- this.events.emit(import_core2.ClientProviderEvents.ConfigurationChanged, { flagsChanged });
330
- } catch (err) {
331
- this.events.emit(import_core2.ClientProviderEvents.Error);
332
- throw err;
333
- }
357
+ putConfiguration(flagConfiguration) {
358
+ return __async(this, null, function* () {
359
+ const flagsChanged = Object.entries(flagConfiguration).filter(([key, value]) => this._flagConfiguration[key] !== value).map(([key]) => key);
360
+ this._flagConfiguration = __spreadValues({}, flagConfiguration);
361
+ try {
362
+ yield this.initialize(this._context);
363
+ this.events.emit(import_core3.ClientProviderEvents.ConfigurationChanged, { flagsChanged });
364
+ } catch (err) {
365
+ this.events.emit(import_core3.ClientProviderEvents.Error);
366
+ throw err;
367
+ }
368
+ });
334
369
  }
335
370
  resolveBooleanEvaluation(flagKey, defaultValue, context, logger) {
336
371
  return this.resolveAndCheckFlag(flagKey, defaultValue, context || this._context, logger);
@@ -347,7 +382,7 @@ var InMemoryProvider = class {
347
382
  resolveAndCheckFlag(flagKey, defaultValue, context, logger) {
348
383
  if (!(flagKey in this._flagConfiguration)) {
349
384
  const message = `no flag found with key ${flagKey}`;
350
- logger?.debug(message);
385
+ logger == null ? void 0 : logger.debug(message);
351
386
  throw new import_core5.FlagNotFoundError(message);
352
387
  }
353
388
  if (this._flagConfiguration[flagKey].disabled) {
@@ -356,7 +391,7 @@ var InMemoryProvider = class {
356
391
  const resolvedFlag = this.resolveFlagWithReason(flagKey, context);
357
392
  if (resolvedFlag.value === void 0) {
358
393
  const message = `no value associated with variant provided for ${flagKey} found`;
359
- logger?.error(message);
394
+ logger == null ? void 0 : logger.error(message);
360
395
  throw new VariantNotFoundError(message);
361
396
  }
362
397
  if (typeof resolvedFlag.value != typeof defaultValue) {
@@ -370,192 +405,31 @@ var InMemoryProvider = class {
370
405
  return resolutionResult;
371
406
  } catch (error) {
372
407
  if (!(error instanceof import_core5.OpenFeatureError)) {
373
- throw new import_core5.GeneralError(error?.message || "unknown error");
408
+ throw new import_core5.GeneralError((error == null ? void 0 : error.message) || "unknown error");
374
409
  }
375
410
  throw error;
376
411
  }
377
412
  }
378
413
  lookupFlagValue(flagKey, ctx) {
414
+ var _a;
379
415
  const flagSpec = this._flagConfiguration[flagKey];
380
- const isContextEval = ctx && flagSpec?.contextEvaluator;
381
- const variant = isContextEval ? flagSpec.contextEvaluator?.(ctx) : flagSpec.defaultVariant;
382
- const value = variant && flagSpec?.variants[variant];
416
+ const isContextEval = ctx && (flagSpec == null ? void 0 : flagSpec.contextEvaluator);
417
+ const variant = isContextEval ? (_a = flagSpec.contextEvaluator) == null ? void 0 : _a.call(flagSpec, ctx) : flagSpec.defaultVariant;
418
+ const value = variant && (flagSpec == null ? void 0 : flagSpec.variants[variant]);
383
419
  const reason = isContextEval ? import_core5.StandardResolutionReasons.TARGETING_MATCH : import_core5.StandardResolutionReasons.STATIC;
384
- return {
385
- value,
386
- ...variant && { variant },
420
+ return __spreadProps(__spreadValues({
421
+ value
422
+ }, variant && { variant }), {
387
423
  reason
388
- };
424
+ });
389
425
  }
390
426
  };
391
427
 
392
428
  // src/open-feature.ts
393
- var GLOBAL_OPENFEATURE_API_KEY = Symbol.for("@openfeature/web-sdk/api");
394
- var _globalThis = globalThis;
395
- var OpenFeatureAPI = class _OpenFeatureAPI extends import_core6.OpenFeatureCommonAPI {
396
- _statusEnumType = import_core3.ClientProviderStatus;
397
- _apiEmitter = new OpenFeatureEventEmitter();
398
- _defaultProvider = new import_core6.ProviderWrapper(NOOP_PROVIDER, import_core3.ClientProviderStatus.NOT_READY, this._statusEnumType);
399
- _domainScopedProviders = /* @__PURE__ */ new Map();
400
- _createEventEmitter = () => new OpenFeatureEventEmitter();
401
- constructor() {
402
- super("client");
403
- }
404
- /**
405
- * Gets a singleton instance of the OpenFeature API.
406
- * @ignore
407
- * @returns {OpenFeatureAPI} OpenFeature API
408
- */
409
- static getInstance() {
410
- const globalApi = _globalThis[GLOBAL_OPENFEATURE_API_KEY];
411
- if (globalApi) {
412
- return globalApi;
413
- }
414
- const instance = new _OpenFeatureAPI();
415
- _globalThis[GLOBAL_OPENFEATURE_API_KEY] = instance;
416
- return instance;
417
- }
418
- getProviderStatus(domain) {
419
- if (!domain) {
420
- return this._defaultProvider.status;
421
- }
422
- return this._domainScopedProviders.get(domain)?.status ?? this._defaultProvider.status;
423
- }
424
- async setContext(domainOrContext, contextOrUndefined) {
425
- const domain = (0, import_core6.stringOrUndefined)(domainOrContext);
426
- const context = (0, import_core6.objectOrUndefined)(domainOrContext) ?? (0, import_core6.objectOrUndefined)(contextOrUndefined) ?? {};
427
- if (domain) {
428
- const wrapper = this._domainScopedProviders.get(domain);
429
- if (wrapper) {
430
- const oldContext = this.getContext(domain);
431
- this._domainScopedContext.set(domain, context);
432
- await this.runProviderContextChangeHandler(domain, wrapper, oldContext, context);
433
- } else {
434
- this._domainScopedContext.set(domain, context);
435
- }
436
- } else {
437
- const oldContext = this._context;
438
- this._context = context;
439
- const unboundProviders = Array.from(this._domainScopedProviders.entries()).filter(([domain2]) => !this._domainScopedContext.has(domain2)).reduce((acc, [domain2, wrapper]) => {
440
- acc.push({ domain: domain2, wrapper });
441
- return acc;
442
- }, []);
443
- const allDomainRecords = [
444
- // add in the default (no domain)
445
- { domain: void 0, wrapper: this._defaultProvider },
446
- ...unboundProviders
447
- ];
448
- await Promise.all(
449
- allDomainRecords.map(
450
- (dm) => this.runProviderContextChangeHandler(dm.domain, dm.wrapper, oldContext, context)
451
- )
452
- );
453
- }
454
- }
455
- getContext(domainOrUndefined) {
456
- const domain = (0, import_core6.stringOrUndefined)(domainOrUndefined);
457
- if (domain) {
458
- const context = this._domainScopedContext.get(domain);
459
- if (context) {
460
- return context;
461
- } else {
462
- this._logger.debug(`Unable to find context for '${domain}'.`);
463
- }
464
- }
465
- return this._context;
466
- }
467
- async clearContext(domainOrUndefined) {
468
- const domain = (0, import_core6.stringOrUndefined)(domainOrUndefined);
469
- if (domain) {
470
- const wrapper = this._domainScopedProviders.get(domain);
471
- if (wrapper) {
472
- const oldContext = this.getContext(domain);
473
- this._domainScopedContext.delete(domain);
474
- const newContext = this.getContext();
475
- await this.runProviderContextChangeHandler(domain, wrapper, oldContext, newContext);
476
- } else {
477
- this._domainScopedContext.delete(domain);
478
- }
479
- } else {
480
- return this.setContext({});
481
- }
482
- }
483
- /**
484
- * Resets the global evaluation context and removes the evaluation context for
485
- * all domains.
486
- */
487
- async clearContexts() {
488
- await this.clearContext();
489
- await Promise.allSettled(Array.from(this._domainScopedProviders.keys()).map((domain) => this.clearContext(domain)));
490
- }
491
- /**
492
- * A factory function for creating new named OpenFeature clients. Clients can contain
493
- * their own state (e.g. logger, hook, context). Multiple clients can be used
494
- * to segment feature flag configuration.
495
- *
496
- * If there is already a provider bound to this name via {@link this.setProvider setProvider}, this provider will be used.
497
- * Otherwise, the default provider is used until a provider is assigned to that name.
498
- * @param {string} domain An identifier which logically binds clients with providers
499
- * @param {string} version The version of the client (only used for metadata)
500
- * @returns {Client} OpenFeature Client
501
- */
502
- getClient(domain, version) {
503
- return new OpenFeatureClient(
504
- // functions are passed here to make sure that these values are always up to date,
505
- // and so we don't have to make these public properties on the API class.
506
- () => this.getProviderForClient(domain),
507
- () => this.getProviderStatus(domain),
508
- () => this.buildAndCacheEventEmitterForClient(domain),
509
- () => this._logger,
510
- { domain, version }
511
- );
512
- }
513
- /**
514
- * Clears all registered providers and resets the default provider.
515
- * @returns {Promise<void>}
516
- */
517
- async clearProviders() {
518
- await super.clearProvidersAndSetDefault(NOOP_PROVIDER);
519
- this._domainScopedContext.clear();
520
- }
521
- async runProviderContextChangeHandler(domain, wrapper, oldContext, newContext) {
522
- const providerName = wrapper.provider?.metadata?.name || "unnamed-provider";
523
- try {
524
- if (typeof wrapper.provider.onContextChange === "function") {
525
- wrapper.incrementPendingContextChanges();
526
- wrapper.status = this._statusEnumType.RECONCILING;
527
- this.getAssociatedEventEmitters(domain).forEach((emitter) => {
528
- emitter?.emit(import_core2.ClientProviderEvents.Reconciling, { domain, providerName });
529
- });
530
- this._apiEmitter?.emit(import_core2.ClientProviderEvents.Reconciling, { domain, providerName });
531
- await wrapper.provider.onContextChange(oldContext, newContext);
532
- wrapper.decrementPendingContextChanges();
533
- }
534
- wrapper.status = this._statusEnumType.READY;
535
- if (wrapper.allContextChangesSettled) {
536
- this.getAssociatedEventEmitters(domain).forEach((emitter) => {
537
- emitter?.emit(import_core2.ClientProviderEvents.ContextChanged, { clientName: domain, domain, providerName });
538
- });
539
- this._apiEmitter?.emit(import_core2.ClientProviderEvents.ContextChanged, { clientName: domain, domain, providerName });
540
- }
541
- } catch (err) {
542
- wrapper.decrementPendingContextChanges();
543
- wrapper.status = this._statusEnumType.ERROR;
544
- if (wrapper.allContextChangesSettled) {
545
- const error = err;
546
- const message = `Error running ${providerName}'s context change handler: ${error?.message}`;
547
- this._logger?.error(`${message}`, err);
548
- this.getAssociatedEventEmitters(domain).forEach((emitter) => {
549
- emitter?.emit(import_core2.ClientProviderEvents.Error, { clientName: domain, domain, providerName, message });
550
- });
551
- this._apiEmitter?.emit(import_core2.ClientProviderEvents.Error, { clientName: domain, domain, providerName, message });
552
- }
553
- }
554
- }
555
- };
556
- var OpenFeature = OpenFeatureAPI.getInstance();
429
+ var import_core7 = require("@openfeature/core");
557
430
 
558
- // src/client/open-feature-client.ts
431
+ // src/client/internal/open-feature-client.ts
432
+ var import_core6 = require("@openfeature/core");
559
433
  var OpenFeatureClient = class {
560
434
  constructor(providerAccessor, providerStatusAccessor, emitterAccessor, globalLogger, options) {
561
435
  this.providerAccessor = providerAccessor;
@@ -563,14 +437,14 @@ var OpenFeatureClient = class {
563
437
  this.emitterAccessor = emitterAccessor;
564
438
  this.globalLogger = globalLogger;
565
439
  this.options = options;
440
+ this._hooks = [];
566
441
  }
567
- _hooks = [];
568
- _clientLogger;
569
442
  get metadata() {
443
+ var _a, _b;
570
444
  return {
571
445
  // Use domain if name is not provided
572
- name: this.options.domain ?? this.options.name,
573
- domain: this.options.domain ?? this.options.name,
446
+ name: (_a = this.options.domain) != null ? _a : this.options.name,
447
+ domain: (_b = this.options.domain) != null ? _b : this.options.name,
574
448
  version: this.options.version,
575
449
  providerMetadata: this.providerAccessor().metadata
576
450
  };
@@ -579,8 +453,9 @@ var OpenFeatureClient = class {
579
453
  return this.providerStatusAccessor();
580
454
  }
581
455
  addHandler(eventType, handler) {
456
+ var _a;
582
457
  this.emitterAccessor().addHandler(eventType, handler);
583
- const shouldRunNow = (0, import_core7.statusMatchesEvent)(eventType, this.providerStatus);
458
+ const shouldRunNow = (0, import_core6.statusMatchesEvent)(eventType, this.providerStatus);
584
459
  if (shouldRunNow) {
585
460
  try {
586
461
  handler({
@@ -589,7 +464,7 @@ var OpenFeatureClient = class {
589
464
  providerName: this._provider.metadata.name
590
465
  });
591
466
  } catch (err) {
592
- this._logger?.error("Error running event handler:", err);
467
+ (_a = this._logger) == null ? void 0 : _a.error("Error running event handler:", err);
593
468
  }
594
469
  }
595
470
  }
@@ -600,7 +475,7 @@ var OpenFeatureClient = class {
600
475
  return this.emitterAccessor().getHandlers(eventType);
601
476
  }
602
477
  setLogger(logger) {
603
- this._clientLogger = new import_core7.SafeLogger(logger);
478
+ this._clientLogger = new import_core6.SafeLogger(logger);
604
479
  return this;
605
480
  }
606
481
  addHooks(...hooks) {
@@ -653,6 +528,7 @@ var OpenFeatureClient = class {
653
528
  return this.evaluate(flagKey, this._provider.resolveObjectEvaluation, defaultValue, "object", options);
654
529
  }
655
530
  evaluate(flagKey, resolver, defaultValue, flagType, options = {}) {
531
+ var _a, _b;
656
532
  const allHooks = [
657
533
  ...OpenFeature.getHooks(),
658
534
  ...this.getHooks(),
@@ -660,9 +536,7 @@ var OpenFeatureClient = class {
660
536
  ...this._provider.hooks || []
661
537
  ];
662
538
  const allHooksReversed = [...allHooks].reverse();
663
- const context = {
664
- ...OpenFeature.getContext(this?.options?.domain)
665
- };
539
+ const context = __spreadValues({}, OpenFeature.getContext((_a = this == null ? void 0 : this.options) == null ? void 0 : _a.domain));
666
540
  const hookContext = {
667
541
  flagKey,
668
542
  defaultValue,
@@ -674,28 +548,30 @@ var OpenFeatureClient = class {
674
548
  };
675
549
  try {
676
550
  this.beforeHooks(allHooks, hookContext, options);
677
- if (this.providerStatus === import_core3.ClientProviderStatus.NOT_READY) {
678
- throw new import_core7.ProviderNotReadyError("provider has not yet initialized");
679
- } else if (this.providerStatus === import_core3.ClientProviderStatus.FATAL) {
680
- throw new import_core7.ProviderFatalError("provider is in an irrecoverable error state");
551
+ if (this.providerStatus === import_core.ClientProviderStatus.NOT_READY) {
552
+ throw new import_core6.ProviderNotReadyError("provider has not yet initialized");
553
+ } else if (this.providerStatus === import_core.ClientProviderStatus.FATAL) {
554
+ throw new import_core6.ProviderFatalError("provider is in an irrecoverable error state");
681
555
  }
682
556
  const resolution = resolver.call(this._provider, flagKey, defaultValue, context, this._logger);
683
- const evaluationDetails = {
684
- ...resolution,
685
- flagMetadata: Object.freeze(resolution.flagMetadata ?? {}),
557
+ const evaluationDetails = __spreadProps(__spreadValues({}, resolution), {
558
+ flagMetadata: Object.freeze((_b = resolution.flagMetadata) != null ? _b : {}),
686
559
  flagKey
687
- };
560
+ });
561
+ if (evaluationDetails.errorCode) {
562
+ throw (0, import_core6.instantiateErrorByErrorCode)(evaluationDetails.errorCode);
563
+ }
688
564
  this.afterHooks(allHooksReversed, hookContext, evaluationDetails, options);
689
565
  return evaluationDetails;
690
566
  } catch (err) {
691
- const errorMessage = err?.message;
692
- const errorCode = err?.code || import_core7.ErrorCode.GENERAL;
567
+ const errorMessage = err == null ? void 0 : err.message;
568
+ const errorCode = (err == null ? void 0 : err.code) || import_core6.ErrorCode.GENERAL;
693
569
  this.errorHooks(allHooksReversed, hookContext, err, options);
694
570
  return {
695
571
  errorCode,
696
572
  errorMessage,
697
573
  value: defaultValue,
698
- reason: import_core7.StandardResolutionReasons.ERROR,
574
+ reason: import_core6.StandardResolutionReasons.ERROR,
699
575
  flagMetadata: Object.freeze({}),
700
576
  flagKey
701
577
  };
@@ -704,40 +580,44 @@ var OpenFeatureClient = class {
704
580
  }
705
581
  }
706
582
  beforeHooks(hooks, hookContext, options) {
583
+ var _a;
707
584
  Object.freeze(hookContext);
708
585
  Object.freeze(hookContext.context);
709
586
  for (const hook of hooks) {
710
- hook?.before?.(hookContext, Object.freeze(options.hookHints));
587
+ (_a = hook == null ? void 0 : hook.before) == null ? void 0 : _a.call(hook, hookContext, Object.freeze(options.hookHints));
711
588
  }
712
589
  }
713
590
  afterHooks(hooks, hookContext, evaluationDetails, options) {
591
+ var _a;
714
592
  for (const hook of hooks) {
715
- hook?.after?.(hookContext, evaluationDetails, options.hookHints);
593
+ (_a = hook == null ? void 0 : hook.after) == null ? void 0 : _a.call(hook, hookContext, evaluationDetails, options.hookHints);
716
594
  }
717
595
  }
718
596
  errorHooks(hooks, hookContext, err, options) {
597
+ var _a;
719
598
  for (const hook of hooks) {
720
599
  try {
721
- hook?.error?.(hookContext, err, options.hookHints);
600
+ (_a = hook == null ? void 0 : hook.error) == null ? void 0 : _a.call(hook, hookContext, err, options.hookHints);
722
601
  } catch (err2) {
723
602
  this._logger.error(`Unhandled error during 'error' hook: ${err2}`);
724
603
  if (err2 instanceof Error) {
725
604
  this._logger.error(err2.stack);
726
605
  }
727
- this._logger.error(err2?.stack);
606
+ this._logger.error(err2 == null ? void 0 : err2.stack);
728
607
  }
729
608
  }
730
609
  }
731
610
  finallyHooks(hooks, hookContext, options) {
611
+ var _a;
732
612
  for (const hook of hooks) {
733
613
  try {
734
- hook?.finally?.(hookContext, options.hookHints);
614
+ (_a = hook == null ? void 0 : hook.finally) == null ? void 0 : _a.call(hook, hookContext, options.hookHints);
735
615
  } catch (err) {
736
616
  this._logger.error(`Unhandled error during 'finally' hook: ${err}`);
737
617
  if (err instanceof Error) {
738
618
  this._logger.error(err.stack);
739
619
  }
740
- this._logger.error(err?.stack);
620
+ this._logger.error(err == null ? void 0 : err.stack);
741
621
  }
742
622
  }
743
623
  }
@@ -749,6 +629,222 @@ var OpenFeatureClient = class {
749
629
  }
750
630
  };
751
631
 
632
+ // src/open-feature.ts
633
+ var GLOBAL_OPENFEATURE_API_KEY = Symbol.for("@openfeature/web-sdk/api");
634
+ var _globalThis = globalThis;
635
+ var OpenFeatureAPI = class _OpenFeatureAPI extends import_core7.OpenFeatureCommonAPI {
636
+ constructor() {
637
+ super("client");
638
+ this._statusEnumType = import_core.ClientProviderStatus;
639
+ this._apiEmitter = new OpenFeatureEventEmitter();
640
+ this._defaultProvider = new import_core7.ProviderWrapper(
641
+ NOOP_PROVIDER,
642
+ import_core.ClientProviderStatus.NOT_READY,
643
+ this._statusEnumType
644
+ );
645
+ this._domainScopedProviders = /* @__PURE__ */ new Map();
646
+ this._createEventEmitter = () => new OpenFeatureEventEmitter();
647
+ }
648
+ /**
649
+ * Gets a singleton instance of the OpenFeature API.
650
+ * @ignore
651
+ * @returns {OpenFeatureAPI} OpenFeature API
652
+ */
653
+ static getInstance() {
654
+ const globalApi = _globalThis[GLOBAL_OPENFEATURE_API_KEY];
655
+ if (globalApi) {
656
+ return globalApi;
657
+ }
658
+ const instance = new _OpenFeatureAPI();
659
+ _globalThis[GLOBAL_OPENFEATURE_API_KEY] = instance;
660
+ return instance;
661
+ }
662
+ getProviderStatus(domain) {
663
+ var _a, _b;
664
+ if (!domain) {
665
+ return this._defaultProvider.status;
666
+ }
667
+ return (_b = (_a = this._domainScopedProviders.get(domain)) == null ? void 0 : _a.status) != null ? _b : this._defaultProvider.status;
668
+ }
669
+ setProviderAndWait(clientOrProvider, providerContextOrUndefined, contextOrUndefined) {
670
+ return __async(this, null, function* () {
671
+ const domain = (0, import_core7.stringOrUndefined)(clientOrProvider);
672
+ const provider = domain ? (0, import_core7.objectOrUndefined)(providerContextOrUndefined) : (0, import_core7.objectOrUndefined)(clientOrProvider);
673
+ const context = domain ? (0, import_core7.objectOrUndefined)(contextOrUndefined) : (0, import_core7.objectOrUndefined)(providerContextOrUndefined);
674
+ if (context) {
675
+ if (domain) {
676
+ this._domainScopedContext.set(domain, context);
677
+ } else {
678
+ this._context = context;
679
+ }
680
+ }
681
+ yield this.setAwaitableProvider(domain, provider);
682
+ });
683
+ }
684
+ setProvider(domainOrProvider, providerContextOrUndefined, contextOrUndefined) {
685
+ const domain = (0, import_core7.stringOrUndefined)(domainOrProvider);
686
+ const provider = domain ? (0, import_core7.objectOrUndefined)(providerContextOrUndefined) : (0, import_core7.objectOrUndefined)(domainOrProvider);
687
+ const context = domain ? (0, import_core7.objectOrUndefined)(contextOrUndefined) : (0, import_core7.objectOrUndefined)(providerContextOrUndefined);
688
+ if (context) {
689
+ if (domain) {
690
+ this._domainScopedContext.set(domain, context);
691
+ } else {
692
+ this._context = context;
693
+ }
694
+ }
695
+ const maybePromise = this.setAwaitableProvider(domain, provider);
696
+ Promise.resolve(maybePromise).catch((err) => {
697
+ this._logger.error("Error during provider initialization:", err);
698
+ });
699
+ return this;
700
+ }
701
+ setContext(domainOrContext, contextOrUndefined) {
702
+ return __async(this, null, function* () {
703
+ var _a, _b;
704
+ const domain = (0, import_core7.stringOrUndefined)(domainOrContext);
705
+ const context = (_b = (_a = (0, import_core7.objectOrUndefined)(domainOrContext)) != null ? _a : (0, import_core7.objectOrUndefined)(contextOrUndefined)) != null ? _b : {};
706
+ if (domain) {
707
+ const wrapper = this._domainScopedProviders.get(domain);
708
+ if (wrapper) {
709
+ const oldContext = this.getContext(domain);
710
+ this._domainScopedContext.set(domain, context);
711
+ yield this.runProviderContextChangeHandler(domain, wrapper, oldContext, context);
712
+ } else {
713
+ this._domainScopedContext.set(domain, context);
714
+ }
715
+ } else {
716
+ const oldContext = this._context;
717
+ this._context = context;
718
+ const unboundProviders = Array.from(this._domainScopedProviders.entries()).filter(([domain2]) => !this._domainScopedContext.has(domain2)).reduce((acc, [domain2, wrapper]) => {
719
+ acc.push({ domain: domain2, wrapper });
720
+ return acc;
721
+ }, []);
722
+ const allDomainRecords = [
723
+ // add in the default (no domain)
724
+ { domain: void 0, wrapper: this._defaultProvider },
725
+ ...unboundProviders
726
+ ];
727
+ yield Promise.all(
728
+ allDomainRecords.map((dm) => this.runProviderContextChangeHandler(dm.domain, dm.wrapper, oldContext, context))
729
+ );
730
+ }
731
+ });
732
+ }
733
+ getContext(domainOrUndefined) {
734
+ const domain = (0, import_core7.stringOrUndefined)(domainOrUndefined);
735
+ if (domain) {
736
+ const context = this._domainScopedContext.get(domain);
737
+ if (context) {
738
+ return context;
739
+ } else {
740
+ this._logger.debug(`Unable to find context for '${domain}'.`);
741
+ }
742
+ }
743
+ return this._context;
744
+ }
745
+ clearContext(domainOrUndefined) {
746
+ return __async(this, null, function* () {
747
+ const domain = (0, import_core7.stringOrUndefined)(domainOrUndefined);
748
+ if (domain) {
749
+ const wrapper = this._domainScopedProviders.get(domain);
750
+ if (wrapper) {
751
+ const oldContext = this.getContext(domain);
752
+ this._domainScopedContext.delete(domain);
753
+ const newContext = this.getContext();
754
+ yield this.runProviderContextChangeHandler(domain, wrapper, oldContext, newContext);
755
+ } else {
756
+ this._domainScopedContext.delete(domain);
757
+ }
758
+ } else {
759
+ return this.setContext({});
760
+ }
761
+ });
762
+ }
763
+ /**
764
+ * Resets the global evaluation context and removes the evaluation context for
765
+ * all domains.
766
+ */
767
+ clearContexts() {
768
+ return __async(this, null, function* () {
769
+ yield this.clearContext();
770
+ yield Promise.allSettled(Array.from(this._domainScopedProviders.keys()).map((domain) => this.clearContext(domain)));
771
+ });
772
+ }
773
+ /**
774
+ * A factory function for creating new named OpenFeature clients. Clients can contain
775
+ * their own state (e.g. logger, hook, context). Multiple clients can be used
776
+ * to segment feature flag configuration.
777
+ *
778
+ * If there is already a provider bound to this name via {@link this.setProvider setProvider}, this provider will be used.
779
+ * Otherwise, the default provider is used until a provider is assigned to that name.
780
+ * @param {string} domain An identifier which logically binds clients with providers
781
+ * @param {string} version The version of the client (only used for metadata)
782
+ * @returns {Client} OpenFeature Client
783
+ */
784
+ getClient(domain, version) {
785
+ return new OpenFeatureClient(
786
+ // functions are passed here to make sure that these values are always up to date,
787
+ // and so we don't have to make these public properties on the API class.
788
+ () => this.getProviderForClient(domain),
789
+ () => this.getProviderStatus(domain),
790
+ () => this.buildAndCacheEventEmitterForClient(domain),
791
+ () => this._logger,
792
+ { domain, version }
793
+ );
794
+ }
795
+ /**
796
+ * Clears all registered providers and resets the default provider.
797
+ * @returns {Promise<void>}
798
+ */
799
+ clearProviders() {
800
+ return __async(this, null, function* () {
801
+ yield __superGet(_OpenFeatureAPI.prototype, this, "clearProvidersAndSetDefault").call(this, NOOP_PROVIDER);
802
+ this._domainScopedContext.clear();
803
+ });
804
+ }
805
+ runProviderContextChangeHandler(domain, wrapper, oldContext, newContext) {
806
+ return __async(this, null, function* () {
807
+ var _a, _b, _c, _d, _e, _f;
808
+ const providerName = ((_b = (_a = wrapper.provider) == null ? void 0 : _a.metadata) == null ? void 0 : _b.name) || "unnamed-provider";
809
+ try {
810
+ if (typeof wrapper.provider.onContextChange === "function") {
811
+ const maybePromise = wrapper.provider.onContextChange(oldContext, newContext);
812
+ if (typeof (maybePromise == null ? void 0 : maybePromise.then) === "function") {
813
+ wrapper.incrementPendingContextChanges();
814
+ wrapper.status = this._statusEnumType.RECONCILING;
815
+ this.getAssociatedEventEmitters(domain).forEach((emitter) => {
816
+ emitter == null ? void 0 : emitter.emit(import_core3.ClientProviderEvents.Reconciling, { domain, providerName });
817
+ });
818
+ (_c = this._apiEmitter) == null ? void 0 : _c.emit(import_core3.ClientProviderEvents.Reconciling, { domain, providerName });
819
+ yield maybePromise;
820
+ wrapper.decrementPendingContextChanges();
821
+ }
822
+ }
823
+ wrapper.status = this._statusEnumType.READY;
824
+ if (wrapper.allContextChangesSettled) {
825
+ this.getAssociatedEventEmitters(domain).forEach((emitter) => {
826
+ emitter == null ? void 0 : emitter.emit(import_core3.ClientProviderEvents.ContextChanged, { clientName: domain, domain, providerName });
827
+ });
828
+ (_d = this._apiEmitter) == null ? void 0 : _d.emit(import_core3.ClientProviderEvents.ContextChanged, { clientName: domain, domain, providerName });
829
+ }
830
+ } catch (err) {
831
+ wrapper.decrementPendingContextChanges();
832
+ wrapper.status = this._statusEnumType.ERROR;
833
+ if (wrapper.allContextChangesSettled) {
834
+ const error = err;
835
+ const message = `Error running ${providerName}'s context change handler: ${error == null ? void 0 : error.message}`;
836
+ (_e = this._logger) == null ? void 0 : _e.error(`${message}`, err);
837
+ this.getAssociatedEventEmitters(domain).forEach((emitter) => {
838
+ emitter == null ? void 0 : emitter.emit(import_core3.ClientProviderEvents.Error, { clientName: domain, domain, providerName, message });
839
+ });
840
+ (_f = this._apiEmitter) == null ? void 0 : _f.emit(import_core3.ClientProviderEvents.Error, { clientName: domain, domain, providerName, message });
841
+ }
842
+ }
843
+ });
844
+ }
845
+ };
846
+ var OpenFeature = OpenFeatureAPI.getInstance();
847
+
752
848
  // src/index.ts
753
849
  __reExport(src_exports, require("@openfeature/core"), module.exports);
754
850
  //# sourceMappingURL=index.js.map