Skip to content

Latest commit

 

History

History
441 lines (329 loc) · 9.64 KB

File metadata and controls

441 lines (329 loc) · 9.64 KB

Contributing to Snaplet

Thank you for your interest in contributing to Snaplet! We're excited to have you join our community of developers working to make database development better for everyone.

Table of Contents

Code of Conduct

We are committed to providing a welcoming and inclusive experience for everyone. Please read and follow our Code of Conduct:

  • Be respectful and inclusive
  • Welcome newcomers and help them get started
  • Focus on constructive criticism
  • Respect differing viewpoints and experiences
  • Show empathy towards other community members

Getting Started

Prerequisites

  • Node.js v18.18.2 or higher
  • Yarn 3.5.0 (we use Yarn workspaces)
  • PostgreSQL 12+ (for running tests)
  • Git

Fork and Clone

  1. Fork the repository on GitHub
  2. Clone your fork locally:
git clone https://github.com/YOUR-USERNAME/snapshot.git
cd snapshot
  1. Add the upstream repository:
git remote add upstream https://github.com/snaplet/snapshot.git

Development Setup

1. Install Dependencies

# Install Yarn if you haven't already
corepack enable

# Install all dependencies
yarn install

2. Set Up Environment Variables

Create a .env file in the root directory:

# Development database for testing
DATABASE_URL=postgresql://localhost:5432/snaplet_dev

# Test database
TEST_DATABASE_URL=postgresql://localhost:5432/snaplet_test

# Optional: Sentry DSN for error tracking
SENTRY_DSN=

# Optional: Debug mode
DEBUG=snaplet:*

3. Set Up Test Databases

# Create test databases
createdb snaplet_dev
createdb snaplet_test

# Run initial setup
yarn workspace @snaplet/cli setup:dev

4. Build the Project

# Build all packages
yarn build

# Watch mode for development
yarn dev

Project Structure

snapshot/
├── cli/                      # Main CLI package (@snaplet/snapshot)
│   ├── src/
│   │   ├── commands/        # CLI command implementations
│   │   ├── components/      # Shared components
│   │   ├── lib/            # Utilities and helpers
│   │   └── testing/        # Test utilities
│   ├── e2e/                # End-to-end tests
│   └── __fixtures__/       # Test fixtures
├── docs/                    # Documentation website
├── packages/               # Shared packages
└── scripts/               # Build and deployment scripts

Key Packages

  • @snaplet/cli: The main CLI application
  • @snaplet/sdk: Core SDK for database operations
  • docs: Documentation website (Next.js + Nextra)

Development Workflow

1. Create a Feature Branch

# Update your local main branch
git checkout main
git pull upstream main

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

2. Make Your Changes

  • Write clean, well-documented code
  • Follow the existing code style
  • Add tests for new functionality
  • Update documentation as needed

3. Run Tests Locally

# Run unit tests
yarn test

# Run specific test file
yarn test path/to/test.ts

# Run e2e tests
yarn test:e2e

# Run all tests with coverage
yarn test:coverage

4. Lint and Format

# Run linter
yarn lint

# Fix linting issues
yarn lint:fix

# Format code
yarn format

Testing

Unit Tests

We use Vitest for unit testing. Tests should be colocated with the code they test:

// src/lib/format.ts
export function formatBytes(bytes: number): string {
  // Implementation
}

// src/lib/format.test.ts
import { describe, it, expect } from 'vitest'
import { formatBytes } from './format'

describe('formatBytes', () => {
  it('should format bytes correctly', () => {
    expect(formatBytes(1024)).toBe('1 KB')
  })
})

E2E Tests

End-to-end tests are located in cli/e2e/. They test the full CLI workflow:

// cli/e2e/capture/e2e.capture.test.ts
import { test, expect } from '@playwright/test'
import { createTestDb, runSnapletCli } from '../testing'

test('should capture a snapshot', async () => {
  const dbUrl = await createTestDb()
  
  const result = await runSnapletCli(['snapshot', 'capture'], {
    env: { DATABASE_URL: dbUrl }
  })
  
  expect(result.exitCode).toBe(0)
  expect(result.stdout).toContain('Snapshot captured successfully')
})

Test Database Fixtures

Test fixtures are located in cli/__fixtures__/. Add new SQL files for testing specific scenarios.

Submitting Changes

1. Commit Your Changes

We follow conventional commits specification:

# Format: <type>(<scope>): <subject>

# Examples:
git commit -m "feat(cli): add support for MySQL databases"
git commit -m "fix(capture): handle tables with no primary key"
git commit -m "docs: update installation instructions"
git commit -m "test(e2e): add tests for subset feature"

Commit Types:

  • feat: New feature
  • fix: Bug fix
  • docs: Documentation changes
  • style: Code style changes (formatting, etc.)
  • refactor: Code refactoring
  • test: Adding or updating tests
  • chore: Maintenance tasks

2. Push Your Branch

git push origin feature/your-feature-name

3. Create a Pull Request

  1. Go to GitHub and create a pull request from your fork
  2. Fill out the PR template with:
    • Clear description of changes
    • Related issue numbers
    • Screenshots (if UI changes)
    • Testing instructions

4. PR Review Process

  • All PRs require at least one review
  • Address review feedback promptly
  • Keep PRs focused and atomic
  • Ensure all tests pass in CI

Code Style Guidelines

TypeScript

  • Use TypeScript for all new code
  • Prefer interfaces over types for object shapes
  • Use explicit return types for public APIs
  • Avoid any - use unknown if type is truly unknown
// Good
interface UserConfig {
  name: string
  email: string
}

export function validateConfig(config: unknown): UserConfig {
  // Validation logic
}

// Avoid
export function validateConfig(config: any) {
  // ...
}

Error Handling

  • Use custom error classes for specific error types
  • Include helpful error messages
  • Preserve stack traces
export class SnapshotError extends Error {
  constructor(
    message: string,
    public code: string,
    public details?: unknown
  ) {
    super(message)
    this.name = 'SnapshotError'
  }
}

// Usage
throw new SnapshotError(
  'Failed to connect to database',
  'DB_CONNECTION_ERROR',
  { host, port }
)

Async/Await

  • Prefer async/await over callbacks or raw promises
  • Handle errors properly with try/catch
  • Use Promise.all() for concurrent operations
// Good
async function captureSnapshot(config: Config): Promise<Snapshot> {
  try {
    const [schema, data] = await Promise.all([
      captureSchema(config),
      captureData(config)
    ])
    return { schema, data }
  } catch (error) {
    throw new SnapshotError('Capture failed', 'CAPTURE_ERROR', error)
  }
}

Documentation

Code Documentation

  • Add JSDoc comments for public APIs
  • Include examples in comments
  • Document complex algorithms
/**
 * Captures a snapshot of the database
 * 
 * @param config - The capture configuration
 * @returns A promise that resolves to the snapshot metadata
 * 
 * @example
 * ```typescript
 * const snapshot = await captureSnapshot({
 *   databaseUrl: 'postgresql://...',
 *   subset: { enabled: true }
 * })
 * ```
 */
export async function captureSnapshot(config: CaptureConfig): Promise<Snapshot> {
  // Implementation
}

User Documentation

  • Update relevant documentation in docs/ when adding features
  • Include code examples
  • Add to changelog for significant changes

Release Process

We use automated releases via GitHub Actions:

  1. Merge PRs to main branch
  2. CI automatically creates a release PR
  3. Review and merge the release PR
  4. CI publishes to npm and creates GitHub release

Version Bumping

Version bumps are determined by conventional commits:

  • fix: → patch version (0.0.X)
  • feat: → minor version (0.X.0)
  • BREAKING CHANGE: → major version (X.0.0)

Getting Help

Resources

Development Tips

  1. Use Debug Mode: Set DEBUG=snaplet:* for verbose logging
  2. Test Fixtures: Use existing fixtures in __fixtures__/ for testing
  3. Local CLI: Run yarn workspace @snaplet/cli dev for hot-reloading
  4. Database Issues: Ensure PostgreSQL is running and accessible

Common Issues

Yarn Installation Issues

# Clear cache and reinstall
yarn cache clean
rm -rf node_modules
yarn install

PostgreSQL Connection Issues

# Check PostgreSQL is running
pg_isready

# Check connection
psql -d postgresql://localhost:5432/snaplet_dev

Build Failures

# Clean build artifacts
yarn clean
yarn build

Thank You!

Thank you for contributing to Snaplet! Your efforts help make database development better for developers everywhere. We appreciate your time and expertise.

If you have any questions or need help, don't hesitate to reach out on Discord or create an issue.