@allstak/react-native 0.4.0 → 0.5.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.
- package/CHANGELOG.md +76 -0
- package/dist/index.d.mts +245 -4
- package/dist/index.d.ts +245 -4
- package/dist/index.js +504 -19
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +504 -19
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1482,7 +1482,9 @@ function tryRequire(id2) {
|
|
|
1482
1482
|
|
|
1483
1483
|
// src/privacy.tsx
|
|
1484
1484
|
import * as React from "react";
|
|
1485
|
-
|
|
1485
|
+
function getRN() {
|
|
1486
|
+
return tryRequire("react-native");
|
|
1487
|
+
}
|
|
1486
1488
|
var state = {
|
|
1487
1489
|
isCapturing: false,
|
|
1488
1490
|
sensitiveRefs: /* @__PURE__ */ new Set()
|
|
@@ -1530,9 +1532,18 @@ function useAllStakPrivacy() {
|
|
|
1530
1532
|
const isCapturing = useIsCapturing();
|
|
1531
1533
|
return { isCapturing, registerSensitiveRef };
|
|
1532
1534
|
}
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1535
|
+
function getView() {
|
|
1536
|
+
const RN = getRN();
|
|
1537
|
+
return RN?.View ?? ((props) => React.createElement(React.Fragment, null, props.children));
|
|
1538
|
+
}
|
|
1539
|
+
function getText() {
|
|
1540
|
+
const RN = getRN();
|
|
1541
|
+
return RN?.Text ?? ((props) => React.createElement(React.Fragment, null, props.children));
|
|
1542
|
+
}
|
|
1543
|
+
function getTextInput() {
|
|
1544
|
+
const RN = getRN();
|
|
1545
|
+
return RN?.TextInput ?? ((props) => React.createElement(React.Fragment, null, null));
|
|
1546
|
+
}
|
|
1536
1547
|
var DEFAULT_MASK_COLOR = "#d8dde7";
|
|
1537
1548
|
var DEFAULT_MASK_LABEL = "\u2022\u2022\u2022\u2022\u2022\u2022";
|
|
1538
1549
|
function AllStakMaskedView({
|
|
@@ -1545,6 +1556,8 @@ function AllStakMaskedView({
|
|
|
1545
1556
|
...rest
|
|
1546
1557
|
}) {
|
|
1547
1558
|
const isCapturing = useIsCapturing();
|
|
1559
|
+
const View = getView();
|
|
1560
|
+
const Text = getText();
|
|
1548
1561
|
if (!isCapturing || privacy === "show") {
|
|
1549
1562
|
return React.createElement(View, { style, ...rest }, children);
|
|
1550
1563
|
}
|
|
@@ -1567,6 +1580,8 @@ function AllStakTextInput({
|
|
|
1567
1580
|
...rest
|
|
1568
1581
|
}) {
|
|
1569
1582
|
const isCapturing = useIsCapturing();
|
|
1583
|
+
const View = getView();
|
|
1584
|
+
const TextInput = getTextInput();
|
|
1570
1585
|
if (isCapturing && privacy !== "show") {
|
|
1571
1586
|
return React.createElement(View, {
|
|
1572
1587
|
style: [{ minHeight: 40, backgroundColor: maskColor, borderRadius: 4 }, style]
|
|
@@ -1582,6 +1597,7 @@ function AllStakSensitiveText({
|
|
|
1582
1597
|
...rest
|
|
1583
1598
|
}) {
|
|
1584
1599
|
const isCapturing = useIsCapturing();
|
|
1600
|
+
const Text = getText();
|
|
1585
1601
|
if (isCapturing && privacy !== "show") {
|
|
1586
1602
|
return React.createElement(Text, { style, ...rest }, maskLabel);
|
|
1587
1603
|
}
|
|
@@ -1683,8 +1699,8 @@ function estimateBase64Size(base64) {
|
|
|
1683
1699
|
}
|
|
1684
1700
|
function readDimensions() {
|
|
1685
1701
|
try {
|
|
1686
|
-
const
|
|
1687
|
-
const dims =
|
|
1702
|
+
const RN = tryRequire("react-native");
|
|
1703
|
+
const dims = RN?.Dimensions?.get?.("window");
|
|
1688
1704
|
if (dims && typeof dims.width === "number" && typeof dims.height === "number") {
|
|
1689
1705
|
return { width: Math.round(dims.width), height: Math.round(dims.height) };
|
|
1690
1706
|
}
|
|
@@ -1767,15 +1783,325 @@ function pickScreenshotConfig(source) {
|
|
|
1767
1783
|
return out;
|
|
1768
1784
|
}
|
|
1769
1785
|
|
|
1786
|
+
// src/contexts.ts
|
|
1787
|
+
function tryReq(id2) {
|
|
1788
|
+
try {
|
|
1789
|
+
return require(id2);
|
|
1790
|
+
} catch {
|
|
1791
|
+
return null;
|
|
1792
|
+
}
|
|
1793
|
+
}
|
|
1794
|
+
function defaultExport(mod) {
|
|
1795
|
+
if (!mod) return null;
|
|
1796
|
+
return mod.default ?? mod;
|
|
1797
|
+
}
|
|
1798
|
+
function strOrUndef(v) {
|
|
1799
|
+
if (v == null) return void 0;
|
|
1800
|
+
const s = String(v);
|
|
1801
|
+
return s.length > 0 ? s : void 0;
|
|
1802
|
+
}
|
|
1803
|
+
function collectAutoContexts(opts = {}) {
|
|
1804
|
+
const captureDev = opts.captureDeviceContext !== false;
|
|
1805
|
+
const captureScreen = opts.captureScreenContext !== false;
|
|
1806
|
+
const contexts = {};
|
|
1807
|
+
const tags = {};
|
|
1808
|
+
const RN = tryReq("react-native");
|
|
1809
|
+
const Platform = RN?.Platform;
|
|
1810
|
+
const Dimensions = RN?.Dimensions;
|
|
1811
|
+
const NativeModules = RN?.NativeModules;
|
|
1812
|
+
const osName = strOrUndef(Platform?.OS);
|
|
1813
|
+
const osVersion = strOrUndef(Platform?.Version);
|
|
1814
|
+
const osConstants = Platform?.constants ?? {};
|
|
1815
|
+
if (osName) {
|
|
1816
|
+
contexts.os = {
|
|
1817
|
+
name: osName === "ios" ? "iOS" : osName === "android" ? "Android" : osName,
|
|
1818
|
+
version: osVersion,
|
|
1819
|
+
build: strOrUndef(osConstants?.osBuildId ?? osConstants?.Release)
|
|
1820
|
+
};
|
|
1821
|
+
tags["os.name"] = osName;
|
|
1822
|
+
if (osVersion) tags["os.version"] = osVersion;
|
|
1823
|
+
}
|
|
1824
|
+
const g = globalThis;
|
|
1825
|
+
const hermes = typeof g.HermesInternal !== "undefined";
|
|
1826
|
+
const fabric = typeof g.__turboModuleProxy !== "undefined";
|
|
1827
|
+
const turboModules = fabric;
|
|
1828
|
+
const bridgeless = typeof g.RN$Bridgeless !== "undefined" && !!g.RN$Bridgeless;
|
|
1829
|
+
const jsEngine = hermes ? "hermes" : "jsc";
|
|
1830
|
+
tags["js_engine"] = jsEngine;
|
|
1831
|
+
tags["fabric"] = String(fabric);
|
|
1832
|
+
tags["turbo_modules"] = String(turboModules);
|
|
1833
|
+
const hermesVersion = (() => {
|
|
1834
|
+
try {
|
|
1835
|
+
return g.HermesInternal?.getRuntimeProperties?.()?.["OSS Release Version"];
|
|
1836
|
+
} catch {
|
|
1837
|
+
return void 0;
|
|
1838
|
+
}
|
|
1839
|
+
})();
|
|
1840
|
+
contexts.runtime = {
|
|
1841
|
+
name: jsEngine,
|
|
1842
|
+
version: strOrUndef(hermesVersion) ?? "unknown",
|
|
1843
|
+
bridgeless
|
|
1844
|
+
};
|
|
1845
|
+
if (captureDev) {
|
|
1846
|
+
const device = {};
|
|
1847
|
+
if (osConstants?.Model) device.model = String(osConstants.Model);
|
|
1848
|
+
if (osConstants?.Brand) device.brand = String(osConstants.Brand);
|
|
1849
|
+
if (osConstants?.Manufacturer) device.manufacturer = String(osConstants.Manufacturer);
|
|
1850
|
+
if (osConstants?.systemName) device.systemName = String(osConstants.systemName);
|
|
1851
|
+
if (osConstants?.interfaceIdiom) device.family = String(osConstants.interfaceIdiom);
|
|
1852
|
+
const isSim = Boolean(osConstants?.isTesting) || typeof osConstants?.reactNativeVersion === "object" && String(osConstants?.systemName ?? "").toLowerCase().includes("simulator");
|
|
1853
|
+
if (isSim) {
|
|
1854
|
+
device.simulator = true;
|
|
1855
|
+
tags["simulator"] = "true";
|
|
1856
|
+
}
|
|
1857
|
+
const expoDevice = tryReq("expo-device");
|
|
1858
|
+
if (expoDevice) {
|
|
1859
|
+
const ed = defaultExport(expoDevice) ?? expoDevice;
|
|
1860
|
+
if (ed.modelName) device.model = String(ed.modelName);
|
|
1861
|
+
if (ed.brand) device.brand = String(ed.brand);
|
|
1862
|
+
if (ed.manufacturer) device.manufacturer = String(ed.manufacturer);
|
|
1863
|
+
if (ed.deviceYearClass != null) device.yearClass = ed.deviceYearClass;
|
|
1864
|
+
if (ed.totalMemory != null) device.memory_size = ed.totalMemory;
|
|
1865
|
+
if (typeof ed.supportedCpuArchitectures !== "undefined") {
|
|
1866
|
+
const arr = ed.supportedCpuArchitectures;
|
|
1867
|
+
if (Array.isArray(arr) && arr.length > 0) device.arch = String(arr[0]);
|
|
1868
|
+
}
|
|
1869
|
+
if (typeof ed.isDevice === "boolean" && !ed.isDevice) {
|
|
1870
|
+
device.simulator = true;
|
|
1871
|
+
tags["simulator"] = "true";
|
|
1872
|
+
}
|
|
1873
|
+
} else {
|
|
1874
|
+
const dinfo = tryReq("react-native-device-info");
|
|
1875
|
+
if (dinfo) {
|
|
1876
|
+
const d = defaultExport(dinfo) ?? dinfo;
|
|
1877
|
+
try {
|
|
1878
|
+
device.model = device.model ?? d.getModel?.();
|
|
1879
|
+
} catch {
|
|
1880
|
+
}
|
|
1881
|
+
try {
|
|
1882
|
+
device.manufacturer = device.manufacturer ?? d.getManufacturerSync?.();
|
|
1883
|
+
} catch {
|
|
1884
|
+
}
|
|
1885
|
+
try {
|
|
1886
|
+
device.memory_size = device.memory_size ?? d.getTotalMemorySync?.();
|
|
1887
|
+
} catch {
|
|
1888
|
+
}
|
|
1889
|
+
try {
|
|
1890
|
+
const isEm = d.isEmulatorSync?.();
|
|
1891
|
+
if (isEm) {
|
|
1892
|
+
device.simulator = true;
|
|
1893
|
+
tags["simulator"] = "true";
|
|
1894
|
+
}
|
|
1895
|
+
} catch {
|
|
1896
|
+
}
|
|
1897
|
+
}
|
|
1898
|
+
}
|
|
1899
|
+
if (captureScreen && Dimensions && typeof Dimensions.get === "function") {
|
|
1900
|
+
try {
|
|
1901
|
+
const screen = Dimensions.get("screen");
|
|
1902
|
+
if (screen?.width && screen?.height) {
|
|
1903
|
+
device.screen_width_pixels = Math.round(screen.width * (screen.scale ?? 1));
|
|
1904
|
+
device.screen_height_pixels = Math.round(screen.height * (screen.scale ?? 1));
|
|
1905
|
+
device.screen_density = screen.scale;
|
|
1906
|
+
device.orientation = screen.width >= screen.height ? "landscape" : "portrait";
|
|
1907
|
+
tags["app_orientation"] = device.orientation;
|
|
1908
|
+
}
|
|
1909
|
+
} catch {
|
|
1910
|
+
}
|
|
1911
|
+
}
|
|
1912
|
+
if (opts.captureBattery) {
|
|
1913
|
+
const expoBattery = tryReq("expo-battery");
|
|
1914
|
+
if (expoBattery) {
|
|
1915
|
+
try {
|
|
1916
|
+
const eb = defaultExport(expoBattery) ?? expoBattery;
|
|
1917
|
+
device.battery_available = true;
|
|
1918
|
+
if (typeof eb.getBatteryLevelAsync === "function") {
|
|
1919
|
+
}
|
|
1920
|
+
} catch {
|
|
1921
|
+
}
|
|
1922
|
+
}
|
|
1923
|
+
}
|
|
1924
|
+
if (Object.keys(device).length > 0) {
|
|
1925
|
+
contexts.device = device;
|
|
1926
|
+
if (device.model) tags["device.model"] = String(device.model);
|
|
1927
|
+
}
|
|
1928
|
+
}
|
|
1929
|
+
const app = {};
|
|
1930
|
+
app.app_start_time = (/* @__PURE__ */ new Date()).toISOString();
|
|
1931
|
+
const expoApp = tryReq("expo-application");
|
|
1932
|
+
if (expoApp) {
|
|
1933
|
+
const ea = defaultExport(expoApp) ?? expoApp;
|
|
1934
|
+
if (ea.applicationName) app.app_name = String(ea.applicationName);
|
|
1935
|
+
if (ea.applicationId) app.app_identifier = String(ea.applicationId);
|
|
1936
|
+
if (ea.nativeBuildVersion) app.app_build = String(ea.nativeBuildVersion);
|
|
1937
|
+
if (ea.nativeApplicationVersion) app.app_version = String(ea.nativeApplicationVersion);
|
|
1938
|
+
} else {
|
|
1939
|
+
const dinfo = tryReq("react-native-device-info");
|
|
1940
|
+
if (dinfo) {
|
|
1941
|
+
const d = defaultExport(dinfo) ?? dinfo;
|
|
1942
|
+
try {
|
|
1943
|
+
app.app_name = d.getApplicationName?.();
|
|
1944
|
+
} catch {
|
|
1945
|
+
}
|
|
1946
|
+
try {
|
|
1947
|
+
app.app_identifier = d.getBundleId?.();
|
|
1948
|
+
} catch {
|
|
1949
|
+
}
|
|
1950
|
+
try {
|
|
1951
|
+
app.app_build = d.getBuildNumber?.();
|
|
1952
|
+
} catch {
|
|
1953
|
+
}
|
|
1954
|
+
try {
|
|
1955
|
+
app.app_version = d.getVersion?.();
|
|
1956
|
+
} catch {
|
|
1957
|
+
}
|
|
1958
|
+
}
|
|
1959
|
+
}
|
|
1960
|
+
if (Object.keys(app).length > 0) {
|
|
1961
|
+
contexts.app = app;
|
|
1962
|
+
if (app.app_version) tags["app.version"] = String(app.app_version);
|
|
1963
|
+
if (app.app_build) tags["app.build"] = String(app.app_build);
|
|
1964
|
+
}
|
|
1965
|
+
const rn = {
|
|
1966
|
+
hermes,
|
|
1967
|
+
fabric,
|
|
1968
|
+
turbo_modules: turboModules,
|
|
1969
|
+
bridgeless,
|
|
1970
|
+
js_engine: jsEngine
|
|
1971
|
+
};
|
|
1972
|
+
if (osConstants?.reactNativeVersion) {
|
|
1973
|
+
const v = osConstants.reactNativeVersion;
|
|
1974
|
+
if (typeof v === "object" && v.major != null) {
|
|
1975
|
+
rn.react_native_version = `${v.major}.${v.minor ?? 0}.${v.patch ?? 0}`;
|
|
1976
|
+
} else if (typeof v === "string") {
|
|
1977
|
+
rn.react_native_version = v;
|
|
1978
|
+
}
|
|
1979
|
+
}
|
|
1980
|
+
const expoConstants = tryReq("expo-constants");
|
|
1981
|
+
if (expoConstants) {
|
|
1982
|
+
const ec = defaultExport(expoConstants) ?? expoConstants;
|
|
1983
|
+
if (ec.expoVersion) rn.expo = ec.expoVersion;
|
|
1984
|
+
else if (ec.expoConfig?.sdkVersion) rn.expo = ec.expoConfig.sdkVersion;
|
|
1985
|
+
if (ec.appOwnership) rn.expo_application_ownership = String(ec.appOwnership);
|
|
1986
|
+
if (ec.executionEnvironment) rn.expo_execution_environment = String(ec.executionEnvironment);
|
|
1987
|
+
} else {
|
|
1988
|
+
rn.expo = false;
|
|
1989
|
+
}
|
|
1990
|
+
contexts.react_native = rn;
|
|
1991
|
+
if (rn.expo && rn.expo !== false) tags["expo"] = "true";
|
|
1992
|
+
if (rn.react_native_version) tags["rn.version"] = String(rn.react_native_version);
|
|
1993
|
+
return { contexts, tags };
|
|
1994
|
+
}
|
|
1995
|
+
function buildUserContext(user, opts = {}) {
|
|
1996
|
+
if (!user) return void 0;
|
|
1997
|
+
const out = {};
|
|
1998
|
+
if (user.id) out.id = user.id;
|
|
1999
|
+
if (user.username) out.username = user.username;
|
|
2000
|
+
if (opts.sendDefaultPii) {
|
|
2001
|
+
if (user.email) out.email = user.email;
|
|
2002
|
+
if (user.ip_address) out.ip_address = user.ip_address;
|
|
2003
|
+
}
|
|
2004
|
+
return Object.keys(out).length > 0 ? out : void 0;
|
|
2005
|
+
}
|
|
2006
|
+
|
|
2007
|
+
// src/mechanism.ts
|
|
2008
|
+
var URL_QUERY_RE = /\?.*$/;
|
|
2009
|
+
function sanitizeUrl(url) {
|
|
2010
|
+
if (!url) return "";
|
|
2011
|
+
const s = String(url).replace(URL_QUERY_RE, "");
|
|
2012
|
+
return s;
|
|
2013
|
+
}
|
|
2014
|
+
function exceptionClassName(err) {
|
|
2015
|
+
if (err && typeof err === "object") {
|
|
2016
|
+
const e = err;
|
|
2017
|
+
const fromName = e.name && e.name !== "Error" ? e.name : void 0;
|
|
2018
|
+
return fromName ?? e.constructor?.name ?? "Error";
|
|
2019
|
+
}
|
|
2020
|
+
return "Error";
|
|
2021
|
+
}
|
|
2022
|
+
function exceptionValue(err) {
|
|
2023
|
+
if (err == null) return "";
|
|
2024
|
+
if (err instanceof Error) return err.message ?? "";
|
|
2025
|
+
if (typeof err === "string") return err;
|
|
2026
|
+
try {
|
|
2027
|
+
return JSON.stringify(err);
|
|
2028
|
+
} catch {
|
|
2029
|
+
return String(err);
|
|
2030
|
+
}
|
|
2031
|
+
}
|
|
2032
|
+
function buildExceptionChain(err, mechanism, handled) {
|
|
2033
|
+
const values = [];
|
|
2034
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2035
|
+
let cursor = err;
|
|
2036
|
+
let depth = 0;
|
|
2037
|
+
while (cursor && depth < 5 && !seen.has(cursor)) {
|
|
2038
|
+
seen.add(cursor);
|
|
2039
|
+
const e = cursor;
|
|
2040
|
+
const frames = parseStack(e?.stack);
|
|
2041
|
+
values.push({
|
|
2042
|
+
type: exceptionClassName(e),
|
|
2043
|
+
value: exceptionValue(e),
|
|
2044
|
+
stacktrace: frames.length > 0 ? { frames } : void 0,
|
|
2045
|
+
// Only the outermost exception carries the mechanism, like Sentry.
|
|
2046
|
+
...depth === 0 ? { mechanism: { type: mechanism, handled } } : {}
|
|
2047
|
+
});
|
|
2048
|
+
cursor = e?.cause;
|
|
2049
|
+
depth += 1;
|
|
2050
|
+
}
|
|
2051
|
+
return values.reverse();
|
|
2052
|
+
}
|
|
2053
|
+
function extractAxiosRequest(err) {
|
|
2054
|
+
if (!err || typeof err !== "object") return null;
|
|
2055
|
+
const e = err;
|
|
2056
|
+
if (e.isAxiosError !== true) return null;
|
|
2057
|
+
const cfg = e.config ?? {};
|
|
2058
|
+
const resp = e.response ?? null;
|
|
2059
|
+
const method = strUpper(cfg.method);
|
|
2060
|
+
const rawUrl = composeAxiosUrl(cfg);
|
|
2061
|
+
const url_sanitized = sanitizeUrl(rawUrl);
|
|
2062
|
+
const status_code = typeof resp?.status === "number" ? resp.status : void 0;
|
|
2063
|
+
const duration_ms = typeof e.duration === "number" ? e.duration : void 0;
|
|
2064
|
+
const category = classifyHttpError(e, status_code);
|
|
2065
|
+
return {
|
|
2066
|
+
method,
|
|
2067
|
+
url_sanitized,
|
|
2068
|
+
status_code,
|
|
2069
|
+
duration_ms,
|
|
2070
|
+
category
|
|
2071
|
+
};
|
|
2072
|
+
}
|
|
2073
|
+
function composeAxiosUrl(cfg) {
|
|
2074
|
+
const base = typeof cfg?.baseURL === "string" ? cfg.baseURL.replace(/\/$/, "") : "";
|
|
2075
|
+
const path = typeof cfg?.url === "string" ? cfg.url : "";
|
|
2076
|
+
if (!base && !path) return "";
|
|
2077
|
+
if (path.startsWith("http://") || path.startsWith("https://")) return path;
|
|
2078
|
+
return base + path;
|
|
2079
|
+
}
|
|
2080
|
+
function strUpper(v) {
|
|
2081
|
+
if (typeof v !== "string" || v.length === 0) return void 0;
|
|
2082
|
+
return v.toUpperCase();
|
|
2083
|
+
}
|
|
2084
|
+
function classifyHttpError(err, status) {
|
|
2085
|
+
const code = typeof err?.code === "string" ? err.code.toUpperCase() : "";
|
|
2086
|
+
if (code === "ECONNABORTED" || code === "ETIMEDOUT") return "timeout";
|
|
2087
|
+
if (code === "ERR_CANCELED" || code === "CANCELED") return "cancel";
|
|
2088
|
+
if (typeof status === "number" && status >= 500) return "http_server_error";
|
|
2089
|
+
if (typeof status === "number" && status >= 400) return "http_client_error";
|
|
2090
|
+
return "network";
|
|
2091
|
+
}
|
|
2092
|
+
function maybeExtractHttpRequest(err) {
|
|
2093
|
+
return extractAxiosRequest(err);
|
|
2094
|
+
}
|
|
2095
|
+
|
|
1770
2096
|
// src/client.ts
|
|
1771
2097
|
var INGEST_HOST = "https://api.allstak.sa";
|
|
1772
2098
|
var SDK_NAME = "allstak-react-native";
|
|
1773
|
-
var SDK_VERSION = "0.
|
|
2099
|
+
var SDK_VERSION = "0.5.0";
|
|
1774
2100
|
var ERRORS_PATH = "/ingest/v1/errors";
|
|
1775
2101
|
var LOGS_PATH = "/ingest/v1/logs";
|
|
1776
2102
|
var VALID_BREADCRUMB_TYPES = /* @__PURE__ */ new Set(["http", "log", "ui", "navigation", "query", "default"]);
|
|
1777
2103
|
var VALID_BREADCRUMB_LEVELS = /* @__PURE__ */ new Set(["info", "warn", "error", "debug"]);
|
|
1778
|
-
var DEFAULT_MAX_BREADCRUMBS =
|
|
2104
|
+
var DEFAULT_MAX_BREADCRUMBS = 100;
|
|
1779
2105
|
function frameToString(f) {
|
|
1780
2106
|
const fn = f.function && f.function.length > 0 ? f.function : "<anonymous>";
|
|
1781
2107
|
const file = f.filename || f.absPath || "<anonymous>";
|
|
@@ -1804,6 +2130,12 @@ var AllStakClient = class {
|
|
|
1804
2130
|
this.replay = null;
|
|
1805
2131
|
this.httpRequests = null;
|
|
1806
2132
|
this._instrumentAxios = null;
|
|
2133
|
+
/** Auto-collected Sentry-shape contexts (device/os/app/react_native/runtime). */
|
|
2134
|
+
this.autoContexts = {};
|
|
2135
|
+
/** Auto-collected tags (device.model, os.name, js_engine, …). */
|
|
2136
|
+
this.autoTags = {};
|
|
2137
|
+
/** Current screen / transaction name — set via setCurrentScreen() or nav auto-instrument. */
|
|
2138
|
+
this.currentTransaction = null;
|
|
1807
2139
|
this.config = { ...config };
|
|
1808
2140
|
if (!this.config.environment) this.config.environment = "production";
|
|
1809
2141
|
if (!this.config.sdkName) this.config.sdkName = SDK_NAME;
|
|
@@ -1825,6 +2157,18 @@ var AllStakClient = class {
|
|
|
1825
2157
|
} catch {
|
|
1826
2158
|
}
|
|
1827
2159
|
}
|
|
2160
|
+
try {
|
|
2161
|
+
const opts = {
|
|
2162
|
+
captureDeviceContext: config.captureDeviceContext !== false,
|
|
2163
|
+
captureBattery: config.captureBattery === true,
|
|
2164
|
+
captureScreenContext: config.captureScreenContext !== false,
|
|
2165
|
+
sendDefaultPii: config.sendDefaultPii === true
|
|
2166
|
+
};
|
|
2167
|
+
const { contexts, tags } = collectAutoContexts(opts);
|
|
2168
|
+
this.autoContexts = contexts;
|
|
2169
|
+
this.autoTags = tags;
|
|
2170
|
+
} catch {
|
|
2171
|
+
}
|
|
1828
2172
|
if (config.enableHttpTracking) {
|
|
1829
2173
|
try {
|
|
1830
2174
|
this.httpRequests = new HttpRequestModule(this.transport);
|
|
@@ -1867,7 +2211,7 @@ var AllStakClient = class {
|
|
|
1867
2211
|
return this.httpRequests?.getRecentFailed() ?? [];
|
|
1868
2212
|
}
|
|
1869
2213
|
// ── Public API ────────────────────────────────────────────────────
|
|
1870
|
-
captureException(error, context) {
|
|
2214
|
+
captureException(error, context, opts) {
|
|
1871
2215
|
if (!this.passesSampleRate()) return;
|
|
1872
2216
|
const frames = parseStack(error.stack).map((f) => ({
|
|
1873
2217
|
...f,
|
|
@@ -1949,6 +2293,35 @@ var AllStakClient = class {
|
|
|
1949
2293
|
breadcrumbs: currentBreadcrumbs,
|
|
1950
2294
|
fingerprint: eff.fingerprint
|
|
1951
2295
|
};
|
|
2296
|
+
const mechanism = opts?.mechanism ?? "captureException";
|
|
2297
|
+
const handled = opts?.handled ?? (mechanism === "captureException" || mechanism === "errorboundary");
|
|
2298
|
+
payload.eventId = generateEventId();
|
|
2299
|
+
payload.timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
2300
|
+
payload.handled = handled;
|
|
2301
|
+
payload.mechanism = mechanism;
|
|
2302
|
+
if (this.currentTransaction) payload.transaction = this.currentTransaction;
|
|
2303
|
+
payload.exception = { values: buildExceptionChain(error, mechanism, handled) };
|
|
2304
|
+
const req = maybeExtractHttpRequest(error);
|
|
2305
|
+
if (req) payload.request = req;
|
|
2306
|
+
const userCtx = buildUserContext(eff.user, { sendDefaultPii: this.config.sendDefaultPii });
|
|
2307
|
+
const traceCtx = {};
|
|
2308
|
+
if (payload.traceId) traceCtx.trace_id = payload.traceId;
|
|
2309
|
+
if (payload.spanId) traceCtx.span_id = payload.spanId;
|
|
2310
|
+
if (payload.parentSpanId) traceCtx.parent_span_id = payload.parentSpanId;
|
|
2311
|
+
payload.contexts = {
|
|
2312
|
+
...this.autoContexts,
|
|
2313
|
+
...eff.contexts ?? {},
|
|
2314
|
+
...userCtx ? { user: userCtx } : {},
|
|
2315
|
+
...Object.keys(traceCtx).length > 0 ? { trace: traceCtx } : {}
|
|
2316
|
+
};
|
|
2317
|
+
payload.tags = {
|
|
2318
|
+
...this.autoTags,
|
|
2319
|
+
...this.config.tags ?? {},
|
|
2320
|
+
...eff.tags ?? {},
|
|
2321
|
+
environment: this.config.environment ?? "production",
|
|
2322
|
+
...this.config.release ? { release: this.config.release } : {},
|
|
2323
|
+
...this.config.dist ? { dist: this.config.dist } : {}
|
|
2324
|
+
};
|
|
1952
2325
|
const flatPresent = this.config.captureScreenshotOnError === true;
|
|
1953
2326
|
const callbackPresent = Boolean(this.config.screenshot?.provider);
|
|
1954
2327
|
warnIfBothApisPresent(callbackPresent, flatPresent);
|
|
@@ -2106,16 +2479,59 @@ var AllStakClient = class {
|
|
|
2106
2479
|
}
|
|
2107
2480
|
}
|
|
2108
2481
|
addBreadcrumb(type, message, level, data) {
|
|
2109
|
-
|
|
2482
|
+
let crumb = {
|
|
2110
2483
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2111
2484
|
type: VALID_BREADCRUMB_TYPES.has(type) ? type : "default",
|
|
2112
2485
|
message,
|
|
2113
2486
|
level: level && VALID_BREADCRUMB_LEVELS.has(level) ? level : "info",
|
|
2114
2487
|
...data ? { data } : {}
|
|
2115
2488
|
};
|
|
2489
|
+
if (crumb.type === "http" && (this.config.denyUrls || this.config.allowUrls)) {
|
|
2490
|
+
const url = typeof crumb.data?.url === "string" ? crumb.data.url : "";
|
|
2491
|
+
if (url) {
|
|
2492
|
+
if (this.config.denyUrls && this.config.denyUrls.some((p) => matchUrlPattern(url, p))) return;
|
|
2493
|
+
if (this.config.allowUrls && this.config.allowUrls.length > 0 && !this.config.allowUrls.some((p) => matchUrlPattern(url, p))) return;
|
|
2494
|
+
}
|
|
2495
|
+
}
|
|
2496
|
+
if (crumb.data && this.config.scrubKeys && this.config.scrubKeys.length > 0) {
|
|
2497
|
+
crumb = { ...crumb, data: scrubObject(crumb.data, this.config.scrubKeys) };
|
|
2498
|
+
}
|
|
2499
|
+
if (this.config.beforeBreadcrumb) {
|
|
2500
|
+
try {
|
|
2501
|
+
const out = this.config.beforeBreadcrumb(crumb);
|
|
2502
|
+
if (out === null) return;
|
|
2503
|
+
if (out) crumb = out;
|
|
2504
|
+
} catch {
|
|
2505
|
+
}
|
|
2506
|
+
}
|
|
2116
2507
|
if (this.breadcrumbs.length >= this.maxBreadcrumbs) this.breadcrumbs.shift();
|
|
2117
2508
|
this.breadcrumbs.push(crumb);
|
|
2118
2509
|
}
|
|
2510
|
+
/**
|
|
2511
|
+
* Set the current screen / route name. Stamps `transaction` on every
|
|
2512
|
+
* subsequent event and emits a `navigation` breadcrumb. Use this when
|
|
2513
|
+
* not on `@react-navigation/native` (the nav auto-instrument calls
|
|
2514
|
+
* this for you).
|
|
2515
|
+
*/
|
|
2516
|
+
setCurrentScreen(name) {
|
|
2517
|
+
if (!name) return;
|
|
2518
|
+
const prev = this.currentTransaction;
|
|
2519
|
+
this.currentTransaction = name;
|
|
2520
|
+
if (prev !== name) {
|
|
2521
|
+
this.addBreadcrumb("navigation", `${prev ?? "<start>"} -> ${name}`, "info", {
|
|
2522
|
+
from: prev,
|
|
2523
|
+
to: name
|
|
2524
|
+
});
|
|
2525
|
+
}
|
|
2526
|
+
}
|
|
2527
|
+
/** @internal — current transaction (or undefined). */
|
|
2528
|
+
getCurrentTransaction() {
|
|
2529
|
+
return this.currentTransaction ?? void 0;
|
|
2530
|
+
}
|
|
2531
|
+
/** @internal — set transaction without emitting a breadcrumb. */
|
|
2532
|
+
__setTransactionSilent(name) {
|
|
2533
|
+
this.currentTransaction = name && name.length > 0 ? name : null;
|
|
2534
|
+
}
|
|
2119
2535
|
clearBreadcrumbs() {
|
|
2120
2536
|
this.breadcrumbs = [];
|
|
2121
2537
|
}
|
|
@@ -2396,9 +2812,9 @@ var AllStak = {
|
|
|
2396
2812
|
return instance;
|
|
2397
2813
|
}
|
|
2398
2814
|
},
|
|
2399
|
-
captureException(error, context) {
|
|
2815
|
+
captureException(error, context, opts) {
|
|
2400
2816
|
try {
|
|
2401
|
-
maybeInit()?.captureException(error, context);
|
|
2817
|
+
maybeInit()?.captureException(error, context, opts);
|
|
2402
2818
|
} catch {
|
|
2403
2819
|
}
|
|
2404
2820
|
},
|
|
@@ -2481,6 +2897,27 @@ var AllStak = {
|
|
|
2481
2897
|
} catch {
|
|
2482
2898
|
}
|
|
2483
2899
|
},
|
|
2900
|
+
/** Set the current screen / transaction name. Stamps event.transaction + emits nav breadcrumb. */
|
|
2901
|
+
setCurrentScreen(name) {
|
|
2902
|
+
try {
|
|
2903
|
+
maybeInit()?.setCurrentScreen(name);
|
|
2904
|
+
} catch {
|
|
2905
|
+
}
|
|
2906
|
+
},
|
|
2907
|
+
getCurrentTransaction() {
|
|
2908
|
+
try {
|
|
2909
|
+
return maybeInit()?.getCurrentTransaction();
|
|
2910
|
+
} catch {
|
|
2911
|
+
return void 0;
|
|
2912
|
+
}
|
|
2913
|
+
},
|
|
2914
|
+
/** @internal — set transaction without emitting a breadcrumb (nav auto-instrument uses this). */
|
|
2915
|
+
__setTransactionSilent(name) {
|
|
2916
|
+
try {
|
|
2917
|
+
maybeInit()?.__setTransactionSilent(name);
|
|
2918
|
+
} catch {
|
|
2919
|
+
}
|
|
2920
|
+
},
|
|
2484
2921
|
/**
|
|
2485
2922
|
* Run `callback` with a fresh scoped context. Any user/tag/extra/context/
|
|
2486
2923
|
* fingerprint/level set on the passed `Scope` is visible only inside the
|
|
@@ -2570,6 +3007,29 @@ var AllStak = {
|
|
|
2570
3007
|
return instance;
|
|
2571
3008
|
}
|
|
2572
3009
|
};
|
|
3010
|
+
function matchUrlPattern(url, p) {
|
|
3011
|
+
if (!url || !p) return false;
|
|
3012
|
+
if (typeof p === "string") return url.includes(p);
|
|
3013
|
+
try {
|
|
3014
|
+
return p.test(url);
|
|
3015
|
+
} catch {
|
|
3016
|
+
return false;
|
|
3017
|
+
}
|
|
3018
|
+
}
|
|
3019
|
+
function scrubObject(obj, keys) {
|
|
3020
|
+
if (!obj || keys.length === 0) return obj;
|
|
3021
|
+
const out = {};
|
|
3022
|
+
const lower = new Set(keys.map((k) => k.toLowerCase()));
|
|
3023
|
+
for (const [k, v] of Object.entries(obj)) {
|
|
3024
|
+
out[k] = lower.has(k.toLowerCase()) ? "[Filtered]" : v;
|
|
3025
|
+
}
|
|
3026
|
+
return out;
|
|
3027
|
+
}
|
|
3028
|
+
function generateEventId() {
|
|
3029
|
+
const hex = (n) => Math.floor(Math.random() * n).toString(16).padStart(1, "0");
|
|
3030
|
+
const seg = (len) => Array.from({ length: len }, () => hex(16)).join("");
|
|
3031
|
+
return `${seg(8)}-${seg(4)}-4${seg(3)}-${(8 + Math.floor(Math.random() * 4)).toString(16)}${seg(3)}-${seg(12)}`;
|
|
3032
|
+
}
|
|
2573
3033
|
function byteSize(value) {
|
|
2574
3034
|
if (!value) return 0;
|
|
2575
3035
|
try {
|
|
@@ -2774,6 +3234,10 @@ function instrumentReactNavigation(navigationRef, options = {}) {
|
|
|
2774
3234
|
);
|
|
2775
3235
|
} catch {
|
|
2776
3236
|
}
|
|
3237
|
+
try {
|
|
3238
|
+
AllStak.__setTransactionSilent?.(next);
|
|
3239
|
+
} catch {
|
|
3240
|
+
}
|
|
2777
3241
|
if (forwardToReplay) {
|
|
2778
3242
|
try {
|
|
2779
3243
|
const replay = AllStak.getReplay?.();
|
|
@@ -3013,7 +3477,7 @@ function installReactNative(options = {}) {
|
|
|
3013
3477
|
AllStak.captureException(error, {
|
|
3014
3478
|
source: "react-native-ErrorUtils",
|
|
3015
3479
|
fatal: String(Boolean(isFatal))
|
|
3016
|
-
});
|
|
3480
|
+
}, { mechanism: "onerror", handled: false });
|
|
3017
3481
|
} catch {
|
|
3018
3482
|
}
|
|
3019
3483
|
try {
|
|
@@ -3027,7 +3491,11 @@ function installReactNative(options = {}) {
|
|
|
3027
3491
|
const wrapTrackerReason = (rejection) => rejection instanceof Error ? rejection : new Error(`Unhandled promise rejection: ${String(rejection)}`);
|
|
3028
3492
|
const ship = (err) => {
|
|
3029
3493
|
try {
|
|
3030
|
-
AllStak.captureException(
|
|
3494
|
+
AllStak.captureException(
|
|
3495
|
+
err,
|
|
3496
|
+
{ source: "unhandledRejection" },
|
|
3497
|
+
{ mechanism: "onunhandledrejection", handled: false }
|
|
3498
|
+
);
|
|
3031
3499
|
} catch {
|
|
3032
3500
|
}
|
|
3033
3501
|
};
|
|
@@ -3065,8 +3533,13 @@ function installReactNative(options = {}) {
|
|
|
3065
3533
|
}
|
|
3066
3534
|
|
|
3067
3535
|
// src/provider.tsx
|
|
3068
|
-
|
|
3069
|
-
|
|
3536
|
+
function getRN2() {
|
|
3537
|
+
return tryRequire("react-native");
|
|
3538
|
+
}
|
|
3539
|
+
function getRootView() {
|
|
3540
|
+
const RN = getRN2();
|
|
3541
|
+
return RN?.View;
|
|
3542
|
+
}
|
|
3070
3543
|
var AllStakContext = React2.createContext(null);
|
|
3071
3544
|
var __providerOwnedInstance = null;
|
|
3072
3545
|
var AllStakErrorBoundary = class extends React2.Component {
|
|
@@ -3086,7 +3559,7 @@ var AllStakErrorBoundary = class extends React2.Component {
|
|
|
3086
3559
|
AllStak.captureException(error, {
|
|
3087
3560
|
componentStack: info.componentStack ?? "",
|
|
3088
3561
|
source: "AllStakProvider.ErrorBoundary"
|
|
3089
|
-
});
|
|
3562
|
+
}, { mechanism: "errorboundary", handled: true });
|
|
3090
3563
|
if (this.props.debug) {
|
|
3091
3564
|
console.log(`[AllStak] Captured render error: ${error.message}`);
|
|
3092
3565
|
}
|
|
@@ -3204,6 +3677,10 @@ function AllStakProvider({
|
|
|
3204
3677
|
};
|
|
3205
3678
|
clientRef.current = AllStak.init(config);
|
|
3206
3679
|
__providerOwnedInstance = clientRef.current;
|
|
3680
|
+
try {
|
|
3681
|
+
AllStak.addBreadcrumb("default", "app.start", "info", { source: "AllStakProvider" });
|
|
3682
|
+
} catch {
|
|
3683
|
+
}
|
|
3207
3684
|
installReactNative({
|
|
3208
3685
|
autoErrorHandler,
|
|
3209
3686
|
autoPromiseRejections,
|
|
@@ -3231,7 +3708,8 @@ function AllStakProvider({
|
|
|
3231
3708
|
};
|
|
3232
3709
|
}, [destroyOnUnmount, debug]);
|
|
3233
3710
|
const boundary = /* @__PURE__ */ React2.createElement(AllStakErrorBoundary, { fallback, onError, debug }, children);
|
|
3234
|
-
const
|
|
3711
|
+
const RootView = getRootView();
|
|
3712
|
+
const wrapped = RootView ? React2.createElement(
|
|
3235
3713
|
RootView,
|
|
3236
3714
|
{ ref: rootRef, style: { flex: 1 }, collapsable: false },
|
|
3237
3715
|
boundary
|
|
@@ -3296,7 +3774,7 @@ async function drainPendingNativeCrashes(release) {
|
|
|
3296
3774
|
AllStak.captureException(err, {
|
|
3297
3775
|
...payload?.metadata || {},
|
|
3298
3776
|
"native.crash": "true"
|
|
3299
|
-
});
|
|
3777
|
+
}, { mechanism: "native_crash", handled: false });
|
|
3300
3778
|
} catch {
|
|
3301
3779
|
}
|
|
3302
3780
|
}
|
|
@@ -3331,23 +3809,30 @@ export {
|
|
|
3331
3809
|
__resetRuntimeModeForTest,
|
|
3332
3810
|
__setNativeModuleForTest,
|
|
3333
3811
|
applyArchitectureTags,
|
|
3812
|
+
buildExceptionChain,
|
|
3813
|
+
buildUserContext,
|
|
3334
3814
|
captureBodyResult,
|
|
3335
3815
|
captureViaViewShot,
|
|
3816
|
+
classifyHttpError,
|
|
3817
|
+
collectAutoContexts,
|
|
3336
3818
|
detectArchitecture,
|
|
3337
3819
|
detectRuntimeMode,
|
|
3338
3820
|
drainPendingNativeCrashes,
|
|
3821
|
+
extractAxiosRequest,
|
|
3339
3822
|
installReactNative,
|
|
3340
3823
|
instrumentNavigationFromLinking,
|
|
3341
3824
|
instrumentReactNavigation,
|
|
3342
3825
|
isCapturingScreenshot,
|
|
3343
3826
|
isViewShotAvailable,
|
|
3344
3827
|
maybeCaptureScreenshot,
|
|
3828
|
+
maybeExtractHttpRequest,
|
|
3345
3829
|
pickScreenshotConfig,
|
|
3346
3830
|
redactUrl,
|
|
3347
3831
|
registerSensitiveRef,
|
|
3348
3832
|
resolveScreenshotConfig,
|
|
3349
3833
|
runtimeAllowsScreenshot,
|
|
3350
3834
|
sanitizeHeaders,
|
|
3835
|
+
sanitizeUrl,
|
|
3351
3836
|
tryAutoInstrumentNavigation,
|
|
3352
3837
|
useAllStak,
|
|
3353
3838
|
useAllStakPrivacy
|