@edraj/sauron-node 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/README.md CHANGED
@@ -56,13 +56,13 @@ adding `Content-Encoding: gzip` once the body crosses the gzip threshold.
56
56
 
57
57
  ## Configuration
58
58
 
59
- `init(options)` takes a single `InitOptions` object. Every field except `dsn` is
60
- optional.
59
+ `init(options)` takes a single `InitOptions` object. Every field except `dsn`
60
+ and `release` is optional.
61
61
 
62
62
  | Option | Type | Default | Description |
63
63
  | --- | --- | --- | --- |
64
- | `dsn` | `string` | — (**required**) | `https://<public_key>@<host>/<environment_id>`. A non-string throws `Error`; a malformed value throws `DsnError`. |
65
- | `release` | `string \| null` | `null` | Written to `header.release`. |
64
+ | `dsn` | `string` | — (**required**) | `https://<public_key>@<host>/<environment_id>`. A non-string or empty value throws `Error`; a malformed value throws `DsnError`. |
65
+ | `release` | `string` | (**required**) | The app version this build reports as, written to `header.release`. Missing or whitespace-only throws `Error`. Trimmed before it is sent. |
66
66
  | `tags` | `Record<string, string>` | `{}` | Default tags seeded into the global scope at init. |
67
67
  | `contexts` | `Record<string, unknown>` | `{}` | Default named dev context blocks seeded into the global scope. Distinct from the machine `context` (device/os/app/runtime). |
68
68
  | `extra` | `Record<string, unknown>` | `{}` | Default free-form extra values seeded into the global scope. |
@@ -140,11 +140,12 @@ function init(options: InitOptions): SauronClient
140
140
  | `options` | `InitOptions` | — (required) | See [Configuration](#configuration). |
141
141
 
142
142
  Returns the `SauronClient` it created, and installs it as the active client.
143
- Throws `Error` when `options.dsn` is not a string, and `DsnError` when the DSN
144
- is malformed.
143
+ Throws `Error` when `options.dsn` is missing/empty/not a string, when
144
+ `options.release` is missing or blank (**required as of v1.6.0**), and
145
+ `DsnError` when the DSN is malformed.
145
146
 
146
147
  ```ts
147
- const client = init({ dsn: 'https://pk@ingest.example.com/42' });
148
+ const client = init({ dsn: 'https://pk@ingest.example.com/42', release: 'api@1.4.2' });
148
149
  ```
149
150
 
150
151
  ### `getClient()`
@@ -823,7 +824,7 @@ Re-entrancy is guarded, so a throw inside the capture path cannot loop. Prefer
823
824
  down on `close()`.
824
825
 
825
826
  ```ts
826
- const client = init({ dsn: DSN });
827
+ const client = init({ dsn: DSN, release: 'api@1.4.2' });
827
828
  const uninstall = installAutoCapture(client);
828
829
  // later
829
830
  uninstall();
@@ -855,7 +856,7 @@ signal fires — if you need to drain HTTP connections first, leave `autoShutdow
855
856
  off and call `close()` yourself from your own handler.
856
857
 
857
858
  ```ts
858
- const client = init({ dsn: DSN });
859
+ const client = init({ dsn: DSN, release: 'api@1.4.2' });
859
860
  const uninstall = installShutdownHooks(client);
860
861
  ```
861
862
 
@@ -1088,7 +1089,7 @@ Emit conventions on the wire:
1088
1089
  `distinct_id` fallback from the scope's user id.
1089
1090
 
1090
1091
  ```ts
1091
- init({ dsn: DSN, tags: { service: 'checkout' } }); // layer 1
1092
+ init({ dsn: DSN, release: 'api@1.4.2', tags: { service: 'checkout' } }); // layer 1
1092
1093
 
1093
1094
  setTag('region', 'eu-west-1'); // layer 2 (global)
1094
1095
 
@@ -1194,7 +1195,7 @@ import {
1194
1195
  init, withScope, addBreadcrumb, captureException, trackTransaction, close,
1195
1196
  } from '@edraj/sauron-node';
1196
1197
 
1197
- init({ dsn: process.env.SAURON_DSN!, autoCaptureUnhandled: true });
1198
+ init({ dsn: process.env.SAURON_DSN!, release: process.env.GIT_SHA, autoCaptureUnhandled: true });
1198
1199
 
1199
1200
  const fastify = Fastify();
1200
1201
  const startedAt = new WeakMap<object, number>();
@@ -1335,4 +1336,5 @@ npm run typecheck # tsc --noEmit
1335
1336
 
1336
1337
  ## License
1337
1338
 
1338
- AGPL-3.0-only — GNU Affero General Public License v3.0.
1339
+ LGPL-3.0-only — GNU Lesser General Public License v3.0. LGPLv3 applies on top of
1340
+ the GNU GPL v3, whose text ships alongside it in `COPYING`.
package/dist/client.js CHANGED
@@ -8,7 +8,6 @@ import { getCurrentScope, getGlobalScope, normalizeBreadcrumb, } from './scope.j
8
8
  import { normalizeReason, normalizeWorkflowName } from './workflow.js';
9
9
  import { capTransactionExtra } from './transaction-extra.js';
10
10
  const DEFAULTS = {
11
- release: null,
12
11
  sampleRate: 1,
13
12
  flushInterval: 5000,
14
13
  maxBatch: 30,
@@ -19,13 +18,16 @@ const DEFAULTS = {
19
18
  debug: false,
20
19
  };
21
20
  function resolveOptions(options) {
22
- if (!options || typeof options.dsn !== 'string') {
21
+ if (!options || typeof options.dsn !== 'string' || options.dsn.length === 0) {
23
22
  throw new Error('[sauron] init requires a { dsn } option');
24
23
  }
24
+ if (typeof options.release !== 'string' || options.release.trim().length === 0) {
25
+ throw new Error('[sauron] init requires a { release } option (the app version this build reports as)');
26
+ }
25
27
  const sampleRate = typeof options.sampleRate === 'number' ? options.sampleRate : DEFAULTS.sampleRate;
26
28
  return {
27
29
  dsn: options.dsn,
28
- release: options.release ?? DEFAULTS.release,
30
+ release: options.release.trim(),
29
31
  tags: options.tags ?? {},
30
32
  contexts: options.contexts ?? {},
31
33
  extra: options.extra ?? {},
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.5.0';
4
+ const SDK_VERSION = '1.6.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
@@ -307,7 +307,8 @@ export interface TransportOptions {
307
307
  export interface InitOptions {
308
308
  /** `https://<public_key>@<host>/<project_id>` */
309
309
  dsn: string;
310
- release?: string | null;
310
+ /** Required. The app version every event is attributed to. */
311
+ release: string;
311
312
  /** Default tags seeded into the global scope at init. */
312
313
  tags?: Record<string, string>;
313
314
  /** Default named dev context blocks seeded into the global scope at init. Distinct from the machine `context`. */
@@ -352,7 +353,7 @@ export interface InitOptions {
352
353
  /** Fully-resolved options with all defaults applied. */
353
354
  export interface ResolvedOptions {
354
355
  dsn: string;
355
- release: string | null;
356
+ release: string;
356
357
  tags: Record<string, string>;
357
358
  contexts: Record<string, unknown>;
358
359
  extra: Record<string, unknown>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@edraj/sauron-node",
3
- "version": "1.5.0",
3
+ "version": "1.6.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": {
@@ -25,7 +25,8 @@
25
25
  "dist",
26
26
  "README.md",
27
27
  "CHANGELOG.md",
28
- "LICENSE"
28
+ "LICENSE",
29
+ "COPYING"
29
30
  ],
30
31
  "scripts": {
31
32
  "build": "tsc -p tsconfig.build.json",
@@ -52,7 +53,7 @@
52
53
  "node",
53
54
  "server"
54
55
  ],
55
- "license": "AGPL-3.0-only",
56
+ "license": "LGPL-3.0-only",
56
57
  "publishConfig": {
57
58
  "access": "public"
58
59
  }