@coderoftime/fints 0.0.0-stage → 0.1.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.
Files changed (254) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/LICENSE +28 -0
  3. package/README.md +156 -2
  4. package/dist/core/account.d.ts +140 -0
  5. package/dist/core/account.d.ts.map +1 -0
  6. package/dist/core/account.js +174 -0
  7. package/dist/core/account.js.map +1 -0
  8. package/dist/core/amount.d.ts +62 -0
  9. package/dist/core/amount.d.ts.map +1 -0
  10. package/dist/core/amount.js +189 -0
  11. package/dist/core/amount.js.map +1 -0
  12. package/dist/core/balance.d.ts +54 -0
  13. package/dist/core/balance.d.ts.map +1 -0
  14. package/dist/core/balance.js +53 -0
  15. package/dist/core/balance.js.map +1 -0
  16. package/dist/core/bank-info.d.ts +49 -0
  17. package/dist/core/bank-info.d.ts.map +1 -0
  18. package/dist/core/bank-info.js +52 -0
  19. package/dist/core/bank-info.js.map +1 -0
  20. package/dist/core/client.d.ts +126 -0
  21. package/dist/core/client.d.ts.map +1 -0
  22. package/dist/core/client.js +2 -0
  23. package/dist/core/client.js.map +1 -0
  24. package/dist/core/config.d.ts +68 -0
  25. package/dist/core/config.d.ts.map +1 -0
  26. package/dist/core/config.js +113 -0
  27. package/dist/core/config.js.map +1 -0
  28. package/dist/core/errors.d.ts +91 -0
  29. package/dist/core/errors.d.ts.map +1 -0
  30. package/dist/core/errors.js +182 -0
  31. package/dist/core/errors.js.map +1 -0
  32. package/dist/core/feedback.d.ts +69 -0
  33. package/dist/core/feedback.d.ts.map +1 -0
  34. package/dist/core/feedback.js +124 -0
  35. package/dist/core/feedback.js.map +1 -0
  36. package/dist/core/transaction.d.ts +98 -0
  37. package/dist/core/transaction.d.ts.map +1 -0
  38. package/dist/core/transaction.js +91 -0
  39. package/dist/core/transaction.js.map +1 -0
  40. package/dist/core/transport.d.ts +37 -0
  41. package/dist/core/transport.d.ts.map +1 -0
  42. package/dist/core/transport.js +92 -0
  43. package/dist/core/transport.js.map +1 -0
  44. package/dist/formats/camt.d.ts +12 -0
  45. package/dist/formats/camt.d.ts.map +1 -0
  46. package/dist/formats/camt.js +159 -0
  47. package/dist/formats/camt.js.map +1 -0
  48. package/dist/formats/mt940.d.ts +42 -0
  49. package/dist/formats/mt940.d.ts.map +1 -0
  50. package/dist/formats/mt940.js +297 -0
  51. package/dist/formats/mt940.js.map +1 -0
  52. package/dist/formats/readers.d.ts +11 -0
  53. package/dist/formats/readers.d.ts.map +1 -0
  54. package/dist/formats/readers.js +47 -0
  55. package/dist/formats/readers.js.map +1 -0
  56. package/dist/formats/sepa-purpose.d.ts +22 -0
  57. package/dist/formats/sepa-purpose.d.ts.map +1 -0
  58. package/dist/formats/sepa-purpose.js +68 -0
  59. package/dist/formats/sepa-purpose.js.map +1 -0
  60. package/dist/index.d.ts +28 -0
  61. package/dist/index.d.ts.map +1 -0
  62. package/dist/index.js +27 -0
  63. package/dist/index.js.map +1 -0
  64. package/dist/session/app-approval.d.ts +60 -0
  65. package/dist/session/app-approval.d.ts.map +1 -0
  66. package/dist/session/app-approval.js +215 -0
  67. package/dist/session/app-approval.js.map +1 -0
  68. package/dist/session/bank-connection.d.ts +28 -0
  69. package/dist/session/bank-connection.d.ts.map +1 -0
  70. package/dist/session/bank-connection.js +48 -0
  71. package/dist/session/bank-connection.js.map +1 -0
  72. package/dist/session/dialog-runner.d.ts +34 -0
  73. package/dist/session/dialog-runner.d.ts.map +1 -0
  74. package/dist/session/dialog-runner.js +112 -0
  75. package/dist/session/dialog-runner.js.map +1 -0
  76. package/dist/session/login-guard.d.ts +73 -0
  77. package/dist/session/login-guard.d.ts.map +1 -0
  78. package/dist/session/login-guard.js +109 -0
  79. package/dist/session/login-guard.js.map +1 -0
  80. package/dist/session/parameter-data.d.ts +83 -0
  81. package/dist/session/parameter-data.d.ts.map +1 -0
  82. package/dist/session/parameter-data.js +68 -0
  83. package/dist/session/parameter-data.js.map +1 -0
  84. package/dist/session/pin-tan-client.d.ts +54 -0
  85. package/dist/session/pin-tan-client.d.ts.map +1 -0
  86. package/dist/session/pin-tan-client.js +153 -0
  87. package/dist/session/pin-tan-client.js.map +1 -0
  88. package/dist/session/pin-tan-dialog.d.ts +71 -0
  89. package/dist/session/pin-tan-dialog.d.ts.map +1 -0
  90. package/dist/session/pin-tan-dialog.js +124 -0
  91. package/dist/session/pin-tan-dialog.js.map +1 -0
  92. package/dist/session/protocol.d.ts +209 -0
  93. package/dist/session/protocol.d.ts.map +1 -0
  94. package/dist/session/protocol.js +75 -0
  95. package/dist/session/protocol.js.map +1 -0
  96. package/dist/session/response-handler.d.ts +48 -0
  97. package/dist/session/response-handler.d.ts.map +1 -0
  98. package/dist/session/response-handler.js +121 -0
  99. package/dist/session/response-handler.js.map +1 -0
  100. package/dist/session/sepa-accounts.d.ts +34 -0
  101. package/dist/session/sepa-accounts.d.ts.map +1 -0
  102. package/dist/session/sepa-accounts.js +96 -0
  103. package/dist/session/sepa-accounts.js.map +1 -0
  104. package/dist/session/session-setup.d.ts +72 -0
  105. package/dist/session/session-setup.d.ts.map +1 -0
  106. package/dist/session/session-setup.js +160 -0
  107. package/dist/session/session-setup.js.map +1 -0
  108. package/dist/session/session-state.d.ts +47 -0
  109. package/dist/session/session-state.d.ts.map +1 -0
  110. package/dist/session/session-state.js +147 -0
  111. package/dist/session/session-state.js.map +1 -0
  112. package/dist/session/tan-selection.d.ts +88 -0
  113. package/dist/session/tan-selection.d.ts.map +1 -0
  114. package/dist/session/tan-selection.js +178 -0
  115. package/dist/session/tan-selection.js.map +1 -0
  116. package/dist/session/user-prompts.d.ts +61 -0
  117. package/dist/session/user-prompts.d.ts.map +1 -0
  118. package/dist/session/user-prompts.js +164 -0
  119. package/dist/session/user-prompts.js.map +1 -0
  120. package/dist/tan/challenge.d.ts +114 -0
  121. package/dist/tan/challenge.d.ts.map +1 -0
  122. package/dist/tan/challenge.js +185 -0
  123. package/dist/tan/challenge.js.map +1 -0
  124. package/dist/tan/flicker.d.ts +36 -0
  125. package/dist/tan/flicker.d.ts.map +1 -0
  126. package/dist/tan/flicker.js +262 -0
  127. package/dist/tan/flicker.js.map +1 -0
  128. package/dist/tan/tan-image.d.ts +21 -0
  129. package/dist/tan/tan-image.d.ts.map +1 -0
  130. package/dist/tan/tan-image.js +41 -0
  131. package/dist/tan/tan-image.js.map +1 -0
  132. package/dist/tan/tan-models.d.ts +145 -0
  133. package/dist/tan/tan-models.d.ts.map +1 -0
  134. package/dist/tan/tan-models.js +148 -0
  135. package/dist/tan/tan-models.js.map +1 -0
  136. package/dist/util/async.d.ts +24 -0
  137. package/dist/util/async.d.ts.map +1 -0
  138. package/dist/util/async.js +49 -0
  139. package/dist/util/async.js.map +1 -0
  140. package/dist/util/bytes.d.ts +23 -0
  141. package/dist/util/bytes.d.ts.map +1 -0
  142. package/dist/util/bytes.js +136 -0
  143. package/dist/util/bytes.js.map +1 -0
  144. package/dist/util/call-context.d.ts +12 -0
  145. package/dist/util/call-context.d.ts.map +1 -0
  146. package/dist/util/call-context.js +29 -0
  147. package/dist/util/call-context.js.map +1 -0
  148. package/dist/util/dates.d.ts +62 -0
  149. package/dist/util/dates.d.ts.map +1 -0
  150. package/dist/util/dates.js +169 -0
  151. package/dist/util/dates.js.map +1 -0
  152. package/dist/util/errors.d.ts +9 -0
  153. package/dist/util/errors.d.ts.map +1 -0
  154. package/dist/util/errors.js +15 -0
  155. package/dist/util/errors.js.map +1 -0
  156. package/dist/util/immutable-map.d.ts +16 -0
  157. package/dist/util/immutable-map.d.ts.map +1 -0
  158. package/dist/util/immutable-map.js +38 -0
  159. package/dist/util/immutable-map.js.map +1 -0
  160. package/dist/util/json.d.ts +13 -0
  161. package/dist/util/json.d.ts.map +1 -0
  162. package/dist/util/json.js +44 -0
  163. package/dist/util/json.js.map +1 -0
  164. package/dist/util/text.d.ts +20 -0
  165. package/dist/util/text.d.ts.map +1 -0
  166. package/dist/util/text.js +78 -0
  167. package/dist/util/text.js.map +1 -0
  168. package/dist/util/xml.d.ts +35 -0
  169. package/dist/util/xml.d.ts.map +1 -0
  170. package/dist/util/xml.js +183 -0
  171. package/dist/util/xml.js.map +1 -0
  172. package/dist/v3/account-extension.d.ts +25 -0
  173. package/dist/v3/account-extension.d.ts.map +1 -0
  174. package/dist/v3/account-extension.js +176 -0
  175. package/dist/v3/account-extension.js.map +1 -0
  176. package/dist/v3/client.d.ts +24 -0
  177. package/dist/v3/client.d.ts.map +1 -0
  178. package/dist/v3/client.js +16 -0
  179. package/dist/v3/client.js.map +1 -0
  180. package/dist/v3/dialog.d.ts +78 -0
  181. package/dist/v3/dialog.d.ts.map +1 -0
  182. package/dist/v3/dialog.js +138 -0
  183. package/dist/v3/dialog.js.map +1 -0
  184. package/dist/v3/message.d.ts +72 -0
  185. package/dist/v3/message.d.ts.map +1 -0
  186. package/dist/v3/message.js +259 -0
  187. package/dist/v3/message.js.map +1 -0
  188. package/dist/v3/parameters.d.ts +79 -0
  189. package/dist/v3/parameters.d.ts.map +1 -0
  190. package/dist/v3/parameters.js +396 -0
  191. package/dist/v3/parameters.js.map +1 -0
  192. package/dist/v3/protocol.d.ts +68 -0
  193. package/dist/v3/protocol.d.ts.map +1 -0
  194. package/dist/v3/protocol.js +263 -0
  195. package/dist/v3/protocol.js.map +1 -0
  196. package/dist/v3/segments.d.ts +89 -0
  197. package/dist/v3/segments.d.ts.map +1 -0
  198. package/dist/v3/segments.js +283 -0
  199. package/dist/v3/segments.js.map +1 -0
  200. package/dist/v3/syntax.d.ts +76 -0
  201. package/dist/v3/syntax.d.ts.map +1 -0
  202. package/dist/v3/syntax.js +301 -0
  203. package/dist/v3/syntax.js.map +1 -0
  204. package/package.json +63 -4
  205. package/src/core/account.ts +250 -0
  206. package/src/core/amount.ts +209 -0
  207. package/src/core/balance.ts +84 -0
  208. package/src/core/bank-info.ts +66 -0
  209. package/src/core/client.ts +149 -0
  210. package/src/core/config.ts +141 -0
  211. package/src/core/errors.ts +203 -0
  212. package/src/core/feedback.ts +137 -0
  213. package/src/core/transaction.ts +156 -0
  214. package/src/core/transport.ts +114 -0
  215. package/src/formats/camt.ts +169 -0
  216. package/src/formats/mt940.ts +333 -0
  217. package/src/formats/readers.ts +56 -0
  218. package/src/formats/sepa-purpose.ts +75 -0
  219. package/src/index.ts +68 -0
  220. package/src/session/app-approval.ts +265 -0
  221. package/src/session/bank-connection.ts +51 -0
  222. package/src/session/dialog-runner.ts +119 -0
  223. package/src/session/login-guard.ts +135 -0
  224. package/src/session/parameter-data.ts +137 -0
  225. package/src/session/pin-tan-client.ts +186 -0
  226. package/src/session/pin-tan-dialog.ts +160 -0
  227. package/src/session/protocol.ts +311 -0
  228. package/src/session/response-handler.ts +130 -0
  229. package/src/session/sepa-accounts.ts +97 -0
  230. package/src/session/session-setup.ts +165 -0
  231. package/src/session/session-state.ts +170 -0
  232. package/src/session/tan-selection.ts +192 -0
  233. package/src/session/user-prompts.ts +174 -0
  234. package/src/tan/challenge.ts +252 -0
  235. package/src/tan/flicker.ts +270 -0
  236. package/src/tan/tan-image.ts +36 -0
  237. package/src/tan/tan-models.ts +247 -0
  238. package/src/util/async.ts +53 -0
  239. package/src/util/bytes.ts +135 -0
  240. package/src/util/call-context.ts +40 -0
  241. package/src/util/dates.ts +193 -0
  242. package/src/util/errors.ts +16 -0
  243. package/src/util/immutable-map.ts +47 -0
  244. package/src/util/json.ts +51 -0
  245. package/src/util/text.ts +82 -0
  246. package/src/util/xml.ts +172 -0
  247. package/src/v3/account-extension.ts +190 -0
  248. package/src/v3/client.ts +29 -0
  249. package/src/v3/dialog.ts +199 -0
  250. package/src/v3/message.ts +321 -0
  251. package/src/v3/parameters.ts +451 -0
  252. package/src/v3/protocol.ts +331 -0
  253. package/src/v3/segments.ts +331 -0
  254. package/src/v3/syntax.ts +307 -0
@@ -0,0 +1,297 @@
1
+ import { Amount } from '../core/amount.js';
2
+ import { Transaction } from '../core/transaction.js';
3
+ import { clampedDate, parseSwiftDate } from '../util/dates.js';
4
+ import { FormatError } from '../util/errors.js';
5
+ import { escapeRegExp } from '../util/text.js';
6
+ import { providedReference, SepaPurpose } from './sepa-purpose.js';
7
+ const tagPattern = /^:(\d{2}[A-Z]?):/gm;
8
+ const statementEnd = /\n-\s*$/;
9
+ const trailingNewlines = /\n+$/;
10
+ /** Parser for SWIFT MT940/MT942 statements, including German structured `:86:` fields. */
11
+ export const Mt940 = Object.freeze({
12
+ /** Parses all transactions; see `parse`. */
13
+ parseTransactions(text, options = {}) {
14
+ return Mt940.parse(text, options).flatMap((s) => [...s.transactions]);
15
+ },
16
+ /**
17
+ * Parses all statements.
18
+ *
19
+ * Throws `FormatError` if a transaction line (`:61:`) cannot be read or the currency of a transaction is unknown.
20
+ */
21
+ parse(text, options = {}) {
22
+ const status = options.status ?? 'booked';
23
+ const lines = text.replace(/\r\n/g, '\n').replace(/\r/g, '\n');
24
+ // Some banks separate lines with `@@` instead of line breaks; where there are line breaks, `@@` is text.
25
+ const normalized = lines.includes('\n') ? lines : lines.replace(/@@/g, '\n');
26
+ const tags = [...normalized.matchAll(tagPattern)];
27
+ const statements = [];
28
+ let current;
29
+ tags.forEach((tag, i) => {
30
+ const end = i + 1 < tags.length ? tags[i + 1].index : normalized.length;
31
+ const value = normalized
32
+ .substring(tag.index + tag[0].length, end)
33
+ .replace(statementEnd, '')
34
+ .replace(trailingNewlines, '');
35
+ if (tag[1] === '20' || current === undefined) {
36
+ if (current !== undefined)
37
+ statements.push(current.build());
38
+ current = new StatementBuilder(status, options.currency);
39
+ }
40
+ current.add(tag[1], value);
41
+ });
42
+ if (current !== undefined)
43
+ statements.push(current.build());
44
+ return statements;
45
+ },
46
+ });
47
+ const balancePattern = /^([CD])(\d{6})([A-Z]{3})(\d+,\d*)/;
48
+ const currencyPrefix = /^([A-Z]{3})/;
49
+ class StatementBuilder {
50
+ status;
51
+ fallbackCurrency;
52
+ reference;
53
+ accountId;
54
+ statementNumber;
55
+ currency;
56
+ opening;
57
+ openingDate;
58
+ closing;
59
+ closingDate;
60
+ transactions = [];
61
+ /**
62
+ * The tag added last: a `:86:` right after a `:61:` details the transaction, anywhere else it informs the account
63
+ * owner about the statement.
64
+ */
65
+ previousTag;
66
+ constructor(status,
67
+ /** Currency to use when the statement states none. */
68
+ fallbackCurrency) {
69
+ this.status = status;
70
+ this.fallbackCurrency = fallbackCurrency;
71
+ }
72
+ add(tag, value) {
73
+ switch (tag) {
74
+ case '20':
75
+ this.reference = value.trim();
76
+ break;
77
+ case '25':
78
+ this.accountId = value.trim();
79
+ break;
80
+ case '28C':
81
+ case '28':
82
+ this.statementNumber = value.trim();
83
+ break;
84
+ case '60F':
85
+ case '60M': {
86
+ const balance = parseBalance(value);
87
+ if (balance) {
88
+ [this.opening, this.openingDate] = balance;
89
+ this.currency ??= balance[0].currency;
90
+ }
91
+ break;
92
+ }
93
+ case '62F':
94
+ case '62M': {
95
+ const balance = parseBalance(value);
96
+ if (balance) {
97
+ [this.closing, this.closingDate] = balance;
98
+ this.currency ??= balance[0].currency;
99
+ }
100
+ break;
101
+ }
102
+ case '34F':
103
+ this.currency ??= currencyPrefix.exec(value.trim())?.[1];
104
+ break;
105
+ case '61':
106
+ this.transactions.push(new TransactionLines(value));
107
+ break;
108
+ case '86':
109
+ if (this.previousTag === '61')
110
+ this.transactions.at(-1).details = value;
111
+ break;
112
+ }
113
+ this.previousTag = tag;
114
+ }
115
+ build() {
116
+ const statementCurrency = this.currency ?? this.fallbackCurrency;
117
+ if (statementCurrency === undefined && this.transactions.length > 0) {
118
+ throw new FormatError('MT940 statement without currency', this.reference);
119
+ }
120
+ return Object.freeze({
121
+ reference: this.reference,
122
+ accountId: this.accountId,
123
+ statementNumber: this.statementNumber,
124
+ currency: statementCurrency,
125
+ openingBalance: this.opening,
126
+ openingDate: this.openingDate,
127
+ closingBalance: this.closing,
128
+ closingDate: this.closingDate,
129
+ transactions: Object.freeze(this.transactions.map((t) => t.toTransaction(statementCurrency, this.status))),
130
+ });
131
+ }
132
+ }
133
+ function parseBalance(value) {
134
+ const m = balancePattern.exec(value.trim());
135
+ if (!m)
136
+ return undefined;
137
+ const amount = Amount.parseDecimal(m[4], m[3]);
138
+ const date = parseSwiftDate(m[2]);
139
+ if (date === undefined)
140
+ throw new FormatError('Invalid balance date', value);
141
+ return [m[1] === 'D' ? amount.negate() : amount, date];
142
+ }
143
+ /**
144
+ * Value date, optional booking date (MMDD), debit/credit mark, funds code, amount, transaction type, customer
145
+ * reference, optional bank reference and supplementary details.
146
+ */
147
+ const line61 = /^(\d{6})(\d{4})?(RC|RD|C|D)([A-Z])?(\d+,\d*)([NFS][A-Z0-9]{3})([^\n]*?)(?:\/\/([^\n]*))?(?:\n([\s\S]*))?$/;
148
+ /** The `:61:` line of a transaction and its `:86:` details. */
149
+ class TransactionLines {
150
+ line;
151
+ details;
152
+ constructor(line) {
153
+ this.line = line;
154
+ }
155
+ toTransaction(currency, status) {
156
+ const m = line61.exec(this.line.trim());
157
+ const valueDate = m ? parseSwiftDate(m[1]) : undefined;
158
+ if (!m || valueDate === undefined)
159
+ throw new FormatError('Unreadable MT940 transaction line (:61:)', this.line);
160
+ const mark = m[3];
161
+ const amount = Amount.parseDecimal(m[5], currency);
162
+ const debit = mark === 'D' || mark === 'RC';
163
+ const customerReference = m[7]?.trim();
164
+ const bankReference = m[8]?.trim();
165
+ const d = Details.parse(this.details);
166
+ return new Transaction({
167
+ status,
168
+ bookingDate: this.bookingDate(m[2], valueDate),
169
+ valueDate,
170
+ amount: debit ? amount.negate() : amount,
171
+ isReversal: mark.startsWith('R'),
172
+ transactionTypeId: m[6],
173
+ customerReference: customerReference === undefined || customerReference === '' || customerReference === 'NONREF'
174
+ ? undefined
175
+ : customerReference,
176
+ bankReference: bankReference === undefined || bankReference === '' ? undefined : bankReference,
177
+ transactionCode: d.transactionCode,
178
+ bookingText: d.bookingText,
179
+ primaNota: d.primaNota,
180
+ purpose: d.purpose,
181
+ counterpartyName: d.name,
182
+ counterpartyIban: d.iban,
183
+ counterpartyBic: d.bic,
184
+ counterpartyAccountNumber: d.accountNumber,
185
+ counterpartyBankCode: d.bankCode,
186
+ endToEndId: providedReference(d.sepa.get('EREF')),
187
+ mandateId: d.sepa.get('MREF'),
188
+ creditorId: d.sepa.get('CRED'),
189
+ ultimateCreditor: d.sepa.get('ABWE'),
190
+ ultimateDebtor: d.sepa.get('ABWA'),
191
+ purposeCodes: d.sepa,
192
+ });
193
+ }
194
+ /** The booking date `MMDD`, in the year that places it closest to `valueDate` (across a year end). */
195
+ bookingDate(mmdd, valueDate) {
196
+ if (mmdd === undefined)
197
+ return undefined;
198
+ const month = Number(mmdd.substring(0, 2));
199
+ const day = Number(mmdd.substring(2, 4));
200
+ let year = valueDate.getFullYear();
201
+ if (month === 12 && valueDate.getMonth() === 0)
202
+ year--;
203
+ if (month === 1 && valueDate.getMonth() === 11)
204
+ year++;
205
+ const date = clampedDate(year, month, day);
206
+ if (date === undefined)
207
+ throw new FormatError('Invalid booking date', this.line);
208
+ return date;
209
+ }
210
+ }
211
+ /**
212
+ * Three-digit business transaction code (GVC), then the first subfield: a separator, usually `?`, and its two-digit
213
+ * number. Text that merely starts with three digits, such as `100 Euro`, is free text.
214
+ */
215
+ const structuredPattern = /^(\d{3})([^\w\s])\d{2}/;
216
+ const ibanPattern = /^[A-Z]{2}\d{2}[A-Z0-9]+$/;
217
+ const bicPattern = /^[A-Z]{6}[A-Z0-9]{2}([A-Z0-9]{3})?$/;
218
+ /** Subfield pattern for a separator: the separator, a two-digit key, then everything up to the next subfield. */
219
+ function subfieldPattern(separator) {
220
+ const s = escapeRegExp(separator);
221
+ return new RegExp(`${s}(\\d{2})((?:(?!${s}\\d{2})[\\s\\S])*)`, 'g');
222
+ }
223
+ /** The German structured `:86:` field: a business transaction code and `?nn` subfields. */
224
+ class Details {
225
+ transactionCode;
226
+ bookingText;
227
+ primaNota;
228
+ purpose;
229
+ name;
230
+ iban;
231
+ bic;
232
+ accountNumber;
233
+ bankCode;
234
+ sepa = new Map();
235
+ static parse(raw) {
236
+ const d = new Details();
237
+ if (raw === undefined)
238
+ return d;
239
+ const text = raw.replace(/\n/g, '');
240
+ const structured = structuredPattern.exec(text);
241
+ if (!structured) {
242
+ // Free text, whose lines are separate phrases; the purpose and its keywords are read from the same text.
243
+ const free = raw.replace(/\n/g, ' ').trim();
244
+ d.sepa = SepaPurpose.parse(free);
245
+ d.purpose = d.sepa.get('SVWZ') ?? (free === '' ? undefined : free);
246
+ return d;
247
+ }
248
+ d.transactionCode = structured[1];
249
+ const subfields = Details.subfields(text.substring(3), structured[2]);
250
+ const subfield = (key) => {
251
+ const value = subfields.get(key)?.trim();
252
+ return value === undefined || value === '' ? undefined : value;
253
+ };
254
+ // Subfields continue each other: they are joined keeping the spaces at their boundaries.
255
+ const parts = (keys) => keys.map((k) => subfields.get(k)).filter((v) => v !== undefined);
256
+ d.bookingText = subfield(0);
257
+ d.primaNota = subfield(10);
258
+ const purposeParts = parts([20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 60, 61, 62, 63]);
259
+ const purpose = purposeParts.join('').trim();
260
+ d.sepa = SepaPurpose.parseParts(purposeParts);
261
+ d.purpose = d.sepa.get('SVWZ') ?? (purpose === '' ? undefined : purpose);
262
+ const name = parts([32, 33]).join('').trim();
263
+ d.name = name === '' ? undefined : name;
264
+ d.readCounterpartyAccount(subfield(30), subfield(31));
265
+ d.iban ??= d.sepa.get('IBAN');
266
+ d.bic ??= d.sepa.get('BIC');
267
+ return d;
268
+ }
269
+ /** The text of each subfield (`?nn` and what follows), by its number; a subfield that appears twice is joined. */
270
+ static subfields(text, separator) {
271
+ const subfields = new Map();
272
+ for (const m of text.matchAll(subfieldPattern(separator))) {
273
+ const key = Number(m[1]);
274
+ subfields.set(key, (subfields.get(key) ?? '') + m[2]);
275
+ }
276
+ return subfields;
277
+ }
278
+ /**
279
+ * Takes the counterparty's account from subfields 30 (bank) and 31 (account): IBAN and BIC, or account number and
280
+ * bank code.
281
+ */
282
+ readCounterpartyAccount(bank, account) {
283
+ if (account !== undefined && ibanPattern.test(account)) {
284
+ this.iban = account;
285
+ this.bic = bank;
286
+ return;
287
+ }
288
+ this.accountNumber = account;
289
+ if (bank !== undefined && bicPattern.test(bank)) {
290
+ this.bic = bank;
291
+ }
292
+ else {
293
+ this.bankCode = bank;
294
+ }
295
+ }
296
+ }
297
+ //# sourceMappingURL=mt940.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mt940.js","sourceRoot":"","sources":["../../src/formats/mt940.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import type { Transaction } from '../core/transaction.js';
2
+ /**
3
+ * The transactions in MT940 data: the `booked` parts joined, since a statement may continue on the next page, then the
4
+ * `pending` ones (MT942).
5
+ *
6
+ * `currency` applies to statements that do not state one; throws `FormatError` if both are missing.
7
+ */
8
+ export declare function mt940Transactions(booked: readonly Uint8Array[], pending: readonly Uint8Array[], currency: string | undefined): Transaction[];
9
+ /** The transactions in camt documents; each document stands on its own. */
10
+ export declare function camtTransactions(booked: readonly Uint8Array[], pending: readonly Uint8Array[]): Transaction[];
11
+ //# sourceMappingURL=readers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"readers.d.ts","sourceRoot":"","sources":["../../src/formats/readers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAM1D;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,SAAS,UAAU,EAAE,EAC7B,OAAO,EAAE,SAAS,UAAU,EAAE,EAC9B,QAAQ,EAAE,MAAM,GAAG,SAAS,GAC3B,WAAW,EAAE,CAKf;AA4BD,2EAA2E;AAC3E,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,SAAS,UAAU,EAAE,EAAE,OAAO,EAAE,SAAS,UAAU,EAAE,GAAG,WAAW,EAAE,CAK7G"}
@@ -0,0 +1,47 @@
1
+ import { BytesBuilder } from '../util/bytes.js';
2
+ import { decodeBankText, decodeXmlText } from '../util/text.js';
3
+ import { Camt } from './camt.js';
4
+ import { Mt940 } from './mt940.js';
5
+ /**
6
+ * The transactions in MT940 data: the `booked` parts joined, since a statement may continue on the next page, then the
7
+ * `pending` ones (MT942).
8
+ *
9
+ * `currency` applies to statements that do not state one; throws `FormatError` if both are missing.
10
+ */
11
+ export function mt940Transactions(booked, pending, currency) {
12
+ return [
13
+ ...Mt940.parseTransactions(joinedMt940(booked), { currency }),
14
+ ...Mt940.parseTransactions(joinedMt940(pending), { currency, status: 'pending' }),
15
+ ];
16
+ }
17
+ const lineFeed = 0x0a;
18
+ const carriageReturn = 0x0d;
19
+ const atSign = 0x40;
20
+ /**
21
+ * The MT940 `parts` as one text.
22
+ *
23
+ * Each part ends a line before the next one follows, since the parser finds fields at the start of a line and a bank
24
+ * need not end its pages with a line break. Banks that separate lines with `@@` get that separator.
25
+ */
26
+ function joinedMt940(parts) {
27
+ const pages = parts.filter((part) => part.length > 0);
28
+ const atSigns = !pages.some((p) => p.includes(lineFeed) || p.includes(carriageReturn));
29
+ const endsLine = (page) => atSigns
30
+ ? page.length >= 2 && page[page.length - 1] === atSign && page[page.length - 2] === atSign
31
+ : page.at(-1) === lineFeed || page.at(-1) === carriageReturn;
32
+ const bytes = new BytesBuilder();
33
+ pages.forEach((page, i) => {
34
+ if (i > 0 && !endsLine(pages[i - 1]))
35
+ bytes.add(atSigns ? [atSign, atSign] : [lineFeed]);
36
+ bytes.add(page);
37
+ });
38
+ return decodeBankText(bytes.takeBytes());
39
+ }
40
+ /** The transactions in camt documents; each document stands on its own. */
41
+ export function camtTransactions(booked, pending) {
42
+ return [
43
+ ...booked.flatMap((document) => Camt.parseTransactions(decodeXmlText(document))),
44
+ ...pending.flatMap((document) => Camt.parseTransactions(decodeXmlText(document), 'pending')),
45
+ ];
46
+ }
47
+ //# sourceMappingURL=readers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"readers.js","sourceRoot":"","sources":["../../src/formats/readers.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAEnC;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAC/B,MAA6B,EAC7B,OAA8B,EAC9B,QAA4B;IAE5B,OAAO;QACL,GAAG,KAAK,CAAC,iBAAiB,CAAC,WAAW,CAAC,MAAM,CAAC,EAAE,EAAE,QAAQ,EAAE,CAAC;QAC7D,GAAG,KAAK,CAAC,iBAAiB,CAAC,WAAW,CAAC,OAAO,CAAC,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;KAClF,CAAC;AACJ,CAAC;AAED,MAAM,QAAQ,GAAG,IAAI,CAAC;AACtB,MAAM,cAAc,GAAG,IAAI,CAAC;AAC5B,MAAM,MAAM,GAAG,IAAI,CAAC;AAEpB;;;;;GAKG;AACH,SAAS,WAAW,CAAC,KAA4B;IAC/C,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IACtD,MAAM,OAAO,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC,CAAC;IACvF,MAAM,QAAQ,GAAG,CAAC,IAAgB,EAAW,EAAE,CAC7C,OAAO;QACL,CAAC,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,KAAK,MAAM,IAAI,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,KAAK,MAAM;QAC1F,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,QAAQ,IAAI,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,cAAc,CAAC;IAEjE,MAAM,KAAK,GAAG,IAAI,YAAY,EAAE,CAAC;IACjC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE;QACxB,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAE,CAAC;YAAE,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC;QAC1F,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;IACH,OAAO,cAAc,CAAC,KAAK,CAAC,SAAS,EAAE,CAAC,CAAC;AAC3C,CAAC;AAED,2EAA2E;AAC3E,MAAM,UAAU,gBAAgB,CAAC,MAA6B,EAAE,OAA8B;IAC5F,OAAO;QACL,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,IAAI,CAAC,iBAAiB,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC,CAAC;QAChF,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,IAAI,CAAC,iBAAiB,CAAC,aAAa,CAAC,QAAQ,CAAC,EAAE,SAAS,CAAC,CAAC;KAC7F,CAAC;AACJ,CAAC"}
@@ -0,0 +1,22 @@
1
+ /** `reference`, or `undefined` if it is missing or the filler for a reference the payer did not give. */
2
+ export declare function providedReference(reference: string | undefined): string | undefined;
3
+ /** Parser for the SEPA keywords in a purpose text. */
4
+ export declare const SepaPurpose: Readonly<{
5
+ /**
6
+ * Splits `purpose` into its SEPA keywords (EREF, KREF, MREF, CRED, SVWZ, …) and their values.
7
+ *
8
+ * A keyword counts unless a capital letter comes right before it, so `XEREF+` does not open an EREF value. After a
9
+ * digit or a small letter it does: a purpose line cut at 35 characters is joined to the next one without a space, so
10
+ * `…4711EREF+` may be where one line ends and the next begins.
11
+ */
12
+ parse(purpose: string): Map<string, string>;
13
+ /**
14
+ * Like `parse` for a purpose the bank sends in `parts`, such as the MT940 subfields `?20` to `?29`, which continue
15
+ * each other without a separator.
16
+ *
17
+ * A keyword also counts at the start of a part, where the previous value may end in a capital letter, as in
18
+ * `EREF+NOTPROVIDED` followed by a part `MREF+…`.
19
+ */
20
+ parseParts(parts: Iterable<string>): Map<string, string>;
21
+ }>;
22
+ //# sourceMappingURL=sepa-purpose.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sepa-purpose.d.ts","sourceRoot":"","sources":["../../src/formats/sepa-purpose.ts"],"names":[],"mappings":"AAqBA,yGAAyG;AACzG,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAEnF;AAID,sDAAsD;AACtD,eAAO,MAAM,WAAW;IACtB;;;;;;OAMG;mBACY,MAAM,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC;IAI3C;;;;;;OAMG;sBACe,QAAQ,CAAC,MAAM,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC;EASxD,CAAC"}
@@ -0,0 +1,68 @@
1
+ /** SEPA keywords German banks put into the purpose text, each followed by `+`. */
2
+ const keywords = [
3
+ 'EREF',
4
+ 'KREF',
5
+ 'MREF',
6
+ 'CRED',
7
+ 'DEBT',
8
+ 'COAM',
9
+ 'OAMT',
10
+ 'SVWZ',
11
+ 'ABWA',
12
+ 'ABWE',
13
+ 'IBAN',
14
+ 'BIC',
15
+ 'PURP',
16
+ 'SQTP',
17
+ ];
18
+ /** The filler SEPA prescribes where the payer gave no end-to-end reference. */
19
+ const notProvided = 'NOTPROVIDED';
20
+ /** `reference`, or `undefined` if it is missing or the filler for a reference the payer did not give. */
21
+ export function providedReference(reference) {
22
+ return reference === notProvided ? undefined : reference;
23
+ }
24
+ const keywordPattern = new RegExp(`(${keywords.join('|')})\\+`, 'g');
25
+ /** Parser for the SEPA keywords in a purpose text. */
26
+ export const SepaPurpose = Object.freeze({
27
+ /**
28
+ * Splits `purpose` into its SEPA keywords (EREF, KREF, MREF, CRED, SVWZ, …) and their values.
29
+ *
30
+ * A keyword counts unless a capital letter comes right before it, so `XEREF+` does not open an EREF value. After a
31
+ * digit or a small letter it does: a purpose line cut at 35 characters is joined to the next one without a space, so
32
+ * `…4711EREF+` may be where one line ends and the next begins.
33
+ */
34
+ parse(purpose) {
35
+ return split(purpose, new Set());
36
+ },
37
+ /**
38
+ * Like `parse` for a purpose the bank sends in `parts`, such as the MT940 subfields `?20` to `?29`, which continue
39
+ * each other without a separator.
40
+ *
41
+ * A keyword also counts at the start of a part, where the previous value may end in a capital letter, as in
42
+ * `EREF+NOTPROVIDED` followed by a part `MREF+…`.
43
+ */
44
+ parseParts(parts) {
45
+ let text = '';
46
+ const partStarts = new Set();
47
+ for (const part of parts) {
48
+ partStarts.add(text.length);
49
+ text += part;
50
+ }
51
+ return split(text, partStarts);
52
+ },
53
+ });
54
+ function split(purpose, partStarts) {
55
+ const atWordStart = (index) => index === 0 || partStarts.has(index) || !isCapitalLetter(purpose, index - 1);
56
+ const matches = [...purpose.matchAll(keywordPattern)].filter((m) => atWordStart(m.index));
57
+ const result = new Map();
58
+ matches.forEach((m, i) => {
59
+ const end = i + 1 < matches.length ? matches[i + 1].index : purpose.length;
60
+ result.set(m[1], purpose.substring(m.index + m[0].length, end).trim());
61
+ });
62
+ return result;
63
+ }
64
+ function isCapitalLetter(text, index) {
65
+ const c = text.charCodeAt(index);
66
+ return c >= 0x41 && c <= 0x5a;
67
+ }
68
+ //# sourceMappingURL=sepa-purpose.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sepa-purpose.js","sourceRoot":"","sources":["../../src/formats/sepa-purpose.ts"],"names":[],"mappings":"AAAA,kFAAkF;AAClF,MAAM,QAAQ,GAAG;IACf,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;IACN,KAAK;IACL,MAAM;IACN,MAAM;CACP,CAAC;AAEF,+EAA+E;AAC/E,MAAM,WAAW,GAAG,aAAa,CAAC;AAElC,yGAAyG;AACzG,MAAM,UAAU,iBAAiB,CAAC,SAA6B;IAC7D,OAAO,SAAS,KAAK,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC;AAC3D,CAAC;AAED,MAAM,cAAc,GAAG,IAAI,MAAM,CAAC,IAAI,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;AAErE,sDAAsD;AACtD,MAAM,CAAC,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,CAAC;IACvC;;;;;;OAMG;IACH,KAAK,CAAC,OAAe;QACnB,OAAO,KAAK,CAAC,OAAO,EAAE,IAAI,GAAG,EAAE,CAAC,CAAC;IACnC,CAAC;IAED;;;;;;OAMG;IACH,UAAU,CAAC,KAAuB;QAChC,IAAI,IAAI,GAAG,EAAE,CAAC;QACd,MAAM,UAAU,GAAG,IAAI,GAAG,EAAU,CAAC;QACrC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YAC5B,IAAI,IAAI,IAAI,CAAC;QACf,CAAC;QACD,OAAO,KAAK,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;IACjC,CAAC;CACF,CAAC,CAAC;AAEH,SAAS,KAAK,CAAC,OAAe,EAAE,UAA+B;IAC7D,MAAM,WAAW,GAAG,CAAC,KAAa,EAAW,EAAE,CAC7C,KAAK,KAAK,CAAC,IAAI,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC,OAAO,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC;IAC/E,MAAM,OAAO,GAAG,CAAC,GAAG,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;IAC1F,MAAM,MAAM,GAAG,IAAI,GAAG,EAAkB,CAAC;IACzC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QACvB,MAAM,GAAG,GAAG,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,CAAE,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC;QAC5E,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAE,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;IAC1E,CAAC,CAAC,CAAC;IACH,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,eAAe,CAAC,IAAY,EAAE,KAAa;IAClD,MAAM,CAAC,GAAG,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;IACjC,OAAO,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,IAAI,CAAC;AAChC,CAAC"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * FinTS 3.0 client for German banks: accounts, balances and transactions with PIN/TAN, PSD2 strong customer
3
+ * authentication and decoupled app approval.
4
+ *
5
+ * Start with `FinTs3Client`. The public API is what this file names; everything else is internal.
6
+ *
7
+ * @packageDocumentation
8
+ */
9
+ export { Account, AccountDataStatus, type AccountCategory, type AccountInit } from './core/account.js';
10
+ export { Amount } from './core/amount.js';
11
+ export { Balance, type BalanceInit } from './core/balance.js';
12
+ export { BankInfo, BankMessage } from './core/bank-info.js';
13
+ export type { BankMessageHandler, FinTsClient, FinTsClientOptions, MessageDirection, MessageLogger, TransactionQuery, WarningHandler, } from './core/client.js';
14
+ export { FinTsConfig, type FinTsConfigInit } from './core/config.js';
15
+ export { FinTsBankError, FinTsDecoupledTimeoutError, FinTsDialogAbortedError, FinTsError, FinTsLoginDataChangedError, FinTsPinError, FinTsProtocolError, FinTsStateError, FinTsTanCancelledError, FinTsTanError, FinTsTransportError, FinTsUnsupportedError, } from './core/errors.js';
16
+ export { FeedbackCodes, FinTsFeedback } from './core/feedback.js';
17
+ export { Transaction, type TransactionFormat, type TransactionInit, type TransactionStatus, } from './core/transaction.js';
18
+ export { HttpTransport, type FinTsTransport, type HttpTransportOptions } from './core/transport.js';
19
+ export { Camt } from './formats/camt.js';
20
+ export { Mt940, type Mt940Options, type Mt940Statement } from './formats/mt940.js';
21
+ export { SepaPurpose } from './formats/sepa-purpose.js';
22
+ export { TanAnswer, TanChallenge, type TanCallback, type TanChallengeInit, type TanMediumSelector, type TanMethodSelector, } from './tan/challenge.js';
23
+ export { FlickerCode, type HhdVersion } from './tan/flicker.js';
24
+ export { TanImage } from './tan/tan-image.js';
25
+ export { TanMedium, TanMethod, type TanMediumInit, type TanMediumRequirement, type TanMediumStatus, type TanMethodInit, } from './tan/tan-models.js';
26
+ export { FormatError } from './util/errors.js';
27
+ export { FinTs3Client, type FinTs3ClientInit } from './v3/client.js';
28
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,OAAO,EAAE,iBAAiB,EAAE,KAAK,eAAe,EAAE,KAAK,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACvG,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC1C,OAAO,EAAE,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAC9D,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAC5D,YAAY,EACV,kBAAkB,EAClB,WAAW,EACX,kBAAkB,EAClB,gBAAgB,EAChB,aAAa,EACb,gBAAgB,EAChB,cAAc,GACf,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,WAAW,EAAE,KAAK,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACrE,OAAO,EACL,cAAc,EACd,0BAA0B,EAC1B,uBAAuB,EACvB,UAAU,EACV,0BAA0B,EAC1B,aAAa,EACb,kBAAkB,EAClB,eAAe,EACf,sBAAsB,EACtB,aAAa,EACb,mBAAmB,EACnB,qBAAqB,GACtB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAClE,OAAO,EACL,WAAW,EACX,KAAK,iBAAiB,EACtB,KAAK,eAAe,EACpB,KAAK,iBAAiB,GACvB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,aAAa,EAAE,KAAK,cAAc,EAAE,KAAK,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AACpG,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AACzC,OAAO,EAAE,KAAK,EAAE,KAAK,YAAY,EAAE,KAAK,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACnF,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AACxD,OAAO,EACL,SAAS,EACT,YAAY,EACZ,KAAK,WAAW,EAChB,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,EACtB,KAAK,iBAAiB,GACvB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,WAAW,EAAE,KAAK,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAChE,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EACL,SAAS,EACT,SAAS,EACT,KAAK,aAAa,EAClB,KAAK,oBAAoB,EACzB,KAAK,eAAe,EACpB,KAAK,aAAa,GACnB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,KAAK,gBAAgB,EAAE,MAAM,gBAAgB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,27 @@
1
+ /**
2
+ * FinTS 3.0 client for German banks: accounts, balances and transactions with PIN/TAN, PSD2 strong customer
3
+ * authentication and decoupled app approval.
4
+ *
5
+ * Start with `FinTs3Client`. The public API is what this file names; everything else is internal.
6
+ *
7
+ * @packageDocumentation
8
+ */
9
+ export { Account, AccountDataStatus } from './core/account.js';
10
+ export { Amount } from './core/amount.js';
11
+ export { Balance } from './core/balance.js';
12
+ export { BankInfo, BankMessage } from './core/bank-info.js';
13
+ export { FinTsConfig } from './core/config.js';
14
+ export { FinTsBankError, FinTsDecoupledTimeoutError, FinTsDialogAbortedError, FinTsError, FinTsLoginDataChangedError, FinTsPinError, FinTsProtocolError, FinTsStateError, FinTsTanCancelledError, FinTsTanError, FinTsTransportError, FinTsUnsupportedError, } from './core/errors.js';
15
+ export { FeedbackCodes, FinTsFeedback } from './core/feedback.js';
16
+ export { Transaction, } from './core/transaction.js';
17
+ export { HttpTransport } from './core/transport.js';
18
+ export { Camt } from './formats/camt.js';
19
+ export { Mt940 } from './formats/mt940.js';
20
+ export { SepaPurpose } from './formats/sepa-purpose.js';
21
+ export { TanAnswer, TanChallenge, } from './tan/challenge.js';
22
+ export { FlickerCode } from './tan/flicker.js';
23
+ export { TanImage } from './tan/tan-image.js';
24
+ export { TanMedium, TanMethod, } from './tan/tan-models.js';
25
+ export { FormatError } from './util/errors.js';
26
+ export { FinTs3Client } from './v3/client.js';
27
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,OAAO,EAAE,iBAAiB,EAA0C,MAAM,mBAAmB,CAAC;AACvG,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC1C,OAAO,EAAE,OAAO,EAAoB,MAAM,mBAAmB,CAAC;AAC9D,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAU5D,OAAO,EAAE,WAAW,EAAwB,MAAM,kBAAkB,CAAC;AACrE,OAAO,EACL,cAAc,EACd,0BAA0B,EAC1B,uBAAuB,EACvB,UAAU,EACV,0BAA0B,EAC1B,aAAa,EACb,kBAAkB,EAClB,eAAe,EACf,sBAAsB,EACtB,aAAa,EACb,mBAAmB,EACnB,qBAAqB,GACtB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAClE,OAAO,EACL,WAAW,GAIZ,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,aAAa,EAAkD,MAAM,qBAAqB,CAAC;AACpG,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AACzC,OAAO,EAAE,KAAK,EAA0C,MAAM,oBAAoB,CAAC;AACnF,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AACxD,OAAO,EACL,SAAS,EACT,YAAY,GAKb,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,WAAW,EAAmB,MAAM,kBAAkB,CAAC;AAChE,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EACL,SAAS,EACT,SAAS,GAKV,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAyB,MAAM,gBAAgB,CAAC"}
@@ -0,0 +1,60 @@
1
+ import { type TanAnswer, type TanChallenge } from '../tan/challenge.js';
2
+ import type { TanMethod } from '../tan/tan-models.js';
3
+ import type { Approval, BankResponse } from './protocol.js';
4
+ /** Shows a challenge and returns the user's answer. */
5
+ export type AskUser = (challenge: TanChallenge) => Promise<TanAnswer>;
6
+ /** Waits for `delayMs`, or until `interrupt` settles. */
7
+ export type Pause = (delayMs: number, interrupt?: Promise<unknown>) => Promise<void>;
8
+ /** What an `AppApprovalWait` needs: `ask` shows a challenge, `pause` waits, `receive` takes in each status response. */
9
+ export interface AppApprovalHooks<R> {
10
+ readonly ask: AskUser;
11
+ readonly pause: Pause;
12
+ /** Takes in each status response; throws if it reports errors. */
13
+ readonly receive: (response: R) => void;
14
+ }
15
+ /**
16
+ * Waits for the user to approve a message in the banking app, and for the bank to confirm it (PIN/TAN B.4.2.2).
17
+ *
18
+ * The bank's parameters decide who triggers the status requests:
19
+ * - The client polls by itself while the callback shows the instructions (`PollingWhileShown`) where the bank allows
20
+ * automatic status requests and announces no push message (3957), and also where the user cannot report the
21
+ * approval: then polling is the one way left to complete it, whatever the other parameters say (step 2a).
22
+ * - Otherwise the client asks after each report of the user (`PollingAfterReports`), which stands in for the push
23
+ * message the client cannot receive.
24
+ *
25
+ * The bank's limit on status requests holds either way, and two requests are at least a second apart. One instance
26
+ * handles one `Approval`; `run` may be called once. A failure of `ask` or `pause`, such as a closed client, ends the
27
+ * wait.
28
+ */
29
+ export declare function appApprovalWait<R extends BankResponse>(approval: Approval<R>, hooks: AppApprovalHooks<R>): AppApprovalWait<R>;
30
+ export declare abstract class AppApprovalWait<R extends BankResponse> {
31
+ protected readonly approval: Approval<R>;
32
+ protected readonly hooks: AppApprovalHooks<R>;
33
+ private requests;
34
+ /** The time the client waited by itself, which counts towards the longest wait. */
35
+ protected waitedMs: number;
36
+ constructor(approval: Approval<R>, hooks: AppApprovalHooks<R>);
37
+ /**
38
+ * Returns the bank's response once the approval is through. Throws `FinTsTanCancelledError` if the user cancels and
39
+ * `FinTsDecoupledTimeoutError` if the approval takes too long.
40
+ */
41
+ abstract run(): Promise<R>;
42
+ protected get method(): TanMethod;
43
+ /** Whether the user may report the approval (PIN/TAN, "Manuelle Bestätigung möglich"). */
44
+ protected get userConfirms(): boolean;
45
+ protected get pollIntervalMs(): number;
46
+ protected get firstPollDelayMs(): number;
47
+ /**
48
+ * Sends the next status request and returns the answer, once `receive` has taken it in.
49
+ *
50
+ * Throws if the answer reports errors, and `FinTsDecoupledTimeoutError` if the approval is still pending after as
51
+ * many requests as the bank allows, or after the longest wait.
52
+ */
53
+ protected requestStatus(): Promise<R>;
54
+ /**
55
+ * `challenge` as the next prompt, with the new instructions of `pending`, the last status answer, where it gives any
56
+ * (PIN/TAN B.4.2.2.1, step 2b).
57
+ */
58
+ protected nextPrompt(challenge: TanChallenge, pending: R): TanChallenge;
59
+ }
60
+ //# sourceMappingURL=app-approval.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app-approval.d.ts","sourceRoot":"","sources":["../../src/session/app-approval.ts"],"names":[],"mappings":"AAEA,OAAO,EAA6B,KAAK,SAAS,EAAE,KAAK,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnG,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAGtD,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAY5D,uDAAuD;AACvD,MAAM,MAAM,OAAO,GAAG,CAAC,SAAS,EAAE,YAAY,KAAK,OAAO,CAAC,SAAS,CAAC,CAAC;AAEtE,yDAAyD;AACzD,MAAM,MAAM,KAAK,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,OAAO,CAAC,OAAO,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;AAErF,wHAAwH;AACxH,MAAM,WAAW,gBAAgB,CAAC,CAAC;IACjC,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IACtB,kEAAkE;IAClE,QAAQ,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,CAAC,KAAK,IAAI,CAAC;CACzC;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,eAAe,CAAC,CAAC,SAAS,YAAY,EACpD,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC,EACrB,KAAK,EAAE,gBAAgB,CAAC,CAAC,CAAC,GACzB,eAAe,CAAC,CAAC,CAAC,CAIpB;AAED,8BAAsB,eAAe,CAAC,CAAC,SAAS,YAAY;IAOxD,SAAS,CAAC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC;IACxC,SAAS,CAAC,QAAQ,CAAC,KAAK,EAAE,gBAAgB,CAAC,CAAC,CAAC;IAP/C,OAAO,CAAC,QAAQ,CAAK;IAErB,mFAAmF;IACnF,SAAS,CAAC,QAAQ,SAAK;gBAGF,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC,EACrB,KAAK,EAAE,gBAAgB,CAAC,CAAC,CAAC;IAG/C;;;OAGG;IACH,QAAQ,CAAC,GAAG,IAAI,OAAO,CAAC,CAAC,CAAC;IAE1B,SAAS,KAAK,MAAM,IAAI,SAAS,CAEhC;IAED,0FAA0F;IAC1F,SAAS,KAAK,YAAY,IAAI,OAAO,CAEpC;IAED,SAAS,KAAK,cAAc,IAAI,MAAM,CAMrC;IAED,SAAS,KAAK,gBAAgB,IAAI,MAAM,CAEvC;IAED;;;;;OAKG;cACa,aAAa,IAAI,OAAO,CAAC,CAAC,CAAC;IAe3C;;;OAGG;IACH,SAAS,CAAC,UAAU,CAAC,SAAS,EAAE,YAAY,EAAE,OAAO,EAAE,CAAC,GAAG,YAAY;CAGxE"}