@coderoftime/fints 0.2.0 → 0.3.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/CHANGELOG.md +377 -0
- package/README.md +31 -23
- package/dist/client.d.ts +3 -2
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +52 -9
- package/dist/client.js.map +1 -1
- package/dist/core/account.d.ts +15 -4
- package/dist/core/account.d.ts.map +1 -1
- package/dist/core/account.js +84 -36
- package/dist/core/account.js.map +1 -1
- package/dist/core/amount.d.ts +13 -3
- package/dist/core/amount.d.ts.map +1 -1
- package/dist/core/amount.js +42 -8
- package/dist/core/amount.js.map +1 -1
- package/dist/core/balance.d.ts +3 -0
- package/dist/core/balance.d.ts.map +1 -1
- package/dist/core/balance.js +5 -0
- package/dist/core/balance.js.map +1 -1
- package/dist/core/bank-info.d.ts +20 -3
- package/dist/core/bank-info.d.ts.map +1 -1
- package/dist/core/bank-info.js +25 -4
- package/dist/core/bank-info.js.map +1 -1
- package/dist/core/client.d.ts +42 -15
- package/dist/core/client.d.ts.map +1 -1
- package/dist/core/config.d.ts +15 -7
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/config.js +29 -14
- package/dist/core/config.js.map +1 -1
- package/dist/core/errors.d.ts +17 -5
- package/dist/core/errors.d.ts.map +1 -1
- package/dist/core/errors.js +25 -7
- package/dist/core/errors.js.map +1 -1
- package/dist/core/feedback.d.ts +7 -0
- package/dist/core/feedback.d.ts.map +1 -1
- package/dist/core/feedback.js +10 -1
- package/dist/core/feedback.js.map +1 -1
- package/dist/core/transaction.d.ts +5 -0
- package/dist/core/transaction.d.ts.map +1 -1
- package/dist/core/transaction.js +12 -0
- package/dist/core/transaction.js.map +1 -1
- package/dist/core/transport.d.ts +22 -7
- package/dist/core/transport.d.ts.map +1 -1
- package/dist/core/transport.js +51 -11
- package/dist/core/transport.js.map +1 -1
- package/dist/formats/camt.d.ts +7 -4
- package/dist/formats/camt.d.ts.map +1 -1
- package/dist/formats/camt.js +53 -54
- package/dist/formats/camt.js.map +1 -1
- package/dist/formats/mt940.d.ts +18 -6
- package/dist/formats/mt940.d.ts.map +1 -1
- package/dist/formats/mt940.js +83 -66
- package/dist/formats/mt940.js.map +1 -1
- package/dist/formats/readers.d.ts.map +1 -1
- package/dist/formats/readers.js +6 -2
- package/dist/formats/readers.js.map +1 -1
- package/dist/formats/sepa-purpose.d.ts +7 -4
- package/dist/formats/sepa-purpose.d.ts.map +1 -1
- package/dist/formats/sepa-purpose.js +18 -9
- package/dist/formats/sepa-purpose.js.map +1 -1
- package/dist/session/dialog-runner.d.ts +5 -2
- package/dist/session/dialog-runner.d.ts.map +1 -1
- package/dist/session/dialog-runner.js +23 -7
- package/dist/session/dialog-runner.js.map +1 -1
- package/dist/session/login-guard.d.ts +4 -4
- package/dist/session/login-guard.d.ts.map +1 -1
- package/dist/session/login-guard.js +29 -14
- package/dist/session/login-guard.js.map +1 -1
- package/dist/session/session-setup.d.ts +14 -5
- package/dist/session/session-setup.d.ts.map +1 -1
- package/dist/session/session-setup.js +30 -9
- package/dist/session/session-setup.js.map +1 -1
- package/dist/session/session-state.d.ts +4 -3
- package/dist/session/session-state.d.ts.map +1 -1
- package/dist/session/session-state.js +28 -9
- package/dist/session/session-state.js.map +1 -1
- package/dist/session/signed-dialog.d.ts +19 -13
- package/dist/session/signed-dialog.d.ts.map +1 -1
- package/dist/session/signed-dialog.js +45 -30
- package/dist/session/signed-dialog.js.map +1 -1
- package/dist/session/user-prompts.d.ts +6 -1
- package/dist/session/user-prompts.d.ts.map +1 -1
- package/dist/session/user-prompts.js +19 -4
- package/dist/session/user-prompts.js.map +1 -1
- package/dist/tan/challenge.d.ts +15 -13
- package/dist/tan/challenge.d.ts.map +1 -1
- package/dist/tan/challenge.js +32 -26
- package/dist/tan/challenge.js.map +1 -1
- package/dist/tan/flicker.d.ts +5 -1
- package/dist/tan/flicker.d.ts.map +1 -1
- package/dist/tan/flicker.js +42 -30
- package/dist/tan/flicker.js.map +1 -1
- package/dist/tan/tan-image.d.ts +4 -1
- package/dist/tan/tan-image.d.ts.map +1 -1
- package/dist/tan/tan-image.js +8 -2
- package/dist/tan/tan-image.js.map +1 -1
- package/dist/tan/tan-models.d.ts +9 -1
- package/dist/tan/tan-models.d.ts.map +1 -1
- package/dist/tan/tan-models.js +14 -2
- package/dist/tan/tan-models.js.map +1 -1
- package/dist/util/arguments.d.ts +13 -0
- package/dist/util/arguments.d.ts.map +1 -0
- package/dist/util/arguments.js +40 -0
- package/dist/util/arguments.js.map +1 -0
- package/dist/util/async.d.ts +4 -1
- package/dist/util/async.d.ts.map +1 -1
- package/dist/util/async.js +6 -3
- package/dist/util/async.js.map +1 -1
- package/dist/util/bytes.d.ts +1 -1
- package/dist/util/bytes.d.ts.map +1 -1
- package/dist/util/bytes.js +3 -3
- package/dist/util/bytes.js.map +1 -1
- package/dist/util/dates.d.ts +3 -10
- package/dist/util/dates.d.ts.map +1 -1
- package/dist/util/dates.js +49 -39
- package/dist/util/dates.js.map +1 -1
- package/dist/util/errors.d.ts +5 -3
- package/dist/util/errors.d.ts.map +1 -1
- package/dist/util/errors.js +8 -4
- package/dist/util/errors.js.map +1 -1
- package/dist/util/immutable-map.d.ts +5 -2
- package/dist/util/immutable-map.d.ts.map +1 -1
- package/dist/util/immutable-map.js +15 -12
- package/dist/util/immutable-map.js.map +1 -1
- package/dist/util/inspect.d.ts +11 -0
- package/dist/util/inspect.d.ts.map +1 -0
- package/dist/util/inspect.js +14 -0
- package/dist/util/inspect.js.map +1 -0
- package/dist/util/text.d.ts +18 -2
- package/dist/util/text.d.ts.map +1 -1
- package/dist/util/text.js +50 -5
- package/dist/util/text.js.map +1 -1
- package/dist/util/xml.d.ts +6 -4
- package/dist/util/xml.d.ts.map +1 -1
- package/dist/util/xml.js +106 -44
- package/dist/util/xml.js.map +1 -1
- package/dist/v3/bank-connection.d.ts +23 -3
- package/dist/v3/bank-connection.d.ts.map +1 -1
- package/dist/v3/bank-connection.js +66 -6
- package/dist/v3/bank-connection.js.map +1 -1
- package/dist/v3/dialog.d.ts +6 -2
- package/dist/v3/dialog.d.ts.map +1 -1
- package/dist/v3/dialog.js +20 -9
- package/dist/v3/dialog.js.map +1 -1
- package/dist/v3/message.d.ts +18 -10
- package/dist/v3/message.d.ts.map +1 -1
- package/dist/v3/message.js +92 -75
- package/dist/v3/message.js.map +1 -1
- package/dist/v3/parameter-store.d.ts +43 -7
- package/dist/v3/parameter-store.d.ts.map +1 -1
- package/dist/v3/parameter-store.js +69 -15
- package/dist/v3/parameter-store.js.map +1 -1
- package/dist/v3/parameters.d.ts +12 -11
- package/dist/v3/parameters.d.ts.map +1 -1
- package/dist/v3/parameters.js +57 -35
- package/dist/v3/parameters.js.map +1 -1
- package/dist/v3/protocol.d.ts +16 -9
- package/dist/v3/protocol.d.ts.map +1 -1
- package/dist/v3/protocol.js +57 -26
- package/dist/v3/protocol.js.map +1 -1
- package/dist/v3/queries.d.ts +2 -2
- package/dist/v3/queries.d.ts.map +1 -1
- package/dist/v3/queries.js +24 -16
- package/dist/v3/queries.js.map +1 -1
- package/dist/v3/segments.d.ts +18 -11
- package/dist/v3/segments.d.ts.map +1 -1
- package/dist/v3/segments.js +30 -21
- package/dist/v3/segments.js.map +1 -1
- package/dist/v3/syntax.d.ts +15 -11
- package/dist/v3/syntax.d.ts.map +1 -1
- package/dist/v3/syntax.js +30 -15
- package/dist/v3/syntax.js.map +1 -1
- package/package.json +1 -1
- package/src/client.ts +58 -17
- package/src/core/account.ts +91 -35
- package/src/core/amount.ts +42 -9
- package/src/core/balance.ts +6 -0
- package/src/core/bank-info.ts +28 -4
- package/src/core/client.ts +42 -15
- package/src/core/config.ts +37 -18
- package/src/core/errors.ts +27 -7
- package/src/core/feedback.ts +12 -1
- package/src/core/transaction.ts +13 -0
- package/src/core/transport.ts +62 -16
- package/src/formats/camt.ts +62 -51
- package/src/formats/mt940.ts +114 -78
- package/src/formats/readers.ts +6 -2
- package/src/formats/sepa-purpose.ts +17 -9
- package/src/session/dialog-runner.ts +34 -7
- package/src/session/login-guard.ts +29 -13
- package/src/session/session-setup.ts +27 -9
- package/src/session/session-state.ts +25 -8
- package/src/session/signed-dialog.ts +60 -30
- package/src/session/user-prompts.ts +28 -3
- package/src/tan/challenge.ts +50 -36
- package/src/tan/flicker.ts +40 -29
- package/src/tan/tan-image.ts +9 -2
- package/src/tan/tan-models.ts +16 -2
- package/src/util/arguments.ts +40 -0
- package/src/util/async.ts +10 -4
- package/src/util/bytes.ts +3 -3
- package/src/util/dates.ts +52 -38
- package/src/util/errors.ts +9 -4
- package/src/util/immutable-map.ts +15 -12
- package/src/util/inspect.ts +14 -0
- package/src/util/text.ts +47 -5
- package/src/util/xml.ts +105 -38
- package/src/v3/bank-connection.ts +65 -6
- package/src/v3/dialog.ts +18 -8
- package/src/v3/message.ts +81 -72
- package/src/v3/parameter-store.ts +82 -16
- package/src/v3/parameters.ts +68 -41
- package/src/v3/protocol.ts +61 -28
- package/src/v3/queries.ts +26 -18
- package/src/v3/segments.ts +32 -20
- package/src/v3/syntax.ts +31 -14
package/dist/v3/syntax.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// Internal to the package, and named after the FinTS specification. Documentation is where the meaning is not evident.
|
|
2
2
|
import { BytesBuilder, latin1Decode, latin1Encode, utf8Encode } from '../util/bytes.js';
|
|
3
3
|
import { FormatError } from '../util/errors.js';
|
|
4
|
-
import { decodeBankText, isLatin1, tryParseInt } from '../util/text.js';
|
|
4
|
+
import { decodeBankText, isLatin1, trimBlanks, tryParseInt } from '../util/text.js';
|
|
5
5
|
// FinTS 3.0 syntax characters.
|
|
6
6
|
const dataElementSeparator = 0x2b; // '+'
|
|
7
7
|
const groupElementSeparator = 0x3a; // ':'
|
|
@@ -58,6 +58,7 @@ export class Segment {
|
|
|
58
58
|
source;
|
|
59
59
|
start;
|
|
60
60
|
end;
|
|
61
|
+
typeValue;
|
|
61
62
|
constructor(elements,
|
|
62
63
|
/** The bytes the segment was read from: `start` to `end` in `source`, terminator included. */
|
|
63
64
|
source, start, end) {
|
|
@@ -67,7 +68,8 @@ export class Segment {
|
|
|
67
68
|
this.end = end;
|
|
68
69
|
}
|
|
69
70
|
get type() {
|
|
70
|
-
|
|
71
|
+
this.typeValue ??= trimBlanks(this.text(0) ?? '');
|
|
72
|
+
return this.typeValue;
|
|
71
73
|
}
|
|
72
74
|
get version() {
|
|
73
75
|
return this.integer(0, 2) ?? 0;
|
|
@@ -92,6 +94,11 @@ export class Segment {
|
|
|
92
94
|
const e = this.element(index, sub);
|
|
93
95
|
return e?.isBinary === true ? e.bytes : undefined;
|
|
94
96
|
}
|
|
97
|
+
/** The binary data or the text without escape characters at `index`; `undefined` for an empty element. */
|
|
98
|
+
bytes(index, sub = 0) {
|
|
99
|
+
const e = this.element(index, sub);
|
|
100
|
+
return e === undefined || e.isEmpty ? undefined : e.bytes;
|
|
101
|
+
}
|
|
95
102
|
/**
|
|
96
103
|
* The element at `index` as the bank sent it, for a value the client sends back, such as the dialog ID: untrimmed,
|
|
97
104
|
* and one character per byte (ISO 8859-1, the FinTS 3.0 character set), so that `Verbatim` gives the bank back the
|
|
@@ -104,7 +111,7 @@ export class Segment {
|
|
|
104
111
|
return latin1Decode(e.bytes);
|
|
105
112
|
}
|
|
106
113
|
integer(index, sub = 0) {
|
|
107
|
-
return tryParseInt(this.text(index, sub)
|
|
114
|
+
return tryParseInt(this.text(index, sub));
|
|
108
115
|
}
|
|
109
116
|
/** The texts of the group at `index`; `undefined` for empty elements. */
|
|
110
117
|
texts(index) {
|
|
@@ -139,16 +146,19 @@ export function encodeText(value) {
|
|
|
139
146
|
return isLatin1(value) ? latin1Encode(value) : utf8Encode(value);
|
|
140
147
|
}
|
|
141
148
|
/**
|
|
142
|
-
* The data elements one
|
|
143
|
-
* parameter data of
|
|
144
|
-
*
|
|
149
|
+
* The data elements and segments one parse may produce together, segment headers and group elements included: what
|
|
150
|
+
* the user parameter data of 6,000 accounts take, at about 155 data elements each, which is about what 9,999 KB, the
|
|
151
|
+
* largest message size HIBPA can state, hold of real data. Without a limit, a message of nothing but separators would
|
|
152
|
+
* take a hundred times its size in memory.
|
|
153
|
+
*
|
|
154
|
+
* @internal Exported for the tests.
|
|
145
155
|
*/
|
|
146
|
-
export const
|
|
156
|
+
export const maxParts = 1_000_000;
|
|
147
157
|
/**
|
|
148
|
-
*
|
|
149
|
-
*
|
|
158
|
+
* What `IncomingMessage3.size` counts for each data element it keeps: more than any of them takes once parsed, so that
|
|
159
|
+
* a message of many short elements counts as the memory it holds rather than its bytes.
|
|
150
160
|
*/
|
|
151
|
-
export const
|
|
161
|
+
export const parsedElementBytes = 512;
|
|
152
162
|
/** Every empty data element of a received segment; it has no bytes to change. */
|
|
153
163
|
const emptyElement = new DataElement(new Uint8Array(0), 0, 0, false);
|
|
154
164
|
function isSeparator(byte) {
|
|
@@ -166,10 +176,15 @@ function isDigit(byte) {
|
|
|
166
176
|
*
|
|
167
177
|
* The elements share the memory of `data`. Throws `FormatError` for anything a complete message cannot hold: a
|
|
168
178
|
* malformed binary length, binary data beyond the end of `data` or not followed by a separator, a last segment without
|
|
169
|
-
* terminator, and more
|
|
179
|
+
* terminator, and more than `maxParts` data elements and segments, an empty one included.
|
|
170
180
|
*/
|
|
171
|
-
export function parseSegments(data
|
|
181
|
+
export function parseSegments(data) {
|
|
172
182
|
const segments = [];
|
|
183
|
+
let parts = 0;
|
|
184
|
+
const count = () => {
|
|
185
|
+
if (++parts > maxParts)
|
|
186
|
+
throw new FormatError(`More than ${maxParts} data elements and segments`);
|
|
187
|
+
};
|
|
173
188
|
// Created with their first element: an array that starts empty reserves room for more than most of them hold.
|
|
174
189
|
let elements;
|
|
175
190
|
let group;
|
|
@@ -212,8 +227,7 @@ export function parseSegments(data, budget = { elements: maxDataElements }) {
|
|
|
212
227
|
i++;
|
|
213
228
|
continue;
|
|
214
229
|
}
|
|
215
|
-
|
|
216
|
-
throw new FormatError('Too many data elements');
|
|
230
|
+
count();
|
|
217
231
|
if (elements === undefined && group === undefined)
|
|
218
232
|
segmentStart = i;
|
|
219
233
|
const element = data[i] === binaryMarker ? readBinary() : readText();
|
|
@@ -230,6 +244,7 @@ export function parseSegments(data, budget = { elements: maxDataElements }) {
|
|
|
230
244
|
elements.push(group);
|
|
231
245
|
group = undefined;
|
|
232
246
|
if (separator === segmentTerminator) {
|
|
247
|
+
count();
|
|
233
248
|
const segment = new Segment(elements, data, segmentStart, i);
|
|
234
249
|
// Skip empty segments, such as a stray double terminator.
|
|
235
250
|
if (segment.type !== '')
|
|
@@ -360,7 +375,7 @@ function encodeValue(value) {
|
|
|
360
375
|
else {
|
|
361
376
|
// All but binary data go without leading and trailing blanks (Formals B.4.1). Encode first, then escape the bytes,
|
|
362
377
|
// so that nothing unescaped slips into the syntax.
|
|
363
|
-
writeEscaped(out, encodeText(String(value)
|
|
378
|
+
writeEscaped(out, encodeText(trimBlanks(String(value))));
|
|
364
379
|
}
|
|
365
380
|
return out.takeBytes();
|
|
366
381
|
}
|
package/dist/v3/syntax.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"syntax.js","sourceRoot":"","sources":["../../src/v3/syntax.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"syntax.js","sourceRoot":"","sources":["../../src/v3/syntax.ts"],"names":[],"mappings":"AAAA,uHAAuH;AAEvH,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACxF,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAEpF,+BAA+B;AAC/B,MAAM,oBAAoB,GAAG,IAAI,CAAC,CAAC,MAAM;AACzC,MAAM,qBAAqB,GAAG,IAAI,CAAC,CAAC,MAAM;AAC1C,MAAM,iBAAiB,GAAG,IAAI,CAAC,CAAC,MAAM;AACtC,MAAM,eAAe,GAAG,IAAI,CAAC,CAAC,MAAM;AACpC,MAAM,YAAY,GAAG,IAAI,CAAC,CAAC,MAAM;AAEjC,SAAS,iBAAiB,CAAC,IAAY;IACrC,OAAO,CACL,IAAI,KAAK,oBAAoB;QAC7B,IAAI,KAAK,qBAAqB;QAC9B,IAAI,KAAK,iBAAiB;QAC1B,IAAI,KAAK,eAAe;QACxB,IAAI,KAAK,YAAY,CACtB,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,OAAO,WAAW;IAIH;IACA;IACA;IACR;IAEQ;IARX,OAAO,CAAqB;IAEpC,YACmB,MAAkB,EAClB,KAAa,EACb,GAAW,EACnB,QAAiB;IAC1B,0EAA0E;IACzD,UAAU,KAAK;QALf,WAAM,GAAN,MAAM,CAAY;QAClB,UAAK,GAAL,KAAK,CAAQ;QACb,QAAG,GAAH,GAAG,CAAQ;QACnB,aAAQ,GAAR,QAAQ,CAAS;QAET,YAAO,GAAP,OAAO,CAAQ;IAC/B,CAAC;IAEJ,8DAA8D;IAC9D,IAAI,KAAK;QACP,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;QACzD,OAAO,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;IAChD,CAAC;IAED,IAAI,OAAO;QACT,OAAO,CAAC,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,KAAK,KAAK,IAAI,CAAC,GAAG,CAAC;IACnD,CAAC;IAED,IAAI,IAAI;QACN,IAAI,CAAC,OAAO,KAAK,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC5C,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;CACF;AAED;;;;GAIG;AACH,MAAM,OAAO,OAAO;IAIP;IAEQ;IACA;IACA;IAPX,SAAS,CAAqB;IAEtC,YACW,QAA6C;IACtD,8FAA8F;IAC7E,MAAkB,EAClB,KAAa,EACb,GAAW;QAJnB,aAAQ,GAAR,QAAQ,CAAqC;QAErC,WAAM,GAAN,MAAM,CAAY;QAClB,UAAK,GAAL,KAAK,CAAQ;QACb,QAAG,GAAH,GAAG,CAAQ;IAC3B,CAAC;IAEJ,IAAI,IAAI;QACN,IAAI,CAAC,SAAS,KAAK,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;QAClD,OAAO,IAAI,CAAC,SAAS,CAAC;IACxB,CAAC;IAED,IAAI,OAAO;QACT,OAAO,IAAI,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;IACjC,CAAC;IAED,IAAI,MAAM;QACR,OAAO,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC;IAC9B,CAAC;IAED,KAAK,CAAC,KAAa;QACjB,OAAO,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;IACpC,CAAC;IAED,OAAO,CAAC,KAAa,EAAE,GAAG,GAAG,CAAC;QAC5B,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC;IAChC,CAAC;IAED,IAAI,CAAC,KAAa,EAAE,GAAG,GAAG,CAAC;QACzB,MAAM,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QACnC,IAAI,CAAC,KAAK,SAAS,IAAI,CAAC,CAAC,OAAO;YAAE,OAAO,SAAS,CAAC;QACnD,OAAO,CAAC,CAAC,IAAI,CAAC;IAChB,CAAC;IAED,8EAA8E;IAC9E,MAAM,CAAC,KAAa,EAAE,GAAG,GAAG,CAAC;QAC3B,MAAM,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QACnC,OAAO,CAAC,EAAE,QAAQ,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;IACpD,CAAC;IAED,0GAA0G;IAC1G,KAAK,CAAC,KAAa,EAAE,GAAG,GAAG,CAAC;QAC1B,MAAM,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QACnC,OAAO,CAAC,KAAK,SAAS,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;IAC5D,CAAC;IAED;;;;OAIG;IACH,QAAQ,CAAC,KAAa,EAAE,GAAG,GAAG,CAAC;QAC7B,MAAM,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QACnC,IAAI,CAAC,KAAK,SAAS,IAAI,CAAC,CAAC,OAAO;YAAE,OAAO,SAAS,CAAC;QACnD,OAAO,YAAY,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;IAC/B,CAAC;IAED,OAAO,CAAC,KAAa,EAAE,GAAG,GAAG,CAAC;QAC5B,OAAO,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC;IAC5C,CAAC;IAED,yEAAyE;IACzE,KAAK,CAAC,KAAa;QACjB,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;IACxE,CAAC;IAED,uFAAuF;IACvF,MAAM;QACJ,OAAO,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;IACpD,CAAC;CACF;AAED,SAAS,YAAY,CAAC,GAAiB,EAAE,KAAiB;IACxD,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;QACtB,IAAI,iBAAiB,CAAC,CAAC,CAAC;YAAE,OAAO,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;QACxD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IACD,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;AACnB,CAAC;AAED,SAAS,WAAW,CAAC,GAAiB,EAAE,KAAiB;IACvD,GAAG,CAAC,GAAG,CAAC,YAAY,CAAC,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAC3C,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;AACjB,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,UAAU,CAAC,KAAa;IACtC,OAAO,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;AACnE,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,SAAS,CAAC;AAElC;;;GAGG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,GAAG,CAAC;AAEtC,iFAAiF;AACjF,MAAM,YAAY,GAAG,IAAI,WAAW,CAAC,IAAI,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC;AAErE,SAAS,WAAW,CAAC,IAAwB;IAC3C,OAAO,IAAI,KAAK,oBAAoB,IAAI,IAAI,KAAK,qBAAqB,IAAI,IAAI,KAAK,iBAAiB,CAAC;AACvG,CAAC;AAED,wEAAwE;AACxE,SAAS,SAAS,CAAC,IAAY;IAC7B,OAAO,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,IAAI,CAAC;AACzD,CAAC;AAED,SAAS,OAAO,CAAC,IAAwB;IACvC,OAAO,IAAI,KAAK,SAAS,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,CAAC;AAC5D,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,aAAa,CAAC,IAAgB;IAC5C,MAAM,QAAQ,GAAc,EAAE,CAAC;IAC/B,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,MAAM,KAAK,GAAG,GAAS,EAAE;QACvB,IAAI,EAAE,KAAK,GAAG,QAAQ;YAAE,MAAM,IAAI,WAAW,CAAC,aAAa,QAAQ,6BAA6B,CAAC,CAAC;IACpG,CAAC,CAAC;IACF,8GAA8G;IAC9G,IAAI,QAAqC,CAAC;IAC1C,IAAI,KAAgC,CAAC;IACrC,IAAI,YAAY,GAAG,CAAC,CAAC;IACrB,IAAI,CAAC,GAAG,CAAC,CAAC;IAEV,MAAM,UAAU,GAAG,GAAgB,EAAE;QACnC,IAAI,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;QAChB,IAAI,MAAM,GAAG,CAAC,CAAC;QACf,OAAO,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;YAC1B,MAAM,GAAG,MAAM,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,EAAE,CAAE,GAAG,IAAI,CAAC;YAC3C,IAAI,MAAM,GAAG,IAAI,CAAC,MAAM;gBAAE,MAAM,IAAI,WAAW,CAAC,2CAA2C,CAAC,CAAC;QAC/F,CAAC;QACD,IAAI,GAAG,KAAK,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,KAAK,YAAY;YAAE,MAAM,IAAI,WAAW,CAAC,yBAAyB,CAAC,CAAC;QAClG,MAAM,KAAK,GAAG,GAAG,GAAG,CAAC,CAAC;QACtB,IAAI,MAAM,GAAG,IAAI,CAAC,MAAM,GAAG,KAAK;YAAE,MAAM,IAAI,WAAW,CAAC,2CAA2C,CAAC,CAAC;QACrG,CAAC,GAAG,KAAK,GAAG,MAAM,CAAC;QACnB,IAAI,CAAC,GAAG,IAAI,CAAC,MAAM,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAAE,MAAM,IAAI,WAAW,CAAC,yCAAyC,CAAC,CAAC;QAC/G,OAAO,IAAI,WAAW,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC;IAC/C,CAAC,CAAC;IAEF,MAAM,QAAQ,GAAG,GAAgB,EAAE;QACjC,MAAM,KAAK,GAAG,CAAC,CAAC;QAChB,IAAI,OAAO,GAAG,KAAK,CAAC;QACpB,OAAO,CAAC,GAAG,IAAI,CAAC,MAAM,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YAChD,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,eAAe,EAAE,CAAC;gBAChC,OAAO,GAAG,IAAI,CAAC;gBACf,CAAC,EAAE,CAAC;YACN,CAAC;YACD,CAAC,EAAE,CAAC;QACN,CAAC;QACD,IAAI,CAAC,GAAG,IAAI,CAAC,MAAM;YAAE,MAAM,IAAI,WAAW,CAAC,4CAA4C,CAAC,CAAC;QACzF,OAAO,CAAC,KAAK,KAAK,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,WAAW,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;IACtF,CAAC,CAAC;IAEF,OAAO,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;QACvB,IAAI,QAAQ,KAAK,SAAS,IAAI,KAAK,KAAK,SAAS,IAAI,SAAS,CAAC,IAAI,CAAC,CAAC,CAAE,CAAC,EAAE,CAAC;YACzE,CAAC,EAAE,CAAC;YACJ,SAAS;QACX,CAAC;QACD,KAAK,EAAE,CAAC;QACR,IAAI,QAAQ,KAAK,SAAS,IAAI,KAAK,KAAK,SAAS;YAAE,YAAY,GAAG,CAAC,CAAC;QACpE,MAAM,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC,KAAK,YAAY,CAAC,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC;QACrE,IAAI,KAAK,KAAK,SAAS;YAAE,KAAK,GAAG,CAAC,OAAO,CAAC,CAAC;;YACtC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACzB,MAAM,SAAS,GAAG,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC;QAC5B,IAAI,SAAS,KAAK,qBAAqB;YAAE,SAAS;QAClD,IAAI,QAAQ,KAAK,SAAS;YAAE,QAAQ,GAAG,CAAC,KAAK,CAAC,CAAC;;YAC1C,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC1B,KAAK,GAAG,SAAS,CAAC;QAClB,IAAI,SAAS,KAAK,iBAAiB,EAAE,CAAC;YACpC,KAAK,EAAE,CAAC;YACR,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC,QAAQ,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC,CAAC,CAAC;YAC7D,0DAA0D;YAC1D,IAAI,OAAO,CAAC,IAAI,KAAK,EAAE;gBAAE,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YAChD,QAAQ,GAAG,SAAS,CAAC;QACvB,CAAC;IACH,CAAC;IACD,IAAI,QAAQ,KAAK,SAAS,IAAI,KAAK,KAAK,SAAS;QAAE,MAAM,IAAI,WAAW,CAAC,4BAA4B,CAAC,CAAC;IACvG,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,0EAA0E;AAC1E,SAAS,QAAQ,CAAC,IAAgB;IAChC,MAAM,GAAG,GAAG,IAAI,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACxC,IAAI,CAAC,GAAG,CAAC,CAAC;IACV,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,eAAe;YAAE,CAAC,EAAE,CAAC;QACrC,GAAG,CAAC,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC,CAAE,CAAC;IACtB,CAAC;IACD,OAAO,GAAG,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AAC5B,CAAC;AAED,oEAAoE;AACpE,MAAM,OAAO,MAAM;IACI;IAArB,YAAqB,KAAiB;QAAjB,UAAK,GAAL,KAAK,CAAY;IAAG,CAAC;CAC3C;AAED;;;;GAIG;AACH,MAAM,OAAO,QAAQ;IACE;IAArB,YAAqB,IAAY;QAAZ,SAAI,GAAJ,IAAI,CAAQ;IAAG,CAAC;IAErC,uDAAuD;IACvD,MAAM,CAAC,EAAE,CAAC,IAAwB;QAChC,OAAO,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC;IAC7D,CAAC;CACF;AAKD;;;;;;;GAOG;AACH,MAAM,OAAO,WAAW;IAEX;IACA;IACA;IAEA;IALX,YACW,IAAY,EACZ,OAAe,EACf,QAAiC;IAC1C,yFAAyF;IAChF,SAAkB;QAJlB,SAAI,GAAJ,IAAI,CAAQ;QACZ,YAAO,GAAP,OAAO,CAAQ;QACf,aAAQ,GAAR,QAAQ,CAAyB;QAEjC,cAAS,GAAT,SAAS,CAAS;IAC1B,CAAC;IAEJ;;;OAGG;IACH,MAAM,CAAC,QAAQ,CAAC,IAAY,EAAE,OAAe,EAAE,MAA8C;QAC3F,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;QAC9D,MAAM,QAAQ,GAAmB,EAAE,CAAC;QACpC,KAAK,IAAI,MAAM,GAAG,CAAC,EAAE,MAAM,IAAI,KAAK,EAAE,MAAM,EAAE;YAAE,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;QAC9E,OAAO,IAAI,WAAW,CAAC,IAAI,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC;IAClD,CAAC;IAED,yCAAyC;IACzC,KAAK,CAAC,MAAc;QAClB,MAAM,GAAG,GAAG,IAAI,YAAY,EAAE,CAAC;QAC/B,GAAG,CAAC,GAAG,CACL,UAAU,CAAC,GAAG,IAAI,CAAC,IAAI,IAAI,MAAM,IAAI,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,SAAS,EAAE,EAAE,CAAC,CAChH,CAAC;QACF,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;QAC/C,OAAO,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,CAAE,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,CAAC,GAAG,EAAE,CAAC;QACzE,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;YACxB,GAAG,CAAC,OAAO,CAAC,oBAAoB,CAAC,CAAC;YAClC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QACb,CAAC;QACD,GAAG,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC;QAC/B,OAAO,GAAG,CAAC,SAAS,EAAE,CAAC;IACzB,CAAC;CACF;AAKD,SAAS,OAAO,CAAC,KAAmB;IAClC,OAAO,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AAC9B,CAAC;AAED,SAAS,WAAW,CAAC,KAAmB;IACtC,MAAM,KAAK,GAAiB,EAAE,CAAC;IAC/B,MAAM,OAAO,GAAG,CAAC,CAAe,EAAQ,EAAE;QACxC,IAAI,OAAO,CAAC,CAAC,CAAC;YAAE,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;;YAC9B,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;IAClC,CAAC,CAAC;IACF,OAAO,CAAC,KAAK,CAAC,CAAC;IACf,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,CAAE,CAAC,MAAM,KAAK,CAAC;QAAE,KAAK,CAAC,GAAG,EAAE,CAAC;IACnE,MAAM,GAAG,GAAG,IAAI,YAAY,EAAE,CAAC;IAC/B,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE;QACxB,IAAI,CAAC,GAAG,CAAC;YAAE,GAAG,CAAC,OAAO,CAAC,qBAAqB,CAAC,CAAC;QAC9C,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAChB,CAAC,CAAC,CAAC;IACH,OAAO,GAAG,CAAC,SAAS,EAAE,CAAC;AACzB,CAAC;AAED,SAAS,WAAW,CAAC,KAAkB;IACrC,MAAM,GAAG,GAAG,IAAI,YAAY,EAAE,CAAC;IAC/B,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QAC1C,SAAS;IACX,CAAC;SAAM,IAAI,KAAK,YAAY,MAAM,EAAE,CAAC;QACnC,WAAW,CAAC,GAAG,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;IAChC,CAAC;SAAM,IAAI,KAAK,YAAY,QAAQ,EAAE,CAAC;QACrC,YAAY,CAAC,GAAG,EAAE,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;IAC5C,CAAC;SAAM,IAAI,OAAO,KAAK,KAAK,SAAS,EAAE,CAAC;QACtC,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,aAAa;IACjD,CAAC;SAAM,CAAC;QACN,mHAAmH;QACnH,mDAAmD;QACnD,YAAY,CAAC,GAAG,EAAE,UAAU,CAAC,UAAU,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAC3D,CAAC;IACD,OAAO,GAAG,CAAC,SAAS,EAAE,CAAC;AACzB,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@coderoftime/fints",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "FinTS 3.0 client for German banks: accounts, balances and transactions with PIN/TAN, PSD2 strong customer authentication and decoupled app approval.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"fints",
|
package/src/client.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { Account } from './core/account.js';
|
|
2
2
|
import type { Balance } from './core/balance.js';
|
|
3
3
|
import type { BankInfo } from './core/bank-info.js';
|
|
4
4
|
import type { FinTsClient, FinTsClientOptions, TransactionQuery } from './core/client.js';
|
|
5
5
|
import { FinTsConfig, requirePin, type FinTsConfigInit } from './core/config.js';
|
|
6
6
|
import { FinTsStateError, FinTsUnsupportedError, type FinTsLoginRefusedError } from './core/errors.js';
|
|
7
|
-
import type { Transaction } from './core/transaction.js';
|
|
7
|
+
import type { Transaction, TransactionFormat } from './core/transaction.js';
|
|
8
|
+
import type { FinTsTransport } from './core/transport.js';
|
|
8
9
|
import { DialogRunner } from './session/dialog-runner.js';
|
|
9
10
|
import { LoginGuard } from './session/login-guard.js';
|
|
10
11
|
import { SepaAccounts } from './session/sepa-accounts.js';
|
|
@@ -13,6 +14,7 @@ import { restoreSession, saveSession, type SessionState } from './session/sessio
|
|
|
13
14
|
import { TanSelection } from './session/tan-selection.js';
|
|
14
15
|
import { UserPrompts } from './session/user-prompts.js';
|
|
15
16
|
import { TanMedium, type TanMethod } from './tan/tan-models.js';
|
|
17
|
+
import { optionalString, requireString } from './util/arguments.js';
|
|
16
18
|
import { SerialExecutor } from './util/async.js';
|
|
17
19
|
import { CallContext } from './util/call-context.js';
|
|
18
20
|
import { calendarDay, notAfterToday } from './util/dates.js';
|
|
@@ -39,6 +41,24 @@ export interface FinTs3ClientInit {
|
|
|
39
41
|
/** A token of the client call running now, so that a call from inside its callbacks is recognized. */
|
|
40
42
|
const runningCalls = new CallContext<object>();
|
|
41
43
|
|
|
44
|
+
/**
|
|
45
|
+
* `transport`, `undefined` for `null`; throws `TypeError` unless it is neither or has the functions of a
|
|
46
|
+
* `FinTsTransport`.
|
|
47
|
+
*/
|
|
48
|
+
function optionalTransport(transport: unknown): FinTsTransport | undefined {
|
|
49
|
+
if (transport === undefined || transport === null) return undefined;
|
|
50
|
+
const candidate = transport as Partial<FinTsTransport>;
|
|
51
|
+
if (typeof candidate.post !== 'function' || typeof candidate.close !== 'function') {
|
|
52
|
+
throw invalidArgument('Must have the functions post and close', 'transport');
|
|
53
|
+
}
|
|
54
|
+
return transport as FinTsTransport;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** Throws `TypeError` for anything but an `Account`, such as one written to JSON and read back. */
|
|
58
|
+
function requireAccount(account: unknown): void {
|
|
59
|
+
if (!(account instanceof Account)) throw invalidArgument('Must be an Account', 'account');
|
|
60
|
+
}
|
|
61
|
+
|
|
42
62
|
/**
|
|
43
63
|
* The calendar day of `bound`, the `name` bound of a `TransactionQuery`: the bank takes dates without time of day.
|
|
44
64
|
* Throws `TypeError` for anything but a valid `Date`, such as an Invalid Date, which would go out as `0NaNNaNNaN`.
|
|
@@ -49,6 +69,16 @@ function requestedDay(bound: unknown, name: string): Date | undefined {
|
|
|
49
69
|
return calendarDay(bound);
|
|
50
70
|
}
|
|
51
71
|
|
|
72
|
+
/**
|
|
73
|
+
* The format a `TransactionQuery` asks for with `format`: `auto` where it is `undefined`. Throws `TypeError` for anything
|
|
74
|
+
* but a `TransactionFormat`, such as `'CAMT'` or `null`.
|
|
75
|
+
*/
|
|
76
|
+
function requestedFormat(format: unknown): TransactionFormat {
|
|
77
|
+
if (format === undefined) return 'auto';
|
|
78
|
+
if (format === 'auto' || format === 'mt940' || format === 'camt') return format;
|
|
79
|
+
throw invalidArgument("Must be 'auto', 'mt940' or 'camt'", 'format');
|
|
80
|
+
}
|
|
81
|
+
|
|
52
82
|
/** FinTS 3.0 PIN/TAN client, the version German banks use. */
|
|
53
83
|
export class FinTs3Client implements FinTsClient {
|
|
54
84
|
// A call such as `getBalance` runs through these parts:
|
|
@@ -89,15 +119,22 @@ export class FinTs3Client implements FinTsClient {
|
|
|
89
119
|
*
|
|
90
120
|
* Throws `TypeError` if the configuration is invalid, as the constructor of `FinTsConfig` tells, or the PIN is empty,
|
|
91
121
|
* begins or ends with a blank, or has characters FinTS 3.0 cannot send: it uses ISO 8859-1, so `€` and most
|
|
92
|
-
* non-Latin letters are not possible.
|
|
122
|
+
* non-Latin letters are not possible. Throws `TypeError` as well for an option of another type than
|
|
123
|
+
* `FinTsClientOptions` names, as `FinTsClientOptions` tells.
|
|
93
124
|
*/
|
|
94
125
|
constructor(init: FinTs3ClientInit) {
|
|
95
126
|
const config = init.config instanceof FinTsConfig ? init.config : new FinTsConfig(init.config);
|
|
127
|
+
const { state, transport } = init.options;
|
|
96
128
|
this.#prompts = new UserPrompts(init.options);
|
|
97
129
|
this.#guard = new LoginGuard(requirePin(init.pin));
|
|
98
130
|
this.#parameters = new ParameterStore(config);
|
|
99
|
-
this.#protocol = new FinTs3Protocol(
|
|
100
|
-
|
|
131
|
+
this.#protocol = new FinTs3Protocol(
|
|
132
|
+
this.#parameters,
|
|
133
|
+
this.#guard,
|
|
134
|
+
optionalTransport(transport),
|
|
135
|
+
this.#prompts.logger,
|
|
136
|
+
);
|
|
137
|
+
this.#sessionState = restoreSession(optionalString(state, 'state'), this.#parameters, this.#guard);
|
|
101
138
|
this.#tans = new TanSelection(this.#protocol, this.#sessionState, this.#prompts);
|
|
102
139
|
const session = {
|
|
103
140
|
parameters: this.#parameters,
|
|
@@ -126,10 +163,13 @@ export class FinTs3Client implements FinTsClient {
|
|
|
126
163
|
return this.#sessionState.tanMedium;
|
|
127
164
|
}
|
|
128
165
|
|
|
129
|
-
selectTanMethod(securityFunction: string, tanMedium?: string): Promise<void> {
|
|
166
|
+
async selectTanMethod(securityFunction: string, tanMedium?: string): Promise<void> {
|
|
167
|
+
// Checked before the dialog ends; an async method, so that every argument error is a rejection.
|
|
168
|
+
const method = requireString(securityFunction, 'securityFunction');
|
|
169
|
+
const medium = optionalString(tanMedium, 'tanMedium');
|
|
130
170
|
return this.#serialized(async () => {
|
|
131
171
|
await this.#dialogs.end();
|
|
132
|
-
this.#tans.select(
|
|
172
|
+
this.#tans.select(method, medium);
|
|
133
173
|
});
|
|
134
174
|
}
|
|
135
175
|
|
|
@@ -170,7 +210,9 @@ export class FinTs3Client implements FinTsClient {
|
|
|
170
210
|
return this.#serialized(() => this.#sepa.completedAccounts());
|
|
171
211
|
}
|
|
172
212
|
|
|
173
|
-
getBalance(account: Account): Promise<Balance> {
|
|
213
|
+
async getBalance(account: Account): Promise<Balance> {
|
|
214
|
+
// Checked before the call waits for others; an async method, so that every argument error is a rejection.
|
|
215
|
+
requireAccount(account);
|
|
174
216
|
return this.#serialized(async () => {
|
|
175
217
|
const completed = await this.#sepa.complete(account);
|
|
176
218
|
// The dialog start delivers the user parameter data, which may carry the complete balance: then the client must
|
|
@@ -185,21 +227,17 @@ export class FinTs3Client implements FinTsClient {
|
|
|
185
227
|
|
|
186
228
|
async getTransactions(account: Account, query: TransactionQuery = {}): Promise<Transaction[]> {
|
|
187
229
|
// Checked before the call waits for others; an async method, so that every argument error is a rejection.
|
|
230
|
+
requireAccount(account);
|
|
188
231
|
const firstDay = requestedDay(query.from, 'from');
|
|
189
232
|
const lastDay = requestedDay(query.to, 'to');
|
|
190
233
|
if (firstDay !== undefined && lastDay !== undefined && firstDay.getTime() > lastDay.getTime()) {
|
|
191
234
|
throw invalidArgument('`from` lies on a day after `to`', 'from');
|
|
192
235
|
}
|
|
236
|
+
const format = requestedFormat(query.format);
|
|
193
237
|
return this.#serialized(async () => {
|
|
194
238
|
const completed = await this.#sepa.complete(account);
|
|
195
239
|
const transactions = await this.#dialogs.query(() =>
|
|
196
|
-
transactionsQuery(
|
|
197
|
-
this.#parameters,
|
|
198
|
-
completed,
|
|
199
|
-
query.format ?? 'auto',
|
|
200
|
-
notAfterToday(firstDay),
|
|
201
|
-
notAfterToday(lastDay),
|
|
202
|
-
),
|
|
240
|
+
transactionsQuery(this.#parameters, completed, format, notAfterToday(firstDay), notAfterToday(lastDay)),
|
|
203
241
|
);
|
|
204
242
|
// A stable sort, so that transactions of the same day keep the bank's order.
|
|
205
243
|
return transactions.sort(
|
|
@@ -239,9 +277,12 @@ export class FinTs3Client implements FinTsClient {
|
|
|
239
277
|
this.#runningCall = call;
|
|
240
278
|
try {
|
|
241
279
|
return await runningCalls.run(call, () =>
|
|
242
|
-
this.#guard.runCall(() => {
|
|
280
|
+
this.#guard.runCall(async () => {
|
|
281
|
+
this.#prompts.checkOpen();
|
|
282
|
+
const result = await this.#prompts.reportingCallbackErrors(action);
|
|
283
|
+
// Also where the last answer arrived after `close`: a closed client hands out no account data.
|
|
243
284
|
this.#prompts.checkOpen();
|
|
244
|
-
return
|
|
285
|
+
return result;
|
|
245
286
|
}),
|
|
246
287
|
);
|
|
247
288
|
} finally {
|
package/src/core/account.ts
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
|
+
import { optionalBoolean, optionalInteger, optionalString, requireString } from '../util/arguments.js';
|
|
1
2
|
import { copyDate } from '../util/dates.js';
|
|
3
|
+
import { invalidArgument } from '../util/errors.js';
|
|
2
4
|
import { ImmutableMap } from '../util/immutable-map.js';
|
|
5
|
+
import { inspectCustom } from '../util/inspect.js';
|
|
6
|
+
import { isString } from '../util/json.js';
|
|
3
7
|
import { maskedId, nonBlank } from '../util/text.js';
|
|
4
8
|
import { defaultCountryCode } from './config.js';
|
|
5
9
|
|
|
@@ -127,22 +131,28 @@ export class Account {
|
|
|
127
131
|
/** What the bank tells about the data it holds for the account, where it does. */
|
|
128
132
|
readonly dataStatus: AccountDataStatus | undefined;
|
|
129
133
|
|
|
130
|
-
/**
|
|
134
|
+
/**
|
|
135
|
+
* Takes copies of the permitted transactions and the data status of `init`, which no other account shares.
|
|
136
|
+
*
|
|
137
|
+
* Throws `TypeError` for a detail of another type than `AccountInit` names, such as a number as `bankCode` or
|
|
138
|
+
* `accountNumber`, or a missing `bankCode`; `null` counts as a detail not given. The message leaves out the value.
|
|
139
|
+
*/
|
|
131
140
|
constructor(init: AccountInit) {
|
|
132
|
-
this.accountNumber = init.accountNumber;
|
|
133
|
-
this.subAccount = init.subAccount;
|
|
134
|
-
this.bankCode = init.bankCode;
|
|
135
|
-
this.countryCode = init.countryCode ?? defaultCountryCode;
|
|
136
|
-
this.iban = electronicFormat(init.iban);
|
|
137
|
-
this.bic = electronicFormat(init.bic);
|
|
138
|
-
this.customerId = init.customerId;
|
|
139
|
-
this.currency = init.currency;
|
|
140
|
-
this.ownerName = init.ownerName;
|
|
141
|
-
this.productName = init.productName;
|
|
142
|
-
this.typeCode = init.typeCode;
|
|
143
|
-
this.allowedTransactions = Object.freeze(
|
|
144
|
-
this.allowedTransactionsComplete =
|
|
145
|
-
|
|
141
|
+
this.accountNumber = optionalString(init.accountNumber, 'accountNumber');
|
|
142
|
+
this.subAccount = optionalString(init.subAccount, 'subAccount');
|
|
143
|
+
this.bankCode = requireString(init.bankCode, 'bankCode');
|
|
144
|
+
this.countryCode = optionalString(init.countryCode, 'countryCode') ?? defaultCountryCode;
|
|
145
|
+
this.iban = electronicFormat(optionalString(init.iban, 'iban'));
|
|
146
|
+
this.bic = electronicFormat(optionalString(init.bic, 'bic'));
|
|
147
|
+
this.customerId = optionalString(init.customerId, 'customerId');
|
|
148
|
+
this.currency = optionalString(init.currency, 'currency');
|
|
149
|
+
this.ownerName = optionalString(init.ownerName, 'ownerName');
|
|
150
|
+
this.productName = optionalString(init.productName, 'productName');
|
|
151
|
+
this.typeCode = optionalInteger(init.typeCode, 'typeCode');
|
|
152
|
+
this.allowedTransactions = Object.freeze(segmentIds(init.allowedTransactions));
|
|
153
|
+
this.allowedTransactionsComplete =
|
|
154
|
+
optionalBoolean(init.allowedTransactionsComplete, 'allowedTransactionsComplete') ?? false;
|
|
155
|
+
this.dataStatus = copiedDataStatus(init.dataStatus);
|
|
146
156
|
}
|
|
147
157
|
|
|
148
158
|
/** The kind of account, derived from `typeCode`. */
|
|
@@ -201,13 +211,35 @@ export class Account {
|
|
|
201
211
|
];
|
|
202
212
|
return `Account(${parts.join(', ')})`;
|
|
203
213
|
}
|
|
214
|
+
|
|
215
|
+
/** What Node.js's `util.inspect` and `console.log` show: `toString`, not the fields. */
|
|
216
|
+
[inspectCustom](): string {
|
|
217
|
+
return this.toString();
|
|
218
|
+
}
|
|
204
219
|
}
|
|
205
220
|
|
|
206
221
|
/**
|
|
207
|
-
* An IBAN or BIC in the form the bank sends and compares, without blanks and in capitals;
|
|
222
|
+
* An IBAN or BIC in the form the bank sends and compares, without blanks, U+0085 (NEL) among them, and in capitals;
|
|
223
|
+
* `undefined` for blanks only.
|
|
208
224
|
*/
|
|
209
225
|
function electronicFormat(code: string | undefined): string | undefined {
|
|
210
|
-
return nonBlank(code?.replace(
|
|
226
|
+
return nonBlank(code?.replace(/[\s\u0085]/g, '').toUpperCase());
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/** A copy of `ids`, none for `undefined` or `null`; throws `TypeError` unless they are an array of strings. */
|
|
230
|
+
function segmentIds(ids: unknown): string[] {
|
|
231
|
+
if (ids === undefined || ids === null) return [];
|
|
232
|
+
if (!Array.isArray(ids) || !ids.every(isString)) {
|
|
233
|
+
throw invalidArgument('Must be an array of strings', 'allowedTransactions');
|
|
234
|
+
}
|
|
235
|
+
return [...ids];
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/** A copy of `status`, none for `undefined` or `null`; throws `TypeError` unless it is an `AccountDataStatus`. */
|
|
239
|
+
function copiedDataStatus(status: unknown): AccountDataStatus | undefined {
|
|
240
|
+
if (status === undefined || status === null) return undefined;
|
|
241
|
+
if (!(status instanceof AccountDataStatus)) throw invalidArgument('Must be an AccountDataStatus', 'dataStatus');
|
|
242
|
+
return new AccountDataStatus(status);
|
|
211
243
|
}
|
|
212
244
|
|
|
213
245
|
function sameOrUnstated(a: string, b: string): boolean {
|
|
@@ -222,12 +254,11 @@ function nationalNumber(account: Account): string | undefined {
|
|
|
222
254
|
/**
|
|
223
255
|
* Accounts by IBAN and by national account, to find the first one an account `matches` without comparing it with each:
|
|
224
256
|
* a bank may list tens of thousands.
|
|
225
|
-
*
|
|
226
|
-
* Bank and country codes count as they are, where `matches` takes an empty one for any: the accounts a bank lists state
|
|
227
|
-
* both.
|
|
228
257
|
*/
|
|
229
258
|
export class AccountIndex {
|
|
230
259
|
private readonly byIban = new Map<string, number>();
|
|
260
|
+
|
|
261
|
+
/** By national account, under its bank and country code and under `null` for any of each, as `matches` takes them. */
|
|
231
262
|
private readonly byNational = new Map<string, number>();
|
|
232
263
|
|
|
233
264
|
/** Those without IBAN only: an account with IBAN matches one with IBAN by that alone. */
|
|
@@ -235,31 +266,48 @@ export class AccountIndex {
|
|
|
235
266
|
|
|
236
267
|
constructor(private readonly accounts: readonly Account[]) {
|
|
237
268
|
accounts.forEach((account, i) => {
|
|
238
|
-
const national = nationalKey(account);
|
|
239
269
|
if (account.iban !== undefined) keepFirst(this.byIban, account.iban, i);
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
270
|
+
const number = nationalNumber(account);
|
|
271
|
+
if (number === undefined) return;
|
|
272
|
+
for (const bankCode of [account.bankCode, null]) {
|
|
273
|
+
for (const countryCode of [account.countryCode, null]) {
|
|
274
|
+
const national = nationalKey(number, account.subAccount, bankCode, countryCode);
|
|
275
|
+
keepFirst(this.byNational, national, i);
|
|
276
|
+
if (account.iban === undefined) keepFirst(this.byNationalWithoutIban, national, i);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
243
279
|
});
|
|
244
280
|
}
|
|
245
281
|
|
|
246
282
|
/** The first of the accounts that `account` matches. */
|
|
247
283
|
find(account: Account): Account | undefined {
|
|
248
|
-
const
|
|
284
|
+
const number = nationalNumber(account);
|
|
249
285
|
const byNational = account.iban === undefined ? this.byNational : this.byNationalWithoutIban;
|
|
250
|
-
const found = [
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
286
|
+
const found = [account.iban === undefined ? undefined : this.byIban.get(account.iban)];
|
|
287
|
+
if (number !== undefined) {
|
|
288
|
+
for (const bankCode of codesMatching(account.bankCode)) {
|
|
289
|
+
for (const countryCode of codesMatching(account.countryCode)) {
|
|
290
|
+
found.push(byNational.get(nationalKey(number, account.subAccount, bankCode, countryCode)));
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
const positions = found.filter((i) => i !== undefined);
|
|
295
|
+
return positions.length === 0 ? undefined : this.accounts[Math.min(...positions)];
|
|
255
296
|
}
|
|
256
297
|
}
|
|
257
298
|
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
return
|
|
261
|
-
|
|
262
|
-
|
|
299
|
+
/** The keys of the codes that `code` matches: an empty one matches any, and a stated one also an empty one. */
|
|
300
|
+
function codesMatching(code: string): (string | null)[] {
|
|
301
|
+
return code === '' ? [null] : [code, ''];
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
function nationalKey(
|
|
305
|
+
number: string,
|
|
306
|
+
subAccount: string | undefined,
|
|
307
|
+
bankCode: string | null,
|
|
308
|
+
countryCode: string | null,
|
|
309
|
+
): string {
|
|
310
|
+
return JSON.stringify([number, subAccount ?? '', bankCode, countryCode]);
|
|
263
311
|
}
|
|
264
312
|
|
|
265
313
|
function keepFirst(index: Map<string, number>, key: string, position: number): void {
|
|
@@ -320,4 +368,12 @@ export class AccountDataStatus {
|
|
|
320
368
|
get camtTransactionsId(): string | undefined {
|
|
321
369
|
return this.inventory.get('HKCAZ');
|
|
322
370
|
}
|
|
371
|
+
|
|
372
|
+
/**
|
|
373
|
+
* What Node.js's `util.inspect` and `console.log` show: the queries `inventory` holds an ID for, not the IDs, which
|
|
374
|
+
* mark the user's data.
|
|
375
|
+
*/
|
|
376
|
+
[inspectCustom](): string {
|
|
377
|
+
return `AccountDataStatus(${[...this.inventory.keys()].join(', ')})`;
|
|
378
|
+
}
|
|
323
379
|
}
|
package/src/core/amount.ts
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { requireString } from '../util/arguments.js';
|
|
2
|
+
import { FormatError, invalidArgument } from '../util/errors.js';
|
|
3
|
+
import { inspectCustom } from '../util/inspect.js';
|
|
4
|
+
import { trimBlanks } from '../util/text.js';
|
|
2
5
|
|
|
3
6
|
/** Most decimal places an amount has: ISO 20022, the widest of the bank formats, allows five. */
|
|
4
7
|
const maxScale = 5;
|
|
@@ -10,6 +13,9 @@ const powersOfTen = [1, 10, 100, 1000, 10000, 100000];
|
|
|
10
13
|
/** Most digits a parsed amount has: few enough that the sum of two parsed amounts still fits. */
|
|
11
14
|
const maxDigits = 15;
|
|
12
15
|
|
|
16
|
+
/** Most characters a parsed value has: room for the zeros banks pad amounts with besides `maxDigits` digits. */
|
|
17
|
+
const maxLength = 64;
|
|
18
|
+
|
|
13
19
|
const decimal = /^([+-]?)(\d*)(?:[.,](\d*))?$/;
|
|
14
20
|
|
|
15
21
|
/** Decimal places of the minor unit of `currency` (ISO 4217): two, except for the currencies listed here. */
|
|
@@ -63,8 +69,13 @@ export class Amount {
|
|
|
63
69
|
/**
|
|
64
70
|
* An amount of `minorUnits` with `scale` decimal places; throws `RangeError` for a `scale` outside 0 to 5, and for
|
|
65
71
|
* `minorUnits` that are no integer or beyond 2^53 - 1 in either direction, about 90 trillion at two decimal places.
|
|
72
|
+
* Throws `TypeError` for `minorUnits` or `scale` that are no number, such as `'1234'`, and a `currency` that is no
|
|
73
|
+
* string.
|
|
66
74
|
*/
|
|
67
75
|
constructor(minorUnits: number, scale: number, currency: string) {
|
|
76
|
+
if (typeof minorUnits !== 'number') throw invalidArgument('Must be a number', 'minorUnits');
|
|
77
|
+
if (typeof scale !== 'number') throw invalidArgument('Must be a number', 'scale');
|
|
78
|
+
requireString(currency, 'currency');
|
|
68
79
|
if (!Number.isInteger(scale) || scale < 0 || scale > maxScale) {
|
|
69
80
|
throw new RangeError(`scale must be an integer from 0 to ${maxScale}: ${scale}`);
|
|
70
81
|
}
|
|
@@ -83,11 +94,15 @@ export class Amount {
|
|
|
83
94
|
* `JPY`, three for `KWD`. It has more where the value has more significant digits. So `100,` in `EUR` is `100.00`, in
|
|
84
95
|
* `JPY` `100`.
|
|
85
96
|
*
|
|
86
|
-
* Throws `FormatError` for anything else, so that `1.234,56` in bank data is an error, not a guess,
|
|
87
|
-
* five decimal places (trailing zeros aside) or more than 15 digits
|
|
97
|
+
* Throws `FormatError` for anything else, so that `1.234,56` in bank data is an error, not a guess, for more than
|
|
98
|
+
* five decimal places (trailing zeros aside) or more than 15 digits, and for more than 64 characters, zeros included
|
|
99
|
+
* and surrounding blanks aside. Throws `TypeError` for a `value` or `currency` that is no string.
|
|
88
100
|
*/
|
|
89
101
|
static parseDecimal(value: string, currency: string): Amount {
|
|
90
|
-
const
|
|
102
|
+
const trimmed = trimBlanks(requireString(value, 'value'));
|
|
103
|
+
requireString(currency, 'currency');
|
|
104
|
+
if (trimmed.length > maxLength) throw new FormatError(`Amount longer than ${maxLength} characters`, value);
|
|
105
|
+
const match = decimal.exec(trimmed);
|
|
91
106
|
const whole = match?.[2] ?? '';
|
|
92
107
|
let fraction = match?.[3] ?? '';
|
|
93
108
|
if (!match || (whole === '' && fraction === '')) throw new FormatError('Invalid amount', value);
|
|
@@ -175,14 +190,15 @@ export class Amount {
|
|
|
175
190
|
return `${this.toDecimalString()} ${this.currency}`;
|
|
176
191
|
}
|
|
177
192
|
|
|
193
|
+
/** What Node.js's `util.inspect` and `console.log` show: `toString`, not the fields. */
|
|
194
|
+
[inspectCustom](): string {
|
|
195
|
+
return this.toString();
|
|
196
|
+
}
|
|
197
|
+
|
|
178
198
|
/** The minor units of both amounts at the larger scale, as `bigint`s, since the factor could leave the safe range. */
|
|
179
199
|
private atCommonScale(other: Amount): [bigint, bigint] {
|
|
180
200
|
const target = Math.max(this.scale, other.scale);
|
|
181
|
-
return [this
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
private rescale(target: number): bigint {
|
|
185
|
-
return BigInt(this.minorUnits) * BigInt(powersOfTen[target - this.scale]!);
|
|
201
|
+
return [unitsAtScale(this, target), unitsAtScale(other, target)];
|
|
186
202
|
}
|
|
187
203
|
|
|
188
204
|
private compareValue(other: Amount): number {
|
|
@@ -197,6 +213,23 @@ export class Amount {
|
|
|
197
213
|
}
|
|
198
214
|
}
|
|
199
215
|
|
|
216
|
+
function unitsAtScale(amount: Amount, scale: number): bigint {
|
|
217
|
+
return BigInt(amount.minorUnits) * BigInt(powersOfTen[scale - amount.scale]!);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Whether `parts` are all in the currency of `total` and add up to exactly `total`; unlike `add`, also where a sum on
|
|
222
|
+
* the way lies beyond what an amount holds.
|
|
223
|
+
*/
|
|
224
|
+
export function addsUpTo(parts: readonly Amount[], total: Amount): boolean {
|
|
225
|
+
let sum = 0n;
|
|
226
|
+
for (const part of parts) {
|
|
227
|
+
if (part.currency !== total.currency) return false;
|
|
228
|
+
sum += unitsAtScale(part, maxScale);
|
|
229
|
+
}
|
|
230
|
+
return sum === unitsAtScale(total, maxScale);
|
|
231
|
+
}
|
|
232
|
+
|
|
200
233
|
/**
|
|
201
234
|
* `amount` as a credit (unchanged) or a debit (negated), by the bank's credit/debit `mark`.
|
|
202
235
|
*
|
package/src/core/balance.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { copyDate, formatIsoDate } from '../util/dates.js';
|
|
2
|
+
import { inspectCustom } from '../util/inspect.js';
|
|
2
3
|
import type { Account } from './account.js';
|
|
3
4
|
import type { Amount } from './amount.js';
|
|
4
5
|
|
|
@@ -82,4 +83,9 @@ export class Balance {
|
|
|
82
83
|
toString(): string {
|
|
83
84
|
return `Balance(${this.account.toString()}, ${formatIsoDate(this.bookedAsOf)})`;
|
|
84
85
|
}
|
|
86
|
+
|
|
87
|
+
/** What Node.js's `util.inspect` and `console.log` show: `toString`, not the fields. */
|
|
88
|
+
[inspectCustom](): string {
|
|
89
|
+
return this.toString();
|
|
90
|
+
}
|
|
85
91
|
}
|