sequaljs
Version:
JavaScript/TypeScript library for parsing and manipulating ProForma peptide sequence notation
417 lines (329 loc) • 10.3 kB
Markdown
# ProForma Implementation Comparison
## Three Implementations Overview
### 1. **Go Implementation** (sequal-go)
**Location**: `/mnt/d/GoLandProjects/sequal`
**Status**: ✅ **ProForma 2.1 Complete**
**Language**: Go
**Version**: 2.1.0
**Features**:
- All 6 ProForma 2.1 features implemented
- 37+ new tests for 2.1 features
- Zero regressions
- Comprehensive integration tests
- Updated documentation
**Key Strengths**:
- Strong typing with Go structs
- Pointer types for optional fields
- Efficient map-based modification storage
- Getter methods for encapsulation
---
### 2. **TypeScript Implementation** (sequaljs)
**Location**: `/mnt/d/WebstormProjects/sequaljs`
**Status**: ⏳ **ProForma 2.0 Complete, 2.1 Planned**
**Language**: TypeScript
**Version**: 1.0.7
**Current Features**:
- Complete ProForma 2.0 support
- 37+ test cases covering 2.0 spec
- Well-architected modification system
- Production-ready
**Upgrade Status**:
- Upgrade plan documented in `PROFORMA_2.1_UPGRADE_PLAN.md`
- Reference implementation available (Go)
- Estimated 12-24 hours for complete upgrade
**Key Strengths**:
- Clean TypeScript types
- Map-based modification indexing
- Extensive JSDoc documentation
- Jest test framework
- Browser-compatible
---
### 3. **Python Implementation** (assumed)
**Status**: Unknown (not analyzed in this session)
**Language**: Python
---
## Architecture Comparison
### Data Structure Mapping
| Concept | Go | TypeScript |
|---------|-----|-----------|
| **Sequence** | `type Sequence struct` | `class Sequence<T>` |
| **Modification** | `type Modification struct` | `class Modification extends BaseBlock` |
| **Global Mod** | `type GlobalModification struct` | `class GlobalModification extends Modification` |
| **Amino Acid** | `type AminoAcid struct` | `class AminoAcid extends BaseBlock` |
| **Mod Value** | `type ModificationValue struct` | `class ModificationValue` |
| **Pipe Value** | `type PipeValue struct` | `class PipeValue` |
### Parser Approach
| Aspect | Go | TypeScript |
|--------|-----|-----------|
| **Entry Point** | `FromProforma(str)` | `Sequence.fromProforma(str)` |
| **Parser Class** | `ProFormaParser` struct | `ProFormaParser` static class |
| **Bracket Tracking** | Counter-based | Counter-based |
| **Regex Usage** | Heavy use of `regexp` | Heavy use of RegExp |
| **Error Handling** | `(Sequence, error)` return | Throws exceptions |
### Modification Storage
| Language | Approach |
|----------|----------|
| **Go** | `map[int][]*Modification` |
| **TypeScript** | `Map<number, Modification[]>` |
**Special Positions**:
- `-1`: N-terminal
- `-2`: C-terminal
- `-3`: Labile
- `-4`: Unknown position
---
## ProForma 2.1 Feature Status
### Feature Matrix
| Feature | Go | TypeScript | Priority |
|---------|-----|-----------|----------|
| **Charged Formulas** (11.1) | ✅ Implemented | ⏳ Planned | High |
| **Placement Controls** (11.2) | ✅ Implemented | ⏳ Planned | High |
| **Named Entities** (11.3) | ✅ Implemented | ⏳ Planned | High |
| **Custom Monosaccharides** (11.4) | ✅ Implemented | ⏳ Planned | Medium |
| **Terminal Global Mods** (11.5) | ✅ Implemented | ⏳ Planned | Medium |
| **Ion Notation** (11.6) | ✅ Implemented | ⏳ Planned | High |
---
## Code Style Differences
### Field Naming Conventions
**Go**:
```go
type Modification struct {
positionConstraint []string
limitPerPosition *int
colocalizeKnown bool
isIonType bool
}
```
**TypeScript**:
```typescript
class Modification {
positionConstraint?: string[];
limitPerPosition?: number;
colocalizeKnown: boolean = false;
isIonType: boolean = false;
}
```
### Optional Fields
**Go**: Uses pointers (`*int`, `*string`) for optionality
```go
limitPerPosition *int
```
**TypeScript**: Uses optional types (`?`) and union with undefined
```typescript
limitPerPosition?: number
```
### Getter Methods
**Go**: Explicit getter methods
```go
func (m *Modification) GetPositionConstraint() []string {
return m.positionConstraint
}
```
**TypeScript**: Explicit getter methods (similar to Go)
```typescript
getPositionConstraint(): string[] | undefined {
return this.positionConstraint;
}
```
---
## Testing Frameworks
### Go
- **Framework**: Standard `testing` package
- **Pattern**: Table-driven tests
- **Run**: `go test ./sequal`
- **Files**: `*_test.go`
**Example**:
```go
func TestPlacementControls_PositionConstraint(t *testing.T) {
tests := []struct {
name string
proformaString string
expectedPos []string
shouldParse bool
}{
{
name: "Single position constraint",
proformaString: "<[Oxidation|Position:M]@M>PEPTIDE",
expectedPos: []string{"M"},
shouldParse: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// Test implementation
})
}
}
```
### TypeScript
- **Framework**: Jest
- **Pattern**: Describe/test blocks
- **Run**: `npm test`
- **Files**: `*.test.ts`
**Example**:
```typescript
describe('Placement Controls', () => {
test('should parse position constraint', () => {
const seq = Sequence.fromProforma('<[Oxidation|Position:M]@M>PEPTIDE');
const globalMod = seq.getGlobalMods()[0];
expect(globalMod.getPositionConstraint()).toEqual(['M']);
});
});
```
---
## Key Implementation Differences
### 1. **Type System**
**Go**:
- Static typing with structs
- Explicit type declarations
- Interface-based polymorphism
- Nil for missing values
**TypeScript**:
- Static typing with classes
- Type inference
- Class-based inheritance
- undefined/null for missing values
### 2. **Error Handling**
**Go**:
```go
seq, err := FromProforma("PEPTIDE")
if err != nil {
return err
}
```
**TypeScript**:
```typescript
try {
const seq = Sequence.fromProforma("PEPTIDE");
} catch (error) {
console.error(error);
}
```
### 3. **Collections**
**Go**:
- Built-in `map[K]V`
- Slices `[]T`
- No generics in older versions
**TypeScript**:
- `Map<K, V>` and `Set<T>`
- Arrays `T[]`
- Generic support
### 4. **Immutability**
**Go**:
- Explicit copying required
- Pointers for mutation
- Value vs reference semantics
**TypeScript**:
- Objects mutable by default
- Spread operator for shallow copy
- `readonly` keyword for immutability
---
## Migration Path: Go → TypeScript
### Step-by-Step Translation
1. **Struct → Class**
```go
type Modification struct { ... }
```
becomes
```typescript
class Modification { ... }
```
2. **Pointer Fields → Optional**
```go
limitPerPosition *int
```
becomes
```typescript
limitPerPosition?: number
```
3. **Constructor Parameters → Object**
```go
func NewModification(val string, pos *int, ...) *Modification
```
becomes
```typescript
constructor(params: ModificationParams)
```
4. **Error Returns → Exceptions**
```go
return nil, fmt.Errorf("error")
```
becomes
```typescript
throw new Error("error");
```
5. **Getter Methods → Methods**
```go
func (m *Modification) GetValue() string
```
becomes
```typescript
getValue(): string
```
---
## Performance Characteristics
### Go
- **Pros**: Compiled, fast, efficient memory usage
- **Cons**: Larger binary size, slower development
### TypeScript
- **Pros**: Fast development, browser-compatible, npm ecosystem
- **Cons**: Runtime overhead, requires transpilation
### Use Cases
| Use Case | Recommended |
|----------|-------------|
| **Backend API** | Go |
| **Web Application** | TypeScript |
| **CLI Tool** | Go |
| **Browser Library** | TypeScript |
| **Data Processing** | Go |
| **Frontend Integration** | TypeScript |
---
## Upgrade Complexity Estimate
### TypeScript → ProForma 2.1
**Complexity by Phase**:
| Phase | Difficulty | Time | Reason |
|-------|-----------|------|---------|
| Charged Formulas | Medium | 2h | PipeValue modification |
| Named Entities | Low | 3h | Similar to existing patterns |
| Custom Monosaccharides | Low | 2h | Built on named entities |
| Terminal Global | Medium | 2h | Parser logic changes |
| Placement Controls | High | 4h | Complex tag parsing |
| Ion Notation | Low | 2h | Simple boolean flag |
| Integration Tests | Medium | 3h | Comprehensive coverage |
| Documentation | Low | 2h | README updates |
**Total**: 20 hours estimated
---
## Recommended Upgrade Order
### For TypeScript Implementation
1. ✅ **Review Go implementation** (Reference)
2. ✅ **Create upgrade plan** (This document)
3. ⏳ **Phase 1: Charged Formulas** (Foundation)
4. ⏳ **Phase 6: Ion Notation** (Easy win)
5. ⏳ **Phase 5: Placement Controls** (Core feature)
6. ⏳ **Phase 2: Named Entities** (Moderate)
7. ⏳ **Phase 3: Custom Monosaccharides** (Builds on #2)
8. ⏳ **Phase 4: Terminal Global** (Edge case)
9. ⏳ **Integration Tests** (Comprehensive)
10. ⏳ **Documentation Updates** (Final)
---
## Success Metrics
### Go Implementation (Achieved)
- ✅ All 6 features implemented
- ✅ 37+ new tests
- ✅ Zero regressions
- ✅ 100% test pass rate
- ✅ Documentation updated
### TypeScript Target (Goals)
- ⏳ All 6 features implemented
- ⏳ 40+ new tests (including integration)
- ⏳ Zero regressions
- ⏳ 100% test pass rate
- ⏳ README updated
- ⏳ Version 2.1.0 published
---
## Conclusion
The Go implementation provides a solid reference for the TypeScript upgrade. The architecture is similar enough that patterns can be directly translated, but different enough that language-specific idioms should be respected.
**Key Takeaway**: The TypeScript implementation is well-positioned for the 2.1 upgrade with:
- Clean existing architecture
- Comprehensive test coverage
- Similar design patterns to Go
- Clear upgrade path documented