ofx-data-extractor 1.0.8 → 1.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 +70 -23
- package/dist/index.js +7 -6
- package/package.json +5 -2
- package/dist/config.d.ts +0 -4
- package/dist/helpers.d.ts +0 -22
- package/dist/index.d.ts +0 -3
- package/dist/index.esm.js +0 -9
- package/dist/index.esm.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/main.d.ts +0 -24
- package/dist/types.d.ts +0 -110
package/README.md
CHANGED
|
@@ -1,51 +1,98 @@
|
|
|
1
|
-
# ofx-data-extractor
|
|
1
|
+
# [ofx-data-extractor](https://www.npmjs.com/package/ofx-data-extractor)
|
|
2
|
+
|
|
3
|
+
[](https://badge.fury.io/js/ofx-data-extractor) [![MIT License][license-image]][license-url]
|
|
4
|
+
[](https://codecov.io/gh/Fabiopf02/ofx-data-extractor)
|
|
5
|
+
|
|
2
6
|
## Ofx Data Extractor and Formatter
|
|
3
|
-
This is a `Node.js` module written in `TypeScript` that provides a utility for extracting data from an `OFX` file. The module can also format some of the data and retrieve specific parts of the file if requested.
|
|
7
|
+
This is a `Node.js` and `Browser` module written in `TypeScript` that provides a utility for extracting data from an `OFX` file. The module can also format some of the data and retrieve specific parts of the file if requested.
|
|
4
8
|
|
|
5
9
|
### Installation
|
|
6
10
|
You can install this module using the Node Package Manager (`NPM`) with the following command:
|
|
7
11
|
|
|
12
|
+
**npm**
|
|
13
|
+
```bash
|
|
14
|
+
npm install ofx-data-extractor
|
|
15
|
+
```
|
|
16
|
+
**yarn**
|
|
8
17
|
```bash
|
|
9
|
-
|
|
18
|
+
yarn add ofx-data-extractor
|
|
10
19
|
```
|
|
11
|
-
|
|
20
|
+
|
|
21
|
+
### Methods
|
|
22
|
+
The `Ofx` class provides the following methods:
|
|
23
|
+
|
|
24
|
+
- `async fromBuffer(data: Buffer)`: Used to read files on the node. Returns the methods
|
|
25
|
+
- `async fromFilePath(path: string)`: Used to read files on the node. Returns the methods below.
|
|
26
|
+
- `fromBlob(data: Blob)`: Used to read files in the browser. Returns the methods below.
|
|
27
|
+
- `config(options: OfxConfig)`: Used for formatting the generated json.`
|
|
28
|
+
- `getHeaders(): OFXMetaData`: Returns the metadata section of the OFX file as an object.
|
|
29
|
+
- `getBankTransferList(): Pick<BankTransferList, 'STRTTRN'>`: Returns a list of bank transfer transactions as an object.
|
|
30
|
+
- `getTransactionsSummary()`: Object: Returns a summary of transactions for a bank statement as an object.
|
|
31
|
+
- `getContent(): OfxStructure`: Returns the OFX file content as an object.
|
|
32
|
+
- `toJson(): OfxResponse`: Returns the entire OFX file content as a JSON object.
|
|
33
|
+
|
|
34
|
+
### Usage
|
|
12
35
|
The module provides a class called Ofx that can be used to extract and format data from an `OFX` file. Here's an example of how to use it:
|
|
13
36
|
|
|
14
37
|
```typescript
|
|
15
|
-
import { Ofx } from 'ofx-data-extractor'
|
|
38
|
+
import { Ofx } from 'ofx-data-extractor'
|
|
16
39
|
|
|
17
|
-
const data = 'OFXHEADER:100\nDATA:OFXSGML\nVERSION:102\n...'
|
|
18
|
-
const ofx = new Ofx(data)
|
|
40
|
+
const data = 'OFXHEADER:100\nDATA:OFXSGML\nVERSION:102\n...'
|
|
41
|
+
const ofx = new Ofx(data) // works in node.js and browser
|
|
19
42
|
|
|
20
|
-
const headers = ofx.getHeaders()
|
|
21
|
-
console.log(headers)
|
|
43
|
+
const headers = ofx.getHeaders()
|
|
44
|
+
console.log(headers)
|
|
22
45
|
|
|
23
|
-
const transactionsSummary = ofx.getTransactionsSummary()
|
|
24
|
-
console.log(transactionsSummary)
|
|
46
|
+
const transactionsSummary = ofx.getTransactionsSummary()
|
|
47
|
+
console.log(transactionsSummary)
|
|
25
48
|
|
|
26
|
-
const bankTransferList = ofx.getBankTransferList()
|
|
27
|
-
console.log(bankTransferList)
|
|
49
|
+
const bankTransferList = ofx.getBankTransferList()
|
|
50
|
+
console.log(bankTransferList)
|
|
28
51
|
|
|
29
|
-
const ofxResponse = ofx.toJson()
|
|
30
|
-
console.log(ofxResponse)
|
|
52
|
+
const ofxResponse = ofx.toJson()
|
|
53
|
+
console.log(ofxResponse)
|
|
31
54
|
```
|
|
32
55
|
### Constructor
|
|
33
56
|
The `Ofx` class constructor takes in two arguments:
|
|
34
57
|
|
|
35
58
|
`data`: The `OFX` file content as a string or a Buffer.
|
|
36
59
|
`config`: Optional configuration options for formatting the OFX data.
|
|
37
|
-
### Methods
|
|
38
|
-
The `Ofx` class provides the following methods:
|
|
39
60
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
61
|
+
### Read data - static methods (`Node.js`)
|
|
62
|
+
```typescript
|
|
63
|
+
import { Ofx } from 'ofx-data-extractor'
|
|
64
|
+
import fs from 'fs'
|
|
65
|
+
|
|
66
|
+
const file = await fs.readFile('/path/to/file')
|
|
67
|
+
const ofx = await Ofx.fromBuffer(file)
|
|
68
|
+
// OR
|
|
69
|
+
const ofx = await Ofx.fromFilePath('/path/to/file')
|
|
70
|
+
|
|
71
|
+
const ofxResponse = ofx.toJson()
|
|
72
|
+
console.log(ofxResponse)
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### Read data - static methods (`Browser`)
|
|
76
|
+
```typescript
|
|
77
|
+
import { Ofx } from 'ofx-data-extractor'
|
|
78
|
+
|
|
79
|
+
function handleFile(event) {
|
|
80
|
+
const ofx = Ofx.fromBlob(event.target.files[0])
|
|
81
|
+
const ofxResponse = ofx.toJson()
|
|
82
|
+
console.log(ofxResponse)
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// tsx/jsx/html
|
|
86
|
+
<input type="file" onChange={handleFile} />
|
|
87
|
+
```
|
|
88
|
+
|
|
45
89
|
|
|
46
90
|
### Configuration
|
|
47
|
-
The `Ofx` class can be configured with the following options:
|
|
91
|
+
The `Ofx` (`constructor` and `config` method) class can be configured with the following options:
|
|
48
92
|
|
|
49
93
|
- `formatDate`: A function that takes in a date string and returns a formatted date string.
|
|
50
94
|
- `fitId`: A string that determines how the financial institution transaction ID is handled. Possible values are "separated" (the default) or "included".
|
|
51
95
|
- `nativeTypes`: A boolean value that determines whether numeric fields should be represented as numbers or strings in the resulting JSON object.
|
|
96
|
+
|
|
97
|
+
[license-image]: https://img.shields.io/badge/license-MIT-blue.svg?style=flat
|
|
98
|
+
[license-url]: LICENSE
|
package/dist/index.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
"use strict";const
|
|
1
|
+
"use strict";var S=Object.create;var d=Object.defineProperty;var w=Object.getOwnPropertyDescriptor;var y=Object.getOwnPropertyNames;var D=Object.getPrototypeOf,b=Object.prototype.hasOwnProperty;var x=(n,t,e,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let s of y(t))!b.call(n,s)&&s!==e&&d(n,s,{get:()=>t[s],enumerable:!(r=w(t,s))||r.enumerable});return n};var E=(n,t,e)=>(e=n!=null?S(D(n)):{},x(t||!n||!n.__esModule?d(e,"default",{value:n,enumerable:!0}):e,n));const O=/<\/\w+>/g,_=/<\w+>/g,u="<STMTTRN>",c="</STMTTRN>";function F(n){const t=n.slice(0,4),e=n.slice(4,6),r=n.slice(6,8),s=n.slice(8,10),i=n.slice(10,12),a=n.slice(12,14),[l,N]=n.slice(14).replace("[","").replace("]","").split(":");return{yyyy:t,yy:t.slice(2),y:t,MM:e,M:e,dd:r,d:r,hh:s,h:s,mm:i,m:i,ss:a,s:a,O:l,TZ:N}}function f(n,t){const e=F(n);let r=t;for(const[s,i]of Object.entries(e))r=r.replace(s,i);return r}function T(n){const t=n.replace(/(},})/g,"}}").replace(/(}")/g,'},"').replace(/(},])/g,"}]").replace(/(,})/g,"}").replace(/({")/g,`{
|
|
2
2
|
"`).replace(/(})/g,`
|
|
3
3
|
}`).replace(/(",")/g,`",
|
|
4
4
|
"`).replace(/,\s*}/g,`
|
|
5
|
-
}`);return t.at(-1)===","?t.slice(0,-1):t}function
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
5
|
+
}`).replace(/(,",)/,",");return t.at(-1)===","?t.slice(0,-1):t}function M(n){const t=n.slice(0,12),e=n.slice(12,19),r=n.slice(19),s={date:t,transactionCode:e,protocol:r};return JSON.stringify(s)}function L(n){return n.startsWith("DT")}function I(n){return n.trim()}function P(n){return n===u?n:n.replace(/[<]/g,`
|
|
6
|
+
`).replace(/[>]/g,":{")}function A(n){return n===c?`
|
|
7
|
+
${n}`:"},"}function C(n){const t=n.search(","),e=n.search(".");return t>e?n.replace(/[.]/g,"").replace(/[,]/g,"."):n.replace(/[,]/g,"")}function p(n,t){return n.endsWith("ID")||n.endsWith("NUM")?!1:!isNaN(Number(t))}function g(n){const t=n.indexOf(u),e=n.lastIndexOf(c)+c.length,r=n.substring(t,e),s=new RegExp(u,"g"),i=new RegExp(c,"g"),a=`"STRTTRN":[${r.replace(s,"{").replace(i,"},")}]`;return{oldListText:r,newListText:a}}function z(n,t){const e={};for(const r of n){const[s,i]=r.split(":"),a=s.replace(`
|
|
8
|
+
`,"");e[a]=t&&p(s,i)?Number(i):i}return e}function B(n){return n.reduce((t,e)=>e.TRNTYPE.toLocaleLowerCase().startsWith("deb")?(t.amountOfDebits++,t.debit+=Number(e.TRNAMT.replace("-","")),t):(t.amountOfCredits++,t.credit+=Number(e.TRNAMT),t),{credit:0,debit:0,amountOfCredits:0,amountOfDebits:0})}function m(n){return n.toString()}async function h(n){return await new Promise((e,r)=>{import("fs").then(s=>s.readFile(n,(i,a)=>{i?r(i):e(a.toString())}))})}async function R(n){return await new Promise((e,r)=>{if(typeof window<"u"&&window.FileReader){const s=new window.FileReader;s.onload=i=>e(i.target.result),s.onerror=i=>r(i.target.error),s.readAsText(n)}else r(new Error("FileReader is not available in this environment."))})}class o{_data;_config={};constructor(t,e){e&&(this._config=e),this._data=t}static fromBuffer(t){return new o(m(t))}static async fromFilePath(t){const e=await h(t);return new o(e)}static async fromBlob(t){const e=await R(t);return new o(e)}config(t){return this._config=t,this}getHeaders(){const[t]=this._data.split("<OFX>"),e=t.split(`
|
|
9
|
+
`),r=i=>!!i.trim().length,s=e.filter(r);return z(s,!!this._config.nativeTypes)}getBankTransferList(){const{newListText:t}=g(this.getPartialJsonData()),e=t.slice(10),r=T(e);return JSON.parse(r)}getPartialJsonData(){const[t,e]=this._data.split("<OFX>"),r="<OFX>"+e,{sanitize:s}=this;return r.replace(O,A).replace(_,P).split(`
|
|
10
|
+
`).map(I).filter(Boolean).map(s,this).join("")}sanitizeValue(t,e){let r=e.replace(/[{]/g,"").replace(/(},)/g,"");return t.endsWith("AMT")&&(r=C(r)),L(t)&&(r=this.configDate(r)),t==="FITID"?this.configFinancialInstitutionTransactionId(r):this._config.nativeTypes&&p(t,r)?`${r},`:`"${r}",`}sanitize(t){let e=t;const r=e.slice(0,e.indexOf(":")),s=this.sanitizeValue,i=l=>s.call(this,r,l);return t.match(/{(\w|\W)+/)&&(e=e.replace(/({(\w|\W)+)$/,i)),e.search(/(^\w+:)/)<0?e:e.replace(r+":",`"${r}":`)}configFinancialInstitutionTransactionId(t){const{fitId:e}=this._config;return e==="separated"?M(t):`"${t}",`}configDate(t){const{formatDate:e}=this._config;return e?f(t,e):f(t,"y-M-d")}getTransactionsSummary(){const t=this.getContent(),{DTEND:e,DTSTART:r,STRTTRN:s}=t.OFX.BANKMSGSRSV1.STMTTRNRS.STMTRS.BANKTRANLIST,i=B(s);return{dateStart:r,dateEnd:e,...i}}getContent(){const t=this.getPartialJsonData(),{newListText:e,oldListText:r}=g(t),s=t.replace(r,e);return JSON.parse(`{${T(s)}}`)}toJson(){const t=this.getHeaders(),e=this.getContent();return{...t,...e}}}exports.Ofx=o;exports.blobToString=R;exports.bufferToString=m;exports.fileFromPathToString=h;exports.fixJsonProblems=T;exports.formatDate=f;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ofx-data-extractor",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"keywords": [
|
|
5
5
|
"ofx",
|
|
6
6
|
"financial",
|
|
@@ -38,13 +38,16 @@
|
|
|
38
38
|
}
|
|
39
39
|
},
|
|
40
40
|
"scripts": {
|
|
41
|
-
"test": "
|
|
41
|
+
"test": "jest tests/*.spec.ts --config jest.config.js",
|
|
42
|
+
"test:coverage": "jest tests/*.spec.ts --coverage --config jest.config.js",
|
|
42
43
|
"build": "rollup --config",
|
|
43
44
|
"start": "node dist/index.js",
|
|
44
45
|
"format": "prettier --write \"src/**/*.ts\"",
|
|
45
46
|
"lint": "tslint -p tsconfig.json"
|
|
46
47
|
},
|
|
47
48
|
"devDependencies": {
|
|
49
|
+
"@rollup/plugin-commonjs": "^25.0.3",
|
|
50
|
+
"@rollup/plugin-node-resolve": "^15.1.0",
|
|
48
51
|
"@rollup/plugin-typescript": "^10.0.1",
|
|
49
52
|
"@types/jest": "^29.2.3",
|
|
50
53
|
"@types/node": "^18.11.10",
|
package/dist/config.d.ts
DELETED
package/dist/helpers.d.ts
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { STRTTRN as STRTTRNType } from './types';
|
|
2
|
-
export declare function formatDate(date: string, format: string): string;
|
|
3
|
-
export declare function fixJsonProblems(content: string): string;
|
|
4
|
-
export declare function extractFinancialInstitutionTransactionId(fitid: string): string;
|
|
5
|
-
export declare function isDateField(field: string): boolean;
|
|
6
|
-
export declare function trim(str: string): string;
|
|
7
|
-
export declare function objectStartReplacer(param: string): string;
|
|
8
|
-
export declare function objectEndReplacer(param: string): "</STMTTRN>" | "},";
|
|
9
|
-
export declare function isValidNumberToConvert(field: string, value: string): boolean;
|
|
10
|
-
export declare function getBankTransferListText(ofxContent: string): {
|
|
11
|
-
oldListText: string;
|
|
12
|
-
newListText: string;
|
|
13
|
-
};
|
|
14
|
-
export declare function convertMetaDataToObject(stringList: string[], nativeTypes: boolean): {
|
|
15
|
-
[key: string]: any;
|
|
16
|
-
};
|
|
17
|
-
export declare function getTransactionsSummary(STRTTRN: STRTTRNType[]): {
|
|
18
|
-
credit: number;
|
|
19
|
-
debit: number;
|
|
20
|
-
amountOfCredits: number;
|
|
21
|
-
amountOfDebits: number;
|
|
22
|
-
};
|
package/dist/index.d.ts
DELETED
package/dist/index.esm.js
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
const p=/<\/\w+>/g,h=/<\w+>/g,l="<STMTTRN>",o="</STMTTRN>";function m(n){const t=n.slice(0,4),e=n.slice(4,6),s=n.slice(6,8),r=n.slice(8,10),i=n.slice(10,12),c=n.slice(12,14),[a,g]=n.slice(14).replace("[","").replace("]","").split(":");return{yyyy:t,yy:t.slice(2),y:t,MM:e,M:e,dd:s,d:s,hh:r,h:r,mm:i,m:i,ss:c,s:c,O:a,TZ:g}}function u(n,t){const e=m(n);let s=t;for(const[r,i]of Object.entries(e))s=s.replace(r,i);return s}function f(n){const t=n.replace(/(},})/g,"}}").replace(/(}")/g,'},"').replace(/(},])/g,"}]").replace(/(,})/g,"}").replace(/({")/g,`{
|
|
2
|
-
"`).replace(/(})/g,`
|
|
3
|
-
}`).replace(/(",")/g,`",
|
|
4
|
-
"`).replace(/,\s*}/g,`
|
|
5
|
-
}`);return t.at(-1)===","?t.slice(0,-1):t}function N(n){const t=n.slice(0,12),e=n.slice(12,19),s=n.slice(19),r={date:t,transactionCode:e,protocol:s};return JSON.stringify(r)}function R(n){return n.startsWith("DT")}function x(n){return n.trim()}function D(n){return n===l?n:n.replace("<","").replace(">",":{")}function S(n){return n===o?n:"},"}function d(n,t){return n.endsWith("ID")||n.endsWith("NUM")?!1:!isNaN(Number(t))}function T(n){const t=n.indexOf(l),e=n.lastIndexOf(o)+o.length,s=n.substring(t,e),r=new RegExp(l,"g"),i=new RegExp(o,"g"),c=`"STRTTRN":[${s.replace(r,"{").replace(i,"},")}]`;return{oldListText:s,newListText:c}}function E(n,t){const e={};for(const s of n){const[r,i]=s.split(":"),c=r.replace(`
|
|
6
|
-
`,"");e[c]=t&&d(r,i)?Number(i):i}return e}function O(n){return n.reduce((t,e)=>e.TRNTYPE.toLocaleLowerCase().startsWith("deb")?(t.amountOfDebits++,t.debit+=Number(e.TRNAMT.replace("-","")),t):(t.amountOfCredits++,t.debit+=Number(e.TRNAMT),t),{credit:0,debit:0,amountOfCredits:0,amountOfDebits:0})}class y{data;config={};constructor(t,e){e&&(this.config=e),t instanceof Buffer?this.data=t.toString():this.data=t}getHeaders(){const[t]=this.data.split("<OFX>"),e=t.split(`
|
|
7
|
-
`),s=i=>!!i.trim().length,r=e.filter(s);return E(r,!!this.config.nativeTypes)}getBankTransferList(){const{newListText:t}=T(this.getPartialJsonData()),e=t.slice(10),s=f(e);return JSON.parse(s)}getPartialJsonData(){const[t,e]=this.data.split("<OFX>"),s="<OFX>"+e,{sanitize:r}=this;return s.replace(p,S).replace(h,D).split(`
|
|
8
|
-
`).map(x).filter(Boolean).map(r,this).join("")}sanitizeValue(t,e){let s=e.replace(/[{},]/g,"");if(R(t))s=this.configDate(s);else{if(t==="FITID")return this.configFinancialInstitutionTransactionId(s);if(this.config.nativeTypes&&d(t,s))return`${s},`}return`"${s}",`}sanitize(t){let e=t;const s=e.slice(0,e.indexOf(":")),r=this.sanitizeValue,i=a=>r.call(this,s,a);return t.match(/{(\w|\W)+/)&&(e=e.replace(/({(\w|\W)+)$/,i)),e.search(/(^\w+:)/)<0?e:e.replace(s,`"${s}"`)}configFinancialInstitutionTransactionId(t){const{fitId:e}=this.config;return e==="separated"?N(t):`"${t}",`}configDate(t){const{formatDate:e}=this.config;return e?u(t,e):u(t,"y-M-d")}getTransactionsSummary(){const t=this.getContent(),{DTEND:e,DTSTART:s,STRTTRN:r}=t.OFX.BANKMSGSRSV1.STMTTRNRS.STMTRS.BANKTRANLIST,i=O(r);return{dateStart:s,dateEnd:e,...i}}getContent(){const t=this.getPartialJsonData(),{newListText:e,oldListText:s}=T(t),r=t.replace(s,e);return JSON.parse(`{${f(r)}}`)}toJson(){const t=this.getHeaders(),e=this.getContent();return{...t,...e}}}export{y as Ofx,f as fixJsonProblems,u as formatDate};
|
|
9
|
-
//# sourceMappingURL=index.esm.js.map
|
package/dist/index.esm.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.esm.js","sources":["../src/config.ts","../src/helpers.ts","../src/main.ts"],"sourcesContent":["export const ELEMENT_CLOSURE_REGEX = /<\\/\\w+>/g\nexport const ELEMENT_OPENING_REGEX = /<\\w+>/g\nexport const START_TEXT_BANK_TRANSFER = '<STMTTRN>'\nexport const END_TEXT_BANK_TRANSFER = '</STMTTRN>'\n","import { END_TEXT_BANK_TRANSFER, START_TEXT_BANK_TRANSFER } from './config'\nimport { STRTTRN as STRTTRNType } from './types'\n\nfunction separatePartsOfDate(date: string) {\n const year = date.slice(0, 4)\n const month = date.slice(4, 6)\n const day = date.slice(6, 8)\n const hour = date.slice(8, 10)\n const minutes = date.slice(10, 12)\n const seconds = date.slice(12, 14)\n const [offset, timezone] = date\n .slice(14)\n .replace('[', '')\n .replace(']', '')\n .split(':')\n return {\n yyyy: year,\n yy: year.slice(2),\n y: year,\n MM: month,\n M: month,\n dd: day,\n d: day,\n hh: hour,\n h: hour,\n mm: minutes,\n m: minutes,\n ss: seconds,\n s: seconds,\n O: offset,\n TZ: timezone,\n }\n}\n\nexport function formatDate(date: string, format: string) {\n const parts = separatePartsOfDate(date)\n let result = format\n for (const [key, value] of Object.entries(parts)) {\n result = result.replace(key, value)\n }\n return result\n}\n\nexport function fixJsonProblems(content: string) {\n const result = content\n .replace(/(},})/g, '}}')\n .replace(/(}\")/g, '},\"')\n .replace(/(},])/g, '}]')\n .replace(/(,})/g, '}')\n .replace(/({\")/g, '{\\n\"')\n .replace(/(})/g, '\\n}')\n .replace(/(\",\")/g, '\",\\n\"')\n .replace(/,\\s*}/g, '\\n}')\n return result.at(-1) === ',' ? result.slice(0, -1) : result\n}\n\nexport function extractFinancialInstitutionTransactionId(fitid: string) {\n const dateText = fitid.slice(0, 12)\n const transactionCode = fitid.slice(12, 19)\n const protocol = fitid.slice(19)\n const resultObject = {\n date: dateText,\n transactionCode,\n protocol,\n }\n return JSON.stringify(resultObject)\n}\n\nexport function isDateField(field: string) {\n return field.startsWith('DT')\n}\n\nexport function trim(str: string) {\n return str.trim()\n}\n\nexport function objectStartReplacer(param: string) {\n if (param === START_TEXT_BANK_TRANSFER) return param\n return param.replace('<', '').replace('>', ':{')\n}\n\nexport function objectEndReplacer(param: string) {\n if (param === END_TEXT_BANK_TRANSFER) return param\n return '},'\n}\n\nexport function isValidNumberToConvert(field: string, value: string) {\n if (field.endsWith('ID') || field.endsWith('NUM')) return false\n return !isNaN(Number(value))\n}\n\nexport function getBankTransferListText(ofxContent: string) {\n const startIndex = ofxContent.indexOf(START_TEXT_BANK_TRANSFER)\n const endIndex =\n ofxContent.lastIndexOf(END_TEXT_BANK_TRANSFER) +\n END_TEXT_BANK_TRANSFER.length\n const oldListText = ofxContent.substring(startIndex, endIndex)\n const startRgx = new RegExp(START_TEXT_BANK_TRANSFER, 'g')\n const endRgx = new RegExp(END_TEXT_BANK_TRANSFER, 'g')\n const newListText = `\"STRTTRN\":[${oldListText\n .replace(startRgx, '{')\n .replace(endRgx, '},')}]`\n return { oldListText, newListText }\n}\n\nexport function convertMetaDataToObject(\n stringList: string[],\n nativeTypes: boolean,\n) {\n const result: { [key: string]: any } = {}\n for (const line of stringList) {\n const [key, value] = line.split(':')\n const sanitizedKey = key.replace('\\n', '')\n result[sanitizedKey] =\n nativeTypes && isValidNumberToConvert(key, value) ? Number(value) : value\n }\n return result\n}\n\nexport function getTransactionsSummary(STRTTRN: STRTTRNType[]) {\n return STRTTRN.reduce(\n (prevValue, currValue) => {\n if (currValue.TRNTYPE.toLocaleLowerCase().startsWith('deb')) {\n prevValue.amountOfDebits++\n prevValue.debit += Number(currValue.TRNAMT.replace('-', ''))\n return prevValue\n }\n prevValue.amountOfCredits++\n prevValue.debit += Number(currValue.TRNAMT)\n return prevValue\n },\n { credit: 0, debit: 0, amountOfCredits: 0, amountOfDebits: 0 },\n )\n}\n","import { ELEMENT_CLOSURE_REGEX, ELEMENT_OPENING_REGEX } from './config'\r\nimport {\r\n convertMetaDataToObject,\r\n extractFinancialInstitutionTransactionId,\r\n fixJsonProblems,\r\n formatDate,\r\n getBankTransferListText,\r\n getTransactionsSummary,\r\n isDateField,\r\n isValidNumberToConvert,\r\n objectEndReplacer,\r\n objectStartReplacer,\r\n trim,\r\n} from './helpers'\r\nimport {\r\n BankTransferList,\r\n OfxConfig,\r\n OFXMetaData,\r\n OfxResponse,\r\n OfxStructure,\r\n} from './types'\r\n\r\nexport class Ofx {\r\n private data: string\r\n private config: OfxConfig = {}\r\n\r\n constructor(data: string | Buffer, config?: OfxConfig) {\r\n if (config) this.config = config\r\n if (data instanceof Buffer) this.data = data.toString()\r\n else this.data = data\r\n }\r\n\r\n getHeaders(): OFXMetaData {\r\n const [metaDataString] = this.data.split('<OFX>')\r\n const metaDataList = metaDataString.split('\\n')\r\n const validate = (line: string) => !!line.trim().length\r\n const validatedMetaDataList = metaDataList.filter(validate)\r\n return convertMetaDataToObject(\r\n validatedMetaDataList,\r\n !!this.config.nativeTypes,\r\n ) as OFXMetaData\r\n }\r\n\r\n getBankTransferList(): Pick<BankTransferList, 'STRTTRN'> {\r\n const { newListText } = getBankTransferListText(this.getPartialJsonData())\r\n\r\n const list = newListText.slice(10)\r\n const fixedList = fixJsonProblems(list)\r\n return JSON.parse(fixedList)\r\n }\r\n\r\n private getPartialJsonData() {\r\n const [_, ofxContentText] = this.data.split('<OFX>')\r\n const ofxContent = '<OFX>' + ofxContentText\r\n const { sanitize } = this\r\n /**\r\n * Use replace first for closing tag so there is no conflict in `objectStartReplacer`\r\n */\r\n return ofxContent\r\n .replace(ELEMENT_CLOSURE_REGEX, objectEndReplacer)\r\n .replace(ELEMENT_OPENING_REGEX, objectStartReplacer)\r\n .split('\\n')\r\n .map(trim)\r\n .filter(Boolean)\r\n .map(sanitize, this)\r\n .join('')\r\n }\r\n\r\n private sanitizeValue(field: string, value: string) {\r\n let fieldValue = value.replace(/[{},]/g, '')\r\n if (isDateField(field)) {\r\n fieldValue = this.configDate(fieldValue)\r\n } else if (field === 'FITID') {\r\n return this.configFinancialInstitutionTransactionId(fieldValue)\r\n } else if (\r\n this.config.nativeTypes &&\r\n isValidNumberToConvert(field, fieldValue)\r\n ) {\r\n return `${fieldValue},`\r\n }\r\n return `\"${fieldValue}\",`\r\n }\r\n\r\n private sanitize(line: string) {\r\n let sanitizedLine = line\r\n const field = sanitizedLine.slice(0, sanitizedLine.indexOf(':'))\r\n const sanitizeValue = this.sanitizeValue\r\n const replacer = (matched: string) =>\r\n sanitizeValue.call(this, field, matched)\r\n if (line.match(/{(\\w|\\W)+/)) {\r\n sanitizedLine = sanitizedLine.replace(/({(\\w|\\W)+)$/, replacer)\r\n }\r\n const matchedProperty = sanitizedLine.search(/(^\\w+:)/)\r\n if (matchedProperty < 0) return sanitizedLine\r\n\r\n return sanitizedLine.replace(field, `\"${field}\"`)\r\n }\r\n\r\n private configFinancialInstitutionTransactionId(fitString: string) {\r\n const { fitId } = this.config\r\n if (fitId === 'separated')\r\n return extractFinancialInstitutionTransactionId(fitString)\r\n return `\"${fitString}\",`\r\n }\r\n\r\n private configDate(dateString: string) {\r\n const { formatDate: format } = this.config\r\n if (format) return formatDate(dateString, format)\r\n return formatDate(dateString, 'y-M-d')\r\n }\r\n\r\n getTransactionsSummary() {\r\n const jsonData = this.getContent()\r\n const { DTEND, DTSTART, STRTTRN } =\r\n jsonData.OFX.BANKMSGSRSV1.STMTTRNRS.STMTRS.BANKTRANLIST\r\n const summary = getTransactionsSummary(STRTTRN)\r\n return {\r\n dateStart: DTSTART,\r\n dateEnd: DTEND,\r\n ...summary,\r\n }\r\n }\r\n\r\n getContent(): OfxStructure {\r\n const ofxText = this.getPartialJsonData()\r\n const { newListText, oldListText } = getBankTransferListText(ofxText)\r\n const result = ofxText.replace(oldListText, newListText)\r\n return JSON.parse(`{${fixJsonProblems(result)}}`)\r\n }\r\n\r\n toJson(): OfxResponse {\r\n const ofxMetaDataResult = this.getHeaders()\r\n const ofxContentResult = this.getContent()\r\n const result = { ...ofxMetaDataResult, ...ofxContentResult }\r\n return result\r\n }\r\n}\r\n"],"names":["ELEMENT_CLOSURE_REGEX","ELEMENT_OPENING_REGEX","START_TEXT_BANK_TRANSFER","END_TEXT_BANK_TRANSFER","separatePartsOfDate","date","year","month","day","hour","minutes","seconds","offset","timezone","formatDate","format","parts","result","key","value","fixJsonProblems","content","extractFinancialInstitutionTransactionId","fitid","dateText","transactionCode","protocol","resultObject","isDateField","field","trim","str","objectStartReplacer","param","objectEndReplacer","isValidNumberToConvert","getBankTransferListText","ofxContent","startIndex","endIndex","oldListText","startRgx","endRgx","newListText","convertMetaDataToObject","stringList","nativeTypes","line","sanitizedKey","getTransactionsSummary","STRTTRN","prevValue","currValue","Ofx","data","config","metaDataString","metaDataList","validate","validatedMetaDataList","list","fixedList","_","ofxContentText","sanitize","fieldValue","sanitizedLine","sanitizeValue","replacer","matched","fitString","fitId","dateString","jsonData","DTEND","DTSTART","summary","ofxText","ofxMetaDataResult","ofxContentResult"],"mappings":"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"}
|
package/dist/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../src/config.ts","../src/helpers.ts","../src/main.ts"],"sourcesContent":["export const ELEMENT_CLOSURE_REGEX = /<\\/\\w+>/g\nexport const ELEMENT_OPENING_REGEX = /<\\w+>/g\nexport const START_TEXT_BANK_TRANSFER = '<STMTTRN>'\nexport const END_TEXT_BANK_TRANSFER = '</STMTTRN>'\n","import { END_TEXT_BANK_TRANSFER, START_TEXT_BANK_TRANSFER } from './config'\nimport { STRTTRN as STRTTRNType } from './types'\n\nfunction separatePartsOfDate(date: string) {\n const year = date.slice(0, 4)\n const month = date.slice(4, 6)\n const day = date.slice(6, 8)\n const hour = date.slice(8, 10)\n const minutes = date.slice(10, 12)\n const seconds = date.slice(12, 14)\n const [offset, timezone] = date\n .slice(14)\n .replace('[', '')\n .replace(']', '')\n .split(':')\n return {\n yyyy: year,\n yy: year.slice(2),\n y: year,\n MM: month,\n M: month,\n dd: day,\n d: day,\n hh: hour,\n h: hour,\n mm: minutes,\n m: minutes,\n ss: seconds,\n s: seconds,\n O: offset,\n TZ: timezone,\n }\n}\n\nexport function formatDate(date: string, format: string) {\n const parts = separatePartsOfDate(date)\n let result = format\n for (const [key, value] of Object.entries(parts)) {\n result = result.replace(key, value)\n }\n return result\n}\n\nexport function fixJsonProblems(content: string) {\n const result = content\n .replace(/(},})/g, '}}')\n .replace(/(}\")/g, '},\"')\n .replace(/(},])/g, '}]')\n .replace(/(,})/g, '}')\n .replace(/({\")/g, '{\\n\"')\n .replace(/(})/g, '\\n}')\n .replace(/(\",\")/g, '\",\\n\"')\n .replace(/,\\s*}/g, '\\n}')\n return result.at(-1) === ',' ? result.slice(0, -1) : result\n}\n\nexport function extractFinancialInstitutionTransactionId(fitid: string) {\n const dateText = fitid.slice(0, 12)\n const transactionCode = fitid.slice(12, 19)\n const protocol = fitid.slice(19)\n const resultObject = {\n date: dateText,\n transactionCode,\n protocol,\n }\n return JSON.stringify(resultObject)\n}\n\nexport function isDateField(field: string) {\n return field.startsWith('DT')\n}\n\nexport function trim(str: string) {\n return str.trim()\n}\n\nexport function objectStartReplacer(param: string) {\n if (param === START_TEXT_BANK_TRANSFER) return param\n return param.replace('<', '').replace('>', ':{')\n}\n\nexport function objectEndReplacer(param: string) {\n if (param === END_TEXT_BANK_TRANSFER) return param\n return '},'\n}\n\nexport function isValidNumberToConvert(field: string, value: string) {\n if (field.endsWith('ID') || field.endsWith('NUM')) return false\n return !isNaN(Number(value))\n}\n\nexport function getBankTransferListText(ofxContent: string) {\n const startIndex = ofxContent.indexOf(START_TEXT_BANK_TRANSFER)\n const endIndex =\n ofxContent.lastIndexOf(END_TEXT_BANK_TRANSFER) +\n END_TEXT_BANK_TRANSFER.length\n const oldListText = ofxContent.substring(startIndex, endIndex)\n const startRgx = new RegExp(START_TEXT_BANK_TRANSFER, 'g')\n const endRgx = new RegExp(END_TEXT_BANK_TRANSFER, 'g')\n const newListText = `\"STRTTRN\":[${oldListText\n .replace(startRgx, '{')\n .replace(endRgx, '},')}]`\n return { oldListText, newListText }\n}\n\nexport function convertMetaDataToObject(\n stringList: string[],\n nativeTypes: boolean,\n) {\n const result: { [key: string]: any } = {}\n for (const line of stringList) {\n const [key, value] = line.split(':')\n const sanitizedKey = key.replace('\\n', '')\n result[sanitizedKey] =\n nativeTypes && isValidNumberToConvert(key, value) ? Number(value) : value\n }\n return result\n}\n\nexport function getTransactionsSummary(STRTTRN: STRTTRNType[]) {\n return STRTTRN.reduce(\n (prevValue, currValue) => {\n if (currValue.TRNTYPE.toLocaleLowerCase().startsWith('deb')) {\n prevValue.amountOfDebits++\n prevValue.debit += Number(currValue.TRNAMT.replace('-', ''))\n return prevValue\n }\n prevValue.amountOfCredits++\n prevValue.debit += Number(currValue.TRNAMT)\n return prevValue\n },\n { credit: 0, debit: 0, amountOfCredits: 0, amountOfDebits: 0 },\n )\n}\n","import { ELEMENT_CLOSURE_REGEX, ELEMENT_OPENING_REGEX } from './config'\r\nimport {\r\n convertMetaDataToObject,\r\n extractFinancialInstitutionTransactionId,\r\n fixJsonProblems,\r\n formatDate,\r\n getBankTransferListText,\r\n getTransactionsSummary,\r\n isDateField,\r\n isValidNumberToConvert,\r\n objectEndReplacer,\r\n objectStartReplacer,\r\n trim,\r\n} from './helpers'\r\nimport {\r\n BankTransferList,\r\n OfxConfig,\r\n OFXMetaData,\r\n OfxResponse,\r\n OfxStructure,\r\n} from './types'\r\n\r\nexport class Ofx {\r\n private data: string\r\n private config: OfxConfig = {}\r\n\r\n constructor(data: string | Buffer, config?: OfxConfig) {\r\n if (config) this.config = config\r\n if (data instanceof Buffer) this.data = data.toString()\r\n else this.data = data\r\n }\r\n\r\n getHeaders(): OFXMetaData {\r\n const [metaDataString] = this.data.split('<OFX>')\r\n const metaDataList = metaDataString.split('\\n')\r\n const validate = (line: string) => !!line.trim().length\r\n const validatedMetaDataList = metaDataList.filter(validate)\r\n return convertMetaDataToObject(\r\n validatedMetaDataList,\r\n !!this.config.nativeTypes,\r\n ) as OFXMetaData\r\n }\r\n\r\n getBankTransferList(): Pick<BankTransferList, 'STRTTRN'> {\r\n const { newListText } = getBankTransferListText(this.getPartialJsonData())\r\n\r\n const list = newListText.slice(10)\r\n const fixedList = fixJsonProblems(list)\r\n return JSON.parse(fixedList)\r\n }\r\n\r\n private getPartialJsonData() {\r\n const [_, ofxContentText] = this.data.split('<OFX>')\r\n const ofxContent = '<OFX>' + ofxContentText\r\n const { sanitize } = this\r\n /**\r\n * Use replace first for closing tag so there is no conflict in `objectStartReplacer`\r\n */\r\n return ofxContent\r\n .replace(ELEMENT_CLOSURE_REGEX, objectEndReplacer)\r\n .replace(ELEMENT_OPENING_REGEX, objectStartReplacer)\r\n .split('\\n')\r\n .map(trim)\r\n .filter(Boolean)\r\n .map(sanitize, this)\r\n .join('')\r\n }\r\n\r\n private sanitizeValue(field: string, value: string) {\r\n let fieldValue = value.replace(/[{},]/g, '')\r\n if (isDateField(field)) {\r\n fieldValue = this.configDate(fieldValue)\r\n } else if (field === 'FITID') {\r\n return this.configFinancialInstitutionTransactionId(fieldValue)\r\n } else if (\r\n this.config.nativeTypes &&\r\n isValidNumberToConvert(field, fieldValue)\r\n ) {\r\n return `${fieldValue},`\r\n }\r\n return `\"${fieldValue}\",`\r\n }\r\n\r\n private sanitize(line: string) {\r\n let sanitizedLine = line\r\n const field = sanitizedLine.slice(0, sanitizedLine.indexOf(':'))\r\n const sanitizeValue = this.sanitizeValue\r\n const replacer = (matched: string) =>\r\n sanitizeValue.call(this, field, matched)\r\n if (line.match(/{(\\w|\\W)+/)) {\r\n sanitizedLine = sanitizedLine.replace(/({(\\w|\\W)+)$/, replacer)\r\n }\r\n const matchedProperty = sanitizedLine.search(/(^\\w+:)/)\r\n if (matchedProperty < 0) return sanitizedLine\r\n\r\n return sanitizedLine.replace(field, `\"${field}\"`)\r\n }\r\n\r\n private configFinancialInstitutionTransactionId(fitString: string) {\r\n const { fitId } = this.config\r\n if (fitId === 'separated')\r\n return extractFinancialInstitutionTransactionId(fitString)\r\n return `\"${fitString}\",`\r\n }\r\n\r\n private configDate(dateString: string) {\r\n const { formatDate: format } = this.config\r\n if (format) return formatDate(dateString, format)\r\n return formatDate(dateString, 'y-M-d')\r\n }\r\n\r\n getTransactionsSummary() {\r\n const jsonData = this.getContent()\r\n const { DTEND, DTSTART, STRTTRN } =\r\n jsonData.OFX.BANKMSGSRSV1.STMTTRNRS.STMTRS.BANKTRANLIST\r\n const summary = getTransactionsSummary(STRTTRN)\r\n return {\r\n dateStart: DTSTART,\r\n dateEnd: DTEND,\r\n ...summary,\r\n }\r\n }\r\n\r\n getContent(): OfxStructure {\r\n const ofxText = this.getPartialJsonData()\r\n const { newListText, oldListText } = getBankTransferListText(ofxText)\r\n const result = ofxText.replace(oldListText, newListText)\r\n return JSON.parse(`{${fixJsonProblems(result)}}`)\r\n }\r\n\r\n toJson(): OfxResponse {\r\n const ofxMetaDataResult = this.getHeaders()\r\n const ofxContentResult = this.getContent()\r\n const result = { ...ofxMetaDataResult, ...ofxContentResult }\r\n return result\r\n }\r\n}\r\n"],"names":["ELEMENT_CLOSURE_REGEX","ELEMENT_OPENING_REGEX","START_TEXT_BANK_TRANSFER","END_TEXT_BANK_TRANSFER","separatePartsOfDate","date","year","month","day","hour","minutes","seconds","offset","timezone","formatDate","format","parts","result","key","value","fixJsonProblems","content","extractFinancialInstitutionTransactionId","fitid","dateText","transactionCode","protocol","resultObject","isDateField","field","trim","str","objectStartReplacer","param","objectEndReplacer","isValidNumberToConvert","getBankTransferListText","ofxContent","startIndex","endIndex","oldListText","startRgx","endRgx","newListText","convertMetaDataToObject","stringList","nativeTypes","line","sanitizedKey","getTransactionsSummary","STRTTRN","prevValue","currValue","Ofx","data","config","metaDataString","metaDataList","validate","validatedMetaDataList","list","fixedList","_","ofxContentText","sanitize","fieldValue","sanitizedLine","sanitizeValue","replacer","matched","fitString","fitId","dateString","jsonData","DTEND","DTSTART","summary","ofxText","ofxMetaDataResult","ofxContentResult"],"mappings":"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"}
|
package/dist/main.d.ts
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
/// <reference types="node" />
|
|
2
|
-
import { BankTransferList, OfxConfig, OFXMetaData, OfxResponse, OfxStructure } from './types';
|
|
3
|
-
export declare class Ofx {
|
|
4
|
-
private data;
|
|
5
|
-
private config;
|
|
6
|
-
constructor(data: string | Buffer, config?: OfxConfig);
|
|
7
|
-
getHeaders(): OFXMetaData;
|
|
8
|
-
getBankTransferList(): Pick<BankTransferList, 'STRTTRN'>;
|
|
9
|
-
private getPartialJsonData;
|
|
10
|
-
private sanitizeValue;
|
|
11
|
-
private sanitize;
|
|
12
|
-
private configFinancialInstitutionTransactionId;
|
|
13
|
-
private configDate;
|
|
14
|
-
getTransactionsSummary(): {
|
|
15
|
-
credit: number;
|
|
16
|
-
debit: number;
|
|
17
|
-
amountOfCredits: number;
|
|
18
|
-
amountOfDebits: number;
|
|
19
|
-
dateStart: import("./types").DateResponse;
|
|
20
|
-
dateEnd: import("./types").DateResponse;
|
|
21
|
-
};
|
|
22
|
-
getContent(): OfxStructure;
|
|
23
|
-
toJson(): OfxResponse;
|
|
24
|
-
}
|
package/dist/types.d.ts
DELETED
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
export type OFXMetaData = {
|
|
2
|
-
OFXHEADER: string;
|
|
3
|
-
DATA: string;
|
|
4
|
-
VERSION: string;
|
|
5
|
-
SECURITY: string;
|
|
6
|
-
ENCODING: string;
|
|
7
|
-
CHARSET: string;
|
|
8
|
-
COMPRESSION: string;
|
|
9
|
-
OLDFILEUID: string;
|
|
10
|
-
NEWFILEUID: string;
|
|
11
|
-
};
|
|
12
|
-
export type DateResponse = {
|
|
13
|
-
datetime: string | null;
|
|
14
|
-
date: string | null;
|
|
15
|
-
time: string | null;
|
|
16
|
-
offset: string | null;
|
|
17
|
-
timezone: string | null;
|
|
18
|
-
};
|
|
19
|
-
/**
|
|
20
|
-
* separated - returns the separate transaction id:
|
|
21
|
-
* "date": string,
|
|
22
|
-
* "transactionCode": string,
|
|
23
|
-
* "protocol": string
|
|
24
|
-
*/
|
|
25
|
-
type ConfigFitId = 'normal' | 'separated';
|
|
26
|
-
export type ConfigDate = {
|
|
27
|
-
/**
|
|
28
|
-
* @description supported keys:
|
|
29
|
-
* yy => year -> 2 digits,
|
|
30
|
-
* yyyy or y => year,
|
|
31
|
-
* MM or M => month,
|
|
32
|
-
* dd or d => day,
|
|
33
|
-
* hh or h => hour,
|
|
34
|
-
* mm or m => minute,
|
|
35
|
-
* ss or s => second,
|
|
36
|
-
* O => offset,
|
|
37
|
-
* TZ => timezone
|
|
38
|
-
* @example format: 'y-M-d h:m:s'
|
|
39
|
-
* @returns '2022-02-21 09:00:00'
|
|
40
|
-
*/
|
|
41
|
-
formatDate?: string;
|
|
42
|
-
};
|
|
43
|
-
type MapKeys<T> = {
|
|
44
|
-
[Property in keyof T]?: string;
|
|
45
|
-
};
|
|
46
|
-
type KeysJson = MapKeys<Status | BankAccountFrom | STRTTRN | BankTransferList | LedGerBal | FINANCIAL_INSTITUTION | OfxStructure>;
|
|
47
|
-
export type OfxConfig = ConfigDate & {
|
|
48
|
-
fitId?: ConfigFitId;
|
|
49
|
-
nativeTypes?: boolean;
|
|
50
|
-
formatJson?: MapKeys<KeysJson>;
|
|
51
|
-
};
|
|
52
|
-
export type Status = {
|
|
53
|
-
CODE: string;
|
|
54
|
-
SEVERITY: string;
|
|
55
|
-
};
|
|
56
|
-
export type BankAccountFrom = {
|
|
57
|
-
BANKID: string;
|
|
58
|
-
ACCTID: string;
|
|
59
|
-
ACCTT: string;
|
|
60
|
-
};
|
|
61
|
-
type TransferType = string;
|
|
62
|
-
export type STRTTRN = {
|
|
63
|
-
TRNTYPE: TransferType;
|
|
64
|
-
DTPOSTED: DateResponse;
|
|
65
|
-
TRNAMT: string;
|
|
66
|
-
FITID: string;
|
|
67
|
-
CHECKNUM: string;
|
|
68
|
-
MEMO: string;
|
|
69
|
-
};
|
|
70
|
-
export type BankTransferList = {
|
|
71
|
-
DTSTART: DateResponse;
|
|
72
|
-
DTEND: DateResponse;
|
|
73
|
-
STRTTRN: STRTTRN[];
|
|
74
|
-
};
|
|
75
|
-
export type LedGerBal = {
|
|
76
|
-
BALAMT: string;
|
|
77
|
-
DTASOF: DateResponse;
|
|
78
|
-
};
|
|
79
|
-
export type FINANCIAL_INSTITUTION = {
|
|
80
|
-
ORG: string;
|
|
81
|
-
FID: string;
|
|
82
|
-
};
|
|
83
|
-
export type OfxStructure = {
|
|
84
|
-
OFX: {
|
|
85
|
-
SIGNONMSGSRSV1: {
|
|
86
|
-
SONRS: {
|
|
87
|
-
STATUS: Status;
|
|
88
|
-
DTSERVER: DateResponse;
|
|
89
|
-
LANGUAGE: string;
|
|
90
|
-
DTACCTUP: DateResponse;
|
|
91
|
-
FI: FINANCIAL_INSTITUTION;
|
|
92
|
-
};
|
|
93
|
-
};
|
|
94
|
-
BANKMSGSRSV1: {
|
|
95
|
-
STMTTRNRS: {
|
|
96
|
-
TRNUID: number;
|
|
97
|
-
STATUS: Status;
|
|
98
|
-
STMTRS: {
|
|
99
|
-
CURDEF: string;
|
|
100
|
-
BANKACCTFROM: BankAccountFrom;
|
|
101
|
-
BANKTRANLIST: BankTransferList;
|
|
102
|
-
LEDGERBAL: LedGerBal;
|
|
103
|
-
MKTGINFO: string;
|
|
104
|
-
};
|
|
105
|
-
};
|
|
106
|
-
};
|
|
107
|
-
};
|
|
108
|
-
};
|
|
109
|
-
export type OfxResponse = OFXMetaData & OfxStructure;
|
|
110
|
-
export {};
|