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
22 changes: 14 additions & 8 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ name: CI

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

jobs:
test:
Expand All @@ -17,13 +17,19 @@ jobs:
version: 9
- uses: actions/setup-node@v4
with:
node-version: "22"
cache: "pnpm"
node-version: '22'
cache: 'pnpm'
- run: pnpm install --frozen-lockfile
- run: pnpm run type-check
- run: pnpm run lint
- run: pnpm run test:coverage
- run: pnpm run build
- name: Check code formatting
run: pnpm run format:check
- name: Type check
run: pnpm run type-check
- name: Lint
run: pnpm run lint
- name: Build
run: pnpm run build
- name: Run tests with coverage
run: pnpm run test:coverage
- name: Verify Changelog on Version Change
if: github.event_name == 'pull_request'
run: |
Expand Down
8 changes: 4 additions & 4 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ on:
branches:
- main
paths-ignore:
- "**.md"
- ".gitignore"
- '**.md'
- '.gitignore'

permissions:
contents: write # to be able to publish a GitHub release
Expand All @@ -31,8 +31,8 @@ jobs:

- uses: actions/setup-node@v4
with:
node-version: "22"
cache: "pnpm"
node-version: '22'
cache: 'pnpm'

- run: pnpm install --frozen-lockfile

Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,5 @@ __snapshots__

# Turborepo
.turbo

/transactions
8 changes: 8 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
node_modules
.next
dist
coverage
*.db
pnpm-lock.yaml
package-lock.json
yarn.lock
7 changes: 7 additions & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"semi": true,
"singleQuote": true,
"tabWidth": 2,
"trailingComma": "es5",
"printWidth": 80
}
65 changes: 65 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,71 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [0.1.0] - 2026-01-11

### Added

- **Multi-Resolver Ticker Enrichment**: Implemented stacked resolver architecture allowing multiple ticker resolution strategies with fallback logic
- **Specialized Yahoo Finance Resolvers**:
- `YahooISINResolver`: High-accuracy ISIN-based ticker resolution
- `YahooNameResolver`: Advanced name-based search with Alphabet Inc Class A/C handling
- `YahooFullResolver`: Combined resolver using both strategies
- **CLI Enhancements**:
- `--yahoo-isin`: Enable ISIN-only resolution
- `--yahoo-name`: Enable name-only resolution
- `--no-yahoo`: Disable automatic Yahoo Finance resolution
- Yahoo Finance resolution now enabled by default
- **Coding Guidelines**: Added `CODING_GUIDELINES.md` with strict terminology standards for `ticker`, `name`, and `symbol`
- **Comprehensive Test Suite**:
- Added 50+ new tests across 5 new test files
- `tests/cache.test.ts`: LocalFileTickerCache tests
- `tests/enricher_advanced.test.ts`: Multi-resolver stacking and edge cases
- `tests/file_resolver_extended.test.ts`: All file format variations
- `tests/resolvers/yahoo.test.ts`: Complete Yahoo resolver coverage
- Achieved 95%+ code coverage on resolvers and enrichment logic
- **CI/CD Enhancements**:
- Added Prettier formatting check to CI pipeline
- Reorganized CI steps for fail-fast approach (format → type-check → lint → build → test)
- All quality gates now enforced automatically on every PR and push

### Changed

- **BREAKING**: Renamed `symbol` field to `name` in `ParsedTransaction` type to clearly distinguish company names from ticker symbols
- **BREAKING**: `enrichTransactions` now accepts `resolvers: TickerResolver[]` (array) instead of `resolver: TickerResolver` (singular)
- Refactored `TickerResolver` interface to require `name` property for better logging and identification
- Updated all parsers (Avanza, Nordnet) to use `name` field instead of `symbol`
- Enhanced Yahoo Finance integration with proper TypeScript types, eliminating all `any` usages
- Improved currency enrichment with fallback chain: `quote()` → `quoteSummary()`
- Updated documentation with resolver stacking examples and terminology reference

### Fixed

- Fixed documentation example showing incorrect `resolver` usage (now correctly uses `resolvers` array)
- Removed backward compatibility for deprecated `symbol` field in `FileTickerResolver`
- Fixed all ESLint warnings by adding proper TypeScript types throughout codebase

### Removed

- Removed `eslint.config copy.mjs` (leftover file with Next.js-specific config)
- Removed backward compatibility for `symbol` field in ticker mapping files (JSON/CSV)

### Documentation

- Updated README with comprehensive examples for:
- Multi-resolver stacking
- All supported ticker mapping formats (JSON object/array, CSV)
- CLI usage with new resolver options
- Added terminology standards section linking to `CODING_GUIDELINES.md`
- Clarified distinction between `name` (company name) and `ticker` (stock symbol)

### Technical Improvements

- All 84 tests passing with zero linting warnings
- 100% function coverage across all modules
- Type-safe Yahoo Finance API integration
- Proper error handling in all resolvers
- Exchange filtering (NMS, NYQ, NGM) for higher quality ticker matches

## [0.0.1] - 2024-01-11

### Added
Expand Down
60 changes: 60 additions & 0 deletions CODING_GUIDELINES.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# Coding Guidelines

## Terminology Standards

### Ticker vs Name vs Symbol

To maintain consistency across the codebase, always adhere to these naming conventions:

- **`ticker`**: Use this for stock ticker symbols (e.g., "AAPL", "META", "GOOGL")
- Variable names: `ticker`, `resolvedTicker`, `stockTicker`
- Field names: `ticker`
- Function parameters: `ticker`

- **`name`**: Use this for company/security names (e.g., "Apple Inc", "Meta Platforms A")
- Variable names: `name`, `companyName`, `securityName`
- Field names: `name`
- Function parameters: `name`

- **`symbol`**: **DEPRECATED** - Do not use this term for company names
- If you encounter `symbol` in legacy code or external APIs, treat it as a `ticker`
- When refactoring, always replace `symbol` with either `ticker` or `name` based on context
- Exception: External API responses where `symbol` is the field name (cast/map to `ticker`)

### Examples

✅ **Correct:**

```typescript
interface Transaction {
name: string; // "Apple Inc"
ticker: string; // "AAPL"
isin: string; // "US0378331005"
}

function resolveTicker(isin: string, name: string): string {
// ...
}
```

❌ **Incorrect:**

```typescript
interface Transaction {
symbol: string; // Ambiguous - is this a ticker or name?
}

function resolveSymbol(isin: string, symbol: string): string {
// ...
}
```

### Rationale

The term "symbol" is ambiguous in financial contexts. It can refer to:

- A ticker symbol (AAPL)
- A company name (Apple Inc)
- A trading symbol on an exchange

By strictly using `ticker` for stock symbols and `name` for company names, we eliminate confusion and make the codebase more maintainable.
1 change: 0 additions & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ We love support for new brokers! To add one:
Create a new file in `src/parsers/` (e.g., `src/parsers/mybroker.ts`) implementing the `BrokerParser` interface.

2. ** Implement Logic**:

- `name`: Unique name of the broker.
- `canParse(row)`: A function returning `true` if this row belongs to this broker. Be specific (check unique headers).
- `parse(row)`: Map the CSV row to the `ParsedTransaction` interface.
Expand Down
Loading
Loading