@flareapp/electron 2.10.0 → 2.12.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/main.cjs CHANGED
@@ -34,7 +34,7 @@ let node_fs_promises = require("node:fs/promises");
34
34
  let node_url = require("node:url");
35
35
 
36
36
  //#region src/env.ts
37
- const CLIENT_VERSION = typeof process !== "undefined" && true ? "2.10.0" : "?";
37
+ const CLIENT_VERSION = typeof process !== "undefined" && true ? "2.12.0" : "?";
38
38
 
39
39
  //#endregion
40
40
  //#region src/types.ts
@@ -48,33 +48,44 @@ const DEFAULT_ELECTRON_OPTIONS = {
48
48
  maxReportBytes: 1e6
49
49
  };
50
50
 
51
+ //#endregion
52
+ //#region src/main/deviceInfo.ts
53
+ var ElectronDeviceInfoProvider = class {
54
+ collect() {
55
+ const versions = process.versions;
56
+ return {
57
+ os: {
58
+ name: node_os.default.type(),
59
+ version: node_os.default.release()
60
+ },
61
+ runtime: {
62
+ name: "electron",
63
+ version: versions.electron
64
+ }
65
+ };
66
+ }
67
+ };
68
+ const electronDeviceInfoProvider = new ElectronDeviceInfoProvider();
69
+
51
70
  //#endregion
52
71
  //#region src/main/collectElectron.ts
53
- /**
54
- * App + runtime attributes safe to overlay onto any report regardless of origin. Reused by both
55
- * the collector (main errors) and the IPC receiver (forwarded renderer reports). Excludes per-process
56
- * fields like `flare.entry_point.type` / `process.type` so forwarded renderer reports keep their own.
57
- */
58
72
  function collectElectronAppAttributes(app) {
59
73
  const versions = process.versions;
60
74
  const attrs = {
61
75
  "service.name": app.getName(),
62
76
  "app.version": app.getVersion(),
63
77
  "app.packaged": app.isPackaged,
64
- "process.runtime.name": "electron",
65
- "process.runtime.version": versions.electron ?? "",
66
78
  "process.versions.electron": versions.electron ?? "",
67
79
  "process.versions.chrome": versions.chrome ?? "",
68
80
  "process.versions.node": versions.node ?? process.version,
69
81
  "host.arch": process.arch,
70
- "os.type": node_os.default.type()
82
+ ...(0, _flareapp_core.deviceInfoToAttributes)(electronDeviceInfoProvider.collect())
71
83
  };
72
84
  if (app.isReady()) try {
73
85
  attrs["app.locale"] = app.getLocale();
74
86
  } catch {}
75
87
  return attrs;
76
88
  }
77
- /** Build the ContextCollector core calls on every main-process report. */
78
89
  function makeElectronContextCollector(app) {
79
90
  return (_config) => ({
80
91
  "flare.entry_point.type": "web",
@@ -85,7 +96,6 @@ function makeElectronContextCollector(app) {
85
96
 
86
97
  //#endregion
87
98
  //#region src/main/ElectronDiskFileReader.ts
88
- /** Reads source snippets for main-process stack frames from disk. Mirrors @flareapp/node's DiskFileReader. */
89
99
  var ElectronDiskFileReader = class {
90
100
  async read(url) {
91
101
  if (!isLocalFileUrl(url)) return null;
@@ -102,7 +112,6 @@ function isLocalFileUrl(url) {
102
112
 
103
113
  //#endregion
104
114
  //#region src/main/ElectronFlushScheduler.ts
105
- /** Flushes pending logs/reports when the Electron app is quitting. App is injectable for tests. */
106
115
  var ElectronFlushScheduler = class {
107
116
  listener = null;
108
117
  constructor(app) {
@@ -115,7 +124,6 @@ var ElectronFlushScheduler = class {
115
124
  };
116
125
  this.app.on("before-quit", this.listener);
117
126
  }
118
- /** Detach the before-quit listener so a disposed ElectronFlare leaves no flush handler on the shared app. */
119
127
  dispose() {
120
128
  if (this.listener) {
121
129
  this.app.off("before-quit", this.listener);
@@ -133,9 +141,7 @@ const FLARE_BRIDGE_KEY = "__flare";
133
141
 
134
142
  //#endregion
135
143
  //#region src/main/ipcReceiver.ts
136
- /** Module-level ownership token for the single flare:report channel. */
137
144
  let currentOwner = null;
138
- /** Default sender-trust check: accept file: and localhost/127.0.0.1 only, plus configured custom protocols. */
139
145
  function defaultTrustPolicy(frame, opts) {
140
146
  let parsed;
141
147
  try {
@@ -155,11 +161,6 @@ function isTrusted(frame, opts) {
155
161
  if (opts.trustSender) return opts.trustSender(frame);
156
162
  return defaultTrustPolicy(frame, opts);
157
163
  }
158
- /**
159
- * Minimal top-level structural guard for a parsed report, not an exhaustive StackFrame/SpanEvent
160
- * validator: a compromised renderer could forge any valid-looking shape anyway. The security boundary
161
- * is the sender-trust check plus the byte-size cap; this only rejects obviously-wrong payloads.
162
- */
163
164
  function isReportShape(value) {
164
165
  if (typeof value !== "object" || value === null) return false;
165
166
  const r = value;
@@ -192,11 +193,6 @@ function disposeIpcReceiver(ipcMain, owner) {
192
193
 
193
194
  //#endregion
194
195
  //#region src/main/processHandlers.ts
195
- /**
196
- * Fatal callbacks for Electron main. Mirrors @flareapp/node's buildFatalCallbacks but exits via the
197
- * injected `exit` (app.exit at the call site), which is immediate and skips before-quit/will-quit,
198
- * correct after an uncaught exception.
199
- */
200
196
  function buildFatalCallbacks(flare, getOpts, exit) {
201
197
  return {
202
198
  async onUncaught(err, origin) {
@@ -225,15 +221,6 @@ function buildFatalCallbacks(flare, getOpts, exit) {
225
221
  }
226
222
  };
227
223
  }
228
- /**
229
- * Owns the lifecycle of the two process-level error listeners for the Electron main process,
230
- * reconciling attach/detach against the desired modes. Mirrors node's ProcessHandlerManager.
231
- *
232
- * Deliberately a copy, not a shared module. @flareapp/electron does not depend on @flareapp/node, and
233
- * the only package both import is @flareapp/core, which ships in every browser bundle and touches
234
- * `process` only behind a typeof guard. A shared manager belongs in a new package, not in core, and
235
- * one method does not pay for one.
236
- */
237
224
  var ProcessHandlerManager = class {
238
225
  uncaughtHandler = null;
239
226
  rejectionHandler = null;
@@ -275,7 +262,6 @@ var ProcessHandlerManager = class {
275
262
  //#endregion
276
263
  //#region src/main/ElectronFlare.ts
277
264
  const SDK_NAME = "@flareapp/electron";
278
- /** Write `value` under `key` when non-empty, otherwise remove any renderer-supplied value. */
279
265
  function overlayOrDelete(attributes, key, value) {
280
266
  if (value) attributes[key] = value;
281
267
  else delete attributes[key];
@@ -346,7 +332,6 @@ var ElectronFlare = class extends _flareapp_core.Flare {
346
332
  disposeIpcReceiver(this.ipcMain, this);
347
333
  this.flushScheduler.dispose();
348
334
  }
349
- /** Attach/detach the process-gone listeners to match options.captureRenderProcessGone. Idempotent. */
350
335
  reconcileCrashListeners() {
351
336
  const want = Boolean(this.options.captureRenderProcessGone);
352
337
  if (want === (this.renderGoneHandler !== null)) return;
@@ -391,9 +376,8 @@ var ElectronFlare = class extends _flareapp_core.Flare {
391
376
  return this.report(error, attrs);
392
377
  }
393
378
  /**
394
- * Wait for both core's tracked reports AND forwarded renderer reports (which bypass core's
395
- * private track()), bounded by timeoutMs. The timeout is cleared when all reports settle
396
- * first, so the event loop is not kept alive unnecessarily.
379
+ * Waits for core's tracked reports and forwarded renderer reports (which bypass track()), bounded by
380
+ * timeoutMs. Clears the timer once everything settles, so the event loop isn't held open needlessly.
397
381
  */
398
382
  flush(timeoutMs = 2e3) {
399
383
  const settled = Promise.allSettled([super.flush(timeoutMs), ...this.forwardedInFlight]);
@@ -405,7 +389,6 @@ var ElectronFlare = class extends _flareapp_core.Flare {
405
389
  });
406
390
  });
407
391
  }
408
- /** Overlay main-authoritative config + Electron metadata + user identity (from the main scope) onto a forwarded report, then send. */
409
392
  receiveRendererReport(report) {
410
393
  for (const key of _flareapp_core.USER_IDENTITY_KEYS) delete report.attributes[key];
411
394
  Object.assign(report.attributes, collectElectronAppAttributes(this.app), (0, _flareapp_core.userIdentityAttributes)(this.mainScope.active()));
package/dist/main.d.cts CHANGED
@@ -44,18 +44,15 @@ declare class ElectronFlare extends Flare {
44
44
  light(key?: string, debug?: boolean): this;
45
45
  configureElectron(partial: ElectronOptions): this;
46
46
  dispose(): void;
47
- /** Attach/detach the process-gone listeners to match options.captureRenderProcessGone. Idempotent. */
48
47
  private reconcileCrashListeners;
49
48
  private attachCrashListeners;
50
49
  private detachCrashListeners;
51
50
  private reportProcessGone;
52
51
  /**
53
- * Wait for both core's tracked reports AND forwarded renderer reports (which bypass core's
54
- * private track()), bounded by timeoutMs. The timeout is cleared when all reports settle
55
- * first, so the event loop is not kept alive unnecessarily.
52
+ * Waits for core's tracked reports and forwarded renderer reports (which bypass track()), bounded by
53
+ * timeoutMs. Clears the timer once everything settles, so the event loop isn't held open needlessly.
56
54
  */
57
55
  flush(timeoutMs?: number): Promise<void>;
58
- /** Overlay main-authoritative config + Electron metadata + user identity (from the main scope) onto a forwarded report, then send. */
59
56
  private receiveRendererReport;
60
57
  }
61
58
  //#endregion
package/dist/main.d.mts CHANGED
@@ -44,18 +44,15 @@ declare class ElectronFlare extends Flare {
44
44
  light(key?: string, debug?: boolean): this;
45
45
  configureElectron(partial: ElectronOptions): this;
46
46
  dispose(): void;
47
- /** Attach/detach the process-gone listeners to match options.captureRenderProcessGone. Idempotent. */
48
47
  private reconcileCrashListeners;
49
48
  private attachCrashListeners;
50
49
  private detachCrashListeners;
51
50
  private reportProcessGone;
52
51
  /**
53
- * Wait for both core's tracked reports AND forwarded renderer reports (which bypass core's
54
- * private track()), bounded by timeoutMs. The timeout is cleared when all reports settle
55
- * first, so the event loop is not kept alive unnecessarily.
52
+ * Waits for core's tracked reports and forwarded renderer reports (which bypass track()), bounded by
53
+ * timeoutMs. Clears the timer once everything settles, so the event loop isn't held open needlessly.
56
54
  */
57
55
  flush(timeoutMs?: number): Promise<void>;
58
- /** Overlay main-authoritative config + Electron metadata + user identity (from the main scope) onto a forwarded report, then send. */
59
56
  private receiveRendererReport;
60
57
  }
61
58
  //#endregion
package/dist/main.mjs CHANGED
@@ -1,11 +1,11 @@
1
1
  import { app, ipcMain } from "electron";
2
- import { Api, DEFAULT_URL_DENYLIST, Flare, FrameworkName, GlobalScopeProvider, GlobalScopeProvider as GlobalScopeProvider$1, Logger, NullFileReader, Scope, USER_IDENTITY_KEYS, convertToError, redactUrlQuery, resolveDenylist, userIdentityAttributes } from "@flareapp/core";
2
+ import { Api, DEFAULT_URL_DENYLIST, Flare, FrameworkName, GlobalScopeProvider, GlobalScopeProvider as GlobalScopeProvider$1, Logger, NullFileReader, Scope, USER_IDENTITY_KEYS, convertToError, deviceInfoToAttributes, redactUrlQuery, resolveDenylist, userIdentityAttributes } from "@flareapp/core";
3
3
  import os from "node:os";
4
4
  import { readFile } from "node:fs/promises";
5
5
  import { fileURLToPath } from "node:url";
6
6
 
7
7
  //#region src/env.ts
8
- const CLIENT_VERSION = typeof process !== "undefined" && true ? "2.10.0" : "?";
8
+ const CLIENT_VERSION = typeof process !== "undefined" && true ? "2.12.0" : "?";
9
9
 
10
10
  //#endregion
11
11
  //#region src/types.ts
@@ -19,33 +19,44 @@ const DEFAULT_ELECTRON_OPTIONS = {
19
19
  maxReportBytes: 1e6
20
20
  };
21
21
 
22
+ //#endregion
23
+ //#region src/main/deviceInfo.ts
24
+ var ElectronDeviceInfoProvider = class {
25
+ collect() {
26
+ const versions = process.versions;
27
+ return {
28
+ os: {
29
+ name: os.type(),
30
+ version: os.release()
31
+ },
32
+ runtime: {
33
+ name: "electron",
34
+ version: versions.electron
35
+ }
36
+ };
37
+ }
38
+ };
39
+ const electronDeviceInfoProvider = new ElectronDeviceInfoProvider();
40
+
22
41
  //#endregion
23
42
  //#region src/main/collectElectron.ts
24
- /**
25
- * App + runtime attributes safe to overlay onto any report regardless of origin. Reused by both
26
- * the collector (main errors) and the IPC receiver (forwarded renderer reports). Excludes per-process
27
- * fields like `flare.entry_point.type` / `process.type` so forwarded renderer reports keep their own.
28
- */
29
43
  function collectElectronAppAttributes(app) {
30
44
  const versions = process.versions;
31
45
  const attrs = {
32
46
  "service.name": app.getName(),
33
47
  "app.version": app.getVersion(),
34
48
  "app.packaged": app.isPackaged,
35
- "process.runtime.name": "electron",
36
- "process.runtime.version": versions.electron ?? "",
37
49
  "process.versions.electron": versions.electron ?? "",
38
50
  "process.versions.chrome": versions.chrome ?? "",
39
51
  "process.versions.node": versions.node ?? process.version,
40
52
  "host.arch": process.arch,
41
- "os.type": os.type()
53
+ ...deviceInfoToAttributes(electronDeviceInfoProvider.collect())
42
54
  };
43
55
  if (app.isReady()) try {
44
56
  attrs["app.locale"] = app.getLocale();
45
57
  } catch {}
46
58
  return attrs;
47
59
  }
48
- /** Build the ContextCollector core calls on every main-process report. */
49
60
  function makeElectronContextCollector(app) {
50
61
  return (_config) => ({
51
62
  "flare.entry_point.type": "web",
@@ -56,7 +67,6 @@ function makeElectronContextCollector(app) {
56
67
 
57
68
  //#endregion
58
69
  //#region src/main/ElectronDiskFileReader.ts
59
- /** Reads source snippets for main-process stack frames from disk. Mirrors @flareapp/node's DiskFileReader. */
60
70
  var ElectronDiskFileReader = class {
61
71
  async read(url) {
62
72
  if (!isLocalFileUrl(url)) return null;
@@ -73,7 +83,6 @@ function isLocalFileUrl(url) {
73
83
 
74
84
  //#endregion
75
85
  //#region src/main/ElectronFlushScheduler.ts
76
- /** Flushes pending logs/reports when the Electron app is quitting. App is injectable for tests. */
77
86
  var ElectronFlushScheduler = class {
78
87
  listener = null;
79
88
  constructor(app) {
@@ -86,7 +95,6 @@ var ElectronFlushScheduler = class {
86
95
  };
87
96
  this.app.on("before-quit", this.listener);
88
97
  }
89
- /** Detach the before-quit listener so a disposed ElectronFlare leaves no flush handler on the shared app. */
90
98
  dispose() {
91
99
  if (this.listener) {
92
100
  this.app.off("before-quit", this.listener);
@@ -104,9 +112,7 @@ const FLARE_BRIDGE_KEY = "__flare";
104
112
 
105
113
  //#endregion
106
114
  //#region src/main/ipcReceiver.ts
107
- /** Module-level ownership token for the single flare:report channel. */
108
115
  let currentOwner = null;
109
- /** Default sender-trust check: accept file: and localhost/127.0.0.1 only, plus configured custom protocols. */
110
116
  function defaultTrustPolicy(frame, opts) {
111
117
  let parsed;
112
118
  try {
@@ -126,11 +132,6 @@ function isTrusted(frame, opts) {
126
132
  if (opts.trustSender) return opts.trustSender(frame);
127
133
  return defaultTrustPolicy(frame, opts);
128
134
  }
129
- /**
130
- * Minimal top-level structural guard for a parsed report, not an exhaustive StackFrame/SpanEvent
131
- * validator: a compromised renderer could forge any valid-looking shape anyway. The security boundary
132
- * is the sender-trust check plus the byte-size cap; this only rejects obviously-wrong payloads.
133
- */
134
135
  function isReportShape(value) {
135
136
  if (typeof value !== "object" || value === null) return false;
136
137
  const r = value;
@@ -163,11 +164,6 @@ function disposeIpcReceiver(ipcMain, owner) {
163
164
 
164
165
  //#endregion
165
166
  //#region src/main/processHandlers.ts
166
- /**
167
- * Fatal callbacks for Electron main. Mirrors @flareapp/node's buildFatalCallbacks but exits via the
168
- * injected `exit` (app.exit at the call site), which is immediate and skips before-quit/will-quit,
169
- * correct after an uncaught exception.
170
- */
171
167
  function buildFatalCallbacks(flare, getOpts, exit) {
172
168
  return {
173
169
  async onUncaught(err, origin) {
@@ -196,15 +192,6 @@ function buildFatalCallbacks(flare, getOpts, exit) {
196
192
  }
197
193
  };
198
194
  }
199
- /**
200
- * Owns the lifecycle of the two process-level error listeners for the Electron main process,
201
- * reconciling attach/detach against the desired modes. Mirrors node's ProcessHandlerManager.
202
- *
203
- * Deliberately a copy, not a shared module. @flareapp/electron does not depend on @flareapp/node, and
204
- * the only package both import is @flareapp/core, which ships in every browser bundle and touches
205
- * `process` only behind a typeof guard. A shared manager belongs in a new package, not in core, and
206
- * one method does not pay for one.
207
- */
208
195
  var ProcessHandlerManager = class {
209
196
  uncaughtHandler = null;
210
197
  rejectionHandler = null;
@@ -246,7 +233,6 @@ var ProcessHandlerManager = class {
246
233
  //#endregion
247
234
  //#region src/main/ElectronFlare.ts
248
235
  const SDK_NAME = "@flareapp/electron";
249
- /** Write `value` under `key` when non-empty, otherwise remove any renderer-supplied value. */
250
236
  function overlayOrDelete(attributes, key, value) {
251
237
  if (value) attributes[key] = value;
252
238
  else delete attributes[key];
@@ -317,7 +303,6 @@ var ElectronFlare = class extends Flare {
317
303
  disposeIpcReceiver(this.ipcMain, this);
318
304
  this.flushScheduler.dispose();
319
305
  }
320
- /** Attach/detach the process-gone listeners to match options.captureRenderProcessGone. Idempotent. */
321
306
  reconcileCrashListeners() {
322
307
  const want = Boolean(this.options.captureRenderProcessGone);
323
308
  if (want === (this.renderGoneHandler !== null)) return;
@@ -362,9 +347,8 @@ var ElectronFlare = class extends Flare {
362
347
  return this.report(error, attrs);
363
348
  }
364
349
  /**
365
- * Wait for both core's tracked reports AND forwarded renderer reports (which bypass core's
366
- * private track()), bounded by timeoutMs. The timeout is cleared when all reports settle
367
- * first, so the event loop is not kept alive unnecessarily.
350
+ * Waits for core's tracked reports and forwarded renderer reports (which bypass track()), bounded by
351
+ * timeoutMs. Clears the timer once everything settles, so the event loop isn't held open needlessly.
368
352
  */
369
353
  flush(timeoutMs = 2e3) {
370
354
  const settled = Promise.allSettled([super.flush(timeoutMs), ...this.forwardedInFlight]);
@@ -376,7 +360,6 @@ var ElectronFlare = class extends Flare {
376
360
  });
377
361
  });
378
362
  }
379
- /** Overlay main-authoritative config + Electron metadata + user identity (from the main scope) onto a forwarded report, then send. */
380
363
  receiveRendererReport(report) {
381
364
  for (const key of USER_IDENTITY_KEYS) delete report.attributes[key];
382
365
  Object.assign(report.attributes, collectElectronAppAttributes(this.app), userIdentityAttributes(this.mainScope.active()));
package/dist/renderer.cjs CHANGED
@@ -8,7 +8,7 @@ const FLARE_BRIDGE_KEY = "__flare";
8
8
 
9
9
  //#endregion
10
10
  //#region src/env.ts
11
- const CLIENT_VERSION = typeof process !== "undefined" && true ? "2.10.0" : "?";
11
+ const CLIENT_VERSION = typeof process !== "undefined" && true ? "2.12.0" : "?";
12
12
 
13
13
  //#endregion
14
14
  //#region src/renderer/RendererFlare.ts
package/dist/renderer.mjs CHANGED
@@ -7,7 +7,7 @@ const FLARE_BRIDGE_KEY = "__flare";
7
7
 
8
8
  //#endregion
9
9
  //#region src/env.ts
10
- const CLIENT_VERSION = typeof process !== "undefined" && true ? "2.10.0" : "?";
10
+ const CLIENT_VERSION = typeof process !== "undefined" && true ? "2.12.0" : "?";
11
11
 
12
12
  //#endregion
13
13
  //#region src/renderer/RendererFlare.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flareapp/electron",
3
- "version": "2.10.0",
3
+ "version": "2.12.0",
4
4
  "description": "Electron SDK for flareapp.io",
5
5
  "homepage": "https://flareapp.io",
6
6
  "bugs": {
@@ -65,8 +65,8 @@
65
65
  "release": "release-it"
66
66
  },
67
67
  "dependencies": {
68
- "@flareapp/core": "2.10.0",
69
- "@flareapp/js": "2.10.0"
68
+ "@flareapp/core": "2.12.0",
69
+ "@flareapp/js": "2.12.0"
70
70
  },
71
71
  "peerDependencies": {
72
72
  "electron": ">=35"