@newtalaria/browser 0.1.16 → 0.1.17

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/README.md CHANGED
@@ -193,9 +193,31 @@ Transport failures (CORS, offline, DNS — browser `TypeError: Failed to fetch`)
193
193
 
194
194
  `Network error: POST https://www.google-analytics.com/g/collect — TypeError: Failed to fetch`
195
195
 
196
- **URL privacy:** network telemetry stores `origin + pathname` only (plus `hostname` / `pathname` fields). Query strings and fragments are stripped by default — analytics/ads URLs often carry `cid`, `sid`, `dl`, etc. Set `includeNetworkUrlQuery: true` to keep query params after sensitive-key redaction (`token`, `api_key`, …).
196
+ **URL privacy:** network telemetry stores `origin + pathname` only (plus `hostname` / `pathname`). Query strings and fragments are stripped by default — analytics/ads URLs often carry `cid`, `sid`, `dl`, etc. Set `captureRequestQueryParameters: true` to keep query params after sensitive-key redaction (`token`, `api_key`, …).
197
197
 
198
- Replay `talaria-network` breadcrumbs include method, sanitized URL, status (when an HTTP response exists), duration, and on failures `errorName` / `errorMessage` / `aborted` / `failureKind`. Request/response bodies and auth headers are never captured.
198
+ Both **`fetch`** and **`XMLHttpRequest`** are instrumented (`http.transport`: `fetch` | `xhr`). Failure kinds are only claimed when detectable:
199
+
200
+ | `failure.kind` | Meaning |
201
+ | --- | --- |
202
+ | `http` | Completed response with a real status (e.g. 500) |
203
+ | `network` | No usable HTTP response (status 0 / Failed to fetch) — CORS, block, DNS, offline, etc. |
204
+ | `timeout` | `TimeoutError` or XHR `timeout` event |
205
+ | `abort` | `AbortError` / XHR abort — recorded in breadcrumbs, **not** promoted as events |
206
+
207
+ We **do not** classify status 0 as `cors` — browsers do not expose that reliably.
208
+
209
+ Promoted events use structured `extra`:
210
+
211
+ ```json
212
+ {
213
+ "http": { "method": "GET", "url": "https://ct.pinterest.com/user/", "hostname": "ct.pinterest.com", "pathname": "/user/", "transport": "xhr" },
214
+ "failure": { "kind": "network", "name": "NetworkError", "message": "XMLHttpRequest failed (status 0)" },
215
+ "durationMs": 158,
216
+ "aborted": false
217
+ }
218
+ ```
219
+
220
+ Crawler UAs are tagged (`bot=true`, `bot.name=Baiduspider`) without inventing a browser name.
199
221
 
200
222
  ```ts
201
223
  Talaria.init({
@@ -204,10 +226,10 @@ Talaria.init({
204
226
  environment: 'production',
205
227
  // Default true — HTTP status promotion
206
228
  captureFailedRequests: true,
207
- // Default true — CORS/offline/DNS fetch failures
229
+ // Default true — transport failures (fetch + XHR)
208
230
  captureNetworkErrors: true,
209
231
  // Default false — do not store ?query on network URLs
210
- includeNetworkUrlQuery: false,
232
+ captureRequestQueryParameters: false,
211
233
  // Default [[500, 599]]. CMS admin often wants 4xx too:
212
234
  failedRequestStatusCodes: [[400, 599]],
213
235
  // Extra URL substrings to skip (Talaria /events and /replays are always skipped)
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -98,9 +98,46 @@ function isSdkInternalNoise(opts) {
98
98
  }
99
99
 
100
100
  // src/utils/browser_context.ts
101
+ var BOT_RULES = [
102
+ { name: "Baiduspider", re: /Baiduspider/i },
103
+ { name: "Googlebot", re: /Googlebot/i },
104
+ { name: "Bingbot", re: /bingbot/i },
105
+ { name: "DuckDuckBot", re: /DuckDuckBot/i },
106
+ { name: "YandexBot", re: /Yandex(Bot|Images)/i },
107
+ { name: "Applebot", re: /Applebot/i },
108
+ { name: "facebookexternalhit", re: /facebookexternalhit|Facebot/i },
109
+ { name: "Twitterbot", re: /Twitterbot/i },
110
+ { name: "LinkedInBot", re: /LinkedInBot/i },
111
+ { name: "Slackbot", re: /Slackbot/i },
112
+ { name: "Discordbot", re: /Discordbot/i },
113
+ { name: "Bytespider", re: /Bytespider/i },
114
+ { name: "PetalBot", re: /PetalBot/i },
115
+ { name: "SemrushBot", re: /SemrushBot/i },
116
+ { name: "AhrefsBot", re: /AhrefsBot/i },
117
+ { name: "DotBot", re: /DotBot/i },
118
+ { name: "GPTBot", re: /GPTBot/i },
119
+ { name: "ClaudeBot", re: /ClaudeBot|anthropic-ai/i },
120
+ { name: "Amazonbot", re: /Amazonbot/i },
121
+ { name: "Sogou", re: /Sogou/i },
122
+ // Generic last — still mark as bot without inventing a browser name.
123
+ { name: "bot", re: /\b(?:bot|crawler|spider|slurp)\b/i }
124
+ ];
125
+ function detectBot(ua) {
126
+ if (!ua) return { bot: false };
127
+ for (const rule2 of BOT_RULES) {
128
+ if (rule2.re.test(ua)) {
129
+ return {
130
+ bot: true,
131
+ botName: rule2.name === "bot" ? void 0 : rule2.name
132
+ };
133
+ }
134
+ }
135
+ return { bot: false };
136
+ }
101
137
  function parseBrowserContext(ua = typeof navigator !== "undefined" ? navigator.userAgent : "", language = typeof navigator !== "undefined" ? navigator.language : "") {
102
138
  const userAgent = ua || "";
103
139
  const lang = language || "";
140
+ const botInfo = detectBot(userAgent);
104
141
  let name = "unknown";
105
142
  let version = "";
106
143
  const rules = [
@@ -111,18 +148,20 @@ function parseBrowserContext(ua = typeof navigator !== "undefined" ? navigator.u
111
148
  { name: "Chrome", re: /(?:Chrome|CriOS)\/([\d.]+)/ },
112
149
  { name: "Safari", re: /Version\/([\d.]+).*Safari/ }
113
150
  ];
114
- for (const rule2 of rules) {
115
- const m = userAgent.match(rule2.re);
116
- if (m) {
117
- name = rule2.name;
118
- version = m[1] ?? "";
119
- break;
151
+ if (!botInfo.bot) {
152
+ for (const rule2 of rules) {
153
+ const m = userAgent.match(rule2.re);
154
+ if (m) {
155
+ name = rule2.name;
156
+ version = m[1] ?? "";
157
+ break;
158
+ }
159
+ }
160
+ if (name === "unknown" && /iPhone|iPad|iPod/.test(userAgent) && /AppleWebKit/.test(userAgent)) {
161
+ name = "Safari";
162
+ const m = userAgent.match(/OS ([\d_]+)/);
163
+ if (m?.[1]) version = m[1].replace(/_/g, ".");
120
164
  }
121
- }
122
- if (name === "unknown" && /iPhone|iPad|iPod/.test(userAgent) && /AppleWebKit/.test(userAgent)) {
123
- name = "Safari";
124
- const m = userAgent.match(/OS ([\d_]+)/);
125
- if (m?.[1]) version = m[1].replace(/_/g, ".");
126
165
  }
127
166
  let os = "unknown";
128
167
  let osVersion = "";
@@ -168,7 +207,9 @@ function parseBrowserContext(ua = typeof navigator !== "undefined" ? navigator.u
168
207
  osVersion,
169
208
  device,
170
209
  language: lang,
171
- userAgent
210
+ userAgent,
211
+ bot: botInfo.bot,
212
+ ...botInfo.botName ? { botName: botInfo.botName } : {}
172
213
  };
173
214
  }
174
215
  function browserContextTags(ctx) {
@@ -177,11 +218,16 @@ function browserContextTags(ctx) {
177
218
  "browser.version": ctx.version || "unknown",
178
219
  "os.name": ctx.os,
179
220
  "os.version": ctx.osVersion || "unknown",
180
- device: ctx.device
221
+ device: ctx.device,
222
+ ...ctx.bot ? {
223
+ bot: "true",
224
+ ...ctx.botName ? { "bot.name": ctx.botName } : {}
225
+ } : {}
181
226
  };
182
227
  }
183
228
  async function collectBrowserContext() {
184
229
  const base = parseBrowserContext();
230
+ if (base.bot) return base;
185
231
  const nav = typeof navigator !== "undefined" ? navigator : void 0;
186
232
  const uad = nav?.userAgentData;
187
233
  if (!uad) return base;
@@ -226,7 +272,7 @@ async function collectBrowserContext() {
226
272
 
227
273
  // src/sdk_meta.ts
228
274
  var SDK_NAME = "@newtalaria/browser";
229
- var SDK_VERSION = "0.1.16";
275
+ var SDK_VERSION = "0.1.17";
230
276
 
231
277
  // src/transport/serverpod.ts
232
278
  var ServerpodTransport = class {
@@ -13546,7 +13592,7 @@ function isAbortError(error) {
13546
13592
  }
13547
13593
  function isLikelyNetworkFetchError(error) {
13548
13594
  if (!(error instanceof Error)) return false;
13549
- if (error.name === "AbortError") return false;
13595
+ if (error.name === "AbortError" || error.name === "TimeoutError") return false;
13550
13596
  if (error.name === "NetworkError") return true;
13551
13597
  const msg = error.message.toLowerCase().trim();
13552
13598
  return msg === "failed to fetch" || msg === "load failed" || msg === "networkerror when attempting to fetch resource." || msg.startsWith("networkerror") || msg.includes("failed to fetch");
@@ -13556,15 +13602,22 @@ function describeUnknownError(error) {
13556
13602
  return {
13557
13603
  errorName: error.name || "Error",
13558
13604
  errorMessage: (error.message || "").slice(0, 500),
13559
- aborted: error.name === "AbortError"
13605
+ aborted: error.name === "AbortError",
13606
+ timedOut: error.name === "TimeoutError"
13560
13607
  };
13561
13608
  }
13562
13609
  return {
13563
13610
  errorName: "Error",
13564
13611
  errorMessage: String(error).slice(0, 500),
13565
- aborted: false
13612
+ aborted: false,
13613
+ timedOut: false
13566
13614
  };
13567
13615
  }
13616
+ function classifyTransportFailure(opts) {
13617
+ if (opts.aborted || opts.errorName === "AbortError") return "abort";
13618
+ if (opts.timedOut || opts.errorName === "TimeoutError") return "timeout";
13619
+ return "network";
13620
+ }
13568
13621
 
13569
13622
  // src/replay/hooks.ts
13570
13623
  function installVisibilityResumeHook(onResume) {
@@ -13705,8 +13758,10 @@ function shouldPromoteFailedRequest(meta, opts) {
13705
13758
  }
13706
13759
  function shouldPromoteNetworkError(meta, opts) {
13707
13760
  if (!opts.captureNetworkErrors) return false;
13708
- if (meta.aborted) return false;
13709
- if (meta.failureKind !== "network") return false;
13761
+ if (meta.aborted || meta.failureKind === "abort") return false;
13762
+ if (meta.failureKind !== "network" && meta.failureKind !== "timeout") {
13763
+ return false;
13764
+ }
13710
13765
  const ignore = buildFailedRequestIgnoreUrls(
13711
13766
  opts.failedRequestIgnoreUrls,
13712
13767
  opts.talariaBaseUrl
@@ -13722,10 +13777,15 @@ function enrichNetworkMeta(meta) {
13722
13777
  failureKind: meta.ok === false ? "http" : meta.failureKind
13723
13778
  };
13724
13779
  }
13725
- if (meta.ok === false || meta.errorName || meta.errorMessage) {
13780
+ if (meta.ok === false || meta.errorName || meta.errorMessage || meta.aborted) {
13781
+ const failureKind = meta.failureKind === "abort" || meta.failureKind === "timeout" || meta.failureKind === "network" ? meta.failureKind : classifyTransportFailure({
13782
+ aborted: meta.aborted,
13783
+ errorName: meta.errorName
13784
+ });
13726
13785
  return {
13727
13786
  ...meta,
13728
- failureKind: "network"
13787
+ failureKind,
13788
+ aborted: meta.aborted ?? failureKind === "abort"
13729
13789
  };
13730
13790
  }
13731
13791
  return meta;
@@ -13751,7 +13811,7 @@ function installNetworkHook(options = {}) {
13751
13811
  failedRequestIgnoreUrls: options.failedRequestIgnoreUrls ?? [],
13752
13812
  talariaBaseUrl: options.talariaBaseUrl
13753
13813
  };
13754
- const includeQuery = options.includeNetworkUrlQuery ?? false;
13814
+ const includeQuery = options.captureRequestQueryParameters ?? options.includeNetworkUrlQuery ?? false;
13755
13815
  const handleMeta = (meta) => {
13756
13816
  const { rawUrl, ...rest } = meta;
13757
13817
  const enriched = enrichNetworkMeta({
@@ -13780,6 +13840,7 @@ function installNetworkHook(options = {}) {
13780
13840
  method,
13781
13841
  rawUrl,
13782
13842
  url: rawUrl,
13843
+ transport: "fetch",
13783
13844
  status: response.status,
13784
13845
  durationMs: Date.now() - started,
13785
13846
  ok: response.ok
@@ -13787,16 +13848,18 @@ function installNetworkHook(options = {}) {
13787
13848
  return response;
13788
13849
  } catch (error) {
13789
13850
  const described = describeUnknownError(error);
13851
+ const failureKind = classifyTransportFailure(described);
13790
13852
  handleMeta({
13791
13853
  method,
13792
13854
  rawUrl,
13793
13855
  url: rawUrl,
13856
+ transport: "fetch",
13794
13857
  durationMs: Date.now() - started,
13795
13858
  ok: false,
13796
13859
  errorName: described.errorName,
13797
13860
  errorMessage: described.errorMessage,
13798
13861
  aborted: described.aborted,
13799
- failureKind: "network"
13862
+ failureKind
13800
13863
  });
13801
13864
  throw error;
13802
13865
  }
@@ -13810,21 +13873,44 @@ function installNetworkHook(options = {}) {
13810
13873
  };
13811
13874
  XHR.prototype.send = function(body) {
13812
13875
  this.__talariaStarted = Date.now();
13876
+ this.__talariaTimedOut = false;
13877
+ this.__talariaAborted = false;
13878
+ this.addEventListener(
13879
+ "timeout",
13880
+ () => {
13881
+ this.__talariaTimedOut = true;
13882
+ },
13883
+ { once: true }
13884
+ );
13885
+ this.addEventListener(
13886
+ "abort",
13887
+ () => {
13888
+ this.__talariaAborted = true;
13889
+ },
13890
+ { once: true }
13891
+ );
13813
13892
  const onDone = () => {
13814
13893
  const status = this.status;
13815
- const networkFail = status === 0;
13894
+ const transportFail = status === 0;
13816
13895
  const rawUrl = this.__talariaUrl ?? "";
13896
+ const aborted = !!this.__talariaAborted;
13897
+ const timedOut = !!this.__talariaTimedOut;
13898
+ const failureKind = transportFail ? classifyTransportFailure({ aborted, timedOut }) : void 0;
13899
+ const errorName = transportFail ? failureKind === "abort" ? "AbortError" : failureKind === "timeout" ? "TimeoutError" : "NetworkError" : void 0;
13900
+ const errorMessage = transportFail ? failureKind === "abort" ? "XMLHttpRequest aborted" : failureKind === "timeout" ? "XMLHttpRequest timed out" : "XMLHttpRequest failed (status 0)" : void 0;
13817
13901
  handleMeta({
13818
13902
  method: this.__talariaMethod ?? "GET",
13819
13903
  rawUrl,
13820
13904
  url: rawUrl,
13905
+ transport: "xhr",
13821
13906
  status,
13822
13907
  durationMs: Date.now() - (this.__talariaStarted ?? Date.now()),
13823
13908
  ok: status >= 200 && status < 400,
13824
- ...networkFail ? {
13825
- failureKind: "network",
13826
- errorName: "NetworkError",
13827
- errorMessage: "XMLHttpRequest failed (status 0)"
13909
+ ...transportFail ? {
13910
+ failureKind,
13911
+ errorName,
13912
+ errorMessage,
13913
+ aborted
13828
13914
  } : {}
13829
13915
  });
13830
13916
  };
@@ -13840,20 +13926,37 @@ function installNetworkHook(options = {}) {
13840
13926
  }
13841
13927
 
13842
13928
  // src/client.ts
13843
- function networkFailureExtra(failure) {
13929
+ function networkFailureTags(failure) {
13844
13930
  return {
13931
+ "http.method": failure.method || "GET",
13932
+ "network.failure_kind": failure.failureKind ?? "network",
13933
+ ...failure.transport ? { "network.transport": failure.transport } : {},
13934
+ ...failure.errorName ? { "network.error_name": failure.errorName } : {}
13935
+ };
13936
+ }
13937
+ function networkFailureExtra(failure) {
13938
+ const http = {
13845
13939
  method: failure.method || "GET",
13846
- url: failure.url || "(unknown url)",
13847
- ...failure.hostname ? { hostname: failure.hostname } : {},
13848
- ...failure.pathname ? { pathname: failure.pathname } : {},
13849
- ...failure.search ? { search: failure.search } : {},
13850
- ...typeof failure.status === "number" ? { status: failure.status } : {},
13940
+ url: failure.url || "(unknown url)"
13941
+ };
13942
+ if (failure.hostname) http.hostname = failure.hostname;
13943
+ if (failure.pathname) http.pathname = failure.pathname;
13944
+ if (failure.search) http.search = failure.search;
13945
+ if (typeof failure.status === "number" && failure.status > 0) {
13946
+ http.status = failure.status;
13947
+ }
13948
+ if (failure.transport) http.transport = failure.transport;
13949
+ const fail = {
13950
+ kind: failure.failureKind ?? "network"
13951
+ };
13952
+ if (failure.errorName) fail.name = failure.errorName;
13953
+ if (failure.errorMessage) fail.message = failure.errorMessage;
13954
+ return {
13955
+ http,
13956
+ failure: fail,
13851
13957
  durationMs: failure.durationMs,
13852
- ok: failure.ok ?? false,
13853
- failureKind: failure.failureKind ?? "network",
13854
13958
  aborted: failure.aborted ?? false,
13855
- ...failure.errorName ? { errorName: failure.errorName } : {},
13856
- ...failure.errorMessage ? { errorMessage: failure.errorMessage } : {}
13959
+ ok: failure.ok ?? false
13857
13960
  };
13858
13961
  }
13859
13962
  function mergeNetworkFailureContext(context, failure) {
@@ -13861,13 +13964,11 @@ function mergeNetworkFailureContext(context, failure) {
13861
13964
  ...context,
13862
13965
  tags: {
13863
13966
  ...context?.tags ?? {},
13864
- "http.method": failure.method || "GET",
13865
- "network.failure_kind": "network",
13866
- ...failure.errorName ? { "network.error_name": failure.errorName } : {}
13967
+ ...networkFailureTags(failure)
13867
13968
  },
13868
13969
  extra: {
13869
13970
  ...context?.extra ?? {},
13870
- network: networkFailureExtra(failure)
13971
+ ...networkFailureExtra(failure)
13871
13972
  }
13872
13973
  };
13873
13974
  }
@@ -13898,7 +13999,7 @@ function resolveOptions(options) {
13898
13999
  disableDefaultIntegrations: options.disableDefaultIntegrations ?? false,
13899
14000
  captureFailedRequests: options.captureFailedRequests ?? true,
13900
14001
  captureNetworkErrors: options.captureNetworkErrors ?? true,
13901
- includeNetworkUrlQuery: options.includeNetworkUrlQuery ?? false,
14002
+ includeNetworkUrlQuery: options.captureRequestQueryParameters ?? options.includeNetworkUrlQuery ?? false,
13902
14003
  failedRequestStatusCodes: options.failedRequestStatusCodes ?? [[500, 599]],
13903
14004
  failedRequestIgnoreUrls: options.failedRequestIgnoreUrls ?? []
13904
14005
  };
@@ -14032,7 +14133,7 @@ var TalariaClient = class {
14032
14133
  failedRequestIgnoreUrls: this.options.failedRequestIgnoreUrls,
14033
14134
  talariaBaseUrl: this.options.baseUrl,
14034
14135
  onNetwork: (meta) => {
14035
- if (meta.failureKind === "network" && !meta.aborted) {
14136
+ if ((meta.failureKind === "network" || meta.failureKind === "timeout") && !meta.aborted) {
14036
14137
  this.rememberNetworkFailure(meta, { promoted: false });
14037
14138
  }
14038
14139
  },
@@ -14040,22 +14141,20 @@ var TalariaClient = class {
14040
14141
  const status = meta.status;
14041
14142
  const method = meta.method || "GET";
14042
14143
  const url = meta.url || "(unknown url)";
14144
+ const enriched = {
14145
+ ...meta,
14146
+ failureKind: "http",
14147
+ aborted: false
14148
+ };
14043
14149
  void this.captureMessage(
14044
14150
  `HTTP ${status}: ${method} ${url}`,
14045
14151
  status >= 500 ? "error" : "warning",
14046
14152
  {
14047
14153
  tags: {
14048
- "http.status_code": String(status),
14049
- "http.method": method,
14050
- "network.failure_kind": "http"
14154
+ ...networkFailureTags(enriched),
14155
+ "http.status_code": String(status)
14051
14156
  },
14052
- extra: {
14053
- ...networkFailureExtra({
14054
- ...meta,
14055
- failureKind: "http",
14056
- aborted: false
14057
- })
14058
- }
14157
+ extra: networkFailureExtra(enriched)
14059
14158
  }
14060
14159
  );
14061
14160
  },
@@ -14064,20 +14163,13 @@ var TalariaClient = class {
14064
14163
  const method = meta.method || "GET";
14065
14164
  const url = meta.url || "(unknown url)";
14066
14165
  const errLabel = meta.errorName && meta.errorMessage ? `${meta.errorName}: ${meta.errorMessage}` : meta.errorMessage || meta.errorName || "Failed to fetch";
14166
+ const prefix = meta.failureKind === "timeout" ? "Timeout error" : "Network error";
14067
14167
  void this.captureMessage(
14068
- `Network error: ${method} ${url} \u2014 ${errLabel}`,
14168
+ `${prefix}: ${method} ${url} \u2014 ${errLabel}`,
14069
14169
  "error",
14070
14170
  {
14071
- tags: {
14072
- "http.method": method,
14073
- "network.failure_kind": "network",
14074
- ...meta.errorName ? { "network.error_name": meta.errorName } : {}
14075
- },
14076
- extra: networkFailureExtra({
14077
- ...meta,
14078
- failureKind: "network",
14079
- aborted: false
14080
- })
14171
+ tags: networkFailureTags(meta),
14172
+ extra: networkFailureExtra(meta)
14081
14173
  }
14082
14174
  );
14083
14175
  }
@@ -14333,7 +14425,9 @@ var TalariaClient = class {
14333
14425
  osVersion: this.browserContext.osVersion,
14334
14426
  device: this.browserContext.device,
14335
14427
  language: this.browserContext.language,
14336
- userAgent: this.browserContext.userAgent
14428
+ userAgent: this.browserContext.userAgent,
14429
+ bot: this.browserContext.bot,
14430
+ ...this.browserContext.botName ? { botName: this.browserContext.botName } : {}
14337
14431
  }
14338
14432
  } : {},
14339
14433
  sdk: {