super-productivity/electron
Benjamin 07ec51b1a5
feat(plugins): add onReady() API with IPC ping + fix consent write delay (#7578)
* feat(plugins): add onReady() API with IPC ping + fix consent write delay #7326

- Remove setTimeout(5000) from _getNodeExecutionConsent; write consent immediately
- Add plugin.onReady(fn) to PluginAPI — fires after plugin.js evaluation and IPC bridge confirmation
- Add _pingNodeBridge() in plugin.service.ts with 3-attempt retry (1s, 2s delays)
- Add triggerReady() and pingNodeBridge() to PluginRunner
- Show snack + set error state if IPC bridge unavailable after retries
- Add NODE_EXECUTION_BRIDGE_UNAVAILABLE translation key
- Add focused tests for onReady, triggerReady, pingNodeBridge, consent persistence
- Update plugin-development.md with onReady usage and nodeExecution guidance

* test(plugins): fix unused variable lint errors in spec files

* fix(plugins): guard triggerReady on instance.loaded; fix doc numbering

* fix(plugins): remove _triggerReady from public API, route ping via bridge, add retry tests

* fix(electron): add paths for @sp/sync-providers subpath exports (node moduleResolution compat)

* fix(plugins): centralize onReady, tear down runtime on activation error, add iframe onReady

Address review on #7578:
- All plugin load paths (startup, upload, reload, lazy) now go through _fireOnReady,
  ensuring the IPC ping + onReady fire on every successful load — not just lazy.
- activatePlugin error path now unloads the plugin runtime (hooks, buttons, side
  effects) before setting status='error', preventing partially-running plugins.
- Iframe PluginAPI now exposes onReady (fires on next microtask after plugin.js
  evaluates), matching the host-side contract for typed iframe plugins.

* fix(plugins): clean up half-loaded plugins on onReady error, test real retry util

Self-review followups:
- _fireOnReadyWithCleanup wraps the 3 non-activatePlugin load paths and tears
  down the plugin (unloadPlugin + remove from list + status='error' + snack)
  if the IPC ping or onReady callback throws. Previously, those paths only
  logged and rethrew, leaving partially-running plugins.
- Extracted retry loop into pure pingWithRetry utility; spec now exercises
  production code instead of an inline-replicated stub. Removed the old
  plugin-ping-node-bridge.spec.ts which was just testing its own copy of
  the logic.
- Documented iframe onReady semantic (fires on microtask, no ping) in both
  the source comment and docs/plugin-development.md, since cold-boot is not
  a concern for iframe plugins (rendered on demand).

* ci(plugins): use npm i for root install to tolerate override drift

The root lockfile pins app-builder-lib's transitive minimatch via the
`overrides` field. npm 10.9.7 (bundled with Node 22 in setup-node@v6)
flags this as drift and fails `npm ci`, while npm 11 accepts it.
ci.yml's main test job uses `npm i`, which tolerates the drift without
mutating the lockfile on disk.

Plugin-Tests has been red on every PR since 2026-05-08 for this reason.
The inner `npm ci` for plugin-specific deps stays strict.

* fix(plugins): make onReady optional, assert callback isolation in spec

- packages/plugin-api/src/types.ts: mark onReady? optional on the public
  PluginAPI interface so existing plugin TypeScript typings (and any
  third-party PluginAPI implementations) remain assignable after upgrade.
  The host runtime already treats onReady as optional (no-op if no
  registration callback is provided), so this aligns the type with the
  actual contract.

- src/app/plugins/plugin-runner.spec.ts: the previous isolation test only
  asserted that triggerReady() resolved for both plugins; it would still
  pass if triggerReady fired every registered callback. The updated test
  wires per-plugin Jasmine spies through globalThis (the same context the
  plugin code's `new Function` runs in) and asserts call counts before
  and after each triggerReady, actually proving isolation.

* refactor(plugins): test real consent logic; scope startup snacks; tighten ping timeout

Address review feedback on PR #7578:

- Extract consent decision into pure `decideNodeExecutionConsent` util so the
  spec exercises real code instead of a reimplemented stub. Delete the
  stub-based plugin-consent.spec.ts and plugin-fire-on-ready.spec.ts (the
  latter was orchestration glue already covered by plugin-runner.spec.ts and
  ping-with-retry.util.spec.ts).
- Reduce per-ping timeout 5000ms -> 1500ms. Worst-case cold-boot bridge-down
  detection drops from ~17s to ~7.5s; in-process vm script returning true
  doesn't need 5s.
- Add PLUGIN_LOAD_FAILED translation wrapping plugin name + error. Strip the
  now-redundant pluginName from NODE_EXECUTION_BRIDGE_UNAVAILABLE.
- Scope activation-failure snack to manual activations only — startup
  auto-activation failures stay silent (plugin tile shows error state).
  _handleReadyFailure still snacks unconditionally since onReady failure
  leaves a partially-loaded runtime that the user needs to see.

---------

Co-authored-by: Benjamin <1159333+benjaminburzan@users.noreply.github.com>
Co-authored-by: Johannes Millan <johannes.millan@gmail.com>
2026-05-14 13:41:01 +02:00
..
assets/icons fix: wrong icon for kde title bar 2025-07-22 20:42:28 +02:00
ipc-handlers fix(window): preserve maximized state for shortcut hide 2026-05-11 14:31:19 +02:00
scripts refactor(electron): bundle preload script with esbuild to support sandbox mode 2026-03-22 19:38:21 +01:00
shared-with-frontend feat(settings): add image picker for background image selection (#7564) 2026-05-13 12:58:07 +02:00
task-widget feat(task-widget): make settings per-instance and fix Mac drag/resize 2026-04-29 21:16:12 +02:00
wayland-idle-helper Add ext-idle-notify backend for Wayland idle detection (#7337) 2026-04-24 16:50:24 +02:00
backup.ts fix(backup): move shared timestamp util into electron/ for snap packaging 2026-04-22 16:14:56 +02:00
clear-stale-idb-locks.ts Feat/to me it looks like there are lots of 60dd04 (#7280) 2026-04-20 12:04:38 +02:00
clipboard-image-handler.ts Adding Ctrl-V pasting function from clipboard. (#5998) 2026-02-04 15:46:51 +01:00
common.const.ts chore: update electron to v41.x (#7097) 2026-04-17 18:12:43 +02:00
CONFIG.ts Increase ping interval and idle time in order to not waste CPU cycles. (#6227) 2026-01-28 15:37:50 +01:00
debug.ts refactor: rename overlay-indicator to task-widget 2026-03-30 22:00:47 +02:00
electronAPI.d.ts feat(settings): add image picker for background image selection (#7564) 2026-05-13 12:58:07 +02:00
error-handler-with-frontend-inform.ts fix(error-handling): prevent [object Object] from appearing in error messages 2026-01-02 15:40:14 +01:00
full-screen-blocker.ts fix(security): harden XSS sinks and add Origin check (#7413) 2026-05-06 21:37:06 +02:00
gpu-startup-guard.ts fix(electron): add GPU startup guard for confined Linux packages 2026-04-20 18:35:31 +02:00
idle-time-handler.ts fix(electron): retry Wayland idle helper startup (#7527) 2026-05-10 22:35:33 +02:00
indicator.test.cjs Caldav subtask import (#7409) 2026-05-01 13:07:03 +02:00
indicator.ts feat(task-widget): make settings per-instance and fix Mac drag/resize 2026-04-29 21:16:12 +02:00
ipc-handler-wrapper.ts Adding Ctrl-V pasting function from clipboard. (#5998) 2026-02-04 15:46:51 +01:00
ipc-handler.ts feat(electron): add Local REST API for desktop automation (#6981) 2026-03-28 13:35:04 +01:00
jira.ts fix: add proxy env support for jira integration #6324 (#6574) 2026-03-09 13:09:51 +01:00
local-file-sync.ts feat(settings): add image picker for background image selection (#7564) 2026-05-13 12:58:07 +02:00
local-rest-api.ts fix(security): harden XSS sinks and add Origin check (#7413) 2026-05-06 21:37:06 +02:00
lockscreen.ts fix(electron): restore macOS lock screen by correcting osascript quoting 2026-04-16 19:47:52 +02:00
main-window.ts fix(window): preserve maximized state for shortcut hide 2026-05-11 14:31:19 +02:00
main.ts fix(electron): improve protocol URL handling and register URL scheme on Linux 2026-03-05 16:45:05 +01:00
plugin-node-executor.ts refactor: improve typing 2 2025-08-12 15:27:48 +02:00
plugin-oauth.ts Improve OAuth error handling and reporting (#7445) 2026-05-01 18:45:11 +02:00
preload.ts feat(settings): add image picker for background image selection (#7564) 2026-05-13 12:58:07 +02:00
protocol-handler.ts fix(electron): restore hidden window on taskbar click 2026-01-20 17:07:23 +01:00
proxy-agent.ts fix: add proxy env support for jira integration #6324 (#6574) 2026-03-09 13:09:51 +01:00
shared-state.ts fix: refactor tray handling to use shared state for task and countdown visibility 2025-11-28 18:53:00 +01:00
simple-store.test.cjs fix(electron): harden simple store writes (#7297) 2026-04-21 15:03:30 +02:00
simple-store.ts fix(electron): harden simple store writes (#7297) 2026-04-21 15:03:30 +02:00
start-app.ts fix(screenshots): force regular activation policy + dock on macOS 2026-05-09 11:39:36 +02:00
tsconfig.electron.json feat(plugins): add onReady() API with IPC ping + fix consent write delay (#7578) 2026-05-14 13:41:01 +02:00
various-shared.ts fix(electron): restore main window correctly when minimize-to-tray and task widget are both enabled 2026-04-16 17:41:39 +02:00