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

jach-ts

v1.0.2

Published

TypeScript library for reading and writing ACH/NACHA documents (port of com.afrunt/jach)

Readme

jach-ts

npm version License

TypeScript port of com.afrunt/jach — a library for reading and writing ACH/NACHA documents.

Zero runtime dependencies. Works in Node.js, browsers, and Deno.


Installation

npm install jach-ts

Quick Start

import { ACH } from 'jach-ts';

const ach = new ACH();

// ── Read ────────────────────────────────────────────────────────────────
const doc = ach.read(achString);

console.log(doc.fileHeader.immediateDestinationName); // 'YOUR BANK'
console.log(doc.batches[0].batchHeader.standardEntryClassCode); // 'PPD'
console.log(doc.batches[0].entries[0].detail.amount); // 10000 (cents)

// ── Write ───────────────────────────────────────────────────────────────
const output: string = ach.write(doc);

// ── With block aligning (pad output to a multiple of 10 lines) ─────────
const ach2 = new ACH({ blockAligning: true });
// or:
const ach3 = ach.withBlockAligning(true);

// ── Bytes API (works in Node.js, browsers, Deno) ───────────────────────
const bytes: Uint8Array = ach.writeBytes(doc);
const doc2 = ach.readBytes(bytes);

// ── Validation ──────────────────────────────────────────────────────────
const { valid, errors } = ach.validate(doc);
ach.validateOrThrow(doc); // throws ACHValidationError if invalid

Building a Document from Scratch

import {
  ACH, ACHDocument, ACHBatch, ACHBatchDetail,
  FileHeader, BatchHeader, PPDEntryDetail, GeneralAddendaRecord,
} from 'jach-ts';

// 1. File Header
const fileHeader = new FileHeader();
fileHeader.immediateDestination     = ' 021000021';
fileHeader.immediateOrigin          = '0210000210';
fileHeader.fileCreationDate         = '260101';        // YYMMDD
fileHeader.immediateDestinationName = 'YOUR BANK              ';
fileHeader.immediateOriginName      = 'YOUR COMPANY           ';

// 2. Batch Header
const batchHeader = new BatchHeader();
batchHeader.serviceClassCode        = '220';           // credits only
batchHeader.companyName             = 'YOUR COMPANY    ';
batchHeader.companyIdentification   = '1234567890';
batchHeader.standardEntryClassCode  = 'PPD';
batchHeader.companyEntryDescription = 'PAYROLL   ';
batchHeader.effectiveEntryDate      = '260103';        // YYMMDD
batchHeader.ODFIIdentification      = '02100002';
batchHeader.batchNumber             = 1;

// 3. Entry Detail
const entry = new PPDEntryDetail();
entry.transactionCode               = '22';            // credit to checking
entry.RDFIIdentification            = '02100002';
entry.checkDigit                    = '1';
entry.DFIAccountNumber              = '123456789      ';
entry.amount                        = 150000;          // $1,500.00 in cents
entry.individualName                = 'JANE SMITH            ';
entry.addendaRecordIndicator        = 0;
entry.traceNumber                   = '021000020000001';

// 4. Assemble
const batch = new ACHBatch(batchHeader);
batch.addEntry(new ACHBatchDetail(entry));

const doc = new ACHDocument(fileHeader);
doc.addBatch(batch);

// 5. Write (FileControl and BatchControl are auto-computed)
const ach = new ACH();
const output = ach.write(doc);

Supported SEC Codes

| Code | Description | |------|-------------| | PPD | Prearranged Payment and Deposit | | CCD | Corporate Credit or Debit | | WEB | Internet-Initiated/Mobile Entry | | TEL | Telephone-Initiated Entry | | ARC | Accounts Receivable Entry | | BOC | Back Office Conversion | | POP | Point-of-Purchase | | POS | Point-of-Sale | | RCK | Represented Check | | CIE | Customer-Initiated Entry | | CTX | Corporate Trade Exchange | | DNE | Death Notification Entry | | XCK | Destroyed Check | | CBR | Cross-Border Entry | | IAT | International ACH Transaction |


Package Structure

src/
├── ACH.ts                    Main façade (read, write, validate)
├── document/                 ACHDocument, ACHBatch, ACHBatchDetail
├── domain/
│   ├── ACHRecord.ts          Abstract base — all lines are 94 chars
│   ├── FileHeader.ts         Record type 1
│   ├── FileControl.ts        Record type 9
│   ├── BatchHeader.ts        Record type 5
│   ├── BatchControl.ts       Record type 8
│   ├── EntryDetail.ts        Record type 6 (base)
│   ├── RecordTypes.ts        Enums + SEC code list
│   ├── detail/               PPD, CCD, WEB, TEL, ARC, BOC, POP, POS,
│   │                         RCK, CIE, CTX, DNE, XCK, CBR entry classes
│   ├── detail/IATEntryDetail.ts
│   └── addenda/
│       ├── index.ts          General (05), Return (99), COR (98), POS (02)
│       └── iat/              IAT addenda types 10–18
├── logic/
│   ├── ACHReader.ts          String → ACHDocument
│   ├── ACHWriter.ts          ACHDocument → string (auto-computes totals)
│   ├── ACHValidator.ts       Structural + field-level validation
│   └── ACHError.ts           ACHError, ACHValidationError
├── annotations/              InclusionRequirement enum + decorators
└── util/StringUtil.ts        Padding, field extraction, amount formatting

Transaction Codes (common)

| Code | Meaning | |------|---------| | 22 | Automated deposit (credit, checking) | | 23 | Prenote for credit, checking | | 27 | Automated payment (debit, checking) | | 28 | Prenote for debit, checking | | 32 | Automated deposit (credit, savings) | | 37 | Automated payment (debit, savings) |


Auto-Computed Fields

When writing, if batchControl or fileControl are not set on the batch/document, the writer computes them automatically:

  • BatchControl: entryAddendaCount, entryHash, totalDebitAmount, totalCreditAmount
  • FileControl: batchCount, blockCount, entryAddendaCount, entryHash, totalDebitAmount, totalCreditAmount

Error Handling

import { ACHError, ACHValidationError } from 'jach-ts';

try {
  ach.validateOrThrow(doc);
} catch (e) {
  if (e instanceof ACHValidationError) {
    console.log('Validation errors:', e.message);
  }
}

try {
  ach.read(badInput);
} catch (e) {
  if (e instanceof ACHError) {
    console.log('Parse error:', e.message);
  }
}

License

Apache-2.0 — same as the original com.afrunt/jach Java library.