jach-ts
v1.0.2
Published
TypeScript library for reading and writing ACH/NACHA documents (port of com.afrunt/jach)
Maintainers
Readme
jach-ts
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-tsQuick 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 invalidBuilding 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 formattingTransaction 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.
