@schematichq/schematic-react 1.2.4 → 1.2.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -53,6 +53,8 @@ const MyComponent = () => {
53
53
  };
54
54
  ```
55
55
 
56
+ To learn more about identifying companies with the `keys` map, see [key management in Schematic public docs](https://docs.schematichq.com/developer_resources/key_management).
57
+
56
58
  ### Tracking usage
57
59
 
58
60
  Once you've set the context with `identify`, you can track events:
@@ -71,6 +73,12 @@ const MyComponent = () => {
71
73
  };
72
74
  ```
73
75
 
76
+ If you want to record large numbers of the same event at once, or perhaps measure usage in terms of a unit like tokens or memory, you can optionally specify a quantity for your event:
77
+
78
+ ```tsx
79
+ track({ event: "query", quantity: 10 });
80
+ ```
81
+
74
82
  ### Checking flags
75
83
 
76
84
  To check a flag, you can use the `useSchematicFlag` hook:
@@ -170,6 +178,7 @@ ReactDOM.render(
170
178
 
171
179
  Offline mode automatically enables debug mode to help with troubleshooting.
172
180
 
181
+
173
182
  ## License
174
183
 
175
184
  MIT
@@ -660,6 +660,7 @@ function CheckFlagResponseDataFromJSONTyped(json, ignoreDiscriminator) {
660
660
  error: json["error"] == null ? void 0 : json["error"],
661
661
  featureAllocation: json["feature_allocation"] == null ? void 0 : json["feature_allocation"],
662
662
  featureUsage: json["feature_usage"] == null ? void 0 : json["feature_usage"],
663
+ featureUsageEvent: json["feature_usage_event"] == null ? void 0 : json["feature_usage_event"],
663
664
  featureUsagePeriod: json["feature_usage_period"] == null ? void 0 : json["feature_usage_period"],
664
665
  featureUsageResetAt: json["feature_usage_reset_at"] == null ? void 0 : new Date(json["feature_usage_reset_at"]),
665
666
  flag: json["flag"],
@@ -749,6 +750,7 @@ var CheckFlagReturnFromJSON = (json) => {
749
750
  error,
750
751
  featureAllocation,
751
752
  featureUsage,
753
+ featureUsageEvent,
752
754
  featureUsagePeriod,
753
755
  featureUsageResetAt,
754
756
  flag,
@@ -768,6 +770,7 @@ var CheckFlagReturnFromJSON = (json) => {
768
770
  error: error == null ? void 0 : error,
769
771
  featureAllocation: featureAllocation == null ? void 0 : featureAllocation,
770
772
  featureUsage: featureUsage == null ? void 0 : featureUsage,
773
+ featureUsageEvent: featureUsageEvent === null ? void 0 : featureUsageEvent,
771
774
  featureUsagePeriod: featureUsagePeriod == null ? void 0 : featureUsagePeriod,
772
775
  featureUsageResetAt: featureUsageResetAt == null ? void 0 : featureUsageResetAt,
773
776
  flag,
@@ -793,7 +796,7 @@ function contextString(context) {
793
796
  }, {});
794
797
  return JSON.stringify(sortedContext);
795
798
  }
796
- var version = "1.2.2";
799
+ var version = "1.2.3";
797
800
  var anonymousIdKey = "schematicId";
798
801
  var Schematic = class {
799
802
  additionalHeaders = {};
@@ -812,6 +815,7 @@ var Schematic = class {
812
815
  storage;
813
816
  useWebSocket = false;
814
817
  checks = {};
818
+ featureUsageEventMap = {};
815
819
  webSocketUrl = "wss://api.schematichq.com";
816
820
  constructor(apiKey, options) {
817
821
  this.apiKey = apiKey;
@@ -906,6 +910,9 @@ var Schematic = class {
906
910
  const parsedResponse = CheckFlagResponseFromJSON(response);
907
911
  this.debug(`checkFlag result: ${key}`, parsedResponse);
908
912
  const result = CheckFlagReturnFromJSON(parsedResponse.data);
913
+ if (typeof result.featureUsageEvent === "string") {
914
+ this.updateFeatureUsageEventMap(result);
915
+ }
909
916
  this.submitFlagCheckEvent(key, result, context);
910
917
  return result.value;
911
918
  }).catch((error) => {
@@ -1025,6 +1032,9 @@ var Schematic = class {
1025
1032
  const data = CheckFlagResponseFromJSON(responseJson);
1026
1033
  this.debug(`fallbackToRest result: ${key}`, data);
1027
1034
  const result = CheckFlagReturnFromJSON(data.data);
1035
+ if (typeof result.featureUsageEvent === "string") {
1036
+ this.updateFeatureUsageEventMap(result);
1037
+ }
1028
1038
  this.submitFlagCheckEvent(key, result, context);
1029
1039
  return result.value;
1030
1040
  } catch (error) {
@@ -1108,14 +1118,11 @@ var Schematic = class {
1108
1118
  * In offline mode, this will just set the context locally without connecting.
1109
1119
  */
1110
1120
  setContext = async (context) => {
1111
- if (this.isOffline()) {
1121
+ if (this.isOffline() || !this.useWebSocket) {
1112
1122
  this.context = context;
1113
1123
  this.setIsPending(false);
1114
1124
  return Promise.resolve();
1115
1125
  }
1116
- if (!this.useWebSocket) {
1117
- return Promise.resolve();
1118
- }
1119
1126
  try {
1120
1127
  this.setIsPending(true);
1121
1128
  if (!this.conn) {
@@ -1131,18 +1138,69 @@ var Schematic = class {
1131
1138
  /**
1132
1139
  * Send a track event
1133
1140
  * Track usage for a company and/or user.
1141
+ * Optimistically updates feature usage flags if tracking a featureUsageEvent.
1134
1142
  */
1135
1143
  track = (body) => {
1136
- const { company, user, event, traits } = body;
1144
+ const { company, user, event, traits, quantity = 1 } = body;
1137
1145
  const trackData = {
1138
1146
  company: company ?? this.context.company,
1139
1147
  event,
1140
1148
  traits: traits ?? {},
1141
- user: user ?? this.context.user
1149
+ user: user ?? this.context.user,
1150
+ quantity
1142
1151
  };
1143
1152
  this.debug(`track:`, trackData);
1153
+ if (event in this.featureUsageEventMap) {
1154
+ this.optimisticallyUpdateFeatureUsage(event, quantity);
1155
+ }
1144
1156
  return this.handleEvent("track", trackData);
1145
1157
  };
1158
+ /**
1159
+ * Optimistically update feature usage flags associated with a tracked event
1160
+ * This updates flags in memory with updated usage counts and value/featureUsageExceeded flags
1161
+ * before the network request completes
1162
+ */
1163
+ optimisticallyUpdateFeatureUsage = (eventName, quantity = 1) => {
1164
+ const flagsForEvent = this.featureUsageEventMap[eventName];
1165
+ if (flagsForEvent === void 0 || flagsForEvent === null) return;
1166
+ this.debug(
1167
+ `Optimistically updating feature usage for event: ${eventName}`,
1168
+ { quantity }
1169
+ );
1170
+ Object.entries(flagsForEvent).forEach(([flagKey, check]) => {
1171
+ if (check === void 0) return;
1172
+ const updatedCheck = { ...check };
1173
+ if (typeof updatedCheck.featureUsage === "number") {
1174
+ updatedCheck.featureUsage += quantity;
1175
+ if (typeof updatedCheck.featureAllocation === "number") {
1176
+ const wasExceeded = updatedCheck.featureUsageExceeded === true;
1177
+ const nowExceeded = updatedCheck.featureUsage >= updatedCheck.featureAllocation;
1178
+ if (nowExceeded !== wasExceeded) {
1179
+ updatedCheck.featureUsageExceeded = nowExceeded;
1180
+ if (nowExceeded) {
1181
+ updatedCheck.value = false;
1182
+ }
1183
+ this.debug(`Usage limit status changed for flag: ${flagKey}`, {
1184
+ was: wasExceeded ? "exceeded" : "within limits",
1185
+ now: nowExceeded ? "exceeded" : "within limits",
1186
+ featureUsage: updatedCheck.featureUsage,
1187
+ featureAllocation: updatedCheck.featureAllocation,
1188
+ value: updatedCheck.value
1189
+ });
1190
+ }
1191
+ }
1192
+ if (this.featureUsageEventMap[eventName] !== void 0) {
1193
+ this.featureUsageEventMap[eventName][flagKey] = updatedCheck;
1194
+ }
1195
+ const contextStr = contextString(this.context);
1196
+ if (this.checks[contextStr] !== void 0 && this.checks[contextStr] !== null) {
1197
+ this.checks[contextStr][flagKey] = updatedCheck;
1198
+ }
1199
+ this.notifyFlagCheckListeners(flagKey, updatedCheck);
1200
+ this.notifyFlagValueListeners(flagKey, updatedCheck.value);
1201
+ }
1202
+ });
1203
+ };
1146
1204
  /**
1147
1205
  * Event processing
1148
1206
  */
@@ -1285,12 +1343,19 @@ var Schematic = class {
1285
1343
  }
1286
1344
  (message.flags ?? []).forEach((flag) => {
1287
1345
  const flagCheck = CheckFlagReturnFromJSON(flag);
1288
- this.checks[contextString(context)][flagCheck.flag] = flagCheck;
1346
+ const contextStr = contextString(context);
1347
+ if (this.checks[contextStr] === void 0) {
1348
+ this.checks[contextStr] = {};
1349
+ }
1350
+ this.checks[contextStr][flagCheck.flag] = flagCheck;
1289
1351
  this.debug(`WebSocket flag update:`, {
1290
1352
  flag: flagCheck.flag,
1291
1353
  value: flagCheck.value,
1292
1354
  flagCheck
1293
1355
  });
1356
+ if (typeof flagCheck.featureUsageEvent === "string") {
1357
+ this.updateFeatureUsageEventMap(flagCheck);
1358
+ }
1294
1359
  if (this.flagCheckListeners[flag.flag]?.size > 0 || this.flagValueListeners[flag.flag]?.size > 0) {
1295
1360
  this.submitFlagCheckEvent(flagCheck.flag, flagCheck, context);
1296
1361
  }
@@ -1383,8 +1448,26 @@ var Schematic = class {
1383
1448
  check
1384
1449
  );
1385
1450
  }
1451
+ if (typeof check.featureUsageEvent === "string") {
1452
+ this.updateFeatureUsageEventMap(check);
1453
+ }
1386
1454
  listeners.forEach((listener) => notifyFlagCheckListener(listener, check));
1387
1455
  };
1456
+ /** Add or update a CheckFlagReturn in the featureUsageEventMap */
1457
+ updateFeatureUsageEventMap = (check) => {
1458
+ if (typeof check.featureUsageEvent !== "string") return;
1459
+ const eventName = check.featureUsageEvent;
1460
+ if (this.featureUsageEventMap[eventName] === void 0 || this.featureUsageEventMap[eventName] === null) {
1461
+ this.featureUsageEventMap[eventName] = {};
1462
+ }
1463
+ if (this.featureUsageEventMap[eventName] !== void 0) {
1464
+ this.featureUsageEventMap[eventName][check.flag] = check;
1465
+ }
1466
+ this.debug(
1467
+ `Updated featureUsageEventMap for event: ${eventName}, flag: ${check.flag}`,
1468
+ check
1469
+ );
1470
+ };
1388
1471
  notifyFlagValueListeners = (flagKey, value) => {
1389
1472
  const listeners = this.flagValueListeners?.[flagKey] ?? [];
1390
1473
  if (listeners.size > 0) {
@@ -1422,7 +1505,7 @@ var notifyFlagValueListener = (listener, value) => {
1422
1505
  var import_react = __toESM(require("react"));
1423
1506
 
1424
1507
  // src/version.ts
1425
- var version2 = "1.2.4";
1508
+ var version2 = "1.2.5";
1426
1509
 
1427
1510
  // src/context/schematic.tsx
1428
1511
  var import_jsx_runtime = require("react/jsx-runtime");
@@ -615,6 +615,7 @@ function CheckFlagResponseDataFromJSONTyped(json, ignoreDiscriminator) {
615
615
  error: json["error"] == null ? void 0 : json["error"],
616
616
  featureAllocation: json["feature_allocation"] == null ? void 0 : json["feature_allocation"],
617
617
  featureUsage: json["feature_usage"] == null ? void 0 : json["feature_usage"],
618
+ featureUsageEvent: json["feature_usage_event"] == null ? void 0 : json["feature_usage_event"],
618
619
  featureUsagePeriod: json["feature_usage_period"] == null ? void 0 : json["feature_usage_period"],
619
620
  featureUsageResetAt: json["feature_usage_reset_at"] == null ? void 0 : new Date(json["feature_usage_reset_at"]),
620
621
  flag: json["flag"],
@@ -704,6 +705,7 @@ var CheckFlagReturnFromJSON = (json) => {
704
705
  error,
705
706
  featureAllocation,
706
707
  featureUsage,
708
+ featureUsageEvent,
707
709
  featureUsagePeriod,
708
710
  featureUsageResetAt,
709
711
  flag,
@@ -723,6 +725,7 @@ var CheckFlagReturnFromJSON = (json) => {
723
725
  error: error == null ? void 0 : error,
724
726
  featureAllocation: featureAllocation == null ? void 0 : featureAllocation,
725
727
  featureUsage: featureUsage == null ? void 0 : featureUsage,
728
+ featureUsageEvent: featureUsageEvent === null ? void 0 : featureUsageEvent,
726
729
  featureUsagePeriod: featureUsagePeriod == null ? void 0 : featureUsagePeriod,
727
730
  featureUsageResetAt: featureUsageResetAt == null ? void 0 : featureUsageResetAt,
728
731
  flag,
@@ -748,7 +751,7 @@ function contextString(context) {
748
751
  }, {});
749
752
  return JSON.stringify(sortedContext);
750
753
  }
751
- var version = "1.2.2";
754
+ var version = "1.2.3";
752
755
  var anonymousIdKey = "schematicId";
753
756
  var Schematic = class {
754
757
  additionalHeaders = {};
@@ -767,6 +770,7 @@ var Schematic = class {
767
770
  storage;
768
771
  useWebSocket = false;
769
772
  checks = {};
773
+ featureUsageEventMap = {};
770
774
  webSocketUrl = "wss://api.schematichq.com";
771
775
  constructor(apiKey, options) {
772
776
  this.apiKey = apiKey;
@@ -861,6 +865,9 @@ var Schematic = class {
861
865
  const parsedResponse = CheckFlagResponseFromJSON(response);
862
866
  this.debug(`checkFlag result: ${key}`, parsedResponse);
863
867
  const result = CheckFlagReturnFromJSON(parsedResponse.data);
868
+ if (typeof result.featureUsageEvent === "string") {
869
+ this.updateFeatureUsageEventMap(result);
870
+ }
864
871
  this.submitFlagCheckEvent(key, result, context);
865
872
  return result.value;
866
873
  }).catch((error) => {
@@ -980,6 +987,9 @@ var Schematic = class {
980
987
  const data = CheckFlagResponseFromJSON(responseJson);
981
988
  this.debug(`fallbackToRest result: ${key}`, data);
982
989
  const result = CheckFlagReturnFromJSON(data.data);
990
+ if (typeof result.featureUsageEvent === "string") {
991
+ this.updateFeatureUsageEventMap(result);
992
+ }
983
993
  this.submitFlagCheckEvent(key, result, context);
984
994
  return result.value;
985
995
  } catch (error) {
@@ -1063,14 +1073,11 @@ var Schematic = class {
1063
1073
  * In offline mode, this will just set the context locally without connecting.
1064
1074
  */
1065
1075
  setContext = async (context) => {
1066
- if (this.isOffline()) {
1076
+ if (this.isOffline() || !this.useWebSocket) {
1067
1077
  this.context = context;
1068
1078
  this.setIsPending(false);
1069
1079
  return Promise.resolve();
1070
1080
  }
1071
- if (!this.useWebSocket) {
1072
- return Promise.resolve();
1073
- }
1074
1081
  try {
1075
1082
  this.setIsPending(true);
1076
1083
  if (!this.conn) {
@@ -1086,18 +1093,69 @@ var Schematic = class {
1086
1093
  /**
1087
1094
  * Send a track event
1088
1095
  * Track usage for a company and/or user.
1096
+ * Optimistically updates feature usage flags if tracking a featureUsageEvent.
1089
1097
  */
1090
1098
  track = (body) => {
1091
- const { company, user, event, traits } = body;
1099
+ const { company, user, event, traits, quantity = 1 } = body;
1092
1100
  const trackData = {
1093
1101
  company: company ?? this.context.company,
1094
1102
  event,
1095
1103
  traits: traits ?? {},
1096
- user: user ?? this.context.user
1104
+ user: user ?? this.context.user,
1105
+ quantity
1097
1106
  };
1098
1107
  this.debug(`track:`, trackData);
1108
+ if (event in this.featureUsageEventMap) {
1109
+ this.optimisticallyUpdateFeatureUsage(event, quantity);
1110
+ }
1099
1111
  return this.handleEvent("track", trackData);
1100
1112
  };
1113
+ /**
1114
+ * Optimistically update feature usage flags associated with a tracked event
1115
+ * This updates flags in memory with updated usage counts and value/featureUsageExceeded flags
1116
+ * before the network request completes
1117
+ */
1118
+ optimisticallyUpdateFeatureUsage = (eventName, quantity = 1) => {
1119
+ const flagsForEvent = this.featureUsageEventMap[eventName];
1120
+ if (flagsForEvent === void 0 || flagsForEvent === null) return;
1121
+ this.debug(
1122
+ `Optimistically updating feature usage for event: ${eventName}`,
1123
+ { quantity }
1124
+ );
1125
+ Object.entries(flagsForEvent).forEach(([flagKey, check]) => {
1126
+ if (check === void 0) return;
1127
+ const updatedCheck = { ...check };
1128
+ if (typeof updatedCheck.featureUsage === "number") {
1129
+ updatedCheck.featureUsage += quantity;
1130
+ if (typeof updatedCheck.featureAllocation === "number") {
1131
+ const wasExceeded = updatedCheck.featureUsageExceeded === true;
1132
+ const nowExceeded = updatedCheck.featureUsage >= updatedCheck.featureAllocation;
1133
+ if (nowExceeded !== wasExceeded) {
1134
+ updatedCheck.featureUsageExceeded = nowExceeded;
1135
+ if (nowExceeded) {
1136
+ updatedCheck.value = false;
1137
+ }
1138
+ this.debug(`Usage limit status changed for flag: ${flagKey}`, {
1139
+ was: wasExceeded ? "exceeded" : "within limits",
1140
+ now: nowExceeded ? "exceeded" : "within limits",
1141
+ featureUsage: updatedCheck.featureUsage,
1142
+ featureAllocation: updatedCheck.featureAllocation,
1143
+ value: updatedCheck.value
1144
+ });
1145
+ }
1146
+ }
1147
+ if (this.featureUsageEventMap[eventName] !== void 0) {
1148
+ this.featureUsageEventMap[eventName][flagKey] = updatedCheck;
1149
+ }
1150
+ const contextStr = contextString(this.context);
1151
+ if (this.checks[contextStr] !== void 0 && this.checks[contextStr] !== null) {
1152
+ this.checks[contextStr][flagKey] = updatedCheck;
1153
+ }
1154
+ this.notifyFlagCheckListeners(flagKey, updatedCheck);
1155
+ this.notifyFlagValueListeners(flagKey, updatedCheck.value);
1156
+ }
1157
+ });
1158
+ };
1101
1159
  /**
1102
1160
  * Event processing
1103
1161
  */
@@ -1240,12 +1298,19 @@ var Schematic = class {
1240
1298
  }
1241
1299
  (message.flags ?? []).forEach((flag) => {
1242
1300
  const flagCheck = CheckFlagReturnFromJSON(flag);
1243
- this.checks[contextString(context)][flagCheck.flag] = flagCheck;
1301
+ const contextStr = contextString(context);
1302
+ if (this.checks[contextStr] === void 0) {
1303
+ this.checks[contextStr] = {};
1304
+ }
1305
+ this.checks[contextStr][flagCheck.flag] = flagCheck;
1244
1306
  this.debug(`WebSocket flag update:`, {
1245
1307
  flag: flagCheck.flag,
1246
1308
  value: flagCheck.value,
1247
1309
  flagCheck
1248
1310
  });
1311
+ if (typeof flagCheck.featureUsageEvent === "string") {
1312
+ this.updateFeatureUsageEventMap(flagCheck);
1313
+ }
1249
1314
  if (this.flagCheckListeners[flag.flag]?.size > 0 || this.flagValueListeners[flag.flag]?.size > 0) {
1250
1315
  this.submitFlagCheckEvent(flagCheck.flag, flagCheck, context);
1251
1316
  }
@@ -1338,8 +1403,26 @@ var Schematic = class {
1338
1403
  check
1339
1404
  );
1340
1405
  }
1406
+ if (typeof check.featureUsageEvent === "string") {
1407
+ this.updateFeatureUsageEventMap(check);
1408
+ }
1341
1409
  listeners.forEach((listener) => notifyFlagCheckListener(listener, check));
1342
1410
  };
1411
+ /** Add or update a CheckFlagReturn in the featureUsageEventMap */
1412
+ updateFeatureUsageEventMap = (check) => {
1413
+ if (typeof check.featureUsageEvent !== "string") return;
1414
+ const eventName = check.featureUsageEvent;
1415
+ if (this.featureUsageEventMap[eventName] === void 0 || this.featureUsageEventMap[eventName] === null) {
1416
+ this.featureUsageEventMap[eventName] = {};
1417
+ }
1418
+ if (this.featureUsageEventMap[eventName] !== void 0) {
1419
+ this.featureUsageEventMap[eventName][check.flag] = check;
1420
+ }
1421
+ this.debug(
1422
+ `Updated featureUsageEventMap for event: ${eventName}, flag: ${check.flag}`,
1423
+ check
1424
+ );
1425
+ };
1343
1426
  notifyFlagValueListeners = (flagKey, value) => {
1344
1427
  const listeners = this.flagValueListeners?.[flagKey] ?? [];
1345
1428
  if (listeners.size > 0) {
@@ -1377,7 +1460,7 @@ var notifyFlagValueListener = (listener, value) => {
1377
1460
  import React, { createContext, useEffect, useMemo, useRef } from "react";
1378
1461
 
1379
1462
  // src/version.ts
1380
- var version2 = "1.2.4";
1463
+ var version2 = "1.2.5";
1381
1464
 
1382
1465
  // src/context/schematic.tsx
1383
1466
  import { jsx } from "react/jsx-runtime";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@schematichq/schematic-react",
3
- "version": "1.2.4",
3
+ "version": "1.2.5",
4
4
  "main": "dist/schematic-react.cjs.js",
5
5
  "module": "dist/schematic-react.esm.js",
6
6
  "types": "dist/schematic-react.d.ts",
@@ -25,31 +25,34 @@
25
25
  "format": "prettier --write \"src/**/*.{ts,tsx}\"",
26
26
  "lint": "eslint src --ext ts,tsx --report-unused-disable-directives --fix",
27
27
  "test": "jest --config jest.config.js",
28
- "tsc": "npx tsc"
28
+ "tsc": "npx tsc",
29
+ "prepare": "husky"
29
30
  },
30
31
  "dependencies": {
31
- "@schematichq/schematic-js": "^1.2.2"
32
+ "@schematichq/schematic-js": "^1.2.3"
32
33
  },
33
34
  "devDependencies": {
34
- "@microsoft/api-extractor": "^7.49.2",
35
+ "@eslint/js": "^9.24.0",
36
+ "@microsoft/api-extractor": "^7.52.2",
35
37
  "@types/jest": "^29.5.14",
36
- "@types/react": "^19.0.8",
37
- "@typescript-eslint/eslint-plugin": "^8.23.0",
38
- "@typescript-eslint/parser": "^8.23.0",
39
- "esbuild": "^0.25.0",
38
+ "@types/react": "^19.1.1",
39
+ "esbuild": "^0.25.2",
40
40
  "esbuild-jest": "^0.5.0",
41
- "eslint": "^8.57.1",
41
+ "eslint": "^9.24.0",
42
42
  "eslint-plugin-import": "^2.31.0",
43
- "eslint-plugin-react": "^7.37.4",
43
+ "eslint-plugin-react": "^7.37.5",
44
44
  "eslint-plugin-react-hooks": "^5.1.0",
45
+ "globals": "^16.0.0",
46
+ "husky": "^9.1.7",
45
47
  "jest": "^29.7.0",
46
48
  "jest-environment-jsdom": "^29.7.0",
47
49
  "jest-esbuild": "^0.3.0",
48
50
  "jest-fetch-mock": "^3.0.3",
49
51
  "prettier": "^3.4.2",
50
- "react": "^19.0.0",
51
- "ts-jest": "^29.2.5",
52
- "typescript": "^5.7.3"
52
+ "react": "^19.1.0",
53
+ "ts-jest": "^29.3.0",
54
+ "typescript": "^5.7.3",
55
+ "typescript-eslint": "^8.29.1"
53
56
  },
54
57
  "peerDependencies": {
55
58
  "react": ">=18"