@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.
@@ -1,4 +1,12 @@
1
1
  import type { FailedRequestStatusCode } from '../types.js';
2
+ /** How the request was issued. */
3
+ export type NetworkTransport = 'fetch' | 'xhr';
4
+ /**
5
+ * Failure classification for network telemetry.
6
+ * `cors` is intentionally absent — browsers do not expose CORS reliably
7
+ * (status 0 / Failed to fetch cover many causes).
8
+ */
9
+ export type NetworkFailureKind = 'http' | 'network' | 'abort' | 'timeout';
2
10
  export type Teardown = () => void;
3
11
  /**
4
12
  * Fire when the document becomes visible again (tab focus) or is restored
@@ -12,17 +20,17 @@ export interface NetworkMeta {
12
20
  url: string;
13
21
  hostname?: string;
14
22
  pathname?: string;
15
- /** Only when `includeNetworkUrlQuery` is enabled. */
23
+ /** Only when query capture is enabled. */
16
24
  search?: string;
17
25
  status?: number;
18
26
  durationMs?: number;
19
27
  ok?: boolean;
28
+ transport?: NetworkTransport;
20
29
  /** Present on transport failures (fetch reject / XHR status 0). */
21
30
  errorName?: string;
22
31
  errorMessage?: string;
23
32
  aborted?: boolean;
24
- /** `http` = completed response with status; `network` = no usable status. */
25
- failureKind?: 'http' | 'network';
33
+ failureKind?: NetworkFailureKind;
26
34
  }
27
35
  export interface NetworkHookOptions {
28
36
  /** Still emit rrweb breadcrumbs for all requests. */
@@ -44,9 +52,11 @@ export interface NetworkHookOptions {
44
52
  captureNetworkErrors?: boolean;
45
53
  /**
46
54
  * Keep URL query strings in network telemetry (after sensitive-key redaction).
47
- * Default `false` GA/ads URLs often carry cid/sid/dl identifiers.
55
+ * Default `false`. Prefer `captureRequestQueryParameters` (same meaning).
48
56
  */
49
57
  includeNetworkUrlQuery?: boolean;
58
+ /** Alias of `includeNetworkUrlQuery` — privacy-preserving default is `false`. */
59
+ captureRequestQueryParameters?: boolean;
50
60
  failedRequestStatusCodes?: FailedRequestStatusCode[];
51
61
  failedRequestIgnoreUrls?: string[];
52
62
  /** SDK base URL — requests under this host + /events|/replays are never promoted. */
@@ -67,8 +77,8 @@ export declare function shouldPromoteFailedRequest(meta: NetworkMeta, opts: {
67
77
  status: number;
68
78
  };
69
79
  /**
70
- * Promote fetch rejects / XHR status-0 failures (CORS, offline, DNS).
71
- * AbortError is never promoted.
80
+ * Promote fetch rejects / XHR status-0 failures (offline, DNS, blocked, etc.).
81
+ * Abort is never promoted; timeout may be promoted as `failureKind: timeout`.
72
82
  */
73
83
  export declare function shouldPromoteNetworkError(meta: NetworkMeta, opts: {
74
84
  captureNetworkErrors: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../../src/replay/hooks.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../../src/replay/hooks.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
1
  /** Bumped with package.json version for event metadata. */
2
2
  export declare const SDK_NAME = "@newtalaria/browser";
3
- export declare const SDK_VERSION = "0.1.16";
3
+ export declare const SDK_VERSION = "0.1.17";
4
4
  //# sourceMappingURL=sdk_meta.d.ts.map
@@ -100,9 +100,46 @@
100
100
  }
101
101
 
102
102
  // src/utils/browser_context.ts
103
+ var BOT_RULES = [
104
+ { name: "Baiduspider", re: /Baiduspider/i },
105
+ { name: "Googlebot", re: /Googlebot/i },
106
+ { name: "Bingbot", re: /bingbot/i },
107
+ { name: "DuckDuckBot", re: /DuckDuckBot/i },
108
+ { name: "YandexBot", re: /Yandex(Bot|Images)/i },
109
+ { name: "Applebot", re: /Applebot/i },
110
+ { name: "facebookexternalhit", re: /facebookexternalhit|Facebot/i },
111
+ { name: "Twitterbot", re: /Twitterbot/i },
112
+ { name: "LinkedInBot", re: /LinkedInBot/i },
113
+ { name: "Slackbot", re: /Slackbot/i },
114
+ { name: "Discordbot", re: /Discordbot/i },
115
+ { name: "Bytespider", re: /Bytespider/i },
116
+ { name: "PetalBot", re: /PetalBot/i },
117
+ { name: "SemrushBot", re: /SemrushBot/i },
118
+ { name: "AhrefsBot", re: /AhrefsBot/i },
119
+ { name: "DotBot", re: /DotBot/i },
120
+ { name: "GPTBot", re: /GPTBot/i },
121
+ { name: "ClaudeBot", re: /ClaudeBot|anthropic-ai/i },
122
+ { name: "Amazonbot", re: /Amazonbot/i },
123
+ { name: "Sogou", re: /Sogou/i },
124
+ // Generic last — still mark as bot without inventing a browser name.
125
+ { name: "bot", re: /\b(?:bot|crawler|spider|slurp)\b/i }
126
+ ];
127
+ function detectBot(ua) {
128
+ if (!ua) return { bot: false };
129
+ for (const rule2 of BOT_RULES) {
130
+ if (rule2.re.test(ua)) {
131
+ return {
132
+ bot: true,
133
+ botName: rule2.name === "bot" ? void 0 : rule2.name
134
+ };
135
+ }
136
+ }
137
+ return { bot: false };
138
+ }
103
139
  function parseBrowserContext(ua = typeof navigator !== "undefined" ? navigator.userAgent : "", language = typeof navigator !== "undefined" ? navigator.language : "") {
104
140
  const userAgent = ua || "";
105
141
  const lang = language || "";
142
+ const botInfo = detectBot(userAgent);
106
143
  let name = "unknown";
107
144
  let version = "";
108
145
  const rules = [
@@ -113,18 +150,20 @@
113
150
  { name: "Chrome", re: /(?:Chrome|CriOS)\/([\d.]+)/ },
114
151
  { name: "Safari", re: /Version\/([\d.]+).*Safari/ }
115
152
  ];
116
- for (const rule2 of rules) {
117
- const m = userAgent.match(rule2.re);
118
- if (m) {
119
- name = rule2.name;
120
- version = m[1] ?? "";
121
- break;
153
+ if (!botInfo.bot) {
154
+ for (const rule2 of rules) {
155
+ const m = userAgent.match(rule2.re);
156
+ if (m) {
157
+ name = rule2.name;
158
+ version = m[1] ?? "";
159
+ break;
160
+ }
161
+ }
162
+ if (name === "unknown" && /iPhone|iPad|iPod/.test(userAgent) && /AppleWebKit/.test(userAgent)) {
163
+ name = "Safari";
164
+ const m = userAgent.match(/OS ([\d_]+)/);
165
+ if (m?.[1]) version = m[1].replace(/_/g, ".");
122
166
  }
123
- }
124
- if (name === "unknown" && /iPhone|iPad|iPod/.test(userAgent) && /AppleWebKit/.test(userAgent)) {
125
- name = "Safari";
126
- const m = userAgent.match(/OS ([\d_]+)/);
127
- if (m?.[1]) version = m[1].replace(/_/g, ".");
128
167
  }
129
168
  let os = "unknown";
130
169
  let osVersion = "";
@@ -170,7 +209,9 @@
170
209
  osVersion,
171
210
  device,
172
211
  language: lang,
173
- userAgent
212
+ userAgent,
213
+ bot: botInfo.bot,
214
+ ...botInfo.botName ? { botName: botInfo.botName } : {}
174
215
  };
175
216
  }
176
217
  function browserContextTags(ctx) {
@@ -179,11 +220,16 @@
179
220
  "browser.version": ctx.version || "unknown",
180
221
  "os.name": ctx.os,
181
222
  "os.version": ctx.osVersion || "unknown",
182
- device: ctx.device
223
+ device: ctx.device,
224
+ ...ctx.bot ? {
225
+ bot: "true",
226
+ ...ctx.botName ? { "bot.name": ctx.botName } : {}
227
+ } : {}
183
228
  };
184
229
  }
185
230
  async function collectBrowserContext() {
186
231
  const base = parseBrowserContext();
232
+ if (base.bot) return base;
187
233
  const nav = typeof navigator !== "undefined" ? navigator : void 0;
188
234
  const uad = nav?.userAgentData;
189
235
  if (!uad) return base;
@@ -228,7 +274,7 @@
228
274
 
229
275
  // src/sdk_meta.ts
230
276
  var SDK_NAME = "@newtalaria/browser";
231
- var SDK_VERSION = "0.1.16";
277
+ var SDK_VERSION = "0.1.17";
232
278
 
233
279
  // src/transport/serverpod.ts
234
280
  var ServerpodTransport = class {
@@ -13548,7 +13594,7 @@
13548
13594
  }
13549
13595
  function isLikelyNetworkFetchError(error) {
13550
13596
  if (!(error instanceof Error)) return false;
13551
- if (error.name === "AbortError") return false;
13597
+ if (error.name === "AbortError" || error.name === "TimeoutError") return false;
13552
13598
  if (error.name === "NetworkError") return true;
13553
13599
  const msg = error.message.toLowerCase().trim();
13554
13600
  return msg === "failed to fetch" || msg === "load failed" || msg === "networkerror when attempting to fetch resource." || msg.startsWith("networkerror") || msg.includes("failed to fetch");
@@ -13558,15 +13604,22 @@
13558
13604
  return {
13559
13605
  errorName: error.name || "Error",
13560
13606
  errorMessage: (error.message || "").slice(0, 500),
13561
- aborted: error.name === "AbortError"
13607
+ aborted: error.name === "AbortError",
13608
+ timedOut: error.name === "TimeoutError"
13562
13609
  };
13563
13610
  }
13564
13611
  return {
13565
13612
  errorName: "Error",
13566
13613
  errorMessage: String(error).slice(0, 500),
13567
- aborted: false
13614
+ aborted: false,
13615
+ timedOut: false
13568
13616
  };
13569
13617
  }
13618
+ function classifyTransportFailure(opts) {
13619
+ if (opts.aborted || opts.errorName === "AbortError") return "abort";
13620
+ if (opts.timedOut || opts.errorName === "TimeoutError") return "timeout";
13621
+ return "network";
13622
+ }
13570
13623
 
13571
13624
  // src/replay/hooks.ts
13572
13625
  function installVisibilityResumeHook(onResume) {
@@ -13707,8 +13760,10 @@
13707
13760
  }
13708
13761
  function shouldPromoteNetworkError(meta, opts) {
13709
13762
  if (!opts.captureNetworkErrors) return false;
13710
- if (meta.aborted) return false;
13711
- if (meta.failureKind !== "network") return false;
13763
+ if (meta.aborted || meta.failureKind === "abort") return false;
13764
+ if (meta.failureKind !== "network" && meta.failureKind !== "timeout") {
13765
+ return false;
13766
+ }
13712
13767
  const ignore = buildFailedRequestIgnoreUrls(
13713
13768
  opts.failedRequestIgnoreUrls,
13714
13769
  opts.talariaBaseUrl
@@ -13724,10 +13779,15 @@
13724
13779
  failureKind: meta.ok === false ? "http" : meta.failureKind
13725
13780
  };
13726
13781
  }
13727
- if (meta.ok === false || meta.errorName || meta.errorMessage) {
13782
+ if (meta.ok === false || meta.errorName || meta.errorMessage || meta.aborted) {
13783
+ const failureKind = meta.failureKind === "abort" || meta.failureKind === "timeout" || meta.failureKind === "network" ? meta.failureKind : classifyTransportFailure({
13784
+ aborted: meta.aborted,
13785
+ errorName: meta.errorName
13786
+ });
13728
13787
  return {
13729
13788
  ...meta,
13730
- failureKind: "network"
13789
+ failureKind,
13790
+ aborted: meta.aborted ?? failureKind === "abort"
13731
13791
  };
13732
13792
  }
13733
13793
  return meta;
@@ -13753,7 +13813,7 @@
13753
13813
  failedRequestIgnoreUrls: options.failedRequestIgnoreUrls ?? [],
13754
13814
  talariaBaseUrl: options.talariaBaseUrl
13755
13815
  };
13756
- const includeQuery = options.includeNetworkUrlQuery ?? false;
13816
+ const includeQuery = options.captureRequestQueryParameters ?? options.includeNetworkUrlQuery ?? false;
13757
13817
  const handleMeta = (meta) => {
13758
13818
  const { rawUrl, ...rest } = meta;
13759
13819
  const enriched = enrichNetworkMeta({
@@ -13782,6 +13842,7 @@
13782
13842
  method,
13783
13843
  rawUrl,
13784
13844
  url: rawUrl,
13845
+ transport: "fetch",
13785
13846
  status: response.status,
13786
13847
  durationMs: Date.now() - started,
13787
13848
  ok: response.ok
@@ -13789,16 +13850,18 @@
13789
13850
  return response;
13790
13851
  } catch (error) {
13791
13852
  const described = describeUnknownError(error);
13853
+ const failureKind = classifyTransportFailure(described);
13792
13854
  handleMeta({
13793
13855
  method,
13794
13856
  rawUrl,
13795
13857
  url: rawUrl,
13858
+ transport: "fetch",
13796
13859
  durationMs: Date.now() - started,
13797
13860
  ok: false,
13798
13861
  errorName: described.errorName,
13799
13862
  errorMessage: described.errorMessage,
13800
13863
  aborted: described.aborted,
13801
- failureKind: "network"
13864
+ failureKind
13802
13865
  });
13803
13866
  throw error;
13804
13867
  }
@@ -13812,21 +13875,44 @@
13812
13875
  };
13813
13876
  XHR.prototype.send = function(body) {
13814
13877
  this.__talariaStarted = Date.now();
13878
+ this.__talariaTimedOut = false;
13879
+ this.__talariaAborted = false;
13880
+ this.addEventListener(
13881
+ "timeout",
13882
+ () => {
13883
+ this.__talariaTimedOut = true;
13884
+ },
13885
+ { once: true }
13886
+ );
13887
+ this.addEventListener(
13888
+ "abort",
13889
+ () => {
13890
+ this.__talariaAborted = true;
13891
+ },
13892
+ { once: true }
13893
+ );
13815
13894
  const onDone = () => {
13816
13895
  const status = this.status;
13817
- const networkFail = status === 0;
13896
+ const transportFail = status === 0;
13818
13897
  const rawUrl = this.__talariaUrl ?? "";
13898
+ const aborted = !!this.__talariaAborted;
13899
+ const timedOut = !!this.__talariaTimedOut;
13900
+ const failureKind = transportFail ? classifyTransportFailure({ aborted, timedOut }) : void 0;
13901
+ const errorName = transportFail ? failureKind === "abort" ? "AbortError" : failureKind === "timeout" ? "TimeoutError" : "NetworkError" : void 0;
13902
+ const errorMessage = transportFail ? failureKind === "abort" ? "XMLHttpRequest aborted" : failureKind === "timeout" ? "XMLHttpRequest timed out" : "XMLHttpRequest failed (status 0)" : void 0;
13819
13903
  handleMeta({
13820
13904
  method: this.__talariaMethod ?? "GET",
13821
13905
  rawUrl,
13822
13906
  url: rawUrl,
13907
+ transport: "xhr",
13823
13908
  status,
13824
13909
  durationMs: Date.now() - (this.__talariaStarted ?? Date.now()),
13825
13910
  ok: status >= 200 && status < 400,
13826
- ...networkFail ? {
13827
- failureKind: "network",
13828
- errorName: "NetworkError",
13829
- errorMessage: "XMLHttpRequest failed (status 0)"
13911
+ ...transportFail ? {
13912
+ failureKind,
13913
+ errorName,
13914
+ errorMessage,
13915
+ aborted
13830
13916
  } : {}
13831
13917
  });
13832
13918
  };
@@ -13842,20 +13928,37 @@
13842
13928
  }
13843
13929
 
13844
13930
  // src/client.ts
13845
- function networkFailureExtra(failure) {
13931
+ function networkFailureTags(failure) {
13846
13932
  return {
13933
+ "http.method": failure.method || "GET",
13934
+ "network.failure_kind": failure.failureKind ?? "network",
13935
+ ...failure.transport ? { "network.transport": failure.transport } : {},
13936
+ ...failure.errorName ? { "network.error_name": failure.errorName } : {}
13937
+ };
13938
+ }
13939
+ function networkFailureExtra(failure) {
13940
+ const http = {
13847
13941
  method: failure.method || "GET",
13848
- url: failure.url || "(unknown url)",
13849
- ...failure.hostname ? { hostname: failure.hostname } : {},
13850
- ...failure.pathname ? { pathname: failure.pathname } : {},
13851
- ...failure.search ? { search: failure.search } : {},
13852
- ...typeof failure.status === "number" ? { status: failure.status } : {},
13942
+ url: failure.url || "(unknown url)"
13943
+ };
13944
+ if (failure.hostname) http.hostname = failure.hostname;
13945
+ if (failure.pathname) http.pathname = failure.pathname;
13946
+ if (failure.search) http.search = failure.search;
13947
+ if (typeof failure.status === "number" && failure.status > 0) {
13948
+ http.status = failure.status;
13949
+ }
13950
+ if (failure.transport) http.transport = failure.transport;
13951
+ const fail = {
13952
+ kind: failure.failureKind ?? "network"
13953
+ };
13954
+ if (failure.errorName) fail.name = failure.errorName;
13955
+ if (failure.errorMessage) fail.message = failure.errorMessage;
13956
+ return {
13957
+ http,
13958
+ failure: fail,
13853
13959
  durationMs: failure.durationMs,
13854
- ok: failure.ok ?? false,
13855
- failureKind: failure.failureKind ?? "network",
13856
13960
  aborted: failure.aborted ?? false,
13857
- ...failure.errorName ? { errorName: failure.errorName } : {},
13858
- ...failure.errorMessage ? { errorMessage: failure.errorMessage } : {}
13961
+ ok: failure.ok ?? false
13859
13962
  };
13860
13963
  }
13861
13964
  function mergeNetworkFailureContext(context, failure) {
@@ -13863,13 +13966,11 @@
13863
13966
  ...context,
13864
13967
  tags: {
13865
13968
  ...context?.tags ?? {},
13866
- "http.method": failure.method || "GET",
13867
- "network.failure_kind": "network",
13868
- ...failure.errorName ? { "network.error_name": failure.errorName } : {}
13969
+ ...networkFailureTags(failure)
13869
13970
  },
13870
13971
  extra: {
13871
13972
  ...context?.extra ?? {},
13872
- network: networkFailureExtra(failure)
13973
+ ...networkFailureExtra(failure)
13873
13974
  }
13874
13975
  };
13875
13976
  }
@@ -13900,7 +14001,7 @@
13900
14001
  disableDefaultIntegrations: options.disableDefaultIntegrations ?? false,
13901
14002
  captureFailedRequests: options.captureFailedRequests ?? true,
13902
14003
  captureNetworkErrors: options.captureNetworkErrors ?? true,
13903
- includeNetworkUrlQuery: options.includeNetworkUrlQuery ?? false,
14004
+ includeNetworkUrlQuery: options.captureRequestQueryParameters ?? options.includeNetworkUrlQuery ?? false,
13904
14005
  failedRequestStatusCodes: options.failedRequestStatusCodes ?? [[500, 599]],
13905
14006
  failedRequestIgnoreUrls: options.failedRequestIgnoreUrls ?? []
13906
14007
  };
@@ -14034,7 +14135,7 @@
14034
14135
  failedRequestIgnoreUrls: this.options.failedRequestIgnoreUrls,
14035
14136
  talariaBaseUrl: this.options.baseUrl,
14036
14137
  onNetwork: (meta) => {
14037
- if (meta.failureKind === "network" && !meta.aborted) {
14138
+ if ((meta.failureKind === "network" || meta.failureKind === "timeout") && !meta.aborted) {
14038
14139
  this.rememberNetworkFailure(meta, { promoted: false });
14039
14140
  }
14040
14141
  },
@@ -14042,22 +14143,20 @@
14042
14143
  const status = meta.status;
14043
14144
  const method = meta.method || "GET";
14044
14145
  const url = meta.url || "(unknown url)";
14146
+ const enriched = {
14147
+ ...meta,
14148
+ failureKind: "http",
14149
+ aborted: false
14150
+ };
14045
14151
  void this.captureMessage(
14046
14152
  `HTTP ${status}: ${method} ${url}`,
14047
14153
  status >= 500 ? "error" : "warning",
14048
14154
  {
14049
14155
  tags: {
14050
- "http.status_code": String(status),
14051
- "http.method": method,
14052
- "network.failure_kind": "http"
14156
+ ...networkFailureTags(enriched),
14157
+ "http.status_code": String(status)
14053
14158
  },
14054
- extra: {
14055
- ...networkFailureExtra({
14056
- ...meta,
14057
- failureKind: "http",
14058
- aborted: false
14059
- })
14060
- }
14159
+ extra: networkFailureExtra(enriched)
14061
14160
  }
14062
14161
  );
14063
14162
  },
@@ -14066,20 +14165,13 @@
14066
14165
  const method = meta.method || "GET";
14067
14166
  const url = meta.url || "(unknown url)";
14068
14167
  const errLabel = meta.errorName && meta.errorMessage ? `${meta.errorName}: ${meta.errorMessage}` : meta.errorMessage || meta.errorName || "Failed to fetch";
14168
+ const prefix = meta.failureKind === "timeout" ? "Timeout error" : "Network error";
14069
14169
  void this.captureMessage(
14070
- `Network error: ${method} ${url} \u2014 ${errLabel}`,
14170
+ `${prefix}: ${method} ${url} \u2014 ${errLabel}`,
14071
14171
  "error",
14072
14172
  {
14073
- tags: {
14074
- "http.method": method,
14075
- "network.failure_kind": "network",
14076
- ...meta.errorName ? { "network.error_name": meta.errorName } : {}
14077
- },
14078
- extra: networkFailureExtra({
14079
- ...meta,
14080
- failureKind: "network",
14081
- aborted: false
14082
- })
14173
+ tags: networkFailureTags(meta),
14174
+ extra: networkFailureExtra(meta)
14083
14175
  }
14084
14176
  );
14085
14177
  }
@@ -14335,7 +14427,9 @@
14335
14427
  osVersion: this.browserContext.osVersion,
14336
14428
  device: this.browserContext.device,
14337
14429
  language: this.browserContext.language,
14338
- userAgent: this.browserContext.userAgent
14430
+ userAgent: this.browserContext.userAgent,
14431
+ bot: this.browserContext.bot,
14432
+ ...this.browserContext.botName ? { botName: this.browserContext.botName } : {}
14339
14433
  }
14340
14434
  } : {},
14341
14435
  sdk: {