Menu ▾ ▴

#70 Typed build + lint + unit-test toolchain for inject/ scripts

closed
nobody
None
2026-07-06
2026-07-06
Anonymous
No

Originally created by: kristofferR

Ref [#48]

inject/messenger.js had grown to 2,555 lines of untyped, untested, unlinted JS with node --check as the only gate. This adds the light toolchain the issue asked for:

What changed

  • TypeScript modules — the injected scripts now live in inject/src/ (one module per feature, strict tsconfig, noUncheckedIndexedAccess), bundled back to the same committed single-file IIFEs the Rust shell embeds (src-tauri/inject/messenger.js + panel.js) by esbuild via bun run build:inject. The logic was transcribed verbatim, and main() calls the feature inits in the old single-file section order — capture-phase listeners on the same event fire in registration order, so that order is part of the behaviour.
  • Unit tests — the pure logic is extracted into inject/src/messenger/lib/ and covered by 43 bun test cases: l.php/link classification, unread "(N)" title parsing, thread-href regexes, DND windows, download-name normalization, the telemetry blocklist (incl. never-block endpoints), emoji glyphs, and preview-identity parsing.
  • Biome for lint/format (biome.jsonc, scoped to inject/), tsgo for typechecking (separate browser/test tsconfigs so Bun's ambient types stay out of page code).
  • CI — new inject job in ci.yml: bun install --frozen-lockfile, lint, typecheck, test, rebuild, then git diff --exit-code src-tauri/inject so the committed bundles can't drift from source.
  • Docs: AGENTS.md gate + architecture notes, README pointer (edit inject/src/, never the generated JS).

Fidelity checks

  • String/number literal diff between the old messenger.js and the rebuilt bundle: every difference traces to stripped comments, template-literal conversion, or esbuild's exponent number printing — no selector/threshold/event-name drift.
  • cargo clippy/cargo test pass with the generated bundles compiled in via include_str!.
  • Live smoke test on a debug build via tauri-mcp: the bundle boots on real Messenger, window.__carrierShortcuts registers all 9 helpers, focusComposer drives the real DOM, and the page renders normally (dark theme, stripped chrome).

Generated messenger.js drops from 106 KB to 82 KB (comments live in the source now).

https://claude.ai/code/session_01RJBYpVt2zj2i3defSHFuvj

Summary by CodeRabbit

  • New Features
  • Added several Messenger enhancements, including zoom controls, keyboard shortcuts, media viewer zoom/pan, native notifications, unread badges, recent thread syncing, and improved link and download handling.
  • Added options to hide names/avatars, enforce theme, auto-refresh stalled chats, manage spellcheck, and simplify the login page.
  • Added support for system emoji, fullscreen behavior, cookie decline automation, and camera/microphone permission warnings.

  • Bug Fixes

  • Improved handling for Messenger updates, telemetry blocking, and browser/WebView quirks.
  • Regenerated bundled scripts and added checks to keep generated files in sync.

Related

Tickets: #48
Tickets: #71
Tickets: #72

Discussion

  • Anonymous

    Anonymous - 2026-07-06

    Originally posted by: kristofferR

    @coderabbitai review

     
  • Anonymous

    Anonymous - 2026-07-06

    Originally posted by: coderabbitai[bot]

    ✅ Action performed Review finished. > Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.
     
  • Anonymous

    Anonymous - 2026-07-06

    Originally posted by: coderabbitai[bot]

    Review Change Stack

    📝 Walkthrough ## Walkthrough This PR migrates injected Facebook Messenger/panel scripts from a single hand-written JS file into a typed Bun/TypeScript source tree (`inject/src/`) bundled via esbuild into `src-tauri/inject`. It adds CI/toolchain (Biome, tsconfig, build script), a shared bridge/types layer, reusable lib utilities with tests, and numerous feature modules (hide-names, login-tidy, cookie-consent, notifications, unread-badge, zoom, shortcuts, telemetry blocking, etc.) wired through a single Messenger entrypoint. ### Changes **Injected Script TypeScript Migration** |Layer / File(s)|Summary| |---|---| |**Build tooling, CI, and config**
    `.github/workflows/ci.yml`, `package.json`, `biome.jsonc`, `tsconfig.json`, `tsconfig.test.json`, `inject/build.ts`, `AGENTS.md`, `README.md`|New CI `inject` job runs lint/typecheck/tests/build and fails on bundle drift; package.json adds build/lint/typecheck/check scripts and dev dependencies; Biome and TypeScript configs are introduced; `inject/build.ts` bundles typed sources into `src-tauri/inject` via esbuild; docs describe the new pipeline.| |**Bridge helpers and ambient types**
    `inject/src/messenger/bridge.ts`, `inject/src/types.d.ts`|Adds `invoke`, `toast`, `diag`, `openUrl` bridge functions and ambient typings for `CarrierSettings`, `Window`, `XMLHttpRequest`, `Element`, `Document` extensions.| |**Shared lib utilities and tests**
    `inject/src/messenger/lib/*.ts`, `inject/src/messenger/lib/*.test.ts`|Adds pure helpers for color parsing, DND windows, download filenames, emoji glyph detection, link classification, privacy/identity text heuristics, telemetry URL blocking, thread id parsing, unread count parsing, and zoom clamping, each with unit tests.| |**Core UX features**
    `inject/src/messenger/features/{conversation-actions,shortcuts,thread-nav,link-handling,zoom,media-viewer,fullscreen,spellcheck}.ts`|Implements conversation navigation, keyboard shortcuts, thread opening, external link handling, page zoom, media zoom/pan viewer, a fullscreen polyfill, and spellcheck toggling.| |**Privacy and appearance features**
    `inject/src/messenger/features/{hide-names,force-theme,login-tidy,cookie-consent}.ts`|Implements identity-hiding DOM scanning, forced theme enforcement, logged-out login page tidying, and optional cookie-decline automation.| |**System integration features**
    `inject/src/messenger/features/{notifications,unread-badge,recent-threads,telemetry,media-permissions,download-anchors,context-menu,selector-health,auto-refresh,system-emoji}.ts`|Implements native notification bridging, Dock/taskbar unread badge sync, recent-thread scraping, telemetry request blocking, media permission warnings, download interception, a custom context menu, selector health monitoring, auto-refresh recovery, and system emoji replacement.| |**Entrypoint wiring and regenerated bundles**
    `inject/src/messenger/index.ts`, `inject/src/panel/index.ts`, `src-tauri/inject/panel.js`|Wires all feature initializers into a single `main()` guarded by top-frame checks; panel entrypoint exposes toast/update/settings bridge globals; regenerated `panel.js` reflects the new bundled output.| **Estimated code review effort:** 4 (Complex) | ~75 minutes ### Sequence Diagram(s) :::mermaid sequenceDiagram participant Window participant MessengerIndex as inject/src/messenger/index.ts participant Features as Feature Initializers participant Bridge as bridge.ts (invoke) participant Tauri as Tauri Backend Window->>MessengerIndex: load script, check window.top===window.self MessengerIndex->>Features: call init*() in fixed order Features->>Bridge: invoke("plugin:event|emit", ...) Bridge->>Tauri: forward via __TAURI_INTERNALS__.invoke Tauri-->>Bridge: response/ack Bridge-->>Features: resolved/rejected promise **Possibly related issues** - [kristofferR/Carrier#48](https://github.com/kristofferR/Carrier/issues/48): Implements the same typed Bun/esbuild build/lint/test toolchain for `inject/` scripts described in this issue, including CI wiring. **Possibly related PRs** - [[kristofferR/Carrier#1](https://github.com/kristofferR/Carrier/issues/1)](https://github.com/kristofferR/Carrier/pull/1): Both PRs modify `src-tauri/inject/panel.js`'s `__carrierToast`, `__carrierCheckUpdates`, and `__carrierToggleSettings` functions. - [[kristofferR/Carrier#22](https://github.com/kristofferR/Carrier/issues/22)](https://github.com/kristofferR/Carrier/pull/22): The new `initHideNames()` implementation corresponds to the same "Hide Names & Avatars" feature and `data-carrier-hide-names` mechanism. - [[kristofferR/Carrier#63](https://github.com/kristofferR/Carrier/issues/63)](https://github.com/kristofferR/Carrier/pull/63): Introduces the same `clampZoom`/`applyZoom`/`initZoom` page-zoom logic later wired to `carrier:zoom` settings.
    🚥 Pre-merge checks | ✅ 5
    ✅ Passed checks (5 passed) | Check name | Status | Explanation | | :------------------------: | :------- | :----------------------------------------------------------------------------------------------------------------------- | | Description Check | ✅ Passed | Check skipped - CodeRabbit’s high-level summary is enabled. | | Title check | ✅ Passed | The title accurately summarizes the main change: adding a typed build, lint, and unit-test toolchain for inject scripts. | | Docstring Coverage | ✅ Passed | No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. | | Linked Issues check | ✅ Passed | Check skipped because no linked issues were found for this pull request. | | Out of Scope Changes check | ✅ Passed | Check skipped because no linked issues were found for this pull request. |
    ✨ Finishing Touches
    📝 Generate docstrings - [ ] Create stacked PR - [ ] Commit on current branch
    🧪 Generate unit tests (beta) - [ ] Create PR with unit tests - [ ] Commit unit tests in branch `typed-inject-toolchain`

    Comment @coderabbitai help to get the list of available commands.

     
  • Anonymous

    Anonymous - 2026-07-06

    Originally posted by: chatgpt-codex-connector[bot]

    You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
    To continue using code reviews, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.

     
  • Anonymous

    Anonymous - 2026-07-06

    Ticket changed by: kristofferR

    • status: open --> closed
     

Log in to post a comment.