@f-o-t/ofx 2.0.0 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -11,11 +11,17 @@ bun add @fot/ofx
11
11
  ## Quick Start
12
12
 
13
13
  ```typescript
14
- import { parse, getTransactions, getBalance } from "@fot/ofx";
14
+ import { parse, parseBuffer, getTransactions, getBalance } from "@fot/ofx";
15
+ import { readFileSync } from "node:fs";
15
16
 
16
- const ofxContent = fs.readFileSync("statement.ofx", "utf-8");
17
+ // For files with known UTF-8 encoding
18
+ const ofxContent = readFileSync("statement.ofx", "utf-8");
17
19
  const result = parse(ofxContent);
18
20
 
21
+ // For files with unknown encoding (recommended for Brazilian banks)
22
+ const buffer = readFileSync("statement.ofx");
23
+ const result = parseBuffer(new Uint8Array(buffer));
24
+
19
25
  if (result.success) {
20
26
  const transactions = getTransactions(result.data);
21
27
  const balances = getBalance(result.data);
@@ -56,6 +62,31 @@ try {
56
62
  }
57
63
  ```
58
64
 
65
+ #### `parseBuffer(buffer: Uint8Array): ParseResult<OFXDocument>`
66
+
67
+ Parses an OFX file from binary data with automatic encoding detection. This is the recommended method for files from Brazilian banks or any file with non-UTF-8 encoding.
68
+
69
+ ```typescript
70
+ import { readFileSync } from "node:fs";
71
+
72
+ const buffer = readFileSync("extrato.ofx");
73
+ const result = parseBuffer(new Uint8Array(buffer));
74
+
75
+ if (result.success) {
76
+ // Portuguese characters like "Cartão" are correctly preserved
77
+ console.log(result.data);
78
+ }
79
+ ```
80
+
81
+ #### `parseBufferOrThrow(buffer: Uint8Array): OFXDocument`
82
+
83
+ Parses an OFX file from binary data and throws on validation errors.
84
+
85
+ ```typescript
86
+ const buffer = readFileSync("extrato.ofx");
87
+ const doc = parseBufferOrThrow(new Uint8Array(buffer));
88
+ ```
89
+
59
90
  ### Extraction Functions
60
91
 
61
92
  #### `getTransactions(document: OFXDocument): OFXTransaction[]`
@@ -229,6 +260,95 @@ console.log("Accounts:", result.accounts);
229
260
  console.log("Balances:", result.balances);
230
261
  ```
231
262
 
263
+ ### Batch Streaming Functions
264
+
265
+ For processing multiple OFX files in a single operation with progress tracking.
266
+
267
+ #### `parseBatchStream(files): AsyncGenerator<BatchStreamEvent>`
268
+
269
+ Parses multiple OFX files sequentially, yielding events as they are parsed. Ideal for importing multiple bank statements at once.
270
+
271
+ ```typescript
272
+ import { parseBatchStream, type BatchFileInput } from "@fot/ofx";
273
+ import { readFileSync } from "node:fs";
274
+
275
+ const files: BatchFileInput[] = [
276
+ { filename: "january.ofx", buffer: new Uint8Array(readFileSync("january.ofx")) },
277
+ { filename: "february.ofx", buffer: new Uint8Array(readFileSync("february.ofx")) },
278
+ { filename: "march.ofx", buffer: new Uint8Array(readFileSync("march.ofx")) },
279
+ ];
280
+
281
+ for await (const event of parseBatchStream(files)) {
282
+ switch (event.type) {
283
+ case "file_start":
284
+ console.log(`Processing: ${event.filename}`);
285
+ break;
286
+ case "transaction":
287
+ console.log(`File ${event.fileIndex}: ${event.data.NAME} - ${event.data.TRNAMT}`);
288
+ break;
289
+ case "file_complete":
290
+ console.log(`Completed ${event.filename}: ${event.transactionCount} transactions`);
291
+ break;
292
+ case "file_error":
293
+ console.error(`Error in ${event.filename}: ${event.error}`);
294
+ break;
295
+ case "batch_complete":
296
+ console.log(`Batch done: ${event.totalTransactions} transactions from ${event.totalFiles} files`);
297
+ break;
298
+ }
299
+ }
300
+ ```
301
+
302
+ #### `parseBatchStreamToArray(files): Promise<BatchParsedFile[]>`
303
+
304
+ Collects all batch results into an array for easier processing.
305
+
306
+ ```typescript
307
+ import { parseBatchStreamToArray } from "@fot/ofx";
308
+
309
+ const results = await parseBatchStreamToArray(files);
310
+
311
+ for (const file of results) {
312
+ console.log(`${file.filename}: ${file.transactions.length} transactions`);
313
+ if (file.error) {
314
+ console.error(` Error: ${file.error}`);
315
+ }
316
+ }
317
+ ```
318
+
319
+ ## Encoding Support
320
+
321
+ The library automatically detects and handles various character encodings commonly used in OFX files, especially from Brazilian banks.
322
+
323
+ ### Supported Charsets
324
+
325
+ | OFX CHARSET Value | Encoding Used |
326
+ | ----------------- | ------------- |
327
+ | `1252`, `WINDOWS-1252`, `CP1252` | windows-1252 |
328
+ | `8859-1`, `ISO-8859-1`, `LATIN1`, `LATIN-1` | iso-8859-1 |
329
+ | `UTF-8`, `UTF8`, `NONE`, (empty) | utf-8 |
330
+
331
+ ### UTF-8 Auto-Detection
332
+
333
+ Some OFX files declare `CHARSET:1252` but are actually encoded as UTF-8. The library automatically detects this and uses UTF-8 when appropriate, ensuring characters like `Transação` are correctly preserved.
334
+
335
+ ### Best Practices
336
+
337
+ For files from Brazilian banks or any file with unknown encoding, use `parseBuffer()` instead of `parse()`:
338
+
339
+ ```typescript
340
+ import { parseBuffer } from "@fot/ofx";
341
+ import { readFileSync } from "node:fs";
342
+
343
+ // Correct: Read as binary, let the library detect encoding
344
+ const buffer = readFileSync("extrato.ofx");
345
+ const result = parseBuffer(new Uint8Array(buffer));
346
+
347
+ // Avoid: Reading as UTF-8 string may corrupt Windows-1252 characters
348
+ // const content = readFileSync("extrato.ofx", "utf-8");
349
+ // const result = parse(content);
350
+ ```
351
+
232
352
  ## Types
233
353
 
234
354
  ### OFXTransaction
@@ -238,7 +358,7 @@ interface OFXTransaction {
238
358
  TRNTYPE: OFXTransactionType;
239
359
  DTPOSTED: OFXDate;
240
360
  TRNAMT: number;
241
- FITID: string;
361
+ FITID?: string; // Optional, auto-generated if missing
242
362
  NAME?: string;
243
363
  MEMO?: string;
244
364
  CHECKNUM?: string;