@edraj/sauron-browser 1.5.0 → 1.6.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 +25 -0
- package/README.md +13 -3
- package/dist/index.cjs +8 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +8 -7
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,31 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to `@edraj/sauron-browser` are documented here.
|
|
4
4
|
|
|
5
|
+
## 1.6.0
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- **Navigation direction on history breadcrumbs.** SPA navigation breadcrumbs
|
|
10
|
+
now carry `operation` alongside `from` and `to`: `push` for
|
|
11
|
+
`history.pushState`, `replace` for `history.replaceState`, and `pop` for
|
|
12
|
+
`popstate`. A breadcrumb trail no longer reads the same whether the user
|
|
13
|
+
advanced through a flow or backed out of it.
|
|
14
|
+
|
|
15
|
+
The vocabulary is shared with the Flutter SDK's `SauronNavigatorObserver`
|
|
16
|
+
(`push` / `pop` / `replace` / `remove`), so a trail reads the same whichever
|
|
17
|
+
SDK sent it. `remove` has no web equivalent and is never emitted here.
|
|
18
|
+
|
|
19
|
+
**A forward navigation is recorded as `pop`.** `history.forward()` fires the
|
|
20
|
+
same `popstate` event as `history.back()` and carries nothing to separate
|
|
21
|
+
them, so `pop` means "moved through history" rather than specifically "went
|
|
22
|
+
back". Telling them apart would mean writing a counter into `history.state`,
|
|
23
|
+
which the host app's router also owns — not a trade this SDK makes to
|
|
24
|
+
improve a breadcrumb.
|
|
25
|
+
|
|
26
|
+
No API change: `operation` is added to `data` on breadcrumbs the SDK already
|
|
27
|
+
emitted, and the same-path guard still suppresses a `replaceState` to the
|
|
28
|
+
current URL before any direction is recorded.
|
|
29
|
+
|
|
5
30
|
## 1.5.0
|
|
6
31
|
|
|
7
32
|
### Added
|
package/README.md
CHANGED
|
@@ -985,7 +985,7 @@ const appFrames = frames.filter((f) => isInAppFrame(f.filename));
|
|
|
985
985
|
|
|
986
986
|
```ts
|
|
987
987
|
const SDK_NAME: string // 'sauron.javascript'
|
|
988
|
-
const SDK_VERSION: string // '1.
|
|
988
|
+
const SDK_VERSION: string // '1.6.0'
|
|
989
989
|
```
|
|
990
990
|
|
|
991
991
|
The SDK identity embedded in `header.sdk` of every envelope.
|
|
@@ -1027,7 +1027,7 @@ On by default:
|
|
|
1027
1027
|
| `window.onunhandledrejection` | Error item from `event.reason`, mechanism `{ type: 'onunhandledrejection', handled: false }`, level `error`. |
|
|
1028
1028
|
| `console.log/info/warn/error/debug` | Breadcrumb, category `console`, level mapped (`warn`→`warning`, `error`→`error`, `debug`→`debug`, else `info`), message = arguments joined and truncated to 512 chars, `data: { arguments: n }`. Output is untouched. |
|
|
1029
1029
|
| `document` click listener (capture, passive) | Breadcrumb, category `ui.click`, message = a `tag#id.class` selector (up to 3 classes). Element text and attribute values are never serialized. |
|
|
1030
|
-
| `history.pushState` / `replaceState` / `popstate` | Breadcrumb, type `navigation`, category `history`, `data: { from, to }`
|
|
1030
|
+
| `history.pushState` / `replaceState` / `popstate` | Breadcrumb, type `navigation`, category `history`, `data: { from, to, operation }` — paths plus the direction: `push`, `replace` or `pop`. Same-path transitions are skipped. |
|
|
1031
1031
|
| `fetch` | Breadcrumb, category `fetch`, message `METHOD url`, `data: { method, url, status_code }`, level `warning` for status >= 400. |
|
|
1032
1032
|
| `XMLHttpRequest.prototype.open` / `send` | Breadcrumb, category `xhr`, same shape as `fetch`. |
|
|
1033
1033
|
| `document` `visibilitychange` + window `pagehide` | Beacon flush of the pending batch on unload. |
|
|
@@ -1040,6 +1040,16 @@ Opt-in:
|
|
|
1040
1040
|
| `performance: true` | A `navigation` transaction for the initial page load (Navigation Timing, captured on `load`), an `http` transaction per instrumented `fetch` (`name` = `METHOD /path`, `status` `ok`/`error`), and a `navigation` transaction per SPA route change measured over one animation frame. No-op when `document` is undefined. |
|
|
1041
1041
|
| `screenTracking: true` | Sets the screen to the new path on each SPA History navigation, which emits a `$screen` event on change. |
|
|
1042
1042
|
|
|
1043
|
+
`operation` uses the same vocabulary as the Flutter SDK's
|
|
1044
|
+
`SauronNavigatorObserver` (`push` / `pop` / `replace` / `remove`), so a trail
|
|
1045
|
+
reads the same whichever SDK sent it. `remove` has no web equivalent and is
|
|
1046
|
+
never emitted here. One limit worth knowing: **a forward navigation is recorded
|
|
1047
|
+
as `pop`.** `history.forward()` fires the same `popstate` event as
|
|
1048
|
+
`history.back()` and carries nothing to separate them, so `pop` means "moved
|
|
1049
|
+
through history", not specifically "went back". Distinguishing them would mean
|
|
1050
|
+
writing to `history.state`, which the host app's router also owns — not a
|
|
1051
|
+
trade the SDK makes.
|
|
1052
|
+
|
|
1043
1053
|
Two guards keep the SDK from observing itself: a reentrancy flag held while SDK
|
|
1044
1054
|
code runs, and a denylist on the DSN host. Requests the transport makes are
|
|
1045
1055
|
therefore never turned into breadcrumbs or transactions. Wrappers are tagged, so
|
|
@@ -1116,7 +1126,7 @@ Sauron.track('upgraded', {}, { tags: { tier: 'trial' } });
|
|
|
1116
1126
|
|
|
1117
1127
|
```html
|
|
1118
1128
|
<script type="module">
|
|
1119
|
-
import { Sauron } from 'https://esm.sh/@edraj/sauron-browser@1.
|
|
1129
|
+
import { Sauron } from 'https://esm.sh/@edraj/sauron-browser@1.6.0';
|
|
1120
1130
|
Sauron.init({ dsn: 'https://pk_test@ingest.example.com/42' });
|
|
1121
1131
|
</script>
|
|
1122
1132
|
```
|
package/dist/index.cjs
CHANGED
|
@@ -8,7 +8,7 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
|
|
|
8
8
|
|
|
9
9
|
// src/utils.ts
|
|
10
10
|
var SDK_NAME = "sauron.javascript";
|
|
11
|
-
var SDK_VERSION = "1.
|
|
11
|
+
var SDK_VERSION = "1.6.0";
|
|
12
12
|
function getGlobal() {
|
|
13
13
|
return globalThis;
|
|
14
14
|
}
|
|
@@ -843,12 +843,12 @@ function installHistory() {
|
|
|
843
843
|
const loc = g2.location;
|
|
844
844
|
if (!hist) return;
|
|
845
845
|
let lastPath = toPath(loc?.href ?? null, loc?.href);
|
|
846
|
-
const emit = (toHref) => {
|
|
846
|
+
const emit = (toHref, operation) => {
|
|
847
847
|
const to = toPath(toHref, loc?.href);
|
|
848
848
|
const from = lastPath;
|
|
849
849
|
lastPath = to;
|
|
850
850
|
if (from === to) return;
|
|
851
|
-
withInternal(() => addNavigationBreadcrumb(from, to));
|
|
851
|
+
withInternal(() => addNavigationBreadcrumb(from, to, operation));
|
|
852
852
|
if (to && navHandler) {
|
|
853
853
|
try {
|
|
854
854
|
navHandler(to);
|
|
@@ -859,11 +859,12 @@ function installHistory() {
|
|
|
859
859
|
const wrap = (name) => {
|
|
860
860
|
const original = hist[name];
|
|
861
861
|
if (typeof original !== "function" || isWrapped(original)) return;
|
|
862
|
+
const operation = name === "pushState" ? "push" : "replace";
|
|
862
863
|
hist[name] = markWrapped(function sauronHistory(...args) {
|
|
863
864
|
const result = original.apply(this, args);
|
|
864
865
|
if (!isInternal()) {
|
|
865
866
|
const urlArg = args[2];
|
|
866
|
-
emit(urlArg != null ? String(urlArg) : loc?.href ?? null);
|
|
867
|
+
emit(urlArg != null ? String(urlArg) : loc?.href ?? null, operation);
|
|
867
868
|
}
|
|
868
869
|
return result;
|
|
869
870
|
});
|
|
@@ -875,7 +876,7 @@ function installHistory() {
|
|
|
875
876
|
wrap("replaceState");
|
|
876
877
|
if (typeof g2.addEventListener === "function") {
|
|
877
878
|
const onPopState = () => {
|
|
878
|
-
if (!isInternal()) emit(loc?.href ?? null);
|
|
879
|
+
if (!isInternal()) emit(loc?.href ?? null, "pop");
|
|
879
880
|
};
|
|
880
881
|
g2.addEventListener("popstate", onPopState);
|
|
881
882
|
registerPatch("popstate", () => {
|
|
@@ -2226,13 +2227,13 @@ function addBreadcrumb(input, hint) {
|
|
|
2226
2227
|
if (!client) return;
|
|
2227
2228
|
client.addBreadcrumb(normalizeBreadcrumb(input), hint);
|
|
2228
2229
|
}
|
|
2229
|
-
function addNavigationBreadcrumb(from, to) {
|
|
2230
|
+
function addNavigationBreadcrumb(from, to, operation = "push") {
|
|
2230
2231
|
addBreadcrumb({
|
|
2231
2232
|
type: "navigation",
|
|
2232
2233
|
category: "history",
|
|
2233
2234
|
level: "info",
|
|
2234
2235
|
message: null,
|
|
2235
|
-
data: { from, to }
|
|
2236
|
+
data: { from, to, operation }
|
|
2236
2237
|
});
|
|
2237
2238
|
}
|
|
2238
2239
|
|