@edraj/sauron-node 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 CHANGED
@@ -2,6 +2,28 @@
2
2
 
3
3
  All notable changes to `@edraj/sauron-node` are documented here.
4
4
 
5
+ ## 1.4.0
6
+
7
+ ### Fixed
8
+
9
+ - **`trackTransaction` shipped transactions with no duration, silently.** This
10
+ SDK's input field is `duration_ms`; the browser SDK's is `durationMs`. A
11
+ snippet moved between the two — or any plain-JavaScript caller, where the type
12
+ checker is not there to object — produced a transaction item missing the one
13
+ field it exists to carry, and nothing anywhere complained: the item validated,
14
+ shipped, and looked delivered.
15
+
16
+ `durationMs` is now accepted as an alias, and a transaction with no usable
17
+ duration is **dropped with a debug log line rather than sent**. Refusing is the
18
+ point: sending it anyway is what let the misspelling survive unnoticed.
19
+ `duration_ms: 0` is a legitimate duration and is still sent.
20
+
21
+ ### Changed
22
+
23
+ - `TransactionInput.duration_ms` is now optional, since `durationMs` may supply
24
+ it instead. Supply exactly one — `duration_ms` wins if both are present.
25
+ Supplying neither is the drop above, not a compile error.
26
+
5
27
  ## 1.3.0
6
28
 
7
29
  ### Added
package/dist/client.js CHANGED
@@ -179,12 +179,25 @@ export class SauronClient {
179
179
  trackTransaction(input) {
180
180
  if (typeof input?.name !== 'string' || input.name.length === 0)
181
181
  return;
182
+ // `durationMs` accepted as an alias — see TransactionInput. Without it, a
183
+ // caller using the browser SDK's spelling shipped a transaction with the
184
+ // duration field absent and no complaint from anywhere.
185
+ const duration = input.duration_ms ?? input.durationMs;
186
+ if (typeof duration !== 'number' || !Number.isFinite(duration)) {
187
+ // Refused loudly rather than sent. A transaction whose whole purpose is
188
+ // to record a duration is not worth persisting without one, and silence
189
+ // here is what let the mis-spelling survive: the item looked delivered.
190
+ this.debugLog(`dropped transaction "${input.name}": duration_ms must be a finite number ` +
191
+ `(got ${typeof duration === 'number' ? duration : typeof duration}). ` +
192
+ `Use duration_ms, or durationMs if you are porting from the browser SDK.`);
193
+ return;
194
+ }
182
195
  const distinctId = input.distinct_id ?? getCurrentScope().data.user?.id ?? undefined;
183
196
  const item = {
184
197
  type: 'transaction',
185
198
  name: input.name,
186
199
  op: input.op ?? 'custom',
187
- duration_ms: input.duration_ms,
200
+ duration_ms: duration,
188
201
  timestamp: isoNow(),
189
202
  };
190
203
  if (input.status !== undefined)
package/dist/transport.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { maybeGzip } from './gzip.js';
2
2
  import { BoundedQueue } from './queue.js';
3
3
  const SDK_NAME = 'sauron-node';
4
- const SDK_VERSION = '1.3.0';
4
+ const SDK_VERSION = '1.4.0';
5
5
  /** Default exponential-backoff base (ms) for the first retry. */
6
6
  const DEFAULT_RETRY_BASE_MS = 200;
7
7
  /** Hard cap on any single backoff delay (ms). */
package/dist/types.d.ts CHANGED
@@ -167,7 +167,20 @@ export interface TransactionInput {
167
167
  name: string;
168
168
  /** Operation class: `navigation | http | resource | screen_load | custom`. Default `custom`. */
169
169
  op?: string;
170
- duration_ms: number;
170
+ duration_ms?: number;
171
+ /**
172
+ * Accepted alias for {@link duration_ms}.
173
+ *
174
+ * The browser SDK's equivalent input takes `durationMs` (`sdks/js`), so a
175
+ * snippet moved between the two — or any plain-JavaScript caller, where the
176
+ * type checker is not there to object — used to produce a transaction with no
177
+ * duration at all. The item still validated and still shipped, just without
178
+ * the one field it exists to carry, which is the worst possible outcome: no
179
+ * error anywhere and a silently useless performance record.
180
+ *
181
+ * Supply exactly one. `duration_ms` wins if both are present.
182
+ */
183
+ durationMs?: number;
171
184
  status?: string;
172
185
  http_method?: string;
173
186
  http_status?: number;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@edraj/sauron-node",
3
- "version": "1.3.0",
3
+ "version": "1.4.0",
4
4
  "description": "Sauron server-side Node/TypeScript SDK: product-analytics events + exception capture for Node backends.",
5
5
  "homepage": "https://github.com/edraj/sauron/tree/main/sdks/node#readme",
6
6
  "repository": {