Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
154 changes: 154 additions & 0 deletions .copilot-instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
# Copilot Instructions for Pecans

## Project Overview
Pecans is an Electron Release Server that provides download URLs and auto-update functionality for Electron applications using GitHub releases. It supports Squirrel-based auto-updates for both macOS and Windows platforms.

## Technology Stack
- **Runtime**: Node.js (>=22)
- **Language**: TypeScript 5.9+
- **Framework**: Express.js
- **Testing**: Vitest with comprehensive coverage reporting
- **Build**: TypeScript compiler with dual CJS/ESM output
- **Release**: Semantic Release with automated versioning

## Architecture & Key Components

### Core Structure
- `/src/index.ts` - Main entry point and Express app setup
- `/src/pecans.ts` - Core Pecans class handling routing and middleware
- `/src/backends/` - Backend implementations (currently GitHub)
- `/src/models/` - Data models for versions, platforms, and releases
- `/src/utils/` - Utility functions and helpers
- `/src/versions.ts` - Version parsing and channel management

### API Endpoints
The server provides several endpoint patterns:
- Download: `/download/latest`, `/download/:version`, `/download/:version/:os`
- Channels: `/download/channel/:channel`, `/download/channel/:channel/:os`
- Updates: `/update/:platform/:version` (Squirrel integration)
- Release Notes: `/notes/:version`
- Feeds: Atom/RSS for versions and channels

## Development Guidelines

### TypeScript Standards
- Use strict TypeScript configuration (check `tsconfig.*.json` files)
- Prefer explicit types over `any`
- Use interfaces for complex object structures
- Export types and interfaces for reusability
- Follow existing naming conventions (PascalCase for classes, camelCase for variables)

### Code Organization
- Keep business logic separate from Express routing
- Use the existing event-driven architecture (`pecans.on()` pattern)
- Maintain the backend abstraction layer for different data sources
- Follow the established error handling patterns

### Testing Approach
- Tests are located in `/test/` directory with clear separation:
- `/test/unit/` - Unit tests for individual components
- `/test/integration/` - Integration tests requiring external services
- **Framework**: Vitest with Node.js environment
- **Coverage**: Comprehensive coverage reporting with v8 provider
- **Setup**: Global test configuration in `/test/setup.ts`
- Mock external dependencies (GitHub API) using nock and sinon
- Test both success and error scenarios extensively
- Run tests with `npm test` (single run) or `npm run test:watch` (watch mode)
- View test UI with `npm run test:ui`
- Coverage reports generated in HTML, JSON, and text formats

### Build & Release
- Dual build system: CommonJS (`dist/cjs/`) and ESM (`dist/mjs/`)
- Use `npm run build` to compile TypeScript
- **Testing**: Vitest with coverage reporting and watch mode
- Development with `npm run dev` (nodemon with hot reload)
- Semantic release handles versioning automatically
- Follow conventional commit format for releases

## Environment Configuration
Key environment variables:
- `GITHUB_TOKEN` - GitHub API authentication
- `GITHUB_USER` / `GITHUB_REPO` - Repository configuration
- `GITHUB_REFRESH_SECRET` - Optional secret for webhook-based cache refreshing
- `PECANS_BASE_PATH` - Base path for proxied deployments
- `CACHE_MAX_AGE` - Cache duration in seconds (default: 7200 = 2 hours)
- `PORT` - Server port (default: 5000)

## Common Patterns

### Backend Implementation
When working with backends, follow the abstract Backend pattern with built-in caching:
```typescript
// Extend Backend class which includes stale-while-revalidate caching
class MyBackend extends Backend {
async fetchReleases(): Promise<PecansReleases> {
// Implementation - this is cached automatically
}
}
```

The Backend class provides automatic caching with stale-while-revalidate strategy:
- Cache duration configurable via `cacheMaxAge` option (default: 2 hours)
- Serves stale data while refreshing in background when cache expires
- Includes webhook middleware for manual cache refreshing

### Error Handling
Use the established Express error handling middleware:
```typescript
// Return structured errors
res.format({
'text/plain': () => res.status(code).send(msg),
'text/html': () => res.status(code).send(msg),
'application/json': () => res.status(code).send({error: msg, code})
});
```

### Event-Driven Downloads
Utilize the event system for logging and monitoring:
```typescript
pecans.on('beforeDownload', (download) => {
// Log or process download
});
```

## File Naming & Structure
- TypeScript files use `.ts` extension
- Test files use `.spec.ts` or `.test.ts` extensions
- Test files mirror source structure in `/test/unit/` and `/test/integration/`
- Configuration files are in root directory
- Built output goes to `/dist/cjs/` and `/dist/mjs/`
- Test configuration in `vitest.config.ts` with coverage setup

## Dependencies Management
- Core runtime dependencies in `dependencies`
- Development tools in `devDependencies`
- Keep dependencies minimal and up-to-date
- Use exact versions for better reproducibility

## Performance Considerations
- **Built-in caching**: Backend class implements stale-while-revalidate caching
- Cache GitHub API responses with configurable TTL (default: 2 hours)
- Handle rate limiting for GitHub API calls gracefully
- Optimize file serving for large Electron app downloads
- Use appropriate Express middleware for compression
- Manual cache refresh via webhook endpoints for immediate updates

## Security Guidelines
- Validate all user inputs, especially version strings
- Sanitize file paths to prevent directory traversal
- Use HTTPS for production deployments
- Regularly update dependencies for security patches

## Deployment Notes
- Designed for containerized deployment (see Dockerfile)
- Supports Cloud Foundry deployment (see .cfignore)
- Can be deployed as Express middleware in larger applications
- Documentation available at https://pecans.darrelopry.com/

## Debugging & Troubleshooting
- Use `npm run dev` for development with nodemon
- Check GitHub API rate limits and authentication
- Verify release asset availability and naming conventions
- Test Squirrel update endpoints with appropriate user agents

When making changes to this project, always consider the impact on existing Electron app deployments and maintain backward compatibility with the API endpoints.
2 changes: 1 addition & 1 deletion .github/workflows/cicd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v3
with:
node-version: 18
node-version: 22
cache: "npm"
- run: npm ci
# - run: npm run lint
Expand Down
9 changes: 0 additions & 9 deletions .mocharc.js

This file was deleted.

14 changes: 14 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,17 @@
# [2.0.0-next.17](https://github.com/dopry/pecans/compare/v2.0.0-next.16...v2.0.0-next.17) (2025-09-20)


### Bug Fixes

* tests switch to vitest and expand test coverage. ([#22](https://github.com/dopry/pecans/issues/22)) ([bbd4ccb](https://github.com/dopry/pecans/commit/bbd4ccbe70601e96c77732244b8537dac1cb6c49))

# [2.0.0-next.16](https://github.com/dopry/pecans/compare/v2.0.0-next.15...v2.0.0-next.16) (2025-09-19)


### Features

* cache releases in abstract Backend class with stale-while-revalidate strategy ([#19](https://github.com/dopry/pecans/issues/19)) ([173e74c](https://github.com/dopry/pecans/commit/173e74c043dbee2b087d125d0804dfda171e4960))

# [2.0.0-next.15](https://github.com/dopry/pecans/compare/v2.0.0-next.14...v2.0.0-next.15) (2025-05-09)


Expand Down
Loading