@devkitio/faultlens 0.1.5 → 1.0.1
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/chunk-DQD732MN.js +293 -0
- package/dist/chunk-YQKZEUXA.js +1282 -0
- package/dist/cli/index.d.ts +14 -0
- package/dist/cli/index.js +57 -26
- package/dist/express/index.d.ts +1 -1
- package/dist/fastify/index.d.ts +1 -1
- package/dist/index.d.ts +30 -3
- package/dist/index.js +2 -2
- package/dist/node/index.d.ts +61 -2
- package/dist/node/index.js +437 -21
- package/dist/nuxt/runtime/nitro-plugin.js +1 -1
- package/dist/nuxt/runtime/plugin.js +2 -2
- package/dist/react/index.d.ts +1 -1
- package/dist/react/index.js +2 -2
- package/dist/testing/index.d.ts +12 -4
- package/dist/testing/index.js +43 -6
- package/dist/types-hWS-GSV1.d.ts +302 -0
- package/dist/vue/index.d.ts +1 -1
- package/dist/web-vitals/index.d.ts +28 -0
- package/dist/web-vitals/index.js +58 -0
- package/package.json +18 -10
- package/dist/chunk-K63I3OJT.js +0 -154
- package/dist/chunk-LRHXSFK2.js +0 -535
- package/dist/types-DxONWOH8.d.ts +0 -136
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
interface StackFrame {
|
|
2
|
+
filename: string;
|
|
3
|
+
function?: string;
|
|
4
|
+
line?: number;
|
|
5
|
+
column?: number;
|
|
6
|
+
inApp: boolean;
|
|
7
|
+
debugId?: string;
|
|
8
|
+
}
|
|
9
|
+
interface ErrorEvent {
|
|
10
|
+
eventId: string;
|
|
11
|
+
occurredAt: string;
|
|
12
|
+
type: string;
|
|
13
|
+
message: string;
|
|
14
|
+
handled: boolean;
|
|
15
|
+
mechanism: string;
|
|
16
|
+
level: "debug" | "info" | "warning" | "error" | "fatal";
|
|
17
|
+
stack: StackFrame[];
|
|
18
|
+
tags: Record<string, string>;
|
|
19
|
+
context?: unknown;
|
|
20
|
+
fingerprint?: string[];
|
|
21
|
+
traceId?: string;
|
|
22
|
+
spanId?: string;
|
|
23
|
+
}
|
|
24
|
+
type TelemetryAttributeValue = string | number | boolean;
|
|
25
|
+
type TelemetryAttributes = Record<string, TelemetryAttributeValue>;
|
|
26
|
+
type TelemetryStatus = "unset" | "ok" | "error";
|
|
27
|
+
interface TelemetryTrace {
|
|
28
|
+
telemetryId: string;
|
|
29
|
+
occurredAt: string;
|
|
30
|
+
traceId: string;
|
|
31
|
+
name: string;
|
|
32
|
+
startedAt: string;
|
|
33
|
+
endedAt: string;
|
|
34
|
+
status: TelemetryStatus;
|
|
35
|
+
attributes: TelemetryAttributes;
|
|
36
|
+
}
|
|
37
|
+
interface TelemetrySpan {
|
|
38
|
+
telemetryId: string;
|
|
39
|
+
occurredAt: string;
|
|
40
|
+
traceId: string;
|
|
41
|
+
spanId: string;
|
|
42
|
+
parentSpanId?: string;
|
|
43
|
+
name: string;
|
|
44
|
+
startedAt: string;
|
|
45
|
+
endedAt: string;
|
|
46
|
+
status: TelemetryStatus;
|
|
47
|
+
attributes: TelemetryAttributes;
|
|
48
|
+
}
|
|
49
|
+
interface WebVital {
|
|
50
|
+
telemetryId: string;
|
|
51
|
+
occurredAt: string;
|
|
52
|
+
name: "CLS" | "FCP" | "FID" | "INP" | "LCP" | "TTFB";
|
|
53
|
+
value: number;
|
|
54
|
+
rating: "good" | "needs-improvement" | "poor";
|
|
55
|
+
pageUrl: string;
|
|
56
|
+
navigationType?: string;
|
|
57
|
+
attributes?: TelemetryAttributes;
|
|
58
|
+
}
|
|
59
|
+
interface TelemetryEnvelope {
|
|
60
|
+
protocolVersion: string;
|
|
61
|
+
sdkName: string;
|
|
62
|
+
sdkVersion: string;
|
|
63
|
+
clientType: "browser" | "relay" | "nitro" | "testing";
|
|
64
|
+
expectedEnvironment?: string;
|
|
65
|
+
release: string;
|
|
66
|
+
dist?: string;
|
|
67
|
+
buildId: string;
|
|
68
|
+
clientBatchId: string;
|
|
69
|
+
traces: TelemetryTrace[];
|
|
70
|
+
spans: TelemetrySpan[];
|
|
71
|
+
webVitals: WebVital[];
|
|
72
|
+
}
|
|
73
|
+
interface EventEnvelope {
|
|
74
|
+
protocolVersion: string;
|
|
75
|
+
sdkName: string;
|
|
76
|
+
sdkVersion: string;
|
|
77
|
+
clientType: "browser" | "relay" | "nitro" | "testing";
|
|
78
|
+
expectedEnvironment?: string;
|
|
79
|
+
release: string;
|
|
80
|
+
dist?: string;
|
|
81
|
+
buildId: string;
|
|
82
|
+
clientBatchId: string;
|
|
83
|
+
events: ErrorEvent[];
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
interface TraceContext {
|
|
87
|
+
traceId: string;
|
|
88
|
+
spanId: string;
|
|
89
|
+
traceFlags: string;
|
|
90
|
+
traceState?: string;
|
|
91
|
+
traceVersion?: string;
|
|
92
|
+
}
|
|
93
|
+
declare function parseTraceParent(traceParent: string | null | undefined, traceState?: string | null): TraceContext | undefined;
|
|
94
|
+
declare function formatTraceParent(context: TraceContext): string;
|
|
95
|
+
declare function traceContextHeaders(context: TraceContext): Record<string, string>;
|
|
96
|
+
|
|
97
|
+
type ContextMode = "minimal" | "full";
|
|
98
|
+
type IngestConfig = {
|
|
99
|
+
mode: "direct";
|
|
100
|
+
dsn: string;
|
|
101
|
+
} | {
|
|
102
|
+
mode: "relay";
|
|
103
|
+
endpoint: string;
|
|
104
|
+
};
|
|
105
|
+
interface CaptureOptions {
|
|
106
|
+
handled?: boolean;
|
|
107
|
+
mechanism?: string;
|
|
108
|
+
context?: unknown;
|
|
109
|
+
level?: ErrorEvent["level"];
|
|
110
|
+
tags?: Record<string, string>;
|
|
111
|
+
traceId?: string;
|
|
112
|
+
spanId?: string;
|
|
113
|
+
}
|
|
114
|
+
interface TelemetryOptions {
|
|
115
|
+
enabled?: boolean;
|
|
116
|
+
sampleRate?: number;
|
|
117
|
+
}
|
|
118
|
+
interface SpanOptions {
|
|
119
|
+
parent?: TraceContext;
|
|
120
|
+
attributes?: Record<string, string | number | boolean>;
|
|
121
|
+
startTime?: Date;
|
|
122
|
+
}
|
|
123
|
+
interface Span {
|
|
124
|
+
readonly traceId: string;
|
|
125
|
+
readonly spanId: string;
|
|
126
|
+
readonly parentSpanId?: string;
|
|
127
|
+
readonly name: string;
|
|
128
|
+
setAttribute(name: string, value: string | number | boolean): void;
|
|
129
|
+
setStatus(status: "unset" | "ok" | "error"): void;
|
|
130
|
+
getTraceContext(): TraceContext;
|
|
131
|
+
toTraceHeaders(): Record<string, string>;
|
|
132
|
+
end(status?: "unset" | "ok" | "error"): void;
|
|
133
|
+
}
|
|
134
|
+
interface SpanContextManager {
|
|
135
|
+
active(): Span | undefined;
|
|
136
|
+
run<T>(span: Span, callback: () => T): T;
|
|
137
|
+
}
|
|
138
|
+
interface Breadcrumb {
|
|
139
|
+
category: string;
|
|
140
|
+
message: string;
|
|
141
|
+
level?: "debug" | "info" | "warning" | "error";
|
|
142
|
+
timestamp?: string;
|
|
143
|
+
data?: unknown;
|
|
144
|
+
}
|
|
145
|
+
interface MonitorOptions {
|
|
146
|
+
ingest: IngestConfig;
|
|
147
|
+
expectedEnvironment: string;
|
|
148
|
+
release: string;
|
|
149
|
+
dist?: string;
|
|
150
|
+
buildId?: string;
|
|
151
|
+
contextMode?: ContextMode;
|
|
152
|
+
ignoreError?: (error: unknown) => boolean;
|
|
153
|
+
beforeSend?: (event: ErrorEvent) => ErrorEvent | null | Promise<ErrorEvent | null>;
|
|
154
|
+
sampleRate?: number;
|
|
155
|
+
queueLimit?: number;
|
|
156
|
+
telemetry?: TelemetryOptions;
|
|
157
|
+
remoteConfigRefreshIntervalMs?: number;
|
|
158
|
+
}
|
|
159
|
+
interface MonitorStatus {
|
|
160
|
+
queueLength: number;
|
|
161
|
+
recentSendStatus: "idle" | "sending" | "accepted" | "retryable" | "permanent_error";
|
|
162
|
+
droppedReasons: Readonly<Record<string, number>>;
|
|
163
|
+
protocolVersion: string;
|
|
164
|
+
sdkVersion: string;
|
|
165
|
+
lastRateLimitedAt: string | null;
|
|
166
|
+
remotelyDisabled: boolean;
|
|
167
|
+
telemetryEnabled: boolean;
|
|
168
|
+
telemetryQueueLength: number;
|
|
169
|
+
remoteConfigLastRefreshAt: string | null;
|
|
170
|
+
remoteConfigLastSuccessAt: string | null;
|
|
171
|
+
remoteConfigFailureCode: string | null;
|
|
172
|
+
remoteConfigRefreshFailures: number;
|
|
173
|
+
}
|
|
174
|
+
interface ErrorMonitor {
|
|
175
|
+
captureException(error: unknown, options?: CaptureOptions): string;
|
|
176
|
+
captureMessage(message: string, options?: CaptureOptions): string;
|
|
177
|
+
addBreadcrumb(breadcrumb: Breadcrumb): void;
|
|
178
|
+
setUser(user: Record<string, unknown> | null): void;
|
|
179
|
+
setContext(name: string, value: unknown): void;
|
|
180
|
+
startSpan(name: string, options?: SpanOptions): Span;
|
|
181
|
+
withSpan<T>(name: string, callback: (span: Span) => T, options?: SpanOptions): T;
|
|
182
|
+
captureWebVital(vital: WebVitalInput): string;
|
|
183
|
+
getStatus(): MonitorStatus;
|
|
184
|
+
flush(timeout: number): Promise<boolean>;
|
|
185
|
+
close(): Promise<boolean>;
|
|
186
|
+
}
|
|
187
|
+
type WebVitalInput = Omit<WebVital, "telemetryId" | "occurredAt"> & {
|
|
188
|
+
occurredAt?: Date | string;
|
|
189
|
+
};
|
|
190
|
+
type BatchEventStatus = "accepted" | "duplicate" | "rejected" | "retryable";
|
|
191
|
+
interface BatchEventOutcome {
|
|
192
|
+
eventId: string;
|
|
193
|
+
status: BatchEventStatus;
|
|
194
|
+
errorCode?: string;
|
|
195
|
+
}
|
|
196
|
+
type BatchTransportOutcome = {
|
|
197
|
+
kind: "batch";
|
|
198
|
+
ingestId: string;
|
|
199
|
+
results: BatchEventOutcome[];
|
|
200
|
+
retryAfterMs: number;
|
|
201
|
+
} | {
|
|
202
|
+
kind: "retryable";
|
|
203
|
+
retryAfterMs: number;
|
|
204
|
+
code: string;
|
|
205
|
+
} | {
|
|
206
|
+
kind: "permanent_error";
|
|
207
|
+
code: string;
|
|
208
|
+
} | {
|
|
209
|
+
kind: "network_error";
|
|
210
|
+
code: "network_error";
|
|
211
|
+
};
|
|
212
|
+
type TransportOutcome = BatchTransportOutcome;
|
|
213
|
+
type RemoteConfigLoadResult = {
|
|
214
|
+
kind: "configured";
|
|
215
|
+
config: RemoteSdkConfig;
|
|
216
|
+
} | {
|
|
217
|
+
kind: "unsupported";
|
|
218
|
+
code: "config_not_found" | "unsupported_protocol";
|
|
219
|
+
} | {
|
|
220
|
+
kind: "retryable_error";
|
|
221
|
+
code: string;
|
|
222
|
+
};
|
|
223
|
+
interface EventTransport {
|
|
224
|
+
send(envelope: EventEnvelope): Promise<TransportOutcome>;
|
|
225
|
+
loadRemoteConfig?(): Promise<RemoteSdkConfig | undefined>;
|
|
226
|
+
loadRemoteConfigResult?(): Promise<RemoteConfigLoadResult>;
|
|
227
|
+
}
|
|
228
|
+
interface RemoteSdkConfig {
|
|
229
|
+
enabled?: boolean;
|
|
230
|
+
sampleRate?: number;
|
|
231
|
+
errorTypeAllowlist?: string[];
|
|
232
|
+
queueLimit?: number;
|
|
233
|
+
retryBaseMs?: number;
|
|
234
|
+
telemetry?: {
|
|
235
|
+
enabled?: boolean;
|
|
236
|
+
sampleRate?: number;
|
|
237
|
+
dailyQuota?: number;
|
|
238
|
+
retentionDays?: number;
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
interface TelemetryBatchItemOutcome {
|
|
242
|
+
telemetryId: string;
|
|
243
|
+
status: BatchEventStatus;
|
|
244
|
+
errorCode?: string;
|
|
245
|
+
}
|
|
246
|
+
type TelemetryTransportOutcome = {
|
|
247
|
+
kind: "batch";
|
|
248
|
+
ingestId: string;
|
|
249
|
+
results: TelemetryBatchItemOutcome[];
|
|
250
|
+
retryAfterMs: number;
|
|
251
|
+
} | {
|
|
252
|
+
kind: "unsupported";
|
|
253
|
+
code: string;
|
|
254
|
+
} | {
|
|
255
|
+
kind: "retryable";
|
|
256
|
+
retryAfterMs: number;
|
|
257
|
+
code: string;
|
|
258
|
+
} | {
|
|
259
|
+
kind: "permanent_error";
|
|
260
|
+
code: string;
|
|
261
|
+
} | {
|
|
262
|
+
kind: "network_error";
|
|
263
|
+
code: "network_error";
|
|
264
|
+
};
|
|
265
|
+
interface TelemetryTransport {
|
|
266
|
+
send(envelope: TelemetryEnvelope): Promise<TelemetryTransportOutcome>;
|
|
267
|
+
}
|
|
268
|
+
interface RuntimeDependencies {
|
|
269
|
+
transport: EventTransport;
|
|
270
|
+
telemetryTransport: TelemetryTransport;
|
|
271
|
+
now: () => Date;
|
|
272
|
+
random: () => number;
|
|
273
|
+
createEventId: () => string;
|
|
274
|
+
createTraceId: () => string;
|
|
275
|
+
createSpanId: () => string;
|
|
276
|
+
spanContextManager: SpanContextManager;
|
|
277
|
+
persistentQueue: PersistentEventQueue;
|
|
278
|
+
sendLease: SendLease;
|
|
279
|
+
installGlobalHandlers: (monitor: ErrorMonitor, transportPath: string) => () => void;
|
|
280
|
+
}
|
|
281
|
+
interface PersistentEventQueue {
|
|
282
|
+
load(now: number): Promise<PersistedQueueItem[]>;
|
|
283
|
+
put(item: PersistedQueueItem): Promise<void>;
|
|
284
|
+
remove(ids: string[]): Promise<void>;
|
|
285
|
+
clear(): Promise<void>;
|
|
286
|
+
}
|
|
287
|
+
interface PersistedQueueItem {
|
|
288
|
+
id: string;
|
|
289
|
+
event: ErrorEvent;
|
|
290
|
+
enqueuedAt: number;
|
|
291
|
+
bytes: number;
|
|
292
|
+
protocolVersion: string;
|
|
293
|
+
attemptCount: number;
|
|
294
|
+
nextAttemptAt: number;
|
|
295
|
+
lastErrorCode?: string;
|
|
296
|
+
}
|
|
297
|
+
interface SendLease {
|
|
298
|
+
acquire(now: number): boolean;
|
|
299
|
+
release(): void;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
export { type Breadcrumb as B, type CaptureOptions as C, type ErrorMonitor as E, type IngestConfig as I, type MonitorOptions as M, type PersistentEventQueue as P, type RemoteSdkConfig as R, type Span as S, type TelemetryTransport as T, type WebVitalInput as W, type TelemetryEnvelope as a, type TelemetryTransportOutcome as b, type ContextMode as c, type MonitorStatus as d, type SpanOptions as e, type TelemetryOptions as f, type TraceContext as g, formatTraceParent as h, type PersistedQueueItem as i, type EventTransport as j, type EventEnvelope as k, type TransportOutcome as l, type RemoteConfigLoadResult as m, type RuntimeDependencies as n, parseTraceParent as p, traceContextHeaders as t };
|
package/dist/vue/index.d.ts
CHANGED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { E as ErrorMonitor } from '../types-hWS-GSV1.js';
|
|
2
|
+
|
|
3
|
+
interface WebVitalsMetric {
|
|
4
|
+
name: "CLS" | "FCP" | "FID" | "INP" | "LCP" | "TTFB";
|
|
5
|
+
value: number;
|
|
6
|
+
rating: "good" | "needs-improvement" | "poor";
|
|
7
|
+
navigationType?: string;
|
|
8
|
+
}
|
|
9
|
+
type WebVitalsRegistrar = (handler: (metric: WebVitalsMetric) => void, options?: {
|
|
10
|
+
reportAllChanges?: boolean;
|
|
11
|
+
}) => void | (() => void);
|
|
12
|
+
interface WebVitalsSource {
|
|
13
|
+
onCLS: WebVitalsRegistrar;
|
|
14
|
+
onFCP: WebVitalsRegistrar;
|
|
15
|
+
onFID?: WebVitalsRegistrar;
|
|
16
|
+
onINP: WebVitalsRegistrar;
|
|
17
|
+
onLCP: WebVitalsRegistrar;
|
|
18
|
+
onTTFB: WebVitalsRegistrar;
|
|
19
|
+
}
|
|
20
|
+
interface WebVitalsInstrumentationOptions {
|
|
21
|
+
source?: WebVitalsSource;
|
|
22
|
+
reportAllChanges?: boolean;
|
|
23
|
+
pageUrl?: () => string;
|
|
24
|
+
attributes?: (metric: WebVitalsMetric) => Record<string, string | number | boolean>;
|
|
25
|
+
}
|
|
26
|
+
declare function installWebVitalsInstrumentation(monitor: ErrorMonitor, options?: WebVitalsInstrumentationOptions): () => void;
|
|
27
|
+
|
|
28
|
+
export { type WebVitalsInstrumentationOptions, type WebVitalsMetric, type WebVitalsRegistrar, type WebVitalsSource, installWebVitalsInstrumentation };
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { onTTFB, onLCP, onINP, onFCP, onCLS } from 'web-vitals';
|
|
2
|
+
|
|
3
|
+
// src/web-vitals/index.ts
|
|
4
|
+
function metricAdapter(handler) {
|
|
5
|
+
return (metric) => handler({
|
|
6
|
+
name: metric.name,
|
|
7
|
+
value: metric.value,
|
|
8
|
+
rating: metric.rating,
|
|
9
|
+
...metric.navigationType ? { navigationType: metric.navigationType } : {}
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
var defaultSource = {
|
|
13
|
+
onCLS: (handler, options) => onCLS(metricAdapter(handler), options),
|
|
14
|
+
onFCP: (handler, options) => onFCP(metricAdapter(handler), options),
|
|
15
|
+
onINP: (handler, options) => onINP(metricAdapter(handler), options),
|
|
16
|
+
onLCP: (handler, options) => onLCP(metricAdapter(handler), options),
|
|
17
|
+
onTTFB: (handler, options) => onTTFB(metricAdapter(handler), options)
|
|
18
|
+
};
|
|
19
|
+
function installWebVitalsInstrumentation(monitor, options = {}) {
|
|
20
|
+
const source = options.source ?? defaultSource;
|
|
21
|
+
const cleanup = [];
|
|
22
|
+
let active = true;
|
|
23
|
+
const handler = (metric) => {
|
|
24
|
+
if (!active) return;
|
|
25
|
+
const pageUrl = options.pageUrl?.() ?? (typeof location !== "undefined" ? location.href : "");
|
|
26
|
+
monitor.captureWebVital({
|
|
27
|
+
name: metric.name,
|
|
28
|
+
value: metric.value,
|
|
29
|
+
rating: metric.rating,
|
|
30
|
+
pageUrl,
|
|
31
|
+
...metric.navigationType ? { navigationType: metric.navigationType } : {},
|
|
32
|
+
...options.attributes ? { attributes: options.attributes(metric) } : {}
|
|
33
|
+
});
|
|
34
|
+
};
|
|
35
|
+
const registrars = [
|
|
36
|
+
source.onCLS,
|
|
37
|
+
source.onFCP,
|
|
38
|
+
source.onFID,
|
|
39
|
+
source.onINP,
|
|
40
|
+
source.onLCP,
|
|
41
|
+
source.onTTFB
|
|
42
|
+
].filter((registrar) => typeof registrar === "function");
|
|
43
|
+
for (const registrar of registrars) {
|
|
44
|
+
try {
|
|
45
|
+
const remove = registrar(handler, { reportAllChanges: options.reportAllChanges ?? false });
|
|
46
|
+
if (remove) cleanup.push(remove);
|
|
47
|
+
} catch {
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return () => {
|
|
52
|
+
if (!active) return;
|
|
53
|
+
active = false;
|
|
54
|
+
for (const remove of cleanup.splice(0)) remove();
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export { installWebVitalsInstrumentation };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@devkitio/faultlens",
|
|
3
|
-
"version": "0.1
|
|
3
|
+
"version": "1.0.1",
|
|
4
4
|
"description": "FaultLens 的 Browser、Node、Vue、Nuxt、React 与 Web 框架错误采集 SDK",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"private": false,
|
|
@@ -28,6 +28,10 @@
|
|
|
28
28
|
"types": "./dist/node/index.d.ts",
|
|
29
29
|
"import": "./dist/node/index.js"
|
|
30
30
|
},
|
|
31
|
+
"./web-vitals": {
|
|
32
|
+
"types": "./dist/web-vitals/index.d.ts",
|
|
33
|
+
"import": "./dist/web-vitals/index.js"
|
|
34
|
+
},
|
|
31
35
|
"./express": {
|
|
32
36
|
"types": "./dist/express/index.d.ts",
|
|
33
37
|
"import": "./dist/express/index.js"
|
|
@@ -48,16 +52,13 @@
|
|
|
48
52
|
"bin": {
|
|
49
53
|
"faultlens": "dist/cli/index.js"
|
|
50
54
|
},
|
|
51
|
-
"files": [
|
|
55
|
+
"files": [
|
|
56
|
+
"dist"
|
|
57
|
+
],
|
|
52
58
|
"publishConfig": {
|
|
53
59
|
"registry": "https://registry.npmjs.org/",
|
|
54
60
|
"access": "public"
|
|
55
61
|
},
|
|
56
|
-
"scripts": {
|
|
57
|
-
"build": "tsup",
|
|
58
|
-
"check": "tsc -p tsconfig.json --noEmit",
|
|
59
|
-
"prepack": "pnpm build"
|
|
60
|
-
},
|
|
61
62
|
"peerDependencies": {
|
|
62
63
|
"@nuxt/kit": ">=4.1.0 <5",
|
|
63
64
|
"@nuxt/schema": ">=4.1.0 <5",
|
|
@@ -91,13 +92,20 @@
|
|
|
91
92
|
}
|
|
92
93
|
},
|
|
93
94
|
"devDependencies": {
|
|
94
|
-
"@faultlens/security": "workspace:*",
|
|
95
95
|
"@nuxt/kit": "4.1.0",
|
|
96
96
|
"@nuxt/schema": "4.1.0",
|
|
97
97
|
"@types/react": "19.1.11",
|
|
98
98
|
"h3": "1.15.9",
|
|
99
99
|
"react": "19.1.1",
|
|
100
100
|
"tsup": "8.5.0",
|
|
101
|
-
"vue": "3.5.20"
|
|
101
|
+
"vue": "3.5.20",
|
|
102
|
+
"@faultlens/security": "1.0.1"
|
|
103
|
+
},
|
|
104
|
+
"dependencies": {
|
|
105
|
+
"web-vitals": "6.2.0"
|
|
106
|
+
},
|
|
107
|
+
"scripts": {
|
|
108
|
+
"build": "tsup",
|
|
109
|
+
"check": "tsc -p tsconfig.json --noEmit"
|
|
102
110
|
}
|
|
103
|
-
}
|
|
111
|
+
}
|
package/dist/chunk-K63I3OJT.js
DELETED
|
@@ -1,154 +0,0 @@
|
|
|
1
|
-
import { createMonitorRuntime } from './chunk-LRHXSFK2.js';
|
|
2
|
-
|
|
3
|
-
// src/browser-queue.ts
|
|
4
|
-
var DATABASE_NAME = "faultlens";
|
|
5
|
-
var STORE_NAME = "events";
|
|
6
|
-
var MAX_BYTES = 5 * 1024 * 1024;
|
|
7
|
-
var MAX_ITEMS = 50;
|
|
8
|
-
var MAX_AGE_MS = 24 * 60 * 60 * 1e3;
|
|
9
|
-
var IndexedDbEventQueue = class {
|
|
10
|
-
databasePromise;
|
|
11
|
-
static available() {
|
|
12
|
-
return typeof indexedDB !== "undefined";
|
|
13
|
-
}
|
|
14
|
-
database() {
|
|
15
|
-
this.databasePromise ??= new Promise((resolve, reject) => {
|
|
16
|
-
const request = indexedDB.open(DATABASE_NAME, 1);
|
|
17
|
-
request.onupgradeneeded = () => {
|
|
18
|
-
const database = request.result;
|
|
19
|
-
if (!database.objectStoreNames.contains(STORE_NAME)) {
|
|
20
|
-
const store = database.createObjectStore(STORE_NAME, { keyPath: "id" });
|
|
21
|
-
store.createIndex("enqueuedAt", "enqueuedAt");
|
|
22
|
-
}
|
|
23
|
-
};
|
|
24
|
-
request.onsuccess = () => resolve(request.result);
|
|
25
|
-
request.onerror = () => reject(request.error ?? new Error("IndexedDB \u6253\u5F00\u5931\u8D25"));
|
|
26
|
-
});
|
|
27
|
-
return this.databasePromise;
|
|
28
|
-
}
|
|
29
|
-
async all() {
|
|
30
|
-
const database = await this.database();
|
|
31
|
-
return new Promise((resolve, reject) => {
|
|
32
|
-
const request = database.transaction(STORE_NAME, "readonly").objectStore(STORE_NAME).getAll();
|
|
33
|
-
request.onsuccess = () => resolve(request.result.sort((a, b) => a.enqueuedAt - b.enqueuedAt));
|
|
34
|
-
request.onerror = () => reject(request.error ?? new Error("IndexedDB \u8BFB\u53D6\u5931\u8D25"));
|
|
35
|
-
});
|
|
36
|
-
}
|
|
37
|
-
async load(now) {
|
|
38
|
-
const items = await this.all();
|
|
39
|
-
const expired = items.filter((item) => now - item.enqueuedAt > MAX_AGE_MS).map((item) => item.id);
|
|
40
|
-
if (expired.length > 0) await this.remove(expired);
|
|
41
|
-
return items.filter((item) => now - item.enqueuedAt <= MAX_AGE_MS).slice(-MAX_ITEMS);
|
|
42
|
-
}
|
|
43
|
-
async put(item) {
|
|
44
|
-
const database = await this.database();
|
|
45
|
-
await new Promise((resolve, reject) => {
|
|
46
|
-
const request = database.transaction(STORE_NAME, "readwrite").objectStore(STORE_NAME).put(item);
|
|
47
|
-
request.onsuccess = () => resolve();
|
|
48
|
-
request.onerror = () => reject(request.error ?? new Error("IndexedDB \u5199\u5165\u5931\u8D25"));
|
|
49
|
-
});
|
|
50
|
-
const items = await this.all();
|
|
51
|
-
let bytes = items.reduce((total, current) => total + current.bytes, 0);
|
|
52
|
-
const removeIds = [];
|
|
53
|
-
for (const current of items) {
|
|
54
|
-
if (items.length - removeIds.length <= MAX_ITEMS && bytes <= MAX_BYTES) break;
|
|
55
|
-
removeIds.push(current.id);
|
|
56
|
-
bytes -= current.bytes;
|
|
57
|
-
}
|
|
58
|
-
if (removeIds.length > 0) await this.remove(removeIds);
|
|
59
|
-
}
|
|
60
|
-
async remove(ids) {
|
|
61
|
-
if (ids.length === 0) return;
|
|
62
|
-
const database = await this.database();
|
|
63
|
-
await new Promise((resolve, reject) => {
|
|
64
|
-
const transaction = database.transaction(STORE_NAME, "readwrite");
|
|
65
|
-
const store = transaction.objectStore(STORE_NAME);
|
|
66
|
-
for (const id of ids) store.delete(id);
|
|
67
|
-
transaction.oncomplete = () => resolve();
|
|
68
|
-
transaction.onerror = () => reject(transaction.error ?? new Error("IndexedDB \u5220\u9664\u5931\u8D25"));
|
|
69
|
-
});
|
|
70
|
-
}
|
|
71
|
-
async clear() {
|
|
72
|
-
const database = await this.database();
|
|
73
|
-
await new Promise((resolve, reject) => {
|
|
74
|
-
const request = database.transaction(STORE_NAME, "readwrite").objectStore(STORE_NAME).clear();
|
|
75
|
-
request.onsuccess = () => resolve();
|
|
76
|
-
request.onerror = () => reject(request.error ?? new Error("IndexedDB \u6E05\u7A7A\u5931\u8D25"));
|
|
77
|
-
});
|
|
78
|
-
}
|
|
79
|
-
};
|
|
80
|
-
var BrowserSendLease = class {
|
|
81
|
-
owner = `${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}`;
|
|
82
|
-
key = "faultlens:send-lease";
|
|
83
|
-
static available() {
|
|
84
|
-
try {
|
|
85
|
-
return typeof localStorage !== "undefined";
|
|
86
|
-
} catch {
|
|
87
|
-
return false;
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
acquire(now, durationMs = 1e4) {
|
|
91
|
-
try {
|
|
92
|
-
const current = JSON.parse(localStorage.getItem(this.key) ?? "null");
|
|
93
|
-
if (current && current.owner !== this.owner && current.expiresAt > now) return false;
|
|
94
|
-
localStorage.setItem(this.key, JSON.stringify({ owner: this.owner, expiresAt: now + durationMs }));
|
|
95
|
-
const confirmed = JSON.parse(localStorage.getItem(this.key) ?? "null");
|
|
96
|
-
return confirmed?.owner === this.owner;
|
|
97
|
-
} catch {
|
|
98
|
-
return true;
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
release() {
|
|
102
|
-
try {
|
|
103
|
-
const current = JSON.parse(localStorage.getItem(this.key) ?? "null");
|
|
104
|
-
if (current?.owner === this.owner) localStorage.removeItem(this.key);
|
|
105
|
-
} catch {
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
};
|
|
109
|
-
|
|
110
|
-
// src/global-handlers.ts
|
|
111
|
-
function installGlobalHandlers(monitor, transportPath) {
|
|
112
|
-
if (typeof window === "undefined") return () => void 0;
|
|
113
|
-
const onError = (event) => {
|
|
114
|
-
if (event.filename?.includes(transportPath)) return;
|
|
115
|
-
if (event.error) {
|
|
116
|
-
monitor.captureException(event.error, { handled: false, mechanism: "window.error" });
|
|
117
|
-
return;
|
|
118
|
-
}
|
|
119
|
-
const target = event.target;
|
|
120
|
-
if (target instanceof HTMLScriptElement || target instanceof HTMLLinkElement || target instanceof HTMLImageElement) {
|
|
121
|
-
const resource = target instanceof HTMLLinkElement ? target.href : target.src;
|
|
122
|
-
if (!resource.includes(transportPath)) {
|
|
123
|
-
monitor.captureMessage("\u524D\u7AEF\u8D44\u6E90\u52A0\u8F7D\u5931\u8D25", {
|
|
124
|
-
handled: false,
|
|
125
|
-
mechanism: "resource.error",
|
|
126
|
-
context: { tagName: target.tagName, resource }
|
|
127
|
-
});
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
};
|
|
131
|
-
const onUnhandledRejection = (event) => {
|
|
132
|
-
monitor.captureException(event.reason, {
|
|
133
|
-
handled: false,
|
|
134
|
-
mechanism: "unhandledrejection"
|
|
135
|
-
});
|
|
136
|
-
};
|
|
137
|
-
window.addEventListener("error", onError, true);
|
|
138
|
-
window.addEventListener("unhandledrejection", onUnhandledRejection);
|
|
139
|
-
return () => {
|
|
140
|
-
window.removeEventListener("error", onError, true);
|
|
141
|
-
window.removeEventListener("unhandledrejection", onUnhandledRejection);
|
|
142
|
-
};
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
// src/index.ts
|
|
146
|
-
function createErrorMonitor(options) {
|
|
147
|
-
return createMonitorRuntime(options, {
|
|
148
|
-
...IndexedDbEventQueue.available() ? { persistentQueue: new IndexedDbEventQueue() } : {},
|
|
149
|
-
...BrowserSendLease.available() ? { sendLease: new BrowserSendLease() } : {},
|
|
150
|
-
installGlobalHandlers
|
|
151
|
-
});
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
export { createErrorMonitor };
|