@tallyrow/safesignal 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.
Files changed (50) hide show
  1. package/README.md +329 -20
  2. package/dist/capture.cjs +77 -0
  3. package/dist/capture.cjs.map +1 -0
  4. package/dist/capture.d.cts +49 -0
  5. package/dist/capture.d.ts +49 -0
  6. package/dist/capture.mjs +75 -0
  7. package/dist/capture.mjs.map +1 -0
  8. package/dist/dev-console.cjs +90 -0
  9. package/dist/dev-console.cjs.map +1 -0
  10. package/dist/dev-console.d.cts +67 -0
  11. package/dist/dev-console.d.ts +67 -0
  12. package/dist/dev-console.mjs +88 -0
  13. package/dist/dev-console.mjs.map +1 -0
  14. package/dist/framework-react.cjs +92 -0
  15. package/dist/framework-react.cjs.map +1 -0
  16. package/dist/framework-react.d.cts +97 -0
  17. package/dist/framework-react.d.ts +97 -0
  18. package/dist/framework-react.mjs +87 -0
  19. package/dist/framework-react.mjs.map +1 -0
  20. package/dist/framework-vue.cjs +88 -0
  21. package/dist/framework-vue.cjs.map +1 -0
  22. package/dist/framework-vue.d.cts +101 -0
  23. package/dist/framework-vue.d.ts +101 -0
  24. package/dist/framework-vue.mjs +82 -0
  25. package/dist/framework-vue.mjs.map +1 -0
  26. package/dist/index.cjs +180 -40
  27. package/dist/index.cjs.map +1 -1
  28. package/dist/index.d.cts +2 -2
  29. package/dist/index.d.ts +2 -2
  30. package/dist/index.mjs +180 -40
  31. package/dist/index.mjs.map +1 -1
  32. package/dist/stacks.cjs +81 -0
  33. package/dist/stacks.cjs.map +1 -0
  34. package/dist/stacks.d.cts +55 -0
  35. package/dist/stacks.d.ts +55 -0
  36. package/dist/stacks.mjs +77 -0
  37. package/dist/stacks.mjs.map +1 -0
  38. package/dist/testing.d.cts +1 -1
  39. package/dist/testing.d.ts +1 -1
  40. package/dist/transport-beacon.cjs.map +1 -1
  41. package/dist/transport-beacon.d.cts +1 -1
  42. package/dist/transport-beacon.d.ts +1 -1
  43. package/dist/transport-beacon.mjs.map +1 -1
  44. package/dist/transport-otlp.cjs.map +1 -1
  45. package/dist/transport-otlp.d.cts +1 -1
  46. package/dist/transport-otlp.d.ts +1 -1
  47. package/dist/transport-otlp.mjs.map +1 -1
  48. package/dist/{types-BiRyHi1e.d.cts → types-CZtSjgq5.d.cts} +53 -1
  49. package/dist/{types-BiRyHi1e.d.ts → types-CZtSjgq5.d.ts} +53 -1
  50. package/package.json +53 -6
package/dist/index.d.cts CHANGED
@@ -1,5 +1,5 @@
1
- import { g as LoggerConfig, C as CreateLoggerOptions, f as Logger, R as RedactionRule, h as Redactor, i as ScrubUrlOptions, T as TraceContext, k as TransportFactory } from './types-BiRyHi1e.cjs';
2
- export { A as AppIdentity, a as AttributeValue, b as Attributes, E as ErrorInfo, L as LevelMap, c as LogContext, d as LogEvent, e as LogLevel, M as ModuleIdentity, S as SanitizerLimits, j as Transport } from './types-BiRyHi1e.cjs';
1
+ import { g as LoggerConfig, C as CreateLoggerOptions, f as Logger, R as RedactionRule, h as Redactor, i as ScrubUrlOptions, T as TraceContext, m as TransportFactory } from './types-CZtSjgq5.cjs';
2
+ export { A as AppIdentity, a as AttributeValue, b as Attributes, B as BreadcrumbsOptions, E as ErrorInfo, L as LevelMap, c as LogContext, d as LogEvent, e as LogLevel, M as ModuleIdentity, S as SanitizerLimits, j as StackFrame, k as StackNormalizer, l as Transport } from './types-CZtSjgq5.cjs';
3
3
 
4
4
  /**
5
5
  * Public logger factories and root configuration flow.
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { g as LoggerConfig, C as CreateLoggerOptions, f as Logger, R as RedactionRule, h as Redactor, i as ScrubUrlOptions, T as TraceContext, k as TransportFactory } from './types-BiRyHi1e.js';
2
- export { A as AppIdentity, a as AttributeValue, b as Attributes, E as ErrorInfo, L as LevelMap, c as LogContext, d as LogEvent, e as LogLevel, M as ModuleIdentity, S as SanitizerLimits, j as Transport } from './types-BiRyHi1e.js';
1
+ import { g as LoggerConfig, C as CreateLoggerOptions, f as Logger, R as RedactionRule, h as Redactor, i as ScrubUrlOptions, T as TraceContext, m as TransportFactory } from './types-CZtSjgq5.js';
2
+ export { A as AppIdentity, a as AttributeValue, b as Attributes, B as BreadcrumbsOptions, E as ErrorInfo, L as LevelMap, c as LogContext, d as LogEvent, e as LogLevel, M as ModuleIdentity, S as SanitizerLimits, j as StackFrame, k as StackNormalizer, l as Transport } from './types-CZtSjgq5.js';
3
3
 
4
4
  /**
5
5
  * Public logger factories and root configuration flow.
package/dist/index.mjs CHANGED
@@ -1,3 +1,119 @@
1
+ // src/internal/errors/internal-errors.ts
2
+ var PACKAGE_ERROR_MARKER = /* @__PURE__ */ Symbol("frontend-logging-sdk/package-error");
3
+ var PackageError = class extends Error {
4
+ constructor(code, message, options = {}) {
5
+ super(message);
6
+ this.name = "PackageError";
7
+ this.code = code;
8
+ if (options.cause !== void 0) {
9
+ this.cause = options.cause;
10
+ }
11
+ if (options.transportName !== void 0) {
12
+ this.transportName = options.transportName;
13
+ }
14
+ Object.defineProperty(this, PACKAGE_ERROR_MARKER, {
15
+ value: true,
16
+ enumerable: false,
17
+ writable: false,
18
+ configurable: false
19
+ });
20
+ }
21
+ };
22
+ function isPackageError(value) {
23
+ if (typeof value !== "object" || value === null) return false;
24
+ return value[PACKAGE_ERROR_MARKER] === true;
25
+ }
26
+ function wrapAsPackageError(code, message, cause, transportName) {
27
+ if (isPackageError(cause)) return cause;
28
+ const options = { cause };
29
+ if (transportName !== void 0) {
30
+ options.transportName = transportName;
31
+ }
32
+ return new PackageError(code, message, options);
33
+ }
34
+ function safeNotify(onInternalError, err) {
35
+ try {
36
+ onInternalError(err);
37
+ } catch {
38
+ }
39
+ }
40
+
41
+ // src/breadcrumbs/breadcrumb-buffer.ts
42
+ function breadcrumbFail(onInternalError, err) {
43
+ safeNotify(
44
+ onInternalError,
45
+ wrapAsPackageError("breadcrumb_failed", "breadcrumb failed", err)
46
+ );
47
+ }
48
+ var DEFAULT_MAX_EVENTS = 20;
49
+ var MAX_EVENTS_BOUND = 100;
50
+ var BREADCRUMBS_KEY = "safesignal.breadcrumbs";
51
+ function buildSnapshot(event) {
52
+ const snap = {
53
+ ts: event.timestamp,
54
+ level: event.level,
55
+ message: event.message
56
+ };
57
+ const app = event.context.application?.name;
58
+ if (app !== void 0) snap.app = app;
59
+ const mod = event.context.module?.name;
60
+ if (mod !== void 0) snap.module = mod;
61
+ const attrs = {};
62
+ let hasAttrs = false;
63
+ for (const key of Object.keys(event.attributes)) {
64
+ const value = event.attributes[key];
65
+ if (key === BREADCRUMBS_KEY || value === void 0) continue;
66
+ attrs[key] = value;
67
+ hasAttrs = true;
68
+ }
69
+ if (hasAttrs) snap.attributes = attrs;
70
+ return snap;
71
+ }
72
+ var BreadcrumbBuffer = class {
73
+ constructor(maxEvents) {
74
+ this.ring = [];
75
+ this.capacity = maxEvents;
76
+ }
77
+ /** Record a compact snapshot of a post-pipeline event; oldest evicted. */
78
+ record(event) {
79
+ this.ring.push(buildSnapshot(event));
80
+ if (this.ring.length > this.capacity) this.ring.shift();
81
+ }
82
+ /**
83
+ * Attach the current trail to an error event as `attributes[BREADCRUMBS_KEY]`
84
+ * (ordered oldest→newest). No-op when the buffer is empty (no placeholder).
85
+ */
86
+ attachTrailTo(event) {
87
+ if (this.ring.length === 0) return;
88
+ event.attributes[BREADCRUMBS_KEY] = this.ring.slice();
89
+ }
90
+ };
91
+ var MAX_CAUSE_DEPTH = 8;
92
+ var CAUSES_KEY = "safesignal.errorCauses";
93
+ function getCause(value) {
94
+ if (value !== null && typeof value === "object" && "cause" in value) {
95
+ return value.cause;
96
+ }
97
+ return void 0;
98
+ }
99
+ function extractCauseChain(value, maxDepth) {
100
+ const chain = [];
101
+ const seen = /* @__PURE__ */ new Set();
102
+ if (value !== null && typeof value === "object") seen.add(value);
103
+ let current = getCause(value);
104
+ while (current !== void 0 && current !== null && chain.length < maxDepth) {
105
+ if (typeof current === "object") {
106
+ if (seen.has(current)) break;
107
+ seen.add(current);
108
+ }
109
+ chain.push(
110
+ current instanceof Error ? { name: current.name, message: current.message } : { name: "NonError", message: String(current) }
111
+ );
112
+ current = getCause(current);
113
+ }
114
+ return chain;
115
+ }
116
+
1
117
  // src/context/context-merge.ts
2
118
  function mergeContexts(...sources) {
3
119
  const merged = {};
@@ -48,46 +164,6 @@ function isPlainAttributeObject(value) {
48
164
  return value !== null && value !== void 0 && typeof value === "object" && !Array.isArray(value);
49
165
  }
50
166
 
51
- // src/internal/errors/internal-errors.ts
52
- var PACKAGE_ERROR_MARKER = /* @__PURE__ */ Symbol("frontend-logging-sdk/package-error");
53
- var PackageError = class extends Error {
54
- constructor(code, message, options = {}) {
55
- super(message);
56
- this.name = "PackageError";
57
- this.code = code;
58
- if (options.cause !== void 0) {
59
- this.cause = options.cause;
60
- }
61
- if (options.transportName !== void 0) {
62
- this.transportName = options.transportName;
63
- }
64
- Object.defineProperty(this, PACKAGE_ERROR_MARKER, {
65
- value: true,
66
- enumerable: false,
67
- writable: false,
68
- configurable: false
69
- });
70
- }
71
- };
72
- function isPackageError(value) {
73
- if (typeof value !== "object" || value === null) return false;
74
- return value[PACKAGE_ERROR_MARKER] === true;
75
- }
76
- function wrapAsPackageError(code, message, cause, transportName) {
77
- if (isPackageError(cause)) return cause;
78
- const options = { cause };
79
- if (transportName !== void 0) {
80
- options.transportName = transportName;
81
- }
82
- return new PackageError(code, message, options);
83
- }
84
- function safeNotify(onInternalError, err) {
85
- try {
86
- onInternalError(err);
87
- } catch {
88
- }
89
- }
90
-
91
167
  // src/pipeline/control-char-guard.ts
92
168
  var CONTROL_CHAR_CLASS = "[\\u0000-\\u0008\\u000B\\u000C\\u000E-\\u001F\\u2028\\u2029]";
93
169
  var HAS_CONTROL_CHAR = new RegExp(CONTROL_CHAR_CLASS);
@@ -845,6 +921,13 @@ function dispatch(event, config) {
845
921
  if (current === null) return;
846
922
  current = controlCharGuard(current, config);
847
923
  if (current === null) return;
924
+ if (config.breadcrumbs !== void 0 && current.level === "error") {
925
+ try {
926
+ config.breadcrumbs.attachTrailTo(current);
927
+ } catch (err) {
928
+ breadcrumbFail(config.onInternalError, err);
929
+ }
930
+ }
848
931
  current = freezeInDev(current, config);
849
932
  if (current === null) return;
850
933
  } catch (err) {
@@ -867,6 +950,13 @@ function dispatch(event, config) {
867
950
  } catch {
868
951
  }
869
952
  }
953
+ if (config.breadcrumbs !== void 0) {
954
+ try {
955
+ config.breadcrumbs.record(current);
956
+ } catch (err) {
957
+ breadcrumbFail(config.onInternalError, err);
958
+ }
959
+ }
870
960
  }
871
961
 
872
962
  // src/pipeline/event-builder.ts
@@ -954,9 +1044,32 @@ function normalizeConfig(config) {
954
1044
  transports,
955
1045
  redactor: config.redactor,
956
1046
  sanitizerLimits,
1047
+ breadcrumbs: resolveBreadcrumbs(config.breadcrumbs, onInternalError),
1048
+ normalizeStack: config.normalizeStack,
957
1049
  onInternalError
958
1050
  };
959
1051
  }
1052
+ function resolveBreadcrumbs(option, onInternalError) {
1053
+ if (!option) return void 0;
1054
+ const requested = option === true ? void 0 : option.maxEvents;
1055
+ if (requested === void 0 || !Number.isFinite(requested)) {
1056
+ return new BreadcrumbBuffer(DEFAULT_MAX_EVENTS);
1057
+ }
1058
+ const maxEvents = Math.min(
1059
+ MAX_EVENTS_BOUND,
1060
+ Math.max(1, Math.floor(requested))
1061
+ );
1062
+ if (maxEvents !== requested) {
1063
+ safeNotify(
1064
+ onInternalError,
1065
+ new PackageError(
1066
+ "breadcrumbs_max_clamped",
1067
+ `breadcrumbs.maxEvents clamped to ${maxEvents}`
1068
+ )
1069
+ );
1070
+ }
1071
+ return new BreadcrumbBuffer(maxEvents);
1072
+ }
960
1073
  function resolveConfigLevel(level, environment) {
961
1074
  if (level === void 0) {
962
1075
  return defaultLevelForEnvironment(environment);
@@ -1234,6 +1347,33 @@ function makeLogger(options, chainedContexts) {
1234
1347
  context,
1235
1348
  errorValue
1236
1349
  });
1350
+ if (cfg.breadcrumbs !== void 0 && level === "error" && errorValue !== void 0) {
1351
+ try {
1352
+ const causes = extractCauseChain(errorValue, MAX_CAUSE_DEPTH);
1353
+ if (causes.length > 0) {
1354
+ event.attributes[CAUSES_KEY] = causes;
1355
+ }
1356
+ } catch (err) {
1357
+ breadcrumbFail(cfg.onInternalError, err);
1358
+ }
1359
+ }
1360
+ if (cfg.normalizeStack !== void 0 && level === "error" && event.error?.stack !== void 0) {
1361
+ try {
1362
+ const frames = cfg.normalizeStack(event.error.stack);
1363
+ if (frames !== null && frames.length > 0) {
1364
+ event.attributes["safesignal.stack"] = frames;
1365
+ }
1366
+ } catch (err) {
1367
+ safeNotify(
1368
+ cfg.onInternalError,
1369
+ wrapAsPackageError(
1370
+ "stack_normalize_failed",
1371
+ "stack normalize failed",
1372
+ err
1373
+ )
1374
+ );
1375
+ }
1376
+ }
1237
1377
  dispatch(event, cfg);
1238
1378
  }
1239
1379
  return {