@configdirector/react-native-sdk 0.7.0 → 0.9.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.
@@ -26,6 +26,15 @@ interface ConfigDirectorLogger {
26
26
  interface ConfigDirectorLogMessageDecorator {
27
27
  decorateMessage(message: string): string;
28
28
  }
29
+ type EvaluationReason = "found-match" | "config-state-missing" | "client-not-ready" | "type-mismatch" | "value-missing" | "invalid-number" | "invalid-json" | "invalid-boolean";
30
+ type ConfigEvaluation = {
31
+ key: string;
32
+ value: ConfigValueType;
33
+ valueId?: string;
34
+ isDefaultValue: boolean;
35
+ reason: EvaluationReason;
36
+ context?: ConfigDirectorContext;
37
+ };
29
38
  /**
30
39
  * The user's context to be sent to ConfigDirector. This context will be used for targeting
31
40
  * rules evaluation.
@@ -131,8 +140,31 @@ type ConfigDirectorClientOptions = {
131
140
  * );
132
141
  */
133
142
  logger?: ConfigDirectorLogger;
143
+ /**
144
+ * Handlers for hooks/events emitted by the client. Each hook accepts either a single event handler or
145
+ * an array of event handlers.
146
+ *
147
+ * @example
148
+ * import { createClient, createConsoleLogger } from "@configdirector/client-sdk";
149
+ * const client = createClient(
150
+ * "YOUR-SDK-KEY",
151
+ * {
152
+ * hooks: {
153
+ * configEvaluated: (event) => { console.log(event.evaluation); }
154
+ * },
155
+ * },
156
+ * );
157
+ */
158
+ hooks?: ClientHooks;
159
+ };
160
+ type ClientHooks = {
161
+ clientReady?: HookHandler<"clientReady"> | HookHandler<"clientReady">[];
162
+ configsUpdated?: HookHandler<"configsUpdated"> | HookHandler<"configsUpdated">[];
163
+ contextUpdated?: HookHandler<"contextUpdated"> | HookHandler<"contextUpdated">[];
164
+ configEvaluated?: HookHandler<"configEvaluated"> | HookHandler<"configEvaluated">[];
134
165
  };
135
166
  type ClientConnectAction = "initialization" | "context update" | "network resume";
167
+ type HookHandler<TEvent extends keyof ClientEvents> = (payload: ClientEvents[TEvent]) => void;
136
168
  type ClientEvents = {
137
169
  configsUpdated: {
138
170
  keys: string[];
@@ -143,6 +175,9 @@ type ClientEvents = {
143
175
  contextUpdated: {
144
176
  context: ConfigDirectorContext | undefined;
145
177
  };
178
+ configEvaluated: {
179
+ evaluation: ConfigEvaluation;
180
+ };
146
181
  };
147
182
  type WatchHandler<T extends ConfigValueType> = (message: T) => void;
148
183
  /**
@@ -297,6 +332,7 @@ type ConfigDirectorProviderOptions = {
297
332
  timeout?: number;
298
333
  context?: ConfigDirectorContext;
299
334
  logger?: ConfigDirectorLogger;
335
+ hooks?: ClientHooks;
300
336
  netInfoSubscribe?: NetInfoSubscribe;
301
337
  };
302
338
  //#endregion
@@ -1,3 +1,4 @@
1
+ import { sha256 } from "@noble/hashes/sha2.js";
1
2
  import React, { Component, useContext as useContext$1 } from "react";
2
3
  import { AppState } from "react-native";
3
4
  import { jsx } from "react/jsx-runtime";
@@ -550,22 +551,25 @@ const parseConfigValue = (configState, defaultValue) => {
550
551
  const requestedType = getRequestedType(defaultValue);
551
552
  if (!value) return {
552
553
  parsedValue: defaultValue,
554
+ parsedValueId: void 0,
553
555
  requestedType,
554
556
  usedDefault: true,
555
557
  reason: "value-missing"
556
558
  };
557
- if (configState.type === "json") return parseJson(value, defaultValue, requestedType);
559
+ if (configState.type === "json") return parseJson(value, defaultValue, requestedType, configState.valueId);
558
560
  if (typeof defaultValue === "string") return {
559
561
  parsedValue: value,
562
+ parsedValueId: configState.valueId,
560
563
  requestedType,
561
564
  usedDefault: false,
562
565
  reason: "found-match"
563
566
  };
564
- if (typeof defaultValue === "boolean" && configState.type === "boolean") {
567
+ if (typeof defaultValue === "boolean" && (configState.type === "boolean" || configState.type === "string")) {
565
568
  const boolValue = parseConfigBoolean(value);
566
569
  const hasBoolean = typeof boolValue === "boolean";
567
570
  return {
568
571
  parsedValue: hasBoolean ? boolValue : defaultValue,
572
+ parsedValueId: hasBoolean ? configState.valueId : void 0,
569
573
  requestedType,
570
574
  usedDefault: !hasBoolean,
571
575
  reason: hasBoolean ? "found-match" : "invalid-boolean"
@@ -576,16 +580,18 @@ const parseConfigValue = (configState, defaultValue) => {
576
580
  const hasNumber = typeof numValue === "number";
577
581
  return {
578
582
  parsedValue: hasNumber ? numValue : defaultValue,
583
+ parsedValueId: hasNumber ? configState.valueId : void 0,
579
584
  requestedType,
580
585
  usedDefault: !hasNumber,
581
586
  reason: hasNumber ? "found-match" : "invalid-number"
582
587
  };
583
588
  }
584
- if (isNumericNativeType(typeof defaultValue) && (configState.type === "float" || configState.type === "enum")) {
589
+ if (isNumericNativeType(typeof defaultValue) && (configState.type === "float" || configState.type === "enum" || configState.type === "string")) {
585
590
  const numValue = parseConfigFloat(value);
586
591
  const hasNumber = typeof numValue === "number";
587
592
  return {
588
593
  parsedValue: hasNumber ? numValue : defaultValue,
594
+ parsedValueId: hasNumber ? configState.valueId : void 0,
589
595
  requestedType,
590
596
  usedDefault: !hasNumber,
591
597
  reason: hasNumber ? "found-match" : "invalid-number"
@@ -593,6 +599,7 @@ const parseConfigValue = (configState, defaultValue) => {
593
599
  }
594
600
  return {
595
601
  parsedValue: value,
602
+ parsedValueId: configState.valueId,
596
603
  requestedType,
597
604
  usedDefault: false,
598
605
  reason: "found-match"
@@ -616,9 +623,10 @@ const parseConfigFloat = (value) => {
616
623
  if (isNaN(num) || !isFinite(num)) return;
617
624
  return num;
618
625
  };
619
- const parseJson = (jsonString, defaultValue, requestedType) => {
626
+ const parseJson = (jsonString, defaultValue, requestedType, valueId) => {
620
627
  if (typeof defaultValue === "string") return {
621
628
  parsedValue: jsonString,
629
+ parsedValueId: valueId,
622
630
  requestedType,
623
631
  usedDefault: false,
624
632
  reason: "found-match"
@@ -626,6 +634,7 @@ const parseJson = (jsonString, defaultValue, requestedType) => {
626
634
  try {
627
635
  return {
628
636
  parsedValue: JSON.parse(jsonString),
637
+ parsedValueId: valueId,
629
638
  requestedType,
630
639
  usedDefault: false,
631
640
  reason: "found-match"
@@ -633,6 +642,7 @@ const parseJson = (jsonString, defaultValue, requestedType) => {
633
642
  } catch {
634
643
  return {
635
644
  parsedValue: defaultValue,
645
+ parsedValueId: void 0,
636
646
  requestedType,
637
647
  usedDefault: true,
638
648
  reason: "invalid-json"
@@ -863,7 +873,7 @@ const CLIENT_BASE_URL = "https://client-sdk-api.configdirector.com";
863
873
  const MAX_EXPONENTIAL_DELAY = 9;
864
874
  var DefaultConfigDirectorClient = class {
865
875
  constructor(telemetryClient, clientSdkKey, sdkOptions, clientOptions, internalClientOptions) {
866
- var _clientOptions$logger, _clientOptions$connec, _clientOptions$connec2, _internalClientOption, _this$parseUrl, _clientOptions$connec3, _clientOptions$connec4, _clientOptions$connec5, _navigator, _internalClientOption2, _clientOptions$connec6;
876
+ var _clientOptions$logger, _clientOptions$connec, _clientOptions$connec2, _internalClientOption, _this$parseUrl, _clientOptions$connec3, _clientOptions$connec4, _clientOptions$connec5, _navigator, _internalClientOption2, _clientOptions$connec6, _clientOptions$hooks, _clientOptions$hooks2, _clientOptions$hooks3, _clientOptions$hooks4;
867
877
  _defineProperty(this, "logger", void 0);
868
878
  _defineProperty(this, "telemetryClient", void 0);
869
879
  _defineProperty(this, "configSet", void 0);
@@ -911,18 +921,27 @@ var DefaultConfigDirectorClient = class {
911
921
  const configKeys = Object.keys(configSet.configs);
912
922
  if (!this.configSet || configSet.kind == "full") {
913
923
  this.configSet = configSet;
914
- this.eventEmitter.emit("configsUpdated", { keys: configKeys });
924
+ this.emit("configsUpdated", { keys: configKeys });
915
925
  this.updateWatchers(configSet.configs);
916
926
  } else {
917
927
  this.configSet.configs = {
918
928
  ...this.configSet.configs,
919
929
  ...configSet.configs
920
930
  };
921
- this.eventEmitter.emit("configsUpdated", { keys: configKeys });
931
+ this.emit("configsUpdated", { keys: configKeys });
922
932
  this.updateWatchers(configSet.configs);
923
933
  }
924
934
  this.logger.debug("[ConfigDirectorClient] ConfigSet updated from server:", { keys: configKeys });
925
935
  });
936
+ this.registerHandler("clientReady", clientOptions === null || clientOptions === void 0 || (_clientOptions$hooks = clientOptions.hooks) === null || _clientOptions$hooks === void 0 ? void 0 : _clientOptions$hooks.clientReady);
937
+ this.registerHandler("configEvaluated", clientOptions === null || clientOptions === void 0 || (_clientOptions$hooks2 = clientOptions.hooks) === null || _clientOptions$hooks2 === void 0 ? void 0 : _clientOptions$hooks2.configEvaluated);
938
+ this.registerHandler("configsUpdated", clientOptions === null || clientOptions === void 0 || (_clientOptions$hooks3 = clientOptions.hooks) === null || _clientOptions$hooks3 === void 0 ? void 0 : _clientOptions$hooks3.configsUpdated);
939
+ this.registerHandler("contextUpdated", clientOptions === null || clientOptions === void 0 || (_clientOptions$hooks4 = clientOptions.hooks) === null || _clientOptions$hooks4 === void 0 ? void 0 : _clientOptions$hooks4.contextUpdated);
940
+ }
941
+ registerHandler(event, handler) {
942
+ if (!handler) return;
943
+ const handlers = Array.isArray(handler) ? handler : [handler];
944
+ for (const h of handlers) if (typeof h === "function") this.on(event, h);
926
945
  }
927
946
  getTransportConstructor(connectionMode) {
928
947
  switch (connectionMode) {
@@ -949,14 +968,14 @@ var DefaultConfigDirectorClient = class {
949
968
  }).then(() => {
950
969
  this.ready = true;
951
970
  this.initializing = false;
952
- this.eventEmitter.emit("clientReady", { action: caller });
971
+ this.emit("clientReady", { action: caller });
953
972
  this.logger.debug("[ConfigDirectorClient] Received initial payload from the server, client is ready");
954
973
  });
955
974
  const startTime = (/* @__PURE__ */ new Date()).getTime();
956
975
  await this.transport.connect(context !== null && context !== void 0 ? context : {}, this.timeout);
957
976
  this.currentContext = context;
958
977
  this.telemetryClient.updateContext(context);
959
- this.eventEmitter.emit("contextUpdated", { context });
978
+ this.emit("contextUpdated", { context });
960
979
  const elapsedTime = (/* @__PURE__ */ new Date()).getTime() - startTime;
961
980
  const remainingTimeout = this.timeout - elapsedTime;
962
981
  clearTimeout(this.timeoutTimer);
@@ -1006,10 +1025,11 @@ var DefaultConfigDirectorClient = class {
1006
1025
  return this.getValueFromConfigState(configKey, configState, defaultValue);
1007
1026
  }
1008
1027
  getValueFromConfigState(configKey, configState, defaultValue) {
1009
- var _this$currentContext2;
1028
+ var _this$currentContext2, _parseResult$parsedVa;
1010
1029
  if (!configState) {
1011
1030
  var _this$currentContext;
1012
1031
  this.logger.debug(`[ConfigDirectorClient] No config state found for '${configKey}', returning default value '${defaultValue}'`);
1032
+ const reason = this.isReady ? "config-state-missing" : "client-not-ready";
1013
1033
  this.telemetryClient.evaluatedConfig({
1014
1034
  contextId: (_this$currentContext = this.currentContext) === null || _this$currentContext === void 0 ? void 0 : _this$currentContext.id,
1015
1035
  key: configKey,
@@ -1017,7 +1037,14 @@ var DefaultConfigDirectorClient = class {
1017
1037
  requestedType: getRequestedType(defaultValue),
1018
1038
  evaluatedValue: defaultValue,
1019
1039
  usedDefault: true,
1020
- evaluationReason: "config-state-missing"
1040
+ evaluationReason: reason
1041
+ });
1042
+ this.dispatchEvaluationEvent({
1043
+ key: configKey,
1044
+ value: defaultValue,
1045
+ isDefaultValue: true,
1046
+ reason,
1047
+ context: this.context
1021
1048
  });
1022
1049
  return defaultValue;
1023
1050
  }
@@ -1029,12 +1056,31 @@ var DefaultConfigDirectorClient = class {
1029
1056
  defaultValue,
1030
1057
  requestedType: parseResult.requestedType,
1031
1058
  evaluatedValue: parseResult.parsedValue,
1059
+ evaluatedValueId: parseResult.parsedValueId,
1032
1060
  usedDefault: parseResult.usedDefault,
1033
1061
  evaluationReason: parseResult.reason
1034
1062
  });
1063
+ this.dispatchEvaluationEvent({
1064
+ key: configKey,
1065
+ value: parseResult.parsedValue,
1066
+ valueId: (_parseResult$parsedVa = parseResult.parsedValueId) !== null && _parseResult$parsedVa !== void 0 ? _parseResult$parsedVa : void 0,
1067
+ isDefaultValue: parseResult.usedDefault,
1068
+ reason: parseResult.reason,
1069
+ context: this.context
1070
+ });
1035
1071
  this.logger.debug(`[ConfigDirectorClient] Evaluated '${configKey}' to '${parseResult.parsedValue}'`);
1036
1072
  return parseResult.parsedValue;
1037
1073
  }
1074
+ dispatchEvaluationEvent(event) {
1075
+ setTimeout(() => this.emit("configEvaluated", { evaluation: event }), 0);
1076
+ }
1077
+ emit(name, payload) {
1078
+ try {
1079
+ this.eventEmitter.emit(name, payload);
1080
+ } catch (error) {
1081
+ this.logger.error(`[ConfigDirectorClient] Error executing event handlers for '${name}'`, error);
1082
+ }
1083
+ }
1038
1084
  parseUrl(url, urlFactory) {
1039
1085
  if (!url) return;
1040
1086
  try {
@@ -1094,26 +1140,36 @@ var DefaultConfigDirectorClient = class {
1094
1140
  //#endregion
1095
1141
  //#region ../shared/src/telemetry/utils.ts
1096
1142
  const CONFIG_VALUE_MAX_LENGTH = 500;
1097
- const sanitizeValue = (value, type) => {
1098
- if (type === "json" || type == null && typeof value === "object") try {
1099
- return { digest: djb2Hash(JSON.stringify(value)) };
1100
- } catch {
1101
- return { digest: value.toString() };
1143
+ const compactTelemetryValue = async (tv, valueIdGenerator) => {
1144
+ if (tv.valueId) return { valueId: tv.valueId };
1145
+ if (tv.value) {
1146
+ if (tv.value.length <= CONFIG_VALUE_MAX_LENGTH && tv.type != "json") return { value: tv.value };
1147
+ return { valueId: await valueIdGenerator(tv.value) };
1102
1148
  }
1103
- if (value.toString().length > CONFIG_VALUE_MAX_LENGTH) return { digest: djb2Hash(value.toString()) };
1104
- else return { value: value.toString() };
1149
+ return tv;
1105
1150
  };
1106
- const djb2Hash = (data) => {
1107
- return djb2(new TextEncoder().encode(data)).toString(16).padStart(8, "0");
1108
- };
1109
- const djb2 = (bytes) => {
1110
- let hash = 5381;
1111
- for (let i = 0; i < bytes.length; i++) {
1112
- var _bytes$i;
1113
- hash = (hash << 5) + hash + ((_bytes$i = bytes[i]) !== null && _bytes$i !== void 0 ? _bytes$i : 0);
1114
- hash = hash >>> 0;
1115
- }
1116
- return hash;
1151
+ const mapToTelemetryValue = (ev) => {
1152
+ var _ev$value;
1153
+ if (ev.type === "json" || ev.type == null && typeof ev.value === "object") {
1154
+ if (ev.valueId) return {
1155
+ valueId: ev.valueId,
1156
+ type: "json"
1157
+ };
1158
+ try {
1159
+ return {
1160
+ value: JSON.stringify(ev.value),
1161
+ type: "json"
1162
+ };
1163
+ } catch {
1164
+ return {
1165
+ value: ev.value.toString(),
1166
+ type: "json"
1167
+ };
1168
+ }
1169
+ }
1170
+ const stringValue = (_ev$value = ev.value) === null || _ev$value === void 0 ? void 0 : _ev$value.toString();
1171
+ if (stringValue && stringValue.length <= CONFIG_VALUE_MAX_LENGTH) return { value: stringValue };
1172
+ return ev.valueId ? { valueId: ev.valueId } : { value: stringValue };
1117
1173
  };
1118
1174
  const isEventListEmpty = (eventList) => {
1119
1175
  const keys = Object.keys(eventList);
@@ -1289,9 +1345,6 @@ var TelemetryEventCollector = class {
1289
1345
  const initialDelay = (_options$initialFlush = options.initialFlushIntervalDelay) !== null && _options$initialFlush !== void 0 ? _options$initialFlush : 5e3;
1290
1346
  this.flushTimeout = setTimeout(() => this.flushAndScheduleNext(), initialDelay);
1291
1347
  }
1292
- sanitizeValue(value, type) {
1293
- return sanitizeValue(value, type);
1294
- }
1295
1348
  async flushAndScheduleNext() {
1296
1349
  if ((await this.flush()).fatalError) {
1297
1350
  this.collectEvents = false;
@@ -1299,20 +1352,6 @@ var TelemetryEventCollector = class {
1299
1352
  this.logger.warn("[TelemetryEventCollector] Received a fatal error from telemetry collection. No longer collecting events.");
1300
1353
  } else this.flushTimeout = setTimeout(() => this.flushAndScheduleNext(), this.flushIntervalDelay);
1301
1354
  }
1302
- async flush() {
1303
- var _this$reporter;
1304
- if (!this.reporter) return {
1305
- success: false,
1306
- fatalError: false
1307
- };
1308
- const evaluationSnapshot = this.evaluationEventQueue.takeSnapshot();
1309
- return await ((_this$reporter = this.reporter) === null || _this$reporter === void 0 ? void 0 : _this$reporter.report({
1310
- context: this._context,
1311
- discreteEvents: {},
1312
- aggregatedEvents: { evaluatedConfig: this.aggregator.aggregate(evaluationSnapshot) },
1313
- droppedEvents: { evaluatedConfig: evaluationSnapshot.droppedCount }
1314
- }));
1315
- }
1316
1355
  cancelScheduledFlush() {
1317
1356
  clearTimeout(this.flushTimeout);
1318
1357
  }
@@ -1327,13 +1366,36 @@ var TelemetryEventCollector = class {
1327
1366
  }
1328
1367
  };
1329
1368
  //#endregion
1369
+ //#region ../shared/src/telemetry/EvaluatedConfigEventPreprocessor.ts
1370
+ var EvaluatedConfigEventPreprocessor = class {
1371
+ constructor(valueIdGenerator) {
1372
+ this.valueIdGenerator = valueIdGenerator;
1373
+ this.valueIdGenerator = valueIdGenerator;
1374
+ }
1375
+ async process(snapshot) {
1376
+ const events = await Promise.all(snapshot.events.map(async (e) => {
1377
+ return {
1378
+ ...e,
1379
+ defaultValue: await compactTelemetryValue(e.defaultValue, this.valueIdGenerator),
1380
+ evaluatedValue: await compactTelemetryValue(e.evaluatedValue, this.valueIdGenerator)
1381
+ };
1382
+ }));
1383
+ return {
1384
+ ...snapshot,
1385
+ events
1386
+ };
1387
+ }
1388
+ };
1389
+ //#endregion
1330
1390
  //#region ../js-client-core/src/telemetry/ClientTelemetryEventCollector.ts
1331
1391
  var ClientTelemetryEventCollector = class extends TelemetryEventCollector {
1332
1392
  constructor(options) {
1333
1393
  super(options);
1394
+ _defineProperty(this, "evaluationEventSnapshotPreprocessor", void 0);
1334
1395
  _defineProperty(this, "reporter", void 0);
1335
1396
  _defineProperty(this, "_context", void 0);
1336
1397
  this.reporter = new ClientEventReporter(options);
1398
+ this.evaluationEventSnapshotPreprocessor = new EvaluatedConfigEventPreprocessor(options.valueIdGenerator);
1337
1399
  }
1338
1400
  async updateContext(value) {
1339
1401
  this.cancelScheduledFlush();
@@ -1349,6 +1411,20 @@ var ClientTelemetryEventCollector = class extends TelemetryEventCollector {
1349
1411
  this.cancelScheduledFlush();
1350
1412
  await this.flushAndScheduleNext();
1351
1413
  }
1414
+ async flush() {
1415
+ var _this$reporter;
1416
+ if (!this.reporter) return {
1417
+ success: false,
1418
+ fatalError: false
1419
+ };
1420
+ const evaluationSnapshot = await this.evaluationEventSnapshotPreprocessor.process(this.evaluationEventQueue.takeSnapshot());
1421
+ return await ((_this$reporter = this.reporter) === null || _this$reporter === void 0 ? void 0 : _this$reporter.report({
1422
+ context: this._context,
1423
+ discreteEvents: {},
1424
+ aggregatedEvents: { evaluatedConfig: this.aggregator.aggregate(evaluationSnapshot) },
1425
+ droppedEvents: { evaluatedConfig: evaluationSnapshot.droppedCount }
1426
+ }));
1427
+ }
1352
1428
  };
1353
1429
  //#endregion
1354
1430
  //#region src/logger.ts
@@ -1475,6 +1551,28 @@ const parseHeaders = (raw) => {
1475
1551
  return headers;
1476
1552
  };
1477
1553
  //#endregion
1554
+ //#region ../shared/src/base62-encoder.ts
1555
+ const BASE62 = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
1556
+ const toBase62 = (buf, length) => {
1557
+ const ZERO = BigInt(0);
1558
+ const BASE = BigInt(62);
1559
+ const hex = Array.from(buf).map((b) => b.toString(16).padStart(2, "0")).join("");
1560
+ let n = BigInt("0x" + hex);
1561
+ let result = "";
1562
+ while (n > ZERO) {
1563
+ result = BASE62[Number(n % BASE)] + result;
1564
+ n /= BASE;
1565
+ }
1566
+ return result.padStart(length, "0");
1567
+ };
1568
+ const BASE62_LENGTH = Math.ceil(128 / Math.log2(62));
1569
+ //#endregion
1570
+ //#region src/value-id-generator.ts
1571
+ const generateValueId = (v) => {
1572
+ var _v$toString;
1573
+ return toBase62(sha256(encodeUtf8((_v$toString = v === null || v === void 0 ? void 0 : v.toString()) !== null && _v$toString !== void 0 ? _v$toString : "")).subarray(0, 16), BASE62_LENGTH);
1574
+ };
1575
+ //#endregion
1478
1576
  //#region src/ReactNativeTelemetryClient.ts
1479
1577
  var ReactNativeTelemetryClient = class {
1480
1578
  constructor(sdkKey, baseUrl, logger, urlFactory) {
@@ -1483,7 +1581,8 @@ var ReactNativeTelemetryClient = class {
1483
1581
  sdkKey,
1484
1582
  logger,
1485
1583
  baseUrl,
1486
- urlFactory
1584
+ urlFactory,
1585
+ valueIdGenerator: async (v) => generateValueId(v)
1487
1586
  });
1488
1587
  }
1489
1588
  async updateContext(value) {
@@ -1498,8 +1597,15 @@ var ReactNativeTelemetryClient = class {
1498
1597
  sanitizeEvaluatedConfigEvent(event) {
1499
1598
  return {
1500
1599
  ...event,
1501
- defaultValue: sanitizeValue(event.defaultValue, event.type),
1502
- evaluatedValue: sanitizeValue(event.evaluatedValue, event.type)
1600
+ defaultValue: mapToTelemetryValue({
1601
+ value: event.defaultValue,
1602
+ type: event.type
1603
+ }),
1604
+ evaluatedValue: mapToTelemetryValue({
1605
+ value: event.evaluatedValue,
1606
+ valueId: event.evaluatedValueId,
1607
+ type: event.type
1608
+ })
1503
1609
  };
1504
1610
  }
1505
1611
  };
@@ -1525,7 +1631,7 @@ const createClient = (clientSdkKey, clientOptions) => {
1525
1631
  const logger = (_clientOptions$logger = clientOptions === null || clientOptions === void 0 ? void 0 : clientOptions.logger) !== null && _clientOptions$logger !== void 0 ? _clientOptions$logger : createConsoleLogger("warn");
1526
1632
  return new DefaultConfigDirectorClient(new ReactNativeTelemetryClient(clientSdkKey, (clientOptions === null || clientOptions === void 0 || (_clientOptions$connec = clientOptions.connection) === null || _clientOptions$connec === void 0 ? void 0 : _clientOptions$connec.url) ? urlFactory(clientOptions.connection.url) : CLIENT_BASE_URL, logger, urlFactory), clientSdkKey, {
1527
1633
  sdkName: "react-native-sdk",
1528
- sdkVersion: "0.7.0"
1634
+ sdkVersion: "0.9.0"
1529
1635
  }, {
1530
1636
  ...clientOptions,
1531
1637
  logger
@@ -1575,7 +1681,8 @@ var ConfigDirectorProvider = class extends Component {
1575
1681
  appName: props.appName,
1576
1682
  appVersion: props.appVersion
1577
1683
  },
1578
- logger: (_props$logger = props.logger) !== null && _props$logger !== void 0 ? _props$logger : createConsoleLogger("warn")
1684
+ logger: (_props$logger = props.logger) !== null && _props$logger !== void 0 ? _props$logger : createConsoleLogger("warn"),
1685
+ hooks: props.hooks
1579
1686
  }),
1580
1687
  status: "loading"
1581
1688
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@configdirector/react-native-sdk",
3
- "version": "0.7.0",
3
+ "version": "0.9.0",
4
4
  "description": "React Native client SDK for ConfigDirector. ConfigDirector is a remote configuration and feature flag service.",
5
5
  "license": "MIT",
6
6
  "author": "ConfigDirector",
@@ -52,6 +52,9 @@
52
52
  "publishConfig": {
53
53
  "registry": "https://registry.npmjs.org/"
54
54
  },
55
+ "dependencies": {
56
+ "@noble/hashes": "^2.2.0"
57
+ },
55
58
  "devDependencies": {
56
59
  "@babel/core": "^7.29.0",
57
60
  "@eslint/js": "^10.0.1",
@@ -112,7 +115,7 @@
112
115
  "^@eventsource/(.*)$": "<rootDir>/../eventsource/src/$1"
113
116
  },
114
117
  "transformIgnorePatterns": [
115
- "node_modules/(?!((jest-)?react-native|@react-native(-community)?)/)"
118
+ "node_modules/(?!((jest-)?react-native|@react-native(-community)?|@noble)/)"
116
119
  ]
117
120
  }
118
121
  }