ofx-data-extractor 1.4.6 → 1.4.8

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.
@@ -26,7 +26,7 @@ export type BankAccount = {
26
26
  export type BankTransactionList = {
27
27
  DTSTART: string;
28
28
  DTEND: string;
29
- STMTTRN: StatementTransaction[];
30
- STRTTRN: StatementTransaction[];
29
+ STMTTRN?: StatementTransaction[];
30
+ STRTTRN?: StatementTransaction[];
31
31
  [key: string]: any;
32
32
  };
@@ -1,9 +1,9 @@
1
- // Ofx-data-extractor v1.4.6 Copyright (c) 2025 Fábio Pereira França
2
- const E=/<\/[\w.]+>/g,N=/<[\w.]+>/g,u="<BANKMSGSRSV1>",d="</BANKMSGSRSV1>",g="<CREDITCARDMSGSRSV1>",S="</CREDITCARDMSGSRSV1>",R="<STMTTRN>",T="</STMTTRN>",x="_#_",M=new RegExp(x,"g"),b=[u,R,g],L=[d,S,T];function _(e){const t=e.slice(0,4),n=e.slice(4,6),r=e.slice(6,8),s=e.slice(8,10),a=e.slice(10,12),i=e.slice(12,14);return{yyyy:t,yy:t.slice(2),y:t,MM:n,M:n,dd:r,d:r,hh:s,h:s,mm:a,m:a,ss:i,s:i}}function k(e,t){const n=_(e);let r=t;for(const[s,a]of Object.entries(n))r=r.replace(s,a);return r}var l;(function(e){e.BANK="BANK",e.CREDIT_CARD="CREDIT_CARD"})(l||(l={}));const G=["debit","fee","srvchg","atm","pos","check","payment","directdebit","cash","repeatpmt"],F=e=>e.includes(u)?l.BANK:l.CREDIT_CARD;function K(e){if(String(e.TRNAMT).startsWith("-"))return!0;const t=String(e.TRNTYPE).toLocaleLowerCase();return t==="1"||G.includes(t)}function f(e){const t=e.replace(/(\\)/g,"\\\\").replace(E,n=>A(n,!0)).replace(N,n=>w(n,!0)).replace(/(},})/g,"}}").replace(/(}")/g,'},"').replace(/(]")/g,'],"').replace(/(},])/g,"}]").replace(/(,})/g,"}").replace(/,\s*}/g,"}").replace(/(,",)/,",").replace(M,'\\"').slice(0,-1);return t.endsWith(",")?t.slice(0,-1):t}const J=e=>JSON.stringify({date:e.slice(0,12),transactionCode:e.slice(12,19),protocol:e.slice(19)}),P=e=>e.startsWith("DT"),D=e=>e.trim();function w(e,t=!1){return b.includes(e)&&!t?e:e.replace(/[<]/g,`
3
- "`).replace(/[>]/g,'":{')}function A(e,t=!1){return L.includes(e)&&!t?`
1
+ // Ofx-data-extractor v1.4.8 Copyright (c) 2025 Fábio Pereira França
2
+ const E=/<\/[\w.]+>/g,N=/<[\w.]+>/g,u="<BANKMSGSRSV1>",d="</BANKMSGSRSV1>",g="<CREDITCARDMSGSRSV1>",S="</CREDITCARDMSGSRSV1>",R="<STMTTRN>",T="</STMTTRN>",x="_#_",M=new RegExp(x,"g"),L=[u,R,g],b=[d,S,T];function _(e){const t=e.slice(0,4),n=e.slice(4,6),r=e.slice(6,8),s=e.slice(8,10),a=e.slice(10,12),i=e.slice(12,14);return{yyyy:t,yy:t.slice(2),y:t,MM:n,M:n,dd:r,d:r,hh:s,h:s,mm:a,m:a,ss:i,s:i}}function k(e,t){const n=_(e);let r=t;for(const[s,a]of Object.entries(n))r=r.replace(s,a);return r}var l;(function(e){e.BANK="BANK",e.CREDIT_CARD="CREDIT_CARD"})(l||(l={}));const G=["debit","fee","srvchg","atm","pos","check","payment","directdebit","cash","repeatpmt"],F=e=>e.includes(u)?l.BANK:l.CREDIT_CARD;function K(e){if(String(e.TRNAMT).startsWith("-"))return!0;const t=String(e.TRNTYPE).toLocaleLowerCase();return t==="1"||G.includes(t)}function f(e){const t=e.replace(/(\\)/g,"\\\\").replace(E,n=>A(n,!0)).replace(N,n=>w(n,!0)).replace(/(},})/g,"}}").replace(/(}")/g,'},"').replace(/(]")/g,'],"').replace(/(},])/g,"}]").replace(/(,})/g,"}").replace(/,\s*}/g,"}").replace(/(,",)/,'",').replace(M,'\\"').slice(0,-1);return t.endsWith(",")?t.slice(0,-1):t}const J=e=>JSON.stringify({date:e.slice(0,12),transactionCode:e.slice(12,19),protocol:e.slice(19)}),P=e=>e.startsWith("DT"),D=e=>e.trim();function w(e,t=!1){return L.includes(e)&&!t?e:e.replace(/[<]/g,`
3
+ "`).replace(/[>]/g,'":{')}function A(e,t=!1){return b.includes(e)&&!t?`
4
4
  ${e}`:`},
5
- `}function X({fitId:e,fitValue:t}){return e==="separated"?J(t):`"${t}",`}function $(e){return e.search(",")>e.search(".")?e.replace(/[.]/g,"").replace(/[,]/g,"."):e.replace(/[,]/g,"")}function V({dateString:e,formatDate:t="y-M-d"}){return k(e,t)}function W(e){let t=e.value.replace(/[{]/g,"").replace(/(},)/g,"").replace(/["]/g,x);const n=e.field.replace(/['"]/g,"");return n.endsWith("AMT")&&(t=$(t)),P(n)&&(t=V({dateString:t,formatDate:e.formatDate})),n==="FITID"?X({fitId:e.fitId,fitValue:t}):e.nativeTypes&&B(n,t)?`${Number(t)},`:`"${t}",`}function z(e,t){let n=e;return e.match(/{(\w|\W)+/)&&(n=n.replace(/({(\w|\W)+)$/,r=>W({field:n.slice(0,n.indexOf(":")),value:r,...t}))),n}function B(e,t){return e.endsWith("ID")||e.endsWith("NUM")?!1:!isNaN(Number(t))}function y(e){const t=e.indexOf(R),n=e.lastIndexOf(T)+T.length,r=e.substring(t,n),s=new RegExp(R,"g"),a=new RegExp(T,"g"),i=`"STRTTRN":[${r.replace(s,"{").replace(a,"},")}]`;return{oldListText:e,newListText:e.replace(r,i)}}function m(e){if(!(e.indexOf(u)>0))return{newBankStatementTransactions:null,oldBankStatementTransactions:null};const n=y(e.substring(e.indexOf(u),e.indexOf(d)+d.length));return{newBankStatementTransactions:n.newListText,oldBankStatementTransactions:n.oldListText}}function h(e){if(!(e.indexOf(g)>0))return{newCreditCardStatementTransactions:null,oldCreditCardStatementTransactions:null};const n=e.substring(e.indexOf(g),e.indexOf(S)+S.length),r=y(n);return{newCreditCardStatementTransactions:r.newListText,oldCreditCardStatementTransactions:r.oldListText}}function j(e){const t=[];for(const n of e)t.push(...n.replace("<?xml"," ").replace("<?OFX"," ").replace("?>"," ").split(" ").filter(Boolean).map(D).map(r=>r.replace("=",":").replace(/["]/g,"")));return t}function H(e,t){const n={};e.join("").search("<?")>-1&&(e=j(e));for(const r of e){const[s,a]=r.split(":"),i=s.replace(`
5
+ `}function X({fitId:e,fitValue:t}){return e==="separated"?J(t):`"${t}",`}function $(e){return e.search(",")>e.search(".")?e.replace(/[.]/g,"").replace(/[,]/g,"."):e.replace(/[,]/g,"")}function V({dateString:e,formatDate:t="y-M-d"}){return k(e,t)}function W(e){let t=e.value.replace(/[{]/g,"").replace(/(},)/g,"").replace(/["]/g,x);const n=e.field.replace(/['"]/g,"");return n.endsWith("AMT")&&(t=$(t)),P(n)&&(t=V({dateString:t,formatDate:e.formatDate})),n==="FITID"?X({fitId:e.fitId,fitValue:t}):e.nativeTypes&&B(n,t)?`${Number(t)},`:`"${t}",`}function z(e,t){let n=e;return e.match(/{(\w|\W)+/)&&(n=n.replace(/({(\w|\W)+)$/,r=>W({field:n.slice(0,n.indexOf(":")),value:r,...t}))),n}function B(e,t){return e.endsWith("ID")||e.endsWith("NUM")?!1:!isNaN(Number(t))}function y(e){const t=e.indexOf(R),n=e.lastIndexOf(T)+T.length;if(t<0||n<0||t>=n)return{oldListText:e,newListText:e};const r=e.substring(t,n),s=new RegExp(R,"g"),a=new RegExp(T,"g"),i=`"STRTTRN":[${r.replace(s,"{").replace(a,"},")}]`;return{oldListText:e,newListText:e.replace(r,i)}}function m(e){if(!(e.indexOf(u)>0))return{newBankStatementTransactions:null,oldBankStatementTransactions:null};const n=y(e.substring(e.indexOf(u),e.indexOf(d)+d.length));return{newBankStatementTransactions:n.newListText,oldBankStatementTransactions:n.oldListText}}function h(e){if(!(e.indexOf(g)>0))return{newCreditCardStatementTransactions:null,oldCreditCardStatementTransactions:null};const n=e.substring(e.indexOf(g),e.indexOf(S)+S.length),r=y(n);return{newCreditCardStatementTransactions:r.newListText,oldCreditCardStatementTransactions:r.oldListText}}function j(e){const t=[];for(const n of e)t.push(...n.replace("<?xml"," ").replace("<?OFX"," ").replace("?>"," ").split(" ").filter(Boolean).map(D).map(r=>r.replace("=",":").replace(/["]/g,"")));return t}function H(e,t){const n={};e.join("").search("<?")>-1&&(e=j(e));for(const r of e){const[s,a]=r.split(":"),i=s.replace(`
6
6
  `,"").toUpperCase();n[i]=t&&B(s,a)?Number(a):String(a).replace(/\?>/,"")}return n}function U(e){return e.reduce((t,n)=>{const r=Math.abs(+n.TRNAMT);return K(n)?(t.amountOfDebits++,t.debit+=r,t):(t.amountOfCredits++,t.credit+=r,t)},{credit:0,debit:0,amountOfCredits:0,amountOfDebits:0})}class v{config;internConfig={};constructor(t){this.config=t,this.internConfig=t}getConfig(){return this.internConfig}sanitizeRow(t){return z(t,this.internConfig)}getPartialJsonData(t){const[n,r]=t.split("<OFX>"),s="<OFX>"+r,{sanitizeRow:a}=this;return s.replace(/<(?=[^\/])/g,`
7
7
  <`).replace(E,i=>A(i)).replace(N,i=>w(i)).split(`
8
- `).map(D).filter(Boolean).map(a,this).join("")}}function I(e){return e.toString()}async function p(e){return await new Promise((n,r)=>{if(typeof window<"u"&&window.FileReader){const s=new window.FileReader;s.onload=a=>n(a.target.result),s.onerror=a=>r(a.target.error),s.readAsText(e)}else r(new Error("FileReader is not available in this environment."))})}class c{data;dataRead="";constructor(t){this.data=t,t&&(this.dataRead=t)}getData(){return this.dataRead}fromString(t){return new c(t)}fromBuffer(t){return new c(I(t))}async fromBlob(t){return new c(await p(t))}static fromString(t){return new c(t)}static fromBuffer(t){return new c(I(t))}static async fromBlob(t){return new c(await p(t))}}class Y{configInstance={}}class O extends Y{setConfig(t){this.configInstance=t}getBankTransferList(t){const{newBankStatementTransactions:n}=m(this.configInstance.getPartialJsonData(t));return n?JSON.parse(`{${f(n)}}`)?.BANKMSGSRSV1?.STMTTRNRS?.STMTRS?.BANKTRANLIST?.STRTTRN:[]}getCreditCardTransferList(t){const{newCreditCardStatementTransactions:n}=h(this.configInstance.getPartialJsonData(t));return n?JSON.parse(`{${f(n)}}`)?.CREDITCARDMSGSRSV1?.CCSTMTTRNRS?.CCSTMTRS?.BANKTRANLIST?.STRTTRN:[]}getTransactionsSummary(t){const n=this.getContent(t),{DTEND:r,DTSTART:s,...a}=n.OFX.BANKMSGSRSV1.STMTTRNRS.STMTRS.BANKTRANLIST,i=U(a.STMTTRN||a.STRTTRN);return{dateStart:s,dateEnd:r,...i}}getContent(t){const n=this.configInstance.getPartialJsonData(t),{newBankStatementTransactions:r,oldBankStatementTransactions:s}=m(n),{newCreditCardStatementTransactions:a,oldCreditCardStatementTransactions:i}=h(n);let o=n;return r&&(o=o.replace(s,r)),a&&(o=o.replace(i,a)),JSON.parse(`{${f(o)}}`)}}class Q{customExtractor;customExtractorInstance;dataReaderInstance=new c("");constructor(t){this.customExtractor=t,this.customExtractorInstance=t||new O,this.config({})}data(t){return this.dataReaderInstance=t,this}config(t){return this.customExtractorInstance.setConfig(new v(t)),this}getType(){return F(this.dataReaderInstance.getData())}getHeaders(){const[t]=this.dataReaderInstance.getData().split("<OFX>");return H(t.split(`
8
+ `).map(D).filter(Boolean).map(a,this).join("")}}function I(e){return e.toString()}async function p(e){return await new Promise((n,r)=>{if(typeof window<"u"&&window.FileReader){const s=new window.FileReader;s.onload=a=>n(a.target.result),s.onerror=a=>r(a.target.error),s.readAsText(e)}else r(new Error("FileReader is not available in this environment."))})}class c{data;dataRead="";constructor(t){this.data=t,t&&(this.dataRead=t)}getData(){return this.dataRead}fromString(t){return new c(t)}fromBuffer(t){return new c(I(t))}async fromBlob(t){return new c(await p(t))}static fromString(t){return new c(t)}static fromBuffer(t){return new c(I(t))}static async fromBlob(t){return new c(await p(t))}}class Y{configInstance={}}class O extends Y{setConfig(t){this.configInstance=t}getBankTransferList(t){const{newBankStatementTransactions:n}=m(this.configInstance.getPartialJsonData(t));return n?JSON.parse(`{${f(n)}}`)?.BANKMSGSRSV1?.STMTTRNRS?.STMTRS?.BANKTRANLIST?.STRTTRN:[]}getCreditCardTransferList(t){const{newCreditCardStatementTransactions:n}=h(this.configInstance.getPartialJsonData(t));return n?JSON.parse(`{${f(n)}}`)?.CREDITCARDMSGSRSV1?.CCSTMTTRNRS?.CCSTMTRS?.BANKTRANLIST?.STRTTRN:[]}getTransactionsSummary(t){const n=this.getContent(t),{DTEND:r,DTSTART:s,...a}=n.OFX.BANKMSGSRSV1.STMTTRNRS.STMTRS.BANKTRANLIST,i=U(a.STMTTRN||a.STRTTRN||[]);return{dateStart:s,dateEnd:r,...i}}getContent(t){const n=this.configInstance.getPartialJsonData(t),{newBankStatementTransactions:r,oldBankStatementTransactions:s}=m(n),{newCreditCardStatementTransactions:a,oldCreditCardStatementTransactions:i}=h(n);let o=n;return r&&(o=o.replace(s,r)),a&&(o=o.replace(i,a)),JSON.parse(`{${f(o)}}`)}}class Q{customExtractor;customExtractorInstance;dataReaderInstance=new c("");constructor(t){this.customExtractor=t,this.customExtractorInstance=t||new O,this.config({})}data(t){return this.dataReaderInstance=t,this}config(t){return this.customExtractorInstance.setConfig(new v(t)),this}getType(){return F(this.dataReaderInstance.getData())}getHeaders(){const[t]=this.dataReaderInstance.getData().split("<OFX>");return H(t.split(`
9
9
  `).filter(n=>!!n.trim().length),!!this.customExtractorInstance.configInstance.getConfig().nativeTypes)}getBankTransferList(){return this.customExtractorInstance.getBankTransferList(this.dataReaderInstance.getData())}getCreditCardTransferList(){return this.customExtractorInstance.getCreditCardTransferList(this.dataReaderInstance.getData())}getTransactionsSummary(){return this.customExtractorInstance.getTransactionsSummary(this.dataReaderInstance.getData())}getContent(){return this.customExtractorInstance.getContent(this.dataReaderInstance.getData())}toJson(){const t=this.getHeaders(),n=this.customExtractorInstance.getContent(this.dataReaderInstance.getData());return{...t,...n}}}class C{extractor;constructor(t,n){this.extractor=new Q(new O),this.extractor.data(new c(t)),this.extractor.config(n||{})}getType(){return this.extractor.getType()}static fromBuffer(t){return new C(c.fromBuffer(t).getData())}static async fromBlob(t){const n=await c.fromBlob(t);return new C(n.getData())}config(t){return this.extractor.config(t),this}getHeaders(){return this.extractor.getHeaders()}getBankTransferList(){return this.extractor.getBankTransferList()}getCreditCardTransferList(){return this.extractor.getCreditCardTransferList()}getTransactionsSummary(){return this.extractor.getTransactionsSummary()}getContent(){return this.extractor.getContent()}toJson(){return this.extractor.toJson()}}export{Q as Extractor,C as Ofx,O as OfxExtractor,c as Reader,p as blobToString,I as bufferToString,f as fixJsonProblems,k as formatDate};
@@ -1,9 +1,9 @@
1
- // Ofx-data-extractor v1.4.6 Copyright (c) 2025 Fábio Pereira França
2
- (function(c,u){typeof exports=="object"&&typeof module<"u"?u(exports):typeof define=="function"&&define.amd?define(["exports"],u):(c=typeof globalThis<"u"?globalThis:c||self,u(c.ofx={}))})(this,function(c){"use strict";const u=/<\/[\w.]+>/g,N=/<[\w.]+>/g,f="<BANKMSGSRSV1>",R="</BANKMSGSRSV1>",m="<CREDITCARDMSGSRSV1>",C="</CREDITCARDMSGSRSV1>",h="<STMTTRN>",d="</STMTTRN>",x="_#_",_=new RegExp(x,"g"),k=[f,h,m],G=[R,C,d];function F(e){const t=e.slice(0,4),n=e.slice(4,6),r=e.slice(6,8),s=e.slice(8,10),a=e.slice(10,12),i=e.slice(12,14);return{yyyy:t,yy:t.slice(2),y:t,MM:n,M:n,dd:r,d:r,hh:s,h:s,mm:a,m:a,ss:i,s:i}}function D(e,t){const n=F(e);let r=t;for(const[s,a]of Object.entries(n))r=r.replace(s,a);return r}var l;(function(e){e.BANK="BANK",e.CREDIT_CARD="CREDIT_CARD"})(l||(l={}));const J=["debit","fee","srvchg","atm","pos","check","payment","directdebit","cash","repeatpmt"],K=e=>e.includes(f)?l.BANK:l.CREDIT_CARD;function P(e){if(String(e.TRNAMT).startsWith("-"))return!0;const t=String(e.TRNTYPE).toLocaleLowerCase();return t==="1"||J.includes(t)}function g(e){const t=e.replace(/(\\)/g,"\\\\").replace(u,n=>y(n,!0)).replace(N,n=>A(n,!0)).replace(/(},})/g,"}}").replace(/(}")/g,'},"').replace(/(]")/g,'],"').replace(/(},])/g,"}]").replace(/(,})/g,"}").replace(/,\s*}/g,"}").replace(/(,",)/,",").replace(_,'\\"').slice(0,-1);return t.endsWith(",")?t.slice(0,-1):t}const X=e=>JSON.stringify({date:e.slice(0,12),transactionCode:e.slice(12,19),protocol:e.slice(19)}),$=e=>e.startsWith("DT"),w=e=>e.trim();function A(e,t=!1){return k.includes(e)&&!t?e:e.replace(/[<]/g,`
1
+ // Ofx-data-extractor v1.4.8 Copyright (c) 2025 Fábio Pereira França
2
+ (function(c,u){typeof exports=="object"&&typeof module<"u"?u(exports):typeof define=="function"&&define.amd?define(["exports"],u):(c=typeof globalThis<"u"?globalThis:c||self,u(c.ofx={}))})(this,function(c){"use strict";const u=/<\/[\w.]+>/g,x=/<[\w.]+>/g,f="<BANKMSGSRSV1>",R="</BANKMSGSRSV1>",m="<CREDITCARDMSGSRSV1>",C="</CREDITCARDMSGSRSV1>",h="<STMTTRN>",d="</STMTTRN>",N="_#_",_=new RegExp(N,"g"),k=[f,h,m],G=[R,C,d];function F(e){const t=e.slice(0,4),n=e.slice(4,6),r=e.slice(6,8),s=e.slice(8,10),a=e.slice(10,12),i=e.slice(12,14);return{yyyy:t,yy:t.slice(2),y:t,MM:n,M:n,dd:r,d:r,hh:s,h:s,mm:a,m:a,ss:i,s:i}}function D(e,t){const n=F(e);let r=t;for(const[s,a]of Object.entries(n))r=r.replace(s,a);return r}var l;(function(e){e.BANK="BANK",e.CREDIT_CARD="CREDIT_CARD"})(l||(l={}));const J=["debit","fee","srvchg","atm","pos","check","payment","directdebit","cash","repeatpmt"],K=e=>e.includes(f)?l.BANK:l.CREDIT_CARD;function P(e){if(String(e.TRNAMT).startsWith("-"))return!0;const t=String(e.TRNTYPE).toLocaleLowerCase();return t==="1"||J.includes(t)}function g(e){const t=e.replace(/(\\)/g,"\\\\").replace(u,n=>y(n,!0)).replace(x,n=>A(n,!0)).replace(/(},})/g,"}}").replace(/(}")/g,'},"').replace(/(]")/g,'],"').replace(/(},])/g,"}]").replace(/(,})/g,"}").replace(/,\s*}/g,"}").replace(/(,",)/,'",').replace(_,'\\"').slice(0,-1);return t.endsWith(",")?t.slice(0,-1):t}const X=e=>JSON.stringify({date:e.slice(0,12),transactionCode:e.slice(12,19),protocol:e.slice(19)}),$=e=>e.startsWith("DT"),w=e=>e.trim();function A(e,t=!1){return k.includes(e)&&!t?e:e.replace(/[<]/g,`
3
3
  "`).replace(/[>]/g,'":{')}function y(e,t=!1){return G.includes(e)&&!t?`
4
4
  ${e}`:`},
5
- `}function V({fitId:e,fitValue:t}){return e==="separated"?X(t):`"${t}",`}function W(e){return e.search(",")>e.search(".")?e.replace(/[.]/g,"").replace(/[,]/g,"."):e.replace(/[,]/g,"")}function j({dateString:e,formatDate:t="y-M-d"}){return D(e,t)}function z(e){let t=e.value.replace(/[{]/g,"").replace(/(},)/g,"").replace(/["]/g,x);const n=e.field.replace(/['"]/g,"");return n.endsWith("AMT")&&(t=W(t)),$(n)&&(t=j({dateString:t,formatDate:e.formatDate})),n==="FITID"?V({fitId:e.fitId,fitValue:t}):e.nativeTypes&&B(n,t)?`${Number(t)},`:`"${t}",`}function H(e,t){let n=e;return e.match(/{(\w|\W)+/)&&(n=n.replace(/({(\w|\W)+)$/,r=>z({field:n.slice(0,n.indexOf(":")),value:r,...t}))),n}function B(e,t){return e.endsWith("ID")||e.endsWith("NUM")?!1:!isNaN(Number(t))}function O(e){const t=e.indexOf(h),n=e.lastIndexOf(d)+d.length,r=e.substring(t,n),s=new RegExp(h,"g"),a=new RegExp(d,"g"),i=`"STRTTRN":[${r.replace(s,"{").replace(a,"},")}]`;return{oldListText:e,newListText:e.replace(r,i)}}function b(e){if(!(e.indexOf(f)>0))return{newBankStatementTransactions:null,oldBankStatementTransactions:null};const n=O(e.substring(e.indexOf(f),e.indexOf(R)+R.length));return{newBankStatementTransactions:n.newListText,oldBankStatementTransactions:n.oldListText}}function M(e){if(!(e.indexOf(m)>0))return{newCreditCardStatementTransactions:null,oldCreditCardStatementTransactions:null};const n=e.substring(e.indexOf(m),e.indexOf(C)+C.length),r=O(n);return{newCreditCardStatementTransactions:r.newListText,oldCreditCardStatementTransactions:r.oldListText}}function U(e){const t=[];for(const n of e)t.push(...n.replace("<?xml"," ").replace("<?OFX"," ").replace("?>"," ").split(" ").filter(Boolean).map(w).map(r=>r.replace("=",":").replace(/["]/g,"")));return t}function v(e,t){const n={};e.join("").search("<?")>-1&&(e=U(e));for(const r of e){const[s,a]=r.split(":"),i=s.replace(`
5
+ `}function V({fitId:e,fitValue:t}){return e==="separated"?X(t):`"${t}",`}function W(e){return e.search(",")>e.search(".")?e.replace(/[.]/g,"").replace(/[,]/g,"."):e.replace(/[,]/g,"")}function j({dateString:e,formatDate:t="y-M-d"}){return D(e,t)}function z(e){let t=e.value.replace(/[{]/g,"").replace(/(},)/g,"").replace(/["]/g,N);const n=e.field.replace(/['"]/g,"");return n.endsWith("AMT")&&(t=W(t)),$(n)&&(t=j({dateString:t,formatDate:e.formatDate})),n==="FITID"?V({fitId:e.fitId,fitValue:t}):e.nativeTypes&&B(n,t)?`${Number(t)},`:`"${t}",`}function H(e,t){let n=e;return e.match(/{(\w|\W)+/)&&(n=n.replace(/({(\w|\W)+)$/,r=>z({field:n.slice(0,n.indexOf(":")),value:r,...t}))),n}function B(e,t){return e.endsWith("ID")||e.endsWith("NUM")?!1:!isNaN(Number(t))}function O(e){const t=e.indexOf(h),n=e.lastIndexOf(d)+d.length;if(t<0||n<0||t>=n)return{oldListText:e,newListText:e};const r=e.substring(t,n),s=new RegExp(h,"g"),a=new RegExp(d,"g"),i=`"STRTTRN":[${r.replace(s,"{").replace(a,"},")}]`;return{oldListText:e,newListText:e.replace(r,i)}}function b(e){if(!(e.indexOf(f)>0))return{newBankStatementTransactions:null,oldBankStatementTransactions:null};const n=O(e.substring(e.indexOf(f),e.indexOf(R)+R.length));return{newBankStatementTransactions:n.newListText,oldBankStatementTransactions:n.oldListText}}function M(e){if(!(e.indexOf(m)>0))return{newCreditCardStatementTransactions:null,oldCreditCardStatementTransactions:null};const n=e.substring(e.indexOf(m),e.indexOf(C)+C.length),r=O(n);return{newCreditCardStatementTransactions:r.newListText,oldCreditCardStatementTransactions:r.oldListText}}function U(e){const t=[];for(const n of e)t.push(...n.replace("<?xml"," ").replace("<?OFX"," ").replace("?>"," ").split(" ").filter(Boolean).map(w).map(r=>r.replace("=",":").replace(/["]/g,"")));return t}function v(e,t){const n={};e.join("").search("<?")>-1&&(e=U(e));for(const r of e){const[s,a]=r.split(":"),i=s.replace(`
6
6
  `,"").toUpperCase();n[i]=t&&B(s,a)?Number(a):String(a).replace(/\?>/,"")}return n}function Y(e){return e.reduce((t,n)=>{const r=Math.abs(+n.TRNAMT);return P(n)?(t.amountOfDebits++,t.debit+=r,t):(t.amountOfCredits++,t.credit+=r,t)},{credit:0,debit:0,amountOfCredits:0,amountOfDebits:0})}class Q{config;internConfig={};constructor(t){this.config=t,this.internConfig=t}getConfig(){return this.internConfig}sanitizeRow(t){return H(t,this.internConfig)}getPartialJsonData(t){const[n,r]=t.split("<OFX>"),s="<OFX>"+r,{sanitizeRow:a}=this;return s.replace(/<(?=[^\/])/g,`
7
- <`).replace(u,i=>y(i)).replace(N,i=>A(i)).split(`
8
- `).map(w).filter(Boolean).map(a,this).join("")}}function E(e){return e.toString()}async function I(e){return await new Promise((n,r)=>{if(typeof window<"u"&&window.FileReader){const s=new window.FileReader;s.onload=a=>n(a.target.result),s.onerror=a=>r(a.target.error),s.readAsText(e)}else r(new Error("FileReader is not available in this environment."))})}class o{data;dataRead="";constructor(t){this.data=t,t&&(this.dataRead=t)}getData(){return this.dataRead}fromString(t){return new o(t)}fromBuffer(t){return new o(E(t))}async fromBlob(t){return new o(await I(t))}static fromString(t){return new o(t)}static fromBuffer(t){return new o(E(t))}static async fromBlob(t){return new o(await I(t))}}class q{configInstance={}}class p extends q{setConfig(t){this.configInstance=t}getBankTransferList(t){const{newBankStatementTransactions:n}=b(this.configInstance.getPartialJsonData(t));return n?JSON.parse(`{${g(n)}}`)?.BANKMSGSRSV1?.STMTTRNRS?.STMTRS?.BANKTRANLIST?.STRTTRN:[]}getCreditCardTransferList(t){const{newCreditCardStatementTransactions:n}=M(this.configInstance.getPartialJsonData(t));return n?JSON.parse(`{${g(n)}}`)?.CREDITCARDMSGSRSV1?.CCSTMTTRNRS?.CCSTMTRS?.BANKTRANLIST?.STRTTRN:[]}getTransactionsSummary(t){const n=this.getContent(t),{DTEND:r,DTSTART:s,...a}=n.OFX.BANKMSGSRSV1.STMTTRNRS.STMTRS.BANKTRANLIST,i=Y(a.STMTTRN||a.STRTTRN);return{dateStart:s,dateEnd:r,...i}}getContent(t){const n=this.configInstance.getPartialJsonData(t),{newBankStatementTransactions:r,oldBankStatementTransactions:s}=b(n),{newCreditCardStatementTransactions:a,oldCreditCardStatementTransactions:i}=M(n);let T=n;return r&&(T=T.replace(s,r)),a&&(T=T.replace(i,a)),JSON.parse(`{${g(T)}}`)}}class L{customExtractor;customExtractorInstance;dataReaderInstance=new o("");constructor(t){this.customExtractor=t,this.customExtractorInstance=t||new p,this.config({})}data(t){return this.dataReaderInstance=t,this}config(t){return this.customExtractorInstance.setConfig(new Q(t)),this}getType(){return K(this.dataReaderInstance.getData())}getHeaders(){const[t]=this.dataReaderInstance.getData().split("<OFX>");return v(t.split(`
7
+ <`).replace(u,i=>y(i)).replace(x,i=>A(i)).split(`
8
+ `).map(w).filter(Boolean).map(a,this).join("")}}function E(e){return e.toString()}async function I(e){return await new Promise((n,r)=>{if(typeof window<"u"&&window.FileReader){const s=new window.FileReader;s.onload=a=>n(a.target.result),s.onerror=a=>r(a.target.error),s.readAsText(e)}else r(new Error("FileReader is not available in this environment."))})}class o{data;dataRead="";constructor(t){this.data=t,t&&(this.dataRead=t)}getData(){return this.dataRead}fromString(t){return new o(t)}fromBuffer(t){return new o(E(t))}async fromBlob(t){return new o(await I(t))}static fromString(t){return new o(t)}static fromBuffer(t){return new o(E(t))}static async fromBlob(t){return new o(await I(t))}}class q{configInstance={}}class p extends q{setConfig(t){this.configInstance=t}getBankTransferList(t){const{newBankStatementTransactions:n}=b(this.configInstance.getPartialJsonData(t));return n?JSON.parse(`{${g(n)}}`)?.BANKMSGSRSV1?.STMTTRNRS?.STMTRS?.BANKTRANLIST?.STRTTRN:[]}getCreditCardTransferList(t){const{newCreditCardStatementTransactions:n}=M(this.configInstance.getPartialJsonData(t));return n?JSON.parse(`{${g(n)}}`)?.CREDITCARDMSGSRSV1?.CCSTMTTRNRS?.CCSTMTRS?.BANKTRANLIST?.STRTTRN:[]}getTransactionsSummary(t){const n=this.getContent(t),{DTEND:r,DTSTART:s,...a}=n.OFX.BANKMSGSRSV1.STMTTRNRS.STMTRS.BANKTRANLIST,i=Y(a.STMTTRN||a.STRTTRN||[]);return{dateStart:s,dateEnd:r,...i}}getContent(t){const n=this.configInstance.getPartialJsonData(t),{newBankStatementTransactions:r,oldBankStatementTransactions:s}=b(n),{newCreditCardStatementTransactions:a,oldCreditCardStatementTransactions:i}=M(n);let T=n;return r&&(T=T.replace(s,r)),a&&(T=T.replace(i,a)),JSON.parse(`{${g(T)}}`)}}class L{customExtractor;customExtractorInstance;dataReaderInstance=new o("");constructor(t){this.customExtractor=t,this.customExtractorInstance=t||new p,this.config({})}data(t){return this.dataReaderInstance=t,this}config(t){return this.customExtractorInstance.setConfig(new Q(t)),this}getType(){return K(this.dataReaderInstance.getData())}getHeaders(){const[t]=this.dataReaderInstance.getData().split("<OFX>");return v(t.split(`
9
9
  `).filter(n=>!!n.trim().length),!!this.customExtractorInstance.configInstance.getConfig().nativeTypes)}getBankTransferList(){return this.customExtractorInstance.getBankTransferList(this.dataReaderInstance.getData())}getCreditCardTransferList(){return this.customExtractorInstance.getCreditCardTransferList(this.dataReaderInstance.getData())}getTransactionsSummary(){return this.customExtractorInstance.getTransactionsSummary(this.dataReaderInstance.getData())}getContent(){return this.customExtractorInstance.getContent(this.dataReaderInstance.getData())}toJson(){const t=this.getHeaders(),n=this.customExtractorInstance.getContent(this.dataReaderInstance.getData());return{...t,...n}}}class S{extractor;constructor(t,n){this.extractor=new L(new p),this.extractor.data(new o(t)),this.extractor.config(n||{})}getType(){return this.extractor.getType()}static fromBuffer(t){return new S(o.fromBuffer(t).getData())}static async fromBlob(t){const n=await o.fromBlob(t);return new S(n.getData())}config(t){return this.extractor.config(t),this}getHeaders(){return this.extractor.getHeaders()}getBankTransferList(){return this.extractor.getBankTransferList()}getCreditCardTransferList(){return this.extractor.getCreditCardTransferList()}getTransactionsSummary(){return this.extractor.getTransactionsSummary()}getContent(){return this.extractor.getContent()}toJson(){return this.extractor.toJson()}}c.Extractor=L,c.Ofx=S,c.OfxExtractor=p,c.Reader=o,c.blobToString=I,c.bufferToString=E,c.fixJsonProblems=g,c.formatDate=D});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ofx-data-extractor",
3
- "version": "1.4.6",
3
+ "version": "1.4.8",
4
4
  "keywords": [
5
5
  "ofx",
6
6
  "financial",
@@ -56,7 +56,7 @@
56
56
  "@rollup/plugin-typescript": "^10.0.1",
57
57
  "@types/jest": "^29.2.3",
58
58
  "@types/node": "^18.11.10",
59
- "esbuild": "^0.15.16",
59
+ "esbuild": "^0.25.0",
60
60
  "jest": "^29.3.1",
61
61
  "prettier": "^2.8.0",
62
62
  "rollup": "^3.5.1",
@@ -1,88 +0,0 @@
1
- import type { ConfigDate, ConfigFitId, DateResponse, MetaData } from './common';
2
- export type Status = {
3
- CODE: string;
4
- SEVERITY: 'INFO' | 'WARN' | 'ERROR';
5
- MESSAGE?: string;
6
- };
7
- export type BankAccountFrom = {
8
- BANKID: string;
9
- ACCTID: string;
10
- ACCTTYPE: 'CHECKING' | 'SAVINGS' | 'CREDITLINE' | 'MONEYMRKT';
11
- };
12
- export type TransactionType = 'CREDIT' | 'DEBIT' | 'INT' | 'DIV' | 'FEE' | 'SRVCHG' | 'DEP' | 'ATM' | 'POS' | 'XFER' | 'CHECK' | 'PAYMENT' | 'CASH' | 'DIRECTDEP' | 'DIRECTDEBIT' | 'REPEATPMT' | 'OTHER';
13
- export type OfxConfig = ConfigDate & {
14
- fitId?: ConfigFitId;
15
- nativeTypes?: boolean;
16
- };
17
- export type STRTTRN = {
18
- TRNTYPE: TransactionType;
19
- DTPOSTED: DateResponse;
20
- TRNAMT: string;
21
- FITID: string | {
22
- date: string;
23
- protocol: string;
24
- transactionCode: string;
25
- };
26
- CHECKNUM?: string;
27
- MEMO?: string;
28
- DTAVAIL?: string;
29
- };
30
- export type BankTransferList = {
31
- DTSTART: DateResponse;
32
- DTEND: DateResponse;
33
- STRTTRN: STRTTRN[];
34
- };
35
- export type Balance = {
36
- BALAMT: string;
37
- DTASOF: DateResponse;
38
- };
39
- export type FINANCIAL_INSTITUTION = {
40
- ORG: string;
41
- FID: string;
42
- };
43
- export type StatementResponse = {
44
- CURDEF: string;
45
- BANKACCTFROM: BankAccountFrom;
46
- BANKTRANLIST: BankTransferList;
47
- LEDGERBAL: Balance;
48
- AVAILBAL?: Balance;
49
- MKTGINFO?: string;
50
- };
51
- export type Bank = {
52
- STMTTRNRS: {
53
- TRNUID: number;
54
- STATUS: Status;
55
- STMTRS: StatementResponse;
56
- };
57
- };
58
- export type CreditCard = {
59
- CCSTMTTRNRS: {
60
- TRNUID: number;
61
- STATUS: Status;
62
- CCSTMTRS: {
63
- CURDEF: string;
64
- CCACCTFROM: {
65
- ACCTID: string;
66
- };
67
- BANKTRANLIST: BankTransferList;
68
- LEDGERBAL: Balance;
69
- MKTGINFO: string;
70
- };
71
- };
72
- };
73
- export type OfxStructure = {
74
- OFX: {
75
- SIGNONMSGSRSV1: {
76
- SONRS: {
77
- STATUS: Status;
78
- DTSERVER: DateResponse;
79
- LANGUAGE: string;
80
- DTACCTUP: DateResponse;
81
- FI: FINANCIAL_INSTITUTION;
82
- };
83
- };
84
- BANKMSGSRSV1: Bank;
85
- CREDITCARDMSGSRSV1: CreditCard;
86
- };
87
- };
88
- export type OfxResponse = MetaData & OfxStructure;
@@ -1,85 +0,0 @@
1
- import type { ConfigDate, ConfigFitId, DateResponse, MetaData } from './common';
2
- export type Status = {
3
- CODE: string;
4
- SEVERITY: string;
5
- };
6
- export type BankAccountFrom = {
7
- BANKID: string;
8
- ACCTID: string;
9
- ACCTT: string;
10
- };
11
- type TransferType = string;
12
- export type OfxConfig = ConfigDate & {
13
- fitId?: ConfigFitId;
14
- nativeTypes?: boolean;
15
- };
16
- export type STRTTRN = {
17
- TRNTYPE: TransferType;
18
- DTPOSTED: DateResponse;
19
- TRNAMT: string;
20
- FITID: string | {
21
- date: string;
22
- protocol: string;
23
- transactionCode: string;
24
- };
25
- CHECKNUM: string;
26
- MEMO: string;
27
- };
28
- export type BankTransferList = {
29
- DTSTART: DateResponse;
30
- DTEND: DateResponse;
31
- STRTTRN: STRTTRN[];
32
- };
33
- export type LedGerBal = {
34
- BALAMT: string;
35
- DTASOF: DateResponse;
36
- };
37
- export type FINANCIAL_INSTITUTION = {
38
- ORG: string;
39
- FID: string;
40
- };
41
- export type Bank = {
42
- STMTTRNRS: {
43
- TRNUID: number;
44
- STATUS: Status;
45
- STMTRS: {
46
- CURDEF: string;
47
- BANKACCTFROM: BankAccountFrom;
48
- BANKTRANLIST: BankTransferList;
49
- LEDGERBAL: LedGerBal;
50
- MKTGINFO: string;
51
- };
52
- };
53
- };
54
- export type CreditCard = {
55
- CCSTMTTRNRS: {
56
- TRNUID: number;
57
- STATUS: Status;
58
- CCSTMTRS: {
59
- CURDEF: string;
60
- CCACCTFROM: {
61
- ACCTID: string;
62
- };
63
- BANKTRANLIST: BankTransferList;
64
- LEDGERBAL: LedGerBal;
65
- MKTGINFO: string;
66
- };
67
- };
68
- };
69
- export type OfxStructure = {
70
- OFX: {
71
- SIGNONMSGSRSV1: {
72
- SONRS: {
73
- STATUS: Status;
74
- DTSERVER: DateResponse;
75
- LANGUAGE: string;
76
- DTACCTUP: DateResponse;
77
- FI: FINANCIAL_INSTITUTION;
78
- };
79
- };
80
- BANKMSGSRSV1: Bank;
81
- CREDITCARDMSGSRSV1: CreditCard;
82
- };
83
- };
84
- export type OfxResponse = MetaData & OfxStructure;
85
- export {};