Contributing
This page covers everything you need to know to contribute to the ms repository, from setting up a local development environment to understanding the release process. The project follows a straightforward monorepo structure with a single source module and a set of quality checks enforced through continuous integration.
Development Environment Setup
Prerequisites
- Node.js version 20 or later (the project requires
node >=20as specified inpackage.json). - pnpm as the package manager. The repository uses pnpm workspaces and expects pnpm to be available globally.
Getting Started
- Clone the repository
git clone https://github.com/vercel/ms.git
cd ms- Install dependencies
pnpm installThis command installs all dependencies and sets up the pnpm workspace. No additional build step is required before development because the source files in src/ are written in TypeScript and are compiled on demand by the test runner and build tool.
- Verify the setup
Run the full test suite to confirm everything is working:
pnpm testThis executes both Node.js and Edge runtime tests (see Running the Test Suite below).
Repository Layout
The repository has a minimal structure:
src/, Contains all library source code. This is the only module that implements functionality.- Root configuration files,
jest.config.ts,lint-staged.config.ts,tsdown.config.ts, andpackage.jsondefine the toolchain. .github/workflows/, CI/CD pipeline definitions (Quality, Test, and Publish workflows).
There are no separate directories for examples, benchmarks, or documentation; all documentation lives in the wiki.
Available Scripts
All scripts are defined in package.json and are run with pnpm run <script>. The key scripts are:
| Script | Purpose |
|---|---|
test | Runs the full test suite (both Node.js and Edge tests) |
test:nodejs | Runs tests in a Node.js environment |
test:edge | Runs tests in an Edge Runtime environment |
build | Compiles the TypeScript source into distributable output |
lint | Runs the linter to check code style |
format | Formats source code using the project's formatter |
typecheck | Runs TypeScript type checking without emitting files |
attw | Runs arethetypeswrong to verify type declarations are correct |
precommit | Runs lint-staged (configured in lint-staged.config.ts) |
Code Style Guidelines
Formatting and Linting
The project enforces consistent code style through automated tools:
- Formatting: Run
pnpm formatto automatically format all source files. The formatter configuration is defined in the project root. - Linting: Run
pnpm lintto check for code quality issues. The linter configuration is part of the project's toolchain. - Type checking: Run
pnpm typecheckto verify TypeScript types are correct without producing output files.
Pre-commit Checks
The project uses lint-staged (configured in lint-staged.config.ts) to run checks on staged files before commits. The precommit script triggers this process. When you commit changes, lint-staged automatically runs the configured linters and formatters on the files you've staged.
TypeScript Conventions
- All source code is written in TypeScript.
- The library exports TypeScript template literal types (e.g.,
StringValue) for type-safe parsing. When adding new parsing functionality, ensure the type definitions remain consistent with the runtime behavior. - Use strict TypeScript configuration; the
typecheckscript validates that no type errors exist.
Testing Conventions
- Tests are written using Jest (configured in
jest.config.ts). - Tests must pass in both Node.js and Edge Runtime environments. The CI matrix runs
test:nodejsandtest:edgeacross Node.js versions 20, 22, and 24. - When adding new features, include corresponding tests for both environments.
Running the Test Suite
Local Testing
Run all tests:
pnpm testRun only Node.js tests:
pnpm test:nodejsRun only Edge Runtime tests:
pnpm test:edgeCI Test Matrix
The project's CI workflow (.github/workflows/test.yml) runs tests automatically on every push to main and on pull requests targeting main. The test matrix covers:
- Node.js versions: 20, 22, and 24
- Test tasks:
test:nodejsandtest:edge
The CI uses fail-fast: false, meaning all combinations run even if one fails, providing full visibility into compatibility across environments.
Quality Checks
Before submitting a pull request, ensure all quality checks pass locally:
pnpm format
pnpm lint
pnpm typecheck
pnpm attw
pnpm testThe CI workflow (.github/workflows/quality.yml) runs these checks automatically on every push and pull request. The quality matrix includes:
- Node.js version: 24
- Tasks:
format,lint,typecheck,attw
Pull Request Process
-
Create a feature branch from
main. Use a descriptive name (e.g.,fix/parse-negative-duration,feat/add-week-unit). -
Make your changes in the
src/directory. Follow the code style guidelines described above. -
Write tests for any new functionality or bug fixes. Ensure tests cover both Node.js and Edge Runtime environments.
-
Run all checks locally as described in the Quality Checks section.
-
Commit your changes. The pre-commit hook (lint-staged) will run automatically on staged files.
-
Push your branch and open a pull request against
main. The CI workflows will run automatically:
- Quality workflow: Runs formatting, linting, type checking, and type declaration verification.
- Test workflow: Runs the full test suite across Node.js 20, 22, and 24 for both Node.js and Edge environments.
-
Address any CI failures. Review the workflow logs and fix issues before requesting review.
-
Request review from a maintainer. All pull requests require at least one approval before merging.
Release Process
The release process is fully automated through the CI/CD pipeline. Understanding this process helps contributors know what happens after their changes are merged.
Canary (Nightly) Releases
The workflow defined in .github/workflows/release.yml publishes a canary release to npm on every push to main. The process:
- Trigger: Any push to the
mainbranch. - Build: Runs
pnpm buildto compile the TypeScript source. - Version calculation: Extracts the base version from
package.json, then creates a nightly version string in the format<base>-nightly.<YYYYMMDDHHMM>(e.g.,2.1.0-nightly.202503151430). - Publish: Publishes to npm with the
nightlytag, using provenance for supply chain security.
The release workflow requires the NPM_TOKEN_ELEVATED secret and the GITHUB_TOKEN for authentication.
Stable Releases
Stable releases are not automated through the CI workflows shown in this repository. They are performed manually by maintainers. The canary release process ensures that the latest code is always available on npm under the nightly tag for testing, while stable versions are published under the default latest tag when a formal release is cut.
Versioning
The project follows semantic versioning. The base version in package.json is the source of truth for stable releases. Canary releases append a nightly timestamp to this base version without modifying the git history (using --no-git-tag-version).
Related Pages
- Overview, High-level description of the
mslibrary - Architecture, System purpose, runtime topology, and key flows
- Project Configuration, Build and test tooling details
- Contributing (this page)