@smarthivelabs-devs/observe-expo 0.0.0-stage → 26.1.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/LICENSE +21 -0
- package/README.md +103 -2
- package/app.plugin.cjs +1 -0
- package/dist/chunk-HDKJGFST.js +362 -0
- package/dist/chunk-HDKJGFST.js.map +1 -0
- package/dist/index.cjs +399 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +130 -0
- package/dist/index.d.ts +130 -0
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -0
- package/dist/plugin.cjs +99 -0
- package/dist/plugin.cjs.map +1 -0
- package/dist/plugin.d.cts +18 -0
- package/dist/plugin.d.ts +18 -0
- package/dist/plugin.js +74 -0
- package/dist/plugin.js.map +1 -0
- package/dist/react.cjs +414 -0
- package/dist/react.cjs.map +1 -0
- package/dist/react.d.cts +18 -0
- package/dist/react.d.ts +18 -0
- package/dist/react.js +24 -0
- package/dist/react.js.map +1 -0
- package/package.json +79 -3
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,399 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
|
|
30
|
+
// src/index.ts
|
|
31
|
+
var index_exports = {};
|
|
32
|
+
__export(index_exports, {
|
|
33
|
+
SmartObserve: () => SmartObserve,
|
|
34
|
+
SmartObserveExpoClient: () => SmartObserveExpoClient
|
|
35
|
+
});
|
|
36
|
+
module.exports = __toCommonJS(index_exports);
|
|
37
|
+
|
|
38
|
+
// src/client.ts
|
|
39
|
+
var import_react_native = require("react-native");
|
|
40
|
+
var Application = __toESM(require("expo-application"), 1);
|
|
41
|
+
var import_expo_constants = __toESM(require("expo-constants"), 1);
|
|
42
|
+
var Device = __toESM(require("expo-device"), 1);
|
|
43
|
+
|
|
44
|
+
// src/internal.ts
|
|
45
|
+
function id() {
|
|
46
|
+
return crypto.randomUUID();
|
|
47
|
+
}
|
|
48
|
+
function randomHex(bytes) {
|
|
49
|
+
return [...crypto.getRandomValues(new Uint8Array(bytes))].map((value) => value.toString(16).padStart(2, "0")).join("");
|
|
50
|
+
}
|
|
51
|
+
function parseDsn(value) {
|
|
52
|
+
const url = new URL(value);
|
|
53
|
+
const key = decodeURIComponent(url.username);
|
|
54
|
+
if (!/^(pk|sk)_[A-Za-z0-9_-]{16,}$/.test(key)) throw new Error("SmartObserve DSN contains an invalid project key");
|
|
55
|
+
const slug = url.pathname.replace(/^\/+|\/+$/g, "");
|
|
56
|
+
if (!slug) throw new Error("SmartObserve DSN must include a project slug");
|
|
57
|
+
return { endpoint: `${url.protocol}//${url.host}/api/v1/envelope`, key };
|
|
58
|
+
}
|
|
59
|
+
var BLOCKED = /* @__PURE__ */ new Set(["password", "passcode", "authorization", "cookie", "access_token", "refresh_token", "api_key", "secret", "private_key", "card_number", "cvv", "cvc"]);
|
|
60
|
+
function sanitize(input, extra = []) {
|
|
61
|
+
const blocked = /* @__PURE__ */ new Set([...BLOCKED, ...extra.map((value) => value.toLowerCase())]);
|
|
62
|
+
const seen = /* @__PURE__ */ new WeakSet();
|
|
63
|
+
const walk = (value, depth) => {
|
|
64
|
+
if (depth > 5) return "[Truncated]";
|
|
65
|
+
if (typeof value === "string") return value.slice(0, 8192);
|
|
66
|
+
if (value === null || typeof value !== "object") return value;
|
|
67
|
+
if (seen.has(value)) return "[Circular]";
|
|
68
|
+
seen.add(value);
|
|
69
|
+
if (Array.isArray(value)) return value.slice(0, 200).map((entry) => walk(entry, depth + 1));
|
|
70
|
+
return Object.fromEntries(Object.entries(value).slice(0, 200).map(([key, entry]) => [key, blocked.has(key.toLowerCase().replace(/[\s-]+/g, "_")) ? "[Redacted]" : walk(entry, depth + 1)]));
|
|
71
|
+
};
|
|
72
|
+
return walk(input, 0);
|
|
73
|
+
}
|
|
74
|
+
function safeUrl(value) {
|
|
75
|
+
try {
|
|
76
|
+
const url = new URL(value);
|
|
77
|
+
url.username = "";
|
|
78
|
+
url.password = "";
|
|
79
|
+
for (const key of [...url.searchParams.keys()]) url.searchParams.set(key, "[Filtered]");
|
|
80
|
+
return url.toString();
|
|
81
|
+
} catch {
|
|
82
|
+
return "[Invalid URL]";
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// src/transport.ts
|
|
87
|
+
var import_async_storage = __toESM(require("@react-native-async-storage/async-storage"), 1);
|
|
88
|
+
var import_netinfo = __toESM(require("@react-native-community/netinfo"), 1);
|
|
89
|
+
|
|
90
|
+
// src/sdk-meta.ts
|
|
91
|
+
var SDK_NAME = "@smarthivelabs-devs/observe-expo";
|
|
92
|
+
var SDK_VERSION = "26.1.0";
|
|
93
|
+
|
|
94
|
+
// src/transport.ts
|
|
95
|
+
var STORAGE_KEY = "@smartobserve/events/v1";
|
|
96
|
+
var ExpoTransport = class {
|
|
97
|
+
constructor(options) {
|
|
98
|
+
this.options = options;
|
|
99
|
+
this.timer = setInterval(() => void this.flush(), options.flushIntervalMs);
|
|
100
|
+
this.unsubscribe = import_netinfo.default.addEventListener((state) => {
|
|
101
|
+
this.online = state.isConnected !== false;
|
|
102
|
+
if (this.online) void this.flush();
|
|
103
|
+
});
|
|
104
|
+
void this.restore();
|
|
105
|
+
}
|
|
106
|
+
options;
|
|
107
|
+
queue = [];
|
|
108
|
+
timer;
|
|
109
|
+
flushing;
|
|
110
|
+
online = true;
|
|
111
|
+
unsubscribe;
|
|
112
|
+
closed = false;
|
|
113
|
+
enqueue(event) {
|
|
114
|
+
if (this.closed) return;
|
|
115
|
+
if (this.queue.length >= this.options.maxQueueSize) this.evict();
|
|
116
|
+
this.queue.push(event);
|
|
117
|
+
void this.persist();
|
|
118
|
+
if (this.queue.length >= 50 || event.level === "fatal") void this.flush();
|
|
119
|
+
}
|
|
120
|
+
async flush() {
|
|
121
|
+
if (this.flushing || !this.queue.length || !this.online) return this.flushing;
|
|
122
|
+
const events = this.queue.splice(0, 50);
|
|
123
|
+
this.flushing = this.send(events).then(() => this.persist()).catch((error) => {
|
|
124
|
+
this.queue.unshift(...events);
|
|
125
|
+
void this.persist();
|
|
126
|
+
if (this.options.debug) console.warn("[SmartObserve] offline batch retained", error);
|
|
127
|
+
}).finally(() => {
|
|
128
|
+
this.flushing = void 0;
|
|
129
|
+
});
|
|
130
|
+
return this.flushing;
|
|
131
|
+
}
|
|
132
|
+
async close() {
|
|
133
|
+
this.closed = true;
|
|
134
|
+
if (this.timer) clearInterval(this.timer);
|
|
135
|
+
this.unsubscribe?.();
|
|
136
|
+
await this.flush();
|
|
137
|
+
}
|
|
138
|
+
async restore() {
|
|
139
|
+
try {
|
|
140
|
+
const raw = await import_async_storage.default.getItem(STORAGE_KEY);
|
|
141
|
+
if (!raw) return;
|
|
142
|
+
const stored = JSON.parse(raw);
|
|
143
|
+
this.queue.push(...stored.filter((event) => Date.now() - (event._storedAt ?? event.timestamp) < 7 * 864e5).slice(-this.options.maxQueueSize));
|
|
144
|
+
await this.flush();
|
|
145
|
+
} catch (error) {
|
|
146
|
+
if (this.options.debug) console.warn("[SmartObserve] offline queue unavailable", error);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
async persist() {
|
|
150
|
+
try {
|
|
151
|
+
let prepared = this.queue.map((event) => ({ ...event, _storedAt: Date.now() }));
|
|
152
|
+
let raw = JSON.stringify(prepared);
|
|
153
|
+
while (raw.length > 10 * 1024 * 1024 && this.queue.length) {
|
|
154
|
+
this.evict();
|
|
155
|
+
prepared = this.queue.map((event) => ({ ...event, _storedAt: Date.now() }));
|
|
156
|
+
raw = JSON.stringify(prepared);
|
|
157
|
+
}
|
|
158
|
+
await import_async_storage.default.setItem(STORAGE_KEY, raw);
|
|
159
|
+
} catch (error) {
|
|
160
|
+
if (this.options.debug) console.warn("[SmartObserve] could not persist offline queue", error);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
async send(events) {
|
|
164
|
+
const body = JSON.stringify({ schemaVersion: 1, envelopeId: id(), sentAt: Date.now(), sdk: { name: SDK_NAME, version: SDK_VERSION }, environment: this.options.environment, release: this.options.release, dist: this.options.dist, events });
|
|
165
|
+
let attempt = 0;
|
|
166
|
+
while (true) {
|
|
167
|
+
const response = await fetch(this.options.endpoint, { method: "POST", headers: { "content-type": "application/json", "origin": "smartobserve-expo://native", "x-smartobserve-key": this.options.key, "x-smartobserve-platform": "expo", "x-smartobserve-internal": "transport" }, body });
|
|
168
|
+
if (response.ok) return;
|
|
169
|
+
if (![408, 429].includes(response.status) && response.status < 500) return;
|
|
170
|
+
if (attempt++ >= 5) throw new Error(`HTTP ${response.status}`);
|
|
171
|
+
await new Promise((resolve) => setTimeout(resolve, Math.random() * Math.min(3e4, 2 ** attempt * 1e3)));
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
evict() {
|
|
175
|
+
const index = this.queue.findIndex((event) => event.type === "span" || event.type === "performance" || event.level === "debug");
|
|
176
|
+
this.queue.splice(index < 0 ? 0 : index, 1);
|
|
177
|
+
}
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
// src/client.ts
|
|
181
|
+
var SmartObserveExpoClient = class {
|
|
182
|
+
config;
|
|
183
|
+
transport;
|
|
184
|
+
user;
|
|
185
|
+
tags = {};
|
|
186
|
+
contexts = {};
|
|
187
|
+
breadcrumbs = [];
|
|
188
|
+
trace;
|
|
189
|
+
beforeSendHook;
|
|
190
|
+
cleanups = [];
|
|
191
|
+
sessionId = id();
|
|
192
|
+
sessionStarted = Date.now();
|
|
193
|
+
constructor(input = {}) {
|
|
194
|
+
this.config = { ...input, environment: input.environment ?? "production", enabled: input.enabled ?? Boolean(input.dsn), debug: input.debug ?? false, tracesSampleRate: input.tracesSampleRate ?? input.sampleRate ?? 0.1, errorSampleRate: input.errorSampleRate ?? 1, maxBreadcrumbs: input.maxBreadcrumbs ?? 100 };
|
|
195
|
+
this.beforeSendHook = input.beforeSend;
|
|
196
|
+
if (this.config.enabled && input.dsn) {
|
|
197
|
+
const parsed = parseDsn(input.dsn);
|
|
198
|
+
this.transport = new ExpoTransport({ ...parsed, environment: this.config.environment, release: input.release ?? Application.nativeApplicationVersion ?? void 0, dist: input.dist ?? Application.nativeBuildVersion ?? void 0, maxQueueSize: input.maxQueueSize ?? 1e3, flushIntervalMs: input.flushIntervalMs ?? 5e3, debug: this.config.debug });
|
|
199
|
+
this.setup(parsed.endpoint);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
captureException(error, hint = {}) {
|
|
203
|
+
const eventId = id();
|
|
204
|
+
if (Math.random() <= this.config.errorSampleRate) {
|
|
205
|
+
const exception = serialize(error);
|
|
206
|
+
void this.capture({ ...this.base("error"), eventId, message: exception.value, level: "error", exceptions: [exception], metadata: hint });
|
|
207
|
+
}
|
|
208
|
+
return eventId;
|
|
209
|
+
}
|
|
210
|
+
captureMessage(message, level = "info", metadata) {
|
|
211
|
+
const eventId = id();
|
|
212
|
+
void this.capture({ ...this.base("log"), eventId, message, level, metadata });
|
|
213
|
+
return eventId;
|
|
214
|
+
}
|
|
215
|
+
log = { debug: (m, d) => this.captureMessage(m, "debug", d), info: (m, d) => this.captureMessage(m, "info", d), warn: (m, d) => this.captureMessage(m, "warn", d), error: (m, d) => this.captureMessage(m, "error", d) };
|
|
216
|
+
addBreadcrumb(value) {
|
|
217
|
+
this.breadcrumbs.push({ ...sanitize(value, this.config.redactKeys), timestamp: value.timestamp ?? Date.now() });
|
|
218
|
+
this.breadcrumbs.splice(0, Math.max(0, this.breadcrumbs.length - this.config.maxBreadcrumbs));
|
|
219
|
+
}
|
|
220
|
+
setUser(value) {
|
|
221
|
+
this.user = value ? sanitize(value, this.config.redactKeys) : void 0;
|
|
222
|
+
}
|
|
223
|
+
setTag(key, value) {
|
|
224
|
+
if (value === null) delete this.tags[key];
|
|
225
|
+
else this.tags[key.slice(0, 64)] = value.slice(0, 256);
|
|
226
|
+
}
|
|
227
|
+
setContext(key, value) {
|
|
228
|
+
if (value === null) delete this.contexts[key];
|
|
229
|
+
else this.contexts[key] = sanitize(value, this.config.redactKeys);
|
|
230
|
+
}
|
|
231
|
+
beforeSend(callback) {
|
|
232
|
+
this.beforeSendHook = callback;
|
|
233
|
+
}
|
|
234
|
+
startSpan(options, callback) {
|
|
235
|
+
const previous = this.trace;
|
|
236
|
+
const trace = { traceId: options.parent?.traceId ?? previous?.traceId ?? randomHex(16), spanId: randomHex(8), parentSpanId: options.parent?.spanId ?? previous?.spanId, sampled: options.sampled ?? previous?.sampled ?? Math.random() < this.config.tracesSampleRate };
|
|
237
|
+
const start = Date.now();
|
|
238
|
+
const attributes = { ...options.attributes ?? {} };
|
|
239
|
+
let status = "unknown";
|
|
240
|
+
let ended = false;
|
|
241
|
+
const span = { traceId: trace.traceId, spanId: trace.spanId, setAttribute: (key, value) => {
|
|
242
|
+
attributes[key] = value;
|
|
243
|
+
}, setStatus: (value) => {
|
|
244
|
+
status = value;
|
|
245
|
+
}, recordException: (error) => {
|
|
246
|
+
status = "error";
|
|
247
|
+
this.captureException(error);
|
|
248
|
+
}, end: () => {
|
|
249
|
+
if (!ended && trace.sampled) {
|
|
250
|
+
ended = true;
|
|
251
|
+
const isRoot = !trace.parentSpanId;
|
|
252
|
+
void this.capture({ ...this.base(isRoot ? "transaction" : "span"), name: options.name, operation: options.operation, startTimestamp: start, endTimestamp: Date.now(), status, ...isRoot ? {} : { attributes }, trace });
|
|
253
|
+
}
|
|
254
|
+
} };
|
|
255
|
+
this.trace = trace;
|
|
256
|
+
try {
|
|
257
|
+
const result = callback(span);
|
|
258
|
+
if (result && typeof result.then === "function") return result.then((value) => {
|
|
259
|
+
if (status === "unknown") status = "ok";
|
|
260
|
+
span.end();
|
|
261
|
+
return value;
|
|
262
|
+
}, (error) => {
|
|
263
|
+
span.recordException(error);
|
|
264
|
+
span.end();
|
|
265
|
+
throw error;
|
|
266
|
+
}).finally(() => {
|
|
267
|
+
this.trace = previous;
|
|
268
|
+
});
|
|
269
|
+
if (status === "unknown") status = "ok";
|
|
270
|
+
span.end();
|
|
271
|
+
return result;
|
|
272
|
+
} finally {
|
|
273
|
+
if (this.trace?.spanId === trace.spanId) this.trace = previous;
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
flush() {
|
|
277
|
+
return this.transport?.flush() ?? Promise.resolve();
|
|
278
|
+
}
|
|
279
|
+
async close() {
|
|
280
|
+
for (const cleanup of this.cleanups.splice(0)) cleanup();
|
|
281
|
+
await this.transport?.close();
|
|
282
|
+
}
|
|
283
|
+
trackScreen(name, params) {
|
|
284
|
+
this.addBreadcrumb({ category: "navigation", message: name, data: params });
|
|
285
|
+
}
|
|
286
|
+
base(type) {
|
|
287
|
+
return { eventId: id(), type, timestamp: Date.now(), platform: "expo", user: applyUser(this.user, this.config.sendDefaultPii), tags: { ...this.tags }, contexts: sanitize({ ...this.contexts, device: { brand: Device.brand, model: Device.modelName, deviceType: Device.deviceType, os: import_react_native.Platform.OS, osVersion: import_react_native.Platform.Version, isDevice: Device.isDevice }, app: { id: Application.applicationId, name: Application.applicationName, version: Application.nativeApplicationVersion, build: Application.nativeBuildVersion, runtimeVersion: import_expo_constants.default.expoConfig?.runtimeVersion } }, this.config.redactKeys), breadcrumbs: [...this.breadcrumbs], trace: this.trace };
|
|
288
|
+
}
|
|
289
|
+
async capture(raw) {
|
|
290
|
+
if (!this.transport) return;
|
|
291
|
+
try {
|
|
292
|
+
let event = sanitize(raw, this.config.redactKeys);
|
|
293
|
+
if (this.beforeSendHook) event = await this.beforeSendHook(event);
|
|
294
|
+
if (event) this.transport.enqueue(event);
|
|
295
|
+
} catch (error) {
|
|
296
|
+
if (this.config.debug) console.warn("[SmartObserve] event dropped", error);
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
setup(endpoint) {
|
|
300
|
+
const original = typeof ErrorUtils !== "undefined" ? ErrorUtils.getGlobalHandler() : void 0;
|
|
301
|
+
if (original && typeof ErrorUtils !== "undefined") {
|
|
302
|
+
ErrorUtils.setGlobalHandler((error, fatal) => {
|
|
303
|
+
this.captureException(error, { mechanism: "react-native.global", fatal });
|
|
304
|
+
if (fatal) void this.capture({ ...this.base("session"), sessionId: this.sessionId, startedAt: this.sessionStarted, endedAt: Date.now(), status: "crashed" });
|
|
305
|
+
original(error, fatal);
|
|
306
|
+
});
|
|
307
|
+
this.cleanups.push(() => ErrorUtils.setGlobalHandler(original));
|
|
308
|
+
}
|
|
309
|
+
if (this.config.trackLifecycle !== false) {
|
|
310
|
+
const sub = import_react_native.AppState.addEventListener("change", (state) => {
|
|
311
|
+
this.addBreadcrumb({ category: "app.lifecycle", message: state });
|
|
312
|
+
if (state === "active") void this.flush();
|
|
313
|
+
if (state === "background" || state === "inactive") void this.capture({ ...this.base("session"), sessionId: this.sessionId, startedAt: this.sessionStarted, endedAt: Date.now(), status: "exited" });
|
|
314
|
+
});
|
|
315
|
+
this.cleanups.push(() => sub.remove());
|
|
316
|
+
}
|
|
317
|
+
if (this.config.trackNetwork !== false) this.patchFetch(endpoint);
|
|
318
|
+
void this.capture({ ...this.base("session"), sessionId: this.sessionId, startedAt: this.sessionStarted, status: "active" });
|
|
319
|
+
}
|
|
320
|
+
patchFetch(endpoint) {
|
|
321
|
+
const original = globalThis.fetch;
|
|
322
|
+
const client2 = this;
|
|
323
|
+
globalThis.fetch = async function(input, init) {
|
|
324
|
+
const url = typeof input === "string" ? input : input instanceof URL ? input.href : input.url;
|
|
325
|
+
if (url.startsWith(endpoint) || init?.headers && new Headers(init.headers).has("x-smartobserve-internal")) return original(input, init);
|
|
326
|
+
const started = Date.now();
|
|
327
|
+
const method = init?.method ?? (typeof input === "object" && "method" in input ? input.method : "GET");
|
|
328
|
+
client2.addBreadcrumb({ category: "http", message: `${method} ${safeUrl(url)}`, data: { method, url: safeUrl(url) } });
|
|
329
|
+
const headers = new Headers(init?.headers ?? (typeof input === "object" && "headers" in input ? input.headers : void 0));
|
|
330
|
+
if (matches(url, client2.config.allowTracePropagationTargets) && client2.trace) headers.set("traceparent", `00-${client2.trace.traceId}-${client2.trace.spanId}-${client2.trace.sampled ? "01" : "00"}`);
|
|
331
|
+
try {
|
|
332
|
+
const response = await original(input, { ...init, headers });
|
|
333
|
+
void client2.capture({ ...client2.base("performance"), metric: "http.client.duration", value: Date.now() - started, unit: "ms", route: safeUrl(url), metadata: { method, status: response.status } });
|
|
334
|
+
return response;
|
|
335
|
+
} catch (error) {
|
|
336
|
+
client2.captureException(error, { mechanism: "fetch", url: safeUrl(url), method });
|
|
337
|
+
throw error;
|
|
338
|
+
}
|
|
339
|
+
};
|
|
340
|
+
this.cleanups.push(() => {
|
|
341
|
+
globalThis.fetch = original;
|
|
342
|
+
});
|
|
343
|
+
}
|
|
344
|
+
};
|
|
345
|
+
function matches(value, patterns) {
|
|
346
|
+
return patterns?.some((pattern) => typeof pattern === "string" ? value.startsWith(pattern) : pattern.test(value)) ?? false;
|
|
347
|
+
}
|
|
348
|
+
function serialize(error) {
|
|
349
|
+
if (!(error instanceof Error)) return { type: typeof error, value: typeof error === "string" ? error : String(error), handled: true, mechanism: "manual" };
|
|
350
|
+
return { type: error.name, value: error.message, handled: true, mechanism: "manual", stacktrace: (error.stack ?? "").split("\n").slice(1, 101).map((line) => {
|
|
351
|
+
const match = line.match(/(?:at\s+)?(?:(.*?)\s+\()?(.+?):(\d+):(\d+)\)?$/);
|
|
352
|
+
return match ? { function: match[1] || "<anonymous>", filename: match[2], line: Number(match[3]), column: Number(match[4]), inApp: !match[2]?.includes("node_modules") } : { function: line.trim() };
|
|
353
|
+
}) };
|
|
354
|
+
}
|
|
355
|
+
function applyUser(user, sendDefaultPii) {
|
|
356
|
+
if (!user) return void 0;
|
|
357
|
+
if (sendDefaultPii) return user;
|
|
358
|
+
return { id: user.id, username: user.username };
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
// src/index.ts
|
|
362
|
+
var client;
|
|
363
|
+
var SmartObserve = { init(config = {}) {
|
|
364
|
+
return client ??= new SmartObserveExpoClient(config);
|
|
365
|
+
}, captureException(error, hint) {
|
|
366
|
+
return active().captureException(error, hint);
|
|
367
|
+
}, captureMessage(message, level, metadata) {
|
|
368
|
+
return active().captureMessage(message, level, metadata);
|
|
369
|
+
}, addBreadcrumb(value) {
|
|
370
|
+
active().addBreadcrumb(value);
|
|
371
|
+
}, setUser(value) {
|
|
372
|
+
active().setUser(value);
|
|
373
|
+
}, setTag(key, value) {
|
|
374
|
+
active().setTag(key, value);
|
|
375
|
+
}, setContext(key, value) {
|
|
376
|
+
active().setContext(key, value);
|
|
377
|
+
}, startSpan(options, callback) {
|
|
378
|
+
return active().startSpan(options, callback);
|
|
379
|
+
}, trackScreen(name, params) {
|
|
380
|
+
active().trackScreen(name, params);
|
|
381
|
+
}, beforeSend(callback) {
|
|
382
|
+
active().beforeSend(callback);
|
|
383
|
+
}, flush() {
|
|
384
|
+
return active().flush();
|
|
385
|
+
}, async close() {
|
|
386
|
+
await client?.close();
|
|
387
|
+
client = void 0;
|
|
388
|
+
}, get log() {
|
|
389
|
+
return active().log;
|
|
390
|
+
} };
|
|
391
|
+
function active() {
|
|
392
|
+
return client ??= new SmartObserveExpoClient({ enabled: false });
|
|
393
|
+
}
|
|
394
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
395
|
+
0 && (module.exports = {
|
|
396
|
+
SmartObserve,
|
|
397
|
+
SmartObserveExpoClient
|
|
398
|
+
});
|
|
399
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/client.ts","../src/internal.ts","../src/transport.ts","../src/sdk-meta.ts"],"sourcesContent":["import { SmartObserveExpoClient } from \"./client.js\";\nimport type { SmartObserveConfig } from \"./types.js\";\nlet client: SmartObserveExpoClient | undefined;\nexport const SmartObserve = { init(config: SmartObserveConfig = {}) { return client ??= new SmartObserveExpoClient(config); }, captureException(error: unknown, hint?: Record<string, unknown>) { return active().captureException(error, hint); }, captureMessage(message: string, level?: import(\"./types.js\").Level, metadata?: Record<string, unknown>) { return active().captureMessage(message, level, metadata); }, addBreadcrumb(value: import(\"./types.js\").Breadcrumb) { active().addBreadcrumb(value); }, setUser(value: import(\"./types.js\").ObserveUser | null) { active().setUser(value); }, setTag(key: string, value: string | null) { active().setTag(key, value); }, setContext(key: string, value: Record<string, unknown> | null) { active().setContext(key, value); }, startSpan<T>(options: import(\"./types.js\").SpanOptions, callback: (span: import(\"./types.js\").ObserveSpan) => T | Promise<T>) { return active().startSpan(options, callback); }, trackScreen(name: string, params?: Record<string, unknown>) { active().trackScreen(name, params); }, beforeSend(callback: import(\"./types.js\").BeforeSend) { active().beforeSend(callback); }, flush() { return active().flush(); }, async close() { await client?.close(); client = undefined; }, get log() { return active().log; } };\nfunction active() { return client ??= new SmartObserveExpoClient({ enabled: false }); }\nexport { SmartObserveExpoClient } from \"./client.js\"; export * from \"./types.js\";\n","import { AppState, Platform } from \"react-native\";\nimport * as Application from \"expo-application\";\nimport Constants from \"expo-constants\";\nimport * as Device from \"expo-device\";\nimport { id, parseDsn, randomHex, safeUrl, sanitize } from \"./internal.js\";\nimport { ExpoTransport } from \"./transport.js\";\nimport type { BeforeSend, Breadcrumb, Level, ObserveEvent, ObserveSpan, ObserveUser, SmartObserveConfig, SpanOptions, TraceContext } from \"./types.js\";\n\ndeclare const ErrorUtils: { getGlobalHandler(): (error: Error, fatal?: boolean) => void; setGlobalHandler(handler: (error: Error, fatal?: boolean) => void): void } | undefined;\n\nexport class SmartObserveExpoClient {\n private config: SmartObserveConfig & { environment: string; enabled: boolean; debug: boolean; tracesSampleRate: number; errorSampleRate: number; maxBreadcrumbs: number }; private transport?: ExpoTransport; private user?: ObserveUser; private tags: Record<string, string> = {}; private contexts: Record<string, unknown> = {}; private breadcrumbs: Breadcrumb[] = []; private trace?: TraceContext; private beforeSendHook?: BeforeSend; private cleanups: Array<() => void> = []; private sessionId = id(); private sessionStarted = Date.now();\n constructor(input: SmartObserveConfig = {}) { this.config = { ...input, environment: input.environment ?? \"production\", enabled: input.enabled ?? Boolean(input.dsn), debug: input.debug ?? false, tracesSampleRate: input.tracesSampleRate ?? input.sampleRate ?? 0.1, errorSampleRate: input.errorSampleRate ?? 1, maxBreadcrumbs: input.maxBreadcrumbs ?? 100 }; this.beforeSendHook = input.beforeSend; if (this.config.enabled && input.dsn) { const parsed = parseDsn(input.dsn); this.transport = new ExpoTransport({ ...parsed, environment: this.config.environment, release: input.release ?? Application.nativeApplicationVersion ?? undefined, dist: input.dist ?? Application.nativeBuildVersion ?? undefined, maxQueueSize: input.maxQueueSize ?? 1_000, flushIntervalMs: input.flushIntervalMs ?? 5_000, debug: this.config.debug }); this.setup(parsed.endpoint); } }\n captureException(error: unknown, hint: Record<string, unknown> = {}) { const eventId = id(); if (Math.random() <= this.config.errorSampleRate) { const exception = serialize(error); void this.capture({ ...this.base(\"error\"), eventId, message: exception.value, level: \"error\", exceptions: [exception], metadata: hint }); } return eventId; }\n captureMessage(message: string, level: Level = \"info\", metadata?: Record<string, unknown>) { const eventId = id(); void this.capture({ ...this.base(\"log\"), eventId, message, level, metadata }); return eventId; }\n log = { debug: (m: string, d?: Record<string, unknown>) => this.captureMessage(m, \"debug\", d), info: (m: string, d?: Record<string, unknown>) => this.captureMessage(m, \"info\", d), warn: (m: string, d?: Record<string, unknown>) => this.captureMessage(m, \"warn\", d), error: (m: string, d?: Record<string, unknown>) => this.captureMessage(m, \"error\", d) };\n addBreadcrumb(value: Breadcrumb) { this.breadcrumbs.push({ ...sanitize(value, this.config.redactKeys), timestamp: value.timestamp ?? Date.now() }); this.breadcrumbs.splice(0, Math.max(0, this.breadcrumbs.length - this.config.maxBreadcrumbs)); }\n setUser(value: ObserveUser | null) { this.user = value ? sanitize(value, this.config.redactKeys) : undefined; }\n setTag(key: string, value: string | null) { if (value === null) delete this.tags[key]; else this.tags[key.slice(0, 64)] = value.slice(0, 256); }\n setContext(key: string, value: Record<string, unknown> | null) { if (value === null) delete this.contexts[key]; else this.contexts[key] = sanitize(value, this.config.redactKeys); }\n beforeSend(callback: BeforeSend) { this.beforeSendHook = callback; }\n startSpan<T>(options: SpanOptions, callback: (span: ObserveSpan) => T | Promise<T>): T | Promise<T> { const previous = this.trace; const trace: TraceContext = { traceId: options.parent?.traceId ?? previous?.traceId ?? randomHex(16), spanId: randomHex(8), parentSpanId: options.parent?.spanId ?? previous?.spanId, sampled: options.sampled ?? previous?.sampled ?? Math.random() < this.config.tracesSampleRate }; const start = Date.now(); const attributes = { ...(options.attributes ?? {}) }; let status: \"ok\" | \"error\" | \"cancelled\" | \"unknown\" = \"unknown\"; let ended = false; const span: ObserveSpan = { traceId: trace.traceId, spanId: trace.spanId, setAttribute: (key, value) => { attributes[key] = value; }, setStatus: (value) => { status = value; }, recordException: (error) => { status = \"error\"; this.captureException(error); }, end: () => { if (!ended && trace.sampled) { ended = true; const isRoot = !trace.parentSpanId; void this.capture({ ...this.base(isRoot ? \"transaction\" : \"span\"), name: options.name, operation: options.operation, startTimestamp: start, endTimestamp: Date.now(), status, ...(isRoot ? {} : { attributes }), trace }); } } }; this.trace = trace; try { const result = callback(span); if (result && typeof (result as Promise<T>).then === \"function\") return (result as Promise<T>).then((value) => { if (status === \"unknown\") status = \"ok\"; span.end(); return value; }, (error) => { span.recordException(error); span.end(); throw error; }).finally(() => { this.trace = previous; }); if (status === \"unknown\") status = \"ok\"; span.end(); return result; } finally { if (this.trace?.spanId === trace.spanId) this.trace = previous; } }\n flush() { return this.transport?.flush() ?? Promise.resolve(); } async close() { for (const cleanup of this.cleanups.splice(0)) cleanup(); await this.transport?.close(); }\n trackScreen(name: string, params?: Record<string, unknown>) { this.addBreadcrumb({ category: \"navigation\", message: name, data: params }); }\n private base(type: ObserveEvent[\"type\"]): ObserveEvent { return { eventId: id(), type, timestamp: Date.now(), platform: \"expo\", user: applyUser(this.user, this.config.sendDefaultPii), tags: { ...this.tags }, contexts: sanitize({ ...this.contexts, device: { brand: Device.brand, model: Device.modelName, deviceType: Device.deviceType, os: Platform.OS, osVersion: Platform.Version, isDevice: Device.isDevice }, app: { id: Application.applicationId, name: Application.applicationName, version: Application.nativeApplicationVersion, build: Application.nativeBuildVersion, runtimeVersion: Constants.expoConfig?.runtimeVersion } }, this.config.redactKeys), breadcrumbs: [...this.breadcrumbs], trace: this.trace }; }\n private async capture(raw: ObserveEvent) { if (!this.transport) return; try { let event = sanitize(raw, this.config.redactKeys); if (this.beforeSendHook) event = await this.beforeSendHook(event) as ObserveEvent; if (event) this.transport.enqueue(event); } catch (error) { if (this.config.debug) console.warn(\"[SmartObserve] event dropped\", error); } }\n private setup(endpoint: string) { const original = typeof ErrorUtils !== \"undefined\" ? ErrorUtils.getGlobalHandler() : undefined; if (original && typeof ErrorUtils !== \"undefined\") { ErrorUtils.setGlobalHandler((error, fatal) => { this.captureException(error, { mechanism: \"react-native.global\", fatal }); if (fatal) void this.capture({ ...this.base(\"session\"), sessionId: this.sessionId, startedAt: this.sessionStarted, endedAt: Date.now(), status: \"crashed\" }); original(error, fatal); }); this.cleanups.push(() => ErrorUtils.setGlobalHandler(original)); } if (this.config.trackLifecycle !== false) { const sub = AppState.addEventListener(\"change\", (state) => { this.addBreadcrumb({ category: \"app.lifecycle\", message: state }); if (state === \"active\") void this.flush(); if (state === \"background\" || state === \"inactive\") void this.capture({ ...this.base(\"session\"), sessionId: this.sessionId, startedAt: this.sessionStarted, endedAt: Date.now(), status: \"exited\" }); }); this.cleanups.push(() => sub.remove()); } if (this.config.trackNetwork !== false) this.patchFetch(endpoint); void this.capture({ ...this.base(\"session\"), sessionId: this.sessionId, startedAt: this.sessionStarted, status: \"active\" }); }\n private patchFetch(endpoint: string) { const original = globalThis.fetch; const client = this; globalThis.fetch = async function(input: RequestInfo | URL, init?: RequestInit) { const url = typeof input === \"string\" ? input : input instanceof URL ? input.href : input.url; if (url.startsWith(endpoint) || (init?.headers && new Headers(init.headers as HeadersInit).has(\"x-smartobserve-internal\"))) return original(input as RequestInfo, init); const started = Date.now(); const method = init?.method ?? (typeof input === \"object\" && \"method\" in input ? (input as Request).method : \"GET\"); client.addBreadcrumb({ category: \"http\", message: `${method} ${safeUrl(url)}`, data: { method, url: safeUrl(url) } }); const headers = new Headers(init?.headers ?? (typeof input === \"object\" && \"headers\" in input ? (input as Request).headers : undefined)); if (matches(url, client.config.allowTracePropagationTargets) && client.trace) headers.set(\"traceparent\", `00-${client.trace.traceId}-${client.trace.spanId}-${client.trace.sampled ? \"01\" : \"00\"}`); try { const response = await original(input as RequestInfo, { ...init, headers }); void client.capture({ ...client.base(\"performance\"), metric: \"http.client.duration\", value: Date.now() - started, unit: \"ms\", route: safeUrl(url), metadata: { method, status: response.status } }); return response; } catch (error) { client.captureException(error, { mechanism: \"fetch\", url: safeUrl(url), method }); throw error; } } as typeof fetch; this.cleanups.push(() => { globalThis.fetch = original; }); }\n}\nfunction matches(value: string, patterns?: Array<string | RegExp>) { return patterns?.some((pattern) => typeof pattern === \"string\" ? value.startsWith(pattern) : pattern.test(value)) ?? false; }\nfunction serialize(error: unknown) { if (!(error instanceof Error)) return { type: typeof error, value: typeof error === \"string\" ? error : String(error), handled: true, mechanism: \"manual\" }; return { type: error.name, value: error.message, handled: true, mechanism: \"manual\", stacktrace: (error.stack ?? \"\").split(\"\\n\").slice(1, 101).map((line) => { const match = line.match(/(?:at\\s+)?(?:(.*?)\\s+\\()?(.+?):(\\d+):(\\d+)\\)?$/); return match ? { function: match[1] || \"<anonymous>\", filename: match[2], line: Number(match[3]), column: Number(match[4]), inApp: !match[2]?.includes(\"node_modules\") } : { function: line.trim() }; }) }; }\nfunction applyUser(user: ObserveUser | undefined, sendDefaultPii?: boolean) { if (!user) return undefined; if (sendDefaultPii) return user; return { id: user.id, username: user.username }; }\n","export function id() { return crypto.randomUUID(); }\nexport function randomHex(bytes: number) { return [...crypto.getRandomValues(new Uint8Array(bytes))].map((value) => value.toString(16).padStart(2, \"0\")).join(\"\"); }\nexport function parseDsn(value: string) { const url = new URL(value); const key = decodeURIComponent(url.username); if (!/^(pk|sk)_[A-Za-z0-9_-]{16,}$/.test(key)) throw new Error(\"SmartObserve DSN contains an invalid project key\"); const slug = url.pathname.replace(/^\\/+|\\/+$/g, \"\"); if (!slug) throw new Error(\"SmartObserve DSN must include a project slug\"); return { endpoint: `${url.protocol}//${url.host}/api/v1/envelope`, key }; }\nconst BLOCKED = new Set([\"password\", \"passcode\", \"authorization\", \"cookie\", \"access_token\", \"refresh_token\", \"api_key\", \"secret\", \"private_key\", \"card_number\", \"cvv\", \"cvc\"]);\nexport function sanitize<T>(input: T, extra: string[] = []): T { const blocked = new Set([...BLOCKED, ...extra.map((value) => value.toLowerCase())]); const seen = new WeakSet<object>(); const walk = (value: unknown, depth: number): unknown => { if (depth > 5) return \"[Truncated]\"; if (typeof value === \"string\") return value.slice(0, 8_192); if (value === null || typeof value !== \"object\") return value; if (seen.has(value)) return \"[Circular]\"; seen.add(value); if (Array.isArray(value)) return value.slice(0, 200).map((entry) => walk(entry, depth + 1)); return Object.fromEntries(Object.entries(value).slice(0, 200).map(([key, entry]) => [key, blocked.has(key.toLowerCase().replace(/[\\s-]+/g, \"_\")) ? \"[Redacted]\" : walk(entry, depth + 1)])); }; return walk(input, 0) as T; }\nexport function safeUrl(value: string) { try { const url = new URL(value); url.username = \"\"; url.password = \"\"; for (const key of [...url.searchParams.keys()]) url.searchParams.set(key, \"[Filtered]\"); return url.toString(); } catch { return \"[Invalid URL]\"; } }\n","import AsyncStorage from \"@react-native-async-storage/async-storage\";\nimport NetInfo from \"@react-native-community/netinfo\";\nimport type { ObserveEvent } from \"./types.js\";\nimport { id } from \"./internal.js\";\nimport { SDK_NAME, SDK_VERSION } from \"./sdk-meta.js\";\nconst STORAGE_KEY = \"@smartobserve/events/v1\";\ninterface Options { endpoint: string; key: string; environment: string; release?: string; dist?: string; maxQueueSize: number; flushIntervalMs: number; debug: boolean }\nexport class ExpoTransport {\n private queue: ObserveEvent[] = []; private timer?: ReturnType<typeof setInterval>; private flushing?: Promise<void>; private online = true; private unsubscribe?: () => void; private closed = false;\n constructor(private readonly options: Options) { this.timer = setInterval(() => void this.flush(), options.flushIntervalMs); this.unsubscribe = NetInfo.addEventListener((state) => { this.online = state.isConnected !== false; if (this.online) void this.flush(); }); void this.restore(); }\n enqueue(event: ObserveEvent) { if (this.closed) return; if (this.queue.length >= this.options.maxQueueSize) this.evict(); this.queue.push(event); void this.persist(); if (this.queue.length >= 50 || event.level === \"fatal\") void this.flush(); }\n async flush() { if (this.flushing || !this.queue.length || !this.online) return this.flushing; const events = this.queue.splice(0, 50); this.flushing = this.send(events).then(() => this.persist()).catch((error) => { this.queue.unshift(...events); void this.persist(); if (this.options.debug) console.warn(\"[SmartObserve] offline batch retained\", error); }).finally(() => { this.flushing = undefined; }); return this.flushing; }\n async close() { this.closed = true; if (this.timer) clearInterval(this.timer); this.unsubscribe?.(); await this.flush(); }\n private async restore() { try { const raw = await AsyncStorage.getItem(STORAGE_KEY); if (!raw) return; const stored = JSON.parse(raw) as Array<ObserveEvent & { _storedAt?: number }>; this.queue.push(...stored.filter((event) => Date.now() - (event._storedAt ?? event.timestamp) < 7 * 86_400_000).slice(-this.options.maxQueueSize)); await this.flush(); } catch (error) { if (this.options.debug) console.warn(\"[SmartObserve] offline queue unavailable\", error); } }\n private async persist(): Promise<void> { try { let prepared = this.queue.map((event) => ({ ...event, _storedAt: Date.now() })); let raw = JSON.stringify(prepared); while (raw.length > 10 * 1024 * 1024 && this.queue.length) { this.evict(); prepared = this.queue.map((event) => ({ ...event, _storedAt: Date.now() })); raw = JSON.stringify(prepared); } await AsyncStorage.setItem(STORAGE_KEY, raw); } catch (error) { if (this.options.debug) console.warn(\"[SmartObserve] could not persist offline queue\", error); } }\n private async send(events: ObserveEvent[]) { const body = JSON.stringify({ schemaVersion: 1, envelopeId: id(), sentAt: Date.now(), sdk: { name: SDK_NAME, version: SDK_VERSION }, environment: this.options.environment, release: this.options.release, dist: this.options.dist, events }); let attempt = 0; while (true) { const response = await fetch(this.options.endpoint, { method: \"POST\", headers: { \"content-type\": \"application/json\", \"origin\": \"smartobserve-expo://native\", \"x-smartobserve-key\": this.options.key, \"x-smartobserve-platform\": \"expo\", \"x-smartobserve-internal\": \"transport\" }, body }); if (response.ok) return; if (![408, 429].includes(response.status) && response.status < 500) return; if (attempt++ >= 5) throw new Error(`HTTP ${response.status}`); await new Promise((resolve) => setTimeout(resolve, Math.random() * Math.min(30_000, 2 ** attempt * 1_000))); } }\n private evict() { const index = this.queue.findIndex((event) => event.type === \"span\" || event.type === \"performance\" || event.level === \"debug\"); this.queue.splice(index < 0 ? 0 : index, 1); }\n}\n","export const SDK_NAME = \"@smarthivelabs-devs/observe-expo\";\nexport const SDK_VERSION = \"26.1.0\";\n"],"mappings":"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","names":["NetInfo","AsyncStorage","Constants","client"]}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
type Level = "debug" | "info" | "warn" | "error" | "fatal";
|
|
2
|
+
interface ObserveUser {
|
|
3
|
+
id: string;
|
|
4
|
+
email?: string;
|
|
5
|
+
username?: string;
|
|
6
|
+
ipAddress?: string;
|
|
7
|
+
}
|
|
8
|
+
interface Breadcrumb {
|
|
9
|
+
timestamp?: number;
|
|
10
|
+
category: string;
|
|
11
|
+
message?: string;
|
|
12
|
+
level?: Level;
|
|
13
|
+
data?: Record<string, unknown>;
|
|
14
|
+
}
|
|
15
|
+
interface TraceContext {
|
|
16
|
+
traceId: string;
|
|
17
|
+
spanId: string;
|
|
18
|
+
parentSpanId?: string;
|
|
19
|
+
sampled?: boolean;
|
|
20
|
+
}
|
|
21
|
+
interface ObserveEvent {
|
|
22
|
+
eventId: string;
|
|
23
|
+
type: "error" | "log" | "transaction" | "span" | "performance" | "session";
|
|
24
|
+
timestamp: number;
|
|
25
|
+
platform: "expo";
|
|
26
|
+
message?: string;
|
|
27
|
+
level?: Level;
|
|
28
|
+
user?: ObserveUser;
|
|
29
|
+
tags?: Record<string, string>;
|
|
30
|
+
contexts?: Record<string, unknown>;
|
|
31
|
+
breadcrumbs?: Breadcrumb[];
|
|
32
|
+
trace?: TraceContext;
|
|
33
|
+
metadata?: Record<string, unknown>;
|
|
34
|
+
[key: string]: unknown;
|
|
35
|
+
}
|
|
36
|
+
type BeforeSend = (event: ObserveEvent) => ObserveEvent | null | Promise<ObserveEvent | null>;
|
|
37
|
+
interface SmartObserveConfig {
|
|
38
|
+
dsn?: string;
|
|
39
|
+
environment?: string;
|
|
40
|
+
release?: string;
|
|
41
|
+
dist?: string;
|
|
42
|
+
enabled?: boolean;
|
|
43
|
+
debug?: boolean;
|
|
44
|
+
sampleRate?: number;
|
|
45
|
+
tracesSampleRate?: number;
|
|
46
|
+
errorSampleRate?: number;
|
|
47
|
+
sendDefaultPii?: boolean;
|
|
48
|
+
maxBreadcrumbs?: number;
|
|
49
|
+
maxQueueSize?: number;
|
|
50
|
+
flushIntervalMs?: number;
|
|
51
|
+
beforeSend?: BeforeSend;
|
|
52
|
+
redactKeys?: string[];
|
|
53
|
+
allowTracePropagationTargets?: Array<string | RegExp>;
|
|
54
|
+
trackNetwork?: boolean;
|
|
55
|
+
trackLifecycle?: boolean;
|
|
56
|
+
}
|
|
57
|
+
interface SpanOptions {
|
|
58
|
+
name: string;
|
|
59
|
+
operation: string;
|
|
60
|
+
attributes?: Record<string, string | number | boolean>;
|
|
61
|
+
parent?: TraceContext;
|
|
62
|
+
sampled?: boolean;
|
|
63
|
+
}
|
|
64
|
+
interface ObserveSpan {
|
|
65
|
+
traceId: string;
|
|
66
|
+
spanId: string;
|
|
67
|
+
setAttribute(key: string, value: string | number | boolean): void;
|
|
68
|
+
setStatus(status: "ok" | "error" | "cancelled" | "unknown"): void;
|
|
69
|
+
recordException(error: unknown): void;
|
|
70
|
+
end(): void;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
declare class SmartObserveExpoClient {
|
|
74
|
+
private config;
|
|
75
|
+
private transport?;
|
|
76
|
+
private user?;
|
|
77
|
+
private tags;
|
|
78
|
+
private contexts;
|
|
79
|
+
private breadcrumbs;
|
|
80
|
+
private trace?;
|
|
81
|
+
private beforeSendHook?;
|
|
82
|
+
private cleanups;
|
|
83
|
+
private sessionId;
|
|
84
|
+
private sessionStarted;
|
|
85
|
+
constructor(input?: SmartObserveConfig);
|
|
86
|
+
captureException(error: unknown, hint?: Record<string, unknown>): `${string}-${string}-${string}-${string}-${string}`;
|
|
87
|
+
captureMessage(message: string, level?: Level, metadata?: Record<string, unknown>): `${string}-${string}-${string}-${string}-${string}`;
|
|
88
|
+
log: {
|
|
89
|
+
debug: (m: string, d?: Record<string, unknown>) => `${string}-${string}-${string}-${string}-${string}`;
|
|
90
|
+
info: (m: string, d?: Record<string, unknown>) => `${string}-${string}-${string}-${string}-${string}`;
|
|
91
|
+
warn: (m: string, d?: Record<string, unknown>) => `${string}-${string}-${string}-${string}-${string}`;
|
|
92
|
+
error: (m: string, d?: Record<string, unknown>) => `${string}-${string}-${string}-${string}-${string}`;
|
|
93
|
+
};
|
|
94
|
+
addBreadcrumb(value: Breadcrumb): void;
|
|
95
|
+
setUser(value: ObserveUser | null): void;
|
|
96
|
+
setTag(key: string, value: string | null): void;
|
|
97
|
+
setContext(key: string, value: Record<string, unknown> | null): void;
|
|
98
|
+
beforeSend(callback: BeforeSend): void;
|
|
99
|
+
startSpan<T>(options: SpanOptions, callback: (span: ObserveSpan) => T | Promise<T>): T | Promise<T>;
|
|
100
|
+
flush(): Promise<void>;
|
|
101
|
+
close(): Promise<void>;
|
|
102
|
+
trackScreen(name: string, params?: Record<string, unknown>): void;
|
|
103
|
+
private base;
|
|
104
|
+
private capture;
|
|
105
|
+
private setup;
|
|
106
|
+
private patchFetch;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
declare const SmartObserve: {
|
|
110
|
+
init(config?: SmartObserveConfig): SmartObserveExpoClient;
|
|
111
|
+
captureException(error: unknown, hint?: Record<string, unknown>): `${string}-${string}-${string}-${string}-${string}`;
|
|
112
|
+
captureMessage(message: string, level?: Level, metadata?: Record<string, unknown>): `${string}-${string}-${string}-${string}-${string}`;
|
|
113
|
+
addBreadcrumb(value: Breadcrumb): void;
|
|
114
|
+
setUser(value: ObserveUser | null): void;
|
|
115
|
+
setTag(key: string, value: string | null): void;
|
|
116
|
+
setContext(key: string, value: Record<string, unknown> | null): void;
|
|
117
|
+
startSpan<T>(options: SpanOptions, callback: (span: ObserveSpan) => T | Promise<T>): T | Promise<T>;
|
|
118
|
+
trackScreen(name: string, params?: Record<string, unknown>): void;
|
|
119
|
+
beforeSend(callback: BeforeSend): void;
|
|
120
|
+
flush(): Promise<void>;
|
|
121
|
+
close(): Promise<void>;
|
|
122
|
+
readonly log: {
|
|
123
|
+
debug: (m: string, d?: Record<string, unknown>) => `${string}-${string}-${string}-${string}-${string}`;
|
|
124
|
+
info: (m: string, d?: Record<string, unknown>) => `${string}-${string}-${string}-${string}-${string}`;
|
|
125
|
+
warn: (m: string, d?: Record<string, unknown>) => `${string}-${string}-${string}-${string}-${string}`;
|
|
126
|
+
error: (m: string, d?: Record<string, unknown>) => `${string}-${string}-${string}-${string}-${string}`;
|
|
127
|
+
};
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
export { type BeforeSend, type Breadcrumb, type Level, type ObserveEvent, type ObserveSpan, type ObserveUser, SmartObserve, type SmartObserveConfig, SmartObserveExpoClient, type SpanOptions, type TraceContext };
|