@schematichq/schematic-js 1.2.9 → 1.2.11

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.
@@ -781,7 +781,7 @@ function contextString(context) {
781
781
  }
782
782
 
783
783
  // src/version.ts
784
- var version = "1.2.9";
784
+ var version = "1.2.11";
785
785
 
786
786
  // src/index.ts
787
787
  var anonymousIdKey = "schematicId";
@@ -813,6 +813,8 @@ var Schematic = class {
813
813
  wsReconnectAttempts = 0;
814
814
  wsReconnectTimer = null;
815
815
  wsIntentionalDisconnect = false;
816
+ currentWebSocket = null;
817
+ isConnecting = false;
816
818
  maxEventQueueSize = 100;
817
819
  // Prevent memory issues with very long network outages
818
820
  maxEventRetries = 5;
@@ -1090,6 +1092,49 @@ var Schematic = class {
1090
1092
  console.log(`[Schematic] ${message}`, ...args);
1091
1093
  }
1092
1094
  }
1095
+ /**
1096
+ * Create a persistent message handler for websocket flag updates
1097
+ */
1098
+ createPersistentMessageHandler(context) {
1099
+ return (event) => {
1100
+ const message = JSON.parse(event.data);
1101
+ this.debug(`WebSocket persistent message received:`, message);
1102
+ if (!(contextString(context) in this.checks)) {
1103
+ this.checks[contextString(context)] = {};
1104
+ }
1105
+ (message.flags ?? []).forEach((flag) => {
1106
+ const flagCheck = CheckFlagReturnFromJSON(flag);
1107
+ const contextStr = contextString(context);
1108
+ if (this.checks[contextStr] === void 0) {
1109
+ this.checks[contextStr] = {};
1110
+ }
1111
+ this.checks[contextStr][flagCheck.flag] = flagCheck;
1112
+ this.debug(`WebSocket flag update:`, {
1113
+ flag: flagCheck.flag,
1114
+ value: flagCheck.value,
1115
+ flagCheck
1116
+ });
1117
+ if (typeof flagCheck.featureUsageEvent === "string") {
1118
+ this.updateFeatureUsageEventMap(flagCheck);
1119
+ }
1120
+ if ((this.flagCheckListeners[flag.flag]?.size ?? 0) > 0 || (this.flagValueListeners[flag.flag]?.size ?? 0) > 0) {
1121
+ this.submitFlagCheckEvent(flagCheck.flag, flagCheck, context);
1122
+ }
1123
+ this.debug(`About to notify listeners for flag ${flag.flag}`, {
1124
+ flag: flag.flag,
1125
+ value: flagCheck.value
1126
+ });
1127
+ this.notifyFlagCheckListeners(flag.flag, flagCheck);
1128
+ this.notifyFlagValueListeners(flag.flag, flagCheck.value);
1129
+ this.debug(`Finished notifying listeners for flag ${flag.flag}`, {
1130
+ flag: flag.flag,
1131
+ value: flagCheck.value
1132
+ });
1133
+ });
1134
+ this.flushContextDependentEventQueue();
1135
+ this.setIsPending(false);
1136
+ };
1137
+ }
1093
1138
  /**
1094
1139
  * Helper function to check if client is in offline mode
1095
1140
  */
@@ -1241,6 +1286,19 @@ var Schematic = class {
1241
1286
  try {
1242
1287
  this.setIsPending(true);
1243
1288
  if (!this.conn) {
1289
+ if (this.isConnecting) {
1290
+ this.debug(
1291
+ `Connection already in progress, waiting for it to complete`
1292
+ );
1293
+ while (this.isConnecting && this.conn === null) {
1294
+ await new Promise((resolve) => setTimeout(resolve, 10));
1295
+ }
1296
+ if (this.conn !== null) {
1297
+ const socket2 = await this.conn;
1298
+ await this.wsSendMessage(socket2, context);
1299
+ return;
1300
+ }
1301
+ }
1244
1302
  if (this.wsReconnectTimer !== null) {
1245
1303
  this.debug(
1246
1304
  `Cancelling scheduled reconnection, connecting immediately`
@@ -1248,7 +1306,17 @@ var Schematic = class {
1248
1306
  clearTimeout(this.wsReconnectTimer);
1249
1307
  this.wsReconnectTimer = null;
1250
1308
  }
1251
- this.conn = this.wsConnect();
1309
+ this.isConnecting = true;
1310
+ try {
1311
+ this.conn = this.wsConnect();
1312
+ const socket2 = await this.conn;
1313
+ this.isConnecting = false;
1314
+ await this.wsSendMessage(socket2, context);
1315
+ return;
1316
+ } catch (error) {
1317
+ this.isConnecting = false;
1318
+ throw error;
1319
+ }
1252
1320
  }
1253
1321
  const socket = await this.conn;
1254
1322
  await this.wsSendMessage(socket, context);
@@ -1413,10 +1481,14 @@ var Schematic = class {
1413
1481
  }
1414
1482
  }
1415
1483
  if (readyEvents.length === 0) {
1416
- this.debug(`No events ready for retry yet (${notReadyEvents.length} still in backoff)`);
1484
+ this.debug(
1485
+ `No events ready for retry yet (${notReadyEvents.length} still in backoff)`
1486
+ );
1417
1487
  return;
1418
1488
  }
1419
- this.debug(`Flushing event queue: ${readyEvents.length} ready, ${notReadyEvents.length} waiting`);
1489
+ this.debug(
1490
+ `Flushing event queue: ${readyEvents.length} ready, ${notReadyEvents.length} waiting`
1491
+ );
1420
1492
  this.eventQueue = notReadyEvents;
1421
1493
  for (const event of readyEvents) {
1422
1494
  try {
@@ -1481,7 +1553,10 @@ var Schematic = class {
1481
1553
  } catch (error) {
1482
1554
  const retryCount = (event.retry_count ?? 0) + 1;
1483
1555
  if (retryCount <= this.maxEventRetries) {
1484
- this.debug(`Event failed to send (attempt ${retryCount}/${this.maxEventRetries}), queueing for retry:`, error);
1556
+ this.debug(
1557
+ `Event failed to send (attempt ${retryCount}/${this.maxEventRetries}), queueing for retry:`,
1558
+ error
1559
+ );
1485
1560
  const baseDelay = this.eventRetryInitialDelay * Math.pow(2, retryCount - 1);
1486
1561
  const jitterDelay = Math.min(baseDelay, this.eventRetryMaxDelay);
1487
1562
  const nextRetryAt = Date.now() + jitterDelay;
@@ -1492,15 +1567,22 @@ var Schematic = class {
1492
1567
  };
1493
1568
  if (this.eventQueue.length < this.maxEventQueueSize) {
1494
1569
  this.eventQueue.push(retryEvent);
1495
- this.debug(`Event queued for retry in ${jitterDelay}ms (${this.eventQueue.length}/${this.maxEventQueueSize})`);
1570
+ this.debug(
1571
+ `Event queued for retry in ${jitterDelay}ms (${this.eventQueue.length}/${this.maxEventQueueSize})`
1572
+ );
1496
1573
  } else {
1497
- this.debug(`Event queue full (${this.maxEventQueueSize}), dropping oldest event`);
1574
+ this.debug(
1575
+ `Event queue full (${this.maxEventQueueSize}), dropping oldest event`
1576
+ );
1498
1577
  this.eventQueue.shift();
1499
1578
  this.eventQueue.push(retryEvent);
1500
1579
  }
1501
1580
  this.startRetryTimer();
1502
1581
  } else {
1503
- this.debug(`Event failed permanently after ${this.maxEventRetries} attempts, dropping:`, error);
1582
+ this.debug(
1583
+ `Event failed permanently after ${this.maxEventRetries} attempts, dropping:`,
1584
+ error
1585
+ );
1504
1586
  }
1505
1587
  }
1506
1588
  return Promise.resolve();
@@ -1530,12 +1612,95 @@ var Schematic = class {
1530
1612
  if (this.conn) {
1531
1613
  try {
1532
1614
  const socket = await this.conn;
1615
+ if (this.currentWebSocket === socket) {
1616
+ this.debug(`Cleaning up current websocket tracking`);
1617
+ this.currentWebSocket = null;
1618
+ }
1533
1619
  socket.close();
1534
1620
  } catch (error) {
1535
1621
  console.error("Error during cleanup:", error);
1536
1622
  } finally {
1537
1623
  this.conn = null;
1624
+ this.currentWebSocket = null;
1625
+ this.isConnecting = false;
1626
+ }
1627
+ }
1628
+ };
1629
+ /**
1630
+ * Force an immediate WebSocket reconnection.
1631
+ * This is useful when the application returns from a background state (e.g., mobile app
1632
+ * coming back to foreground) and wants to immediately re-establish the connection
1633
+ * rather than waiting for the exponential backoff timer.
1634
+ *
1635
+ * This method will:
1636
+ * - Cancel any pending reconnection timer
1637
+ * - Reset the reconnection attempt counter
1638
+ * - Immediately attempt to reconnect
1639
+ * - Re-send the current context to get fresh flag values
1640
+ *
1641
+ * If a connection is already active and healthy, this will close it and create a new one.
1642
+ * If you just want to ensure a connection exists, check the connection state first.
1643
+ *
1644
+ * @example
1645
+ * ```typescript
1646
+ * // React Native example: reconnect when app comes to foreground
1647
+ * useEffect(() => {
1648
+ * const subscription = AppState.addEventListener("change", (state) => {
1649
+ * if (state === "active") {
1650
+ * client.forceReconnect();
1651
+ * }
1652
+ * });
1653
+ * return () => subscription.remove();
1654
+ * }, [client]);
1655
+ * ```
1656
+ */
1657
+ forceReconnect = async () => {
1658
+ if (this.isOffline()) {
1659
+ this.debug("forceReconnect: skipped (offline mode)");
1660
+ return Promise.resolve();
1661
+ }
1662
+ this.debug("forceReconnect: forcing immediate reconnection");
1663
+ this.wsIntentionalDisconnect = false;
1664
+ if (this.wsReconnectTimer !== null) {
1665
+ this.debug("forceReconnect: cancelling pending reconnection timer");
1666
+ clearTimeout(this.wsReconnectTimer);
1667
+ this.wsReconnectTimer = null;
1668
+ }
1669
+ this.wsReconnectAttempts = 0;
1670
+ if (this.conn !== null) {
1671
+ this.debug("forceReconnect: closing existing connection");
1672
+ try {
1673
+ const existingSocket = await this.conn;
1674
+ if (this.currentWebSocket === existingSocket) {
1675
+ this.currentWebSocket = null;
1676
+ }
1677
+ if (existingSocket.readyState === WebSocket.OPEN || existingSocket.readyState === WebSocket.CONNECTING) {
1678
+ existingSocket.close();
1679
+ }
1680
+ } catch (error) {
1681
+ this.debug("forceReconnect: error closing existing connection:", error);
1682
+ }
1683
+ this.conn = null;
1684
+ this.isConnecting = false;
1685
+ }
1686
+ if (this.context.company !== void 0 || this.context.user !== void 0) {
1687
+ this.debug("forceReconnect: reconnecting with existing context");
1688
+ try {
1689
+ this.isConnecting = true;
1690
+ this.conn = this.wsConnect();
1691
+ const socket = await this.conn;
1692
+ this.isConnecting = false;
1693
+ await this.wsSendMessage(socket, this.context, true);
1694
+ this.debug("forceReconnect: reconnection successful");
1695
+ } catch (error) {
1696
+ this.isConnecting = false;
1697
+ this.debug("forceReconnect: reconnection failed:", error);
1698
+ this.attemptReconnect();
1538
1699
  }
1700
+ } else {
1701
+ this.debug(
1702
+ "forceReconnect: no context available, websocket will connect when context is set"
1703
+ );
1539
1704
  }
1540
1705
  };
1541
1706
  /**
@@ -1559,7 +1724,9 @@ var Schematic = class {
1559
1724
  if (this.conn !== null) {
1560
1725
  try {
1561
1726
  const socket = await this.conn;
1562
- socket.close();
1727
+ if (socket.readyState === WebSocket.OPEN || socket.readyState === WebSocket.CONNECTING) {
1728
+ socket.close();
1729
+ }
1563
1730
  } catch (error) {
1564
1731
  this.debug("Error closing connection on offline:", error);
1565
1732
  }
@@ -1574,7 +1741,9 @@ var Schematic = class {
1574
1741
  * Handle browser coming back online
1575
1742
  */
1576
1743
  handleNetworkOnline = () => {
1577
- this.debug("Network online, attempting reconnection and flushing queued events");
1744
+ this.debug(
1745
+ "Network online, attempting reconnection and flushing queued events"
1746
+ );
1578
1747
  this.wsReconnectAttempts = 0;
1579
1748
  if (this.wsReconnectTimer !== null) {
1580
1749
  clearTimeout(this.wsReconnectTimer);
@@ -1597,7 +1766,10 @@ var Schematic = class {
1597
1766
  return;
1598
1767
  }
1599
1768
  if (this.wsReconnectTimer !== null) {
1600
- clearTimeout(this.wsReconnectTimer);
1769
+ this.debug(
1770
+ `Reconnection attempt already scheduled, ignoring duplicate request`
1771
+ );
1772
+ return;
1601
1773
  }
1602
1774
  const delay = this.calculateReconnectDelay();
1603
1775
  this.debug(
@@ -1610,23 +1782,57 @@ var Schematic = class {
1610
1782
  `Attempting to reconnect (attempt ${this.wsReconnectAttempts}/${this.webSocketMaxReconnectAttempts})`
1611
1783
  );
1612
1784
  try {
1613
- this.conn = this.wsConnect();
1614
- const socket = await this.conn;
1615
- this.debug(`Reconnection context check:`, {
1616
- hasCompany: this.context.company !== void 0,
1617
- hasUser: this.context.user !== void 0,
1618
- context: this.context
1619
- });
1620
- if (this.context.company !== void 0 || this.context.user !== void 0) {
1621
- this.debug(`Reconnected, force re-sending context`);
1622
- await this.wsSendContextAfterReconnection(socket, this.context);
1623
- } else {
1624
- this.debug(`No context to re-send after reconnection - websocket ready for new context`);
1785
+ if (this.conn !== null) {
1786
+ this.debug(`Cleaning up existing connection before reconnection`);
1787
+ try {
1788
+ const existingSocket = await this.conn;
1789
+ if (this.currentWebSocket === existingSocket) {
1790
+ this.debug(`Existing websocket is current, will be replaced`);
1791
+ this.currentWebSocket = null;
1792
+ }
1793
+ if (existingSocket.readyState === WebSocket.OPEN || existingSocket.readyState === WebSocket.CONNECTING) {
1794
+ existingSocket.close();
1795
+ }
1796
+ } catch (error) {
1797
+ this.debug(`Error cleaning up existing connection:`, error);
1798
+ }
1799
+ this.conn = null;
1800
+ this.currentWebSocket = null;
1801
+ this.isConnecting = false;
1802
+ }
1803
+ this.isConnecting = true;
1804
+ try {
1805
+ this.conn = this.wsConnect();
1806
+ const socket = await this.conn;
1807
+ this.isConnecting = false;
1808
+ this.debug(`Reconnection context check:`, {
1809
+ hasCompany: this.context.company !== void 0,
1810
+ hasUser: this.context.user !== void 0,
1811
+ context: this.context
1812
+ });
1813
+ if (this.context.company !== void 0 || this.context.user !== void 0) {
1814
+ this.debug(`Reconnected, force re-sending context`);
1815
+ await this.wsSendMessage(socket, this.context, true);
1816
+ } else {
1817
+ this.debug(
1818
+ `No context to re-send after reconnection - websocket ready for new context`
1819
+ );
1820
+ this.debug(
1821
+ `Setting up tracking for reconnected websocket (no context to send)`
1822
+ );
1823
+ this.currentWebSocket = socket;
1824
+ }
1825
+ this.flushEventQueue().catch((error) => {
1826
+ this.debug(
1827
+ "Error flushing event queue after websocket reconnection:",
1828
+ error
1829
+ );
1830
+ });
1831
+ this.debug(`Reconnection successful`);
1832
+ } catch (error) {
1833
+ this.isConnecting = false;
1834
+ throw error;
1625
1835
  }
1626
- this.flushEventQueue().catch((error) => {
1627
- this.debug("Error flushing event queue after websocket reconnection:", error);
1628
- });
1629
- this.debug(`Reconnection successful`);
1630
1836
  } catch (error) {
1631
1837
  this.debug(`Reconnection attempt failed:`, error);
1632
1838
  }
@@ -1644,6 +1850,8 @@ var Schematic = class {
1644
1850
  const wsUrl = `${this.webSocketUrl}/flags/bootstrap?apiKey=${this.apiKey}`;
1645
1851
  this.debug(`connecting to WebSocket:`, wsUrl);
1646
1852
  const webSocket = new WebSocket(wsUrl);
1853
+ const connectionId = Math.random().toString(36).substring(7);
1854
+ this.debug(`Creating WebSocket connection ${connectionId} to ${wsUrl}`);
1647
1855
  let timeoutId = null;
1648
1856
  let isResolved = false;
1649
1857
  timeoutId = setTimeout(() => {
@@ -1662,7 +1870,7 @@ var Schematic = class {
1662
1870
  }
1663
1871
  this.wsReconnectAttempts = 0;
1664
1872
  this.wsIntentionalDisconnect = false;
1665
- this.debug(`WebSocket connection opened`);
1873
+ this.debug(`WebSocket connection ${connectionId} opened successfully`);
1666
1874
  resolve(webSocket);
1667
1875
  };
1668
1876
  webSocket.onerror = (error) => {
@@ -1670,7 +1878,7 @@ var Schematic = class {
1670
1878
  if (timeoutId !== null) {
1671
1879
  clearTimeout(timeoutId);
1672
1880
  }
1673
- this.debug(`WebSocket connection error:`, error);
1881
+ this.debug(`WebSocket connection ${connectionId} error:`, error);
1674
1882
  reject(error);
1675
1883
  };
1676
1884
  webSocket.onclose = () => {
@@ -1678,121 +1886,48 @@ var Schematic = class {
1678
1886
  if (timeoutId !== null) {
1679
1887
  clearTimeout(timeoutId);
1680
1888
  }
1681
- this.debug(`WebSocket connection closed`);
1889
+ this.debug(`WebSocket connection ${connectionId} closed`);
1682
1890
  this.conn = null;
1891
+ if (this.currentWebSocket === webSocket) {
1892
+ this.currentWebSocket = null;
1893
+ this.isConnecting = false;
1894
+ }
1683
1895
  if (!this.wsIntentionalDisconnect && this.webSocketReconnect) {
1684
1896
  this.attemptReconnect();
1685
1897
  }
1686
1898
  };
1687
1899
  });
1688
1900
  };
1689
- // Send a message on the websocket after reconnection, forcing the send even if context appears unchanged
1690
- // because the server has lost all state and needs the initial context
1691
- wsSendContextAfterReconnection = (socket, context) => {
1692
- if (this.isOffline()) {
1693
- this.debug("wsSendContextAfterReconnection: skipped (offline mode)");
1694
- this.setIsPending(false);
1695
- return Promise.resolve();
1696
- }
1697
- return new Promise((resolve) => {
1698
- this.debug(`WebSocket force sending context after reconnection:`, context);
1699
- this.context = context;
1700
- const sendMessage = () => {
1701
- let resolved = false;
1702
- const messageHandler = (event) => {
1703
- const message = JSON.parse(event.data);
1704
- this.debug(`WebSocket message received after reconnection:`, message);
1705
- if (!(contextString(context) in this.checks)) {
1706
- this.checks[contextString(context)] = {};
1707
- }
1708
- (message.flags ?? []).forEach((flag) => {
1709
- const flagCheck = CheckFlagReturnFromJSON(flag);
1710
- const contextStr = contextString(context);
1711
- if (this.checks[contextStr] === void 0) {
1712
- this.checks[contextStr] = {};
1713
- }
1714
- this.checks[contextStr][flagCheck.flag] = flagCheck;
1715
- });
1716
- this.useWebSocket = true;
1717
- socket.removeEventListener("message", messageHandler);
1718
- if (!resolved) {
1719
- resolved = true;
1720
- resolve(this.setIsPending(false));
1721
- }
1722
- };
1723
- socket.addEventListener("message", messageHandler);
1724
- const clientVersion = this.additionalHeaders["X-Schematic-Client-Version"] ?? `schematic-js@${version}`;
1725
- const messagePayload = {
1726
- apiKey: this.apiKey,
1727
- clientVersion,
1728
- data: context
1729
- };
1730
- this.debug(`WebSocket sending forced message after reconnection:`, messagePayload);
1731
- socket.send(JSON.stringify(messagePayload));
1732
- };
1733
- if (socket.readyState === WebSocket.OPEN) {
1734
- this.debug(`WebSocket already open, sending forced message after reconnection`);
1735
- sendMessage();
1736
- } else {
1737
- socket.addEventListener("open", () => {
1738
- this.debug(`WebSocket opened, sending forced message after reconnection`);
1739
- sendMessage();
1740
- });
1741
- }
1742
- });
1743
- };
1744
1901
  // Send a message on the websocket indicating interest in a particular evaluation context
1745
1902
  // and wait for the initial set of flag values to be returned
1746
- wsSendMessage = (socket, context) => {
1903
+ wsSendMessage = (socket, context, forceContextSend = false) => {
1747
1904
  if (this.isOffline()) {
1748
1905
  this.debug("wsSendMessage: skipped (offline mode)");
1749
1906
  this.setIsPending(false);
1750
1907
  return Promise.resolve();
1751
1908
  }
1752
1909
  return new Promise((resolve, reject) => {
1753
- if (contextString(context) == contextString(this.context)) {
1910
+ if (!forceContextSend && contextString(context) == contextString(this.context)) {
1754
1911
  this.debug(`WebSocket context unchanged, skipping update`);
1755
1912
  return resolve(this.setIsPending(false));
1756
1913
  }
1757
- this.debug(`WebSocket context updated:`, context);
1914
+ this.debug(
1915
+ forceContextSend ? `WebSocket force sending context (reconnection):` : `WebSocket context updated:`,
1916
+ context
1917
+ );
1758
1918
  this.context = context;
1759
1919
  const sendMessage = () => {
1760
1920
  let resolved = false;
1921
+ const persistentMessageHandler = this.createPersistentMessageHandler(context);
1761
1922
  const messageHandler = (event) => {
1762
- const message = JSON.parse(event.data);
1763
- this.debug(`WebSocket message received:`, message);
1764
- if (!(contextString(context) in this.checks)) {
1765
- this.checks[contextString(context)] = {};
1766
- }
1767
- (message.flags ?? []).forEach((flag) => {
1768
- const flagCheck = CheckFlagReturnFromJSON(flag);
1769
- const contextStr = contextString(context);
1770
- if (this.checks[contextStr] === void 0) {
1771
- this.checks[contextStr] = {};
1772
- }
1773
- this.checks[contextStr][flagCheck.flag] = flagCheck;
1774
- this.debug(`WebSocket flag update:`, {
1775
- flag: flagCheck.flag,
1776
- value: flagCheck.value,
1777
- flagCheck
1778
- });
1779
- if (typeof flagCheck.featureUsageEvent === "string") {
1780
- this.updateFeatureUsageEventMap(flagCheck);
1781
- }
1782
- if (this.flagCheckListeners[flag.flag]?.size > 0 || this.flagValueListeners[flag.flag]?.size > 0) {
1783
- this.submitFlagCheckEvent(flagCheck.flag, flagCheck, context);
1784
- }
1785
- this.notifyFlagCheckListeners(flag.flag, flagCheck);
1786
- this.notifyFlagValueListeners(flag.flag, flagCheck.value);
1787
- });
1788
- this.flushContextDependentEventQueue();
1789
- this.setIsPending(false);
1923
+ persistentMessageHandler(event);
1790
1924
  if (!resolved) {
1791
1925
  resolved = true;
1792
1926
  resolve();
1793
1927
  }
1794
1928
  };
1795
1929
  socket.addEventListener("message", messageHandler);
1930
+ this.currentWebSocket = socket;
1796
1931
  const clientVersion = this.additionalHeaders["X-Schematic-Client-Version"] ?? `schematic-js@${version}`;
1797
1932
  const messagePayload = {
1798
1933
  apiKey: this.apiKey,
@@ -1900,7 +2035,17 @@ var Schematic = class {
1900
2035
  { value }
1901
2036
  );
1902
2037
  }
1903
- listeners.forEach((listener) => notifyFlagValueListener(listener, value));
2038
+ listeners.forEach((listener, index) => {
2039
+ this.debug(`Calling listener ${index} for flag ${flagKey}`, {
2040
+ flagKey,
2041
+ value
2042
+ });
2043
+ notifyFlagValueListener(listener, value);
2044
+ this.debug(`Listener ${index} for flag ${flagKey} completed`, {
2045
+ flagKey,
2046
+ value
2047
+ });
2048
+ });
1904
2049
  };
1905
2050
  };
1906
2051
  var notifyPendingListener = (listener, value) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@schematichq/schematic-js",
3
- "version": "1.2.9",
3
+ "version": "1.2.11",
4
4
  "main": "dist/schematic.cjs.js",
5
5
  "module": "dist/schematic.esm.js",
6
6
  "types": "dist/schematic.d.ts",
@@ -39,7 +39,7 @@
39
39
  "devDependencies": {
40
40
  "@eslint/js": "^9.39.1",
41
41
  "@microsoft/api-extractor": "^7.55.0",
42
- "@openapitools/openapi-generator-cli": "^2.25.1",
42
+ "@openapitools/openapi-generator-cli": "^2.25.2",
43
43
  "@vitest/browser": "^4.0.10",
44
44
  "esbuild": "^0.27.0",
45
45
  "eslint": "^9.39.1",