@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/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,380 @@
|
|
|
1
|
+
## 0.3.0
|
|
2
|
+
|
|
3
|
+
An app may notice these changes: arguments and options of another type than declared, such as a number as `bankCode`
|
|
4
|
+
or a `state` that is no string, and a user ID or customer ID of more than 30 characters fail with a `TypeError` before
|
|
5
|
+
the bank is contacted; the client reads its options once; `close` waits up to five seconds for the request on its way,
|
|
6
|
+
so the call it ends fails with `FinTsStateError` where the answer comes in time; a TAN goes out as the user typed it;
|
|
7
|
+
`console.log` shows the models of the package only by what identifies no person, account or TAN, and `toString` of
|
|
8
|
+
`FinTsFeedback` and `BankMessage` leaves out the bank's texts; `feedback` and `source` of an error are getters; and more
|
|
9
|
+
malformed bank data fail with `FinTsProtocolError`. Where these notes compare with the Dart package, they mean its
|
|
10
|
+
source after its release 0.2.0, unless they name 0.2.0, which differs in more ways: it keeps no refused login in the
|
|
11
|
+
saved state.
|
|
12
|
+
|
|
13
|
+
### Breaking
|
|
14
|
+
|
|
15
|
+
- `getTransactions` rejects a `format` other than `'auto'`, `'mt940'` and `'camt'` with a `TypeError`, before it waits
|
|
16
|
+
for other calls or contacts the bank: one such as `'CAMT'` asked for MT940, and `null` meant `'auto'`, as `undefined`
|
|
17
|
+
still does.
|
|
18
|
+
- `getBalance` and `getTransactions` reject anything but an `Account`, such as one written to JSON and read back, with a
|
|
19
|
+
`TypeError` before they wait for other calls or contact the bank. They logged in, fetched the SEPA account list, and
|
|
20
|
+
then failed with an unrelated `TypeError`.
|
|
21
|
+
- `selectTanMethod` rejects a TAN method or medium that is no string, and a missing method, with a `TypeError` before it
|
|
22
|
+
ends the dialog. A number as the method was saved and then dropped at the next login, which asked `tanMethodSelector`
|
|
23
|
+
instead; a medium of another type went out as its text or as a data element group, which the bank refused as a login;
|
|
24
|
+
and a state saved in between could not be restored.
|
|
25
|
+
- `FinTs3Client` throws a `TypeError` for options of another type, before contacting the bank: a missing `tanCallback`
|
|
26
|
+
or one that is no function, another callback that is neither a function nor `undefined` or `null`, a `state` that is
|
|
27
|
+
neither a string nor `undefined` or `null`, such as the parsed JSON a store hands back, and a `transport` without the
|
|
28
|
+
functions `post` and `close`. A callback that was no function failed the call after its messages had gone out,
|
|
29
|
+
`tanCallback` at the first TAN challenge after the PIN-signed login; a `state` that was no string was ignored; and a
|
|
30
|
+
transport without `close` made `close` reject.
|
|
31
|
+
- The client reads its options once, when it is built, as the Dart package does: assigning another `tanCallback`,
|
|
32
|
+
selector, `onBankMessage` or `onWarning` to the options object afterwards no longer changes what the client calls.
|
|
33
|
+
- `Account`, `Amount` and `FinTsConfig` throw a `TypeError` ('Invalid argument (<name>): …', without the value) for an
|
|
34
|
+
argument of another type than declared, as the Dart package's types refuse it: such as a number as `bankCode`,
|
|
35
|
+
`accountNumber`, `iban`, `currency` or `customerId`, a missing `bankCode`, a string as `minorUnits`, `scale` or
|
|
36
|
+
`typeCode`, anything but an array of strings as `allowedTransactions`, anything but a boolean as `allowInsecureUrl`,
|
|
37
|
+
and anything but an `AccountDataStatus` as `dataStatus`. `Amount.parseDecimal` does for a `value` or `currency` that
|
|
38
|
+
is no string. Such an account passed the constructor, threw in `toString`, and failed `getBalance` and
|
|
39
|
+
`getTransactions` only after the login, or matched none of the bank's accounts, so that the query failed with
|
|
40
|
+
`FinTsUnsupportedError` or went out without the bank's IBAN and BIC. A `dataStatus` written to JSON and read back
|
|
41
|
+
failed with an unrelated `TypeError` ('object is not iterable'), and a string counted as an empty status. An amount
|
|
42
|
+
kept a number as its currency, and a string as `minorUnits` threw a `RangeError` that showed it as a valid value.
|
|
43
|
+
- `FinTsConfig` throws a `TypeError` for a `userId` or `customerId` longer than 30 characters, the length FinTS 3.0
|
|
44
|
+
gives them (Formals, data type `id`). The bank refused such a login with a syntax error, which the client counted as
|
|
45
|
+
a refused login, so it sent the PIN no more.
|
|
46
|
+
- A `FinTsConfig` is frozen once its constructor has checked it: assigning to a field throws a `TypeError` in
|
|
47
|
+
strict-mode code and does nothing otherwise, and a subclass cannot add fields.
|
|
48
|
+
- As in the Dart package, `Mt940.parse` and `Mt940.parseTransactions` throw a `TypeError` for a `status` other than
|
|
49
|
+
`'booked'` and `'pending'`, `null` included, which meant `'booked'`, and for a `currency` that is no string;
|
|
50
|
+
`Camt.parse` and `Camt.parseTransactions` for a status other than these, `undefined` and `null`. Such a status became
|
|
51
|
+
the transactions' `status`, and such a currency that of their amounts. `SepaPurpose.parseParts` throws a `TypeError`
|
|
52
|
+
for a string, whose characters it took for parts, and for parts that are no strings.
|
|
53
|
+
- camt documents are read as XML 1.0 has them, failing `getTransactions` with `FinTsProtocolError` and `Camt.parse` with
|
|
54
|
+
`FormatError` for a name that is no XML name, such as `<1x>`, an end tag with another namespace prefix than its start
|
|
55
|
+
tag, a second XML declaration or one inside or after the root element, a processing instruction without a target, and
|
|
56
|
+
an attribute stated twice.
|
|
57
|
+
- camt: a `Dt` that holds a date and time is read like a `DtTm`. One whose time the client cannot read, such as
|
|
58
|
+
`2024-03-15T25:00:00` or `2024-03-15T10:00`, fails `getTransactions` with `FinTsProtocolError` and `Camt.parse` with
|
|
59
|
+
`FormatError` instead of counting on the date written. So do a UTC offset beyond ±14:00, such as `+15:00`, which XML
|
|
60
|
+
Schema does not allow and which the client used to read as an offset, and `24:00:00` with a fraction of a second other
|
|
61
|
+
than zero.
|
|
62
|
+
- `BankInfo.maxMessageSize`, `minTimeout` and `maxTimeout` are `undefined` for a value above 9999, the four digits HIBPA
|
|
63
|
+
allows, as in the Dart package. The client then sends messages of any size and starts a new dialog after 5 idle
|
|
64
|
+
minutes. `TanChallenge.plainMessage` leaves a structured challenge of more than 65,536 characters as the bank sent it,
|
|
65
|
+
as the Dart package does.
|
|
66
|
+
- `close` no longer aborts a request on its way at once: it waits up to five seconds for the answer and only then aborts
|
|
67
|
+
it, and the dialog ends then have five seconds once that request is over, so `close` may take about ten seconds where
|
|
68
|
+
the bank has stopped answering. Where the answer comes in time, the running call fails with `FinTsStateError` instead
|
|
69
|
+
of `FinTsTransportError`, also where that answer completes it, unless the answer brings an error of its own, such as a
|
|
70
|
+
rejected PIN, which it fails with instead; a request aborted after the five seconds still fails it with
|
|
71
|
+
`FinTsTransportError`. A call whose last answer arrives after `close`, within those five seconds, fails with
|
|
72
|
+
`FinTsStateError` instead of returning its result.
|
|
73
|
+
- A TAN goes out as the user typed it, except for full-width characters, which count as their ASCII counterparts, and
|
|
74
|
+
the ideographic space U+3000, which counts as a blank, as in the Dart package. Unicode NFKC changed it before:
|
|
75
|
+
superscript, circled and mathematical digits counted as digits, and characters that ISO 8859-1 holds went out altered,
|
|
76
|
+
such as `²` as `2` or a no-break space inside the TAN as a space, which the bank counts as a failed attempt; `µ`, `½`
|
|
77
|
+
and the like failed with a `TypeError` as not sendable. Other characters outside ISO 8859-1, and digits other than 0
|
|
78
|
+
to 9 for a `numericTan` method, fail the call with a `TypeError` before it is sent.
|
|
79
|
+
- `FinTsFeedback.toString` gives the code only, such as `FinTsFeedback(3072)`, and `BankMessage.toString` gives
|
|
80
|
+
`BankMessage(…)`, as `console.log` showed them already. So `String(f)`, template strings and loggers that call
|
|
81
|
+
`toString` no longer collect the bank's texts and parameters, which with return code 3072 hold the new login data, or
|
|
82
|
+
a message that may address the user by name. To show them to the user, use `code`, `text` and `parameters`, or
|
|
83
|
+
`subject` and `text`. The message of a `FinTsBankError` stays as it was, with the code, text and parameters of each
|
|
84
|
+
error, such as `9010: Konto gesperrt [DE89370400440532013000]`.
|
|
85
|
+
- `FinTsBankError.feedback` and `FormatError.source` are getters instead of own properties of the error, so
|
|
86
|
+
`Object.keys`, object spread and `JSON.stringify` of the error leave them out.
|
|
87
|
+
|
|
88
|
+
### Security
|
|
89
|
+
|
|
90
|
+
- Plain JavaScript can no longer change a `FinTsConfig` once checked, which could send the PIN to an http URL, or login
|
|
91
|
+
data the constructor had not checked, to the bank.
|
|
92
|
+
- `FinTsConfig` refuses an `allowInsecureUrl` that is no boolean, such as the string `'false'` read from an environment
|
|
93
|
+
variable, with a `TypeError`: it allowed plain http to a loopback host, where the PIN passes any proxy the runtime's
|
|
94
|
+
`fetch` takes from the environment.
|
|
95
|
+
- `console.log` and `util.inspect` on Node.js, Deno and Bun show the objects of this package only by what identifies no
|
|
96
|
+
person, account or TAN. An `Account`, `Balance`, `Transaction`, `TanMethod` or `TanMedium` shows as its `toString`, a
|
|
97
|
+
`TanChallenge` by its method, kind and attempt, a `FinTsFeedback` by its code and a `TanAnswer` by its kind.
|
|
98
|
+
`AccountDataStatus`, `BankInfo`, `FinTsConfig`, `FlickerCode` and `TanImage` show codes, versions and sizes only, the
|
|
99
|
+
statements of `Mt940.parse` and `Camt.parse` the last digits of the account and the number of transactions, and a
|
|
100
|
+
`BankMessage` shows as `BankMessage(…)`. Until now they showed every field: the bank's texts, references and
|
|
101
|
+
parameters (with return code 3072 the new login data), TAN media names, the TAN, the challenge data and image, the
|
|
102
|
+
login name and product ID, and a statement's full account. An error shows its message and stack, and a
|
|
103
|
+
`FinTsTransportError` its `statusCode`; the message of a `FinTsBankError` holds the texts and parameters of its
|
|
104
|
+
errors, as before. `JSON.stringify` and the browser console still show every field.
|
|
105
|
+
- Node.js's report of an uncaught error ignores what `console.log` shows of an object. It printed the whole `feedback`
|
|
106
|
+
of a `FinTsBankError`, including the texts, references and parameters of its successes and warnings and, with return
|
|
107
|
+
code 3072, the new login data, as well as the `source` of a `FormatError`. `JSON.stringify` of such an error, and
|
|
108
|
+
loggers that copy an error's fields, got them too. Both are getters now, so an uncaught `FinTsBankError` or
|
|
109
|
+
`FormatError` prints its message and stack only, as in the Dart package, and `JSON.stringify` leaves them out.
|
|
110
|
+
- `TanMedium.toString` leaves out the medium's name, which the user may have chosen after themselves, such as
|
|
111
|
+
`Max’s iPhone`: it gives `TanMedium(M, active)`, or, for a card, the last digits of its number,
|
|
112
|
+
`TanMedium(…2014, active)`, as before for a card without a name.
|
|
113
|
+
- A PIN that begins or ends with U+0085 (NEL) fails with a `TypeError` before it is sent, like one with other blanks at
|
|
114
|
+
either end. It went out with the byte 0x85, which the bank could count as a failed attempt.
|
|
115
|
+
- New login data (3072) next to an error in the answer to the login's TAN or app approval, such as 9941 for a wrong TAN,
|
|
116
|
+
an aborted dialog (9800) or any other error but a rejected PIN, end the old ones as well, as in the Dart package: the
|
|
117
|
+
call fails with `FinTsLoginDataChangedError`, the client ends the dialog where the bank keeps it open, and no later
|
|
118
|
+
call logs in with the old data. Until now the call failed with `FinTsTanError`, `FinTsDialogAbortedError` or
|
|
119
|
+
`FinTsBankError`, and the next call logged in again with the old login data and the PIN, which the bank may count as a
|
|
120
|
+
failed attempt, and asked for another TAN.
|
|
121
|
+
- A refused login, and the count of logins whose answer was lost, are restored from a saved state whose owner names the
|
|
122
|
+
server by something other than a string, such as a number or `null`, as in the Dart package; the rest of such a state
|
|
123
|
+
is dropped, as for another server. Until now the whole state was dropped, and the next call sent the PIN the bank had
|
|
124
|
+
refused.
|
|
125
|
+
- A `state` that is no string, such as the parsed JSON a json column returns, fails the `FinTs3Client` constructor with
|
|
126
|
+
a `TypeError`: the client ignored it, and with it a refused login it held, and sent the PIN again.
|
|
127
|
+
- A refused login stays refused where the `loginGuard` section of a saved state for the same user is damaged, such as a
|
|
128
|
+
return code without its code or `unreadLogins` that is no integer: the client restores a `FinTsLoginRefusedError`
|
|
129
|
+
without return codes and sends the PIN no more until `clearLoginRefusal`. Such damage dropped the refusal, and the
|
|
130
|
+
next call sent the refused PIN again. A state without the section, as fints-ts 0.1 and the Dart package 0.2.0 save
|
|
131
|
+
it, restores as before.
|
|
132
|
+
- `HttpTransport` copies each part of an answer as it arrives, as the Dart package does. An answer within
|
|
133
|
+
`maxResponseBytes` that a server sent in one-byte parts took gigabytes of memory and could end a Node.js process with
|
|
134
|
+
an out-of-memory error, which the app cannot catch. A `fetch` that refills the part it handed out corrupted the
|
|
135
|
+
answer.
|
|
136
|
+
- The documentation of `HttpTransport` and `allowInsecureUrl` warns that plain http to a local server goes wherever the
|
|
137
|
+
global `fetch` sends it, as https does. Whatever replaces `globalThis.fetch`, such as a test's stub, and on Node.js a
|
|
138
|
+
global dispatcher get every message with the PIN. A proxy that the runtime's `fetch` takes from the environment, as
|
|
139
|
+
Node.js does with `NODE_USE_ENV_PROXY=1`, and Deno and Bun do from `HTTP_PROXY`, sees the PIN unencrypted: exempt the
|
|
140
|
+
host with `NO_PROXY` or pass a `fetch` that connects directly. The Dart package connects to the loopback host
|
|
141
|
+
directly, also bypassing a client set with `runWithClient`.
|
|
142
|
+
- The limits on bank data are those of the Dart package. The following fail the call with `FinTsProtocolError`, and
|
|
143
|
+
`Mt940.parse`, `Camt.parse` and `Amount.parseDecimal` with `FormatError`: an answer with more than 1,000,000 data
|
|
144
|
+
elements and segments in its plain or in its encrypted part, or with more than one encrypted part (HNVSD); XML nested
|
|
145
|
+
more than 100 levels deep, an empty element such as `<a/>` included, or with more than 500,000 nodes besides text or
|
|
146
|
+
one per 16 characters, whichever is more; an MT940 field of more than 65,536 characters; and an amount written with
|
|
147
|
+
more than 64 characters. The limits were 200,000 data elements per answer, the encrypted part included, and XML of 256
|
|
148
|
+
levels or 1,000,000 elements and attributes; fields and amounts had none. A hostile answer can now take up to about
|
|
149
|
+
210 MB of memory while it is read, instead of about 25 MB. The 128 MiB a query may hold count each data element its
|
|
150
|
+
pages keep as 512 bytes instead of 256, and no longer count the elements of the encrypted part's envelope, so a query
|
|
151
|
+
of many short elements stops after half as many. The 200,000 statements and transactions per query stay.
|
|
152
|
+
- XML text or an attribute value of megabytes of `&`, or of unknown entities such as `&a;`, fails at its first bad
|
|
153
|
+
reference. The parser first found every reference, which took more than a second and about a gigabyte of memory for
|
|
154
|
+
12 MB, beyond the 210 MB the limits allow.
|
|
155
|
+
- camt: remittance information (`Ustrd`) of more than 65,536 characters, as for an MT940 field, fails
|
|
156
|
+
`getTransactions` with `FinTsProtocolError` and `Camt.parse` with `FormatError`. Megabytes of SEPA keywords took
|
|
157
|
+
about 40 times their size in memory.
|
|
158
|
+
- camt: blanks alone between elements, such as the line breaks of an indented document, are no longer kept as text,
|
|
159
|
+
which halves the memory such a document takes while it is read.
|
|
160
|
+
- MT940: the counterparty's IBAN and BIC come from the subfields `?31` and `?30` only, where the bank states them. A
|
|
161
|
+
payer could write `IBAN+…` and `BIC+…` into the end-to-end reference, and these filled `counterpartyIban` and
|
|
162
|
+
`counterpartyBic` where the subfields stated none. Both values stay readable in `purposeCodes`.
|
|
163
|
+
- In a browser, `HttpTransport` sends no cookies and no referrer with a message, and the browser's cache keeps no copy
|
|
164
|
+
of the exchange (`credentials: 'omit'`, `referrerPolicy: 'no-referrer'`, `cache: 'no-store'`). With the defaults,
|
|
165
|
+
cookies of the page and its URL as referrer went along to a server on the page's own origin.
|
|
166
|
+
- The relay server of the README refuses a body without `Content-Length` or of more than 1 MiB before reading it:
|
|
167
|
+
update relays built from it. The documentation of `FinTsTransport.post` says that the client bounds neither the time
|
|
168
|
+
of the exchange nor the size of the answer, so a transport of the app's own has to, as `HttpTransport` does.
|
|
169
|
+
|
|
170
|
+
### Fixed
|
|
171
|
+
|
|
172
|
+
- `close` ends the dialog of a request it aborts after five seconds, unless that request opened the dialog, whose ID
|
|
173
|
+
only the answer tells: the end goes out after the abort, under the next message number, since the bank may have
|
|
174
|
+
received the aborted message. Until now the abort dropped the dialog without an end, and the bank kept it open until
|
|
175
|
+
its timeout. The answer to that end refuses the login only for a rejected PIN, as at any dialog end, not for an error
|
|
176
|
+
such as a message number the bank did not expect because the aborted message never reached it.
|
|
177
|
+
- `close` gives the dialog ends five seconds once the request on its way, if any, is over: then the client stops
|
|
178
|
+
waiting for them, a transport that takes the abort, as `HttpTransport` does, stops them, and none goes out later. A
|
|
179
|
+
bank that has stopped answering held up `close` for the end of an open dialog until the transport's timeout, 90
|
|
180
|
+
seconds by default.
|
|
181
|
+
- The answer to a request on its way when `close` is called counts as any other, as in the Dart package: the logger gets
|
|
182
|
+
it, and the saved state keeps the bank and user parameter data, the customer system ID, the TAN medium and the SEPA
|
|
183
|
+
account list it brings. `close` aborted it at once, so a client restored from the state repeated the anonymous dialog,
|
|
184
|
+
the synchronization, which has the bank register another customer system ID, the lookup of the TAN media or the SEPA
|
|
185
|
+
account list, and its next login reported user parameter data version 0. The dialog of that request is ended as well,
|
|
186
|
+
also where the request opened it, whose ID only the answer tells, and a login answered so no longer counts as one
|
|
187
|
+
whose answer was lost.
|
|
188
|
+
- A dialog end that `close` keeps from going out, once the time after the request on its way is up, no longer reaches
|
|
189
|
+
the logger as an outgoing message, as in the Dart package: the logger showed a dialog end the bank never received.
|
|
190
|
+
- A TAN medium name the app passes to `selectTanMethod`, also from the saved state, goes out without blanks at either
|
|
191
|
+
end (Formals B.4.1), and one of blanks only as no name, as in the Dart package: a bank that knows the medium without
|
|
192
|
+
them refused the login, and the state kept the refusal. `selectedTanMedium` and the state keep the name as the app
|
|
193
|
+
passed it. A name the bank issued still goes back as the bank sent it, blanks at either end included, and the medium
|
|
194
|
+
in use of a state saved by 0.2.0, which does not tell the two apart, as 0.2.0 sent it.
|
|
195
|
+
- `selectTanMethod(method, null)` leaves the TAN medium to the next login, which looks the media up where the method
|
|
196
|
+
needs one, as without a medium and as in the Dart package. The login went out without a medium, which the bank
|
|
197
|
+
refused, and the client kept the refusal until `clearLoginRefusal`.
|
|
198
|
+
- A `tanMethodSelector` or `tanMediumSelector` that returns `null` picks the first method or medium, as for `undefined`,
|
|
199
|
+
instead of failing the call with a `TypeError`; the selector types allow `null`.
|
|
200
|
+
- `null` for `logger`, `onBankMessage`, `onWarning`, `tanMethodSelector`, `tanMediumSelector` or `state` means none, as
|
|
201
|
+
in the Dart package. `logger: null` failed every call that exchanged messages, and `close`, after their traffic;
|
|
202
|
+
`onBankMessage: null` and `onWarning: null` failed a call whose answer carried a bank message or a warning; and a
|
|
203
|
+
`null` selector failed the call after the PIN-signed synchronization or the lookup of the TAN media.
|
|
204
|
+
- `null` counts as not given for the details of an `Account`, whose `toString` threw for an `accountNumber` of `null`,
|
|
205
|
+
for the `customerId` of `FinTsConfig`, which is then the user ID, where a `TypeError` without the package's message
|
|
206
|
+
was thrown, and for the `currency` of `Mt940.parse`, which gave amounts in the currency `null` instead of the
|
|
207
|
+
`FormatError` 'MT940 statement without currency', as in the Dart package.
|
|
208
|
+
- Where the bank parameter data rule out a login, by the PIN's length or the message's size, the client fetches them
|
|
209
|
+
anew in an anonymous dialog, which carries no PIN, and tries the login once more, which goes out only if the new
|
|
210
|
+
limits allow it; where they rule it out as well, the call fails with the error that names the new limits, as in the
|
|
211
|
+
Dart package. Until now outdated parameter data, as saved ones may be, failed every call that logs in with a
|
|
212
|
+
`TypeError` (`FinTsProtocolError` for the size) until the app dropped `client.state`. It takes only the limits from
|
|
213
|
+
the anonymous answer, and only from parameter data of another version than those kept, the PIN's length only where
|
|
214
|
+
they state it. Those limits serve until the login brings the user's parameter data, which the login asks for by
|
|
215
|
+
reporting version 0, so the login the new limits judge may be up to two bytes shorter than the one the old ones
|
|
216
|
+
stopped. The anonymous parameter data never replace the user's. A bank that does not answer anonymously cannot refresh
|
|
217
|
+
them; the call then fails as before, without sending the PIN.
|
|
218
|
+
- A SEPA account list saved empty, as fints-ts 0.1 and the Dart package 0.2.0 saved it, is ignored on restore, as the
|
|
219
|
+
Dart package does after 0.2.0, so the client asks the bank for it again. Until the bank changed its user parameter
|
|
220
|
+
data, such a state kept the client from asking: `getAccounts` returned the accounts without their BIC, and an account
|
|
221
|
+
the app built from its IBAN went out without one, which a bank may refuse, or failed with `FinTsUnsupportedError`
|
|
222
|
+
where the user parameter data name the account by its number only.
|
|
223
|
+
- `TanChallenge.tanMediumName` is `undefined` for a challenge in the dialog that looks up the TAN media, or where the
|
|
224
|
+
bank echoes it, instead of the placeholder `noref`.
|
|
225
|
+
- The client no longer keeps the result of its last call, such as the transactions, until its next call or `close`.
|
|
226
|
+
- `console.log` and `util.inspect` show an `Amount` as its `toString`, such as `-123.45 EUR`, as the Dart package prints
|
|
227
|
+
it, instead of its fields `minorUnits`, `scale` and `currency`.
|
|
228
|
+
- An answer that is no FinTS message at all, such as the web page of a proxy or a maintenance notice, fails with the
|
|
229
|
+
`FinTsProtocolError` 'Malformed bank data: Not a FinTS message: no message header' instead of 'Malformed bank data:
|
|
230
|
+
Segment without terminator'. A message that starts with its header and is cut short still reports what is wrong with
|
|
231
|
+
it.
|
|
232
|
+
- `HttpTransport` refuses an answer whose `Content-Length` announces more than `maxResponseBytes` at once, without
|
|
233
|
+
reading it, with the same `FinTsTransportError` as for a body over the limit, as the Dart package does. A server that
|
|
234
|
+
announced more and then stalled held the call until the timeout, 90 seconds by default. One that sent the whole answer
|
|
235
|
+
had it read up to the limit before the refusal.
|
|
236
|
+
- `getTransactions` reads statement data that a bank sends as text instead of binary data, as it did for booked camt
|
|
237
|
+
documents: booked and pending MT940 (HIKAZ) and the pending camt document (HICAZ) were dropped without an error. A
|
|
238
|
+
malformed or overlong binary length still fails the call with `FinTsProtocolError`.
|
|
239
|
+
- `TransactionFormat` `auto` takes camt.052 where the bank offers it and MT940 cannot be requested for the account (the
|
|
240
|
+
bank offers no `HKKAZ` version the client implements, or PIN/TAN does not permit it), instead of failing with
|
|
241
|
+
`FinTsUnsupportedError`.
|
|
242
|
+
- A FinTS 3.0 time `240000` is midnight of the next day. So `Balance.bookedAsOfTime`, `Balance.bookingTime` and
|
|
243
|
+
`TanChallenge.validUntil` are set for it instead of `undefined`, and the account extension of the user parameter data
|
|
244
|
+
is read with it instead of being dropped as malformed, BIC, balance and data status included. `bookedAsOf` and
|
|
245
|
+
`bookingDate` stay the stated day.
|
|
246
|
+
- camt: a booking or value date given as `DtTm` without a `T` after the date, such as `2023-12-31`,
|
|
247
|
+
`2024-01-02 10:00:00` or `2024-01-02t10:00:00`, is the date written, as in the Dart package, instead of failing
|
|
248
|
+
`getTransactions` with `FinTsProtocolError`. Whatever follows the date is not read then. A `DtTm` or `Dt` with the
|
|
249
|
+
time `24:00:00` is midnight of the next day, as a FinTS 3.0 time `240000` is. A `Dt` with date and time counts on its
|
|
250
|
+
German day, as a `DtTm` does: `2024-03-15T23:30:00Z` is 16 March.
|
|
251
|
+
- MT940 and camt: `SVWZ+` after `ABWA+` or `ABWE+`, the order some banks write them in, starts the remittance
|
|
252
|
+
information, which went into the ultimate debtor or creditor, leaving the whole text, keywords and all, as the
|
|
253
|
+
purpose. Any other keyword in that text still starts no value, and one that occurs twice still has none.
|
|
254
|
+
- MT940: `getTransactions` joins pages with `@@` where none of them holds a line break. After a first page without `@@`,
|
|
255
|
+
such as `:20:X`, the `@@` of the other pages were read as text, and the query returned no transactions without an
|
|
256
|
+
error.
|
|
257
|
+
- camt: a comment ends only after its `<!--`, so that `<!-->` starts one instead of closing at once, which turned the
|
|
258
|
+
comment into text; an attribute counts by its name, namespace prefix and all, so that `q:Ccy` is not the currency of
|
|
259
|
+
an amount; an element named with a leading colon, such as `<:Ntry>`, is not the unprefixed one.
|
|
260
|
+
- The `EREF`, `MREF` and `CRED` of camt `purposeCodes` keep the place the remittance text gives them, before `SVWZ` as
|
|
261
|
+
banks write them, instead of following all other keywords. Their values still come from their elements only.
|
|
262
|
+
- MT940: the booking date of an MT942 lies between its value date and the creation date `:13D:`, which the statement's
|
|
263
|
+
balances otherwise bound, instead of in the year closest to the value date: a booking `1230` with value date
|
|
264
|
+
2023-06-15 in an MT942 created on 2024-01-02 is dated 2023-12-30, not 2022-12-30.
|
|
265
|
+
- MT940: a statement whose closing balance is dated before its opening balance, or whose creation date `:13D:` cannot be
|
|
266
|
+
read or is stated twice, is a `FormatError` (`FinTsProtocolError` in `getTransactions`) instead of being read.
|
|
267
|
+
- MT940: a statement that balances is read also where a sum on the way lies beyond what an `Amount` holds (about 90
|
|
268
|
+
trillion at two decimal places, less with more decimals), as camt batch bookings are. It failed `getTransactions` with
|
|
269
|
+
`FinTsProtocolError` 'Malformed bank data: MT940 amounts too large to add up', and `Mt940.parse` with `FormatError`. A
|
|
270
|
+
statement that does not balance fails with 'MT940 transactions do not add up to the closing balance' however large its
|
|
271
|
+
amounts, as in the Dart package.
|
|
272
|
+
- MT940: the subfield that ends a `:86:` field keeps the blanks at its end, as in the Dart package and before 0.2.0.
|
|
273
|
+
Where the bank writes it before subfields it continues, such as `?33Mustermann?32Max `, the purpose, the
|
|
274
|
+
counterparty's name and the SEPA keywords are joined with that blank (`Max Mustermann`, not `MaxMustermann`). Only the
|
|
275
|
+
statement end and line feeds are dropped from the end of a field.
|
|
276
|
+
- camt: a batch booking whose details add up to it is split also where their sum on the way lies beyond what an `Amount`
|
|
277
|
+
holds (about 90 trillion at two decimal places), whatever the order of the details; such a batch stayed one booking.
|
|
278
|
+
- U+0085 (NEL), the byte 0x85 in ISO 8859-1 text, counts as a blank wherever the client drops the blanks around a value,
|
|
279
|
+
as Unicode and the Dart package have it. That covers what it reads: MT940, SEPA purpose and camt values (a camt `Sts`
|
|
280
|
+
of `PDNG` followed by it reads as pending, not booked), the parameter data, such as the account owner, a segment's
|
|
281
|
+
type and numbers, amounts and challenge texts; and what it sends: segment values, the login details of `FinTsConfig`
|
|
282
|
+
and the TAN the user enters. The IBAN and BIC of an `Account`, which go without any blanks, drop it as well.
|
|
283
|
+
- camt: U+0085 (NEL), the byte 0x85 in ISO 8859-1, counts as white space between the parts of a start or end tag and
|
|
284
|
+
between the nodes outside the root element, as other Unicode white space did and as in the Dart package. Such a
|
|
285
|
+
document failed `getTransactions` with `FinTsProtocolError` and `Camt.parse` with `FormatError`.
|
|
286
|
+
- Bank text read as UTF-8 that starts with two byte order marks loses both, as in the Dart package; the second stayed as
|
|
287
|
+
U+FEFF in data element texts and the message log, and on an MT940 page after the first it failed `getTransactions`
|
|
288
|
+
with `FinTsProtocolError`.
|
|
289
|
+
- The security control reference that ties the signature head (HNSHK) to the signature end (HNSHA) is drawn uniformly:
|
|
290
|
+
its first nine digits up to 794967295 came up a quarter more often than the rest.
|
|
291
|
+
- A number in the parameter data beyond 9007199254740991 (2^53 - 1), which a JavaScript number holds only approximately,
|
|
292
|
+
counts as not stated, as a malformed one does. Such a version of the bank or user parameter data went back to the bank
|
|
293
|
+
as `100000000000000000000` or `1e+22` instead of `0`. A minimum PIN length of that size failed every login with a
|
|
294
|
+
`TypeError`. Polling parameters of that size let a decoupled TAN method poll every 60 seconds with no limit on the
|
|
295
|
+
number of requests other than the 10 minutes, instead of the defaults. An account type of that size made `category`
|
|
296
|
+
`'other'` instead of `'unknown'`.
|
|
297
|
+
- A number in the parameter data written `-0`, such as a version or an account type, reads as 0, as in the Dart package,
|
|
298
|
+
not as JavaScript's negative zero, which `util.inspect` shows as `-0` and `Object.is` tells apart from 0.
|
|
299
|
+
- An account in the user parameter data whose national account has the older layout without sub-account (number, country
|
|
300
|
+
and bank code, such as `1234567890:280:12345678`) keeps its country and bank code, as in the Dart package. It got the
|
|
301
|
+
sub-account `280`, the country code `12345678` and the configured bank code, so queries for it named an account the
|
|
302
|
+
bank does not know. Three elements whose last is a country code, such as `1234567890:01:280` or `987654321::040`,
|
|
303
|
+
still read as number, sub-account and country code: a country code has three digits, a German bank code eight.
|
|
304
|
+
- `getAccounts` completes an account of the user parameter data with the IBAN and BIC of the SEPA account list also
|
|
305
|
+
where one of the two states no bank or country code, which matches any, as in `Account.matches` and the Dart package.
|
|
306
|
+
This happens with a saved state edited so, or where a code the bank sent was only a byte order mark. The list entry
|
|
307
|
+
came out as an account of its own, and an account the app built from its IBAN went out as that entry, without bank
|
|
308
|
+
code, permitted transactions and currency.
|
|
309
|
+
- Up to three further pages of a query may ask for an approval, as its first page may: the client asks `tanCallback`, or
|
|
310
|
+
waits for the app approval, as for the first page. Until now only the first page could, and a bank that asked again
|
|
311
|
+
for a later page failed every such query with `FinTsProtocolError`, without asking the user. Where a fourth further
|
|
312
|
+
page of the same query asks for an approval, the call still fails with `FinTsProtocolError`, before the user is asked,
|
|
313
|
+
and the dialog ends. A query thus asks the user four times at most, and an approval the user cancels still fails the
|
|
314
|
+
call with `FinTsTanCancelledError` and loses the pages fetched so far. The Dart package 0.2.0 asks for every page, up
|
|
315
|
+
to 1000.
|
|
316
|
+
- `close` no longer waits for a transport that ignores the abort: five seconds after `close`, the request on its way
|
|
317
|
+
fails with a `FinTsTransportError` whatever the transport, and the dialog ends then have five seconds of their own.
|
|
318
|
+
A custom transport that ignored the `AbortSignal` and had no timeout of its own held up the call, and with it
|
|
319
|
+
`close`, forever.
|
|
320
|
+
- A network error whose cause has no message of its own, as Node.js reports a refused or failed connection to a host
|
|
321
|
+
with both IPv6 and IPv4 addresses, gives the reasons of the attempts or the error code, such as
|
|
322
|
+
`fetch failed: connect ECONNREFUSED ::1:3000; connect ECONNREFUSED 127.0.0.1:3000`, instead of just `fetch failed: `.
|
|
323
|
+
- The bank's dialog abort message (Formals B.7.6) fails the call with a `FinTsBankError` that carries the bank's
|
|
324
|
+
return codes and text, and ends the dialog. The bank sends it unencrypted, with the dialog ID `unbekannt` and message
|
|
325
|
+
number 9999, where it cannot tell them, such as for a broken message header, an unknown bank code or a bank locked
|
|
326
|
+
for a release. Such an answer to any message but the first of a dialog failed with the `FinTsProtocolError` 'The
|
|
327
|
+
answer belongs to another message than the one sent', which lost the bank's text, and the client then sent a dialog
|
|
328
|
+
end to the dialog the bank had aborted.
|
|
329
|
+
- Balance and transaction queries that name the account by its international account (`HKSAL` 7 and 8, `HKKAZ` 7,
|
|
330
|
+
`HKCAZ`) name an account with BIC by IBAN and BIC only, without account number, sub-account and bank code, where the
|
|
331
|
+
bank parameter data rule out the national account (`HISPAS` 'Nationale Kontoverbindung erlaubt' `N`). They no longer
|
|
332
|
+
send an IBAN without its BIC, which the specification rules out (Messages B.3.2): such an account goes out with its
|
|
333
|
+
account number, sub-account and bank code instead, where it has an account number. Until now these queries always
|
|
334
|
+
sent the national account, and an IBAN without BIC with an empty BIC.
|
|
335
|
+
- The account extension of the user parameter data (BIC, data status and complete balance) is read where the bank
|
|
336
|
+
pads it with U+0085 (NEL) or U+00A0, as the client allows for the other fields. Such an extension was ignored, so the
|
|
337
|
+
client fetched the BIC with the SEPA account list and the balance with a balance query.
|
|
338
|
+
- A synchronization with the one-step method that the bank answers with `9955` (one-step TAN method not allowed) and
|
|
339
|
+
`3920`, as PIN/TAN B.8.2 prescribes for a user bound to two-step methods, is repeated with a method the bank lists,
|
|
340
|
+
with or without `9800`. It refused the login for good and forgot the PIN.
|
|
341
|
+
- A call whose TAN method prompt after a refused login ends with an error, such as `close` during
|
|
342
|
+
`tanMethodSelector`, fails with that error and leaves no refusal behind. The refusal, which named a TAN method the
|
|
343
|
+
user may not use and not the PIN, outlasted the call: the client forgot the PIN, saved the refusal in `client.state`,
|
|
344
|
+
and refused every login until `clearLoginRefusal`.
|
|
345
|
+
- Plain JavaScript can no longer change `Transaction.purposeCodes` or `AccountDataStatus.inventory` through the map
|
|
346
|
+
inside them: `ImmutableMap` keeps its entries in an ECMAScript-private field.
|
|
347
|
+
- A flicker code whose start code states a length of 0, or sets bit 6 of its length, is refused, as a data element of
|
|
348
|
+
such a length already was. `FlickerCode.parse` read an empty start code, which rendered as ASCII data of length 0,
|
|
349
|
+
and dropped bit 6.
|
|
350
|
+
- A flicker code whose tenth control byte announces another one is refused. It was read as if the list had ended
|
|
351
|
+
there, and the rest of the code was read from the wrong position.
|
|
352
|
+
- A blank in the data of a flicker code, such as `1,00 EUR`, stays part of the data. The client removed every white
|
|
353
|
+
space before reading the code, so such a code in HHD_UC was refused and the challenge had no `flickerCode`.
|
|
354
|
+
- A challenge whose HHD_UC is neither a photoTAN image nor a flicker code takes the flicker code of its challenge text
|
|
355
|
+
(`CHLGUC`). `TanChallenge.flickerCode` was `undefined` then, although `plainMessage` left out the code.
|
|
356
|
+
- Challenge text counts as a combined challenge only where it starts with `CHLGUC`, after blanks, and the four digits
|
|
357
|
+
after it state the length of the code. Elsewhere it is shown as the bank sent it: `plainMessage` dropped everything
|
|
358
|
+
up to a `CHLGTEXT` anywhere in the text, such as in a payment purpose the bank copied in, and a `CHLGUC` in the
|
|
359
|
+
middle of the text gave a flicker code.
|
|
360
|
+
- `TanImage.tryParse` refuses a container that declares an image of 0 bytes. It gave an image whose `toDataUrl()` was
|
|
361
|
+
an empty `data:` URL.
|
|
362
|
+
- MT940: the balance date `0` or `000000`, which the specification allows for the first statement of an account,
|
|
363
|
+
reads as no date (`openingDate` or `closingDate` `undefined`). It failed `getTransactions` with
|
|
364
|
+
`FinTsProtocolError` and `Mt940.parse` with `FormatError`.
|
|
365
|
+
- MT940: the `:61:` customer reference `KREF+` reads as the `KREF+` value of `:86:`, as the specification has it,
|
|
366
|
+
instead of `'KREF+'` for every such transaction.
|
|
367
|
+
- MT940: a bank code in `?30` next to an IBAN in `?31` is `counterpartyBankCode`, not `counterpartyBic`.
|
|
368
|
+
- `Mt940.parse` reads text that starts with a byte order mark or blanks, as `fs.readFile(…, 'utf8')` returns it. It
|
|
369
|
+
dropped the first `:20:` and returned its statement without `reference`.
|
|
370
|
+
- camt: a transaction whose remittance information is structured only (`Strd/CdtrRefInf/Ref`, such as an RF creditor
|
|
371
|
+
reference) takes that reference as its `purpose`, which was `undefined` or the `AddtlTxInf`.
|
|
372
|
+
- The README example saves `client.state` after `close`, not before, also where `close` fails: the answers `close`
|
|
373
|
+
waits for may bring a PIN the bank rejects at the dialog end, which a client restored from a state saved before would
|
|
374
|
+
send again, as well as the parameter data and the customer system ID of a request on its way.
|
|
375
|
+
- The README says what the type declarations need: the global `URL`, `AbortSignal` and `fetch` types, from the
|
|
376
|
+
TypeScript lib `DOM` or `@types/node`, instead of a TypeScript version.
|
|
377
|
+
|
|
1
378
|
## 0.2.0
|
|
2
379
|
|
|
3
380
|
### Breaking
|
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
A FinTS 3.0 client for German banks, written in TypeScript, without runtime dependencies. It reads accounts, balances and transactions with PIN/TAN, including PSD2 strong customer authentication and app approval (pushTAN, SecureGo plus and the like).
|
|
4
4
|
|
|
5
|
-
It is a port of the Dart package [`fints`](https://pub.dev/packages/fints)
|
|
5
|
+
It is a port of the Dart package [`fints`](https://pub.dev/packages/fints) (see [Differences from the Dart package](#differences-from-the-dart-package)). FinTS 4.1, which hardly any bank offers, is not part of the port.
|
|
6
6
|
|
|
7
7
|
## Features
|
|
8
8
|
|
|
@@ -20,7 +20,7 @@ It is a port of the Dart package [`fints`](https://pub.dev/packages/fints), with
|
|
|
20
20
|
|
|
21
21
|
1. **A FinTS product registration.** German banks only accept registered products. Register for free with the Deutsche Kreditwirtschaft at <https://www.fints.org/de/hersteller/produktregistrierung> and pass the ID as `productId`. Keep it out of your repository.
|
|
22
22
|
2. **Your bank's FinTS URL and bank code (BLZ)**, for example from the DK institute list.
|
|
23
|
-
3. **A runtime with `fetch`, Web Crypto and `TextDecoder`**: Node.js from 22.12, Deno from 2.1, Bun from 1.2.6, or a browser behind a server of your own (see [Using it with Vue](#using-it-with-vue)). The type declarations
|
|
23
|
+
3. **A runtime with `fetch`, Web Crypto and `TextDecoder`**: Node.js from 22.12, Deno from 2.1, Bun from 1.2.6, or a browser behind a server of your own (see [Using it with Vue](#using-it-with-vue)). The type declarations use the global `URL`, `AbortSignal` and `fetch` types: include the TypeScript lib `DOM` or `@types/node`.
|
|
24
24
|
|
|
25
25
|
## Usage
|
|
26
26
|
|
|
@@ -62,12 +62,15 @@ try {
|
|
|
62
62
|
const balance = await client.getBalance(accounts[0]!);
|
|
63
63
|
const transactions = await client.getTransactions(accounts[0]!, { from: new Date(2024, 0, 1) });
|
|
64
64
|
} finally {
|
|
65
|
-
|
|
66
|
-
|
|
65
|
+
try {
|
|
66
|
+
await client.close();
|
|
67
|
+
} finally {
|
|
68
|
+
saveEncrypted(client.state); // after close, whose answers may change it; no PIN or TAN, but login and account data
|
|
69
|
+
}
|
|
67
70
|
}
|
|
68
71
|
```
|
|
69
72
|
|
|
70
|
-
A call logs in where it needs to, which sends the PIN and may ask the callbacks for a TAN method, a TAN medium and an approval; so does `getTanMethods` of a client without saved state. Calls share one bank dialog while it is open, so the approval of its login serves them all. The next call logs in anew, which may ask for another approval, once the dialog has idled longer than the bank allows (`BankInfo.maxTimeout`, 5 minutes where it states none), after `selectTanMethod` and `clearLoginRefusal`, once the bank has ended the dialog, and after a message failed with another error than a `FinTsBankError`, such as a cancelled or timed-out approval, a failing `tanCallback`, or a lost or unreadable answer. A query may need an approval of its own, such as one for transactions older than 90 days
|
|
73
|
+
A call logs in where it needs to, which sends the PIN and may ask the callbacks for a TAN method, a TAN medium and an approval; so does `getTanMethods` of a client without saved state. Calls share one bank dialog while it is open, so the approval of its login serves them all. The next call logs in anew, which may ask for another approval, once the dialog has idled longer than the bank allows (`BankInfo.maxTimeout`, 5 minutes where it states none), after `selectTanMethod` and `clearLoginRefusal`, once the bank has ended the dialog, and after a message failed with another error than a `FinTsBankError`, such as a cancelled or timed-out approval, a failing `tanCallback`, or a lost or unreadable answer. A query may need an approval of its own, such as one for transactions older than 90 days, and so may up to three of its further pages; where a fourth asks for one, the call fails with `FinTsProtocolError` before the user is asked.
|
|
71
74
|
|
|
72
75
|
Calls run one after another. A callback must not wait for another call of its client, which would wait for the running call: on Node.js, Deno and Bun such a call fails with `FinTsStateError`, in browsers it waits forever.
|
|
73
76
|
|
|
@@ -75,6 +78,8 @@ A saved state belongs to one client at a time. Run the clients of one bank user
|
|
|
75
78
|
|
|
76
79
|
Never log the client: `JSON.stringify` and Node.js's `console.log` leave out the PIN, which the client keeps in a private field until it is closed or the login refused, but a debugger and the browser's DevTools show it.
|
|
77
80
|
|
|
81
|
+
`console.log` and `util.inspect` on Node.js, Deno and Bun show the objects of this package only by what identifies no person, account or TAN: codes, kinds, counts, dates and the last digits of an IBAN or card number, such as `Account(…3000, Girokonto)`, `TanChallenge(TanMethod(942, pushTAN), decoupled, attempt 1)` or `FinTsFeedback(9010)`. They leave out the bank's texts, references and parameters, TAN media names, TANs, challenge data and images, login data, and the amounts of balances and transactions; an `Amount` on its own shows as its `toString`, such as `-123.45 EUR`. `toString` of a `FinTsFeedback` and of a `BankMessage` leaves out the bank's texts as well: show `code` and `text`, or `subject` and `text`, to the user. An error shows its message and stack, and a `FinTsTransportError` its `statusCode`, also where Node.js reports it uncaught; the message of a `FinTsBankError`, and so its stack, holds the bank's texts and parameters of its errors, such as an IBAN, so log its `codes` instead. `JSON.stringify` and the browser console show every field, IBANs, names, amounts, purposes and the TAN of a `TanAnswer` included, so that a server can pass the data to its own front end: neither belongs in logs. Only `JSON.stringify` of an error leaves out the `feedback` of a `FinTsBankError` and the `source` of a `FormatError`.
|
|
82
|
+
|
|
78
83
|
An account the app builds itself, such as `new Account({ bankCode, iban })`, stands for the account of `getAccounts` it matches by IBAN or account number, whose details and permitted transactions the queries take. One the bank names nowhere goes out with what identifies it only, and fails with `FinTsUnsupportedError` where the bank's lists of permitted transactions are complete.
|
|
79
84
|
|
|
80
85
|
Calendar dates, such as `Transaction.bookingDate`, are `Date`s at local midnight, of which only the day counts. Moments, such as `Balance.bookedAsOfTime`, are exact; the bank states them in German time.
|
|
@@ -97,7 +102,7 @@ There are three ways to set it up:
|
|
|
97
102
|
method: 'POST',
|
|
98
103
|
headers: { 'Content-Type': contentType, 'X-FinTS-URL': url.href },
|
|
99
104
|
body: body.slice(), // a copy on an ArrayBuffer of its own, the only kind TypeScript's fetch types take
|
|
100
|
-
signal, // aborted
|
|
105
|
+
signal, // aborted five seconds after the client is closed
|
|
101
106
|
redirect: 'error', // never send the PIN on to another address
|
|
102
107
|
cache: 'no-store',
|
|
103
108
|
});
|
|
@@ -111,16 +116,20 @@ There are three ways to set it up:
|
|
|
111
116
|
};
|
|
112
117
|
```
|
|
113
118
|
|
|
114
|
-
The relay forwards with `HttpTransport`, which times out, limits the size of the answer and follows no redirect, and passes the bank's HTTP status on. A sketch with the web-standard `Request` and `Response`:
|
|
119
|
+
Until it is closed, the client limits neither the time of an exchange nor the size of an answer, so a transport of your own has to, unless it goes through a relay that does, as this one does. The relay forwards with `HttpTransport`, which times out, limits the size of the answer and follows no redirect, and passes the bank's HTTP status on. A sketch with the web-standard `Request` and `Response`:
|
|
115
120
|
|
|
116
121
|
```ts
|
|
117
122
|
import { FinTsTransportError, HttpTransport } from '@coderoftime/fints';
|
|
118
123
|
|
|
119
124
|
const bank = new HttpTransport();
|
|
125
|
+
const maxBodyBytes = 1024 * 1024; // far more than a message of the client takes
|
|
120
126
|
|
|
121
127
|
// Behind the app's login and a rate limit per session; bankUrl is the bank the user chose, as URL.href writes it.
|
|
122
128
|
export async function relay(request: Request, session: { bankUrl: string }): Promise<Response> {
|
|
123
129
|
if (request.headers.get('X-FinTS-URL') !== session.bankUrl) return new Response(null, { status: 403 });
|
|
130
|
+
// Checked before the body is read, of which the server reads no more than the length states.
|
|
131
|
+
const length = Number(request.headers.get('Content-Length') ?? NaN);
|
|
132
|
+
if (!(length <= maxBodyBytes)) return new Response(null, { status: 413 });
|
|
124
133
|
try {
|
|
125
134
|
const body = new Uint8Array(await request.arrayBuffer());
|
|
126
135
|
const answer = await bank.post(new URL(session.bankUrl), body, 'text/plain', request.signal);
|
|
@@ -135,7 +144,7 @@ There are three ways to set it up:
|
|
|
135
144
|
|
|
136
145
|
Anyone who can call the relay can send logins to the banks it forwards to, from your server's address, which a bank may then block for all your users. So serve it to the signed-in sessions of your app only, limit the requests of each session, and forward only to the bank the user chose for the session, from a list of known https URLs such as the DK institute list. The body holds PIN and TAN: never log it, on either side, nor put it in an error message, which the client passes on. And never mix up the answers of two sessions: the client cannot tell the answer to the first message of a dialog from that of another user. The product ID ends up in the page; anyone can read it there.
|
|
137
146
|
|
|
138
|
-
3. **The app is not a web page**: Electron, Tauri or Capacitor can send requests without CORS. Pass a `FinTsTransport` that uses the platform's HTTP client without following redirects, or `HttpTransport` where `fetch` is not bound by CORS.
|
|
147
|
+
3. **The app is not a web page**: Electron, Tauri or Capacitor can send requests without CORS. Pass a `FinTsTransport` that uses the platform's HTTP client without following redirects, with a timeout and a limit on the size of the answer, or `HttpTransport` where `fetch` is not bound by CORS.
|
|
139
148
|
|
|
140
149
|
Keep a client in the Vue app out of reactive state (`ref`, `reactive`, a Pinia store): Vue wraps it in a proxy there, which cannot reach the client's private fields, so every call fails with a `TypeError`. A plain variable, a `shallowRef` or `markRaw(client)` keeps the client as it is.
|
|
141
150
|
|
|
@@ -157,7 +166,7 @@ export function tanCallback(challenge: TanChallenge): Promise<TanAnswer> {
|
|
|
157
166
|
// TanAnswer.approved or TanAnswer.cancelled, then clears pending.value.
|
|
158
167
|
```
|
|
159
168
|
|
|
160
|
-
The dialog shows the challenge's text with `{{ }}`, which Vue escapes, never with `v-html`: `plainMessage` and `message`, like any text of the bank, are no markup to trust, and as HTML they could run scripts in the page where the user enters the PIN. `white-space: pre-line` keeps the line breaks of `plainMessage`:
|
|
169
|
+
The dialog shows the challenge's text with `{{ }}`, which Vue escapes, never with `v-html`: `plainMessage` and `message`, like any text of the bank, are no markup to trust, and as HTML they could run scripts in the page where the user enters the PIN. The same holds for the bank messages and warnings of `onBankMessage` and `onWarning`, whose number and length the bank chooses without a limit, so bound what the app shows of them. `white-space: pre-line` keeps the line breaks of `plainMessage`:
|
|
161
170
|
|
|
162
171
|
```vue
|
|
163
172
|
<div v-if="pending">
|
|
@@ -187,7 +196,7 @@ The dialog shows the challenge's text with `{{ }}`, which Vue escapes, never wit
|
|
|
187
196
|
|
|
188
197
|
The client never repeats a call by itself: the bank's answer cannot tell whether an order went through.
|
|
189
198
|
|
|
190
|
-
It reads only complete answers to the message it sent: one cut short, broken,
|
|
199
|
+
It reads only complete answers to the message it sent: one cut short, broken, or with the number or dialog ID of another message fails the call with `FinTsProtocolError`. Only the bank's dialog abort message, which names neither (dialog ID `unbekannt`, message number 9999), answers any message: it fails the call with a `FinTsBankError` that holds the bank's text, and ends the dialog. The first message of every dialog goes out with the same number and dialog ID, though, so the answer to another user's first message passes: a relay must never mix up answers. A query whose pages hold more than 128 MiB, each data element counted as 512 bytes, or more than 200,000 statements and transactions, fails with `FinTsProtocolError` as well: ask for a shorter period then. So that a broken or hostile server cannot block the app or exhaust its memory, the client also refuses an answer with more than 1,000,000 data elements and segments in its plain or in its encrypted part, or with more than one encrypted part; XML nested more than 100 levels deep, or with more than 500,000 nodes besides text or one per 16 characters, whichever is more; an MT940 field or camt remittance information (`Ustrd`) of more than 65,536 characters; and an amount written with more than 64 characters. `Mt940.parse`, `Camt.parse` and `Amount.parseDecimal` throw `FormatError` for these.
|
|
191
200
|
|
|
192
201
|
MT940 statements must balance. Where a bank wraps a purpose at a fixed width, a payer could start a line of it like a field, such as `:61:`, which would add a transaction; `getTransactions` fails with `FinTsProtocolError` instead, and `Mt940.parse` with `FormatError`. The check misses such lines that add up to nothing, and statements without balances, such as pending transactions (MT942).
|
|
193
202
|
|
|
@@ -195,11 +204,11 @@ MT940 statements must balance. Where a bank wraps a purpose at a fixed width, a
|
|
|
195
204
|
|
|
196
205
|
Banks lock the online access after a few failed logins. So once the bank has refused a login, the client does not send the PIN again: every call that would fails with the refusal, a `FinTsLoginRefusedError`, without contacting the bank. Any error in the answer to a login refuses it, since a return code does not always tell whether the PIN was the reason, and so does a wrong PIN the bank reports later in the dialog.
|
|
197
206
|
|
|
198
|
-
Only where the bank names a reason the client can take care of does the same call log in once more, once per reason: with another TAN method where the bank lists those the user may use without the one the login was signed with (`3920`, after the one-step method only next to no error but `9050` or `
|
|
207
|
+
Only where the bank names a reason the client can take care of does the same call log in once more, once per reason: with another TAN method where the bank lists those the user may use without the one the login was signed with (`3920`, after the one-step method only next to no error but `9050`, `9800` or `9955`) or demands strong authentication of a one-step login (`9075`), and with a new customer system ID where the bank rejects the old one (`9391`). None of them follows a wrong PIN, and a call sends at most three logins the bank refuses.
|
|
199
208
|
|
|
200
209
|
A login whose answer is lost, times out, is aborted by `close` or cannot be read may have counted as a failed attempt all the same. After two such logins in a row the client refuses the login itself, with a `FinTsLoginRefusedError` whose `feedback` is empty; it cannot tell a login that never reached the bank, so a connection that fails twice in a row stops it as well. A login the bank takes clears the count.
|
|
201
210
|
|
|
202
|
-
The refusal and that count are part of `client.state`, so a client restored from it does not send the PIN either, as long as the clients of the user take turns with the state (see [Usage](#usage)); `client.loginRefusal` tells it before any call. Lift it with a PIN the user has entered anew, unless the bank has changed the login data:
|
|
211
|
+
The refusal and that count are part of `client.state`, so a client restored from it does not send the PIN either, as long as the clients of the user take turns with the state (see [Usage](#usage)); where their part of the state is damaged, the client restores a refusal whose `feedback` is empty. `client.loginRefusal` tells it before any call. Lift it with a PIN the user has entered anew, unless the bank has changed the login data:
|
|
203
212
|
|
|
204
213
|
```ts
|
|
205
214
|
const refusal = client.loginRefusal;
|
|
@@ -215,19 +224,18 @@ Never pass `clearLoginRefusal` a stored PIN without asking the user: that is how
|
|
|
215
224
|
|
|
216
225
|
## Differences from the Dart package
|
|
217
226
|
|
|
218
|
-
|
|
227
|
+
This section compares with the Dart package as its source stands after its release 0.2.0, which differs in more ways. Both keep the saved state in the same layout, a refused login included, so each restores the other's. The Dart package 0.2.0 keeps no refused login, though: restored from a state of this package, it sends the PIN the bank refused. They differ in:
|
|
228
|
+
|
|
229
|
+
- Errors are named `…Error` instead of `…Exception`; invalid arguments are `TypeError`s, malformed data `FormatError`s, and a closed client or a call from inside a callback a `FinTsStateError`. Some messages are worded differently.
|
|
219
230
|
- `getTransactions(account, { from, to, format })` takes an options object; enums are string unions such as `'mt940'`.
|
|
220
231
|
- The polling parameters of `TanMethod` are in seconds: `decoupledFirstPollDelaySeconds`, `decoupledPollIntervalSeconds`.
|
|
221
|
-
-
|
|
222
|
-
- `close` aborts a request on its way
|
|
223
|
-
-
|
|
224
|
-
-
|
|
225
|
-
-
|
|
226
|
-
-
|
|
227
|
-
-
|
|
228
|
-
- MT940 statements must balance.
|
|
229
|
-
- camt batch bookings are split only where their details add up, the creditor ID is the creditor's, and `DtTm` counts on its German day.
|
|
230
|
-
- A SEPA keyword in the text the payer or payee writes (`SVWZ+`, `ABWA+`, `ABWE+`) never replaces a value the bank stated.
|
|
232
|
+
- No FinTS 4.1, so no `FinTs4Client`, `FinTsClient.version` or `BankInfo.bic`. `FinTsConfig` checks the login data against what FinTS 3.0 can send, which the Dart package does in `FinTs3Client`, and also refuses a user ID or customer ID of more than 30 characters, which the Dart package sends.
|
|
233
|
+
- `HttpTransport` takes a `fetch` and `timeoutMs` instead of an HTTP client and a `Duration`. `FinTsTransport.post` takes an `AbortSignal`, with which `close` aborts a request on its way after five seconds, also through a custom transport, and then stops waiting for it whatever the transport does; the Dart package aborts only its own `HttpTransport` (`abortRequests`) and waits for any other transport up to that transport's timeout.
|
|
234
|
+
- HTTP goes through the runtime's `fetch`, with its proxies, timeouts and trusted certificates. Plain http to a local server, which `allowInsecureUrl` allows, goes wherever the global `fetch` sends it, as https does: to whatever replaces `globalThis.fetch`, such as a test's stub, to a global dispatcher on Node.js, and through any proxy that `fetch` takes from the environment (Node.js with `NODE_USE_ENV_PROXY=1`, Deno and Bun with `HTTP_PROXY`), which sees the PIN. Exempt the host with `NO_PROXY=localhost,127.0.0.1,::1` or pass a `fetch` that connects directly. The Dart package connects to the loopback host directly, also bypassing a client set with `runWithClient`, and on native platforms follows `HTTPS_PROXY` and `NO_PROXY` for https, which Node.js does only with `NODE_USE_ENV_PROXY=1`.
|
|
235
|
+
- A call from inside a callback fails on Node.js, Deno and Bun only; in browsers it waits forever, where the Dart package fails on every platform.
|
|
236
|
+
- `console.log` and `util.inspect` show the objects of this package as [Usage](#usage) describes, where the Dart package prints most of them as `Instance of '…'`, and `toString` of a `FinTsFeedback` or a `BankMessage` leaves out the bank's texts, which the Dart package prints. The browser console shows every field, where the Dart package on the web prints `toString`.
|
|
237
|
+
- `JSON.stringify` gives every field of a model, the TAN of a `TanAnswer` included, and of an error its `name`, and the `statusCode` of a `FinTsTransportError`; the Dart package's models and errors have no JSON form.
|
|
238
|
+
- Some bank data are read and sent otherwise. In MT940, the counterparty's IBAN and BIC come from the subfields `?31` and `?30` only, not from `IBAN+` and `BIC+` in the payer's reference, a bank code in `?30` next to an IBAN is the bank code, the customer reference `KREF+` stands for the one of `:86:`, and the balance date `0` or `000000` for none. A camt purpose falls back to the structured creditor reference, and remittance information of more than 65,536 characters is refused. Challenge text counts as a combined chipTAN challenge only where it starts with `CHLGUC` and states the length of its code. The bank's dialog abort message fails the call with a `FinTsBankError`. A balance or transaction query that names the account by its international account (KTI) leaves out the national account where the bank parameter data rule it out, unless the account has no BIC, and sends no IBAN without its BIC, unless the account has no account number. A one-step login that the bank answers with `9955` and `3920` is repeated with a two-step method.
|
|
231
239
|
|
|
232
240
|
## Development
|
|
233
241
|
|
package/dist/client.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
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';
|
|
@@ -28,7 +28,8 @@ export declare class FinTs3Client implements FinTsClient {
|
|
|
28
28
|
*
|
|
29
29
|
* Throws `TypeError` if the configuration is invalid, as the constructor of `FinTsConfig` tells, or the PIN is empty,
|
|
30
30
|
* begins or ends with a blank, or has characters FinTS 3.0 cannot send: it uses ISO 8859-1, so `€` and most
|
|
31
|
-
* non-Latin letters are not possible.
|
|
31
|
+
* non-Latin letters are not possible. Throws `TypeError` as well for an option of another type than
|
|
32
|
+
* `FinTsClientOptions` names, as `FinTsClientOptions` tells.
|
|
32
33
|
*/
|
|
33
34
|
constructor(init: FinTs3ClientInit);
|
|
34
35
|
get state(): string;
|
package/dist/client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAC5C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,KAAK,EAAE,WAAW,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAC1F,OAAO,EAAE,WAAW,EAAc,KAAK,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACjF,OAAO,EAA0C,KAAK,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;AACvG,OAAO,KAAK,EAAE,WAAW,EAAqB,MAAM,uBAAuB,CAAC;AAS5E,OAAO,EAAE,SAAS,EAAE,KAAK,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAUhE,iCAAiC;AACjC,MAAM,WAAW,gBAAgB;IAC/B,mFAAmF;IACnF,MAAM,EAAE,WAAW,GAAG,eAAe,CAAC;IACtC;;;;;OAKG;IACH,GAAG,EAAE,MAAM,CAAC;IACZ,oDAAoD;IACpD,OAAO,EAAE,kBAAkB,CAAC;CAC7B;AA2CD,8DAA8D;AAC9D,qBAAa,YAAa,YAAW,WAAW;;IAkC9C;;;;;;;OAOG;gBACS,IAAI,EAAE,gBAAgB;IAyBlC,IAAI,KAAK,IAAI,MAAM,CAElB;IAED,IAAI,YAAY,IAAI,sBAAsB,GAAG,SAAS,CAErD;IAED,IAAI,iBAAiB,IAAI,MAAM,GAAG,SAAS,CAE1C;IAED,IAAI,iBAAiB,IAAI,MAAM,GAAG,SAAS,CAE1C;IAEK,eAAe,CAAC,gBAAgB,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAUlF,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAU7C,WAAW,IAAI,OAAO,CAAC,QAAQ,CAAC;IAIhC,aAAa,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;IAIrC,WAAW,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;IAenC,WAAW,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;IAI3B,UAAU,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IAe9C,eAAe,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,GAAE,gBAAqB,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IAqB7F,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CA4CvB"}
|