npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

neat-edifact

v0.6.0

Published

A TypeScript UN/EDIFACT interchange parser. Zero dependencies, strict and non-strict modes.

Readme

neat-edifact

A TypeScript parser for UN/EDIFACT interchanges. Give it a raw EDIFACT string, get back typed Interchange, Message, and Segment objects. That's it.

It handles the syntax layer only — no segment group logic, no domain-specific knowledge, no opinions about what your messages mean. If you need BAPLIE parsing or similar, build that on top of this.

Install

npm install neat-edifact
pnpm add neat-edifact

Usage

import { Parser } from 'neat-edifact'

const raw = `UNB+UNOA:2+SENDER+RECEIVER+260424:0811+000001'
UNH+000001+BAPLIE:D:95B:UN:SMDG20'
BGM++V123456+9'
UNT+3+000001'
UNZ+1+000001'`

const result = new Parser(raw).parse()
const interchange = result.first();

console.log(interchange.senderId)   // 'SENDER'
console.log(interchange.messages[0].messageType) // 'BAPLIE'
console.log(interchange.messages[0].segments[0].tag) // 'BGM'

parse() always returns InterchangeResult — even for single interchange files. Just use result.first() for the common case.

Strict mode

By default the parser is lenient. It'll do its best with whatever you give it — orphaned segments, missing UNZ, mismatched references, it'll handle it all gracefully.

If you want it to throw on any of that, pass true as the second argument:

new Parser(raw, true).parse()

Strict mode enforces:

  • First segment must be UNB, last must be UNZ
  • Only one UNB/UNZ pair
  • Every UNH must have a matching UNT
  • No segments outside a UNH/UNT pair
  • Control references must match between UNB/UNZ and UNH/UNT
  • Segment and message counts must match what's declared

UNA

If the file has a UNA service string advice, the parser reads it automatically and uses those delimiters. If not, it falls back to the EDIFACT defaults (+, :, ', ?). You don't need to do anything.

API

Parser

new Parser(rawContent: string, strict?: boolean)
parser.parse(): InterchangeResult

InterchangeResult

interchangeResult.first()
interchangeResult.firstOrFail()
interchangeResult.at(0)
interchangeResult.atOrFail(1)
interchangeResult.length()
interchangeResult.all()
interchangeResult.errors()
interchangeResult.hasErrors()
interchangeResult.isValid()

Interchange

interchange.syntaxIdentifier  // e.g. 'UNOA'
interchange.syntaxVersion     // e.g. '2'
interchange.senderId
interchange.recipientId
interchange.date              // 'YYMMDD'
interchange.time              // 'HHMM'
interchange.controlReference
interchange.declaredMessageCount
interchange.messages          // Message[]

Message

message.messageReferenceNumber
message.messageType     // e.g. 'BAPLIE'
message.messageVersion  // e.g. 'D'
message.messageRelease  // e.g. '95B'
message.controllingAgency
message.associationCode
message.declaredSegmentCount
message.segments        // Segment[]

Segment

segment.tag                        // e.g. 'LOC'
segment.getDataElement(0)          // DataElement | undefined
segment.getDataElement(0)?.Value   // first component of that element
segment.getDataElement(0)?.getComponent(1)?.value  // specific component

Errors

import { EdifactSyntaxError, EdifactEnvelopeError, EdifactValidationError, InterchangeNotFoundError } from 'neat-edifact'
  • EdifactSyntaxError — malformed input, e.g. a segment with no tag
  • EdifactEnvelopeError — missing or broken UNB/UNZ/UNH/UNT structure
  • EdifactValidationError — count or reference mismatches (strict mode only)
  • InterchangeNotFoundError — thrown by .firstOrFail() when the result is empty, or .atOrFail(n) when no interchange exists at that index

Notes

  • Multiple interchanges in one file are supported in non-strict mode — each UNB produces a separate Interchange on the InterchangeResult
  • The release character (? by default) is handled correctly at all levels
  • Zero runtime dependencies