Skip to content
Merged
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
19 changes: 19 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
root = true

[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true

[*.{js,ts,json,yml,yaml}]
indent_style = space
indent_size = 2

[*.md]
trim_trailing_whitespace = false
max_line_length = off

[{package.json,pnpm-lock.yaml}]
indent_style = space
indent_size = 2
125 changes: 125 additions & 0 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
# Copilot Instructions for Outport Project

## Project Overview

This is a TypeScript project using modern best practices with ES modules, pnpm package management, and comprehensive tooling.

## Technology Stack

- **TypeScript**: Strict mode enabled with modern ES2022+ features
- **Package Manager**: pnpm (required)
- **Build Tool**: TypeScript Compiler (tsc)
- **Testing**: Vitest with coverage support
- **Linting**: ESLint v9+ with flat config format
- **Formatting**: Prettier
- **CI/CD**: GitHub Actions

## Code Standards

### TypeScript

- Always use ES modules (`import`/`export`)
- Enable strict type checking
- Prefer type inference but add explicit return types for exported functions
- Use `type` imports when importing only types
- Avoid `any` - use `unknown` or proper types
- Use optional chaining and nullish coalescing operators

### File Organization

- Source files in `src/`
- Test files alongside source with `.test.ts` extension
- One export per file when possible
- Barrel exports in `index.ts` files

### Testing

- Write tests for all new functionality
- Use descriptive test names
- Follow AAA pattern: Arrange, Act, Assert
- Aim for 80%+ code coverage
- Use Vitest's global APIs (describe, it, expect)

### Naming Conventions

- Files: kebab-case (e.g., `user-service.ts`)
- Classes/Interfaces/Types: PascalCase
- Functions/Variables: camelCase
- Constants: UPPER_SNAKE_CASE for true constants
- Private class members: prefix with `#` or `_`

### Code Style

- Use single quotes for strings
- Semicolons required
- Trailing commas in ES5-compatible contexts
- 100 character line length
- 2 space indentation

## Development Workflow

### Before Committing

1. Run `pnpm run typecheck` to verify types
2. Run `pnpm run lint` to check for linting errors
3. Run `pnpm run format:check` to verify formatting
4. Run `pnpm run test` to ensure tests pass
5. Or use `pnpm run ci` to run all checks

### Scripts

- `pnpm run build` - Compile TypeScript
- `pnpm run test` - Run tests once
- `pnpm run test:watch` - Run tests in watch mode
- `pnpm run test:coverage` - Generate coverage report
- `pnpm run lint` - Check for linting errors
- `pnpm run lint:fix` - Fix auto-fixable linting errors
- `pnpm run format` - Format all files
- `pnpm run format:check` - Check formatting
- `pnpm run typecheck` - Type check without emitting
- `pnpm run ci` - Run all CI checks locally

## Best Practices

### Error Handling

- Use custom error classes for domain errors
- Always type-guard error objects in catch blocks
- Prefer Result types over throwing for expected errors

### Async Code

- Use async/await over Promises.then()
- Handle promise rejections properly
- Avoid mixing callbacks and promises

### Dependencies

- Keep dependencies minimal
- Prefer packages with TypeScript support
- Update dependencies regularly
- Use exact versions in package.json when stability is critical

### Documentation

- Add JSDoc comments for public APIs
- Keep README.md up to date
- Document complex algorithms inline
- Update this file when project conventions change

## CI/CD

- All PRs must pass CI checks
- CI runs on Node.js 18.x, 20.x, and 22.x
- Must pass: typecheck, lint, format check, build, and tests
- Coverage reports uploaded for Node.js 22.x

## Contributing

When adding new features:

1. Create a feature branch
2. Write tests first (TDD)
3. Implement the feature
4. Ensure all CI checks pass locally
5. Create a pull request with clear description
31 changes: 31 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
version: 2
updates:
- package-ecosystem: 'npm'
directory: '/'
schedule:
interval: 'weekly'
day: 'monday'
time: '09:00'
open-pull-requests-limit: 10
groups:
typescript-eslint:
patterns:
- '@typescript-eslint/*'
vitest:
patterns:
- 'vitest'
- '@vitest/*'
development-dependencies:
dependency-type: 'development'
update-types:
- 'minor'
- 'patch'
commit-message:
prefix: 'chore'
include: 'scope'
labels:
- 'dependencies'
reviewers:
- 'scottluskcis'
assignees:
- 'scottluskcis'
73 changes: 73 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
name: CI

on:
push:
branches: [main]
pull_request:
branches: [main]

jobs:
ci:
runs-on: ubuntu-latest

strategy:
matrix:
node-version: [18.x, 20.x, 22.x]

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Read .nvmrc
id: nvmrc
run: echo "NODE_VERSION=$(cat .nvmrc)" >> $GITHUB_OUTPUT

- name: Install pnpm
uses: pnpm/action-setup@v4

- name: Setup Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
cache: 'pnpm'

- name: Verify Node.js version matches .nvmrc for v22
if: matrix.node-version == '22.x'
run: |
if [[ "$(node --version)" != v${{ steps.nvmrc.outputs.NODE_VERSION }}.* ]]; then
echo "Warning: Node version doesn't match .nvmrc"
fi

- name: Install dependencies
run: pnpm install --frozen-lockfile

- name: Type check
run: pnpm run typecheck

- name: Lint
run: pnpm run lint

- name: Format check
run: pnpm run format:check

- name: Build
run: pnpm run build

- name: Test
run: pnpm run test
if: matrix.node-version != '22.x'

- name: Test coverage
run: pnpm run test:coverage
if: matrix.node-version == '22.x'

- name: Upload coverage reports
uses: codecov/codecov-action@v4
if: matrix.node-version == '22.x'
with:
files: ./coverage/coverage-final.json
flags: unittests
name: codecov-umbrella
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
continue-on-error: true
1 change: 1 addition & 0 deletions .husky/pre-commit
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pnpm lint-staged
39 changes: 39 additions & 0 deletions .npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Source files
src/
*.test.ts
*.spec.ts

# Config files
tsconfig.json
vitest.config.ts
eslint.config.js
.prettierrc
.prettierignore
.editorconfig
.nvmrc

# CI/CD
.github/
.gitignore
.husky/

# Development
coverage/
node_modules/
.vscode/
.idea/

# Logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*

# Misc
.DS_Store
.env
.env.local
.env.*.local

# Documentation
1 change: 1 addition & 0 deletions .nvmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
22
12 changes: 12 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Dependencies
node_modules
pnpm-lock.yaml

# Build output
dist
coverage

# Environment files
.env
.env.local
.env.*.local
9 changes: 9 additions & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"semi": true,
"trailingComma": "es5",
"singleQuote": true,
"printWidth": 100,
"tabWidth": 2,
"useTabs": false,
"endOfLine": "lf"
}
9 changes: 9 additions & 0 deletions .vscode/extensions.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"recommendations": [
"esbenp.prettier-vscode",
"dbaeumer.vscode-eslint",
"vitest.explorer",
"github.copilot",
"github.copilot-chat"
]
}
30 changes: 30 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{
"editor.formatOnSave": true,
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit"
},
"typescript.tsdk": "node_modules/typescript/lib",
"typescript.enablePromptUseWorkspaceTsdk": true,
"files.associations": {
"*.css": "css",
"*.json": "jsonc"
},
"files.exclude": {
"**/node_modules": true,
"**/dist": true
},
"search.exclude": {
"**/node_modules": true,
"**/dist": true,
"**/coverage": true,
"pnpm-lock.yaml": true
},
"editor.rulers": [100],
"editor.tabSize": 2,
"files.insertFinalNewline": true,
"files.trimTrailingWhitespace": true,
"[markdown]": {
"files.trimTrailingWhitespace": false
}
}
Loading