@flareapp/core 2.9.0 → 2.11.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/index.cjs CHANGED
@@ -26,7 +26,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
26
26
  }) : target, mod));
27
27
 
28
28
  //#endregion
29
- const require_urlAttributes = require('./urlAttributes-CEP6bOBn.cjs');
29
+ const require_urlAttributes = require('./urlAttributes-Cinqzwjy.cjs');
30
30
  let error_stack_parser = require("error-stack-parser");
31
31
  error_stack_parser = __toESM(error_stack_parser);
32
32
 
@@ -220,6 +220,7 @@ var TelemetryBuffer = class {
220
220
  }
221
221
  add(record) {
222
222
  const config = this.deps.getConfig();
223
+ if (config.hasConsent === false) return;
223
224
  const limits = this.policy.limits(config);
224
225
  const bytes = this.policy.estimateBytes(record);
225
226
  if (bytes > limits.maxBytes) {
@@ -239,6 +240,10 @@ var TelemetryBuffer = class {
239
240
  const config = this.deps.getConfig();
240
241
  if (!this.policy.enabled(config)) return;
241
242
  if (this.entries.length === 0) return;
243
+ if (config.hasConsent === false) {
244
+ this.clearTimer();
245
+ return;
246
+ }
242
247
  if (!require_urlAttributes.assertKey(config.key, config.debug)) {
243
248
  this.clearTimer();
244
249
  return;
@@ -574,6 +579,7 @@ var Logger = class {
574
579
  }
575
580
  record(level, message, context, attributes) {
576
581
  const config = this.deps.getConfig();
582
+ if (config.hasConsent === false) return;
577
583
  if (!config.enableLogs) return;
578
584
  if (config.minimumLogLevel && !isAtOrAboveMinimum(level, config.minimumLogLevel)) return;
579
585
  const userAttributes = {
@@ -612,6 +618,8 @@ const RESOURCE_PREFIXES = [
612
618
  "host.",
613
619
  "os.",
614
620
  "process.",
621
+ "device.",
622
+ "network.",
615
623
  "flare.framework.",
616
624
  "flare.language."
617
625
  ];
@@ -1441,6 +1449,7 @@ var Flare = class {
1441
1449
  _tracer;
1442
1450
  _config = {
1443
1451
  key: null,
1452
+ hasConsent: true,
1444
1453
  version: "",
1445
1454
  sourcemapVersionId: require_urlAttributes.SOURCEMAP_VERSION,
1446
1455
  stage: "",
@@ -1582,6 +1591,21 @@ var Flare = class {
1582
1591
  this._tracer.flush();
1583
1592
  return this;
1584
1593
  }
1594
+ /**
1595
+ * Turn sending on or off for consent. Off blocks errors, logs, and traces, and drops telemetry
1596
+ * captured earlier so a later grant cannot ship it. On re-grant, flushes anything still buffered.
1597
+ */
1598
+ setConsent(granted) {
1599
+ this._config.hasConsent = granted;
1600
+ if (granted) {
1601
+ this._logger.flush();
1602
+ this._tracer.flush();
1603
+ } else {
1604
+ this._logger.clear();
1605
+ this._tracer.clear();
1606
+ }
1607
+ return this;
1608
+ }
1585
1609
  configure(config) {
1586
1610
  const wasLogsEnabled = this._config.enableLogs;
1587
1611
  const wasTracingEnabled = this._config.enableTracing;
@@ -1668,11 +1692,19 @@ var Flare = class {
1668
1692
  this.framework = framework;
1669
1693
  return this;
1670
1694
  }
1695
+ /**
1696
+ * True when a report must not be captured: consent withdrawn, or dropped by sampling. Consent is
1697
+ * checked first, so a blocked report never runs the sampler or assembles a report (no cookie read).
1698
+ */
1699
+ shouldSkipCapture() {
1700
+ if (this._config.hasConsent === false) return true;
1701
+ return this._config.sampleRate < 1 && Math.random() >= this._config.sampleRate;
1702
+ }
1671
1703
  report(error, attributes = {}) {
1672
1704
  return this.track(this.reportInternal(error, attributes));
1673
1705
  }
1674
1706
  async reportInternal(error, attributes = {}) {
1675
- if (this._config.sampleRate < 1 && Math.random() >= this._config.sampleRate) return;
1707
+ if (this.shouldSkipCapture()) return;
1676
1708
  const seenAtUnixNano = Date.now() * 1e6;
1677
1709
  const coerced = error instanceof Error ? error : new Error(String(error));
1678
1710
  const errorToReport = await this._config.beforeEvaluate(coerced);
@@ -1688,7 +1720,7 @@ var Flare = class {
1688
1720
  return this.track(this.reportUnhandledRejectionInternal(message, attributes));
1689
1721
  }
1690
1722
  async reportUnhandledRejectionInternal(message, attributes = {}) {
1691
- if (this._config.sampleRate < 1 && Math.random() >= this._config.sampleRate) return;
1723
+ if (this.shouldSkipCapture()) return;
1692
1724
  const seenAtUnixNano = Date.now() * 1e6;
1693
1725
  const report = this.buildReport({
1694
1726
  exceptionClass: "UnhandledRejection",
@@ -1706,7 +1738,7 @@ var Flare = class {
1706
1738
  return this.track(this.reportMessageInternal(message, level, attributes));
1707
1739
  }
1708
1740
  async reportMessageInternal(message, level, attributes = {}) {
1709
- if (this._config.sampleRate < 1 && Math.random() >= this._config.sampleRate) return;
1741
+ if (this.shouldSkipCapture()) return;
1710
1742
  const seenAtUnixNano = Date.now() * 1e6;
1711
1743
  const stackTrace = await createStackTrace(/* @__PURE__ */ new Error(), this._config.debug, this.fileReader);
1712
1744
  stackTrace.shift();
@@ -1823,6 +1855,7 @@ var Flare = class {
1823
1855
  return report;
1824
1856
  }
1825
1857
  async sendReport(report) {
1858
+ if (this._config.hasConsent === false) return;
1826
1859
  if (!require_urlAttributes.assertKey(this._config.key, this._config.debug)) return;
1827
1860
  const reportToSubmit = await this._config.beforeSubmit(report);
1828
1861
  if (!reportToSubmit) return;
@@ -1830,6 +1863,73 @@ var Flare = class {
1830
1863
  }
1831
1864
  };
1832
1865
 
1866
+ //#endregion
1867
+ //#region src/device/DeviceInfoProvider.ts
1868
+ /** Default for platforms with no device info. */
1869
+ var NullDeviceInfoProvider = class {
1870
+ collect() {
1871
+ return {};
1872
+ }
1873
+ };
1874
+
1875
+ //#endregion
1876
+ //#region src/device/deviceInfoToAttributes.ts
1877
+ /** Map `DeviceInfo` to wire attributes: flat keys plus a `context.device` card. Shared by every SDK, so keys never drift. */
1878
+ function deviceInfoToAttributes(info) {
1879
+ const attrs = {};
1880
+ require_urlAttributes.setDefined(attrs, "os.name", info.os?.name);
1881
+ require_urlAttributes.setDefined(attrs, "os.version", info.os?.version);
1882
+ require_urlAttributes.setDefined(attrs, "process.runtime.name", info.runtime?.name);
1883
+ require_urlAttributes.setDefined(attrs, "process.runtime.version", info.runtime?.version);
1884
+ require_urlAttributes.setDefined(attrs, "device.type", info.device?.type);
1885
+ require_urlAttributes.setDefined(attrs, "device.model.name", info.device?.model);
1886
+ require_urlAttributes.setDefined(attrs, "device.memory_gb", info.device?.memoryGb);
1887
+ require_urlAttributes.setDefined(attrs, "device.cpu_cores", info.device?.cpuCores);
1888
+ require_urlAttributes.setDefined(attrs, "device.screen.width", info.device?.screen?.width);
1889
+ require_urlAttributes.setDefined(attrs, "device.screen.height", info.device?.screen?.height);
1890
+ require_urlAttributes.setDefined(attrs, "device.screen.scale", info.device?.screen?.scale);
1891
+ require_urlAttributes.setDefined(attrs, "network.effective_type", info.network?.effectiveType);
1892
+ require_urlAttributes.setDefined(attrs, "network.downlink_mbps", info.network?.downlinkMbps);
1893
+ require_urlAttributes.setDefined(attrs, "network.rtt_ms", info.network?.rttMs);
1894
+ require_urlAttributes.setDefined(attrs, "network.online", info.network?.online);
1895
+ require_urlAttributes.setDefined(attrs, "app.version", info.app?.version);
1896
+ require_urlAttributes.setDefined(attrs, "app.id", info.app?.id);
1897
+ const group = buildDeviceContextGroup(info);
1898
+ if (Object.keys(group).length > 0) attrs["context.device"] = group;
1899
+ return attrs;
1900
+ }
1901
+ /**
1902
+ * `context.device` card for the error UI. Rendered one level deep, so values stay scalar. Built only when
1903
+ * a device or network signal exists (an os-only Node report gets none).
1904
+ */
1905
+ function buildDeviceContextGroup(info) {
1906
+ if (!hasDeviceSignal(info.device) && !hasNetworkSignal(info.network)) return {};
1907
+ const group = {};
1908
+ const os = [info.os?.name, info.os?.version].filter((value) => value != null).join(" ");
1909
+ if (os) group.OS = os;
1910
+ require_urlAttributes.setDefined(group, "Model", info.device?.model);
1911
+ require_urlAttributes.setDefined(group, "Type", info.device?.type);
1912
+ const screen = info.device?.screen;
1913
+ if (screen?.width != null && screen?.height != null) group.Screen = screen.scale != null ? `${screen.width} × ${screen.height} @ ${screen.scale}x` : `${screen.width} × ${screen.height}`;
1914
+ if (info.device?.memoryGb != null) group.Memory = `${info.device.memoryGb} GB`;
1915
+ require_urlAttributes.setDefined(group, "CPU cores", info.device?.cpuCores);
1916
+ require_urlAttributes.setDefined(group, "Connection", info.network?.effectiveType);
1917
+ if (info.network?.downlinkMbps != null) group.Downlink = `${info.network.downlinkMbps} Mbps`;
1918
+ if (info.network?.rttMs != null) group.RTT = `${info.network.rttMs} ms`;
1919
+ require_urlAttributes.setDefined(group, "Online", info.network?.online);
1920
+ require_urlAttributes.setDefined(group, "App version", info.app?.version);
1921
+ require_urlAttributes.setDefined(group, "App ID", info.app?.id);
1922
+ require_urlAttributes.setDefined(group, "Language", info.locale?.language);
1923
+ require_urlAttributes.setDefined(group, "Timezone", info.locale?.timezone);
1924
+ return group;
1925
+ }
1926
+ function hasDeviceSignal(device) {
1927
+ return device != null && (device.type != null || device.model != null || device.memoryGb != null || device.cpuCores != null || device.screen?.width != null || device.screen?.height != null);
1928
+ }
1929
+ function hasNetworkSignal(network) {
1930
+ return network != null && (network.effectiveType != null || network.downlinkMbps != null || network.rttMs != null || network.online != null);
1931
+ }
1932
+
1833
1933
  //#endregion
1834
1934
  exports.Api = Api;
1835
1935
  exports.BrowserSpanEventType = BrowserSpanEventType;
@@ -1843,6 +1943,7 @@ exports.InMemoryActiveSpanHolder = InMemoryActiveSpanHolder;
1843
1943
  exports.Logger = Logger;
1844
1944
  exports.MAX_BREADCRUMB_URL_LENGTH = MAX_BREADCRUMB_URL_LENGTH;
1845
1945
  exports.NoopFlushScheduler = NoopFlushScheduler;
1946
+ exports.NullDeviceInfoProvider = NullDeviceInfoProvider;
1846
1947
  exports.NullFileReader = NullFileReader;
1847
1948
  exports.Scope = Scope;
1848
1949
  exports.SpanStatusCode = SpanStatusCode;
@@ -1851,6 +1952,7 @@ exports.USER_IDENTITY_KEYS = USER_IDENTITY_KEYS;
1851
1952
  exports.assert = require_urlAttributes.assert;
1852
1953
  exports.assertKey = require_urlAttributes.assertKey;
1853
1954
  exports.breadcrumbUrl = breadcrumbUrl;
1955
+ exports.buildDeviceContextGroup = buildDeviceContextGroup;
1854
1956
  exports.buildTraceparent = buildTraceparent;
1855
1957
  exports.buildTracesEnvelope = buildTracesEnvelope;
1856
1958
  exports.convertToError = require_urlAttributes.convertToError;
@@ -1858,6 +1960,7 @@ exports.createIdentityTagger = require_urlAttributes.createIdentityTagger;
1858
1960
  exports.createStackTrace = createStackTrace;
1859
1961
  exports.defaultNowNano = defaultNowNano;
1860
1962
  exports.describeRejectionReason = require_urlAttributes.describeRejectionReason;
1963
+ exports.deviceInfoToAttributes = deviceInfoToAttributes;
1861
1964
  exports.extractCode = require_urlAttributes.extractCode;
1862
1965
  exports.flatJsonStringify = require_urlAttributes.flatJsonStringify;
1863
1966
  exports.getCodeSnippet = getCodeSnippet;
package/dist/index.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- import { $ as TracesSampler, A as BufferedLog, B as OtelLogRecord, D as AnyValue, E as assert, F as Framework, G as SdkInfo, H as OverriddenGrouping, I as Glow, J as SpanOptions, K as Span, L as KeyValue, M as Config, N as EntryPointHandler, O as AttributeValue, P as EntryPointType, Q as TracesEnvelope, R as LogsEnvelope, S as convertToError, T as assertKey, U as Report, V as OtelSpan, W as SamplingContext, X as SpanStatusCode, Y as SpanStatus, Z as StackFrame, _ as glowsToEvents, a as SafeCloneOptions, b as SdkTaggable, c as describeRejectionReason, d as redactObjectValues, et as User, f as redactUrlQuery, h as now, it as FrameworkName, j as BufferedSpan, k as Attributes, l as routeRejection, m as safeDecode, n as urlAttributes, nt as BrowserSpanType, o as safeClone, p as resolveDenylist, q as SpanEvent, r as toCustomContext, rt as SpanTypeName, s as RejectionReporter, tt as BrowserSpanEventType, u as DEFAULT_URL_DENYLIST, v as flatJsonStringify, x as createIdentityTagger, y as extractCode, z as MessageLevel } from "./urlAttributes-DSPpBmH-.cjs";
1
+ import { $ as TracesEnvelope, A as Attributes, B as MessageLevel, C as convertToError, D as assert, E as assertKey, F as EntryPointType, G as SamplingContext, H as OtelSpan, I as Framework, J as SpanEvent, K as SdkInfo, L as Glow, M as BufferedSpan, N as Config, O as AnyValue, P as EntryPointHandler, Q as StackFrame, R as KeyValue, S as createIdentityTagger, U as OverriddenGrouping, V as OtelLogRecord, W as Report, X as SpanStatus, Y as SpanOptions, Z as SpanStatusCode, at as FrameworkName, b as extractCode, c as RejectionReporter, d as DEFAULT_URL_DENYLIST, et as TracesSampler, f as redactObjectValues, g as now, h as safeDecode, it as SpanTypeName, j as BufferedLog, k as AttributeValue, l as describeRejectionReason, m as resolveDenylist, n as urlAttributes, nt as BrowserSpanEventType, o as SafeCloneOptions, p as redactUrlQuery, q as Span, r as toCustomContext, rt as BrowserSpanType, s as safeClone, tt as User, u as routeRejection, v as glowsToEvents, x as SdkTaggable, y as flatJsonStringify, z as LogsEnvelope } from "./urlAttributes-D0zqStcw.cjs";
2
2
 
3
3
  //#region src/api/Api.d.ts
4
4
  declare class Api {
@@ -277,6 +277,11 @@ declare class Flare {
277
277
  */
278
278
  withSpan<T>(name: string, fn: (span: Span) => T, opts?: SpanOptions): T;
279
279
  light(key?: string, debug?: boolean): this;
280
+ /**
281
+ * Turn sending on or off for consent. Off blocks errors, logs, and traces, and drops telemetry
282
+ * captured earlier so a later grant cannot ship it. On re-grant, flushes anything still buffered.
283
+ */
284
+ setConsent(granted: boolean): this;
280
285
  configure(config: Partial<Config>): this;
281
286
  test(): Promise<void>;
282
287
  private testInternal;
@@ -293,6 +298,11 @@ declare class Flare {
293
298
  setEntryPoint(handler: EntryPointHandler): this;
294
299
  setSdkInfo(info: SdkInfo): this;
295
300
  setFramework(framework: Framework): this;
301
+ /**
302
+ * True when a report must not be captured: consent withdrawn, or dropped by sampling. Consent is
303
+ * checked first, so a blocked report never runs the sampler or assembles a report (no cookie read).
304
+ */
305
+ private shouldSkipCapture;
296
306
  report(error: Error, attributes?: Attributes): Promise<void>;
297
307
  private reportInternal;
298
308
  reportSilently(error: Error, attributes?: Attributes): void;
@@ -350,7 +360,66 @@ declare class NullFileReader implements FileReader {
350
360
  read(_url: string): Promise<string | null>;
351
361
  }
352
362
  //#endregion
363
+ //#region src/device/types.d.ts
364
+ /** Effective connection quality. The API never reports 5g: a 5g device reports '4g'. */
365
+ type EffectiveConnectionType = 'slow-2g' | '2g' | '3g' | '4g';
366
+ /** Normalised device info. Every field optional: each provider fills what it reads, the mapper drops the rest. */
367
+ type DeviceInfo = {
368
+ os?: {
369
+ name?: string;
370
+ version?: string;
371
+ };
372
+ runtime?: {
373
+ name?: string;
374
+ version?: string;
375
+ };
376
+ device?: {
377
+ type?: string;
378
+ model?: string;
379
+ memoryGb?: number;
380
+ cpuCores?: number;
381
+ screen?: {
382
+ width?: number;
383
+ height?: number;
384
+ scale?: number;
385
+ };
386
+ };
387
+ network?: {
388
+ effectiveType?: EffectiveConnectionType;
389
+ downlinkMbps?: number;
390
+ rttMs?: number;
391
+ online?: boolean;
392
+ };
393
+ app?: {
394
+ version?: string;
395
+ id?: string;
396
+ };
397
+ locale?: {
398
+ language?: string;
399
+ timezone?: string;
400
+ };
401
+ };
402
+ //#endregion
403
+ //#region src/device/DeviceInfoProvider.d.ts
404
+ /** The seam each platform implements to read device info. A `ContextCollector` maps it with `deviceInfoToAttributes`. */
405
+ interface DeviceInfoProvider {
406
+ collect(): DeviceInfo;
407
+ }
408
+ /** Default for platforms with no device info. */
409
+ declare class NullDeviceInfoProvider implements DeviceInfoProvider {
410
+ collect(): DeviceInfo;
411
+ }
412
+ //#endregion
413
+ //#region src/device/deviceInfoToAttributes.d.ts
414
+ /** Map `DeviceInfo` to wire attributes: flat keys plus a `context.device` card. Shared by every SDK, so keys never drift. */
415
+ declare function deviceInfoToAttributes(info: DeviceInfo): Attributes;
416
+ /**
417
+ * `context.device` card for the error UI. Rendered one level deep, so values stay scalar. Built only when
418
+ * a device or network signal exists (an os-only Node report gets none).
419
+ */
420
+ declare function buildDeviceContextGroup(info: DeviceInfo): Record<string, AttributeValue>;
421
+ //#endregion
353
422
  //#region src/stacktrace/createStackTrace.d.ts
354
423
  declare function createStackTrace(error: Error, debug: boolean, fileReader: FileReader): Promise<Array<StackFrame>>;
355
424
  //#endregion
356
- export { type ActiveSpanHolder, type AnyValue, Api, type AttributeValue, type Attributes, BrowserSpanEventType, BrowserSpanType, type BufferedLog, type BufferedSpan, type Config, type ContextCollector, DEFAULT_MAX_LIVE_TRACES, DEFAULT_URL_DENYLIST, type EntryPointHandler, type EntryPointType, type FileReader, Flare, type FlushFn, type FlushScheduler, type Framework, FrameworkName, GlobalScopeProvider, type Glow, InMemoryActiveSpanHolder, type KeyValue, Logger, type LoggerDeps, type LogsEnvelope, MAX_BREADCRUMB_URL_LENGTH, type MessageLevel, NoopFlushScheduler, NullFileReader, type OtelLogRecord, type OtelSpan, type OverriddenGrouping, type RejectionReporter, type Report, type SafeCloneOptions, type SamplingContext, Scope, type ScopeProvider, type SdkInfo, type SdkTaggable, type Span, type SpanEvent, type SpanLifecycleEvent, type SpanLifecycleListener, type SpanOptions, type SpanPhase, type SpanStatus, SpanStatusCode, type SpanTypeName, type StackFrame, Tracer, type TracerDeps, type TracesEnvelope, type TracesSampler, USER_IDENTITY_KEYS, type User, assert, assertKey, breadcrumbUrl, buildTraceparent, buildTracesEnvelope, convertToError, createIdentityTagger, createStackTrace, defaultNowNano, describeRejectionReason, extractCode, flatJsonStringify, getCodeSnippet, glowsToEvents, now, parseTraceparent, readLinesFromFile, recordBreadcrumb, redactObjectValues, redactUrlQuery, resolveDenylist, routeRejection, safeClone, safeDecode, spanId, toCustomContext, urlAttributes, userIdentityAttributes };
425
+ export { type ActiveSpanHolder, type AnyValue, Api, type AttributeValue, type Attributes, BrowserSpanEventType, BrowserSpanType, type BufferedLog, type BufferedSpan, type Config, type ContextCollector, DEFAULT_MAX_LIVE_TRACES, DEFAULT_URL_DENYLIST, type DeviceInfo, type DeviceInfoProvider, type EffectiveConnectionType, type EntryPointHandler, type EntryPointType, type FileReader, Flare, type FlushFn, type FlushScheduler, type Framework, FrameworkName, GlobalScopeProvider, type Glow, InMemoryActiveSpanHolder, type KeyValue, Logger, type LoggerDeps, type LogsEnvelope, MAX_BREADCRUMB_URL_LENGTH, type MessageLevel, NoopFlushScheduler, NullDeviceInfoProvider, NullFileReader, type OtelLogRecord, type OtelSpan, type OverriddenGrouping, type RejectionReporter, type Report, type SafeCloneOptions, type SamplingContext, Scope, type ScopeProvider, type SdkInfo, type SdkTaggable, type Span, type SpanEvent, type SpanLifecycleEvent, type SpanLifecycleListener, type SpanOptions, type SpanPhase, type SpanStatus, SpanStatusCode, type SpanTypeName, type StackFrame, Tracer, type TracerDeps, type TracesEnvelope, type TracesSampler, USER_IDENTITY_KEYS, type User, assert, assertKey, breadcrumbUrl, buildDeviceContextGroup, buildTraceparent, buildTracesEnvelope, convertToError, createIdentityTagger, createStackTrace, defaultNowNano, describeRejectionReason, deviceInfoToAttributes, extractCode, flatJsonStringify, getCodeSnippet, glowsToEvents, now, parseTraceparent, readLinesFromFile, recordBreadcrumb, redactObjectValues, redactUrlQuery, resolveDenylist, routeRejection, safeClone, safeDecode, spanId, toCustomContext, urlAttributes, userIdentityAttributes };
package/dist/index.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { $ as TracesSampler, A as BufferedLog, B as OtelLogRecord, D as AnyValue, E as assert, F as Framework, G as SdkInfo, H as OverriddenGrouping, I as Glow, J as SpanOptions, K as Span, L as KeyValue, M as Config, N as EntryPointHandler, O as AttributeValue, P as EntryPointType, Q as TracesEnvelope, R as LogsEnvelope, S as convertToError, T as assertKey, U as Report, V as OtelSpan, W as SamplingContext, X as SpanStatusCode, Y as SpanStatus, Z as StackFrame, _ as glowsToEvents, a as SafeCloneOptions, b as SdkTaggable, c as describeRejectionReason, d as redactObjectValues, et as User, f as redactUrlQuery, h as now, it as FrameworkName, j as BufferedSpan, k as Attributes, l as routeRejection, m as safeDecode, n as urlAttributes, nt as BrowserSpanType, o as safeClone, p as resolveDenylist, q as SpanEvent, r as toCustomContext, rt as SpanTypeName, s as RejectionReporter, tt as BrowserSpanEventType, u as DEFAULT_URL_DENYLIST, v as flatJsonStringify, x as createIdentityTagger, y as extractCode, z as MessageLevel } from "./urlAttributes-CYJKlJKi.mjs";
1
+ import { $ as TracesEnvelope, A as Attributes, B as MessageLevel, C as convertToError, D as assert, E as assertKey, F as EntryPointType, G as SamplingContext, H as OtelSpan, I as Framework, J as SpanEvent, K as SdkInfo, L as Glow, M as BufferedSpan, N as Config, O as AnyValue, P as EntryPointHandler, Q as StackFrame, R as KeyValue, S as createIdentityTagger, U as OverriddenGrouping, V as OtelLogRecord, W as Report, X as SpanStatus, Y as SpanOptions, Z as SpanStatusCode, at as FrameworkName, b as extractCode, c as RejectionReporter, d as DEFAULT_URL_DENYLIST, et as TracesSampler, f as redactObjectValues, g as now, h as safeDecode, it as SpanTypeName, j as BufferedLog, k as AttributeValue, l as describeRejectionReason, m as resolveDenylist, n as urlAttributes, nt as BrowserSpanEventType, o as SafeCloneOptions, p as redactUrlQuery, q as Span, r as toCustomContext, rt as BrowserSpanType, s as safeClone, tt as User, u as routeRejection, v as glowsToEvents, x as SdkTaggable, y as flatJsonStringify, z as LogsEnvelope } from "./urlAttributes-DhkRD7pA.mjs";
2
2
 
3
3
  //#region src/api/Api.d.ts
4
4
  declare class Api {
@@ -277,6 +277,11 @@ declare class Flare {
277
277
  */
278
278
  withSpan<T>(name: string, fn: (span: Span) => T, opts?: SpanOptions): T;
279
279
  light(key?: string, debug?: boolean): this;
280
+ /**
281
+ * Turn sending on or off for consent. Off blocks errors, logs, and traces, and drops telemetry
282
+ * captured earlier so a later grant cannot ship it. On re-grant, flushes anything still buffered.
283
+ */
284
+ setConsent(granted: boolean): this;
280
285
  configure(config: Partial<Config>): this;
281
286
  test(): Promise<void>;
282
287
  private testInternal;
@@ -293,6 +298,11 @@ declare class Flare {
293
298
  setEntryPoint(handler: EntryPointHandler): this;
294
299
  setSdkInfo(info: SdkInfo): this;
295
300
  setFramework(framework: Framework): this;
301
+ /**
302
+ * True when a report must not be captured: consent withdrawn, or dropped by sampling. Consent is
303
+ * checked first, so a blocked report never runs the sampler or assembles a report (no cookie read).
304
+ */
305
+ private shouldSkipCapture;
296
306
  report(error: Error, attributes?: Attributes): Promise<void>;
297
307
  private reportInternal;
298
308
  reportSilently(error: Error, attributes?: Attributes): void;
@@ -350,7 +360,66 @@ declare class NullFileReader implements FileReader {
350
360
  read(_url: string): Promise<string | null>;
351
361
  }
352
362
  //#endregion
363
+ //#region src/device/types.d.ts
364
+ /** Effective connection quality. The API never reports 5g: a 5g device reports '4g'. */
365
+ type EffectiveConnectionType = 'slow-2g' | '2g' | '3g' | '4g';
366
+ /** Normalised device info. Every field optional: each provider fills what it reads, the mapper drops the rest. */
367
+ type DeviceInfo = {
368
+ os?: {
369
+ name?: string;
370
+ version?: string;
371
+ };
372
+ runtime?: {
373
+ name?: string;
374
+ version?: string;
375
+ };
376
+ device?: {
377
+ type?: string;
378
+ model?: string;
379
+ memoryGb?: number;
380
+ cpuCores?: number;
381
+ screen?: {
382
+ width?: number;
383
+ height?: number;
384
+ scale?: number;
385
+ };
386
+ };
387
+ network?: {
388
+ effectiveType?: EffectiveConnectionType;
389
+ downlinkMbps?: number;
390
+ rttMs?: number;
391
+ online?: boolean;
392
+ };
393
+ app?: {
394
+ version?: string;
395
+ id?: string;
396
+ };
397
+ locale?: {
398
+ language?: string;
399
+ timezone?: string;
400
+ };
401
+ };
402
+ //#endregion
403
+ //#region src/device/DeviceInfoProvider.d.ts
404
+ /** The seam each platform implements to read device info. A `ContextCollector` maps it with `deviceInfoToAttributes`. */
405
+ interface DeviceInfoProvider {
406
+ collect(): DeviceInfo;
407
+ }
408
+ /** Default for platforms with no device info. */
409
+ declare class NullDeviceInfoProvider implements DeviceInfoProvider {
410
+ collect(): DeviceInfo;
411
+ }
412
+ //#endregion
413
+ //#region src/device/deviceInfoToAttributes.d.ts
414
+ /** Map `DeviceInfo` to wire attributes: flat keys plus a `context.device` card. Shared by every SDK, so keys never drift. */
415
+ declare function deviceInfoToAttributes(info: DeviceInfo): Attributes;
416
+ /**
417
+ * `context.device` card for the error UI. Rendered one level deep, so values stay scalar. Built only when
418
+ * a device or network signal exists (an os-only Node report gets none).
419
+ */
420
+ declare function buildDeviceContextGroup(info: DeviceInfo): Record<string, AttributeValue>;
421
+ //#endregion
353
422
  //#region src/stacktrace/createStackTrace.d.ts
354
423
  declare function createStackTrace(error: Error, debug: boolean, fileReader: FileReader): Promise<Array<StackFrame>>;
355
424
  //#endregion
356
- export { type ActiveSpanHolder, type AnyValue, Api, type AttributeValue, type Attributes, BrowserSpanEventType, BrowserSpanType, type BufferedLog, type BufferedSpan, type Config, type ContextCollector, DEFAULT_MAX_LIVE_TRACES, DEFAULT_URL_DENYLIST, type EntryPointHandler, type EntryPointType, type FileReader, Flare, type FlushFn, type FlushScheduler, type Framework, FrameworkName, GlobalScopeProvider, type Glow, InMemoryActiveSpanHolder, type KeyValue, Logger, type LoggerDeps, type LogsEnvelope, MAX_BREADCRUMB_URL_LENGTH, type MessageLevel, NoopFlushScheduler, NullFileReader, type OtelLogRecord, type OtelSpan, type OverriddenGrouping, type RejectionReporter, type Report, type SafeCloneOptions, type SamplingContext, Scope, type ScopeProvider, type SdkInfo, type SdkTaggable, type Span, type SpanEvent, type SpanLifecycleEvent, type SpanLifecycleListener, type SpanOptions, type SpanPhase, type SpanStatus, SpanStatusCode, type SpanTypeName, type StackFrame, Tracer, type TracerDeps, type TracesEnvelope, type TracesSampler, USER_IDENTITY_KEYS, type User, assert, assertKey, breadcrumbUrl, buildTraceparent, buildTracesEnvelope, convertToError, createIdentityTagger, createStackTrace, defaultNowNano, describeRejectionReason, extractCode, flatJsonStringify, getCodeSnippet, glowsToEvents, now, parseTraceparent, readLinesFromFile, recordBreadcrumb, redactObjectValues, redactUrlQuery, resolveDenylist, routeRejection, safeClone, safeDecode, spanId, toCustomContext, urlAttributes, userIdentityAttributes };
425
+ export { type ActiveSpanHolder, type AnyValue, Api, type AttributeValue, type Attributes, BrowserSpanEventType, BrowserSpanType, type BufferedLog, type BufferedSpan, type Config, type ContextCollector, DEFAULT_MAX_LIVE_TRACES, DEFAULT_URL_DENYLIST, type DeviceInfo, type DeviceInfoProvider, type EffectiveConnectionType, type EntryPointHandler, type EntryPointType, type FileReader, Flare, type FlushFn, type FlushScheduler, type Framework, FrameworkName, GlobalScopeProvider, type Glow, InMemoryActiveSpanHolder, type KeyValue, Logger, type LoggerDeps, type LogsEnvelope, MAX_BREADCRUMB_URL_LENGTH, type MessageLevel, NoopFlushScheduler, NullDeviceInfoProvider, NullFileReader, type OtelLogRecord, type OtelSpan, type OverriddenGrouping, type RejectionReporter, type Report, type SafeCloneOptions, type SamplingContext, Scope, type ScopeProvider, type SdkInfo, type SdkTaggable, type Span, type SpanEvent, type SpanLifecycleEvent, type SpanLifecycleListener, type SpanOptions, type SpanPhase, type SpanStatus, SpanStatusCode, type SpanTypeName, type StackFrame, Tracer, type TracerDeps, type TracesEnvelope, type TracesSampler, USER_IDENTITY_KEYS, type User, assert, assertKey, breadcrumbUrl, buildDeviceContextGroup, buildTraceparent, buildTracesEnvelope, convertToError, createIdentityTagger, createStackTrace, defaultNowNano, describeRejectionReason, deviceInfoToAttributes, extractCode, flatJsonStringify, getCodeSnippet, glowsToEvents, now, parseTraceparent, readLinesFromFile, recordBreadcrumb, redactObjectValues, redactUrlQuery, resolveDenylist, routeRejection, safeClone, safeDecode, spanId, toCustomContext, urlAttributes, userIdentityAttributes };
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { D as CLIENT_VERSION, E as assert, O as KEY, S as convertToError, T as assertKey, _ as TRUNCATED, a as routeRejection, b as extractCode, c as redactUrlQuery, d as now, f as timelineEvents, g as MAX_TRAVERSAL_DEPTH, h as safeClone, i as describeRejectionReason, k as SOURCEMAP_VERSION, l as resolveDenylist, m as flatJsonStringify, n as urlAttributes, o as DEFAULT_URL_DENYLIST, p as glowsToEvents, r as toCustomContext, s as redactObjectValues, u as safeDecode, v as createTraversalBudget, x as createIdentityTagger, y as spendNode } from "./urlAttributes-qNkR9fIF.mjs";
1
+ import { A as SOURCEMAP_VERSION, C as convertToError, D as assert, E as assertKey, O as CLIENT_VERSION, S as createIdentityTagger, _ as MAX_TRAVERSAL_DEPTH, a as describeRejectionReason, b as spendNode, c as redactObjectValues, d as safeDecode, f as now, g as safeClone, h as flatJsonStringify, i as setDefined, k as KEY, l as redactUrlQuery, m as glowsToEvents, n as urlAttributes, o as routeRejection, p as timelineEvents, r as toCustomContext, s as DEFAULT_URL_DENYLIST, u as resolveDenylist, v as TRUNCATED, x as extractCode, y as createTraversalBudget } from "./urlAttributes-DmpMd_4O.mjs";
2
2
  import ErrorStackParser from "error-stack-parser";
3
3
 
4
4
  //#region src/framework.ts
@@ -191,6 +191,7 @@ var TelemetryBuffer = class {
191
191
  }
192
192
  add(record) {
193
193
  const config = this.deps.getConfig();
194
+ if (config.hasConsent === false) return;
194
195
  const limits = this.policy.limits(config);
195
196
  const bytes = this.policy.estimateBytes(record);
196
197
  if (bytes > limits.maxBytes) {
@@ -210,6 +211,10 @@ var TelemetryBuffer = class {
210
211
  const config = this.deps.getConfig();
211
212
  if (!this.policy.enabled(config)) return;
212
213
  if (this.entries.length === 0) return;
214
+ if (config.hasConsent === false) {
215
+ this.clearTimer();
216
+ return;
217
+ }
213
218
  if (!assertKey(config.key, config.debug)) {
214
219
  this.clearTimer();
215
220
  return;
@@ -545,6 +550,7 @@ var Logger = class {
545
550
  }
546
551
  record(level, message, context, attributes) {
547
552
  const config = this.deps.getConfig();
553
+ if (config.hasConsent === false) return;
548
554
  if (!config.enableLogs) return;
549
555
  if (config.minimumLogLevel && !isAtOrAboveMinimum(level, config.minimumLogLevel)) return;
550
556
  const userAttributes = {
@@ -583,6 +589,8 @@ const RESOURCE_PREFIXES = [
583
589
  "host.",
584
590
  "os.",
585
591
  "process.",
592
+ "device.",
593
+ "network.",
586
594
  "flare.framework.",
587
595
  "flare.language."
588
596
  ];
@@ -1412,6 +1420,7 @@ var Flare = class {
1412
1420
  _tracer;
1413
1421
  _config = {
1414
1422
  key: null,
1423
+ hasConsent: true,
1415
1424
  version: "",
1416
1425
  sourcemapVersionId: SOURCEMAP_VERSION,
1417
1426
  stage: "",
@@ -1553,6 +1562,21 @@ var Flare = class {
1553
1562
  this._tracer.flush();
1554
1563
  return this;
1555
1564
  }
1565
+ /**
1566
+ * Turn sending on or off for consent. Off blocks errors, logs, and traces, and drops telemetry
1567
+ * captured earlier so a later grant cannot ship it. On re-grant, flushes anything still buffered.
1568
+ */
1569
+ setConsent(granted) {
1570
+ this._config.hasConsent = granted;
1571
+ if (granted) {
1572
+ this._logger.flush();
1573
+ this._tracer.flush();
1574
+ } else {
1575
+ this._logger.clear();
1576
+ this._tracer.clear();
1577
+ }
1578
+ return this;
1579
+ }
1556
1580
  configure(config) {
1557
1581
  const wasLogsEnabled = this._config.enableLogs;
1558
1582
  const wasTracingEnabled = this._config.enableTracing;
@@ -1639,11 +1663,19 @@ var Flare = class {
1639
1663
  this.framework = framework;
1640
1664
  return this;
1641
1665
  }
1666
+ /**
1667
+ * True when a report must not be captured: consent withdrawn, or dropped by sampling. Consent is
1668
+ * checked first, so a blocked report never runs the sampler or assembles a report (no cookie read).
1669
+ */
1670
+ shouldSkipCapture() {
1671
+ if (this._config.hasConsent === false) return true;
1672
+ return this._config.sampleRate < 1 && Math.random() >= this._config.sampleRate;
1673
+ }
1642
1674
  report(error, attributes = {}) {
1643
1675
  return this.track(this.reportInternal(error, attributes));
1644
1676
  }
1645
1677
  async reportInternal(error, attributes = {}) {
1646
- if (this._config.sampleRate < 1 && Math.random() >= this._config.sampleRate) return;
1678
+ if (this.shouldSkipCapture()) return;
1647
1679
  const seenAtUnixNano = Date.now() * 1e6;
1648
1680
  const coerced = error instanceof Error ? error : new Error(String(error));
1649
1681
  const errorToReport = await this._config.beforeEvaluate(coerced);
@@ -1659,7 +1691,7 @@ var Flare = class {
1659
1691
  return this.track(this.reportUnhandledRejectionInternal(message, attributes));
1660
1692
  }
1661
1693
  async reportUnhandledRejectionInternal(message, attributes = {}) {
1662
- if (this._config.sampleRate < 1 && Math.random() >= this._config.sampleRate) return;
1694
+ if (this.shouldSkipCapture()) return;
1663
1695
  const seenAtUnixNano = Date.now() * 1e6;
1664
1696
  const report = this.buildReport({
1665
1697
  exceptionClass: "UnhandledRejection",
@@ -1677,7 +1709,7 @@ var Flare = class {
1677
1709
  return this.track(this.reportMessageInternal(message, level, attributes));
1678
1710
  }
1679
1711
  async reportMessageInternal(message, level, attributes = {}) {
1680
- if (this._config.sampleRate < 1 && Math.random() >= this._config.sampleRate) return;
1712
+ if (this.shouldSkipCapture()) return;
1681
1713
  const seenAtUnixNano = Date.now() * 1e6;
1682
1714
  const stackTrace = await createStackTrace(/* @__PURE__ */ new Error(), this._config.debug, this.fileReader);
1683
1715
  stackTrace.shift();
@@ -1794,6 +1826,7 @@ var Flare = class {
1794
1826
  return report;
1795
1827
  }
1796
1828
  async sendReport(report) {
1829
+ if (this._config.hasConsent === false) return;
1797
1830
  if (!assertKey(this._config.key, this._config.debug)) return;
1798
1831
  const reportToSubmit = await this._config.beforeSubmit(report);
1799
1832
  if (!reportToSubmit) return;
@@ -1802,4 +1835,71 @@ var Flare = class {
1802
1835
  };
1803
1836
 
1804
1837
  //#endregion
1805
- export { Api, BrowserSpanEventType, BrowserSpanType, DEFAULT_MAX_LIVE_TRACES, DEFAULT_URL_DENYLIST, Flare, FrameworkName, GlobalScopeProvider, InMemoryActiveSpanHolder, Logger, MAX_BREADCRUMB_URL_LENGTH, NoopFlushScheduler, NullFileReader, Scope, SpanStatusCode, Tracer, USER_IDENTITY_KEYS, assert, assertKey, breadcrumbUrl, buildTraceparent, buildTracesEnvelope, convertToError, createIdentityTagger, createStackTrace, defaultNowNano, describeRejectionReason, extractCode, flatJsonStringify, getCodeSnippet, glowsToEvents, now, parseTraceparent, readLinesFromFile, recordBreadcrumb, redactObjectValues, redactUrlQuery, resolveDenylist, routeRejection, safeClone, safeDecode, spanId, toCustomContext, urlAttributes, userIdentityAttributes };
1838
+ //#region src/device/DeviceInfoProvider.ts
1839
+ /** Default for platforms with no device info. */
1840
+ var NullDeviceInfoProvider = class {
1841
+ collect() {
1842
+ return {};
1843
+ }
1844
+ };
1845
+
1846
+ //#endregion
1847
+ //#region src/device/deviceInfoToAttributes.ts
1848
+ /** Map `DeviceInfo` to wire attributes: flat keys plus a `context.device` card. Shared by every SDK, so keys never drift. */
1849
+ function deviceInfoToAttributes(info) {
1850
+ const attrs = {};
1851
+ setDefined(attrs, "os.name", info.os?.name);
1852
+ setDefined(attrs, "os.version", info.os?.version);
1853
+ setDefined(attrs, "process.runtime.name", info.runtime?.name);
1854
+ setDefined(attrs, "process.runtime.version", info.runtime?.version);
1855
+ setDefined(attrs, "device.type", info.device?.type);
1856
+ setDefined(attrs, "device.model.name", info.device?.model);
1857
+ setDefined(attrs, "device.memory_gb", info.device?.memoryGb);
1858
+ setDefined(attrs, "device.cpu_cores", info.device?.cpuCores);
1859
+ setDefined(attrs, "device.screen.width", info.device?.screen?.width);
1860
+ setDefined(attrs, "device.screen.height", info.device?.screen?.height);
1861
+ setDefined(attrs, "device.screen.scale", info.device?.screen?.scale);
1862
+ setDefined(attrs, "network.effective_type", info.network?.effectiveType);
1863
+ setDefined(attrs, "network.downlink_mbps", info.network?.downlinkMbps);
1864
+ setDefined(attrs, "network.rtt_ms", info.network?.rttMs);
1865
+ setDefined(attrs, "network.online", info.network?.online);
1866
+ setDefined(attrs, "app.version", info.app?.version);
1867
+ setDefined(attrs, "app.id", info.app?.id);
1868
+ const group = buildDeviceContextGroup(info);
1869
+ if (Object.keys(group).length > 0) attrs["context.device"] = group;
1870
+ return attrs;
1871
+ }
1872
+ /**
1873
+ * `context.device` card for the error UI. Rendered one level deep, so values stay scalar. Built only when
1874
+ * a device or network signal exists (an os-only Node report gets none).
1875
+ */
1876
+ function buildDeviceContextGroup(info) {
1877
+ if (!hasDeviceSignal(info.device) && !hasNetworkSignal(info.network)) return {};
1878
+ const group = {};
1879
+ const os = [info.os?.name, info.os?.version].filter((value) => value != null).join(" ");
1880
+ if (os) group.OS = os;
1881
+ setDefined(group, "Model", info.device?.model);
1882
+ setDefined(group, "Type", info.device?.type);
1883
+ const screen = info.device?.screen;
1884
+ if (screen?.width != null && screen?.height != null) group.Screen = screen.scale != null ? `${screen.width} × ${screen.height} @ ${screen.scale}x` : `${screen.width} × ${screen.height}`;
1885
+ if (info.device?.memoryGb != null) group.Memory = `${info.device.memoryGb} GB`;
1886
+ setDefined(group, "CPU cores", info.device?.cpuCores);
1887
+ setDefined(group, "Connection", info.network?.effectiveType);
1888
+ if (info.network?.downlinkMbps != null) group.Downlink = `${info.network.downlinkMbps} Mbps`;
1889
+ if (info.network?.rttMs != null) group.RTT = `${info.network.rttMs} ms`;
1890
+ setDefined(group, "Online", info.network?.online);
1891
+ setDefined(group, "App version", info.app?.version);
1892
+ setDefined(group, "App ID", info.app?.id);
1893
+ setDefined(group, "Language", info.locale?.language);
1894
+ setDefined(group, "Timezone", info.locale?.timezone);
1895
+ return group;
1896
+ }
1897
+ function hasDeviceSignal(device) {
1898
+ return device != null && (device.type != null || device.model != null || device.memoryGb != null || device.cpuCores != null || device.screen?.width != null || device.screen?.height != null);
1899
+ }
1900
+ function hasNetworkSignal(network) {
1901
+ return network != null && (network.effectiveType != null || network.downlinkMbps != null || network.rttMs != null || network.online != null);
1902
+ }
1903
+
1904
+ //#endregion
1905
+ export { Api, BrowserSpanEventType, BrowserSpanType, DEFAULT_MAX_LIVE_TRACES, DEFAULT_URL_DENYLIST, Flare, FrameworkName, GlobalScopeProvider, InMemoryActiveSpanHolder, Logger, MAX_BREADCRUMB_URL_LENGTH, NoopFlushScheduler, NullDeviceInfoProvider, NullFileReader, Scope, SpanStatusCode, Tracer, USER_IDENTITY_KEYS, assert, assertKey, breadcrumbUrl, buildDeviceContextGroup, buildTraceparent, buildTracesEnvelope, convertToError, createIdentityTagger, createStackTrace, defaultNowNano, describeRejectionReason, deviceInfoToAttributes, extractCode, flatJsonStringify, getCodeSnippet, glowsToEvents, now, parseTraceparent, readLinesFromFile, recordBreadcrumb, redactObjectValues, redactUrlQuery, resolveDenylist, routeRejection, safeClone, safeDecode, spanId, toCustomContext, urlAttributes, userIdentityAttributes };
@@ -1,6 +1,6 @@
1
1
 
2
2
  //#region src/env/index.ts
3
- const CLIENT_VERSION = typeof process !== "undefined" && true ? "2.9.0" : "?";
3
+ const CLIENT_VERSION = typeof process !== "undefined" && true ? "2.11.0" : "?";
4
4
  const KEY = typeof FLARE_JS_KEY === "undefined" ? "" : FLARE_JS_KEY;
5
5
  const SOURCEMAP_VERSION = typeof FLARE_SOURCEMAP_VERSION === "undefined" ? "" : FLARE_SOURCEMAP_VERSION;
6
6
 
@@ -351,6 +351,13 @@ function routeRejection(reporter, reason) {
351
351
  Promise.resolve(reporter.reportUnhandledRejection(describeRejectionReason(reason))).catch(() => {});
352
352
  }
353
353
 
354
+ //#endregion
355
+ //#region src/util/setDefined.ts
356
+ /** Assign the value only when it is neither undefined nor null. */
357
+ function setDefined(target, key, value) {
358
+ if (value !== void 0 && value !== null) target[key] = value;
359
+ }
360
+
354
361
  //#endregion
355
362
  //#region src/util/toCustomContext.ts
356
363
  /** Wraps a framework payload as the `context.custom` attribute a report expects. */
@@ -534,6 +541,12 @@ Object.defineProperty(exports, 'safeDecode', {
534
541
  return safeDecode;
535
542
  }
536
543
  });
544
+ Object.defineProperty(exports, 'setDefined', {
545
+ enumerable: true,
546
+ get: function () {
547
+ return setDefined;
548
+ }
549
+ });
537
550
  Object.defineProperty(exports, 'spendNode', {
538
551
  enumerable: true,
539
552
  get: function () {
@@ -65,6 +65,9 @@ type User = {
65
65
  };
66
66
  type Config = {
67
67
  key: string | null;
68
+ /** When false, the SDK sends nothing: no errors, logs, or traces. Flip it with `setConsent()`.
69
+ * Default true, so setups without a consent tool are unchanged. */
70
+ hasConsent: boolean;
68
71
  version: string;
69
72
  sourcemapVersionId: string;
70
73
  stage: string;
@@ -434,6 +437,10 @@ type SafeCloneOptions = {
434
437
  */
435
438
  declare function safeClone(value: unknown, options: SafeCloneOptions): unknown;
436
439
  //#endregion
440
+ //#region src/util/setDefined.d.ts
441
+ /** Assign the value only when it is neither undefined nor null. */
442
+ declare function setDefined(target: Attributes, key: string, value: AttributeValue | undefined): void;
443
+ //#endregion
437
444
  //#region src/util/statelessRegExp.d.ts
438
445
  /**
439
446
  * A `/g` or `/y` regex carries `lastIndex` between `test()` calls, so every other call misses. Returns
@@ -460,4 +467,4 @@ declare const MAX_URL_LENGTH = 2048;
460
467
  */
461
468
  declare function urlAttributes(url: string, denylist?: RegExp): Attributes;
462
469
  //#endregion
463
- export { TracesSampler as $, BufferedLog as A, OtelLogRecord as B, ProfileComponentsOption as C, AnyValue as D, assert as E, Framework as F, SdkInfo as G, OverriddenGrouping as H, Glow as I, SpanOptions as J, Span as K, KeyValue as L, Config as M, EntryPointHandler as N, AttributeValue as O, EntryPointType as P, TracesEnvelope as Q, LogsEnvelope as R, convertToError as S, assertKey as T, Report as U, OtelSpan as V, SamplingContext as W, SpanStatusCode as X, SpanStatus as Y, StackFrame as Z, glowsToEvents as _, SafeCloneOptions as a, SdkTaggable as b, describeRejectionReason as c, redactObjectValues as d, User as et, redactUrlQuery as f, timelineEvents as g, now as h, withoutStatefulFlags as i, FrameworkName as it, BufferedSpan as j, Attributes as k, routeRejection as l, safeDecode as m, urlAttributes as n, BrowserSpanType as nt, safeClone as o, resolveDenylist as p, SpanEvent as q, toCustomContext as r, SpanTypeName as rt, RejectionReporter as s, MAX_URL_LENGTH as t, BrowserSpanEventType as tt, DEFAULT_URL_DENYLIST as u, flatJsonStringify as v, createComponentMatcher as w, createIdentityTagger as x, extractCode as y, MessageLevel as z };
470
+ export { TracesEnvelope as $, Attributes as A, MessageLevel as B, convertToError as C, assert as D, assertKey as E, EntryPointType as F, SamplingContext as G, OtelSpan as H, Framework as I, SpanEvent as J, SdkInfo as K, Glow as L, BufferedSpan as M, Config as N, AnyValue as O, EntryPointHandler as P, StackFrame as Q, KeyValue as R, createIdentityTagger as S, createComponentMatcher as T, OverriddenGrouping as U, OtelLogRecord as V, Report as W, SpanStatus as X, SpanOptions as Y, SpanStatusCode as Z, timelineEvents as _, setDefined as a, FrameworkName as at, extractCode as b, RejectionReporter as c, DEFAULT_URL_DENYLIST as d, TracesSampler as et, redactObjectValues as f, now as g, safeDecode as h, withoutStatefulFlags as i, SpanTypeName as it, BufferedLog as j, AttributeValue as k, describeRejectionReason as l, resolveDenylist as m, urlAttributes as n, BrowserSpanEventType as nt, SafeCloneOptions as o, redactUrlQuery as p, Span as q, toCustomContext as r, BrowserSpanType as rt, safeClone as s, MAX_URL_LENGTH as t, User as tt, routeRejection as u, glowsToEvents as v, ProfileComponentsOption as w, SdkTaggable as x, flatJsonStringify as y, LogsEnvelope as z };
@@ -65,6 +65,9 @@ type User = {
65
65
  };
66
66
  type Config = {
67
67
  key: string | null;
68
+ /** When false, the SDK sends nothing: no errors, logs, or traces. Flip it with `setConsent()`.
69
+ * Default true, so setups without a consent tool are unchanged. */
70
+ hasConsent: boolean;
68
71
  version: string;
69
72
  sourcemapVersionId: string;
70
73
  stage: string;
@@ -434,6 +437,10 @@ type SafeCloneOptions = {
434
437
  */
435
438
  declare function safeClone(value: unknown, options: SafeCloneOptions): unknown;
436
439
  //#endregion
440
+ //#region src/util/setDefined.d.ts
441
+ /** Assign the value only when it is neither undefined nor null. */
442
+ declare function setDefined(target: Attributes, key: string, value: AttributeValue | undefined): void;
443
+ //#endregion
437
444
  //#region src/util/statelessRegExp.d.ts
438
445
  /**
439
446
  * A `/g` or `/y` regex carries `lastIndex` between `test()` calls, so every other call misses. Returns
@@ -460,4 +467,4 @@ declare const MAX_URL_LENGTH = 2048;
460
467
  */
461
468
  declare function urlAttributes(url: string, denylist?: RegExp): Attributes;
462
469
  //#endregion
463
- export { TracesSampler as $, BufferedLog as A, OtelLogRecord as B, ProfileComponentsOption as C, AnyValue as D, assert as E, Framework as F, SdkInfo as G, OverriddenGrouping as H, Glow as I, SpanOptions as J, Span as K, KeyValue as L, Config as M, EntryPointHandler as N, AttributeValue as O, EntryPointType as P, TracesEnvelope as Q, LogsEnvelope as R, convertToError as S, assertKey as T, Report as U, OtelSpan as V, SamplingContext as W, SpanStatusCode as X, SpanStatus as Y, StackFrame as Z, glowsToEvents as _, SafeCloneOptions as a, SdkTaggable as b, describeRejectionReason as c, redactObjectValues as d, User as et, redactUrlQuery as f, timelineEvents as g, now as h, withoutStatefulFlags as i, FrameworkName as it, BufferedSpan as j, Attributes as k, routeRejection as l, safeDecode as m, urlAttributes as n, BrowserSpanType as nt, safeClone as o, resolveDenylist as p, SpanEvent as q, toCustomContext as r, SpanTypeName as rt, RejectionReporter as s, MAX_URL_LENGTH as t, BrowserSpanEventType as tt, DEFAULT_URL_DENYLIST as u, flatJsonStringify as v, createComponentMatcher as w, createIdentityTagger as x, extractCode as y, MessageLevel as z };
470
+ export { TracesEnvelope as $, Attributes as A, MessageLevel as B, convertToError as C, assert as D, assertKey as E, EntryPointType as F, SamplingContext as G, OtelSpan as H, Framework as I, SpanEvent as J, SdkInfo as K, Glow as L, BufferedSpan as M, Config as N, AnyValue as O, EntryPointHandler as P, StackFrame as Q, KeyValue as R, createIdentityTagger as S, createComponentMatcher as T, OverriddenGrouping as U, OtelLogRecord as V, Report as W, SpanStatus as X, SpanOptions as Y, SpanStatusCode as Z, timelineEvents as _, setDefined as a, FrameworkName as at, extractCode as b, RejectionReporter as c, DEFAULT_URL_DENYLIST as d, TracesSampler as et, redactObjectValues as f, now as g, safeDecode as h, withoutStatefulFlags as i, SpanTypeName as it, BufferedLog as j, AttributeValue as k, describeRejectionReason as l, resolveDenylist as m, urlAttributes as n, BrowserSpanEventType as nt, SafeCloneOptions as o, redactUrlQuery as p, Span as q, toCustomContext as r, BrowserSpanType as rt, safeClone as s, MAX_URL_LENGTH as t, User as tt, routeRejection as u, glowsToEvents as v, ProfileComponentsOption as w, SdkTaggable as x, flatJsonStringify as y, LogsEnvelope as z };
@@ -1,5 +1,5 @@
1
1
  //#region src/env/index.ts
2
- const CLIENT_VERSION = typeof process !== "undefined" && true ? "2.9.0" : "?";
2
+ const CLIENT_VERSION = typeof process !== "undefined" && true ? "2.11.0" : "?";
3
3
  const KEY = typeof FLARE_JS_KEY === "undefined" ? "" : FLARE_JS_KEY;
4
4
  const SOURCEMAP_VERSION = typeof FLARE_SOURCEMAP_VERSION === "undefined" ? "" : FLARE_SOURCEMAP_VERSION;
5
5
 
@@ -350,6 +350,13 @@ function routeRejection(reporter, reason) {
350
350
  Promise.resolve(reporter.reportUnhandledRejection(describeRejectionReason(reason))).catch(() => {});
351
351
  }
352
352
 
353
+ //#endregion
354
+ //#region src/util/setDefined.ts
355
+ /** Assign the value only when it is neither undefined nor null. */
356
+ function setDefined(target, key, value) {
357
+ if (value !== void 0 && value !== null) target[key] = value;
358
+ }
359
+
353
360
  //#endregion
354
361
  //#region src/util/toCustomContext.ts
355
362
  /** Wraps a framework payload as the `context.custom` attribute a report expects. */
@@ -389,4 +396,4 @@ function urlAttributes(url, denylist = DEFAULT_URL_DENYLIST) {
389
396
  }
390
397
 
391
398
  //#endregion
392
- export { createComponentMatcher as C, CLIENT_VERSION as D, assert as E, KEY as O, convertToError as S, assertKey as T, TRUNCATED as _, routeRejection as a, extractCode as b, redactUrlQuery as c, now as d, timelineEvents as f, MAX_TRAVERSAL_DEPTH as g, safeClone as h, describeRejectionReason as i, SOURCEMAP_VERSION as k, resolveDenylist as l, flatJsonStringify as m, urlAttributes as n, DEFAULT_URL_DENYLIST as o, glowsToEvents as p, toCustomContext as r, redactObjectValues as s, MAX_URL_LENGTH as t, safeDecode as u, createTraversalBudget as v, withoutStatefulFlags as w, createIdentityTagger as x, spendNode as y };
399
+ export { SOURCEMAP_VERSION as A, convertToError as C, assert as D, assertKey as E, CLIENT_VERSION as O, createIdentityTagger as S, withoutStatefulFlags as T, MAX_TRAVERSAL_DEPTH as _, describeRejectionReason as a, spendNode as b, redactObjectValues as c, safeDecode as d, now as f, safeClone as g, flatJsonStringify as h, setDefined as i, KEY as k, redactUrlQuery as l, glowsToEvents as m, urlAttributes as n, routeRejection as o, timelineEvents as p, toCustomContext as r, DEFAULT_URL_DENYLIST as s, MAX_URL_LENGTH as t, resolveDenylist as u, TRUNCATED as v, createComponentMatcher as w, extractCode as x, createTraversalBudget as y };
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
- const require_urlAttributes = require('../urlAttributes-CEP6bOBn.cjs');
2
+ const require_urlAttributes = require('../urlAttributes-Cinqzwjy.cjs');
3
3
 
4
4
  exports.DEFAULT_URL_DENYLIST = require_urlAttributes.DEFAULT_URL_DENYLIST;
5
5
  exports.MAX_URL_LENGTH = require_urlAttributes.MAX_URL_LENGTH;
@@ -19,6 +19,7 @@ exports.resolveDenylist = require_urlAttributes.resolveDenylist;
19
19
  exports.routeRejection = require_urlAttributes.routeRejection;
20
20
  exports.safeClone = require_urlAttributes.safeClone;
21
21
  exports.safeDecode = require_urlAttributes.safeDecode;
22
+ exports.setDefined = require_urlAttributes.setDefined;
22
23
  exports.timelineEvents = require_urlAttributes.timelineEvents;
23
24
  exports.toCustomContext = require_urlAttributes.toCustomContext;
24
25
  exports.urlAttributes = require_urlAttributes.urlAttributes;
@@ -1,2 +1,2 @@
1
- import { C as ProfileComponentsOption, E as assert, S as convertToError, T as assertKey, _ as glowsToEvents, a as SafeCloneOptions, b as SdkTaggable, c as describeRejectionReason, d as redactObjectValues, f as redactUrlQuery, g as timelineEvents, h as now, i as withoutStatefulFlags, l as routeRejection, m as safeDecode, n as urlAttributes, o as safeClone, p as resolveDenylist, r as toCustomContext, s as RejectionReporter, t as MAX_URL_LENGTH, u as DEFAULT_URL_DENYLIST, v as flatJsonStringify, w as createComponentMatcher, x as createIdentityTagger, y as extractCode } from "../urlAttributes-DSPpBmH-.cjs";
2
- export { DEFAULT_URL_DENYLIST, MAX_URL_LENGTH, ProfileComponentsOption, RejectionReporter, SafeCloneOptions, SdkTaggable, assert, assertKey, convertToError, createComponentMatcher, createIdentityTagger, describeRejectionReason, extractCode, flatJsonStringify, glowsToEvents, now, redactObjectValues, redactUrlQuery, resolveDenylist, routeRejection, safeClone, safeDecode, timelineEvents, toCustomContext, urlAttributes, withoutStatefulFlags };
1
+ import { C as convertToError, D as assert, E as assertKey, S as createIdentityTagger, T as createComponentMatcher, _ as timelineEvents, a as setDefined, b as extractCode, c as RejectionReporter, d as DEFAULT_URL_DENYLIST, f as redactObjectValues, g as now, h as safeDecode, i as withoutStatefulFlags, l as describeRejectionReason, m as resolveDenylist, n as urlAttributes, o as SafeCloneOptions, p as redactUrlQuery, r as toCustomContext, s as safeClone, t as MAX_URL_LENGTH, u as routeRejection, v as glowsToEvents, w as ProfileComponentsOption, x as SdkTaggable, y as flatJsonStringify } from "../urlAttributes-D0zqStcw.cjs";
2
+ export { DEFAULT_URL_DENYLIST, MAX_URL_LENGTH, ProfileComponentsOption, RejectionReporter, SafeCloneOptions, SdkTaggable, assert, assertKey, convertToError, createComponentMatcher, createIdentityTagger, describeRejectionReason, extractCode, flatJsonStringify, glowsToEvents, now, redactObjectValues, redactUrlQuery, resolveDenylist, routeRejection, safeClone, safeDecode, setDefined, timelineEvents, toCustomContext, urlAttributes, withoutStatefulFlags };
@@ -1,2 +1,2 @@
1
- import { C as ProfileComponentsOption, E as assert, S as convertToError, T as assertKey, _ as glowsToEvents, a as SafeCloneOptions, b as SdkTaggable, c as describeRejectionReason, d as redactObjectValues, f as redactUrlQuery, g as timelineEvents, h as now, i as withoutStatefulFlags, l as routeRejection, m as safeDecode, n as urlAttributes, o as safeClone, p as resolveDenylist, r as toCustomContext, s as RejectionReporter, t as MAX_URL_LENGTH, u as DEFAULT_URL_DENYLIST, v as flatJsonStringify, w as createComponentMatcher, x as createIdentityTagger, y as extractCode } from "../urlAttributes-CYJKlJKi.mjs";
2
- export { DEFAULT_URL_DENYLIST, MAX_URL_LENGTH, ProfileComponentsOption, RejectionReporter, SafeCloneOptions, SdkTaggable, assert, assertKey, convertToError, createComponentMatcher, createIdentityTagger, describeRejectionReason, extractCode, flatJsonStringify, glowsToEvents, now, redactObjectValues, redactUrlQuery, resolveDenylist, routeRejection, safeClone, safeDecode, timelineEvents, toCustomContext, urlAttributes, withoutStatefulFlags };
1
+ import { C as convertToError, D as assert, E as assertKey, S as createIdentityTagger, T as createComponentMatcher, _ as timelineEvents, a as setDefined, b as extractCode, c as RejectionReporter, d as DEFAULT_URL_DENYLIST, f as redactObjectValues, g as now, h as safeDecode, i as withoutStatefulFlags, l as describeRejectionReason, m as resolveDenylist, n as urlAttributes, o as SafeCloneOptions, p as redactUrlQuery, r as toCustomContext, s as safeClone, t as MAX_URL_LENGTH, u as routeRejection, v as glowsToEvents, w as ProfileComponentsOption, x as SdkTaggable, y as flatJsonStringify } from "../urlAttributes-DhkRD7pA.mjs";
2
+ export { DEFAULT_URL_DENYLIST, MAX_URL_LENGTH, ProfileComponentsOption, RejectionReporter, SafeCloneOptions, SdkTaggable, assert, assertKey, convertToError, createComponentMatcher, createIdentityTagger, describeRejectionReason, extractCode, flatJsonStringify, glowsToEvents, now, redactObjectValues, redactUrlQuery, resolveDenylist, routeRejection, safeClone, safeDecode, setDefined, timelineEvents, toCustomContext, urlAttributes, withoutStatefulFlags };
@@ -1,3 +1,3 @@
1
- import { C as createComponentMatcher, E as assert, S as convertToError, T as assertKey, a as routeRejection, b as extractCode, c as redactUrlQuery, d as now, f as timelineEvents, h as safeClone, i as describeRejectionReason, l as resolveDenylist, m as flatJsonStringify, n as urlAttributes, o as DEFAULT_URL_DENYLIST, p as glowsToEvents, r as toCustomContext, s as redactObjectValues, t as MAX_URL_LENGTH, u as safeDecode, w as withoutStatefulFlags, x as createIdentityTagger } from "../urlAttributes-qNkR9fIF.mjs";
1
+ import { C as convertToError, D as assert, E as assertKey, S as createIdentityTagger, T as withoutStatefulFlags, a as describeRejectionReason, c as redactObjectValues, d as safeDecode, f as now, g as safeClone, h as flatJsonStringify, i as setDefined, l as redactUrlQuery, m as glowsToEvents, n as urlAttributes, o as routeRejection, p as timelineEvents, r as toCustomContext, s as DEFAULT_URL_DENYLIST, t as MAX_URL_LENGTH, u as resolveDenylist, w as createComponentMatcher, x as extractCode } from "../urlAttributes-DmpMd_4O.mjs";
2
2
 
3
- export { DEFAULT_URL_DENYLIST, MAX_URL_LENGTH, assert, assertKey, convertToError, createComponentMatcher, createIdentityTagger, describeRejectionReason, extractCode, flatJsonStringify, glowsToEvents, now, redactObjectValues, redactUrlQuery, resolveDenylist, routeRejection, safeClone, safeDecode, timelineEvents, toCustomContext, urlAttributes, withoutStatefulFlags };
3
+ export { DEFAULT_URL_DENYLIST, MAX_URL_LENGTH, assert, assertKey, convertToError, createComponentMatcher, createIdentityTagger, describeRejectionReason, extractCode, flatJsonStringify, glowsToEvents, now, redactObjectValues, redactUrlQuery, resolveDenylist, routeRejection, safeClone, safeDecode, setDefined, timelineEvents, toCustomContext, urlAttributes, withoutStatefulFlags };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flareapp/core",
3
- "version": "2.9.0",
3
+ "version": "2.11.0",
4
4
  "description": "Environment-agnostic core for the Flare JS SDK",
5
5
  "homepage": "https://flareapp.io",
6
6
  "bugs": {