@debugkit/sdk 0.1.0 → 0.2.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/README.md +55 -3
- package/dist/{chunk-3UN5VMQU.js → chunk-3WRI3DI2.js} +5 -5
- package/dist/chunk-3WRI3DI2.js.map +1 -0
- package/dist/chunk-5C7KJJNO.js +651 -0
- package/dist/chunk-5C7KJJNO.js.map +1 -0
- package/dist/chunk-EGCXLOFH.cjs +663 -0
- package/dist/chunk-EGCXLOFH.cjs.map +1 -0
- package/dist/{chunk-BD2FNVCP.js → chunk-HO3JW55K.js} +15 -7
- package/dist/chunk-HO3JW55K.js.map +1 -0
- package/dist/{chunk-NSWUGBA2.cjs → chunk-NJ6DTUVX.cjs} +20 -12
- package/dist/chunk-NJ6DTUVX.cjs.map +1 -0
- package/dist/{chunk-KUJ4EW3D.cjs → chunk-YELZOB7J.cjs} +10 -10
- package/dist/chunk-YELZOB7J.cjs.map +1 -0
- package/dist/client-ekzlpWIR.d.cts +220 -0
- package/dist/client-ekzlpWIR.d.ts +220 -0
- package/dist/expo-router.cjs +4 -4
- package/dist/expo-router.d.cts +1 -1
- package/dist/expo-router.d.ts +1 -1
- package/dist/expo-router.js +2 -2
- package/dist/expo.cjs +13 -13
- package/dist/expo.d.cts +1 -1
- package/dist/expo.d.ts +1 -1
- package/dist/expo.js +5 -5
- package/dist/index.cjs +12 -8
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/node.cjs +69 -14
- package/dist/node.cjs.map +1 -1
- package/dist/node.d.cts +4 -7
- package/dist/node.d.ts +4 -7
- package/dist/node.js +55 -5
- package/dist/node.js.map +1 -1
- package/dist/react-native.cjs +10 -10
- package/dist/react-native.d.cts +1 -1
- package/dist/react-native.d.ts +1 -1
- package/dist/react-native.js +3 -3
- package/dist/react.cjs +6 -6
- package/dist/react.d.cts +1 -1
- package/dist/react.d.ts +1 -1
- package/dist/react.js +2 -2
- package/package.json +2 -2
- package/dist/chunk-3UN5VMQU.js.map +0 -1
- package/dist/chunk-BD2FNVCP.js.map +0 -1
- package/dist/chunk-KUJ4EW3D.cjs.map +0 -1
- package/dist/chunk-NSWUGBA2.cjs.map +0 -1
- package/dist/chunk-VIJ5USKQ.js +0 -300
- package/dist/chunk-VIJ5USKQ.js.map +0 -1
- package/dist/chunk-XEFWRCN4.cjs +0 -311
- package/dist/chunk-XEFWRCN4.cjs.map +0 -1
- package/dist/client-drmb0n15.d.cts +0 -103
- package/dist/client-drmb0n15.d.ts +0 -103
package/dist/chunk-XEFWRCN4.cjs
DELETED
|
@@ -1,311 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
var __defProp = Object.defineProperty;
|
|
4
|
-
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
5
|
-
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
6
|
-
|
|
7
|
-
// ../schema/src/core.ts
|
|
8
|
-
var V8 = /^\s*at (?:(.+?) \()?(.+?):(\d+):(\d+)\)?\s*$/;
|
|
9
|
-
var GECKO = /^\s*(.*?)@(.+?):(\d+):(\d+)\s*$/;
|
|
10
|
-
var NOT_IN_APP = [/node_modules/, /\bnative\b/, /\[native code\]/, /InternalBytecode/];
|
|
11
|
-
var RN_BUNDLE = /\.(?:js)?bundle\b/;
|
|
12
|
-
function cleanFile(file) {
|
|
13
|
-
return file.replace(/^address at /, "");
|
|
14
|
-
}
|
|
15
|
-
function parseStack(stack) {
|
|
16
|
-
var _a;
|
|
17
|
-
if (!stack) return [];
|
|
18
|
-
const frames = [];
|
|
19
|
-
for (const raw of stack.split("\n")) {
|
|
20
|
-
const m = (_a = V8.exec(raw)) != null ? _a : GECKO.exec(raw);
|
|
21
|
-
if (!m) continue;
|
|
22
|
-
const [, fn, rawFile, line, col] = m;
|
|
23
|
-
const file = cleanFile(rawFile != null ? rawFile : "");
|
|
24
|
-
frames.push({
|
|
25
|
-
fn: fn || void 0,
|
|
26
|
-
file,
|
|
27
|
-
line: Number(line),
|
|
28
|
-
col: Number(col),
|
|
29
|
-
inApp: RN_BUNDLE.test(file) ? !/^(?:anonymous|eval|global code)$/.test(fn != null ? fn : "") : !NOT_IN_APP.some((re) => re.test(file))
|
|
30
|
-
});
|
|
31
|
-
if (frames.length >= 100) break;
|
|
32
|
-
}
|
|
33
|
-
return frames;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
// src/context.ts
|
|
37
|
-
function mergeContext(a, b) {
|
|
38
|
-
const out = { ...a };
|
|
39
|
-
for (const [k, v] of Object.entries(b)) {
|
|
40
|
-
const prev = out[k];
|
|
41
|
-
out[k] = v && typeof v === "object" && prev && typeof prev === "object" ? { ...prev, ...v } : v != null ? v : prev;
|
|
42
|
-
}
|
|
43
|
-
return out;
|
|
44
|
-
}
|
|
45
|
-
function safe(fn) {
|
|
46
|
-
try {
|
|
47
|
-
return fn();
|
|
48
|
-
} catch {
|
|
49
|
-
return void 0;
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
function timezone() {
|
|
53
|
-
return safe(() => Intl.DateTimeFormat().resolvedOptions().timeZone);
|
|
54
|
-
}
|
|
55
|
-
function locale() {
|
|
56
|
-
return safe(() => Intl.DateTimeFormat().resolvedOptions().locale);
|
|
57
|
-
}
|
|
58
|
-
function browserContext() {
|
|
59
|
-
var _a, _b, _c;
|
|
60
|
-
if (typeof navigator === "undefined" || typeof window === "undefined") {
|
|
61
|
-
const ua2 = typeof navigator !== "undefined" ? navigator.userAgent : void 0;
|
|
62
|
-
const node = typeof process !== "undefined" ? (_a = process.versions) == null ? void 0 : _a.node : void 0;
|
|
63
|
-
return {
|
|
64
|
-
runtime: { name: ua2 === "Cloudflare-Workers" ? "cloudflare-workers" : node ? "node" : "edge", version: node },
|
|
65
|
-
os: { name: "server" },
|
|
66
|
-
timezone: timezone()
|
|
67
|
-
};
|
|
68
|
-
}
|
|
69
|
-
const ua = navigator.userAgent;
|
|
70
|
-
const android = (_b = /Android ([\d.]+)/.exec(ua)) == null ? void 0 : _b[1];
|
|
71
|
-
const ios = (_c = /(?:iPhone|iPad|iPod).*? OS (\d+[_\d]*)/.exec(ua)) == null ? void 0 : _c[1];
|
|
72
|
-
const os = android ? { name: "android", version: android } : ios ? { name: "ios", version: ios.replace(/_/g, ".") } : /Mac OS X/.test(ua) ? { name: "macos" } : /Windows/.test(ua) ? { name: "windows" } : /Linux/.test(ua) ? { name: "linux" } : { name: "web" };
|
|
73
|
-
const conn = navigator.connection;
|
|
74
|
-
const browser = /Edg\/([\d.]+)/.exec(ua) ? { name: "edge", v: /Edg\/([\d.]+)/.exec(ua)[1] } : /Chrome\/([\d.]+)/.exec(ua) ? { name: "chrome", v: /Chrome\/([\d.]+)/.exec(ua)[1] } : /Version\/([\d.]+).*Safari/.exec(ua) ? { name: "safari", v: /Version\/([\d.]+)/.exec(ua)[1] } : /Firefox\/([\d.]+)/.exec(ua) ? { name: "firefox", v: /Firefox\/([\d.]+)/.exec(ua)[1] } : void 0;
|
|
75
|
-
return {
|
|
76
|
-
os,
|
|
77
|
-
runtime: { name: "browser", version: browser ? `${browser.name} ${browser.v}` : void 0 },
|
|
78
|
-
device: {
|
|
79
|
-
type: /iPad|Tablet/.test(ua) ? "tablet" : /Mobi/.test(ua) ? "phone" : "desktop",
|
|
80
|
-
screen: typeof screen !== "undefined" ? { width: screen.width, height: screen.height, scale: window.devicePixelRatio } : void 0
|
|
81
|
-
},
|
|
82
|
-
network: conn ? {
|
|
83
|
-
type: conn.type === "wifi" ? "wifi" : conn.type === "cellular" ? "cellular" : "unknown",
|
|
84
|
-
effectiveType: conn.effectiveType,
|
|
85
|
-
isConnected: navigator.onLine
|
|
86
|
-
} : void 0,
|
|
87
|
-
locale: navigator.language,
|
|
88
|
-
timezone: timezone()
|
|
89
|
-
};
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
// src/client.ts
|
|
93
|
-
var SDK_NAME = "@debugkit/sdk";
|
|
94
|
-
var SDK_VERSION = "0.1.0";
|
|
95
|
-
var QUEUE_KEY = "@debugkit/queue";
|
|
96
|
-
var MAX_QUEUE = 500;
|
|
97
|
-
var uid = () => {
|
|
98
|
-
var _a, _b, _c;
|
|
99
|
-
return ((_c = (_b = (_a = globalThis.crypto) == null ? void 0 : _a.randomUUID) == null ? void 0 : _b.call(_a)) != null ? _c : `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 12)}`).replace(/-/g, "");
|
|
100
|
-
};
|
|
101
|
-
var now = () => (/* @__PURE__ */ new Date()).toISOString();
|
|
102
|
-
var DebugClient = class {
|
|
103
|
-
constructor() {
|
|
104
|
-
__publicField(this, "opts");
|
|
105
|
-
__publicField(this, "queue", []);
|
|
106
|
-
__publicField(this, "crumbs", []);
|
|
107
|
-
__publicField(this, "session", { id: uid(), startedAt: now() });
|
|
108
|
-
__publicField(this, "user", { anonymousId: uid() });
|
|
109
|
-
__publicField(this, "timer");
|
|
110
|
-
__publicField(this, "flushing");
|
|
111
|
-
__publicField(this, "backoffUntil", 0);
|
|
112
|
-
__publicField(this, "failures", 0);
|
|
113
|
-
__publicField(this, "ready", false);
|
|
114
|
-
__publicField(this, "handlersInstalled", false);
|
|
115
|
-
}
|
|
116
|
-
init(options) {
|
|
117
|
-
var _a, _b;
|
|
118
|
-
if (this.timer) clearInterval(this.timer);
|
|
119
|
-
this.opts = { flushIntervalMs: 5e3, maxBatch: 50, maxBreadcrumbs: 30, captureGlobalErrors: true, ...options };
|
|
120
|
-
if (!this.opts.context && typeof window !== "undefined") this.opts.context = browserContext();
|
|
121
|
-
this.ready = true;
|
|
122
|
-
void this.restore();
|
|
123
|
-
if (this.opts.captureGlobalErrors && !this.handlersInstalled) this.installGlobalHandlers();
|
|
124
|
-
if (this.opts.flushIntervalMs > 0) {
|
|
125
|
-
this.timer = setInterval(() => void this.flush(), this.opts.flushIntervalMs);
|
|
126
|
-
(_b = (_a = this.timer).unref) == null ? void 0 : _b.call(_a);
|
|
127
|
-
}
|
|
128
|
-
return this;
|
|
129
|
-
}
|
|
130
|
-
get initialized() {
|
|
131
|
-
return this.ready;
|
|
132
|
-
}
|
|
133
|
-
/** Merge extra context (e.g. after an async device lookup). Applies to events sent from now on. */
|
|
134
|
-
setContext(patch) {
|
|
135
|
-
var _a;
|
|
136
|
-
if (this.opts) this.opts.context = mergeContext((_a = this.opts.context) != null ? _a : {}, patch);
|
|
137
|
-
}
|
|
138
|
-
setUser(id) {
|
|
139
|
-
this.user = { ...this.user, id };
|
|
140
|
-
}
|
|
141
|
-
breadcrumb(category, message, data, level = "info") {
|
|
142
|
-
var _a, _b;
|
|
143
|
-
this.crumbs.push({ ts: now(), category, message: message.slice(0, 500), data, level });
|
|
144
|
-
if (this.crumbs.length > ((_b = (_a = this.opts) == null ? void 0 : _a.maxBreadcrumbs) != null ? _b : 30)) this.crumbs.shift();
|
|
145
|
-
}
|
|
146
|
-
/** Log an error. `flow` is the part of the app it belongs to, e.g. "auth.login". */
|
|
147
|
-
error(err, meta = {}) {
|
|
148
|
-
var _a;
|
|
149
|
-
const e = normaliseError(err);
|
|
150
|
-
this.enqueue({
|
|
151
|
-
type: "error",
|
|
152
|
-
id: uid(),
|
|
153
|
-
ts: now(),
|
|
154
|
-
flow: meta.flow,
|
|
155
|
-
step: meta.step,
|
|
156
|
-
tags: meta.tags,
|
|
157
|
-
severity: meta.severity,
|
|
158
|
-
handled: (_a = meta.handled) != null ? _a : true,
|
|
159
|
-
error: { name: e.name, message: e.message, stack: e.stack, frames: parseStack(e.stack) },
|
|
160
|
-
breadcrumbs: [...this.crumbs]
|
|
161
|
-
});
|
|
162
|
-
}
|
|
163
|
-
/** Log a custom event. Use outcome to let deBug compute failure rates per flow. */
|
|
164
|
-
event(name, meta = {}) {
|
|
165
|
-
this.breadcrumb("event", name, meta.props);
|
|
166
|
-
this.enqueue({ type: "event", id: uid(), ts: now(), name, flow: meta.flow, step: meta.step, tags: meta.tags, outcome: meta.outcome, props: meta.props });
|
|
167
|
-
}
|
|
168
|
-
/** Wraps an async step: logs success, or failure + the error, against a flow. */
|
|
169
|
-
/**
|
|
170
|
-
* Wraps an async step: logs a success or failure outcome for the flow, plus the error.
|
|
171
|
-
* Pass `{ captureError: false }` when the error is already reported elsewhere, e.g. a
|
|
172
|
-
* server function wrapped in withDebug, so it isn't counted twice.
|
|
173
|
-
*/
|
|
174
|
-
async track(flow, step, fn, opts = {}) {
|
|
175
|
-
try {
|
|
176
|
-
const out = await fn();
|
|
177
|
-
this.event(`${flow}.${step}`, { flow, step, outcome: "success" });
|
|
178
|
-
return out;
|
|
179
|
-
} catch (err) {
|
|
180
|
-
this.event(`${flow}.${step}`, { flow, step, outcome: "failure" });
|
|
181
|
-
if (opts.captureError !== false) this.error(err, { flow, step });
|
|
182
|
-
throw err;
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
async flush() {
|
|
186
|
-
if (!this.ready || this.flushing || this.queue.length === 0 || Date.now() < this.backoffUntil) return this.flushing;
|
|
187
|
-
const batch = this.queue.splice(0, this.opts.maxBatch);
|
|
188
|
-
this.flushing = this.send(batch).then(() => {
|
|
189
|
-
this.failures = 0;
|
|
190
|
-
}).catch((err) => {
|
|
191
|
-
this.queue.unshift(...batch);
|
|
192
|
-
this.failures++;
|
|
193
|
-
this.backoffUntil = Date.now() + Math.min(6e4, 1e3 * 2 ** this.failures);
|
|
194
|
-
this.log("flush failed", err);
|
|
195
|
-
}).finally(() => {
|
|
196
|
-
this.flushing = void 0;
|
|
197
|
-
void this.persist();
|
|
198
|
-
});
|
|
199
|
-
return this.flushing;
|
|
200
|
-
}
|
|
201
|
-
close() {
|
|
202
|
-
if (this.timer) clearInterval(this.timer);
|
|
203
|
-
return this.flush();
|
|
204
|
-
}
|
|
205
|
-
/* ---------------- internals ---------------- */
|
|
206
|
-
enqueue(e) {
|
|
207
|
-
if (!this.ready) return;
|
|
208
|
-
const out = this.opts.beforeSend ? this.opts.beforeSend(e) : e;
|
|
209
|
-
if (!out) return;
|
|
210
|
-
this.queue.push(out);
|
|
211
|
-
if (this.queue.length > MAX_QUEUE) this.queue.splice(0, this.queue.length - MAX_QUEUE);
|
|
212
|
-
if (out.type === "error" || this.queue.length >= this.opts.maxBatch) void this.flush();
|
|
213
|
-
else void this.persist();
|
|
214
|
-
}
|
|
215
|
-
buildContext() {
|
|
216
|
-
var _a, _b, _c, _d, _e;
|
|
217
|
-
const c = (_a = this.opts.context) != null ? _a : {};
|
|
218
|
-
return {
|
|
219
|
-
...c,
|
|
220
|
-
app: { ...(_b = c.app) != null ? _b : {}, ...this.opts.app },
|
|
221
|
-
os: { name: "unknown", ...(_c = c.os) != null ? _c : {} },
|
|
222
|
-
runtime: { name: "unknown", ...(_d = c.runtime) != null ? _d : {} },
|
|
223
|
-
device: (_e = c.device) != null ? _e : {}
|
|
224
|
-
};
|
|
225
|
-
}
|
|
226
|
-
async send(events) {
|
|
227
|
-
var _a;
|
|
228
|
-
const body = {
|
|
229
|
-
sdk: { name: SDK_NAME, version: SDK_VERSION },
|
|
230
|
-
context: this.buildContext(),
|
|
231
|
-
user: this.user,
|
|
232
|
-
session: this.session,
|
|
233
|
-
events
|
|
234
|
-
};
|
|
235
|
-
const f = (_a = this.opts.fetch) != null ? _a : fetch;
|
|
236
|
-
const res = await f(this.opts.endpoint, {
|
|
237
|
-
method: "POST",
|
|
238
|
-
headers: { "content-type": "application/json", "x-debug-key": this.opts.ingestKey },
|
|
239
|
-
body: JSON.stringify(body)
|
|
240
|
-
});
|
|
241
|
-
if (res.status >= 400 && res.status < 500 && res.status !== 429) {
|
|
242
|
-
this.log(`ingest rejected batch (${res.status})`, await res.text().catch(() => ""));
|
|
243
|
-
return;
|
|
244
|
-
}
|
|
245
|
-
if (!res.ok) throw new Error(`ingest responded ${res.status}`);
|
|
246
|
-
}
|
|
247
|
-
async persist() {
|
|
248
|
-
var _a;
|
|
249
|
-
try {
|
|
250
|
-
await ((_a = this.opts.storage) == null ? void 0 : _a.setItem(QUEUE_KEY, JSON.stringify(this.queue)));
|
|
251
|
-
} catch {
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
async restore() {
|
|
255
|
-
var _a;
|
|
256
|
-
try {
|
|
257
|
-
const raw = await ((_a = this.opts.storage) == null ? void 0 : _a.getItem(QUEUE_KEY));
|
|
258
|
-
if (raw) this.queue.unshift(...JSON.parse(raw));
|
|
259
|
-
} catch {
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
installGlobalHandlers() {
|
|
263
|
-
var _a, _b, _c;
|
|
264
|
-
this.handlersInstalled = true;
|
|
265
|
-
const g = globalThis;
|
|
266
|
-
if ((_a = g.ErrorUtils) == null ? void 0 : _a.setGlobalHandler) {
|
|
267
|
-
const prev = (_c = (_b = g.ErrorUtils).getGlobalHandler) == null ? void 0 : _c.call(_b);
|
|
268
|
-
g.ErrorUtils.setGlobalHandler((err, isFatal) => {
|
|
269
|
-
this.error(err, { handled: false, severity: isFatal ? "critical" : void 0 });
|
|
270
|
-
void this.flush();
|
|
271
|
-
prev == null ? void 0 : prev(err, isFatal);
|
|
272
|
-
});
|
|
273
|
-
}
|
|
274
|
-
if (typeof window !== "undefined" && typeof g.addEventListener === "function") {
|
|
275
|
-
g.addEventListener("error", (ev) => {
|
|
276
|
-
var _a2;
|
|
277
|
-
return this.error((_a2 = ev.error) != null ? _a2 : ev.message, { handled: false });
|
|
278
|
-
});
|
|
279
|
-
g.addEventListener("unhandledrejection", (ev) => this.error(ev.reason, { handled: false }));
|
|
280
|
-
}
|
|
281
|
-
}
|
|
282
|
-
log(...args) {
|
|
283
|
-
var _a;
|
|
284
|
-
if ((_a = this.opts) == null ? void 0 : _a.debug) console.warn("[deBug]", ...args);
|
|
285
|
-
}
|
|
286
|
-
};
|
|
287
|
-
function normaliseError(err) {
|
|
288
|
-
if (err instanceof Error) return { name: err.name || "Error", message: err.message, stack: err.stack };
|
|
289
|
-
if (typeof err === "string") return { name: "Error", message: err };
|
|
290
|
-
try {
|
|
291
|
-
return { name: "NonError", message: JSON.stringify(err).slice(0, 2e3) };
|
|
292
|
-
} catch {
|
|
293
|
-
return { name: "NonError", message: String(err) };
|
|
294
|
-
}
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
// src/index.ts
|
|
298
|
-
var deBug = new DebugClient();
|
|
299
|
-
|
|
300
|
-
exports.DebugClient = DebugClient;
|
|
301
|
-
exports.SDK_NAME = SDK_NAME;
|
|
302
|
-
exports.SDK_VERSION = SDK_VERSION;
|
|
303
|
-
exports.__publicField = __publicField;
|
|
304
|
-
exports.browserContext = browserContext;
|
|
305
|
-
exports.deBug = deBug;
|
|
306
|
-
exports.locale = locale;
|
|
307
|
-
exports.mergeContext = mergeContext;
|
|
308
|
-
exports.parseStack = parseStack;
|
|
309
|
-
exports.timezone = timezone;
|
|
310
|
-
//# sourceMappingURL=chunk-XEFWRCN4.cjs.map
|
|
311
|
-
//# sourceMappingURL=chunk-XEFWRCN4.cjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../schema/src/core.ts","../src/context.ts","../src/client.ts","../src/index.ts"],"names":["ua","_a"],"mappings":"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","file":"chunk-XEFWRCN4.cjs","sourcesContent":["/**\n * Zod-free half of the schema: types, constants and pure helpers.\n * Client code (the SDK) imports only this entry so validators never reach app bundles.\n */\nimport type { Severity, StackFrame } from \"./index\";\n\nexport type {\n Flow,\n Device,\n Context,\n ContextInput,\n Breadcrumb,\n StackFrame,\n Severity,\n ErrorEvent,\n CustomEvent,\n Event,\n EventInput,\n Envelope,\n EnvelopeInput,\n StoredEvent,\n Issue,\n RollupDimension,\n RollupIncrement,\n RollupRow,\n} from \"./index\";\n\nexport const SCHEMA_VERSION = 1;\n\n/* ---------- Severity (shared by ingest + dashboard) ---------- */\n\nexport interface SeverityThresholds {\n critical: number;\n high: number;\n medium: number;\n}\n\n/** Occurrences in the trailing 24h window. */\nexport const DEFAULT_SEVERITY_THRESHOLDS: SeverityThresholds = { critical: 100, high: 25, medium: 5 };\n\nexport function severityFromCount(count: number, t: SeverityThresholds = DEFAULT_SEVERITY_THRESHOLDS): Severity {\n if (count >= t.critical) return \"critical\";\n if (count >= t.high) return \"high\";\n if (count >= t.medium) return \"medium\";\n return \"low\";\n}\n\nexport const SEVERITY_ORDER: Record<Severity, number> = { critical: 3, high: 2, medium: 1, low: 0 };\n\n/* ---------- Stack parsing ---------- */\n\n\n// V8/Hermes: \" at fn (file:line:col)\" or \" at file:line:col\"\nconst V8 = /^\\s*at (?:(.+?) \\()?(.+?):(\\d+):(\\d+)\\)?\\s*$/;\n// JSC/Firefox: \"fn@file:line:col\"\nconst GECKO = /^\\s*(.*?)@(.+?):(\\d+):(\\d+)\\s*$/;\n\nconst NOT_IN_APP = [/node_modules/, /\\bnative\\b/, /\\[native code\\]/, /InternalBytecode/];\n\n/**\n * React Native ships one JS bundle, so every frame points at it: in development a Metro URL\n * (\".../entry.bundle//&platform=ios&dev=true...\"), in release \"address at index.android.bundle\"\n * or \"main.jsbundle\". We can't tell app code from library code without source maps, so bundle\n * frames count as in-app and the function name carries the signal.\n */\nconst RN_BUNDLE = /\\.(?:js)?bundle\\b/;\n\nfunction cleanFile(file: string): string {\n return file.replace(/^address at /, \"\");\n}\n\nexport function parseStack(stack: string | undefined): StackFrame[] {\n if (!stack) return [];\n const frames: StackFrame[] = [];\n for (const raw of stack.split(\"\\n\")) {\n const m = V8.exec(raw) ?? GECKO.exec(raw);\n if (!m) continue;\n const [, fn, rawFile, line, col] = m;\n const file = cleanFile(rawFile ?? \"\");\n frames.push({\n fn: fn || undefined,\n file,\n line: Number(line),\n col: Number(col),\n inApp: RN_BUNDLE.test(file) ? !/^(?:anonymous|eval|global code)$/.test(fn ?? \"\") : !NOT_IN_APP.some((re) => re.test(file)),\n });\n if (frames.length >= 100) break;\n }\n return frames;\n}\n","import type { ContextInput } from \"@debugkit/schema/core\";\n\ntype Shallow<T> = { [K in keyof T]?: T[K] extends object ? Partial<T[K]> : T[K] };\nexport type ContextPatch = Shallow<ContextInput>;\n\n/** Merge two context patches one level deep (os, device, app ... are merged field by field). */\nexport function mergeContext(a: ContextPatch, b: ContextPatch): ContextPatch {\n const out: Record<string, unknown> = { ...a };\n for (const [k, v] of Object.entries(b)) {\n const prev = out[k];\n out[k] = v && typeof v === \"object\" && prev && typeof prev === \"object\" ? { ...prev, ...v } : v ?? prev;\n }\n return out as ContextPatch;\n}\n\nfunction safe<T>(fn: () => T): T | undefined {\n try {\n return fn();\n } catch {\n return undefined;\n }\n}\n\nexport function timezone(): string | undefined {\n return safe(() => Intl.DateTimeFormat().resolvedOptions().timeZone);\n}\nexport function locale(): string | undefined {\n return safe(() => Intl.DateTimeFormat().resolvedOptions().locale);\n}\n\n/**\n * Best-effort context for browsers (React, TanStack Start/Router client, Next client ...).\n * Safe to call in any runtime: it never touches globals that might not exist.\n */\nexport function browserContext(): ContextPatch {\n if (typeof navigator === \"undefined\" || typeof window === \"undefined\") {\n const ua = typeof navigator !== \"undefined\" ? navigator.userAgent : undefined;\n const node = typeof process !== \"undefined\" ? process.versions?.node : undefined;\n return {\n runtime: { name: ua === \"Cloudflare-Workers\" ? \"cloudflare-workers\" : node ? \"node\" : \"edge\", version: node },\n os: { name: \"server\" },\n timezone: timezone(),\n };\n }\n const ua = navigator.userAgent;\n const android = /Android ([\\d.]+)/.exec(ua)?.[1];\n const ios = /(?:iPhone|iPad|iPod).*? OS (\\d+[_\\d]*)/.exec(ua)?.[1];\n const os = android\n ? { name: \"android\", version: android }\n : ios\n ? { name: \"ios\", version: ios.replace(/_/g, \".\") }\n : /Mac OS X/.test(ua)\n ? { name: \"macos\" }\n : /Windows/.test(ua)\n ? { name: \"windows\" }\n : /Linux/.test(ua)\n ? { name: \"linux\" }\n : { name: \"web\" };\n const conn = (navigator as { connection?: { effectiveType?: string; type?: string } }).connection;\n const browser = /Edg\\/([\\d.]+)/.exec(ua)\n ? { name: \"edge\", v: /Edg\\/([\\d.]+)/.exec(ua)![1] }\n : /Chrome\\/([\\d.]+)/.exec(ua)\n ? { name: \"chrome\", v: /Chrome\\/([\\d.]+)/.exec(ua)![1] }\n : /Version\\/([\\d.]+).*Safari/.exec(ua)\n ? { name: \"safari\", v: /Version\\/([\\d.]+)/.exec(ua)![1] }\n : /Firefox\\/([\\d.]+)/.exec(ua)\n ? { name: \"firefox\", v: /Firefox\\/([\\d.]+)/.exec(ua)![1] }\n : undefined;\n return {\n os,\n runtime: { name: \"browser\", version: browser ? `${browser.name} ${browser.v}` : undefined },\n device: {\n type: /iPad|Tablet/.test(ua) ? \"tablet\" : /Mobi/.test(ua) ? \"phone\" : \"desktop\",\n screen: typeof screen !== \"undefined\" ? { width: screen.width, height: screen.height, scale: window.devicePixelRatio } : undefined,\n },\n network: conn\n ? {\n type: conn.type === \"wifi\" ? \"wifi\" : conn.type === \"cellular\" ? \"cellular\" : \"unknown\",\n effectiveType: conn.effectiveType,\n isConnected: navigator.onLine,\n }\n : undefined,\n locale: navigator.language,\n timezone: timezone(),\n };\n}\n","import type { Breadcrumb, ContextInput, EnvelopeInput, EventInput, Severity } from \"@debugkit/schema/core\";\nimport { parseStack } from \"@debugkit/schema/core\";\nimport { browserContext, mergeContext, type ContextPatch } from \"./context\";\n\nexport const SDK_NAME = \"@debugkit/sdk\";\nexport const SDK_VERSION = \"0.1.0\";\n\n/** Optional persistence so events survive app restarts / offline. e.g. AsyncStorage. */\nexport interface QueueStorage {\n getItem(key: string): Promise<string | null>;\n setItem(key: string, value: string): Promise<void>;\n}\n\nexport interface InitOptions {\n /** URL of the ingest function deployed in your cloud. */\n endpoint: string;\n /** Public, write-only key. Safe to ship in the app. */\n ingestKey: string;\n app: { id: string; version?: string; build?: string; environment?: string };\n /**\n * Platform context. Defaults to browserContext() in browsers. The framework entry points\n * (`/expo`, `/react-native`, `/node`) fill this in for you.\n */\n context?: ContextPatch;\n /** Capture uncaught errors and unhandled promise rejections. Default true. */\n captureGlobalErrors?: boolean;\n storage?: QueueStorage;\n /** How often queued events are sent. 0 disables the timer (edge runtimes): call flush() yourself. Default 5000. */\n flushIntervalMs?: number;\n maxBatch?: number;\n maxBreadcrumbs?: number;\n /** Drop or edit events before they are sent (PII scrubbing). Return null to drop. */\n beforeSend?: (e: EventInput) => EventInput | null;\n fetch?: typeof fetch;\n debug?: boolean;\n}\n\nexport interface EventMeta {\n flow?: string;\n step?: string;\n tags?: Record<string, string>;\n}\n\nconst QUEUE_KEY = \"@debugkit/queue\";\nconst MAX_QUEUE = 500;\n\nconst uid = () =>\n (globalThis.crypto?.randomUUID?.() ??\n `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 12)}`).replace(/-/g, \"\");\nconst now = () => new Date().toISOString();\n\nexport class DebugClient {\n private opts!: Required<Pick<InitOptions, \"flushIntervalMs\" | \"maxBatch\" | \"maxBreadcrumbs\">> & InitOptions;\n private queue: EventInput[] = [];\n private crumbs: Breadcrumb[] = [];\n private session = { id: uid(), startedAt: now() };\n private user: { id?: string; anonymousId: string } = { anonymousId: uid() };\n private timer: ReturnType<typeof setInterval> | undefined;\n private flushing: Promise<void> | undefined;\n private backoffUntil = 0;\n private failures = 0;\n private ready = false;\n private handlersInstalled = false;\n\n init(options: InitOptions): this {\n if (this.timer) clearInterval(this.timer);\n this.opts = { flushIntervalMs: 5000, maxBatch: 50, maxBreadcrumbs: 30, captureGlobalErrors: true, ...options };\n if (!this.opts.context && typeof window !== \"undefined\") this.opts.context = browserContext();\n this.ready = true;\n void this.restore();\n if (this.opts.captureGlobalErrors && !this.handlersInstalled) this.installGlobalHandlers();\n if (this.opts.flushIntervalMs > 0) {\n this.timer = setInterval(() => void this.flush(), this.opts.flushIntervalMs);\n (this.timer as { unref?: () => void }).unref?.();\n }\n return this;\n }\n\n get initialized() {\n return this.ready;\n }\n\n /** Merge extra context (e.g. after an async device lookup). Applies to events sent from now on. */\n setContext(patch: ContextPatch) {\n if (this.opts) this.opts.context = mergeContext(this.opts.context ?? {}, patch);\n }\n\n setUser(id: string | undefined) {\n this.user = { ...this.user, id };\n }\n\n breadcrumb(category: Breadcrumb[\"category\"], message: string, data?: Record<string, string | number | boolean | null>, level: Breadcrumb[\"level\"] = \"info\") {\n this.crumbs.push({ ts: now(), category, message: message.slice(0, 500), data, level });\n if (this.crumbs.length > (this.opts?.maxBreadcrumbs ?? 30)) this.crumbs.shift();\n }\n\n /** Log an error. `flow` is the part of the app it belongs to, e.g. \"auth.login\". */\n error(err: unknown, meta: EventMeta & { severity?: Severity; handled?: boolean } = {}) {\n const e = normaliseError(err);\n this.enqueue({\n type: \"error\",\n id: uid(),\n ts: now(),\n flow: meta.flow,\n step: meta.step,\n tags: meta.tags,\n severity: meta.severity,\n handled: meta.handled ?? true,\n error: { name: e.name, message: e.message, stack: e.stack, frames: parseStack(e.stack) },\n breadcrumbs: [...this.crumbs],\n });\n }\n\n /** Log a custom event. Use outcome to let deBug compute failure rates per flow. */\n event(name: string, meta: EventMeta & { outcome?: \"success\" | \"failure\" | \"abandoned\"; props?: Record<string, string | number | boolean | null> } = {}) {\n this.breadcrumb(\"event\", name, meta.props);\n this.enqueue({ type: \"event\", id: uid(), ts: now(), name, flow: meta.flow, step: meta.step, tags: meta.tags, outcome: meta.outcome, props: meta.props });\n }\n\n /** Wraps an async step: logs success, or failure + the error, against a flow. */\n /**\n * Wraps an async step: logs a success or failure outcome for the flow, plus the error.\n * Pass `{ captureError: false }` when the error is already reported elsewhere, e.g. a\n * server function wrapped in withDebug, so it isn't counted twice.\n */\n async track<T>(flow: string, step: string, fn: () => Promise<T>, opts: { captureError?: boolean } = {}): Promise<T> {\n try {\n const out = await fn();\n this.event(`${flow}.${step}`, { flow, step, outcome: \"success\" });\n return out;\n } catch (err) {\n this.event(`${flow}.${step}`, { flow, step, outcome: \"failure\" });\n if (opts.captureError !== false) this.error(err, { flow, step });\n throw err;\n }\n }\n\n async flush(): Promise<void> {\n if (!this.ready || this.flushing || this.queue.length === 0 || Date.now() < this.backoffUntil) return this.flushing;\n const batch = this.queue.splice(0, this.opts.maxBatch);\n this.flushing = this.send(batch)\n .then(() => {\n this.failures = 0;\n })\n .catch((err) => {\n this.queue.unshift(...batch);\n this.failures++;\n this.backoffUntil = Date.now() + Math.min(60_000, 1000 * 2 ** this.failures);\n this.log(\"flush failed\", err);\n })\n .finally(() => {\n this.flushing = undefined;\n void this.persist();\n });\n return this.flushing;\n }\n\n close() {\n if (this.timer) clearInterval(this.timer);\n return this.flush();\n }\n\n /* ---------------- internals ---------------- */\n\n private enqueue(e: EventInput) {\n if (!this.ready) return;\n const out = this.opts.beforeSend ? this.opts.beforeSend(e) : e;\n if (!out) return;\n this.queue.push(out);\n if (this.queue.length > MAX_QUEUE) this.queue.splice(0, this.queue.length - MAX_QUEUE);\n if (out.type === \"error\" || this.queue.length >= this.opts.maxBatch) void this.flush();\n else void this.persist();\n }\n\n private buildContext(): ContextInput {\n const c = this.opts.context ?? {};\n return {\n ...c,\n app: { ...(c.app ?? {}), ...this.opts.app },\n os: { name: \"unknown\", ...(c.os ?? {}) },\n runtime: { name: \"unknown\", ...(c.runtime ?? {}) },\n device: c.device ?? {},\n } as ContextInput;\n }\n\n private async send(events: EventInput[]) {\n const body: EnvelopeInput = {\n sdk: { name: SDK_NAME, version: SDK_VERSION },\n context: this.buildContext(),\n user: this.user,\n session: this.session,\n events,\n };\n const f = this.opts.fetch ?? fetch;\n const res = await f(this.opts.endpoint, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\", \"x-debug-key\": this.opts.ingestKey },\n body: JSON.stringify(body),\n });\n // 4xx (other than 429) means the payload will never be accepted: drop it instead of retrying forever.\n if (res.status >= 400 && res.status < 500 && res.status !== 429) {\n this.log(`ingest rejected batch (${res.status})`, await res.text().catch(() => \"\"));\n return;\n }\n if (!res.ok) throw new Error(`ingest responded ${res.status}`);\n }\n\n private async persist() {\n try {\n await this.opts.storage?.setItem(QUEUE_KEY, JSON.stringify(this.queue));\n } catch {}\n }\n\n private async restore() {\n try {\n const raw = await this.opts.storage?.getItem(QUEUE_KEY);\n if (raw) this.queue.unshift(...(JSON.parse(raw) as EventInput[]));\n } catch {}\n }\n\n private installGlobalHandlers() {\n this.handlersInstalled = true;\n const g = globalThis as Record<string, any>;\n // React Native\n if (g.ErrorUtils?.setGlobalHandler) {\n const prev = g.ErrorUtils.getGlobalHandler?.();\n g.ErrorUtils.setGlobalHandler((err: unknown, isFatal?: boolean) => {\n this.error(err, { handled: false, severity: isFatal ? \"critical\" : undefined });\n void this.flush();\n prev?.(err, isFatal);\n });\n }\n // Browser (not workers / edge runtimes, which also expose addEventListener)\n if (typeof window !== \"undefined\" && typeof g.addEventListener === \"function\") {\n g.addEventListener(\"error\", (ev: { error?: unknown; message?: string }) => this.error(ev.error ?? ev.message, { handled: false }));\n g.addEventListener(\"unhandledrejection\", (ev: { reason?: unknown }) => this.error(ev.reason, { handled: false }));\n }\n }\n\n private log(...args: unknown[]) {\n if (this.opts?.debug) console.warn(\"[deBug]\", ...args);\n }\n}\n\nfunction normaliseError(err: unknown): { name: string; message: string; stack?: string } {\n if (err instanceof Error) return { name: err.name || \"Error\", message: err.message, stack: err.stack };\n if (typeof err === \"string\") return { name: \"Error\", message: err };\n try {\n return { name: \"NonError\", message: JSON.stringify(err).slice(0, 2000) };\n } catch {\n return { name: \"NonError\", message: String(err) };\n }\n}\n","import { DebugClient } from \"./client\";\n\nexport { DebugClient, SDK_NAME, SDK_VERSION } from \"./client\";\nexport type { InitOptions, EventMeta, QueueStorage } from \"./client\";\nexport { browserContext, mergeContext, type ContextPatch } from \"./context\";\nexport { parseStack } from \"@debugkit/schema/core\";\nexport type { Breadcrumb, EventInput, Severity, StackFrame } from \"@debugkit/schema/core\";\n\n/**\n * Default client. Framework entry points (`/react`, `/react-native`, `/expo`, `/node`) use this\n * same instance, so `import { deBug } from \"@debugkit/sdk\"` works everywhere.\n */\nexport const deBug = new DebugClient();\n"]}
|
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
import { ContextInput, EventInput, Breadcrumb, Severity } from '@debugkit/schema/core';
|
|
2
|
-
|
|
3
|
-
type Shallow<T> = {
|
|
4
|
-
[K in keyof T]?: T[K] extends object ? Partial<T[K]> : T[K];
|
|
5
|
-
};
|
|
6
|
-
type ContextPatch = Shallow<ContextInput>;
|
|
7
|
-
/** Merge two context patches one level deep (os, device, app ... are merged field by field). */
|
|
8
|
-
declare function mergeContext(a: ContextPatch, b: ContextPatch): ContextPatch;
|
|
9
|
-
/**
|
|
10
|
-
* Best-effort context for browsers (React, TanStack Start/Router client, Next client ...).
|
|
11
|
-
* Safe to call in any runtime: it never touches globals that might not exist.
|
|
12
|
-
*/
|
|
13
|
-
declare function browserContext(): ContextPatch;
|
|
14
|
-
|
|
15
|
-
declare const SDK_NAME = "@debugkit/sdk";
|
|
16
|
-
declare const SDK_VERSION = "0.1.0";
|
|
17
|
-
/** Optional persistence so events survive app restarts / offline. e.g. AsyncStorage. */
|
|
18
|
-
interface QueueStorage {
|
|
19
|
-
getItem(key: string): Promise<string | null>;
|
|
20
|
-
setItem(key: string, value: string): Promise<void>;
|
|
21
|
-
}
|
|
22
|
-
interface InitOptions {
|
|
23
|
-
/** URL of the ingest function deployed in your cloud. */
|
|
24
|
-
endpoint: string;
|
|
25
|
-
/** Public, write-only key. Safe to ship in the app. */
|
|
26
|
-
ingestKey: string;
|
|
27
|
-
app: {
|
|
28
|
-
id: string;
|
|
29
|
-
version?: string;
|
|
30
|
-
build?: string;
|
|
31
|
-
environment?: string;
|
|
32
|
-
};
|
|
33
|
-
/**
|
|
34
|
-
* Platform context. Defaults to browserContext() in browsers. The framework entry points
|
|
35
|
-
* (`/expo`, `/react-native`, `/node`) fill this in for you.
|
|
36
|
-
*/
|
|
37
|
-
context?: ContextPatch;
|
|
38
|
-
/** Capture uncaught errors and unhandled promise rejections. Default true. */
|
|
39
|
-
captureGlobalErrors?: boolean;
|
|
40
|
-
storage?: QueueStorage;
|
|
41
|
-
/** How often queued events are sent. 0 disables the timer (edge runtimes): call flush() yourself. Default 5000. */
|
|
42
|
-
flushIntervalMs?: number;
|
|
43
|
-
maxBatch?: number;
|
|
44
|
-
maxBreadcrumbs?: number;
|
|
45
|
-
/** Drop or edit events before they are sent (PII scrubbing). Return null to drop. */
|
|
46
|
-
beforeSend?: (e: EventInput) => EventInput | null;
|
|
47
|
-
fetch?: typeof fetch;
|
|
48
|
-
debug?: boolean;
|
|
49
|
-
}
|
|
50
|
-
interface EventMeta {
|
|
51
|
-
flow?: string;
|
|
52
|
-
step?: string;
|
|
53
|
-
tags?: Record<string, string>;
|
|
54
|
-
}
|
|
55
|
-
declare class DebugClient {
|
|
56
|
-
private opts;
|
|
57
|
-
private queue;
|
|
58
|
-
private crumbs;
|
|
59
|
-
private session;
|
|
60
|
-
private user;
|
|
61
|
-
private timer;
|
|
62
|
-
private flushing;
|
|
63
|
-
private backoffUntil;
|
|
64
|
-
private failures;
|
|
65
|
-
private ready;
|
|
66
|
-
private handlersInstalled;
|
|
67
|
-
init(options: InitOptions): this;
|
|
68
|
-
get initialized(): boolean;
|
|
69
|
-
/** Merge extra context (e.g. after an async device lookup). Applies to events sent from now on. */
|
|
70
|
-
setContext(patch: ContextPatch): void;
|
|
71
|
-
setUser(id: string | undefined): void;
|
|
72
|
-
breadcrumb(category: Breadcrumb["category"], message: string, data?: Record<string, string | number | boolean | null>, level?: Breadcrumb["level"]): void;
|
|
73
|
-
/** Log an error. `flow` is the part of the app it belongs to, e.g. "auth.login". */
|
|
74
|
-
error(err: unknown, meta?: EventMeta & {
|
|
75
|
-
severity?: Severity;
|
|
76
|
-
handled?: boolean;
|
|
77
|
-
}): void;
|
|
78
|
-
/** Log a custom event. Use outcome to let deBug compute failure rates per flow. */
|
|
79
|
-
event(name: string, meta?: EventMeta & {
|
|
80
|
-
outcome?: "success" | "failure" | "abandoned";
|
|
81
|
-
props?: Record<string, string | number | boolean | null>;
|
|
82
|
-
}): void;
|
|
83
|
-
/** Wraps an async step: logs success, or failure + the error, against a flow. */
|
|
84
|
-
/**
|
|
85
|
-
* Wraps an async step: logs a success or failure outcome for the flow, plus the error.
|
|
86
|
-
* Pass `{ captureError: false }` when the error is already reported elsewhere, e.g. a
|
|
87
|
-
* server function wrapped in withDebug, so it isn't counted twice.
|
|
88
|
-
*/
|
|
89
|
-
track<T>(flow: string, step: string, fn: () => Promise<T>, opts?: {
|
|
90
|
-
captureError?: boolean;
|
|
91
|
-
}): Promise<T>;
|
|
92
|
-
flush(): Promise<void>;
|
|
93
|
-
close(): Promise<void>;
|
|
94
|
-
private enqueue;
|
|
95
|
-
private buildContext;
|
|
96
|
-
private send;
|
|
97
|
-
private persist;
|
|
98
|
-
private restore;
|
|
99
|
-
private installGlobalHandlers;
|
|
100
|
-
private log;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
export { type ContextPatch as C, DebugClient as D, type EventMeta as E, type InitOptions as I, type QueueStorage as Q, SDK_NAME as S, SDK_VERSION as a, browserContext as b, mergeContext as m };
|
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
import { ContextInput, EventInput, Breadcrumb, Severity } from '@debugkit/schema/core';
|
|
2
|
-
|
|
3
|
-
type Shallow<T> = {
|
|
4
|
-
[K in keyof T]?: T[K] extends object ? Partial<T[K]> : T[K];
|
|
5
|
-
};
|
|
6
|
-
type ContextPatch = Shallow<ContextInput>;
|
|
7
|
-
/** Merge two context patches one level deep (os, device, app ... are merged field by field). */
|
|
8
|
-
declare function mergeContext(a: ContextPatch, b: ContextPatch): ContextPatch;
|
|
9
|
-
/**
|
|
10
|
-
* Best-effort context for browsers (React, TanStack Start/Router client, Next client ...).
|
|
11
|
-
* Safe to call in any runtime: it never touches globals that might not exist.
|
|
12
|
-
*/
|
|
13
|
-
declare function browserContext(): ContextPatch;
|
|
14
|
-
|
|
15
|
-
declare const SDK_NAME = "@debugkit/sdk";
|
|
16
|
-
declare const SDK_VERSION = "0.1.0";
|
|
17
|
-
/** Optional persistence so events survive app restarts / offline. e.g. AsyncStorage. */
|
|
18
|
-
interface QueueStorage {
|
|
19
|
-
getItem(key: string): Promise<string | null>;
|
|
20
|
-
setItem(key: string, value: string): Promise<void>;
|
|
21
|
-
}
|
|
22
|
-
interface InitOptions {
|
|
23
|
-
/** URL of the ingest function deployed in your cloud. */
|
|
24
|
-
endpoint: string;
|
|
25
|
-
/** Public, write-only key. Safe to ship in the app. */
|
|
26
|
-
ingestKey: string;
|
|
27
|
-
app: {
|
|
28
|
-
id: string;
|
|
29
|
-
version?: string;
|
|
30
|
-
build?: string;
|
|
31
|
-
environment?: string;
|
|
32
|
-
};
|
|
33
|
-
/**
|
|
34
|
-
* Platform context. Defaults to browserContext() in browsers. The framework entry points
|
|
35
|
-
* (`/expo`, `/react-native`, `/node`) fill this in for you.
|
|
36
|
-
*/
|
|
37
|
-
context?: ContextPatch;
|
|
38
|
-
/** Capture uncaught errors and unhandled promise rejections. Default true. */
|
|
39
|
-
captureGlobalErrors?: boolean;
|
|
40
|
-
storage?: QueueStorage;
|
|
41
|
-
/** How often queued events are sent. 0 disables the timer (edge runtimes): call flush() yourself. Default 5000. */
|
|
42
|
-
flushIntervalMs?: number;
|
|
43
|
-
maxBatch?: number;
|
|
44
|
-
maxBreadcrumbs?: number;
|
|
45
|
-
/** Drop or edit events before they are sent (PII scrubbing). Return null to drop. */
|
|
46
|
-
beforeSend?: (e: EventInput) => EventInput | null;
|
|
47
|
-
fetch?: typeof fetch;
|
|
48
|
-
debug?: boolean;
|
|
49
|
-
}
|
|
50
|
-
interface EventMeta {
|
|
51
|
-
flow?: string;
|
|
52
|
-
step?: string;
|
|
53
|
-
tags?: Record<string, string>;
|
|
54
|
-
}
|
|
55
|
-
declare class DebugClient {
|
|
56
|
-
private opts;
|
|
57
|
-
private queue;
|
|
58
|
-
private crumbs;
|
|
59
|
-
private session;
|
|
60
|
-
private user;
|
|
61
|
-
private timer;
|
|
62
|
-
private flushing;
|
|
63
|
-
private backoffUntil;
|
|
64
|
-
private failures;
|
|
65
|
-
private ready;
|
|
66
|
-
private handlersInstalled;
|
|
67
|
-
init(options: InitOptions): this;
|
|
68
|
-
get initialized(): boolean;
|
|
69
|
-
/** Merge extra context (e.g. after an async device lookup). Applies to events sent from now on. */
|
|
70
|
-
setContext(patch: ContextPatch): void;
|
|
71
|
-
setUser(id: string | undefined): void;
|
|
72
|
-
breadcrumb(category: Breadcrumb["category"], message: string, data?: Record<string, string | number | boolean | null>, level?: Breadcrumb["level"]): void;
|
|
73
|
-
/** Log an error. `flow` is the part of the app it belongs to, e.g. "auth.login". */
|
|
74
|
-
error(err: unknown, meta?: EventMeta & {
|
|
75
|
-
severity?: Severity;
|
|
76
|
-
handled?: boolean;
|
|
77
|
-
}): void;
|
|
78
|
-
/** Log a custom event. Use outcome to let deBug compute failure rates per flow. */
|
|
79
|
-
event(name: string, meta?: EventMeta & {
|
|
80
|
-
outcome?: "success" | "failure" | "abandoned";
|
|
81
|
-
props?: Record<string, string | number | boolean | null>;
|
|
82
|
-
}): void;
|
|
83
|
-
/** Wraps an async step: logs success, or failure + the error, against a flow. */
|
|
84
|
-
/**
|
|
85
|
-
* Wraps an async step: logs a success or failure outcome for the flow, plus the error.
|
|
86
|
-
* Pass `{ captureError: false }` when the error is already reported elsewhere, e.g. a
|
|
87
|
-
* server function wrapped in withDebug, so it isn't counted twice.
|
|
88
|
-
*/
|
|
89
|
-
track<T>(flow: string, step: string, fn: () => Promise<T>, opts?: {
|
|
90
|
-
captureError?: boolean;
|
|
91
|
-
}): Promise<T>;
|
|
92
|
-
flush(): Promise<void>;
|
|
93
|
-
close(): Promise<void>;
|
|
94
|
-
private enqueue;
|
|
95
|
-
private buildContext;
|
|
96
|
-
private send;
|
|
97
|
-
private persist;
|
|
98
|
-
private restore;
|
|
99
|
-
private installGlobalHandlers;
|
|
100
|
-
private log;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
export { type ContextPatch as C, DebugClient as D, type EventMeta as E, type InitOptions as I, type QueueStorage as Q, SDK_NAME as S, SDK_VERSION as a, browserContext as b, mergeContext as m };
|