reportli 1.0.1 → 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1,15 +1,12 @@
1
- /**
2
- * Reportli SDK v1.0.1
3
- * Your AI agent that never sleeps.
4
- * Watches your SaaS, catches every error, files the GitHub issue — automatically.
5
- */
6
- declare const Reportli: {
7
- init({ apiKey }: {
8
- apiKey: string;
9
- }): void;
10
- capture(error: any): void;
1
+ type Config = {
2
+ apiKey: string;
3
+ environment?: string;
4
+ };
5
+ export declare const Reportli: {
6
+ init(cfg: Config): void;
7
+ capture(error: unknown): void;
8
+ captureMessage(message: string): void;
11
9
  errorHandler(): (err: any, _req: any, _res: any, next: any) => void;
12
10
  };
13
11
  export default Reportli;
14
- export { Reportli };
15
12
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AA2UH,QAAA,MAAM,QAAQ;qBACK;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;mBAoC3B,GAAG,GAAG,IAAI;qBAMN,KAAK,GAAG,EAAE,MAAM,GAAG,EAAE,MAAM,GAAG,EAAE,MAAM,GAAG;CAK7D,CAAC;AAEF,eAAe,QAAQ,CAAC;AACxB,OAAO,EAAE,QAAQ,EAAE,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAOA,KAAK,MAAM,GAAG;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AA+WF,eAAO,MAAM,QAAQ;cACT,MAAM;mBAyBD,OAAO;4BAQE,MAAM;qBAMX,KAAK,GAAG,EAAE,MAAM,GAAG,EAAE,MAAM,GAAG,EAAE,MAAM,GAAG;CAK7D,CAAC;AAEF,eAAe,QAAQ,CAAC"}
package/dist/index.js CHANGED
@@ -25,14 +25,64 @@ __export(src_exports, {
25
25
  });
26
26
  module.exports = __toCommonJS(src_exports);
27
27
  var ENDPOINT = "https://fahikyfmgdyzejdfftox.supabase.co/functions/v1/rapid-processor";
28
- var isBrowser = typeof window !== "undefined";
29
- var isNode = typeof process !== "undefined" && !!process.versions?.node;
30
- var _apiKey = "";
31
- function getEnvironment() {
32
- return isBrowser ? "browser" : "server";
28
+ var initialized = false;
29
+ var _config;
30
+ var queue = [];
31
+ var flushTimer = null;
32
+ var isFlushing = false;
33
+ function scheduleFlush() {
34
+ if (flushTimer)
35
+ return;
36
+ flushTimer = setTimeout(() => {
37
+ flushTimer = null;
38
+ flush();
39
+ }, 2e3);
40
+ }
41
+ async function flush() {
42
+ if (isFlushing || queue.length === 0)
43
+ return;
44
+ isFlushing = true;
45
+ const batch = queue.splice(0, 10);
46
+ for (const payload of batch) {
47
+ await sendNow(payload);
48
+ }
49
+ isFlushing = false;
50
+ if (queue.length > 0)
51
+ flush();
52
+ }
53
+ async function sendNow(payload, attempts = 3) {
54
+ for (let i = 0; i < attempts; i++) {
55
+ try {
56
+ const res = await fetch(ENDPOINT, {
57
+ method: "POST",
58
+ headers: {
59
+ "Content-Type": "application/json",
60
+ "x-api-key": _config?.apiKey ?? ""
61
+ },
62
+ body: JSON.stringify(payload)
63
+ });
64
+ if (res.ok)
65
+ return;
66
+ } catch {
67
+ }
68
+ await sleep(1e3 * (i + 1));
69
+ }
70
+ }
71
+ function sleep(ms) {
72
+ return new Promise((resolve) => setTimeout(resolve, ms));
73
+ }
74
+ function enqueue(payload) {
75
+ if (queue.length >= 100)
76
+ return;
77
+ queue.push(payload);
78
+ scheduleFlush();
79
+ }
80
+ function sendImmediate(payload) {
81
+ sendNow(payload).catch(() => {
82
+ });
33
83
  }
34
84
  function getUrl() {
35
- if (isBrowser)
85
+ if (typeof window !== "undefined")
36
86
  return window.location.href;
37
87
  try {
38
88
  return require("os").hostname();
@@ -41,10 +91,13 @@ function getUrl() {
41
91
  }
42
92
  }
43
93
  function getBrowser() {
44
- if (isBrowser)
94
+ if (typeof navigator !== "undefined")
45
95
  return navigator.userAgent;
46
96
  return `Node.js ${typeof process !== "undefined" ? process.version : "unknown"}`;
47
97
  }
98
+ function getEnvironment() {
99
+ return _config?.environment ?? (typeof window !== "undefined" ? "browser" : "server");
100
+ }
48
101
  function parseStack(stack) {
49
102
  if (!stack)
50
103
  return { file: "unknown", line: 0, column: 0 };
@@ -61,140 +114,79 @@ function getErrorCode(error) {
61
114
  function classifyError(error, context) {
62
115
  const msg = String(error?.message || error || "").toLowerCase();
63
116
  const name = String(error?.name || "").toLowerCase();
64
- if (name.includes("quotaexceeded") || msg.includes("quota exceeded") || msg.includes("localstorage") || msg.includes("indexeddb"))
65
- return { errorType: "localStorage quota exceeded", severity: "medium" };
117
+ if (msg.includes("stripe") || msg.includes("payment") || msg.includes("card declined") || msg.includes("checkout") || msg.includes("refund"))
118
+ return { category: "Payment Error", severity: "critical" };
119
+ if (msg.includes("jwt") || msg.includes("token expired") || msg.includes("unauthorized") || msg.includes("session") || msg.includes("oauth") || msg.includes("login failed"))
120
+ return { category: "Auth Error", severity: "high" };
121
+ if (msg.includes("supabase") || msg.includes("database") || msg.includes("query") || msg.includes("connection lost") || msg.includes("transaction") || msg.includes("duplicate key") || msg.includes("foreign key"))
122
+ return { category: "Database Error", severity: "critical" };
66
123
  if (msg.includes("hydration") || msg.includes("does not match server"))
67
- return { errorType: "React hydration error", severity: "high" };
68
- if (msg.includes("invalid hook call") || msg.includes("rules of hooks"))
69
- return { errorType: "Invalid hook call error", severity: "critical" };
70
- if (msg.includes("failed prop type") || msg.includes("invalid prop"))
71
- return { errorType: "Props type error", severity: "low" };
72
- if (msg.includes("render") || msg.includes("react error boundary"))
73
- return { errorType: "Component render error", severity: "critical" };
74
- if (msg.includes("route not found") || msg.includes("404 route"))
75
- return { errorType: "Route not found error", severity: "medium" };
76
- if (msg.includes("failed to fetch dynamically imported") || msg.includes("dynamic import"))
77
- return { errorType: "Dynamic import error", severity: "high" };
78
- if (msg.includes("suspense"))
79
- return { errorType: "Suspense boundary error", severity: "medium" };
80
- if (name === "typeerror" || msg.startsWith("typeerror"))
81
- return { errorType: "TypeError", severity: "high" };
82
- if (name === "referenceerror")
83
- return { errorType: "ReferenceError", severity: "critical" };
84
- if (name === "rangeerror" || msg.includes("maximum call stack"))
85
- return { errorType: "Stack overflow error", severity: "critical" };
86
- if (name === "syntaxerror")
87
- return { errorType: "SyntaxError", severity: "high" };
88
- if (msg.includes("stripe") && (msg.includes("init") || msg.includes("key")))
89
- return { errorType: "Stripe initialization error", severity: "critical" };
90
- if (msg.includes("payment") || msg.includes("card declined"))
91
- return { errorType: "Payment processing error", severity: "critical" };
92
- if (msg.includes("checkout session"))
93
- return { errorType: "Checkout session error", severity: "high" };
94
- if (msg.includes("refund failed"))
95
- return { errorType: "Refund failed error", severity: "high" };
96
- if (msg.includes("supabase") || msg.includes("postgresterror"))
97
- return { errorType: "Supabase query error", severity: "critical" };
98
- if (msg.includes("unique constraint") || msg.includes("duplicate key"))
99
- return { errorType: "Unique constraint error", severity: "high" };
100
- if (msg.includes("foreign key"))
101
- return { errorType: "Foreign key error", severity: "high" };
102
- if (msg.includes("transaction failed") || msg.includes("rollback"))
103
- return { errorType: "Transaction failed error", severity: "critical" };
104
- if (msg.includes("connection lost") || msg.includes("econnrefused"))
105
- return { errorType: "Connection lost error", severity: "critical" };
106
- if (msg.includes("query timeout"))
107
- return { errorType: "Query timeout error", severity: "high" };
108
- if (msg.includes("jwt expired") || msg.includes("token expired"))
109
- return { errorType: "JWT expired error", severity: "high" };
110
- if (msg.includes("jwt") && msg.includes("invalid"))
111
- return { errorType: "JWT verification error", severity: "high" };
112
- if (msg.includes("firebase admin"))
113
- return { errorType: "Firebase admin error", severity: "critical" };
114
- if (msg.includes("unauthorized") || msg.includes("permission denied"))
115
- return { errorType: "Unauthorized access error", severity: "high" };
116
- if (msg.includes("login failed") || msg.includes("invalid credentials"))
117
- return { errorType: "Login failed error", severity: "medium" };
118
- if (msg.includes("session ended") || msg.includes("session expired"))
119
- return { errorType: "Session ended error", severity: "medium" };
120
- if (msg.includes("oauth"))
121
- return { errorType: "OAuth callback error", severity: "high" };
122
- if (msg.includes("cron job") || msg.includes("cron failed"))
123
- return { errorType: "Cron job failed", severity: "high" };
124
- if (msg.includes("queue processing") || msg.includes("bullmq"))
125
- return { errorType: "Queue processing error", severity: "high" };
126
- if (msg.includes("webhook"))
127
- return { errorType: "Webhook delivery failed", severity: "high" };
128
- if (msg.includes("retry limit"))
129
- return { errorType: "Retry limit exceeded", severity: "high" };
130
- if (msg.includes("out of memory") || msg.includes("heap limit"))
131
- return { errorType: "Out of memory error", severity: "critical" };
132
- if (msg.includes("cannot find module"))
133
- return { errorType: "Module not found error", severity: "critical" };
134
- if (msg.includes("email") || msg.includes("smtp") || msg.includes("sendgrid") || msg.includes("nodemailer"))
135
- return { errorType: "Email sending failed", severity: "high" };
136
- if (msg.includes("onesignal") || msg.includes("push notification"))
137
- return { errorType: "OneSignal API error", severity: "high" };
138
- if (msg.includes("file upload") || msg.includes("upload failed"))
139
- return { errorType: "File upload failed", severity: "high" };
140
- if (msg.includes("file size exceeded") || msg.includes("payload too large"))
141
- return { errorType: "File size exceeded", severity: "medium" };
142
- if (msg.includes("invalid file type") || msg.includes("mime type"))
143
- return { errorType: "Invalid file type", severity: "medium" };
124
+ return { category: "Hydration Error", severity: "high" };
125
+ if (msg.includes("invalid hook") || msg.includes("rules of hooks"))
126
+ return { category: "Hook Error", severity: "critical" };
127
+ if (msg.includes("render") || msg.includes("error boundary"))
128
+ return { category: "Render Error", severity: "critical" };
129
+ if (msg.includes("dynamic import") || msg.includes("failed to fetch dynamically"))
130
+ return { category: "Import Error", severity: "high" };
144
131
  if (msg.includes("cors") || msg.includes("cross-origin"))
145
- return { errorType: "CORS error", severity: "high" };
146
- if (msg.includes("fetch failed") || msg.includes("failed to fetch"))
147
- return { errorType: "Fetch failed error", severity: "high" };
132
+ return { category: "CORS Error", severity: "high" };
133
+ if (msg.includes("fetch failed") || msg.includes("failed to fetch") || name === "fetcherror")
134
+ return { category: "Network Error", severity: "high" };
148
135
  if (msg.includes("timeout") || msg.includes("timed out") || msg.includes("etimedout"))
149
- return { errorType: "Request timeout error", severity: "medium" };
136
+ return { category: "Timeout Error", severity: "medium" };
150
137
  if (msg.includes("websocket"))
151
- return { errorType: "WebSocket connection error", severity: "high" };
138
+ return { category: "WebSocket Error", severity: "high" };
139
+ if (msg.includes("http 401") || msg.includes("xhr 401"))
140
+ return { category: "Auth Error", severity: "high" };
141
+ if (msg.includes("http 403") || msg.includes("xhr 403"))
142
+ return { category: "Auth Error", severity: "high" };
143
+ if (msg.includes("http 404") || msg.includes("xhr 404"))
144
+ return { category: "Not Found Error", severity: "medium" };
145
+ if (msg.includes("http 500") || msg.includes("xhr 500"))
146
+ return { category: "Server Error", severity: "critical" };
147
+ if (msg.includes("http 503") || msg.includes("xhr 503"))
148
+ return { category: "Server Error", severity: "critical" };
149
+ if (msg.includes("maximum call stack") || msg.includes("out of memory") || msg.includes("heap limit"))
150
+ return { category: "Memory Error", severity: "critical" };
151
+ if (msg.includes("cannot find module") || msg.includes("module not found"))
152
+ return { category: "Module Error", severity: "critical" };
153
+ if (msg.includes("econnrefused") || msg.includes("connection refused"))
154
+ return { category: "Connection Error", severity: "critical" };
155
+ if (msg.includes("email") || msg.includes("smtp") || msg.includes("sendgrid"))
156
+ return { category: "Email Error", severity: "high" };
157
+ if (msg.includes("cron") || msg.includes("webhook") || msg.includes("queue"))
158
+ return { category: "Job Error", severity: "high" };
159
+ if (msg.includes("upload") || msg.includes("file size") || msg.includes("invalid file"))
160
+ return { category: "File Error", severity: "medium" };
161
+ if (msg.includes("quota exceeded") || msg.includes("localstorage") || msg.includes("indexeddb"))
162
+ return { category: "Storage Error", severity: "medium" };
163
+ if (name === "typeerror")
164
+ return { category: "TypeError", severity: "high" };
165
+ if (name === "referenceerror")
166
+ return { category: "ReferenceError", severity: "critical" };
167
+ if (name === "rangeerror")
168
+ return { category: "RangeError", severity: "high" };
169
+ if (name === "syntaxerror")
170
+ return { category: "SyntaxError", severity: "high" };
152
171
  if (context === "unhandledrejection")
153
- return { errorType: "Unhandled promise rejection", severity: "medium" };
154
- if (context === "uncaughtexception")
155
- return { errorType: "Uncaught exception", severity: "high" };
172
+ return { category: "Promise Error", severity: "medium" };
156
173
  if (context === "express")
157
- return { errorType: "Route handler error", severity: "high" };
158
- return { errorType: "Uncaught exception", severity: "medium" };
159
- }
160
- function normalizeError(err) {
161
- if (err instanceof Error)
162
- return { name: err.name, message: err.message, stack: err.stack };
163
- if (typeof err === "string")
164
- return { name: "Error", message: err, stack: new Error(err).stack };
165
- if (err && typeof err === "object")
166
- return {
167
- name: err.name || err.code || "Error",
168
- message: err.message || err.reason || JSON.stringify(err),
169
- stack: err.stack || new Error(err.message).stack
170
- };
171
- return { name: "Error", message: "Unknown error", stack: new Error().stack };
172
- }
173
- async function send(payload) {
174
- try {
175
- if (payload.message?.includes("rapid-processor"))
176
- return;
177
- await fetch(ENDPOINT, {
178
- method: "POST",
179
- headers: {
180
- "Content-Type": "application/json",
181
- "x-api-key": _apiKey
182
- },
183
- body: JSON.stringify(payload)
184
- });
185
- } catch {
186
- }
174
+ return { category: "Server Error", severity: "high" };
175
+ if (context === "resource")
176
+ return { category: "Resource Error", severity: "low" };
177
+ return { category: "Unknown Error", severity: "medium" };
187
178
  }
188
179
  function buildErrorPayload(error, context) {
189
- const normalized = normalizeError(error);
190
- const { file, line, column } = parseStack(normalized.stack);
191
- const { errorType, severity } = classifyError(normalized, context);
180
+ const message = error?.message || String(error) || "Unknown error";
181
+ const stack = error?.stack || "";
182
+ const { file, line, column } = parseStack(stack);
183
+ const { category, severity } = classifyError(error, context);
192
184
  return {
193
185
  type: "ERROR",
194
- apiKey: _apiKey,
195
- message: normalized.message,
186
+ apiKey: _config?.apiKey,
187
+ message,
196
188
  code: getErrorCode(error),
197
- stack: normalized.stack || "",
189
+ stack,
198
190
  file,
199
191
  line,
200
192
  column,
@@ -202,166 +194,157 @@ function buildErrorPayload(error, context) {
202
194
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
203
195
  environment: getEnvironment(),
204
196
  browser: getBrowser(),
205
- error_category: errorType,
197
+ error_category: category,
206
198
  severity,
207
- status: "open"
199
+ status: "open",
200
+ context: context || "auto"
208
201
  };
209
202
  }
210
203
  function activateBrowserListeners() {
211
204
  window.addEventListener("error", (event) => {
212
- if (event.filename?.includes("rapid-processor"))
213
- return;
214
205
  const target = event.target;
215
- if (target && target.tagName) {
216
- const tag = target.tagName;
217
- const src = target.src || target.href || "";
218
- if (["IMG", "SCRIPT", "LINK", "VIDEO", "AUDIO", "SOURCE"].includes(tag)) {
219
- send(buildErrorPayload({
220
- name: "ResourceError",
221
- message: `${tag} failed to load: ${src}`,
222
- stack: `at ${window.location.href}`
223
- }));
224
- return;
225
- }
206
+ if (target && target.tagName && ["IMG", "SCRIPT", "LINK", "VIDEO", "AUDIO"].includes(target.tagName)) {
207
+ const src = target.src || target.href || "unknown";
208
+ enqueue(buildErrorPayload({ name: "ResourceError", message: `${target.tagName} failed to load: ${src}`, stack: "" }, "resource"));
209
+ return;
226
210
  }
227
211
  const err = event.error || {
228
212
  name: "Error",
229
213
  message: event.message,
230
- stack: `${event.message} at ${event.filename}:${event.lineno}:${event.colno}`
214
+ stack: `at ${event.filename}:${event.lineno}:${event.colno}`
231
215
  };
232
- send(buildErrorPayload(err));
216
+ enqueue(buildErrorPayload(err, "window"));
233
217
  }, true);
234
218
  window.addEventListener("unhandledrejection", (event) => {
235
- send(buildErrorPayload(event.reason || { message: "Unhandled Promise Rejection" }, "unhandledrejection"));
219
+ const err = event.reason instanceof Error ? event.reason : { name: "UnhandledRejection", message: String(event.reason || "Unhandled Promise Rejection"), stack: "" };
220
+ enqueue(buildErrorPayload(err, "unhandledrejection"));
236
221
  });
237
222
  const originalFetch = window.fetch;
238
- window.fetch = async function(input, init) {
239
- const url = typeof input === "string" ? input : input instanceof URL ? input.toString() : input.url;
240
- if (url.includes("rapid-processor") || url.includes("supabase.co/functions")) {
241
- return originalFetch.apply(this, arguments);
242
- }
223
+ window.fetch = async function(...args) {
224
+ const url = typeof args[0] === "string" ? args[0] : args[0] instanceof URL ? args[0].toString() : args[0]?.url ?? "";
225
+ if (url.includes("rapid-processor"))
226
+ return originalFetch(...args);
243
227
  try {
244
- const response = await originalFetch.apply(this, arguments);
228
+ const response = await originalFetch(...args);
245
229
  if (!response.ok) {
246
- send(buildErrorPayload({
247
- name: `API ${response.status} Error`,
248
- message: `HTTP ${response.status}: ${init?.method || "GET"} ${url}`,
249
- stack: `${init?.method || "GET"} ${url} \u2192 ${response.status} ${response.statusText}`,
230
+ enqueue(buildErrorPayload({
231
+ name: `HTTP_${response.status}`,
232
+ message: `HTTP ${response.status}: ${args[1]?.method || "GET"} ${url}`,
233
+ stack: `${args[1]?.method || "GET"} ${url} \u2192 ${response.status} ${response.statusText}`,
250
234
  status: response.status
251
- }));
235
+ }, "fetch"));
252
236
  }
253
237
  return response;
254
238
  } catch (err) {
255
- send(buildErrorPayload({
239
+ enqueue(buildErrorPayload({
256
240
  name: "FetchError",
257
- message: `Fetch failed: ${init?.method || "GET"} ${url} \u2014 ${err.message}`,
241
+ message: `Fetch failed: ${args[1]?.method || "GET"} ${url} \u2014 ${err.message}`,
258
242
  stack: err.stack
259
- }));
243
+ }, "fetch"));
260
244
  throw err;
261
245
  }
262
246
  };
263
247
  const originalOpen = XMLHttpRequest.prototype.open;
264
248
  const originalSend = XMLHttpRequest.prototype.send;
265
- XMLHttpRequest.prototype.open = function(method, url) {
249
+ XMLHttpRequest.prototype.open = function(method, url, ...rest) {
266
250
  this._r_method = method;
267
251
  this._r_url = url;
268
- return originalOpen.apply(this, arguments);
252
+ return originalOpen.call(this, method, url, ...rest);
269
253
  };
270
- XMLHttpRequest.prototype.send = function() {
271
- this.addEventListener("loadend", () => {
272
- const url = this._r_url || "";
273
- const method = this._r_method || "GET";
274
- if (url.includes("rapid-processor"))
275
- return;
276
- if (this.status >= 400 || this.status === 0) {
277
- send(buildErrorPayload({
278
- name: `XHR ${this.status} Error`,
279
- message: `XHR ${this.status}: ${method} ${url}`,
280
- stack: `${method} ${url} \u2192 ${this.status} ${this.statusText}`,
281
- status: this.status
282
- }));
283
- }
284
- });
285
- return originalSend.apply(this, arguments);
254
+ XMLHttpRequest.prototype.send = function(...args) {
255
+ const url = this._r_url || "";
256
+ const method = this._r_method || "GET";
257
+ if (!url.includes("rapid-processor")) {
258
+ this.addEventListener("loadend", () => {
259
+ if (this.status >= 400 || this.status === 0) {
260
+ enqueue(buildErrorPayload({
261
+ name: `XHR_${this.status}`,
262
+ message: `XHR ${this.status}: ${method} ${url}`,
263
+ stack: `${method} ${url} \u2192 ${this.status} ${this.statusText}`,
264
+ status: this.status
265
+ }, "xhr"));
266
+ }
267
+ });
268
+ }
269
+ return originalSend.apply(this, args);
286
270
  };
287
271
  window.addEventListener("beforeunload", () => {
288
272
  try {
289
- navigator.sendBeacon(ENDPOINT, JSON.stringify({
290
- type: "SDK_DISCONNECTED",
291
- apiKey: _apiKey,
292
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
293
- environment: "browser",
294
- url: getUrl()
295
- }));
273
+ navigator.sendBeacon(
274
+ ENDPOINT,
275
+ JSON.stringify({
276
+ type: "SDK_DISCONNECTED",
277
+ apiKey: _config?.apiKey,
278
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
279
+ environment: getEnvironment(),
280
+ url: getUrl()
281
+ })
282
+ );
296
283
  } catch {
297
284
  }
298
285
  });
299
286
  }
300
287
  function activateServerListeners() {
301
288
  process.on("uncaughtException", (error) => {
302
- send(buildErrorPayload(error, "uncaughtexception"));
289
+ enqueue(buildErrorPayload(error, "uncaughtException"));
290
+ flush();
303
291
  });
304
292
  process.on("unhandledRejection", (reason) => {
305
- send(buildErrorPayload(
293
+ enqueue(buildErrorPayload(
306
294
  reason instanceof Error ? reason : { name: "UnhandledRejection", message: String(reason), stack: "" },
307
295
  "unhandledrejection"
308
296
  ));
309
297
  });
310
- const shutdown = async () => {
311
- await send({
298
+ const shutdown = async (signal) => {
299
+ await sendNow({
312
300
  type: "SDK_DISCONNECTED",
313
- apiKey: _apiKey,
301
+ apiKey: _config?.apiKey,
314
302
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
315
- environment: "server",
316
- url: getUrl()
303
+ environment: getEnvironment(),
304
+ url: getUrl(),
305
+ signal
317
306
  });
318
307
  process.exit(0);
319
308
  };
320
- process.on("SIGTERM", shutdown);
321
- process.on("SIGINT", shutdown);
309
+ process.on("SIGTERM", () => shutdown("SIGTERM"));
310
+ process.on("SIGINT", () => shutdown("SIGINT"));
322
311
  }
323
312
  var Reportli = {
324
- init({ apiKey }) {
325
- if (!apiKey || _apiKey)
313
+ init(cfg) {
314
+ if (initialized)
326
315
  return;
327
- _apiKey = apiKey;
328
- if (isBrowser && typeof localStorage !== "undefined") {
329
- const key = `reportli_init_${apiKey}`;
330
- if (!localStorage.getItem(key)) {
331
- localStorage.setItem(key, "true");
332
- send({
333
- type: "SDK_INITIALIZED",
334
- apiKey: _apiKey,
335
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
336
- environment: getEnvironment(),
337
- url: getUrl(),
338
- browser: getBrowser()
339
- });
340
- }
341
- } else {
342
- send({
343
- type: "SDK_INITIALIZED",
344
- apiKey: _apiKey,
345
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
346
- environment: getEnvironment(),
347
- url: getUrl(),
348
- browser: getBrowser()
349
- });
350
- }
351
- if (isBrowser) {
316
+ if (!cfg?.apiKey)
317
+ return;
318
+ _config = cfg;
319
+ initialized = true;
320
+ sendImmediate({
321
+ type: "SDK_INITIALIZED",
322
+ apiKey: cfg.apiKey,
323
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
324
+ environment: getEnvironment(),
325
+ url: getUrl(),
326
+ browser: getBrowser()
327
+ });
328
+ if (typeof window !== "undefined") {
352
329
  activateBrowserListeners();
353
- } else if (isNode) {
330
+ } else if (typeof process !== "undefined" && process.versions?.node) {
354
331
  activateServerListeners();
355
332
  }
356
333
  },
357
334
  capture(error) {
358
- if (!_apiKey)
335
+ if (!initialized)
336
+ return;
337
+ const err = error instanceof Error ? error : { name: "ManualCapture", message: String(error), stack: new Error().stack };
338
+ enqueue(buildErrorPayload(err, "manual"));
339
+ },
340
+ captureMessage(message) {
341
+ if (!initialized)
359
342
  return;
360
- send(buildErrorPayload(error, "manual"));
343
+ enqueue(buildErrorPayload({ name: "Message", message, stack: "" }, "manual"));
361
344
  },
362
345
  errorHandler() {
363
346
  return function(err, _req, _res, next) {
364
- send(buildErrorPayload(err, "express"));
347
+ enqueue(buildErrorPayload(err, "express"));
365
348
  next(err);
366
349
  };
367
350
  }