@schematichq/schematic-react 1.2.7 → 1.2.8

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.
@@ -799,7 +799,7 @@ function contextString(context) {
799
799
  }, {});
800
800
  return JSON.stringify(sortedContext);
801
801
  }
802
- var version = "1.2.7";
802
+ var version = "1.2.8";
803
803
  var anonymousIdKey = "schematicId";
804
804
  var Schematic = class {
805
805
  additionalHeaders = {};
@@ -829,6 +829,15 @@ var Schematic = class {
829
829
  wsReconnectAttempts = 0;
830
830
  wsReconnectTimer = null;
831
831
  wsIntentionalDisconnect = false;
832
+ maxEventQueueSize = 100;
833
+ // Prevent memory issues with very long network outages
834
+ maxEventRetries = 5;
835
+ // Maximum retry attempts for failed events
836
+ eventRetryInitialDelay = 1e3;
837
+ // Initial retry delay in ms
838
+ eventRetryMaxDelay = 3e4;
839
+ // Maximum retry delay in ms
840
+ retryTimer = null;
832
841
  constructor(apiKey, options) {
833
842
  this.apiKey = apiKey;
834
843
  this.eventQueue = [];
@@ -887,6 +896,18 @@ var Schematic = class {
887
896
  if (options?.webSocketMaxRetryDelay !== void 0) {
888
897
  this.webSocketMaxRetryDelay = options.webSocketMaxRetryDelay;
889
898
  }
899
+ if (options?.maxEventQueueSize !== void 0) {
900
+ this.maxEventQueueSize = options.maxEventQueueSize;
901
+ }
902
+ if (options?.maxEventRetries !== void 0) {
903
+ this.maxEventRetries = options.maxEventRetries;
904
+ }
905
+ if (options?.eventRetryInitialDelay !== void 0) {
906
+ this.eventRetryInitialDelay = options.eventRetryInitialDelay;
907
+ }
908
+ if (options?.eventRetryMaxDelay !== void 0) {
909
+ this.eventRetryMaxDelay = options.eventRetryMaxDelay;
910
+ }
890
911
  if (typeof window !== "undefined" && window?.addEventListener) {
891
912
  window.addEventListener("beforeunload", () => {
892
913
  this.flushEventQueue();
@@ -1302,11 +1323,53 @@ var Schematic = class {
1302
1323
  }
1303
1324
  }
1304
1325
  };
1305
- flushEventQueue = () => {
1306
- while (this.eventQueue.length > 0) {
1307
- const event = this.eventQueue.shift();
1308
- if (event) {
1309
- this.sendEvent(event);
1326
+ startRetryTimer = () => {
1327
+ if (this.retryTimer !== null) {
1328
+ return;
1329
+ }
1330
+ this.retryTimer = setInterval(() => {
1331
+ this.flushEventQueue().catch((error) => {
1332
+ this.debug("Error in retry timer flush:", error);
1333
+ });
1334
+ if (this.eventQueue.length === 0) {
1335
+ this.stopRetryTimer();
1336
+ }
1337
+ }, 5e3);
1338
+ this.debug("Started retry timer");
1339
+ };
1340
+ stopRetryTimer = () => {
1341
+ if (this.retryTimer !== null) {
1342
+ clearInterval(this.retryTimer);
1343
+ this.retryTimer = null;
1344
+ this.debug("Stopped retry timer");
1345
+ }
1346
+ };
1347
+ flushEventQueue = async () => {
1348
+ if (this.eventQueue.length === 0) {
1349
+ return;
1350
+ }
1351
+ const now = Date.now();
1352
+ const readyEvents = [];
1353
+ const notReadyEvents = [];
1354
+ for (const event of this.eventQueue) {
1355
+ if (event.next_retry_at === void 0 || event.next_retry_at <= now) {
1356
+ readyEvents.push(event);
1357
+ } else {
1358
+ notReadyEvents.push(event);
1359
+ }
1360
+ }
1361
+ if (readyEvents.length === 0) {
1362
+ this.debug(`No events ready for retry yet (${notReadyEvents.length} still in backoff)`);
1363
+ return;
1364
+ }
1365
+ this.debug(`Flushing event queue: ${readyEvents.length} ready, ${notReadyEvents.length} waiting`);
1366
+ this.eventQueue = notReadyEvents;
1367
+ for (const event of readyEvents) {
1368
+ try {
1369
+ await this.sendEvent(event);
1370
+ this.debug(`Queued event sent successfully:`, event.type);
1371
+ } catch (error) {
1372
+ this.debug(`Failed to send queued event:`, error);
1310
1373
  }
1311
1374
  }
1312
1375
  };
@@ -1354,12 +1417,37 @@ var Schematic = class {
1354
1417
  },
1355
1418
  body: payload
1356
1419
  });
1420
+ if (!response.ok) {
1421
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
1422
+ }
1357
1423
  this.debug(`event sent:`, {
1358
1424
  status: response.status,
1359
1425
  statusText: response.statusText
1360
1426
  });
1361
1427
  } catch (error) {
1362
- console.error("Error sending Schematic event: ", error);
1428
+ const retryCount = (event.retry_count ?? 0) + 1;
1429
+ if (retryCount <= this.maxEventRetries) {
1430
+ this.debug(`Event failed to send (attempt ${retryCount}/${this.maxEventRetries}), queueing for retry:`, error);
1431
+ const baseDelay = this.eventRetryInitialDelay * Math.pow(2, retryCount - 1);
1432
+ const jitterDelay = Math.min(baseDelay, this.eventRetryMaxDelay);
1433
+ const nextRetryAt = Date.now() + jitterDelay;
1434
+ const retryEvent = {
1435
+ ...event,
1436
+ retry_count: retryCount,
1437
+ next_retry_at: nextRetryAt
1438
+ };
1439
+ if (this.eventQueue.length < this.maxEventQueueSize) {
1440
+ this.eventQueue.push(retryEvent);
1441
+ this.debug(`Event queued for retry in ${jitterDelay}ms (${this.eventQueue.length}/${this.maxEventQueueSize})`);
1442
+ } else {
1443
+ this.debug(`Event queue full (${this.maxEventQueueSize}), dropping oldest event`);
1444
+ this.eventQueue.shift();
1445
+ this.eventQueue.push(retryEvent);
1446
+ }
1447
+ this.startRetryTimer();
1448
+ } else {
1449
+ this.debug(`Event failed permanently after ${this.maxEventRetries} attempts, dropping:`, error);
1450
+ }
1363
1451
  }
1364
1452
  return Promise.resolve();
1365
1453
  };
@@ -1384,6 +1472,7 @@ var Schematic = class {
1384
1472
  clearTimeout(this.wsReconnectTimer);
1385
1473
  this.wsReconnectTimer = null;
1386
1474
  }
1475
+ this.stopRetryTimer();
1387
1476
  if (this.conn) {
1388
1477
  try {
1389
1478
  const socket = await this.conn;
@@ -1431,16 +1520,15 @@ var Schematic = class {
1431
1520
  * Handle browser coming back online
1432
1521
  */
1433
1522
  handleNetworkOnline = () => {
1434
- if (this.context.company === void 0 && this.context.user === void 0) {
1435
- this.debug("No context set, skipping reconnection");
1436
- return;
1437
- }
1523
+ this.debug("Network online, attempting reconnection and flushing queued events");
1438
1524
  this.wsReconnectAttempts = 0;
1439
1525
  if (this.wsReconnectTimer !== null) {
1440
1526
  clearTimeout(this.wsReconnectTimer);
1441
1527
  this.wsReconnectTimer = null;
1442
1528
  }
1443
- this.debug("Network online, reconnecting immediately");
1529
+ this.flushEventQueue().catch((error) => {
1530
+ this.debug("Error flushing event queue on network online:", error);
1531
+ });
1444
1532
  this.attemptReconnect();
1445
1533
  };
1446
1534
  /**
@@ -1470,10 +1558,20 @@ var Schematic = class {
1470
1558
  try {
1471
1559
  this.conn = this.wsConnect();
1472
1560
  const socket = await this.conn;
1561
+ this.debug(`Reconnection context check:`, {
1562
+ hasCompany: this.context.company !== void 0,
1563
+ hasUser: this.context.user !== void 0,
1564
+ context: this.context
1565
+ });
1473
1566
  if (this.context.company !== void 0 || this.context.user !== void 0) {
1474
- this.debug(`Reconnected, re-sending context`);
1475
- await this.wsSendMessage(socket, this.context);
1567
+ this.debug(`Reconnected, force re-sending context`);
1568
+ await this.wsSendContextAfterReconnection(socket, this.context);
1569
+ } else {
1570
+ this.debug(`No context to re-send after reconnection - websocket ready for new context`);
1476
1571
  }
1572
+ this.flushEventQueue().catch((error) => {
1573
+ this.debug("Error flushing event queue after websocket reconnection:", error);
1574
+ });
1477
1575
  this.debug(`Reconnection successful`);
1478
1576
  } catch (error) {
1479
1577
  this.debug(`Reconnection attempt failed:`, error);
@@ -1534,6 +1632,61 @@ var Schematic = class {
1534
1632
  };
1535
1633
  });
1536
1634
  };
1635
+ // Send a message on the websocket after reconnection, forcing the send even if context appears unchanged
1636
+ // because the server has lost all state and needs the initial context
1637
+ wsSendContextAfterReconnection = (socket, context) => {
1638
+ if (this.isOffline()) {
1639
+ this.debug("wsSendContextAfterReconnection: skipped (offline mode)");
1640
+ this.setIsPending(false);
1641
+ return Promise.resolve();
1642
+ }
1643
+ return new Promise((resolve) => {
1644
+ this.debug(`WebSocket force sending context after reconnection:`, context);
1645
+ this.context = context;
1646
+ const sendMessage = () => {
1647
+ let resolved = false;
1648
+ const messageHandler = (event) => {
1649
+ const message = JSON.parse(event.data);
1650
+ this.debug(`WebSocket message received after reconnection:`, message);
1651
+ if (!(contextString(context) in this.checks)) {
1652
+ this.checks[contextString(context)] = {};
1653
+ }
1654
+ (message.flags ?? []).forEach((flag) => {
1655
+ const flagCheck = CheckFlagReturnFromJSON(flag);
1656
+ const contextStr = contextString(context);
1657
+ if (this.checks[contextStr] === void 0) {
1658
+ this.checks[contextStr] = {};
1659
+ }
1660
+ this.checks[contextStr][flagCheck.flag] = flagCheck;
1661
+ });
1662
+ this.useWebSocket = true;
1663
+ socket.removeEventListener("message", messageHandler);
1664
+ if (!resolved) {
1665
+ resolved = true;
1666
+ resolve(this.setIsPending(false));
1667
+ }
1668
+ };
1669
+ socket.addEventListener("message", messageHandler);
1670
+ const clientVersion = this.additionalHeaders["X-Schematic-Client-Version"] ?? `schematic-js@${version}`;
1671
+ const messagePayload = {
1672
+ apiKey: this.apiKey,
1673
+ clientVersion,
1674
+ data: context
1675
+ };
1676
+ this.debug(`WebSocket sending forced message after reconnection:`, messagePayload);
1677
+ socket.send(JSON.stringify(messagePayload));
1678
+ };
1679
+ if (socket.readyState === WebSocket.OPEN) {
1680
+ this.debug(`WebSocket already open, sending forced message after reconnection`);
1681
+ sendMessage();
1682
+ } else {
1683
+ socket.addEventListener("open", () => {
1684
+ this.debug(`WebSocket opened, sending forced message after reconnection`);
1685
+ sendMessage();
1686
+ });
1687
+ }
1688
+ });
1689
+ };
1537
1690
  // Send a message on the websocket indicating interest in a particular evaluation context
1538
1691
  // and wait for the initial set of flag values to be returned
1539
1692
  wsSendMessage = (socket, context) => {
@@ -1722,7 +1875,7 @@ var notifyFlagValueListener = (listener, value) => {
1722
1875
  var import_react = __toESM(require("react"));
1723
1876
 
1724
1877
  // src/version.ts
1725
- var version2 = "1.2.7";
1878
+ var version2 = "1.2.8";
1726
1879
 
1727
1880
  // src/context/schematic.tsx
1728
1881
  var import_jsx_runtime = require("react/jsx-runtime");
@@ -754,7 +754,7 @@ function contextString(context) {
754
754
  }, {});
755
755
  return JSON.stringify(sortedContext);
756
756
  }
757
- var version = "1.2.7";
757
+ var version = "1.2.8";
758
758
  var anonymousIdKey = "schematicId";
759
759
  var Schematic = class {
760
760
  additionalHeaders = {};
@@ -784,6 +784,15 @@ var Schematic = class {
784
784
  wsReconnectAttempts = 0;
785
785
  wsReconnectTimer = null;
786
786
  wsIntentionalDisconnect = false;
787
+ maxEventQueueSize = 100;
788
+ // Prevent memory issues with very long network outages
789
+ maxEventRetries = 5;
790
+ // Maximum retry attempts for failed events
791
+ eventRetryInitialDelay = 1e3;
792
+ // Initial retry delay in ms
793
+ eventRetryMaxDelay = 3e4;
794
+ // Maximum retry delay in ms
795
+ retryTimer = null;
787
796
  constructor(apiKey, options) {
788
797
  this.apiKey = apiKey;
789
798
  this.eventQueue = [];
@@ -842,6 +851,18 @@ var Schematic = class {
842
851
  if (options?.webSocketMaxRetryDelay !== void 0) {
843
852
  this.webSocketMaxRetryDelay = options.webSocketMaxRetryDelay;
844
853
  }
854
+ if (options?.maxEventQueueSize !== void 0) {
855
+ this.maxEventQueueSize = options.maxEventQueueSize;
856
+ }
857
+ if (options?.maxEventRetries !== void 0) {
858
+ this.maxEventRetries = options.maxEventRetries;
859
+ }
860
+ if (options?.eventRetryInitialDelay !== void 0) {
861
+ this.eventRetryInitialDelay = options.eventRetryInitialDelay;
862
+ }
863
+ if (options?.eventRetryMaxDelay !== void 0) {
864
+ this.eventRetryMaxDelay = options.eventRetryMaxDelay;
865
+ }
845
866
  if (typeof window !== "undefined" && window?.addEventListener) {
846
867
  window.addEventListener("beforeunload", () => {
847
868
  this.flushEventQueue();
@@ -1257,11 +1278,53 @@ var Schematic = class {
1257
1278
  }
1258
1279
  }
1259
1280
  };
1260
- flushEventQueue = () => {
1261
- while (this.eventQueue.length > 0) {
1262
- const event = this.eventQueue.shift();
1263
- if (event) {
1264
- this.sendEvent(event);
1281
+ startRetryTimer = () => {
1282
+ if (this.retryTimer !== null) {
1283
+ return;
1284
+ }
1285
+ this.retryTimer = setInterval(() => {
1286
+ this.flushEventQueue().catch((error) => {
1287
+ this.debug("Error in retry timer flush:", error);
1288
+ });
1289
+ if (this.eventQueue.length === 0) {
1290
+ this.stopRetryTimer();
1291
+ }
1292
+ }, 5e3);
1293
+ this.debug("Started retry timer");
1294
+ };
1295
+ stopRetryTimer = () => {
1296
+ if (this.retryTimer !== null) {
1297
+ clearInterval(this.retryTimer);
1298
+ this.retryTimer = null;
1299
+ this.debug("Stopped retry timer");
1300
+ }
1301
+ };
1302
+ flushEventQueue = async () => {
1303
+ if (this.eventQueue.length === 0) {
1304
+ return;
1305
+ }
1306
+ const now = Date.now();
1307
+ const readyEvents = [];
1308
+ const notReadyEvents = [];
1309
+ for (const event of this.eventQueue) {
1310
+ if (event.next_retry_at === void 0 || event.next_retry_at <= now) {
1311
+ readyEvents.push(event);
1312
+ } else {
1313
+ notReadyEvents.push(event);
1314
+ }
1315
+ }
1316
+ if (readyEvents.length === 0) {
1317
+ this.debug(`No events ready for retry yet (${notReadyEvents.length} still in backoff)`);
1318
+ return;
1319
+ }
1320
+ this.debug(`Flushing event queue: ${readyEvents.length} ready, ${notReadyEvents.length} waiting`);
1321
+ this.eventQueue = notReadyEvents;
1322
+ for (const event of readyEvents) {
1323
+ try {
1324
+ await this.sendEvent(event);
1325
+ this.debug(`Queued event sent successfully:`, event.type);
1326
+ } catch (error) {
1327
+ this.debug(`Failed to send queued event:`, error);
1265
1328
  }
1266
1329
  }
1267
1330
  };
@@ -1309,12 +1372,37 @@ var Schematic = class {
1309
1372
  },
1310
1373
  body: payload
1311
1374
  });
1375
+ if (!response.ok) {
1376
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
1377
+ }
1312
1378
  this.debug(`event sent:`, {
1313
1379
  status: response.status,
1314
1380
  statusText: response.statusText
1315
1381
  });
1316
1382
  } catch (error) {
1317
- console.error("Error sending Schematic event: ", error);
1383
+ const retryCount = (event.retry_count ?? 0) + 1;
1384
+ if (retryCount <= this.maxEventRetries) {
1385
+ this.debug(`Event failed to send (attempt ${retryCount}/${this.maxEventRetries}), queueing for retry:`, error);
1386
+ const baseDelay = this.eventRetryInitialDelay * Math.pow(2, retryCount - 1);
1387
+ const jitterDelay = Math.min(baseDelay, this.eventRetryMaxDelay);
1388
+ const nextRetryAt = Date.now() + jitterDelay;
1389
+ const retryEvent = {
1390
+ ...event,
1391
+ retry_count: retryCount,
1392
+ next_retry_at: nextRetryAt
1393
+ };
1394
+ if (this.eventQueue.length < this.maxEventQueueSize) {
1395
+ this.eventQueue.push(retryEvent);
1396
+ this.debug(`Event queued for retry in ${jitterDelay}ms (${this.eventQueue.length}/${this.maxEventQueueSize})`);
1397
+ } else {
1398
+ this.debug(`Event queue full (${this.maxEventQueueSize}), dropping oldest event`);
1399
+ this.eventQueue.shift();
1400
+ this.eventQueue.push(retryEvent);
1401
+ }
1402
+ this.startRetryTimer();
1403
+ } else {
1404
+ this.debug(`Event failed permanently after ${this.maxEventRetries} attempts, dropping:`, error);
1405
+ }
1318
1406
  }
1319
1407
  return Promise.resolve();
1320
1408
  };
@@ -1339,6 +1427,7 @@ var Schematic = class {
1339
1427
  clearTimeout(this.wsReconnectTimer);
1340
1428
  this.wsReconnectTimer = null;
1341
1429
  }
1430
+ this.stopRetryTimer();
1342
1431
  if (this.conn) {
1343
1432
  try {
1344
1433
  const socket = await this.conn;
@@ -1386,16 +1475,15 @@ var Schematic = class {
1386
1475
  * Handle browser coming back online
1387
1476
  */
1388
1477
  handleNetworkOnline = () => {
1389
- if (this.context.company === void 0 && this.context.user === void 0) {
1390
- this.debug("No context set, skipping reconnection");
1391
- return;
1392
- }
1478
+ this.debug("Network online, attempting reconnection and flushing queued events");
1393
1479
  this.wsReconnectAttempts = 0;
1394
1480
  if (this.wsReconnectTimer !== null) {
1395
1481
  clearTimeout(this.wsReconnectTimer);
1396
1482
  this.wsReconnectTimer = null;
1397
1483
  }
1398
- this.debug("Network online, reconnecting immediately");
1484
+ this.flushEventQueue().catch((error) => {
1485
+ this.debug("Error flushing event queue on network online:", error);
1486
+ });
1399
1487
  this.attemptReconnect();
1400
1488
  };
1401
1489
  /**
@@ -1425,10 +1513,20 @@ var Schematic = class {
1425
1513
  try {
1426
1514
  this.conn = this.wsConnect();
1427
1515
  const socket = await this.conn;
1516
+ this.debug(`Reconnection context check:`, {
1517
+ hasCompany: this.context.company !== void 0,
1518
+ hasUser: this.context.user !== void 0,
1519
+ context: this.context
1520
+ });
1428
1521
  if (this.context.company !== void 0 || this.context.user !== void 0) {
1429
- this.debug(`Reconnected, re-sending context`);
1430
- await this.wsSendMessage(socket, this.context);
1522
+ this.debug(`Reconnected, force re-sending context`);
1523
+ await this.wsSendContextAfterReconnection(socket, this.context);
1524
+ } else {
1525
+ this.debug(`No context to re-send after reconnection - websocket ready for new context`);
1431
1526
  }
1527
+ this.flushEventQueue().catch((error) => {
1528
+ this.debug("Error flushing event queue after websocket reconnection:", error);
1529
+ });
1432
1530
  this.debug(`Reconnection successful`);
1433
1531
  } catch (error) {
1434
1532
  this.debug(`Reconnection attempt failed:`, error);
@@ -1489,6 +1587,61 @@ var Schematic = class {
1489
1587
  };
1490
1588
  });
1491
1589
  };
1590
+ // Send a message on the websocket after reconnection, forcing the send even if context appears unchanged
1591
+ // because the server has lost all state and needs the initial context
1592
+ wsSendContextAfterReconnection = (socket, context) => {
1593
+ if (this.isOffline()) {
1594
+ this.debug("wsSendContextAfterReconnection: skipped (offline mode)");
1595
+ this.setIsPending(false);
1596
+ return Promise.resolve();
1597
+ }
1598
+ return new Promise((resolve) => {
1599
+ this.debug(`WebSocket force sending context after reconnection:`, context);
1600
+ this.context = context;
1601
+ const sendMessage = () => {
1602
+ let resolved = false;
1603
+ const messageHandler = (event) => {
1604
+ const message = JSON.parse(event.data);
1605
+ this.debug(`WebSocket message received after reconnection:`, message);
1606
+ if (!(contextString(context) in this.checks)) {
1607
+ this.checks[contextString(context)] = {};
1608
+ }
1609
+ (message.flags ?? []).forEach((flag) => {
1610
+ const flagCheck = CheckFlagReturnFromJSON(flag);
1611
+ const contextStr = contextString(context);
1612
+ if (this.checks[contextStr] === void 0) {
1613
+ this.checks[contextStr] = {};
1614
+ }
1615
+ this.checks[contextStr][flagCheck.flag] = flagCheck;
1616
+ });
1617
+ this.useWebSocket = true;
1618
+ socket.removeEventListener("message", messageHandler);
1619
+ if (!resolved) {
1620
+ resolved = true;
1621
+ resolve(this.setIsPending(false));
1622
+ }
1623
+ };
1624
+ socket.addEventListener("message", messageHandler);
1625
+ const clientVersion = this.additionalHeaders["X-Schematic-Client-Version"] ?? `schematic-js@${version}`;
1626
+ const messagePayload = {
1627
+ apiKey: this.apiKey,
1628
+ clientVersion,
1629
+ data: context
1630
+ };
1631
+ this.debug(`WebSocket sending forced message after reconnection:`, messagePayload);
1632
+ socket.send(JSON.stringify(messagePayload));
1633
+ };
1634
+ if (socket.readyState === WebSocket.OPEN) {
1635
+ this.debug(`WebSocket already open, sending forced message after reconnection`);
1636
+ sendMessage();
1637
+ } else {
1638
+ socket.addEventListener("open", () => {
1639
+ this.debug(`WebSocket opened, sending forced message after reconnection`);
1640
+ sendMessage();
1641
+ });
1642
+ }
1643
+ });
1644
+ };
1492
1645
  // Send a message on the websocket indicating interest in a particular evaluation context
1493
1646
  // and wait for the initial set of flag values to be returned
1494
1647
  wsSendMessage = (socket, context) => {
@@ -1677,7 +1830,7 @@ var notifyFlagValueListener = (listener, value) => {
1677
1830
  import React, { createContext, useEffect, useMemo, useRef } from "react";
1678
1831
 
1679
1832
  // src/version.ts
1680
- var version2 = "1.2.7";
1833
+ var version2 = "1.2.8";
1681
1834
 
1682
1835
  // src/context/schematic.tsx
1683
1836
  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.7",
3
+ "version": "1.2.8",
4
4
  "main": "dist/schematic-react.cjs.js",
5
5
  "module": "dist/schematic-react.esm.js",
6
6
  "types": "dist/schematic-react.d.ts",
@@ -31,7 +31,7 @@
31
31
  "prepare": "husky"
32
32
  },
33
33
  "dependencies": {
34
- "@schematichq/schematic-js": "^1.2.7"
34
+ "@schematichq/schematic-js": "^1.2.8"
35
35
  },
36
36
  "devDependencies": {
37
37
  "@eslint/js": "^9.39.1",
@@ -39,7 +39,7 @@
39
39
  "@testing-library/dom": "^10.4.1",
40
40
  "@testing-library/jest-dom": "^6.9.1",
41
41
  "@testing-library/react": "^16.3.0",
42
- "@types/react": "^19.2.3",
42
+ "@types/react": "^19.2.6",
43
43
  "@vitest/browser": "^4.0.8",
44
44
  "esbuild": "^0.27.0",
45
45
  "eslint": "^9.39.1",
@@ -54,7 +54,7 @@
54
54
  "react": "^19.2.0",
55
55
  "react-dom": "^19.2.0",
56
56
  "typescript": "^5.9.3",
57
- "typescript-eslint": "^8.46.4",
57
+ "typescript-eslint": "^8.47.0",
58
58
  "vitest": "^4.0.8"
59
59
  },
60
60
  "peerDependencies": {