@flareapp/electron 2.6.0 → 2.8.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.6.0" : "?";
37
+ const CLIENT_VERSION = typeof process !== "undefined" && true ? "2.8.0" : "?";
38
38
 
39
39
  //#endregion
40
40
  //#region src/types.ts
@@ -51,11 +51,9 @@ const DEFAULT_ELECTRON_OPTIONS = {
51
51
  //#endregion
52
52
  //#region src/main/collectElectron.ts
53
53
  /**
54
- * App + runtime attributes that are safe to overlay onto ANY report regardless of origin.
55
- * Reused by both the collector (main errors) and the IPC receiver (forwarded renderer reports).
56
- *
57
- * Intentionally does NOT include per-process fields like `flare.entry_point.type` or `process.type`
58
- * so that forwarded renderer reports keep their own `flare.entry_point.type: 'web'` intact.
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.
59
57
  */
60
58
  function collectElectronAppAttributes(app) {
61
59
  const versions = process.versions;
@@ -79,7 +77,7 @@ function collectElectronAppAttributes(app) {
79
77
  /** Build the ContextCollector core calls on every main-process report. */
80
78
  function makeElectronContextCollector(app) {
81
79
  return (_config) => ({
82
- "flare.entry_point.type": "server",
80
+ "flare.entry_point.type": "web",
83
81
  "process.type": process.type ?? "browser",
84
82
  ...collectElectronAppAttributes(app)
85
83
  });
@@ -158,10 +156,9 @@ function isTrusted(frame, opts) {
158
156
  return defaultTrustPolicy(frame, opts);
159
157
  }
160
158
  /**
161
- * Minimal top-level structural guard for a parsed report. This is intentionally NOT an exhaustive
162
- * validator of every StackFrame / SpanEvent: the renderer builds the report with our own Flare code,
163
- * and a compromised renderer could forge any valid-looking shape anyway. The real security boundary
164
- * is the sender-trust check plus the byte-size cap; this guard only rejects obviously-wrong payloads.
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.
165
162
  */
166
163
  function isReportShape(value) {
167
164
  if (typeof value !== "object" || value === null) return false;
@@ -196,9 +193,9 @@ function disposeIpcReceiver(ipcMain, owner) {
196
193
  //#endregion
197
194
  //#region src/main/processHandlers.ts
198
195
  /**
199
- * Fatal callbacks for Electron main. Mirrors @flareapp/node's buildFatalCallbacks but exits via
200
- * the injected `exit` (defaulting to app.exit at the call site), which is immediate and skips
201
- * before-quit/will-quit, correct after an uncaught exception.
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.
202
199
  */
203
200
  function buildFatalCallbacks(flare, getOpts, exit) {
204
201
  return {
@@ -229,9 +226,13 @@ function buildFatalCallbacks(flare, getOpts, exit) {
229
226
  };
230
227
  }
231
228
  /**
232
- * Owns the lifecycle of the two process-level error listeners for the Electron main process.
233
- * Mirrors node's ProcessHandlerManager. Attach/detach the two process listeners, reconciling
234
- * against the desired modes.
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.
235
236
  */
236
237
  var ProcessHandlerManager = class {
237
238
  uncaughtHandler = null;
@@ -260,13 +261,14 @@ var ProcessHandlerManager = class {
260
261
  reconcileOne(event, mode, get, set, impl) {
261
262
  const current = get();
262
263
  const wants = mode !== "off";
263
- if (wants && !current) {
264
- set(impl);
265
- process.on(event, impl);
266
- } else if (!wants && current) {
264
+ if (wants === (current !== null)) return;
265
+ if (!wants) {
267
266
  process.off(event, current);
268
267
  set(null);
268
+ return;
269
269
  }
270
+ set(impl);
271
+ process.on(event, impl);
270
272
  }
271
273
  };
272
274
 
@@ -306,6 +308,7 @@ var ElectronFlare = class extends _flareapp_core.Flare {
306
308
  name: SDK_NAME,
307
309
  version: CLIENT_VERSION
308
310
  });
311
+ this.setFramework({ name: _flareapp_core.FrameworkName.NodeElectron });
309
312
  this.handlerManager = new ProcessHandlerManager(buildFatalCallbacks(this, () => this.options, (code) => this.app.exit(code)));
310
313
  registerIpcReceiver(this.ipcMain, this, {
311
314
  getOptions: () => this.options,
@@ -343,20 +346,25 @@ var ElectronFlare = class extends _flareapp_core.Flare {
343
346
  disposeIpcReceiver(this.ipcMain, this);
344
347
  this.flushScheduler.dispose();
345
348
  }
346
- /** Attach or detach the process-gone listeners to match options.captureRenderProcessGone. Idempotent. */
349
+ /** Attach/detach the process-gone listeners to match options.captureRenderProcessGone. Idempotent. */
347
350
  reconcileCrashListeners() {
348
- const want = this.options.captureRenderProcessGone;
349
- const attached = this.renderGoneHandler !== null;
350
- if (want && !attached) {
351
- this.renderGoneHandler = (_event, webContents, details) => {
352
- return this.reportProcessGone("renderer", details, webContents?.id);
353
- };
354
- this.childGoneHandler = (_event, details) => {
355
- return this.reportProcessGone("child", details);
356
- };
357
- this.app.on("render-process-gone", this.renderGoneHandler);
358
- this.app.on("child-process-gone", this.childGoneHandler);
359
- } else if (!want && attached) this.detachCrashListeners();
351
+ const want = Boolean(this.options.captureRenderProcessGone);
352
+ if (want === (this.renderGoneHandler !== null)) return;
353
+ if (!want) {
354
+ this.detachCrashListeners();
355
+ return;
356
+ }
357
+ this.attachCrashListeners();
358
+ }
359
+ attachCrashListeners() {
360
+ this.renderGoneHandler = (_event, webContents, details) => {
361
+ return this.reportProcessGone("renderer", details, webContents?.id);
362
+ };
363
+ this.childGoneHandler = (_event, details) => {
364
+ return this.reportProcessGone("child", details);
365
+ };
366
+ this.app.on("render-process-gone", this.renderGoneHandler);
367
+ this.app.on("child-process-gone", this.childGoneHandler);
360
368
  }
361
369
  detachCrashListeners() {
362
370
  if (this.renderGoneHandler) {
package/dist/main.d.cts CHANGED
@@ -44,8 +44,9 @@ 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 or detach the process-gone listeners to match options.captureRenderProcessGone. Idempotent. */
47
+ /** Attach/detach the process-gone listeners to match options.captureRenderProcessGone. Idempotent. */
48
48
  private reconcileCrashListeners;
49
+ private attachCrashListeners;
49
50
  private detachCrashListeners;
50
51
  private reportProcessGone;
51
52
  /**
package/dist/main.d.mts CHANGED
@@ -44,8 +44,9 @@ 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 or detach the process-gone listeners to match options.captureRenderProcessGone. Idempotent. */
47
+ /** Attach/detach the process-gone listeners to match options.captureRenderProcessGone. Idempotent. */
48
48
  private reconcileCrashListeners;
49
+ private attachCrashListeners;
49
50
  private detachCrashListeners;
50
51
  private reportProcessGone;
51
52
  /**
package/dist/main.mjs CHANGED
@@ -1,11 +1,11 @@
1
1
  import { app, ipcMain } from "electron";
2
- import { Api, DEFAULT_URL_DENYLIST, Flare, 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, 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.6.0" : "?";
8
+ const CLIENT_VERSION = typeof process !== "undefined" && true ? "2.8.0" : "?";
9
9
 
10
10
  //#endregion
11
11
  //#region src/types.ts
@@ -22,11 +22,9 @@ const DEFAULT_ELECTRON_OPTIONS = {
22
22
  //#endregion
23
23
  //#region src/main/collectElectron.ts
24
24
  /**
25
- * App + runtime attributes that are safe to overlay onto ANY report regardless of origin.
26
- * Reused by both the collector (main errors) and the IPC receiver (forwarded renderer reports).
27
- *
28
- * Intentionally does NOT include per-process fields like `flare.entry_point.type` or `process.type`
29
- * so that forwarded renderer reports keep their own `flare.entry_point.type: 'web'` intact.
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.
30
28
  */
31
29
  function collectElectronAppAttributes(app) {
32
30
  const versions = process.versions;
@@ -50,7 +48,7 @@ function collectElectronAppAttributes(app) {
50
48
  /** Build the ContextCollector core calls on every main-process report. */
51
49
  function makeElectronContextCollector(app) {
52
50
  return (_config) => ({
53
- "flare.entry_point.type": "server",
51
+ "flare.entry_point.type": "web",
54
52
  "process.type": process.type ?? "browser",
55
53
  ...collectElectronAppAttributes(app)
56
54
  });
@@ -129,10 +127,9 @@ function isTrusted(frame, opts) {
129
127
  return defaultTrustPolicy(frame, opts);
130
128
  }
131
129
  /**
132
- * Minimal top-level structural guard for a parsed report. This is intentionally NOT an exhaustive
133
- * validator of every StackFrame / SpanEvent: the renderer builds the report with our own Flare code,
134
- * and a compromised renderer could forge any valid-looking shape anyway. The real security boundary
135
- * is the sender-trust check plus the byte-size cap; this guard only rejects obviously-wrong payloads.
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.
136
133
  */
137
134
  function isReportShape(value) {
138
135
  if (typeof value !== "object" || value === null) return false;
@@ -167,9 +164,9 @@ function disposeIpcReceiver(ipcMain, owner) {
167
164
  //#endregion
168
165
  //#region src/main/processHandlers.ts
169
166
  /**
170
- * Fatal callbacks for Electron main. Mirrors @flareapp/node's buildFatalCallbacks but exits via
171
- * the injected `exit` (defaulting to app.exit at the call site), which is immediate and skips
172
- * before-quit/will-quit, correct after an uncaught exception.
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.
173
170
  */
174
171
  function buildFatalCallbacks(flare, getOpts, exit) {
175
172
  return {
@@ -200,9 +197,13 @@ function buildFatalCallbacks(flare, getOpts, exit) {
200
197
  };
201
198
  }
202
199
  /**
203
- * Owns the lifecycle of the two process-level error listeners for the Electron main process.
204
- * Mirrors node's ProcessHandlerManager. Attach/detach the two process listeners, reconciling
205
- * against the desired modes.
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.
206
207
  */
207
208
  var ProcessHandlerManager = class {
208
209
  uncaughtHandler = null;
@@ -231,13 +232,14 @@ var ProcessHandlerManager = class {
231
232
  reconcileOne(event, mode, get, set, impl) {
232
233
  const current = get();
233
234
  const wants = mode !== "off";
234
- if (wants && !current) {
235
- set(impl);
236
- process.on(event, impl);
237
- } else if (!wants && current) {
235
+ if (wants === (current !== null)) return;
236
+ if (!wants) {
238
237
  process.off(event, current);
239
238
  set(null);
239
+ return;
240
240
  }
241
+ set(impl);
242
+ process.on(event, impl);
241
243
  }
242
244
  };
243
245
 
@@ -277,6 +279,7 @@ var ElectronFlare = class extends Flare {
277
279
  name: SDK_NAME,
278
280
  version: CLIENT_VERSION
279
281
  });
282
+ this.setFramework({ name: FrameworkName.NodeElectron });
280
283
  this.handlerManager = new ProcessHandlerManager(buildFatalCallbacks(this, () => this.options, (code) => this.app.exit(code)));
281
284
  registerIpcReceiver(this.ipcMain, this, {
282
285
  getOptions: () => this.options,
@@ -314,20 +317,25 @@ var ElectronFlare = class extends Flare {
314
317
  disposeIpcReceiver(this.ipcMain, this);
315
318
  this.flushScheduler.dispose();
316
319
  }
317
- /** Attach or detach the process-gone listeners to match options.captureRenderProcessGone. Idempotent. */
320
+ /** Attach/detach the process-gone listeners to match options.captureRenderProcessGone. Idempotent. */
318
321
  reconcileCrashListeners() {
319
- const want = this.options.captureRenderProcessGone;
320
- const attached = this.renderGoneHandler !== null;
321
- if (want && !attached) {
322
- this.renderGoneHandler = (_event, webContents, details) => {
323
- return this.reportProcessGone("renderer", details, webContents?.id);
324
- };
325
- this.childGoneHandler = (_event, details) => {
326
- return this.reportProcessGone("child", details);
327
- };
328
- this.app.on("render-process-gone", this.renderGoneHandler);
329
- this.app.on("child-process-gone", this.childGoneHandler);
330
- } else if (!want && attached) this.detachCrashListeners();
322
+ const want = Boolean(this.options.captureRenderProcessGone);
323
+ if (want === (this.renderGoneHandler !== null)) return;
324
+ if (!want) {
325
+ this.detachCrashListeners();
326
+ return;
327
+ }
328
+ this.attachCrashListeners();
329
+ }
330
+ attachCrashListeners() {
331
+ this.renderGoneHandler = (_event, webContents, details) => {
332
+ return this.reportProcessGone("renderer", details, webContents?.id);
333
+ };
334
+ this.childGoneHandler = (_event, details) => {
335
+ return this.reportProcessGone("child", details);
336
+ };
337
+ this.app.on("render-process-gone", this.renderGoneHandler);
338
+ this.app.on("child-process-gone", this.childGoneHandler);
331
339
  }
332
340
  detachCrashListeners() {
333
341
  if (this.renderGoneHandler) {
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.6.0" : "?";
11
+ const CLIENT_VERSION = typeof process !== "undefined" && true ? "2.8.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.6.0" : "?";
10
+ const CLIENT_VERSION = typeof process !== "undefined" && true ? "2.8.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.6.0",
3
+ "version": "2.8.0",
4
4
  "description": "Electron SDK for flareapp.io",
5
5
  "homepage": "https://flareapp.io",
6
6
  "bugs": {
@@ -15,6 +15,9 @@
15
15
  "name": "Spatie",
16
16
  "email": "info@spatie.be"
17
17
  },
18
+ "contributors": [
19
+ "Dries Heyninck <dries@spatie.be>"
20
+ ],
18
21
  "files": [
19
22
  "dist"
20
23
  ],
@@ -62,14 +65,15 @@
62
65
  "release": "release-it"
63
66
  },
64
67
  "dependencies": {
65
- "@flareapp/core": "2.6.0",
66
- "@flareapp/js": "2.6.0"
68
+ "@flareapp/core": "2.8.0",
69
+ "@flareapp/js": "2.8.0"
67
70
  },
68
71
  "peerDependencies": {
69
72
  "electron": ">=35"
70
73
  },
71
74
  "devDependencies": {
72
75
  "@flareapp/react": "file:../react",
76
+ "@flareapp/test-helpers": "*",
73
77
  "@flareapp/vue": "file:../vue",
74
78
  "electron": "^35.0.0",
75
79
  "react": "^19.0.0",