@f-o-t/ofx 2.3.0 → 2.4.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/dist/index.d.ts CHANGED
@@ -1773,6 +1773,11 @@ type ParseResult<T> = {
1773
1773
  };
1774
1774
  declare function parse(content: string): ParseResult<OFXDocument>;
1775
1775
  declare function parseOrThrow(content: string): OFXDocument;
1776
+ /**
1777
+ * Decodes an OFX buffer to a string with proper charset detection.
1778
+ * Automatically detects encoding from OFX header (CHARSET field).
1779
+ */
1780
+ declare function decodeOfxBuffer(buffer: Uint8Array): string;
1776
1781
  declare function parseBuffer(buffer: Uint8Array): ParseResult<OFXDocument>;
1777
1782
  declare function parseBufferOrThrow(buffer: Uint8Array): OFXDocument;
1778
1783
  interface StreamOptions {
@@ -1883,4 +1888,4 @@ declare function formatOfxDate(date: Date, timezone?: {
1883
1888
  offset: number;
1884
1889
  name: string;
1885
1890
  }): string;
1886
- export { parseStreamToArray, parseStream, parseOrThrow, parseBufferOrThrow, parseBuffer, parseBatchStreamToArray, parseBatchStream, parse, getTransactions, getSignOnInfo, getEncodingFromCharset, getBalance, getAccountInfo, generateTransactionInputSchema, generateHeaderOptionsSchema, generateHeader, generateCreditCardStatementOptionsSchema, generateCreditCardStatement, generateBankStatementOptionsSchema, generateBankStatement, formatOfxDate, StreamOptions, StreamEvent, ParseResult, OFXTransactionType, OFXTransactionList, OFXTransaction, OFXStatus, OFXSignOnResponse, OFXSignOnMessageSetResponse, OFXResponse, OFXHeader, OFXFinancialInstitution, OFXDocument, OFXDate, OFXCreditCardStatementTransactionResponse, OFXCreditCardStatementResponse, OFXCreditCardMessageSetResponse, OFXCreditCardAccount, OFXBankStatementTransactionResponse, OFXBankStatementResponse, OFXBankMessageSetResponse, OFXBankAccount, OFXBalance, OFXAccountType, GenerateTransactionInput, GenerateHeaderOptions, GenerateCreditCardStatementOptions, GenerateBankStatementOptions, BatchStreamEvent, BatchParsedFile, BatchFileInput, BalanceInfo };
1891
+ export { parseStreamToArray, parseStream, parseOrThrow, parseBufferOrThrow, parseBuffer, parseBatchStreamToArray, parseBatchStream, parse, getTransactions, getSignOnInfo, getEncodingFromCharset, getBalance, getAccountInfo, generateTransactionInputSchema, generateHeaderOptionsSchema, generateHeader, generateCreditCardStatementOptionsSchema, generateCreditCardStatement, generateBankStatementOptionsSchema, generateBankStatement, formatOfxDate, decodeOfxBuffer, StreamOptions, StreamEvent, ParseResult, OFXTransactionType, OFXTransactionList, OFXTransaction, OFXStatus, OFXSignOnResponse, OFXSignOnMessageSetResponse, OFXResponse, OFXHeader, OFXFinancialInstitution, OFXDocument, OFXDate, OFXCreditCardStatementTransactionResponse, OFXCreditCardStatementResponse, OFXCreditCardMessageSetResponse, OFXCreditCardAccount, OFXBankStatementTransactionResponse, OFXBankStatementResponse, OFXBankMessageSetResponse, OFXBankAccount, OFXBalance, OFXAccountType, GenerateTransactionInput, GenerateHeaderOptions, GenerateCreditCardStatementOptions, GenerateBankStatementOptions, BatchStreamEvent, BatchParsedFile, BatchFileInput, BalanceInfo };
package/dist/index.js CHANGED
@@ -21,7 +21,9 @@ function escapeOfxText(text) {
21
21
  return text.replace(/[&<>]/g, (c) => c === "&" ? "&amp;" : c === "<" ? "&lt;" : "&gt;");
22
22
  }
23
23
  function formatAmount(amount) {
24
- return amount.toFixed(2);
24
+ const rounded = Math.round(amount * 100) / 100;
25
+ const [intPart, decPart = ""] = rounded.toString().split(".");
26
+ return `${intPart}.${decPart.padEnd(2, "0").slice(0, 2)}`;
25
27
  }
26
28
  function formatOfxDate(date, timezone) {
27
29
  const tz = timezone ?? { name: "GMT", offset: 0 };
@@ -537,10 +539,10 @@ var CHARSET_MAP = {
537
539
  "1252": "windows-1252",
538
540
  "WINDOWS-1252": "windows-1252",
539
541
  CP1252: "windows-1252",
540
- "8859-1": "iso-8859-1",
541
- "ISO-8859-1": "iso-8859-1",
542
- LATIN1: "iso-8859-1",
543
- "LATIN-1": "iso-8859-1",
542
+ "8859-1": "windows-1252",
543
+ "ISO-8859-1": "windows-1252",
544
+ LATIN1: "windows-1252",
545
+ "LATIN-1": "windows-1252",
544
546
  "UTF-8": "utf-8",
545
547
  UTF8: "utf-8",
546
548
  NONE: "utf-8",
@@ -794,7 +796,7 @@ function hasUtf8MultiByte(buffer) {
794
796
  }
795
797
  function parseHeaderFromBuffer(buffer) {
796
798
  const maxHeaderSize = Math.min(buffer.length, 1000);
797
- const headerSection = new TextDecoder("iso-8859-1").decode(buffer.slice(0, maxHeaderSize));
799
+ const headerSection = new TextDecoder("windows-1252").decode(buffer.slice(0, maxHeaderSize));
798
800
  const header = {};
799
801
  const singleLineMatch = headerSection.match(/^(OFXHEADER:\d+.*?)(?=<OFX|<\?xml)/is);
800
802
  if (singleLineMatch?.[1]) {
@@ -832,6 +834,11 @@ function parseHeaderFromBuffer(buffer) {
832
834
  }
833
835
  return { encoding, header: parsedHeader };
834
836
  }
837
+ function decodeOfxBuffer(buffer) {
838
+ const { encoding } = parseHeaderFromBuffer(buffer);
839
+ const decoder = new TextDecoder(encoding);
840
+ return decoder.decode(buffer);
841
+ }
835
842
  function parseBuffer(buffer) {
836
843
  try {
837
844
  if (!(buffer instanceof Uint8Array)) {
@@ -859,9 +866,7 @@ function parseBuffer(buffer) {
859
866
  success: false
860
867
  };
861
868
  }
862
- const { encoding } = parseHeaderFromBuffer(buffer);
863
- const decoder = new TextDecoder(encoding);
864
- const content = decoder.decode(buffer);
869
+ const content = decodeOfxBuffer(buffer);
865
870
  return parse(content);
866
871
  } catch (err) {
867
872
  if (err instanceof z3.ZodError) {
@@ -1063,7 +1068,7 @@ async function* parseStream(input, options) {
1063
1068
  combined.set(chunk, offset);
1064
1069
  offset += chunk.length;
1065
1070
  }
1066
- const headerSection = new TextDecoder("iso-8859-1").decode(combined.slice(0, Math.min(combined.length, 1000)));
1071
+ const headerSection = new TextDecoder("windows-1252").decode(combined.slice(0, Math.min(combined.length, 1000)));
1067
1072
  if (headerSection.includes("<OFX") || headerSection.includes("<?xml")) {
1068
1073
  const charsetMatch = headerSection.match(/CHARSET:(\S+)/i);
1069
1074
  if (charsetMatch && !detectedEncoding) {
@@ -1136,11 +1141,7 @@ async function* parseBatchStream(files, options) {
1136
1141
  yield { type: "file_start", fileIndex: i, filename: file.filename };
1137
1142
  try {
1138
1143
  let fileTransactionCount = 0;
1139
- const headerSection = new TextDecoder("iso-8859-1").decode(file.buffer.slice(0, Math.min(file.buffer.length, 1000)));
1140
- const charsetMatch = headerSection.match(/CHARSET:(\S+)/i);
1141
- const encoding = charsetMatch ? getEncodingFromCharset(charsetMatch[1]) : options?.encoding ?? "utf-8";
1142
- const decoder = new TextDecoder(encoding);
1143
- const content = decoder.decode(file.buffer);
1144
+ const content = decodeOfxBuffer(file.buffer);
1144
1145
  const chunkIterable = createChunkIterable(content);
1145
1146
  for await (const event of parseStream(chunkIterable, options)) {
1146
1147
  switch (event.type) {
@@ -1251,5 +1252,6 @@ export {
1251
1252
  generateCreditCardStatement,
1252
1253
  generateBankStatementOptionsSchema,
1253
1254
  generateBankStatement,
1254
- formatOfxDate
1255
+ formatOfxDate,
1256
+ decodeOfxBuffer
1255
1257
  };
package/package.json CHANGED
@@ -59,5 +59,5 @@
59
59
  },
60
60
  "type": "module",
61
61
  "types": "./dist/index.d.ts",
62
- "version": "2.3.0"
62
+ "version": "2.4.0"
63
63
  }