@edraj/sauron-browser 1.3.0 → 1.4.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/CHANGELOG.md +53 -0
- package/README.md +32 -12
- package/dist/index.cjs +105 -20
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +53 -10
- package/dist/index.d.ts +53 -10
- package/dist/index.js +105 -21
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -24,9 +24,17 @@ interface Mechanism {
|
|
|
24
24
|
type: string;
|
|
25
25
|
handled: boolean;
|
|
26
26
|
}
|
|
27
|
-
/**
|
|
27
|
+
/**
|
|
28
|
+
* The exception payload of an error item.
|
|
29
|
+
*
|
|
30
|
+
* `type` is NOT nullable: the backend's `ExceptionInfo.ty` is a non-`Option`
|
|
31
|
+
* `String` with no serde default, so `null` fails to deserialize and the
|
|
32
|
+
* gateway 400s the ENTIRE envelope — every other item in the batch with it.
|
|
33
|
+
* An item with no exception type omits `exception` altogether and carries its
|
|
34
|
+
* text in {@link ErrorItem.message}.
|
|
35
|
+
*/
|
|
28
36
|
interface ExceptionValue {
|
|
29
|
-
type: string
|
|
37
|
+
type: string;
|
|
30
38
|
value: string | null;
|
|
31
39
|
mechanism: Mechanism;
|
|
32
40
|
stacktrace: Frame[];
|
|
@@ -50,8 +58,14 @@ interface ErrorItem {
|
|
|
50
58
|
event_id?: string;
|
|
51
59
|
timestamp: string;
|
|
52
60
|
level: Level;
|
|
53
|
-
|
|
54
|
-
|
|
61
|
+
/**
|
|
62
|
+
* The captured exception. OPTIONAL — a message capture omits it entirely and
|
|
63
|
+
* carries its text in {@link message} instead (the backend's `exception` is
|
|
64
|
+
* `Option<ExceptionInfo>`, and with no exception it fingerprints off
|
|
65
|
+
* `message`). Never emit a placeholder here just to fill the field.
|
|
66
|
+
*/
|
|
67
|
+
exception?: ExceptionValue;
|
|
68
|
+
/** Human-readable summary; the ONLY text carrier when `exception` is absent. */
|
|
55
69
|
message?: string;
|
|
56
70
|
breadcrumbs: Breadcrumb[];
|
|
57
71
|
fingerprint: string[] | null;
|
|
@@ -392,7 +406,6 @@ declare class SauronClient {
|
|
|
392
406
|
private readonly nativeFetch?;
|
|
393
407
|
private enabled;
|
|
394
408
|
private installed;
|
|
395
|
-
private anonymousId;
|
|
396
409
|
private beaconCleanup;
|
|
397
410
|
constructor(options: ResolvedOptions);
|
|
398
411
|
/** Install global handlers + auto-instrumentation and start the transport. */
|
|
@@ -410,11 +423,29 @@ declare class SauronClient {
|
|
|
410
423
|
* null` as the no-op/disabled case before it ever reaches here.
|
|
411
424
|
*/
|
|
412
425
|
isEnabled(): boolean;
|
|
426
|
+
/**
|
|
427
|
+
* Whether the anonymous id has actually been USED as a `distinct_id` in this
|
|
428
|
+
* browser session.
|
|
429
|
+
*
|
|
430
|
+
* A persisted id that has never been observed anonymously must not create a
|
|
431
|
+
* permanent `identities` alias row on the server: aliasing is a durable
|
|
432
|
+
* server-side binding of this browser profile to a named user, and an
|
|
433
|
+
* identify() on a first-ever page load has no anonymous history to link.
|
|
434
|
+
*/
|
|
435
|
+
private anonUsed;
|
|
413
436
|
/** The current distinct id: the user id when identified, else an anon id. */
|
|
414
437
|
getDistinctId(): string | null;
|
|
415
|
-
/** The anonymous id, or null
|
|
438
|
+
/** The anonymous id, or null when it was never actually used as an identity. */
|
|
416
439
|
getAnonymousId(): string | null;
|
|
417
|
-
|
|
440
|
+
/**
|
|
441
|
+
* Forget the current person: clear the scope user and mint a fresh anonymous
|
|
442
|
+
* id.
|
|
443
|
+
*
|
|
444
|
+
* MUST BE CALLED ON LOGOUT. Without it, the next anonymous visitor on this
|
|
445
|
+
* browser reuses the persisted anon id, and a later identify() aliases their
|
|
446
|
+
* activity to the previous account server-side, permanently.
|
|
447
|
+
*/
|
|
448
|
+
reset(): void;
|
|
418
449
|
/** Stamp a fresh envelope (new `sent_at`, current context) around `items`. */
|
|
419
450
|
makeEnvelope(items: EnvelopeItem[]): Envelope;
|
|
420
451
|
/** Add a breadcrumb, running it through `beforeBreadcrumb` first. */
|
|
@@ -486,7 +517,7 @@ declare function parseError(err: unknown): Frame[];
|
|
|
486
517
|
/** Small dependency-free helpers shared across the SDK. */
|
|
487
518
|
/** SDK identity, embedded in every envelope header. */
|
|
488
519
|
declare const SDK_NAME = "sauron.javascript";
|
|
489
|
-
declare const SDK_VERSION = "1.
|
|
520
|
+
declare const SDK_VERSION = "1.4.0";
|
|
490
521
|
|
|
491
522
|
/**
|
|
492
523
|
* `@edraj/sauron-browser` — public API surface.
|
|
@@ -536,8 +567,19 @@ declare function cancelWorkflow(name?: string, options?: {
|
|
|
536
567
|
declare function getWorkflow(): ActiveWorkflow | null;
|
|
537
568
|
/** Record a breadcrumb. */
|
|
538
569
|
declare function addBreadcrumb(breadcrumb: BreadcrumbInput, hint?: Hint): void;
|
|
539
|
-
/**
|
|
570
|
+
/**
|
|
571
|
+
* Set (or clear, with `null`) the current user.
|
|
572
|
+
*
|
|
573
|
+
* `setUser(null)` is a logout, so it also rotates the anonymous id — otherwise
|
|
574
|
+
* the next anonymous visitor on this browser inherits the previous person's
|
|
575
|
+
* durable id and a later identify() aliases them together server-side.
|
|
576
|
+
*/
|
|
540
577
|
declare function setUser(user: UserInput): void;
|
|
578
|
+
/**
|
|
579
|
+
* Forget the current person: clears the scope user and mints a fresh anonymous
|
|
580
|
+
* id. Call this on logout.
|
|
581
|
+
*/
|
|
582
|
+
declare function reset(): void;
|
|
541
583
|
/** Set a single scope tag (lifted onto later errors/events). */
|
|
542
584
|
declare function setTag(key: string, value: string): void;
|
|
543
585
|
/** Merge a batch of scope tags (last-write-wins per key). */
|
|
@@ -561,6 +603,7 @@ declare const Sauron: {
|
|
|
561
603
|
identify: typeof identify;
|
|
562
604
|
addBreadcrumb: typeof addBreadcrumb;
|
|
563
605
|
setUser: typeof setUser;
|
|
606
|
+
reset: typeof reset;
|
|
564
607
|
setTag: typeof setTag;
|
|
565
608
|
setTags: typeof setTags;
|
|
566
609
|
setContext: typeof setContext;
|
|
@@ -576,4 +619,4 @@ declare const Sauron: {
|
|
|
576
619
|
getClient: typeof getClient;
|
|
577
620
|
};
|
|
578
621
|
|
|
579
|
-
export { type ActiveWorkflow, type AppContext, type BeforeBreadcrumb, type BeforeSend, type Breadcrumb, type BreadcrumbBatchItem, type BreadcrumbInput, type CaptureOptions, type Context, type DeviceContext, type Dsn, DsnError, type Envelope, type EnvelopeHeader, type EnvelopeItem, type ErrorItem, type EventItem, type ExceptionValue, type Frame, type Hint, type IdentifyItem, type InitOptions, type ItemType, type Level, type Mechanism, type OsContext, type ResolvedOptions, type RuntimeContext, SDK_NAME, SDK_VERSION, Sauron, SauronClient, type SdkInfo, type TrackOptions, type TransactionInput, type TransactionItem, type TransactionOp, type TransportOptions, type UserContext, type UserInput, type WorkflowResult, type WorkflowStatus, addBreadcrumb, buildEnvelope, cancelWorkflow, captureException, captureMessage, close, Sauron as default, endWorkflow, flush, getClient, getScreen, getWorkflow, identify, init, isInAppFrame, parseDsn, parseError, parseStackString, setContext, setExtra, setScreen, setTag, setTags, setUser, startWorkflow, track, trackTransaction };
|
|
622
|
+
export { type ActiveWorkflow, type AppContext, type BeforeBreadcrumb, type BeforeSend, type Breadcrumb, type BreadcrumbBatchItem, type BreadcrumbInput, type CaptureOptions, type Context, type DeviceContext, type Dsn, DsnError, type Envelope, type EnvelopeHeader, type EnvelopeItem, type ErrorItem, type EventItem, type ExceptionValue, type Frame, type Hint, type IdentifyItem, type InitOptions, type ItemType, type Level, type Mechanism, type OsContext, type ResolvedOptions, type RuntimeContext, SDK_NAME, SDK_VERSION, Sauron, SauronClient, type SdkInfo, type TrackOptions, type TransactionInput, type TransactionItem, type TransactionOp, type TransportOptions, type UserContext, type UserInput, type WorkflowResult, type WorkflowStatus, addBreadcrumb, buildEnvelope, cancelWorkflow, captureException, captureMessage, close, Sauron as default, endWorkflow, flush, getClient, getScreen, getWorkflow, identify, init, isInAppFrame, parseDsn, parseError, parseStackString, reset, setContext, setExtra, setScreen, setTag, setTags, setUser, startWorkflow, track, trackTransaction };
|
package/dist/index.d.ts
CHANGED
|
@@ -24,9 +24,17 @@ interface Mechanism {
|
|
|
24
24
|
type: string;
|
|
25
25
|
handled: boolean;
|
|
26
26
|
}
|
|
27
|
-
/**
|
|
27
|
+
/**
|
|
28
|
+
* The exception payload of an error item.
|
|
29
|
+
*
|
|
30
|
+
* `type` is NOT nullable: the backend's `ExceptionInfo.ty` is a non-`Option`
|
|
31
|
+
* `String` with no serde default, so `null` fails to deserialize and the
|
|
32
|
+
* gateway 400s the ENTIRE envelope — every other item in the batch with it.
|
|
33
|
+
* An item with no exception type omits `exception` altogether and carries its
|
|
34
|
+
* text in {@link ErrorItem.message}.
|
|
35
|
+
*/
|
|
28
36
|
interface ExceptionValue {
|
|
29
|
-
type: string
|
|
37
|
+
type: string;
|
|
30
38
|
value: string | null;
|
|
31
39
|
mechanism: Mechanism;
|
|
32
40
|
stacktrace: Frame[];
|
|
@@ -50,8 +58,14 @@ interface ErrorItem {
|
|
|
50
58
|
event_id?: string;
|
|
51
59
|
timestamp: string;
|
|
52
60
|
level: Level;
|
|
53
|
-
|
|
54
|
-
|
|
61
|
+
/**
|
|
62
|
+
* The captured exception. OPTIONAL — a message capture omits it entirely and
|
|
63
|
+
* carries its text in {@link message} instead (the backend's `exception` is
|
|
64
|
+
* `Option<ExceptionInfo>`, and with no exception it fingerprints off
|
|
65
|
+
* `message`). Never emit a placeholder here just to fill the field.
|
|
66
|
+
*/
|
|
67
|
+
exception?: ExceptionValue;
|
|
68
|
+
/** Human-readable summary; the ONLY text carrier when `exception` is absent. */
|
|
55
69
|
message?: string;
|
|
56
70
|
breadcrumbs: Breadcrumb[];
|
|
57
71
|
fingerprint: string[] | null;
|
|
@@ -392,7 +406,6 @@ declare class SauronClient {
|
|
|
392
406
|
private readonly nativeFetch?;
|
|
393
407
|
private enabled;
|
|
394
408
|
private installed;
|
|
395
|
-
private anonymousId;
|
|
396
409
|
private beaconCleanup;
|
|
397
410
|
constructor(options: ResolvedOptions);
|
|
398
411
|
/** Install global handlers + auto-instrumentation and start the transport. */
|
|
@@ -410,11 +423,29 @@ declare class SauronClient {
|
|
|
410
423
|
* null` as the no-op/disabled case before it ever reaches here.
|
|
411
424
|
*/
|
|
412
425
|
isEnabled(): boolean;
|
|
426
|
+
/**
|
|
427
|
+
* Whether the anonymous id has actually been USED as a `distinct_id` in this
|
|
428
|
+
* browser session.
|
|
429
|
+
*
|
|
430
|
+
* A persisted id that has never been observed anonymously must not create a
|
|
431
|
+
* permanent `identities` alias row on the server: aliasing is a durable
|
|
432
|
+
* server-side binding of this browser profile to a named user, and an
|
|
433
|
+
* identify() on a first-ever page load has no anonymous history to link.
|
|
434
|
+
*/
|
|
435
|
+
private anonUsed;
|
|
413
436
|
/** The current distinct id: the user id when identified, else an anon id. */
|
|
414
437
|
getDistinctId(): string | null;
|
|
415
|
-
/** The anonymous id, or null
|
|
438
|
+
/** The anonymous id, or null when it was never actually used as an identity. */
|
|
416
439
|
getAnonymousId(): string | null;
|
|
417
|
-
|
|
440
|
+
/**
|
|
441
|
+
* Forget the current person: clear the scope user and mint a fresh anonymous
|
|
442
|
+
* id.
|
|
443
|
+
*
|
|
444
|
+
* MUST BE CALLED ON LOGOUT. Without it, the next anonymous visitor on this
|
|
445
|
+
* browser reuses the persisted anon id, and a later identify() aliases their
|
|
446
|
+
* activity to the previous account server-side, permanently.
|
|
447
|
+
*/
|
|
448
|
+
reset(): void;
|
|
418
449
|
/** Stamp a fresh envelope (new `sent_at`, current context) around `items`. */
|
|
419
450
|
makeEnvelope(items: EnvelopeItem[]): Envelope;
|
|
420
451
|
/** Add a breadcrumb, running it through `beforeBreadcrumb` first. */
|
|
@@ -486,7 +517,7 @@ declare function parseError(err: unknown): Frame[];
|
|
|
486
517
|
/** Small dependency-free helpers shared across the SDK. */
|
|
487
518
|
/** SDK identity, embedded in every envelope header. */
|
|
488
519
|
declare const SDK_NAME = "sauron.javascript";
|
|
489
|
-
declare const SDK_VERSION = "1.
|
|
520
|
+
declare const SDK_VERSION = "1.4.0";
|
|
490
521
|
|
|
491
522
|
/**
|
|
492
523
|
* `@edraj/sauron-browser` — public API surface.
|
|
@@ -536,8 +567,19 @@ declare function cancelWorkflow(name?: string, options?: {
|
|
|
536
567
|
declare function getWorkflow(): ActiveWorkflow | null;
|
|
537
568
|
/** Record a breadcrumb. */
|
|
538
569
|
declare function addBreadcrumb(breadcrumb: BreadcrumbInput, hint?: Hint): void;
|
|
539
|
-
/**
|
|
570
|
+
/**
|
|
571
|
+
* Set (or clear, with `null`) the current user.
|
|
572
|
+
*
|
|
573
|
+
* `setUser(null)` is a logout, so it also rotates the anonymous id — otherwise
|
|
574
|
+
* the next anonymous visitor on this browser inherits the previous person's
|
|
575
|
+
* durable id and a later identify() aliases them together server-side.
|
|
576
|
+
*/
|
|
540
577
|
declare function setUser(user: UserInput): void;
|
|
578
|
+
/**
|
|
579
|
+
* Forget the current person: clears the scope user and mints a fresh anonymous
|
|
580
|
+
* id. Call this on logout.
|
|
581
|
+
*/
|
|
582
|
+
declare function reset(): void;
|
|
541
583
|
/** Set a single scope tag (lifted onto later errors/events). */
|
|
542
584
|
declare function setTag(key: string, value: string): void;
|
|
543
585
|
/** Merge a batch of scope tags (last-write-wins per key). */
|
|
@@ -561,6 +603,7 @@ declare const Sauron: {
|
|
|
561
603
|
identify: typeof identify;
|
|
562
604
|
addBreadcrumb: typeof addBreadcrumb;
|
|
563
605
|
setUser: typeof setUser;
|
|
606
|
+
reset: typeof reset;
|
|
564
607
|
setTag: typeof setTag;
|
|
565
608
|
setTags: typeof setTags;
|
|
566
609
|
setContext: typeof setContext;
|
|
@@ -576,4 +619,4 @@ declare const Sauron: {
|
|
|
576
619
|
getClient: typeof getClient;
|
|
577
620
|
};
|
|
578
621
|
|
|
579
|
-
export { type ActiveWorkflow, type AppContext, type BeforeBreadcrumb, type BeforeSend, type Breadcrumb, type BreadcrumbBatchItem, type BreadcrumbInput, type CaptureOptions, type Context, type DeviceContext, type Dsn, DsnError, type Envelope, type EnvelopeHeader, type EnvelopeItem, type ErrorItem, type EventItem, type ExceptionValue, type Frame, type Hint, type IdentifyItem, type InitOptions, type ItemType, type Level, type Mechanism, type OsContext, type ResolvedOptions, type RuntimeContext, SDK_NAME, SDK_VERSION, Sauron, SauronClient, type SdkInfo, type TrackOptions, type TransactionInput, type TransactionItem, type TransactionOp, type TransportOptions, type UserContext, type UserInput, type WorkflowResult, type WorkflowStatus, addBreadcrumb, buildEnvelope, cancelWorkflow, captureException, captureMessage, close, Sauron as default, endWorkflow, flush, getClient, getScreen, getWorkflow, identify, init, isInAppFrame, parseDsn, parseError, parseStackString, setContext, setExtra, setScreen, setTag, setTags, setUser, startWorkflow, track, trackTransaction };
|
|
622
|
+
export { type ActiveWorkflow, type AppContext, type BeforeBreadcrumb, type BeforeSend, type Breadcrumb, type BreadcrumbBatchItem, type BreadcrumbInput, type CaptureOptions, type Context, type DeviceContext, type Dsn, DsnError, type Envelope, type EnvelopeHeader, type EnvelopeItem, type ErrorItem, type EventItem, type ExceptionValue, type Frame, type Hint, type IdentifyItem, type InitOptions, type ItemType, type Level, type Mechanism, type OsContext, type ResolvedOptions, type RuntimeContext, SDK_NAME, SDK_VERSION, Sauron, SauronClient, type SdkInfo, type TrackOptions, type TransactionInput, type TransactionItem, type TransactionOp, type TransportOptions, type UserContext, type UserInput, type WorkflowResult, type WorkflowStatus, addBreadcrumb, buildEnvelope, cancelWorkflow, captureException, captureMessage, close, Sauron as default, endWorkflow, flush, getClient, getScreen, getWorkflow, identify, init, isInAppFrame, parseDsn, parseError, parseStackString, reset, setContext, setExtra, setScreen, setTag, setTags, setUser, startWorkflow, track, trackTransaction };
|
package/dist/index.js
CHANGED
|
@@ -4,7 +4,7 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
|
|
|
4
4
|
|
|
5
5
|
// src/utils.ts
|
|
6
6
|
var SDK_NAME = "sauron.javascript";
|
|
7
|
-
var SDK_VERSION = "1.
|
|
7
|
+
var SDK_VERSION = "1.4.0";
|
|
8
8
|
function getGlobal() {
|
|
9
9
|
return globalThis;
|
|
10
10
|
}
|
|
@@ -87,6 +87,7 @@ function makeLogger(debug) {
|
|
|
87
87
|
// src/identity.ts
|
|
88
88
|
var DEVICE_ID_KEY = "sauron.device_id";
|
|
89
89
|
var SESSION_ID_KEY = "sauron.session_id";
|
|
90
|
+
var ANON_ID_KEY = "sauron.anon_id";
|
|
90
91
|
function webStorage(name) {
|
|
91
92
|
try {
|
|
92
93
|
const s = globalThis[name];
|
|
@@ -119,6 +120,7 @@ function persistentId(cached, storage, key) {
|
|
|
119
120
|
}
|
|
120
121
|
var deviceId = null;
|
|
121
122
|
var sessionId = null;
|
|
123
|
+
var anonymousId = null;
|
|
122
124
|
function getDeviceId() {
|
|
123
125
|
deviceId = persistentId(deviceId, webStorage("localStorage"), DEVICE_ID_KEY);
|
|
124
126
|
return deviceId;
|
|
@@ -127,6 +129,40 @@ function getSessionId() {
|
|
|
127
129
|
sessionId = persistentId(sessionId, webStorage("sessionStorage"), SESSION_ID_KEY);
|
|
128
130
|
return sessionId;
|
|
129
131
|
}
|
|
132
|
+
function getAnonymousId() {
|
|
133
|
+
if (anonymousId) return anonymousId;
|
|
134
|
+
const storage = webStorage("localStorage");
|
|
135
|
+
if (storage) {
|
|
136
|
+
try {
|
|
137
|
+
const existing = storage.getItem(ANON_ID_KEY);
|
|
138
|
+
if (existing) {
|
|
139
|
+
anonymousId = existing;
|
|
140
|
+
return anonymousId;
|
|
141
|
+
}
|
|
142
|
+
} catch {
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
const fresh = `anon_${uuidv4()}`;
|
|
146
|
+
if (storage) {
|
|
147
|
+
try {
|
|
148
|
+
storage.setItem(ANON_ID_KEY, fresh);
|
|
149
|
+
} catch {
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
anonymousId = fresh;
|
|
153
|
+
return anonymousId;
|
|
154
|
+
}
|
|
155
|
+
function resetAnonymousId() {
|
|
156
|
+
anonymousId = null;
|
|
157
|
+
const storage = webStorage("localStorage");
|
|
158
|
+
if (storage) {
|
|
159
|
+
try {
|
|
160
|
+
storage.removeItem(ANON_ID_KEY);
|
|
161
|
+
} catch {
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
return getAnonymousId();
|
|
165
|
+
}
|
|
130
166
|
|
|
131
167
|
// src/context.ts
|
|
132
168
|
function getNavigator() {
|
|
@@ -624,12 +660,7 @@ function captureMessage(message, level = "info", hint) {
|
|
|
624
660
|
type: "error",
|
|
625
661
|
timestamp: nowIso(),
|
|
626
662
|
level,
|
|
627
|
-
|
|
628
|
-
type: null,
|
|
629
|
-
value: message,
|
|
630
|
-
mechanism: { type: "message", handled: true },
|
|
631
|
-
stacktrace: []
|
|
632
|
-
},
|
|
663
|
+
message,
|
|
633
664
|
breadcrumbs,
|
|
634
665
|
fingerprint: hint?.fingerprint ?? null,
|
|
635
666
|
session_id: getSessionId(),
|
|
@@ -885,12 +916,12 @@ function setScreen(name) {
|
|
|
885
916
|
function identify(id, traits = {}) {
|
|
886
917
|
const client = getClient();
|
|
887
918
|
if (!client) return;
|
|
888
|
-
const
|
|
919
|
+
const anonymousId2 = client.getAnonymousId();
|
|
889
920
|
client.getScope().setUser({ id, traits });
|
|
890
921
|
const item = {
|
|
891
922
|
type: "identify",
|
|
892
923
|
distinct_id: id,
|
|
893
|
-
anonymous_id:
|
|
924
|
+
anonymous_id: anonymousId2,
|
|
894
925
|
traits: traits ?? {}
|
|
895
926
|
};
|
|
896
927
|
client.captureItem(item);
|
|
@@ -1395,6 +1426,21 @@ var OfflineQueue = class {
|
|
|
1395
1426
|
if (entries.length) this.write([]);
|
|
1396
1427
|
return entries;
|
|
1397
1428
|
}
|
|
1429
|
+
/**
|
|
1430
|
+
* Put drained payloads BACK at the head, keeping their relative order.
|
|
1431
|
+
*
|
|
1432
|
+
* The counterpart to {@link drain}: a drain empties the store immediately, so
|
|
1433
|
+
* whatever the caller could not deliver only exists in its local array and is
|
|
1434
|
+
* lost the moment the caller returns. Re-parking at the head (rather than via
|
|
1435
|
+
* {@link enqueue}) keeps the queue oldest-first, which is what the byte-cap
|
|
1436
|
+
* eviction policy assumes — the oldest entry must stay the first one evicted.
|
|
1437
|
+
*/
|
|
1438
|
+
requeueFront(payloads) {
|
|
1439
|
+
if (!this.storage || payloads.length === 0) return;
|
|
1440
|
+
const entries = [...payloads, ...this.read()];
|
|
1441
|
+
this.evict(entries);
|
|
1442
|
+
this.write(entries);
|
|
1443
|
+
}
|
|
1398
1444
|
/** Non-destructive read of the current entries, oldest first. */
|
|
1399
1445
|
peek() {
|
|
1400
1446
|
return this.read();
|
|
@@ -1580,11 +1626,21 @@ var Transport = class {
|
|
|
1580
1626
|
}
|
|
1581
1627
|
}
|
|
1582
1628
|
}
|
|
1583
|
-
/**
|
|
1629
|
+
/**
|
|
1630
|
+
* Re-attempt any envelopes that were parked while offline.
|
|
1631
|
+
*
|
|
1632
|
+
* `drain()` empties `localStorage` in one shot, so from here on the ONLY copy
|
|
1633
|
+
* of the backlog is the local `payloads` array. Every early return therefore
|
|
1634
|
+
* has to re-park the whole untried remainder, not just the payload that
|
|
1635
|
+
* failed: this used to re-park the failing one and return, which silently
|
|
1636
|
+
* deleted every payload behind it — the exact reconnect-then-one-500 case the
|
|
1637
|
+
* queue exists for.
|
|
1638
|
+
*/
|
|
1584
1639
|
async drainOfflineQueue() {
|
|
1585
1640
|
if (this.disabled || !this.offline.available) return;
|
|
1586
1641
|
const payloads = this.offline.drain();
|
|
1587
|
-
for (
|
|
1642
|
+
for (let i = 0; i < payloads.length; i++) {
|
|
1643
|
+
const json = payloads[i];
|
|
1588
1644
|
let outcome;
|
|
1589
1645
|
try {
|
|
1590
1646
|
outcome = await this.post(json);
|
|
@@ -1592,13 +1648,14 @@ var Transport = class {
|
|
|
1592
1648
|
outcome = { action: "retry_backoff" };
|
|
1593
1649
|
}
|
|
1594
1650
|
if (outcome.action === "disable") {
|
|
1651
|
+
this.logger.warn("server rejected credentials while draining; disabling client");
|
|
1595
1652
|
this.disable();
|
|
1596
1653
|
this.onDisable();
|
|
1597
|
-
this.offline.
|
|
1654
|
+
this.offline.requeueFront(payloads.slice(i));
|
|
1598
1655
|
return;
|
|
1599
1656
|
}
|
|
1600
1657
|
if (outcome.action === "retry_after" || outcome.action === "retry_backoff") {
|
|
1601
|
-
this.offline.
|
|
1658
|
+
this.offline.requeueFront(payloads.slice(i));
|
|
1602
1659
|
return;
|
|
1603
1660
|
}
|
|
1604
1661
|
}
|
|
@@ -1708,8 +1765,17 @@ var SauronClient = class {
|
|
|
1708
1765
|
__publicField(this, "nativeFetch");
|
|
1709
1766
|
__publicField(this, "enabled", true);
|
|
1710
1767
|
__publicField(this, "installed", false);
|
|
1711
|
-
__publicField(this, "anonymousId", null);
|
|
1712
1768
|
__publicField(this, "beaconCleanup", null);
|
|
1769
|
+
/**
|
|
1770
|
+
* Whether the anonymous id has actually been USED as a `distinct_id` in this
|
|
1771
|
+
* browser session.
|
|
1772
|
+
*
|
|
1773
|
+
* A persisted id that has never been observed anonymously must not create a
|
|
1774
|
+
* permanent `identities` alias row on the server: aliasing is a durable
|
|
1775
|
+
* server-side binding of this browser profile to a named user, and an
|
|
1776
|
+
* identify() on a first-ever page load has no anonymous history to link.
|
|
1777
|
+
*/
|
|
1778
|
+
__publicField(this, "anonUsed", false);
|
|
1713
1779
|
this.options = options;
|
|
1714
1780
|
this.dsn = parseDsn(options.dsn);
|
|
1715
1781
|
this.logger = makeLogger(options.debug);
|
|
@@ -1776,15 +1842,25 @@ var SauronClient = class {
|
|
|
1776
1842
|
getDistinctId() {
|
|
1777
1843
|
const user = this.scope.getUser();
|
|
1778
1844
|
if (user.id) return user.id;
|
|
1779
|
-
|
|
1845
|
+
this.anonUsed = true;
|
|
1846
|
+
return getAnonymousId();
|
|
1780
1847
|
}
|
|
1781
|
-
/** The anonymous id, or null
|
|
1848
|
+
/** The anonymous id, or null when it was never actually used as an identity. */
|
|
1782
1849
|
getAnonymousId() {
|
|
1783
|
-
return this.
|
|
1850
|
+
return this.anonUsed ? getAnonymousId() : null;
|
|
1784
1851
|
}
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1852
|
+
/**
|
|
1853
|
+
* Forget the current person: clear the scope user and mint a fresh anonymous
|
|
1854
|
+
* id.
|
|
1855
|
+
*
|
|
1856
|
+
* MUST BE CALLED ON LOGOUT. Without it, the next anonymous visitor on this
|
|
1857
|
+
* browser reuses the persisted anon id, and a later identify() aliases their
|
|
1858
|
+
* activity to the previous account server-side, permanently.
|
|
1859
|
+
*/
|
|
1860
|
+
reset() {
|
|
1861
|
+
this.scope.setUser(null);
|
|
1862
|
+
resetAnonymousId();
|
|
1863
|
+
this.anonUsed = false;
|
|
1788
1864
|
}
|
|
1789
1865
|
/** Stamp a fresh envelope (new `sent_at`, current context) around `items`. */
|
|
1790
1866
|
makeEnvelope(items) {
|
|
@@ -2043,8 +2119,15 @@ function addBreadcrumb2(breadcrumb, hint) {
|
|
|
2043
2119
|
addBreadcrumb(breadcrumb, hint);
|
|
2044
2120
|
}
|
|
2045
2121
|
function setUser(user) {
|
|
2122
|
+
if (user === null) {
|
|
2123
|
+
getClient()?.reset();
|
|
2124
|
+
return;
|
|
2125
|
+
}
|
|
2046
2126
|
getClient()?.getScope().setUser(user);
|
|
2047
2127
|
}
|
|
2128
|
+
function reset() {
|
|
2129
|
+
getClient()?.reset();
|
|
2130
|
+
}
|
|
2048
2131
|
function setTag(key, value) {
|
|
2049
2132
|
getClient()?.getScope().setTag(key, value);
|
|
2050
2133
|
}
|
|
@@ -2074,6 +2157,7 @@ var Sauron = {
|
|
|
2074
2157
|
identify: identify2,
|
|
2075
2158
|
addBreadcrumb: addBreadcrumb2,
|
|
2076
2159
|
setUser,
|
|
2160
|
+
reset,
|
|
2077
2161
|
setTag,
|
|
2078
2162
|
setTags,
|
|
2079
2163
|
setContext,
|
|
@@ -2090,6 +2174,6 @@ var Sauron = {
|
|
|
2090
2174
|
};
|
|
2091
2175
|
var index_default = Sauron;
|
|
2092
2176
|
|
|
2093
|
-
export { DsnError, SDK_NAME, SDK_VERSION, Sauron, SauronClient, addBreadcrumb2 as addBreadcrumb, buildEnvelope, cancelWorkflow2 as cancelWorkflow, captureException2 as captureException, captureMessage2 as captureMessage, close, index_default as default, endWorkflow2 as endWorkflow, flush, getClient, getScreen2 as getScreen, getWorkflow2 as getWorkflow, identify2 as identify, init2 as init, isInAppFrame, parseDsn, parseError, parseStackString, setContext, setExtra, setScreen2 as setScreen, setTag, setTags, setUser, startWorkflow2 as startWorkflow, track2 as track, trackTransaction2 as trackTransaction };
|
|
2177
|
+
export { DsnError, SDK_NAME, SDK_VERSION, Sauron, SauronClient, addBreadcrumb2 as addBreadcrumb, buildEnvelope, cancelWorkflow2 as cancelWorkflow, captureException2 as captureException, captureMessage2 as captureMessage, close, index_default as default, endWorkflow2 as endWorkflow, flush, getClient, getScreen2 as getScreen, getWorkflow2 as getWorkflow, identify2 as identify, init2 as init, isInAppFrame, parseDsn, parseError, parseStackString, reset, setContext, setExtra, setScreen2 as setScreen, setTag, setTags, setUser, startWorkflow2 as startWorkflow, track2 as track, trackTransaction2 as trackTransaction };
|
|
2094
2178
|
//# sourceMappingURL=index.js.map
|
|
2095
2179
|
//# sourceMappingURL=index.js.map
|