Skip to content

Latest commit

 

History

History
421 lines (296 loc) · 8.48 KB

File metadata and controls

421 lines (296 loc) · 8.48 KB

Contributing to NZ Legislation Tool

Thank you for your interest in contributing to the NZ Legislation Tool! This document provides guidelines and instructions for contributing to the project.

🎯 Table of Contents


🤝 Code of Conduct

Please be respectful and constructive in your interactions. We're committed to providing a welcoming and inspiring community for all.


🚀 Getting Started

Prerequisites

  • Node.js 18+ (LTS versions: 18, 20, 22)
  • pnpm 9+ (package manager)
  • Git for version control
  • GitHub account for contributing

Setup

  1. Fork the repository

    # Click "Fork" on GitHub, then clone your fork
    git clone https://github.com/YOUR_USERNAME/nz-legislation.git
    cd nz-legislation-tool
  2. Install dependencies

    pnpm install
  3. Set up environment

    cp .env.example .env
    # Edit .env with your NZ Legislation API key
  4. Verify setup

    pnpm dev -- --help
    pnpm test:run

🔄 Development Workflow

Branch Strategy

  • main - Production-ready code (protected)
  • feature/ - New features (e.g., feature/add-csv-export)
  • fix/ - Bug fixes (e.g., fix/rate-limiting-error)
  • chore/ - Maintenance (e.g., chore/update-dependencies)
  • docs/ - Documentation updates
  • test/ - Test additions/updates

Creating a Branch

# Always branch from main
git checkout main
git pull origin main

# Create feature branch
git checkout -b feature/your-feature-name

✏️ Making Changes

1. Make Your Changes

Edit the code, add features, fix bugs, etc.

2. Create a Changeset

For any user-facing changes, create a changeset:

pnpm changeset

Follow the prompts to:

  • Select the package (nz-legislation-tool)
  • Choose version bump type (major/minor/patch)
  • Add a descriptive message

Examples:

  • Patch: "Fix rate limiting configuration error"
  • Minor: "Add CSV export format for search results"
  • Major: "Change authentication method from query param to header"

3. Commit Your Changes

We use Conventional Commits:

git add .
git commit -m "type: description"

# Examples:
git commit -m "feat: add CSV export functionality"
git commit -m "fix: resolve rate limiting configuration issue"
git commit -m "docs: update installation instructions"
git commit -m "test: add integration tests for search API"

Commit Types:

  • feat: - New feature
  • fix: - Bug fix
  • docs: - Documentation
  • test: - Tests
  • refactor: - Code refactoring
  • chore: - Maintenance
  • perf: - Performance improvement
  • style: - Formatting/style
  • ci: - CI/CD changes

📬 Pull Request Process

Before Submitting

  1. Update your branch

    git fetch origin
    git rebase origin/main
  2. Run quality checks

    pnpm lint
    pnpm typecheck
    pnpm format
    pnpm test:run
  3. Verify changeset exists

    ls .changeset/

Submitting the PR

  1. Push your branch

    git push origin feature/your-feature-name
  2. Create PR on GitHub

  3. PR Title Format

    type: description
    
    Examples:
    feat: add CSV export functionality
    fix: resolve rate limiting issue
    

PR Review Process

  • ✅ All CI/CD checks must pass
  • ✅ At least 1 approval required
  • ✅ Address all review comments
  • ✅ Keep PR focused and reasonably sized

💻 Coding Standards

TypeScript

  • Use strict mode (strict: true in tsconfig.json)
  • No any types - use proper type definitions
  • Export types and interfaces for public APIs
  • Use async/await for asynchronous code

Example:

// ✅ Good
export interface SearchParams {
  query: string;
  limit?: number;
}

export async function searchWorks(params: SearchParams): Promise<SearchResults> {
  // Implementation
}

// ❌ Avoid
export async function searchWorks(params: any): Promise<any> {
  // Implementation
}

Error Handling

  • Use custom error classes for domain-specific errors
  • Provide helpful error messages with suggestions
  • Log errors with appropriate context

Example:

// ✅ Good
export class APIError extends Error {
  constructor(
    message: string,
    public statusCode?: number,
    public suggestion?: string
  ) {
    super(message);
    this.name = 'APIError';
  }
}

throw new APIError('Rate limit exceeded', 429, 'Wait 60 seconds before retrying');

Code Organization

  • Group related functionality in modules
  • Use path aliases for imports (@utils, @models, etc.)
  • Keep files focused and reasonably sized (<500 lines)

Example:

import { searchWorks } from '@client';
import { formatAsCSV } from '@output/formatters';
import type { Work } from '@models/work';

🧪 Testing

Running Tests

# Run all tests in watch mode
pnpm test

# Run tests once
pnpm test:run

# Run with coverage
pnpm test:coverage

# Run specific test file
pnpm test src/client.test.ts

Writing Tests

  • Use Vitest test framework
  • Name test files: *.test.ts
  • Place tests in tests/ or alongside source (src/*.test.ts)
  • Use descriptive test names

Example:

import { describe, it, expect } from 'vitest';
import { searchWorks } from '../client';

describe('searchWorks', () => {
  it('should return works matching the query', async () => {
    const results = await searchWorks({ query: 'health', limit: 5 });

    expect(results).toBeDefined();
    expect(results.works).toBeInstanceOf(Array);
    expect(results.works.length).toBeLessThanOrEqual(5);
  });
});

Test Coverage

  • Aim for >80% coverage
  • Test happy path and error cases
  • Include edge cases and boundary conditions

📚 Documentation

README Updates

Update the README.md if you:

  • Add new features or commands
  • Change installation steps
  • Modify configuration options
  • Add or change examples

Code Comments

  • Add JSDoc comments for exported functions
  • Explain complex logic
  • Document parameters and return values

Example:

/**
 * Search for legislation works matching the query.
 *
 * @param params - Search parameters
 * @param params.query - Search query string
 * @param params.limit - Maximum number of results (default: 10)
 * @returns Search results with matching works
 * @throws {APIError} If the API request fails
 */
export async function searchWorks(params: SearchParams): Promise<SearchResults> {
  // Implementation
}

🚀 Release Process

Automated Releases

This project uses Changesets for automated releases:

  1. Contributors create changesets with their PRs
  2. When PR is merged to main, Changesets action runs
  3. Version Packages PR is created automatically
  4. When Version PR is merged, release is published to npm

Manual Release (Maintainers Only)

# 1. Ensure all changesets are committed
git pull origin main

# 2. Bump versions and update changelog
pnpm changeset:version

# 3. Review changes
git diff

# 4. Commit and push
git commit -m "chore: version packages"
git push origin main

# 5. Publish to npm
pnpm changeset:publish

❓ Questions?

Common Issues

Q: How do I get an API key? A: Contact the NZ Legislation API team or check the README for setup instructions.

Q: Tests are failing locally A: Ensure your .env file has a valid API key and run pnpm install to update dependencies.

Q: How do I add a new command? A: Create a new file in src/commands/, export the command function, and register it in src/cli.ts.

Getting Help

  • 📖 Check the README for setup and usage
  • 📚 Review the CHANGESETS.md for versioning
  • 🐛 Open an issue for bugs or feature requests
  • 💬 Discuss in GitHub Discussions

🎉 Thank You!

Your contributions make this project better for everyone. We appreciate your time and effort!

Happy coding! 🚀


Last Updated: 2026-03-10 License: Apache 2.0