Contributing
Contributions are welcome! This project follows strict code quality standards and automated testing to maintain reliability.
Development Setup
git clone https://github.com/nubisco/homebridge-tuya-local-platform.git
cd homebridge-tuya-local-platform
npm installDevelopment Workflow
Build & Watch
npm run build # Compile TypeScript to dist/
npm run dev # Watch mode (rebuilds on file changes)Code Quality
Before committing, ensure your code passes all checks:
npm run lint # ESLint (must pass)
npm run format:check # Prettier formatting check
npm run format # Auto-format code
npm test # Run all unit tests (must pass)Pre-commit checks:
- Linting and formatting run automatically via
lint-stagedon commit - All tests must pass before pushing to remote
Testing
This project uses Vitest for unit testing. Tests are located in tests/ and run against the TypeScript source directly.
npm test # Run all tests
npm test -- --watch # Run tests in watch modeTesting guidelines:
- Add tests for new device types and accessory logic
- Mock HAP services/characteristics using the helpers in
tests/helpers.ts - Target 80%+ code coverage for new features
- Tests run in CI on Node 20 and 22
Adding a New Device Type
Create the accessory file:
- Create
src/accessories/{DeviceName}.accessory.tsextendingBaseAccessory - Implement
getCategory()static method returning the HAP category - Implement
_registerPlatformAccessory()to add HAP services - Implement
_registerCharacteristics()to bind characteristics and handle DP updates
- Create
Register the device type:
- Export as
defaultfrom your accessory file - Add re-export in
src/accessories/index.ts - Add lowercase type key → class mapping to
CLASS_DEFinsrc/index.ts
- Export as
Update configuration schema:
- Add the type to the
oneOfarray inconfig.schema.json - Add device-specific config parameters with appropriate
conditionfunctions - Test in Homebridge Config UI X to ensure fields appear correctly
- Add the type to the
Document the device:
- Add to the device table in
docs/introduction.md - Add detailed configuration section in
docs/device-types.mdwith:- Description and use case
- Example JSON5 configuration
- List of all DP overrides and optional parameters
- Any special notes or warnings
- Add to the device table in
Add unit tests:
- Create a test file in
tests/{DeviceName}.test.ts - Test service registration, characteristic binding, DP updates, and state changes
- Use the mock helpers in
tests/helpers.ts
- Create a test file in
Verify the build:
bashnpm run lint && npm test && npm run build
Commit Message Format
This project uses Conventional Commits to trigger automatic releases and changelog generation. Commits must follow this format:
<type>(<scope>): <subject>
<body>
<footer>Types:
feat:— New feature (triggers minor version bump)fix:— Bug fix (triggers patch version bump)docs:— Documentation onlytest:— Adding or updating testsrefactor:— Code refactoring (no functional changes)chore:— Maintenance tasks (dependencies, build config)ci:— CI/CD changes
Examples:
feat(accessories): add support for smart thermostat device type
fix(dehumidifier): correct rotation speed calculation
docs(device-types): add configuration examples for air purifiers
test(base-accessory): add tests for _getDividedState methodBreaking changes: Add BREAKING CHANGE: in the footer or append ! after the type:
feat(api)!: change DP mapping configuration format
BREAKING CHANGE: dpPower now requires string instead of numberCode Style
- TypeScript with strict mode (
strictNullChecksandstrictFunctionTypesdisabled) - Indentation: 2 spaces (enforced by Prettier)
- Line endings: LF
- Naming conventions:
- PascalCase for classes and types
- camelCase for variables, functions, and methods
- Prefix private members with
_
- File naming:
- Accessories:
{DeviceType}.accessory.ts - Tests:
{DeviceType}.test.ts
- Accessories:
Pull Request Process
Fork the repository and create a feature branch:
bashgit checkout -b feat/my-new-featureMake your changes following the guidelines above
Ensure all checks pass:
bashnpm run lint && npm test && npm run buildCommit using conventional commit format
Push to your fork and open a pull request against
masterWait for CI checks to pass:
- Linting (Node 22)
- Build (Node 20, 22)
- Tests (Node 20, 22)
Address any review feedback
Documentation
Documentation is built with VitePress and deployed to GitHub Pages automatically on release.
Local Docs Development
npm run docs:dev # Start dev server (localhost:5173)
npm run docs:build # Build static site to docs/.vitepress/dist/
npm run docs:preview # Preview built docsDocumentation Structure
docs/
index.md # Home page (hero + features)
introduction.md # Overview + device type table
installation.md # Installation instructions
get-local-keys.md # How to extract Tuya local keys
configuration.md # Basic configuration guide
device-types.md # Detailed device-specific config
config-example.md # Full config examples
troubleshooting.md # Common issues and solutions
contributing.md # This file
credits.md # AttributionReporting Issues
When opening an issue, include:
- Homebridge version:
homebridge -V - Node.js version:
node -v - Plugin version: Check in Homebridge UI or
npm list @nubisco/homebridge-tuya-local-platform - Device information:
- Device type (from your config)
- Manufacturer and model
- Tuya protocol version (3.1, 3.3, or 3.4)
- Relevant Homebridge log output (enable debug mode if needed)
- Device signature (DPS state from logs) — redact device ID and key
Release Process
Releases are fully automated via semantic-release:
- Commits pushed to
mastertrigger CI - semantic-release analyzes commit messages
- If release-worthy commits exist:
- Version is bumped automatically
CHANGELOG.mdis generated- Git tag is created
- GitHub release is published
- Package is published to npm
- Documentation is deployed to GitHub Pages
You do not need to manually update version numbers or CHANGELOG.md.
Questions?
Open a discussion for general questions or feature requests.