@edraj/sauron-browser 1.0.0 → 1.3.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 +19 -0
- package/README.md +988 -53
- package/dist/index.cjs +181 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +91 -5
- package/dist/index.d.ts +91 -5
- package/dist/index.js +178 -5
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -74,6 +74,13 @@ interface ErrorItem {
|
|
|
74
74
|
*/
|
|
75
75
|
user?: UserContext | null;
|
|
76
76
|
session_id?: string | null;
|
|
77
|
+
/**
|
|
78
|
+
* The active workflow this item was stamped with, if any. A pair —
|
|
79
|
+
* always both present or both absent, never one without the other. See
|
|
80
|
+
* {@link ActiveWorkflow}.
|
|
81
|
+
*/
|
|
82
|
+
workflow_id?: string;
|
|
83
|
+
workflow_name?: string;
|
|
77
84
|
screen?: string | null;
|
|
78
85
|
}
|
|
79
86
|
/** A product-analytics event (PostHog-style `track`). */
|
|
@@ -82,6 +89,13 @@ interface EventItem {
|
|
|
82
89
|
name: string;
|
|
83
90
|
distinct_id: string | null;
|
|
84
91
|
session_id?: string | null;
|
|
92
|
+
/**
|
|
93
|
+
* The active workflow this item was stamped with, if any. A pair —
|
|
94
|
+
* always both present or both absent, never one without the other. See
|
|
95
|
+
* {@link ActiveWorkflow}.
|
|
96
|
+
*/
|
|
97
|
+
workflow_id?: string;
|
|
98
|
+
workflow_name?: string;
|
|
85
99
|
screen?: string | null;
|
|
86
100
|
timestamp: string;
|
|
87
101
|
properties: Record<string, unknown>;
|
|
@@ -108,6 +122,13 @@ interface TransactionItem {
|
|
|
108
122
|
url?: string | null;
|
|
109
123
|
distinct_id?: string | null;
|
|
110
124
|
session_id?: string | null;
|
|
125
|
+
/**
|
|
126
|
+
* The active workflow this item was stamped with, if any. A pair —
|
|
127
|
+
* always both present or both absent, never one without the other. See
|
|
128
|
+
* {@link ActiveWorkflow}.
|
|
129
|
+
*/
|
|
130
|
+
workflow_id?: string;
|
|
131
|
+
workflow_name?: string;
|
|
111
132
|
timestamp: string;
|
|
112
133
|
}
|
|
113
134
|
/** An identity association (PostHog-style `identify`). */
|
|
@@ -163,7 +184,6 @@ interface EnvelopeHeader {
|
|
|
163
184
|
dsn: string;
|
|
164
185
|
sdk: SdkInfo;
|
|
165
186
|
sent_at: string;
|
|
166
|
-
environment: string;
|
|
167
187
|
release: string | null;
|
|
168
188
|
}
|
|
169
189
|
/** The complete, serializable envelope posted to the ingest gateway. */
|
|
@@ -191,6 +211,25 @@ interface CaptureOptions {
|
|
|
191
211
|
interface TrackOptions extends CaptureOptions {
|
|
192
212
|
screen?: string;
|
|
193
213
|
}
|
|
214
|
+
/**
|
|
215
|
+
* Outcome of `startWorkflow` / `endWorkflow` / `cancelWorkflow`. Telemetry
|
|
216
|
+
* never throws — every call resolves to one of these instead.
|
|
217
|
+
*/
|
|
218
|
+
type WorkflowStatus = 'ok' | 'already_active' | 'not_active' | 'name_mismatch' | 'invalid_name' | 'disabled';
|
|
219
|
+
/** Result of a workflow lifecycle call. */
|
|
220
|
+
interface WorkflowResult {
|
|
221
|
+
status: WorkflowStatus;
|
|
222
|
+
/** The workflow id involved, when `status` is `'ok'`. */
|
|
223
|
+
workflowId?: string;
|
|
224
|
+
}
|
|
225
|
+
/** The currently-active workflow, as returned by `getWorkflow()`. */
|
|
226
|
+
interface ActiveWorkflow {
|
|
227
|
+
/** Client-generated UUID — the server rollup key is `(app_id, workflow_id)`. */
|
|
228
|
+
workflowId: string;
|
|
229
|
+
name: string;
|
|
230
|
+
/** ISO-8601 UTC timestamp of `startWorkflow()`. */
|
|
231
|
+
startedAt: string;
|
|
232
|
+
}
|
|
194
233
|
/** Value accepted by `setUser` — normalized into a `UserContext`. */
|
|
195
234
|
type UserInput = (Partial<UserContext> & {
|
|
196
235
|
id?: string | null;
|
|
@@ -211,7 +250,6 @@ interface TransportOptions {
|
|
|
211
250
|
interface InitOptions {
|
|
212
251
|
/** `https://<public_key>@<host>/<project_id>` */
|
|
213
252
|
dsn: string;
|
|
214
|
-
environment?: string;
|
|
215
253
|
release?: string;
|
|
216
254
|
/** Error sample rate in [0, 1]. Default 1 (send everything). */
|
|
217
255
|
sampleRate?: number;
|
|
@@ -244,7 +282,6 @@ interface InitOptions {
|
|
|
244
282
|
/** Fully-resolved options with all defaults applied. */
|
|
245
283
|
interface ResolvedOptions {
|
|
246
284
|
dsn: string;
|
|
247
|
-
environment: string;
|
|
248
285
|
release: string | null;
|
|
249
286
|
sampleRate: number;
|
|
250
287
|
maxBreadcrumbs: number;
|
|
@@ -361,6 +398,17 @@ declare class SauronClient {
|
|
|
361
398
|
/** Install global handlers + auto-instrumentation and start the transport. */
|
|
362
399
|
install(): void;
|
|
363
400
|
getScope(): Scope;
|
|
401
|
+
/**
|
|
402
|
+
* False once this client was explicitly disabled/closed, OR once the
|
|
403
|
+
* transport has auto-disabled itself on a 401/403 (revoked/invalid DSN
|
|
404
|
+
* key) — computed from the transport's own state on every call, not a
|
|
405
|
+
* separately mirrored flag, so a propagation regression there cannot leave
|
|
406
|
+
* this predicate stale. `this.transport` always exists once a client
|
|
407
|
+
* exists (it is constructed synchronously in the constructor); the
|
|
408
|
+
* "nothing installed yet" case is instead handled one layer up, by every
|
|
409
|
+
* module-level API (`startWorkflow`, `track`, ...) treating `getClient() ===
|
|
410
|
+
* null` as the no-op/disabled case before it ever reaches here.
|
|
411
|
+
*/
|
|
364
412
|
isEnabled(): boolean;
|
|
365
413
|
/** The current distinct id: the user id when identified, else an anon id. */
|
|
366
414
|
getDistinctId(): string | null;
|
|
@@ -379,6 +427,23 @@ declare class SauronClient {
|
|
|
379
427
|
* `event_id` is always minted so callers can correlate the report.
|
|
380
428
|
*/
|
|
381
429
|
private enrichErrorItem;
|
|
430
|
+
/**
|
|
431
|
+
* Stamp the active workflow (if any) onto a signal item.
|
|
432
|
+
*
|
|
433
|
+
* Done HERE — the single choke point every capture path funnels through —
|
|
434
|
+
* rather than at each item-construction site, so a capture path added later
|
|
435
|
+
* is stamped by construction instead of by remembering to. The keys are
|
|
436
|
+
* ASSIGNED ONLY when a workflow is active: an item with no workflow keeps
|
|
437
|
+
* them absent entirely (not present-as-`undefined`), which is what makes
|
|
438
|
+
* `JSON.stringify` omit them and keeps the no-workflow wire bytes identical
|
|
439
|
+
* to pre-1.3.0.
|
|
440
|
+
*
|
|
441
|
+
* Only error/event/transaction carry `workflow_id`/`workflow_name` columns
|
|
442
|
+
* server-side — identify and breadcrumb_batch items are deliberately left
|
|
443
|
+
* alone. An item that already carries an explicit `workflow_id` is left
|
|
444
|
+
* untouched, matching how `enrichErrorItem` defers to caller-set fields.
|
|
445
|
+
*/
|
|
446
|
+
private stampWorkflow;
|
|
382
447
|
/**
|
|
383
448
|
* Run an item through sampling (errors only) and `beforeSend`, then hand it to
|
|
384
449
|
* the transport. Returns silently when dropped.
|
|
@@ -421,7 +486,7 @@ declare function parseError(err: unknown): Frame[];
|
|
|
421
486
|
/** Small dependency-free helpers shared across the SDK. */
|
|
422
487
|
/** SDK identity, embedded in every envelope header. */
|
|
423
488
|
declare const SDK_NAME = "sauron.javascript";
|
|
424
|
-
declare const SDK_VERSION = "1.
|
|
489
|
+
declare const SDK_VERSION = "1.3.0";
|
|
425
490
|
|
|
426
491
|
/**
|
|
427
492
|
* `@edraj/sauron-browser` — public API surface.
|
|
@@ -452,6 +517,23 @@ declare function trackTransaction(input: TransactionInput): void;
|
|
|
452
517
|
declare function setScreen(name: string): void;
|
|
453
518
|
/** The current screen name, or null. */
|
|
454
519
|
declare function getScreen(): string | null;
|
|
520
|
+
/**
|
|
521
|
+
* Start a named, explicitly-bounded workflow. `workflow_id` is a fresh
|
|
522
|
+
* client-generated UUID; the id + name are then stamped on every subsequent
|
|
523
|
+
* event/error/transaction until the workflow ends or is cancelled. Optional —
|
|
524
|
+
* an app that never calls this behaves exactly as before.
|
|
525
|
+
*/
|
|
526
|
+
declare function startWorkflow(name: string, options?: {
|
|
527
|
+
force?: boolean;
|
|
528
|
+
}): WorkflowResult;
|
|
529
|
+
/** End the active workflow (or the one named `name`, if given). */
|
|
530
|
+
declare function endWorkflow(name?: string): WorkflowResult;
|
|
531
|
+
/** Cancel the active workflow (or the one named `name`, if given). */
|
|
532
|
+
declare function cancelWorkflow(name?: string, options?: {
|
|
533
|
+
reason?: string;
|
|
534
|
+
}): WorkflowResult;
|
|
535
|
+
/** The currently active workflow, or `null` when none is active. */
|
|
536
|
+
declare function getWorkflow(): ActiveWorkflow | null;
|
|
455
537
|
/** Record a breadcrumb. */
|
|
456
538
|
declare function addBreadcrumb(breadcrumb: BreadcrumbInput, hint?: Hint): void;
|
|
457
539
|
/** Set (or clear, with `null`) the current user. */
|
|
@@ -485,9 +567,13 @@ declare const Sauron: {
|
|
|
485
567
|
setExtra: typeof setExtra;
|
|
486
568
|
setScreen: typeof setScreen;
|
|
487
569
|
getScreen: typeof getScreen;
|
|
570
|
+
startWorkflow: typeof startWorkflow;
|
|
571
|
+
endWorkflow: typeof endWorkflow;
|
|
572
|
+
cancelWorkflow: typeof cancelWorkflow;
|
|
573
|
+
getWorkflow: typeof getWorkflow;
|
|
488
574
|
flush: typeof flush;
|
|
489
575
|
close: typeof close;
|
|
490
576
|
getClient: typeof getClient;
|
|
491
577
|
};
|
|
492
578
|
|
|
493
|
-
export { 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, addBreadcrumb, buildEnvelope, captureException, captureMessage, close, Sauron as default, flush, getClient, getScreen, identify, init, isInAppFrame, parseDsn, parseError, parseStackString, setContext, setExtra, setScreen, setTag, setTags, setUser, track, trackTransaction };
|
|
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 };
|
package/dist/index.d.ts
CHANGED
|
@@ -74,6 +74,13 @@ interface ErrorItem {
|
|
|
74
74
|
*/
|
|
75
75
|
user?: UserContext | null;
|
|
76
76
|
session_id?: string | null;
|
|
77
|
+
/**
|
|
78
|
+
* The active workflow this item was stamped with, if any. A pair —
|
|
79
|
+
* always both present or both absent, never one without the other. See
|
|
80
|
+
* {@link ActiveWorkflow}.
|
|
81
|
+
*/
|
|
82
|
+
workflow_id?: string;
|
|
83
|
+
workflow_name?: string;
|
|
77
84
|
screen?: string | null;
|
|
78
85
|
}
|
|
79
86
|
/** A product-analytics event (PostHog-style `track`). */
|
|
@@ -82,6 +89,13 @@ interface EventItem {
|
|
|
82
89
|
name: string;
|
|
83
90
|
distinct_id: string | null;
|
|
84
91
|
session_id?: string | null;
|
|
92
|
+
/**
|
|
93
|
+
* The active workflow this item was stamped with, if any. A pair —
|
|
94
|
+
* always both present or both absent, never one without the other. See
|
|
95
|
+
* {@link ActiveWorkflow}.
|
|
96
|
+
*/
|
|
97
|
+
workflow_id?: string;
|
|
98
|
+
workflow_name?: string;
|
|
85
99
|
screen?: string | null;
|
|
86
100
|
timestamp: string;
|
|
87
101
|
properties: Record<string, unknown>;
|
|
@@ -108,6 +122,13 @@ interface TransactionItem {
|
|
|
108
122
|
url?: string | null;
|
|
109
123
|
distinct_id?: string | null;
|
|
110
124
|
session_id?: string | null;
|
|
125
|
+
/**
|
|
126
|
+
* The active workflow this item was stamped with, if any. A pair —
|
|
127
|
+
* always both present or both absent, never one without the other. See
|
|
128
|
+
* {@link ActiveWorkflow}.
|
|
129
|
+
*/
|
|
130
|
+
workflow_id?: string;
|
|
131
|
+
workflow_name?: string;
|
|
111
132
|
timestamp: string;
|
|
112
133
|
}
|
|
113
134
|
/** An identity association (PostHog-style `identify`). */
|
|
@@ -163,7 +184,6 @@ interface EnvelopeHeader {
|
|
|
163
184
|
dsn: string;
|
|
164
185
|
sdk: SdkInfo;
|
|
165
186
|
sent_at: string;
|
|
166
|
-
environment: string;
|
|
167
187
|
release: string | null;
|
|
168
188
|
}
|
|
169
189
|
/** The complete, serializable envelope posted to the ingest gateway. */
|
|
@@ -191,6 +211,25 @@ interface CaptureOptions {
|
|
|
191
211
|
interface TrackOptions extends CaptureOptions {
|
|
192
212
|
screen?: string;
|
|
193
213
|
}
|
|
214
|
+
/**
|
|
215
|
+
* Outcome of `startWorkflow` / `endWorkflow` / `cancelWorkflow`. Telemetry
|
|
216
|
+
* never throws — every call resolves to one of these instead.
|
|
217
|
+
*/
|
|
218
|
+
type WorkflowStatus = 'ok' | 'already_active' | 'not_active' | 'name_mismatch' | 'invalid_name' | 'disabled';
|
|
219
|
+
/** Result of a workflow lifecycle call. */
|
|
220
|
+
interface WorkflowResult {
|
|
221
|
+
status: WorkflowStatus;
|
|
222
|
+
/** The workflow id involved, when `status` is `'ok'`. */
|
|
223
|
+
workflowId?: string;
|
|
224
|
+
}
|
|
225
|
+
/** The currently-active workflow, as returned by `getWorkflow()`. */
|
|
226
|
+
interface ActiveWorkflow {
|
|
227
|
+
/** Client-generated UUID — the server rollup key is `(app_id, workflow_id)`. */
|
|
228
|
+
workflowId: string;
|
|
229
|
+
name: string;
|
|
230
|
+
/** ISO-8601 UTC timestamp of `startWorkflow()`. */
|
|
231
|
+
startedAt: string;
|
|
232
|
+
}
|
|
194
233
|
/** Value accepted by `setUser` — normalized into a `UserContext`. */
|
|
195
234
|
type UserInput = (Partial<UserContext> & {
|
|
196
235
|
id?: string | null;
|
|
@@ -211,7 +250,6 @@ interface TransportOptions {
|
|
|
211
250
|
interface InitOptions {
|
|
212
251
|
/** `https://<public_key>@<host>/<project_id>` */
|
|
213
252
|
dsn: string;
|
|
214
|
-
environment?: string;
|
|
215
253
|
release?: string;
|
|
216
254
|
/** Error sample rate in [0, 1]. Default 1 (send everything). */
|
|
217
255
|
sampleRate?: number;
|
|
@@ -244,7 +282,6 @@ interface InitOptions {
|
|
|
244
282
|
/** Fully-resolved options with all defaults applied. */
|
|
245
283
|
interface ResolvedOptions {
|
|
246
284
|
dsn: string;
|
|
247
|
-
environment: string;
|
|
248
285
|
release: string | null;
|
|
249
286
|
sampleRate: number;
|
|
250
287
|
maxBreadcrumbs: number;
|
|
@@ -361,6 +398,17 @@ declare class SauronClient {
|
|
|
361
398
|
/** Install global handlers + auto-instrumentation and start the transport. */
|
|
362
399
|
install(): void;
|
|
363
400
|
getScope(): Scope;
|
|
401
|
+
/**
|
|
402
|
+
* False once this client was explicitly disabled/closed, OR once the
|
|
403
|
+
* transport has auto-disabled itself on a 401/403 (revoked/invalid DSN
|
|
404
|
+
* key) — computed from the transport's own state on every call, not a
|
|
405
|
+
* separately mirrored flag, so a propagation regression there cannot leave
|
|
406
|
+
* this predicate stale. `this.transport` always exists once a client
|
|
407
|
+
* exists (it is constructed synchronously in the constructor); the
|
|
408
|
+
* "nothing installed yet" case is instead handled one layer up, by every
|
|
409
|
+
* module-level API (`startWorkflow`, `track`, ...) treating `getClient() ===
|
|
410
|
+
* null` as the no-op/disabled case before it ever reaches here.
|
|
411
|
+
*/
|
|
364
412
|
isEnabled(): boolean;
|
|
365
413
|
/** The current distinct id: the user id when identified, else an anon id. */
|
|
366
414
|
getDistinctId(): string | null;
|
|
@@ -379,6 +427,23 @@ declare class SauronClient {
|
|
|
379
427
|
* `event_id` is always minted so callers can correlate the report.
|
|
380
428
|
*/
|
|
381
429
|
private enrichErrorItem;
|
|
430
|
+
/**
|
|
431
|
+
* Stamp the active workflow (if any) onto a signal item.
|
|
432
|
+
*
|
|
433
|
+
* Done HERE — the single choke point every capture path funnels through —
|
|
434
|
+
* rather than at each item-construction site, so a capture path added later
|
|
435
|
+
* is stamped by construction instead of by remembering to. The keys are
|
|
436
|
+
* ASSIGNED ONLY when a workflow is active: an item with no workflow keeps
|
|
437
|
+
* them absent entirely (not present-as-`undefined`), which is what makes
|
|
438
|
+
* `JSON.stringify` omit them and keeps the no-workflow wire bytes identical
|
|
439
|
+
* to pre-1.3.0.
|
|
440
|
+
*
|
|
441
|
+
* Only error/event/transaction carry `workflow_id`/`workflow_name` columns
|
|
442
|
+
* server-side — identify and breadcrumb_batch items are deliberately left
|
|
443
|
+
* alone. An item that already carries an explicit `workflow_id` is left
|
|
444
|
+
* untouched, matching how `enrichErrorItem` defers to caller-set fields.
|
|
445
|
+
*/
|
|
446
|
+
private stampWorkflow;
|
|
382
447
|
/**
|
|
383
448
|
* Run an item through sampling (errors only) and `beforeSend`, then hand it to
|
|
384
449
|
* the transport. Returns silently when dropped.
|
|
@@ -421,7 +486,7 @@ declare function parseError(err: unknown): Frame[];
|
|
|
421
486
|
/** Small dependency-free helpers shared across the SDK. */
|
|
422
487
|
/** SDK identity, embedded in every envelope header. */
|
|
423
488
|
declare const SDK_NAME = "sauron.javascript";
|
|
424
|
-
declare const SDK_VERSION = "1.
|
|
489
|
+
declare const SDK_VERSION = "1.3.0";
|
|
425
490
|
|
|
426
491
|
/**
|
|
427
492
|
* `@edraj/sauron-browser` — public API surface.
|
|
@@ -452,6 +517,23 @@ declare function trackTransaction(input: TransactionInput): void;
|
|
|
452
517
|
declare function setScreen(name: string): void;
|
|
453
518
|
/** The current screen name, or null. */
|
|
454
519
|
declare function getScreen(): string | null;
|
|
520
|
+
/**
|
|
521
|
+
* Start a named, explicitly-bounded workflow. `workflow_id` is a fresh
|
|
522
|
+
* client-generated UUID; the id + name are then stamped on every subsequent
|
|
523
|
+
* event/error/transaction until the workflow ends or is cancelled. Optional —
|
|
524
|
+
* an app that never calls this behaves exactly as before.
|
|
525
|
+
*/
|
|
526
|
+
declare function startWorkflow(name: string, options?: {
|
|
527
|
+
force?: boolean;
|
|
528
|
+
}): WorkflowResult;
|
|
529
|
+
/** End the active workflow (or the one named `name`, if given). */
|
|
530
|
+
declare function endWorkflow(name?: string): WorkflowResult;
|
|
531
|
+
/** Cancel the active workflow (or the one named `name`, if given). */
|
|
532
|
+
declare function cancelWorkflow(name?: string, options?: {
|
|
533
|
+
reason?: string;
|
|
534
|
+
}): WorkflowResult;
|
|
535
|
+
/** The currently active workflow, or `null` when none is active. */
|
|
536
|
+
declare function getWorkflow(): ActiveWorkflow | null;
|
|
455
537
|
/** Record a breadcrumb. */
|
|
456
538
|
declare function addBreadcrumb(breadcrumb: BreadcrumbInput, hint?: Hint): void;
|
|
457
539
|
/** Set (or clear, with `null`) the current user. */
|
|
@@ -485,9 +567,13 @@ declare const Sauron: {
|
|
|
485
567
|
setExtra: typeof setExtra;
|
|
486
568
|
setScreen: typeof setScreen;
|
|
487
569
|
getScreen: typeof getScreen;
|
|
570
|
+
startWorkflow: typeof startWorkflow;
|
|
571
|
+
endWorkflow: typeof endWorkflow;
|
|
572
|
+
cancelWorkflow: typeof cancelWorkflow;
|
|
573
|
+
getWorkflow: typeof getWorkflow;
|
|
488
574
|
flush: typeof flush;
|
|
489
575
|
close: typeof close;
|
|
490
576
|
getClient: typeof getClient;
|
|
491
577
|
};
|
|
492
578
|
|
|
493
|
-
export { 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, addBreadcrumb, buildEnvelope, captureException, captureMessage, close, Sauron as default, flush, getClient, getScreen, identify, init, isInAppFrame, parseDsn, parseError, parseStackString, setContext, setExtra, setScreen, setTag, setTags, setUser, track, trackTransaction };
|
|
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 };
|
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.3.0";
|
|
8
8
|
function getGlobal() {
|
|
9
9
|
return globalThis;
|
|
10
10
|
}
|
|
@@ -832,6 +832,30 @@ var Scope = class {
|
|
|
832
832
|
}
|
|
833
833
|
};
|
|
834
834
|
|
|
835
|
+
// src/workflow.ts
|
|
836
|
+
var WORKFLOW_NAME_MAX = 120;
|
|
837
|
+
var WORKFLOW_REASON_MAX = 120;
|
|
838
|
+
var current = null;
|
|
839
|
+
function getWorkflow() {
|
|
840
|
+
return current;
|
|
841
|
+
}
|
|
842
|
+
function setWorkflowState(workflow) {
|
|
843
|
+
current = workflow;
|
|
844
|
+
}
|
|
845
|
+
function resetWorkflow() {
|
|
846
|
+
current = null;
|
|
847
|
+
}
|
|
848
|
+
function normalizeWorkflowName(name) {
|
|
849
|
+
if (typeof name !== "string") return null;
|
|
850
|
+
const trimmed = name.trim();
|
|
851
|
+
if (trimmed.length === 0 || trimmed.length > WORKFLOW_NAME_MAX) return null;
|
|
852
|
+
return trimmed;
|
|
853
|
+
}
|
|
854
|
+
function normalizeReason(reason) {
|
|
855
|
+
if (typeof reason !== "string" || reason.trim().length === 0) return "user";
|
|
856
|
+
return reason.trim().slice(0, WORKFLOW_REASON_MAX);
|
|
857
|
+
}
|
|
858
|
+
|
|
835
859
|
// src/api/product.ts
|
|
836
860
|
function track(name, properties = {}, options = {}) {
|
|
837
861
|
const client = getClient();
|
|
@@ -902,6 +926,86 @@ function trackTransaction(input) {
|
|
|
902
926
|
const item = buildTransactionItem(input, client.getDistinctId(), getSessionId());
|
|
903
927
|
client.captureItem(item);
|
|
904
928
|
}
|
|
929
|
+
var NOOP_LOGGER = makeLogger(false);
|
|
930
|
+
function emitWorkflowClose(active, eventName, reason, logger) {
|
|
931
|
+
const properties = {
|
|
932
|
+
workflow_id: active.workflowId,
|
|
933
|
+
workflow_name: active.name,
|
|
934
|
+
duration_ms: Math.max(0, Date.now() - Date.parse(active.startedAt))
|
|
935
|
+
};
|
|
936
|
+
if (eventName === "$workflow_cancel") {
|
|
937
|
+
properties.reason = normalizeReason(reason);
|
|
938
|
+
}
|
|
939
|
+
try {
|
|
940
|
+
track(eventName, properties);
|
|
941
|
+
} catch (err) {
|
|
942
|
+
logger.warn(`${eventName}: failed to emit the lifecycle event`, err);
|
|
943
|
+
} finally {
|
|
944
|
+
resetWorkflow();
|
|
945
|
+
}
|
|
946
|
+
}
|
|
947
|
+
function startWorkflow(name, options) {
|
|
948
|
+
let logger = NOOP_LOGGER;
|
|
949
|
+
try {
|
|
950
|
+
const client = getClient();
|
|
951
|
+
if (!client || !client.isEnabled()) return { status: "disabled" };
|
|
952
|
+
logger = makeLogger(client.options.debug);
|
|
953
|
+
const normalized = normalizeWorkflowName(name);
|
|
954
|
+
if (!normalized) {
|
|
955
|
+
logger.warn("startWorkflow: invalid name", name);
|
|
956
|
+
return { status: "invalid_name" };
|
|
957
|
+
}
|
|
958
|
+
const active = getWorkflow();
|
|
959
|
+
if (active && !options?.force) {
|
|
960
|
+
logger.warn(
|
|
961
|
+
`startWorkflow("${normalized}"): "${active.name}" is already active; pass { force: true } to replace it`
|
|
962
|
+
);
|
|
963
|
+
return { status: "already_active" };
|
|
964
|
+
}
|
|
965
|
+
const workflow = {
|
|
966
|
+
workflowId: uuidv4(),
|
|
967
|
+
name: normalized,
|
|
968
|
+
startedAt: nowIso()
|
|
969
|
+
};
|
|
970
|
+
if (active) emitWorkflowClose(active, "$workflow_cancel", "superseded", logger);
|
|
971
|
+
setWorkflowState(workflow);
|
|
972
|
+
try {
|
|
973
|
+
track("$workflow_start", { workflow_id: workflow.workflowId, workflow_name: workflow.name });
|
|
974
|
+
} catch (err) {
|
|
975
|
+
logger.warn("startWorkflow: failed to emit $workflow_start", err);
|
|
976
|
+
}
|
|
977
|
+
return { status: "ok", workflowId: workflow.workflowId };
|
|
978
|
+
} catch (err) {
|
|
979
|
+
logger.warn("startWorkflow failed", err);
|
|
980
|
+
return { status: "disabled" };
|
|
981
|
+
}
|
|
982
|
+
}
|
|
983
|
+
function closeWorkflow(eventName, name, reason) {
|
|
984
|
+
let logger = NOOP_LOGGER;
|
|
985
|
+
try {
|
|
986
|
+
const client = getClient();
|
|
987
|
+
if (!client || !client.isEnabled()) return { status: "disabled" };
|
|
988
|
+
logger = makeLogger(client.options.debug);
|
|
989
|
+
const active = getWorkflow();
|
|
990
|
+
if (!active) return { status: "not_active" };
|
|
991
|
+
if (name !== void 0 && normalizeWorkflowName(name) !== active.name) {
|
|
992
|
+
logger.warn(`${eventName}: "${name}" does not match active workflow "${active.name}"`);
|
|
993
|
+
return { status: "name_mismatch" };
|
|
994
|
+
}
|
|
995
|
+
const workflowId = active.workflowId;
|
|
996
|
+
emitWorkflowClose(active, eventName, reason, logger);
|
|
997
|
+
return { status: "ok", workflowId };
|
|
998
|
+
} catch (err) {
|
|
999
|
+
logger.warn(`${eventName} failed`, err);
|
|
1000
|
+
return { status: "disabled" };
|
|
1001
|
+
}
|
|
1002
|
+
}
|
|
1003
|
+
function endWorkflow(name) {
|
|
1004
|
+
return closeWorkflow("$workflow_end", name);
|
|
1005
|
+
}
|
|
1006
|
+
function cancelWorkflow(name, options) {
|
|
1007
|
+
return closeWorkflow("$workflow_cancel", name, options?.reason);
|
|
1008
|
+
}
|
|
905
1009
|
|
|
906
1010
|
// src/integrations/performance.ts
|
|
907
1011
|
var PERF_FETCH = "__sauron_perf_fetch__";
|
|
@@ -1354,6 +1458,9 @@ var Transport = class {
|
|
|
1354
1458
|
__publicField(this, "pending", []);
|
|
1355
1459
|
__publicField(this, "timer", null);
|
|
1356
1460
|
__publicField(this, "onlineHandler", null);
|
|
1461
|
+
/** Permanent auto-disable latch, flipped by this transport itself the moment
|
|
1462
|
+
* it classifies a response as 401/403 — it is the source of truth for
|
|
1463
|
+
* {@link isEnabled}, not merely a mirror of something the client decided. */
|
|
1357
1464
|
__publicField(this, "disabled", false);
|
|
1358
1465
|
this.dsn = config.dsn;
|
|
1359
1466
|
this.makeEnvelope = config.makeEnvelope;
|
|
@@ -1401,6 +1508,10 @@ var Transport = class {
|
|
|
1401
1508
|
this.pending = [];
|
|
1402
1509
|
this.stop();
|
|
1403
1510
|
}
|
|
1511
|
+
/** Whether the transport still accepts items (false once auth-disabled by a 401/403). */
|
|
1512
|
+
isEnabled() {
|
|
1513
|
+
return !this.disabled;
|
|
1514
|
+
}
|
|
1404
1515
|
/** Queue an item for the next batch; flush eagerly once the batch is full. */
|
|
1405
1516
|
send(item) {
|
|
1406
1517
|
if (this.disabled) return;
|
|
@@ -1443,6 +1554,7 @@ var Transport = class {
|
|
|
1443
1554
|
return;
|
|
1444
1555
|
case "disable":
|
|
1445
1556
|
this.logger.warn("server rejected credentials; disabling client");
|
|
1557
|
+
this.disable();
|
|
1446
1558
|
this.onDisable();
|
|
1447
1559
|
return;
|
|
1448
1560
|
case "split": {
|
|
@@ -1480,6 +1592,7 @@ var Transport = class {
|
|
|
1480
1592
|
outcome = { action: "retry_backoff" };
|
|
1481
1593
|
}
|
|
1482
1594
|
if (outcome.action === "disable") {
|
|
1595
|
+
this.disable();
|
|
1483
1596
|
this.onDisable();
|
|
1484
1597
|
this.offline.enqueue(json);
|
|
1485
1598
|
return;
|
|
@@ -1645,8 +1758,19 @@ var SauronClient = class {
|
|
|
1645
1758
|
getScope() {
|
|
1646
1759
|
return this.scope;
|
|
1647
1760
|
}
|
|
1761
|
+
/**
|
|
1762
|
+
* False once this client was explicitly disabled/closed, OR once the
|
|
1763
|
+
* transport has auto-disabled itself on a 401/403 (revoked/invalid DSN
|
|
1764
|
+
* key) — computed from the transport's own state on every call, not a
|
|
1765
|
+
* separately mirrored flag, so a propagation regression there cannot leave
|
|
1766
|
+
* this predicate stale. `this.transport` always exists once a client
|
|
1767
|
+
* exists (it is constructed synchronously in the constructor); the
|
|
1768
|
+
* "nothing installed yet" case is instead handled one layer up, by every
|
|
1769
|
+
* module-level API (`startWorkflow`, `track`, ...) treating `getClient() ===
|
|
1770
|
+
* null` as the no-op/disabled case before it ever reaches here.
|
|
1771
|
+
*/
|
|
1648
1772
|
isEnabled() {
|
|
1649
|
-
return this.enabled;
|
|
1773
|
+
return this.enabled && this.transport.isEnabled();
|
|
1650
1774
|
}
|
|
1651
1775
|
/** The current distinct id: the user id when identified, else an anon id. */
|
|
1652
1776
|
getDistinctId() {
|
|
@@ -1668,7 +1792,6 @@ var SauronClient = class {
|
|
|
1668
1792
|
dsn: this.dsn.raw,
|
|
1669
1793
|
sdk: { name: SDK_NAME, version: SDK_VERSION },
|
|
1670
1794
|
sent_at: nowIso(),
|
|
1671
|
-
environment: this.options.environment,
|
|
1672
1795
|
release: this.options.release
|
|
1673
1796
|
};
|
|
1674
1797
|
const context = buildContext(this.options.release, this.scope.getUser());
|
|
@@ -1714,6 +1837,39 @@ var SauronClient = class {
|
|
|
1714
1837
|
item.user = this.scope.getUser();
|
|
1715
1838
|
}
|
|
1716
1839
|
}
|
|
1840
|
+
/**
|
|
1841
|
+
* Stamp the active workflow (if any) onto a signal item.
|
|
1842
|
+
*
|
|
1843
|
+
* Done HERE — the single choke point every capture path funnels through —
|
|
1844
|
+
* rather than at each item-construction site, so a capture path added later
|
|
1845
|
+
* is stamped by construction instead of by remembering to. The keys are
|
|
1846
|
+
* ASSIGNED ONLY when a workflow is active: an item with no workflow keeps
|
|
1847
|
+
* them absent entirely (not present-as-`undefined`), which is what makes
|
|
1848
|
+
* `JSON.stringify` omit them and keeps the no-workflow wire bytes identical
|
|
1849
|
+
* to pre-1.3.0.
|
|
1850
|
+
*
|
|
1851
|
+
* Only error/event/transaction carry `workflow_id`/`workflow_name` columns
|
|
1852
|
+
* server-side — identify and breadcrumb_batch items are deliberately left
|
|
1853
|
+
* alone. An item that already carries an explicit `workflow_id` is left
|
|
1854
|
+
* untouched, matching how `enrichErrorItem` defers to caller-set fields.
|
|
1855
|
+
*/
|
|
1856
|
+
stampWorkflow(item) {
|
|
1857
|
+
if (item.type !== "error" && item.type !== "event" && item.type !== "transaction") return;
|
|
1858
|
+
const hasId = item.workflow_id !== void 0;
|
|
1859
|
+
const hasName = item.workflow_name !== void 0;
|
|
1860
|
+
if (hasId || hasName) {
|
|
1861
|
+
if (hasId !== hasName) {
|
|
1862
|
+
this.logger.warn(
|
|
1863
|
+
"item sets only one of workflow_id/workflow_name; the server treats them as a pair and will drop this attribution. Set both, or neither."
|
|
1864
|
+
);
|
|
1865
|
+
}
|
|
1866
|
+
return;
|
|
1867
|
+
}
|
|
1868
|
+
const workflow = getWorkflow();
|
|
1869
|
+
if (!workflow) return;
|
|
1870
|
+
item.workflow_id = workflow.workflowId;
|
|
1871
|
+
item.workflow_name = workflow.name;
|
|
1872
|
+
}
|
|
1717
1873
|
/**
|
|
1718
1874
|
* Run an item through sampling (errors only) and `beforeSend`, then hand it to
|
|
1719
1875
|
* the transport. Returns silently when dropped.
|
|
@@ -1727,6 +1883,7 @@ var SauronClient = class {
|
|
|
1727
1883
|
}
|
|
1728
1884
|
this.enrichErrorItem(item, hint);
|
|
1729
1885
|
}
|
|
1886
|
+
this.stampWorkflow(item);
|
|
1730
1887
|
let processed = item;
|
|
1731
1888
|
if (this.options.beforeSend) {
|
|
1732
1889
|
try {
|
|
@@ -1763,6 +1920,7 @@ var SauronClient = class {
|
|
|
1763
1920
|
}
|
|
1764
1921
|
onNavigation(null);
|
|
1765
1922
|
resetScreen();
|
|
1923
|
+
resetWorkflow();
|
|
1766
1924
|
unpatchAll();
|
|
1767
1925
|
setDsnHost(null);
|
|
1768
1926
|
this.installed = false;
|
|
@@ -1785,7 +1943,6 @@ function resolveOptions(options) {
|
|
|
1785
1943
|
const t = options.transport ?? {};
|
|
1786
1944
|
return {
|
|
1787
1945
|
dsn: options.dsn,
|
|
1788
|
-
environment: options.environment ?? "production",
|
|
1789
1946
|
release: options.release ?? null,
|
|
1790
1947
|
sampleRate: clamp(options.sampleRate ?? 1, 0, 1),
|
|
1791
1948
|
maxBreadcrumbs: options.maxBreadcrumbs ?? 50,
|
|
@@ -1870,6 +2027,18 @@ function setScreen2(name) {
|
|
|
1870
2027
|
function getScreen2() {
|
|
1871
2028
|
return getScreen();
|
|
1872
2029
|
}
|
|
2030
|
+
function startWorkflow2(name, options) {
|
|
2031
|
+
return startWorkflow(name, options);
|
|
2032
|
+
}
|
|
2033
|
+
function endWorkflow2(name) {
|
|
2034
|
+
return endWorkflow(name);
|
|
2035
|
+
}
|
|
2036
|
+
function cancelWorkflow2(name, options) {
|
|
2037
|
+
return cancelWorkflow(name, options);
|
|
2038
|
+
}
|
|
2039
|
+
function getWorkflow2() {
|
|
2040
|
+
return getWorkflow();
|
|
2041
|
+
}
|
|
1873
2042
|
function addBreadcrumb2(breadcrumb, hint) {
|
|
1874
2043
|
addBreadcrumb(breadcrumb, hint);
|
|
1875
2044
|
}
|
|
@@ -1911,12 +2080,16 @@ var Sauron = {
|
|
|
1911
2080
|
setExtra,
|
|
1912
2081
|
setScreen: setScreen2,
|
|
1913
2082
|
getScreen: getScreen2,
|
|
2083
|
+
startWorkflow: startWorkflow2,
|
|
2084
|
+
endWorkflow: endWorkflow2,
|
|
2085
|
+
cancelWorkflow: cancelWorkflow2,
|
|
2086
|
+
getWorkflow: getWorkflow2,
|
|
1914
2087
|
flush,
|
|
1915
2088
|
close,
|
|
1916
2089
|
getClient
|
|
1917
2090
|
};
|
|
1918
2091
|
var index_default = Sauron;
|
|
1919
2092
|
|
|
1920
|
-
export { DsnError, SDK_NAME, SDK_VERSION, Sauron, SauronClient, addBreadcrumb2 as addBreadcrumb, buildEnvelope, captureException2 as captureException, captureMessage2 as captureMessage, close, index_default as default, flush, getClient, getScreen2 as getScreen, identify2 as identify, init2 as init, isInAppFrame, parseDsn, parseError, parseStackString, setContext, setExtra, setScreen2 as setScreen, setTag, setTags, setUser, track2 as track, trackTransaction2 as trackTransaction };
|
|
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 };
|
|
1921
2094
|
//# sourceMappingURL=index.js.map
|
|
1922
2095
|
//# sourceMappingURL=index.js.map
|