@edraj/sauron-node 1.0.0 → 1.3.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/dist/types.d.ts CHANGED
@@ -68,6 +68,30 @@ export interface ScopeData {
68
68
  contexts: Record<string, unknown>;
69
69
  extra: Record<string, unknown>;
70
70
  breadcrumbs: Breadcrumb[];
71
+ /**
72
+ * The workflow bounded by `startWorkflow`/`endWorkflow`/`cancelWorkflow` on
73
+ * THIS scope, or `null` if none. Request-isolated: the async-local child
74
+ * scope created by `withScope`/`runWithAsyncScope` gets its own copy, so
75
+ * concurrent requests never observe each other's workflow.
76
+ */
77
+ workflow: ActiveWorkflow | null;
78
+ }
79
+ /** Exactly six reachable outcomes for a workflow lifecycle call. No seventh. */
80
+ export type WorkflowStatus = 'ok' | 'already_active' | 'not_active' | 'name_mismatch' | 'invalid_name' | 'disabled';
81
+ /** Return value of `startWorkflow` / `endWorkflow` / `cancelWorkflow`. */
82
+ export interface WorkflowResult {
83
+ status: WorkflowStatus;
84
+ /** Present when `status` is `'ok'`. */
85
+ workflowId?: string;
86
+ }
87
+ /** The workflow currently bounded on a scope. */
88
+ export interface ActiveWorkflow {
89
+ /** Fresh client-generated UUID v4, minted by `startWorkflow`. */
90
+ workflowId: string;
91
+ /** Trimmed, caller-supplied name (see `normalizeWorkflowName`). */
92
+ name: string;
93
+ /** ISO-8601 timestamp of when the workflow started. */
94
+ startedAt: string;
71
95
  }
72
96
  /** An error item (manual `captureException` / `captureMessage`). */
73
97
  export interface ErrorItem {
@@ -84,6 +108,14 @@ export interface ErrorItem {
84
108
  fingerprint: string[] | null;
85
109
  user: ErrorUser | null;
86
110
  session_id: string | null;
111
+ /**
112
+ * Id/name of the workflow this error occurred within, if the SDK bounded
113
+ * one via `startWorkflow`. Optional-not-nullable: apps that never use
114
+ * workflows must be byte-identical to before this field existed, so an
115
+ * absent workflow means the key is OMITTED from the item, never `null`.
116
+ */
117
+ workflow_id?: string;
118
+ workflow_name?: string;
87
119
  screen: string | null;
88
120
  }
89
121
  /** A product-analytics event (PostHog-style `track`). */
@@ -94,6 +126,9 @@ export interface EventItem {
94
126
  properties: Record<string, unknown>;
95
127
  timestamp: string;
96
128
  session_id: string | null;
129
+ /** See {@link ErrorItem.workflow_id} — same omit-not-null convention. */
130
+ workflow_id?: string;
131
+ workflow_name?: string;
97
132
  screen: string | null;
98
133
  tags?: Record<string, string>;
99
134
  contexts?: Record<string, unknown>;
@@ -122,6 +157,9 @@ export interface TransactionItem {
122
157
  http_status?: number;
123
158
  url?: string;
124
159
  distinct_id?: string;
160
+ /** See {@link ErrorItem.workflow_id} — same omit-not-null convention. */
161
+ workflow_id?: string;
162
+ workflow_name?: string;
125
163
  timestamp: string;
126
164
  }
127
165
  /** Caller input for {@link TransactionItem} via `trackTransaction`. */
@@ -169,7 +207,6 @@ export interface EnvelopeHeader {
169
207
  dsn: string;
170
208
  sdk: SdkInfo;
171
209
  sent_at: string;
172
- environment: string;
173
210
  release: string | null;
174
211
  }
175
212
  /** The complete, serializable envelope posted to the ingest gateway. */
@@ -223,7 +260,6 @@ export interface TransportOptions {
223
260
  export interface InitOptions {
224
261
  /** `https://<public_key>@<host>/<project_id>` */
225
262
  dsn: string;
226
- environment?: string;
227
263
  release?: string | null;
228
264
  /** Default tags seeded into the global scope at init. */
229
265
  tags?: Record<string, string>;
@@ -269,7 +305,6 @@ export interface InitOptions {
269
305
  /** Fully-resolved options with all defaults applied. */
270
306
  export interface ResolvedOptions {
271
307
  dsn: string;
272
- environment: string;
273
308
  release: string | null;
274
309
  tags: Record<string, string>;
275
310
  contexts: Record<string, unknown>;
@@ -0,0 +1,26 @@
1
+ import type { ActiveWorkflow } from './types.js';
2
+ /** Cap on a workflow name, after trimming. */
3
+ export declare const WORKFLOW_NAME_MAX = 120;
4
+ /** Cap on a cancel reason. */
5
+ export declare const WORKFLOW_REASON_MAX = 120;
6
+ /**
7
+ * Returns the trimmed name, or `null` when invalid (not a string, empty after
8
+ * trimming, or over {@link WORKFLOW_NAME_MAX} characters). Trims BEFORE
9
+ * checking length/emptiness so an all-whitespace or over-long-but-padded name
10
+ * is rejected rather than silently truncated.
11
+ */
12
+ export declare function normalizeWorkflowName(name: unknown): string | null;
13
+ /**
14
+ * Normalize a cancel reason: default to `'user'` for a non-string or
15
+ * all-whitespace value, else trim and cap at {@link WORKFLOW_REASON_MAX}.
16
+ * The internal `force`-supersede path also routes its literal `'superseded'`
17
+ * reason through this, so every reason on the wire is consistently shaped.
18
+ */
19
+ export declare function normalizeReason(reason: unknown): string;
20
+ /**
21
+ * The active workflow on the CURRENT scope — the `AsyncLocalStorage` child
22
+ * inside `withScope`/`runWithAsyncScope`, else the process-wide global scope —
23
+ * or `null` if none. Client-agnostic: reflects scope state regardless of
24
+ * whether an SDK client is initialized, same as `getCurrentScope()` itself.
25
+ */
26
+ export declare function getWorkflow(): ActiveWorkflow | null;
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Workflow name/reason normalization — pure helpers, no state of their own.
3
+ *
4
+ * Unlike the browser SDK (`sdks/js/src/workflow.ts`), the active workflow is
5
+ * NOT held in a module-level variable here: a module global would leak one
6
+ * HTTP request's workflow into every other concurrent request's telemetry.
7
+ * Instead it lives on the per-request {@link Scope} (`scope.data.workflow`),
8
+ * isolated by `AsyncLocalStorage` exactly like `user`/`tags`/`breadcrumbs`
9
+ * already are (see `scope.ts`). `getWorkflow()` below is a bare read of that
10
+ * scope field — it takes no client and never throws, mirroring the existing
11
+ * `getCurrentScope()`/`getGlobalScope()` getters.
12
+ */
13
+ import { getCurrentScope } from './scope.js';
14
+ /** Cap on a workflow name, after trimming. */
15
+ export const WORKFLOW_NAME_MAX = 120;
16
+ /** Cap on a cancel reason. */
17
+ export const WORKFLOW_REASON_MAX = 120;
18
+ /**
19
+ * Returns the trimmed name, or `null` when invalid (not a string, empty after
20
+ * trimming, or over {@link WORKFLOW_NAME_MAX} characters). Trims BEFORE
21
+ * checking length/emptiness so an all-whitespace or over-long-but-padded name
22
+ * is rejected rather than silently truncated.
23
+ */
24
+ export function normalizeWorkflowName(name) {
25
+ if (typeof name !== 'string')
26
+ return null;
27
+ const trimmed = name.trim();
28
+ if (trimmed.length === 0 || trimmed.length > WORKFLOW_NAME_MAX)
29
+ return null;
30
+ return trimmed;
31
+ }
32
+ /**
33
+ * Normalize a cancel reason: default to `'user'` for a non-string or
34
+ * all-whitespace value, else trim and cap at {@link WORKFLOW_REASON_MAX}.
35
+ * The internal `force`-supersede path also routes its literal `'superseded'`
36
+ * reason through this, so every reason on the wire is consistently shaped.
37
+ */
38
+ export function normalizeReason(reason) {
39
+ if (typeof reason !== 'string' || reason.trim().length === 0)
40
+ return 'user';
41
+ return reason.trim().slice(0, WORKFLOW_REASON_MAX);
42
+ }
43
+ /**
44
+ * The active workflow on the CURRENT scope — the `AsyncLocalStorage` child
45
+ * inside `withScope`/`runWithAsyncScope`, else the process-wide global scope —
46
+ * or `null` if none. Client-agnostic: reflects scope state regardless of
47
+ * whether an SDK client is initialized, same as `getCurrentScope()` itself.
48
+ */
49
+ export function getWorkflow() {
50
+ return getCurrentScope().data.workflow;
51
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@edraj/sauron-node",
3
- "version": "1.0.0",
3
+ "version": "1.3.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": {