@statoss/sdk 0.0.0-stage → 0.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.
Files changed (88) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +411 -2
  3. package/dist/cjs/client.d.ts +50 -0
  4. package/dist/cjs/client.js +462 -0
  5. package/dist/cjs/dsn.d.ts +25 -0
  6. package/dist/cjs/dsn.js +62 -0
  7. package/dist/cjs/envelope.d.ts +36 -0
  8. package/dist/cjs/envelope.js +55 -0
  9. package/dist/cjs/event.d.ts +9 -0
  10. package/dist/cjs/event.js +128 -0
  11. package/dist/cjs/hub.d.ts +37 -0
  12. package/dist/cjs/hub.js +119 -0
  13. package/dist/cjs/index.d.ts +38 -0
  14. package/dist/cjs/index.js +107 -0
  15. package/dist/cjs/integrations/browser.d.ts +7 -0
  16. package/dist/cjs/integrations/browser.js +124 -0
  17. package/dist/cjs/integrations/console.d.ts +3 -0
  18. package/dist/cjs/integrations/console.js +106 -0
  19. package/dist/cjs/integrations/dedupe.d.ts +7 -0
  20. package/dist/cjs/integrations/dedupe.js +32 -0
  21. package/dist/cjs/integrations/fetch.d.ts +3 -0
  22. package/dist/cjs/integrations/fetch.js +69 -0
  23. package/dist/cjs/integrations/handlers.d.ts +9 -0
  24. package/dist/cjs/integrations/handlers.js +192 -0
  25. package/dist/cjs/levels.d.ts +20 -0
  26. package/dist/cjs/levels.js +77 -0
  27. package/dist/cjs/logger.d.ts +18 -0
  28. package/dist/cjs/logger.js +38 -0
  29. package/dist/cjs/package.json +1 -0
  30. package/dist/cjs/ratelimit.d.ts +11 -0
  31. package/dist/cjs/ratelimit.js +50 -0
  32. package/dist/cjs/runtime.d.ts +42 -0
  33. package/dist/cjs/runtime.js +188 -0
  34. package/dist/cjs/scope.d.ts +30 -0
  35. package/dist/cjs/scope.js +127 -0
  36. package/dist/cjs/stack.d.ts +9 -0
  37. package/dist/cjs/stack.js +129 -0
  38. package/dist/cjs/transport.d.ts +40 -0
  39. package/dist/cjs/transport.js +218 -0
  40. package/dist/cjs/types.d.ts +180 -0
  41. package/dist/cjs/types.js +2 -0
  42. package/dist/cjs/utils.d.ts +27 -0
  43. package/dist/cjs/utils.js +227 -0
  44. package/dist/cjs/version.d.ts +3 -0
  45. package/dist/cjs/version.js +7 -0
  46. package/dist/esm/client.d.ts +50 -0
  47. package/dist/esm/client.js +458 -0
  48. package/dist/esm/dsn.d.ts +25 -0
  49. package/dist/esm/dsn.js +55 -0
  50. package/dist/esm/envelope.d.ts +36 -0
  51. package/dist/esm/envelope.js +49 -0
  52. package/dist/esm/event.d.ts +9 -0
  53. package/dist/esm/event.js +124 -0
  54. package/dist/esm/hub.d.ts +37 -0
  55. package/dist/esm/hub.js +111 -0
  56. package/dist/esm/index.d.ts +38 -0
  57. package/dist/esm/index.js +88 -0
  58. package/dist/esm/integrations/browser.d.ts +7 -0
  59. package/dist/esm/integrations/browser.js +119 -0
  60. package/dist/esm/integrations/console.d.ts +3 -0
  61. package/dist/esm/integrations/console.js +103 -0
  62. package/dist/esm/integrations/dedupe.d.ts +7 -0
  63. package/dist/esm/integrations/dedupe.js +29 -0
  64. package/dist/esm/integrations/fetch.d.ts +3 -0
  65. package/dist/esm/integrations/fetch.js +66 -0
  66. package/dist/esm/integrations/handlers.d.ts +9 -0
  67. package/dist/esm/integrations/handlers.js +188 -0
  68. package/dist/esm/levels.d.ts +20 -0
  69. package/dist/esm/levels.js +69 -0
  70. package/dist/esm/logger.d.ts +18 -0
  71. package/dist/esm/logger.js +33 -0
  72. package/dist/esm/ratelimit.d.ts +11 -0
  73. package/dist/esm/ratelimit.js +45 -0
  74. package/dist/esm/runtime.d.ts +42 -0
  75. package/dist/esm/runtime.js +181 -0
  76. package/dist/esm/scope.d.ts +30 -0
  77. package/dist/esm/scope.js +123 -0
  78. package/dist/esm/stack.d.ts +9 -0
  79. package/dist/esm/stack.js +125 -0
  80. package/dist/esm/transport.d.ts +40 -0
  81. package/dist/esm/transport.js +213 -0
  82. package/dist/esm/types.d.ts +180 -0
  83. package/dist/esm/types.js +1 -0
  84. package/dist/esm/utils.d.ts +27 -0
  85. package/dist/esm/utils.js +211 -0
  86. package/dist/esm/version.d.ts +3 -0
  87. package/dist/esm/version.js +4 -0
  88. package/package.json +48 -4
@@ -0,0 +1,181 @@
1
+ import { safely } from "./utils.js";
2
+ function g() {
3
+ return globalThis;
4
+ }
5
+ export function getProcess() {
6
+ const p = safely(() => g().process);
7
+ return p && typeof p === "object" ? p : undefined;
8
+ }
9
+ /** A Node built-in without a static import, so bundlers for the browser never see one. */
10
+ export function getBuiltin(id) {
11
+ return safely(() => {
12
+ const p = getProcess();
13
+ return p && typeof p.getBuiltinModule === "function"
14
+ ? p.getBuiltinModule(id)
15
+ : undefined;
16
+ });
17
+ }
18
+ export function detectRuntime() {
19
+ return (safely(() => {
20
+ const global = g();
21
+ const deno = global.Deno;
22
+ if (deno &&
23
+ typeof deno === "object" &&
24
+ typeof deno.version?.deno === "string")
25
+ return "deno";
26
+ const proc = getProcess();
27
+ if ((global.Bun && typeof global.Bun === "object") || proc?.versions?.bun)
28
+ return "bun";
29
+ const nav = global.navigator;
30
+ if (nav && nav.userAgent === "Cloudflare-Workers")
31
+ return "cloudflare";
32
+ if (typeof global.EdgeRuntime === "string")
33
+ return "vercel-edge";
34
+ if (global.window &&
35
+ typeof global.window === "object" &&
36
+ global.document &&
37
+ typeof global.document === "object") {
38
+ return "browser";
39
+ }
40
+ if (typeof global.WorkerGlobalScope === "function" &&
41
+ typeof global.importScripts === "function") {
42
+ return "worker";
43
+ }
44
+ if (proc?.versions?.node)
45
+ return "node";
46
+ return "unknown";
47
+ }) ?? "unknown");
48
+ }
49
+ const OS_NAMES = {
50
+ darwin: "macOS",
51
+ win32: "Windows",
52
+ windows: "Windows",
53
+ linux: "Linux",
54
+ freebsd: "FreeBSD",
55
+ openbsd: "OpenBSD",
56
+ android: "Android",
57
+ };
58
+ function compact(obj) {
59
+ const out = {};
60
+ for (const [k, v] of Object.entries(obj))
61
+ if (v !== undefined && v !== "")
62
+ out[k] = v;
63
+ return out;
64
+ }
65
+ /** Browser and OS from a user agent, for the common browsers only. */
66
+ export function parseUserAgent(ua) {
67
+ const out = {};
68
+ const browsers = [
69
+ [/Edg(?:e|A|iOS)?\/([\d.]+)/, "Edge"],
70
+ [/OPR\/([\d.]+)/, "Opera"],
71
+ [/SamsungBrowser\/([\d.]+)/, "Samsung Internet"],
72
+ [/(?:Firefox|FxiOS)\/([\d.]+)/, "Firefox"],
73
+ [/(?:Chrome|CriOS|HeadlessChrome)\/([\d.]+)/, "Chrome"],
74
+ [/Version\/([\d.]+).*Safari\//, "Safari"],
75
+ ];
76
+ for (const [re, name] of browsers) {
77
+ const m = re.exec(ua);
78
+ if (m) {
79
+ out.browser = { name, version: m[1] };
80
+ break;
81
+ }
82
+ }
83
+ let m;
84
+ if ((m = /Windows NT ([\d.]+)/.exec(ua)))
85
+ out.os = { name: "Windows", version: m[1] };
86
+ else if ((m = /(?:iPhone|iPad|iPod).*? OS ([\d_]+)/.exec(ua)))
87
+ out.os = { name: "iOS", version: m[1].replace(/_/g, ".") };
88
+ else if ((m = /Mac OS X ([\d_.]+)/.exec(ua)))
89
+ out.os = { name: "macOS", version: m[1].replace(/_/g, ".") };
90
+ else if ((m = /Android ([\d.]+)/.exec(ua)))
91
+ out.os = { name: "Android", version: m[1] };
92
+ else if (/CrOS/.test(ua))
93
+ out.os = { name: "Chrome OS" };
94
+ else if (/Linux/.test(ua))
95
+ out.os = { name: "Linux" };
96
+ return out;
97
+ }
98
+ function nodeLike(name) {
99
+ const proc = getProcess();
100
+ const os = getBuiltin("node:os");
101
+ const bun = g().Bun;
102
+ const runtime = compact({
103
+ name,
104
+ version: name === "bun" ? (bun?.version ?? proc?.versions?.bun) : proc?.version,
105
+ });
106
+ const osContext = compact({
107
+ name: OS_NAMES[proc?.platform ?? ""] ?? proc?.platform,
108
+ kernel_version: safely(() => os?.release?.()),
109
+ });
110
+ const device = compact({
111
+ arch: proc?.arch,
112
+ memory_size: safely(() => os?.totalmem?.()),
113
+ processor_count: safely(() => os?.availableParallelism?.() ?? os?.cpus?.().length),
114
+ });
115
+ return {
116
+ contexts: { runtime, os: osContext, device },
117
+ serverName: safely(() => os?.hostname?.()),
118
+ };
119
+ }
120
+ function deno() {
121
+ const d = g().Deno;
122
+ // Only when already allowed: asking for sys access would prompt the user.
123
+ const serverName = safely(() => d.permissions?.querySync?.({ name: "sys", kind: "hostname" }).state ===
124
+ "granted"
125
+ ? d.hostname?.()
126
+ : undefined);
127
+ return {
128
+ contexts: {
129
+ runtime: compact({ name: "deno", version: d.version?.deno }),
130
+ os: compact({ name: OS_NAMES[d.build?.os ?? ""] ?? d.build?.os }),
131
+ device: compact({ arch: d.build?.arch }),
132
+ },
133
+ serverName,
134
+ };
135
+ }
136
+ function browser(name) {
137
+ const global = g();
138
+ const ua = safely(() => global.navigator?.userAgent) ?? "";
139
+ const parsed = typeof ua === "string" ? parseUserAgent(ua) : {};
140
+ const contexts = {};
141
+ if (parsed.browser)
142
+ contexts.browser = parsed.browser;
143
+ if (parsed.os)
144
+ contexts.os = compact(parsed.os);
145
+ if (name === "browser") {
146
+ const screen = global.screen;
147
+ const device = compact({
148
+ screen_width_pixels: screen?.width,
149
+ screen_height_pixels: screen?.height,
150
+ screen_density: global.devicePixelRatio,
151
+ });
152
+ if (Object.keys(device).length)
153
+ contexts.device = device;
154
+ }
155
+ return { contexts };
156
+ }
157
+ export function describeRuntime(name = detectRuntime()) {
158
+ const base = {
159
+ name,
160
+ platform: name === "node" ? "node" : "javascript",
161
+ browserLike: name === "browser" || name === "worker",
162
+ };
163
+ const details = safely(() => {
164
+ switch (name) {
165
+ case "node":
166
+ case "bun":
167
+ return nodeLike(name);
168
+ case "deno":
169
+ return deno();
170
+ case "browser":
171
+ case "worker":
172
+ return browser(name);
173
+ case "cloudflare":
174
+ case "vercel-edge":
175
+ return { contexts: { runtime: { name } } };
176
+ default:
177
+ return { contexts: {} };
178
+ }
179
+ }) ?? { contexts: {} };
180
+ return { ...base, ...details };
181
+ }
@@ -0,0 +1,30 @@
1
+ import type { Breadcrumb, CaptureContext, Event, Level, Primitive, User } from "./types.js";
2
+ export declare const MAX_BREADCRUMBS = 100;
3
+ /**
4
+ * What is attached to the events captured while it is current: user, tags,
5
+ * extra, contexts, level, fingerprint and breadcrumbs.
6
+ */
7
+ export declare class Scope {
8
+ clone(): Scope;
9
+ /** Like captureException, with this scope whatever is current. Returns the event id. */
10
+ captureException(error: unknown, context?: CaptureContext): string;
11
+ /** Like captureMessage, with this scope whatever is current. Returns the event id. */
12
+ captureMessage(message: string, levelOrContext?: Level | CaptureContext): string;
13
+ /** Like captureEvent, with this scope whatever is current. Returns the event id. */
14
+ captureEvent(event: Event, context?: CaptureContext): string;
15
+ /** Pass null to forget the user. */
16
+ setUser(user: User | null): this;
17
+ setTag(key: string, value: Primitive): this;
18
+ setTags(tags: Record<string, Primitive>): this;
19
+ setExtra(key: string, value: unknown): this;
20
+ setExtras(extras: Record<string, unknown>): this;
21
+ /** Pass null to remove the context. */
22
+ setContext(name: string, context: Record<string, unknown> | null): this;
23
+ /** A Sentry level or one of your own names; overrides the level of events captured with this scope. */
24
+ setLevel(level: Level | undefined): this;
25
+ setFingerprint(fingerprint: string[] | undefined): this;
26
+ /** Adds a breadcrumb to this scope only, without `beforeBreadcrumb`, as Sentry's scope does. */
27
+ addBreadcrumb(breadcrumb: Breadcrumb): this;
28
+ clearBreadcrumbs(): this;
29
+ clear(): this;
30
+ }
@@ -0,0 +1,123 @@
1
+ // hub imports this module too; the calls into it happen only at capture time.
2
+ import { captureWith, messageContext } from "./hub.js";
3
+ import { now } from "./utils.js";
4
+ export const MAX_BREADCRUMBS = 100;
5
+ /**
6
+ * What is attached to the events captured while it is current: user, tags,
7
+ * extra, contexts, level, fingerprint and breadcrumbs.
8
+ */
9
+ export class Scope {
10
+ constructor() {
11
+ /** @internal */ this._tags = {};
12
+ /** @internal */ this._extra = {};
13
+ /** @internal */ this._contexts = {};
14
+ /** @internal */ this._breadcrumbs = [];
15
+ /** @internal */ this._maxBreadcrumbs = MAX_BREADCRUMBS;
16
+ }
17
+ clone() {
18
+ const scope = new Scope();
19
+ scope._user = this._user ? { ...this._user } : undefined;
20
+ scope._tags = { ...this._tags };
21
+ scope._extra = { ...this._extra };
22
+ scope._contexts = { ...this._contexts };
23
+ scope._level = this._level;
24
+ scope._fingerprint = this._fingerprint ? [...this._fingerprint] : undefined;
25
+ scope._breadcrumbs = [...this._breadcrumbs];
26
+ scope._maxBreadcrumbs = this._maxBreadcrumbs;
27
+ return scope;
28
+ }
29
+ /** Like captureException, with this scope whatever is current. Returns the event id. */
30
+ captureException(error, context) {
31
+ return captureWith(this, (client, scope) => client.captureException(error, context, scope));
32
+ }
33
+ /** Like captureMessage, with this scope whatever is current. Returns the event id. */
34
+ captureMessage(message, levelOrContext) {
35
+ return captureWith(this, (client, scope) => client.captureMessage(message, messageContext(levelOrContext), scope));
36
+ }
37
+ /** Like captureEvent, with this scope whatever is current. Returns the event id. */
38
+ captureEvent(event, context) {
39
+ return captureWith(this, (client, scope) => client.captureEvent(event, context, scope));
40
+ }
41
+ /** Pass null to forget the user. */
42
+ setUser(user) {
43
+ this._user = user ? { ...user } : undefined;
44
+ return this;
45
+ }
46
+ setTag(key, value) {
47
+ this._tags[key] = value;
48
+ return this;
49
+ }
50
+ setTags(tags) {
51
+ Object.assign(this._tags, tags);
52
+ return this;
53
+ }
54
+ setExtra(key, value) {
55
+ this._extra[key] = value;
56
+ return this;
57
+ }
58
+ setExtras(extras) {
59
+ Object.assign(this._extra, extras);
60
+ return this;
61
+ }
62
+ /** Pass null to remove the context. */
63
+ setContext(name, context) {
64
+ if (context === null || typeof context !== "object")
65
+ delete this._contexts[name];
66
+ else
67
+ this._contexts[name] = context;
68
+ return this;
69
+ }
70
+ /** A Sentry level or one of your own names; overrides the level of events captured with this scope. */
71
+ setLevel(level) {
72
+ this._level = level;
73
+ return this;
74
+ }
75
+ setFingerprint(fingerprint) {
76
+ this._fingerprint = fingerprint ? [...fingerprint] : undefined;
77
+ return this;
78
+ }
79
+ /** Adds a breadcrumb to this scope only, without `beforeBreadcrumb`, as Sentry's scope does. */
80
+ addBreadcrumb(breadcrumb) {
81
+ const crumb = { ...breadcrumb, timestamp: breadcrumb.timestamp ?? now() };
82
+ this._breadcrumbs.push(crumb);
83
+ if (this._breadcrumbs.length > this._maxBreadcrumbs) {
84
+ this._breadcrumbs.splice(0, this._breadcrumbs.length - this._maxBreadcrumbs);
85
+ }
86
+ return this;
87
+ }
88
+ clearBreadcrumbs() {
89
+ this._breadcrumbs = [];
90
+ return this;
91
+ }
92
+ clear() {
93
+ this._user = undefined;
94
+ this._tags = {};
95
+ this._extra = {};
96
+ this._contexts = {};
97
+ this._level = undefined;
98
+ this._fingerprint = undefined;
99
+ this._breadcrumbs = [];
100
+ return this;
101
+ }
102
+ /** @internal */
103
+ _apply(data) {
104
+ if (!data || typeof data !== "object")
105
+ return this;
106
+ if (data.user)
107
+ this.setUser(data.user);
108
+ if (data.tags)
109
+ this.setTags(data.tags);
110
+ if (data.extra)
111
+ this.setExtras(data.extra);
112
+ if (data.contexts) {
113
+ for (const [name, context] of Object.entries(data.contexts)) {
114
+ this.setContext(name, context);
115
+ }
116
+ }
117
+ if (data.level !== undefined)
118
+ this.setLevel(data.level);
119
+ if (data.fingerprint)
120
+ this.setFingerprint(data.fingerprint);
121
+ return this;
122
+ }
123
+ }
@@ -0,0 +1,9 @@
1
+ import type { StackFrame } from "./types.js";
2
+ /**
3
+ * Parses a stack string from V8 (Chrome, Edge, Node, Deno, Bun, workers),
4
+ * SpiderMonkey (Firefox) or JavaScriptCore (Safari) into Sentry frames,
5
+ * oldest first, keeping the 50 closest to the throw.
6
+ */
7
+ export declare function parseStack(stack: unknown): StackFrame[];
8
+ /** A frame for a bare location, such as a browser error event's file and line. */
9
+ export declare function frameAt(location: string, line?: number, column?: number): StackFrame | undefined;
@@ -0,0 +1,125 @@
1
+ const MAX_FRAMES = 50;
2
+ const MAX_LINE = 1024;
3
+ const UNKNOWN_FUNCTION = "?";
4
+ const V8_LINE = /^\s*at /;
5
+ // Frames from dependencies, runtimes, browser extensions and this SDK.
6
+ const NOT_IN_APP = new RegExp([
7
+ String.raw `(?:^|[/\\])node_modules[/\\]`,
8
+ String.raw `^(?:node|ext|internal|native|chrome|resource|bun):`,
9
+ String.raw `^internal[/\\]`,
10
+ String.raw `^(?:native|unknown|<anonymous>|\[native code\])$`,
11
+ String.raw `^(?:chrome|moz|safari|safari-web|ms-browser)-extension:`,
12
+ String.raw `^webkit-masked-url:`,
13
+ String.raw `[/\\]@statoss[/\\]sdk(?:[/\\@]|$)`,
14
+ String.raw `[/\\]registry\.npmjs\.org[/\\]`,
15
+ String.raw `^https?:\/\/(?:jsr\.io|deno\.land|esm\.sh|unpkg\.com|cdn\.jsdelivr\.net|cdn\.skypack\.dev)\/`,
16
+ ].join("|"), "i");
17
+ /**
18
+ * Parses a stack string from V8 (Chrome, Edge, Node, Deno, Bun, workers),
19
+ * SpiderMonkey (Firefox) or JavaScriptCore (Safari) into Sentry frames,
20
+ * oldest first, keeping the 50 closest to the throw.
21
+ */
22
+ export function parseStack(stack) {
23
+ if (typeof stack !== "string" || stack === "")
24
+ return [];
25
+ const lines = stack.split("\n");
26
+ const v8 = lines.some((line) => V8_LINE.test(line));
27
+ const frames = [];
28
+ for (const line of lines) {
29
+ if (frames.length >= MAX_FRAMES)
30
+ break;
31
+ if (line.length > MAX_LINE)
32
+ continue;
33
+ const frame = v8 ? parseV8Line(line) : parseGeckoLine(line);
34
+ if (frame)
35
+ frames.push(frame);
36
+ }
37
+ return frames.reverse();
38
+ }
39
+ // " at fn (location)", " at location", " at async fn (location)"
40
+ function parseV8Line(line) {
41
+ const m = /^\s*at (?:async )?(.*)$/.exec(line);
42
+ if (!m)
43
+ return undefined;
44
+ const rest = m[1].trim();
45
+ let fn;
46
+ let location = rest;
47
+ if (rest.endsWith(")")) {
48
+ const open = rest.indexOf(" (");
49
+ if (open > 0) {
50
+ fn = rest.slice(0, open);
51
+ location = rest.slice(open + 2, -1);
52
+ }
53
+ }
54
+ if (location.startsWith("eval at ")) {
55
+ // The frame ran in eval'd code: point at the call site that made it.
56
+ const origin = /\((\S+?):(\d+):(\d+)\)/.exec(location);
57
+ if (origin)
58
+ return makeFrame(fn, origin[1], origin[2], origin[3]);
59
+ }
60
+ const at = /^(.*?):(\d+)(?::(\d+))?$/.exec(location);
61
+ return at ? makeFrame(fn, at[1], at[2], at[3]) : makeFrame(fn, location);
62
+ }
63
+ // "fn@location" (Firefox, Safari); "async*fn@...", "async fn@...", "@location"
64
+ function parseGeckoLine(line) {
65
+ const at = line.indexOf("@");
66
+ if (at < 0)
67
+ return undefined;
68
+ let fn = line.slice(0, at).trim();
69
+ const location = line.slice(at + 1).trim();
70
+ if (!location)
71
+ return undefined;
72
+ const star = fn.lastIndexOf("*");
73
+ if (star >= 0)
74
+ fn = fn.slice(star + 1);
75
+ if (fn.startsWith("async "))
76
+ fn = fn.slice(6);
77
+ if (location === "[native code]")
78
+ return makeFrame(fn, location);
79
+ // "url line 28 > eval:1:29": code run by eval or new Function, at line 28 of url.
80
+ const evalled = /^(\S+) line (\d+) > /.exec(location);
81
+ if (evalled)
82
+ return makeFrame(fn || "eval", evalled[1], evalled[2]);
83
+ const m = /^(.*?):(\d+)(?::(\d+))?$/.exec(location);
84
+ return m ? makeFrame(fn, m[1], m[2], m[3]) : undefined;
85
+ }
86
+ /** A frame for a bare location, such as a browser error event's file and line. */
87
+ export function frameAt(location, line, column) {
88
+ return makeFrame(undefined, location, line?.toString(), column?.toString());
89
+ }
90
+ function makeFrame(fn, location, line, column) {
91
+ if (!location)
92
+ return undefined;
93
+ let filename = location;
94
+ let absPath = location;
95
+ if (/^https?:\/\//i.test(location)) {
96
+ filename =
97
+ location.replace(/^https?:\/\/[^/]*/i, "").replace(/[?#].*$/, "") || "/";
98
+ }
99
+ else if (location.startsWith("file://")) {
100
+ const path = location.replace(/^file:\/\//, "");
101
+ filename = safeDecode(path);
102
+ absPath = filename;
103
+ }
104
+ const lineno = line ? parseInt(line, 10) || undefined : undefined;
105
+ const colno = column ? parseInt(column, 10) || undefined : undefined;
106
+ const frame = {
107
+ filename,
108
+ abs_path: absPath,
109
+ function: !fn || fn === "<anonymous>" ? UNKNOWN_FUNCTION : fn,
110
+ };
111
+ if (lineno !== undefined)
112
+ frame.lineno = lineno;
113
+ if (colno !== undefined)
114
+ frame.colno = colno;
115
+ frame.in_app = lineno !== undefined && !NOT_IN_APP.test(absPath);
116
+ return frame;
117
+ }
118
+ function safeDecode(path) {
119
+ try {
120
+ return decodeURI(path);
121
+ }
122
+ catch {
123
+ return path;
124
+ }
125
+ }
@@ -0,0 +1,40 @@
1
+ import { type Envelope } from "./envelope.js";
2
+ import type { Logger } from "./logger.js";
3
+ import type { Transport } from "./types.js";
4
+ export declare const QUEUE_LIMIT = 30;
5
+ export declare const CONCURRENCY = 5;
6
+ /** The default transport: fetch, called on globalThis (Workers refuse any other this). */
7
+ export declare function fetchTransport(browserLike: boolean): Transport;
8
+ export type RecordLoss = (reason: string, category: string, quantity?: number) => void;
9
+ export interface SenderOptions {
10
+ url: string;
11
+ headers: Record<string, string>;
12
+ browserLike: boolean;
13
+ transport: Transport;
14
+ recordLoss: RecordLoss;
15
+ logger: Logger;
16
+ }
17
+ /**
18
+ * Sends envelopes in order of arrival, a few at a time, keeping at most 30
19
+ * waiting or in flight. Whatever cannot be sent is counted for client reports.
20
+ */
21
+ export declare class Sender {
22
+ private readonly options;
23
+ private readonly queue;
24
+ private active;
25
+ private limits;
26
+ private waiters;
27
+ private keepaliveBytes;
28
+ private keepaliveCount;
29
+ constructor(options: SenderOptions);
30
+ send(envelope: Envelope): void;
31
+ /** Resolves true once nothing waits or is in flight, false if timeoutMs passes first. */
32
+ flush(timeoutMs: number): Promise<boolean>;
33
+ private idle;
34
+ private notify;
35
+ /** Drops the items whose category is rate limited; undefined when none is left. */
36
+ private withoutLimited;
37
+ private pump;
38
+ private deliver;
39
+ private lose;
40
+ }