Building EDIFlow in TypeScript: Part 1 - Why Clean Architecture?

Building EDIFlow in TypeScript: Part 1 - Why Clean Architecture?

# typescript# cleanarchitecture# edifact# x12
Building EDIFlow in TypeScript: Part 1 - Why Clean Architecture?hello-ediflow

Series: Building EDIFlow - A Clean Architecture Journey in TypeScript (Part 1/6) Author:...

Series: Building EDIFlow - A Clean Architecture Journey in TypeScript (Part 1/6)

Author: EDIFlow

Published: February 2026

Reading Time: ~7 minutes


1. Introduction - The Problem πŸ€”

I've been working in data integration for over 20 years. SOAP, REST APIs, and yesβ€”EDI. Lots of EDI.

If you've ever worked with EDIFACT, you know the pain:

UNH+1+ORDERS:D:96A:UN'
BGM+220+ORDER12345+9'
DTM+137:20240201:102'
NAD+BY+BUYER123::92'
Enter fullscreen mode Exit fullscreen mode

What does BGM+220 mean? What is DTM+137? What's ::92?

This is the "old school EDI" world:

  • ❌ No human-readable names
  • ❌ Just codes and tags (BGM, NAD, DTM...)
  • ❌ Makes onboarding new developers incredibly hard

And the existing parsers? They don't help much:

// ❌ Typical EDI Parser - Generic segments
const bgm = message.segments.find(s => s.tag === 'BGM');
const docNumber = bgm?.elements[1]?.value;  // What is element[1]? 🀷
Enter fullscreen mode Exit fullscreen mode

No type safety. No IntelliSense. No business logic.

After 20+ years of this, I had enough. I wanted to build an EDI library that:

  • βœ… Maps to type-safe TypeScript business objects
  • βœ… Uses Clean Architecture principles
  • βœ… Makes EDI development enjoyable (yes, really!)

So I started EDIFlow.

But here's the honest truth: I didn't just want to build a library. I wanted to LEARN Clean Architecture by doing.


2. Why Clean Architecture? πŸ“š

The Honest Answer: I Wanted to Learn It!

I first encountered Clean Architecture around 2020. Read the books:

I was hooked. The principles made so much sense:

  • Single Responsibility
  • Dependency Inversion
  • Separation of Concerns
  • Testability

But then I tried to apply it at work...

The Reality: Resistance to Change

Typical problems I faced:

  • 🏒 "We've always done it this way"
  • 😰 "New architecture? Too risky!"
  • ⏰ "We don't have time to refactor"
  • 🀷 "Why change if it works?"

The structures were too entrenched. No trust in "new" architectures. The typical corporate fears.

Sound familiar?

The Solution: Build My Own Project

I realized: The best way to learn Clean Architecture is to build something real from scratch.

Not a TODO app. Not a toy example. A real-world library that solves a real problem.

So when I decided to build EDIFlow, I made a commitment:

  • βœ… Clean Architecture from Day 1
  • βœ… TDD (Test-Driven Development)
  • βœ… Agile principles (even solo!)
  • βœ… No compromises on code quality

Could I have hacked it together in a weekend? Sure!

But where's the learning in that? 🀷

So... Was Clean Architecture Worth It?

This is the question everyone asks: "Is Clean Architecture worth the extra effort?"

My answer: YES! But it wasn't without challenges.

What went well:

  • βœ… 599 tests - Writing tests became easy (and fun!)
  • βœ… Zero coupling - Changed parser implementation twice, no problem
  • βœ… Added 4 EDIFACT versions - Clean separation made it trivial
  • βœ… Confidence - I can refactor without fear

But there were challenges too:

  • ⚠️ More files - Sometimes felt like overkill for simple features
  • ⚠️ Initial velocity - First weeks were slower ("I could have hacked this in a weekend!")
  • ⚠️ TypeScript DI complexity - No framework = manual wiring gets verbose
  • ⚠️ Solo discipline - Easy to cut corners when no one is watching

The verdict? For a library like EDIFlow: Absolutely worth it! Every hour spent on architecture saved me days in maintenance.

For a throwaway script? Probably overkill.

(We'll dive into the honest pros & cons, with real examples, in Part 5!)


3. Why TypeScript? πŸ’™

EDI parsing is complex. You're dealing with:

  • 618+ message types (ORDERS, INVOIC, DESADV...)
  • Thousands of segment definitions
  • Complex validation rules
  • Delimiters, escape characters, special cases

Without type safety, this becomes a nightmare.

TypeScript Benefits for EDIFlow:

1. Type Safety for Complex Parsing Logic

// ❌ JavaScript - Runtime errors waiting to happen
const delimiters = {
  component: ':',
  element: '+',
  segment: "'"
};
delimiters.component = delimiters.element; // Oops! No error! πŸ’₯

// βœ… TypeScript - Caught at compile time
export class Delimiters {
  private constructor(
    public readonly component: string,
    public readonly element: string,
    public readonly segment: string
  ) {
    if (component === element) {
      throw new Error("Delimiters must be different!");
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

2. IntelliSense = Developer Happiness

// βœ… Auto-completion works!
const order = mapper.mapToBusinessObject(message);
console.log(order.documentNumber);        // IntelliSense suggests fields
console.log(order.parties.buyer.id);      // Type-safe navigation
console.log(order.lineItems[0].quantity); // No guessing!
Enter fullscreen mode Exit fullscreen mode

3. Interface-Driven Design (Perfect for Clean Architecture!)

// Domain Layer - Just an interface, no implementation details
export interface IEDIParser {
  parse(message: string): EDIMessage;
}

// Infrastructure Layer - Implements the interface
export class EdifactMessageParser implements IEDIParser {
  parse(message: string): EDIMessage {
    // EDIFACT-specific logic here
  }
}
Enter fullscreen mode Exit fullscreen mode

This is Dependency Inversion in action! The domain doesn't know about EDIFACT. The domain just knows "I need a parser."

4. Easy to Publish to npm

TypeScript compiles to JavaScript, so it works everywhere:

npm install @ediflow/core     # Works in Node.js
import { EdifactParser } from '@ediflow/core';  # Works in browsers (with bundler)
Enter fullscreen mode Exit fullscreen mode

Plus, TypeScript generates .d.ts files automaticallyβ€”users get IntelliSense out of the box!

5. Strong Ecosystem

  • Vitest for testing (fast, great DX)
  • tsup for building (zero config!)
  • TypeScript strict mode catches bugs early

TypeScript Made EDI Development Enjoyable

Before EDIFlow, EDI development was:

  • 😫 Debugging runtime errors
  • 🀷 Guessing what element[3] means
  • πŸ’₯ Breaking changes at runtime

With TypeScript:

  • βœ… Compile-time safety
  • βœ… IntelliSense everywhere
  • βœ… Refactoring with confidence

TypeScript isn't just a nice-to-have for EDIFlow. It's essential.


4. Why Open Source? 🌍

Learning in Public

I could have built EDIFlow as a private project. But I chose open source for several reasons:

1. Accountability

When you know others might read your code, you write better code.

No shortcuts. No "I'll fix this later." Everything has to be production-ready.

2. Community Feedback

Open source means:

  • πŸ› Bug reports from real users
  • πŸ’‘ Feature suggestions I never thought of
  • 🀝 Potential contributors
  • πŸ“– Documentation improvements

The best products are built WITH the community, not just FOR them.

3. Portfolio & Learning

Let's be honest: If I'm spending 100+ hours building this, I want to:

  • βœ… Show it in my portfolio
  • βœ… Get feedback from experts
  • βœ… Help others with the same problem
  • βœ… Build my personal brand

Open source is the ultimate resume.

4. Solving a Real Problem

I'm not the only one struggling with EDI libraries. By open-sourcing EDIFlow, I hope to:

  • Help developers new to EDI
  • Provide a modern alternative to legacy tools
  • Show that EDI can be developer-friendly

5. MIT License = Maximum Freedom

EDIFlow is MIT licensed:

  • βœ… Use it commercially
  • βœ… Modify it however you want
  • βœ… No attribution required (but appreciated!)
  • βœ… No strings attached

Why MIT? Because I want maximum adoption. The more people use it, the better it gets.


5. What is EDIFlow? πŸš€

Okay, enough about motivation. What IS EDIFlow?

EDI = Electronic Data Interchange

Companies exchange business documents electronically:

  • Purchase Orders (ORDERS)
  • Invoices (INVOIC)
  • Shipping Notices (DESADV)
  • Inventory Reports (INVRPT)

Instead of paper, they send structured messages like:

UNH+1+ORDERS:D:96A:UN'
BGM+220+ORDER12345+9'
DTM+137:20240201:102'
...
Enter fullscreen mode Exit fullscreen mode

EDIFACT = UN/EDIFACT Standard

EDIFACT (Electronic Data Interchange For Administration, Commerce and Transport) is the United Nations standard for EDI.

It's used globally, especially in:

  • 🚒 Logistics & Supply Chain
  • 🏭 Manufacturing
  • πŸ₯ Healthcare
  • πŸ›οΈ Government

EDIFlow = Modern TypeScript Library for EDI

EDIFlow is:

  • βœ… Parser - EDIFACT string β†’ TypeScript objects
  • βœ… Validator - 3-phase validation (Syntax β†’ Structure β†’ Business)
  • βœ… Builder - TypeScript objects β†’ EDIFACT string
  • βœ… Mapper - Auto-convert to/from business objects
  • βœ… Schema Exporter - Generate JSON Schema & TypeScript types

Built with:

  • Clean Architecture (Uncle Bob)
  • TypeScript (strict mode)
  • TDD (599 tests!)
  • Zero dependencies (core package)

And this is just the beginning! πŸš€

Right now, EDIFlow supports EDIFACT (4 versions). But the journey continues:

  • πŸ”œ X12 (ANSI ASC X12) - Coming soon!
  • πŸ”œ More EDI formats - We're agile, we follow the flow!
  • πŸ”œ Community-driven features - What does the community need?

The Clean Architecture foundation makes adding new formats easy. That's the power of good design!

Quick Example:

import { DIContainer } from '@ediflow/core';

// 1. Parse EDIFACT string
const container = DIContainer.getInstance();
const parseUseCase = container.resolve('ParseEDIUseCase');

const result = parseUseCase.execute({
  message: edifactString,
  standard: 'EDIFACT'
});

console.log(result.message.messageType); // "ORDERS"

// 2. Map to business object (type-safe!)
const mapper = container.resolve('BusinessObjectMapper');
const order = mapper.mapToBusinessObject(result.message);

console.log(order.documentNumber);         // "ORDER12345"
console.log(order.parties.buyer.id);       // "BUYER123"
console.log(order.lineItems[0].productId); // IntelliSense works!

// 3. Modify with type safety
order.lineItems[0].quantity = 150;

// 4. Build back to EDIFACT
const buildUseCase = container.resolve('BuildEDIUseCase');
const ediString = buildUseCase.execute({
  message: mapper.mapFromBusinessObject(order),
  standard: 'EDIFACT'
});
Enter fullscreen mode Exit fullscreen mode

This is what "modern EDI" looks like. ✨


6. Project Stats πŸ“Š

Let me give you a sneak peek at what we've built so far:

Packages (npm)

Current (EDIFACT):

  • @ediflow/core - Parser, Validator, Builder engine (MIT)
  • @ediflow/edifact-d96a - D.96A (1996) - 89 messages (MIT)
  • @ediflow/edifact-d01b - D.01B (2001) - 155 messages (MIT)
  • @ediflow/edifact-d20b - D.20B (2020) - 178 messages (MIT)
  • @ediflow/edifact-d12a - D.12A (2012) - 196 messages (MIT, Prep)

Coming Soon:

  • @ediflow/x12 - ANSI ASC X12 support πŸ”œ
  • More formats - We're agile, we follow where "Flow" leads us! 🌊

Current Total: 618 EDIFACT message types supported (and growing!)

Tests & Quality

  • βœ… ~600 tests passing (unit + integration + e2e)
  • βœ… ~90% test coverage (goal: 95%+)
  • βœ… Clean Architecture - All layers tested independently
  • βœ… TypeScript strict mode - No any types!
  • βœ… Zero dependencies (core package)

Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚     Presentation Layer                β”‚  CLI, API, UI (Future)
β”‚                                       β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚  β”‚   Infrastructure Layer          β”‚ β”‚  Parsers, Repositories
β”‚  β”‚                                 β”‚ β”‚
β”‚  β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚ β”‚
β”‚  β”‚  β”‚   Application Layer       β”‚  β”‚ β”‚  Use Cases, Services
β”‚  β”‚  β”‚                           β”‚  β”‚ β”‚
β”‚  β”‚  β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚  β”‚ β”‚
β”‚  β”‚  β”‚  β”‚   Domain Layer      β”‚  β”‚  β”‚ β”‚  Entities, Value Objects
β”‚  β”‚  β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚  β”‚ β”‚
β”‚  β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚ β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
Enter fullscreen mode Exit fullscreen mode

Dependency direction: Always inward β†’ β†’ β†’ β†’

Note: Presentation Layer (CLI, REST API, Web UI) is planned for future releases!


7. What's Coming in This Series? πŸ—“οΈ

This is just Part 1 of 6! Here's what's next:

Part 1 (This Article): Why? ← You are here! βœ…

  • Motivation & personal story
  • Why Clean Architecture?
  • Why TypeScript?
  • Why Open Source?

Part 2 (Next Week): Domain Layer Deep-Dive

  • Entities (EDIMessage, Segment)
  • Value Objects (Delimiters, Standard, Version)
  • Business Rules (ValidationRule, MandatoryRule)
  • Real code examples from EDIFlow

Part 3: Application Layer - Use Cases & Services

  • ParseEDIUseCase, ValidateMessageUseCase, BuildEDIUseCase
  • ComposableValidationService
  • DTOs & Dependency Injection
  • How orchestration works

Part 4: Infrastructure Layer & Monorepo Structure

  • Parsers (EdifactMessageParser)
  • Repositories (FileBasedMessageStructureRepository)
  • Why 5 packages? (Monorepo strategy)
  • TypeScript project references

Part 5: Presentation Layer - The Interface

  • CLI tools and commands
  • REST API design (planned)
  • Web UI vision (future)
  • How Presentation Layer stays clean
  • Dependency Injection from top to bottom

Part 6 (Finale): Lessons Learned & Future

  • Was Clean Architecture worth it? (honest answer!)
  • Performance analysis (benchmarks!)
  • Testing insights (600 tests!)
  • What I'd do differently
  • Roadmap & future plans

Each article: 1000-1800 words, deep technical dive with real code!


8. Conclusion & Call to Action πŸš€

My Journey

EDIFlow is more than just a library. It's my journey of:

  • πŸ“š Learning Clean Architecture by doing, not just reading
  • πŸ’™ Proving TypeScript is perfect for enterprise-grade libraries
  • 🌍 Building in public and sharing the process
  • πŸ”§ Making "old school EDI" developer-friendly
  • 🌊 Following the Flow - Starting with EDIFACT, next X12, then... who knows? We're agile!

It's Not Perfect (Yet!)

I'm not claiming EDIFlow is perfect. I've made mistakes. I've refactored. I've learned.

And that's exactly what this series is about.

In the next 4 articles, I'll show you:

  • βœ… What worked (spoiler: a lot!)
  • ❌ What didn't work (also a lot!)
  • πŸ’‘ How to apply Clean Architecture in TypeScript
  • πŸš€ Real code from a production-ready library

This is Pair Programming... with You!

I built EDIFlow with GitHub Copilot as my pair programming partner. Now I'm sharing the journey with you.

Follow along, and let's learn together!


πŸ”— Links & Resources

Try EDIFlow:

Join the Community:

Read More:


πŸ’­ What Do YOU Want to Learn?

This series is for you. What topics should I cover?

  • Domain Layer patterns?
  • TypeScript DI without frameworks?
  • Testing strategies?
  • Performance optimization?

Comment below! πŸ‘‡


πŸ“’ Next Up: Part 2 - Domain Layer

Next week, we'll dive into the Domain Layer:

  • How do Entities differ from Value Objects?
  • Why immutability matters
  • Real code examples from EDIFlow
  • TypeScript patterns that make Clean Architecture easier

See you next week! πŸš€


If you found this helpful:

Let's make EDI development great again! πŸ˜„


This article is part of the "Building EDIFlow: A Clean Architecture Journey in TypeScript" series. Follow along as we build a production-ready EDIFACT library from scratch using Clean Architecture principles.


Word Count: ~1,650 words

Reading Time: ~7 minutes

Series: Part 1 of 6


Coming Soon:

  • Part 2: Domain Layer Deep-Dive
  • Part 3: Application Layer
  • Part 4: Infrastructure & Packages
  • Part 5: Presentation Layer
  • Part 6: Lessons Learned