# ๐Ÿค Contribution Guide We warmly welcome and appreciate all forms of contributions, whether it's reporting a bug, submitting a new feature, improving documentation, or making suggestions. This guide will help you get involved in the project smoothly. ## ๐Ÿงญ Contribution Workflow ### 1. Preparation Before you start, please ensure you have: 1. **Installed [pnpm](https://pnpm.io/installation)**: This project uses pnpm as its package manager. 2. **Forked this repository**: Click the "Fork" button in the upper right corner of the page. 3. **Cloned your fork**: `git clone https://github.com/YOUR_USERNAME/mailbox.js.git` 4. **Installed dependencies**: Run `pnpm install` in the project root directory. ### 2. Choose a Contribution Type Based on your interests and experience, you can start with any of the following: | Type | Suitable For | Entry Point | | :------------------- | :--------------------------------- | :---------------------------------------------------------------------------------------------------------------------------- | | ๐Ÿž **Bug Fixes** | All developers | [View Good First Issues](https://github.com/mboxlabs/mailbox.js/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22) | | ๐Ÿ“š **Documentation** | Beginner-friendly | [View Documentation Issues](https://github.com/mboxlabs/mailbox.js/issues?q=is%3Aissue+is%3Aopen+label%3Adocumentation) | | ๐Ÿงฉ **New Provider** | Experience with specific protocols | [Propose a Provider](https://github.com/mboxlabs/mailbox.js/issues?q=is%3Aissue+is%3Aopen+label%3Aprovider) | | ๐Ÿ’ก **New Feature** | Power users | [Propose a New Feature](https://github.com/mboxlabs/mailbox.js/issues?q=is%3Aissue+is%3Aopen+label%3Aenhancement) | ### 3. Development and Submission 1. **Create a branch**: Create a descriptive branch from the `main` branch, such as `feat/add-new-provider` or `fix/login-bug`. ```shell git checkout -b feat/your-feature-name ``` 2. **Implement your changes**: Make your code modifications. Please follow the coding standards below. 3. **Write tests**: Add or update unit tests for your changes. All core logic, edge cases, and error handling should be covered. 4. **Run checks**: Ensure all tests and style checks pass. ```shell pnpm test pnpm style # The Mailbox family is three repositories: mailbox.js (this one), mailbox.py and mailbox.rust. # When a change touches behaviour shared across the three, clone the ports next to this repo # (they are not tracked here) and run their suites too: # git clone git@github.com:mboxlabs/mailbox.py.git python # git clone git@github.com:mboxlabs/mailbox.rust.git rust (cd python && python3 -m pytest -q) (cd rust && cargo test) ``` `pnpm test` runs `pnpm run typecheck` first: `vitest` only transpiles, it does not type-check, so a change the downstream code has not caught up with would otherwise sail through green. That wiring is pinned by `test/typecheck-runs-before-tests.test.ts` โ€” do not "speed it up" back to `vitest run`. `tsconfig.release.json` is **not** a check surface (`noEmit: false`, no `outDir`: `tsc -p` writes JS into `src/`); the published surface is checked by `pnpm build`. In the other direction: this package's `dist/index.d.ts` **is** the type-check surface of the packages built on it (`@mboxlabs/input`, and through it `@mboxlabs/input-inquirer`; `@isdk/tool-rpc`). They link it through `package.json` `types`, so an edited `src` with a stale `dist` means they type-check against a contract this repo no longer has โ€” green, and meaningless. Rebuild with `pnpm build` (which passes `--dts --dts-resolve` to tsup); `build-fast` emits no `.d.ts`, so it does not refresh that surface. 5. **Commit your code**: Follow the [Conventional Commits](https://www.conventionalcommits.org/) specification. 6. **Open a Pull Request**: Push your branch to GitHub and create a Pull Request to the `main` branch of the main repository. Please clearly describe the changes you have made in the PR description. ## ๐Ÿ“ Coding Standards ### Naming Conventions - **Variables and Functions**: Use `camelCase`, e.g., `myVariable`. - **Classes, Interfaces, and Types**: Use `PascalCase`, e.g., `MyClass`, `MailboxProvider`. - **Constants**: Use `UPPER_CASE`, e.g., `DEFAULT_TIMEOUT`. - **Private Properties/Methods**: Use an underscore prefix, e.g., `_privateMethod`. ### Code Style The project uses Prettier and ESLint to enforce a consistent code style. Before committing, please run `pnpm style:fix` to automatically format your code. ## ๐Ÿงช Testing Requirements We use [Vitest](https://vitest.dev/) for unit testing. The Mailbox family ships three implementations in three repositories: this package, [mailbox.py](https://github.com/mboxlabs/mailbox.py) (covered by `pytest`) and [mailbox.rust](https://github.com/mboxlabs/mailbox.rust) (covered by `cargo test`). A `python/` or `rust/` directory next to this one is only a local development layout โ€” it is not part of this repository. Delivery semantics โ€” subscribe versus fetch, ack/nack and in-flight timeouts, requeue deduplication, and the opt-in retry policy โ€” are specified once (in `README.md`) and implemented in all three, so changing them requires matching tests in each. ### Required Coverage - **Core Functionality**: Ensure your modified or added core logic has corresponding tests. - **Edge Cases**: For example, empty inputs, max/min values, etc. - **Error Handling**: Simulate and test all expected error paths. - **Asynchronous Operations**: Ensure Promises are resolved and rejected correctly. ### Vitest Best Practices - Use `describe` to logically group your tests. - The description of a test case (`it` or `test`'s first argument) should be clear and concise. - Prefer `vi.fn()` or `vi.spyOn()` for mocking functions and objects. - Use `beforeEach` and `afterEach` to clean up the test environment where appropriate. ## ๐Ÿ“ Commit Message Specification We follow the Conventional Commits specification. The format is as follows: ```sh (): [optional body] ``` | Type | Description | | :--------- | :-------------------------------------------------------------------------------- | | `feat` | A new feature | | `fix` | A bug fix | | `docs` | Documentation only changes | | `test` | Adding missing tests or correcting existing tests | | `refactor` | A code change that neither fixes a bug nor adds a feature | | `style` | Changes that do not affect the meaning of the code (white-space, formatting, etc) | | `chore` | Changes to the build process or auxiliary tools and libraries | **Example**: ```text feat(mailbox): add xxx option to fetch - Add `xxx?: boolean` to fetch options - Default: xxx=false (semantics) ``` ## ๐Ÿ“ฆ Release Process (for Maintainers) The release process is automated by `commit-and-tag-version` (run through `pnpm dlx`), which generates the `CHANGELOG.md` and tags the version based on Conventional Commits. It neither publishes nor pushes: `pnpm publish` and `git push --follow-tags` stay manual. The tool is pinned to an exact version, `commit-and-tag-version@12.7.3`. `@12` would be a floating major range: every future 12.x patch would then get to decide how the changelog renders, with no lockfile in this repo to argue with. The `///` regression starts at `13.0.0` โ€” its `hosted-git-info` can no longer read a repository whose name ends in `.js`, so host/user/project come out empty and the links collapse to `](///compare/v1.0.0...v2.0.0)`, with commit references degraded to bare SHAs. Measured on this history: `12.5.2` and `12.7.3` render correctly; `13.0.0`, `13.1.0`, `13.1.2` do not. Test a link before raising the pin. ```shell # Preview the version and the changelog without touching the repo pnpm dlx commit-and-tag-version@12.7.3 --dry-run # Official release pnpm release ``` `pnpm release -- --dry-run` is **not** a read-only preview: pnpm appends the flag to the last command in the chain only, so `clean`, the docs rebuild, and the `docs` commit all still happen before anything is previewed. Preview with the command above instead. Publish with `pnpm publish`, from inside the `@isdk/ai-tools` workspace โ€” not with `npm publish`. The package's one runtime dependency is declared as `"@isdk/hash": "workspace:^"`, and only pnpm rewrites that protocol into a real range (measured: `^0.1.1`). Outside the workspace, `pnpm pack` already fails with `ERR_PNPM_CANNOT_RESOLVE_WORKSPACE_PROTOCOL`; `npm publish` would put a range no consumer package manager can resolve in front of users. Expect `--no-git-checks` when the release commit has not been pushed yet, and publish the sibling package first if the version it points at is not on the registry.