@classytic/fin-io
v0.1.0
Published
Financial data interchange — parse and emit OFX, CAMT.053, MT940, CSV, IIF, Xero, Plaid into one canonical shape. Ledger-agnostic, ESM-first, tree-shakable, streaming-capable.
Maintainers
Readme
@classytic/fin-io
Financial data interchange — parse and emit OFX, CAMT.053, MT940, CSV, IIF, Xero, Plaid into one canonical shape.
Status: scaffolded, not implemented. See PLAN.md for the architecture, scope, format research, and phased delivery.
What this is
A standalone, ledger-agnostic TypeScript package for parsing financial file formats into a single normalized canonical shape (CanonicalStatement, CanonicalTransaction, CanonicalInvoice, CanonicalContact, CanonicalJournalEntry). Modern, ESM-first, tree-shakable via subpath exports, streaming-capable for large corporate files, mongokit-friendly via an optional adapter.
Who it's for
@classytic/ledgerconsumers — pair with@classytic/ledger/sync(subpath, planned for ledger 0.8.0) to map canonical shapes intoJournalEntrys and post them through your existing repositories- TaxCycle-style apps — parse statements without ever touching an accounting engine
- Migration tools — read QuickBooks IIF, Xero CSV, or live bank exports and re-emit them in any other format
- Bookkeeping / treasury / expense apps — ingest bank data with one consistent vocabulary across formats
Quickstart (when Phase 1 ships)
import { parseOfx } from '@classytic/fin-io/ofx';
const result = parseOfx(buffer);
if (result.ok) {
for (const stmt of result.data) {
console.log(stmt.account.iban, stmt.transactions.length);
}
}With the optional mongokit adapter:
import { parseOfx } from '@classytic/fin-io/ofx';
import { createTransactionImporter } from '@classytic/fin-io/adapters/mongokit';
const importer = createTransactionImporter({ db, collection: 'bank_transactions' });
const parsed = parseOfx(buffer);
if (parsed.ok) {
await importer.import({ organizationId, accountId: 'acc_1', statement: parsed.data[0] });
}With @classytic/ledger integration:
import { parseOfx } from '@classytic/fin-io/ofx';
import { wireImport, ofxBankMapper } from '@classytic/ledger/sync';
const parsed = parseOfx(buffer);
if (parsed.ok) {
const importer = wireImport({
source: parsed.data,
mapper: ofxBankMapper({ bankAccountCode: '1010', defaultCounterAccountCode: '5900', organizationId }),
journalEntries,
});
await importer.run();
}Subpath exports (when implemented)
| Import | Purpose |
|---|---|
| @classytic/fin-io | Canonical types + Money/date helpers |
| @classytic/fin-io/ofx | OFX 1.x SGML + 2.x XML + QFX |
| @classytic/fin-io/camt053 | ISO 20022 CAMT.053 (buffer + streaming) |
| @classytic/fin-io/mt940 | SWIFT MT940 |
| @classytic/fin-io/csv | Configurable CSV with bank presets |
| @classytic/fin-io/iif | QuickBooks Desktop IIF |
| @classytic/fin-io/xero | Xero CSV templates |
| @classytic/fin-io/plaid | Plaid Transaction JSON mapper |
| @classytic/fin-io/schemas | Optional Zod schemas (peer dep) |
| @classytic/fin-io/adapters/mongokit | Optional mongokit upsert helper (peer dep) |
What it will NOT do
- No double-entry / accounting logic — that's
@classytic/ledger - No tax computation — that's
packages/tax/ - No live API connectors (QBO, Xero, Plaid Link) — those become sibling packages
@classytic/fin-io-{qbo,xero,plaid}with their own SDK deps - No payment file generation (PAIN.001, NACHA) — future
@classytic/payments-io - No PDF / OCR
See PLAN.md for the complete out-of-scope list and the reasoning.
