@configdirector/client-sdk 1.10.1 → 1.11.1

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.
@@ -25,24 +25,72 @@ interface ConfigDirectorLogMessageDecorator {
25
25
  }
26
26
  /**
27
27
  * Why an evaluation returned the value it did. `found-match` returns a value from ConfigDirector,
28
- * and `cached` a value kept on the device while a client SDK waits for live values. `value-missing`
28
+ * and `cached` a value kept on the device while a client SDK waits for live values.
29
+ * `rollout-skipped-no-identifier` returns the default targeting rule value: a server SDK skipped a
30
+ * percentage rollout because the context has no `id` to place it in a share. `value-missing`
29
31
  * returns the in-code default value because the config has no value. Every other reason returns the
30
32
  * in-code default value because of an error: the config does not exist (`config-state-missing`), no
31
33
  * values have arrived yet (`client-not-ready`), or the value cannot be read as the type of the in-code
32
34
  * default value.
33
35
  */
34
- type EvaluationReason = "found-match" | "config-state-missing" | "client-not-ready" | "type-mismatch" | "value-missing" | "invalid-number" | "invalid-json" | "invalid-boolean" | "cached";
36
+ type EvaluationReason = "found-match" | "rollout-skipped-no-identifier" | "config-state-missing" | "client-not-ready" | "type-mismatch" | "value-missing" | "invalid-number" | "invalid-json" | "invalid-boolean" | "cached";
37
+ /**
38
+ * One of the values a config can serve, such as the control or a treatment of an experiment.
39
+ */
40
+ type Variation = {
41
+ /** The ID ConfigDirector assigned to the variation, which stays the same when it is renamed. */id: string; /** The variation's name, when it has one. */
42
+ name?: string;
43
+ };
35
44
  /**
36
45
  * One evaluation of a config: the value it returned, why, and the context it was evaluated for.
37
46
  */
38
47
  type ConfigEvaluation<T extends ConfigValueType = ConfigValueType> = {
39
48
  /** The config key that was evaluated. */key: string; /** The value returned, which is the in-code default value when {@link isDefaultValue} is `true`. */
40
49
  value: T; /** The ID ConfigDirector assigned to the value returned, when ConfigDirector sent one with it. */
41
- valueId?: string; /** Whether the evaluation returned the in-code default value. */
50
+ valueId?: string;
51
+ /**
52
+ * The variation that was served. It is `undefined` when the config has no variations or the
53
+ * in-code default value is returned.
54
+ */
55
+ variation?: Variation; /** Whether the evaluation returned the in-code default value. */
42
56
  isDefaultValue: boolean; /** Why the evaluation returned this value. */
43
57
  reason: EvaluationReason; /** The context the config was evaluated for, if any. */
44
58
  context?: ConfigDirectorContext;
45
59
  };
60
+ /**
61
+ * A value in the details of a tracked event: a string, a number, a boolean, or an array or object
62
+ * of such values.
63
+ */
64
+ type TrackedEventDetailValue = string | number | boolean | TrackedEventDetailValue[] | {
65
+ [key: string]: TrackedEventDetailValue;
66
+ };
67
+ /**
68
+ * Details of a tracked event, such as the plan a customer chose. Details with more than 20
69
+ * top-level keys, or larger than 1 KB as JSON, are left out and the event is still reported.
70
+ */
71
+ type TrackedEventDetails = {
72
+ [key: string]: TrackedEventDetailValue;
73
+ };
74
+ /**
75
+ * What a tracked event carries besides its name.
76
+ */
77
+ type TrackOptions = {
78
+ /**
79
+ * A number the event measures, such as an amount of money, a count or a duration. A value that
80
+ * is not a finite number is left out and the event is still reported.
81
+ */
82
+ value?: number; /** Details of the event. */
83
+ details?: TrackedEventDetails;
84
+ };
85
+ /**
86
+ * An event the code under test tracked, as a test client recorded it.
87
+ */
88
+ type TrackedEvent = {
89
+ /** The name the event was tracked with. */name: string; /** The context the event was tracked for, if any. */
90
+ context?: ConfigDirectorContext; /** The value the event was tracked with, when it is a finite number. */
91
+ value?: number; /** The details the event was tracked with, when they are within the limits. */
92
+ details?: TrackedEventDetails;
93
+ };
46
94
  /**
47
95
  * The context to be sent to ConfigDirector: the user or other entity, such as a device or an
48
96
  * organization, that configs are evaluated for. This context will be used for targeting rules
@@ -371,8 +419,8 @@ interface ConfigDirectorClient extends EventProvider<ClientEvents> {
371
419
  getValue<T extends ConfigValueType>(configKey: string, defaultValue: T): T;
372
420
  /**
373
421
  * Evaluates a config as {@link getValue} does and returns the evaluation: the value, the reason it
374
- * was served and its value ID. Like every read, it fires `configEvaluated` and is counted in
375
- * telemetry.
422
+ * was served, its value ID and its variation. Like every read, it fires `configEvaluated` and is
423
+ * counted in telemetry.
376
424
  *
377
425
  * @returns The evaluation, whose `value` is what {@link getValue} returns
378
426
  * @param configKey The config key to evaluate
@@ -404,6 +452,20 @@ interface ConfigDirectorClient extends EventProvider<ClientEvents> {
404
452
  * Removes all subscribers from all config keys
405
453
  */
406
454
  unwatchAll(): void;
455
+ /**
456
+ * Reports to ConfigDirector that something happened for the current context, such as a completed
457
+ * checkout, so it can be counted. The event is sent with the next telemetry batch. `track` never
458
+ * throws, and does nothing in `offline` mode.
459
+ *
460
+ * An event counts for an experiment only when the current context has an `id`, the one the
461
+ * experiment's config was evaluated for. Before the client has a context, or for a context
462
+ * without an `id`, the event is still reported.
463
+ *
464
+ * @param eventName The name of the event, 1 to 150 characters. An event with any other name is
465
+ * not reported and a warning is logged.
466
+ * @param options The event's {@link TrackOptions.value} and {@link TrackOptions.details} (optional)
467
+ */
468
+ track(eventName: string, options?: TrackOptions): void;
407
469
  /**
408
470
  * Pauses the network connection without clearing event handlers, watch handlers, or config
409
471
  * state. Intended for mobile environments where the OS may kill background connections (e.g.
@@ -441,5 +503,5 @@ declare class ConfigDirectorInitializationError extends Error {
441
503
  constructor(message: string);
442
504
  }
443
505
  //#endregion
444
- export { ConfigDirectorLoggingLevel as _, CachingProvider as a, EvaluationReason as b, OfflineClientOptions as c, NativeJsonValue as d, NativeValue as f, ConfigDirectorLogger as g, ConfigDirectorLogMessageDecorator as h, CachingOptions as i, OfflineValue as l, ConfigDirectorContext as m, ConfigDirectorInitializationError as n, ConfigDirectorClient as o, NativeValues as p, ConfigDirectorValidationError as r, ConfigDirectorClientOptions as s, ConfigDirectorConnectionError as t, OfflineValues as u, ConfigEvaluation as v, ConfigValueType as y };
445
- //# sourceMappingURL=errors-CkIP6urQ.d.mts.map
506
+ export { TrackedEventDetailValue as C, TrackedEvent as S, Variation as T, ConfigDirectorLoggingLevel as _, CachingProvider as a, EvaluationReason as b, OfflineClientOptions as c, NativeJsonValue as d, NativeValue as f, ConfigDirectorLogger as g, ConfigDirectorLogMessageDecorator as h, CachingOptions as i, OfflineValue as l, ConfigDirectorContext as m, ConfigDirectorInitializationError as n, ConfigDirectorClient as o, NativeValues as p, ConfigDirectorValidationError as r, ConfigDirectorClientOptions as s, ConfigDirectorConnectionError as t, OfflineValues as u, ConfigEvaluation as v, TrackedEventDetails as w, TrackOptions as x, ConfigValueType as y };
507
+ //# sourceMappingURL=errors-CV6G7vPq.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors-CV6G7vPq.d.mts","names":[],"sources":["../../js-client-core/src/Emitter.ts","../../shared/src/types.ts","../../shared/src/native-values.ts","../../js-client-core/src/types.ts","../../shared/src/errors.ts"],"mappings":";KAAK,SAAA;AAAA,KACA,YAAA,GAAe,MAAA,CAAO,SAAA;AAAA,KAEtB,OAAA,uBAA8B,YAAA,qBAAiC,aAAA,KAClE,OAAA,EAAS,aAAA,CAAc,IAAA;AAAA,UAGR,aAAA,uBAAoC,YAAA;EACnD,EAAA,qBAAuB,aAAA,EAAe,IAAA,EAAM,KAAA,EAAO,OAAA,EAAS,OAAA,CAAQ,aAAA,EAAe,KAAA;EACnF,GAAA,qBAAwB,aAAA,EAAe,IAAA,EAAM,KAAA,EAAO,OAAA,GAAU,OAAA,CAAQ,aAAA,EAAe,KAAA;EACrF,KAAA;AAAA;;;KCEU,kBAAA;EAAA,CAAwB,GAAA;AAAA;AAAA,KAExB,eAAA,wCAAuD,kBAAA;AAAA,KAkBvD,0BAAA;AAAA,UAEK,oBAAA;EACf,KAAA,CAAM,OAAA,aAAoB,IAAA;EAE1B,IAAA,CAAK,OAAA,aAAoB,IAAA;EAEzB,IAAA,CAAK,OAAA,aAAoB,IAAA;EAEzB,KAAA,CAAM,OAAA,aAAoB,IAAA;AAAA;AAAA,UAGX,iCAAA;EACf,eAAA,CAAgB,OAAA;AAAA;;;;;;;;;;;KAaN,gBAAA;;;;KAeA,SAAA;EDjEP,gGCmEH,EAAA,UDnE4C;ECqE5C,IAAA;AAAA;;;;KAMU,gBAAA,WAA2B,eAAA,GAAkB,eAAA;ED1EnD,yCC4EJ,GAAA,UD5E6C;EC8E7C,KAAA,EAAO,CAAA,ED9EuD;ECgF9D,OAAA;EDhFqF;;;;ECqFrF,SAAA,GAAY,SAAA;EAEZ,cAAA;EAEA,MAAA,EAAQ,gBAAA,EAtFoB;EAwF5B,OAAA,GAAU,qBAAA;AAAA;;AAtFZ;;;KA6FY,uBAAA,+BAIR,uBAAA;EAAA,CACG,GAAA,WAAc,uBAAA;AAAA;;;;;KAMT,mBAAA;EAAA,CAAyB,GAAA,WAAc,uBAAA;AAAA;;;;KAKvC,YAAA;EAtFV;;;;EA2FA,KAAA,WAzFyB;EA2FzB,OAAA,GAAU,mBAAA;AAAA;;;;KAMA,YAAA;EA5FsC,2CA8FhD,IAAA,UA7FA;EA+FA,OAAA,GAAU,qBAAA,EAlFA;EAoFV,KAAA;EAEA,OAAA,GAAU,mBAAA;AAAA;AAvEZ;;;;;AAAA,KA+EY,qBAAA;EArEgB;;;;;;;;;;EAgF1B,EAAA;EAhFqC;;;;;;;;;;;EA6FrC,IAAA;EA5EU;;;AAOZ;EA2EE,IAAA;;;;;EAMA,MAAA;IAAA,CAAY,GAAA;EAAA;EAtEF;;;;;AAKZ;;EA0EE,SAAA;AAAA;;;;;KAOU,yBAAA;EACV,UAAA;EACA,OAAA;AAAA;AAAA,KAGU,cAAA;;;KC9MA,eAAA,sCAAqD,eAAA;EAAA,CAAuB,GAAA,WAAc,eAAA;AAAA;AAAA,KAE1F,WAAA,+BAA0C,eAAA;EAAA,CAAuB,GAAA,WAAc,eAAA;AAAA;AAAA,KAE/E,YAAA,GAAe,MAAA,SAAe,WAAA;;;;;AFA1C;;;KG0CY,eAAA;EHzCa;;;EG6CvB,IAAA,gCAAoC,OAAA;EH7CwB;;;EGiD5D,KAAA,CAAM,KAAA,kBAAuB,OAAA;EHhDwD;;;EGoDrF,MAAA,WAAiB,OAAA;EHtDY;;;;EG2D7B,SAAA;AAAA;;;;;KAOU,cAAA;EHhEV;;;EGoEA,OAAA;EHpEuC;;;;EGyEvC,QAAA,GAAW,eAAA;AAAA;;;;;AFlDb;KEwEY,YAAA,GAAe,WAAA;;;;AFtE3B;KE4EY,aAAA,GAAgB,YAAA;;;;KAKhB,iBAAA;EFhFgB;;;;;;;;;;;;EE6F1B,IAAA,GAAO,cAAA;EFpFyC;;;;AAclD;;EE6EE,MAAA,GAAS,aAAA;EF7EiB;;AAe5B;;;;;EEsEE,eAAA;EF5D0B;;;;;;;EEoE1B,OAAA;EFnD+B;;;;;EEyD/B,GAAA;AAAA;;;;KAMU,2BAAA;EFnEV;;;EEuEA,QAAA,GAAW,yBAAA;EFnED;;;EEuEV,UAAA,GAAa,iBAAA;EFhEoB;;;;;EEsEjC,OAAA,GAAU,cAAA;EFjEgC;;AAM5C;;;;;AAKA;;;;;;EEoEE,MAAA,GAAS,oBAAA;EF7DoB;;AAM/B;;;;;;;;;;;;AAgBA;EEwDE,KAAA,GAAQ,WAAA;AAAA;;;;KAME,oBAAA,GAAuB,2BAAA;EACjC,UAAA,EAAY,iBAAA;IAAsB,IAAA;EAAA;AAAA;AAAA,KAGxB,WAAA;EACV,WAAA,GAAc,WAAA,kBAA6B,WAAA;EAC3C,cAAA,GAAiB,WAAA,qBAAgC,WAAA;EACjD,cAAA,GAAiB,WAAA,qBAAgC,WAAA;EACjD,eAAA,GAAkB,WAAA,sBAAiC,WAAA;EACnD,eAAA,GAAkB,WAAA,sBAAiC,WAAA;EACnD,kBAAA,GAAqB,WAAA,yBAAoC,WAAA;AAAA;AAAA,KAG/C,mBAAA;AAAA,KAEA,WAAA,sBAAiC,YAAA,KAAiB,OAAA,EAAS,YAAA,CAAa,MAAA;AAAA,KAExE,YAAA;EACV,cAAA;IAAkB,IAAA;IAAgB,WAAA;EAAA;EAClC,WAAA;IAAe,MAAA,EAAQ,mBAAA;EAAA;EACvB,cAAA;IAAkB,OAAA,EAAS,qBAAA;EAAA;EAC3B,eAAA;IAAmB,UAAA,EAAY,gBAAA;EAAA;EAC/B,eAAA;IAAmB,KAAA,EAAO,KAAA;EAAA;EAC1B,kBAAA,EAAoB,MAAA;AAAA;AAAA,KAGV,YAAA,WAAuB,eAAA,KAAoB,OAAA,EAAS,CAAA;;;ADzOhE;;;;;;;UCoPiB,oBAAA,SAA6B,aAAA,CAAc,YAAA;EA1MhD;;;;;;;;;;;;;;;;EA2NV,UAAA,CAAW,OAAA,GAAU,qBAAA,GAAwB,OAAA;EA1MpC;AAOX;;;;;;;;EA8ME,aAAA,CAAc,OAAA,EAAS,qBAAA,GAAwB,OAAA;EA/KrC;;;;;AAMZ;;;;EANY,IA0LN,OAAA,IAAW,qBAAA;EA/KL;;;;;;EAAA,IAuLN,OAAA;EAnKK;;;;;;AA4BX;EA5BW,IA4KL,cAAA;;;;;;;;;;EAWJ,QAAA,WAAmB,eAAA,EAAiB,SAAA,UAAmB,YAAA,EAAc,CAAA,GAAI,CAAA;EAnJzE;;;;;;;;;EA8JA,QAAA,WAAmB,eAAA,EAAiB,SAAA,UAAmB,YAAA,EAAc,CAAA,GAAI,gBAAA,CAAiB,CAAA;EAnHhF;;;;;;;;;;AAIZ;EA4HE,KAAA,WAAgB,eAAA,EAAiB,SAAA,UAAmB,YAAA,EAAc,CAAA,EAAG,QAAA,EAAU,YAAA,CAAa,CAAA;;;;;;;;;EAU5F,OAAA,WAAkB,eAAA,EAAiB,SAAA,UAAmB,QAAA,GAAW,YAAA,CAAa,CAAA;EAjI5D;;;EAsIlB,UAAA;EArIoE;;;;;;;;;;;;;EAoJpE,KAAA,CAAM,SAAA,UAAmB,OAAA,GAAU,YAAA;EArJnC;;;;;;;EA8JA,YAAA;EA1JU;;;;EAgKV,aAAA,IAAiB,OAAA;EA9JP;;;;;;EAsKV,OAAA;AAAA;;;cC3YW,6BAAA,SAAsC,KAAA;EAAA,SACxB,IAAA;EAAA,SACT,MAAA;cAEJ,OAAA,UAAiB,MAAA;AAAA;AAAA,cAQlB,6BAAA,SAAsC,KAAA;EAAA,SACxB,IAAA;cAEb,OAAA;AAAA;AAAA,cAOD,iCAAA,SAA0C,KAAA;EAAA,SAC5B,IAAA;cAEb,OAAA;AAAA"}
@@ -25,24 +25,72 @@ interface ConfigDirectorLogMessageDecorator {
25
25
  }
26
26
  /**
27
27
  * Why an evaluation returned the value it did. `found-match` returns a value from ConfigDirector,
28
- * and `cached` a value kept on the device while a client SDK waits for live values. `value-missing`
28
+ * and `cached` a value kept on the device while a client SDK waits for live values.
29
+ * `rollout-skipped-no-identifier` returns the default targeting rule value: a server SDK skipped a
30
+ * percentage rollout because the context has no `id` to place it in a share. `value-missing`
29
31
  * returns the in-code default value because the config has no value. Every other reason returns the
30
32
  * in-code default value because of an error: the config does not exist (`config-state-missing`), no
31
33
  * values have arrived yet (`client-not-ready`), or the value cannot be read as the type of the in-code
32
34
  * default value.
33
35
  */
34
- type EvaluationReason = "found-match" | "config-state-missing" | "client-not-ready" | "type-mismatch" | "value-missing" | "invalid-number" | "invalid-json" | "invalid-boolean" | "cached";
36
+ type EvaluationReason = "found-match" | "rollout-skipped-no-identifier" | "config-state-missing" | "client-not-ready" | "type-mismatch" | "value-missing" | "invalid-number" | "invalid-json" | "invalid-boolean" | "cached";
37
+ /**
38
+ * One of the values a config can serve, such as the control or a treatment of an experiment.
39
+ */
40
+ type Variation = {
41
+ /** The ID ConfigDirector assigned to the variation, which stays the same when it is renamed. */id: string; /** The variation's name, when it has one. */
42
+ name?: string;
43
+ };
35
44
  /**
36
45
  * One evaluation of a config: the value it returned, why, and the context it was evaluated for.
37
46
  */
38
47
  type ConfigEvaluation<T extends ConfigValueType = ConfigValueType> = {
39
48
  /** The config key that was evaluated. */key: string; /** The value returned, which is the in-code default value when {@link isDefaultValue} is `true`. */
40
49
  value: T; /** The ID ConfigDirector assigned to the value returned, when ConfigDirector sent one with it. */
41
- valueId?: string; /** Whether the evaluation returned the in-code default value. */
50
+ valueId?: string;
51
+ /**
52
+ * The variation that was served. It is `undefined` when the config has no variations or the
53
+ * in-code default value is returned.
54
+ */
55
+ variation?: Variation; /** Whether the evaluation returned the in-code default value. */
42
56
  isDefaultValue: boolean; /** Why the evaluation returned this value. */
43
57
  reason: EvaluationReason; /** The context the config was evaluated for, if any. */
44
58
  context?: ConfigDirectorContext;
45
59
  };
60
+ /**
61
+ * A value in the details of a tracked event: a string, a number, a boolean, or an array or object
62
+ * of such values.
63
+ */
64
+ type TrackedEventDetailValue = string | number | boolean | TrackedEventDetailValue[] | {
65
+ [key: string]: TrackedEventDetailValue;
66
+ };
67
+ /**
68
+ * Details of a tracked event, such as the plan a customer chose. Details with more than 20
69
+ * top-level keys, or larger than 1 KB as JSON, are left out and the event is still reported.
70
+ */
71
+ type TrackedEventDetails = {
72
+ [key: string]: TrackedEventDetailValue;
73
+ };
74
+ /**
75
+ * What a tracked event carries besides its name.
76
+ */
77
+ type TrackOptions = {
78
+ /**
79
+ * A number the event measures, such as an amount of money, a count or a duration. A value that
80
+ * is not a finite number is left out and the event is still reported.
81
+ */
82
+ value?: number; /** Details of the event. */
83
+ details?: TrackedEventDetails;
84
+ };
85
+ /**
86
+ * An event the code under test tracked, as a test client recorded it.
87
+ */
88
+ type TrackedEvent = {
89
+ /** The name the event was tracked with. */name: string; /** The context the event was tracked for, if any. */
90
+ context?: ConfigDirectorContext; /** The value the event was tracked with, when it is a finite number. */
91
+ value?: number; /** The details the event was tracked with, when they are within the limits. */
92
+ details?: TrackedEventDetails;
93
+ };
46
94
  /**
47
95
  * The context to be sent to ConfigDirector: the user or other entity, such as a device or an
48
96
  * organization, that configs are evaluated for. This context will be used for targeting rules
@@ -371,8 +419,8 @@ interface ConfigDirectorClient extends EventProvider<ClientEvents> {
371
419
  getValue<T extends ConfigValueType>(configKey: string, defaultValue: T): T;
372
420
  /**
373
421
  * Evaluates a config as {@link getValue} does and returns the evaluation: the value, the reason it
374
- * was served and its value ID. Like every read, it fires `configEvaluated` and is counted in
375
- * telemetry.
422
+ * was served, its value ID and its variation. Like every read, it fires `configEvaluated` and is
423
+ * counted in telemetry.
376
424
  *
377
425
  * @returns The evaluation, whose `value` is what {@link getValue} returns
378
426
  * @param configKey The config key to evaluate
@@ -404,6 +452,20 @@ interface ConfigDirectorClient extends EventProvider<ClientEvents> {
404
452
  * Removes all subscribers from all config keys
405
453
  */
406
454
  unwatchAll(): void;
455
+ /**
456
+ * Reports to ConfigDirector that something happened for the current context, such as a completed
457
+ * checkout, so it can be counted. The event is sent with the next telemetry batch. `track` never
458
+ * throws, and does nothing in `offline` mode.
459
+ *
460
+ * An event counts for an experiment only when the current context has an `id`, the one the
461
+ * experiment's config was evaluated for. Before the client has a context, or for a context
462
+ * without an `id`, the event is still reported.
463
+ *
464
+ * @param eventName The name of the event, 1 to 150 characters. An event with any other name is
465
+ * not reported and a warning is logged.
466
+ * @param options The event's {@link TrackOptions.value} and {@link TrackOptions.details} (optional)
467
+ */
468
+ track(eventName: string, options?: TrackOptions): void;
407
469
  /**
408
470
  * Pauses the network connection without clearing event handlers, watch handlers, or config
409
471
  * state. Intended for mobile environments where the OS may kill background connections (e.g.
@@ -441,5 +503,5 @@ declare class ConfigDirectorInitializationError extends Error {
441
503
  constructor(message: string);
442
504
  }
443
505
  //#endregion
444
- export { ConfigDirectorLoggingLevel as _, CachingProvider as a, EvaluationReason as b, OfflineClientOptions as c, NativeJsonValue as d, NativeValue as f, ConfigDirectorLogger as g, ConfigDirectorLogMessageDecorator as h, CachingOptions as i, OfflineValue as l, ConfigDirectorContext as m, ConfigDirectorInitializationError as n, ConfigDirectorClient as o, NativeValues as p, ConfigDirectorValidationError as r, ConfigDirectorClientOptions as s, ConfigDirectorConnectionError as t, OfflineValues as u, ConfigEvaluation as v, ConfigValueType as y };
445
- //# sourceMappingURL=errors-BUWbQes2.d.cts.map
506
+ export { TrackedEventDetailValue as C, TrackedEvent as S, Variation as T, ConfigDirectorLoggingLevel as _, CachingProvider as a, EvaluationReason as b, OfflineClientOptions as c, NativeJsonValue as d, NativeValue as f, ConfigDirectorLogger as g, ConfigDirectorLogMessageDecorator as h, CachingOptions as i, OfflineValue as l, ConfigDirectorContext as m, ConfigDirectorInitializationError as n, ConfigDirectorClient as o, NativeValues as p, ConfigDirectorValidationError as r, ConfigDirectorClientOptions as s, ConfigDirectorConnectionError as t, OfflineValues as u, ConfigEvaluation as v, TrackedEventDetails as w, TrackOptions as x, ConfigValueType as y };
507
+ //# sourceMappingURL=errors-CpjOLax4.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors-CpjOLax4.d.cts","names":[],"sources":["../../js-client-core/src/Emitter.ts","../../shared/src/types.ts","../../shared/src/native-values.ts","../../js-client-core/src/types.ts","../../shared/src/errors.ts"],"mappings":";KAAK,SAAA;AAAA,KACA,YAAA,GAAe,MAAA,CAAO,SAAA;AAAA,KAEtB,OAAA,uBAA8B,YAAA,qBAAiC,aAAA,KAClE,OAAA,EAAS,aAAA,CAAc,IAAA;AAAA,UAGR,aAAA,uBAAoC,YAAA;EACnD,EAAA,qBAAuB,aAAA,EAAe,IAAA,EAAM,KAAA,EAAO,OAAA,EAAS,OAAA,CAAQ,aAAA,EAAe,KAAA;EACnF,GAAA,qBAAwB,aAAA,EAAe,IAAA,EAAM,KAAA,EAAO,OAAA,GAAU,OAAA,CAAQ,aAAA,EAAe,KAAA;EACrF,KAAA;AAAA;;;KCEU,kBAAA;EAAA,CAAwB,GAAA;AAAA;AAAA,KAExB,eAAA,wCAAuD,kBAAA;AAAA,KAkBvD,0BAAA;AAAA,UAEK,oBAAA;EACf,KAAA,CAAM,OAAA,aAAoB,IAAA;EAE1B,IAAA,CAAK,OAAA,aAAoB,IAAA;EAEzB,IAAA,CAAK,OAAA,aAAoB,IAAA;EAEzB,KAAA,CAAM,OAAA,aAAoB,IAAA;AAAA;AAAA,UAGX,iCAAA;EACf,eAAA,CAAgB,OAAA;AAAA;;;;;;;;;;;KAaN,gBAAA;;;;KAeA,SAAA;EDjEP,gGCmEH,EAAA,UDnE4C;ECqE5C,IAAA;AAAA;;;;KAMU,gBAAA,WAA2B,eAAA,GAAkB,eAAA;ED1EnD,yCC4EJ,GAAA,UD5E6C;EC8E7C,KAAA,EAAO,CAAA,ED9EuD;ECgF9D,OAAA;EDhFqF;;;;ECqFrF,SAAA,GAAY,SAAA;EAEZ,cAAA;EAEA,MAAA,EAAQ,gBAAA,EAtFoB;EAwF5B,OAAA,GAAU,qBAAA;AAAA;;AAtFZ;;;KA6FY,uBAAA,+BAIR,uBAAA;EAAA,CACG,GAAA,WAAc,uBAAA;AAAA;;;;;KAMT,mBAAA;EAAA,CAAyB,GAAA,WAAc,uBAAA;AAAA;;;;KAKvC,YAAA;EAtFV;;;;EA2FA,KAAA,WAzFyB;EA2FzB,OAAA,GAAU,mBAAA;AAAA;;;;KAMA,YAAA;EA5FsC,2CA8FhD,IAAA,UA7FA;EA+FA,OAAA,GAAU,qBAAA,EAlFA;EAoFV,KAAA;EAEA,OAAA,GAAU,mBAAA;AAAA;AAvEZ;;;;;AAAA,KA+EY,qBAAA;EArEgB;;;;;;;;;;EAgF1B,EAAA;EAhFqC;;;;;;;;;;;EA6FrC,IAAA;EA5EU;;;AAOZ;EA2EE,IAAA;;;;;EAMA,MAAA;IAAA,CAAY,GAAA;EAAA;EAtEF;;;;;AAKZ;;EA0EE,SAAA;AAAA;;;;;KAOU,yBAAA;EACV,UAAA;EACA,OAAA;AAAA;AAAA,KAGU,cAAA;;;KC9MA,eAAA,sCAAqD,eAAA;EAAA,CAAuB,GAAA,WAAc,eAAA;AAAA;AAAA,KAE1F,WAAA,+BAA0C,eAAA;EAAA,CAAuB,GAAA,WAAc,eAAA;AAAA;AAAA,KAE/E,YAAA,GAAe,MAAA,SAAe,WAAA;;;;;AFA1C;;;KG0CY,eAAA;EHzCa;;;EG6CvB,IAAA,gCAAoC,OAAA;EH7CwB;;;EGiD5D,KAAA,CAAM,KAAA,kBAAuB,OAAA;EHhDwD;;;EGoDrF,MAAA,WAAiB,OAAA;EHtDY;;;;EG2D7B,SAAA;AAAA;;;;;KAOU,cAAA;EHhEV;;;EGoEA,OAAA;EHpEuC;;;;EGyEvC,QAAA,GAAW,eAAA;AAAA;;;;;AFlDb;KEwEY,YAAA,GAAe,WAAA;;;;AFtE3B;KE4EY,aAAA,GAAgB,YAAA;;;;KAKhB,iBAAA;EFhFgB;;;;;;;;;;;;EE6F1B,IAAA,GAAO,cAAA;EFpFyC;;;;AAclD;;EE6EE,MAAA,GAAS,aAAA;EF7EiB;;AAe5B;;;;;EEsEE,eAAA;EF5D0B;;;;;;;EEoE1B,OAAA;EFnD+B;;;;;EEyD/B,GAAA;AAAA;;;;KAMU,2BAAA;EFnEV;;;EEuEA,QAAA,GAAW,yBAAA;EFnED;;;EEuEV,UAAA,GAAa,iBAAA;EFhEoB;;;;;EEsEjC,OAAA,GAAU,cAAA;EFjEgC;;AAM5C;;;;;AAKA;;;;;;EEoEE,MAAA,GAAS,oBAAA;EF7DoB;;AAM/B;;;;;;;;;;;;AAgBA;EEwDE,KAAA,GAAQ,WAAA;AAAA;;;;KAME,oBAAA,GAAuB,2BAAA;EACjC,UAAA,EAAY,iBAAA;IAAsB,IAAA;EAAA;AAAA;AAAA,KAGxB,WAAA;EACV,WAAA,GAAc,WAAA,kBAA6B,WAAA;EAC3C,cAAA,GAAiB,WAAA,qBAAgC,WAAA;EACjD,cAAA,GAAiB,WAAA,qBAAgC,WAAA;EACjD,eAAA,GAAkB,WAAA,sBAAiC,WAAA;EACnD,eAAA,GAAkB,WAAA,sBAAiC,WAAA;EACnD,kBAAA,GAAqB,WAAA,yBAAoC,WAAA;AAAA;AAAA,KAG/C,mBAAA;AAAA,KAEA,WAAA,sBAAiC,YAAA,KAAiB,OAAA,EAAS,YAAA,CAAa,MAAA;AAAA,KAExE,YAAA;EACV,cAAA;IAAkB,IAAA;IAAgB,WAAA;EAAA;EAClC,WAAA;IAAe,MAAA,EAAQ,mBAAA;EAAA;EACvB,cAAA;IAAkB,OAAA,EAAS,qBAAA;EAAA;EAC3B,eAAA;IAAmB,UAAA,EAAY,gBAAA;EAAA;EAC/B,eAAA;IAAmB,KAAA,EAAO,KAAA;EAAA;EAC1B,kBAAA,EAAoB,MAAA;AAAA;AAAA,KAGV,YAAA,WAAuB,eAAA,KAAoB,OAAA,EAAS,CAAA;;;ADzOhE;;;;;;;UCoPiB,oBAAA,SAA6B,aAAA,CAAc,YAAA;EA1MhD;;;;;;;;;;;;;;;;EA2NV,UAAA,CAAW,OAAA,GAAU,qBAAA,GAAwB,OAAA;EA1MpC;AAOX;;;;;;;;EA8ME,aAAA,CAAc,OAAA,EAAS,qBAAA,GAAwB,OAAA;EA/KrC;;;;;AAMZ;;;;EANY,IA0LN,OAAA,IAAW,qBAAA;EA/KL;;;;;;EAAA,IAuLN,OAAA;EAnKK;;;;;;AA4BX;EA5BW,IA4KL,cAAA;;;;;;;;;;EAWJ,QAAA,WAAmB,eAAA,EAAiB,SAAA,UAAmB,YAAA,EAAc,CAAA,GAAI,CAAA;EAnJzE;;;;;;;;;EA8JA,QAAA,WAAmB,eAAA,EAAiB,SAAA,UAAmB,YAAA,EAAc,CAAA,GAAI,gBAAA,CAAiB,CAAA;EAnHhF;;;;;;;;;;AAIZ;EA4HE,KAAA,WAAgB,eAAA,EAAiB,SAAA,UAAmB,YAAA,EAAc,CAAA,EAAG,QAAA,EAAU,YAAA,CAAa,CAAA;;;;;;;;;EAU5F,OAAA,WAAkB,eAAA,EAAiB,SAAA,UAAmB,QAAA,GAAW,YAAA,CAAa,CAAA;EAjI5D;;;EAsIlB,UAAA;EArIoE;;;;;;;;;;;;;EAoJpE,KAAA,CAAM,SAAA,UAAmB,OAAA,GAAU,YAAA;EArJnC;;;;;;;EA8JA,YAAA;EA1JU;;;;EAgKV,aAAA,IAAiB,OAAA;EA9JP;;;;;;EAsKV,OAAA;AAAA;;;cC3YW,6BAAA,SAAsC,KAAA;EAAA,SACxB,IAAA;EAAA,SACT,MAAA;cAEJ,OAAA,UAAiB,MAAA;AAAA;AAAA,cAQlB,6BAAA,SAAsC,KAAA;EAAA,SACxB,IAAA;cAEb,OAAA;AAAA;AAAA,cAOD,iCAAA,SAA0C,KAAA;EAAA,SAC5B,IAAA;cAEb,OAAA;AAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@configdirector/client-sdk",
3
- "version": "1.10.1",
3
+ "version": "1.11.1",
4
4
  "description": "Javascript client SDK for ConfigDirector. ConfigDirector is a remote configuration and feature flag service.",
5
5
  "license": "MIT",
6
6
  "author": "ConfigDirector",
@@ -1,6 +0,0 @@
1
- var e=class e extends Error{constructor(t,n){super(t),this.name=`ConfigDirectorConnectionError`,this.status=n,Object.setPrototypeOf(this,e.prototype)}},t=class e extends Error{constructor(t){super(t),this.name=`ConfigDirectorValidationError`,Object.setPrototypeOf(this,e.prototype)}},n=class e extends Error{constructor(t){super(t),this.name=`ConfigDirectorInitializationError`,Object.setPrototypeOf(this,e.prototype)}};function r(e){"@babel/helpers - typeof";return r=typeof Symbol==`function`&&typeof Symbol.iterator==`symbol`?function(e){return typeof e}:function(e){return e&&typeof Symbol==`function`&&e.constructor===Symbol&&e!==Symbol.prototype?`symbol`:typeof e},r(e)}function i(e,t){if(r(e)!=`object`||!e)return e;var n=e[Symbol.toPrimitive];if(n!==void 0){var i=n.call(e,t||`default`);if(r(i)!=`object`)return i;throw TypeError(`@@toPrimitive must return a primitive value.`)}return(t===`string`?String:Number)(e)}function a(e){var t=i(e,`string`);return r(t)==`symbol`?t:t+``}function o(e,t,n){return(t=a(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function s(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter(function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable})),n.push.apply(n,r)}return n}function c(e){for(var t=1;t<arguments.length;t++){var n=arguments[t]==null?{}:arguments[t];t%2?s(Object(n),!0).forEach(function(t){o(e,t,n[t])}):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):s(Object(n)).forEach(function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))})}return e}var l=class{constructor(){this.handlerMap=new Map}on(e,t){let n=this.handlerMap.get(e);n?n.push(t):this.handlerMap.set(e,[t])}once(e,t){let n=this;function r(i){n.off(e,r),t.apply(n,i)}this.on(e,r)}off(e,t){let n=this.handlerMap.get(e);if(n)if(t){let e=n.indexOf(t);e>=0&&n.splice(e,1)}else this.handlerMap.set(e,[])}clear(){this.handlerMap.clear()}emit(e,t){let n=this.handlerMap.get(e);n&&n.slice().map(e=>e(t))}},u=class e extends Error{constructor(t){super(t),this.name=`StreamClosedError`,Object.setPrototypeOf(this,e.prototype)}},d=class e extends Error{constructor(t){super(t),this.name=`MissingResponseBodyError`,Object.setPrototypeOf(this,e.prototype)}},f=class e extends Error{constructor(t){super(t),this.name=`InvalidOptionError`,Object.setPrototypeOf(this,e.prototype)}},p=class e extends Error{constructor(t){super(t),this.name=`ValueOutOfRangeError`,Object.setPrototypeOf(this,e.prototype)}},m=class{constructor(e){var t;this.isFirstChunk=!0,this.bufferedInput=``,this.currentEvent={data:``},this.currentEvent={data:``},this.onEvent=(t=e.onEvent)==null?(()=>{}):t,this.onRetry=e.onRetry,this.onComment=e.onComment}parse(e){let t=e;this.isFirstChunk&&(this.isFirstChunk=!1,t.startsWith(``)?t=t.slice(1):t.startsWith(``)&&(t=t.slice(3)));let n=this.scanLines(this.bufferedInput+t);for(let e of n)this.dispatchLine(e)}finish(){this.bufferedInput=``}scanLines(e){let t=[],n=0,r=0;for(;r<e.length;){let i=e[r];i===`\r`||i===`
2
- `?(t.push(e.slice(n,r)),i===`\r`&&e[r+1]===`
3
- `&&r++,r++,n=r):r++}return this.bufferedInput=e.slice(n),t}dispatchLine(e){if(e.startsWith(`:`)){var t;(t=this.onComment)==null||t.call(this,this.extractValue(e,1));return}if(e===``){this.emitEvent();return}this.applyField(this.parseField(e))}emitEvent(){let e=this.currentEvent.data.endsWith(`
4
- `)?this.currentEvent.data.slice(0,-1):this.currentEvent.data;e!==``&&this.onEvent(c(c({},this.currentEvent),{},{id:this.lastEventId,data:e})),this.currentEvent={data:``}}applyField(e){switch(e.field){case`event`:this.currentEvent.type=e.value;break;case`data`:this.currentEvent.data+=e.value+`
5
- `;break;case`id`:e.value.includes(`\0`)||(this.lastEventId=e.value);break;case`retry`:if(/^\d+$/.test(e.value)){var t;(t=this.onRetry)==null||t.call(this,Number.parseInt(e.value,10))}break;default:break}}parseField(e){let t=e.indexOf(`:`);return t===-1?{field:e,value:``}:{field:e.slice(0,t),value:this.extractValue(e,t+1)}}extractValue(e,t){return e[t]===` `?e.slice(t+1):e.slice(t)}};let h=function(e){return e.OPEN=`open`,e.CLOSED=`closed`,e.CONNECTING=`connecting`,e}({});var g=class{constructor(e){var t,n;this.DEFAULT_SHOULD_RECONNECT=()=>!0,this.DEFAULT_CALCULATE_RECONNECT_DELAY=()=>this.serverReconnectionTime,this.reconnectAttempt=0,this.abortController=new AbortController,this._readyState=h.CLOSED,this.serverReconnectionTime=2e3,this.url=e.url.toString(),this.lastEventId=e.lastEventId,this.headers=c({Accept:`text/event-stream`},e.headers);let r=e.body;this.body=typeof r==`function`?r:()=>r,this.requestOptions={method:(t=e.method)==null?`GET`:t,mode:e.mode,credentials:e.credentials,redirect:e.redirect,referrer:e.referrer,referrerPolicy:e.referrerPolicy},this._fetch=(n=e.fetch)==null?((e,t)=>fetch(e,t)):n,this._onError=this.resolveCallback(e.onError,()=>{},`onError`),this._onConnect=this.resolveCallback(e.onConnect,()=>{},`onConnect`),this._onDisconnect=this.resolveCallback(e.onDisconnect,()=>{},`onDisconnect`),this._onMessage=this.resolveCallback(e.onMessage,()=>{},`onMessage`),this._onComment=this.resolveCallback(e.onComment,()=>{},`onComment`),this._shouldReconnect=this.resolveCallback(e.shouldReconnect,this.DEFAULT_SHOULD_RECONNECT,`shouldReconnect`),this._calculateReconnectDelay=this.resolveCallback(e.calculateReconnectDelay,this.DEFAULT_CALCULATE_RECONNECT_DELAY,`calculateReconnectDelay`)}set onError(e){this._onError=this.resolveCallback(e,()=>{},`onError`)}set onMessage(e){this._onMessage=this.resolveCallback(e,()=>{},`onMessage`)}set onComment(e){this._onComment=this.resolveCallback(e,()=>{},`onComment`)}set onConnect(e){this._onConnect=this.resolveCallback(e,()=>{},`onConnect`)}set onDisconnect(e){this._onDisconnect=this.resolveCallback(e,()=>{},`onDisconnect`)}set shouldReconnect(e){this._shouldReconnect=this.resolveCallback(e,this.DEFAULT_SHOULD_RECONNECT,`shouldReconnect`)}set calculateReconnectDelay(e){this._calculateReconnectDelay=this.resolveCallback(e,this.DEFAULT_CALCULATE_RECONNECT_DELAY,`shouldReconnect`)}get readyState(){return this._readyState}connect(){this._readyState===h.CLOSED&&(this.reconnectAttempt=0,this.initiateConnection())}close(){clearTimeout(this.reconnectTimeout),this._readyState=h.CLOSED,this.abortController.abort()}initiateConnection(){this.abortController=new AbortController,this._readyState=h.CONNECTING,this._fetch(this.url,c(c({},this.requestOptions),{},{body:this.body(),headers:this.buildRequestHeaders(),signal:this.abortController.signal,cache:`no-store`})).then(e=>this.handleFetchResponse(e)).catch(e=>{if(e.name===`AbortError`||this.abortController.signal.aborted){this.close();return}this._onError(e),this.scheduleReconnect({error:e})})}async handleFetchResponse(e){var t=this;let{body:n,status:r}=e;if(r===204){t.disconnected();return}if(r>=400){t.scheduleReconnect({status:r});return}if(!n)throw new d(`The server response did not have a body`);t._readyState=h.OPEN,t._onConnect(),t.reconnectAttempt=0;let i=new m({onEvent:e=>{typeof e.id==`string`&&(t.lastEventId=e.id),t._onMessage(e)},onComment:e=>t._onComment(e),onRetry:e=>t.serverReconnectionTime=e});await t.readResponseStream(n,i),t.scheduleReconnect({status:r,error:new u(`The server response stream was closed`)})}async readResponseStream(e,t){let n=e.getReader(),r=new TextDecoder,i=!1;for(;!i;){let e=await n.read();e.value&&t.parse(r.decode(e.value,{stream:!0})),i=e.done}t.finish()}disconnected(){clearTimeout(this.reconnectTimeout),this._readyState=h.CLOSED,this._onDisconnect()}buildRequestHeaders(){let e=this.lastEventId?{"Last-Event-ID":this.lastEventId}:void 0;return c(c({},this.headers),e)}scheduleReconnect(e){if(this.abortController.signal.aborted)return;clearTimeout(this.reconnectTimeout),this.reconnectAttempt+=1;let t={attempt:this.reconnectAttempt,status:e.status,error:e.error,serverReconnectionTime:this.serverReconnectionTime};if(!this._shouldReconnect(t)){this.disconnected();return}this._readyState=h.CONNECTING;let n=this._calculateReconnectDelay(t);(!Number.isFinite(n)||n<1||n>1e3*60*60)&&(this._onError(new p(`The calculated reconnect delay is out of range: ${n}. Defaulting to ${this.serverReconnectionTime}`)),n=this.serverReconnectionTime),this.reconnectTimeout=setTimeout(()=>this.initiateConnection(),n)}resolveCallback(e,t,n){if(e==null)return t;if(typeof e!=`function`)throw new f(`${n} must be a function`);return e}};const _=e=>new g(e);var v=class{constructor(e){this.options=e,this.eventEmitter=new l,this.connectionGeneration=0,this.options=e,this.logger=e.logger,this.url=e.resolveUrl(`client/sse/v1`,e.baseUrl)}async connect(e,t){var n=this;let r=++n.connectionGeneration,i=await n.options.clientSession;if(r!==n.connectionGeneration)return n;n.eventSource&&n.close();let a=new Promise((t,r)=>{n.eventSource=_({url:n.url,method:`POST`,headers:{"Content-Type":`application/json`},fetch:n.options.fetch,body:JSON.stringify({givenContext:e,metaContext:n.options.metaContext,clientSdkKey:n.options.clientSdkKey,instanceId:i.instanceId,ephemeral:i.ephemeral}),onMessage:({data:e})=>{n.dispatchMessage(e)},onConnect:()=>{n.logger.debug(`[StreamingTransport] Connected`),t(n)},shouldReconnect:e=>{let t=!n.isStatusFatal(e.status);if(!t){let t=n.prepareFatalError(e.status,e.error);n.eventEmitter.emit(`connectionError`,t),r(t)}return t},calculateReconnectDelay:e=>{let t=n.options.connectionRetryDelay(e.attempt),r=`[StreamingTransport] Scheduling reconnect attempt #${e.attempt} in ${t}ms.`;return e.attempt<=5?n.logger.info(r):n.logger.warn(r),t},onError:e=>{n.logger.debug(`[StreamingTransport] Error: `,e)},onDisconnect:()=>{n.logger.debug(`[StreamingTransport] Disconnected`)}}),n.eventSource.connect()});return clearTimeout(n.timeoutTimer),n.timeoutTimer=void 0,Promise.race([a,new Promise(e=>{n.timeoutTimer=setTimeout(()=>e(n),t)})]).finally(()=>clearTimeout(n.timeoutTimer))}dispatchMessage(e){try{let t=JSON.parse(e);this.eventEmitter.emit(`configSetReceived`,t)}catch(e){this.logger.error(`[StreamingTransport] Error parsing and dispatching config data update: `,e)}}prepareFatalError(t,n){let r=t==null?0:t;return new e(`${`Connection failed with status: ${t==null?`unknown`:t}.`}${n?` Error: ${n}`:``}. This is an unrecoverable error, will not attempt to reconnect.`,r)}isStatusFatal(e){return!!e&&e>=400&&e<500&&e!=429}on(e,t){this.eventEmitter.on(e,t)}off(e,t){this.eventEmitter.off(e,t)}clear(){this.eventEmitter.clear()}close(){var e;this.connectionGeneration++,(e=this.eventSource)==null||e.close(),clearTimeout(this.timeoutTimer)}dispose(){this.close(),this.clear()}};const ee=(e,n)=>{if(e.trim().length==0)throw new t(`Invalid config key. The key of a value cannot be empty.`);return te(e,n)},te=(e,n)=>{switch(typeof n){case`boolean`:return{type:`boolean`,value:n?`true`:`false`};case`number`:return y(e,n);case`string`:return{type:`string`,value:n};case`object`:if(n!==null)return x(e,n,``),{type:`json`,value:JSON.stringify(n)}}throw new t(`Invalid value for '${e}': ${w(n)}. Use a boolean, a number, a string, a plain object, or an array.`)},y=(e,n)=>{if(!Number.isFinite(n))throw new t(`Invalid value for '${e}': ${w(n)} is not a finite number.`);if(Number.isInteger(n)){if(!Number.isSafeInteger(n))throw new t(`Invalid value for '${e}': ${n} is not a safe integer, so the SDK could not read it back exactly.`);return{type:`integer`,value:String(n)}}return{type:`float`,value:b(n)}},b=e=>{let t=String(e),n=t.indexOf(`e-`);if(n<0)return t;let r=t.startsWith(`-`)?`-`:``,[i=``,a=``]=t.slice(r.length,n).split(`.`),o=Number(t.slice(n+2))-i.length;return`${r}0.${`0`.repeat(o)}${i}${a}`},x=(e,t,n)=>{if(!(t===null||typeof t==`boolean`||typeof t==`string`)){if(typeof t==`number`){if(!Number.isFinite(t))throw S(e,n,`${w(t)} is not a finite number`);return}if(Array.isArray(t)){t.forEach((t,r)=>x(e,t,`${n}[${r}]`));return}if(C(t)){for(let[r,i]of Object.entries(t))x(e,i,n?`${n}.${r}`:r);return}throw S(e,n,`${w(t)} cannot be encoded as JSON`)}},S=(e,n,r)=>new t(`Invalid value for '${e}'${n?` at '${n}'`:``}: ${r}. JSON contents can hold booleans, finite numbers, strings, null, arrays, and plain objects.`),C=e=>{if(typeof e!=`object`||!e)return!1;let t=Object.getPrototypeOf(e);return t===Object.prototype||t===null},w=e=>{if(e===null)return`null`;if(typeof e==`function`)return`a function`;if(typeof e==`object`){var t,n;return`a ${(t=(n=e.constructor)==null?void 0:n.name)==null?`object`:t} instance`}return typeof e==`symbol`?`a symbol`:String(e)},T=(e,t,n,r)=>{let i=ee(t,n);return{id:e,key:t,type:i.type,value:i.value,valueId:r}},E={environmentId:`offline`,projectId:`offline`};var D=class{constructor(e){this.source=e,this.emitter=new l,this.on=(e,t)=>this.emitter.on(e,t),this.off=(e,t)=>this.emitter.off(e,t)}async connect(){var e=this;let t=O(e.source);return e.emitter.emit(`configSetReceived`,c(c({},E),{},{kind:`full`,configs:t})),e}clear(){this.emitter.clear()}close(){}dispose(){this.clear()}};const O=e=>{switch(e.kind){case`in-code-defaults`:return{};case`values`:return ne(e.values);case`rejected`:throw new n(e.message)}},ne=e=>{try{return Object.fromEntries(Object.entries(e).map(([e,t])=>[e,T(`offline:${e}`,e,t,void 0)]))}catch(e){throw e instanceof t?new n(`The offline values could not be loaded. ${e.message}`):e}},re=(e,n,r)=>{var i;if((n==null?void 0:n.mode)===`offline`)return{kind:`stay-offline`,source:ae(n)};let a=(i=n==null?void 0:n.mode)==null?`streaming`:i;if(!e||e.trim().length==0)throw new t(`No client SDK key was provided, the client cannot be instantiated without a valid client SDK key`);return(n==null?void 0:n.values)===void 0?{kind:`connect`,mode:a,clientSdkKey:e,baseUrl:ie(n==null?void 0:n.url,r)}:{kind:`stay-offline`,source:{kind:`rejected`,message:`The connection option 'values' applies only when the connection mode is 'offline', but the mode is '${a}'.`}}},ie=(e,n)=>{if(!e)return`https://client-sdk-api.configdirector.com`;try{return n(e)}catch(n){throw new t(`Invalid base URL '${e}'. Parsing failed: ${n}`)}},ae=e=>e.values===void 0?{kind:`in-code-defaults`}:{kind:`values`,values:e.values},k=e=>{let t=typeof e;if(t===`object`)try{var n,r;return(n=(r=e.constructor)==null?void 0:r.name)==null?t:n}catch(e){return t}else if(t===`function`)try{let n=e.name;return n?`function: ${n}`:t}catch(e){return t}return t},A=e=>e===`number`||e===`bigint`,oe=new Set([`boolean`,`integer`,`float`]),se=(e,t)=>{let n=e.value,r=k(t);if(n==null||n===``)return{parsedValue:t,parsedValueId:void 0,requestedType:r,usedDefault:!0,reason:`value-missing`};if(e.type===`json`)return F(n,t,r,e.valueId);if(typeof t==`string`)return oe.has(e.type)?{parsedValue:t,parsedValueId:void 0,requestedType:r,usedDefault:!0,reason:`type-mismatch`}:{parsedValue:n,parsedValueId:e.valueId,requestedType:r,usedDefault:!1,reason:`found-match`};if(typeof t==`boolean`&&(e.type===`boolean`||e.type===`string`||e.type===`enum`)){let i=ce(n),a=typeof i==`boolean`;return{parsedValue:a?i:t,parsedValueId:a?e.valueId:void 0,requestedType:r,usedDefault:!a,reason:a?`found-match`:`invalid-boolean`}}if(A(typeof t)&&e.type===`integer`){let i=j(n),a=typeof i==`number`;return{parsedValue:a?i:t,parsedValueId:a?e.valueId:void 0,requestedType:r,usedDefault:!a,reason:a?`found-match`:`invalid-number`}}if(A(typeof t)&&(e.type===`float`||e.type===`enum`||e.type===`string`)){let i=M(n),a=typeof i==`number`;return{parsedValue:a?i:t,parsedValueId:a?e.valueId:void 0,requestedType:r,usedDefault:!a,reason:a?`found-match`:`invalid-number`}}return{parsedValue:t,parsedValueId:void 0,requestedType:r,usedDefault:!0,reason:`type-mismatch`}},ce=e=>{if(!e)return;let t=e.toLowerCase();if(!(t!=`true`&&t!=`false`))return t===`true`},j=e=>{let t=N(e);return t==null?void 0:Math.trunc(t)},M=e=>N(e),N=e=>{if(!e||!P(e))return;let t=Number(e);if(!(isNaN(t)||!isFinite(t)))return t},P=e=>{for(let t of e)if(!(t>=`0`&&t<=`9`)&&!`+-.eE`.includes(t))return!1;return!0},F=(e,t,n,r)=>{if(typeof t==`string`)return{parsedValue:e,parsedValueId:r,requestedType:n,usedDefault:!1,reason:`found-match`};try{let i=JSON.parse(e);return I(i,t)?{parsedValue:i,parsedValueId:r,requestedType:n,usedDefault:!1,reason:`found-match`}:{parsedValue:t,parsedValueId:void 0,requestedType:n,usedDefault:!0,reason:`type-mismatch`}}catch(e){return{parsedValue:t,parsedValueId:void 0,requestedType:n,usedDefault:!0,reason:`invalid-json`}}},I=(e,t)=>e===null?!1:L(e)===L(t),L=e=>{if(Array.isArray(e))return`array`;let t=typeof e;return t===`bigint`?`number`:t},R={off:-1,error:0,warn:1,info:2,debug:3},z=()=>{let e={year:`numeric`,month:`2-digit`,day:`2-digit`,hour:`2-digit`,minute:`2-digit`,second:`2-digit`,timeZoneName:`short`};try{return new Intl.DateTimeFormat(void 0,c(c({},e),{},{fractionalSecondDigits:3}))}catch(t){return new Intl.DateTimeFormat(void 0,e)}};var B=class{constructor(e,t){this.level=e,this.decorator=t,this.level=e,this.decorator=t,this.dateFormatter=z()}debug(e,...t){this.log(console.debug,`debug`,e,...t)}info(e,...t){this.log(console.info,`info`,e,...t)}warn(e,...t){this.log(console.warn,`warn`,e,...t)}error(e,...t){this.log(console.error,`error`,e,...t)}log(e,t,n,...r){if(R[this.level]>=R[t]){var i;e(`[${this.dateFormatter.format(new Date)}] ${(i=this.decorator)==null?void 0:i.decorateMessage(n)}`,...r)}}},V=class{decorateMessage(e){return`[ConfigDirector:js-client-sdk] ${e}`}};const H=(e,t)=>new B(e==null?`warn`:e,t==null?new V:t),U={updateContext:async()=>{},evaluatedConfig:()=>{},recordInvalidContext:()=>{},close:async()=>{}},W=(e,t)=>new URL(e,t==null?void 0:t.toString()),G=(e,t)=>e===void 0?{seconds:t.defaultSeconds,warning:void 0}:e>=t.minimumSeconds?{seconds:e,warning:void 0}:{seconds:t.minimumSeconds,warning:`pollingInterval of ${e} seconds is below the minimum of ${t.minimumSeconds} seconds. Using ${t.minimumSeconds} seconds.`},le=()=>typeof crypto<`u`&&typeof crypto.randomUUID==`function`?crypto.randomUUID():`xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx`.replace(/[xy]/g,e=>{let t=Math.random()*16|0;return(e===`x`?t:t&3|8).toString(16)}),K=e=>{try{return e(globalThis)}catch(e){return}},ue=()=>K(e=>{var t;return(t=e.navigator)==null?void 0:t.userAgent}),de=()=>K(e=>{var t;return(t=e.location)==null?void 0:t.host}),q=()=>{try{var e;return(e=globalThis.localStorage)==null?void 0:e}catch(e){return}},J=`configdirector-sdk:instance-id`,Y=1e3,fe=/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/,X=(e,t)=>{let n=t;for(let t=0;t<e.length;t++)n^=e.charCodeAt(t),n=Math.imul(n,16777619);return n>>>0},Z=(e,t)=>{let n=`configdirector.instanceId.v1|${e}|${t}`,r=X(n,2166136261);return X(`${r}|${n}`,16777619).toString(16).padStart(8,`0`)+r.toString(16).padStart(8,`0`)},pe=e=>{if(!e||typeof e!=`object`)return!1;let{v:t,id:n,createdAt:r,checksum:i}=e;return t!==1||typeof n!=`string`||typeof i!=`string`||typeof r!=`number`||!Number.isInteger(r)||r<=0||!fe.test(n)?!1:i===Z(n,r)},me=async(e,t)=>{let n;try{n=await e.getItem(J)}catch(e){return t.debug(`[ConfigDirectorClient] Could not read the stored instance id, using an ephemeral one`,e),{outcome:`failed`}}if(typeof n!=`string`||n===``)return{outcome:`nothing usable`};let r;try{r=JSON.parse(n)}catch(e){return t.debug(`[ConfigDirectorClient] The stored instance id is not valid JSON, generating a new one`),{outcome:`nothing usable`}}return pe(r)?{outcome:`stored`,instanceId:r.id}:(t.debug(`[ConfigDirectorClient] The stored instance id failed validation, generating a new one`),{outcome:`nothing usable`})},he=async(e,t,n)=>{let r=Date.now(),i={v:1,id:t,createdAt:r,checksum:Z(t,r)};try{return await e.setItem(J,JSON.stringify(i)),!0}catch(e){return n.debug(`[ConfigDirectorClient] Could not persist the instance id, using it as an ephemeral one`,e),!1}},ge=async(e,t,n,r)=>{let i=await me(e,r);switch(i.outcome){case`stored`:return{instanceId:i.instanceId};case`failed`:return{instanceId:t,ephemeral:!0};case`nothing usable`:break}return n.passed?{instanceId:t,ephemeral:!0}:await he(e,t,r)?{instanceId:t}:{instanceId:t,ephemeral:!0}},_e=(e,t=q())=>{let n=le();if(!t)return e.debug(`[ConfigDirectorClient] No instance id storage is available, using an ephemeral instance id`),Promise.resolve({instanceId:n,ephemeral:!0});let r={passed:!1},i,a=new Promise(t=>{i=setTimeout(()=>{r.passed=!0,e.warn(`[ConfigDirectorClient] The instance id storage did not respond within ${Y}ms, using an ephemeral instance id`),t({instanceId:n,ephemeral:!0})},Y)});return Promise.race([ge(t,n,r,e),a]).finally(()=>clearTimeout(i))};var ve=class{constructor(){this.fatalError=!1}clearPollingInterval(){clearInterval(this.pollingInterval)}schedulePollingInterval(e){clearInterval(this.pollingInterval),!(this.pollingIntervalSeconds<=0)&&(this.pollingInterval=setInterval(e,this.pollingIntervalSeconds*1e3))}async handleNonOkResponse(t){var n=this;if(!t.ok)throw n.isStatusFatal(t.status)?(n.fatalError=!0,n.close(),n.prepareFatalResponseStatusError(t.status,await t.text())):new e(`Connection failed with status: ${t.status}`,t.status)}handleFetchError(t){throw this.isFetchErrorFatal(t)?(this.fatalError=!0,this.close(),new e(`Connection failed with fatal error: ${t}. This is an unrecoverable error, retry attempts will be ignored.`)):t instanceof SyntaxError?new e(`Failed to parse the response from the server: ${t}`):new e(`Connection failed with error: ${t}.`)}prepareFatalResponseStatusError(t,n){var r,i;let a=t==null?0:t;return new e(`${`Connection failed with status: ${t==null?`unknown`:t}`}${((r=n==null||(i=n.trim())==null?void 0:i.length)==null?0:r)>0?` (${n})`:``}. This is an unrecoverable error, retry attempts will be ignored.`,a)}isStatusFatal(e){return!!e&&e>=400&&e<500&&e!=429}isFetchErrorFatal(e){return(e==null?void 0:e.name)===`NotAllowedError`}get isConnected(){return this.pollingInterval!==void 0}close(){clearInterval(this.pollingInterval),this.pollingInterval=void 0}dispose(){this.close(),this.clear()}};const ye=async(e,t,n,r)=>{let i=new AbortController,a=setTimeout(()=>{r.debug(`[fetchWithTimeout] Reached timeout, aborting request`),i.abort()},e);try{let e=await fetch(typeof t==`string`||t instanceof Request?t:t.toString(),c(c({},n),{},{signal:i.signal}));return clearTimeout(a),e}catch(e){throw r.warn(`[fetchWithTimeout] Fetch error: `,e),clearTimeout(a),e}};var be=class extends ve{constructor(e){var t;super(),this.options=e,this.eventEmitter=new l,this.connectionGeneration=0,this.options=e,this.logger=e.logger,this.url=e.resolveUrl(`client/polling/v1`,e.baseUrl),this.pollingIntervalSeconds=(t=e.pollingInterval)==null?60:t}async connect(e,t){var n=this;n.endCurrentConnection();let r=n.connectionGeneration,i=await n.options.clientSession;if(r!==n.connectionGeneration)return n;try{await n.fetchConfigs(e,t,i)}finally{n.fatalError||n.schedulePollingInterval(()=>{n.fetchConfigs(e,t,i).catch(e=>{n.logger.error(`[PollingTransport] Error during polling:`,e)})})}return n}close(){this.endCurrentConnection(),super.close()}endCurrentConnection(){this.connectionGeneration++,this.clearPollingInterval(),this.lastUpdateTimestamp=void 0}async fetchConfigs(e,t,n){var r=this;if(r.fatalError){r.logger.warn(`[PollingTransport] There was a prior unrecoverable error. Ignoring attempt to reconnect.`);return}try{let i=await ye(t,r.url,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({givenContext:e,metaContext:r.options.metaContext,clientSdkKey:r.options.clientSdkKey,instanceId:n.instanceId,ephemeral:n.ephemeral,lastUpdateTimestamp:r.lastUpdateTimestamp})},r.logger);if(await r.handleNonOkResponse(i),i.status==200){let e=JSON.parse(await i.text());r.lastUpdateTimestamp=e.timestamp,r.eventEmitter.emit(`configSetReceived`,e)}}catch(e){try{r.handleFetchError(e)}catch(e){throw r.fatalError&&r.eventEmitter.emit(`connectionError`,e),e}}}on(e,t){this.eventEmitter.on(e,t)}off(e,t){this.eventEmitter.off(e,t)}clear(){this.eventEmitter.clear()}};const xe=e=>e>=`a`&&e<=`z`||e>=`0`&&e<=`9`||e===`-`||e===`_`,Se=e=>{if(e.length<1||e.length>64)return!1;for(let t of e)if(!xe(t))return!1;return!0},Ce=e=>e==null||typeof e==`string`&&Se(e),we=e=>{if(typeof e==`string`)return e;try{return String(e)}catch(t){return Object.prototype.toString.call(e)}},Te=(e,t)=>{let n=``,r=0;for(let i of e){if(r===t)break;n+=i,r+=1}return n},Ee=e=>{let t=e==null?void 0:e.kind;return Ce(t)?{outcome:`admitted`,context:e}:{outcome:`ignored`,kindSample:Te(we(t),128)}},De=e=>e>=55296&&e<=56319,Oe=e=>e>=56320&&e<=57343,Q=e=>{let t=0;for(let n=0;n<e.length;n++){let r=e.charCodeAt(n);r<=127?t+=1:r<=2047?t+=2:De(r)&&n+1<e.length&&Oe(e.charCodeAt(n+1))?(t+=4,n++):t+=3}return t},ke=`configdirector-sdk:cached-values:`,Ae=256*1024,je=(e,t,n,r)=>{var i;if(e.kind===`stay-offline`)return{kind:`no cache`,reason:`offline mode`};if((t==null?void 0:t.enabled)===!1)return{kind:`no cache`,reason:`turned off`};if(!n)return{kind:`no cache`,reason:`no SHA-256 available`};let a=n(e.clientSdkKey),o=(i=t==null?void 0:t.provider)==null?r==null?void 0:r(a):i;return o?{kind:`cache`,provider:o,clientSdkKeyDigest:a}:{kind:`no cache`,reason:`no provider available`}},$=(e,t)=>{var n;let r=(n=e==null?void 0:e.kind)==null?`user`:n;return(e==null?void 0:e.id)==null?{contextKind:r,anonymousInstanceId:t}:{contextKind:r,contextId:e.id}},Me=(e,t)=>e.contextKind===t.contextKind?`contextId`in e&&`contextId`in t?e.contextId===t.contextId:`anonymousInstanceId`in e&&`anonymousInstanceId`in t?e.anonymousInstanceId===t.anonymousInstanceId:!1:!1,Ne=(e,t,n)=>n?`live values already arrived`:Me(e.contextTag,t)?`adopt`:`context mismatch`,Pe=e=>{if(!e||typeof e!=`object`)return!1;let{contextKind:t,contextId:n,anonymousInstanceId:r}=e;return typeof t==`string`?typeof n==`string`||typeof r==`string`:!1},Fe=e=>!e||typeof e!=`object`||Array.isArray(e)?!1:Object.values(e).every(e=>e&&typeof e==`object`&&typeof e.id==`string`&&typeof e.key==`string`),Ie=(e,t)=>{if(!t||typeof t!=`object`)return!1;let n=t;return n.formatVersion===2&&n.clientSdkKeyDigest===e&&Pe(n.contextTag)&&typeof n.environmentId==`string`&&typeof n.projectId==`string`&&Fe(n.configs)&&typeof n.receivedAt==`number`},Le=e=>!!e&&typeof e==`object`&&e.formatVersion===1,Re=(e,t)=>{let n;try{n=JSON.parse(e)}catch(e){return{outcome:`unreadable`}}return Ie(t,n)?{outcome:`stored`,cachedValues:n}:Le(n)?{outcome:`first format`}:{outcome:`unreadable`}};var ze=class{constructor(e,t,n){this.provider=e,this.clientSdkKeyDigest=t,this.logger=n,this.warned=new Set,this.writing=!1}read(){return this.pendingRead!=null||(this.pendingRead=this.readEntry()),this.pendingRead}replace(e){this.queuedCachedValues=e,this.writeQueued()}async readEntry(){var e=this;let t;try{t=await e.provider.read()}catch(t){return e.warnOnce(`read failed`,`Could not read the values kept on the device, starting without them:`,t),{outcome:`failed`}}if(t==null||t===``)return{outcome:`nothing stored`};let n=Re(t,await e.clientSdkKeyDigest);switch(n.outcome){case`stored`:return n;case`first format`:return await e.removeEntry(),n;case`unreadable`:return e.warnOnce(`unreadable`,`The values kept on the device could not be read and were removed, starting without them`),await e.removeEntry(),n}}async writeQueued(){var e=this;if(!e.writing){e.writing=!0;try{for(;e.queuedCachedValues;){let t=e.queuedCachedValues;e.queuedCachedValues=void 0,await e.writeEntry(t)}}finally{e.writing=!1}}}async writeEntry(e){var t=this;let n=c({formatVersion:2,clientSdkKeyDigest:await t.clientSdkKeyDigest},e),r=JSON.stringify(n),i=Q(r),a=t.provider.sizeLimit();if(i>a){t.warnOnce(`over the size limit`,`The values received (${i} bytes) exceed the caching provider's limit of ${a} bytes, so no values are kept on the device`),await t.removeEntry();return}try{await t.provider.write(r)}catch(e){t.warnOnce(`write failed`,`Could not keep the values on the device:`,e)}}async removeEntry(){var e=this;try{await e.provider.remove()}catch(t){e.warnOnce(`remove failed`,`Could not remove the values kept on the device:`,t)}}warnOnce(e,t,...n){this.warned.has(e)||(this.warned.add(e),this.logger.warn(`[ConfigDirectorClient] ${t}`,...n))}},Be=class e{static from(t,n,r,i,a){return typeof n==`object`?new e(t,void 0,r,n,a):new e(t,n,r,i,a)}constructor(e,t,n,r,i){var a,o,s,u,d,f,p,m,h,g,_;this.handlersMap=new Map,this.eventEmitter=new l,this.ready=!1,this.initializing=!1,this.hasReceivedConfigSet=!1,this.servingCachedValues=!1,this.cachedValuesAdoptionStarted=!1,this.logger=(a=r==null?void 0:r.logger)==null?H():a,this.clientSession=_e(this.logger,i==null?void 0:i.instanceIdStorage),this.timeout=(o=r==null||(s=r.connection)==null?void 0:s.timeout)==null?3e3:o;let v=(u=i==null?void 0:i.urlFactory)==null?W:u;this.connectionPlan=re(t,r==null?void 0:r.connection,v),this.cachedValuesStore=this.buildCachedValuesStore(je(this.connectionPlan,r==null?void 0:r.caching,i==null?void 0:i.sha256HexDigest,i==null?void 0:i.platformCachingProvider)),this.telemetryClient=this.buildTelemetryClient(e,r),this.transport=(d=i==null?void 0:i.transport)==null?this.buildTransport(n,r,v,i):d,this.transport.on(`configSetReceived`,e=>{var t;this.hasReceivedConfigSet=!0,this.servingCachedValues=!1,(t=this.readyResolve)==null||t.call(this);let n=this.findKeysRemovedBy(e);!this.configSet||e.kind==`full`?this.configSet=e:this.configSet.configs=c(c({},this.configSet.configs),e.configs),this.keepValuesOnTheDevice(this.configSet);let r=Object.keys(e.configs);this.emit(`configsUpdated`,{keys:r,removedKeys:n}),this.updateWatchers([...r,...n]),this.logger.debug(`[ConfigDirectorClient] ConfigSet updated from server:`,{keys:r,removedKeys:n})}),this.transport.on(`connectionError`,e=>{this.initializing=!1,this.logger.error(`[ConfigDirectorClient] The connection encountered an unrecoverable error and will not be retried. Configs will no longer receive updates.`,e),this.emit(`connectionError`,{error:e})}),this.registerHandler(`clientReady`,r==null||(f=r.hooks)==null?void 0:f.clientReady),this.registerHandler(`configEvaluated`,r==null||(p=r.hooks)==null?void 0:p.configEvaluated),this.registerHandler(`configsUpdated`,r==null||(m=r.hooks)==null?void 0:m.configsUpdated),this.registerHandler(`contextUpdated`,r==null||(h=r.hooks)==null?void 0:h.contextUpdated),this.registerHandler(`connectionError`,r==null||(g=r.hooks)==null?void 0:g.connectionError),this.registerHandler(`cachedValuesLoaded`,r==null||(_=r.hooks)==null?void 0:_.cachedValuesLoaded)}buildCachedValuesStore(e){switch(e.kind){case`no cache`:this.logger.debug(`[ConfigDirectorClient] No values are kept on the device: ${e.reason}`);return;case`cache`:{let t=new ze(e.provider,e.clientSdkKeyDigest,this.logger);return t.read(),t}}}startCachedValuesAdoption(){let e=this.cachedValuesStore;!e||this.cachedValuesAdoptionStarted||(this.cachedValuesAdoptionStarted=!0,this.adoptCachedValues(e))}async adoptCachedValues(e){var t=this;let n=await e.read();switch(n.outcome){case`nothing stored`:case`first format`:case`unreadable`:case`failed`:return;case`stored`:break}let{instanceId:r}=await t.clientSession,i=$(t.submittedContext,r),a=Ne(n.cachedValues,i,t.hasReceivedConfigSet);switch(a){case`adopt`:t.serveCachedValues(n.cachedValues);return;case`live values already arrived`:case`context mismatch`:t.logger.debug(`[ConfigDirectorClient] The values kept on the device were not adopted: ${a}`);return}}serveCachedValues(e){let{environmentId:t,projectId:n,configs:r}=e;this.configSet={environmentId:t,projectId:n,configs:r,kind:`full`},this.servingCachedValues=!0;let i=Object.keys(r);this.emit(`cachedValuesLoaded`,{}),this.emit(`configsUpdated`,{keys:i,removedKeys:[]}),this.updateWatchers(i),this.logger.debug(`[ConfigDirectorClient] Serving the values kept on the device until live values arrive:`,{keys:i})}keepValuesOnTheDevice(e){let t=this.cachedValuesStore;if(!t)return;let n=this.submittedContext,r=Date.now();this.clientSession.then(({instanceId:i})=>t.replace({contextTag:$(n,i),environmentId:e.environmentId,projectId:e.projectId,configs:e.configs,receivedAt:r}))}servedReason(e){return this.servingCachedValues&&e===`found-match`?`cached`:e}registerHandler(e,t){if(!t)return;let n=Array.isArray(t)?t:[t];for(let t of n)typeof t==`function`&&this.on(e,t)}pollingIntervalFor(e,t){if(e!==`polling`)return;let n=G(t,{defaultSeconds:60,minimumSeconds:30});return n.warning&&this.logger.warn(`[ConfigDirectorClient] ${n.warning}`),n.seconds}buildTelemetryClient(e,t){let n=this.connectionPlan;switch(n.kind){case`stay-offline`:return U;case`connect`:return e({clientSdkKey:n.clientSdkKey,baseUrl:n.baseUrl,logger:this.logger,metadata:t==null?void 0:t.metadata,clientSession:this.clientSession})}}buildTransport(e,t,n,r){let i=this.connectionPlan;switch(i.kind){case`stay-offline`:return new D(i.source);case`connect`:var a,o;return new(this.getTransportConstructor(i.mode))({clientSession:this.clientSession,clientSdkKey:i.clientSdkKey,baseUrl:i.baseUrl,resolveUrl:n,metaContext:c(c({},t==null?void 0:t.metadata),{},{sdkName:e.sdkName,sdkVersion:e.sdkVersion,userAgent:ue(),host:de()}),logger:this.logger,fetch:r==null?void 0:r.fetch,connectionRetryDelay:(a=r==null?void 0:r.connectionRetryDelay)==null?(e=>2**Math.min(e,9)*1e3):a,pollingInterval:this.pollingIntervalFor(i.mode,t==null||(o=t.connection)==null?void 0:o.pollingInterval)})}}getTransportConstructor(e){switch(e){case`polling`:return be;case`streaming`:return v}}async initialize(e){var t=this;t.hasReceivedConfigSet||(t.initializing=!0),await t.submitContext(e,`initialization`)}async updateContext(e){var t=this;switch(t.connectionPlan.kind){case`connect`:await t.submitContext(e,`context update`);return;case`stay-offline`:t.storeContext(t.admittedContextFor(e,`context update`));return}}storeContext(e){this.currentContext=e,this.emit(`contextUpdated`,{context:e})}async submitContext(e,t){var n=this;await n.connectToTransport(n.admittedContextFor(e,t),t)}admittedContextFor(e,t){let n=Ee(e);switch(n.outcome){case`admitted`:return n.context;case`ignored`:this.logger.error(`[ConfigDirectorClient] Ignored the context supplied for ${t} because its kind '${n.kindSample}' is invalid; continuing as if no context was supplied. A context kind has 1 to 64 characters, using only lowercase letters, digits, '-' and '_'.`),this.telemetryClient.recordInvalidContext(n.kindSample);return}}get context(){return this.currentContext}async connectToTransport(e,t){var r=this;r.submittedContext=e,t===`initialization`&&r.startCachedValuesAdoption();try{r.ready=!1,r.readyPromise=new Promise(e=>{r.readyResolve=e}).then(e=>{e||(r.ready=!0,r.initializing=!1,r.emit(`clientReady`,{action:t}),r.logger.debug(`[ConfigDirectorClient] Received initial payload from the server, client is ready`))});let n=new Date().getTime();await r.transport.connect(e==null?{}:e,r.timeout,t),r.currentContext=e,r.telemetryClient.updateContext(e).catch(e=>r.logger.warn(`[ConfigDirectorClient] Telemetry could not update the context: `,e)),r.emit(`contextUpdated`,{context:e});let i=new Date().getTime()-n,a=r.timeout-i;clearTimeout(r.timeoutTimer),r.timeoutTimer=void 0,a>0&&await Promise.race([r.readyPromise,new Promise(e=>{r.timeoutTimer=setTimeout(()=>e(),a)})]).finally(()=>clearTimeout(r.timeoutTimer)),r.ready||r.logger.warn(`[ConfigDirectorClient] Timed out waiting for ${t} after ${r.timeout}ms. ${r.timeoutWarningDetails()}`)}catch(e){if(e instanceof n)throw r.initializing=!1,e;r.logger.error(`[ConfigDirectorClient] An error occurred during ${t}: `,e)}}timeoutWarningDetails(){switch(this.connectionPlan.kind){case`connect`:return`The client will continue to retry since there were no fatal errors detected. Configs will return the default value until the connection succeeds.`;case`stay-offline`:return`The offline values were not delivered, so configs return the default value.`}}findKeysRemovedBy(e){return!this.configSet||e.kind!=`full`?[]:Object.keys(this.configSet.configs).filter(t=>!Object.prototype.hasOwnProperty.call(e.configs,t))}updateWatchers(e){e.forEach(e=>this.updateWatchersForConfig(e))}updateWatchersForConfig(e){var t,n;let r=(t=this.configSet)==null?void 0:t.configs[e];(n=this.handlersMap.get(e))==null||n.forEach(t=>{let n=this.evaluationOf(e,r,t.defaultValue).value;t.handler(n)})}watch(e,t,n){this.validateDefaultValue(t);let r=this.handlersMap.get(e),i={handler:n,defaultValue:t,requestedType:typeof t};return r?r.push(i):this.handlersMap.set(e,[i]),()=>this.unwatch(e,n)}unwatch(e,t){let n=this.handlersMap.get(e);if(n)if(t){let e=n.findIndex(e=>e.handler==t);e>=0&&(n==null||n.splice(e,1))}else n.splice(0)}getValue(e,t){return this.evaluate(e,t).value}evaluate(e,t){var n;this.validateDefaultValue(t);let r=(n=this.configSet)==null?void 0:n.configs[e];return this.evaluationOf(e,r,t)}evaluationOf(e,t,n){var r,i;if(!t){var a;this.logger.debug(`[ConfigDirectorClient] No config state found for '${e}', returning default value '${n}'`);let t=this.isReady?`config-state-missing`:`client-not-ready`;this.telemetryClient.evaluatedConfig({contextId:(a=this.currentContext)==null?void 0:a.id,key:e,defaultValue:n,requestedType:k(n),evaluatedValue:n,usedDefault:!0,evaluationReason:t});let r={key:e,value:n,isDefaultValue:!0,reason:t,context:this.context};return this.dispatchEvaluationEvent(r),r}let o=se(t,n),s=this.servedReason(o.reason);this.telemetryClient.evaluatedConfig({contextId:(r=this.currentContext)==null?void 0:r.id,type:t.type,key:e,defaultValue:n,requestedType:o.requestedType,evaluatedValue:o.parsedValue,evaluatedValueId:o.parsedValueId,usedDefault:o.usedDefault,evaluationReason:s});let c={key:e,value:o.parsedValue,valueId:(i=o.parsedValueId)==null?void 0:i,isDefaultValue:o.usedDefault,reason:s,context:this.context};return this.dispatchEvaluationEvent(c),this.logger.debug(`[ConfigDirectorClient] Evaluated '${e}' to '${o.parsedValue}'`),c}dispatchEvaluationEvent(e){setTimeout(()=>this.emit(`configEvaluated`,{evaluation:e}),0)}emit(e,t){try{this.eventEmitter.emit(e,t)}catch(t){this.logger.error(`[ConfigDirectorClient] Error executing event handlers for '${e}'`,t)}}validateDefaultValue(e){if(e==null)throw new t(`Invalid default value. The default value for a config must be defined and non-null.`);if(typeof e==`function`)throw new t(`Invalid default value. The default value for a config cannot be a function.`)}get isReady(){return this.ready}get isInitializing(){return this.initializing}on(e,t){this.eventEmitter.on(e,t)}off(e,t){this.eventEmitter.off(e,t)}clear(){this.logger.debug(`[ConfigDirectorClient] clear() has been called, removing all observers`),this.eventEmitter.clear(),this.handlersMap.clear()}unwatchAll(){this.handlersMap.clear()}pauseNetwork(){switch(this.connectionPlan.kind){case`stay-offline`:return;case`connect`:this.logger.debug(`[ConfigDirectorClient] pauseNetwork() called, pausing transport connection`),clearTimeout(this.timeoutTimer),this.timeoutTimer=void 0,this.transport.close(),this.ready=!1;return}}async resumeNetwork(){var e=this;switch(e.connectionPlan.kind){case`stay-offline`:return;case`connect`:await e.connectToTransport(e.currentContext,`network resume`);return}}async close(){var e=this,t;e.logger.debug(`[ConfigDirectorClient] close() has been called, closing connection to server`),clearTimeout(e.timeoutTimer),(t=e.readyResolve)==null||t.call(e,!0),e.telemetryClient.close().catch(t=>e.logger.warn(`[ConfigDirectorClient] Telemetry could not close: `,t)),e.transport.close(),e.ready=!1,e.initializing=!1}dispose(){this.clear(),this.close()}};export{W as a,T as c,e as d,n as f,q as i,l,ke as n,U as o,t as p,Ae as r,H as s,Be as t,c as u};
6
- //# sourceMappingURL=DefaultConfigDirectorClient-BlVECy2L.mjs.map