Skip to content

Parser Implementation Complete - Design & Architecture Documentation #8

@deepracticexs

Description

@deepracticexs

Overview

The @darp/parser package has been successfully implemented. This issue documents the design decisions, architecture, and implementation details.

Design Principles

1. Responsibility: Syntax Only, Not Semantics

The parser is solely responsible for syntax parsing, not semantic validation:

// ✅ Parser accepts these - syntax is valid
parseARP('arp:unknown:weird://...')  // Unknown semantic/transport
parseARP('arp:custom:ipfs://QmHash') // Custom types

// ❌ Parser rejects these - syntax is invalid  
parseARP('tool://myorg@name')        // Missing 'arp:' prefix
parseARP('arp:tool')                 // Missing location

Rationale: Semantic validation is the responsibility of upper layers (validators, handlers). Parser stays focused and extensible.

2. Strong Contracts, Not Convenience

  • API: `parseARP(input: string): ARP` - throws exceptions
  • No `parseARPSafe()` wrapper - applications handle errors as needed
  • No Result type in this package - keep it focused

Rationale: Library layer provides strong contracts. Application layer wraps as needed.

3. Type Flexibility

interface ARP {
  protocol: 'arp'     // Fixed - this is ARP protocol
  semantic: string    // Open - any semantic type allowed
  transport: string   // Open - any transport protocol allowed  
  location: string
}

Rationale: Parser doesn't dictate what semantics/transports are valid. Extensibility over type safety at this layer.

Architecture

Three-Layer Structure (NodeSpec Standard)

src/
├── types/          # Public type definitions
│   ├── arp.ts     # ARP interface
│   ├── errors.ts  # Error codes + Error classes
│   └── index.ts
├── api/           # Public API
│   ├── parser.ts  # parseARP function
│   └── index.ts
└── core/          # Internal implementation
    └── parser.ts  # Parsing logic (not exported)

Key Points:

  • `types/` - Exported to users (ARP, ARPError, ARPErrorCode)
  • `api/` - Exported to users (parseARP)
  • `core/` - Internal only, can refactor freely

Error Handling Strategy

Error classes in `types/` not `api/`:

  • Error classes are type definitions users need
  • Part of the public contract
  • Belong with other type definitions

Implementation Details

ARI as Syntactic Sugar

ARI is NOT a separate type - it's a convenience syntax that defaults `transport: 'registry'`:

// ARI input
"arp:tool://myorg@name"

// Parses to same ARP object structure
{
  protocol: 'arp',
  semantic: 'tool',
  transport: 'registry',  // Implicitly set
  location: 'myorg@name'
}

Parsing Algorithm

  1. Validate `arp:` prefix
  2. Extract semantic: `arp:([^:]+):(.+)`
  3. Detect transport format:
    • `(\w+)://(.+)` → Explicit transport (ARL)
    • `//(.+)` → Implicit registry (ARI)
  4. Return structured ARP object

Testing Strategy

BDD with Cucumber

  • 16 test scenarios across 3 feature files
  • All tests passing ✅

Test Coverage:

  • `parse-arl.feature` - 6 scenarios (HTTPS, file, git, registry, unknown types)
  • `parse-ari.feature` - 4 scenarios (with/without org, version, digest)
  • `parse-errors.feature` - 6 scenarios (missing parts, invalid formats)

Test Structure

packages/parser/
├── features/           # Gherkin feature files
└── tests/
    └── e2e/
        ├── support/   # (Reserved for hooks/world)
        └── steps/     # Step definitions

Build Output

dist/
├── index.js        # 2.5KB ESM bundle
├── index.js.map    # Source map
└── index.d.ts      # TypeScript definitions

Usage Examples

Basic Parsing

import { parseARP } from '@darp/parser'

// Parse ARL (explicit transport)
const arl = parseARP('arp:tool:https://cdn.com/tool.wasm')
// → { protocol: 'arp', semantic: 'tool', transport: 'https', location: 'cdn.com/tool.wasm' }

// Parse ARI (implicit registry)  
const ari = parseARP('arp:tool://myorg@web-search')
// → { protocol: 'arp', semantic: 'tool', transport: 'registry', location: 'myorg@name' }

Error Handling

import { parseARP, ARPError, ARPErrorCode } from '@darp/parser'

try {
  parseARP('invalid-input')
} catch (error) {
  if (error instanceof ARPError) {
    console.log(error.code)    // ARPErrorCode.MISSING_PROTOCOL
    console.log(error.message) // 'ARP must start with "arp:"'
    console.log(error.input)   // 'invalid-input'
  }
}

Next Steps

  • Implement transport handlers (registry, https, file, git)
  • Implement semantic validators
  • Create registry client package
  • Add integration tests with handlers

Related

Commit

Implementation: 098d57a

Metadata

Metadata

Assignees

No one assigned

    Labels

    documentationImprovements or additions to documentationenhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions