@schematichq/schematic-react 1.2.12 → 1.2.13
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/dist/schematic-react.cjs.js +56 -20
- package/dist/schematic-react.esm.js +56 -20
- package/package.json +2 -2
|
@@ -799,7 +799,7 @@ function contextString(context) {
|
|
|
799
799
|
}, {});
|
|
800
800
|
return JSON.stringify(sortedContext);
|
|
801
801
|
}
|
|
802
|
-
var version = "1.2.
|
|
802
|
+
var version = "1.2.13";
|
|
803
803
|
var anonymousIdKey = "schematicId";
|
|
804
804
|
var Schematic = class {
|
|
805
805
|
additionalHeaders = {};
|
|
@@ -824,6 +824,9 @@ var Schematic = class {
|
|
|
824
824
|
webSocketConnectionTimeout = 1e4;
|
|
825
825
|
webSocketReconnect = true;
|
|
826
826
|
webSocketMaxReconnectAttempts = 7;
|
|
827
|
+
// Max attempts after connection disrupted
|
|
828
|
+
webSocketMaxConnectionAttempts = 3;
|
|
829
|
+
// Max attempts for initial connection
|
|
827
830
|
webSocketInitialRetryDelay = 1e3;
|
|
828
831
|
webSocketMaxRetryDelay = 3e4;
|
|
829
832
|
wsReconnectAttempts = 0;
|
|
@@ -1047,7 +1050,7 @@ var Schematic = class {
|
|
|
1047
1050
|
this.submitFlagCheckEvent(key, result, context);
|
|
1048
1051
|
return result.value;
|
|
1049
1052
|
}).catch((error) => {
|
|
1050
|
-
console.
|
|
1053
|
+
console.warn("There was a problem with the fetch operation:", error);
|
|
1051
1054
|
const errorResult = this.resolveFallbackCheckFlagReturn(
|
|
1052
1055
|
key,
|
|
1053
1056
|
fallback,
|
|
@@ -1070,10 +1073,7 @@ var Schematic = class {
|
|
|
1070
1073
|
try {
|
|
1071
1074
|
await this.setContext(context);
|
|
1072
1075
|
} catch (error) {
|
|
1073
|
-
console.error
|
|
1074
|
-
"WebSocket connection failed, falling back to REST:",
|
|
1075
|
-
error
|
|
1076
|
-
);
|
|
1076
|
+
console.warn("WebSocket connection failed, falling back to REST:", error);
|
|
1077
1077
|
return this.fallbackToRest(key, context, fallback);
|
|
1078
1078
|
}
|
|
1079
1079
|
const contextVals = this.checks[contextStr] ?? {};
|
|
@@ -1213,7 +1213,7 @@ var Schematic = class {
|
|
|
1213
1213
|
this.submitFlagCheckEvent(key, result, context);
|
|
1214
1214
|
return result.value;
|
|
1215
1215
|
} catch (error) {
|
|
1216
|
-
console.
|
|
1216
|
+
console.warn("REST API call failed, using fallback value:", error);
|
|
1217
1217
|
const errorResult = this.resolveFallbackCheckFlagReturn(
|
|
1218
1218
|
key,
|
|
1219
1219
|
fallback,
|
|
@@ -1262,7 +1262,7 @@ var Schematic = class {
|
|
|
1262
1262
|
{}
|
|
1263
1263
|
);
|
|
1264
1264
|
}).catch((error) => {
|
|
1265
|
-
console.
|
|
1265
|
+
console.warn("There was a problem with the fetch operation:", error);
|
|
1266
1266
|
return {};
|
|
1267
1267
|
});
|
|
1268
1268
|
};
|
|
@@ -1279,7 +1279,7 @@ var Schematic = class {
|
|
|
1279
1279
|
user: body.keys
|
|
1280
1280
|
});
|
|
1281
1281
|
} catch (error) {
|
|
1282
|
-
console.
|
|
1282
|
+
console.warn("Error setting context:", error);
|
|
1283
1283
|
}
|
|
1284
1284
|
return this.handleEvent("identify", body);
|
|
1285
1285
|
};
|
|
@@ -1337,7 +1337,7 @@ var Schematic = class {
|
|
|
1337
1337
|
const socket = await this.conn;
|
|
1338
1338
|
await this.wsSendMessage(socket, context);
|
|
1339
1339
|
} catch (error) {
|
|
1340
|
-
console.
|
|
1340
|
+
console.warn("Failed to establish WebSocket connection:", error);
|
|
1341
1341
|
throw error;
|
|
1342
1342
|
}
|
|
1343
1343
|
};
|
|
@@ -1758,7 +1758,7 @@ var Schematic = class {
|
|
|
1758
1758
|
}
|
|
1759
1759
|
socket.close();
|
|
1760
1760
|
} catch (error) {
|
|
1761
|
-
console.
|
|
1761
|
+
console.warn("Error during cleanup:", error);
|
|
1762
1762
|
} finally {
|
|
1763
1763
|
this.conn = null;
|
|
1764
1764
|
this.currentWebSocket = null;
|
|
@@ -1901,14 +1901,49 @@ var Schematic = class {
|
|
|
1901
1901
|
}
|
|
1902
1902
|
}, delay);
|
|
1903
1903
|
};
|
|
1904
|
-
// Open a websocket connection
|
|
1905
|
-
wsConnect = () => {
|
|
1904
|
+
// Open a websocket connection with retry logic for timeouts
|
|
1905
|
+
wsConnect = async () => {
|
|
1906
1906
|
if (this.isOffline()) {
|
|
1907
1907
|
this.debug("wsConnect: skipped (offline mode)");
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1908
|
+
throw new Error("WebSocket connection skipped in offline mode");
|
|
1909
|
+
}
|
|
1910
|
+
let lastError = null;
|
|
1911
|
+
const maxAttempts = this.webSocketMaxConnectionAttempts;
|
|
1912
|
+
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
|
1913
|
+
try {
|
|
1914
|
+
const socket = await this.wsConnectOnce();
|
|
1915
|
+
this.wsReconnectAttempts = 0;
|
|
1916
|
+
return socket;
|
|
1917
|
+
} catch (error) {
|
|
1918
|
+
lastError = error instanceof Error ? error : new Error(String(error));
|
|
1919
|
+
const isTimeout = lastError.message === "WebSocket connection timeout";
|
|
1920
|
+
if (!isTimeout) {
|
|
1921
|
+
this.debug(
|
|
1922
|
+
`WebSocket connection failed with non-timeout error, not retrying:`,
|
|
1923
|
+
lastError.message
|
|
1924
|
+
);
|
|
1925
|
+
throw lastError;
|
|
1926
|
+
}
|
|
1927
|
+
if (attempt < maxAttempts - 1) {
|
|
1928
|
+
const baseDelay = this.webSocketInitialRetryDelay * Math.pow(2, attempt);
|
|
1929
|
+
const cappedDelay = Math.min(baseDelay, this.webSocketMaxRetryDelay);
|
|
1930
|
+
const jitter = cappedDelay * 0.2 * Math.random();
|
|
1931
|
+
const delay = cappedDelay + jitter;
|
|
1932
|
+
this.debug(
|
|
1933
|
+
`WebSocket connection timeout (attempt ${attempt + 1}/${maxAttempts}), retrying in ${delay.toFixed(0)}ms`
|
|
1934
|
+
);
|
|
1935
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
1936
|
+
} else {
|
|
1937
|
+
this.debug(
|
|
1938
|
+
`WebSocket connection timeout (attempt ${attempt + 1}/${maxAttempts}), no more retries`
|
|
1939
|
+
);
|
|
1940
|
+
}
|
|
1941
|
+
}
|
|
1911
1942
|
}
|
|
1943
|
+
throw lastError ?? new Error("WebSocket connection failed");
|
|
1944
|
+
};
|
|
1945
|
+
// Single attempt to open a websocket connection (no retry logic)
|
|
1946
|
+
wsConnectOnce = () => {
|
|
1912
1947
|
return new Promise((resolve, reject) => {
|
|
1913
1948
|
const wsUrl = `${this.webSocketUrl}/flags/bootstrap?apiKey=${this.apiKey}`;
|
|
1914
1949
|
this.debug(`connecting to WebSocket:`, wsUrl);
|
|
@@ -1919,6 +1954,7 @@ var Schematic = class {
|
|
|
1919
1954
|
let isResolved = false;
|
|
1920
1955
|
timeoutId = setTimeout(() => {
|
|
1921
1956
|
if (!isResolved) {
|
|
1957
|
+
isResolved = true;
|
|
1922
1958
|
this.debug(
|
|
1923
1959
|
`WebSocket connection timeout after ${this.webSocketConnectionTimeout}ms`
|
|
1924
1960
|
);
|
|
@@ -1927,16 +1963,17 @@ var Schematic = class {
|
|
|
1927
1963
|
}
|
|
1928
1964
|
}, this.webSocketConnectionTimeout);
|
|
1929
1965
|
webSocket.onopen = () => {
|
|
1966
|
+
if (isResolved) return;
|
|
1930
1967
|
isResolved = true;
|
|
1931
1968
|
if (timeoutId !== null) {
|
|
1932
1969
|
clearTimeout(timeoutId);
|
|
1933
1970
|
}
|
|
1934
|
-
this.wsReconnectAttempts = 0;
|
|
1935
1971
|
this.wsIntentionalDisconnect = false;
|
|
1936
1972
|
this.debug(`WebSocket connection ${connectionId} opened successfully`);
|
|
1937
1973
|
resolve(webSocket);
|
|
1938
1974
|
};
|
|
1939
1975
|
webSocket.onerror = (error) => {
|
|
1976
|
+
if (isResolved) return;
|
|
1940
1977
|
isResolved = true;
|
|
1941
1978
|
if (timeoutId !== null) {
|
|
1942
1979
|
clearTimeout(timeoutId);
|
|
@@ -1945,7 +1982,6 @@ var Schematic = class {
|
|
|
1945
1982
|
reject(error);
|
|
1946
1983
|
};
|
|
1947
1984
|
webSocket.onclose = () => {
|
|
1948
|
-
isResolved = true;
|
|
1949
1985
|
if (timeoutId !== null) {
|
|
1950
1986
|
clearTimeout(timeoutId);
|
|
1951
1987
|
}
|
|
@@ -1955,7 +1991,7 @@ var Schematic = class {
|
|
|
1955
1991
|
this.currentWebSocket = null;
|
|
1956
1992
|
this.isConnecting = false;
|
|
1957
1993
|
}
|
|
1958
|
-
if (!this.wsIntentionalDisconnect && this.webSocketReconnect) {
|
|
1994
|
+
if (!isResolved && !this.wsIntentionalDisconnect && this.webSocketReconnect) {
|
|
1959
1995
|
this.attemptReconnect();
|
|
1960
1996
|
}
|
|
1961
1997
|
};
|
|
@@ -2137,7 +2173,7 @@ var notifyFlagValueListener = (listener, value) => {
|
|
|
2137
2173
|
var import_react = __toESM(require("react"));
|
|
2138
2174
|
|
|
2139
2175
|
// src/version.ts
|
|
2140
|
-
var version2 = "1.2.
|
|
2176
|
+
var version2 = "1.2.13";
|
|
2141
2177
|
|
|
2142
2178
|
// src/context/schematic.tsx
|
|
2143
2179
|
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.
|
|
757
|
+
var version = "1.2.13";
|
|
758
758
|
var anonymousIdKey = "schematicId";
|
|
759
759
|
var Schematic = class {
|
|
760
760
|
additionalHeaders = {};
|
|
@@ -779,6 +779,9 @@ var Schematic = class {
|
|
|
779
779
|
webSocketConnectionTimeout = 1e4;
|
|
780
780
|
webSocketReconnect = true;
|
|
781
781
|
webSocketMaxReconnectAttempts = 7;
|
|
782
|
+
// Max attempts after connection disrupted
|
|
783
|
+
webSocketMaxConnectionAttempts = 3;
|
|
784
|
+
// Max attempts for initial connection
|
|
782
785
|
webSocketInitialRetryDelay = 1e3;
|
|
783
786
|
webSocketMaxRetryDelay = 3e4;
|
|
784
787
|
wsReconnectAttempts = 0;
|
|
@@ -1002,7 +1005,7 @@ var Schematic = class {
|
|
|
1002
1005
|
this.submitFlagCheckEvent(key, result, context);
|
|
1003
1006
|
return result.value;
|
|
1004
1007
|
}).catch((error) => {
|
|
1005
|
-
console.
|
|
1008
|
+
console.warn("There was a problem with the fetch operation:", error);
|
|
1006
1009
|
const errorResult = this.resolveFallbackCheckFlagReturn(
|
|
1007
1010
|
key,
|
|
1008
1011
|
fallback,
|
|
@@ -1025,10 +1028,7 @@ var Schematic = class {
|
|
|
1025
1028
|
try {
|
|
1026
1029
|
await this.setContext(context);
|
|
1027
1030
|
} catch (error) {
|
|
1028
|
-
console.error
|
|
1029
|
-
"WebSocket connection failed, falling back to REST:",
|
|
1030
|
-
error
|
|
1031
|
-
);
|
|
1031
|
+
console.warn("WebSocket connection failed, falling back to REST:", error);
|
|
1032
1032
|
return this.fallbackToRest(key, context, fallback);
|
|
1033
1033
|
}
|
|
1034
1034
|
const contextVals = this.checks[contextStr] ?? {};
|
|
@@ -1168,7 +1168,7 @@ var Schematic = class {
|
|
|
1168
1168
|
this.submitFlagCheckEvent(key, result, context);
|
|
1169
1169
|
return result.value;
|
|
1170
1170
|
} catch (error) {
|
|
1171
|
-
console.
|
|
1171
|
+
console.warn("REST API call failed, using fallback value:", error);
|
|
1172
1172
|
const errorResult = this.resolveFallbackCheckFlagReturn(
|
|
1173
1173
|
key,
|
|
1174
1174
|
fallback,
|
|
@@ -1217,7 +1217,7 @@ var Schematic = class {
|
|
|
1217
1217
|
{}
|
|
1218
1218
|
);
|
|
1219
1219
|
}).catch((error) => {
|
|
1220
|
-
console.
|
|
1220
|
+
console.warn("There was a problem with the fetch operation:", error);
|
|
1221
1221
|
return {};
|
|
1222
1222
|
});
|
|
1223
1223
|
};
|
|
@@ -1234,7 +1234,7 @@ var Schematic = class {
|
|
|
1234
1234
|
user: body.keys
|
|
1235
1235
|
});
|
|
1236
1236
|
} catch (error) {
|
|
1237
|
-
console.
|
|
1237
|
+
console.warn("Error setting context:", error);
|
|
1238
1238
|
}
|
|
1239
1239
|
return this.handleEvent("identify", body);
|
|
1240
1240
|
};
|
|
@@ -1292,7 +1292,7 @@ var Schematic = class {
|
|
|
1292
1292
|
const socket = await this.conn;
|
|
1293
1293
|
await this.wsSendMessage(socket, context);
|
|
1294
1294
|
} catch (error) {
|
|
1295
|
-
console.
|
|
1295
|
+
console.warn("Failed to establish WebSocket connection:", error);
|
|
1296
1296
|
throw error;
|
|
1297
1297
|
}
|
|
1298
1298
|
};
|
|
@@ -1713,7 +1713,7 @@ var Schematic = class {
|
|
|
1713
1713
|
}
|
|
1714
1714
|
socket.close();
|
|
1715
1715
|
} catch (error) {
|
|
1716
|
-
console.
|
|
1716
|
+
console.warn("Error during cleanup:", error);
|
|
1717
1717
|
} finally {
|
|
1718
1718
|
this.conn = null;
|
|
1719
1719
|
this.currentWebSocket = null;
|
|
@@ -1856,14 +1856,49 @@ var Schematic = class {
|
|
|
1856
1856
|
}
|
|
1857
1857
|
}, delay);
|
|
1858
1858
|
};
|
|
1859
|
-
// Open a websocket connection
|
|
1860
|
-
wsConnect = () => {
|
|
1859
|
+
// Open a websocket connection with retry logic for timeouts
|
|
1860
|
+
wsConnect = async () => {
|
|
1861
1861
|
if (this.isOffline()) {
|
|
1862
1862
|
this.debug("wsConnect: skipped (offline mode)");
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1863
|
+
throw new Error("WebSocket connection skipped in offline mode");
|
|
1864
|
+
}
|
|
1865
|
+
let lastError = null;
|
|
1866
|
+
const maxAttempts = this.webSocketMaxConnectionAttempts;
|
|
1867
|
+
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
|
1868
|
+
try {
|
|
1869
|
+
const socket = await this.wsConnectOnce();
|
|
1870
|
+
this.wsReconnectAttempts = 0;
|
|
1871
|
+
return socket;
|
|
1872
|
+
} catch (error) {
|
|
1873
|
+
lastError = error instanceof Error ? error : new Error(String(error));
|
|
1874
|
+
const isTimeout = lastError.message === "WebSocket connection timeout";
|
|
1875
|
+
if (!isTimeout) {
|
|
1876
|
+
this.debug(
|
|
1877
|
+
`WebSocket connection failed with non-timeout error, not retrying:`,
|
|
1878
|
+
lastError.message
|
|
1879
|
+
);
|
|
1880
|
+
throw lastError;
|
|
1881
|
+
}
|
|
1882
|
+
if (attempt < maxAttempts - 1) {
|
|
1883
|
+
const baseDelay = this.webSocketInitialRetryDelay * Math.pow(2, attempt);
|
|
1884
|
+
const cappedDelay = Math.min(baseDelay, this.webSocketMaxRetryDelay);
|
|
1885
|
+
const jitter = cappedDelay * 0.2 * Math.random();
|
|
1886
|
+
const delay = cappedDelay + jitter;
|
|
1887
|
+
this.debug(
|
|
1888
|
+
`WebSocket connection timeout (attempt ${attempt + 1}/${maxAttempts}), retrying in ${delay.toFixed(0)}ms`
|
|
1889
|
+
);
|
|
1890
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
1891
|
+
} else {
|
|
1892
|
+
this.debug(
|
|
1893
|
+
`WebSocket connection timeout (attempt ${attempt + 1}/${maxAttempts}), no more retries`
|
|
1894
|
+
);
|
|
1895
|
+
}
|
|
1896
|
+
}
|
|
1866
1897
|
}
|
|
1898
|
+
throw lastError ?? new Error("WebSocket connection failed");
|
|
1899
|
+
};
|
|
1900
|
+
// Single attempt to open a websocket connection (no retry logic)
|
|
1901
|
+
wsConnectOnce = () => {
|
|
1867
1902
|
return new Promise((resolve, reject) => {
|
|
1868
1903
|
const wsUrl = `${this.webSocketUrl}/flags/bootstrap?apiKey=${this.apiKey}`;
|
|
1869
1904
|
this.debug(`connecting to WebSocket:`, wsUrl);
|
|
@@ -1874,6 +1909,7 @@ var Schematic = class {
|
|
|
1874
1909
|
let isResolved = false;
|
|
1875
1910
|
timeoutId = setTimeout(() => {
|
|
1876
1911
|
if (!isResolved) {
|
|
1912
|
+
isResolved = true;
|
|
1877
1913
|
this.debug(
|
|
1878
1914
|
`WebSocket connection timeout after ${this.webSocketConnectionTimeout}ms`
|
|
1879
1915
|
);
|
|
@@ -1882,16 +1918,17 @@ var Schematic = class {
|
|
|
1882
1918
|
}
|
|
1883
1919
|
}, this.webSocketConnectionTimeout);
|
|
1884
1920
|
webSocket.onopen = () => {
|
|
1921
|
+
if (isResolved) return;
|
|
1885
1922
|
isResolved = true;
|
|
1886
1923
|
if (timeoutId !== null) {
|
|
1887
1924
|
clearTimeout(timeoutId);
|
|
1888
1925
|
}
|
|
1889
|
-
this.wsReconnectAttempts = 0;
|
|
1890
1926
|
this.wsIntentionalDisconnect = false;
|
|
1891
1927
|
this.debug(`WebSocket connection ${connectionId} opened successfully`);
|
|
1892
1928
|
resolve(webSocket);
|
|
1893
1929
|
};
|
|
1894
1930
|
webSocket.onerror = (error) => {
|
|
1931
|
+
if (isResolved) return;
|
|
1895
1932
|
isResolved = true;
|
|
1896
1933
|
if (timeoutId !== null) {
|
|
1897
1934
|
clearTimeout(timeoutId);
|
|
@@ -1900,7 +1937,6 @@ var Schematic = class {
|
|
|
1900
1937
|
reject(error);
|
|
1901
1938
|
};
|
|
1902
1939
|
webSocket.onclose = () => {
|
|
1903
|
-
isResolved = true;
|
|
1904
1940
|
if (timeoutId !== null) {
|
|
1905
1941
|
clearTimeout(timeoutId);
|
|
1906
1942
|
}
|
|
@@ -1910,7 +1946,7 @@ var Schematic = class {
|
|
|
1910
1946
|
this.currentWebSocket = null;
|
|
1911
1947
|
this.isConnecting = false;
|
|
1912
1948
|
}
|
|
1913
|
-
if (!this.wsIntentionalDisconnect && this.webSocketReconnect) {
|
|
1949
|
+
if (!isResolved && !this.wsIntentionalDisconnect && this.webSocketReconnect) {
|
|
1914
1950
|
this.attemptReconnect();
|
|
1915
1951
|
}
|
|
1916
1952
|
};
|
|
@@ -2092,7 +2128,7 @@ var notifyFlagValueListener = (listener, value) => {
|
|
|
2092
2128
|
import React, { createContext, useEffect, useMemo, useRef } from "react";
|
|
2093
2129
|
|
|
2094
2130
|
// src/version.ts
|
|
2095
|
-
var version2 = "1.2.
|
|
2131
|
+
var version2 = "1.2.13";
|
|
2096
2132
|
|
|
2097
2133
|
// src/context/schematic.tsx
|
|
2098
2134
|
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.
|
|
3
|
+
"version": "1.2.13",
|
|
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.
|
|
34
|
+
"@schematichq/schematic-js": "^1.2.13"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
37
|
"@eslint/js": "^9.39.1",
|