other
This commit is contained in:
+319
@@ -0,0 +1,319 @@
|
||||
<div align="center">
|
||||
<img src="./assets/logo.png" alt="LinkForty Logo" width="150"/>
|
||||
|
||||
# Contributing to @linkforty/core
|
||||
|
||||
Thank you for your interest in contributing to LinkForty Core! This document provides guidelines and instructions for contributing.
|
||||
</div>
|
||||
|
||||
## Code of Conduct
|
||||
|
||||
We are committed to providing a welcoming and inclusive environment. Please be respectful and considerate in all interactions.
|
||||
|
||||
## Getting Started
|
||||
|
||||
### Prerequisites
|
||||
|
||||
- Node.js 18+ and npm
|
||||
- PostgreSQL 14+
|
||||
- Redis 6+ (optional but recommended)
|
||||
- Git
|
||||
|
||||
### Development Setup
|
||||
|
||||
1. **Fork and clone the repository**
|
||||
|
||||
```bash
|
||||
git clone https://github.com/YOUR_USERNAME/core.git
|
||||
cd core
|
||||
```
|
||||
|
||||
2. **Install dependencies**
|
||||
|
||||
```bash
|
||||
npm install
|
||||
```
|
||||
|
||||
3. **Set up environment variables**
|
||||
|
||||
```bash
|
||||
cp .env.example .env
|
||||
# Edit .env with your local database credentials
|
||||
```
|
||||
|
||||
For self-hosted deployments behind a reverse proxy, set `TRUST_PROXY=1` (or the number of proxy hops) so client IP is taken from `X-Forwarded-For`. Client-provided `ipAddress` in the SDK install body is not used as the trusted IP (debug metadata only).
|
||||
|
||||
4. **Start PostgreSQL and Redis**
|
||||
|
||||
```bash
|
||||
# Using Docker
|
||||
docker compose -f examples/docker-compose.yml up -d postgres redis
|
||||
```
|
||||
|
||||
5. **Run database migrations**
|
||||
|
||||
```bash
|
||||
npm run migrate
|
||||
```
|
||||
|
||||
6. **Start development server**
|
||||
|
||||
```bash
|
||||
npm run dev
|
||||
```
|
||||
|
||||
The server will be running at `http://localhost:3000`.
|
||||
|
||||
## Development Workflow
|
||||
|
||||
### Branch Naming
|
||||
|
||||
- `feature/` - New features (e.g., `feature/webhook-support`)
|
||||
- `fix/` - Bug fixes (e.g., `fix/redirect-caching`)
|
||||
- `docs/` - Documentation updates (e.g., `docs/api-reference`)
|
||||
- `refactor/` - Code refactoring (e.g., `refactor/database-connection`)
|
||||
|
||||
### Commit Messages
|
||||
|
||||
Follow conventional commits format:
|
||||
|
||||
```
|
||||
type(scope): description
|
||||
|
||||
[optional body]
|
||||
|
||||
[optional footer]
|
||||
```
|
||||
|
||||
**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
|
||||
|
||||
**Examples:**
|
||||
```
|
||||
feat(analytics): add webhook support for click events
|
||||
fix(redirect): cache invalidation on link update
|
||||
docs(readme): update API examples
|
||||
```
|
||||
|
||||
### Making Changes
|
||||
|
||||
1. **Create a new branch**
|
||||
|
||||
```bash
|
||||
git checkout -b feature/your-feature-name
|
||||
```
|
||||
|
||||
2. **Make your changes**
|
||||
|
||||
- Write clean, readable code
|
||||
- Follow existing code style and patterns
|
||||
- Add comments for complex logic
|
||||
- Update documentation if needed
|
||||
|
||||
3. **Test your changes**
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
npm run test # When tests are available
|
||||
```
|
||||
|
||||
4. **Commit your changes**
|
||||
|
||||
```bash
|
||||
git add .
|
||||
git commit -m "feat(scope): description"
|
||||
```
|
||||
|
||||
5. **Push to your fork**
|
||||
|
||||
```bash
|
||||
git push origin feature/your-feature-name
|
||||
```
|
||||
|
||||
6. **Create a Pull Request**
|
||||
|
||||
- Go to the original repository on GitHub
|
||||
- Click "New Pull Request"
|
||||
- Select your fork and branch
|
||||
- Fill out the PR template with details
|
||||
|
||||
## Code Style Guidelines
|
||||
|
||||
### TypeScript
|
||||
|
||||
- Use TypeScript strict mode
|
||||
- Define explicit types for function parameters and return values
|
||||
- Use interfaces for object shapes
|
||||
- Avoid `any` types when possible
|
||||
|
||||
**Example:**
|
||||
```typescript
|
||||
interface CreateLinkParams {
|
||||
userId: string;
|
||||
originalUrl: string;
|
||||
title?: string;
|
||||
}
|
||||
|
||||
async function createLink(params: CreateLinkParams): Promise<Link> {
|
||||
// Implementation
|
||||
}
|
||||
```
|
||||
|
||||
### Naming Conventions
|
||||
|
||||
- **Files**: kebab-case (e.g., `redirect-handler.ts`)
|
||||
- **Classes**: PascalCase (e.g., `LinkManager`)
|
||||
- **Functions**: camelCase (e.g., `createShortLink`)
|
||||
- **Constants**: UPPER_SNAKE_CASE (e.g., `MAX_RETRIES`)
|
||||
- **Interfaces**: PascalCase (e.g., `DatabaseConfig`)
|
||||
|
||||
### File Organization
|
||||
|
||||
```
|
||||
src/
|
||||
├── index.ts # Main entry point
|
||||
├── lib/ # Shared utilities
|
||||
│ ├── database.ts # Database connection
|
||||
│ ├── utils.ts # Helper functions
|
||||
│ └── auth.ts # Authentication
|
||||
├── routes/ # API routes
|
||||
│ ├── links.ts
|
||||
│ ├── analytics.ts
|
||||
│ └── redirect.ts
|
||||
└── types/ # TypeScript types
|
||||
└── index.ts
|
||||
```
|
||||
|
||||
### Error Handling
|
||||
|
||||
- Use try-catch blocks for async operations
|
||||
- Provide meaningful error messages
|
||||
- Log errors appropriately
|
||||
|
||||
**Example:**
|
||||
```typescript
|
||||
try {
|
||||
const result = await db.query('SELECT * FROM links WHERE id = $1', [id]);
|
||||
if (result.rows.length === 0) {
|
||||
throw new Error('Link not found');
|
||||
}
|
||||
return result.rows[0];
|
||||
} catch (error) {
|
||||
fastify.log.error(`Error fetching link: ${error}`);
|
||||
throw error;
|
||||
}
|
||||
```
|
||||
|
||||
## Testing
|
||||
|
||||
### Running Tests
|
||||
|
||||
```bash
|
||||
npm run test
|
||||
npm run test:watch # Watch mode
|
||||
npm run test:coverage # Coverage report
|
||||
```
|
||||
|
||||
### Writing Tests
|
||||
|
||||
- Write tests for all new features
|
||||
- Ensure existing tests pass
|
||||
- Aim for >80% code coverage
|
||||
|
||||
**Example:**
|
||||
```typescript
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { detectDevice } from '../lib/utils';
|
||||
|
||||
describe('detectDevice', () => {
|
||||
it('should detect iOS devices', () => {
|
||||
const ua = 'Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X)';
|
||||
expect(detectDevice(ua)).toBe('ios');
|
||||
});
|
||||
|
||||
it('should detect Android devices', () => {
|
||||
const ua = 'Mozilla/5.0 (Linux; Android 11; Pixel 5)';
|
||||
expect(detectDevice(ua)).toBe('android');
|
||||
});
|
||||
|
||||
it('should default to web for unknown devices', () => {
|
||||
const ua = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)';
|
||||
expect(detectDevice(ua)).toBe('web');
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
## Pull Request Guidelines
|
||||
|
||||
### Before Submitting
|
||||
|
||||
- [ ] Code builds successfully (`npm run build`)
|
||||
- [ ] All tests pass (`npm run test`)
|
||||
- [ ] Documentation is updated
|
||||
- [ ] No linting errors
|
||||
- [ ] Commit messages follow conventional format
|
||||
- [ ] Branch is up to date with main
|
||||
|
||||
### PR Description Template
|
||||
|
||||
```markdown
|
||||
## Description
|
||||
Brief description of changes
|
||||
|
||||
## Type of Change
|
||||
- [ ] Bug fix
|
||||
- [ ] New feature
|
||||
- [ ] Breaking change
|
||||
- [ ] Documentation update
|
||||
|
||||
## Changes Made
|
||||
- List key changes
|
||||
- Include relevant details
|
||||
|
||||
## Testing
|
||||
Describe how you tested the changes
|
||||
|
||||
## Screenshots (if applicable)
|
||||
Add screenshots for UI changes
|
||||
|
||||
## Related Issues
|
||||
Closes #123
|
||||
```
|
||||
|
||||
## Documentation
|
||||
|
||||
- Update README.md for new features
|
||||
- Add JSDoc comments for exported functions
|
||||
- Update API documentation
|
||||
- Include examples for new functionality
|
||||
|
||||
## Questions or Need Help?
|
||||
|
||||
- **GitHub Discussions**: For general questions
|
||||
- **GitHub Issues**: For bug reports and feature requests
|
||||
- **Discord**: [Join our community](https://discord.gg/linkforty) (if available)
|
||||
|
||||
## Contributor License Agreement (CLA)
|
||||
|
||||
All contributors must sign our [Contributor License Agreement](CLA.md) before their first pull request can be merged. When you open a PR, the CLA Assistant bot will post a link to sign via GitHub OAuth — it's a one-time step.
|
||||
|
||||
The CLA allows us to use your contributions in both the open-source Core project (AGPL-3.0) and the commercial LinkForty Cloud product. You retain full ownership of your contributions.
|
||||
|
||||
## License
|
||||
|
||||
By contributing, you agree that your contributions will be licensed under the AGPL-3.0 License, and you agree to the terms of the [CLA](CLA.md).
|
||||
|
||||
## Recognition
|
||||
|
||||
Contributors will be recognized in:
|
||||
- README.md contributors section
|
||||
- CHANGELOG.md for significant contributions
|
||||
- GitHub releases notes
|
||||
|
||||
Thank you for contributing to LinkForty Core! 🎉
|
||||
Reference in New Issue
Block a user