Development Setup
Relevant source files
The following files were used as context for generating this wiki page:This document provides a comprehensive guide to setting up the development environment for Ghostbird, a Thunderbird add-on. It covers prerequisites, installation, the build system, testing, and the common development workflow. The project uses Node.js, Yarn for package management, and tsdown for bundling TypeScript code.
The codebase follows a Ports and Adapters architecture, emphasizing the Dependency Inversion Principle. This is facilitated by a custom dependency injection mechanism that automates class instantiation, making the code more testable and maintainable. For more details on the architecture, see the Design Document.
Sources: CONTRIBUTING.md, doc/design.md:80-86
Prerequisites
Before starting, ensure you have the following software installed on your system.
| Software | Minimum Version | Notes |
|---|---|---|
| Git | - | For version control. |
| Thunderbird | 128+ | The target application for the add-on. |
| Node.js | LTS (v22+) | Required to run the build tools and scripts. |
| Yarn | 4.10.3+ | Used for package management via corepack. |
Sources: CONTRIBUTING.md:21-26, package.json:12
Initial Setup
Follow these steps to clone the repository and install dependencies:
-
Fork and Clone: Fork the repository on GitHub, then clone your fork locally.
git clone <your-fork-url> cd ghostbird -
Enable Corepack and Install Yarn: The project uses
corepackto manage the Yarn version.corepack install && corepack enable -
Install Dependencies: Run
yarnto install all project dependencies defined inpackage.json. This command will also trigger thepostinstallscript, which generatesindex.tsbarrel files.yarn
Sources: CONTRIBUTING.md:41-50, package.json:28
Build System
The project is built using tsdown, a bundler based on Rolldown and Oxc. The entire build configuration is defined in tools/tsdown_config.ts. The build process is responsible for transpiling TypeScript, generating the manifest, handling localization, and packaging the final add-on.
Sources: doc/building.md:3-5
Build Process Flow
The following diagram illustrates the inputs, processing steps, and outputs of the build system.
This diagram shows how source files and templates are processed by various tsdown plugins to produce the bundled JavaScript, manifest, and other assets, which are then packaged into an .xpi file by web-ext.
Sources: doc/building.md:8-32
Build Modes
The build script operates in two modes: development and release. The mode is determined by the presence of the CI environment variable or an existing ext/manifest.json file.
- Development Build:
- Source maps contain absolute paths for easier debugging.
console.log()statements are preserved and prefixed with[Ghostbird].
- Release Build:
- Source maps use relative paths.
console.log()statements are removed to clean up the output.- Sanity tests and type-checking are skipped as they are expected to be run as pre-build steps.
Sources: doc/building.md:46-64, tools/tsdown_config.ts:24, 70-82
Key Build Scripts
The package.json file contains several scripts for managing the development lifecycle.
| Script | Description |
|---|---|
yarn build | Runs a full build process: check, test, build-js, and build-xpi. |
yarn build-js | Runs tsdown to bundle TypeScript files and generate assets into dist/ext/. |
yarn watch | Runs build-js in watch mode, automatically rebuilding on file changes. |
yarn build-xpi | Uses web-ext to package the contents of dist/ext/ into an .xpi file. |
yarn start | Launches Thunderbird with the extension loaded temporarily for debugging. |
yarn test | Runs the full suite of unit tests using Vitest. |
yarn check | Runs the type checker (tsc) and Biome linter. |
yarn fix | Automatically fixes linting and formatting issues found by Biome. |
Sources: package.json:24-49, CONTRIBUTING.md:58-72
Development Workflow
A typical development cycle involves coding, building, testing, and debugging.
1. Coding
- Make your code changes in the
src/directory. - Run
yarn checkto check for type errors and linting issues. - Run
yarn fixto automatically format code and fix simple issues. - For better editor integration (e.g., with VSCode or Vim), you can generate editor SDKs by running
yarn sdk $your_editor_name.
Sources: CONTRIBUTING.md:92-99
2. Building
- For a one-time build, run
yarn build. - For continuous development, run
yarn watchin a separate terminal to have the extension rebuild automatically as you save files.
Sources: CONTRIBUTING.md:74-76
3. Testing
The project uses Vitest for unit testing.
- Run
yarn testto execute all tests. - Use
yarn test:watchto run tests in watch mode. - For a graphical interface, use
yarn test:ui. - Test results are output to
build/test/.
Tests are located in src/test/ and also as in-source tests within application files, guarded by if (import.meta.vitest).
Sources: doc/testing.md:3-15, package.json:31-36
4. Debugging
- Run
yarn startto launch Thunderbird with the add-on temporarily loaded. This usesweb-ext run. - You may need to create a
.web-ext-config.mjsfile from the provided example to configure the Thunderbird path and profile settings. - The project also includes an example launch configuration for VSCode debugging in
.vscode/launch.example.json.
Sources: CONTRIBUTING.md:107-116
Code Structure and Dependency Management
The project uses a custom dependency injection (DI) mechanism to manage class instantiation and promote the Dependency Inversion Principle. This is primarily handled by startup functions in src/root/startup/.
Automatic Instantiation
Classes intended for automatic instantiation must declare a static isSingleton property.
static isSingleton: true: The class is instantiated once and shared as a singleton.static isSingleton: false: A new instance is created each time it's required (factory pattern).
The startup logic scans for these classes, resolves their dependencies via constructor parameters, and instantiates them. This system avoids manual new calls in the main application logic, centralizing object creation to the "Composition Root".
This diagram illustrates the instantiation logic:
Dependency Analysis
To help developers understand the complex dependency graph, a report can be generated. After running yarn test, a file named build/test/dependency_tree.md is created. This file contains a Mermaid diagram of the dependency graph and example startup code, generated by src/test/util/dependency_reporter.ts.
Sources: doc/faq-architectural.md:16-19, src/test/util/dependency_reporter.ts:11-19