@xrayradar/core 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.
- package/dist/index.d.mts +146 -0
- package/dist/index.d.ts +146 -0
- package/dist/index.js +213 -0
- package/dist/index.mjs +179 -0
- package/package.json +1 -0
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Event severity levels (aligned with server and Python SDK).
|
|
3
|
+
*/
|
|
4
|
+
type Level = "fatal" | "error" | "warning" | "info" | "debug";
|
|
5
|
+
/**
|
|
6
|
+
* Breadcrumb type hint.
|
|
7
|
+
*/
|
|
8
|
+
type BreadcrumbType = "default" | "http" | "navigation" | "ui" | "console" | "error" | "query" | "user";
|
|
9
|
+
interface BreadcrumbData {
|
|
10
|
+
timestamp: string;
|
|
11
|
+
message: string;
|
|
12
|
+
category?: string;
|
|
13
|
+
level?: Level;
|
|
14
|
+
data?: Record<string, unknown>;
|
|
15
|
+
type?: BreadcrumbType;
|
|
16
|
+
}
|
|
17
|
+
interface UserContext {
|
|
18
|
+
id?: string;
|
|
19
|
+
username?: string;
|
|
20
|
+
email?: string;
|
|
21
|
+
ip_address?: string;
|
|
22
|
+
data?: Record<string, unknown>;
|
|
23
|
+
}
|
|
24
|
+
interface RequestContext {
|
|
25
|
+
url?: string;
|
|
26
|
+
method?: string;
|
|
27
|
+
headers?: Record<string, string>;
|
|
28
|
+
query_string?: string;
|
|
29
|
+
data?: string;
|
|
30
|
+
env?: Record<string, string>;
|
|
31
|
+
}
|
|
32
|
+
interface EventContexts {
|
|
33
|
+
user?: UserContext | null;
|
|
34
|
+
request?: RequestContext | null;
|
|
35
|
+
tags?: Record<string, string>;
|
|
36
|
+
extra?: Record<string, unknown>;
|
|
37
|
+
server_name?: string;
|
|
38
|
+
release?: string;
|
|
39
|
+
environment?: string;
|
|
40
|
+
}
|
|
41
|
+
interface StackFrame {
|
|
42
|
+
filename: string;
|
|
43
|
+
function: string;
|
|
44
|
+
lineno: number;
|
|
45
|
+
colno?: number;
|
|
46
|
+
abs_path?: string;
|
|
47
|
+
context_line?: string;
|
|
48
|
+
pre_context?: string[];
|
|
49
|
+
post_context?: string[];
|
|
50
|
+
in_app?: boolean;
|
|
51
|
+
}
|
|
52
|
+
interface ExceptionValue {
|
|
53
|
+
type: string;
|
|
54
|
+
value: string;
|
|
55
|
+
module?: string;
|
|
56
|
+
stacktrace?: {
|
|
57
|
+
frames: StackFrame[];
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
interface EventException {
|
|
61
|
+
values: ExceptionValue[];
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Event payload sent to POST /api/{project_id}/store/
|
|
65
|
+
*/
|
|
66
|
+
interface EventPayload {
|
|
67
|
+
event_id: string;
|
|
68
|
+
timestamp: string;
|
|
69
|
+
level: Level;
|
|
70
|
+
message: string;
|
|
71
|
+
platform: string;
|
|
72
|
+
sdk: {
|
|
73
|
+
name: string;
|
|
74
|
+
version: string;
|
|
75
|
+
};
|
|
76
|
+
contexts: EventContexts;
|
|
77
|
+
breadcrumbs: BreadcrumbData[];
|
|
78
|
+
fingerprint?: string[];
|
|
79
|
+
exception?: EventException;
|
|
80
|
+
modules?: Record<string, string>;
|
|
81
|
+
}
|
|
82
|
+
interface Transport {
|
|
83
|
+
sendEvent(event: EventPayload): void | Promise<void>;
|
|
84
|
+
flush?(timeout?: number): void | Promise<void>;
|
|
85
|
+
close?(): void | Promise<void>;
|
|
86
|
+
}
|
|
87
|
+
interface ClientOptions {
|
|
88
|
+
dsn?: string;
|
|
89
|
+
authToken?: string;
|
|
90
|
+
debug?: boolean;
|
|
91
|
+
environment?: string;
|
|
92
|
+
release?: string;
|
|
93
|
+
serverName?: string;
|
|
94
|
+
sampleRate?: number;
|
|
95
|
+
maxBreadcrumbs?: number;
|
|
96
|
+
beforeSend?: (event: EventPayload) => EventPayload | null | Promise<EventPayload | null>;
|
|
97
|
+
transport?: Transport;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
declare class Scope {
|
|
101
|
+
private _breadcrumbs;
|
|
102
|
+
private _context;
|
|
103
|
+
maxBreadcrumbs: number;
|
|
104
|
+
addBreadcrumb(message: string, options?: {
|
|
105
|
+
category?: string;
|
|
106
|
+
level?: Level;
|
|
107
|
+
data?: Record<string, unknown>;
|
|
108
|
+
type?: string;
|
|
109
|
+
timestamp?: string;
|
|
110
|
+
}): void;
|
|
111
|
+
clearBreadcrumbs(): void;
|
|
112
|
+
getBreadcrumbs(): BreadcrumbData[];
|
|
113
|
+
setUser(user: UserContext | null): void;
|
|
114
|
+
setTag(key: string, value: string): void;
|
|
115
|
+
setExtra(key: string, value: unknown): void;
|
|
116
|
+
setRequest(request: RequestContext | null): void;
|
|
117
|
+
setContext(key: string, data: Record<string, unknown>): void;
|
|
118
|
+
getContext(): EventContexts;
|
|
119
|
+
applyToContext(overrides: Partial<EventContexts>): void;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Build event payload from an Error. Server can compute fingerprint if not provided.
|
|
124
|
+
*/
|
|
125
|
+
declare function eventFromException(error: Error, level: Level, message?: string, scope?: Scope): EventPayload;
|
|
126
|
+
/**
|
|
127
|
+
* Build event payload from a message (no exception).
|
|
128
|
+
*/
|
|
129
|
+
declare function eventFromMessage(message: string, level: Level, scope?: Scope): EventPayload;
|
|
130
|
+
/**
|
|
131
|
+
* Check if level string is valid.
|
|
132
|
+
*/
|
|
133
|
+
declare function normalizeLevel(level: string): Level;
|
|
134
|
+
/**
|
|
135
|
+
* Apply sampleRate: return true if event should be sent (random < sampleRate).
|
|
136
|
+
*/
|
|
137
|
+
declare function shouldSample(sampleRate: number): boolean;
|
|
138
|
+
|
|
139
|
+
declare const SDK_NAME = "xrayradar.javascript";
|
|
140
|
+
declare const SDK_VERSION = "0.1.0";
|
|
141
|
+
declare function getSdkInfo(): {
|
|
142
|
+
name: string;
|
|
143
|
+
version: string;
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
export { type BreadcrumbData, type BreadcrumbType, type ClientOptions, type EventContexts, type EventException, type EventPayload, type ExceptionValue, type Level, type RequestContext, SDK_NAME, SDK_VERSION, Scope, type StackFrame, type Transport, type UserContext, eventFromException, eventFromMessage, getSdkInfo, normalizeLevel, shouldSample };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Event severity levels (aligned with server and Python SDK).
|
|
3
|
+
*/
|
|
4
|
+
type Level = "fatal" | "error" | "warning" | "info" | "debug";
|
|
5
|
+
/**
|
|
6
|
+
* Breadcrumb type hint.
|
|
7
|
+
*/
|
|
8
|
+
type BreadcrumbType = "default" | "http" | "navigation" | "ui" | "console" | "error" | "query" | "user";
|
|
9
|
+
interface BreadcrumbData {
|
|
10
|
+
timestamp: string;
|
|
11
|
+
message: string;
|
|
12
|
+
category?: string;
|
|
13
|
+
level?: Level;
|
|
14
|
+
data?: Record<string, unknown>;
|
|
15
|
+
type?: BreadcrumbType;
|
|
16
|
+
}
|
|
17
|
+
interface UserContext {
|
|
18
|
+
id?: string;
|
|
19
|
+
username?: string;
|
|
20
|
+
email?: string;
|
|
21
|
+
ip_address?: string;
|
|
22
|
+
data?: Record<string, unknown>;
|
|
23
|
+
}
|
|
24
|
+
interface RequestContext {
|
|
25
|
+
url?: string;
|
|
26
|
+
method?: string;
|
|
27
|
+
headers?: Record<string, string>;
|
|
28
|
+
query_string?: string;
|
|
29
|
+
data?: string;
|
|
30
|
+
env?: Record<string, string>;
|
|
31
|
+
}
|
|
32
|
+
interface EventContexts {
|
|
33
|
+
user?: UserContext | null;
|
|
34
|
+
request?: RequestContext | null;
|
|
35
|
+
tags?: Record<string, string>;
|
|
36
|
+
extra?: Record<string, unknown>;
|
|
37
|
+
server_name?: string;
|
|
38
|
+
release?: string;
|
|
39
|
+
environment?: string;
|
|
40
|
+
}
|
|
41
|
+
interface StackFrame {
|
|
42
|
+
filename: string;
|
|
43
|
+
function: string;
|
|
44
|
+
lineno: number;
|
|
45
|
+
colno?: number;
|
|
46
|
+
abs_path?: string;
|
|
47
|
+
context_line?: string;
|
|
48
|
+
pre_context?: string[];
|
|
49
|
+
post_context?: string[];
|
|
50
|
+
in_app?: boolean;
|
|
51
|
+
}
|
|
52
|
+
interface ExceptionValue {
|
|
53
|
+
type: string;
|
|
54
|
+
value: string;
|
|
55
|
+
module?: string;
|
|
56
|
+
stacktrace?: {
|
|
57
|
+
frames: StackFrame[];
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
interface EventException {
|
|
61
|
+
values: ExceptionValue[];
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Event payload sent to POST /api/{project_id}/store/
|
|
65
|
+
*/
|
|
66
|
+
interface EventPayload {
|
|
67
|
+
event_id: string;
|
|
68
|
+
timestamp: string;
|
|
69
|
+
level: Level;
|
|
70
|
+
message: string;
|
|
71
|
+
platform: string;
|
|
72
|
+
sdk: {
|
|
73
|
+
name: string;
|
|
74
|
+
version: string;
|
|
75
|
+
};
|
|
76
|
+
contexts: EventContexts;
|
|
77
|
+
breadcrumbs: BreadcrumbData[];
|
|
78
|
+
fingerprint?: string[];
|
|
79
|
+
exception?: EventException;
|
|
80
|
+
modules?: Record<string, string>;
|
|
81
|
+
}
|
|
82
|
+
interface Transport {
|
|
83
|
+
sendEvent(event: EventPayload): void | Promise<void>;
|
|
84
|
+
flush?(timeout?: number): void | Promise<void>;
|
|
85
|
+
close?(): void | Promise<void>;
|
|
86
|
+
}
|
|
87
|
+
interface ClientOptions {
|
|
88
|
+
dsn?: string;
|
|
89
|
+
authToken?: string;
|
|
90
|
+
debug?: boolean;
|
|
91
|
+
environment?: string;
|
|
92
|
+
release?: string;
|
|
93
|
+
serverName?: string;
|
|
94
|
+
sampleRate?: number;
|
|
95
|
+
maxBreadcrumbs?: number;
|
|
96
|
+
beforeSend?: (event: EventPayload) => EventPayload | null | Promise<EventPayload | null>;
|
|
97
|
+
transport?: Transport;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
declare class Scope {
|
|
101
|
+
private _breadcrumbs;
|
|
102
|
+
private _context;
|
|
103
|
+
maxBreadcrumbs: number;
|
|
104
|
+
addBreadcrumb(message: string, options?: {
|
|
105
|
+
category?: string;
|
|
106
|
+
level?: Level;
|
|
107
|
+
data?: Record<string, unknown>;
|
|
108
|
+
type?: string;
|
|
109
|
+
timestamp?: string;
|
|
110
|
+
}): void;
|
|
111
|
+
clearBreadcrumbs(): void;
|
|
112
|
+
getBreadcrumbs(): BreadcrumbData[];
|
|
113
|
+
setUser(user: UserContext | null): void;
|
|
114
|
+
setTag(key: string, value: string): void;
|
|
115
|
+
setExtra(key: string, value: unknown): void;
|
|
116
|
+
setRequest(request: RequestContext | null): void;
|
|
117
|
+
setContext(key: string, data: Record<string, unknown>): void;
|
|
118
|
+
getContext(): EventContexts;
|
|
119
|
+
applyToContext(overrides: Partial<EventContexts>): void;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Build event payload from an Error. Server can compute fingerprint if not provided.
|
|
124
|
+
*/
|
|
125
|
+
declare function eventFromException(error: Error, level: Level, message?: string, scope?: Scope): EventPayload;
|
|
126
|
+
/**
|
|
127
|
+
* Build event payload from a message (no exception).
|
|
128
|
+
*/
|
|
129
|
+
declare function eventFromMessage(message: string, level: Level, scope?: Scope): EventPayload;
|
|
130
|
+
/**
|
|
131
|
+
* Check if level string is valid.
|
|
132
|
+
*/
|
|
133
|
+
declare function normalizeLevel(level: string): Level;
|
|
134
|
+
/**
|
|
135
|
+
* Apply sampleRate: return true if event should be sent (random < sampleRate).
|
|
136
|
+
*/
|
|
137
|
+
declare function shouldSample(sampleRate: number): boolean;
|
|
138
|
+
|
|
139
|
+
declare const SDK_NAME = "xrayradar.javascript";
|
|
140
|
+
declare const SDK_VERSION = "0.1.0";
|
|
141
|
+
declare function getSdkInfo(): {
|
|
142
|
+
name: string;
|
|
143
|
+
version: string;
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
export { type BreadcrumbData, type BreadcrumbType, type ClientOptions, type EventContexts, type EventException, type EventPayload, type ExceptionValue, type Level, type RequestContext, SDK_NAME, SDK_VERSION, Scope, type StackFrame, type Transport, type UserContext, eventFromException, eventFromMessage, getSdkInfo, normalizeLevel, shouldSample };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
SDK_NAME: () => SDK_NAME,
|
|
24
|
+
SDK_VERSION: () => SDK_VERSION,
|
|
25
|
+
Scope: () => Scope,
|
|
26
|
+
eventFromException: () => eventFromException,
|
|
27
|
+
eventFromMessage: () => eventFromMessage,
|
|
28
|
+
getSdkInfo: () => getSdkInfo,
|
|
29
|
+
normalizeLevel: () => normalizeLevel,
|
|
30
|
+
shouldSample: () => shouldSample
|
|
31
|
+
});
|
|
32
|
+
module.exports = __toCommonJS(index_exports);
|
|
33
|
+
|
|
34
|
+
// src/scope.ts
|
|
35
|
+
var DEFAULT_MAX_BREADCRUMBS = 100;
|
|
36
|
+
var Scope = class {
|
|
37
|
+
constructor() {
|
|
38
|
+
this._breadcrumbs = [];
|
|
39
|
+
this._context = {
|
|
40
|
+
tags: {},
|
|
41
|
+
extra: {}
|
|
42
|
+
};
|
|
43
|
+
this.maxBreadcrumbs = DEFAULT_MAX_BREADCRUMBS;
|
|
44
|
+
}
|
|
45
|
+
addBreadcrumb(message, options) {
|
|
46
|
+
const crumb = {
|
|
47
|
+
timestamp: options?.timestamp ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
48
|
+
message,
|
|
49
|
+
category: options?.category,
|
|
50
|
+
level: options?.level,
|
|
51
|
+
data: options?.data ?? {},
|
|
52
|
+
type: options?.type ?? "default"
|
|
53
|
+
};
|
|
54
|
+
this._breadcrumbs.push(crumb);
|
|
55
|
+
if (this._breadcrumbs.length > this.maxBreadcrumbs) {
|
|
56
|
+
this._breadcrumbs = this._breadcrumbs.slice(-this.maxBreadcrumbs);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
clearBreadcrumbs() {
|
|
60
|
+
this._breadcrumbs = [];
|
|
61
|
+
}
|
|
62
|
+
getBreadcrumbs() {
|
|
63
|
+
return [...this._breadcrumbs];
|
|
64
|
+
}
|
|
65
|
+
setUser(user) {
|
|
66
|
+
this._context.user = user ?? void 0;
|
|
67
|
+
}
|
|
68
|
+
setTag(key, value) {
|
|
69
|
+
if (!this._context.tags) this._context.tags = {};
|
|
70
|
+
this._context.tags[key] = value;
|
|
71
|
+
}
|
|
72
|
+
setExtra(key, value) {
|
|
73
|
+
if (!this._context.extra) this._context.extra = {};
|
|
74
|
+
this._context.extra[key] = value;
|
|
75
|
+
}
|
|
76
|
+
setRequest(request) {
|
|
77
|
+
this._context.request = request ?? void 0;
|
|
78
|
+
}
|
|
79
|
+
setContext(key, data) {
|
|
80
|
+
if (key === "user") {
|
|
81
|
+
this._context.user = data;
|
|
82
|
+
} else if (key === "request") {
|
|
83
|
+
this._context.request = data;
|
|
84
|
+
} else {
|
|
85
|
+
if (!this._context.extra) this._context.extra = {};
|
|
86
|
+
this._context.extra[key] = data;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
getContext() {
|
|
90
|
+
return { ...this._context };
|
|
91
|
+
}
|
|
92
|
+
applyToContext(overrides) {
|
|
93
|
+
if (overrides.user !== void 0) this._context.user = overrides.user;
|
|
94
|
+
if (overrides.request !== void 0) this._context.request = overrides.request;
|
|
95
|
+
if (overrides.tags) this._context.tags = { ...this._context.tags, ...overrides.tags };
|
|
96
|
+
if (overrides.extra) this._context.extra = { ...this._context.extra, ...overrides.extra };
|
|
97
|
+
if (overrides.server_name !== void 0) this._context.server_name = overrides.server_name;
|
|
98
|
+
if (overrides.release !== void 0) this._context.release = overrides.release;
|
|
99
|
+
if (overrides.environment !== void 0) this._context.environment = overrides.environment;
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
// src/sdk.ts
|
|
104
|
+
var SDK_NAME = "xrayradar.javascript";
|
|
105
|
+
var SDK_VERSION = "0.1.0";
|
|
106
|
+
function getSdkInfo() {
|
|
107
|
+
return { name: SDK_NAME, version: SDK_VERSION };
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// src/event.ts
|
|
111
|
+
var LEVELS = ["fatal", "error", "warning", "info", "debug"];
|
|
112
|
+
function parseStack(err) {
|
|
113
|
+
const stack = err.stack;
|
|
114
|
+
if (!stack) return [];
|
|
115
|
+
const lines = stack.split("\n").slice(1);
|
|
116
|
+
const frames = [];
|
|
117
|
+
const re = new RegExp(
|
|
118
|
+
"^\\s*at (?:(.+?) \\()?(?:(.+?):(\\d+):(\\d+))\\)?$|^\\s*at (.+?):(\\d+):(\\d+)$"
|
|
119
|
+
);
|
|
120
|
+
for (const line of lines) {
|
|
121
|
+
const m = line.match(re);
|
|
122
|
+
if (!m) continue;
|
|
123
|
+
let functionName = "?";
|
|
124
|
+
let filename = "";
|
|
125
|
+
let lineno = 0;
|
|
126
|
+
let colno;
|
|
127
|
+
if (m[1] !== void 0 && m[2] !== void 0) {
|
|
128
|
+
functionName = m[1].trim();
|
|
129
|
+
filename = m[2];
|
|
130
|
+
lineno = parseInt(m[3] ?? "0", 10) || 0;
|
|
131
|
+
colno = parseInt(m[4] ?? "0", 10) || void 0;
|
|
132
|
+
} else if (m[5] !== void 0) {
|
|
133
|
+
filename = m[5];
|
|
134
|
+
lineno = parseInt(m[6] ?? "0", 10) || 0;
|
|
135
|
+
colno = parseInt(m[7] ?? "0", 10) || void 0;
|
|
136
|
+
}
|
|
137
|
+
const isInApp = !filename.includes("node_modules") && !filename.includes("<anonymous>") && !/^internal\//.test(filename);
|
|
138
|
+
frames.push({
|
|
139
|
+
filename,
|
|
140
|
+
function: functionName,
|
|
141
|
+
lineno,
|
|
142
|
+
colno,
|
|
143
|
+
abs_path: filename,
|
|
144
|
+
in_app: isInApp
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
return frames.reverse();
|
|
148
|
+
}
|
|
149
|
+
function eventFromException(error, level, message, scope) {
|
|
150
|
+
const frames = parseStack(error);
|
|
151
|
+
const exception = {
|
|
152
|
+
values: [
|
|
153
|
+
{
|
|
154
|
+
type: error.name,
|
|
155
|
+
value: error.message,
|
|
156
|
+
stacktrace: { frames }
|
|
157
|
+
}
|
|
158
|
+
]
|
|
159
|
+
};
|
|
160
|
+
const contexts = scope?.getContext() ?? { tags: {}, extra: {} };
|
|
161
|
+
const breadcrumbs = scope?.getBreadcrumbs() ?? [];
|
|
162
|
+
const payload = {
|
|
163
|
+
event_id: crypto.randomUUID?.() ?? `${Date.now()}-${Math.random().toString(36).slice(2)}`,
|
|
164
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
165
|
+
level,
|
|
166
|
+
message: message ?? `${error.name}: ${error.message}`,
|
|
167
|
+
platform: "javascript",
|
|
168
|
+
sdk: getSdkInfo(),
|
|
169
|
+
contexts,
|
|
170
|
+
breadcrumbs,
|
|
171
|
+
exception,
|
|
172
|
+
fingerprint: [error.name, error.message, frames[0]?.function].filter(
|
|
173
|
+
(x) => typeof x === "string" && x.length > 0
|
|
174
|
+
)
|
|
175
|
+
};
|
|
176
|
+
return payload;
|
|
177
|
+
}
|
|
178
|
+
function eventFromMessage(message, level, scope) {
|
|
179
|
+
const contexts = scope?.getContext() ?? { tags: {}, extra: {} };
|
|
180
|
+
const breadcrumbs = scope?.getBreadcrumbs() ?? [];
|
|
181
|
+
return {
|
|
182
|
+
event_id: crypto.randomUUID?.() ?? `${Date.now()}-${Math.random().toString(36).slice(2)}`,
|
|
183
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
184
|
+
level,
|
|
185
|
+
message,
|
|
186
|
+
platform: "javascript",
|
|
187
|
+
sdk: getSdkInfo(),
|
|
188
|
+
contexts,
|
|
189
|
+
breadcrumbs,
|
|
190
|
+
fingerprint: [message]
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
function normalizeLevel(level) {
|
|
194
|
+
const lower = level.toLowerCase();
|
|
195
|
+
if (LEVELS.includes(lower)) return lower;
|
|
196
|
+
return "error";
|
|
197
|
+
}
|
|
198
|
+
function shouldSample(sampleRate) {
|
|
199
|
+
if (sampleRate >= 1) return true;
|
|
200
|
+
if (sampleRate <= 0) return false;
|
|
201
|
+
return Math.random() < sampleRate;
|
|
202
|
+
}
|
|
203
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
204
|
+
0 && (module.exports = {
|
|
205
|
+
SDK_NAME,
|
|
206
|
+
SDK_VERSION,
|
|
207
|
+
Scope,
|
|
208
|
+
eventFromException,
|
|
209
|
+
eventFromMessage,
|
|
210
|
+
getSdkInfo,
|
|
211
|
+
normalizeLevel,
|
|
212
|
+
shouldSample
|
|
213
|
+
});
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
// src/scope.ts
|
|
2
|
+
var DEFAULT_MAX_BREADCRUMBS = 100;
|
|
3
|
+
var Scope = class {
|
|
4
|
+
constructor() {
|
|
5
|
+
this._breadcrumbs = [];
|
|
6
|
+
this._context = {
|
|
7
|
+
tags: {},
|
|
8
|
+
extra: {}
|
|
9
|
+
};
|
|
10
|
+
this.maxBreadcrumbs = DEFAULT_MAX_BREADCRUMBS;
|
|
11
|
+
}
|
|
12
|
+
addBreadcrumb(message, options) {
|
|
13
|
+
const crumb = {
|
|
14
|
+
timestamp: options?.timestamp ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
15
|
+
message,
|
|
16
|
+
category: options?.category,
|
|
17
|
+
level: options?.level,
|
|
18
|
+
data: options?.data ?? {},
|
|
19
|
+
type: options?.type ?? "default"
|
|
20
|
+
};
|
|
21
|
+
this._breadcrumbs.push(crumb);
|
|
22
|
+
if (this._breadcrumbs.length > this.maxBreadcrumbs) {
|
|
23
|
+
this._breadcrumbs = this._breadcrumbs.slice(-this.maxBreadcrumbs);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
clearBreadcrumbs() {
|
|
27
|
+
this._breadcrumbs = [];
|
|
28
|
+
}
|
|
29
|
+
getBreadcrumbs() {
|
|
30
|
+
return [...this._breadcrumbs];
|
|
31
|
+
}
|
|
32
|
+
setUser(user) {
|
|
33
|
+
this._context.user = user ?? void 0;
|
|
34
|
+
}
|
|
35
|
+
setTag(key, value) {
|
|
36
|
+
if (!this._context.tags) this._context.tags = {};
|
|
37
|
+
this._context.tags[key] = value;
|
|
38
|
+
}
|
|
39
|
+
setExtra(key, value) {
|
|
40
|
+
if (!this._context.extra) this._context.extra = {};
|
|
41
|
+
this._context.extra[key] = value;
|
|
42
|
+
}
|
|
43
|
+
setRequest(request) {
|
|
44
|
+
this._context.request = request ?? void 0;
|
|
45
|
+
}
|
|
46
|
+
setContext(key, data) {
|
|
47
|
+
if (key === "user") {
|
|
48
|
+
this._context.user = data;
|
|
49
|
+
} else if (key === "request") {
|
|
50
|
+
this._context.request = data;
|
|
51
|
+
} else {
|
|
52
|
+
if (!this._context.extra) this._context.extra = {};
|
|
53
|
+
this._context.extra[key] = data;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
getContext() {
|
|
57
|
+
return { ...this._context };
|
|
58
|
+
}
|
|
59
|
+
applyToContext(overrides) {
|
|
60
|
+
if (overrides.user !== void 0) this._context.user = overrides.user;
|
|
61
|
+
if (overrides.request !== void 0) this._context.request = overrides.request;
|
|
62
|
+
if (overrides.tags) this._context.tags = { ...this._context.tags, ...overrides.tags };
|
|
63
|
+
if (overrides.extra) this._context.extra = { ...this._context.extra, ...overrides.extra };
|
|
64
|
+
if (overrides.server_name !== void 0) this._context.server_name = overrides.server_name;
|
|
65
|
+
if (overrides.release !== void 0) this._context.release = overrides.release;
|
|
66
|
+
if (overrides.environment !== void 0) this._context.environment = overrides.environment;
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
// src/sdk.ts
|
|
71
|
+
var SDK_NAME = "xrayradar.javascript";
|
|
72
|
+
var SDK_VERSION = "0.1.0";
|
|
73
|
+
function getSdkInfo() {
|
|
74
|
+
return { name: SDK_NAME, version: SDK_VERSION };
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// src/event.ts
|
|
78
|
+
var LEVELS = ["fatal", "error", "warning", "info", "debug"];
|
|
79
|
+
function parseStack(err) {
|
|
80
|
+
const stack = err.stack;
|
|
81
|
+
if (!stack) return [];
|
|
82
|
+
const lines = stack.split("\n").slice(1);
|
|
83
|
+
const frames = [];
|
|
84
|
+
const re = new RegExp(
|
|
85
|
+
"^\\s*at (?:(.+?) \\()?(?:(.+?):(\\d+):(\\d+))\\)?$|^\\s*at (.+?):(\\d+):(\\d+)$"
|
|
86
|
+
);
|
|
87
|
+
for (const line of lines) {
|
|
88
|
+
const m = line.match(re);
|
|
89
|
+
if (!m) continue;
|
|
90
|
+
let functionName = "?";
|
|
91
|
+
let filename = "";
|
|
92
|
+
let lineno = 0;
|
|
93
|
+
let colno;
|
|
94
|
+
if (m[1] !== void 0 && m[2] !== void 0) {
|
|
95
|
+
functionName = m[1].trim();
|
|
96
|
+
filename = m[2];
|
|
97
|
+
lineno = parseInt(m[3] ?? "0", 10) || 0;
|
|
98
|
+
colno = parseInt(m[4] ?? "0", 10) || void 0;
|
|
99
|
+
} else if (m[5] !== void 0) {
|
|
100
|
+
filename = m[5];
|
|
101
|
+
lineno = parseInt(m[6] ?? "0", 10) || 0;
|
|
102
|
+
colno = parseInt(m[7] ?? "0", 10) || void 0;
|
|
103
|
+
}
|
|
104
|
+
const isInApp = !filename.includes("node_modules") && !filename.includes("<anonymous>") && !/^internal\//.test(filename);
|
|
105
|
+
frames.push({
|
|
106
|
+
filename,
|
|
107
|
+
function: functionName,
|
|
108
|
+
lineno,
|
|
109
|
+
colno,
|
|
110
|
+
abs_path: filename,
|
|
111
|
+
in_app: isInApp
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
return frames.reverse();
|
|
115
|
+
}
|
|
116
|
+
function eventFromException(error, level, message, scope) {
|
|
117
|
+
const frames = parseStack(error);
|
|
118
|
+
const exception = {
|
|
119
|
+
values: [
|
|
120
|
+
{
|
|
121
|
+
type: error.name,
|
|
122
|
+
value: error.message,
|
|
123
|
+
stacktrace: { frames }
|
|
124
|
+
}
|
|
125
|
+
]
|
|
126
|
+
};
|
|
127
|
+
const contexts = scope?.getContext() ?? { tags: {}, extra: {} };
|
|
128
|
+
const breadcrumbs = scope?.getBreadcrumbs() ?? [];
|
|
129
|
+
const payload = {
|
|
130
|
+
event_id: crypto.randomUUID?.() ?? `${Date.now()}-${Math.random().toString(36).slice(2)}`,
|
|
131
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
132
|
+
level,
|
|
133
|
+
message: message ?? `${error.name}: ${error.message}`,
|
|
134
|
+
platform: "javascript",
|
|
135
|
+
sdk: getSdkInfo(),
|
|
136
|
+
contexts,
|
|
137
|
+
breadcrumbs,
|
|
138
|
+
exception,
|
|
139
|
+
fingerprint: [error.name, error.message, frames[0]?.function].filter(
|
|
140
|
+
(x) => typeof x === "string" && x.length > 0
|
|
141
|
+
)
|
|
142
|
+
};
|
|
143
|
+
return payload;
|
|
144
|
+
}
|
|
145
|
+
function eventFromMessage(message, level, scope) {
|
|
146
|
+
const contexts = scope?.getContext() ?? { tags: {}, extra: {} };
|
|
147
|
+
const breadcrumbs = scope?.getBreadcrumbs() ?? [];
|
|
148
|
+
return {
|
|
149
|
+
event_id: crypto.randomUUID?.() ?? `${Date.now()}-${Math.random().toString(36).slice(2)}`,
|
|
150
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
151
|
+
level,
|
|
152
|
+
message,
|
|
153
|
+
platform: "javascript",
|
|
154
|
+
sdk: getSdkInfo(),
|
|
155
|
+
contexts,
|
|
156
|
+
breadcrumbs,
|
|
157
|
+
fingerprint: [message]
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
function normalizeLevel(level) {
|
|
161
|
+
const lower = level.toLowerCase();
|
|
162
|
+
if (LEVELS.includes(lower)) return lower;
|
|
163
|
+
return "error";
|
|
164
|
+
}
|
|
165
|
+
function shouldSample(sampleRate) {
|
|
166
|
+
if (sampleRate >= 1) return true;
|
|
167
|
+
if (sampleRate <= 0) return false;
|
|
168
|
+
return Math.random() < sampleRate;
|
|
169
|
+
}
|
|
170
|
+
export {
|
|
171
|
+
SDK_NAME,
|
|
172
|
+
SDK_VERSION,
|
|
173
|
+
Scope,
|
|
174
|
+
eventFromException,
|
|
175
|
+
eventFromMessage,
|
|
176
|
+
getSdkInfo,
|
|
177
|
+
normalizeLevel,
|
|
178
|
+
shouldSample
|
|
179
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"name":"@xrayradar/core","version":"0.1.0","description":"XrayRadar SDK core – types, scope, breadcrumbs, transport interface","main":"./dist/index.js","module":"./dist/index.mjs","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"}},"files":["dist"],"scripts":{"build":"tsup src/index.ts --format cjs,esm --dts --clean","test":"vitest run","lint":"eslint src","clean":"rm -rf dist"},"devDependencies":{"tsup":"^8.0.0","typescript":"^5.3.3","vitest":"^4.0.0"}}
|